PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / trunk
Booking for Appointments and Events Calendar – Amelia vtrunk
2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Infrastructure / WP / Integrations / PluginInstaller.php
ameliabooking / src / Infrastructure / WP / Integrations Last commit date
IvyForms 2 weeks ago WooCommerce 1 year ago PluginInstaller.php 2 weeks ago
PluginInstaller.php
246 lines
1 <?php
2
3 namespace AmeliaBooking\Infrastructure\WP\Integrations;
4
5 use Plugin_Upgrader;
6 use WP_Ajax_Upgrader_Skin;
7 use WP_Error;
8
9 /**
10 * Plugin Installer Service
11 *
12 * Handles the installation and activation of WordPress plugins
13 */
14 class PluginInstaller
15 {
16 /**
17 * Map of allowed plugins to install
18 *
19 * @var array<string, string>
20 */
21 private static array $allowedPlugins = [
22 'ivyforms' => 'ivyforms/ivyforms.php',
23 ];
24
25 /**
26 * Check if plugin is allowed to be installed
27 *
28 * @param string $pluginSlug
29 *
30 * @return bool
31 */
32 public static function isPluginAllowed(string $pluginSlug): bool
33 {
34 return isset(self::$allowedPlugins[$pluginSlug]);
35 }
36
37 /**
38 * Get plugin file path
39 *
40 * @param string $pluginSlug
41 *
42 * @return string|null
43 */
44 public static function getPluginFile(string $pluginSlug): ?string
45 {
46 return self::$allowedPlugins[$pluginSlug] ?? null;
47 }
48
49 /**
50 * Check if plugin is already installed
51 *
52 * @param string $pluginSlug
53 *
54 * @return bool
55 */
56 public static function isPluginInstalled(string $pluginSlug): bool
57 {
58 $pluginFile = self::getPluginFile($pluginSlug);
59
60 return $pluginFile !== null && file_exists(WP_PLUGIN_DIR . '/' . $pluginFile);
61 }
62
63 /**
64 * Check if plugin is active
65 *
66 * @param string $pluginSlug
67 *
68 * @return bool
69 */
70 public static function isPluginActive(string $pluginSlug): bool
71 {
72 if (!function_exists('is_plugin_active')) {
73 require_once ABSPATH . 'wp-admin/includes/plugin.php';
74 }
75
76 $pluginFile = self::getPluginFile($pluginSlug);
77
78 return $pluginFile !== null && is_plugin_active($pluginFile);
79 }
80
81 /**
82 * Activate a plugin
83 *
84 * @param string $pluginSlug
85 *
86 * @return array
87 */
88 public static function activatePlugin(string $pluginSlug)
89 {
90 $activated = activate_plugin(self::getPluginFile($pluginSlug) ?? '');
91
92 if (is_wp_error($activated)) {
93 return [
94 'success' => false,
95 'message' => 'Plugin failed to activate: ' . $activated->get_error_message(),
96 ];
97 }
98
99 return [
100 'success' => true,
101 'message' => 'Plugin activated successfully',
102 ];
103 }
104
105 /**
106 * Get plugin information from WordPress.org
107 *
108 * @param string $pluginSlug
109 *
110 * @return object|WP_Error
111 */
112 public static function getPluginInfo(string $pluginSlug)
113 {
114 if (!function_exists('plugins_api')) {
115 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
116 }
117
118 return plugins_api('plugin_information', [
119 'slug' => $pluginSlug,
120 'fields' => [
121 'short_description' => false,
122 'sections' => false,
123 'requires' => false,
124 'rating' => false,
125 'ratings' => false,
126 'downloaded' => false,
127 'download_link' => true,
128 'last_updated' => false,
129 'added' => false,
130 'tags' => false,
131 'compatibility' => false,
132 'homepage' => false,
133 'donate_link' => false,
134 ],
135 ]);
136 }
137
138 /**
139 * Install plugin from download URL
140 *
141 * @param string $downloadUrl
142 *
143 * @return bool|WP_Error
144 */
145 public static function installPlugin(string $downloadUrl)
146 {
147 self::loadRequiredFiles();
148
149 $upgrader = new Plugin_Upgrader(new WP_Ajax_Upgrader_Skin());
150
151 return $upgrader->install($downloadUrl);
152 }
153
154 /**
155 * Install and activate plugin
156 *
157 * @param string $pluginSlug
158 *
159 * @return array
160 */
161 public static function installAndActivatePlugin(string $pluginSlug): array
162 {
163 if (!self::isPluginAllowed($pluginSlug)) {
164 return [
165 'success' => false,
166 'message' => 'Plugin is not allowed',
167 ];
168 }
169
170 if (!current_user_can('install_plugins')) {
171 return [
172 'success' => false,
173 'message' => 'Insufficient permissions to install plugins',
174 ];
175 }
176
177 // Get plugin info from WordPress.org
178 $api = self::getPluginInfo($pluginSlug);
179
180 if (is_wp_error($api)) {
181 return [
182 'success' => false,
183 'message' => 'Failed to get plugin information: ' . $api->get_error_message(),
184 ];
185 }
186
187 // Install the plugin
188 $installed = self::installPlugin($api->download_link);
189
190 if (is_wp_error($installed)) {
191 return [
192 'success' => false,
193 'message' => 'Failed to install plugin: ' . $installed->get_error_message(),
194 ];
195 }
196
197 if (!$installed) {
198 return [
199 'success' => false,
200 'message' => 'Failed to install plugin',
201 ];
202 }
203
204 // Activate the plugin
205 $activated = self::activatePlugin($pluginSlug);
206
207 if (!$activated['success']) {
208 return [
209 'success' => false,
210 'message' => 'Plugin installed but failed to activate: ' . $activated['message'],
211 ];
212 }
213
214 return [
215 'success' => true,
216 'message' => 'Plugin installed and activated successfully',
217 ];
218 }
219
220 /**
221 * Load required WordPress files for plugin installation
222 *
223 * @return void
224 */
225 private static function loadRequiredFiles(): void
226 {
227 // phpcs:disable
228 if (file_exists(ABSPATH . 'wp-admin/includes/file.php')) {
229 require_once ABSPATH . 'wp-admin/includes/file.php';
230 }
231
232 if (file_exists(ABSPATH . 'wp-admin/includes/misc.php')) {
233 require_once ABSPATH . 'wp-admin/includes/misc.php';
234 }
235
236 if (file_exists(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php')) {
237 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
238 }
239
240 if (file_exists(ABSPATH . 'wp-admin/includes/plugin-install.php')) {
241 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
242 }
243 // phpcs:enable
244 }
245 }
246