New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add function_exists( 'add_action' ) check to initialization file #303
Comments
By checking that the function add_action() exists, before we call it, we can avoid throwing a fatal error when a PHP tool is run (e.g. phpcs) even if we are loading `action-scheduler.php` via Composer's autoload. See woocommerce#303
For reference: this same problem occurs when loading the CMB2 library as a composer dependency (see CMB2 Issue 1270 Add function_exists( 'add_action' ) check to initialization file) |
IMO this isn't the correct solution. A WordPress plugin should be able to assume that the WordPress plugin API functions are available, otherwise every plugin in the WordPress ecosystem needs to be updated with The mistake is that your project is autoloading a WordPress plugin. By its nature a WordPress plugin entrypoint file will almost always have side effects (most commonly by adding actions and filters) instead of simply declaring symbols, which makes it unfit and inappropriate for autoloading in the context of Composer. Most established Composer-based project frameworks recommend to load WordPress plugins as actual plugins or mu-plugins, instead of autoloading them directly via Composer, for exactly the reason you've identified. For example Bedrock has its own autoloader and any must-use plugins are loaded at the correct point instead of being directly autoloaded in the Composer configuration. |
@johnbillion, I'm a big fan of your work and I really appreciate your input on this issue. I agree whole heartedly with much of what you've written, specifically I agree with the rule
Updated: An additional rule I would propose is a library should never hook into WordPress without being called. Because Action Scheduler (and CMB2) exist as both a plugin and a library (See Action Scheduler Installation and CMB2 Installation), I see a conflict of these two rules. The problem I've described in this issue (being unable to run PHPCS) occurs when we treat Action Scheduler as a library (rather than a plugin). Proposed Solutions1. Add the function_exists() checkIn PR #304, I've created this proposed solution. While I recognize this is not an ideal solution, I think it is the most practical. 2. Create a Library and a PluginWe could move all of the functionality (with the exception of the initial I see this is the purest programming solution however I don't think it is the most practical. 3. Remove Documentation on Using this as a LibraryWhile I recognize removing any documentation regarding loading this code as a library seems extreme, I think if the project is going to be treated strictly as a plugin, the documentation should reflect this. 4. Document this Library Should Not be used with ComposerIf we keep the documentation on loading this project as a library, we could document the problem with loading this library via Composer. I'm not a big fan of this approach as it feels like we're leaving something broken and documenting why it is broken. Thank You for Your ConsiderationI appreciate your time on this issue and while I would certainly like to see the |
Ah-ha, now I agree with you that if we assume this is a library instead of a WordPress plugin then autoloading it ought to be possible with Composer. That said, the bootstrap procedure of the library needs to work differently in that case so the only files that are autoloaded are ones with no side effect (ie. files that define functions and classes). The problem that introduces is moving the bootstrap process to the consumer, which should be a case of calling a function which sets up the actions and filters which are otherwise set up in the base plugin file (as you mention in point 2). |
Agreed. What do you see as impractical about this approach though @salcode? I think it would be relatively straightforward. At first, I was concerned it would break backward compatibility and require a lot of plugins using it to change how they load it. However, existing plugins loading it as a library by including The changeset would be quite minimal too. We'd just need to move |
Viewing the cost/benefit ratio, I'm not sure I see this as a good use of time. I see a number of costs (that would be borne by you as the maintainers, which I try to minimize when submitting a PR 馃榾), with not a significant amount of benefit over the current PR. Costs
BenefitsThe action-scheduler functionality could be loaded as a library via composer without automatically hooking in (thus solving the problem with other PHP tools that run outside of WordPress (e.g. PHP_CodeSniffer)). From my perspective merging the current PR to add the conditional check for |
Ah thanks for the clarification @salcode, I completely misunderstood what you were saying, and thought you were referring to having the library & plugin use cases handled in the same codebase still. Specifically, I thought we could make
Yes, agreed. My only lingering concern is the gotcha it creates. Developers will likely (and rightly) expect AS to init itself when loaded via composer. Out of curiosity, how are you loading AS when adding the |
The current behavior will not change for developers. Currently, if you require Action Scheduler via composer as a dependency it will not
I've added
By adding the Another way to look at this is when running outside the context of WordPress we do not want to autoload |
Perfect, thanks for the explanation.
I think that's the context I was looking for. The @johnbillion I really appreciate you sharing your expertise on this thread. Any final thoughts before I merge #304? |
I think this is okay to change for now. I have a few ideas but they can wait and I'll open a follow-up ticket. 馃憤 |
Fixed via #304. |
Loading Action Scheduler via Composer
When loading Action Scheduler via Composer, I need to autoload
vendor/prospress/action-scheduler/action-scheduler.php
which Composer supports natively 馃槂 .This works great when
action-scheduler.php
is loaded within the context of WordPress.The Problem with Autoloading action-scheduler.php
If a project is also using a PHP based development tool (e.g. PHP_CodeSniffer (phpcs)), that tool runs outside of the context of WordPress. Because of this when鈽癸笍 .
vendor/prospress/action-scheduler/action-scheduler.php
is autoloaded, a Fatal Error is thrown becauseadd_action()
is not a defined functionSuggested Solution
By adding a
function_exists( 'add_action' )
check before callingadd_action()
, we could skip this fatal error when a PHP based development tool is run andaction-scheduler.php
is autoloaded via Composer.Thanks for this great library (and regardless of how I load it) it is a big help on my current project.
Thanks!
The text was updated successfully, but these errors were encountered: