PluginProbe ʕ •ᴥ•ʔ
FAPI Member / trunk
FAPI Member vtrunk
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 / FapiMemberTools.php
fapi-member / src Last commit date
Api 1 day ago Container 2 years ago Deprecated 2 years ago Divi 1 year ago Elementor 7 months ago Email 3 years ago Email 2 2 years ago Mioweb 1 year ago Model 1 year ago Repository 3 weeks ago Service 1 day ago Templates 2 years ago Utils 1 day ago Utils 2 2 years ago services 2 2 years ago styles 2 2 years ago Bootstrap.php 1 day ago EmailTemplatesProvider.php 3 years ago FapiApi.php 2 years ago FapiClients.php 2 years ago FapiLevels.php 2 years ago FapiMemberPlugin.php 1 year ago FapiMemberTools.php 2 years ago FapiMembership.php 2 years ago FapiMembershipLoader.php 2 years ago FapiSanitization.php 2 years ago FapiTermEnvelope.php 4 years ago FapiUserUtils.php 3 years ago
FapiMemberTools.php
1000 lines
1 <?php
2
3 namespace FapiMember;
4
5 use FapiMember\Utils\PostTypeHelper;
6 use WP_User;
7 use function get_posts;
8 use function htmlentities;
9 use function in_array;
10 use function sprintf;
11
12 final class FapiMemberTools {
13
14
15 /** @var array<array<string>> */
16 private static $errorMap
17 = array(
18 'apiFormEmpty' => array( 'error', 'Je třeba zadat jak uživatelské jméno, tak API klíč.' ),
19 'apiFormSuccess' => array( 'success', 'Údaje pro API uloženy.' ),
20 'apiFormError' => array( 'error', 'Neplatné údaje pro API.' ),
21 'apiFormCredentialsExist' => array( 'error', 'Zadané údaje pro API se již používají.' ),
22 'apiFormTooManyCredentials' => array( 'error', 'Není možné propojit více než ' . FapiMemberPlugin::CONNECTED_API_KEYS_LIMIT . ' účtů.' ),
23 'apiFormCredentialsRemoved' => array( 'success', 'Účet byl odpojen.' ),
24 'sectionNameEmpty' => array( 'error', 'Název sekce je povinný.' ),
25 'levelNameOrParentEmpty' => array( 'error', 'Název úrovně a výběr sekce je povinný.' ),
26 'sectionNotFound' => array( 'error', 'Sekce nenalezena.' ),
27 'removeLevelSuccessful' => array( 'success', 'Sekce/úroveň smazána.' ),
28 'editLevelSuccessful' => array( 'success', 'Sekce/úroveň upravena.' ),
29 'levelIdOrToAddEmpty' => array( 'error', 'Zvolte prosím úroveň a stránky k přidání.' ),
30 'editLevelNoName' => array( 'error', 'Chyba změny sekce/úrovně.' ),
31 'editMailsRemoved' => array( 'success', 'Šablona emailu byla odebrána.' ),
32 'editMailsUpdated' => array( 'success', 'Šablona emailu byla upravena.' ),
33 'editOtherPagesRemoved' => array( 'success', 'Stránka byla nastavena.' ),
34 'editOtherPagesUpdated' => array( 'success', 'Stránka byla nastavena..' ),
35 'settingsSettingsUpdated' => array( 'success', 'Nastavení uložena.' ),
36 'settingsSettingsNoValidPage' => array( 'error', 'Stránka nenalezena.' ),
37 );
38
39 /**
40 * @return string
41 */
42 public static function showErrors() {
43 $errorKey = self::findValidErrorKey();
44
45 if ( $errorKey ) {
46 $e = self::$errorMap[ $errorKey ];
47
48 return sprintf( '<div class="notice notice-%s is-dismissible"><p>%s</p></div>', $e[0], $e[1] );
49 }
50
51 return '';
52 }
53
54 /**
55 * @return string|null
56 */
57 protected static function findValidErrorKey() {
58 if ( isset( $_GET['e'], self::$errorMap[ $_GET['e'] ] ) && is_string( $_GET['e'] ) ) {
59 return $_GET['e'];
60 }
61
62 return null;
63 }
64
65 /**
66 * @param string $subpage
67 * @param string $label
68 * @param string $activeSubpage
69 * @return string
70 */
71 public static function subSubmenuItem( $subpage, $label, $activeSubpage ) {
72 $classes = array( 'subsubmenuitem' );
73
74 if ( $activeSubpage === $subpage ) {
75 $classes[] = 'active';
76 }
77
78 $level = ( isset( $_GET['level'] ) ) ? self::sanitizeLevelId( $_GET['level'] ) : null;
79
80 if ( $level ) {
81 $tail = sprintf( '&level=%s', $level );
82 } else {
83 $tail = '';
84 }
85
86 return sprintf(
87 '<a href="%s%s" class="%s">%s</a>',
88 self::fapilink( $subpage ),
89 $tail,
90 implode( ' ', $classes ),
91 $label
92 );
93 }
94
95 /**
96 * @param int $levelId
97 * @return int|null
98 */
99 public static function sanitizeLevelId( $levelId ) {
100 global $FapiPlugin;
101 if ( ! is_numeric( $levelId ) ) {
102 return null;
103 }
104 $t = $FapiPlugin->levels()->loadById( $levelId );
105 if ( ! $t ) {
106 return null;
107 }
108
109 return (int) $levelId;
110 }
111
112 /**
113 * @param string $subpage
114 * @return string
115 */
116 public static function fapilink( $subpage ) {
117 return admin_url( sprintf( '/admin.php?page=fapi-member-options&subpage=%s', $subpage ) );
118 }
119
120 /**
121 * @return string
122 */
123 public static function help() {
124 return '
125 <div class="help">
126 <h3>Nápověda</h3>
127 <div class="inner">
128 <div>
129 <h4>Jak propojit plugin s FAPI?</h4>
130 <p>Prvním krokem ke zprovoznění členských sekcí je propojení pluginu s vaším účtem FAPI.</p>
131 <a href="https://napoveda.fapi.cz/article/97-fapi-member-propojeni-s-fapi" target="_blank" class="btn outline">Přečíst</a>
132 </div>
133 <div>
134 <h4>Jak vytvořit členskou sekci?</h4>
135 <p>Zde se dozvíte, co je to členská sekce nebo úroveň a jak ji správně nastavit.</p>
136 <a href="https://napoveda.fapi.cz/article/98-fapi-member-nastaveni-clenske-sekce" target="_blank" class="btn outline">Přečíst</a>
137 </div>
138 <div>
139 <h4>Jak přidat uživatele do členské sekce?</h4>
140 <p>Zjistěte, jak nastavit prodejní formulář FAPI, aby automaticky zakládal členství vašim klientům.</p>
141 <a href="https://napoveda.fapi.cz/article/99-fapi-member-zakladani-clenstvi" target="_blank" class="btn outline">Přečíst</a>
142 </div>
143 </div>
144 </div>
145 ';
146 }
147
148 /**
149 * @return void
150 */
151 public static function levels() {
152 global $FapiPlugin;
153 $envelopes = $FapiPlugin->levels()->loadAsTermEnvelopes();
154
155 $lis = array();
156 $actions = '<button class="edit"></button><button class="remove"></button><button class="up"></button><button class="down"></button>';
157
158 foreach ( $envelopes as $envelope ) {
159 $term = $envelope->getTerm();
160 $under = array();
161 if ( $term->parent === 0 ) {
162 foreach ( $envelopes as $underEnvelope ) {
163 $underTerm = $underEnvelope->getTerm();
164 if ( $underTerm->parent === $term->term_id ) {
165 $under[] = sprintf(
166 '<li data-id="%s" data-name="%s"><span title="%s">%s</span>%s</li>',
167 $underTerm->term_id,
168 htmlentities( $underTerm->name ),
169 $underTerm->term_id,
170 self::trimName( $underTerm->name ),
171 $actions
172 );
173 }
174 }
175 $lis[] = sprintf(
176 '<li data-id="%s" data-name="%s"><span title="%s">%s</span>%s<ol>%s</ol></li>',
177 $term->term_id,
178 htmlentities( $term->name ),
179 $term->term_id,
180 self::trimName( $term->name ),
181 $actions,
182 implode( '', $under )
183 );
184 }
185 }
186
187 ?>
188 <div class="levels">
189 <ol>
190 <?php echo implode( '', $lis ); ?>
191 </ol>
192 </div>
193 <form method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>" id="LevelRemoveForm">
194 <input type="hidden" name="action" value="fapi_member_remove_level">
195 <input type="hidden" name="fapi_member_remove_level_nonce"
196 value="<?php echo wp_create_nonce( 'fapi_member_remove_level_nonce' ); ?>">
197 <input type="hidden" name="level_id" value="">
198 </form>
199 <form method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>" id="LevelEditForm">
200 <input type="hidden" name="action" value="fapi_member_edit_level">
201 <input type="hidden" name="fapi_member_edit_level_nonce"
202 value="<?php echo wp_create_nonce( 'fapi_member_edit_level_nonce' ); ?>">
203 <input type="hidden" name="name" value="">
204 <input type="hidden" name="level_id" value="">
205 </form>
206 <form method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>" id="LevelOrderForm">
207 <input type="hidden" name="action" value="fapi_member_order_level">
208 <input type="hidden" name="fapi_member_order_level_nonce"
209 value="<?php echo wp_create_nonce( 'fapi_member_order_level_nonce' ); ?>">
210 <input type="hidden" name="direction" value="">
211 <input type="hidden" name="id" value="">
212 </form>
213 <?php
214 }
215
216 /**
217 * @param string $name
218 * @param int $chars
219 * @return string
220 */
221 public static function trimName( $name, $chars = 30 ) {
222 if ( mb_strlen( $name ) > $chars ) {
223 return sprintf( '%s&hellip;', mb_substr( $name, 0, $chars - 1 ) );
224 }
225
226 return $name;
227 }
228
229 /**
230 * @return void
231 */
232 public static function levelsSelection() {
233 global $FapiPlugin;
234 $subpage = $FapiPlugin->findSubpage();
235
236 $subpage = ( $subpage === 'settingsContentSelect' ) ? 'settingsContentRemove' : $subpage;
237 $selected = ( isset( $_GET['level'] ) ) ? self::sanitizeLevelId( $_GET['level'] ) : null;
238
239 $envelopes = $FapiPlugin->levels()->loadAsTermEnvelopes();
240
241 $lis = array();
242
243 foreach ( $envelopes as $envelope ) {
244 $term = $envelope->getTerm();
245 $under = array();
246 if ( $term->parent === 0 ) {
247 foreach ( $envelopes as $underEnvelope ) {
248 $underTerm = $underEnvelope->getTerm();
249 if ( $underTerm->parent === $term->term_id ) {
250 $under[] = self::oneLevelSelection(
251 $underTerm->term_id,
252 self::fapilink( $subpage ) . sprintf( '&level=%s', $underTerm->term_id ),
253 $underTerm->name,
254 '',
255 $underTerm->term_id === $selected
256 );
257 }
258 }
259 $lis[] = self::oneLevelSelection(
260 $term->term_id,
261 self::fapilink( $subpage ) . sprintf( '&level=%s', $term->term_id ),
262 $term->name,
263 implode( '', $under ),
264 $term->term_id === $selected
265 );
266 }
267 }
268
269 ?>
270 <div class="levels">
271 <ol>
272 <?php echo implode( '', $lis ); ?>
273 </ol>
274 </div>
275 <?php
276 }
277
278 /**
279 * @param int $id
280 * @param string $link
281 * @param string $name
282 * @param string $children
283 * @param bool $highlight
284 * @return string
285 */
286 public static function oneLevelSelection( $id, $link, $name, $children = '', $highlight = false ) {
287 $c = ( $highlight ) ? 'class="selected"' : '';
288 $ch = ( ! empty( $children ) ) ? sprintf( '<ol>%s</ol>', $children ) : '';
289
290 return sprintf(
291 '<li data-id="%s" %s><a href="%s">%s</a>%s</li>',
292 $id,
293 $c,
294 $link,
295 $name,
296 $ch
297 );
298 }
299
300 /**
301 * @return void
302 */
303 public static function levelsSelectionNonJs() {
304 global $FapiPlugin;
305 $subpage = $FapiPlugin->findSubpage();
306
307 $subpage = ( $subpage === 'settingsContentSelect' ) ? 'settingsContentRemove' : $subpage;
308 $selected = ( isset( $_GET['level'] ) ) ? self::sanitizeLevelId( $_GET['level'] ) : null;
309
310 $evnelopes = $FapiPlugin->levels()->loadAsTermEnvelopes();
311
312 $lis = array();
313
314 foreach ( $evnelopes as $envelope ) {
315 $term = $envelope->getTerm();
316 $under = array();
317 if ( $term->parent === 0 ) {
318 foreach ( $evnelopes as $underEnvelope ) {
319 $underTerm = $underEnvelope->getTerm();
320 if ( $underTerm->parent === $term->term_id ) {
321 $under[] = self::oneLevelSelection(
322 $underTerm->term_id,
323 self::fapilink( $subpage ) . sprintf( '&level=%s', $underTerm->term_id ),
324 self::trimName( $underTerm->name ),
325 '',
326 $underTerm->term_id === $selected
327 );
328 }
329 }
330 $lis[] = self::oneLevelSelection(
331 $term->term_id,
332 self::fapilink( $subpage ) . sprintf( '&level=%s', $term->term_id ),
333 self::trimName( $term->name ),
334 implode( '', $under ),
335 $term->term_id === $selected
336 );
337 }
338 }
339
340 ?>
341 <div class="levelsNonJs">
342 <ol>
343 <?php echo implode( '', $lis ); ?>
344 </ol>
345 </div>
346 <?php
347 }
348
349 /**
350 * @return string
351 */
352 public static function getLevelOptions() {
353 global $FapiPlugin;
354 $t = $FapiPlugin->levels()->loadAsTermEnvelopes();
355
356 $options = array();
357
358 foreach ( $t as $termEnvelope ) {
359 $term = $termEnvelope->getTerm();
360 if ( $term->parent === 0 ) {
361 $options[] = sprintf( '<option value="%s">%s</option>', $term->term_id, $term->name );
362 }
363 }
364
365 return implode( '', $options );
366 }
367
368 /**
369 * @param int $levelId
370 * @return string
371 */
372 public static function allPagesForForm( $levelId ) {
373 global $FapiPlugin;
374
375 $posts = get_posts(
376 array(
377 'post_type' => PostTypeHelper::getSupportedPostTypes(),
378 'post_status' => array( 'publish' ),
379 'numberposts' => -1,
380 'orderby' => 'post_title',
381 'order' => 'ASC',
382 )
383 );
384 $levelTerm = $FapiPlugin->levels()->loadById( $levelId );
385 $postsInLevel = $FapiPlugin->levels()->pageIdsForLevel( $levelTerm );
386 $output = array();
387
388 $posts_by_type = array();
389 foreach ( $posts as $post ) {
390 $posts_by_type[ $post->post_type ][] = $post;
391 }
392
393 ksort( $posts_by_type );
394
395 foreach ( array( 'page', 'post' ) as $type ) {
396
397 if ( isset( $posts_by_type[ $type ] ) ) {
398
399 $output[] = '<br/><h2><strong>' . __( $type . 's', 'fapi-member' ) . '</strong></h2>';
400
401 foreach ( $posts_by_type[ $type ] as $post ) {
402
403 $checked = ( in_array( $post->ID, $postsInLevel, true ) ) ? ' checked ' : '';
404
405 $output[] = sprintf(
406 '<div class="onePage"><input type="checkbox" name="selection[]" value="%s" %s> %s </div>',
407 $post->ID,
408 $checked,
409 $post->post_title
410 );
411 }
412
413 unset( $posts_by_type[ $type ] );
414 }
415 }
416
417 $all_post_types = PostTypeHelper::getSupportedPostTypes( true );
418 $all_stored_post_types = get_option( 'fapi_member_post_types', array() );
419
420 $stored_post_types = empty( $all_stored_post_types[ $levelId ] ) ? array() : $all_stored_post_types[ $levelId ];
421
422 if ( $all_post_types ) {
423
424 $output[] = '<br/><h2><strong>' . __( 'CPT', 'fapi-member' ) . '</strong></h2>';
425
426 foreach ( $all_post_types as $post_type ) {
427
428 $checked = ( in_array( $post_type, $stored_post_types, true ) ) ? ' checked ' : '';
429
430 $output[] = sprintf(
431 '<div class="onePage"><input type="checkbox" name="cpt_selection[]" value="%s" %s> %s</div>',
432 $post_type,
433 $checked,
434 ucfirst( $post_type )
435 );
436 }
437 }
438
439 return implode( '', $output );
440 }
441
442 /**
443 * @param int $levelId
444 * @return string
445 */
446 public static function allPagesInLevel( $levelId ) {
447 global $FapiPlugin;
448 $levelTerm = $FapiPlugin->levels()->loadById( $levelId );
449 $pageIds = $FapiPlugin->levels()->pageIdsForLevel( $levelTerm );
450
451 if ( count( $pageIds ) === 0 ) {
452 // return '';
453 $pageIds = array( PHP_INT_MAX ); // TODO[hack] ;-)
454 }
455
456 $posts = get_posts(
457 array(
458 'post_type' => PostTypeHelper::getSupportedPostTypes(),
459 'post_status' => array( 'publish' ),
460 'numberposts' => -1,
461 'include' => $pageIds,
462 'orderby' => 'page_title',
463 'order' => 'ASC',
464 )
465 );
466
467 $posts_by_type = array();
468
469 foreach ( $posts as $post ) {
470 $posts_by_type[ $post->post_type ][] = $post;
471 }
472
473 ksort( $posts_by_type );
474
475 $o = array();
476
477 foreach ( array( 'page', 'post' ) as $type ) {
478
479 if ( isset( $posts_by_type[ $type ] ) ) {
480
481 $o[] = '<br/><h2><strong>' . __( $type . 's', 'fapi-member' ) . '</strong></h2>';
482
483 $arrayMap = array_map(
484 static function ( $p ) {
485 return sprintf(
486 '<div class="onePage">%s</div>',
487 $p->post_title
488 );
489 },
490 $posts_by_type[ $type ]
491 );
492
493 $o = array_merge(
494 $o,
495 $arrayMap
496 );
497
498 unset( $posts_by_type[ $type ] );
499 }
500 }
501
502 /*
503 if ($posts_by_type) {
504
505 $o[] = '<br/><big><strong>' . __('CPT (příspěvky)', 'fapi-member') . '</strong></big><br/>';
506
507 foreach( $posts_by_type as $posts ) {
508
509 $o = array_merge($o, array_map(
510 function ( $p ) {
511 return sprintf(
512 '<div class="onePage">%s <small><em>(%s)</em></small></div>',
513 $p->post_title,
514 $p->post_type
515 );
516 },
517 $posts
518 ));
519
520 }
521 }*/
522
523 $all_post_types = PostTypeHelper::getSupportedPostTypes( true );
524 $all_stored_post_types = get_option( 'fapi_member_post_types', array() );
525
526 $stored_post_types = empty( $all_stored_post_types[ $levelId ] ) ? array() : $all_stored_post_types[ $levelId ];
527
528 $displayed_post_types = array_intersect( $stored_post_types, $all_post_types );
529
530 if ( $displayed_post_types ) {
531
532 $o[] = '<br/><h2><strong>' . __( 'CPT', 'fapi-member' ) . '</strong></h2><br/>';
533
534 $o = array_merge(
535 $o,
536 array_map(
537 static function ( $p ) {
538 return sprintf(
539 '<div class="onePage">%s</div>',
540 ucfirst( $p )
541 );
542 },
543 $displayed_post_types
544 )
545 );
546 }
547
548 return implode( '', $o );
549 }
550
551 /**
552 * @param int $pageId
553 * @return string|null
554 */
555 public static function getPageTitle( $pageId ) {
556 $posts = get_posts(
557 array(
558 'post_type' => PostTypeHelper::getSupportedPostTypes(),
559 'post_status' => array( 'publish' ),
560 'numberposts' => -1,
561 )
562 );
563
564 foreach ( $posts as $post ) {
565 if ( (int) $post->ID !== $pageId ) {
566 continue;
567 }
568
569 return $post->post_title;
570 }
571
572 return null;
573 }
574
575 /**
576 * @param int $currentId
577 * @return string
578 */
579 public static function allPagesAsOptions( $currentId ) {
580 $posts = get_posts(
581 array(
582 'post_type' => 'page',
583 'post_status' => array( 'publish' ),
584 'numberposts' => -1,
585 'orderby' => 'post_title',
586 'order' => 'ASC',
587 )
588 );
589 $output = array();
590
591 foreach ( $posts as $post ) {
592 $selected = ( $currentId === $post->ID ) ? 'selected' : '';
593
594 $output[] = sprintf( '<option value="%s" %s>%s</option>\n', $post->ID, $selected, $post->post_title );
595 }
596
597 return implode( ' ', $output );
598 }
599
600 /**
601 * @return string
602 */
603 public static function levelToPageJson() {
604 global $FapiPlugin;
605
606 return json_encode( $FapiPlugin->levels()->levelsToPages() );
607 }
608
609 /**
610 * @param array<mixed> $attrs
611 * @return string
612 */
613 public static function shortcodeSectionExpirationDate( array $attrs ) {
614 global $FapiPlugin;
615
616 if ( ! isset( $attrs['section'] ) ) {
617 return __( 'neznámá sekce nebo úrověň', 'fapi-member' );
618 }
619
620 $user = wp_get_current_user();
621
622 if ( $user === null ) {
623 return __( 'uživatel není přihlášen', 'fapi-member' );
624 }
625
626 $sectionOrLevelId = (int) $attrs['section'];
627
628 $dateFormat = get_option( 'date_format' );
629
630 if ( $dateFormat === null ) {
631 $dateFormat = 'Y-m-d';
632 }
633
634 $memberships = $FapiPlugin->fapiMembershipLoader()->loadForUser( $user->ID );
635 $currentMemberShip = null;
636
637 /** @var FapiMembership $membership */
638 foreach ( $memberships as $membership ) {
639 if ( $membership->level === $sectionOrLevelId ) {
640 $currentMemberShip = $membership;
641
642 break;
643 }
644 }
645
646 if ( $currentMemberShip === null ) {
647 return __( 'bez přístupu', 'fapi-member' );
648
649 }
650
651 if ( $currentMemberShip->until === null ) {
652 return __( 'neomezeně', 'fapi-member' );
653 }
654
655 return $currentMemberShip->until->format( $dateFormat );
656 }
657
658 /**
659 * @param array<mixed> $attrs
660 * @return string
661 */
662 public static function shortcodeUnlockLevel( array $attrs )
663 {
664 if ( ! isset( $attrs['level'] ) ) {
665 return __( 'neznámá sekce nebo úrověň', 'fapi-member' );
666 }
667
668 $sectionOrLevelId = (int) $attrs['level'];
669 $html = self::formStart('button_level_unlock');
670 $html .= '<input type="hidden" name="level" value="' . $sectionOrLevelId . '">';
671
672 if (isset($attrs['page'])) {
673 $html .= '<input type="hidden" name="page" value="' . $attrs['page'] . '">';
674 }
675
676 $html .= '<button class="unlock-level-button" type="submit" name="submit"">Odemknout úroveň</button></form>';
677
678 return $html;
679 }
680
681 /**
682 * @param array<mixed> $attrs
683 * @return string
684 */
685 public static function shortcodeLevelUnlockDate( array $attrs ) {
686 global $FapiPlugin;
687
688 if ( ! isset( $attrs['section'] ) ) {
689 return __( 'neznámá sekce nebo úrověň', 'fapi-member' );
690 }
691
692 $user = wp_get_current_user();
693
694 if ( $user === null ) {
695 return __( 'uživatel není přihlášen', 'fapi-member' );
696 }
697
698 $sectionOrLevelId = (int) $attrs['section'];
699
700 $dateFormat = get_option( 'date_format' );
701
702 if ( $dateFormat === null ) {
703 $dateFormat = 'Y-m-d';
704 }
705
706 $memberships = $FapiPlugin->fapiMembershipLoader()->loadForUser( $user->ID );
707 $parentLevel = $FapiPlugin->levels()->loadParentById($sectionOrLevelId);
708 $currentMemberShip = null;
709 $parentMembership = null;
710
711 /** @var FapiMembership $membership */
712 foreach ($memberships as $membership) {
713 if ($membership->level === $sectionOrLevelId) {
714 $currentMemberShip = $membership;
715 }
716
717 if ($membership->level === $parentLevel->term_id) {
718 $parentMembership = $membership;
719 }
720
721 if ($currentMemberShip !== null && $parentMembership !== null) {
722 break;
723 }
724 }
725
726 if ( $currentMemberShip === null ||
727 ($currentMemberShip === null &&
728 (bool) get_term_meta($sectionOrLevelId, $FapiPlugin::TIME_UNLOCK_META_KEY, true) === false)
729 ) {
730 return __( 'bez přístupu', 'fapi-member' );
731 }
732
733
734 if ( $currentMemberShip === null && $parentMembership->registered !== null) {
735 $daysToUnlock = get_term_meta($sectionOrLevelId, $FapiPlugin::DAYS_TO_UNLOCK_META_KEY, true);
736
737 $unlockDate = date(
738 'd.m.Y',
739 strtotime($parentMembership->registered->format($dateFormat))
740 + (86400 * (int) $daysToUnlock),
741 );
742
743 return __( 'Bude odemčeno', 'fapi-member' ) . " " . $unlockDate;
744 }
745
746 if ( $currentMemberShip->until === null ) {
747 return __( 'neomezeně', 'fapi-member' );
748 }
749
750 return $currentMemberShip->until->format( $dateFormat );
751 }
752
753 /**
754 * @return string
755 */
756 public static function shortcodeLoginForm() {
757 return '
758 <div class="fapiShortcodeLoginForm">
759 <form method="post" action="' . wp_login_url() . '">
760 <div class="f-m-row">
761 <label for="log">' . __( 'Přihlašovací jméno', 'fapi-member' ) . '</label>
762 <input type="text" name="log" id="user_login" value="" size="20">
763 </div>
764 <div class="f-m-row">
765 <label for="pwd">' . __( 'Heslo', 'fapi-member' ) . '</label>
766 <input type="password" name="pwd" id="user_pass" value="" size="20">
767 </div>
768 <div class="f-m-row">
769 <a href="' . wp_lostpassword_url() . '">' . __( 'Zapomněli jste heslo?', 'fapi-member' ) . '</a>
770 </div>
771 <div class="f-m-row controls">
772 <input type="submit" class="primary" value="' . __( 'Přihlásit se', 'fapi-member' ) . '">
773 </div>
774 </form>
775 </div>
776 ';
777 }
778
779 /**
780 * @return string
781 */
782 public static function shortcodeUser() {
783 global $FapiPlugin;
784
785 $u = wp_get_current_user();
786 if ( $u instanceof WP_User && is_user_logged_in() ) {
787 return '
788 <div class="fapiShortcodeUser">
789 <span class="i">
790 <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
791 viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
792 <g>
793 <g>
794 <path d="M437.02,330.98c-27.883-27.882-61.071-48.523-97.281-61.018C378.521,243.251,404,198.548,404,148
795 C404,66.393,337.607,0,256,0S108,66.393,108,148c0,50.548,25.479,95.251,64.262,121.962
796 c-36.21,12.495-69.398,33.136-97.281,61.018C26.629,379.333,0,443.62,0,512h40c0-119.103,96.897-216,216-216s216,96.897,216,216
797 h40C512,443.62,485.371,379.333,437.02,330.98z M256,256c-59.551,0-108-48.448-108-108S196.449,40,256,40
798 c59.551,0,108,48.448,108,108S315.551,256,256,256z"/>
799 </g>
800 </g>
801 </svg>
802 </span>
803 <span class="h">' . __( 'Uživatel', 'fapi-member' ) . '</span>
804 <div>
805 <span class="l">' . $u->user_login . '</span><span class="dots">...</span>
806 </div>
807 <div class="f-m-submenu">
808 <a href="' . wp_logout_url( get_permalink() ) . '">' . __( 'Odhlásit se', 'fapi-member' ) . '</a>
809 </div>
810 </div>
811 ';
812 }
813
814 $setLoginPageId = $FapiPlugin->getSetting( 'login_page_id' );
815
816 if ( $setLoginPageId === null ) {
817 $url = wp_login_url();
818 } else {
819 $url = get_permalink( $setLoginPageId );
820 }
821
822 return '
823 <div class="fapiShortcodeUser notLogged">
824 <span class="i">
825 <svg id="bold" enable-background="new 0 0 24 24" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m18.75 9h-.75v-3c0-3.309-2.691-6-6-6s-6 2.691-6 6v3h-.75c-1.24 0-2.25 1.009-2.25 2.25v10.5c0 1.241 1.01 2.25 2.25 2.25h13.5c1.24 0 2.25-1.009 2.25-2.25v-10.5c0-1.241-1.01-2.25-2.25-2.25zm-10.75-3c0-2.206 1.794-4 4-4s4 1.794 4 4v3h-8zm5 10.722v2.278c0 .552-.447 1-1 1s-1-.448-1-1v-2.278c-.595-.347-1-.985-1-1.722 0-1.103.897-2 2-2s2 .897 2 2c0 .737-.405 1.375-1 1.722z"/></svg>
826 </span>
827 <span class="l"><a href="' . $url . '">' . __( 'Přihlásit se', 'fapi-member' ) . '</a></span>
828 </div>
829 ';
830 }
831
832 /**
833 * @param string $hook
834 * @param array<string> $formClasses
835 * @return string
836 */
837 public static function formStart( $hook, $formClasses = array() ) {
838 $class = ( empty( $formClasses ) ) ? '' : sprintf( ' class="%s"', implode( ' ', $formClasses ) );
839
840 return '
841 <form ' . $class . ' method="post" action="' . admin_url( 'admin-post.php' ) . '">
842 <input type="hidden" name="action" value="fapi_member_' . $hook . '">
843 <input type="hidden" name="fapi_member_' . $hook . '_nonce"
844 value="' . wp_create_nonce( 'fapi_member_' . $hook . '_nonce' ) . '">
845 ';
846 }
847
848 /**
849 * @return string
850 */
851 public static function heading() {
852 return sprintf(
853 '%s<div class="baseGrid">%s%s%s',
854 self::resolutionMessage(),
855 self::h1(),
856 self::nav(),
857 self::submenu()
858 );
859 }
860
861 /**
862 * @return string
863 */
864 public static function resolutionMessage() {
865 return '<p class="resolutionAlert">' . __( 'Tento doplněk není optimalizován pro telefony a malé monitory.', 'fapi-member' ) . '</p>';
866 }
867
868 /**
869 * @return string
870 */
871 public static function h1() {
872 $svg = file_get_contents( __DIR__ . '/../_sources/LOGO_FAPI_svg.svg' );
873
874 return sprintf( '<div class="h1"><a href="https://web.fapi.cz">%s</a></div>', $svg );
875 }
876
877 /**
878 * @return string
879 */
880 public static function nav() {
881 global $FapiPlugin;
882 $subpage = $FapiPlugin->findSubpage();
883 $areApiCredentialsSet = $FapiPlugin->areApiCredentialsSet();
884
885 $c = file_get_contents( __DIR__ . '/../_sources/connect.svg' );
886 $h = file_get_contents( __DIR__ . '/../_sources/home-solid.svg' );
887 $p = file_get_contents( __DIR__ . '/../_sources/padlock.svg' );
888
889 $testActionLink = '';
890 if ( $FapiPlugin::isDevelopment() ) {
891 $testActionLink = '
892 <a href="' . self::fapilink( 'test' ) . '" ' . ( ( $subpage === 'test' ) ? 'class="active"' : '' ) . '>
893 <span class="a" style="color: #9a1818;">Testovací akce</span>
894 </a>';
895 }
896
897 if ( ! $areApiCredentialsSet ) {
898 return '
899 <nav>
900 <span class="disabled">
901 <span class="a">' . __( 'Přehled', 'fapi-member' ) . '</span>
902 ' . $h . '
903 </span>
904 <span class="disabled">
905 <span class="a">' . __( 'Členské sekce', 'fapi-member' ) . '</span>
906 ' . $p . '
907 </span>
908 <a href="#" class="active">
909 <span class="a">' . __( 'Propojení s FAPI', 'fapi-member' ) . '</span>
910 ' . $c . '
911 </a>
912 ' . $testActionLink . '
913 </nav>';
914 }
915
916 return '
917 <nav>
918 <a href="' . self::fapilink( 'index' ) . '" ' . ( ( $subpage === 'index' ) ? 'class="active"' : '' ) . '>
919 <span class="a">' . __( 'Přehled', 'fapi-member' ) . '</span>
920 ' . $h . '
921 </a>
922 <a href="' . self::fapilink( 'settingsSectionNew' ) . '" ' . ( ( strpos(
923 $subpage,
924 'settings'
925 ) === 0 ) ? 'class="active"' : '' ) . '>
926 <span class="a">' . __( 'Členské sekce', 'fapi-member' ) . '</span>
927 ' . $p . '
928 </a>
929 <a href="' . self::fapilink( 'connection' ) . '" ' . ( ( $subpage === 'connection' ) ? 'class="active"' : '' ) . '>
930 <span class="a">' . __( 'Propojení s FAPI', 'fapi-member' ) . '</span>
931 ' . $c . '
932 </a>
933 ' . $testActionLink . '
934 </nav>';
935 }
936
937 /**
938 * @return string
939 */
940 public static function submenu() {
941 global $FapiPlugin;
942 $subpage = $FapiPlugin->findSubpage();
943
944 switch ( true ) {
945 case ( $subpage === 'index' ):
946 return '
947 <div class="submenu">
948 <span class="active">' . __( 'Přehled', 'fapi-member' ) . '</a>
949 </div>
950 ';
951 case ( $subpage === 'connection' ):
952 return '
953 <div class="submenu">
954 <span class="active">' . __( 'Propojení', 'fapi-member' ) . '</a>
955 </div>
956 ';
957 case ( mb_strpos( $subpage, 'settings' ) === 0 ):
958 return '
959 <div class="submenu">
960 ' . self::submenuItem( 'settingsSectionNew', 'Sekce / úrovně', $subpage, array( 'settingsLevelNew' ) ) . '
961 ' . self::submenuItem(
962 'settingsContentAdd',
963 __( 'Přiřazené stránky a příspěvky', 'fapi-member' ),
964 $subpage,
965 array( 'settingsContentRemove' )
966 ) . '
967 ' . self::submenuItem( 'settingsEmails', __( 'E-maily', 'fapi-member' ), $subpage ) . '
968 ' . self::submenuItem( 'settingsPages', __( 'Servisní stránky', 'fapi-member' ), $subpage ) . '
969 ' . self::submenuItem( 'settingsElements', __( 'Prvky pro web', 'fapi-member' ), $subpage ) . '
970 ' . self::submenuItem( 'settingsSettings', __( 'Společné', 'fapi-member' ), $subpage ) . '
971 ' . self::submenuItem( 'settingsUnlocking', __( 'Uvolňování obsahu', 'fapi-member' ), $subpage ) . '
972 </div>
973 ';
974 }
975
976 return '';
977 }
978
979 /**
980 * @param string $subpage
981 * @param string $label
982 * @param string $activeSubpage
983 * @param array<string> $otherChildren
984 * @return string
985 */
986 public static function submenuItem( $subpage, $label, $activeSubpage, $otherChildren = null ) {
987 $classes = array();
988
989 if ( $activeSubpage === $subpage ) {
990 $classes[] = 'active';
991 }
992 if ( $otherChildren !== null && in_array( $activeSubpage, $otherChildren, true ) ) {
993 $classes[] = 'active';
994 }
995
996 return sprintf( '<a href="%s" class="%s">%s</a>', self::fapilink( $subpage ), implode( ' ', $classes ), $label );
997 }
998
999 }
1000