Conversation
71239db to
dd41dbb
Compare
tyxla
left a comment
There was a problem hiding this comment.
Awesome work! Tests beautifully in all cases (no WC, WC installed but inactive, WC installed and active)! 👍 💯 🎯
Left several comments, nothing major really.
| } | ||
| } | ||
|
|
||
| if ( isset( $data['installWooCommerce'] ) && $data['installWooCommerce'] ) { |
There was a problem hiding this comment.
isset( $data['installWooCommerce'] ) && $data['installWooCommerce']
can be simplified to:
! empty( $data['installWooCommerce'] )
| * | ||
| * @return bool True if installation succeeded, error object otherwise. | ||
| */ | ||
| static function _install_plugin( $slug ) { |
There was a problem hiding this comment.
Several things here:
- this duplicates a lot of what
Jetpack_JSON_API_Plugins_Install_Endpoint::install()does 😞 it would be really nice if we can abstract the installation functionality and reuse it in the plugins install endpoint and here as well. - why the underscore in the method name?
There was a problem hiding this comment.
why the underscore in the method name?
I was mimicking the (private) _process_onboarding() method's nomenclature here (since _install_plugin, while not private, is only used by that private method). I'm perfectly fine with dropping it (especially if I move it to a different file and it becomes a public function).
There was a problem hiding this comment.
Ah, makes sense. Anyway, I still don't see why we should be prefixing with an underscore - why not just making the method private or protected? That applies to _process_onboarding() too.
There was a problem hiding this comment.
I think the idea is just to signal "this method is private" as part of its name (so its immediately visible at call sites). A bit like including type information in a variable name (can't think of anything really ugly now, maybe something like counter_int or __super_ugly_struct_t or CFooBarSubClass 😛).
There was a problem hiding this comment.
I still don't follow why prefixing with an underscore would be more immediately visible than having the method defined with protected or private visibility. After all, visibility is specified before the method name. Not to mention that if a method should be considered private, it is beneficial that it should be implemented as such, so it's not inadvertently used as a public one.
| * | ||
| * @param string $slug Plugin slug. | ||
| * | ||
| * @return bool True if installation succeeded, error object otherwise. |
| include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; | ||
| include_once ABSPATH . 'wp-admin/includes/file.php'; | ||
| $upgrader = new Plugin_Upgrader( new Automatic_Upgrader_Skin() ); | ||
| $zip_url = "https://downloads.wordpress.org/plugin/{$slug}.latest-stable.zip"; |
There was a problem hiding this comment.
This essentially duplicates Jetpack_JSON_API_Plugins_Install_Endpoint::generate_wordpress_org_plugin_download_link() 😞
|
|
||
| } | ||
|
|
||
| /** |
There was a problem hiding this comment.
If we were to use code from there, we'd have to move it to a shared file; not sure that makes sense, since the install endpoint code also included bulk install logic which we don't need.
I this it makes complete sense to use a shared file; the fact that it was done like that in the install endpoint doesn't make it the best solution IMHO, especially in cases like this, where we're forced to duplicate code because of this decision.
I would assume that any plugin installation/activation/deactivation helper methods would not be defined in the endpoint itself. Rationale: see how the same is done in Jetpack_JSON_API_Plugins_Install_Endpoint, and that prevents us from reusing this functionality.
I'd prefer moving these methods in their own library class, just like Jetpack_Widgets, and load that library with jetpack_require_lib() when we need it. We could eventually migrate the endpoint to use these helpers afterwards.
There was a problem hiding this comment.
Started de-duping PR #8464, to be merged before this one.
| require_once ABSPATH . 'wp-admin/includes/plugin.php'; | ||
| } | ||
|
|
||
| $WOOCOMMERCE_ID = 'woocommerce/woocommerce.php'; |
There was a problem hiding this comment.
Naming nit: if we have those defined as variables, let's lowercase them in order to conform to the coding standards.
These could make a good use of class constants if we move those methods to a separate library class - in that case we could keep the uppercase names.
| if ( is_wp_error( $installed ) ) { | ||
| return $installed; | ||
| } | ||
| return activate_plugin( $WOOCOMMERCE_ID ); |
There was a problem hiding this comment.
activate_plugin will return null on successful activation (yeah, it's weird, I agree), we need to account for that and return true in that case.
| } | ||
| return activate_plugin( $WOOCOMMERCE_ID ); | ||
| } else if ( ! is_plugin_active( $WOOCOMMERCE_ID ) ) { | ||
| return activate_plugin( $WOOCOMMERCE_ID ); |
There was a problem hiding this comment.
activate_plugin will return null on successful activation (yeah, it's weird, I agree), we need to account for that and return true in that case.
Perhaps we can alter both return activate_plugin cases to $activated = activate_plugin( $WOOCOMMERCE_ID );, and then have a single check that relies on ! is_wp_error( $activated ) before actually returning true at the end of the method.
| * @return bool True if installation succeeded, error object otherwise. | ||
| */ | ||
| static function _install_plugin( $slug ) { | ||
| if ( is_multisite() && ! current_user_can( 'manage_network' ) ) { |
There was a problem hiding this comment.
Maybe a good idea to have a ! current_user_can( 'install_plugins' ) permission check too (for both multisites and single sites)?
| if ( is_wp_error( $installed ) ) { | ||
| return $installed; | ||
| } | ||
| return activate_plugin( $WOOCOMMERCE_ID ); |
There was a problem hiding this comment.
activate_plugin does not check for any capabilities, so before calling it, we should check whether the user can actually activate plugins (current_user_can( 'activate_plugins' )).
|
Closing in favor of the less redundant #8482. |
Counterpart to Automattic/wp-calypso#21237.
Code mostly stolen from https://github.com/Automattic/jetpack-onboarding/blob/06c6c51417b95d7b766ee5aad762769b9c208571/class.jetpack-onboarding-end-points.php#L582-L615. I tried to find prior art for plugin installation in Jetpack itself, but only found a dedicated endpoint. If we were to use code from there, we'd have to move it to a shared file; not sure that makes sense, since the install endpoint code also included bulk install logic which we don't need.
I've also noted that @tyxla left some comments on the PR that originally added WooCommerce installation to the JPO plugin, but I don't know the mentioned core functions well enough to make sense of it 😳.