Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 62
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ThemeInstallTaskManager
0.00% covered (danger)
0.00%
0 / 62
0.00% covered (danger)
0.00%
0 / 5
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 expedite
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
30
 install
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
30
 add_to_queue
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
 complete
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace NewfoldLabs\WP\Module\Installer\TaskManagers;
4
5use NewfoldLabs\WP\Module\Installer\Data\Options;
6use NewfoldLabs\WP\Module\Installer\Tasks\ThemeInstallTask;
7use NewfoldLabs\WP\Module\Installer\Models\PriorityQueue;
8
9/**
10 * Manages the execution of ThemeInstallTasks.
11 */
12class ThemeInstallTaskManager extends AbstractTaskManager {
13
14    /**
15     * Name of the ThemeInstallTaskManager Queue.
16     *
17     * @var string
18     */
19    protected static $queue_name = 'theme_install_queue';
20
21    /**
22     * Name of the ThemeInstallTaskManager Hook.
23     *
24     * @var string
25     */
26    protected static $hook_name = 'nfd_module_installer_theme_install_cron';
27
28    /**
29     * ThemeInstallTaskManager constructor.
30     */
31    public function __construct() {
32        parent::__construct();
33
34        // Ten second cron hook
35        add_action( self::$hook_name, array( $this, 'install' ) );
36
37        // Register the cron task
38        if ( ! wp_next_scheduled( self::$hook_name ) ) {
39            wp_schedule_event( time(), 'ten_seconds', self::$hook_name );
40        }
41    }
42
43    /**
44     * Expedites an existing ThemeInstallTask with a given slug.
45     *
46     * @param string $theme_slug The theme slug to expedite.
47     * @return boolean
48     */
49    public static function expedite( $theme_slug ) {
50        $themes            = \get_option( Options::get_option_name( self::$queue_name ), array() );
51        $position_in_queue = array_search( $theme_slug, array_column( $themes, 'slug' ), true );
52        if ( false === $position_in_queue ) {
53            return false;
54        }
55
56        $theme_to_install = $themes[ $position_in_queue ];
57        unset( $themes[ $position_in_queue ] );
58        $themes = array_values( $themes );
59        \update_option( Options::get_option_name( self::$queue_name ), $themes );
60
61        $theme_install_task = new ThemeInstallTask(
62            $theme_to_install['slug'],
63            $theme_to_install['activate'],
64            $theme_to_install['priority'],
65            $theme_to_install['retries']
66        );
67
68        // Update status to the current slug being installed.
69        \update_option( Options::get_option_name( 'theme_init_status' ), $theme_install_task->get_slug() );
70
71        // Execute the ThemeInstallTask.
72        $status = $theme_install_task->execute();
73        if ( \is_wp_error( $status ) ) {
74
75            // If there is an error, then increase the retry count for the task.
76            $theme_install_task->increment_retries();
77
78            /*
79                If the number of retries have not exceeded the limit
80                then re-queue the task at the end of the queue to be retried.
81            */
82            if ( $theme_install_task->get_retries() <= self::$retry_limit ) {
83                array_push( $themes, $theme_install_task->to_array() );
84            }
85        }
86
87        // If there are no more themes to be installed then change the status to completed.
88        if ( empty( $themes ) ) {
89            \update_option( Options::get_option_name( 'theme_init_status' ), 'completed' );
90        }
91        // Update the theme install queue.
92        \update_option( Options::get_option_name( self::$queue_name ), $themes );
93
94        return true;
95    }
96
97    /**
98     * Queue out a ThemeInstallTask with the highest priority in the theme install queue and execute it.
99     *
100     * @return array|false
101     */
102    public function install() {
103        /*
104        Get the theme install tasks queued up to be installed, the ThemeInstallTask gets
105        converted to an associative array before storing it in the option.
106        */
107        $themes = \get_option( Options::get_option_name( self::$queue_name ), array() );
108
109        /*
110        Conversion of the max heap to an array will always place the ThemeInstallTask with the highest
111        priority at the beginning of the array
112        */
113        $theme_to_install = array_shift( $themes );
114        if ( ! $theme_to_install ) {
115            self::complete();
116            return true;
117        }
118
119        // Recreate the ThemeInstallTask from the associative array.
120        $theme_install_task = new ThemeInstallTask(
121            $theme_to_install['slug'],
122            $theme_to_install['activate'],
123            $theme_to_install['priority'],
124            $theme_to_install['retries']
125        );
126
127        // Update status to the current slug being installed.
128        \update_option( Options::get_option_name( 'theme_init_status' ), $theme_install_task->get_slug() );
129
130        // Execute the ThemeInstallTask.
131        $status = $theme_install_task->execute();
132        if ( \is_wp_error( $status ) ) {
133
134            // If there is an error, then increase the retry count for the task.
135            $theme_install_task->increment_retries();
136
137            /*
138                If the number of retries have not exceeded the limit
139                then re-queue the task at the end of the queue to be retried.
140            */
141            if ( $theme_install_task->get_retries() <= self::$retry_limit ) {
142                array_push( $themes, $theme_install_task->to_array() );
143            }
144        }
145
146        // If there are no more themes to be installed then change the status to completed.
147        if ( empty( $themes ) ) {
148            self::complete();
149        }
150
151        // Update the theme install queue.
152        return \update_option( Options::get_option_name( self::$queue_name ), $themes );
153    }
154
155    /**
156     * Adds a new ThemeInstallTask to the Theme Install queue.
157     * The Task will be inserted at an appropriate position in the queue based on it's priority.
158     *
159     * @param ThemeInstallTask $theme_install_task Theme Install Task to add to the queue
160     * @return array|false
161     */
162    public static function add_to_queue( ThemeInstallTask $theme_install_task ) {
163        /*
164        Get the ThemeInstallTasks queued up to be installed, the ThemeInstallTask gets
165        converted to an associative array before storing it in the option.
166        */
167        $themes = \get_option( Options::get_option_name( self::$queue_name ), array() );
168
169        $queue = new PriorityQueue();
170        foreach ( $themes as $queued_theme ) {
171            /*
172            Check if there is an already existing ThemeInstallTask in the queue
173            for a given slug and activation criteria.
174            */
175            if ( $queued_theme['slug'] === $theme_install_task->get_slug()
176                && $queued_theme['activate'] === $theme_install_task->get_activate() ) {
177                return false;
178            }
179            $queue->insert( $queued_theme, $queued_theme['priority'] );
180        }
181
182        // Insert a new ThemeInstallTask at the appropriate position in the queue.
183        $queue->insert(
184            $theme_install_task->to_array(),
185            $theme_install_task->get_priority()
186        );
187
188        return \update_option( Options::get_option_name( self::$queue_name ), $queue->to_array() );
189    }
190
191
192    /**
193     * Clear all the hook scheduling and update the status option
194     *
195     * @return bool
196     */
197    private static function complete() {
198        wp_clear_scheduled_hook( self::get_hook_name() );
199        return \update_option( Options::get_option_name( 'theme_init_status' ), 'completed' );
200    }
201}