Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 149
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ThemeInstallerController
0.00% covered (danger)
0.00%
0 / 149
0.00% covered (danger)
0.00%
0 / 7
272
0.00% covered (danger)
0.00%
0 / 1
 register_routes
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 1
2
 get_expedite_args
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 get_install_theme_args
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
2
 get_status_args
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 install
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
30
 get_status
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
20
 expedite
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2namespace NewfoldLabs\WP\Module\Installer\RestApi;
3
4use NewfoldLabs\WP\Module\Installer\Permissions;
5use NewfoldLabs\WP\Module\Installer\Services\ThemeInstaller;
6use NewfoldLabs\WP\Module\Installer\TaskManagers\ThemeInstallTaskManager;
7use NewfoldLabs\WP\Module\Installer\Tasks\ThemeInstallTask;
8
9/**
10 * Controller defining API's for theme install related functionalities.
11 */
12class ThemeInstallerController extends \WP_REST_Controller {
13    /**
14     * The namespace of this controller's route.
15     *
16     * @var string
17     */
18    protected $namespace = 'newfold-installer/v1';
19
20    /**
21     * The base of this controller's route.
22     *
23     * @var string
24     */
25    protected $rest_base = '/themes';
26
27    /**
28     * Register the controller routes.
29     */
30    public function register_routes() {
31
32        \register_rest_route(
33            $this->namespace,
34            $this->rest_base . '/install',
35            array(
36                array(
37                    'methods'             => \WP_REST_Server::CREATABLE,
38                    'callback'            => array( $this, 'install' ),
39                    'args'                => $this->get_install_theme_args(),
40                    'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ),
41                ),
42            )
43        );
44
45        \register_rest_route(
46            $this->namespace,
47            $this->rest_base . '/status',
48            array(
49                array(
50                    'methods'             => \WP_REST_Server::READABLE,
51                    'callback'            => array( $this, 'get_status' ),
52                    'args'                => $this->get_status_args(),
53                    'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ),
54                ),
55            )
56        );
57
58        \register_rest_route(
59            $this->namespace,
60            $this->rest_base . '/expedite',
61            array(
62                array(
63                    'methods'             => \WP_REST_Server::CREATABLE,
64                    'callback'            => array( $this, 'expedite' ),
65                    'args'                => $this->get_expedite_args(),
66                    'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ),
67                ),
68            )
69        );
70    }
71
72    /**
73     * Get args for the expedite route.
74     *
75     * @return array
76     */
77    public static function get_expedite_args() {
78        return array(
79            'theme'    => array(
80                'type'     => 'string',
81                'required' => true,
82            ),
83            'activate' => array(
84                'type'    => 'boolean',
85                'default' => true,
86            ),
87        );
88    }
89
90    /**
91     * Get args for the install route.
92     *
93     * @return array
94     */
95    public function get_install_theme_args() {
96        return array(
97            'theme'    => array(
98                'type'     => 'string',
99                'required' => true,
100            ),
101            'activate' => array(
102                'type'    => 'boolean',
103                'default' => false,
104            ),
105            'queue'    => array(
106                'type'    => 'boolean',
107                'default' => true,
108            ),
109            'priority' => array(
110                'type'    => 'integer',
111                'default' => 0,
112            ),
113        );
114    }
115
116    /**
117     * Get the theme status check arguments.
118     *
119     * @return array
120     */
121    public function get_status_args() {
122        return array(
123            'theme'     => array(
124                'type'     => 'string',
125                'required' => true,
126            ),
127            'activated' => array(
128                'type'    => 'boolean',
129                'default' => true,
130            ),
131        );
132    }
133
134    /**
135     * Install the requested theme via a slug (theme).
136     *
137     * @param \WP_REST_Request $request The request object.
138     *
139     * @return \WP_REST_Response|\WP_Error
140     */
141    public static function install( \WP_REST_Request $request ) {
142        $theme    = $request->get_param( 'theme' );
143        $activate = $request->get_param( 'activate' );
144        $queue    = $request->get_param( 'queue' );
145        $priority = $request->get_param( 'priority' );
146
147        // Checks if a theme with the given slug and activation criteria already exists.
148        if ( ThemeInstaller::exists( $theme, $activate ) ) {
149            return new \WP_REST_Response(
150                array(),
151                200
152            );
153        }
154
155        // Queue the theme install if specified in the request.
156        if ( $queue ) {
157            ThemeInstallTaskManager::add_to_queue(
158                new ThemeInstallTask(
159                    $theme,
160                    $activate,
161                    $priority
162                )
163            );
164
165            return new \WP_REST_Response(
166                array(),
167                202
168            );
169        }
170
171        // Execute the task if it need not be queued.
172        $theme_install_task = new ThemeInstallTask( $theme, $activate );
173
174        $status = $theme_install_task->execute();
175        if ( ! \is_wp_error( $status ) ) {
176            return new \WP_REST_Response(
177                array(),
178                200
179            );
180        }
181
182        // Handle race condition, incase it got installed in between.
183        $code = $status->get_error_code();
184        if ( 'folder_exists' !== $code ) {
185            return $status;
186        }
187
188        return new \WP_REST_Response(
189            array(),
190            200
191        );
192    }
193
194    /**
195     * Returns the status of a given theme slug.
196     *
197     * @param \WP_REST_Request $request The request object
198     *
199     * @return \WP_REST_Response
200     */
201    public function get_status( \WP_REST_Request $request ) {
202        $theme     = $request->get_param( 'theme' );
203        $activated = $request->get_param( 'activated' );
204
205        if ( ThemeInstaller::exists( $theme, $activated ) ) {
206            return new \WP_REST_Response(
207                array(
208                    'status' => $activated ? 'activated' : 'installed',
209                ),
210                200
211            );
212        }
213
214        $position_in_queue = ThemeInstallTaskManager::status( $theme );
215
216        if ( false !== $position_in_queue ) {
217            return new \WP_REST_Response(
218                array(
219                    'status'   => 'installing',
220                    'estimate' => ( ( $position_in_queue + 1 ) * 10 ),
221                ),
222                200
223            );
224        }
225
226        return new \WP_REST_Response(
227            array(
228                'status' => 'inactive',
229            ),
230            200
231        );
232    }
233
234    /**
235     * Expedites an existing ThemeInstallTask with a given slug.
236     *
237     * @param \WP_REST_Request $request The request object
238     * @return \WP_REST_Response
239     */
240    public function expedite( \WP_REST_Request $request ) {
241        $theme    = $request->get_param( 'theme' );
242        $activate = $request->get_param( 'activate' );
243
244        if ( ThemeInstaller::exists( $theme, $activate ) ) {
245            return new \WP_REST_Response(
246                array(),
247                200
248            );
249        }
250
251        if ( ThemeInstallTaskManager::expedite( $theme ) ) {
252            return new \WP_REST_Response(
253                array(),
254                200
255            );
256        }
257
258        return new \WP_REST_Response(
259            array(),
260            400
261        );
262    }
263}