Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
PluginUninstallTaskManager
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 4
240
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
 add_ten_seconds_schedule
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 uninstall
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
20
 add_to_queue
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2
3namespace NewfoldLabs\WP\Module\Installer\TaskManagers;
4
5use NewfoldLabs\WP\Module\Installer\Data\Plugins;
6use NewfoldLabs\WP\Module\Installer\Data\Options;
7use NewfoldLabs\WP\Module\Installer\Models\PriorityQueue;
8use NewfoldLabs\WP\Module\Installer\Tasks\PluginUninstallTask;
9use NewfoldLabs\WP\Module\Installer\Services\PluginUninstaller;
10
11/**
12 * Manages the execution of PluginUninstallTasks.
13 */
14class PluginUninstallTaskManager extends AbstractTaskManager {
15
16    /**
17     * The number of times a PluginUninstallTask can be retried.
18     *
19     * @var int
20     */
21    protected static $retry_limit = 2;
22
23    /**
24     * Name of the PluginUninstallTask Queue.
25     *
26     * @var string
27     */
28    protected static $queue_name = 'plugin_uninstall_queue';
29
30    /**
31     * Name of the PluginUninstallTask Hook.
32     *
33     * @var string
34     */
35    protected static $hook_name = 'nfd_module_installer_plugin_uninstall_cron';
36
37    /**
38     * PluginUninstallTaskManager constructor.
39     */
40    public function __construct() {
41        parent::__construct();
42
43        // Ten second cron hook
44        add_action( self::$hook_name, array( $this, 'uninstall' ) );
45
46        // Register the cron task
47        if ( ! wp_next_scheduled( self::$hook_name ) ) {
48            wp_schedule_event( time(), 'ten_seconds', self::$hook_name );
49        }
50    }
51
52
53    /**
54     * Adds ten seconds option in the cron schedule.
55     *
56     * @param array $schedules Cron Schedule duration
57     * @return array
58     */
59    public function add_ten_seconds_schedule( $schedules ) {
60        if ( ! array_key_exists( 'ten_seconds', $schedules ) || 10 !== $schedules['ten_seconds']['interval'] ) {
61            $schedules['ten_seconds'] = array(
62                'interval' => 10,
63                'display'  => __( 'Once Every Ten Seconds', 'wp-module-installer' ),
64            );
65        }
66
67        return $schedules;
68    }
69
70    /**
71     * Queue out a PluginUninstallTask with the highest priority in the plugin uninstall queue and execute it.
72     *
73     * @return array|false
74     */
75    public function uninstall() {
76        /*
77        Get the plugins queued up to be uninstalled, the PluginUninstall task gets
78        converted to an associative array before storing it in the option.
79        */
80        $plugins = \get_option( Options::get_option_name( self::$queue_name ), array() );
81
82        /*
83        Conversion of the max heap to an array will always place the PluginUninstallTask with the highest
84        priority at the beginning of the array
85        */
86        $plugin_to_uninstall = array_shift( $plugins );
87        if ( ! $plugin_to_uninstall ) {
88            wp_unschedule_event( self::get_hook_name() );
89            return true;
90        }
91
92        // Update the plugin uninstall queue.
93        \update_option( Options::get_option_name( self::$queue_name ), $plugins );
94
95        // Recreate the PluginInstall task from the associative array.
96        $plugin_uninstall_task = new PluginUninstallTask(
97            $plugin_to_uninstall['slug'],
98            $plugin_to_uninstall['priority'],
99            $plugin_to_uninstall['retries']
100        );
101
102        // Execute the PluginUninstall Task.
103        $status = $plugin_uninstall_task->execute();
104        if ( \is_wp_error( $status ) ) {
105
106            // If there is an error, then increase the retry count for the task.
107            $plugin_uninstall_task->increment_retries();
108
109            /*
110                If the number of retries have not exceeded the limit
111                then re-queue the task at the end of the queue to be retried.
112            */
113            if ( $plugin_uninstall_task->get_retries() <= self::$retry_limit ) {
114                array_push( $plugins, $plugin_uninstall_task->to_array() );
115
116                // Update the plugin install queue.
117                \update_option( Options::get_option_name( self::$queue_name ), $plugins );
118            }
119        }
120
121        return true;
122    }
123
124    /**
125     * Adds a new PluginUninstallTask to the Plugin Uninstall queue.
126     * The Task will be inserted at an appropriate position in the queue based on it's priority.
127     *
128     * @param PluginUninstallTask $plugin_uninstall_task Plugin Task Details
129     * @return array|false
130     */
131    public static function add_to_queue( PluginUninstallTask $plugin_uninstall_task ) {
132        /*
133        Get the plugins queued up to be uninstalled, the PluginUninstall task gets
134        converted to an associative array before storing it in the option.
135        */
136        $plugins = \get_option( Options::get_option_name( self::$queue_name ), array() );
137
138        $position_in_queue = PluginInstallTaskManager::status( $plugin_uninstall_task->get_slug() );
139        if ( false !== $position_in_queue && 0 !== $position_in_queue ) {
140            PluginInstallTaskManager::remove_from_queue(
141                $plugin_uninstall_task->get_slug()
142            );
143
144            return true;
145        }
146
147        $plugin_list = Plugins::get_squashed();
148        // Gets the specified path for the Plugin from the predefined list
149        $plugin_path = $plugin_list[ $plugin_uninstall_task->get_slug() ]['path'];
150
151        if ( ! PluginUninstaller::is_plugin_installed( $plugin_path ) ) {
152            return true;
153        }
154
155        $queue = new PriorityQueue();
156        foreach ( $plugins as $queued_plugin ) {
157            /*
158            Check if there is an already existing PluginUninstallTask in the queue
159            for a given slug.
160            */
161            if ( $queued_plugin['slug'] === $plugin_uninstall_task->get_slug() ) {
162                return false;
163            }
164            $queue->insert( $queued_plugin, $queued_plugin['priority'] );
165        }
166
167        // Insert a new PluginUninstallTask at the appropriate position in the queue.
168        $queue->insert(
169            $plugin_uninstall_task->to_array(),
170            $plugin_uninstall_task->get_priority()
171        );
172
173        return \update_option( Options::get_option_name( self::$queue_name ), $queue->to_array() );
174    }
175}