Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
18.60% covered (danger)
18.60%
8 / 43
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Jetpack_JSON_API_Themes_New_Endpoint
20.51% covered (danger)
20.51%
8 / 39
33.33% covered (danger)
33.33%
1 / 3
112.43
0.00% covered (danger)
0.00%
0 / 1
 validate_call
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
 validate_input
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 install
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 1
72
1<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3use Automattic\Jetpack\Automatic_Install_Skin;
4
5if ( ! defined( 'ABSPATH' ) ) {
6    exit( 0 );
7}
8
9require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
10require_once ABSPATH . 'wp-admin/includes/file.php';
11
12/**
13 * Themes new endpoint class.
14 *
15 * /sites/%s/themes/%s/install
16 *
17 * @phan-constructor-used-for-side-effects
18 */
19class Jetpack_JSON_API_Themes_New_Endpoint extends Jetpack_JSON_API_Themes_Endpoint {
20    use Jetpack_JSON_API_Attachment_Ownership_Trait;
21
22    /**
23     * Needed capabilities.
24     *
25     * @var string
26     */
27    protected $needed_capabilities = 'install_themes';
28
29    /**
30     * Action.
31     *
32     * @var string
33     */
34    protected $action = 'install';
35
36    /**
37     * Download links.
38     *
39     * @var array
40     */
41    protected $download_links = array();
42
43    /**
44     * Validate the call.
45     *
46     * @param int    $_blog_id - the blod ID.
47     * @param string $capability - the capability we're checking.
48     * @param bool   $check_manage_active - if managing capabilities is active.
49     *
50     * @return bool|WP_Error
51     */
52    protected function validate_call( $_blog_id, $capability, $check_manage_active = true ) {
53        $validate = parent::validate_call( $_blog_id, $capability, $check_manage_active );
54        if ( is_wp_error( $validate ) ) {
55            // Lets delete the attachment... if the user doesn't have the right permissions to do things.
56            // Only clean up an upload the caller actually owns. This runs *after* the capability check
57            // has already failed, so without the ownership guard any connected user could name someone
58            // else's attachment and have it hard-deleted on their behalf.
59            $args = $this->input();
60            if ( isset( $args['zip'][0]['id'] ) && is_scalar( $args['zip'][0]['id'] ) ) {
61                $attachment_id = (int) $args['zip'][0]['id'];
62                if ( true === $this->validate_attachment_ownership( $attachment_id ) ) {
63                    wp_delete_attachment( $attachment_id, true );
64                }
65            }
66        }
67
68        return $validate;
69    }
70
71    /**
72     * Validate the input.
73     *
74     * @param string $theme - the theme.
75     */
76    protected function validate_input( $theme ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
77        $this->bulk   = false;
78        $this->themes = array();
79    }
80
81    /**
82     * Install the theme.
83     *
84     * @return bool
85     */
86    public function install() {
87        $args = $this->input();
88
89        if ( isset( $args['zip'][0]['id'] ) ) {
90            $attachment_id = $args['zip'][0]['id'];
91            $local_file    = get_attached_file( $attachment_id );
92            if ( ! $local_file ) {
93                return new WP_Error( 'local-file-does-not-exist' );
94            }
95            $skin     = new Automatic_Install_Skin();
96            $upgrader = new Theme_Upgrader( $skin );
97
98            $pre_install_list = wp_get_themes();
99            $result           = $upgrader->install( $local_file );
100
101            // clean up.
102            wp_delete_attachment( $attachment_id, true );
103
104            if ( is_wp_error( $result ) ) {
105                return $result;
106            }
107
108            $after_install_list = wp_get_themes();
109            $plugin             = array_values( array_diff( array_keys( $after_install_list ), array_keys( $pre_install_list ) ) );
110
111            if ( ! $result ) {
112                $error_code = $skin->get_main_error_code();
113                $message    = $skin->get_main_error_message();
114                if ( empty( $message ) ) {
115                    $message = __( 'An unknown error occurred during installation', 'jetpack' );
116                }
117
118                if ( 'download_failed' === $error_code ) {
119                    $error_code = 'no_package';
120                }
121
122                return new WP_Error( $error_code, $message, 400 );
123            }
124
125            if ( empty( $plugin ) ) {
126                return new WP_Error( 'theme_already_installed' );
127            }
128
129            $this->themes            = $plugin;
130            $this->log[ $plugin[0] ] = $upgrader->skin->get_upgrade_messages();
131
132            return true;
133        }
134
135        return new WP_Error( 'no_theme_installed' );
136    }
137}