LearnPress – WordPress LMS Plugin - Version 3.2.1

Version Description

~ Fixed can't enroll course. ~ Fixed upload issue and drag user avatar on mobile. ~ Fixed course duration does not work properly. ~ Fixed question with multi language. ~ Fixed mail to user 2 times when completed course.

Download this release

Release Info

Developer phonglq.foobla
Plugin Icon 128x128 LearnPress – WordPress LMS Plugin
Version 3.2.1
Comparing to
See all releases

Code changes from version 3.2.0 to 3.2.1

Files changed (190) hide show
  1. inc/class-lp-assets.php +2 -1
  2. inc/class-lp-schedules.php +1 -2
  3. inc/course/abstract-course.php +62 -0
  4. inc/course/class-lp-course-item.php +15 -14
  5. inc/curds/class-lp-user-curd.php +0 -1
  6. inc/curds/class-lp-user-item-curd.php +107 -57
  7. inc/custom-post-types/order.php +1 -2
  8. inc/libraries/meta-box/css/autocomplete.css +1 -1
  9. inc/libraries/meta-box/css/button-group.css +13 -13
  10. inc/libraries/meta-box/css/color.css +1 -1
  11. inc/libraries/meta-box/css/divider.css +1 -1
  12. inc/libraries/meta-box/css/heading.css +1 -1
  13. inc/libraries/meta-box/css/input-list.css +3 -3
  14. inc/libraries/meta-box/css/map.css +44 -0
  15. inc/libraries/meta-box/css/oembed.css +1 -1
  16. inc/libraries/meta-box/css/osm.css +49 -0
  17. inc/libraries/meta-box/css/select.css +1 -1
  18. inc/libraries/meta-box/css/select2/select2.css +4 -3
  19. inc/libraries/meta-box/css/slider.css +1 -1
  20. inc/libraries/meta-box/css/style-rtl.css +5 -5
  21. inc/libraries/meta-box/css/text-list.css +19 -0
  22. inc/libraries/meta-box/css/upload.css +0 -4
  23. inc/libraries/meta-box/inc/about/about.php +129 -24
  24. inc/libraries/meta-box/inc/about/css/about.css +219 -0
  25. inc/libraries/meta-box/inc/about/images/meta-box.svg +5 -0
  26. inc/libraries/meta-box/inc/about/js/about.js +26 -0
  27. inc/libraries/meta-box/inc/about/sections/extensions.php +351 -0
  28. inc/libraries/meta-box/inc/about/sections/getting-started.php +15 -20
  29. inc/libraries/meta-box/inc/about/sections/newsletter.php +16 -0
  30. inc/libraries/meta-box/inc/about/sections/support.php +35 -0
  31. inc/libraries/meta-box/inc/about/sections/tabs.php +5 -3
  32. inc/libraries/meta-box/inc/about/sections/upgrade.php +26 -0
  33. inc/libraries/meta-box/inc/about/sections/welcome.php +11 -4
  34. inc/libraries/meta-box/inc/clone.php +4 -4
  35. inc/libraries/meta-box/inc/core.php +3 -3
  36. inc/libraries/meta-box/inc/field.php +95 -48
  37. inc/libraries/meta-box/inc/fields/autocomplete.php +15 -8
  38. inc/libraries/meta-box/inc/fields/background.php +167 -0
  39. inc/libraries/meta-box/inc/fields/button-group.php +82 -0
  40. inc/libraries/meta-box/inc/fields/button.php +12 -6
  41. inc/libraries/meta-box/inc/fields/checkbox-list.php +1 -1
  42. inc/libraries/meta-box/inc/fields/checkbox.php +1 -1
  43. inc/libraries/meta-box/inc/fields/choice.php +17 -73
  44. inc/libraries/meta-box/inc/fields/color.php +21 -12
  45. inc/libraries/meta-box/inc/fields/datetime.php +39 -24
  46. inc/libraries/meta-box/inc/fields/file-input.php +11 -7
  47. inc/libraries/meta-box/inc/fields/file-upload.php +12 -6
  48. inc/libraries/meta-box/inc/fields/file.php +44 -28
  49. inc/libraries/meta-box/inc/fields/image-advanced.php +12 -6
  50. inc/libraries/meta-box/inc/fields/image-select.php +1 -1
  51. inc/libraries/meta-box/inc/fields/image.php +16 -8
  52. inc/libraries/meta-box/inc/fields/input-list.php +26 -24
  53. inc/libraries/meta-box/inc/fields/input.php +28 -19
  54. inc/libraries/meta-box/inc/fields/key-value.php +8 -5
  55. inc/libraries/meta-box/inc/fields/map.php +68 -41
  56. inc/libraries/meta-box/inc/fields/media.php +44 -31
  57. inc/libraries/meta-box/inc/fields/number.php +16 -10
  58. inc/libraries/meta-box/inc/fields/object-choice.php +46 -28
  59. inc/libraries/meta-box/inc/fields/oembed.php +46 -10
  60. inc/libraries/meta-box/inc/fields/osm.php +175 -0
  61. inc/libraries/meta-box/inc/fields/post.php +65 -50
  62. inc/libraries/meta-box/inc/fields/radio.php +1 -1
  63. inc/libraries/meta-box/inc/fields/range.php +7 -4
  64. inc/libraries/meta-box/inc/fields/select-advanced.php +21 -12
  65. inc/libraries/meta-box/inc/fields/select-tree.php +7 -9
  66. inc/libraries/meta-box/inc/fields/select.php +25 -20
  67. inc/libraries/meta-box/inc/fields/sidebar.php +68 -0
  68. inc/libraries/meta-box/inc/fields/single-image.php +76 -0
  69. inc/libraries/meta-box/inc/fields/slider.php +24 -14
  70. inc/libraries/meta-box/inc/fields/switch.php +97 -0
  71. inc/libraries/meta-box/inc/fields/taxonomy-advanced.php +26 -27
  72. inc/libraries/meta-box/inc/fields/taxonomy.php +90 -42
  73. inc/libraries/meta-box/inc/fields/text-list.php +39 -13
  74. inc/libraries/meta-box/inc/fields/text.php +17 -11
  75. inc/libraries/meta-box/inc/fields/textarea.php +24 -18
  76. inc/libraries/meta-box/inc/fields/time.php +1 -1
  77. inc/libraries/meta-box/inc/fields/user.php +42 -42
  78. inc/libraries/meta-box/inc/fields/video.php +23 -15
  79. inc/libraries/meta-box/inc/fields/wysiwyg.php +15 -9
  80. inc/libraries/meta-box/inc/functions.php +119 -16
  81. inc/libraries/meta-box/inc/loader.php +1 -1
  82. inc/libraries/meta-box/inc/meta-box.php +48 -23
  83. inc/libraries/meta-box/inc/sanitizer.php +16 -4
  84. inc/libraries/meta-box/inc/validation.php +7 -3
  85. inc/libraries/meta-box/inc/walkers/base.php +13 -16
  86. inc/libraries/meta-box/inc/walkers/input-list.php +3 -5
  87. inc/libraries/meta-box/inc/walkers/select-tree.php +18 -26
  88. inc/libraries/meta-box/inc/walkers/select.php +3 -5
  89. inc/libraries/meta-box/js/autosave.js +1 -1
  90. inc/libraries/meta-box/js/input-list.js +5 -5
  91. inc/libraries/meta-box/js/map.js +65 -32
  92. inc/libraries/meta-box/js/media.js +2 -2
  93. inc/libraries/meta-box/js/oembed.js +2 -1
  94. inc/libraries/meta-box/js/osm-frontend.js +50 -0
  95. inc/libraries/meta-box/js/osm.js +266 -0
  96. inc/libraries/meta-box/js/select-advanced.js +34 -0
  97. inc/libraries/meta-box/js/select.js +20 -41
  98. inc/libraries/meta-box/js/select2/i18n/af.js +3 -0
  99. inc/libraries/meta-box/js/select2/i18n/ar.js +2 -2
  100. inc/libraries/meta-box/js/select2/i18n/az.js +1 -1
  101. inc/libraries/meta-box/js/select2/i18n/bg.js +1 -1
  102. inc/libraries/meta-box/js/select2/i18n/bs.js +3 -0
  103. inc/libraries/meta-box/js/select2/i18n/ca.js +1 -1
  104. inc/libraries/meta-box/js/select2/i18n/cs.js +2 -2
  105. inc/libraries/meta-box/js/select2/i18n/da.js +2 -2
  106. inc/libraries/meta-box/js/select2/i18n/de.js +2 -2
  107. inc/libraries/meta-box/js/select2/i18n/dsb.js +3 -0
  108. inc/libraries/meta-box/js/select2/i18n/el.js +3 -0
  109. inc/libraries/meta-box/js/select2/i18n/en.js +1 -1
  110. inc/libraries/meta-box/js/select2/i18n/es.js +2 -2
  111. inc/libraries/meta-box/js/select2/i18n/et.js +1 -1
  112. inc/libraries/meta-box/js/select2/i18n/eu.js +1 -1
  113. inc/libraries/meta-box/js/select2/i18n/fa.js +1 -1
  114. inc/libraries/meta-box/js/select2/i18n/fi.js +2 -2
  115. inc/libraries/meta-box/js/select2/i18n/fr.js +2 -2
  116. inc/libraries/meta-box/js/select2/i18n/gl.js +2 -2
  117. inc/libraries/meta-box/js/select2/i18n/he.js +1 -1
  118. inc/libraries/meta-box/js/select2/i18n/hi.js +1 -1
  119. inc/libraries/meta-box/js/select2/i18n/hr.js +1 -1
  120. inc/libraries/meta-box/js/select2/i18n/hsb.js +3 -0
  121. inc/libraries/meta-box/js/select2/i18n/hu.js +2 -2
  122. inc/libraries/meta-box/js/select2/i18n/hy.js +3 -0
  123. inc/libraries/meta-box/js/select2/i18n/id.js +1 -1
  124. inc/libraries/meta-box/js/select2/i18n/is.js +1 -1
  125. inc/libraries/meta-box/js/select2/i18n/it.js +1 -1
  126. inc/libraries/meta-box/js/select2/i18n/ja.js +1 -1
  127. inc/libraries/meta-box/js/select2/i18n/km.js +3 -0
  128. inc/libraries/meta-box/js/select2/i18n/ko.js +1 -1
  129. inc/libraries/meta-box/js/select2/i18n/lt.js +2 -2
  130. inc/libraries/meta-box/js/select2/i18n/lv.js +1 -1
  131. inc/libraries/meta-box/js/select2/i18n/mk.js +1 -1
  132. inc/libraries/meta-box/js/select2/i18n/ms.js +1 -1
  133. inc/libraries/meta-box/js/select2/i18n/nb.js +2 -2
  134. inc/libraries/meta-box/js/select2/i18n/nl.js +1 -1
  135. inc/libraries/meta-box/js/select2/i18n/pl.js +1 -1
  136. inc/libraries/meta-box/js/select2/i18n/ps.js +3 -0
  137. inc/libraries/meta-box/js/select2/i18n/pt-BR.js +1 -1
  138. inc/libraries/meta-box/js/select2/i18n/pt.js +2 -2
  139. inc/libraries/meta-box/js/select2/i18n/ro.js +2 -2
  140. inc/libraries/meta-box/js/select2/i18n/ru.js +1 -1
  141. inc/libraries/meta-box/js/select2/i18n/sk.js +2 -2
  142. inc/libraries/meta-box/js/select2/i18n/sl.js +3 -0
  143. inc/libraries/meta-box/js/select2/i18n/sr-Cyrl.js +1 -1
  144. inc/libraries/meta-box/js/select2/i18n/sr.js +1 -1
  145. inc/libraries/meta-box/js/select2/i18n/sv.js +1 -1
  146. inc/libraries/meta-box/js/select2/i18n/th.js +2 -2
  147. inc/libraries/meta-box/js/select2/i18n/tr.js +2 -2
  148. inc/libraries/meta-box/js/select2/i18n/uk.js +1 -1
  149. inc/libraries/meta-box/js/select2/i18n/vi.js +2 -2
  150. inc/libraries/meta-box/js/select2/i18n/zh-CN.js +1 -1
  151. inc/libraries/meta-box/js/select2/i18n/zh-TW.js +1 -1
  152. inc/libraries/meta-box/js/select2/select2.min.js +1 -2
  153. inc/libraries/meta-box/js/validate.js +7 -2
  154. inc/libraries/meta-box/js/wysiwyg.js +1 -1
  155. inc/libraries/meta-box/languages/default.pot +353 -0
  156. inc/libraries/meta-box/languages/meta-box-ar.mo +0 -0
  157. inc/libraries/meta-box/languages/meta-box-ar.po +122 -0
  158. inc/libraries/meta-box/languages/meta-box-fa_IR.mo +0 -0
  159. inc/libraries/meta-box/languages/meta-box-fa_IR.po +184 -0
  160. inc/libraries/meta-box/languages/meta-box-fr_FR.mo +0 -0
  161. inc/libraries/meta-box/languages/meta-box-fr_FR.po +217 -0
  162. inc/libraries/meta-box/languages/meta-box-it_IT.mo +0 -0
  163. inc/libraries/meta-box/languages/meta-box-it_IT.po +318 -0
  164. inc/libraries/meta-box/languages/meta-box-nb_NO.mo +0 -0
  165. inc/libraries/meta-box/languages/meta-box-nb_NO.po +149 -0
  166. inc/libraries/meta-box/languages/meta-box-nl_NL.mo +0 -0
  167. inc/libraries/meta-box/languages/meta-box-nl_NL.po +130 -0
  168. inc/libraries/meta-box/languages/meta-box-pl_PL.mo +0 -0
  169. inc/libraries/meta-box/languages/meta-box-pl_PL.po +215 -0
  170. inc/libraries/meta-box/languages/meta-box-pt_BR.mo +0 -0
  171. inc/libraries/meta-box/languages/meta-box-pt_BR.po +124 -0
  172. inc/libraries/meta-box/languages/meta-box-ru_RU.mo +0 -0
  173. inc/libraries/meta-box/languages/meta-box-ru_RU.po +637 -0
  174. inc/libraries/meta-box/languages/meta-box-tr_TR.mo +0 -0
  175. inc/libraries/meta-box/languages/meta-box-tr_TR.po +180 -0
  176. inc/libraries/meta-box/languages/meta-box-zh_CN.mo +0 -0
  177. inc/libraries/meta-box/languages/meta-box-zh_CN.po +189 -0
  178. inc/libraries/meta-box/languages/readme.md +15 -0
  179. inc/libraries/meta-box/meta-box.php +2 -3
  180. inc/libraries/meta-box/readme.txt +97 -65
  181. inc/lp-constants.php +1 -1
  182. inc/lp-template-functions.php +1 -0
  183. inc/order/class-lp-order.php +0 -1
  184. inc/quiz/class-lp-quiz.php +6 -1
  185. inc/user-item/class-lp-user-item-course-bk.php +898 -0
  186. inc/user/class-lp-user-factory.php +1 -1
  187. inc/user/lp-user-functions.php +1 -0
  188. learnpress.php +3 -4
  189. readme.txt +62 -56
  190. templates/single-course/loop-section.php +10 -5
inc/class-lp-assets.php CHANGED
@@ -128,7 +128,8 @@ class LP_Assets extends LP_Abstract_Assets {
128
  'plupload',
129
  'backbone',
130
  'jquery-ui-slider',
131
- 'jquery-ui-draggable'
 
132
  ),
133
  'enqueue' => learn_press_is_profile()
134
  ),
128
  'plupload',
129
  'backbone',
130
  'jquery-ui-slider',
131
+ 'jquery-ui-draggable',
132
+ 'jquery-touch-punch',
133
  ),
134
  'enqueue' => learn_press_is_profile()
135
  ),
inc/class-lp-schedules.php CHANGED
@@ -88,8 +88,7 @@ class LP_Schedules {
88
  return;
89
  }
90
  $this->_update_user_course_items_expired( $course, $user );
91
- $user_course = $user->get_course_data( $course->get_id() );
92
- $item_meta_id = $user_course->finish();
93
  if ( $item_meta_id ) {
94
  learn_press_update_user_item_meta( $item_meta_id, 'finishing_type', 'automation' );
95
  do_action( 'learn_press_user_finish_course_automation', $course->get_id(), $item_meta_id, $user->get_id() );
88
  return;
89
  }
90
  $this->_update_user_course_items_expired( $course, $user );
91
+ $item_meta_id = $user->finish_course( $course->get_id(), true );
 
92
  if ( $item_meta_id ) {
93
  learn_press_update_user_item_meta( $item_meta_id, 'finishing_type', 'automation' );
94
  do_action( 'learn_press_user_finish_course_automation', $course->get_id(), $item_meta_id, $user->get_id() );
inc/course/abstract-course.php CHANGED
@@ -1764,5 +1764,67 @@ if ( ! function_exists( 'LP_Abstract_Course' ) ) {
1764
  public function is_enable_item_link() {
1765
  return get_post_meta( $this->get_id(), '_lp_submission', true ) === 'yes';
1766
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1767
  }
1768
  }
1764
  public function is_enable_item_link() {
1765
  return get_post_meta( $this->get_id(), '_lp_submission', true ) === 'yes';
1766
  }
1767
+
1768
+ /**
1769
+ * Prepare course items.
1770
+ *
1771
+ * @since 3.2.0
1772
+ *
1773
+ * @return array
1774
+ */
1775
+ public function prepare() {
1776
+ global $wpdb;
1777
+ $id = $this->get_id();
1778
+ $all_items = LP_Object_Cache::get( $id, 'course-raw-items' );
1779
+
1780
+ $type_items = LP_Object_Cache::get( 'course-' . $id, 'learn-press/course-item-group-types' );
1781
+ $section_items = LP_Object_Cache::get( $id, 'learn-press/section-items' );
1782
+ $course_sections = LP_Object_Cache::get( $id, 'learn-press/course-sections-ids' );
1783
+
1784
+ if ( false === $type_items || false === $section_items || false === $course_sections ) {
1785
+ $types = learn_press_get_course_item_types();
1786
+ $type_items = array_fill_keys( $types, array() );
1787
+ $section_items = array();
1788
+ $course_sections = array();
1789
+
1790
+ if ( $all_items === false ) {
1791
+ $query = $wpdb->prepare( "
1792
+ SELECT section_items.item_id AS id, course_sections.section_id AS section, item.post_type AS type
1793
+ FROM {$wpdb->posts} course
1794
+ INNER JOIN {$wpdb->learnpress_sections} course_sections ON course.ID = course_sections.section_course_id
1795
+ INNER JOIN {$wpdb->learnpress_section_items} section_items ON course_sections.section_id = section_items.section_id
1796
+ INNER JOIN {$wpdb->posts} item ON item.ID = section_items.item_id
1797
+ WHERE course.ID = %d
1798
+ ORDER BY course_sections.section_id, course_sections.section_order,section_items.section_item_id, section_items.item_order ASC
1799
+ ", $id );
1800
+
1801
+ $all_items = $wpdb->get_results( $query );
1802
+
1803
+ LP_Object_Cache::set( $id, $all_items, 'course-raw-items' );
1804
+ }
1805
+
1806
+ if ( $all_items ) {
1807
+ foreach ( $all_items as $item ) {
1808
+ if ( ! array_key_exists( $item->type, $type_items ) ) {
1809
+ continue;
1810
+ }
1811
+ $type_items[ $item->type ][] = $item->id;
1812
+ $section_items[ 'section-' . $item->section ][] = $item->id;
1813
+ $course_sections[ $item->section ] = $item->section;
1814
+ }
1815
+ }
1816
+
1817
+ LP_Object_Cache::set( 'course-' . $id, $type_items, 'learn-press/course-item-group-types' );
1818
+ foreach ( $section_items as $k => $v ) {
1819
+ LP_Object_Cache::set( $k, $v, 'learn-press/section-items' );
1820
+ }
1821
+ LP_Object_Cache::set( $id, $course_sections, 'learn-press/course-sections-ids' );
1822
+
1823
+ $all_ids = call_user_func_array( 'array_merge', $type_items );
1824
+ LP_Helper_CURD::cache_posts( $all_ids );
1825
+ }
1826
+
1827
+ return compact( 'type_items', 'section_items', 'course_sections' );
1828
+ }
1829
  }
1830
  }
inc/course/class-lp-course-item.php CHANGED
@@ -95,25 +95,26 @@ if ( ! class_exists( 'LP_Course_Item' ) ) {
95
  * @return bool
96
  */
97
  public function is_preview( $context = 'display' ) {
98
- if ( $this->get_post_type() === LP_LESSON_CPT && '' === $this->_preview ) {
99
- $is_preview = get_post_meta( $this->get_id(), '_lp_preview', true ) == 'yes';
 
100
 
101
- if ( $course = $this->get_course() ) {
102
- $user_id = get_current_user_id();
 
 
 
103
 
104
- if ( false === ( $cached = LP_Object_Cache::get( 'item-' . $user_id . '-' . $course->get_id() . '-' . $this->get_id(), 'learn-press/preview-items' ) ) ) {
105
- $user = learn_press_get_current_user();
 
106
 
107
- if ( $user->has_enrolled_course( $course->get_id() ) ) {
108
- $is_preview = false;
109
- }
110
- LP_Object_Cache::set( 'item-' . $user_id . '-' . $course->get_id() . '-' . $this->get_id(), $is_preview ? 'yes' : 'no', 'learn-press/preview-items' );
111
- } else {
112
- $is_preview = $cached === 'yes' ? true : false;
113
- }
114
  }
115
- $this->_preview = $is_preview;
 
116
  }
 
117
 
118
  return $context === 'display' ? apply_filters( 'learn-press/course-item-preview', $this->_preview, $this->get_id() ) : $this->_preview;
119
  }
95
  * @return bool
96
  */
97
  public function is_preview( $context = 'display' ) {
98
+ if ( empty( $GLOBALS['course-item/is-preview'] ) ) {
99
+ $GLOBALS['course-item/is-preview'] = 0;
100
+ }
101
 
102
+ $t = microtime( true );
103
+ $user_id = get_current_user_id();
104
+ if ( $this->get_post_type() === LP_LESSON_CPT && '' === $this->_preview ) {
105
+ $course_id = $this->get_course_id();
106
+ $item_id = $this->get_id();
107
 
108
+ if ( false === ( $is_preview = LP_Object_Cache::get( 'item-' . $user_id . '-' . $course_id . '-' . $item_id, 'learn-press/preview-items' ) ) ) {
109
+ $api = new LP_User_Item_CURD();
110
+ $items = $api->parse_items_preview( $course_id, $user_id );
111
 
112
+ $is_preview = isset( $items[ $item_id ] ) ? $items[ $item_id ] : 'no';
 
 
 
 
 
 
113
  }
114
+
115
+ $this->_preview = $is_preview === 'yes';
116
  }
117
+ $GLOBALS['course-item/is-preview'] += microtime( true ) - $t;
118
 
119
  return $context === 'display' ? apply_filters( 'learn-press/course-item-preview', $this->_preview, $this->get_id() ) : $this->_preview;
120
  }
inc/curds/class-lp-user-curd.php CHANGED
@@ -895,7 +895,6 @@ class LP_User_CURD extends LP_Object_Data_CURD implements LP_Interface_CURD {
895
  * @return bool|mixed
896
  */
897
  public function get_user_item( $user_id, $item_id, $course_id = 0, $last = true ) {
898
-
899
  $num_args = func_num_args();
900
 
901
  if ( $num_args == 2 ) {
895
  * @return bool|mixed
896
  */
897
  public function get_user_item( $user_id, $item_id, $course_id = 0, $last = true ) {
 
898
  $num_args = func_num_args();
899
 
900
  if ( $num_args == 2 ) {
inc/curds/class-lp-user-item-curd.php CHANGED
@@ -483,6 +483,54 @@ class LP_User_Item_CURD implements LP_Interface_CURD {
483
  }
484
 
485
  /**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486
  * @since 3.2.0
487
  *
488
  * @param int $course_id
@@ -509,75 +557,77 @@ class LP_User_Item_CURD implements LP_Interface_CURD {
509
  $is_free = $course->is_free();
510
  $required_enroll = $course->is_required_enroll();
511
 
512
- foreach ( $get_item_ids as $item_id ) {
513
- $item = $course->get_item( $item_id );
 
514
 
515
- $defaults = array_merge(
516
- array(
517
- 'course-item',
518
- 'course-item-' . $item->get_item_type(),
519
- 'course-item-' . $item_id
520
- ), (array) $more
521
- );
522
 
523
- if ( ( 'standard' !== ( $post_format = $item->get_format() ) ) && $post_format ) {
524
- $defaults[] = 'course-item-type-' . $post_format;
525
- }
526
 
527
- if ( $current_item && $current_item->get_id() == $item->get_id() ) {
528
- $defaults[] = 'current';
529
- }
530
 
531
- if ( $item->is_preview() ) {
532
- $defaults[] = 'item-preview';
533
- $defaults[] = 'has-status';
534
- } elseif ( $item->is_blocked() ) {
535
- $defaults[] = 'item-locked';
536
- } else {
537
- if ( $course ) {
538
- if ( $is_free && ! $required_enroll ) {
539
- $defaults[] = 'item-free';
540
- } else {
541
- if ( $user ) {
542
- if ( $enrolled ) {
543
- $item_status = $user->get_item_status( $item_id, $course_id );
544
- $item_grade = $user->get_item_grade( $item_id, $course_id );
545
-
546
- if ( $item_status ) {
547
- $defaults[] = 'has-status';
548
- $defaults[] = 'status-' . $item_status;
549
- }
550
- switch ( $item_status ) {
551
- case 'started':
552
- break;
553
- case 'completed':
554
- $defaults[] = $item_grade;
555
- break;
556
- default:
557
- if ( $item_class = apply_filters( 'learn-press/course-item-status-class', $item_status, $item_grade, $item->get_item_type(), $item_id, $course_id ) ) {
558
- $defaults[] = $item_class;
559
- }
 
560
  }
561
  }
562
- }
563
 
564
- if ( ! $enrolled ) {
565
- $defaults[] = 'item-locked';
 
566
  }
 
 
567
  }
568
- } else {
569
- $defaults[] = 'item-locked';
570
  }
571
- }
572
- $classes = apply_filters( 'learn-press/course-item-class', $defaults, $item->get_item_type(), $item_id, $course_id );
573
 
574
- // Filter unwanted values
575
- $classes = is_array( $classes ) ? $classes : explode( ' ', $classes );
576
- $classes = array_filter( $classes );
577
- $classes = array_unique( $classes );
578
 
579
- LP_Object_Cache::set( 'item-' . $user_id . '-' . $item_id, $classes, 'learn-press/post-classes' );
580
- $items[ $item_id ] = $classes;
 
581
  }
582
 
583
  return $items;
483
  }
484
 
485
  /**
486
+ * Parse attribute 'preview' for all items in a course
487
+ *
488
+ * @since 3.2.0
489
+ *
490
+ * @param int $course_id
491
+ * @param int $user_id
492
+ *
493
+ * @return array
494
+ */
495
+ public function parse_items_preview( $course_id, $user_id = 0 ) {
496
+
497
+ $items = array();
498
+
499
+ if ( ! $course = learn_press_get_course( $course_id ) ) {
500
+ return $items;
501
+ }
502
+
503
+ if ( ! $user_id ) {
504
+ $user_id = get_current_user_id();
505
+ }
506
+
507
+ $user = learn_press_get_user( $user_id, false );
508
+ $current_item = LP_Global::course_item();
509
+ $get_item_ids = $course->get_item_ids();
510
+ $enrolled = $user ? $user->has_enrolled_course( $course_id ) : false;
511
+
512
+ if ( $get_item_ids ) {
513
+ foreach ( $get_item_ids as $item_id ) {
514
+ $is_preview = get_post_meta( $item_id, '_lp_preview', true );#// == 'yes';
515
+ if( $enrolled ){
516
+ $is_preview = 'no';
517
+ }
518
+ if ( false === ( $cached = LP_Object_Cache::get( 'item-' . $user_id . '-' . $course_id . '-' . $item_id, 'learn-press/preview-items' ) ) ) {
519
+ LP_Object_Cache::set( 'item-' . $user_id . '-' . $course->get_id() . '-' . $item_id, $is_preview, 'learn-press/preview-items' );
520
+ } else {
521
+ ///$is_preview = $cached === 'yes' ? true : false;
522
+ }
523
+
524
+ $items[ $item_id ] = $is_preview;
525
+ }
526
+ }
527
+
528
+ return $items;
529
+ }
530
+
531
+ /**
532
+ * Parse classes for all items in a course.
533
+ *
534
  * @since 3.2.0
535
  *
536
  * @param int $course_id
557
  $is_free = $course->is_free();
558
  $required_enroll = $course->is_required_enroll();
559
 
560
+ if ( $get_item_ids ) {
561
+ foreach ( $get_item_ids as $item_id ) {
562
+ $item = $course->get_item( $item_id );
563
 
564
+ $defaults = array_merge(
565
+ array(
566
+ 'course-item',
567
+ 'course-item-' . $item->get_item_type(),
568
+ 'course-item-' . $item_id
569
+ ), (array) $more
570
+ );
571
 
572
+ if ( ( 'standard' !== ( $post_format = $item->get_format() ) ) && $post_format ) {
573
+ $defaults[] = 'course-item-type-' . $post_format;
574
+ }
575
 
576
+ if ( $current_item && $current_item->get_id() == $item->get_id() ) {
577
+ $defaults[] = 'current';
578
+ }
579
 
580
+ if ( $item->is_preview() ) {
581
+ $defaults[] = 'item-preview';
582
+ $defaults[] = 'has-status';
583
+ } elseif ( $item->is_blocked() ) {
584
+ $defaults[] = 'item-locked';
585
+ } else {
586
+ if ( $course ) {
587
+ if ( $is_free && ! $required_enroll ) {
588
+ $defaults[] = 'item-free';
589
+ } else {
590
+ if ( $user ) {
591
+ if ( $enrolled ) {
592
+ $item_status = $user->get_item_status( $item_id, $course_id );
593
+ $item_grade = $user->get_item_grade( $item_id, $course_id );
594
+
595
+ if ( $item_status ) {
596
+ $defaults[] = 'has-status';
597
+ $defaults[] = 'status-' . $item_status;
598
+ }
599
+ switch ( $item_status ) {
600
+ case 'started':
601
+ break;
602
+ case 'completed':
603
+ $defaults[] = $item_grade;
604
+ break;
605
+ default:
606
+ if ( $item_class = apply_filters( 'learn-press/course-item-status-class', $item_status, $item_grade, $item->get_item_type(), $item_id, $course_id ) ) {
607
+ $defaults[] = $item_class;
608
+ }
609
+ }
610
  }
611
  }
 
612
 
613
+ if ( ! $enrolled ) {
614
+ $defaults[] = 'item-locked';
615
+ }
616
  }
617
+ } else {
618
+ $defaults[] = 'item-locked';
619
  }
 
 
620
  }
621
+ $classes = apply_filters( 'learn-press/course-item-class', $defaults, $item->get_item_type(), $item_id, $course_id );
 
622
 
623
+ // Filter unwanted values
624
+ $classes = is_array( $classes ) ? $classes : explode( ' ', $classes );
625
+ $classes = array_filter( $classes );
626
+ $classes = array_unique( $classes );
627
 
628
+ LP_Object_Cache::set( 'item-' . $user_id . '-' . $item_id, $classes, 'learn-press/post-classes' );
629
+ $items[ $item_id ] = $classes;
630
+ }
631
  }
632
 
633
  return $items;
inc/custom-post-types/order.php CHANGED
@@ -435,10 +435,9 @@ if ( ! class_exists( 'LP_Order_Post_Type' ) ) {
435
  * user. If the order is for multi users then it will trigger in
436
  * each child order
437
  */
438
- if ( ! is_array( $user_id ) && ( ( $new_status !== $old_status ) || $trigger_action ) ) {
439
  $status = str_replace( 'lp-', '', $new_status );
440
  do_action( 'learn-press/order/status-' . $status, $order->get_id(), $status );
441
- do_action( 'learn-press/order/status-' . $status . '-to-' . $status, $order->get_id() );
442
  do_action( 'learn-press/order/status-changed', $order->get_id(), $status, $status );
443
  }
444
 
435
  * user. If the order is for multi users then it will trigger in
436
  * each child order
437
  */
438
+ if ( ! is_array( $user_id ) && ( ( $new_status == $old_status ) && $trigger_action ) ) {
439
  $status = str_replace( 'lp-', '', $new_status );
440
  do_action( 'learn-press/order/status-' . $status, $order->get_id(), $status );
 
441
  do_action( 'learn-press/order/status-changed', $order->get_id(), $status, $status );
442
  }
443
 
inc/libraries/meta-box/css/autocomplete.css CHANGED
@@ -11,4 +11,4 @@
11
  width: 10%;
12
  float: right;
13
  cursor: pointer;
14
- }
11
  width: 10%;
12
  float: right;
13
  cursor: pointer;
14
+ }
inc/libraries/meta-box/css/button-group.css CHANGED
@@ -21,48 +21,48 @@
21
  }
22
  /* Layout not inline
23
  -------------------------------------------------*/
24
- .rwmb-button-input-list:not(.inline) li label {
25
  border-top-width: 0;
26
  }
27
- .rwmb-button-input-list:not(.inline) li:first-child label {
28
  border-top-width: 1px;
29
  }
30
- .rwmb-button-input-list:not(.inline) li label.selected {
31
  border-bottom: 1px solid #fff;
32
  }
33
- .rwmb-button-input-list:not(.inline) li:last-child label.selected {
34
  border-bottom-color: #0073aa;
35
  }
36
- .rwmb-button-input-list:not(.inline) > li:first-child:not(:last-child) label {
37
  border-top-left-radius: 3px;
38
  border-top-right-radius: 3px;
39
  }
40
- .rwmb-button-input-list:not(.inline) > li:last-child:not(:first-child) label {
41
  border-bottom-right-radius: 3px;
42
  border-bottom-left-radius: 3px;
43
  }
44
  /* Layout inline
45
  ---------------------------------------------*/
46
- .rwmb-button-input-list.inline li {
47
  display: inline-block;
48
  }
49
- .rwmb-button-input-list.inline li label {
50
  border-left-width: 0;
51
  }
52
- .rwmb-button-input-list.inline li:first-child label {
53
  border-left-width: 1px;
54
  }
55
- .rwmb-button-input-list.inline li label.selected {
56
  border-right-color: rgb(255, 255, 255);
57
  }
58
- .rwmb-button-input-list.inline li:last-child label.selected {
59
  border-right-color: #0073aa;
60
  }
61
- .rwmb-button-input-list.inline > li:first-child:not(:last-child) label {
62
  border-top-left-radius: 3px;
63
  border-bottom-left-radius: 3px;
64
  }
65
- .rwmb-button-input-list.inline > li:last-child:not(:first-child) label {
66
  border-top-right-radius: 3px;
67
  border-bottom-right-radius: 3px;
68
  }
21
  }
22
  /* Layout not inline
23
  -------------------------------------------------*/
24
+ .rwmb-button-input-list:not(.rwmb-inline) li label {
25
  border-top-width: 0;
26
  }
27
+ .rwmb-button-input-list:not(.rwmb-inline) li:first-child label {
28
  border-top-width: 1px;
29
  }
30
+ .rwmb-button-input-list:not(.rwmb-inline) li label.selected {
31
  border-bottom: 1px solid #fff;
32
  }
33
+ .rwmb-button-input-list:not(.rwmb-inline) li:last-child label.selected {
34
  border-bottom-color: #0073aa;
35
  }
36
+ .rwmb-button-input-list:not(.rwmb-inline) > li:first-child:not(:last-child) label {
37
  border-top-left-radius: 3px;
38
  border-top-right-radius: 3px;
39
  }
40
+ .rwmb-button-input-list:not(.rwmb-inline) > li:last-child:not(:first-child) label {
41
  border-bottom-right-radius: 3px;
42
  border-bottom-left-radius: 3px;
43
  }
44
  /* Layout inline
45
  ---------------------------------------------*/
46
+ .rwmb-button-input-list.rwmb-inline li {
47
  display: inline-block;
48
  }
49
+ .rwmb-button-input-list.rwmb-inline li label {
50
  border-left-width: 0;
51
  }
52
+ .rwmb-button-input-list.rwmb-inline li:first-child label {
53
  border-left-width: 1px;
54
  }
55
+ .rwmb-button-input-list.rwmb-inline li label.selected {
56
  border-right-color: rgb(255, 255, 255);
57
  }
58
+ .rwmb-button-input-list.rwmb-inline li:last-child label.selected {
59
  border-right-color: #0073aa;
60
  }
61
+ .rwmb-button-input-list.rwmb-inline > li:first-child:not(:last-child) label {
62
  border-top-left-radius: 3px;
63
  border-bottom-left-radius: 3px;
64
  }
65
+ .rwmb-button-input-list.rwmb-inline > li:last-child:not(:first-child) label {
66
  border-top-right-radius: 3px;
67
  border-bottom-right-radius: 3px;
68
  }
inc/libraries/meta-box/css/color.css CHANGED
@@ -3,6 +3,6 @@
3
  }
4
  .rwmb-color-wrapper .wp-picker-holder {
5
  position: absolute;
6
- z-index: 9;
7
  min-width: 255px;
8
  }
3
  }
4
  .rwmb-color-wrapper .wp-picker-holder {
5
  position: absolute;
6
+ z-index: 99;
7
  min-width: 255px;
8
  }
inc/libraries/meta-box/css/divider.css CHANGED
@@ -4,4 +4,4 @@
4
  .rwmb-divider-wrapper hr {
5
  border: none;
6
  border-top: 1px solid #e6e6e6;
7
- }
4
  .rwmb-divider-wrapper hr {
5
  border: none;
6
  border-top: 1px solid #e6e6e6;
7
+ }
inc/libraries/meta-box/css/heading.css CHANGED
@@ -9,4 +9,4 @@
9
  text-transform: uppercase;
10
  padding: .75rem 0 .375rem;
11
  margin: 0 0 6px;
12
- }
9
  text-transform: uppercase;
10
  padding: .75rem 0 .375rem;
11
  margin: 0 0 6px;
12
+ }
inc/libraries/meta-box/css/input-list.css CHANGED
@@ -9,12 +9,12 @@
9
  list-style: none;
10
  margin-bottom: 0;
11
  }
12
- .rwmb-input-list.inline {
13
  line-height: inherit;
14
  }
15
- .rwmb-input-list.inline li {
16
  display: inline-block;
17
  }
18
- .rwmb-input-list.inline li:not(:last-child) {
19
  margin-right: 20px;
20
  }
9
  list-style: none;
10
  margin-bottom: 0;
11
  }
12
+ .rwmb-input-list.rwmb-inline {
13
  line-height: inherit;
14
  }
15
+ .rwmb-input-list.rwmb-inline li {
16
  display: inline-block;
17
  }
18
+ .rwmb-input-list.rwmb-inline li:not(:last-child) {
19
  margin-right: 20px;
20
  }
inc/libraries/meta-box/css/map.css CHANGED
@@ -3,3 +3,47 @@
3
  height: 400px;
4
  margin-bottom: 10px;
5
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  height: 400px;
4
  margin-bottom: 10px;
5
  }
6
+
7
+ /* Autocomplete style, copy from WordPress's common.css and forms.css */
8
+
9
+ input.ui-autocomplete-input.open {
10
+ border-bottom-color: transparent;
11
+ }
12
+
13
+ .ui-autocomplete {
14
+ padding: 0;
15
+ margin: 0;
16
+ list-style: none;
17
+ position: absolute;
18
+ z-index: 10000;
19
+ border: 1px solid #5b9dd9;
20
+ box-shadow: 0 1px 2px rgba( 30, 140, 190, 0.8 );
21
+ background-color: #fff;
22
+ }
23
+
24
+ .ui-autocomplete li {
25
+ margin-bottom: 0;
26
+ padding: 4px 10px;
27
+ white-space: nowrap;
28
+ text-align: left;
29
+ cursor: pointer;
30
+ }
31
+
32
+ /* Colors for the wplink toolbar autocomplete. */
33
+ .ui-autocomplete .ui-state-focus {
34
+ background-color: #ddd;
35
+ }
36
+
37
+ .ui-helper-hidden-accessible {
38
+ border: 0;
39
+ clip: rect(1px, 1px, 1px, 1px);
40
+ -webkit-clip-path: inset(50%);
41
+ clip-path: inset(50%);
42
+ height: 1px;
43
+ margin: -1px;
44
+ overflow: hidden;
45
+ padding: 0;
46
+ position: absolute;
47
+ width: 1px;
48
+ word-wrap: normal !important; /* many screen reader and browser combinations announce broken words as they would appear visually */
49
+ }
inc/libraries/meta-box/css/oembed.css CHANGED
@@ -8,4 +8,4 @@
8
  }
9
  .rwmb-embed-media iframe {
10
  max-width: 100%;
11
- }
8
  }
9
  .rwmb-embed-media iframe {
10
  max-width: 100%;
11
+ }
inc/libraries/meta-box/css/osm.css ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .rwmb-osm-canvas {
2
+ width: 100%;
3
+ height: 400px;
4
+ margin-bottom: 10px;
5
+ }
6
+
7
+ /* Autocomplete style, copy from WordPress's common.css and forms.css */
8
+
9
+ input.ui-autocomplete-input.open {
10
+ border-bottom-color: transparent;
11
+ }
12
+
13
+ .ui-autocomplete {
14
+ padding: 0;
15
+ margin: 0;
16
+ list-style: none;
17
+ position: absolute;
18
+ z-index: 10000;
19
+ border: 1px solid #5b9dd9;
20
+ box-shadow: 0 1px 2px rgba( 30, 140, 190, 0.8 );
21
+ background-color: #fff;
22
+ }
23
+
24
+ .ui-autocomplete li {
25
+ margin-bottom: 0;
26
+ padding: 4px 10px;
27
+ white-space: nowrap;
28
+ text-align: left;
29
+ cursor: pointer;
30
+ }
31
+
32
+ /* Colors for the wplink toolbar autocomplete. */
33
+ .ui-autocomplete .ui-state-focus {
34
+ background-color: #ddd;
35
+ }
36
+
37
+ .ui-helper-hidden-accessible {
38
+ border: 0;
39
+ clip: rect(1px, 1px, 1px, 1px);
40
+ -webkit-clip-path: inset(50%);
41
+ clip-path: inset(50%);
42
+ height: 1px;
43
+ margin: -1px;
44
+ overflow: hidden;
45
+ padding: 0;
46
+ position: absolute;
47
+ width: 1px;
48
+ word-wrap: normal !important; /* many screen reader and browser combinations announce broken words as they would appear visually */
49
+ }
inc/libraries/meta-box/css/select.css CHANGED
@@ -3,7 +3,7 @@
3
  padding: 0;
4
  }
5
  .rwmb-select option {
6
- padding: 4px 8px;
7
  }
8
  .rwmb-select-all-none {
9
  display: block;
3
  padding: 0;
4
  }
5
  .rwmb-select option {
6
+ padding: 4px 8px;
7
  }
8
  .rwmb-select-all-none {
9
  display: block;
inc/libraries/meta-box/css/select2/select2.css CHANGED
@@ -3,8 +3,7 @@
3
  display: inline-block;
4
  margin: 0;
5
  position: relative;
6
- vertical-align: middle;
7
- }
8
  .select2-container .select2-selection--single {
9
  box-sizing: border-box;
10
  cursor: pointer;
@@ -32,7 +31,7 @@
32
  user-select: none;
33
  -webkit-user-select: none; }
34
  .select2-container .select2-selection--multiple .select2-selection__rendered {
35
- /*display: inline-block;*/
36
  overflow: hidden;
37
  padding-left: 8px;
38
  text-overflow: ellipsis;
@@ -185,6 +184,8 @@
185
  margin: 0;
186
  padding: 0 5px;
187
  width: 100%; }
 
 
188
  .select2-container--default .select2-selection--multiple .select2-selection__placeholder {
189
  color: #999;
190
  margin-top: 5px;
3
  display: inline-block;
4
  margin: 0;
5
  position: relative;
6
+ vertical-align: middle; }
 
7
  .select2-container .select2-selection--single {
8
  box-sizing: border-box;
9
  cursor: pointer;
31
  user-select: none;
32
  -webkit-user-select: none; }
33
  .select2-container .select2-selection--multiple .select2-selection__rendered {
34
+ display: inline-block;
35
  overflow: hidden;
36
  padding-left: 8px;
37
  text-overflow: ellipsis;
184
  margin: 0;
185
  padding: 0 5px;
186
  width: 100%; }
187
+ .select2-container--default .select2-selection--multiple .select2-selection__rendered li {
188
+ list-style: none; }
189
  .select2-container--default .select2-selection--multiple .select2-selection__placeholder {
190
  color: #999;
191
  margin-top: 5px;
inc/libraries/meta-box/css/slider.css CHANGED
@@ -10,4 +10,4 @@
10
  /* Fix slider handle being visible through jQuery panel */
11
  .ui-slider .ui-slider-handle {
12
  z-index: 1;
13
- }
10
  /* Fix slider handle being visible through jQuery panel */
11
  .ui-slider .ui-slider-handle {
12
  z-index: 1;
13
+ }
inc/libraries/meta-box/css/style-rtl.css CHANGED
@@ -1,11 +1,11 @@
1
  .rwmb-label, .rwmb-input{
2
- float: right;
3
  }
4
  label.error{
5
- padding-left: auto;
6
- padding-right: 3px;
7
  }
8
  .rwmb-button.remove-clone {
9
- right: auto;
10
- left: 0;
11
  }
1
  .rwmb-label, .rwmb-input{
2
+ float: right;
3
  }
4
  label.error{
5
+ padding-left: auto;
6
+ padding-right: 3px;
7
  }
8
  .rwmb-button.remove-clone {
9
+ right: auto;
10
+ left: 0;
11
  }
inc/libraries/meta-box/css/text-list.css ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .rwmb-text_list-non-cloneable > .rwmb-input,
2
+ .rwmb-text_list-clone {
3
+ display: flex;
4
+ flex-wrap: wrap;
5
+ }
6
+ .rwmb-text_list-non-cloneable > .rwmb-input > label,
7
+ .rwmb-text_list-clone > label {
8
+ margin: 0 10px 10px 0;
9
+ }
10
+ .rwmb-text_list-non-cloneable > .rwmb-input > label:last-child,
11
+ .rwmb-text_list-clone > label:last-child {
12
+ margin-right: 0;
13
+ }
14
+
15
+ .rwmb-text-list-label {
16
+ font-weight: 600;
17
+ display: block;
18
+ margin-bottom: 5px;
19
+ }
inc/libraries/meta-box/css/upload.css CHANGED
@@ -5,10 +5,6 @@
5
  height: 200px;
6
  border: 4px dashed #ddd;
7
  }
8
- /* Fix blank space in the footer */
9
- .rwmb-upload-area .moxie-shim {
10
- display: none;
11
- }
12
  .rwmb-upload-inside {
13
  text-align: center;
14
  position: absolute;
5
  height: 200px;
6
  border: 4px dashed #ddd;
7
  }
 
 
 
 
8
  .rwmb-upload-inside {
9
  text-align: center;
10
  position: absolute;
inc/libraries/meta-box/inc/about/about.php CHANGED
@@ -28,12 +28,12 @@ class RWMB_About {
28
  // Add links to about page in the plugin action links.
29
  add_filter( 'plugin_action_links_meta-box/meta-box.php', array( $this, 'plugin_links' ) );
30
 
31
- // Add a hidden about page.
32
- add_action( 'admin_menu', array( $this, 'register_page' ) );
33
- add_action( 'admin_head', array( $this, 'hide_page' ) );
34
 
35
- // Enqueue scripts and styles for about page.
36
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) );
37
 
38
  // Redirect to about page after activation.
39
  add_action( 'activated_plugin', array( $this, 'redirect' ), 10, 2 );
@@ -47,28 +47,56 @@ class RWMB_About {
47
  * @return array
48
  */
49
  public function plugin_links( $links ) {
50
- $links[] = '<a href="' . esc_url( admin_url( 'index.php?page=meta-box-about' ) ) . '">' . esc_html__( 'About', 'learnpress' ) . '</a>';
51
  return $links;
52
  }
53
 
54
  /**
55
  * Register admin page.
56
  */
57
- public function register_page() {
58
- add_dashboard_page(
59
- __( 'Welcome to Meta Box', 'learnpress' ),
60
- __( 'Welcome to Meta Box', 'learnpress' ),
 
 
 
61
  'activate_plugins',
62
- 'meta-box-about',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  array( $this, 'render' )
64
  );
 
 
 
 
 
 
 
 
 
65
  }
66
 
67
  /**
68
  * Hide about page from the admin menu.
69
  */
70
  public function hide_page() {
71
- remove_submenu_page( 'index.php', 'meta-box-about' );
72
  }
73
 
74
  /**
@@ -76,10 +104,31 @@ class RWMB_About {
76
  */
77
  public function render() {
78
  ?>
79
- <div class="wrap about-wrap">
80
- <?php include dirname( __FILE__ ) . '/sections/welcome.php'; ?>
81
- <?php include dirname( __FILE__ ) . '/sections/tabs.php'; ?>
82
- <?php include dirname( __FILE__ ) . '/sections/getting-started.php'; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  </div>
84
  <?php
85
  }
@@ -88,12 +137,24 @@ class RWMB_About {
88
  * Enqueue CSS and JS.
89
  */
90
  public function enqueue() {
91
- $screen = get_current_screen();
92
- if ( 'dashboard_page_meta-box-about' !== $screen->id ) {
93
- return;
94
- }
95
- wp_enqueue_style( 'meta-box-about', RWMB_URL . 'inc/about/css/style.css' );
96
- wp_enqueue_script( 'meta-box-about', RWMB_URL . 'inc/about/js/script.js', array( 'jquery' ), '', true );
 
 
 
 
 
 
 
 
 
 
 
 
97
  }
98
 
99
  /**
@@ -104,12 +165,40 @@ class RWMB_About {
104
  * or just the current site. Multisite only. Default is false.
105
  */
106
  public function redirect( $plugin, $network_wide ) {
107
- if ( ! $network_wide && 'meta-box/meta-box.php' === $plugin && ! $this->is_bundled() ) {
108
- wp_safe_redirect( admin_url( 'index.php?page=meta-box-about' ) );
109
  die;
110
  }
111
  }
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  /**
114
  * Check if Meta Box is bundled by TGM Activation Class.
115
  */
@@ -122,4 +211,20 @@ class RWMB_About {
122
  }
123
  return false;
124
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
28
  // Add links to about page in the plugin action links.
29
  add_filter( 'plugin_action_links_meta-box/meta-box.php', array( $this, 'plugin_links' ) );
30
 
31
+ // Add a shared top-level admin menu and Dashboard page. Use priority 5 to show Dashboard at the top.
32
+ add_action( 'admin_menu', array( $this, 'add_menu' ), 5 );
33
+ add_action( 'admin_menu', array( $this, 'add_submenu' ), 5 );
34
 
35
+ // If no admin menu, then hide the About page.
36
+ add_action( 'admin_head', array( $this, 'hide_page' ) );
37
 
38
  // Redirect to about page after activation.
39
  add_action( 'activated_plugin', array( $this, 'redirect' ), 10, 2 );
47
  * @return array
48
  */
49
  public function plugin_links( $links ) {
50
+ $links[] = '<a href="' . esc_url( $this->get_menu_link() ) . '">' . esc_html__( 'About', 'meta-box' ) . '</a>';
51
  return $links;
52
  }
53
 
54
  /**
55
  * Register admin page.
56
  */
57
+ public function add_menu() {
58
+ if ( ! $this->has_menu() ) {
59
+ return;
60
+ }
61
+ add_menu_page(
62
+ __( 'Meta Box', 'meta-box' ),
63
+ __( 'Meta Box', 'meta-box' ),
64
  'activate_plugins',
65
+ 'meta-box',
66
+ '__return_null',
67
+ 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2aWV3Qm94PSIxNjQuMzI4IDE0OS40NDEgNTMuNDcgNDIuNjYiIHdpZHRoPSI1My40NyIgaGVpZ2h0PSI0Mi42NiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cGF0aCBkPSJNIDIwNC42NjggMTc5LjM5MSBMIDIwNS40ODggMTYwLjU1MSBMIDIwNS4zMTggMTYwLjUyMSBMIDE5My44ODggMTkyLjEwMSBMIDE4OC4xNDggMTkyLjEwMSBMIDE3Ni43NzggMTYwLjY0MSBMIDE3Ni42MDggMTYwLjY2MSBMIDE3Ny40MjggMTc5LjM5MSBMIDE3Ny40MjggMTg2LjA5MSBMIDE4MS45OTggMTg2Ljk3MSBMIDE4MS45OTggMTkyLjEwMSBMIDE2NC4zMjggMTkyLjEwMSBMIDE2NC4zMjggMTg2Ljk3MSBMIDE2OC44NjggMTg2LjA5MSBMIDE2OC44NjggMTU1LjQ4MSBMIDE2NC4zMjggMTU0LjYwMSBMIDE2NC4zMjggMTQ5LjQ0MSBMIDE2OC44NjggMTQ5LjQ0MSBMIDE4MC4wMjggMTQ5LjQ0MSBMIDE5MC44OTggMTgwLjg4MSBMIDE5MS4wNzggMTgwLjg4MSBMIDIwMi4wMzggMTQ5LjQ0MSBMIDIxNy43OTggMTQ5LjQ0MSBMIDIxNy43OTggMTU0LjYwMSBMIDIxMy4yMjggMTU1LjQ4MSBMIDIxMy4yMjggMTg2LjA5MSBMIDIxNy43OTggMTg2Ljk3MSBMIDIxNy43OTggMTkyLjEwMSBMIDIwMC4xMjggMTkyLjEwMSBMIDIwMC4xMjggMTg2Ljk3MSBMIDIwNC42NjggMTg2LjA5MSBMIDIwNC42NjggMTc5LjM5MSBaIiBzdHlsZT0iZmlsbDogcmdiKDE1OCwgMTYzLCAxNjgpOyB3aGl0ZS1zcGFjZTogcHJlOyIvPgo8L3N2Zz4='
68
+ );
69
+ }
70
+
71
+ /**
72
+ * Add submenu for the About page.
73
+ */
74
+ public function add_submenu() {
75
+ $parent_menu = $this->has_menu() ? 'meta-box' : $this->get_parent_menu();
76
+ $about = add_submenu_page(
77
+ $parent_menu,
78
+ __( 'Welcome to Meta Box', 'meta-box' ),
79
+ __( 'Dashboard', 'meta-box' ),
80
+ 'activate_plugins',
81
+ 'meta-box',
82
  array( $this, 'render' )
83
  );
84
+ add_action( "load-$about", array( $this, 'load_about' ) );
85
+ }
86
+
87
+ /**
88
+ * Functions and hooks for about page.
89
+ */
90
+ public function load_about() {
91
+ $this->enqueue();
92
+ add_filter( 'admin_footer_text', array( $this, 'change_footer_text' ) );
93
  }
94
 
95
  /**
96
  * Hide about page from the admin menu.
97
  */
98
  public function hide_page() {
99
+ remove_submenu_page( $this->get_parent_menu(), 'meta-box' );
100
  }
101
 
102
  /**
104
  */
105
  public function render() {
106
  ?>
107
+ <div class="wrap">
108
+ <div id="poststuff">
109
+ <div id="post-body" class="metabox-holder columns-2">
110
+ <div id="post-body-content">
111
+ <div class="about-wrap">
112
+ <?php
113
+ include dirname( __FILE__ ) . '/sections/welcome.php';
114
+ include dirname( __FILE__ ) . '/sections/tabs.php';
115
+ include dirname( __FILE__ ) . '/sections/getting-started.php';
116
+ include dirname( __FILE__ ) . '/sections/extensions.php';
117
+ include dirname( __FILE__ ) . '/sections/support.php';
118
+ do_action( 'rwmb_about_tabs_content' );
119
+ ?>
120
+ </div>
121
+ </div>
122
+ <div id="postbox-container-1" class="postbox-container">
123
+ <?php
124
+ include dirname( __FILE__ ) . '/sections/newsletter.php';
125
+ if ( ! $this->is_premium_user() ) {
126
+ include dirname( __FILE__ ) . '/sections/upgrade.php';
127
+ }
128
+ ?>
129
+ </div>
130
+ </div>
131
+ </div>
132
  </div>
133
  <?php
134
  }
137
  * Enqueue CSS and JS.
138
  */
139
  public function enqueue() {
140
+ wp_enqueue_style( 'meta-box-about', RWMB_URL . 'inc/about/css/about.css', array(), RWMB_VER );
141
+ wp_enqueue_script( 'meta-box-about', RWMB_URL . 'inc/about/js/about.js', array( 'jquery' ), RWMB_VER, true );
142
+ }
143
+
144
+ /**
145
+ * Change WordPress footer text on about page.
146
+ */
147
+ public function change_footer_text() {
148
+ $allowed_html = array(
149
+ 'a' => array(
150
+ 'href' => array(),
151
+ 'target' => array(),
152
+ ),
153
+ 'strong' => array(),
154
+ );
155
+
156
+ // Translators: %1$s - link to review form.
157
+ echo wp_kses( sprintf( __( 'Please rate <strong>Meta Box</strong> <a href="%1$s" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a> on <a href="%1$s" target="_blank">WordPress.org</a> to help us spread the word. Thank you from the Meta Box team!', 'meta-box' ), 'https://wordpress.org/support/view/plugin-reviews/meta-box?filter=5#new-post' ), $allowed_html );
158
  }
159
 
160
  /**
165
  * or just the current site. Multisite only. Default is false.
166
  */
167
  public function redirect( $plugin, $network_wide ) {
168
+ if ( 'cli' !== php_sapi_name() && ! $network_wide && 'meta-box/meta-box.php' === $plugin && ! $this->is_bundled() ) {
169
+ wp_safe_redirect( $this->get_menu_link() );
170
  die;
171
  }
172
  }
173
 
174
+ /**
175
+ * Get link to the plugin admin menu.
176
+ *
177
+ * @return string
178
+ */
179
+ protected function get_menu_link() {
180
+ $menu = $this->has_menu() ? 'admin.php?page=meta-box' : $this->get_parent_menu() . '?page=meta-box';
181
+ return admin_url( $menu );
182
+ }
183
+
184
+ /**
185
+ * Get default parent menu, which is Plugins.
186
+ *
187
+ * @return string
188
+ */
189
+ protected function get_parent_menu() {
190
+ return 'plugins.php';
191
+ }
192
+
193
+ /**
194
+ * Check if the plugin has a top-level admin menu.
195
+ *
196
+ * @return bool
197
+ */
198
+ protected function has_menu() {
199
+ return apply_filters( 'rwmb_admin_menu', false );
200
+ }
201
+
202
  /**
203
  * Check if Meta Box is bundled by TGM Activation Class.
204
  */
211
  }
212
  return false;
213
  }
214
+
215
+ /**
216
+ * Check if current user is a premium user.
217
+ *
218
+ * @return bool
219
+ */
220
+ protected function is_premium_user() {
221
+ $option = is_multisite() ? get_site_option( 'meta_box_updater' ) : get_option( 'meta_box_updater' );
222
+ if ( empty( $option['api_key'] ) ) {
223
+ return false;
224
+ }
225
+ if ( isset( $option['status'] ) && 'success' !== $option['status'] ) {
226
+ return false;
227
+ }
228
+ return true;
229
+ }
230
  }
inc/libraries/meta-box/inc/about/css/about.css ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .about-wrap.about-wrap .wp-badge {
2
+ background-image: url(../images/meta-box.svg);
3
+ background-color: #fff;
4
+ color: #222;
5
+ text-transform: uppercase;
6
+ font-weight: bold;
7
+ text-decoration: none;
8
+ }
9
+
10
+ .wp-badge:hover {
11
+ text-decoration: none;
12
+ }
13
+
14
+ .about-buttons .dashicons {
15
+ position: relative;
16
+ top: 5px;
17
+ width: 16px;
18
+ height: 16px;
19
+ font-size: 16px;
20
+ }
21
+
22
+ #poststuff .nav-tab-wrapper {
23
+ padding: 0;
24
+ margin-top: 60px;
25
+ }
26
+
27
+ .feature-section.two-col {
28
+ align-items: flex-start;
29
+ }
30
+
31
+ .feature-section.two-col h3:not(:first-child) {
32
+ margin-top: 3em;
33
+ }
34
+
35
+ .feature-section img {
36
+ display: block;
37
+ box-shadow: 0 0 20px rgba(0, 0, 0, .1);
38
+ }
39
+
40
+ .nav-tab-active:focus {
41
+ box-shadow: none;
42
+ }
43
+
44
+ .gt-tab-pane {
45
+ display: none;
46
+ }
47
+
48
+ .gt-is-active {
49
+ display: block;
50
+ }
51
+
52
+ .screenshot {
53
+ display: block;
54
+ margin: 3em auto;
55
+ }
56
+ .col ul {
57
+ font-size: 14px;
58
+ margin: 2em 0;
59
+ }
60
+
61
+ .col li a {
62
+ text-decoration: none;
63
+ }
64
+
65
+ .col .dashicons {
66
+ color: #82878c;
67
+ padding-right: 5px;
68
+ font-size: 16px;
69
+ vertical-align: middle;
70
+ }
71
+
72
+ /* Extensions tab */
73
+ .theme-browser {
74
+ margin-top: 40px;
75
+ }
76
+ .theme-browser .theme:hover {
77
+ cursor: initial;
78
+ }
79
+ .extension-inner {
80
+ display: flex;
81
+ background: #fff;
82
+ padding: 25px 20px;
83
+ }
84
+ .extension-inner svg {
85
+ width: 36px;
86
+ height: 36px;
87
+ margin: 8px 15px 0 0;
88
+ fill: #b4b9be;
89
+ }
90
+ .extension-info {
91
+ flex: 1;
92
+ }
93
+ .extension-info.extension-info h3 {
94
+ margin: 0 0 5px;
95
+ font-size: 1.2em;
96
+ }
97
+ .extension-info p {
98
+ margin: 0;
99
+ }
100
+ .extension-action {
101
+ border-top: 1px solid #ddd;
102
+ text-align: center;
103
+ padding: 20px;
104
+ background: #f7f7f7;
105
+ }
106
+
107
+ /* Extensions tab: 2 columns */
108
+ .extension {
109
+ margin-bottom: 4%;
110
+ }
111
+ @media (min-width: 768px) {
112
+ .extension {
113
+ float: left;
114
+ width: 47.5%;
115
+ margin: 0 4% 4% 0;
116
+ }
117
+ .extension:nth-child(2n) {
118
+ margin-right: 0;
119
+ }
120
+ .extension:nth-child(2n+1) {
121
+ clear: left;
122
+ }
123
+ }
124
+ /* For large screen: 2 columns */
125
+ @media (min-width: 1640px) {
126
+ .extension {
127
+ width: 30.6%;
128
+ }
129
+ .extension:nth-child(2n) {
130
+ margin-right: 4%;
131
+ }
132
+ .extension:nth-child(2n+1) {
133
+ clear: none;
134
+ }
135
+ .extension:nth-child(3n) {
136
+ margin-right: 0;
137
+ }
138
+ .extension:nth-child(3n+1) {
139
+ clear: left;
140
+ }
141
+ }
142
+
143
+ /* Right column */
144
+ #post-body.columns-2 #postbox-container-1 {
145
+ position: fixed;
146
+ right: 320px;
147
+ top: 40px;
148
+ }
149
+
150
+ @media (max-width: 1279px) {
151
+ #postbox-container-1 {
152
+ display: none;
153
+ }
154
+ #poststuff #post-body.columns-2 {
155
+ margin-right: 0;
156
+ }
157
+ }
158
+
159
+ /* Newsletter */
160
+ .newsletter {
161
+ margin: 40px 0;
162
+ border: 3px dashed #82878c;
163
+ padding: 15px;
164
+ background: #fff;
165
+ }
166
+ .newsletter .dashicons {
167
+ color: #00b9eb;
168
+ width: 30px;
169
+ height: 30px;
170
+ font-size: 30px;
171
+ position: relative;
172
+ top: -5px;
173
+ left: -2px;
174
+ }
175
+ .newsletter h3 {
176
+ margin: 0 0 5px;
177
+ }
178
+ .newsletter p {
179
+ margin-top: 0;
180
+ }
181
+ .newsletter.newsletter input,
182
+ .newsletter.newsletter button {
183
+ margin-top: 5px;
184
+ }
185
+ .newsletter.newsletter input {
186
+ width: 145px;
187
+ padding: 5px;
188
+ }
189
+
190
+ /* Upgrade */
191
+ .upgrade {
192
+ border: 3px dashed #82878c;
193
+ background: #fff;
194
+ padding: 15px;
195
+ }
196
+ .upgrade .dashicons {
197
+ color: #ef4836;
198
+ width: 26px;
199
+ height: 26px;
200
+ font-size: 30px;
201
+ position: relative;
202
+ top: -4px;
203
+ left: -5px;
204
+ }
205
+ .upgrade h3 {
206
+ margin: 0;
207
+ }
208
+ .upgrade li {
209
+ padding-left: 20px;
210
+ position: relative;
211
+ }
212
+ .upgrade svg {
213
+ width: 1em;
214
+ height: 1em;
215
+ fill: #0073aa;
216
+ position: absolute;
217
+ top: 4px;
218
+ left: 0;
219
+ }
inc/libraries/meta-box/inc/about/images/meta-box.svg ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <svg viewBox="227 227 46 46" width="46" height="46" xmlns="http://www.w3.org/2000/svg">
3
+ <rect style="" x="227" y="227" width="46" height="46" rx="4" ry="4"/>
4
+ <path d="M 256.873 255.508 L 257.283 246.088 L 257.193 246.078 L 251.483 261.868 L 248.613 261.868 L 242.933 246.138 L 242.843 246.148 L 243.253 255.508 L 243.253 258.868 L 245.533 259.308 L 245.533 261.868 L 236.703 261.868 L 236.703 259.308 L 238.973 258.868 L 238.973 243.558 L 236.703 243.118 L 236.703 240.538 L 238.973 240.538 L 244.553 240.538 L 249.993 256.258 L 250.073 256.258 L 255.553 240.538 L 263.433 240.538 L 263.433 243.118 L 261.153 243.558 L 261.153 258.868 L 263.433 259.308 L 263.433 261.868 L 254.603 261.868 L 254.603 259.308 L 256.873 258.868 L 256.873 255.508 Z" style="fill:#fff"/>
5
+ </svg>
inc/libraries/meta-box/inc/about/js/about.js ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ( function ( $ ) {
2
+ 'use strict';
3
+
4
+ function tabs() {
5
+ var $container = $( '.nav-tab-wrapper' ),
6
+ $tabs = $container.find( '.nav-tab' ),
7
+ $panes = $( '.gt-tab-pane' );
8
+
9
+ $container.on(
10
+ 'click',
11
+ '.nav-tab',
12
+ function ( e ) {
13
+ e.preventDefault();
14
+
15
+ $tabs.removeClass( 'nav-tab-active' );
16
+ $( this ).addClass( 'nav-tab-active' );
17
+
18
+ $panes.removeClass( 'gt-is-active' );
19
+ $panes.filter( $( this ).attr( 'href' ) ).addClass( 'gt-is-active' );
20
+ }
21
+ );
22
+ }
23
+
24
+ // Auto activate tabs when DOM ready.
25
+ $( tabs );
26
+ } ( jQuery ) );
inc/libraries/meta-box/inc/about/sections/extensions.php ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Extensions section.
4
+ *
5
+ * @package Meta Box
6
+ */
7
+
8
+ ?>
9
+ <div id="extensions" class="gt-tab-pane">
10
+ <p class="about-description">
11
+ <?php esc_html_e( 'Extend custom fields in WordPress well beyond what others would ever consider ordinary! Save over 70% with our extensions bundles.', 'meta-box' ); ?> <a target="_blank" href="https://metabox.io/pricing/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin"><?php esc_html_e( 'View Bundles', 'meta-box' ); ?> &rarr;</a>
12
+ </p>
13
+ <div class="extensions wp-clearfix">
14
+ <div class="extension">
15
+ <div class="extension-inner">
16
+ <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M736 1440q0 12-10 24l-319 319q-10 9-23 9-12 0-23-9l-320-320q-15-16-7-35 8-20 30-20h192v-1376q0-14 9-23t23-9h192q14 0 23 9t9 23v1376h192q14 0 23 9t9 23zm1056 128v192q0 14-9 23t-23 9h-832q-14 0-23-9t-9-23v-192q0-14 9-23t23-9h832q14 0 23 9t9 23zm-192-512v192q0 14-9 23t-23 9h-640q-14 0-23-9t-9-23v-192q0-14 9-23t23-9h640q14 0 23 9t9 23zm-192-512v192q0 14-9 23t-23 9h-448q-14 0-23-9t-9-23v-192q0-14 9-23t23-9h448q14 0 23 9t9 23zm-192-512v192q0 14-9 23t-23 9h-256q-14 0-23-9t-9-23v-192q0-14 9-23t23-9h256q14 0 23 9t9 23z"/></svg>
17
+ <div class="extension-info">
18
+ <h3>Meta Box Builder</h3>
19
+ <p><?php esc_html_e( 'Drag and drop your custom fields into place without a single line of code.', 'meta-box' ); ?></p>
20
+ </div>
21
+ </div>
22
+ <div class="extension-action">
23
+ <a class="button" target="_blank" href="https://metabox.io/plugins/meta-box-builder/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin"><?php esc_html_e( 'Learn More', 'meta-box' ); ?></a>
24
+ </div>
25
+ </div>
26
+ <div class="extension">
27
+ <div class="extension-inner">
28
+ <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1596 476q14 14 28 36h-472v-472q22 14 36 28zm-476 164h544v1056q0 40-28 68t-68 28h-1344q-40 0-68-28t-28-68v-1600q0-40 28-68t68-28h800v544q0 40 28 68t68 28zm160 736v-64q0-14-9-23t-23-9h-704q-14 0-23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23-9t9-23zm0-256v-64q0-14-9-23t-23-9h-704q-14 0-23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23-9t9-23zm0-256v-64q0-14-9-23t-23-9h-704q-14 0-23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23-9t9-23z" /></svg>
29
+ <div class="extension-info">
30
+ <h3>MB Custom Post Type</h3>
31
+ <p><?php esc_html_e( 'Create and manage custom post types easily in WordPress with an easy-to-use interface.', 'meta-box' ); ?></p>
32
+ </div>
33
+ </div>
34
+ <div class="extension-action">
35
+ <a class="button" target="_blank" href="https://metabox.io/plugins/custom-post-type/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin"><?php esc_html_e( 'Free Download', 'meta-box' ); ?></a>
36
+ </div>
37
+ </div>
38
+ <div class="extension">
39
+ <div class="extension-inner">
40
+ <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M512 1248v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68zm0-512v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68zm1280 512v192q0 40-28 68t-68 28h-960q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h960q40 0 68 28t28 68zm-1280-1024v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68zm1280 512v192q0 40-28 68t-68 28h-960q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h960q40 0 68 28t28 68zm0-512v192q0 40-28 68t-68 28h-960q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h960q40 0 68 28t28 68z" /></svg>
41
+ <div class="extension-info">
42
+ <h3>Meta Box Group</h3>
43
+ <p><?php esc_html_e( 'Create repeatable groups of custom fields for better appearance and structure.', 'meta-box' ); ?></p>
44
+ </div>
45
+ </div>
46
+ <div class="extension-action">
47
+ <a class="button" target="_blank" href="https://metabox.io/plugins/meta-box-group/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin"><?php esc_html_e( 'Learn More', 'meta-box' ); ?></a>
48
+ </div>
49
+ </div>
50
+ <div class="extension">
51
+ <div class="extension-inner">
52
+ <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1152 896q0-106-75-181t-181-75-181 75-75 181 75 181 181 75 181-75 75-181zm512-109v222q0 12-8 23t-20 13l-185 28q-19 54-39 91 35 50 107 138 10 12 10 25t-9 23q-27 37-99 108t-94 71q-12 0-26-9l-138-108q-44 23-91 38-16 136-29 186-7 28-36 28h-222q-14 0-24.5-8.5t-11.5-21.5l-28-184q-49-16-90-37l-141 107q-10 9-25 9-14 0-25-11-126-114-165-168-7-10-7-23 0-12 8-23 15-21 51-66.5t54-70.5q-27-50-41-99l-183-27q-13-2-21-12.5t-8-23.5v-222q0-12 8-23t19-13l186-28q14-46 39-92-40-57-107-138-10-12-10-24 0-10 9-23 26-36 98.5-107.5t94.5-71.5q13 0 26 10l138 107q44-23 91-38 16-136 29-186 7-28 36-28h222q14 0 24.5 8.5t11.5 21.5l28 184q49 16 90 37l142-107q9-9 24-9 13 0 25 10 129 119 165 170 7 8 7 22 0 12-8 23-15 21-51 66.5t-54 70.5q26 50 41 98l183 28q13 2 21 12.5t8 23.5z" /></svg>
53
+ <div class="extension-info">
54
+ <h3>MB Settings Page</h3>
55
+ <p><?php esc_html_e( 'Create a powerful settings page for your theme, plugin or website.', 'meta-box' ); ?></p>
56
+ </div>
57
+ </div>
58
+ <div class="extension-action">
59
+ <a class="button" target="_blank" href="https://metabox.io/plugins/mb-settings-page/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin"><?php esc_html_e( 'Learn More', 'meta-box' ); ?></a>
60
+ </div>
61
+