PluginProbe ʕ •ᴥ•ʔ
FAPI Member / 2.2.24
FAPI Member v2.2.24
2.2.33 2.2.32 trunk 1.9.47 2.1.18 2.2.24 2.2.25 2.2.26 2.2.28 2.2.29 2.2.30 2.2.31
fapi-member / src / Bootstrap.php
fapi-member / src Last commit date
Api 11 months ago Container 11 months ago Divi 11 months ago Elementor 11 months ago Mioweb 11 months ago Model 11 months ago Repository 11 months ago Service 11 months ago Templates 11 months ago Utils 11 months ago Bootstrap.php 11 months ago FapiMemberPlugin.php 11 months ago
Bootstrap.php
600 lines
1 <?php declare(strict_types = 1);
2
3 namespace FapiMember;
4
5 use FapiMember\Api\V1\RequestHandler;
6 use FapiMember\Api\V2\ApiController;
7 use FapiMember\Container\Container;
8 use FapiMember\Divi\FapiMemberDivi;
9 use FapiMember\Mioweb\FapiMemberMioweb;
10 use FapiMember\Model\Enums\Keys\OptionKey;
11 use FapiMember\Model\Enums\Types\MembershipChangeType;
12 use FapiMember\Model\Enums\Types\RequestMethodType;
13 use FapiMember\Model\Enums\UserPermission;
14 use FapiMember\Repository\MemberActivityRepository;
15 use FapiMember\Repository\MembershipChangeRepository;
16 use FapiMember\Repository\MembershipRepository;
17 use FapiMember\Service\ApiService;
18 use FapiMember\Service\ElementService;
19 use FapiMember\Service\RedirectService;
20 use FapiMember\Service\StatisticsService;
21 use FapiMember\Utils\DisplayHelper;
22 use FapiMember\Utils\PostTypeHelper;
23 use FapiMember\Utils\Random;
24 use FapiMember\Utils\ShortcodeSubstitutor;
25
26 final class Bootstrap
27 {
28
29 private FapiMemberPlugin $fapiMemberPlugin;
30
31 private FapiMemberDivi $fapiMemberDivi;
32
33 private FapiMemberMioweb $fapiMemberMioweb;
34
35 private ApiService $apiService;
36
37 private ElementService $elementService;
38
39 private RedirectService $redirectService;
40
41 private RequestHandler $requestHandler;
42
43 private ShortcodeSubstitutor $shortcodeSubstitutor;
44
45 private ApiController $apiController;
46
47 private MembershipRepository $membershipRepository;
48
49 private MembershipChangeRepository $membershipChangeRepository;
50
51 private MemberActivityRepository $memberActivityRepository;
52
53 private StatisticsService $statisticsService;
54
55 public function __construct(FapiMemberPlugin $fapiMemberPlugin)
56 {
57 $this->fapiMemberPlugin = $fapiMemberPlugin;
58 Container::set(FapiMemberPlugin::class, $fapiMemberPlugin);
59
60 $this->apiService = Container::get(ApiService::class);
61 $this->elementService = Container::get(ElementService::class);
62 $this->redirectService = Container::get(RedirectService::class);
63 $this->requestHandler = Container::get(RequestHandler::class);
64 $this->shortcodeSubstitutor = Container::get(ShortcodeSubstitutor::class);
65 $this->apiController = Container::get(ApiController::class);
66 $this->fapiMemberDivi = Container::get(FapiMemberDivi::class);
67 $this->fapiMemberMioweb = Container::get(FapiMemberMioweb::class);
68 $this->membershipRepository = Container::get(MembershipRepository::class);
69 $this->membershipChangeRepository = Container::get(MembershipChangeRepository::class);
70 $this->memberActivityRepository = Container::get(MemberActivityRepository::class);
71 $this->statisticsService = Container::get(StatisticsService::class);
72 }
73
74 public function initialize(): void
75 {
76 $this->addHooks();
77 $this->generateTokenIfNeeded();
78 $this->migrateCredentialsIfNeeded();
79
80 update_option(OptionKey::FAPI_MEMBER_VERSION, FAPI_MEMBER_PLUGIN_VERSION);
81 }
82
83 private function generateTokenIfNeeded(): void
84 {
85 $token = get_option(OptionKey::TOKEN, '');
86
87 if (!$token) {
88 update_option(OptionKey::TOKEN, Random::generate(20, 'A-Za-z'));
89 }
90 }
91
92 public function migrateCredentialsIfNeeded(): void
93 {
94 $oldVersion = get_option(OptionKey::FAPI_MEMBER_VERSION, '');
95
96 if (!empty($oldVersion)) {
97 return;
98 }
99
100 $fapiCredentials = get_option(OptionKey::API_CREDENTIALS, null);
101
102 if ((!empty($fapiCredentials))) {
103 return;
104 }
105
106 $apiUser = get_option(OptionKey::API_USER, null);
107 $apiKey = get_option(OptionKey::API_KEY, null);
108
109 if (empty($apiKey) || empty($apiUser)) {
110 return;
111 }
112
113 update_option(
114 OptionKey::API_CREDENTIALS,
115 json_encode(
116 [
117 [
118 'username' => $apiUser,
119 'token' => $apiKey,
120 ],
121 ]
122 )
123 );
124
125 $credentialsOk = $this->apiService->checkCredentials();
126 update_option(OptionKey::API_CHECKED, $credentialsOk);
127
128 if (!$credentialsOk) {
129 update_option(OptionKey::API_CREDENTIALS, '0');
130 }
131 }
132
133 private function addHooks(): void
134 {
135 $this->addInitHooks();
136 $this->addAdminHooks();
137 $this->registerUserFapiMemberTableColumn();
138
139 add_action('wp_enqueue_scripts', [$this, 'addPublicScripts']);
140
141 add_action('rest_api_init', [$this, 'addRestEndpoints']);
142
143 // adds meta boxed to setting page/post side bar
144 add_action('add_meta_boxes', [$this->elementService, 'addMetaBoxes']);
145 add_action('save_post', [$this->elementService, 'savePostMetadata']);
146
147 // check if page in fapi level
148 add_action('template_redirect', [$this->redirectService, 'checkPageForRedirects']);
149
150 // user profile
151 add_action('edit_user_profile', [$this->elementService, 'addUserMenuPage']);
152 add_action('plugins_loaded', [$this, 'initializeStatisticsIfNeeded']);
153
154 add_action('wp_enqueue_scripts', [$this, 'addPublicScripts']);
155
156 $this->addMiowebHooks();
157 $this->addDiviHooks();
158
159 add_image_size('level-selection', 300, 164, true);
160 add_filter('login_redirect', [$this->fapiMemberPlugin, 'loginRedirect'], 5, 3);
161 add_filter('show_admin_bar', [$this->elementService, 'hideAdminBar']);
162
163 // filters block to render by section and levels provided
164 add_filter(
165 'render_block',
166 function ($blockContent, $block) {
167 if (!isset($block['attrs']['hasSectionOrLevel'])) {
168 return $blockContent;
169 }
170
171 if (!isset($block['attrs']['fapiSectionAndLevels'])) {
172 return $blockContent;
173 }
174
175 if (DisplayHelper::shouldContentBeRendered(
176 (string) $block['attrs']['hasSectionOrLevel'],
177 $block['attrs']['fapiSectionAndLevels']
178 )) {
179 return $blockContent;
180 }
181
182 return '';
183 },
184 15,
185 2
186 );
187
188 // WPS hide login plugin
189 add_filter('whl_logged_in_redirect', [$this->redirectService, 'loggedInRedirect'], 1);
190 add_filter('whl_logged_in_redirect', [$this->redirectService, 'loggedInRedirect'], 1);
191 }
192
193 private function addInitHooks(): void
194 {
195 add_action('init', [$this, 'registerLevelsTaxonomy']);
196 add_action('init', [$this, 'registerRoles']);
197 add_action('init', [$this, 'addShortcodes']);
198 add_action('init', [$this->fapiMemberPlugin, 'checkTimedLevelUnlock']);
199 add_action('init', [$this->statisticsService, 'handleUserActive']);
200 }
201
202 private function addAdminHooks(): void
203 {
204 add_action('admin_init', [$this, 'registerSettings']);
205 add_action('admin_menu', [$this->elementService, 'addAdminMenu']);
206 add_action('admin_enqueue_scripts', [$this, 'addScripts']);
207 add_action('admin_enqueue_scripts', [$this, 'addApiNonce']);
208 add_action('admin_enqueue_scripts', [$this, 'checkFapiMemberPlusStatus']);
209 add_action('admin_enqueue_scripts', [$this, 'checkSimpleShopStatus']);
210
211 }
212
213 private function addMiowebHooks(): void
214 {
215 add_action('wp_ajax_open_element_setting', [$this->fapiMemberMioweb, 'addSetting']);
216 add_action('wp_ajax_open_row_setting', [$this->fapiMemberMioweb, 'addSetting']);
217 add_action('mw_page_init', [$this->fapiMemberMioweb, 'hideContentIfNeeded']);
218 }
219
220 public function addDiviHooks(): void
221 {
222 add_action('divi_extensions_init', [$this, 'initializeDiviExtension']);
223
224 add_filter('et_builder_get_parent_modules', [$this->fapiMemberDivi, 'addToggle']);
225
226 foreach ($this->fapiMemberDivi->allowedModuleSlugs as $slug) {
227 add_filter("et_pb_all_fields_unprocessed_" . $slug, [$this->fapiMemberDivi, 'addFields']);
228 }
229
230 add_filter('et_pb_module_content', [$this->fapiMemberDivi, 'hideElements'], 10, 4);
231 }
232
233 public function initializeDiviExtension(): void
234 {
235 require_once plugin_dir_path(__FILE__) . 'Divi/includes/FmDivi.php';
236 }
237
238 function addApiNonce(): void
239 {
240 if (current_user_can(UserPermission::REQUIRED_CAPABILITY)) {
241 $nonce = wp_create_nonce('wp_rest');
242 echo "<script>window.apiInternalAccessNonce = '{$nonce}'</script>";
243 }
244
245 }
246
247 function checkFapiMemberPlusStatus(): void
248 {
249 if (current_user_can(UserPermission::REQUIRED_CAPABILITY)) {
250 $licenceActive = $this->apiService->checkLicence();
251
252 echo "<script>
253 window.licenceActive = '{$licenceActive}'
254 </script>";
255 }
256 }
257
258 function checkSimpleShopStatus(): void
259 {
260 if (current_user_can(UserPermission::REQUIRED_CAPABILITY)) {
261 $simpleShopActive = is_plugin_active('simpleshop-cz/simpleshop-cz.php') && class_exists('Redbit\SimpleShop\WpPlugin\Group');
262
263 $ssSections = [];
264
265 if (!$simpleShopActive) {
266 echo "<script>
267 window.simpleShopToFAPIMember = false
268 </script>";
269
270 return;
271 }
272
273 $groups = new \Redbit\SimpleShop\WpPlugin\Group();
274
275 foreach ($groups->get_groups() as $groupId => $group) {
276 $group = new \Redbit\SimpleShop\WpPlugin\Group($groupId);
277
278 $ssSections[] = [
279 'id' => $group->id,
280 'name' => $group->name,
281 'users' => array_values(array_map(function ($user) use ($groupId) {
282 $membership = new \Redbit\SimpleShop\WpPlugin\Membership($user->ID);
283
284 return [
285 'id' => $user->ID,
286 'email' => $user->user_email,
287 'registered' => $membership->groups[$groupId]['subscription_date'] ?? null,
288 'until' => $membership->groups[$groupId]['valid_to'] ?? null,
289 ];
290 }, $group->get_users())),
291 ];
292 }
293
294 $pagesGroups = [];
295
296 $pages = get_posts([
297 'post_type' => 'page',
298 'numberposts' => -1,
299 ]);
300
301 $ss = \Redbit\SimpleShop\WpPlugin\SimpleShop::getInstance();
302
303 foreach ($pages as $page) {
304 $pagesGroups[] = [
305 'id' => $page->ID,
306 'name' => $page->post_title,
307 'groups' => $ss->get_access()->get_post_groups($page->ID),
308 ];
309 }
310
311 echo "<script>
312 window.simpleShopToFAPIMember = true
313 window.ssSections = " . json_encode($ssSections) . "
314 window.ssPagesGroups = " . json_encode($pagesGroups) . "
315 </script>";
316 }
317 }
318
319 public function addRestEndpoints(): void
320 {
321 $this->addRestEndpointV1('sections', 'handleApiSections', RequestMethodType::GET);
322 $this->addRestEndpointV1('sections-simple', 'handleApiSectionsSimple', RequestMethodType::GET);
323 $this->addRestEndpointV1('callback', 'handleApiCallback', RequestMethodType::POST);
324 $this->addRestEndpointV1('check-connection', 'handleApiCheckConnectionCallback', RequestMethodType::POST);
325 $this->addRestEndpointV1(
326 'list-forms/(?P<user>[^/]+(?:\+[^/]+)?)',
327 'handleApiListFormsCallback',
328 RequestMethodType::GET,
329 );
330 $this->addRestEndpointV1('list-users', 'handleApiUsernamesCallback', RequestMethodType::GET);
331
332 $this->addRestEndpointV2('sections');
333 $this->addRestEndpointV2('pages');
334 $this->addRestEndpointV2('emails');
335 $this->addRestEndpointV2('memberships');
336 $this->addRestEndpointV2('users');
337 $this->addRestEndpointV2('apiConnections');
338 $this->addRestEndpointV2('statistics');
339 }
340
341 public function addRestEndpointV2(
342 string $route
343 ): void
344 {
345 register_rest_route(
346 'fapi/v2',
347 '/' . $route,
348 [
349 'methods' => [RequestMethodType::GET, RequestMethodType::POST],
350 'callback' => [$this->apiController, 'handleRequest'],
351 'permission_callback' => function () {
352 return true;
353 },
354 ],
355 );
356 }
357
358 public function addRestEndpointV1(
359 string $route, string $functionName, string $method
360 ): void
361 {
362 register_rest_route(
363 'fapi/v1',
364 '/' . $route,
365 [
366 'methods' => $method,
367 'callback' => [$this->requestHandler, $functionName],
368 'permission_callback' => function () {
369 return true;
370 },
371 ],
372 );
373 }
374
375 public function addShortcodes(): void
376 {
377 add_shortcode('fapi-member-login', [$this->shortcodeSubstitutor, 'shortcodeLoginForm']);
378 add_shortcode('fapi-member-user', [$this->shortcodeSubstitutor, 'shortcodeUser']);
379 add_shortcode('fapi-member-user-section-expiration', [$this->shortcodeSubstitutor, 'shortcodeSectionExpirationDate']);
380 add_shortcode('fapi-member-level-unlock-date', [$this->shortcodeSubstitutor, 'shortcodeLevelUnlockDate']);
381 add_shortcode('fapi-member-unlock-level', [$this->shortcodeSubstitutor, 'shortcodeUnlockLevel']);
382 }
383
384 public function addScripts(): void
385 {
386 $this->registerStyles();
387 $this->registerScripts();
388
389 global $pagenow;
390
391 if ($pagenow === 'admin.php' || $pagenow === 'options-general.php') {
392 wp_enqueue_style('fapi-member-admin-font', '', [], FAPI_MEMBER_PLUGIN_VERSION);
393 wp_enqueue_style('fapi-member-swal-css', '', [], FAPI_MEMBER_PLUGIN_VERSION);
394 wp_enqueue_script('fapi-member-swal', '', [], FAPI_MEMBER_PLUGIN_VERSION);
395 wp_enqueue_script('fapi-member-swal-promise-polyfill', '', [], FAPI_MEMBER_PLUGIN_VERSION);
396 wp_enqueue_script('fapi-member-clipboard', '', [], FAPI_MEMBER_PLUGIN_VERSION);
397 wp_enqueue_script('fapi-member-main', '', [], FAPI_MEMBER_PLUGIN_VERSION);
398 }
399 if ($pagenow === 'user-edit.php') {
400 wp_enqueue_style('fapi-member-user-profile', '', [], FAPI_MEMBER_PLUGIN_VERSION);
401 wp_enqueue_script('fapi-member-main', '', [], FAPI_MEMBER_PLUGIN_VERSION);
402 }
403
404 wp_enqueue_script(
405 'fm-react-app',
406 trailingslashit(plugins_url('/', __FILE__)) . '../app/dist/bundle.js',
407 ['jquery', 'wp-element'],
408 FAPI_MEMBER_PLUGIN_VERSION,
409 true,
410 );
411
412 wp_localize_script('fm-react-app', 'environmentData', [
413 'timeZoneOffset' => get_option('gmt_offset'),
414 ]);
415 }
416
417 public function registerStyles(): void
418 {
419 wp_register_style(
420 'fapi-member-user-profile',
421 plugins_url('fapi-member/media/fapi-user-profile.css'),
422 [],
423 FAPI_MEMBER_PLUGIN_VERSION
424 );
425 wp_register_style(
426 'fapi-member-admin-font',
427 plugins_url('fapi-member/media/font/stylesheet.css'),
428 [],
429 FAPI_MEMBER_PLUGIN_VERSION
430 );
431 wp_register_style(
432 'fapi-member-swal-css',
433 plugins_url('fapi-member/media/dist/sweetalert2.min.css'),
434 [],
435 FAPI_MEMBER_PLUGIN_VERSION
436 );
437 wp_register_style(
438 'fapi-member-public-style',
439 plugins_url('fapi-member/media/fapi-member-public.css'),
440 [],
441 FAPI_MEMBER_PLUGIN_VERSION
442 );
443 }
444
445 public function registerScripts(): void
446 {
447 wp_register_script(
448 'fapi-member-swal',
449 plugins_url('fapi-member/media/dist/sweetalert2.js'),
450 [],
451 FAPI_MEMBER_PLUGIN_VERSION
452 );
453
454 wp_register_script(
455 'fapi-member-swal-promise-polyfill',
456 plugins_url('fapi-member/media/dist/polyfill.min.js'),
457 [],
458 FAPI_MEMBER_PLUGIN_VERSION
459 );
460
461 wp_register_script(
462 'fapi-member-clipboard',
463 plugins_url('fapi-member/media/dist/clipboard.min.js'),
464 [],
465 FAPI_MEMBER_PLUGIN_VERSION
466 );
467
468 if (FapiMemberPlugin::isDevelopment()) {
469 wp_register_script(
470 'fapi-member-main',
471 plugins_url('fapi-member/media/dist/fapi.dev.js'),
472 [],
473 FAPI_MEMBER_PLUGIN_VERSION
474 );
475 } else {
476 wp_register_script(
477 'fapi-member-main',
478 plugins_url('fapi-member/media/dist/fapi.dist.js'),
479 [],
480 FAPI_MEMBER_PLUGIN_VERSION
481 );
482 }
483 }
484
485 public
486 function addPublicScripts(): void
487 {
488 $this->registerPublicStyles();
489
490 wp_enqueue_style('fapi-member-public-style', '',
491 [],
492 FAPI_MEMBER_PLUGIN_VERSION);
493
494 if (defined('FAPI_SHOWING_LEVEL_SELECTION')) {
495 wp_register_style(
496 'fapi-member-public-levelselection-font',
497 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap',
498 [],
499 FAPI_MEMBER_PLUGIN_VERSION
500 );
501 wp_enqueue_style('fapi-member-public-levelselection-font', '',
502 [],
503 FAPI_MEMBER_PLUGIN_VERSION);
504 }
505 }
506
507 public function registerPublicStyles(): void
508 {
509 wp_register_style(
510 'fapi-member-public-style',
511 plugins_url('fapi-member/media/fapi-member-public.css'),
512 [],
513 FAPI_MEMBER_PLUGIN_VERSION
514 );
515 }
516
517 public function registerRoles(): void
518 {
519 if (get_role('member') === null) {
520 add_role('member', __('Člen', 'fapi-member'), get_role('subscriber')->capabilities);
521 }
522 }
523
524 public function registerSettings(): void
525 {
526 register_setting(
527 'options',
528 'fapiMemberApiEmail',
529 [
530 'type' => 'string',
531 'description' => __('Fapi Member - API e-mail', 'fapi-member'),
532 'show_in_rest' => false,
533 'default' => null,
534 ]
535 );
536 register_setting(
537 'options',
538 'fapiMemberApiKey',
539 [
540 'type' => 'string',
541 'description' => __('Fapi Member - API key', 'fapi-member'),
542 'show_in_rest' => false,
543 'default' => null,
544 ]
545 );
546 }
547
548 public function registerLevelsTaxonomy(): void
549 {
550 register_taxonomy(
551 'fapi_levels',
552 PostTypeHelper::getSupportedPostTypes(),
553 [
554 'public' => false,
555 'hierarchical' => true,
556 'show_ui' => false,
557 'show_in_rest' => false,
558 ]
559 );
560 }
561
562 public function initializeStatisticsIfNeeded(): void
563 {
564 if (!$this->membershipChangeRepository->tableExists()) {
565 $this->initializeMembershipChanges();
566 }
567
568 if (!$this->memberActivityRepository->tableExists()) {
569 $this->memberActivityRepository->createTableIfNeeded();
570 }
571 }
572
573 private function initializeMembershipChanges(): void
574 {
575 $this->membershipChangeRepository->createTableIfNeeded();
576
577 $memberships = $this->membershipRepository->getAll();
578
579 foreach ($memberships as $membershipsByUserId) {
580 foreach ($membershipsByUserId as $membership) {
581 $this->membershipChangeRepository->addChange(
582 $membership->toMembershipChange(
583 MembershipChangeType::CREATED,
584 $membership->getRegistered(),
585 )
586 );
587 }
588 }
589 }
590
591 public function registerUserFapiMemberTableColumn(): void
592 {
593 add_filter('manage_users_columns', [$this->elementService, 'addUserColumn']);
594 add_action('manage_users_custom_column', [$this->elementService, 'showUserColumnContent'], 10, 3);
595 add_action('show_user_profile', [$this->elementService, 'addUserProfileSection']);
596 add_action('edit_user_profile', [$this->elementService, 'addUserProfileSection']);
597 }
598
599 }
600