Toolset Types – Custom Post Types, Custom Fields and Taxonomies - Version 2.0

Version Description

  • Release date: 2016-04-11
  • Revamped Field Control page for all field domains.
  • Added information table on post, post type and field group edit pages.
  • Added columns with previews of field values in taxonomy term listing pages.
  • Fixed issue with cursor that was moved automatically to the end of the slug input.
  • Fixed issue with slugs that could not be numeric.
  • Fixed disabled buttons when saving a child post in post-relationship table.
  • Fixed upgrade issue from version 1.9 to 1.9.1 that was removing assignment between custom post types and native taxonomies.
  • Fixed issue with initial expression of "Advanced text mode" in data-dependent display conditions for field groups.
  • Fixed issue with special characters when displaying taxonomy names on the Edit Taxonomy page.
  • Fixed issue with special characters when displaying term names on the Edit Post Field Group page.
Download this release

Release Info

Developer christianglingener
Plugin Icon 128x128 Toolset Types – Custom Post Types, Custom Fields and Taxonomies
Version 2.0
Comparing to
See all releases

Code changes from version 1.9.1 to 2.0

Files changed (221) hide show
  1. admin.php +0 -1559
  2. application/api.php +4 -0
  3. application/bootstrap.php +69 -0
  4. application/controllers/admin.php +54 -0
  5. application/controllers/admin_menu.php +124 -0
  6. application/controllers/ajax.php +278 -0
  7. application/controllers/asset/help_tab_loader.php +151 -0
  8. application/controllers/asset/manager.php +79 -0
  9. application/controllers/assets.php +57 -0
  10. application/controllers/dialog_box.php +89 -0
  11. application/controllers/embedded.php +28 -0
  12. application/controllers/field/type_converter.php +196 -0
  13. application/controllers/field/utils.php +382 -0
  14. application/controllers/frontend.php +14 -0
  15. application/controllers/information/controller.php +211 -0
  16. application/controllers/main.php +86 -0
  17. application/controllers/page/abstract.php +84 -0
  18. application/controllers/page/extension/edit_post.php +60 -0
  19. application/controllers/page/extension/edit_post_fields.php +58 -0
  20. application/controllers/page/extension/edit_post_type.php +51 -0
  21. application/controllers/page/field_control.php +618 -0
  22. application/controllers/page/hidden/helper.php +136 -0
  23. application/controllers/twig_autoloader.php +84 -0
  24. application/data/information/documentation-urls.php +27 -0
  25. application/data/information/layouts-not-compatible.php +30 -0
  26. application/data/information/table/archive.php +290 -0
  27. application/data/information/table/forms.php +134 -0
  28. application/data/information/table/question-marks.php +70 -0
  29. application/data/information/table/template.php +264 -0
  30. application/data/information/table/views.php +134 -0
  31. application/functions.php +186 -0
  32. application/models/api/helper.php +25 -0
  33. application/models/field/type/definition.php +167 -0
  34. application/models/field/type/definition/checkbox.php +39 -0
  35. application/models/field/type/definition/numeric.php +39 -0
  36. application/models/field/type/definition/singular.php +18 -0
  37. application/models/field/type/definition_factory.php +243 -0
  38. application/models/helper/condition.php +32 -0
  39. application/models/helper/condition/archive/exists.php +31 -0
  40. application/models/helper/condition/archive/has_fields.php +18 -0
  41. application/models/helper/condition/archive/missing.php +13 -0
  42. application/models/helper/condition/archive/no_fields.php +32 -0
  43. application/models/helper/condition/archive/no_support.php +12 -0
  44. application/models/helper/condition/archive/support.php +17 -0
  45. application/models/helper/condition/cred/active.php +13 -0
  46. application/models/helper/condition/cred/forms_exist.php +64 -0
  47. application/models/helper/condition/cred/forms_missing.php +15 -0
  48. application/models/helper/condition/cred/missing.php +10 -0
  49. application/models/helper/condition/layouts/active.php +13 -0
  50. application/models/helper/condition/layouts/archive_exists.php +39 -0
  51. application/models/helper/condition/layouts/archive_missing.php +13 -0
  52. application/models/helper/condition/layouts/compatible.php +40 -0
  53. application/models/helper/condition/layouts/missing.php +10 -0
  54. application/models/helper/condition/layouts/template_exists.php +76 -0
  55. application/models/helper/condition/layouts/template_missing.php +12 -0
  56. application/models/helper/condition/screen.php +18 -0
  57. application/models/helper/condition/single/exists.php +14 -0
  58. application/models/helper/condition/single/has_fields.php +16 -0
  59. application/models/helper/condition/single/missing.php +10 -0
  60. application/models/helper/condition/single/no_fields.php +30 -0
  61. application/models/helper/condition/template.php +23 -0
  62. application/models/helper/condition/type/fields_assigned.php +25 -0
  63. application/models/helper/condition/views/active.php +13 -0
  64. application/models/helper/condition/views/archive_exists.php +48 -0
  65. application/models/helper/condition/views/archive_missing.php +15 -0
  66. application/models/helper/condition/views/missing.php +10 -0
  67. application/models/helper/condition/views/template_exists.php +74 -0
  68. application/models/helper/condition/views/template_missing.php +15 -0
  69. application/models/helper/condition/views/views_exist.php +54 -0
  70. application/models/helper/condition/views/views_missing.php +15 -0
  71. application/models/helper/create/content_template.php +71 -0
  72. application/models/helper/create/form.php +40 -0
  73. application/models/helper/create/layout.php +120 -0
  74. application/models/helper/create/view.php +39 -0
  75. application/models/helper/create/wordpress_archive.php +62 -0
  76. application/models/helper/output/interface.php +7 -0
  77. application/models/helper/output/meta_box.php +70 -0
  78. application/models/helper/placeholder.php +272 -0
  79. application/models/helper/twig.php +21 -0
  80. application/models/helper/type_hinting.php +30 -0
  81. application/models/helper/url.php +92 -0
  82. application/models/information/container.php +168 -0
  83. application/models/information/message.php +219 -0
  84. application/models/information/table.php +61 -0
  85. application/views/help/basic.twig +25 -0
  86. application/views/information/description/dialog.twig +22 -0
  87. application/views/information/description/link.twig +5 -0
  88. application/views/information/description/list.twig +5 -0
  89. application/views/information/description/paragraph.twig +3 -0
  90. application/views/information/single.twig +18 -0
  91. application/views/information/table.twig +44 -0
  92. application/views/information/table/tbody-cell.twig +9 -0
  93. application/views/information/table/thead-cell.twig +17 -0
  94. application/views/page/base.twig +9 -0
  95. application/views/page/field_control/bulk_change_management_status_dialog.twig +11 -0
  96. application/views/page/field_control/change_assignment_dialog.twig +20 -0
  97. application/views/page/field_control/change_type_dialog.twig +59 -0
  98. application/views/page/field_control/delete_dialog.twig +14 -0
  99. application/views/page/field_control/main.twig +187 -0
  100. application/views/page/field_control/message_definition_list.html +8 -0
  101. application/views/page/field_control/message_multiple.html +8 -0
  102. embedded/admin.php +0 -728
  103. embedded/bootstrap.php +0 -431
  104. embedded/classes/field.php +0 -990
  105. embedded/classes/field/data_saver.php +0 -151
  106. embedded/classes/field/datamapper/checkboxes.php +0 -54
  107. embedded/classes/field/definition.php +0 -362
  108. embedded/classes/field/definition_abstract.php +0 -61
  109. embedded/classes/field/definition_factory.php +0 -455
  110. embedded/classes/field/definition_term.php +0 -67
  111. embedded/classes/field/group.php +0 -338
  112. embedded/classes/field/group_factory.php +0 -259
  113. embedded/classes/field/group_term.php +0 -115
  114. embedded/classes/field/group_term_factory.php +0 -136
  115. embedded/classes/field/renderer/factory.php +0 -86
  116. embedded/classes/field/term_definition_factory.php +0 -51
  117. embedded/classes/field/type_definition.php +0 -79
  118. embedded/classes/field/type_definition_factory.php +0 -148
  119. embedded/classes/field/utils.php +0 -65
  120. embedded/classes/gui/term_field_editing.php +0 -411
  121. embedded/classes/loader.php +0 -335
  122. embedded/classes/repeater.php +0 -1196
  123. embedded/classes/usermeta_field.php +0 -188
  124. embedded/classes/usermeta_repeater.php +0 -575
  125. embedded/classes/validate.php +0 -6
  126. embedded/classes/validation-cakephp.php +0 -1141
  127. embedded/composer/installed.json +0 -247
  128. embedded/composer/installers/.editorconfig +0 -10
  129. embedded/composer/installers/.travis.yml +0 -21
  130. embedded/composer/installers/LICENSE +0 -19
  131. embedded/composer/installers/README.md +0 -193
  132. embedded/composer/installers/phpunit.xml.dist +0 -25
  133. embedded/composer/installers/src/Composer/Installers/AglInstaller.php +0 -21
  134. embedded/composer/installers/src/Composer/Installers/AimeosInstaller.php +0 -9
  135. embedded/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php +0 -11
  136. embedded/composer/installers/src/Composer/Installers/AsgardInstaller.php +0 -45
  137. embedded/composer/installers/src/Composer/Installers/BaseInstaller.php +0 -135
  138. embedded/composer/installers/src/Composer/Installers/BitrixInstaller.php +0 -89
  139. embedded/composer/installers/src/Composer/Installers/BonefishInstaller.php +0 -9
  140. embedded/composer/installers/src/Composer/Installers/CakePHPInstaller.php +0 -84
  141. embedded/composer/installers/src/Composer/Installers/ChefInstaller.php +0 -11
  142. embedded/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php +0 -10
  143. embedded/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php +0 -11
  144. embedded/composer/installers/src/Composer/Installers/Concrete5Installer.php +0 -12
  145. embedded/composer/installers/src/Composer/Installers/CraftInstaller.php +0 -35
  146. embedded/composer/installers/src/Composer/Installers/CroogoInstaller.php +0 -21
  147. embedded/composer/installers/src/Composer/Installers/DokuWikiInstaller.php +0 -50
  148. embedded/composer/installers/src/Composer/Installers/DolibarrInstaller.php +0 -16
  149. embedded/composer/installers/src/Composer/Installers/DrupalInstaller.php +0 -14
  150. embedded/composer/installers/src/Composer/Installers/ElggInstaller.php +0 -9
  151. embedded/composer/installers/src/Composer/Installers/FuelInstaller.php +0 -11
  152. embedded/composer/installers/src/Composer/Installers/FuelphpInstaller.php +0 -9
  153. embedded/composer/installers/src/Composer/Installers/GravInstaller.php +0 -30
  154. embedded/composer/installers/src/Composer/Installers/HuradInstaller.php +0 -25
  155. embedded/composer/installers/src/Composer/Installers/Installer.php +0 -176
  156. embedded/composer/installers/src/Composer/Installers/JoomlaInstaller.php +0 -15
  157. embedded/composer/installers/src/Composer/Installers/KirbyInstaller.php +0 -9
  158. embedded/composer/installers/src/Composer/Installers/KodiCMSInstaller.php +0 -10
  159. embedded/composer/installers/src/Composer/Installers/KohanaInstaller.php +0 -9
  160. embedded/composer/installers/src/Composer/Installers/LaravelInstaller.php +0 -9
  161. embedded/composer/installers/src/Composer/Installers/LithiumInstaller.php +0 -10
  162. embedded/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php +0 -9
  163. embedded/composer/installers/src/Composer/Installers/MODXEvoInstaller.php +0 -16
  164. embedded/composer/installers/src/Composer/Installers/MagentoInstaller.php +0 -11
  165. embedded/composer/installers/src/Composer/Installers/MakoInstaller.php +0 -9
  166. embedded/composer/installers/src/Composer/Installers/MediaWikiInstaller.php +0 -50
  167. embedded/composer/installers/src/Composer/Installers/MicroweberInstaller.php +0 -111
  168. embedded/composer/installers/src/Composer/Installers/MoodleInstaller.php +0 -56
  169. embedded/composer/installers/src/Composer/Installers/OctoberInstaller.php +0 -46
  170. embedded/composer/installers/src/Composer/Installers/OxidInstaller.php +0 -59
  171. embedded/composer/installers/src/Composer/Installers/PPIInstaller.php +0 -9
  172. embedded/composer/installers/src/Composer/Installers/PhpBBInstaller.php +0 -11
  173. embedded/composer/installers/src/Composer/Installers/PimcoreInstaller.php +0 -21
  174. embedded/composer/installers/src/Composer/Installers/PiwikInstaller.php +0 -32
  175. embedded/composer/installers/src/Composer/Installers/Plugin.php +0 -17
  176. embedded/composer/installers/src/Composer/Installers/PrestashopInstaller.php +0 -10
  177. embedded/composer/installers/src/Composer/Installers/PuppetInstaller.php +0 -11
  178. embedded/composer/installers/src/Composer/Installers/RedaxoInstaller.php +0 -10
  179. embedded/composer/installers/src/Composer/Installers/RoundcubeInstaller.php +0 -22
  180. embedded/composer/installers/src/Composer/Installers/SMFInstaller.php +0 -10
  181. embedded/composer/installers/src/Composer/Installers/ShopwareInstaller.php +0 -58
  182. embedded/composer/installers/src/Composer/Installers/SilverStripeInstaller.php +0 -36
  183. embedded/composer/installers/src/Composer/Installers/Symfony1Installer.php +0 -26
  184. embedded/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php +0 -14
  185. embedded/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php +0 -38
  186. embedded/composer/installers/src/Composer/Installers/TheliaInstaller.php +0 -12
  187. embedded/composer/installers/src/Composer/Installers/TuskInstaller.php +0 -14
  188. embedded/composer/installers/src/Composer/Installers/WHMCSInstaller.php +0 -10
  189. embedded/composer/installers/src/Composer/Installers/WolfCMSInstaller.php +0 -9
  190. embedded/composer/installers/src/Composer/Installers/WordPressInstaller.php +0 -11
  191. embedded/composer/installers/src/Composer/Installers/ZendInstaller.php +0 -11
  192. embedded/composer/installers/src/Composer/Installers/ZikulaInstaller.php +0 -10
  193. embedded/composer/installers/src/bootstrap.php +0 -13
  194. embedded/composer/installers/tests/Composer/Installers/Test/AsgardInstallerTest.php +0 -61
  195. embedded/composer/installers/tests/Composer/Installers/Test/CakePHPInstallerTest.php +0 -115
  196. embedded/composer/installers/tests/Composer/Installers/Test/CraftInstallerTest.php +0 -83
  197. embedded/composer/installers/tests/Composer/Installers/Test/DokuWikiInstallerTest.php +0 -89
  198. embedded/composer/installers/tests/Composer/Installers/Test/GravInstallerTest.php +0 -63
  199. embedded/composer/installers/tests/Composer/Installers/Test/InstallerTest.php +0 -428
  200. embedded/composer/installers/tests/Composer/Installers/Test/MediaWikiInstallerTest.php +0 -66
  201. embedded/composer/installers/tests/Composer/Installers/Test/OctoberInstallerTest.php +0 -66
  202. embedded/composer/installers/tests/Composer/Installers/Test/PimcoreInstallerTest.php +0 -44
  203. embedded/composer/installers/tests/Composer/Installers/Test/PiwikInstallerTest.php +0 -63
  204. embedded/composer/installers/tests/Composer/Installers/Test/TestCase.php +0 -64
  205. embedded/composer/installers/tests/bootstrap.php +0 -4
  206. embedded/frontend.php +0 -1128
  207. embedded/functions.php +0 -1076
  208. embedded/includes/ajax.php +0 -645
  209. embedded/includes/autoloader.php +0 -274
  210. embedded/includes/conditional-display.php +0 -363
  211. embedded/includes/custom-types.php +0 -699
  212. embedded/includes/fields-post.php +0 -1967
  213. embedded/includes/fields.php +0 -967
  214. embedded/includes/fields/checkboxes.php +0 -385
  215. embedded/includes/fields/date.php +0 -559
  216. embedded/includes/fields/date/functions.php +0 -521
  217. embedded/includes/fields/email.php +0 -97
  218. embedded/includes/fields/entry.php +0 -266
  219. embedded/includes/fields/file.php +0 -248
  220. embedded/includes/fields/image.php +0 -1087
  221. embedded/includes/fields/numeric.php +0 -43
admin.php DELETED
@@ -1,1559 +0,0 @@
1
- <?php
2
- /**
3
- *
4
- * Admin functions
5
- *
6
- *
7
- */
8
- require_once WPCF_ABSPATH.'/marketing.php';
9
- require_once WPCF_ABSPATH.'/includes/classes/class.wpcf.roles.php';
10
- WPCF_Roles::getInstance();
11
- /*
12
- * This needs to be called after main 'init' hook.
13
- * Main init hook calls required Types code for frontend.
14
- * Admin init hook only in admin area.
15
- *
16
- * TODO Revise it to change to 'admin_init'
17
- */
18
- add_action( 'admin_init', 'wpcf_admin_init_hook', 11 );
19
-
20
- add_action( 'init', 'wpcf_init_admin_pages' );
21
-
22
- add_action( 'admin_menu', 'wpcf_admin_menu_hook' );
23
- add_action( 'wpcf_admin_page_init', 'wpcf_enqueue_scripts' );
24
-
25
- // OMG, why so early? At this point we don't even have embedded Types (with functions.php).
26
- if ( defined( 'DOING_AJAX' ) ) {
27
- require_once WPCF_INC_ABSPATH . '/ajax.php';
28
- if ( isset($_REQUEST['action']) ) {
29
- switch( $_REQUEST['action']){
30
- /**
31
- * post edit screen
32
- */
33
- case 'wpcf_edit_post_get_child_fields_screen':
34
- case 'wpcf_edit_post_get_icons_list':
35
- case 'wpcf_edit_post_save_child_fields':
36
- require_once WPCF_INC_ABSPATH.'/classes/class.types.admin.edit.post.type.php';
37
- new Types_Admin_Edit_Post_Type();
38
- break;
39
- /**
40
- * custom fields group edit screen
41
- */
42
- case 'wpcf_ajax_filter':
43
- case 'wpcf_edit_field_choose':
44
- case 'wpcf_edit_field_insert':
45
- case 'wpcf_edit_field_select':
46
- case 'wpcf_edit_field_add_existed': {
47
-
48
- require_once WPCF_INC_ABSPATH.'/classes/class.types.admin.edit.custom.fields.group.php';
49
-
50
- // Be careful here. For some AJAX actions we rely on the fact that the page parameter is not set and/or
51
- // that post and user fields can use the same handler (which is originally meant for post fields only).
52
-
53
- // We don't have functions.php at this point, can't use wpcf_getpost().
54
- $current_page = isset( $_REQUEST['page'] ) ? $_REQUEST['page'] : Types_Admin_Edit_Custom_Fields_Group::PAGE_NAME;
55
- if( in_array( $current_page, array( Types_Admin_Edit_Custom_Fields_Group::PAGE_NAME, 'wpcf-edit-usermeta' ) ) ) {
56
- new Types_Admin_Edit_Custom_Fields_Group();
57
- }
58
-
59
- // For other pages, we will initialize during the 'init' hook when the autoloader is already available.
60
- // At this point we don't even have access to names of the pages.
61
- // See wpcf_init_admin_pages().
62
- break;
63
- }
64
- case 'wpcf_edit_field_condition_get':
65
- case 'wpcf_edit_field_condition_get_row':
66
- case 'wpcf_edit_field_condition_save':
67
- case 'wpcf_edit_custom_field_group_get':
68
- require_once WPCF_INC_ABSPATH.'/classes/class.types.fields.conditional.php';
69
- new Types_Fields_Conditional();
70
- break;
71
- case 'wpcf_edit_post_get_fields_box':
72
- require_once WPCF_INC_ABSPATH.'/classes/class.types.admin.fields.php';
73
- new Types_Admin_Fields();
74
- break;
75
- /**
76
- * custom fields control screen
77
- */
78
- case 'wpcf_custom_fields_control_change_type':
79
- case 'wpcf_custom_fields_control_get_groups':
80
- case 'wpcf_usermeta_control_get_groups':
81
- require_once WPCF_INC_ABSPATH.'/classes/class.types.admin.control.fields.php';
82
- new Types_Admin_Control_Fields();
83
- break;
84
- }
85
- }
86
- }
87
- include_once WPCF_ABSPATH.'/includes/classes/class.wpcf.marketing.messages.php';
88
- new WPCF_Types_Marketing_Messages();
89
-
90
- /**
91
- * last edit flag
92
- */
93
- if ( !defined('TOOLSET_EDIT_LAST' )){
94
- define( 'TOOLSET_EDIT_LAST', '_toolset_edit_last');
95
- }
96
-
97
- /**
98
- * last author
99
- */
100
- if ( !defined('WPCF_AUTHOR' )){
101
- define( 'WPCF_AUTHOR', '_wpcf_author_id');
102
- }
103
-
104
- /**
105
- * admin_init hook.
106
- */
107
- function wpcf_admin_init_hook()
108
- {
109
- wp_register_style('wpcf-css-embedded', WPCF_EMBEDDED_RES_RELPATH . '/css/basic.css', array(), WPCF_VERSION );
110
-
111
- wp_enqueue_style( 'wpcf-promo-tabs', WPCF_EMBEDDED_RES_RELPATH . '/css/tabs.css', array(), WPCF_VERSION );
112
- wp_enqueue_style('toolset-dashicons');
113
-
114
- }
115
-
116
-
117
- /**
118
- * Initialize admin pages.
119
- *
120
- * @todo This, also, needs a review very badly.
121
- * @since 1.9
122
- */
123
- function wpcf_init_admin_pages() {
124
-
125
- if( is_admin() ) {
126
- WPCF_Page_Listing_Termmeta::get_instance();
127
- }
128
-
129
- if( defined( 'DOING_AJAX' ) ) {
130
- $action = wpcf_getpost( 'action' );
131
- $current_page = wpcf_getpost( 'page' );
132
-
133
- switch( $action ) {
134
-
135
- case 'wpcf_edit_field_select':
136
- case 'wpcf_ajax_filter': {
137
- if( WPCF_Page_Edit_Termmeta::PAGE_NAME == $current_page ) {
138
- WPCF_Page_Edit_Termmeta::get_instance()->initialize_ajax_handler();
139
- }
140
- break;
141
- }
142
- }
143
- }
144
-
145
-
146
- }
147
-
148
-
149
- /**
150
- * Get information about admin menu subpages.
151
- *
152
- * It is also being used as a source for dashboard items.
153
- *
154
- * @return array See the wpcf_admin_menu_get_subpages filter description.
155
- */
156
- function wpcf_admin_menu_get_subpages()
157
- {
158
- $subpages = array();
159
-
160
- // Dashboard
161
- $subpages['wpcf-dashboard'] = array(
162
- 'menu_title' => __( 'Dashboard', 'wpcf' ),
163
- 'function' => 'wpcf_admin_menu_summary_dashboard',
164
- 'capability_filter' => 'wpcf_cpt_view',
165
- 'capability' => WPCF_CUSTOM_POST_TYPE_VIEW,
166
- 'context' => 'menu_only',
167
- );
168
-
169
- // Post Types
170
- $subpages['wpcf-cpt'] = array(
171
- 'menu_title' => __( 'Post Types', 'wpcf' ),
172
- 'function' => 'wpcf_admin_menu_summary_cpt',
173
- 'capability_filter' => 'wpcf_cpt_view',
174
- 'capability' => WPCF_CUSTOM_POST_TYPE_VIEW,
175
- 'toolset_icon' => 'dashicons dashicons-admin-post',
176
- );
177
-
178
- // Taxonomies
179
- $subpages['wpcf-ctt'] = array(
180
- 'menu_title' => __( 'Taxonomies', 'wpcf' ),
181
- 'function' => 'wpcf_admin_menu_summary_ctt',
182
- 'capability_filter' => 'wpcf_ctt_view',
183
- 'capability' => WPCF_CUSTOM_TAXONOMY_VIEW,
184
- 'toolset_icon' => 'dashicons dashicons-tag',
185
- );
186
-
187
- // Custom fields
188
- $subpages['wpcf-cf'] = array(
189
- 'menu_title' => __( 'Post Fields', 'wpcf' ),
190
- 'function' => 'wpcf_admin_menu_summary',
191
- 'capability_filter' => 'wpcf_cf_view',
192
- 'capability' => WPCF_CUSTOM_FIELD_VIEW,
193
- 'toolset_icon' => 'dashicons dashicons-forms',
194
- );
195
-
196
- // User Meta
197
- $subpages['wpcf-um'] = array(
198
- 'menu_title' => __( 'User Fields', 'wpcf' ),
199
- 'function' => 'wpcf_usermeta_summary',
200
- 'capability_filter' => 'wpcf_uf_view',
201
- 'capability' => WPCF_USER_META_FIELD_VIEW,
202
- 'toolset_icon' => 'dashicons dashicons-id-alt',
203
- );
204
-
205
- // Settings
206
- $subpages['wpcf-custom-settings'] = array(
207
- 'menu_title' => __( 'Settings', 'wpcf' ),
208
- 'function' => 'wpcf_admin_menu_settings',
209
- 'toolset_icon' => 'dashicons dashicons-admin-settings',
210
- );
211
-
212
-
213
- /**
214
- * Allow for adding more admin menu subpages.
215
- *
216
- * Each subpage definition is an associative with following elements:
217
- *
218
- * string $menu_title: Title to be displayed in the menu.
219
- * string $function: Callback function name to render the page.
220
- * string $capability_filter: Name of the filter that will be applied to the capability,
221
- * see wpcf_admin_add_submenu_page() for details.
222
- * string $capability: Capability required to access the page.
223
- * string $context: Where to display this menu item. 'context_only'|'dashboard_only'|missing
224
- *
225
- * Key of the subpage definition is the page name.
226
- */
227
- $subpages = apply_filters( 'wpcf_admin_menu_get_subpages', $subpages );
228
-
229
- return $subpages;
230
- }
231
-
232
- /**
233
- * admin_menu hook.
234
- */
235
- function wpcf_admin_menu_hook()
236
- {
237
- $wpcf_capability = apply_filters( 'wpcf_capability', WPCF_CUSTOM_POST_TYPE_VIEW);
238
-
239
- add_menu_page(
240
- __( 'Types', 'wpcf' ),
241
- __( 'Types', 'wpcf' ),
242
- $wpcf_capability,
243
- 'wpcf',
244
- 'wpcf_admin_menu_summary'
245
- );
246
-
247
- $subpages = wpcf_admin_menu_get_subpages();
248
-
249
- foreach( $subpages as $menu_slug => $menu ) {
250
- if ( isset($menu['context']) && 'dashboard_only' == $menu['context'] ) {
251
- continue;
252
- }
253
- wpcf_admin_add_submenu_page($menu, $menu_slug);
254
- }
255
-
256
- if ( isset( $_GET['page'] ) ) {
257
- $current_page = $_GET['page'];
258
- switch ( $current_page ) {
259
- /**
260
- * User Fields Control
261
- */
262
- case 'wpcf-user-fields-control':
263
- wpcf_admin_add_submenu_page(
264
- array(
265
- 'menu_title' => __( 'User Field Control', 'wpcf' ),
266
- 'function' => 'wpcf_admin_menu_user_fields_control',
267
- 'capability_filter' => 'wpcf_ufc_view',
268
- ),
269
- 'wpcf-user-fields-control'
270
- );
271
- break;
272
-
273
- /**
274
- * Post Fields Control
275
- */
276
- case 'wpcf-custom-fields-control':
277
- wpcf_admin_add_submenu_page(
278
- array(
279
- 'menu_title' => __( 'Post Field Control', 'wpcf' ),
280
- 'function' => 'wpcf_admin_menu_custom_fields_control',
281
- 'capability_filter' => 'wpcf_cfc_view',
282
- ),
283
- 'wpcf-custom-fields-control'
284
- );
285
- break;
286
- /**
287
- * Import/Export
288
- */
289
- case 'wpcf-import-export':
290
- wpcf_admin_add_submenu_page(
291
- array(
292
- 'menu_title' => __( 'Import/Export', 'wpcf' ),
293
- 'function' => 'wpcf_admin_menu_import_export',
294
- ),
295
- 'wpcf-import-export'
296
- );
297
- break;
298
-
299
- /**
300
- * debug
301
- */
302
- case 'wpcf-debug-information':
303
- wpcf_admin_add_submenu_page(
304
- array(
305
- 'menu_title' => __( 'Debug Information', 'wpcf' ),
306
- 'function' => 'wpcf_admin_menu_debug_information',
307
- ),
308
- 'wpcf-debug-information'
309
- );
310
- break;
311
- /**
312
- * custom field grup
313
- */
314
- case 'wpcf-edit':
315
- $title = isset( $_GET['group_id'] ) ? __( 'Edit Group', 'wpcf' ) : __( 'Add New Post Field Group', 'wpcf' );
316
- $hook = wpcf_admin_add_submenu_page(
317
- array(
318
- 'menu_title' => $title,
319
- 'function' => 'wpcf_admin_menu_edit_fields',
320
- 'capability' => WPCF_CUSTOM_FIELD_VIEW
321
- ),
322
- $current_page
323
- );
324
- add_action( 'load-' . $hook, 'wpcf_admin_menu_edit_fields_hook' );
325
- wpcf_admin_plugin_help( $hook, 'wpcf-edit' );
326
- break;
327
-
328
- case 'wpcf-view-custom-field':
329
- $hook = wpcf_admin_add_submenu_page(
330
- array(
331
- 'menu_title' => __( 'View Post Field Group', 'wpcf' ),
332
- 'function' => 'wpcf_admin_menu_edit_fields',
333
- 'capability' => WPCF_CUSTOM_FIELD_VIEW
334
- ),
335
- $current_page
336
- );
337
- wpcf_admin_plugin_help( $hook, 'wpcf-edit' );
338
- break;
339
- /**
340
- * custom post
341
- */
342
- case 'wpcf-edit-type':
343
- $title = __( 'Add New Post Type', 'wpcf' );
344
- if ( isset( $_GET['wpcf-post-type'] ) ) {
345
- $title = __( 'Edit Post Type', 'wpcf' );
346
- }
347
- $hook = wpcf_admin_add_submenu_page(
348
- array(
349
- 'menu_title' => $title,
350
- 'function' => 'wpcf_admin_menu_edit_type',
351
- 'capability' => WPCF_CUSTOM_FIELD_EDIT
352
- ),
353
- $current_page
354
- );
355
- add_action( 'load-' . $hook, 'wpcf_admin_menu_edit_type_hook' );
356
- wpcf_admin_plugin_help( $hook, 'wpcf-edit-type' );
357
- break;
358
-
359
- case 'wpcf-view-type':
360
- $hook = wpcf_admin_add_submenu_page(
361
- array(
362
- 'menu_title' => __( 'View Post Type', 'wpcf' ),
363
- 'function' => 'wpcf_admin_menu_edit_type',
364
- 'capability' => WPCF_CUSTOM_FIELD_VIEW
365
- ),
366
- $current_page
367
- );
368
- add_action( 'load-' . $hook, 'wpcf_admin_menu_edit_type_hook' );
369
- wpcf_admin_plugin_help( $hook, 'wpcf-edit-type' );
370
- break;
371
-
372
- case 'wpcf-edit-tax':
373
- $title = isset( $_GET['wpcf-tax'] ) ? __( 'Edit Taxonomy', 'wpcf' ) : __( 'Add New Taxonomy', 'wpcf' );
374
- $hook = wpcf_admin_add_submenu_page(
375
- array(
376
- 'menu_title' => $title,
377
- 'function' => 'wpcf_admin_menu_edit_tax',
378
- 'capability' => WPCF_CUSTOM_TAXONOMY_EDIT
379
- ),
380
- $current_page
381
- );
382
- add_action( 'load-' . $hook, 'wpcf_admin_menu_edit_tax_hook' );
383
- wpcf_admin_plugin_help( $hook, 'wpcf-edit-tax' );
384
- break;
385
-
386
- case 'wpcf-view-tax':
387
- $hook = wpcf_admin_add_submenu_page(
388
- array(
389
- 'menu_title' => __( 'View Taxonomy', 'wpcf' ),
390
- 'function' => 'wpcf_admin_menu_edit_tax',
391
- 'capability' => WPCF_CUSTOM_TAXONOMY_VIEW
392
- ),
393
- $current_page
394
- );
395
- add_action( 'load-' . $hook, 'wpcf_admin_menu_edit_tax_hook' );
396
- wpcf_admin_plugin_help( $hook, 'wpcf-edit-tax' );
397
- break;
398
-
399
- /**
400
- * user meta fields
401
- */
402
- case 'wpcf-edit-usermeta':
403
- $title = isset( $_GET['group_id'] ) ? __( 'Edit User Field Group', 'wpcf' ) : __( 'Add New User Field Group', 'wpcf' );
404
- $hook = wpcf_admin_add_submenu_page(
405
- array(
406
- 'menu_title' => $title,
407
- 'function' => 'wpcf_admin_menu_edit_user_fields',
408
- 'capability' => WPCF_USER_META_FIELD_EDIT,
409
- ),
410
- $current_page
411
- );
412
- wpcf_admin_plugin_help( $hook, 'wpcf-edit-usermeta' );
413
- break;
414
-
415
- case 'wpcf-view-usermeta':
416
- $hook = wpcf_admin_add_submenu_page(
417
- array(
418
- 'menu_title' => __( 'View User Field Group', 'wpcf' ),
419
- 'function' => 'wpcf_admin_menu_edit_user_fields',
420
- 'capability' => WPCF_USER_META_FIELD_VIEW,
421
- ),
422
- $current_page
423
- );
424
- wpcf_admin_plugin_help( $hook, 'wpcf-edit-usermeta' );
425
- break;
426
-
427
- case WPCF_Page_Edit_Termmeta::PAGE_NAME:
428
-
429
- // Initialize the page.
430
- /** @var WPCF_Page_Edit_Termmeta $termmeta_page */
431
- $termmeta_page = WPCF_Page_Edit_Termmeta::get_instance();
432
- $termmeta_page->initialize();
433
-
434
- break;
435
-
436
- case WPCF_Page_Control_Termmeta::PAGE_NAME:
437
-
438
- // Initialize by creating an instance.
439
- /** @var WPCF_Page_Control_Termmeta $term_field_control_page */
440
- $term_field_control_page = WPCF_Page_Control_Termmeta::get_instance();
441
- $term_field_control_page->initialize();
442
- break;
443
-
444
- }
445
-
446
- }
447
-
448
- // Check if migration from other plugin is needed
449
- if (
450
- (class_exists( 'Acf') && !class_exists('acf_pro'))
451
- || defined( 'CPT_VERSION' )
452
- ) {
453
- $hook = add_submenu_page( 'wpcf', __( 'Migration', 'wpcf' ),
454
- __( 'Migration', 'wpcf' ), 'manage_options', 'wpcf-migration',
455
- 'wpcf_admin_menu_migration' );
456
- add_action( 'load-' . $hook, 'wpcf_admin_menu_migration_hook' );
457
- wpcf_admin_plugin_help( $hook, 'wpcf-migration' );
458
- }
459
-
460
- do_action( 'wpcf_menu_plus' );
461
-
462
- // remove the repeating Types submenu
463
- remove_submenu_page( 'wpcf', 'wpcf' );
464
- }
465
-
466
- /**
467
- * Menu page hook.
468
- */
469
- function wpcf_admin_menu_debug_information()
470
- {
471
- require_once WPCF_EMBEDDED_ABSPATH.'/toolset/toolset-common/debug/debug-information.php';
472
- }
473
-
474
- /**
475
- * Types Dashboard
476
- */
477
- function wpcf_admin_menu_summary_dashboard_hook()
478
- {
479
- do_action( 'wpcf_admin_page_init' );
480
- require_once WPCF_INC_ABSPATH.'/classes/class.types.dashboard.php';
481
- $wpcf_admin = new Types_Dashboard();
482
- $form = $wpcf_admin->form();
483
- wpcf_form( 'wpcf_form_dashboard', $form );
484
- }
485
-
486
- function wpcf_admin_menu_summary_dashboard()
487
- {
488
- $post_type = current_filter();
489
- wpcf_add_admin_header( __( 'Dashboard', 'wpcf' ));
490
- $form = wpcf_form( 'wpcf_form_dashboard' );
491
- $form_output = $form->renderForm();
492
- wpcf_admin_screen($post_type, $form_output);
493
- }
494
-
495
- /**
496
- * Menu page hook.
497
- */
498
- function wpcf_usermeta_summary_hook()
499
- {
500
- do_action( 'wpcf_admin_page_init' );
501
- wpcf_admin_load_collapsible();
502
- wpcf_admin_page_add_options('uf', __( 'User Fields', 'wpcf' ));
503
- }
504
-
505
- /**
506
- * Menu page hook.
507
- */
508
- function wpcf_admin_menu_summary_hook()
509
- {
510
- do_action( 'wpcf_admin_page_init' );
511
- wpcf_admin_load_collapsible();
512
- wpcf_admin_page_add_options('cf', __( 'Post Fields', 'wpcf' ));
513
- }
514
-
515
- /**
516
- * Menu page display.
517
- */
518
- function wpcf_admin_menu_summary()
519
- {
520
- wpcf_add_admin_header( __( 'Post Field Groups', 'wpcf' ), array('page'=>'wpcf-edit'));
521
- require_once WPCF_INC_ABSPATH . '/fields.php';
522
- require_once WPCF_INC_ABSPATH . '/fields-list.php';
523
- $to_display = wpcf_admin_fields_get_fields();
524
- if ( !empty( $to_display ) ) {
525
- add_action( 'wpcf_groups_list_table_after', 'wpcf_admin_promotional_text' );
526
- }
527
- wpcf_admin_fields_list();
528
- wpcf_add_admin_footer();
529
- }
530
-
531
-
532
- function wpcf_admin_enqueue_group_edit_page_assets() {
533
- do_action( 'wpcf_admin_page_init' );
534
-
535
- /*
536
- * Enqueue scripts
537
- */
538
- // Group filter
539
- wp_enqueue_script( 'wpcf-filter-js',
540
- WPCF_EMBEDDED_RES_RELPATH
541
- . '/js/custom-fields-form-filter.js', array('jquery'), WPCF_VERSION );
542
- // Form
543
- wp_enqueue_script( 'wpcf-form-validation',
544
- WPCF_EMBEDDED_RES_RELPATH . '/js/'
545
- . 'jquery-form-validation/jquery.validate.min.js', array('jquery'),
546
- WPCF_VERSION );
547
- wp_enqueue_script( 'wpcf-form-validation-additional',
548
- WPCF_EMBEDDED_RES_RELPATH . '/js/'
549
- . 'jquery-form-validation/additional-methods.min.js',
550
- array('jquery'), WPCF_VERSION );
551
- // Scroll
552
- wp_enqueue_script( 'wpcf-scrollbar',
553
- WPCF_EMBEDDED_RELPATH . '/toolset/toolset-common/visual-editor/res/js/scrollbar.js',
554
- array('jquery') );
555
- wp_enqueue_script( 'wpcf-mousewheel',
556
- WPCF_EMBEDDED_RELPATH . '/toolset/toolset-common/visual-editor/res/js/mousewheel.js',
557
- array('wpcf-scrollbar') );
558
- // MAIN
559
- wp_enqueue_script(
560
- 'wpcf-fields-form',
561
- WPCF_EMBEDDED_RES_RELPATH.'/js/fields-form.js',
562
- array( 'wpcf-js' ),
563
- WPCF_VERSION
564
- );
565
- wp_enqueue_script(
566
- 'wpcf-admin-fields-form',
567
- WPCF_RES_RELPATH.'/js/fields-form.js',
568
- array(),
569
- WPCF_VERSION
570
- );
571
-
572
- /*
573
- * Enqueue styles
574
- */
575
- wp_enqueue_style( 'wpcf-scroll',
576
- WPCF_EMBEDDED_RELPATH . '/toolset/toolset-common/visual-editor/res/css/scroll.css' );
577
-
578
- //Css editor
579
- wp_enqueue_script( 'wpcf-form-codemirror' ,
580
- WPCF_RELPATH . '/resources/js/codemirror234/lib/codemirror.js', array('wpcf-js'));
581
- wp_enqueue_script( 'wpcf-form-codemirror-css-editor' ,
582
- WPCF_RELPATH . '/resources/js/codemirror234/mode/css/css.js', array('wpcf-js'));
583
- wp_enqueue_script( 'wpcf-form-codemirror-html-editor' ,
584
- WPCF_RELPATH . '/resources/js/codemirror234/mode/xml/xml.js', array('wpcf-js'));
585
- wp_enqueue_script( 'wpcf-form-codemirror-html-editor2' ,
586
- WPCF_RELPATH . '/resources/js/codemirror234/mode/htmlmixed/htmlmixed.js', array('wpcf-js'));
587
- wp_enqueue_script( 'wpcf-form-codemirror-editor-resize' ,
588
- WPCF_RELPATH . '/resources/js/jquery_ui/jquery.ui.resizable.min.js', array('wpcf-js'));
589
-
590
- wp_enqueue_style( 'wpcf-css-editor',
591
- WPCF_RELPATH . '/resources/js/codemirror234/lib/codemirror.css' );
592
- //wp_enqueue_style( 'wpcf-css-editor-resize',
593
- // WPCF_RELPATH . '/resources/js/jquery_ui/jquery.ui.theme.min.css' );
594
- wp_enqueue_style( 'wpcf-usermeta',
595
- WPCF_EMBEDDED_RES_RELPATH . '/css/usermeta.css' );
596
-
597
- wp_enqueue_style( 'font-awesome' );
598
-
599
- add_action( 'admin_footer', 'wpcf_admin_fields_form_js_validation' );
600
-
601
- }
602
-
603
-
604
- /**
605
- * Menu page hook.
606
- */
607
- function wpcf_admin_menu_edit_fields_hook()
608
- {
609
- wpcf_admin_enqueue_group_edit_page_assets();
610
-
611
- require_once WPCF_INC_ABSPATH . '/fields.php';
612
- require_once WPCF_INC_ABSPATH . '/fields-form.php';
613
- // $form = wpcf_admin_fields_form();
614
- //require_once WPCF_INC_ABSPATH.'/classes/class.types.admin.edit.custom.fields.group.php';
615
- $wpcf_admin = new Types_Admin_Edit_Custom_Fields_Group();
616
- $wpcf_admin->init_admin();
617
- $form = $wpcf_admin->form();
618
- wpcf_form( 'wpcf_form_fields', $form );
619
- }
620
-
621
- /**
622
- * Menu page display.
623
- */
624
- function wpcf_admin_menu_edit_fields()
625
- {
626
- $add_new = false;
627
- $post_type = current_filter();
628
- $title = __('View Post Field Group', 'wpcf');
629
- if ( isset( $_GET['group_id'] ) ) {
630
- if ( WPCF_Roles::user_can_edit('custom-field', array('id' => $_GET['group_id']))) {
631
- $title = __( 'Edit Post Field Group', 'wpcf' );
632
- $add_new = array(
633
- 'page' => 'wpcf-edit',
634
- );
635
- }
636
- } else if ( WPCF_Roles::user_can_create('custom-field')) {
637
- $title = __( 'Add New Post Field Group', 'wpcf' );
638
- }
639
- wpcf_add_admin_header( $title, $add_new );
640
- wpcf_wpml_warning();
641
- $form = wpcf_form( 'wpcf_form_fields' );
642
- echo '<form method="post" action="" class="wpcf-fields-form wpcf-form-validate js-types-show-modal">';
643
- wpcf_admin_screen($post_type, $form->renderForm());
644
- echo '</form>';
645
- wpcf_add_admin_footer();
646
- }
647
-
648
- function wpcf_admin_page_add_options( $name, $label)
649
- {
650
- $option = 'per_page';
651
- $args = array(
652
- 'label' => $label,
653
- 'default' => 10,
654
- 'option' => sprintf('wpcf_%s_%s', $name, $option),
655
- );
656
- add_screen_option( $option, $args );
657
- }
658
-
659
- function wpcf_admin_menu_summary_cpt_ctt_hook()
660
- {
661
- do_action( 'wpcf_admin_page_init' );
662
- wp_enqueue_style( 'wpcf-promo-tabs', WPCF_RES_RELPATH . '/css/tabs.css', array(), WPCF_VERSION );
663
- wpcf_admin_load_collapsible();
664
- require_once WPCF_INC_ABSPATH . '/custom-types.php';
665
- require_once WPCF_INC_ABSPATH . '/custom-taxonomies.php';
666
- require_once WPCF_INC_ABSPATH . '/custom-types-taxonomies-list.php';
667
- }
668
-
669
- /**
670
- * Menu page hook.
671
- */
672
- function wpcf_admin_menu_summary_cpt_hook()
673
- {
674
- wpcf_admin_menu_summary_cpt_ctt_hook();
675
- wpcf_admin_page_add_options('cpt', __( 'Post Types', 'wpcf' ));
676
- }
677
-
678
- /**
679
- * Menu page display.
680
- */
681
- function wpcf_admin_menu_summary_cpt()
682
- {
683
- wpcf_add_admin_header(
684
- __( 'Post Types', 'wpcf' ),
685
- array('page'=>'wpcf-edit-type'),
686
- __('Add New', 'wpcf')
687
- );
688
- $to_display_posts = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
689
- $to_display_tax = get_option( WPCF_OPTION_NAME_CUSTOM_TAXONOMIES, array() );
690
- if ( !empty( $to_display_posts ) || !empty( $to_display_tax ) ) {
691
- add_action( 'wpcf_types_tax_list_table_after', 'wpcf_admin_promotional_text' );
692
- }
693
- wpcf_admin_custom_post_types_list();
694
- wpcf_add_admin_footer();
695
- }
696
-
697
- /**
698
- * Menu page hook.
699
- */
700
- function wpcf_admin_menu_summary_ctt_hook()
701
- {
702
- wpcf_admin_menu_summary_cpt_ctt_hook();
703
- wpcf_admin_page_add_options('ctt', __( 'Taxonomies', 'wpcf' ));
704
- }
705
-
706
- /**
707
- * Menu page display.
708
- */
709
- function wpcf_admin_menu_summary_ctt()
710
- {
711
- wpcf_add_admin_header( __( 'Taxonomies', 'wpcf' ), array('page' => 'wpcf-edit-tax') );
712
- wpcf_admin_custom_taxonomies_list();
713
- do_action('wpcf_types_tax_list_table_after');
714
- wpcf_add_admin_footer();
715
- }
716
-
717
- /**
718
- * Menu page hook.
719
- */
720
- function wpcf_admin_menu_edit_type_hook()
721
- {
722
- require_once WPCF_INC_ABSPATH . '/fields.php';
723
- do_action( 'wpcf_admin_page_init' );
724
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/custom-types.php';
725
- require_once WPCF_INC_ABSPATH . '/custom-types-form.php';
726
- require_once WPCF_INC_ABSPATH . '/post-relationship.php';
727
- wp_enqueue_script( 'wpcf-custom-types-form',
728
- WPCF_RES_RELPATH . '/js/'
729
- . 'custom-types-form.js', array('jquery', 'jquery-ui-dialog', 'jquery-masonry'), WPCF_VERSION );
730
- wp_enqueue_script( 'wpcf-form-validation',
731
- WPCF_RES_RELPATH . '/js/'
732
- . 'jquery-form-validation/jquery.validate.min.js', array('jquery'),
733
- WPCF_VERSION );
734
- wp_enqueue_script( 'wpcf-form-validation-additional',
735
- WPCF_RES_RELPATH . '/js/'
736
- . 'jquery-form-validation/additional-methods.min.js',
737
- array('jquery'), WPCF_VERSION );
738
- wp_enqueue_style('wp-jquery-ui-dialog');
739
- add_action( 'admin_footer', 'wpcf_admin_types_form_js_validation' );
740
- wpcf_post_relationship_init();
741
- /**
742
- * add form
743
- */
744
- // $form = wpcf_admin_custom_types_form();
745
- require_once WPCF_INC_ABSPATH.'/classes/class.types.admin.edit.post.type.php';
746
- $wpcf_admin = new Types_Admin_Edit_Post_Type();
747
- $wpcf_admin->init_admin();
748
- $form = $wpcf_admin->form();
749
- wpcf_form( 'wpcf_form_types', $form );
750
- }
751
-
752
- /**
753
- * Menu page display.
754
- */
755
- function wpcf_admin_menu_edit_type()
756
- {
757
- $post_type = current_filter();
758
- $title = __('View Post Type', 'wpcf');
759
- if ( WPCF_Roles::user_can_edit('custom-post-type', array()) ) {
760
- if ( isset( $_GET['wpcf-post-type'] ) ) {
761
- $title = __( 'Edit Post Type', 'wpcf' );
762
- /**
763
- * add new CPT link
764
- */
765
- $title .= sprintf(
766
- '<a href="%s" class="add-new-h2">%s</a>',
767
- esc_url(add_query_arg( 'page', 'wpcf-edit-type', admin_url('admin.php'))),
768
- __('Add New', 'wpcf')
769
- );
770
- } else {
771
- $title = __( 'Add New Post Type', 'wpcf' );
772
- }
773
- }
774
- wpcf_add_admin_header( $title );
775
- wpcf_wpml_warning();
776
- $form = wpcf_form( 'wpcf_form_types' );
777
- echo '<form method="post" action="" class="wpcf-types-form wpcf-form-validate js-types-do-not-show-modal">';
778
- wpcf_admin_screen($post_type, $form->renderForm());
779
- echo '</form>';
780
- wpcf_add_admin_footer();
781
- }
782
-
783
- /**
784
- * Menu page hook.
785
- */
786
- function wpcf_admin_menu_edit_tax_hook()
787
- {
788
- do_action( 'wpcf_admin_page_init' );
789
- wp_enqueue_script( 'wpcf-form-validation',
790
- WPCF_RES_RELPATH . '/js/'
791
- . 'jquery-form-validation/jquery.validate.min.js', array('jquery'),
792
- WPCF_VERSION );
793
- wp_enqueue_script( 'wpcf-form-validation-additional',
794
- WPCF_RES_RELPATH . '/js/'
795
- . 'jquery-form-validation/additional-methods.min.js',
796
- array('jquery'), WPCF_VERSION );
797
- wp_enqueue_script( 'wpcf-taxonomy-form',
798
- WPCF_RES_RELPATH . '/js/'
799
- . 'taxonomy-form.js', array( 'jquery' ), WPCF_VERSION );
800
- add_action( 'admin_footer', 'wpcf_admin_tax_form_js_validation' );
801
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/custom-taxonomies.php';
802
- require_once WPCF_INC_ABSPATH . '/custom-taxonomies-form.php';
803
- // $form = wpcf_admin_custom_taxonomies_form();
804
- require_once WPCF_INC_ABSPATH.'/classes/class.types.admin.edit.taxonomy.php';
805
- $wpcf_admin = new Types_Admin_Edit_Taxonomy();
806
- $wpcf_admin->init_admin();
807
- $form = $wpcf_admin->form();
808
- wpcf_form( 'wpcf_form_tax', $form );
809
- }
810
-
811
- /**
812
- * Menu page display.
813
- */
814
- function wpcf_admin_menu_edit_tax()
815
- {
816
- $post_type = current_filter();
817
- $title = __( 'View Taxonomy', 'wpcf' );
818
- $add_new = false;
819
- if ( WPCF_Roles::user_can_create('custom-taxonomy') ) {
820
- $title = __( 'Add New Taxonomy', 'wpcf' );
821
- if ( isset( $_GET['wpcf-tax'] ) ) {
822
- $title = __( 'Edit Taxonomy', 'wpcf' );
823
- $add_new = array('page' => 'wpcf-edit-tax' );
824
- }
825
- }
826
- wpcf_add_admin_header( $title, $add_new);
827
- wpcf_wpml_warning();
828
- $form = wpcf_form( 'wpcf_form_tax' );
829
- echo '<form method="post" action="" class="wpcf-tax-form wpcf-form-validate js-types-show-modal">';
830
- wpcf_admin_screen($post_type, $form->renderForm());
831
- echo '</form>';
832
- wpcf_add_admin_footer();
833
- }
834
-
835
- /**
836
- * Menu page hook.
837
- */
838
- function wpcf_admin_menu_import_export_hook()
839
- {
840
- do_action( 'wpcf_admin_page_init' );
841
- require_once WPCF_INC_ABSPATH . '/fields.php';
842
- require_once WPCF_INC_ABSPATH . '/import-export.php';
843
- if ( extension_loaded( 'simplexml' ) && isset( $_POST['export'] )
844
- && wp_verify_nonce( $_POST['_wpnonce'], 'wpcf_import' ) ) {
845
- wpcf_admin_export_data();
846
- die();
847
- }
848
- }
849
-
850
- /**
851
- * Menu page display.
852
- */
853
- function wpcf_admin_menu_import_export()
854
- {
855
- wpcf_add_admin_header( __( 'Import/Export', 'wpcf' ) );
856
- echo '<form method="post" action="" class="wpcf-import-export-form '
857
- . 'wpcf-form-validate" enctype="multipart/form-data">';
858
- echo wpcf_form_simple( wpcf_admin_import_export_form() );
859
- echo '</form>';
860
- wpcf_add_admin_footer();
861
- }
862
-
863
- /**
864
- * Menu page hook.
865
- */
866
- function wpcf_admin_menu_custom_fields_control_hook()
867
- {
868
- require_once WPCF_INC_ABSPATH . '/fields-control.php';
869
- wpcf_admin_menu_custom_fields_control_hook_helper();
870
- }
871
-
872
-
873
- /**
874
- * Menu page display.
875
- */
876
- function wpcf_admin_menu_custom_fields_control()
877
- {
878
- global $wpcf_control_table;
879
- wpcf_add_admin_header( __( 'Post Field Control', 'wpcf' ) );
880
- echo '<form method="post" action="" id="wpcf-custom-fields-control-form" class="wpcf-custom-fields-control-form wpcf-form-validate" enctype="multipart/form-data">';
881
- echo wpcf_admin_custom_fields_control_form( $wpcf_control_table );
882
- wp_nonce_field( 'custom_fields_control_bulk' );
883
- echo '</form>';
884
- wpcf_add_admin_footer();
885
- }
886
-
887
- /**
888
- * Menu page hook.
889
- */
890
- function wpcf_admin_menu_migration_hook()
891
- {
892
- do_action( 'wpcf_admin_page_init' );
893
- require_once WPCF_INC_ABSPATH . '/fields.php';
894
- require_once WPCF_INC_ABSPATH . '/custom-types.php';
895
- require_once WPCF_INC_ABSPATH . '/custom-taxonomies.php';
896
- require_once WPCF_INC_ABSPATH . '/migration.php';
897
- $form = wpcf_admin_migration_form();
898
- wpcf_form( 'wpcf_form_migration', $form );
899
- }
900
-
901
- /**
902
- * Menu page display.
903
- */
904
- function wpcf_admin_menu_migration()
905
- {
906
- wpcf_add_admin_header( __( 'Migration', 'wpcf' ) );
907
- echo '<form method="post" action="" id="wpcf-migration-form" class="wpcf-migration-form '
908
- . 'wpcf-form-validate" enctype="multipart/form-data">';
909
- $form = wpcf_form( 'wpcf_form_migration' );
910
- echo $form->renderForm();
911
- echo '</form>';
912
- wpcf_add_admin_footer();
913
- }
914
-
915
- /**
916
- * Menu page hook.
917
- */
918
- function wpcf_admin_menu_settings_hook()
919
- {
920
- do_action( 'wpcf_admin_page_init' );
921
- require_once WPCF_INC_ABSPATH . '/settings.php';
922
- $form = wpcf_admin_general_settings_form();
923
- wpcf_form( 'wpcf_form_general_settings', $form );
924
- }
925
-
926
- /**
927
- * Menu page display.
928
- */
929
- function wpcf_admin_menu_settings()
930
- {
931
- ob_start();
932
- wpcf_add_admin_header( __( 'Settings', 'wpcf' ) );
933
- ?>
934
- <form method="post" action="" id="wpcf-general-settings-form" class="wpcf-settings-form wpcf-form-validate">
935
- <?php
936
-
937
- $form = wpcf_form( 'wpcf_form_general_settings' );
938
- echo $form->renderForm();
939
-
940
- ?>
941
- </form>
942
- <?php
943
- wpcf_add_admin_footer();
944
-
945
- echo ob_get_clean();
946
- }
947
-
948
- /**
949
- * Adds typical header on admin pages.
950
- *
951
- * @param string $title
952
- * @param string $icon_id Custom icon
953
- * @return string
954
- */
955
- function wpcf_add_admin_header($title, $add_new = false, $add_new_title = false)
956
- {
957
- echo '<div class="wrap">';
958
- echo '<h2>', $title;
959
- if ( !$add_new_title ) {
960
- $add_new_title = __('Add New', 'wpcf');
961
- }
962
- if ( is_array($add_new) && isset($add_new['page']) ) {
963
- $add_button = false;
964
- /**
965
- * check user can?
966
- */
967
- switch($add_new['page']) {
968
- case 'wpcf-edit-type':
969
- $add_button = WPCF_Roles::user_can_create( 'custom-post-type' );
970
- break;
971
- case 'wpcf-edit-tax':
972
- $add_button = WPCF_Roles::user_can_create( 'custom-taxonomy' );
973
- break;
974
- case 'wpcf-edit':
975
- $add_button = WPCF_Roles::user_can_create( 'custom-field' );
976
- break;
977
- case 'wpcf-edit-usermeta':
978
- $add_button = WPCF_Roles::user_can_create( 'user-meta-field' );
979
- break;
980
- case WPCF_Page_Edit_Termmeta::PAGE_NAME:
981
- $add_button = WPCF_Roles::user_can_create( 'term-field' );
982
- break;
983
- }
984
- if ( $add_button ) {
985
- printf(
986
- ' <a href="%s" class="add-new-h2">%s</a>',
987
- esc_url(add_query_arg( $add_new, admin_url('admin.php'))),
988
- $add_new_title
989
- );
990
- }
991
- }
992
- echo '</h2>';
993
- $current_page = sanitize_text_field( $_GET['page'] );
994
- do_action( 'wpcf_admin_header' );
995
- do_action( 'wpcf_admin_header_' . $current_page );
996
- }
997
-
998
- /**
999
- * Adds footer on admin pages.
1000
- *
1001
- * <b>Strongly recomended</b> if wpcf_add_admin_header() is called before.
1002
- * Otherwise invalid HTML formatting will occur.
1003
- */
1004
- function wpcf_add_admin_footer()
1005
- {
1006
- $current_page = sanitize_text_field( $_GET['page'] );
1007
- do_action( 'wpcf_admin_footer_' . $current_page );
1008
- do_action( 'wpcf_admin_footer' );
1009
- echo '</div>';
1010
- }
1011
-
1012
- /**
1013
- * Returns HTML formatted 'widefat' table.
1014
- *
1015
- * @param type $ID
1016
- * @param type $header
1017
- * @param type $rows
1018
- * @param type $empty_message
1019
- */
1020
- function wpcf_admin_widefat_table( $ID, $header, $rows = array(), $empty_message = 'No results' )
1021
- {
1022
- if ( 'No results' == $empty_message ) {
1023
- $empty_message = __('No results', 'wpcf');
1024
- }
1025
- $head = '';
1026
- $footer = '';
1027
- foreach ( $header as $key => $value ) {
1028
- $head .= '<th id="wpcf-table-' . $key . '">' . $value . '</th>' . "\r\n";
1029
- $footer .= '<th>' . $value . '</th>' . "\r\n";
1030
- }
1031
- echo '<table id="' . $ID . '" class="widefat" cellspacing="0">
1032
- <thead>
1033
- <tr>
1034
- ' . $head . '
1035
- </tr>
1036
- </thead>
1037
- <tfoot>
1038
- <tr>
1039
- ' . $footer . '
1040
- </tr>
1041
- </tfoot>
1042
- <tbody>
1043
- ';
1044
- $row = '';
1045
- if ( empty( $rows ) ) {
1046
- echo '<tr><td colspan="' . count( $header ) . '">' . $empty_message
1047
- . '</td></tr>';
1048
- } else {
1049
- $i = 0;
1050
- foreach ( $rows as $row ) {
1051
- $classes = array();
1052
- if ( $i++%2 ) {
1053
- $classes[] = 'alternate';
1054
- }
1055
- if ( isset($row['status']) && 'inactive' == $row['status'] ) {
1056
- $classes[] = sprintf('status-%s', $row['status']);
1057
- };
1058
- printf('<tr class="%s">', implode(' ', $classes ));
1059
- foreach ( $row as $column_name => $column_value ) {
1060
- if ( preg_match( '/^(status|raw_name)$/', $column_name )) {
1061
- continue;
1062
- }
1063
- echo '<td class="wpcf-table-column-' . $column_name . '">';
1064
- echo $column_value;
1065
- echo '</td>' . "\r\n";
1066
- }
1067
- echo '</tr>' . "\r\n";
1068
- }
1069
- }
1070
- echo '
1071
- </tbody>
1072
- </table>' . "\r\n";
1073
- }
1074
-
1075
- /**
1076
- * Admin tabs.
1077
- *
1078
- * @param type $tabs
1079
- * @param type $page
1080
- * @param type $default
1081
- * @param type $current
1082
- * @return string
1083
- */
1084
- function wpcf_admin_tabs($tabs, $page, $default = '', $current = '')
1085
- {
1086
- if ( empty( $current ) && isset( $_GET['tab'] ) ) {
1087
- $current = sanitize_text_field( $_GET['tab'] );
1088
- } else {
1089
- $current = $default;
1090
- }
1091
- $output = '<h2 class="nav-tab-wrapper">';
1092
- foreach ( $tabs as $tab => $name ) {
1093
- $class = ( $tab == $current ) ? ' nav-tab-active' : '';
1094
- $output .= "<a class='nav-tab$class' href='?page=$page&tab=$tab'>$name</a>";
1095
- }
1096
- $output .= '</h2>';
1097
- return $output;
1098
- }
1099
-
1100
- /**
1101
- * Saves open fieldsets.
1102
- *
1103
- * @param type $action
1104
- * @param type $fieldset
1105
- */
1106
- function wpcf_admin_form_fieldset_save_toggle($action, $fieldset)
1107
- {
1108
- $data = get_user_meta( get_current_user_id(), 'wpcf-form-fieldsets-toggle',
1109
- true );
1110
- if ( $action == 'open' ) {
1111
- $data[$fieldset] = 1;
1112
- } elseif ( $action == 'close' ) {
1113
- unset( $data[$fieldset] );
1114
- }
1115
- update_user_meta( get_current_user_id(), 'wpcf-form-fieldsets-toggle', $data );
1116
- }
1117
-
1118
- /**
1119
- * Check if fieldset is saved as open.
1120
- *
1121
- * @param type $fieldset
1122
- */
1123
- function wpcf_admin_form_fieldset_is_collapsed($fieldset)
1124
- {
1125
- $data = get_user_meta( get_current_user_id(), 'wpcf-form-fieldsets-toggle',
1126
- true );
1127
- if ( empty( $data ) ) {
1128
- return true;
1129
- }
1130
- return array_key_exists( $fieldset, $data ) ? false : true;
1131
- }
1132
-
1133
- /**
1134
- * Adds help on admin pages.
1135
- *
1136
- * @param type $contextual_help
1137
- * @param type $screen_id
1138
- * @param type $screen
1139
- * @return type
1140
- */
1141
- function wpcf_admin_plugin_help($hook, $page)
1142
- {
1143
- global $wp_version;
1144
- $call = false;
1145
- $contextual_help = '';
1146
- $page = $page;
1147
- if ( isset( $page ) && isset( $_GET['page'] ) && $_GET['page'] == $page ) {
1148
- switch ( $page ) {
1149
- case 'wpcf-cf':
1150
- $call = 'custom_fields';
1151
- break;
1152
-
1153
- case 'wpcf-cpt':
1154
- $call = 'post_types_list';
1155
- break;
1156
-
1157
- case 'wpcf-ctt':
1158
- $call = 'custom_taxonomies_list';
1159
- break;
1160
-
1161
- case 'wpcf-import-export':
1162
- $call = 'import_export';
1163
- break;
1164
-
1165
- case 'wpcf-edit':
1166
- $call = 'edit_group';
1167
- break;
1168
-
1169
- case 'wpcf-edit-type':
1170
- $call = 'edit_type';
1171
- break;
1172
-
1173
- case 'wpcf-edit-tax':
1174
- $call = 'edit_tax';
1175
- break;
1176
-
1177
- case 'wpcf':
1178
- $call = 'wpcf';
1179
- break;
1180
-
1181
- case 'wpcf-um':
1182
- $call = 'user_fields_list';
1183
- break;
1184
-
1185
- case 'wpcf-edit-usermeta':
1186
- $call = 'user_fields_edit';
1187
- break;
1188
-
1189
- case 'wpcf-termmeta-listing':
1190
- $call = 'term_fields_list';
1191
- break;
1192
-
1193
- case WPCF_Page_Edit_Termmeta::PAGE_NAME:
1194
- $call = 'edit_termmeta';
1195
- }
1196
- }
1197
- if ( $call ) {
1198
- require_once WPCF_ABSPATH . '/help.php';
1199
- // WP 3.3 changes
1200
- if ( version_compare( $wp_version, '3.2.1', '>' ) ) {
1201
- wpcf_admin_help_add_tabs($call, $hook, $contextual_help);
1202
- } else {
1203
- $contextual_help = wpcf_admin_help( $call, $contextual_help );
1204
- add_contextual_help( $hook, $contextual_help );
1205
- }
1206
- }
1207
- }
1208
-
1209
- /**
1210
- * Promo texts
1211
- *
1212
- * @todo Move!
1213
- */
1214
- function wpcf_admin_promotional_text()
1215
- {
1216
- $promo_tabs = get_option( '_wpcf_promo_tabs', false );
1217
- // random selection every one hour
1218
- if ( $promo_tabs ) {
1219
- $time = time();
1220
- $time_check = intval( $promo_tabs['time'] ) + 60 * 60;
1221
- if ( $time > $time_check ) {
1222
- $selected = mt_rand( 0, 3 );
1223
- $promo_tabs['selected'] = $selected;
1224
- $promo_tabs['time'] = $time;
1225
- update_option( '_wpcf_promo_tabs', $promo_tabs );
1226
- } else {
1227
- $selected = $promo_tabs['selected'];
1228
- }
1229
- } else {
1230
- $promo_tabs = array();
1231
- $selected = mt_rand( 0, 3 );
1232
- $promo_tabs['selected'] = $selected;
1233
- $promo_tabs['time'] = time();
1234
- update_option( '_wpcf_promo_tabs', $promo_tabs );
1235
- }
1236
- }
1237
-
1238
- /**
1239
- * Collapsible scripts.
1240
- */
1241
- function wpcf_admin_load_collapsible()
1242
- {
1243
- wp_enqueue_script( 'wpcf-collapsible',
1244
- WPCF_RES_RELPATH . '/js/collapsible.js', array('jquery'),
1245
- WPCF_VERSION );
1246
- wp_enqueue_style( 'wpcf-collapsible',
1247
- WPCF_RES_RELPATH . '/css/collapsible.css', array(), WPCF_VERSION );
1248
- $option = get_option( 'wpcf_toggle', array() );
1249
- if ( !empty( $option ) ) {
1250
- $setting = 'new Array("' . implode( '", "', array_keys( $option ) ) . '")';
1251
- wpcf_admin_add_js_settings( 'wpcf_collapsed', $setting );
1252
- }
1253
- }
1254
-
1255
- /**
1256
- * Various delete/deactivate content actions.
1257
- *
1258
- * @param type $type
1259
- * @param type $arg
1260
- * @param type $action
1261
- */
1262
- function wpcf_admin_deactivate_content($type, $arg, $action = 'delete')
1263
- {
1264
- switch ( $type ) {
1265
- case 'post_type':
1266
- // Clean tax relations
1267
- if ( $action == 'delete' ) {
1268
- $custom = get_option( WPCF_OPTION_NAME_CUSTOM_TAXONOMIES, array() );
1269
- foreach ( $custom as $post_type => $data ) {
1270
- if ( empty( $data['supports'] ) ) {
1271
- continue;
1272
- }
1273
- if ( array_key_exists( $arg, $data['supports'] ) ) {
1274
- unset( $custom[$post_type]['supports'][$arg] );
1275
- $custom[$post_type][TOOLSET_EDIT_LAST] = time();
1276
- }
1277
- }
1278
- update_option( WPCF_OPTION_NAME_CUSTOM_TAXONOMIES, $custom );
1279
- }
1280
- break;
1281
-
1282
- case 'taxonomy':
1283
- // Clean post relations
1284
- if ( $action == 'delete' ) {
1285
- $custom = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
1286
- foreach ( $custom as $post_type => $data ) {
1287
- if ( empty( $data['taxonomies'] ) ) {
1288
- continue;
1289
- }
1290
- if ( array_key_exists( $arg, $data['taxonomies'] ) ) {
1291
- unset( $custom[$post_type]['taxonomies'][$arg] );
1292
- $custom[$post_type][TOOLSET_EDIT_LAST] = time();
1293
- }
1294
- }
1295
- update_option( WPCF_OPTION_NAME_CUSTOM_TYPES, $custom );
1296
- }
1297
- break;
1298
-
1299
- default:
1300
- break;
1301
- }
1302
- }
1303
-
1304
- /**
1305
- * Loads teasers.
1306
- *
1307
- * @param type $teasers
1308
- */
1309
- function wpcf_admin_load_teasers($teasers)
1310
- {
1311
- foreach ( $teasers as $teaser ) {
1312
- $file = WPCF_ABSPATH . '/plus/' . $teaser;
1313
- if ( file_exists( $file ) ) {
1314
- require_once $file;
1315
- }
1316
- }
1317
- }
1318
-
1319
- /**
1320
- * Get temporary directory
1321
- *
1322
- * @return
1323
- */
1324
-
1325
- function wpcf_get_temporary_directory()
1326
- {
1327
- $dir = sys_get_temp_dir();
1328
- if ( !empty( $dir ) && is_dir( $dir ) && is_writable( $dir ) ) {
1329
- return $dir;
1330
- }
1331
- $dir = wp_upload_dir();
1332
- $dir = $dir['basedir'];
1333
- return $dir;
1334
- }
1335
-
1336
- /**
1337
- * add types configuration to debug
1338
- */
1339
-
1340
- function wpcf_get_extra_debug_info($extra_debug)
1341
- {
1342
- $extra_debug['types'] = wpcf_get_settings();
1343
- return $extra_debug;
1344
- }
1345
-
1346
- add_filter( 'icl_get_extra_debug_info', 'wpcf_get_extra_debug_info' );
1347
-
1348
- function wpcf_admin_add_submenu_page($menu, $menu_slug = null, $menu_parent = 'wpcf')
1349
- {
1350
- if ( !is_admin() ) {
1351
- return;
1352
- }
1353
- $menu_slug = array_key_exists('menu_slug', $menu)? $menu['menu_slug']:$menu_slug;
1354
-
1355
- $capability = array_key_exists('capability', $menu)? $menu['capability']:'manage_options';;
1356
- $wpcf_capability = apply_filters( 'wpcf_capability', $capability, $menu, $menu_slug );
1357
- $wpcf_capability = apply_filters( 'wpcf_capability'.$menu_slug, $capability, $menu, $menu_slug );
1358
-
1359
- /**
1360
- * allow change capability by filter
1361
- * full list https://goo.gl/OJYTvl
1362
- */
1363
- if ( isset($menu['capability_filter'] ) ) {
1364
- $wpcf_capability = apply_filters( $menu['capability_filter'], $wpcf_capability, $menu, $menu_slug );
1365
- }
1366
-
1367
- /**
1368
- * add submenu
1369
- */
1370
- $hook = add_submenu_page(
1371
- $menu_parent,
1372
- isset($menu['page_title'])? $menu['page_title']:$menu['menu_title'],
1373
- $menu['menu_title'],
1374
- $wpcf_capability,
1375
- $menu_slug,
1376
- array_key_exists('function', $menu)? $menu['function']:null
1377
- );
1378
-
1379
- // For given menu slug, publish the final hook name in case we need it somewhere.
1380
- do_action( "wpcf_admin_add_submenu_page_$menu_slug", $hook );
1381
-
1382
- if ( !empty($menu_slug) ) {
1383
- wpcf_admin_plugin_help( $hook, $menu_slug );
1384
- }
1385
- /**
1386
- * add action
1387
- */
1388
- if ( !array_key_exists('load_hook', $menu) && array_key_exists('function', $menu) && is_string( $menu['function' ] ) ) {
1389
- $menu['load_hook'] = sprintf( '%s_hook', $menu['function'] );
1390
- }
1391
- if ( !empty($menu['load_hook']) && function_exists( $menu['load_hook'] ) ) {
1392
- $action = sprintf(
1393
- 'load-%s',
1394
- array_key_exists('hook', $menu)? $menu['hook']:$hook
1395
- );
1396
- add_action( $action, $menu['load_hook'] );
1397
- }
1398
- /**
1399
- * add submenu to submenu
1400
- */
1401
- if ( array_key_exists('submenu', $menu) ) {
1402
- foreach( $menu['submenu'] as $submenu_slug => $submenu ) {
1403
- wpcf_admin_add_submenu_page($submenu, $submenu_slug, $hook);
1404
- }
1405
- }
1406
- return $hook;
1407
- }
1408
-
1409
- /**
1410
- * sort helper for tables
1411
- */
1412
- function wpcf_usort_reorder($a,$b)
1413
- {
1414
- $orderby = (!empty($_REQUEST['orderby'])) ? sanitize_text_field( $_REQUEST['orderby'] ) : 'title'; //If no sort, default to title
1415
- $order = (!empty($_REQUEST['order'])) ? sanitize_text_field( $_REQUEST['order'] ) : 'asc'; //If no order, default to asc
1416
- if ( ! in_array( $order, array( 'asc', 'desc' ) ) ) {
1417
- $order = 'asc';
1418
- }
1419
- if ('title' == $orderby || !isset($a[$orderby])) {
1420
- $orderby = 'slug';
1421
- }
1422
- /**
1423
- * sort by slug if sort field is the same
1424
- */
1425
- if ( $a[$orderby] == $b[$orderby] ) {
1426
- $orderby = 'slug';
1427
- }
1428
- $result = strcmp($a[$orderby], $b[$orderby]); //Determine sort order
1429
- return ($order==='asc') ? $result : -$result; //Send final sort direction to usort
1430
- }
1431
-
1432
- add_filter('set-screen-option', 'wpcf_table_set_option', 10, 3);
1433
- function wpcf_table_set_option($status, $option, $value)
1434
- {
1435
- return $value;
1436
- }
1437
-
1438
- function wpcf_admin_screen( $post_type, $form_output = '')
1439
- {
1440
- ?>
1441
- <div id="poststuff">
1442
- <div id="post-body" class="metabox-holder columns-<?php echo 1 == get_current_screen()->get_columns() ? '1' : '2'; ?>">
1443
- <?php echo $form_output; ?>
1444
- <div id="postbox-container-1" class="postbox-container">
1445
- <?php do_meta_boxes($post_type, 'side', null); ?>
1446
- </div>
1447
- <div id="postbox-container-2" class="postbox-container">
1448
- <?php
1449
- do_meta_boxes($post_type, 'normal', null);
1450
- do_meta_boxes($post_type, 'advanced', null);
1451
- ?>
1452
- </div>
1453
- </div>
1454
- </div>
1455
- <?php
1456
- }
1457
-
1458
- /**
1459
- * Add Usermeta Fields manager page.
1460
- *
1461
- * @author Gen gen.i@icanlocalize.com
1462
- * @since Types 1.3
1463
- */
1464
- function wpcf_admin_menu_user_fields_control_hook()
1465
- {
1466
- require_once WPCF_INC_ABSPATH . '/usermeta-control.php';
1467
- wpcf_admin_menu_user_fields_control_hook_helper();
1468
- }
1469
-
1470
- /**
1471
- * Menu page display.
1472
- */
1473
- function wpcf_admin_menu_user_fields_control() {
1474
- global $wpcf_control_table;
1475
- wpcf_add_admin_header( __( 'User Field Control', 'wpcf' ) );
1476
- echo '<form method="post" action="" id="wpcf-custom-fields-control-form" class="wpcf-custom-fields-control-form '
1477
- . 'wpcf-form-validate" enctype="multipart/form-data">';
1478
- echo wpcf_admin_custom_fields_control_form( $wpcf_control_table );
1479
- wp_nonce_field( 'user_fields_control_bulk' );
1480
- echo '</form>';
1481
- wpcf_add_admin_footer();
1482
- }
1483
-
1484
-
1485
- /* Delete this with release of 2.0 as it's than fixed in toolset-common */
1486
- function types_670() { ?>
1487
- <script type="text/javascript">
1488
- function typesCheckTrigger(trigger, formID)
1489
- {
1490
- var $ = jQuery;
1491
- $trigger = $('[data-wpt-name="' + trigger + '"]', formID)
1492
-
1493
- if ($('body').hasClass('wp-admin')) {
1494
- trigger = trigger.replace(/wpcf\-/, 'wpcf[') + ']';
1495
- $trigger = $('[data-wpt-name="' + trigger + '"]', formID);
1496
- }
1497
-
1498
- if ($trigger.length < 1) {
1499
- $trigger = $('[data-wpt-name="' + trigger + '[skypename]"]', formID);
1500
- }
1501
-
1502
- if ($trigger.length < 1) {
1503
- $trigger = $('[data-wpt-name="' + trigger + '[datepicker]"]', formID);
1504
- }
1505
-
1506
- if ($trigger.length < 1) {
1507
- $trigger = $('[data-wpt-name="' + trigger + '[]"]', formID);
1508
- }
1509
-
1510
- if ($trigger.length > 0 && 'option' == $trigger.data('wpt-type')) {
1511
- $trigger = $trigger.parent();
1512
- }
1513
-
1514
- if ($trigger.length < 1) {
1515
- if( trigger.indexOf( 'cred-' ) == -1 )
1516
- $trigger = typesCheckTrigger('cred-' + trigger, formID);
1517
-
1518
-
1519
- return false;
1520
- }
1521
- return $trigger;
1522
- }
1523
-
1524
- if( typeof wptCondTriggers !== 'undefined' ) {
1525
- _.each(wptCondTriggers, function (triggers, formID) {
1526
- _.each(triggers, function (fields, trigger) {
1527
- if( ! typesCheckTrigger(trigger, formID, trigger) ) {
1528
- delete wptCondTriggers[formID][trigger];
1529
- if( typeof wptCondFields !== 'undefined' ) {
1530
- _.each( wptCondFields, function( fields, pageID ) {
1531
- _.each( fields, function( field, fieldKey ) {
1532
- _.each( field[ 'conditions' ], function( condition, conditionKey ) {
1533
- if( condition[ 'id' ] == trigger ) {
1534
- delete wptCondFields[ pageID ][ fieldKey ][ 'conditions' ][ conditionKey ];
1535
- }
1536
- } )
1537
- } );
1538
- } );
1539
- }
1540
- }
1541
- });
1542
- });
1543
- }
1544
-
1545
- if( typeof wptCondCustomTriggers !== 'undefined' ) {
1546
- _.each( wptCondCustomTriggers, function( triggers, formID ) {
1547
- _.each( triggers, function( fields, trigger ) {
1548
- if( !typesCheckTrigger( trigger, formID, trigger ) ) {
1549
- delete wptCondCustomTriggers[ formID ][ trigger ];
1550
- }
1551
- } );
1552
- } );
1553
- }
1554
-
1555
- </script>
1556
- <?php
1557
- }
1558
-
1559
- add_action( 'admin_print_footer_scripts', 'types_670', 100 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
application/api.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+
3
+ // get all field group ids by post type
4
+ add_filter( 'types_filter_get_field_group_ids_by_post_type', array( 'Types_Api_Helper', 'get_field_group_ids_by_post_type' ), 10, 2 );
application/bootstrap.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * Autoloader
5
+ */
6
+ require_once( TYPES_ABSPATH . '/library/toolset/autoloader/autoloader.php' );
7
+
8
+ $autoloader = Toolset_Autoloader::get_instance();
9
+ $autoloader->add_paths( array(
10
+ TYPES_ABSPATH . '/application/controllers',
11
+ TYPES_ABSPATH . '/application/models',
12
+ TYPES_ABSPATH . '/library'
13
+ ) );
14
+ $autoloader->add_prefix( 'Types' );
15
+
16
+
17
+ /*
18
+ * Load old Types
19
+ */
20
+ if( ! defined( 'WPCF_RELPATH' ) ) {
21
+ define( 'WPCF_RELPATH', TYPES_RELPATH . '/library/toolset/types' );
22
+ }
23
+
24
+ if( ! defined( 'WPCF_EMBEDDED_TOOLSET_ABSPATH' ) ) {
25
+ define( 'WPCF_EMBEDDED_TOOLSET_ABSPATH', TYPES_ABSPATH . '/library/toolset' );
26
+ }
27
+
28
+ if( ! defined( 'WPCF_EMBEDDED_TOOLSET_RELPATH') ) {
29
+ define( 'WPCF_EMBEDDED_TOOLSET_RELPATH', TYPES_RELPATH . '/library/toolset' );
30
+ }
31
+
32
+ if( ! defined( 'WPTOOLSET_COMMON_PATH' ) ) {
33
+ define( 'WPTOOLSET_COMMON_PATH', TYPES_ABSPATH . '/library/toolset/toolset-common' );
34
+ }
35
+
36
+ if ( !defined( 'EDITOR_ADDON_RELPATH' ) ) {
37
+ define( 'EDITOR_ADDON_RELPATH', WPCF_EMBEDDED_TOOLSET_RELPATH . '/toolset-common/visual-editor' );
38
+ }
39
+
40
+ // installer
41
+ $installer = TYPES_ABSPATH . '/library/toolset/installer/loader.php';
42
+ if ( file_exists($installer) ) {
43
+ include_once $installer;
44
+ if ( function_exists('WP_Installer_Setup') ) {
45
+ WP_Installer_Setup(
46
+ $wp_installer_instance,
47
+ array(
48
+ 'plugins_install_tab' => '1',
49
+ 'repositories_include' => array('toolset', 'wpml')
50
+ )
51
+ );
52
+ }
53
+ }
54
+
55
+
56
+ // Get new functions.php
57
+ require_once( dirname( __FILE__ ) . '/functions.php' );
58
+
59
+ // Initialize legacy code
60
+ require_once( dirname( __FILE__ ) . '/../library/toolset/types/wpcf.php' );
61
+
62
+ // Get api
63
+ require_once( dirname( __FILE__ ) . '/api.php' );
64
+
65
+ // Embedded
66
+ Types_Embedded::initialize();
67
+
68
+ // Jumpstart new Types
69
+ Types_Main::initialize();
application/controllers/admin.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Main backend controller for Types.
5
+ *
6
+ * @since 2.0
7
+ */
8
+ final class Types_Admin {
9
+
10
+
11
+ /**
12
+ * Initialize Types for backend.
13
+ *
14
+ * This is expected to be called during init.
15
+ *
16
+ * @since 2.0
17
+ */
18
+ public static function initialize() {
19
+ new self();
20
+ }
21
+
22
+
23
+ private function __construct() {
24
+ $this->on_init();
25
+ }
26
+
27
+
28
+ private function __clone() { }
29
+
30
+
31
+ private function on_init() {
32
+
33
+ // Load Twig - this is a bit hacky way to do it, see Types_Twig_Autoloader class for explanation.
34
+ Types_Twig_Autoloader::register();
35
+
36
+ // Load Menu - won't be loaded in embedded version.
37
+ if( apply_filters( 'types_register_pages', true ) )
38
+ Types_Admin_Menu::initialize();
39
+
40
+ // load page extensions
41
+ $this->page_extensions();
42
+ }
43
+
44
+ private function page_extensions() {
45
+ // extensions for post edit page
46
+ add_action( 'load-post.php', array( 'Types_Page_Extension_Edit_Post', 'get_instance' ) );
47
+
48
+ // extension for post type edit page
49
+ add_action( 'load-toolset_page_wpcf-edit-type', array( 'Types_Page_Extension_Edit_Post_Type', 'get_instance' ) );
50
+
51
+ // extension for post fields edit page
52
+ add_action( 'load-toolset_page_wpcf-edit', array( 'Types_Page_Extension_Edit_Post_Fields', 'get_instance' ) );
53
+ }
54
+ }
application/controllers/admin_menu.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Admin menu controller for Types.
5
+ *
6
+ * All Types pages, menus, submenus and whatnot need to be registered here. One of the main goals is to avoid
7
+ * loading specific page controllers unless their page is actually being loaded. All page slugs in Types *must*
8
+ * be defined here as constants PAGE_NAME_*.
9
+ *
10
+ * @since 2.0
11
+ */
12
+ final class Types_Admin_Menu {
13
+
14
+ /** Temporary slug compatible with the legacy code. */
15
+ const MENU_SLUG = 'wpcf';
16
+
17
+
18
+ // All (non-legacy) page slugs.
19
+ const PAGE_NAME_FIELD_CONTROL = 'types-field-control';
20
+ const PAGE_NAME_HELPER = 'types-helper'; // hidden page
21
+
22
+
23
+ private static $instance;
24
+
25
+
26
+ public static function get_instance() {
27
+ if( null == self::$instance ) {
28
+ self::$instance = new self();
29
+ }
30
+ return self::$instance;
31
+ }
32
+
33
+
34
+ public static function initialize() {
35
+ self::get_instance();
36
+ }
37
+
38
+
39
+
40
+ private function __construct() {
41
+ // Priority is hardcoded by filter documentation.
42
+ add_filter( 'toolset_filter_register_menu_pages', array( $this, 'on_admin_menu' ), 10 );
43
+ }
44
+
45
+
46
+ private function __clone() { }
47
+
48
+
49
+ /**
50
+ * Add all Types submenus and jumpstart a specific page controller if needed.
51
+ *
52
+ * Toolset shared menu usage is described here:
53
+ * @link https://git.onthegosystems.com/toolset/toolset-common/wikis/toolset-shared-menu
54
+ *
55
+ * @param array $pages Array of menu item definitions.
56
+ * @return array Updated item definition array.
57
+ * @since 2.0
58
+ */
59
+ public function on_admin_menu( $pages ) {
60
+
61
+ // Add legacy pages
62
+ $pages = wpcf_admin_toolset_register_menu_pages( $pages );
63
+
64
+ $page_name = wpcf_getget( 'page' );
65
+ if( !empty( $page_name ) ) {
66
+ $pages = $this->maybe_add_ondemand_submenu( $pages, $page_name );
67
+ }
68
+
69
+ return $pages;
70
+ }
71
+
72
+
73
+ /**
74
+ * Check if an on-demand submenu should be added, and jumpstart it's controller if needed.
75
+ *
76
+ * On-demand submenu means that the submenu isn't displayed normally, it appears only when its page is loaded.
77
+ *
78
+ * Note: All page controllers should inherit from Types_Page_Abstract.
79
+ *
80
+ * @param array $pages Array of menu item definitions.
81
+ * @param string $page_name
82
+ * @return array Updated item definition array.
83
+ * @since 2.0
84
+ */
85
+ private function maybe_add_ondemand_submenu( $pages, $page_name ) {
86
+ $page = null;
87
+
88
+ switch( $page_name ) {
89
+ case self::PAGE_NAME_FIELD_CONTROL:
90
+ $page = Types_Page_Field_Control::get_instance();
91
+ break;
92
+
93
+ case self::PAGE_NAME_HELPER:
94
+ Types_Page_Hidden_Helper::get_instance();
95
+ break;
96
+ }
97
+
98
+ if( $page instanceof Types_Page_Abstract ) {
99
+
100
+ // Jumpstart the page controller.
101
+ try {
102
+ $page->prepare();
103
+ } catch( Exception $e ) {
104
+ wp_die( $e->getMessage() );
105
+ }
106
+
107
+ $pages[ $page_name ] = array(
108
+ 'slug' => $page_name,
109
+ 'menu_title' => $page->get_title(),
110
+ 'page_title' => $page->get_title(),
111
+ 'callback' => $page->get_render_callback(),
112
+ 'load_hook' => $page->get_load_callback(),
113
+ 'capability' => $page->get_required_capability(),
114
+ 'contextual_help_hook' => array( Types_Asset_Help_Tab_Loader::get_instance(), 'add_help_tab' )
115
+ );
116
+
117
+ // todo we might need to handle adding URL parameters to submenu URLs in some standard way, it's common scenario for ondemand submenus
118
+
119
+ }
120
+
121
+ return $pages;
122
+ }
123
+
124
+ }
application/controllers/ajax.php ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Main AJAX call controller for Types.
5
+ *
6
+ * All AJAX actions should be defined as constants and callbacks should be placed here. However, more complex logic
7
+ * should probably be handled outside of this class, here you need only to parse arguments, authenticate, validate the
8
+ * input and handle sending the response. All callbacks must use the ajax_begin() and ajax_finish() methods.
9
+ *
10
+ * @since 2.0
11
+ */
12
+ final class Types_Ajax {
13
+
14
+
15
+ const CALLBACK_FIELD_CONTROL_ACTION = 'field_control_action';
16
+
17
+
18
+ private static $instance;
19
+
20
+
21
+ public static function get_instance() {
22
+ if( null == self::$instance ) {
23
+ self::$instance = new self();
24
+ }
25
+ return self::$instance;
26
+ }
27
+
28
+
29
+ public static function initialize() {
30
+ self::get_instance();
31
+ }
32
+
33
+
34
+ private function __clone() { }
35
+
36
+
37
+ private function __construct() {
38
+ $this->register_callbacks();
39
+ }
40
+
41
+
42
+ /**
43
+ * Register all callbacks.
44
+ *
45
+ * Each callback is registered as a "types_{$callback}" action and needs to have a "callback_{$callback_name}"
46
+ * method in this class.
47
+ *
48
+ * @since 2.0
49
+ */
50
+ private function register_callbacks() {
51
+
52
+ $callbacks = array(
53
+ self::CALLBACK_FIELD_CONTROL_ACTION
54
+ );
55
+
56
+ foreach( $callbacks as $callback_name ) {
57
+ add_action( 'wp_ajax_types_' . $callback_name, array( $this, 'callback_' . $callback_name ) );
58
+ }
59
+
60
+ }
61
+
62
+
63
+ public function get_action_js_name( $action ) {
64
+ return 'types_' . $action;
65
+ }
66
+
67
+
68
+
69
+ /**
70
+ * Perform basic authentication check.
71
+ *
72
+ * Check user capability and nonce. Dies with an error message (wp_json_error() by default) if the authentization
73
+ * is not successful.
74
+ *
75
+ * @param array $args Arguments (
76
+ * @type string $nonce_name Name of the nonce that should be verified. Mandatory
77
+ * @type string $nonce_parameter Name of the parameter containing nonce value.
78
+ * Optional, defaults to "wpnonce".
79
+ * @type string $parameter_source Determines where the function should look for the nonce parameter.
80
+ * Allowed values are 'get' and 'post'. Optional, defaults to 'post'.
81
+ * @type string $capability_needed Capability that user has to have in order to pass the check.
82
+ * Optional, default is "manage_options".
83
+ * @type string $type_of_death How to indicate failure:
84
+ * - 'die': Call wp_json_error with array( 'type' => 'capability'|'nonce', 'message' => $error_message )
85
+ * - 'return': Do not die, just return the error array as above.
86
+ * Optional, default is 'die'.
87
+ * )
88
+ *
89
+ * @return array|void
90
+ *
91
+ * @since 2.0
92
+ */
93
+ private function ajax_authenticate( $args = array() ) {
94
+ // Read arguments
95
+ $type_of_death = wpcf_getarr( $args, 'type_of_death', 'die', array( 'die', 'return' ) );
96
+ $nonce_name = wpcf_getarr( $args, 'nonce' );
97
+ $nonce_parameter = wpcf_getarr( $args, 'nonce_parameter', 'wpnonce' );
98
+ $capability_needed = wpcf_getarr( $args, 'capability_needed', 'manage_options' );
99
+ $parameter_source_name = wpcf_getarr( $args, 'parameter_source', 'post', array( 'get', 'post' ) );
100
+ $parameter_source = ( $parameter_source_name == 'get' ) ? $_GET : $_POST;
101
+
102
+ $is_error = false;
103
+ $error_message = null;
104
+ $error_type = null;
105
+
106
+ // Check permissions
107
+ if ( ! current_user_can( $capability_needed ) ) {
108
+ $error_message = __( 'You do not have permissions for that.', 'wpv-views' );
109
+ $error_type = 'capability';
110
+ $is_error = true;
111
+ }
112
+
113
+ // Check nonce
114
+ if ( !$is_error && !wp_verify_nonce( wpcf_getarr( $parameter_source, $nonce_parameter, '' ), $nonce_name ) ) {
115
+ $error_message = __( 'Your security credentials have expired. Please reload the page to get new ones.', 'wpv-views' );
116
+ $error_type = 'nonce';
117
+ $is_error = true;
118
+ }
119
+
120
+ if( $is_error ) {
121
+ $error_description = array( 'type' => $error_type, 'message' => $error_message );
122
+ switch( $type_of_death ) {
123
+
124
+ case 'die':
125
+ wp_send_json_error( $error_description );
126
+ break;
127
+
128
+ case 'return':
129
+ default:
130
+ return $error_description;
131
+ }
132
+ }
133
+
134
+ return true;
135
+ }
136
+
137
+
138
+ /**
139
+ * Begin an AJAX call handling.
140
+ *
141
+ * To be extended in the future.
142
+ *
143
+ * @param array $args See ajax_authenticate for details
144
+ * @return array|void
145
+ * @since 2.0
146
+ */
147
+ private function ajax_begin( $args ) {
148
+ return $this->ajax_authenticate( $args );
149
+ }
150
+
151
+
152
+ /**
153
+ * Complete an AJAX call handling.
154
+ *
155
+ * Sends a success/error response in a standard way.
156
+ *
157
+ * To be extended in the future.
158
+ *
159
+ * @param array $response Custom response data
160
+ * @param bool $is_success
161
+ * @since 2.0
162
+ */
163
+ private function ajax_finish( $response, $is_success = true ) {
164
+ if( $is_success ) {
165
+ wp_send_json_success( $response );
166
+ } else {
167
+ wp_send_json_error( $response );
168
+ }
169
+ }
170
+
171
+
172
+ /**
173
+ * Handle action with field definitions on the Field Control page.
174
+ *
175
+ * todo comment
176
+ * @since 2.0
177
+ */
178
+ public function callback_field_control_action() {
179
+ $this->ajax_begin( array( 'nonce' => $this->get_action_js_name( self::CALLBACK_FIELD_CONTROL_ACTION ) ) );
180
+
181
+ // Read and validate input
182
+ $field_action = wpcf_getpost( 'field_action' );
183
+ $fields = wpcf_getpost( 'fields' );
184
+
185
+ $current_domain = wpcf_getpost( 'domain', null, Types_Field_Utils::get_domains() );
186
+ if( null == $current_domain ) {
187
+ $this->ajax_finish( array( 'message' => __( 'Wrong field domain.', 'wpcf' ) ), false );
188
+ }
189
+
190
+ if( !is_array( $fields ) || empty( $fields ) ) {
191
+ $this->ajax_finish( array( 'message' => __( 'No fields have been selected.', 'wpcf' ) ), false );
192
+ }
193
+
194
+ $action_specific_data = wpcf_getpost( 'action_specific', array() );
195
+
196
+ // Process fields one by one
197
+ $errors = array();
198
+ $results = array();
199
+ foreach( $fields as $field ) {
200
+
201
+ $result = $this->single_field_control_action( $field_action, $field, $current_domain, $action_specific_data );
202
+
203
+ if( is_array( $result ) ) {
204
+ // Array of errors
205
+ $errors = array_merge( $errors, $result );
206
+ } else if( $result instanceof WP_Error ) {
207
+ // Single error
208
+ $errors[] = $result;
209
+ } else if( false == $result ) {
210
+ // This should not happen...!
211
+ $errors[] = new WP_Error( 0, __( 'An unexpected error happened while processing the request.', 'wpcf' ) );
212
+ } else {
213
+ // Success
214
+
215
+ // Save the field definition model as a result if we got a whole definition
216
+ if( $result instanceof WPCF_Field_Definition ) {
217
+ $result = $result->to_json();
218
+ }
219
+
220
+ $results[ wpcf_getarr( $field, 'slug' ) ] = $result;
221
+ }
222
+ }
223
+
224
+ $data = array( 'results' => $results );
225
+ $is_success = empty( $errors );
226
+
227
+ if( !$is_success ) {
228
+ $error_messages = array();
229
+ /** @var WP_Error $error */
230
+ foreach( $errors as $error ) {
231
+ $error_messages[] = $error->get_error_message();
232
+ }
233
+ $data['messages'] = $error_messages;
234
+ }
235
+
236
+ $this->ajax_finish( $data, $is_success );
237
+ }
238
+
239
+
240
+ /**
241
+ * @param string $action_name One of the allowed action names: 'manage_with_types'
242
+ * @param array $field Field definition model passed from JS.
243
+ * @param string $domain Field domain name.
244
+ * @param mixed $action_specific_data
245
+ * @return bool|mixed|null|WP_Error|WP_Error[]|WPCF_Field_Definition An error, array of errors, boolean indicating
246
+ * success or a result value to be passed back to JS.
247
+ * @since 2.0
248
+ */
249
+ private function single_field_control_action( $action_name, $field, $domain, $action_specific_data ) {
250
+
251
+ $field_slug = wpcf_getarr( $field, 'slug' );
252
+
253
+ switch ( $action_name ) {
254
+
255
+ case 'manage_with_types':
256
+ return Types_Field_Utils::start_managing_field( wpcf_getarr( $field, 'metaKey' ), $domain );
257
+
258
+ case 'stop_managing_with_types':
259
+ return Types_Field_Utils::stop_managing_field( $field_slug, $domain );
260
+
261
+ case 'change_group_assignment':
262
+ return Types_Field_Utils::change_assignment_to_groups( $field_slug, $domain, $action_specific_data );
263
+
264
+ case 'delete_field':
265
+ return Types_Field_Utils::delete_field( $field_slug, $domain );
266
+
267
+ case 'change_field_type':
268
+ return Types_Field_Utils::change_field_type( $field_slug, $domain, $action_specific_data );
269
+
270
+ case 'change_field_cardinality':
271
+ return Types_Field_Utils::change_field_cardinality( $field_slug, $domain, $action_specific_data );
272
+
273
+ default:
274
+ return new WP_Error( 42, __( 'Invalid action name.', 'wpcf' ) );
275
+ }
276
+ }
277
+
278
+ }
application/controllers/asset/help_tab_loader.php ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Manages adding help tabs to admin pages.
5
+ *
6
+ * Usage: Set array( Types_Asset_Help_Tab_Loader::get_instance, 'add_help_tab' ) to 'contextual_help_hook' in
7
+ * the shared Toolset menu item configuration and then extend the get_help_config() method to return a valid
8
+ * help tab configuration for the needed page name.
9
+ *
10
+ * @since 2.0
11
+ */
12
+ final class Types_Asset_Help_Tab_Loader {
13
+
14
+
15
+ private static $instance;
16
+
17
+ public static function get_instance() {
18
+ if( null == self::$instance ) {
19
+ self::$instance = new self();
20
+ }
21
+ return self::$instance;
22
+ }
23
+
24
+ private function __construct() { }
25
+
26
+ private function __clone() { }
27
+
28
+
29
+ /**
30
+ * Add help tabs to current screen.
31
+ *
32
+ * Used as a hook for 'contextual_help_hook' in the shared Toolset menu.
33
+ *
34
+ * @since 2.0
35
+ */
36
+ public function add_help_tab() {
37
+
38
+ $screen = get_current_screen();
39
+
40
+ if ( is_null( $screen ) ) {
41
+ return;
42
+ }
43
+
44
+ $current_page = wpcf_getget( 'page', null );
45
+ if ( null == $current_page ) {
46
+ return;
47
+ }
48
+
49
+ $help_content = $this->get_help_content( $current_page );
50
+ if( null == $help_content ) {
51
+ return;
52
+ }
53
+
54
+ $args = array(
55
+ 'title' => wpcf_getarr( $help_content, 'title' ),
56
+ 'id' => 'wpcf',
57
+ 'content' => wpcf_getarr( $help_content, 'content' ),
58
+ 'callback' => false,
59
+ );
60
+
61
+ $screen->add_help_tab( $args );
62
+
63
+ $this->add_need_help_tab();
64
+
65
+ }
66
+
67
+
68
+ /**
69
+ * Need Help section for a bit advertising.
70
+ *
71
+ * @since 2.0
72
+ */
73
+ private function add_need_help_tab() {
74
+
75
+ $args = array(
76
+ 'title' => __( 'Need More Help?', 'wpcf' ),
77
+ 'id' => 'custom_fields_group-need-help',
78
+ 'content' => wpcf_admin_help( 'need-more-help' ),
79
+ 'callback' => false,
80
+ );
81
+
82
+ $screen = get_current_screen();
83
+ $screen->add_help_tab( $args );
84
+
85
+ }
86
+
87
+
88
+ /**
89
+ * Generate the configuration for help tab.
90
+ *
91
+ * The configuration needs to contain three keys:
92
+ * - title: Title of the tab.
93
+ * - template: Name of the Twig template (assuming the 'help' namespace is available)
94
+ * - context: Context object for Twig.
95
+ *
96
+ * @param string $page_name Name of current page.
97
+ * @return array|null Help tab configuration array or null when no help tab should be displayed.
98
+ * @since 2.0
99
+ */
100
+ private function get_help_config( $page_name ) {
101
+
102
+ switch( $page_name ) {
103
+ case Types_Admin_Menu::PAGE_NAME_FIELD_CONTROL:
104
+ return Types_Page_Field_Control::get_instance()->get_help_config();
105
+
106
+ default:
107
+ return null;
108
+ }
109
+ }
110
+
111
+
112
+ /**
113
+ * Render help tab content from its configuration.
114
+ *
115
+ * @param string $page_name Name of current page.
116
+ * @return array|null Null when no help tab should be displayed, or an array with keys 'title' and 'content'.
117
+ * @since 2.0
118
+ */
119
+ private function get_help_content( $page_name ) {
120
+
121
+ $config = $this->get_help_config( $page_name );
122
+ if( null == $config ) {
123
+ return null;
124
+ }
125
+
126
+ return array(
127
+ 'title' => wpcf_getarr( $config, 'title' ),
128
+ 'content' => $this->get_twig()->render( wpcf_getarr( $config, 'template' ), wpcf_getarr( $config, 'context' ) )
129
+ );
130
+ }
131
+
132
+
133
+ /** @var Twig_Environment|null */
134
+ private $twig = null;
135
+
136
+
137
+ /**
138
+ * @return Twig_Environment Initialized Twig environment object for help tab content rendering.
139
+ * @throws Twig_Error_Loader
140
+ * @since 2.0
141
+ */
142
+ private function get_twig() {
143
+ if( null == $this->twig ) {
144
+ $loader = new Twig_Loader_Filesystem();
145
+ $loader->addPath( TYPES_ABSPATH . '/application/views/help', 'help' );
146
+ $this->twig = new Twig_Environment( $loader );
147
+ }
148
+ return $this->twig;
149
+ }
150
+
151
+ }
application/controllers/asset/manager.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The script and style asset manager for Types implemented in a standard Toolset way.
5
+ *
6
+ * Keeping this separate from Types_Assets also for performance reasons (this is not needed at all times).
7
+ *
8
+ * @since 2.0
9
+ */
10
+ final class Types_Asset_Manager extends Toolset_Assets_Manager {
11
+
12
+ const SCRIPT_ADJUST_MENU_LINK = 'types-adjust-menu-link';
13
+
14
+ const SCRIPT_KNOCKOUT = 'knockout';
15
+
16
+ // Registered in Toolset common
17
+
18
+ const SCRIPT_DIALOG_BOXES = 'ddl-dialog-boxes';
19
+
20
+ const SCRIPT_UTILS = 'toolset-utils';
21
+
22
+ // WordPress Core handles
23
+
24
+ const STYLE_JQUERY_UI_DIALOG = 'wp-jquery-ui-dialog';
25
+
26
+ /**
27
+ * @return Types_Asset_Manager
28
+ */
29
+ static public function get_instance() {
30
+ return parent::getInstance();
31
+ }
32
+
33
+
34
+ protected function __initialize_styles() {
35
+ return parent::__initialize_styles();
36
+ }
37
+
38
+
39
+ protected function __initialize_scripts() {
40
+
41
+ $this->register_script(
42
+ self::SCRIPT_ADJUST_MENU_LINK,
43
+ TYPES_RELPATH . '/public/page/adjust_submenu_links.js',
44
+ array( 'jquery', 'underscore' ),
45
+ TYPES_VERSION
46
+ );
47
+
48
+
49
+ $this->register_script(
50
+ self::SCRIPT_KNOCKOUT,
51
+ TYPES_RELPATH . '/library/knockout/knockout-3.4.0.debug.js',
52
+ array(),
53
+ '3.4.0'
54
+ );
55
+
56
+ return parent::__initialize_scripts();
57
+ }
58
+
59
+
60
+ /**
61
+ * @param Toolset_Script $script
62
+ */
63
+ public function register_toolset_script( $script ) {
64
+ if ( ! isset( $this->scripts[ $script->handle ] ) ) {
65
+ $this->scripts[ $script->handle ] = $script;
66
+ }
67
+ }
68
+
69
+
70
+ /**
71
+ * @param Toolset_Style $style
72
+ */
73
+ public function register_toolset_style( $style ) {
74
+ if( !isset( $this->styles[ $style->handle ] ) ) {
75
+ $this->styles[ $style->handle ] = $style;
76
+ }
77
+ }
78
+
79
+ }
application/controllers/assets.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Types assets manager.
5
+ *
6
+ * All assets (like images and other files) should be defined here, referenced only by constants and their paths/URLs
7
+ * retrieved only with methods of this class.
8
+ *
9
+ * That will make their management way easier when some paths or filenames need to be changed.
10
+ *
11
+ * @since 2.0
12
+ */
13
+ final class Types_Assets {
14
+
15
+ // Constants with image paths relative to public/images.
16
+ const IMG_AJAX_LOADER_OVERLAY = '/ajax-loader-overlay.gif';
17
+
18
+
19
+ private static $instance;
20
+
21
+ public static function get_instance() {
22
+ if( null == self::$instance ) {
23
+ self::$instance = new self();
24
+ }
25
+ return self::$instance;
26
+ }
27
+
28
+
29
+ /**
30
+ * Initialize the asset manager for script and styles.
31
+ *
32
+ * Must be called early, before init, else special measures are needed.
33
+ *
34
+ * @since 2.0
35
+ */
36
+ public function initialize_scripts_and_styles() {
37
+ Types_Asset_Manager::get_instance();
38
+ }
39
+
40
+
41
+ private function __clone() { }
42
+
43
+ private function __construct() { }
44
+
45
+
46
+ /**
47
+ * For given image, return it's relative URL.
48
+ *
49
+ * @param string $image Image defined as a constant of Types_Assets.
50
+ * @return string Relative URL of the image.
51
+ * @since 2.0
52
+ */
53
+ public function get_image_url( $image ) {
54
+ return TYPES_RELPATH . '/public/images' . $image;
55
+ }
56
+
57
+ }
application/controllers/dialog_box.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Represents a single dialog box whose template will be rendered on the page when an instance of this class is
5
+ * created. Enqueues all the assets needed for displaying it.
6
+ *
7
+ * @since 2.0
8
+ */
9
+ class Types_Dialog_Box extends Toolset_DialogBoxes {
10
+
11
+ /** @var array */
12
+ private $context;
13
+
14
+ /** @var Twig_Environment */
15
+ private $twig;
16
+
17
+ /** @var string */
18
+ private $template_name;
19
+
20
+ /** @var string */
21
+ private $dialog_id;
22
+
23
+
24
+ /**
25
+ * Types_Dialog_Box constructor.
26
+ *
27
+ * Should be called during the 'current_screen' action, not sooner or later.
28
+ *
29
+ * @param string $dialog_id Unique ID (at least within the page) used to reference the dialog in JS.
30
+ * @param Twig_Environment $twig Prepared Twig environment.
31
+ * @param array $context Twig context for the dialog template.
32
+ * @param string $template_name Twig template name that will be recognized by the provided environment.
33
+ * @param bool $late_register_assets Whether to run late_register_assets() or not.
34
+ *
35
+ * @since 2.0
36
+ */
37
+ public function __construct( $dialog_id, $twig, $context, $template_name, $late_register_assets = true ) {
38
+
39
+ $current_screen = get_current_screen();
40
+ parent::__construct( array( $current_screen->id ) );
41
+
42
+ $this->dialog_id = $dialog_id;
43
+ $this->twig = $twig;
44
+ $this->context = $context;
45
+ $this->template_name = $template_name;
46
+
47
+ if( $late_register_assets ) {
48
+ $this->late_register_assets();
49
+ }
50
+
51
+ // We're going to render on the page we're creating this instance.
52
+ $this->init_screen_render();
53
+ }
54
+
55
+
56
+ /**
57
+ * Render a predefined Twig template.
58
+ *
59
+ * @since 2.0
60
+ */
61
+ public function template() {
62
+ printf(
63
+ '<script type="text/html" id="%s">%s</script>',
64
+ esc_attr( $this->dialog_id ),
65
+ $this->twig->render( $this->template_name, $this->context )
66
+ );
67
+ }
68
+
69
+
70
+ /**
71
+ * Manually register dialog assets in Types_Asset_Manager because by now we have already missed the
72
+ * toolset_add_registered_styles and toolset_add_registered_scripts filters (but there is still enough time
73
+ * to enqueue).
74
+ *
75
+ * @since 2.0
76
+ */
77
+ protected function late_register_assets() {
78
+ // Get script and styles from parent methods, and register them manually.
79
+ $styles = $this->register_styles( array() );
80
+ foreach( $styles as $style ) {
81
+ Types_Asset_Manager::get_instance()->register_toolset_style( $style );
82
+ }
83
+
84
+ $scripts = $this->register_scripts( array() );
85
+ foreach( $scripts as $script ) {
86
+ Types_Asset_Manager::get_instance()->register_toolset_script( $script );
87
+ }
88
+ }
89
+ }
application/controllers/embedded.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Embedded controller.
5
+ *
6
+ * @since 2.0
7
+ */
8
+ final class Types_Embedded {
9
+
10
+ private function __construct() {
11
+ // disable pages
12
+ add_filter( 'types_register_pages', '__return_false' );
13
+
14
+ // disable information table
15
+ add_filter( 'types_information_table', '__return_false' );
16
+ }
17
+
18
+
19
+ private function __clone() { }
20
+
21
+
22
+ public static function initialize() {
23
+ if( file_exists( TYPES_ABSPATH . '/embedded.lock' )
24
+ || ( defined( 'TYPES_EMBEDDED') && TYPES_EMBEDDED === true ) )
25
+ new self();
26
+ }
27
+
28
+ }
application/controllers/field/type_converter.php ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // WIP
4
+ final class Types_Field_Type_Converter {
5
+
6
+ private static $instance;
7
+
8
+ public static function get_instance() {
9
+ if( null == self::$instance ) {
10
+ self::$instance = new self();
11
+ }
12
+ return self::$instance;
13
+ }
14
+
15
+
16
+ private function __clone() { }
17
+
18
+ private function __construct() {
19
+ // Toolset Maps uses priority 10 for this filter, we need to run later and override.
20
+ add_filter( 'wpcf_filter_field_control_change_type_allowed_types_from', array( $this, 'google_address_field_control_change_type_allowed_from' ), 15, 2 );
21
+ }
22
+
23
+
24
+ private $conversion_matrix = null;
25
+
26
+
27
+ /**
28
+ * Construct a matrix of allowed field type conversions.
29
+ *
30
+ * For each field type as key it contains an array of types it can be converted into.
31
+ *
32
+ * Usually, you shouldn't use this method directly, but instead use dedicated methods for a specific field type.
33
+ *
34
+ * Note: An empty row for a field type can be interpreted in a way that any conversion is allowed. If that's not
35
+ * desired, make sure each type can be converted to itself.
36
+ *
37
+ * Note: The conversion matrix is cached, so any used filters must be hooked into soon enough.
38
+ *
39
+ * @return string[][]|mixed
40
+ * @since 2.0
41
+ */
42
+ public function get_conversion_matrix() {
43
+
44
+ if( null == $this->conversion_matrix ) {
45
+
46
+ $simple_string_types = array(
47
+ 'audio', 'email', 'embed', 'file', 'google_address', 'image', 'numeric', 'phone', 'textfield',
48
+ 'url', 'video', 'colorpicker', 'textarea'
49
+ );
50
+
51
+ $allowed_conversion_source = array(
52
+ 'audio' => $simple_string_types,
53
+ 'colorpicker' => $simple_string_types,
54
+ 'checkbox' => array( 'checkbox' ),
55
+ 'checkboxes' => array( 'checkboxes' ),
56
+ 'date' => array( 'date' ),
57
+ 'email' => $simple_string_types,
58
+ 'embed' => $simple_string_types,
59
+ 'file' => $simple_string_types,
60
+ 'google_address' => $simple_string_types,
61
+ 'image' => $simple_string_types,
62
+ 'numeric' => $simple_string_types,
63
+ 'phone' => $simple_string_types,
64
+ 'radio' => array( 'radio' ),
65
+ 'select' => array( 'select' ),
66
+ 'skype' => array( 'skype' ),
67
+ 'textarea' => $simple_string_types,
68
+ 'textfield' => $simple_string_types,
69
+ 'url' => $simple_string_types,
70
+ 'video' => $simple_string_types,
71
+ 'wysiwyg' => array( 'wysiwyg' ),
72
+ );
73
+
74
+
75
+ $filtered_conversion_matrix = array();
76
+ foreach( $allowed_conversion_source as $field_type_slug => $allowed_conversions ) {
77
+
78
+ /**
79
+ * wpcf_filter_field_control_change_type_allowed_types_from
80
+ *
81
+ * Filter the field types that you can switch to, given a type field
82
+ *
83
+ * @param string[] $allowed_conversions Valid targets for a given origin type.
84
+ * @param string $field_type_slug Field type to switch from.
85
+ *
86
+ * @since 1.8.9
87
+ */
88
+ $filtered_conversion_matrix[ $field_type_slug ] = apply_filters( 'wpcf_filter_field_control_change_type_allowed_types_from', $allowed_conversions, $field_type_slug );
89
+ }
90
+
91
+
92
+ /**
93
+ * wpcf_filter_field_control_change_type_allowed_types
94
+ *
95
+ * Filter the pairs field type origin -> valid field type targets when using the fields control change field type feature
96
+ *
97
+ * @param array $allowed_conversion_matrix Valid correspondence between field types and target field types
98
+ *
99
+ * @since 1.8.9
100
+ */
101
+ $result = apply_filters( 'wpcf_filter_field_control_change_type_allowed_types', $filtered_conversion_matrix );
102
+
103
+
104
+ $this->conversion_matrix = $result;
105
+ }
106
+
107
+ return $this->conversion_matrix;
108
+ }
109
+
110
+
111
+ /**
112
+ * @param Types_Field_Type_Definition $type
113
+ * @return Types_Field_Type_Definition[]
114
+ */
115
+ public function get_possible_conversions( $type ) {
116
+
117
+ if( ! $type instanceof Types_Field_Type_Definition ) {
118
+ throw new InvalidArgumentException( 'Not a field type definition' );
119
+ }
120
+
121
+ $matrix = $this->get_conversion_matrix();
122
+ $allowed_slugs = wpcf_ensarr( wpcf_getarr( $matrix, $type->get_slug() ) );
123
+ $allowed_types = Types_Field_Type_Definition_Factory::get_instance()->load_multiple_definitions( $allowed_slugs );
124
+ return $allowed_types;
125
+ }
126
+
127
+
128
+ /**
129
+ * @param Types_Field_Type_Definition $from_type
130
+ * @param Types_Field_Type_Definition $to_type
131
+ *
132
+ * @return bool
133
+ */
134
+ public function is_conversion_possible( $from_type, $to_type ) {
135
+
136
+ if( ! $from_type instanceof Types_Field_Type_Definition || ! $to_type instanceof Types_Field_Type_Definition ) {
137
+ throw new InvalidArgumentException( 'Not a field type definition' );
138
+ }
139
+
140
+ $possible_conversions = $this->get_possible_conversions( $from_type );
141
+
142
+ return in_array( $to_type->get_slug(), array_keys( $possible_conversions ) );
143
+ }
144
+
145
+
146
+ public function is_conversion_two_way( $type_1, $type_2 ) {
147
+ if( ! $type_1 instanceof Types_Field_Type_Definition || ! $type_2 instanceof Types_Field_Type_Definition ) {
148
+ throw new InvalidArgumentException( 'Not a field type definition' );
149
+ }
150
+
151
+ return ( $this->is_conversion_possible( $type_1, $type_2 ) && $this->is_conversion_possible( $type_2, $type_1 ) );
152
+ }
153
+
154
+
155
+ /**
156
+ * Disallow certain conversion from or to google address field.
157
+ *
158
+ * This is hooked into the wpcf_filter_field_control_change_type_allowed_types_from filter with higher priority
159
+ * than the Toolset Maps hook that adds the google_address field type to the conversion matrix.
160
+ *
161
+ * This way we can properly handle the allowed conversions not depending on the particular Toolset Maps version
162
+ * that is active.
163
+ *
164
+ * @param string[] $targets Field type slugs TO which the conversion is allowed from $origin.
165
+ * @param string $origin Field type slug FROM which the conversion can happen.
166
+ *
167
+ * @return string[] Updated $targets.
168
+ * @since 2.0
169
+ */
170
+ public function google_address_field_control_change_type_allowed_from( $targets, $origin ) {
171
+
172
+ $disallowed_targets = array(
173
+ Types_Field_Type_Definition_Factory::DATE,
174
+ Types_Field_Type_Definition_Factory::CHECKBOX,
175
+ Types_Field_Type_Definition_Factory::CHECKBOXES,
176
+ Types_Field_Type_Definition_Factory::RADIO,
177
+ Types_Field_Type_Definition_Factory::SELECT,
178
+ Types_Field_Type_Definition_Factory::SKYPE,
179
+ Types_Field_Type_Definition_Factory::WYSIWYG
180
+ );
181
+
182
+ if( Types_Field_Type_Definition_Factory::GOOGLE_ADDRESS == $origin ) {
183
+ // Here we're filtering possible conversions FROM google address field
184
+ $safe_targets = array_diff( $targets, $disallowed_targets );
185
+ $targets = $safe_targets;
186
+ } else if( in_array( $origin, $disallowed_targets ) ) {
187
+ // Here we're filtering possible conversions TO google address field from an undesired field type
188
+ if( in_array( Types_Field_Type_Definition_Factory::GOOGLE_ADDRESS, $targets ) ) {
189
+ $item_pos = array_search( Types_Field_Type_Definition_Factory::GOOGLE_ADDRESS, $targets );
190
+ unset( $targets[ $item_pos ] );
191
+ }
192
+ }
193
+ return $targets;
194
+ }
195
+
196
+ }
application/controllers/field/utils.php ADDED
@@ -0,0 +1,382 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Static class for shortcut functions related to field types, groups, definitions and instances.
5
+ * @since 1.9
6
+ */
7
+ final class Types_Field_Utils {
8
+
9
+ private function __construct() { }
10
+
11
+
12
+ // Field domains supported by the page.
13
+ const DOMAIN_POSTS = 'posts';
14
+ const DOMAIN_USERS = 'users';
15
+ const DOMAIN_TERMS = 'terms';
16
+
17
+ // Since PHP 5.6, noooo!
18
+ // const DOMAINS = array( self::DOMAIN_POSTS, self::DOMAIN_USERS, self::DOMAIN_TERMS );
19
+
20
+
21
+ /**
22
+ * Array of valid field domains.
23
+ *
24
+ * Replacement for self::DOMAINS because damn you old PHP versions.
25
+ *
26
+ * @return array
27
+ * @since 2.0
28
+ */
29
+ public static function get_domains() {
30
+ return array( self::DOMAIN_POSTS, self::DOMAIN_USERS, self::DOMAIN_TERMS );
31
+ }
32
+
33
+
34
+ public static function get_definition_factory_by_domain( $domain ) {
35
+ switch( $domain ) {
36
+ case self::DOMAIN_POSTS:
37
+ return WPCF_Field_Definition_Factory_Post::get_instance();
38
+ case self::DOMAIN_USERS:
39
+ return WPCF_Field_Definition_Factory_User::get_instance();
40
+ case self::DOMAIN_TERMS:
41
+ return WPCF_Field_Definition_Factory_Term::get_instance();
42
+ default:
43
+ throw new InvalidArgumentException( 'Invalid field domain.' );
44
+ }
45
+ }
46
+
47
+
48
+ /**
49
+ * For a given field domain, return the appropriate field group factory instance.
50
+ *
51
+ * @param string $domain
52
+ * @return WPCF_Field_Group_Factory
53
+ * @since 2.0
54
+ */
55
+ public static function get_group_factory_by_domain( $domain ) {
56
+ switch( $domain ) {
57
+ case self::DOMAIN_POSTS:
58
+ return WPCF_Field_Group_Post_Factory::get_instance();
59
+ case self::DOMAIN_USERS:
60
+ return WPCF_Field_Group_User_Factory::get_instance();
61
+ case self::DOMAIN_TERMS:
62
+ return WPCF_Field_Group_Term_Factory::get_instance();
63
+ default:
64
+ throw new InvalidArgumentException( 'Invalid field domain.' );
65
+ }
66
+ }
67
+
68
+
69
+ /**
70
+ * Translate a field domain into a "meta_type" value, which is used in field definition arrays.
71
+ *
72
+ * @param string $domain
73
+ * @return string
74
+ * @since 2.0
75
+ */
76
+ public static function domain_to_legacy_meta_type( $domain ) {
77
+ static $map = array(
78
+ self::DOMAIN_POSTS => 'postmeta',
79
+ self::DOMAIN_USERS => 'usermeta',
80
+ self::DOMAIN_TERMS => 'termmeta'
81
+ );
82
+ return wpcf_getarr( $map, $domain );
83
+ }
84
+
85
+
86
+ /**
87
+ * Create a term field instance.
88
+ *
89
+ * @param string $field_slug Slug of existing field definition.
90
+ * @param int $term_id ID of the term where the field belongs.
91
+ *
92
+ * @return null|WPCF_Field_Instance Field instance or null if an error occurs.
93
+ * @since 1.9
94
+ */
95
+ public static function create_term_field_instance( $field_slug, $term_id ) {
96
+ try {
97
+ return new WPCF_Field_Instance_Term( WPCF_Field_Definition_Factory_Term::get_instance()->load_field_definition( $field_slug ), $term_id );
98
+ } catch( Exception $e ) {
99
+ return null;
100
+ }
101
+ }
102
+
103
+
104
+ /**
105
+ * Obtain toolset-forms "field configuration", which is an array of settings for specific field instance.
106
+ *
107
+ * @param WPCF_Field_Instance $field
108
+ * @since 1.9
109
+ */
110
+ public static function get_toolset_forms_field_config( $field ) {
111
+ return wptoolset_form_filter_types_field(
112
+ $field->get_definition()->get_definition_array(),
113
+ $field->get_object_id()
114
+ );
115
+ }
116
+
117
+
118
+ /**
119
+ * Gather an unique array of field definitions from given groups.
120
+ *
121
+ * The groups are expected to belong to the same domain (term/post/user), otherwise problems may occur when
122
+ * field slugs conflict.
123
+ *
124
+ * @param WPCF_Field_Group[] $field_groups
125
+ * @return WPCF_Field_Definition[]
126
+ * @since 1.9
127
+ */
128
+ public static function get_field_definitions_from_groups( $field_groups ) {
129
+ $field_definitions = array();
130
+ foreach( $field_groups as $group ) {
131
+ $group_field_definitions = $group->get_field_definitions();
132
+
133
+ foreach( $group_field_definitions as $field_definition ) {
134
+ $field_definitions[ $field_definition->get_slug() ] = $field_definition;
135
+ }
136
+ }
137
+ return $field_definitions;
138
+ }
139
+
140
+
141
+ /**
142
+ * Start managing a field with given meta_key with Types.
143
+ *
144
+ * Looks if there already exists a field definition that uses the meta_key. If yes, it's most probably a "disabled"
145
+ * one, that is stored only for the possibility of later "re-activation" (which is happening now). In that case,
146
+ * the field definition will be simply updated.
147
+ *
148
+ * If there is no matching field definition whatsoever, it will be created with in some default manner.
149
+ * Check WPCF_Field_Definition_Factory::create_field_definition_for_existing_fields() for details.
150
+ *
151
+ * AJAX callback helper only, do not use elsewhere.
152
+ *
153
+ * @param string $meta_key
154
+ * @param string $domain Field domain
155
+ * @return false|null|WPCF_Field_Definition The updated/newly created field definition or falsy value on failure.
156
+ * @since 2.0
157
+ */
158
+ public static function start_managing_field( $meta_key, $domain ) {
159
+ $factory = self::get_definition_factory_by_domain( $domain );
160
+ $definition = $factory->meta_key_belongs_to_types_field( $meta_key, 'definition' );
161
+ if( null == $definition ) {
162
+ $result = $factory->create_field_definition_for_existing_fields( $meta_key );
163
+ if( false != $result ) {
164
+ return $factory->load_field_definition( $result );
165
+ } else {
166
+ return false;
167
+ }
168
+ } else {
169
+ $is_success = $definition->set_types_management_status( true );
170
+ return ( $is_success ? $definition : false );
171
+ }
172
+ }
173
+
174
+
175
+ /**
176
+ * Stop managing a field with given field slug by Types.
177
+ *
178
+ * AJAX callback helper only, do not use elsewhere.
179
+ *
180
+ * @param string $field_slug
181
+ * @param string $domain Field domain.
182
+ * @return WP_Error|WPCF_Field_Definition Error with a user-friendly message on failure
183
+ * or the updated definition on success.
184
+ * @since 2.0
185
+ */
186
+ public static function stop_managing_field( $field_slug, $domain ) {
187
+
188
+ $factory = self::get_definition_factory_by_domain( $domain );
189
+ $definition = $factory->load_field_definition( $field_slug );
190
+
191
+ if( null == $definition ) {
192
+
193
+ return new WP_Error( 42, sprintf( __( 'Field definition for field "%s" not found in options.', 'wpcf' ), sanitize_text_field( $field_slug ) ) );
194
+
195
+ } else {
196
+
197
+ $is_success = $definition->set_types_management_status( false );
198
+
199
+ if( $is_success ) {
200
+ return $definition;
201
+ } else {
202
+ return new WP_Error(
203
+ 42,
204
+ sprintf(
205
+ __( 'Unable to set types management status for field definition "%s".', 'wpcf' ),
206
+ sanitize_text_field( $field_slug )
207
+ )
208
+ );
209
+ }
210
+ }
211
+ }
212
+
213
+
214
+ /**
215
+ * Change which groups is a field definition associated with.
216
+ *
217
+ * AJAX callback helper only, do not use elsewhere.
218
+ *
219
+ * @param string $field_slug Field definition slug.
220
+ * @param string $domain Field domain
221
+ * @param string[][] $groups Action-specific data passed through AJAX. Array containing a single key 'group_slugs',
222
+ * containing an array of field group slugs.
223
+ *
224
+ * @return WP_Error|WPCF_Field_Definition The updated field definition on success or an error object.
225
+ * @since 2.0
226
+ */
227
+ public static function change_assignment_to_groups( $field_slug, $domain, $groups ) {
228
+ $factory = Types_Field_Utils::get_definition_factory_by_domain( $domain );
229
+ $definition = $factory->load_field_definition( $field_slug );
230
+ if( null == $definition ) {
231
+ return new WP_Error( 42, sprintf( __( 'Field definition for field "%s" not found in options.', 'wpcf' ), sanitize_text_field( $field_slug ) ) );
232
+ }
233
+ $new_groups = wpcf_ensarr( wpcf_getarr( $groups, 'group_slugs' ) );
234
+ $associated_groups = $definition->get_associated_groups();
235
+ $is_success = true;
236
+ foreach( $associated_groups as $group ) {
237
+ if( !in_array( $group->get_slug(), $new_groups ) ) {
238
+ $is_success = $is_success && $group->remove_field_definition( $definition );
239
+ }
240
+ }
241
+ $group_factory = $factory->get_group_factory();
242
+ foreach( $new_groups as $new_group_slug ) {
243
+ $new_group = $group_factory->load_field_group( $new_group_slug );
244
+ if( null != $new_group ) {
245
+ $is_success = $is_success && $new_group->add_field_definition( $definition );
246
+ } else {
247
+ $is_success = false;
248
+ }
249
+ }
250
+
251
+ if( $is_success ) {
252
+ return $definition;
253
+ } else {
254
+ return new WP_Error();
255
+ }
256
+ }
257
+
258
+
259
+ /**
260
+ * Delete a field definition and all values of the field within given domain.
261
+ *
262
+ * @param string $field_slug
263
+ * @param string $domain
264
+ * @return bool|WP_Error True for success, false or WP_Error on error.
265
+ * @since 2.0
266
+ */
267
+ public static function delete_field( $field_slug, $domain ) {
268
+
269
+ $factory = Types_Field_Utils::get_definition_factory_by_domain( $domain );
270
+ $definition = $factory->load_field_definition( $field_slug );
271
+ if( null == $definition ) {
272
+ return new WP_Error( 42, sprintf( __( 'Field definition for field "%s" not found in options.', 'wpcf' ), sanitize_text_field( $field_slug ) ) );
273
+ } else if( ! $definition->is_managed_by_types() ) {
274
+ return new WP_Error( 42, sprintf( __( 'Field "%s" will not be deleted because it is not managed by Types.', 'wpcf' ), sanitize_text_field( $field_slug ) ) );
275
+ }
276
+
277
+ $response = $factory->delete_definition( $definition );
278
+
279
+ return $response;
280
+ }
281
+
282
+
283
+ /**
284
+ * Change a field type for given field definition.
285
+ *
286
+ * Performs checks if the conversion is allowed, and if not, generate a proper error message.
287
+ *
288
+ * @param string $field_slug
289
+ * @param string $domain
290
+ * @param string[] $arguments Needs to contain the 'field_type' key with target type slug.
291
+ * @return false|WP_Error|WPCF_Field_Definition The updated definition on succes, error/false otherwise.
292
+ * @since 2.0
293
+ */
294
+ public static function change_field_type( $field_slug, $domain, $arguments ) {
295
+
296
+ // Load all information we need, fail if it doesn't exist.
297
+ $factory = Types_Field_Utils::get_definition_factory_by_domain( $domain );
298
+ $definition = $factory->load_field_definition( $field_slug );
299
+ if( null == $definition ) {
300
+ return new WP_Error( 42, sprintf( __( 'Field definition for field "%s" not found in options.', 'wpcf' ), sanitize_text_field( $field_slug ) ) );
301
+ } else if( ! $definition->is_managed_by_types() ) {
302
+ return new WP_Error( 42, sprintf( __( 'Field "%s" will not be converted because it is not managed by Types.', 'wpcf' ), sanitize_text_field( $field_slug ) ) );
303
+ }
304
+
305
+ $type_slug = wpcf_getarr( $arguments, 'field_type' );
306
+ $target_type = Types_Field_Type_Definition_Factory::get_instance()->load_field_type_definition( $type_slug );
307
+ if( null == $target_type ) {
308
+ return new WP_Error( 42, sprintf( __( 'Unknown field type "%s".', 'wpcf' ), $type_slug ) );
309
+ }
310
+
311
+ // Check if we can convert between types
312
+ $is_conversion_possible = Types_Field_Type_Converter::get_instance()->is_conversion_possible( $definition->get_type(), $target_type );
313
+ if( !$is_conversion_possible ) {
314
+ return new WP_Error(
315
+ 42,
316
+ sprintf(
317
+ __( 'Conversion from type "%s" to "%s" is currently not allowed.', 'wpcf' ),
318
+ $definition->get_type()->get_display_name(),
319
+ $target_type->get_display_name()
320
+ )
321
+ );
322
+ }
323
+
324
+ // Check if we can do the conversion with current field's cardinality
325
+ $is_cardinality_sustainable = ( ! $definition->get_is_repetitive() || $target_type->can_be_repetitive() );
326
+ if( !$is_cardinality_sustainable ) {
327
+ return new WP_Error(
328
+ 42,
329
+ sprintf(
330
+ __( 'Field "%s" cannot be converted from "%s" to "%s" because it is repetitive and the target type doesn\'t support that.', 'wpcf' ),
331
+ $definition->get_display_name(),
332
+ $definition->get_type()->get_display_name(),
333
+ $target_type->get_display_name()
334
+ )
335
+ );
336
+ }
337
+
338
+ // All is fine, proceed.
339
+ $result = $definition->change_type( $target_type );
340
+ if( $result ) {
341
+ return $definition;
342
+ } else {
343
+ // Something unexpected went wrong.
344
+ return false;
345
+ }
346
+ }
347
+
348
+
349
+ /**
350
+ * Change cardinality of given field, if it is permitted by its type.
351
+ *
352
+ * @param string $field_slug Field definition slug.
353
+ * @param string $domain Field domain.
354
+ * @param string[] $arguments Needs to contain the 'target_cardinality' key with 'single'|'repetitive' value.
355
+ * @return bool|WP_Error|WPCF_Field_Definition The updated definition on succes, error/false otherwise.
356
+ * @since 2.0
357
+ */
358
+ public static function change_field_cardinality( $field_slug, $domain, $arguments ) {
359
+ $factory = Types_Field_Utils::get_definition_factory_by_domain( $domain );
360
+ $definition = $factory->load_field_definition( $field_slug );
361
+ if( null == $definition ) {
362
+ return new WP_Error( 42, sprintf( __( 'Field definition for field "%s" not found in options.', 'wpcf' ), sanitize_text_field( $field_slug ) ) );
363
+ } else if( ! $definition->is_managed_by_types() ) {
364
+ return new WP_Error( 42, sprintf( __( 'Field "%s" will not be converted because it is not managed by Types.', 'wpcf' ), sanitize_text_field( $field_slug ) ) );
365
+ }
366
+
367
+ $target_cardinality = wpcf_getarr( $arguments, 'target_cardinality', null, array( 'single', 'repetitive' ) );
368
+ if( null == $target_cardinality ) {
369
+ return false;
370
+ }
371
+ $set_as_repetitive = ( 'repetitive' == $target_cardinality );
372
+
373
+ $result = $definition->set_is_repetitive( $set_as_repetitive );
374
+
375
+ if( $result ) {
376
+ return $definition;
377
+ } else {
378
+ return false;
379
+ }
380
+ }
381
+
382
+ }
application/controllers/frontend.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Main front-end controller for Types.
5
+ *
6
+ * @since 2.0
7
+ */
8
+ final class Types_Frontend {
9
+
10
+ public static function initialize() {
11
+
12
+ }
13
+
14
+ }
application/controllers/information/controller.php ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Information_Controller {
5
+
6
+ protected $information;
7
+ protected $twig;
8
+
9
+ public function prepare() {
10
+ if( ! apply_filters( 'types_information_table', true ) )
11
+ return false;
12
+
13
+ // no infos if any embedded plugin runs
14
+ if( $this->embedded_plugin_running() )
15
+ return false;
16
+
17
+ // twig
18
+ $this->twig = new Types_Helper_Twig();
19
+
20
+ // script / style
21
+ add_action( 'admin_enqueue_scripts', array( $this, 'on_admin_enqueue_scripts' ) );
22
+
23
+ // special case: layouts active, but not compatible
24
+ // the only case where we don't show the table
25
+ if( defined( 'WPDDL_DEVELOPMENT' ) ) {
26
+ $compatible = new Types_Helper_Condition_Layouts_Compatible();
27
+ if( !$compatible->valid() ) {
28
+ $data_files = array( TYPES_DATA . '/information/layouts-not-compatible.php' );
29
+ $this->show_data_as_container_in_meta_box( $data_files );
30
+ return;
31
+ }
32
+ }
33
+
34
+ /* data files */
35
+ $data_files = array(
36
+ TYPES_DATA . '/information/table/template.php',
37
+ TYPES_DATA . '/information/table/archive.php',
38
+ TYPES_DATA . '/information/table/views.php',
39
+ TYPES_DATA . '/information/table/forms.php',
40
+ );
41
+
42
+ $this->show_data_as_table_in_meta_box( $data_files );
43
+ }
44
+
45
+ public function on_admin_enqueue_scripts() {
46
+
47
+ // script
48
+ wp_enqueue_script(
49
+ 'types-information',
50
+ TYPES_RELPATH . '/public/js/information.js',
51
+ array( 'jquery-ui-dialog', 'wp-pointer' ),
52
+ TYPES_VERSION,
53
+ true
54
+ );
55
+
56
+ // style
57
+ wp_enqueue_style(
58
+ 'types-information',
59
+ TYPES_RELPATH . '/public/css/information.css',
60
+ array( 'wp-jquery-ui-dialog', 'wp-pointer' ),
61
+ TYPES_VERSION
62
+ );
63
+
64
+ // load icons
65
+ wp_enqueue_style(
66
+ 'onthegosystems-icons',
67
+ WPCF_EMBEDDED_TOOLSET_RELPATH . '/onthego-resources/onthegosystems-icons/css/onthegosystems-icons.css',
68
+ array(),
69
+ TYPES_VERSION
70
+ );
71
+ }
72
+
73
+ protected function show_data_as_table_in_meta_box( $data_files ) {
74
+ // prepare meta box
75
+ $this->prepare_table_in_meta_box();
76
+
77
+ // thead
78
+ $thead_views = $this->thead_views_template_archive_views_forms();
79
+
80
+ // load infos
81
+ foreach( $data_files as $data_file ) {
82
+ $this->load_data_to_table( $data_file );
83
+ }
84
+
85
+ // table view
86
+ $output_inner = $this->twig->render(
87
+ '/information/table.twig',
88
+ array(
89
+ 'labels' => array(
90
+ 'or' => __( 'Or...', 'types' )
91
+ ),
92
+ 'thead' => $thead_views,
93
+ 'table' => $this->information
94
+ )
95
+ );
96
+
97
+ // Replace Placeholders
98
+ Types_Helper_Placeholder::replace( $output_inner );
99
+
100
+ // no "echo" because we use meta-box as output
101
+ $this->information->render( $output_inner );
102
+ }
103
+
104
+
105
+ protected function show_data_as_container_in_meta_box( $data_files ) {
106
+ // add container for warning messages
107
+ $this->information = new Types_Information_Container( 'types-informations-container' );
108
+ // $this->information->cache_on_hook( 'edit_post' );
109
+
110
+ // add messages
111
+ foreach( $data_files as $data_file ) {
112
+ $this->load_data_to_table( $data_file );
113
+ }
114
+
115
+ // outer box
116
+ $output_meta_box = new Types_Helper_Output_Meta_Box();
117
+ $output_meta_box->set_id( $this->information->get_id() );
118
+ $output_meta_box->set_title( __( 'Front-end Display', 'types' ) );
119
+ // $output_meta_box->set_css_class( 'types-table-in-meta-box' );
120
+
121
+ $this->information->set_output_container( $output_meta_box );
122
+
123
+ $output_inner = $this->twig->render(
124
+ '/information/single.twig',
125
+ array(
126
+ 'icon' => 'dashicons dashicons-warning',
127
+ 'information' => $this->information
128
+ )
129
+ );
130
+
131
+ // Replace Placeholders
132
+ Types_Helper_Placeholder::replace( $output_inner );
133
+
134
+ // no "echo" because we use meta-box as output
135
+ $this->information->render( $output_inner );
136
+ }
137
+
138
+ protected function load_data_to_table( $path ) {
139
+ $data = require( $path );
140
+
141
+ foreach( $data as $msg_id => $msg_data ) {
142
+ $msg = new Types_Information_Message();
143
+ $msg_data['id'] = $msg_id;
144
+ $msg->data_import( $msg_data );
145
+ $this->information->add_message( $msg );
146
+ }
147
+ }
148
+
149
+ protected function thead_views_template_archive_views_forms() {
150
+
151
+ $thead_data = require( TYPES_DATA . '/information/table/question-marks.php' );
152
+ $views = array();
153
+
154
+ $post_type = Types_Helper_Condition::get_post_type();
155
+ if( $post_type->name == 'post' || $post_type->name == 'page' )
156
+ unset( $thead_data['archive'] );
157
+
158
+ foreach( $thead_data as $data ) {
159
+ $views[] = $this->twig->render(
160
+ '/information/table/thead-cell.twig',
161
+ $data
162
+ );
163
+ }
164
+
165
+ return $views;
166
+ }
167
+
168
+ protected function prepare_table_in_meta_box() {
169
+ // add dashboard
170
+ $this->information = new Types_Information_Table( 'types-information-table' );
171
+
172
+ // save on edit post
173
+ //$this->information->cache_on_hook( 'edit_post' );
174
+
175
+ // we want to display dashboard in a meta-box
176
+ $output_meta_box = new Types_Helper_Output_Meta_Box();
177
+ $output_meta_box->set_id( $this->information->get_id() );
178
+ $output_meta_box->set_title( __( 'Front-end Display', 'types' ) );
179
+ $output_meta_box->set_css_class( 'types-table-in-meta-box' );
180
+
181
+ $this->information->set_output_container( $output_meta_box );
182
+ }
183
+
184
+ /**
185
+ * Check if any embedded plugin is running.
186
+ *
187
+ * @todo Would be better placed in a helper.
188
+ * @return bool
189
+ */
190
+ protected function embedded_plugin_running() {
191
+
192
+ // check Layouts
193
+ if( defined( 'WPDDL_EMBEDDED' ) )
194
+ return true;
195
+
196
+ // check CRED
197
+ if( defined( 'CRED_FE_VERSION' ) && class_exists('CRED_Admin') === false )
198
+ return true;
199
+
200
+ // check Views
201
+ if( defined( 'WPV_VERSION' ) ) {
202
+ global $WP_Views;
203
+
204
+ if( is_object( $WP_Views ) && method_exists( $WP_Views, 'is_embedded' ))
205
+ return $WP_Views->is_embedded();
206
+ }
207
+
208
+
209
+ return false;
210
+ }
211
+ }
application/controllers/main.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Main Types controller.
5
+ *
6
+ * Determines if we're in admin or front-end mode or if an AJAX call is being performed. Handles tasks that are common
7
+ * to all three modes, if there are any.
8
+ *
9
+ * @since 2.0
10
+ */
11
+ final class Types_Main {
12
+
13
+
14
+ private static $instance;
15
+
16
+ public static function get_instance() {
17
+ if( null == self::$instance ) {
18
+ self::$instance = new self();
19
+ }
20
+ return self::$instance;
21
+ }
22
+
23
+ public static function initialize() {
24
+ self::get_instance();
25
+ }
26
+
27
+ private function __clone() { }
28
+
29
+
30
+ private function __construct() {
31
+
32
+ add_action( 'after_setup_theme', array( $this, 'after_setup_theme' ), 10 );
33
+ add_action( 'init', array( $this, 'on_init' ) );
34
+
35
+ }
36
+
37
+
38
+
39
+ /**
40
+ * Determine in which mode we are and initialize the right dedicated controller.
41
+ *
42
+ * @since 2.0
43
+ */
44
+ public function on_init() {
45
+ if( is_admin() ) {
46
+ if( defined( 'DOING_AJAX' ) ) {
47
+ Types_Ajax::initialize();
48
+ } else {
49
+ Types_Admin::initialize();
50
+ }
51
+ } else {
52
+ Types_Frontend::initialize();
53
+ }
54
+ }
55
+
56
+
57
+ /**
58
+ * Early loading actions.
59
+ *
60
+ * Initialize the Toolset Common library with the new loader.
61
+ * Initialize asset manager if we're not doing an AJAX call.
62
+ *
63
+ * @since 2.0
64
+ */
65
+ public function after_setup_theme() {
66
+ Toolset_Common_Bootstrap::getInstance();
67
+
68
+ // If an AJAX callback handler needs other assets, they should initialize the asset manager by themselves.
69
+ if( !defined( 'DOING_AJAX' ) ) {
70
+ Types_Assets::get_instance()->initialize_scripts_and_styles();
71
+ }
72
+ }
73
+
74
+
75
+ /**
76
+ * In some cases, it may not be clear what legacy files are includes and what aren't.
77
+ *
78
+ * This method should make sure all is covered (add files when needed). Use only when necessary.
79
+ *
80
+ * @since 2.0
81
+ */
82
+ public function require_legacy_functions() {
83
+ require_once WPCF_INC_ABSPATH . '/fields.php';
84
+ }
85
+
86
+ }
application/controllers/page/abstract.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Abstract admin page controller.
5
+ *
6
+ * All page controllers must inherit from this one.
7
+ *
8
+ * @since 2.0
9
+ */
10
+ abstract class Types_Page_Abstract {
11
+
12
+
13
+ /** @var bool Whether to disable heartbeat. Default is true (disable). */
14
+ protected $disable_heartbeat = true;
15
+
16
+
17
+ /**
18
+ * Prepare the page controller for displaying a page.
19
+ *
20
+ * This should be the first time where any kind of preparation happens (it shouldn't happen during
21
+ * instantiating the class).
22
+ *
23
+ * By default, this disables the WordPress Heartbeat API in order to save resources and speed up AJAX calls.
24
+ *
25
+ * @since 2.0
26
+ */
27
+ public function prepare() {
28
+
29
+ if ( $this->disable_heartbeat ) {
30
+ wp_deregister_script( 'heartbeat' );
31
+ wp_register_script( 'heartbeat', false );
32
+ }
33
+ }
34
+
35
+
36
+ /**
37
+ * Title to be displayed on the menu as well in the page title.
38
+ *
39
+ * @return string
40
+ * @since 2.0
41
+ */
42
+ abstract public function get_title();
43
+
44
+
45
+ /**
46
+ * Callback for the page rendering action.
47
+ *
48
+ * @return callable
49
+ * @since 2.0
50
+ */
51
+ abstract public function get_render_callback();
52
+
53
+
54
+ /**
55
+ * Callback for the page load action (load-{$hook}).
56
+ *
57
+ * @return null|callable Optional.
58
+ * @since 2.0
59
+ */
60
+ public function get_load_callback() {
61
+ return null;
62
+ }
63
+
64
+
65
+ /**
66
+ * Page name slug.
67
+ *
68
+ * Should be taken directly from constants in Types_Admin_Menu.
69
+ *
70
+ * @return string
71
+ * @since 2.0
72
+ */
73
+ abstract public function get_page_name();
74
+
75
+
76
+ /**
77
+ * User capability required to display the submenu item and access the page.
78
+ *
79
+ * @return string
80
+ * @since 2.0
81
+ */
82
+ abstract public function get_required_capability();
83
+
84
+ }
application/controllers/page/extension/edit_post.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * This controller extends all post edit pages
5
+ *
6
+ * @since 2.0
7
+ */
8
+ final class Types_Page_Extension_Edit_Post {
9
+
10
+ private static $instance;
11
+
12
+ public static function get_instance() {
13
+ if( null == self::$instance ) {
14
+ self::$instance = new self();
15
+ }
16
+ return self::$instance;
17
+ }
18
+
19
+ private function __construct() {
20
+ $post = wpcf_admin_get_edited_post();
21
+ $post_type = wpcf_admin_get_edited_post_type( $post );
22
+
23
+ // if no post or no page
24
+ if( $post_type != 'post' && $post_type != 'page' ) {
25
+ $custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
26
+
27
+ // abort if also no custom post type of types
28
+ if( ! array_key_exists( $post_type, $custom_types ) )
29
+ return false;
30
+ }
31
+
32
+ $this->prepare();
33
+ }
34
+
35
+ private function __clone() { }
36
+
37
+
38
+ public function prepare() {
39
+ // documentation urls
40
+ $documentation_urls = include( TYPES_DATA . '/information/documentation-urls.php' );
41
+
42
+ // add links to use analytics
43
+ Types_Helper_Url::add_urls( $documentation_urls );
44
+
45
+ // set analytics medium
46
+ Types_Helper_Url::set_medium( 'post_editor' );
47
+
48
+ // add informations
49
+ $this->prepare_informations();
50
+
51
+ // @todo load scripts
52
+ if( function_exists( 'wpcf_edit_post_screen_scripts' ) )
53
+ wpcf_edit_post_screen_scripts();
54
+ }
55
+
56
+ private function prepare_informations() {
57
+ $information = new Types_Information_Controller;
58
+ $information->prepare();
59
+ }
60
+ }
application/controllers/page/extension/edit_post_fields.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * This controller extends all post edit pages
5
+ *
6
+ * @since 2.0
7
+ */
8
+ final class Types_Page_Extension_Edit_Post_Fields {
9
+
10
+ private static $instance;
11
+
12
+ public static function get_instance() {
13
+ if( null == self::$instance ) {
14
+ self::$instance = new self();
15
+ }
16
+ return self::$instance;
17
+ }
18
+
19
+ private function __construct() {
20
+ if( ! isset( $_GET['group_id'] ) )
21
+ return;
22
+
23
+ $post_types = get_post_meta( $_GET['group_id'], '_wp_types_group_post_types', 'string' );
24
+ $post_types = explode( ',', $post_types );
25
+ $post_types = array_values( array_filter( $post_types ) );
26
+
27
+ if( count( $post_types ) != 1 || $post_types[0] == 'all' )
28
+ return;
29
+
30
+ Types_Helper_Placeholder::set_post_type( $post_types[0] );
31
+ Types_Helper_Condition::set_post_type( $post_types[0] );
32
+
33
+ $this->prepare();
34
+ }
35
+
36
+ private function __clone() { }
37
+
38
+
39
+ public function prepare() {
40
+ // documentation urls
41
+ $documentation_urls = include( TYPES_DATA . '/information/documentation-urls.php' );
42
+
43
+ // add links to use analytics
44
+ Types_Helper_Url::add_urls( $documentation_urls );
45
+
46
+ // set analytics medium
47
+ Types_Helper_Url::set_medium( 'field_group_editor' );
48
+
49
+ // add informations
50
+ $this->prepare_informations();
51
+
52
+ }
53
+
54
+ private function prepare_informations() {
55
+ $information = new Types_Information_Controller;
56
+ $information->prepare();
57
+ }
58
+ }
application/controllers/page/extension/edit_post_type.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * This controller extends all post edit pages
5
+ *
6
+ * @since 2.0
7
+ */
8
+ final class Types_Page_Extension_Edit_Post_Type {
9
+
10
+ private static $instance;
11
+
12
+ public static function get_instance() {
13
+ if( null == self::$instance ) {
14
+ self::$instance = new self();
15
+ }
16
+ return self::$instance;
17
+ }
18
+
19
+ private function __construct() {
20
+ if( ! isset( $_GET['wpcf-post-type'] ) )
21
+ return;
22
+
23
+ Types_Helper_Placeholder::set_post_type( $_GET['wpcf-post-type'] );
24
+ Types_Helper_Condition::set_post_type( $_GET['wpcf-post-type'] );
25
+
26
+ $this->prepare();
27
+ }
28
+
29
+ private function __clone() { }
30
+
31
+
32
+ public function prepare() {
33
+ // documentation urls
34
+ $documentation_urls = include( TYPES_DATA . '/information/documentation-urls.php' );
35
+
36
+ // add links to use analytics
37
+ Types_Helper_Url::add_urls( $documentation_urls );
38
+
39
+ // set analytics medium
40
+ Types_Helper_Url::set_medium( 'cpt_editor' );
41
+
42
+ // add informations
43
+ $this->prepare_informations();
44
+
45
+ }
46
+
47
+ private function prepare_informations() {
48
+ $information = new Types_Information_Controller;
49
+ $information->prepare();
50
+ }
51
+ }
application/controllers/page/field_control.php ADDED
@@ -0,0 +1,618 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * "Field Control" page controller.
5
+ *
6
+ * @since 2.0
7
+ */
8
+ final class Types_Page_Field_Control extends Types_Page_Abstract {
9
+
10
+
11
+ /** Name of the URL parameter for the field domain. */
12
+ const PARAM_DOMAIN = 'domain';
13
+
14
+
15
+ // Screen options...
16
+ const SCREEN_OPTION_PER_PAGE_NAME = 'types_field_control_fields_per_page';
17
+ const SCREEN_OPTION_PER_PAGE_DEFAULT_VALUE = 20;
18
+
19
+
20
+ /** @var string Current field domain. Will be populated during self::prepare(). Never access directly. */
21
+ private $current_domain;
22
+
23
+
24
+ private static $instance;
25
+
26
+
27
+ public static function get_instance() {
28
+ if( null == self::$instance ) {
29
+ self::$instance = new self();
30
+ }
31
+ return self::$instance;
32
+ }
33
+
34
+
35
+ private function __construct() { }
36
+
37
+
38
+ private function __clone() { }
39
+
40
+
41
+ /**
42
+ * Generate full URL to the Field Control page for given field domain.
43
+ *
44
+ * @param string $domain
45
+ * @return null|string The URL or null if the domain was invalid.
46
+ * @since 2.0
47
+ */
48
+ public static function get_page_url( $domain ) {
49
+
50
+ if( !in_array( $domain, Types_Field_Utils::get_domains() ) ) {
51
+ return null;
52
+ }
53
+
54
+ return esc_url_raw(
55
+ add_query_arg(
56
+ array( 'page' => Types_Admin_Menu::PAGE_NAME_FIELD_CONTROL, 'domain' => $domain ),
57
+ admin_url( 'admin.php' )
58
+ )
59
+ );
60
+ }
61
+
62
+
63
+ /**
64
+ * @inheritdoc
65
+ *
66
+ * Validate field domain, which must be part of the GET request.
67
+ *
68
+ * @throws InvalidArgumentException when the domain is invalid.
69
+ * @since 2.0
70
+ */
71
+ public function prepare() {
72
+
73
+ parent::prepare();
74
+
75
+ $current_domain = $this->get_current_domain();
76
+
77
+ // Fail on invalid domain.
78
+ if( null == $current_domain ) {
79
+ throw new InvalidArgumentException(
80
+ sprintf(
81
+ __( 'Invalid field domain provided. Expected one of those values: %s', 'wpcf' ),
82
+ implode( ', ', Types_Field_Utils::get_domains() )
83
+ )
84
+ );
85
+ }
86
+
87
+ add_action( 'admin_enqueue_scripts', array( $this, 'on_admin_enqueue_scripts' ) );
88
+
89
+ add_action( 'current_screen', array( $this, 'prepare_dialogs' ) );
90
+
91
+ }
92
+
93
+
94
+ /**
95
+ * @inheritdoc
96
+ * @return string
97
+ */
98
+ public function get_title() {
99
+
100
+ switch( $this->get_current_domain() ) {
101
+ case Types_Field_Utils::DOMAIN_POSTS:
102
+ return __( 'Post Field Control', 'wpcf' );
103
+ case Types_Field_Utils::DOMAIN_USERS:
104
+ return __( 'User Field Control', 'wpcf' );
105
+ case Types_Field_Utils::DOMAIN_TERMS:
106
+ return __( 'Term Field Control', 'wpcf' );
107
+ default:
108
+ // will never happen
109
+ return '';
110
+ }
111
+ }
112
+
113
+
114
+ /**
115
+ * @inheritdoc
116
+ * @return callable
117
+ */
118
+ public function get_render_callback() {
119
+ return array( $this, 'render_page' );
120
+ }
121
+
122
+
123
+ /**
124
+ * @inheritdoc
125
+ * @return string
126
+ */
127
+ public function get_page_name() {
128
+ return Types_Admin_Menu::PAGE_NAME_FIELD_CONTROL;
129
+ }
130
+
131
+
132
+ /**
133
+ * @inheritdoc
134
+ * @return string
135
+ */
136
+ public function get_required_capability() {
137
+ return 'manage_options'; // todo better role/cap handling
138
+ }
139
+
140
+
141
+ /**
142
+ * @inheritdoc
143
+ * @return callable
144
+ */
145
+ public function get_load_callback() {
146
+ return array( $this, 'add_screen_options' );
147
+ }
148
+
149
+
150
+ /**
151
+ * Current field domain.
152
+ *
153
+ * @return string|null
154
+ * @since 2.0
155
+ */
156
+ private function get_current_domain() {
157
+ if( null == $this->current_domain ) {
158
+ $this->current_domain = wpcf_getget( self::PARAM_DOMAIN, null, Types_Field_Utils::get_domains() );
159
+ }
160
+ return $this->current_domain;
161
+ }
162
+
163
+
164
+ public function on_admin_enqueue_scripts() {
165
+
166
+ $main_handle = 'types-page-field-control-main';
167
+
168
+ // Enqueuing with the wp-admin dependency because we need to override something !important.
169
+ Types_Asset_Manager::get_instance()->enqueue_styles(
170
+ array(
171
+ 'wp-admin',
172
+ 'common',
173
+ 'font-awesome',
174
+ 'wpcf-css-embedded'
175
+ )
176
+ );
177
+
178
+ wp_enqueue_style(
179
+ $main_handle,
180
+ TYPES_RELPATH . '/public/page/field_control/style.css'
181
+ );
182
+
183
+ wp_enqueue_script(
184
+ $main_handle,
185
+ TYPES_RELPATH . '/public/page/field_control/main.js',
186
+ array(
187
+ 'jquery', 'backbone', 'headjs', 'underscore',
188
+ Types_Asset_Manager::SCRIPT_ADJUST_MENU_LINK,
189
+ Types_Asset_Manager::SCRIPT_KNOCKOUT,
190
+ Types_Asset_Manager::SCRIPT_DIALOG_BOXES,
191
+ Types_Asset_Manager::SCRIPT_UTILS
192
+ ),
193
+ TYPES_VERSION
194
+ );
195
+
196
+ }
197
+
198
+
199
+ private $twig = null;
200
+
201
+
202
+ private function get_twig() {
203
+ if( null == $this->twig ) {
204
+ $loader = new Twig_Loader_Filesystem();
205
+ $loader->addPath( TYPES_ABSPATH . '/application/views/page', 'generic_page' );
206
+ $loader->addPath( TYPES_ABSPATH . '/application/views/page/field_control', 'field_control' );
207
+ $this->twig = new Twig_Environment( $loader );
208
+ }
209
+ return $this->twig;
210
+ }
211
+
212
+
213
+ /**
214
+ * @inheritdoc
215
+ *
216
+ * @since 2.0
217
+ */
218
+ public function render_page() {
219
+
220
+ $context = $this->build_page_context();
221
+
222
+ echo $this->get_twig()->render( '@field_control/main.twig', $context );
223
+ }
224
+
225
+
226
+ /**
227
+ * Build the context for main poge template.
228
+ *
229
+ * That includes variables for the template as well as data to be passed to JavaScript.
230
+ *
231
+ * @return array Page context. See the main page template for details.
232
+ * @since 2.0
233
+ */
234
+ private function build_page_context() {
235
+
236
+ $context = array(
237
+ 'strings' => $this->build_strings_for_twig(),
238
+ 'js_model_data' => base64_encode( wp_json_encode( $this->build_js_data() ) ),
239
+ 'assets' => array(
240
+ 'loaderOverlay' => Types_Assets::get_instance()->get_image_url( Types_Assets::IMG_AJAX_LOADER_OVERLAY )
241
+ )
242
+ );
243
+
244
+ return $context;
245
+ }
246
+
247
+
248
+ /**
249
+ * Build data to be passed to JavaScript.
250
+ *
251
+ * @return array
252
+ * @since 2.0
253
+ */
254
+ private function build_js_data() {
255
+
256
+ $field_action_name = Types_Ajax::get_instance()->get_action_js_name( Types_Ajax::CALLBACK_FIELD_CONTROL_ACTION );
257
+
258
+ return array(
259
+ 'jsIncludePath' => TYPES_RELPATH . '/public/page/field_control',
260
+ 'fieldDefinitions' => $this->build_field_definitions(),
261
+ 'fieldTypeDefinitions' => Types_Field_Type_Definition_Factory::get_instance()->get_field_type_definitions(),
262
+ 'templates' => $this->build_templates(),
263
+ 'strings' => $this->build_strings_for_js(),
264
+ 'ajaxInfo' => array(
265
+ 'fieldAction' => array(
266
+ 'name' => $field_action_name,
267
+ 'nonce' => wp_create_nonce( $field_action_name )
268
+ )
269
+ ),
270
+ 'currentDomain' => $this->get_current_domain(),
271
+ 'groups' => $this->build_group_data(),
272
+ 'typeConversionMatrix' => Types_Field_Type_Converter::get_instance()->get_conversion_matrix(),
273
+ 'itemsPerPage' => $this->get_items_per_page_setting()
274
+ );
275
+
276
+ }
277
+
278
+
279
+ /**
280
+ * Prepare field definition data, depending on current field domain, for passing to JavaScript.
281
+ *
282
+ * @return array
283
+ * @since 2.0
284
+ */
285
+ private function build_field_definitions() {
286
+
287
+ $query_args = array(
288
+ 'filter' => 'all',
289
+ 'orderby' => 'name',
290
+ 'order' => 'asc'
291
+ );
292
+
293
+ $definitions = array();
294
+ switch( $this->get_current_domain() ) {
295
+ case Types_Field_Utils::DOMAIN_POSTS:
296
+ $definitions = WPCF_Field_Definition_Factory_Post::get_instance()->query_definitions( $query_args );
297
+ break;
298
+ case Types_Field_Utils::DOMAIN_USERS:
299
+ $definitions = WPCF_Field_Definition_Factory_User::get_instance()->query_definitions( $query_args );
300
+ break;
301
+ case Types_Field_Utils::DOMAIN_TERMS:
302
+ $definitions = WPCF_Field_Definition_Factory_Term::get_instance()->query_definitions( $query_args );
303
+ break;
304
+ }
305
+
306
+
307
+ $definition_data = array();
308
+ foreach( $definitions as $definition ) {
309
+ $definition_data[] = $definition->to_json();
310
+ }
311
+
312
+ return $definition_data;
313
+ }
314
+
315
+
316
+ /**
317
+ * Build array of templates that will be passed to JavaScript.
318
+ *
319
+ * If the template file does not exist or is not readable, it will be silently omitted.
320
+ *
321
+ * @return array
322
+ * @since 2.0
323
+ */
324
+ private function build_templates() {
325
+
326
+ $template_sources = array(
327
+ 'messageDefinitionList' => 'field_control/message_definition_list.html',
328
+ 'messageMultiple' => 'field_control/message_multiple.html',
329
+ );
330
+
331
+ $templates = array();
332
+ foreach( $template_sources as $template_name => $template_relpath ) {
333
+
334
+ $template_path = TYPES_ABSPATH . '/application/views/page/' . $template_relpath;
335
+
336
+ if( file_exists( $template_path ) ) {
337
+ $templates[ $template_name ] = file_get_contents( $template_path );
338
+ }
339
+ }
340
+
341
+ return $templates;
342
+ }
343
+
344
+
345
+ private function build_strings_for_twig() {
346
+
347
+ return array(
348
+ 'column' => array(
349
+ 'name' => __( 'Field name', 'wpcf' ),
350
+ 'slug' => __( 'Slug', 'wpcf' ),
351
+ 'metaKey' => __( 'Meta key', 'wpcf' ),
352
+ 'groups' => __( 'Field groups', 'wpcf' ),
353
+ 'type' => __( 'Type' )
354
+ ),
355
+ 'rowAction' => array(
356
+ 'changeAssignment' => __( 'Change assignment', 'wpcf' ),
357
+ 'changeType' => __( 'Change type', 'wpcf' ),
358
+ 'delete' => __( 'Delete', 'wpcf' )
359
+ ),
360
+ 'misc' => array(
361
+ 'noItemsFound' => __( 'No field definitions found.', 'wpcf' ),
362
+ 'applyBulkAction' => __( 'Apply', 'wpcf' ),
363
+ 'searchPlaceholder' => __( 'Search', 'wpcf' ),
364
+ 'pageTitle' => $this->get_title(),
365
+ 'items' => __( 'items', 'wpcf' ),
366
+ 'of' => __( 'of', 'wpcf' ),
367
+ 'thisFieldIsRepeating' => __( 'This is a repeating field.', 'wpcf' )
368
+ ),
369
+ 'bulkAction' => array(
370
+ 'select' => __( 'Bulk action', 'wpcf' ),
371
+ 'delete' => __( 'Delete', 'wpcf' ),
372
+ 'manageWithTypes' => __( 'Manage with Types', 'wpcf' ),
373
+ 'stopManagingWithTypes' => __( 'Stop managing with Types', 'wpcf' )
374
+ )
375
+ );
376
+ }
377
+
378
+
379
+
380
+ /**
381
+ * Prepare an array of strings used in JavaScript.
382
+ *
383
+ * @return array
384
+ * @since 2.0
385
+ */
386
+ private function build_strings_for_js() {
387
+ return array(
388
+ 'misc' => array(
389
+ 'notManagedByTypes' => __( 'Not managed by Types', 'wpcf'),
390
+ 'undefinedAjaxError' => __( 'The action was not successful, an unknown error has happened.', 'wpcf' ),
391
+ 'genericSuccess' => __( 'The action was completed successfully.', 'wpcf' ),
392
+ 'fieldsAlreadyManaged' => __( 'Some of the fields you selected are already managed by Types.', 'wpcf' ),
393
+ 'fieldsAlreadyUnmanaged' => __( 'Some of the fields you selected are already not managed by Types.', 'wpcf' ),
394
+ 'unselectAndRetry' => __( 'Please unselect them and try again.', 'wpcf' ),
395
+ 'changeAssignmentToGroups' => __( 'Change assignment to field groups for the field', 'wpcf' ),
396
+ 'deleteField' => __( 'Delete field', 'wpcf' ),
397
+ 'deleteFields' => __( 'Delete multiple fields', 'wpcf' ),
398
+ 'cannotDeleteUnmanagedFields' => __( 'Some fields will cannot be deleted because they are not managed by Types.', 'wpcf' ),
399
+ 'changeFieldType' => __( 'Change field type for the field', 'wpcf' ),
400
+ 'startManagingFieldsWithTypes' => __( 'Start managing fields with Types', 'wpcf' ),
401
+ 'stopManagingFieldsWithTypes' => __( 'Stop managing fields with Types', 'wpcf' )
402
+ ),
403
+ 'rowAction' => array(
404
+ 'manageByTypes' => array(
405
+ 'yes' => __( 'Manage with Types', 'wpcf' ),
406
+ 'no' => __( 'Stop managing with Types', 'wpcf' )
407
+ ),
408
+ 'changeCardinality' => array(
409
+ 'makeRepetitive' => __( 'Turn into repetitive', 'wpcf' ),
410
+ 'makeSingle' => __( 'Turn into single-value', 'wpcf' )
411
+ )
412
+ ),
413
+ 'bulkAction' => array(
414
+ 'select' => __( 'Bulk action', 'wpcf' ),
415
+ 'delete' => __( 'Delete', 'wpcf' ),
416
+ 'manageWithTypes' => __( 'Manage with Types', 'wpcf' ),
417
+ 'stopManagingWithTypes' => __( 'Stop managing with Types', 'wpcf' )
418
+ ),
419
+ 'button' => array(
420
+ 'apply' => __( 'Apply', 'wpcf' ),
421
+ 'cancel' => __( 'Cancel', 'wpcf' ),
422
+ 'delete' => __( 'Delete', 'wpcf' )
423
+ )
424
+ );
425
+ }
426
+
427
+
428
+ /**
429
+ * Build an array describing existing field groups within the domain.
430
+ *
431
+ * @return array
432
+ * @since 2.0
433
+ */
434
+ private function build_group_data() {
435
+ $factory = Types_Field_Utils::get_group_factory_by_domain( $this->get_current_domain() );
436
+ $groups = $factory->query_groups();
437
+
438
+ $group_data = array();
439
+ foreach( $groups as $group ) {
440
+ $group_data[ $group->get_slug() ] = array(
441
+ 'slug' => $group->get_slug(),
442
+ 'displayName' => $group->get_display_name()
443
+ );
444
+ }
445
+
446
+ return $group_data;
447
+ }
448
+
449
+
450
+ /**
451
+ * Display screen options on the page.
452
+ *
453
+ * @since 2.0
454
+ */
455
+ public function add_screen_options() {
456
+
457
+ $args = array(
458
+ 'label' => __( 'Number of displayed fields', 'wpcf' ),
459
+ 'default' => self::SCREEN_OPTION_PER_PAGE_DEFAULT_VALUE,
460
+ 'option' => self::SCREEN_OPTION_PER_PAGE_NAME,
461
+ );
462
+ add_screen_option( 'per_page', $args );
463
+
464
+ add_filter( 'set-screen-option', array( $this, 'set_screen_option' ), 10, 3);
465
+ }
466
+
467
+
468
+ /**
469
+ * Update the "per page" screen option.
470
+ *
471
+ * @param $status
472
+ * @param string $option
473
+ * @param $value
474
+ * @return mixed
475
+ * @since 2.0
476
+ */
477
+ public function set_screen_option( $status, $option, $value ) {
478
+
479
+ if ( self::SCREEN_OPTION_PER_PAGE_NAME == $option ) {
480
+ return $value;
481
+ }
482
+
483
+ return $status;
484
+
485
+ }
486
+
487
+
488
+ /**
489
+ * Value of the "items per page" setting for current page and current user.
490
+ *
491
+ * @return int
492
+ * @since 2.0
493
+ */
494
+ private function get_items_per_page_setting() {
495
+ $user = get_current_user_id();
496
+ $screen = get_current_screen();
497
+ $option = $screen->get_option( 'per_page', 'option' );
498
+ $per_page = get_user_meta( $user, $option, true );
499
+ if ( empty ( $per_page ) || $per_page < 1 ) {
500
+ $per_page = $screen->get_option( 'per_page', 'default' );
501
+ }
502
+
503
+ return (int) $per_page;
504
+ }
505
+
506
+
507
+ /**
508
+ * Prepare assets for all dialogs that are going to be used on the page.
509
+ *
510
+ * @since 2.0
511
+ */
512
+ public function prepare_dialogs() {
513
+
514
+ new Types_Dialog_Box(
515
+ 'types-change-assignment-dialog',
516
+ $this->get_twig(),
517
+ array(
518
+ 'groups' => $this->build_group_data(),
519
+ 'strings' => array(
520
+ 'noFieldGroups' => __( 'No field groups exist yet. You have to create one first.', 'wpcf' )
521
+ )
522
+ ),
523
+ '@field_control/change_assignment_dialog.twig'
524
+ );
525
+
526
+ new Types_Dialog_Box(
527
+ 'types-delete-field-dialog',
528
+ $this->get_twig(),
529
+ array(
530
+ 'strings' => array(
531
+ 'deletingWillRemoveDefinitionAndData' => __( 'Deleting fields will remove them from all groups and delete the field data from the database as well.', 'wpcf' ),
532
+ 'cannotBeUndone' => __( 'This cannot be undone!', 'wpcf' ),
533
+ 'doYouReallyWantDelete' => __( 'Do you really want to delete?', 'wpcf' )
534
+ )
535
+ ),
536
+ '@field_control/delete_dialog.twig'
537
+ );
538
+
539
+ new Types_Dialog_Box(
540
+ 'types-change-field-type-dialog',
541
+ $this->get_twig(),
542
+ array(
543
+ 'fieldTypeDefinitions' => Types_Field_Type_Definition_Factory::get_instance()->get_field_type_definitions(),
544
+ 'strings' => array(
545
+ 'aboutFieldTypeChanging' => __( 'Select a new type for this field.', 'wpcf' ),
546
+ 'someTypesAreDisabled' => __( 'Note: Some of the field types are disabled for conversion because they\'re using a significantly different data format, which is not compatible with the current field type.', 'wpcf' ),
547
+ 'potentiallyRiskyOperation' => __( 'Changing field type is a potentially risky operation. Make sure you know what you are doing.', 'wpcf' ),
548
+ 'singleOrRepeatingField' => __( 'Single or repeating field', 'wpcf' ),
549
+ 'repetitiveField' => __( 'Allow multiple instances of this field', 'wpcf' ),
550
+ 'singleField' => __( 'This field can have only one value', 'wpcf' ),
551
+ 'targetSupportsSingleOnly' => __( 'Selected field type supports only single fields.', 'wpcf' ),
552
+ 'repetitiveToSingleWarning' => __( 'Changing from repeating to single field <strong>will cause partial data loss</strong> if there already are fields with multiple values stored in the database. In such case, only one of those value will be saved on update and some inconsistencies appear when displaying values of this field.', 'wpcf' )
553
+ )
554
+ ),
555
+ '@field_control/change_type_dialog.twig'
556
+ );
557
+
558
+
559
+ new Types_Dialog_Box(
560
+ 'types-bulk-change-management-status-dialog',
561
+ $this->get_twig(),
562
+ array(
563
+ 'strings' => array(
564
+ 'youAreAboutToManageFields' => __( 'You are about to start managing these fields with Types:', 'wpcf' ),
565
+ 'youAreAboutToStopManagingFields' => __( 'You are about to stop managing these fields with Types:', 'wpcf' ),
566
+ 'confirmContinue' => __( 'Do you want to continue?', 'wpcf' )
567
+ )
568
+ ),
569
+ '@field_control/bulk_change_management_status_dialog.twig'
570
+ );
571
+ }
572
+
573
+
574
+ /**
575
+ * Get help configuration for Types_Asset_Help_Tab_Loader.
576
+ *
577
+ * @return array
578
+ * @since 2.0
579
+ */
580
+ public function get_help_config() {
581
+ return array(
582
+ 'title' => $this->get_title(),
583
+ 'template' => '@help/basic.twig',
584
+ 'context' => array(
585
+ 'introductory_paragraphs' => array(
586
+ __( 'Types plugin provides you with a powerful way to control the Post/User/Term fields.', 'wpcf' ),
587
+ __( 'On this page you can see the list of all the custom fields present in your site. Some of them were created by Types and some were not.', 'wpcf' ),
588
+ __( 'When changing changing properties of existing fields, caution is strongly advised because wrong usage can cause issues with themes, plugins and functionality connected to the applied changes.', 'wpcf' )
589
+ ),
590
+ 'your_options' => __( 'You have the following options:', 'wpcf' ),
591
+ 'options' => array(
592
+ array(
593
+ 'name' => __( 'Change assignment', 'wpcf' ),
594
+ 'explanation' => __( 'Change a group that the field belongs to.', 'wpcf' )
595
+ ),
596
+ array(
597
+ 'name' => __( 'Change type', 'wpcf' ),
598
+ 'explanation' => __( 'Change the type of the field and change whether field can have a single value or multiple values (repetitive field).', 'wpcf' )
599
+ ),
600
+ array(
601
+ 'name' => __( 'Manage with Types', 'wpcf' ),
602
+ 'explanation' => __( 'Select whether the field is under the control of Types plugin.', 'wpcf' )
603
+ ),
604
+ array(
605
+ 'name' => __( 'Delete', 'wpcf' ),
606
+ 'explanation' =>
607
+ __( 'Click to delete a field and all of its values from the database.', 'wpcf' )
608
+ . ' <strong>' . __( 'Warning: This cannot be undone.', 'wpcf' ) . '</strong>'
609
+ )
610
+ ),
611
+ 'ending_paragraphs' => array(
612
+ __( 'Note: An asterisk (*) beside a field type marks a repeating field.', 'wpcf' )
613
+ )
614
+ )
615
+ );
616
+ }
617
+
618
+ }
application/controllers/page/hidden/helper.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Page_Hidden_Helper extends Types_Page_Abstract {
4
+
5
+ private static $instance;
6
+
7
+ private $redirect_url = false;
8
+
9
+ public static function get_instance() {
10
+ if( null == self::$instance ) {
11
+ self::$instance = new self();
12
+ self::$instance->add_sneaky_hidden_helper();
13
+ }
14
+ }
15
+
16
+ public function add_sneaky_hidden_helper() {
17
+ add_submenu_page(
18
+ 'options.php', // hidden
19
+ $this->get_title(),
20
+ $this->get_title(),
21
+ $this->get_required_capability(),
22
+ $this->get_page_name(),
23
+ array( $this, $this->get_load_callback() )
24
+ );
25
+ }
26
+
27
+ public function get_title() {
28
+ return 'Loading...';
29
+ }
30
+
31
+ public function get_render_callback() {
32
+ return null;
33
+ }
34
+
35
+ public function get_load_callback() {
36
+ return 'route';
37
+ }
38
+
39
+ public function get_page_name() {
40
+ return Types_Admin_Menu::PAGE_NAME_HELPER;
41
+ }
42
+
43
+ public function get_required_capability() {
44
+ return 'manage_options';
45
+ }
46
+
47
+ public function route() {
48
+
49
+ $this->redirect_url = false;
50
+
51
+ if( isset( $_GET['action'] ) && isset( $_GET['type'] ) ) {
52
+
53
+ switch( $_GET['action'] ) {
54
+ case 'new-form':
55
+ $this->redirect_url = $this->new_form_action( $_GET['type'] );
56
+ break;
57
+ case 'new-view':
58
+ $this->redirect_url = $this->new_view_action( $_GET['type'] );
59
+ break;
60
+ case 'new-layout-template':
61
+ $this->redirect_url = $this->new_layout_template_action( $_GET['type'] );
62
+ break;
63
+ case 'new-content-template':
64
+ $this->redirect_url = $this->new_content_template_action( $_GET['type'] );
65
+ break;
66
+ case 'new-wordpress-archive':
67
+ $this->redirect_url = $this->new_wordpress_archive_action( $_GET['type'] );
68
+ break;
69
+ }
70
+
71
+ }
72
+
73
+ $this->redirect();
74
+ }
75
+
76
+ private function new_form_action( $type ) {
77
+ $new_form = new Types_Helper_Create_Form();
78
+
79
+ if( $id = $new_form->for_post( $type ) ) {
80
+ return get_edit_post_link( $id, 'Please WordPress, be so nice and do not encode &.' );
81
+ }
82
+
83
+ return false;
84
+ }
85
+
86
+ private function new_view_action( $type ) {
87
+ $new_view = new Types_Helper_Create_View();
88
+
89
+ if( $id = $new_view->for_post( $type ) ) {
90
+ return admin_url() . 'admin.php?page=views-editor&view_id='.$id;
91
+ }
92
+
93
+ return false;
94
+ }
95
+
96
+ private function new_layout_template_action( $type ) {
97
+ $new_layout = new Types_Helper_Create_Layout();
98
+
99
+ if( $id = $new_layout->for_post( $type ) ) {
100
+ return admin_url() . 'admin.php?page=dd_layouts_edit&action=edit&layout_id='.$id;
101
+ }
102
+
103
+ return false;
104
+ }
105
+
106
+ private function new_content_template_action( $type ) {
107
+ $new_layout = new Types_Helper_Create_Content_Template();
108
+
109
+ if( $id = $new_layout->for_post( $type ) ) {
110
+ return admin_url() . 'admin.php?page=ct-editor&ct_id='.$id;
111
+ }
112
+
113
+ return false;
114
+ }
115
+
116
+ private function new_wordpress_archive_action( $type ) {
117
+ $new_wordpress_archive = new Types_Helper_Create_Wordpress_Archive();
118
+
119
+ if( $id = $new_wordpress_archive->for_post( $type ) ) {
120
+ return admin_url() . 'admin.php?page=view-archives-editor&view_id='.$id;
121
+ }
122
+
123
+ return false;
124
+ }
125
+
126
+ /**
127
+ * hidden page, but only when redirect after doing what we have to do
128
+ */
129
+ private function redirect() {
130
+ // shouldn't happen but if we have no redirect_url here: goto admin main page.
131
+ if( ! $this->redirect_url )
132
+ $this->redirect_url = admin_url();
133
+
134
+ die( '<script type="text/javascript">'.'window.location = "' . $this->redirect_url . '";'.'</script>' );
135
+ }
136
+ }
application/controllers/twig_autoloader.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Autoloads Twig classes.
14
+ *
15
+ * This is a modified version of Twig_Autoloader that survives without producing a fatal error even if someone else
16
+ * includes Twig_Autoloader recklessly, without checking if !class_exists(). When the register() method is being
17
+ * called, it checks all registered autoloaders. If the native Twig_Autoloader is already there, this class resigns
18
+ * and doesn't complete it's own registration.
19
+ *
20
+ * This will, however, work only if it happens late enough. In Types we assume that it is ok to do this during 'init'.
21
+ * The one known issue is with older WPML versions that register Twig right when the plugin is loaded.
22
+ *
23
+ * Note: Twig_Autoloader is marked as deprecated, however we can't easily use the proposed composer autoloader, since
24
+ * that breaks the PHP 5.2 compatibility.
25
+ *
26
+ * The original author of this class:
27
+ * @author Fabien Potencier <fabien@symfony.com>
28
+ *
29
+ * @since 2.0
30
+ */
31
+ class Types_Twig_Autoloader
32
+ {
33
+
34
+ /**
35
+ * Registers Types_Twig_Autoloader as an SPL autoloader if Twig_Autoloader isn't already registered.
36
+ *
37
+ * @param bool $prepend Whether to prepend the autoloader or not.
38
+ */
39
+ public static function register($prepend = false)
40
+ {
41
+ $autoloaders = spl_autoload_functions();
42
+ foreach( $autoloaders as $autoloader ) {
43
+
44
+ // Resign if we detect Twig_Autoloader
45
+ if( is_array( $autoloader )
46
+ && 2 == count( $autoloader )
47
+ && is_string( $autoloader[0] )
48
+ && 'Twig_Autoloader' == $autoloader[0]
49
+ && is_string( $autoloader[1] )
50
+ && 'autoload' == $autoloader[1]
51
+ ) {
52
+ return;
53
+ }
54
+ }
55
+
56
+ if (PHP_VERSION_ID < 50300) {
57
+ spl_autoload_register(array(__CLASS__, 'autoload'));
58
+ } else {
59
+ spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
60
+ }
61
+
62
+ }
63
+
64
+
65
+ /**
66
+ * Handles autoloading of classes.
67
+ *
68
+ * @param string $class A class name.
69
+ */
70
+ public static function autoload($class)
71
+ {
72
+ if (0 !== strpos($class, 'Twig')) {
73
+ return;
74
+ }
75
+
76
+ // Modified path to Twig in Types.
77
+ $file = TYPES_ABSPATH . '/library/twig/twig/lib/' . str_replace( array( '_', "\0" ), array( '/', '' ), $class .'.php' );
78
+
79
+ if( is_file( $file ) ) {
80
+ /** @noinspection PhpIncludeInspection */
81
+ require $file;
82
+ }
83
+ }
84
+ }
application/data/information/documentation-urls.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Google Analytics
4
+ // ?utm_source=typesplugin&utm_campaign=types&utm_medium=%CURRENT-SCREEN%&utm_term=EMPTY&utm_content=EMPTY
5
+
6
+ return array(
7
+ 'learn-how-template' => 'https://wp-types.com/documentation/user-guides/benefits-of-templates-for-custom-types/',
8
+ 'learn-how-archive' => 'https://wp-types.com/documentation/user-guides/what-archives-are-and-why-they-are-so-important/',
9
+ 'learn-how-views' => 'https://wp-types.com/documentation/user-guides/learn-what-you-can-do-with-views/',
10
+ 'learn-how-forms' => 'https://wp-types.com/documentation/user-guides/learn-what-you-can-do-with-cred/',
11
+ 'creating-templates-with-toolset' => 'https://wp-types.com/documentation/user-guides/learn-about-creating-templates-with-toolset/',
12
+ 'creating-templates-with-php' => 'https://wp-types.com/documentation/user-guides/creating-templates-for-single-custom-posts-in-php/',
13
+ 'creating-archives-with-toolset' => 'https://wp-types.com/documentation/user-guides/learn-about-creating-archives-with-toolset/',
14
+ 'creating-archives-with-php' => 'https://wp-types.com/documentation/user-guides/creating-templates-custom-post-type-archives-php/',
15
+ 'how-views-work' => 'https://wp-types.com/documentation/user-guides/views/',
16
+ 'how-to-add-views-to-layouts' => 'https://wp-types.com/documentation/user-guides/views/',
17
+ 'learn-views' => 'https://wp-types.com/documentation/user-guides/learn-what-you-can-do-with-views/',
18
+ 'how-cred-work' => 'https://wp-types.com/documentation/user-guides/creating-cred-forms/',
19
+ 'how-to-add-forms-to-layouts' => 'https://wp-types.com/documentation/user-guides/creating-cred-forms/',
20
+ 'learn-cred' => 'https://wp-types.com/documentation/user-guides/learn-what-you-can-do-with-cred/',
21
+ 'free-trial' => 'https://wp-types.com/?add-to-cart=363363&buy_now=1',
22
+ 'adding-custom-fields-with-php' => 'https://wp-types.com/documentation/user-guides/displaying-wordpress-custom-fields/#1',
23
+ 'themes-compatible-with-layouts' => 'https://wp-types.com/documentation/user-guides/layouts-theme-integration/#popular-integrated-themes',
24
+ 'layouts-integration-instructions' => 'https://wp-types.com/documentation/user-guides/layouts-theme-integration/#replacing-wp-loop-with-layouts',
25
+ 'adding-views-to-layouts' => 'https://wp-types.com/documentation/user-guides/adding-views-to-layouts/',
26
+ 'adding-forms-to-layouts' => 'https://wp-types.com/documentation/user-guides/adding-cred-forms-to-layouts/',
27
+ );
application/data/information/layouts-not-compatible.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ return array(
3
+ 'layouts-not-compatible' => array(
4
+
5
+ 'conditions'=> array(),
6
+
7
+ 'description' => array(
8
+ array(
9
+ 'type' => 'paragraph',
10
+ 'content' => __( 'Layouts plugin is installed in your site, but it is not integrated with your theme.
11
+ This will make it difficult to display custom content and fields. You can:', 'types' )
12
+ ),
13
+ array(
14
+ 'type' => 'list',
15
+ 'content' => array(
16
+ __( 'Disable Layouts plugin and use Views plugin to design front-end display', 'types' ),
17
+ sprintf(
18
+ __( 'Choose a different theme (<a href="%s" target="_blank">themes compatible with Layouts</a>)', 'types' ),
19
+ Types_Helper_Url::get_url( 'themes-compatible-with-layouts', 'table' )
20
+ ),
21
+ sprintf(
22
+ __( 'Integrate Layouts with this theme (<a href="%s" target="_blank">Layouts integration instructions</a>)', 'types' ),
23
+ Types_Helper_Url::get_url( 'layouts-integration-instructions', 'table' )
24
+ ),
25
+ )
26
+ )
27
+ ),
28
+
29
+ ),
30
+ );
application/data/information/table/archive.php ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ return array(
3
+ /* Post Type with has_archive = false */
4
+ 'no-archive-support' => array(
5
+ 'type' => 'archive',
6
+
7
+ 'priority' => 'important',
8
+
9
+ 'conditions'=> array(
10
+ 'Types_Helper_Condition_Archive_No_Support'
11
+ ),
12
+
13
+ 'description' => array(
14
+ array(
15
+ 'type' => 'paragraph',
16
+ 'content' => __( 'The archive is disabled for this post type.', 'types' )
17
+ ),
18
+ array(
19
+ 'type' => 'paragraph',
20
+ 'content' => __( 'To enable, go to <a href="%POST-TYPE-EDIT-HAS-ARCHIVE%">Options</a> and mark "has_archive".', 'types' )
21
+ ),
22
+ ),
23
+ ),
24
+
25
+ /* No Views, No Layouts, Archive missing */
26
+ 'archive-missing' => array(
27
+ 'type' => 'archive',
28
+
29
+ 'priority' => 'important',
30
+
31
+ 'conditions'=> array(
32
+ 'Types_Helper_Condition_Layouts_Missing',
33
+ 'Types_Helper_Condition_Views_Missing',
34
+ 'Types_Helper_Condition_Archive_Missing'
35
+ ),
36
+
37
+ 'description' => array(
38
+ array(
39
+ 'type' => 'paragraph',
40
+ 'content' => __( 'Your theme is missing the standard WordPress archive for %POST-LABEL-PLURAL%.', 'types' )
41
+ ),
42
+ array(
43
+ 'type' => 'link',
44
+ 'external' => true,
45
+ 'label' => __( 'Visit the %POST-LABEL-PLURAL% archive', 'types' ),
46
+ 'target' => '%POST-ARCHIVE-PERMALINK%'
47
+ ),
48
+ array(
49
+ 'type' => 'dialog',
50
+ 'class' => 'button-primary types-button',
51
+ 'label' => __( 'Resolve', 'types' ),
52
+ 'dialog' => array(
53
+ 'id' => 'resolve-no-archive',
54
+ 'description' => array(
55
+ array(
56
+ 'type' => 'paragraph',
57
+ 'content' => __( 'Toolset plugins let you design archive pages without writing PHP. Your archives will include all
58
+ the fields that you need and your design.', 'types' )
59
+ ),
60
+ array(
61
+ 'type' => 'link',
62
+ 'class' => 'button-primary types-button',
63
+ 'external' => true,
64
+ 'label' => __( 'Learn about creating archives with Toolset', 'types' ),
65
+ 'target' => Types_Helper_Url::get_url( 'creating-archives-with-toolset', 'popup' ),
66
+ ),
67
+ array(
68
+ 'type' => 'paragraph',
69
+ 'content' => __( 'Or...', 'types' )
70
+ ),
71
+ array(
72
+ 'type' => 'link',
73
+ 'external' => true,
74
+ 'label' => __( 'Instructions to create the archive-%POST-TYPE-NAME%.php in PHP', 'types' ),
75
+ 'target' => Types_Helper_Url::get_url( 'creating-archives-with-php', 'popup' )
76
+ ),
77
+ )
78
+ )
79
+ )
80
+ ),
81
+ ),
82
+
83
+ /* No Views, No Layouts, Archive without Fields */
84
+ 'archive-fields-missing' => array(
85
+ 'type' => 'archive',
86
+
87
+ 'priority' => 'important',
88
+
89
+ 'conditions'=> array(
90
+ 'Types_Helper_Condition_Layouts_Missing',
91
+ 'Types_Helper_Condition_Views_Missing',
92
+ 'Types_Helper_Condition_Archive_No_Fields',
93
+ ),
94
+
95
+ 'description' => array(
96
+ array(
97
+ 'type' => 'paragraph',
98
+ 'content' => __( 'The %POST-LABEL-PLURAL% archive of your theme is missing custom fields.', 'types' )
99
+ ),
100
+ array(
101
+ 'type' => 'link',
102
+ 'external' => true,
103
+ 'label' => __( 'Visit the %POST-LABEL-PLURAL% archive', 'types' ),
104
+ 'target' => '%POST-ARCHIVE-PERMALINK%'
105
+ ),
106
+ array(
107
+ 'type' => 'dialog',
108
+ 'class' => 'button-primary types-button',
109
+ 'label' => __( 'Resolve', 'types' ),
110
+ 'dialog' => array(
111
+ 'id' => 'resolve-no-custom-fields',
112
+ 'description' => array(
113
+ array(
114
+ 'type' => 'paragraph',
115
+ 'content' => __( 'Toolset plugins let you design archives with custom fields, without writing PHP.', 'types' )
116
+ ),
117
+ array(
118
+ 'type' => 'link',
119
+ 'class' => 'button-primary types-button',
120
+ 'external' => true,
121
+ 'label' => __( 'Learn about creating archives with Toolset', 'types' ),
122
+ 'target' => Types_Helper_Url::get_url( 'creating-archives-with-toolset', 'popup' ),
123
+ ),
124
+ array(
125
+ 'type' => 'paragraph',
126
+ 'content' => __( 'Or...', 'types' )
127
+ ),
128
+ array(
129
+ 'type' => 'link',
130
+ 'external' => true,
131
+ 'label' => __( 'Instructions to create the archive-%POST-TYPE-NAME%.php in PHP', 'types' ),
132
+ 'target' => Types_Helper_Url::get_url( 'creating-archives-with-php', 'popup' )
133
+ ),
134
+ )
135
+ )
136
+ )
137
+ ),
138
+ ),
139
+
140
+ /* No Views, No Layouts, Archive Fields */
141
+ 'archive-fields' => array(
142
+ 'type' => 'archive',
143
+
144
+ 'conditions'=> array(
145
+ 'Types_Helper_Condition_Layouts_Missing',
146
+ 'Types_Helper_Condition_Views_Missing',
147
+ 'Types_Helper_Condition_Archive_Has_Fields',
148
+ ),
149
+
150
+ 'description' => array(
151
+ array(
152
+ 'type' => 'paragraph',
153
+ 'content' => __( 'Your theme displays the %POST-LABEL-SINGULAR% archive using the file: %POST-ARCHIVE-FILE%', 'types' )
154
+ ),
155
+ array(
156
+ 'type' => 'link',
157
+ 'external' => true,
158
+ 'label' => __( 'Visit the %POST-LABEL-PLURAL% archive', 'types' ),
159
+ 'target' => '%POST-ARCHIVE-PERMALINK%'
160
+ ),
161
+ ),
162
+ ),
163
+
164
+ /* Views, template missing */
165
+ 'views-archive-missing' => array(
166
+ 'type' => 'archive',
167
+
168
+ 'priority' => 'important',
169
+
170
+ 'conditions'=> array(
171
+ 'Types_Helper_Condition_Layouts_Missing',
172
+ 'Types_Helper_Condition_Views_Archive_Missing'
173
+ ),
174
+
175
+ 'description' => array(
176
+ array(
177
+ 'type' => 'paragraph',
178
+ 'content' => __( 'There is no WordPress Archive for %POST-LABEL-PLURAL%.', 'types' )
179
+ ),
180
+ array(
181
+ 'type' => 'link',
182
+ 'external' => true,
183
+ 'label' => __( 'Visit the %POST-LABEL-PLURAL% archive', 'types' ),
184
+ 'target' => '%POST-ARCHIVE-PERMALINK%'
185
+ ),
186
+ array(
187
+ 'type' => 'link',
188
+ 'class' => 'button-primary types-button',
189
+ 'target' => '%POST-CREATE-VIEWS-ARCHIVE%',
190
+ 'label' => __( 'Create archive', 'types' )
191
+ )
192
+
193
+ ),
194
+
195
+ ),
196
+
197
+ /* Views, archive */
198
+ 'views-archive' => array(
199
+ 'type' => 'archive',
200
+
201
+ 'conditions'=> array(
202
+ 'Types_Helper_Condition_Layouts_Missing',
203
+ 'Types_Helper_Condition_Views_Archive_Exists'
204
+ ),
205
+
206
+ 'description' => array(
207
+ array(
208
+ 'type' => 'paragraph',
209
+ 'content' => __( 'The WordPress Archive for %POST-LABEL-PLURAL% is "%POST-VIEWS-ARCHIVE%"', 'types' )
210
+ ),
211
+
212
+ array(
213
+ 'type' => 'link',
214
+ 'external' => true,
215
+ 'label' => __( 'Visit the %POST-LABEL-PLURAL% archive', 'types' ),
216
+ 'target' => '%POST-ARCHIVE-PERMALINK%'
217
+ ),
218
+
219
+ array(
220
+ 'type' => 'link',
221
+ 'class' => 'button',
222
+ 'label' => __( 'Edit WordPress Archive', 'types' ),
223
+ 'target' => '%POST-EDIT-VIEWS-ARCHIVE%',
224
+ )
225
+ ),
226
+
227
+ ),
228
+
229
+ /* Layouts, Archive missing */
230
+ 'layouts-archive-missing' => array(
231
+ 'type' => 'archive',
232
+
233
+ 'priority' => 'important',
234
+
235
+ 'conditions'=> array(
236
+ 'Types_Helper_Condition_Layouts_Active',
237
+ 'Types_Helper_Condition_Layouts_Archive_Missing'
238
+ ),
239
+
240
+ 'description' => array(
241
+ array(
242
+ 'type' => 'paragraph',
243
+ 'content' => __( 'There is no layout for the %POST-LABEL-PLURAL% archive.', 'types' )
244
+ ),
245
+
246
+ array(
247
+ 'type' => 'link',
248
+ 'external' => true,
249
+ 'label' => __( 'Visit the %POST-LABEL-PLURAL% archive', 'types' ),
250
+ 'target' => '%POST-ARCHIVE-PERMALINK%'
251
+ ),
252
+
253
+ array(
254
+ 'type' => 'link',
255
+ 'class' => 'button-primary types-button',
256
+ 'label' => __( 'Create archive', 'types' ),
257
+ 'target' => '%POST-CREATE-LAYOUT-ARCHIVE%',
258
+ )
259
+ ),
260
+ ),
261
+
262
+ /* Layouts, Archive */
263
+ 'layouts-archive' => array(
264
+ 'type' => 'archive',
265
+
266
+ 'conditions'=> array(
267
+ 'Types_Helper_Condition_Layouts_Active',
268
+ 'Types_Helper_Condition_Layouts_Archive_Exists'
269
+ ),
270
+
271
+ 'description' => array(
272
+ array(
273
+ 'type' => 'paragraph',
274
+ 'content' => __( 'The layout for the %POST-LABEL-PLURAL% archive is "%POST-LAYOUT-ARCHIVE%".', 'types' )
275
+ ),
276
+ array(
277
+ 'type' => 'link',
278
+ 'external' => true,
279
+ 'label' => __( 'Visit the %POST-LABEL-PLURAL% archive', 'types' ),
280
+ 'target' => '%POST-ARCHIVE-PERMALINK%'
281
+ ),
282
+ array(
283
+ 'type' => 'link',
284
+ 'class' => 'button',
285
+ 'label' => __( 'Edit layout', 'types' ),
286
+ 'target' => '%POST-EDIT-LAYOUT-ARCHIVE%',
287
+ )
288
+ ),
289
+ )
290
+ );
application/data/information/table/forms.php ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ return array(
3
+ /* CRED missing */
4
+ 'cred-missing' => array(
5
+ 'type' => 'forms',
6
+
7
+ 'conditions'=> array(
8
+ 'Types_Helper_Condition_Cred_Missing'
9
+ ),
10
+
11
+ 'description' => array(
12
+ array(
13
+ 'type' => 'dialog',
14
+ 'class' => 'button',
15
+ 'label' => __( 'Create Form', 'types' ),
16
+ 'dialog' => array(
17
+ 'id' => 'create-form',
18
+ 'description' => array(
19
+ array(
20
+ 'type' => 'paragraph',
21
+ 'content' => __( 'To create a form for front-end content submission and editing, you need have CRED plugin installed.
22
+ CRED is part of the complete Toolset package for adding and displaying custom content.', 'types' )
23
+ ),
24
+ array(
25
+ 'type' => 'link',
26
+ 'external' => true,
27
+ 'label' => __( 'Learn how CRED forms work', 'types' ),
28
+ 'target' => Types_Helper_Url::get_url( 'how-cred-work', 'popup' )
29
+ ),
30
+ /*
31
+ array(
32
+ 'type' => 'link',
33
+ 'external' => true,
34
+ 'label' => __( 'Free Toolset Trial', 'types' ),
35
+ 'target' => Types_Helper_Url::get_url( 'free-trial', 'popup' )
36
+ ),
37
+ */
38
+ )
39
+ )
40
+ )
41
+ ),
42
+ ),
43
+
44
+ /* CRED, forms missing */
45
+ 'cred-forms-missing' => array(
46
+ 'type' => 'forms',
47
+
48
+ 'conditions'=> array(
49
+ 'Types_Helper_Condition_Layouts_Missing',
50
+ 'Types_Helper_Condition_Cred_Forms_Missing'
51
+ ),
52
+
53
+ 'description' => array(
54
+ array(
55
+ 'type' => 'link',
56
+ 'class' => 'button',
57
+ 'target' => '%POST-CREATE-FORM%',
58
+ 'label' => __( 'Create form', 'types' )
59
+ )
60
+ )
61
+ ),
62
+
63
+ /* CRED, forms */
64
+ 'cred-forms' => array(
65
+ 'type' => 'forms',
66
+
67
+ 'conditions'=> array(
68
+ 'Types_Helper_Condition_Cred_Active',
69
+ 'Types_Helper_Condition_Layouts_Missing',
70
+ 'Types_Helper_Condition_Cred_Forms_Exist'
71
+ ),
72
+
73
+ 'description' => array(
74
+ array(
75
+ 'type' => 'paragraph',
76
+ 'content' => '%POST-FORMS-LIST%', 'types'
77
+ ),
78
+ array(
79
+ 'type' => 'link',
80
+ 'class' => 'button',
81
+ 'target' => '%POST-CREATE-FORM%',
82
+ 'label' => __( 'Create form', 'types' )
83
+ )
84
+ )
85
+ ),
86
+
87
+ /* CRED & Layouts, forms missing */
88
+ 'cred-layouts-forms-missing' => array(
89
+ 'type' => 'forms',
90
+
91
+ 'conditions'=> array(
92
+ 'Types_Helper_Condition_Layouts_Active',
93
+ 'Types_Helper_Condition_Cred_Forms_Missing'
94
+ ),
95
+
96
+ 'description' => array(
97
+ array(
98
+ 'type' => 'paragraph',
99
+ 'content' => __(
100
+ 'You can create forms for front-end submission and editing of %POST-LABEL-PLURAL%.', 'types'
101
+ )
102
+ ),
103
+ array(
104
+ 'type' => 'link',
105
+ 'external' => true,
106
+ 'target' => Types_Helper_Url::get_url( 'adding-forms-to-layouts', 'table' ),
107
+ 'label' => __( 'Learn how', 'types' )
108
+ ),
109
+ )
110
+ ),
111
+
112
+ /* CRED & Layouts, forms exists */
113
+ 'cred-layouts-forms' => array(
114
+ 'type' => 'forms',
115
+
116
+ 'conditions'=> array(
117
+ 'Types_Helper_Condition_Layouts_Active',
118
+ 'Types_Helper_Condition_Cred_Forms_Exist'
119
+ ),
120
+
121
+ 'description' => array(
122
+ array(
123
+ 'type' => 'paragraph',
124
+ 'content' => '%POST-FORMS-LIST%', 'types'
125
+ ),
126
+ array(
127
+ 'type' => 'link',
128
+ 'external' => true,
129
+ 'target' => Types_Helper_Url::get_url( 'adding-forms-to-layouts', 'table' ),
130
+ 'label' => __( 'How to add forms to layouts', 'types' )
131
+ ),
132
+ )
133
+ ),
134
+ );
application/data/information/table/question-marks.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ return array(
3
+ 'template' => array(
4
+ 'id' => 'template',
5
+ 'title' => __( 'Template', 'types' ),
6
+ 'description' => array(
7
+ array(
8
+ 'type' => 'paragraph',
9
+ 'content' => __( 'A template displays single-item pages with your design and fields.', 'types' )
10
+ ),
11
+ array(
12
+ 'type' => 'link',
13
+ 'external' => true,
14
+ 'label' => __( 'Learn more', 'types' ),
15
+ 'target' => Types_Helper_Url::get_url( 'learn-how-template', 'tooltip' )
16
+ ),
17
+ )
18
+ ),
19
+
20
+ 'archive' => array(
21
+ 'id' => 'archive',
22
+ 'title' => __( 'Archive', 'types' ),
23
+ 'description' => array(
24
+ array(
25
+ 'type' => 'paragraph',
26
+ 'content' => __( 'An archive is the standard list that WordPress produces for content.', 'types' )
27
+ ),
28
+ array(
29
+ 'type' => 'link',
30
+ 'external' => true,
31
+ 'label' => __( 'Learn more', 'types' ),
32
+ 'target' => Types_Helper_Url::get_url( 'learn-how-archive', 'tooltip' )
33
+ ),
34
+ )
35
+ ),
36
+
37
+ 'views' => array(
38
+ 'id' => 'views',
39
+ 'title' => __( 'Views', 'types' ),
40
+ 'description' => array(
41
+ array(
42
+ 'type' => 'paragraph',
43
+ 'content' => __( 'Views are custom lists of content, which you can display anywhere in the site.', 'types' )
44
+ ),
45
+ array(
46
+ 'type' => 'link',
47
+ 'external' => true,
48
+ 'label' => __( 'Learn more', 'types' ),
49
+ 'target' => Types_Helper_Url::get_url( 'learn-how-views', 'tooltip' )
50
+ ),
51
+ )
52
+ ),
53
+
54
+ 'forms' => array(
55
+ 'id' => 'forms',
56
+ 'title' => __( 'Forms', 'types' ),
57
+ 'description' => array(
58
+ array(
59
+ 'type' => 'paragraph',
60
+ 'content' => __( 'Forms allow to create and edit content from the site’s front-end.', 'types' )
61
+ ),
62
+ array(
63
+ 'type' => 'link',
64
+ 'external' => true,
65
+ 'label' => __( 'Learn more', 'types' ),
66
+ 'target' => Types_Helper_Url::get_url( 'learn-how-forms', 'tooltip' )
67
+ ),
68
+ )
69
+ )
70
+ );
application/data/information/table/template.php ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ return array(
3
+ /* No Views, No Layouts, Single Missing */
4
+ 'single-missing' => array(
5
+ 'type' => 'template',
6
+
7
+ 'priority' => 'important',
8
+
9
+ 'conditions'=> array(
10
+ 'Types_Helper_Condition_Layouts_Missing',
11
+ 'Types_Helper_Condition_Views_Missing',
12
+ 'Types_Helper_Condition_Single_Missing'
13
+ ),
14
+
15
+ 'description' => array(
16
+ array(
17
+ 'type' => 'paragraph',
18
+ 'content' => __( 'Your theme doesn’t have a template to display %POST-LABEL-PLURAL%.', 'types' )
19
+ ),
20
+ array(
21
+ 'type' => 'link',
22
+ 'external' => true,
23
+ 'label' => __( 'Visit example %POST-LABEL-SINGULAR%', 'types' ),
24
+ 'target' => '%POST-PERMALINK%'
25
+ ),
26
+ array(
27
+ 'type' => 'dialog',
28
+ 'class' => 'button-primary types-button',
29
+ 'label' => __( 'Resolve', 'types' ),
30
+ 'dialog' => array(
31
+ 'id' => 'resolve-single-no-template',
32
+ 'description' => array(
33
+ array(
34
+ 'type' => 'paragraph',
35
+ 'content' => __( 'Toolset plugins let you design templates for single items (%POST-LABEL-SINGULAR% pages) without
36
+ writing PHP. Your templates will include all the fields that you need and your design.', 'types' )
37
+ ),
38
+ array(
39
+ 'type' => 'link',
40
+ 'class' => 'button-primary types-button',
41
+ 'external' => true,
42
+ 'label' => __( 'Learn about creating templates with Toolset', 'types' ),
43
+ 'target' => Types_Helper_Url::get_url( 'creating-templates-with-toolset', 'popup' ),
44
+ ),
45
+ array(
46
+ 'type' => 'paragraph',
47
+ 'content' => __( 'Or...', 'types' )
48
+ ),
49
+ array(
50
+ 'type' => 'link',
51
+ 'external' => true,
52
+ 'label' => __( 'Instructions to create a single-%POST-TYPE-NAME%.php in PHP', 'types' ),
53
+ 'target' => Types_Helper_Url::get_url( 'creating-templates-with-php', 'popup' )
54
+ ),
55
+ )
56
+ )
57
+ )
58
+ ),
59
+ ),
60
+
61
+ /* No Views, No Layouts, Single, without Fields */
62
+ 'single-fields-missing' => array(
63
+ 'type' => 'template',
64
+
65
+ 'priority' => 'important',
66
+
67
+ 'conditions'=> array(
68
+ 'Types_Helper_Condition_Layouts_Missing',
69
+ 'Types_Helper_Condition_Views_Missing',
70
+ 'Types_Helper_Condition_Single_No_Fields',
71
+ ),
72
+
73
+ 'description' => array(
74
+ array(
75
+ 'type' => 'paragraph',
76
+ 'content' => __( 'Your theme’s template file for displaying %POST-LABEL-SINGULAR% items is missing custom fields.', 'types' )
77
+ ),
78
+ array(
79
+ 'type' => 'link',
80
+ 'external' => true,
81
+ 'label' => __( 'Visit example %POST-LABEL-SINGULAR%', 'types' ),
82
+ 'target' => '%POST-PERMALINK%'
83
+ ),
84
+ array(
85
+ 'type' => 'dialog',
86
+ 'class' => 'button-primary types-button',
87
+ 'label' => __( 'Resolve', 'types' ),
88
+ 'dialog' => array(
89
+ 'id' => 'resolve-single-no-fields',
90
+ 'description' => array(
91
+ array(
92
+ 'type' => 'paragraph',
93
+ 'content' => __( 'Toolset plugins let you design templates for single items (%POST-LABEL-SINGULAR% pages),
94
+ with all the fields that you need to display.', 'types' )
95
+ ),
96
+ array(
97
+ 'type' => 'link',
98
+ 'class' => 'button-primary types-button',
99
+ 'external' => true,
100
+ 'label' => __( 'Learn about creating templates with Toolset', 'types' ),
101
+ 'target' => Types_Helper_Url::get_url( 'creating-templates-with-toolset', 'popup' ),
102
+ ),
103
+ array(
104
+ 'type' => 'paragraph',
105
+ 'content' => __( 'Or...', 'types' )
106
+ ),
107
+ array(
108
+ 'type' => 'link',
109
+ 'external' => true,
110
+ 'label' => __( 'Instructions for adding custom fields to single-%POST-TYPE-NAME%.php in PHP', 'types' ),
111
+ 'target' => Types_Helper_Url::get_url( 'adding-custom-fields-with-php', 'popup' )
112
+ ),
113
+ )
114
+ )
115
+ )
116
+ ),
117
+ ),
118
+
119
+ /* No Views, No Layouts, Single with Fields */
120
+ 'single-fields' => array(
121
+ 'type' => 'template',
122
+
123
+ 'conditions'=> array(
124
+ 'Types_Helper_Condition_Layouts_Missing',
125
+ 'Types_Helper_Condition_Views_Missing',
126
+ 'Types_Helper_Condition_Single_Has_Fields',
127
+ ),
128
+
129
+ 'description' => array(
130
+ array(
131
+ 'type' => 'paragraph',
132
+ 'content' => __( 'Your theme displays single %POST-LABEL-SINGULAR% pages using the template file: %POST-TEMPLATE-FILE%', 'types' )
133
+ ),
134
+ array(
135
+ 'type' => 'link',
136
+ 'external' => true,
137
+ 'label' => __( 'Visit example %POST-LABEL-SINGULAR%', 'types' ),
138
+ 'target' => '%POST-PERMALINK%'
139
+ ),
140
+ ),
141
+ ),
142
+
143
+ /* Views, template missing */
144
+ 'views-template-missing' => array(
145
+ 'type' => 'template',
146
+
147
+ 'priority' => 'important',
148
+
149
+ 'conditions'=> array(
150
+ 'Types_Helper_Condition_Layouts_Missing',
151
+ 'Types_Helper_Condition_Views_Template_Missing'
152
+ ),
153
+
154
+ 'description' => array(
155
+ array(
156
+ 'type' => 'paragraph',
157
+ 'content' => __( 'There is no Content Template for %POST-LABEL-SINGULAR% items.', 'types' )
158
+ ),
159
+ array(
160
+ 'type' => 'link',
161
+ 'external' => true,
162
+ 'label' => __( 'Visit example %POST-LABEL-SINGULAR%', 'types' ),
163
+ 'target' => '%POST-PERMALINK%'
164
+ ),
165
+ array(
166
+ 'type' => 'link',
167
+ 'class' => 'button-primary types-button',
168
+ 'target' => '%POST-CREATE-CONTENT-TEMPLATE%',
169
+ 'label' => __( 'Create Content Template', 'types' )
170
+ )
171
+ ),
172
+
173
+ ),
174
+
175
+ /* Views, template */
176
+ 'views-template' => array(
177
+ 'type' => 'template',
178
+
179
+ 'conditions'=> array(
180
+ 'Types_Helper_Condition_Layouts_Missing',
181
+ 'Types_Helper_Condition_Views_Template_Exists'
182
+ ),
183
+
184
+ 'description' => array(
185
+ array(
186
+ 'type' => 'paragraph',
187
+ 'content' => __( 'The Content Template for %POST-LABEL-PLURAL% is "%POST-CONTENT-TEMPLATE-NAME%"', 'types' )
188
+ ),
189
+ array(
190
+ 'type' => 'link',
191
+ 'external' => true,
192
+ 'label' => __( 'Visit example %POST-LABEL-SINGULAR%', 'types' ),
193
+ 'target' => '%POST-PERMALINK%'
194
+ ),
195
+ array(
196
+ 'type' => 'link',
197
+ 'class' => 'button',
198
+ 'label' => __( 'Edit Content Template', 'types' ),
199
+ 'target' => '%POST-EDIT-CONTENT-TEMPLATE%'
200
+ ),
201
+ ),
202
+
203
+ ),
204
+
205
+ /* Layouts, template missing*/
206
+ 'layouts-template-missing' => array(
207
+ 'type' => 'template',
208
+
209
+ 'priority' => 'important',
210
+
211
+ 'conditions'=> array(
212
+ 'Types_Helper_Condition_Layouts_Active',
213
+ 'Types_Helper_Condition_Layouts_Template_Missing'
214
+ ),
215
+
216
+ 'description' => array(
217
+ array(
218
+ 'type' => 'paragraph',
219
+ 'content' => __( 'There is no template layout for %POST-LABEL-SINGULAR% items.', 'types' )
220
+ ),
221
+ array(
222
+ 'type' => 'link',
223
+ 'external' => true,
224
+ 'label' => __( 'Visit example %POST-LABEL-SINGULAR%', 'types' ),
225
+ 'target' => '%POST-PERMALINK%'
226
+ ),
227
+ array(
228
+ 'type' => 'link',
229
+ 'class' => 'button-primary types-button',
230
+ 'label' => __( 'Create template', 'types' ),
231
+ 'target' => '%POST-CREATE-LAYOUT-TEMPLATE%',
232
+ )
233
+ ),
234
+ ),
235
+
236
+ /* Layouts, template */
237
+ 'layouts-template' => array(
238
+ 'type' => 'template',
239
+
240
+ 'conditions'=> array(
241
+ 'Types_Helper_Condition_Layouts_Active',
242
+ 'Types_Helper_Condition_Layouts_Template_Exists'
243
+ ),
244
+
245
+ 'description' => array(
246
+ array(
247
+ 'type' => 'paragraph',
248
+ 'content' => __( 'The template layout for %POST-LABEL-SINGULAR% items is "%POST-LAYOUT-TEMPLATE%".', 'types' )
249
+ ),
250
+ array(
251
+ 'type' => 'link',
252
+ 'external' => true,
253
+ 'label' => __( 'Visit example %POST-LABEL-SINGULAR%', 'types' ),
254
+ 'target' => '%POST-PERMALINK%'
255
+ ),
256
+ array(
257
+ 'type' => 'link',
258
+ 'class' => 'button',
259
+ 'label' => __( 'Edit template', 'types' ),
260
+ 'target' => '%POST-EDIT-LAYOUT-TEMPLATE%'
261
+ ),
262
+ ),
263
+ ),
264
+ );
application/data/information/table/views.php ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ return array(
3
+ /* Views missing */
4
+ 'views-missing' => array(
5
+ 'type' => 'views',
6
+
7
+ 'conditions'=> array(
8
+ 'Types_Helper_Condition_Views_Missing'
9
+ ),
10
+
11
+ 'description' => array(
12
+ array(
13
+ 'type' => 'dialog',
14
+ 'class' => 'button',
15
+ 'label' => __( 'Create View', 'types' ),
16
+ 'dialog' => array(
17
+ 'id' => 'create-view',
18
+ 'description' => array(
19
+ array(
20
+ 'type' => 'paragraph',
21
+ 'content' => __( 'To create a View for this content type, you need have Views plugin installed. Views is part of the
22
+ complete Toolset package for adding and displaying custom content.', 'types' )
23
+ ),
24
+ array(
25
+ 'type' => 'link',
26
+ 'external' => true,
27
+ 'label' => __( 'Learn how Views work', 'types' ),
28
+ 'target' => Types_Helper_Url::get_url( 'how-views-work', 'popup' )
29
+ ),
30
+ /*
31
+ array(
32
+ 'type' => 'link',
33
+ 'external' => true,
34
+ 'label' => __( 'Free Toolset Trial', 'types' ),
35
+ 'target' => Types_Helper_Url::get_url( 'free-trial', 'popup' )
36
+ )
37
+ */
38
+ )
39
+ )
40
+ )
41
+ ),
42
+
43
+ ),
44
+
45
+ /* Views, views missing */
46
+ 'views-views-missing' => array(
47
+ 'type' => 'views',
48
+
49
+ 'conditions'=> array(
50
+ 'Types_Helper_Condition_Layouts_Missing',
51
+ 'Types_Helper_Condition_Views_Views_Missing',
52
+ ),
53
+
54
+ 'description' => array(
55
+ array(
56
+ 'type' => 'link',
57
+ 'class' => 'button',
58
+ 'target' => '%POST-CREATE-VIEW%',
59
+ 'label' => __( 'Create View', 'types' )
60
+ )
61
+ )
62
+ ),
63
+
64
+ /* Views, views */
65
+ 'views-views' => array(
66
+ 'type' => 'views',
67
+
68
+ 'conditions'=> array(
69
+ 'Types_Helper_Condition_Layouts_Missing',
70
+ 'Types_Helper_Condition_Views_Views_Exist',
71
+ ),
72
+
73
+ 'description' => array(
74
+ array(
75
+ 'type' => 'paragraph',
76
+ 'content' => '%POST-VIEWS-LIST%', 'types'
77
+ ),
78
+ array(
79
+ 'type' => 'link',
80
+ 'class' => 'button',
81
+ 'target' => '%POST-CREATE-VIEW%',
82
+ 'label' => __( 'Create View', 'types' )
83
+ )
84
+ )
85
+ ),
86
+
87
+ /* Views Layouts, views missing */
88
+ 'views-layouts-views-missing' => array(
89
+ 'type' => 'views',
90
+
91
+ 'conditions'=> array(
92
+ 'Types_Helper_Condition_Layouts_Active',
93
+ 'Types_Helper_Condition_Views_Views_Missing'
94
+ ),
95
+
96
+ 'description' => array(
97
+ array(
98
+ 'type' => 'paragraph',
99
+ 'content' => __(
100
+ 'Edit any layout and add a View cell to it, to display lists of %POST-LABEL-PLURAL%.', 'types'
101
+ )
102
+ ),
103
+ array(
104
+ 'type' => 'link',
105
+ 'external' => true,
106
+ 'target' => Types_Helper_Url::get_url( 'adding-views-to-layouts', 'table' ),
107
+ 'label' => __( 'Learn how', 'types' )
108
+ ),
109
+ )
110
+ ),
111
+
112
+ /* Views Layouts, views */
113
+ 'views-layouts-views' => array(
114
+ 'type' => 'views',
115
+
116
+ 'conditions'=> array(
117
+ 'Types_Helper_Condition_Layouts_Active',
118
+ 'Types_Helper_Condition_Views_Views_Exist'
119
+ ),
120
+
121
+ 'description' => array(
122
+ array(
123
+ 'type' => 'paragraph',
124
+ 'content' => '%POST-VIEWS-LIST%', 'types'
125
+ ),
126
+ array(
127
+ 'type' => 'link',
128
+ 'external' => true,
129
+ 'target' => Types_Helper_Url::get_url( 'adding-views-to-layouts', 'table' ),
130
+ 'label' => __( 'How to add Views to layouts', 'types' )
131
+ ),
132
+ )
133
+ ),
134
+ );
application/functions.php ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is meant for very generic functions that should be allways available, PHP compatibility fixes and so on.
4
+ *
5
+ * Do not let it grow too much and make sure to wrap each function in !function_exists() condition.
6
+ *
7
+ * @since 2.0
8
+ */
9
+
10
+
11
+ if ( !function_exists( 'get_called_class' ) ) {
12
+
13
+ /**
14
+ * PHP 5.2 support.
15
+ *
16
+ * get_called_class() is only in PHP >= 5.3, this is a workaround.
17
+ *
18
+ * @since 1.9
19
+ */
20
+ function get_called_class() {
21
+ $bt = debug_backtrace();
22
+ $l = 0;
23
+ do {
24
+ $l++;
25
+ $lines = file( $bt[ $l ]['file'] );
26
+ $callerLine = $lines[ $bt[ $l ]['line'] - 1 ];
27
+ preg_match( '/([a-zA-Z0-9\_]+)::' . $bt[ $l ]['function'] . '/', $callerLine, $matches );
28
+ } while( $matches[1] === 'parent' && $matches[1] );
29
+
30
+ return $matches[1];
31
+ }
32
+ }
33
+
34
+
35
+
36
+ if( !function_exists( 'wpcf_getpost' ) ) {
37
+
38
+ /**
39
+ * Safely retrieve a key from $_POST variable.
40
+ *
41
+ * This is a wrapper for wpcf_getarr(). See that for more information.
42
+ *
43
+ * @param string $key
44
+ * @param mixed $default
45
+ * @param null|array $valid
46
+ *
47
+ * @return mixed
48
+ * @since 1.9
49
+ */
50
+ function wpcf_getpost( $key, $default = '', $valid = null ) {
51
+ return wpcf_getarr( $_POST, $key, $default, $valid );
52
+ }
53
+
54
+ }
55
+
56
+
57
+ if( !function_exists( 'wpcf_getget' ) ) {
58
+
59
+ /**
60
+ * Safely retrieve a key from $_GET variable.
61
+ *
62
+ * This is a wrapper for wpcf_getarr(). See that for more information.
63
+ *
64
+ * @param string $key
65
+ * @param mixed $default
66
+ * @param null|array $valid
67
+ *
68
+ * @return mixed
69
+ * @since 1.9
70
+ */
71
+ function wpcf_getget( $key, $default = '', $valid = null ) {
72
+ return wpcf_getarr( $_GET, $key, $default, $valid );
73
+ }
74
+
75
+ }
76
+
77
+
78
+ if( !function_exists( 'wpcf_getarr' ) ) {
79
+
80
+ /**
81
+ * Safely retrieve a key from given array (meant for $_POST, $_GET, etc).
82
+ *
83
+ * Checks if the key is set in the source array. If not, default value is returned. Optionally validates against array
84
+ * of allowed values and returns default value if the validation fails.
85
+ *
86
+ * @param array $source The source array.
87
+ * @param string $key The key to be retrieved from the source array.
88
+ * @param mixed $default Default value to be returned if key is not set or the value is invalid. Optional.
89
+ * Default is empty string.
90
+ * @param null|array $valid If an array is provided, the value will be validated against it's elements.
91
+ *
92
+ * @return mixed The value of the given key or $default.
93
+ *
94
+ * @since 1.9
95
+ */
96
+ function wpcf_getarr( &$source, $key, $default = '', $valid = null ) {
97
+ if ( isset( $source[ $key ] ) ) {
98
+ $val = $source[ $key ];
99
+ if ( is_array( $valid ) && ! in_array( $val, $valid ) ) {
100
+ return $default;
101
+ }
102
+
103
+ return $val;
104
+ } else {
105
+ return $default;
106
+ }
107
+ }
108
+
109
+ }
110
+
111
+
112
+ if( !function_exists( 'wpcf_ensarr' ) ) {
113
+
114
+ /**
115
+ * Ensure that a variable is an array.
116
+ *
117
+ * @param mixed $array The original value.
118
+ * @param array $default Default value to use when no array is provided. This one should definitely be an array,
119
+ * otherwise the function doesn't make much sense.
120
+ *
121
+ * @return array The original array or a default value if no array is provided.
122
+ *
123
+ * @since 1.9
124
+ */
125
+ function wpcf_ensarr( $array, $default = array() ) {
126
+ return ( is_array( $array ) ? $array : $default );
127
+ }
128
+
129
+ }
130
+
131
+
132
+ if( !function_exists( 'wpcf_wraparr' ) ) {
133
+
134
+ /**
135
+ * Wrap a variable value in an array if it's not array already.
136
+ *
137
+ * @param mixed $input
138
+ *
139
+ * @return array
140
+ * @since 1.9.1
141
+ */
142
+ function wpcf_wraparr( $input ) {
143
+ return ( is_array( $input ) ? $input : array( $input ) );
144
+ }
145
+
146
+ }
147
+
148
+
149
+ if( !function_exists( 'wpcf_getnest' ) ) {
150
+
151
+ /**
152
+ * Get a value from nested associative array.
153
+ *
154
+ * This function will try to traverse a nested associative array by the set of keys provided.
155
+ *
156
+ * E.g. if you have $source = array( 'a' => array( 'b' => array( 'c' => 'my_value' ) ) ) and want to reach 'my_value',
157
+ * you need to write: $my_value = wpcf_getnest( $source, array( 'a', 'b', 'c' ) );
158
+ *
159
+ * @param mixed|array $source The source array.
160
+ * @param string[] $keys Keys which will be used to access the final value.
161
+ * @param null|mixed $default Default value to return when the keys cannot be followed.
162
+ *
163
+ * @return mixed|null Value in the nested structure defined by keys or default value.
164
+ *
165
+ * @since 1.9
166
+ */
167
+ function wpcf_getnest( &$source, $keys = array(), $default = null ) {
168
+
169
+ $current_value = $source;
170
+ while( ! empty( $keys ) ) {
171
+ $current_key = array_shift( $keys );
172
+ $is_last_key = empty( $keys );
173
+
174
+ $current_value = wpcf_getarr( $current_value, $current_key, null );
175
+
176
+ if ( $is_last_key ) {
177
+ return $current_value;
178
+ } elseif ( ! is_array( $current_value ) ) {
179
+ return $default;
180
+ }
181
+ }
182
+
183
+ return $default;
184
+ }
185
+
186
+ }
application/models/api/helper.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Api_Helper {
5
+
6
+ /**
7
+ * Returns all ids of field groups assigned to the given post type.
8
+ * This is used by CRED (auto complete form)
9
+ *
10
+ * @todo write tests and refactor code.
11
+ * @param $post_type
12
+ *
13
+ * @return array
14
+ */
15
+ public static function get_field_group_ids_by_post_type( $value, $post_type ) {
16
+ global $wpdb;
17
+ $sql = 'SELECT post_id FROM ' .$wpdb->postmeta . '
18
+ WHERE meta_key="_wp_types_group_post_types"
19
+ AND (meta_value LIKE "%'.$post_type.'%" OR meta_value="all" OR meta_value REGEXP "^[,]+$")
20
+ ORDER BY post_id ASC';
21
+ $post_ids = $wpdb->get_col( $sql );
22
+
23
+ return $post_ids;
24
+ }
25
+ }
application/models/field/type/definition.php ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Field type definition.
5
+ *
6
+ * This represents a single field type like "email", "audio", "checkbox" and so on. This class must be instantiated
7
+ * exclusively through Types_Field_Type_Definition_Factory.
8
+ */
9
+ class Types_Field_Type_Definition {
10
+
11
+
12
+ /**
13
+ * @var string Slug of the registered field type.
14
+ */
15
+ private $field_type_slug;
16
+
17
+
18
+ /**
19
+ * @var string Name of the field type that can be displayed to the user.
20
+ */
21
+ private $display_name;
22
+
23
+
24
+ /**
25
+ * @var string Field description entered by the user.
26
+ */
27
+ private $description;
28
+
29
+
30
+ /**
31
+ * @var array Arguments defining the field type. Can contain some legacy values.
32
+ */
33
+ private $args;
34
+
35
+
36
+ /**
37
+ * Types_Field_Type_Definition constructor.
38
+ *
39
+ * @param string $field_type_slug Field type slug.
40
+ * @param array $args Additional array of arguments which should contain at least 'display_name' (or 'title')
41
+ * and 'description' elements, but omitting them is not critical.
42
+ */
43
+ public function __construct( $field_type_slug, $args ) {
44
+
45
+ if( sanitize_title( $field_type_slug ) != $field_type_slug ) {
46
+ throw new InvalidArgumentException( 'Invalid field type slug.' );
47
+ }
48
+
49
+ if( ! is_array( $args ) ) {
50
+ throw new InvalidArgumentException( 'Wrong arguments provided.' );
51
+ }
52
+
53
+ $this->field_type_slug = $field_type_slug;
54
+
55
+ // Try to fall back to legacy "title", and if even that fails, use id instead.
56
+ $this->display_name = sanitize_text_field( wpcf_getarr( $args, 'display_name', wpcf_getarr( $args, 'title', $field_type_slug ) ) );
57
+
58
+ $this->description = wpcf_getarr( $args, 'description', '' );
59
+ $this->args = $args;
60
+ }
61
+
62
+
63
+ public function get_slug() { return $this->field_type_slug; }
64
+
65
+ public function get_display_name() { return $this->display_name; }
66
+
67
+ public function get_description() { return $this->description; }
68
+
69
+
70
+ /**
71
+ * Determine if the fields of this type can be repetitive.
72
+ *
73
+ * @return bool
74
+ * @since 2.0
75
+ */
76
+ public function can_be_repetitive() { return true; }
77
+
78
+
79
+ /**
80
+ * Direct access to the field type configuration.
81
+ *
82
+ * It is strongly encouraged to write custom (and safe) getters for anything you need to get from it.
83
+ *
84
+ * @param null|string $argument_name Specific argument name or null to return all arguments.
85
+ * @param string $default Default value when a specific argument is not set.
86
+ * @return array|mixed
87
+ * @since 2.0
88
+ */
89
+ public function get_args( $argument_name = null, $default = '' ) {
90
+ if( null == $argument_name ) {
91
+ return $this->args;
92
+ } else {
93
+ return wpcf_getarr( $this->args, $argument_name, $default );
94
+ }
95
+ }
96
+
97
+
98
+ /**
99
+ * Retrieve CSS classes for a field type icon.
100
+ *
101
+ * To be placed in the i tag.
102
+ *
103
+ * @return string One or more CSS classes separated by spaces.
104
+ * @since 2.0
105
+ */
106
+ public function get_icon_classes() {
107
+ $fa_class = $this->get_args( 'font-awesome', null );
108
+ if( null != $fa_class ) {
109
+ return sprintf( 'fa fa-%s', esc_attr( $fa_class ) );
110
+ }
111
+
112
+ $types_class = $this->get_args( 'types-field-image', null );
113
+ if( null != $types_class ) {
114
+ return sprintf( 'types-field-icon types-field-icon-%s', esc_attr( $types_class ) );
115
+ }
116
+
117
+ return '';
118
+ }
119
+
120
+
121
+ /**
122
+ * Make sure that the field definition array contains all necessary information.
123
+ *
124
+ * Note: This is a WIP, currently it sanitizes only very specific cases. It should be extended in the future.
125
+ *
126
+ * Expected definition array structure common to all fields:
127
+ *
128
+ * - slug: string
129
+ * - data: array
130
+ * - validate: array
131
+ *
132
+ * @param array $definition_array Field definition array
133
+ * @return array Field definition array that is safe to be used even with legacy code.
134
+ * @since 2.0
135
+ */
136
+ public function sanitize_field_definition_array( $definition_array ) {
137
+
138
+ $definition_array['data'] = wpcf_ensarr( wpcf_getarr( $definition_array, 'data' ) );
139
+
140
+ $definition_array['data']['validate'] = wpcf_ensarr( wpcf_getarr( $definition_array['data'], 'validate' ) );
141
+
142
+ $definition_array = $this->sanitize_numeric_validation( $definition_array );
143
+
144
+ return $definition_array;
145
+ }
146
+
147
+
148
+ /**
149
+ * For all fields, remove the "number" validation option.
150
+ *
151
+ * Numeric field will override this and do the opposite instead.
152
+ *
153
+ * @param array $definition_array
154
+ * @return array
155
+ * @since 2.0
156
+ */
157
+ protected function sanitize_numeric_validation( $definition_array ) {
158
+
159
+ // This is what wpcf_admin_custom_fields_change_type() was doing.
160
+ if( isset( $definition_array['data']['validate']['number'] ) ) {
161
+ unset( $definition_array['data']['validate']['number'] );
162
+ }
163
+
164
+ return $definition_array;
165
+ }
166
+
167
+ }
application/models/field/type/definition/checkbox.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Checkbox field type.
5
+ *
6
+ * @since 2.0
7
+ */
8
+ final class Types_Field_Type_Definition_Checkbox extends Types_Field_Type_Definition_Singular {
9
+
10
+
11
+ public function __construct( $args ) {
12
+ parent::__construct( Types_Field_Type_Definition_Factory::CHECKBOX, $args );
13
+ }
14
+
15
+
16
+ /**
17
+ * @inheritdoc
18
+ *
19
+ * Checkbox field definition needs to contain these keys:
20
+ *
21
+ * - data/set_value: The value that will be saved to database when the field is checked. Default is '1'
22
+ *
23
+ * @param array $definition_array
24
+ * @return array
25
+ * @since 2.0
26
+ */
27
+ public function sanitize_field_definition_array( $definition_array ) {
28
+ $definition_array = parent::sanitize_field_definition_array( $definition_array );
29
+
30
+ $set_value = wpcf_getnest( $definition_array, array( 'data', 'set_value' ), '1' );
31
+ if( !is_string( $set_value ) && !is_numeric( $set_value ) ) {
32
+ $set_value = '1';
33
+ }
34
+ $definition_array['data']['set_value'] = $set_value;
35
+
36
+ return $definition_array;
37
+ }
38
+
39
+ }
application/models/field/type/definition/numeric.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Numeric field type.
5
+ *
6
+ * @since 2.0
7
+ */
8
+ final class Types_Field_Type_Definition_Numeric extends Types_Field_Type_Definition {
9
+
10
+
11
+ public function __construct( $args ) {
12
+ parent::__construct( Types_Field_Type_Definition_Factory::NUMERIC, $args );
13
+ }
14
+
15
+
16
+ /**
17
+ * Add the 'number' validation if it was not already there, and activate it.
18
+ *
19
+ * @param array $definition_array
20
+ * @return array
21
+ * @since 2.0
22
+ */
23
+ protected function sanitize_numeric_validation( $definition_array ) {
24
+
25
+ // Get the original setting or a default one.
26
+ $validation_setting = wpcf_ensarr(
27
+ wpcf_getnest( $definition_array, array( 'data', 'validate', 'number' ) ),
28
+ array( 'active' => true, 'message' => __( 'Please enter numeric data', 'wpcf' ) )
29
+ );
30
+
31
+ // Force the activation of this validation.
32
+ $validation_setting['active'] = true;
33
+
34
+ // Store the setting.
35
+ $definition_array['data']['validate']['number'] = $validation_setting;
36
+
37
+ return $definition_array;
38
+ }
39
+ }
application/models/field/type/definition/singular.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Field type definition for single-value only fields.
5
+ *
6
+ * @since 2.0
7
+ */
8
+ class Types_Field_Type_Definition_Singular extends Types_Field_Type_Definition {
9
+
10
+ /**
11
+ * @inheritdoc
12
+ * @return bool
13
+ */
14
+ public function can_be_repetitive() {
15
+ return false;
16
+ }
17
+
18
+ }
application/models/field/type/definition_factory.php ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Factory class for loading field type definitions.
5
+ *
6
+ * Handles creation of the objects as well as their caching.
7
+ *
8
+ * Currently it is only possible to load existing field types, not create new ones. We're depending on the legacy code
9
+ * in WPCF_Fields and field types defined through specially named functions. But that is hidden from anyone who uses
10
+ * this class.
11
+ *
12
+ * @since 1.9
13
+ */
14
+ final class Types_Field_Type_Definition_Factory {
15
+
16
+ const AUDIO = 'audio';
17
+ const COLORPICKER = 'colorpicker';
18
+ const DATE = 'date';
19
+ const EMBED = 'embed';
20
+ const FILE = 'file';
21
+ const GOOGLE_ADDRESS = 'google_address';
22
+ const CHECKBOX = 'checkbox';
23
+ const CHECKBOXES = 'checkboxes';
24
+ const IMAGE = 'image';
25
+ const NUMERIC = 'numeric';
26
+ const RADIO = 'radio';
27
+ const SELECT = 'select';
28
+ const SKYPE = 'skype';
29
+ const TEXTFIELD = 'textfield';
30
+ const URL = 'url';
31
+ const VIDEO = 'video';
32
+ const WYSIWYG = 'wysiwyg';
33
+
34
+ private static $instance = null;
35
+
36
+ private function __construct() { }
37
+
38
+ private function __clone() { }
39
+
40
+
41
+ public static function get_instance() {
42
+ if( null == self::$instance ) {
43
+ self::$instance = new self();
44
+ }
45
+ return self::$instance;
46
+ }
47
+
48
+
49
+ /**
50
+ * @var array Associative array of instantiated field type definitions, indexed by field type slugs ("checkbox",
51
+ * "email" and such).
52
+ */
53
+ private $field_type_definitions = array();
54
+
55
+
56
+ /**
57
+ * @var null|array Cached array containing path to files (!) that contain specially named functions (!) that
58
+ * can be used to return configuration array for a field type (!). We're caching it because
59
+ * WPCF_Fields::getFieldsTypes() applies a filter each time it is called.
60
+ */
61
+ private $legacy_field_types = null;
62
+
63
+
64
+ /**
65
+ * @return array See $legacy_field_types.
66
+ */
67
+ private function get_legacy_field_types() {
68
+ if( null == $this->legacy_field_types ) {
69
+ $this->legacy_field_types = WPCF_Fields::getFieldsTypes();
70
+ }
71
+ return $this->legacy_field_types;
72
+ }
73
+
74
+
75
+ /**
76
+ * Load a field type definition.
77
+ *
78
+ * @param string $field_type_slug Slug of the field type. If the function fails to find the field type and the slug
79
+ * starts with a "wpcf-" prefix, it attempts to remove it and search again. This way, passing a field type ID,
80
+ * which usually has this form, is also supported.
81
+ * @return null|Types_Field_Type_Definition Field type definition or null if it can't be loaded.
82
+ */
83
+ public function load_field_type_definition( $field_type_slug ) {
84
+
85
+ if( !is_string( $field_type_slug ) ) {
86
+ return null;
87
+ }
88
+
89
+ // Check if we can use cached version.
90
+ if( !array_key_exists( $field_type_slug, $this->field_type_definitions ) ) {
91
+
92
+ // now it gets hacky
93
+ $field_types = $this->get_legacy_field_types();
94
+ if( !array_key_exists( $field_type_slug, $field_types ) ) {
95
+ // Field slug not recognized. Maybe we got a field identifier instead. Check if we can remove
96
+ // the wpcf- prefix and try again.
97
+ $prefix = 'wpcf-';
98
+ if( substr( $field_type_slug, 0, strlen( $prefix ) ) == $prefix ) {
99
+ $field_type_slug = substr( $field_type_slug, strlen( $prefix ) );
100
+ if( !array_key_exists( $field_type_slug, $field_types ) ) {
101
+ // Removing prefix didn't help
102
+ return null;
103
+ }
104
+ // Check the cache again (now with correct slug).
105
+ if( array_key_exists( $field_type_slug, $this->field_type_definitions ) ) {
106
+ return $this->field_type_definitions[ $field_type_slug ];
107
+ }
108
+ } else {
109
+ // There was no prefix to remove.
110
+ return null;
111
+ }
112
+ }
113
+
114
+ // Not using getFieldTypeData() directly to avoid unnecessary getFieldsTypes() and filter applying.
115
+ $field_type_configuration_path = $field_types[ $field_type_slug ];
116
+ $field_type_configuration = WPCF_Fields::getFieldTypeConfig( $field_type_configuration_path );
117
+
118
+ $field_type_id = wpcf_getarr( $field_type_configuration, 'id', null );
119
+ if( null == $field_type_id ) {
120
+ return null;
121
+ }
122
+
123
+ try {
124
+ $field_type_definition = $this->create_definition_instance( $field_type_slug, $field_type_configuration );
125
+ } catch( Exception $e ) {
126
+ return null;
127
+ }
128
+
129
+ // Save new instance to cache.
130
+ $this->field_type_definitions[ $field_type_slug ] = $field_type_definition;
131
+ }
132
+
133
+ // Use cache.
134
+ return $this->field_type_definitions[ $field_type_slug ];
135
+ }
136
+
137
+
138
+ /**
139
+ * Create the proper instance of a type definition class, based on the type slug.
140
+ *
141
+ * @param string $field_type_slug
142
+ * @param array $field_type_configuration Legacy configuration array
143
+ * @return Types_Field_Type_Definition
144
+ * @since 2.0
145
+ * @throws Exception
146
+ */
147
+ private function create_definition_instance( $field_type_slug, $field_type_configuration ) {
148
+ switch( $field_type_slug ) {
149
+ case self::CHECKBOX:
150
+ return new Types_Field_Type_Definition_Checkbox( $field_type_configuration );
151
+
152
+ case self::NUMERIC:
153
+ return new Types_Field_Type_Definition_Numeric( $field_type_configuration );
154
+
155
+ case self::CHECKBOXES:
156
+ case self::RADIO:
157
+ case self::SELECT:
158
+ case self::WYSIWYG:
159
+ return new Types_Field_Type_Definition_Singular( $field_type_slug, $field_type_configuration );
160
+
161
+ default:
162
+ return new Types_Field_Type_Definition( $field_type_slug, $field_type_configuration );
163
+ }
164
+ }
165
+
166
+
167
+ /**
168
+ * Get field type definitions from an array of slugs.
169
+ *
170
+ * If a definition cannot be loaded for a given slug, the slug is skipped without reporting an error in any other way.
171
+ *
172
+ * @param string[] $field_type_slugs
173
+ * @return Types_Field_Type_Definition[]
174
+ * @since 2.0
175
+ */
176
+ public function load_multiple_definitions( $field_type_slugs ) {
177
+ $results = array();
178
+ $field_type_slugs = wpcf_ensarr( $field_type_slugs );
179
+ foreach( $field_type_slugs as $field_type_slug ) {
180
+ $type_definition = $this->load_field_type_definition( $field_type_slug );
181
+ if( null != $type_definition ) {
182
+ $results[ $field_type_slug ] = $type_definition;
183
+ }
184
+ }
185
+ return $results;
186
+ }
187
+
188
+
189
+ /**
190
+ * Get all field type definitions available.
191
+ *
192
+ * @return Types_Field_Type_Definition[]
193
+ * @since 2.0
194
+ */
195
+ public function get_all_definitions() {
196
+ $legacy_types = $this->get_legacy_field_types();
197
+ $definitions = array();
198
+ foreach( $legacy_types as $type_slug => $ignored ) {
199
+ $defintion = $this->load_field_type_definition( $type_slug );
200
+ if( null != $defintion ) {
201
+ $definitions[] = $defintion;
202
+ }
203
+ }
204
+ return $definitions;
205
+ }
206
+
207
+
208
+ /**
209
+ * Get a map of all field definition slugs to their properties.
210
+ *
211
+ * @return string[]
212
+ * @since 2.0
213
+ */
214
+ public function get_field_type_definitions() {
215
+ $field_types = $this->get_all_definitions();
216
+ $field_type_names = array();
217
+ foreach( $field_types as $field_type ) {
218
+ $field_type_names[ $field_type->get_slug() ] = array(
219
+ 'slug' => $field_type->get_slug(),
220
+ 'displayName' => $field_type->get_display_name(),
221
+ 'canBeRepetitive' => $field_type->can_be_repetitive(),
222
+ 'iconClasses' => $field_type->get_icon_classes()
223
+ );
224
+ }
225
+
226
+ return $field_type_names;
227
+ }
228
+
229
+
230
+ /**
231
+ * Static shortcut to load_field_type_definition.
232
+ *
233
+ * @param string $field_type_slug
234
+ * @return null|Types_Field_Type_Definition
235
+ */
236
+ public static function load( $field_type_slug ) {
237
+ // we cannot use self::get_instance here, because of low PHP requirements and missing get_called_class function
238
+ // we have a fallback class for get_called_class but that scans files by debug_backtrace and return 'self'
239
+ // instead of Types_Field_Type_Definition_Factory like the original get_called_class() function does
240
+ // ends in an error because of parents (abstract) $var = new self();
241
+ return Types_Field_Type_Definition_Factory::get_instance()->load_field_type_definition( $field_type_slug );
242
+ }
243
+ }
application/models/helper/condition.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ abstract class Types_Helper_Condition {
5
+
6
+ protected $condition;
7
+ public static $post_type;
8
+
9
+ public function set_condition( $value ) {
10
+ $this->condition = $value;
11
+ }
12
+
13
+ public function valid() {}
14
+
15
+ public static function set_post_type( $posttype = false ) {
16
+ if( ! $posttype ) {
17
+ global $typenow;
18
+
19
+ $posttype = isset( $typenow ) && ! empty( $typenow ) ? $typenow : false;
20
+ }
21
+
22
+ if( $posttype )
23
+ self::$post_type = get_post_type_object( $posttype );
24
+ }
25
+
26
+ public static function get_post_type() {
27
+ if( self::$post_type === null )
28
+ self::set_post_type();
29
+
30
+ return self::$post_type;
31
+ }
32
+ }
application/models/helper/condition/archive/exists.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Archive_Exists extends Types_Helper_Condition_Template {
5
+
6
+ public function __construct() {
7
+ $cpt = Types_Helper_Condition::get_post_type();
8
+
9
+ $this->templates = array(
10
+ 'archive-' . $cpt->name . '.php',
11
+ 'archive.php'
12
+ );
13
+ }
14
+
15
+ protected function has_archive() {
16
+ $cpt = Types_Helper_Condition::get_post_type();
17
+ if( ! get_post_type_archive_link( $cpt->name ) )
18
+ return false;
19
+
20
+ return true;
21
+ }
22
+
23
+
24
+ public function valid() {
25
+ if( ! $this->has_archive() )
26
+ return false;
27
+
28
+ return parent::valid();
29
+ }
30
+
31
+ }
application/models/helper/condition/archive/has_fields.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Condition_Archive_Has_Fields extends Types_Helper_Condition_Archive_No_Fields {
4
+
5
+ public function valid() {
6
+ if( ! $this->has_archive() )
7
+ return false;
8
+
9
+ $template = $this->find_template();
10
+
11
+ // no template available
12
+ if( empty( $template ) )
13
+ return false;
14
+
15
+ // opposite of parents "No Fields".
16
+ return ! parent::valid();
17
+ }
18
+ }
application/models/helper/condition/archive/missing.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Archive_Missing extends Types_Helper_Condition_Archive_Exists {
5
+ // this is valid if no template is found
6
+ public function valid() {
7
+ if( ! $this->has_archive() )
8
+ return false;
9
+
10
+ // opposite of parents "Archive Exists"
11
+ return ! parent::valid();
12
+ }
13
+ }
application/models/helper/condition/archive/no_fields.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Types_Helper_Condition_Archive_No_Fields extends Types_Helper_Condition_Archive_Missing {
3
+
4
+ public function valid() {
5
+ if( ! $this->has_archive() )
6
+ return false;
7
+
8
+ $template = $this->find_template();
9
+
10
+ // no template available
11
+ if( empty( $template ) )
12
+ return false;
13
+
14
+ // do not check if there are no fields assigned to current post
15
+ // this check is not placed very well as it's out of class scope
16
+ $check_fields_assigned = new Types_Helper_Condition_Type_Fields_Assigned();
17
+ if( ! $check_fields_assigned->valid() )
18
+ return false;
19
+
20
+ $file = new Toolset_Filesystem_File();
21
+
22
+ // abort if file can't be found
23
+ if( ! $file->open( $template ) )
24
+ return false;
25
+
26
+ // check for fields, abort if there results in true
27
+ if( $file->search( 'types_render_field' ) )
28
+ return false;
29
+
30
+ return true;
31
+ }
32
+ }
application/models/helper/condition/archive/no_support.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Archive_No_Support extends Types_Helper_Condition_Archive_Support {
5
+
6
+ public function __construct() {}
7
+
8
+ public function valid() {
9
+ return ! parent::valid();
10
+ }
11
+
12
+ }
application/models/helper/condition/archive/support.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Archive_Support extends Types_Helper_Condition {
5
+
6
+ public function __construct() {}
7
+
8
+ public function valid() {
9
+ $cpt = Types_Helper_Condition::get_post_type();
10
+
11
+ if ( ! $cpt->has_archive && $cpt->name != 'post' && $cpt->name != 'page' )
12
+ return false;
13
+
14
+ return true;
15
+ }
16
+
17
+ }
application/models/helper/condition/cred/active.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Cred_Active extends Types_Helper_Condition {
5
+
6
+ public function valid() {
7
+ if( defined( 'CRED_FE_VERSION' ) )
8
+ return true;
9
+
10
+ return false;
11
+ }
12
+
13
+ }
application/models/helper/condition/cred/forms_exist.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Cred_Forms_Exist extends Types_Helper_Condition_Cred_Active {
5
+
6
+ public static $forms_per_post_type;
7
+
8
+ public function valid() {
9
+ // false if cred not active
10
+ if( ! parent::valid() )
11
+ return false;
12
+
13
+ global $wpdb;
14
+
15
+ $cpt = Types_Helper_Condition::get_post_type();
16
+
17
+ if( isset( self::$forms_per_post_type[$cpt->name] ) )
18
+ return true;
19
+
20
+ // @todo check with Francesco if CRED has a get_forms_of_post_type() function
21
+ $forms_settings = $wpdb->get_results( "SELECT meta_value, post_id FROM $wpdb->postmeta WHERE meta_key = '_cred_form_settings'" );
22
+
23
+ foreach( $forms_settings as $setting ) {
24
+ $post_type = false;
25
+ $setting->meta_value = unserialize( $setting->meta_value );
26
+
27
+ // post type
28
+ if( isset( $setting->meta_value->post['post_type'] ) )
29
+ $post_type = $setting->meta_value->post['post_type'];
30
+
31
+ // different structure created by CredFormCreator
32
+ // (surely old style, but compatible with new and restructured after first form save)
33
+ if( ! $post_type && is_array( $setting->meta_value ) && isset( $setting->meta_value['post_type'] ) )
34
+ $post_type = $setting->meta_value['post_type'];
35
+
36
+ // another structure...
37
+ if( ! $post_type && is_object( $setting->meta_value ) && isset( $setting->meta_value->post_type ) )
38
+ $post_type = $setting->meta_value->post_type;
39
+
40
+ if( $post_type && $cpt->name == $post_type ) {
41
+ $title = get_the_title( $setting->post_id );
42
+
43
+ self::$forms_per_post_type[$cpt->name][] = array(
44
+ 'id' => $setting->post_id,
45
+ 'name' => $title
46
+ );
47
+ }
48
+ }
49
+
50
+ if( isset( self::$forms_per_post_type[$cpt->name] ) )
51
+ return true;
52
+
53
+ return false;
54
+ }
55
+
56
+ public static function get_forms_of_post_type() {
57
+ $cpt = Types_Helper_Condition::get_post_type();
58
+
59
+ if( isset( self::$forms_per_post_type[$cpt->name] ) )
60
+ return self::$forms_per_post_type[$cpt->name];
61
+
62
+ return false;
63
+ }
64
+ }
application/models/helper/condition/cred/forms_missing.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Cred_Forms_Missing extends Types_Helper_Condition_Cred_Forms_Exist {
5
+
6
+ public function valid() {
7
+ // if views not active
8
+ if( ! defined( 'CRED_FE_VERSION' ) )
9
+ return false;
10
+
11
+ // opposite of parent "forms exists"
12
+ return ! parent::valid();
13
+ }
14
+
15
+ }
application/models/helper/condition/cred/missing.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Cred_Missing extends Types_Helper_Condition_Cred_Active {
5
+
6
+ public function valid() {
7
+ return ! parent::valid();
8
+ }
9
+
10
+ }
application/models/helper/condition/layouts/active.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Layouts_Active extends Types_Helper_Condition {
5
+
6
+ public function valid() {
7
+ if( defined( 'WPDDL_DEVELOPMENT' ) )
8
+ return true;
9
+
10
+ return false;
11
+ }
12
+
13
+ }
application/models/helper/condition/layouts/archive_exists.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Condition_Layouts_Archive_Exists extends Types_Helper_Condition_Template {
4
+
5
+ private static $layout_id;
6
+ private static $layout_name;
7
+
8
+ public function valid() {
9
+ if( ! defined( 'WPDDL_GENERAL_OPTIONS' ) )
10
+ return false;
11
+
12
+ $cpt = Types_Helper_Condition::get_post_type();
13
+
14
+ $layouts = get_option( WPDDL_GENERAL_OPTIONS, array() );
15
+
16
+ if( ! array_key_exists( 'layouts_cpt_' . $cpt->name, $layouts ) )
17
+ return false;
18
+
19
+ self::$layout_id = $layouts['layouts_cpt_' . $cpt->name];
20
+
21
+ return true;
22
+ }
23
+
24
+ public static function get_layout_id() {
25
+ if( self::$layout_id === null ) {
26
+ $self = new Types_Helper_Condition_Layouts_Archive_Exists();
27
+ $self->valid();
28
+ }
29
+
30
+ return self::$layout_id;
31
+ }
32
+
33
+ public static function get_layout_name() {
34
+ if( self::$layout_name === null )
35
+ self::$layout_name = get_the_title( self::get_layout_id() );
36
+
37
+ return self::$layout_name;
38
+ }
39
+ }
application/models/helper/condition/layouts/archive_missing.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Condition_Layouts_Archive_Missing extends Types_Helper_Condition_Layouts_Archive_Exists {
4
+
5
+ public function valid() {
6
+ if( ! defined( 'WPDDL_GENERAL_OPTIONS' ) )
7
+ return false;
8
+
9
+ // opposite of parents "exists"
10
+ return ! parent::valid();
11
+ }
12
+
13
+ }
application/models/helper/condition/layouts/compatible.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Layouts_Compatible extends Types_Helper_Condition_Template {
5
+
6
+ public function __construct() {
7
+ $cpt = Types_Helper_Condition::get_post_type();
8
+
9
+ $this->templates = array(
10
+ 'single-' . $cpt->name . '.php',
11
+ 'archive-' . $cpt->name . '.php',
12
+ 'single.php',
13
+ 'archive.php',
14
+ 'index.php'
15
+ );
16
+ }
17
+
18
+ public function valid() {
19
+ // theme + theme integration running
20
+ if( defined( 'LAYOUTS_INTEGRATION_THEME_NAME' ) )
21
+ return true;
22
+
23
+ $filesystem = new Toolset_Filesystem_File();
24
+ foreach( $this->templates as $name => $file ) {
25
+ // file exists
26
+ if( $filesystem->open( get_stylesheet_directory() . '/' . $file ) ) {
27
+ // supports layouts
28
+ if( $filesystem->search( 'the_ddlayout') )
29
+ return true;
30
+
31
+ // if for example single.php exists and it does not support Layouts we don't need to look at index.php
32
+ return false;
33
+ }
34
+ }
35
+
36
+ // no file exists
37
+ return false;
38
+ }
39
+
40
+ }
application/models/helper/condition/layouts/missing.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Layouts_Missing extends Types_Helper_Condition_Layouts_Active {
5
+
6
+ public function valid() {
7
+ return ! parent::valid();
8
+ }
9
+
10
+ }
application/models/helper/condition/layouts/template_exists.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Condition_Layouts_Template_Exists extends Types_Helper_Condition_Template {
4
+
5
+ public static $layout_id;
6
+ public static $layout_name;
7
+
8
+ public function valid() {
9
+ if( self::$layout_id !== null && self::$layout_id !== false )
10
+ return true;
11
+
12
+ $post = wpcf_admin_get_edited_post();
13
+ if( ! empty( $post ) )
14
+ return $this->valid_per_post( $post );
15
+
16
+ return $this->valid_per_post_type();
17
+
18
+ }
19
+
20
+ // needed for single post edit screen
21
+ private function valid_per_post( $post ) {
22
+ if( ! class_exists( 'WPDD_Utils' ) || ! method_exists( 'WPDD_Utils', 'page_has_layout' ) || ! is_object( $post ) )
23
+ return false;
24
+
25
+ if( self::$layout_id = WPDD_Utils::page_has_layout( $post->ID ) ) {
26
+ self::$layout_id = WPDD_Utils::get_layout_id_from_post_name( self::$layout_id );
27
+ return true;
28
+ }
29
+
30
+ return false;
31
+ }
32
+
33
+ // needed for cpt / fields group edit screen
34
+ private function valid_per_post_type() {
35
+ $cpt = Types_Helper_Condition::get_post_type();
36
+
37
+ global $wpdb;
38
+
39
+ $layouts_per_post_type = $wpdb->get_results( "SELECT meta_value, post_id FROM $wpdb->postmeta WHERE meta_key = '_ddl_post_types_was_batched'" );
40
+
41
+ foreach( $layouts_per_post_type as $setting ) {
42
+
43
+ $setting->meta_value = unserialize( $setting->meta_value );
44
+
45
+ if( is_array( $setting->meta_value )
46
+ && in_array( $cpt->name, $setting->meta_value ) ) {
47
+
48
+ if( get_post_status( $setting->post_id) == 'trash' )
49
+ continue;
50
+
51
+ $title = get_the_title( $setting->post_id );
52
+ self::$layout_id = $setting->post_id;
53
+ self::$layout_name = $title;
54
+ return true;
55
+ }
56
+ }
57
+
58
+ return false;
59
+ }
60
+
61
+ public static function get_layout_id() {
62
+ if( self::$layout_id === null ) {
63
+ $self = new Types_Helper_Condition_Layouts_Template_Exists();
64
+ $self->valid();
65
+ }
66
+
67
+ return self::$layout_id;
68
+ }
69
+
70
+ public static function get_layout_name() {
71
+ if( self::$layout_name === null )
72
+ self::$layout_name = get_the_title( self::get_layout_id() );
73
+
74
+ return self::$layout_name;
75
+ }
76
+ }
application/models/helper/condition/layouts/template_missing.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Condition_Layouts_Template_Missing extends Types_Helper_Condition_Layouts_Template_Exists {
4
+
5
+ public function valid() {
6
+ if( parent::$layout_id !== null && parent::$layout_id !== false )
7
+ return false;
8
+
9
+ return ! parent::valid();
10
+ }
11
+
12
+ }
application/models/helper/condition/screen.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Screen extends Types_Helper_Condition {
5
+
6
+ // check if current screen is screen
7
+ public function valid() {
8
+ global $pagenow;
9
+
10
+ if( empty( $pagenow ) )
11
+ return false;
12
+
13
+ if( $this->condition == $pagenow )
14
+ return true;
15
+
16
+ return false;
17
+ }
18
+ }
application/models/helper/condition/single/exists.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Single_Exists extends Types_Helper_Condition_Template {
5
+
6
+ public function __construct() {
7
+ $cpt = Types_Helper_Condition::get_post_type();
8
+
9
+ $this->templates = array(
10
+ 'single-' . $cpt->name . '.php',
11
+ 'single.php'
12
+ );
13
+ }
14
+ }
application/models/helper/condition/single/has_fields.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Condition_Single_Has_Fields extends Types_Helper_Condition_Single_No_Fields {
4
+
5
+ public function valid() {
6
+
7
+ $template = $this->find_template();
8
+
9
+ // no template available
10
+ if( empty( $template ) )
11
+ return false;
12
+
13
+ // opposite of parents "No Fields".
14
+ return ! parent::valid();
15
+ }
16
+ }
application/models/helper/condition/single/missing.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Single_Missing extends Types_Helper_Condition_Single_Exists {
5
+ // this is valid if no template is found
6
+ public function valid() {
7
+ // opposite of parents "Single Exists"
8
+ return ! parent::valid();
9
+ }
10
+ }
application/models/helper/condition/single/no_fields.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Condition_Single_No_Fields extends Types_Helper_Condition_Single_Missing {
4
+
5
+ public function valid() {
6
+ $template = $this->find_template();
7
+
8
+ // no template available
9
+ if( empty( $template ) )
10
+ return false;
11
+
12
+ // do not check if there are no fields assigned to current post
13
+ // this check is not placed very well as it's out of class scope
14
+ $check_fields_assigned = new Types_Helper_Condition_Type_Fields_Assigned();
15
+ if( ! $check_fields_assigned->valid() )
16
+ return false;
17
+
18
+ $file = new Toolset_Filesystem_File();
19
+
20
+ // abort if file can't be found
21
+ if( ! $file->open( $template ) )
22
+ return false;
23
+
24
+ // check for fields, abort if there results in true
25
+ if( $file->search( 'types_render_field' ) )
26
+ return false;
27
+
28
+ return true;
29
+ }
30
+ }
application/models/helper/condition/template.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ abstract class Types_Helper_Condition_Template extends Types_Helper_Condition {
5
+
6
+ protected $templates;
7
+
8
+ public function find_template() {
9
+ $template = locate_template( $this->templates ) ;
10
+
11
+ return $template;
12
+ }
13
+
14
+ // check if current screen is screen
15
+ public function valid() {
16
+ $template = $this->find_template();
17
+
18
+ if( empty( $template ) )
19
+ return false;
20
+
21
+ return true;
22
+ }
23
+ }
application/models/helper/condition/type/fields_assigned.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Condition_Type_Fields_Assigned extends Types_Helper_Condition {
4
+
5
+ public function valid() {
6
+ $post_type = Types_Helper_Condition::get_post_type();
7
+
8
+ $query = new WP_Query( 'post_type=' . $post_type->name . '&posts_per_page=1' );
9
+ if( $query->have_posts() ) {
10
+
11
+ if( !function_exists( 'wpcf_admin_post_get_post_groups_fields') )
12
+ include_once( WPCF_EMBEDDED_ABSPATH . '/includes/fields-post.php' );
13
+
14
+ $fields = wpcf_admin_post_get_post_groups_fields( $query->posts[0] );
15
+ }
16
+
17
+ if(
18
+ isset( $fields )
19
+ && is_array( $fields )
20
+ && !empty( $fields )
21
+ ) return true;
22
+
23
+ return false;
24
+ }
25
+ }
application/models/helper/condition/views/active.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Views_Active extends Types_Helper_Condition {
5
+
6
+ public function valid() {
7
+ if( defined( 'WPV_VERSION' ) )
8
+ return true;
9
+
10
+ return false;
11
+ }
12
+
13
+ }
application/models/helper/condition/views/archive_exists.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Views_Archive_Exists extends Types_Helper_Condition_Views_Views_Exist {
5
+
6
+ private static $template_id;
7
+ private static $template_name;
8
+
9
+ public function valid() {
10
+ if( self::$template_id !== null && self::$template_id !== false )
11
+ return true;
12
+
13
+ // if views not active
14
+ if( ! defined( 'WPV_VERSION' )
15
+ || !function_exists( 'wpv_has_wordpress_archive') )
16
+ return false;
17
+
18
+ $cpt = Types_Helper_Condition::get_post_type();
19
+
20
+ $archive = $cpt->name == 'post'
21
+ ? wpv_has_wordpress_archive()
22
+ : wpv_has_wordpress_archive( 'post', $cpt->name );
23
+
24
+ if( ! $archive && $archive === 0 )
25
+ return false;
26
+
27
+ self::$template_id = $archive;
28
+
29
+ return true;
30
+ }
31
+
32
+ public static function get_template_id() {
33
+ if( self::$template_id === null ) {
34
+ $self = new Types_Helper_Condition_Views_Template_Exists();
35
+ $self->valid();
36
+ }
37
+
38
+ return self::$template_id;
39
+ }
40
+
41
+ public static function get_template_name() {
42
+ if( self::$template_name === null )
43
+ self::$template_name = get_the_title( self::get_template_id() );
44
+
45
+ return self::$template_name;
46
+ }
47
+
48
+ }
application/models/helper/condition/views/archive_missing.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Views_Archive_Missing extends Types_Helper_Condition_Views_Archive_Exists {
5
+
6
+ public function valid() {
7
+ // if views not active
8
+ if( ! defined( 'WPV_VERSION' ) )
9
+ return false;
10
+
11
+ // opposite of parent "Views Archive exists"
12
+ return ! parent::valid();
13
+ }
14
+
15
+ }
application/models/helper/condition/views/missing.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Views_Missing extends Types_Helper_Condition_Views_Active {
5
+
6
+ public function valid() {
7
+ return ! parent::valid();
8
+ }
9
+
10
+ }
application/models/helper/condition/views/template_exists.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Views_Template_Exists extends Types_Helper_Condition_Views_Views_Exist {
5
+
6
+ private static $template_id;
7
+ private static $template_name;
8
+
9
+ public function valid() {
10
+ if( self::$template_id !== null && self::$template_id !== false )
11
+ return true;
12
+
13
+ // if views not active
14
+ if( ! defined( 'WPV_VERSION' ) )
15
+ return false;
16
+
17
+ if( isset( $_GET['post'] ) )
18
+ return $this->valid_per_post();
19
+
20
+ return $this->valid_per_post_type();
21
+ }
22
+
23
+ // needed for single post edit screen
24
+ private function valid_per_post( ) {
25
+ if( function_exists( 'has_wpv_content_template' ) ) {
26
+ $template = has_wpv_content_template( $_GET['post'] );
27
+
28
+ if( ! $template
29
+ || $template === 0
30
+ || ! get_post_type( $template )
31
+ )
32
+ return false;
33
+
34
+ self::$template_id = $template;
35
+ }
36
+
37
+ return true;
38
+ }
39
+
40
+ // needed for cpt / fields group edit screen
41
+ private function valid_per_post_type() {
42
+ $cpt = Types_Helper_Condition::get_post_type();
43
+
44
+ $wpv_options = get_option( 'wpv_options', array() );
45
+
46
+ if( empty( $wpv_options )
47
+ || ! isset( $wpv_options['views_template_for_'.$cpt->name] )
48
+ || ! get_post_type( $wpv_options['views_template_for_'.$cpt->name] )
49
+ )
50
+ return false;
51
+
52
+ $title = get_the_title( $wpv_options['views_template_for_'.$cpt->name] );
53
+ self::$template_id = $wpv_options['views_template_for_'.$cpt->name];
54
+ self::$template_name = $title;
55
+ return true;
56
+ }
57
+
58
+ public static function get_template_id() {
59
+ if( self::$template_id === null ) {
60
+ $self = new Types_Helper_Condition_Views_Template_Exists();
61
+ $self->valid();
62
+ }
63
+
64
+ return self::$template_id;
65
+ }
66
+
67
+ public static function get_template_name() {
68
+ if( self::$template_name === null )
69
+ self::$template_name = get_the_title( self::get_template_id() );
70
+
71
+ return self::$template_name;
72
+ }
73
+
74
+ }
application/models/helper/condition/views/template_missing.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Views_Template_Missing extends Types_Helper_Condition_Views_Template_Exists {
5
+
6
+ public function valid() {
7
+ // if views not active
8
+ if( ! defined( 'WPV_VERSION' ) )
9
+ return false;
10
+
11
+ // opposite of parent "Views Template exists"
12
+ return ! parent::valid();
13
+ }
14
+
15
+ }
application/models/helper/condition/views/views_exist.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Views_Views_Exist extends Types_Helper_Condition_Views_Active {
5
+
6
+ public static $views_per_post_type;
7
+
8
+ public function valid() {
9
+ // false if views not active
10
+ if( ! parent::valid() )
11
+ return false;
12
+
13
+ global $wpdb;
14
+
15
+ $cpt = Types_Helper_Condition::get_post_type();
16
+
17
+ if( isset( self::$views_per_post_type[$cpt->name] ) )
18
+ return true;
19
+
20
+ // @todo check with Juan if views has a get_views_of_post_type() function
21
+ $views_settings = $wpdb->get_results( "SELECT meta_value, post_id FROM $wpdb->postmeta WHERE meta_key = '_wpv_settings'" );
22
+
23
+ foreach( $views_settings as $setting ) {
24
+
25
+ $setting->meta_value = unserialize( $setting->meta_value );
26
+ if( isset( $setting->meta_value['post_type'] )
27
+ && in_array( $cpt->name, $setting->meta_value['post_type'] ) ) {
28
+
29
+ if( get_post_status( $setting->post_id) == 'trash' )
30
+ continue;
31
+
32
+ $title = get_the_title( $setting->post_id );
33
+ self::$views_per_post_type[$cpt->name][] = array(
34
+ 'id' => $setting->post_id,
35
+ 'name' => $title
36
+ );
37
+ }
38
+ }
39
+
40
+ if( isset( self::$views_per_post_type[$cpt->name] ) )
41
+ return true;
42
+
43
+ return false;
44
+ }
45
+
46
+ public static function get_views_of_post_type() {
47
+ $cpt = Types_Helper_Condition::get_post_type();
48
+
49
+ if( isset( self::$views_per_post_type[$cpt->name] ) )
50
+ return self::$views_per_post_type[$cpt->name];
51
+
52
+ return false;
53
+ }
54
+ }
application/models/helper/condition/views/views_missing.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Condition_Views_Views_Missing extends Types_Helper_Condition_Views_Views_Exist {
5
+
6
+ public function valid() {
7
+ // if views not active
8
+ if( ! defined( 'WPV_VERSION' ) )
9
+ return false;
10
+
11
+ // opposite of parent "Views exists"
12
+ return ! parent::valid();
13
+ }
14
+
15
+ }
application/models/helper/create/content_template.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Create_Content_Template {
4
+
5
+ public function for_post( $type, $name = false ) {
6
+
7
+ if( ! $this->needed_components_loaded() )
8
+ return false;
9
+
10
+ global $WPV_settings;
11
+ $option = sanitize_text_field( sprintf( 'views_template_for_%s', $type ) );
12
+
13
+ // already has an content template
14
+ if( isset( $WPV_settings[$option] ) && is_numeric( $WPV_settings[$option] ) && $WPV_settings[$option] > 0 )
15
+ return $WPV_settings[$option];
16
+
17
+ if( ! $name ) {
18
+ $type_object = get_post_type_object( $type );
19
+ $name = sprintf( __( 'Template for %s', 'types' ), $type_object->labels->name );
20
+ }
21
+
22
+ $name = $this->validate_name( $name );
23
+
24
+ if( ! $name )
25
+ return false;
26
+
27
+ $ct = WPV_Content_Template::create( $name );
28
+ $ct_post = get_post( $ct->id );
29
+
30
+ if( $ct_post === null )
31
+ return false;
32
+
33
+ $WPV_settings[$option] = $ct_post->ID;
34
+ $WPV_settings->save();
35
+
36
+ $posts = get_posts( 'post_type=' . $type . '&post_status=any&posts_per_page=-1&fields=ids' );
37
+
38
+ foreach( $posts as $id ) {
39
+ $ct = get_post_meta( $id, '_views_template', true );
40
+
41
+ if( empty( $ct ) )
42
+ update_post_meta( $id, '_views_template', $ct_post->ID );
43
+
44
+ }
45
+
46
+ return $ct_post->ID;
47
+ }
48
+
49
+ private function needed_components_loaded( ) {
50
+ global $WPV_settings;
51
+ if(
52
+ ! is_object( $WPV_settings )
53
+ || ! class_exists( 'WPV_Content_Template' )
54
+ || ! method_exists( 'WPV_Content_Template', 'create' )
55
+ ) return false;
56
+
57
+ return true;
58
+ }
59
+
60
+ private function validate_name( $name, $id = 1 ) {
61
+ $name_exists = get_page_by_title( html_entity_decode( $name ), OBJECT, 'view-template' );
62
+
63
+ if( $name_exists ) {
64
+ $name = $id > 1 ? rtrim( rtrim( $name, $id - 1 ) ) : $name;
65
+ return $this->validate_name( $name . ' ' . $id, $id + 1 );
66
+ }
67
+
68
+ return $name;
69
+ }
70
+
71
+ }
application/models/helper/create/form.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Create_Form {
4
+
5
+ public function for_post( $type, $name = false ) {
6
+ if( ! defined( 'CRED_CLASSES_PATH' ) )
7
+ return false;
8
+
9
+ if( ! file_exists( CRED_CLASSES_PATH . '/CredFormCreator.php' ) )
10
+ return false;
11
+
12
+ require_once( CRED_CLASSES_PATH . '/CredFormCreator.php' );
13
+
14
+ if( ! class_exists( 'CredFormCreator' )
15
+ || ! method_exists( 'CredFormCreator', 'cred_create_form' ) )
16
+ return false;
17
+
18
+ if( ! $name ) {
19
+ $type_object = get_post_type_object( $type );
20
+ $name = sprintf( __( 'Form for %s', 'types' ), $type_object->labels->name );
21
+ }
22
+
23
+ $name = $this->validate_name( $name );
24
+
25
+ $id = CredFormCreator::cred_create_form( $name, 'new', $type );
26
+ return $id;
27
+ }
28
+
29
+ private function validate_name( $name, $id = 1 ) {
30
+ $name_exists = get_page_by_title( html_entity_decode( $name ), OBJECT, CRED_FORMS_CUSTOM_POST_NAME );
31
+
32
+ if( $name_exists !== null ) {
33
+ $name = $id > 1 ? rtrim( rtrim( $name, $id - 1 ) ) : $name;
34
+ return $this->validate_name( $name . ' ' . $id, $id + 1 );
35
+ }
36
+
37
+ return $name;
38
+ }
39
+
40
+ }
application/models/helper/create/layout.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Create_Layout {
4
+
5
+ public function for_post( $type, $name = false ) {
6
+
7
+ if( ! $name ) {
8
+ $type_object = get_post_type_object( $type );
9
+ $name = sprintf( __( 'Template for %s', 'types' ), $type_object->labels->name );
10
+ }
11
+
12
+ $name = $this->validate_name( $name );
13
+
14
+ if( ! $name )
15
+ return false;
16
+
17
+ $layout_id = $this->create_layout( $name );
18
+
19
+ if( ! $layout_id )
20
+ return false;
21
+
22
+ global $wpddlayout;
23
+ $posts = get_posts( 'post_type=' . $type . '&post_status=any&posts_per_page=-1&fields=ids' );
24
+
25
+ // store layout assignments before assign new
26
+ $post_has_layout = array();
27
+ foreach( $posts as $id ) {
28
+ $layout = get_post_meta( $id, WPDDL_LAYOUTS_META_KEY, true );
29
+ if( !empty( $layout ) ) {
30
+ $post_has_layout[] = array(
31
+ 'id' => $id,
32
+ 'layout-slug' => $layout
33
+ );
34
+ }
35
+ }
36
+
37
+ // assign the new layout to all post types
38
+ $wpddlayout->post_types_manager->handle_set_option_and_bulk_at_once( $layout_id, array( $type ), array( $type ) );
39
+
40
+ // restore previously assigned layouts
41
+ if( !empty( $post_has_layout ) ) {
42
+ foreach( $post_has_layout as $post ) {
43
+ update_post_meta( $post['id'], WPDDL_LAYOUTS_META_KEY, $post['layout-slug'] );
44
+ }
45
+ }
46
+
47
+ return $layout_id;
48
+ }
49
+
50
+ private function needed_components_loaded( ) {
51
+ global $wpddlayout;
52
+ if(
53
+ ! is_object( $wpddlayout )
54
+ || ! class_exists( 'WPDD_Layouts' )
55
+ || ! class_exists( 'WPDD_Layouts_Users_Profiles' )
56
+ || ! method_exists( 'WPDD_Layouts', 'create_layout' )
57
+ || ! method_exists( 'WPDD_Layouts', 'save_layout_settings' )
58
+ || ! method_exists( 'WPDD_Layouts_Users_Profiles', 'user_can_create' )
59
+ || ! method_exists( 'WPDD_Layouts_Users_Profiles', 'user_can_assign' )
60
+ || ! method_exists( $wpddlayout, 'get_css_framework' )
61
+ ) return false;
62
+
63
+ return true;
64
+ }
65
+
66
+ private function create_layout( $name ) {
67
+ // @todo check with Ric to get a more handy class to create a new layout.
68
+ // currently there is only (which I found)
69
+ // - create_layout_auto(), which has a redirect
70
+ // - create_layout_callback() for ajax only -> uses die()
71
+ global $wpddlayout;
72
+
73
+ if( ! $this->needed_components_loaded() )
74
+ return false;
75
+
76
+ // permissions
77
+ if( ! current_user_can( 'manage_options' ) && WPDD_Layouts_Users_Profiles::user_can_create() && WPDD_Layouts_Users_Profiles::user_can_assign() )
78
+ return false;
79
+
80
+ $layout = WPDD_Layouts::create_layout( 12, 'fluid' );
81
+
82
+ // Define layout parameters
83
+ $layout['type'] = 'fluid'; // layout_type
84
+ $layout['cssframework'] = $wpddlayout->get_css_framework();
85
+ $layout['template'] = '';
86
+ $layout['parent'] = '';
87
+ $layout['name'] = $name;
88
+
89
+ $args = array(
90
+ 'post_title' => $name,
91
+ 'post_content' => '',
92
+ 'post_status' => 'publish',
93
+ 'post_type' => WPDDL_LAYOUTS_POST_TYPE
94
+ );
95
+ $layout_id = wp_insert_post( $args );
96
+
97
+ // force layout object to take right ID
98
+ // @see WPDD_Layouts::create_layout_callback() @ wpddl.class.php
99
+ $layout_post = get_post( $layout_id );
100
+ $layout['id'] = $layout_id;
101
+ $layout['slug'] = $layout_post->post_name;
102
+
103
+ // update changes
104
+ WPDD_Layouts::save_layout_settings( $layout_id, $layout );
105
+
106
+ return $layout_id;
107
+ }
108
+
109
+ private function validate_name( $name, $id = 1 ) {
110
+ $name_exists = get_page_by_title( html_entity_decode( $name ), OBJECT, WPDDL_LAYOUTS_POST_TYPE );
111
+
112
+ if( $name_exists ) {
113
+ $name = $id > 1 ? rtrim( rtrim( $name, $id - 1 ) ) : $name;
114
+ return $this->validate_name( $name . ' ' . $id, $id + 1 );
115
+ }
116
+
117
+ return $name;
118
+ }
119
+
120
+ }
application/models/helper/create/view.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Create_View {
4
+
5
+ public function for_post( $type, $name = false ) {
6
+ if( ! class_exists( 'WPV_View' )
7
+ || ! method_exists( 'WPV_View', 'create' ) )
8
+ return false;
9
+
10
+ if( ! $name ) {
11
+ $type_object = get_post_type_object( $type );
12
+ $name = sprintf( __( 'View for %s', 'types' ), $type_object->labels->name );
13
+ }
14
+
15
+ $name = $this->validate_name( $name );
16
+
17
+ $args = array(
18
+ 'view_settings' => array(
19
+ 'view-query-mode' => 'normal',
20
+ 'view_purpose' => 'all',
21
+ 'post_type' => array( $type )
22
+ )
23
+ );
24
+
25
+ $view = WPV_View::create( $name, $args );
26
+ return $view->id;
27
+ }
28
+
29
+ private function validate_name( $name, $id = 1 ) {
30
+ $name_exists = get_page_by_title( html_entity_decode( $name ), OBJECT, 'view' );
31
+ if( $name_exists !== null ) {
32
+ $name = $id > 1 ? rtrim( rtrim( $name, $id - 1 ) ) : $name;
33
+ return $this->validate_name( $name . ' ' . $id, $id + 1 );
34
+ }
35
+
36
+ return $name;
37
+ }
38
+
39
+ }
application/models/helper/create/wordpress_archive.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Types_Helper_Create_Wordpress_Archive {
4
+
5
+ public function for_post( $type, $name = false ) {
6
+
7
+ if( ! $this->needed_components_loaded() )
8
+ return false;
9
+
10
+ global $WPV_settings;
11
+ $option = sanitize_text_field( sprintf( 'view_cpt_%s', $type ) );
12
+
13
+ // already has an archive
14
+ if( isset( $WPV_settings[$option] ) && is_numeric( $WPV_settings[$option] ) && $WPV_settings[$option] > 0 )
15
+ return $WPV_settings[$option];
16
+
17
+ if( ! $name ) {
18
+ $type_object = get_post_type_object( $type );
19
+ $name = sprintf( __( 'Archive for %s', 'types' ), $type_object->labels->name );
20
+ }
21
+
22
+ $name = $this->validate_name( $name );
23
+
24
+ if( ! $name )
25
+ return false;
26
+
27
+ $archive = WPV_WordPress_Archive::create( $name, array() );
28
+ $archive_post = get_post( $archive->id );
29
+
30
+ if( $archive_post === null )
31
+ return false;
32
+
33
+
34
+ $WPV_settings[$option] = $archive_post->ID;
35
+ $WPV_settings->save();
36
+
37
+ return $archive_post->ID;
38
+ }
39
+
40
+ private function needed_components_loaded( ) {
41
+ global $WPV_settings;
42
+ if(
43
+ ! is_object( $WPV_settings )
44
+ || ! class_exists( 'WPV_WordPress_Archive' )
45
+ || ! method_exists( 'WPV_WordPress_Archive', 'create' )
46
+ ) return false;
47
+
48
+ return true;
49
+ }
50
+
51
+ private function validate_name( $name, $id = 1 ) {
52
+ $name_exists = get_page_by_title( html_entity_decode( $name ), OBJECT, 'view-template' );
53
+
54
+ if( $name_exists ) {
55
+ $name = $id > 1 ? rtrim( rtrim( $name, $id - 1 ) ) : $name;
56
+ return $this->validate_name( $name . ' ' . $id, $id + 1 );
57
+ }
58
+
59
+ return $name;
60
+ }
61
+
62
+ }
application/models/helper/output/interface.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ interface Types_Helper_Output_Interface {
5
+ public function set_content( $content );
6
+ public function output();
7
+ }
application/models/helper/output/meta_box.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Output_Meta_Box implements Types_Helper_Output_Interface {
5
+
6
+ private $output;
7
+
8
+ public $id;
9
+ public $title = '';
10
+ public $screen = null;
11
+ public $context = 'normal';
12
+ public $priority = 'high';
13
+ public $css_class = false;
14
+
15
+ public function __construct( $id = false ) {
16
+ if( $id )
17
+ $this->set_id( $id );
18
+ }
19
+
20
+ public function set_id( $id ) {
21
+ $this->id = $id;
22
+ }
23
+
24
+ public function set_title( $string ) {
25
+ $this->title = $string;
26
+ }
27
+
28
+ public function set_css_class( $string ) {
29
+ $this->css_class = $string;
30
+ }
31
+
32
+ public function set_context( $context ) {
33
+ switch( $context ) {
34
+ case 'normal':
35
+ case 'side':
36
+ case 'advanced':
37
+ $this->context = $context;
38
+ break;
39
+ }
40
+ }
41
+
42
+ public function set_content( $content ){
43
+ $this->output = $content;
44
+ }
45
+
46
+ public function meta_box_output() {
47
+ echo $this->output;
48
+ }
49
+
50
+ public function add_css_class( $classes ) {
51
+ $classes[] = $this->css_class;
52
+ return $classes;
53
+ }
54
+
55
+ public function output() {
56
+ add_meta_box(
57
+ $this->id,
58
+ $this->title,
59
+ array( $this, 'meta_box_output' ),
60
+ $this->screen,
61
+ $this->context,
62
+ $this->priority
63
+ );
64
+
65
+ if( $this->css_class ) {
66
+ $screen = get_current_screen();
67
+ add_action( 'postbox_classes_'.$screen->id.'_'. $this->id, array( $this, 'add_css_class' ) );
68
+ }
69
+ }
70
+ }
application/models/helper/placeholder.php ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Placeholder {
5
+
6
+ private static $post_type;
7
+ private static $post_type_template_file;
8
+ private static $post_type_archive_file;
9
+ private static $post_type_create_layout_template;
10
+ private static $post_type_create_layout_archive;
11
+
12
+ private static $archive_link;
13
+ private static $single_link;
14
+
15
+ private static $post_type_edit_layout_template;
16
+ private static $post_type_edit_layout_archive;
17
+
18
+ private static $post_type_edit_views_template;
19
+ private static $post_type_edit_views_archive;
20
+ private static $post_type_create_views_archive;
21
+
22
+ private static $post_type_create_view;
23
+
24
+ public static function set_post_type( $posttype = false ) {
25
+
26
+ if( ! $posttype ) {
27
+ global $typenow;
28
+
29
+ $posttype = isset( $typenow ) && ! empty( $typenow ) ? $typenow : false;
30
+ }
31
+
32
+ if( $posttype )
33
+ self::$post_type = get_post_type_object( $posttype );
34
+ }
35
+
36
+ public static function replace( &$original ) {
37
+ if( self::$post_type == null )
38
+ self::set_post_type();
39
+
40
+ if( is_array( $original ) ) {
41
+ foreach( $original as &$nested ) {
42
+ self::replace( $nested );
43
+ }
44
+ return;
45
+ }
46
+
47
+ // skip if there are no placeholders
48
+ if( strpos( $original, '%' ) === false )
49
+ return;
50
+
51
+
52
+ // placeholders
53
+ $admin_url = admin_url();
54
+ $placeholders = array(
55
+ '%POST-LABEL-PLURAL%' => self::$post_type->labels->name,
56
+ '%POST-PERMALINK%' => self::get_permalink(),
57
+ '%POST-ARCHIVE-PERMALINK%' => self::get_archive_permalink(),
58
+ '%POST-LABEL-SINGULAR%' => self::$post_type->labels->singular_name,
59
+ '%POST-TYPE-NAME%' => self::$post_type->name,
60
+ '%THEME-NAME%' => wp_get_theme(),
61
+ '%POST-TEMPLATE-FILE%' => '<nobr>' . self::get_post_template_file() . '</nobr>',
62
+ '%POST-ARCHIVE-FILE%' => '<nobr>' . self::get_post_archive_file() . '</nobr>',
63
+ '%POST-FORMS-LIST%' => self::get_post_type_forms_list(),
64
+ '%POST-CREATE-FORM%' => $admin_url . 'admin.php?page=types-helper&action=new-form&type=' . self::$post_type->name,
65
+ '%POST-TYPE-EDIT-HAS-ARCHIVE%' => $admin_url . 'admin.php?page=wpcf-edit-type&wpcf-post-type=' . self::$post_type->name . '#types_options',
66
+ );
67
+
68
+ // Views specifics
69
+ if( defined( 'WPV_VERSION' ) ) {
70
+ $placeholders = array_merge( $placeholders, array(
71
+ //'%POST-CREATE-LAYOUT-TEMPLATE%' => self::get_post_create_layout_template(),
72
+ '%POST-CONTENT-TEMPLATE-NAME%' => Types_Helper_Condition_Views_Template_Exists::get_template_name(),
73
+ '%POST-VIEWS-ARCHIVE%' => Types_Helper_Condition_Views_Archive_Exists::get_template_name(),
74
+ '%POST-EDIT-VIEWS-ARCHIVE%' => self::get_post_edit_views_archive(),
75
+ '%POST-EDIT-CONTENT-TEMPLATE%' => self::get_post_edit_views_template(),
76
+ '%POST-CREATE-CONTENT-TEMPLATE%' => $admin_url . 'admin.php?page=types-helper&action=new-content-template&type='.self::$post_type->name,
77
+ '%POST-CREATE-VIEWS-ARCHIVE%' => $admin_url . 'admin.php?page=types-helper&action=new-wordpress-archive&type='.self::$post_type->name,
78
+ //'%POST-CREATE-VIEWS-ARCHIVE%' => self::get_post_create_views_archive(),
79
+ '%POST-VIEWS-LIST%' => self::get_post_type_views_list(),
80
+ '%POST-CREATE-VIEW%' => $admin_url . 'admin.php?page=types-helper&action=new-view&type='.self::$post_type->name,
81
+ ) );
82
+
83
+ }
84
+
85
+ // Layouts specifics
86
+ if( defined( 'WPDDL_DEVELOPMENT' ) ) {
87
+ $placeholders = array_merge( $placeholders, array(
88
+ //'%POST-CREATE-LAYOUT-TEMPLATE%' => self::get_post_create_layout_template(),
89
+ '%POST-CREATE-LAYOUT-TEMPLATE%' => $admin_url . 'admin.php?page=types-helper&action=new-layout-template&type='.self::$post_type->name,
90
+ '%POST-CREATE-LAYOUT-ARCHIVE%' => self::get_post_create_layout_archive(),
91
+ '%POST-EDIT-LAYOUT-TEMPLATE%' => self::get_post_edit_layout_template(),
92
+ '%POST-EDIT-LAYOUT-ARCHIVE%' => self::get_post_edit_layout_archive(),
93
+ '%POST-LAYOUT-TEMPLATE%' => Types_Helper_Condition_Layouts_Template_Exists::get_layout_name(),
94
+ '%POST-LAYOUT-ARCHIVE%' => Types_Helper_Condition_Layouts_Archive_Exists::get_layout_name(),
95
+ ) );
96
+ }
97
+
98
+ $original = strtr( $original, $placeholders );
99
+ }
100
+
101
+ private static function get_post_create_views_archive() {
102
+ if( self::$post_type_create_views_archive === null ){
103
+ $tool_admin_bar = Toolset_Admin_Bar_Menu::get_instance();
104
+
105
+ $post_type = self::$post_type->name == 'post' ? 'home-blog' : self::$post_type->name;
106
+ self::$post_type_create_views_archive = $tool_admin_bar->get_edit_link( 'views', true, $post_type, 'archive', 0 );
107
+ }
108
+
109
+ return self::$post_type_create_views_archive;
110
+ }
111
+
112
+ private static function get_post_edit_views_archive() {
113
+ if( self::$post_type_edit_views_archive === null ) {
114
+ self::$post_type_edit_views_archive =
115
+ admin_url() . 'admin.php?page=view-archives-editor&view_id='
116
+ . Types_Helper_Condition_Views_Archive_Exists::get_template_id();
117
+ }
118
+ return self::$post_type_edit_views_archive;
119
+ }
120
+
121
+ private static function get_post_create_layout_archive() {
122
+ if( self::$post_type_create_layout_archive === null ){
123
+ $tool_admin_bar = Toolset_Admin_Bar_Menu::get_instance();
124
+ self::$post_type_create_layout_archive = $tool_admin_bar->get_edit_link( 'layouts', true, self::$post_type->name, 'archive', 0 );
125
+ }
126
+
127
+ return self::$post_type_create_layout_archive;
128
+ }
129
+
130
+ private static function get_post_edit_layout_archive() {
131
+ if( self::$post_type_edit_layout_archive === null ) {
132
+ self::$post_type_edit_layout_archive =
133
+ admin_url() . 'admin.php?page=dd_layouts_edit&action=edit&layout_id='
134
+ . Types_Helper_Condition_Layouts_Archive_Exists::get_layout_id();
135
+ }
136
+
137
+ return self::$post_type_edit_layout_archive;
138
+ }
139
+
140
+ private static function get_post_edit_layout_template() {
141
+ if( self::$post_type_edit_layout_template === null ) {
142
+ self::$post_type_edit_layout_template =
143
+ admin_url() . 'admin.php?page=dd_layouts_edit&action=edit&layout_id='
144
+ . Types_Helper_Condition_Layouts_Template_Exists::get_layout_id();
145
+ }
146
+
147
+ return self::$post_type_edit_layout_template;
148
+ }
149
+
150
+ private static function get_post_edit_views_template() {
151
+ if( self::$post_type_edit_views_template === null ) {
152
+ self::$post_type_edit_views_template =
153
+ admin_url() . 'admin.php?page=ct-editor&ct_id='
154
+ . Types_Helper_Condition_Views_Template_Exists::get_template_id();
155
+ }
156
+
157
+ return self::$post_type_edit_views_template;
158
+ }
159
+
160
+ private static function get_post_template_file() {
161
+ if( self::$post_type_template_file === null ) {
162
+ $helper = new Types_Helper_Condition_Single_Exists();
163
+ self::$post_type_template_file = basename( $helper->find_template() );
164
+ }
165
+
166
+ return self::$post_type_template_file;
167
+ }
168
+
169
+ private static function get_post_archive_file() {
170
+ if( self::$post_type_archive_file === null ) {
171
+ $helper = new Types_Helper_Condition_Archive_Exists();
172
+ self::$post_type_archive_file = basename( $helper->find_template() );
173
+ }
174
+
175
+ return self::$post_type_archive_file;
176
+ }
177
+
178
+ public static function get_permalink( $id = 0 ) {
179
+ if( self::$single_link !== null )
180
+ return self::$single_link;
181
+
182
+ $permalink = get_permalink( $id );
183
+
184
+ if( $permalink ) {
185
+ $query_args['preview'] = 'true';
186
+ $permalink = add_query_arg( $query_args, $permalink );
187
+ self::$single_link = $permalink;
188
+ return $permalink;
189
+ }
190
+
191
+ if( isset( $_GET['post'] ) && $id != $_GET['post'] )
192
+ return self::get_permalink( $_GET['post'] );
193
+
194
+ // cpt edit page
195
+ if( isset( $_GET['wpcf-post-type'] ) && $id == 0 ) {
196
+ $query = new WP_Query( 'post_type=' . $_GET['wpcf-post-type'] . '&posts_per_page=1' );
197
+ if( $query->have_posts() )
198
+ return self::get_permalink( $query->posts[0]->ID );
199
+ }
200
+
201
+ // fields edit page
202
+ if( is_object( self::$post_type ) && $id == 0 ){
203
+ $query = new WP_Query( 'post_type=' . self::$post_type->name . '&posts_per_page=1' );
204
+ if( $query->have_posts() )
205
+ return self::get_permalink( $query->posts[0]->ID );
206
+ }
207
+
208
+ self::$single_link = false;
209
+ return self::$single_link ;
210
+ }
211
+
212
+ public static function get_archive_permalink() {
213
+ if( self::$archive_link !== null )
214
+ return self::$archive_link;
215
+
216
+ // cpt edit page
217
+ if( isset( $_GET['wpcf-post-type'] ) ) {
218
+ $query = new WP_Query( 'post_type=' . $_GET['wpcf-post-type'] . '&post_status=publish&posts_per_page=1' );
219
+ if( $query->have_posts() ) {
220
+ self::$archive_link = get_post_type_archive_link( $_GET['wpcf-post-type'] );
221
+ return self::$archive_link;
222
+ }
223
+
224
+ self::$archive_link = false;
225
+ return self::$archive_link;
226
+ }
227
+
228
+ if( ! is_object( self::$post_type ) )
229
+ self::set_post_type();
230
+
231
+ $query = new WP_Query( 'post_type=' . self::$post_type->name . '&post_status=publish&posts_per_page=1' );
232
+ if( $query->have_posts() ) {
233
+ self::$archive_link = get_post_type_archive_link( self::$post_type->name );
234
+ return self::$archive_link;
235
+ }
236
+
237
+ self::$archive_link = false;
238
+ return self::$archive_link;
239
+ }
240
+
241
+ private static function get_post_type_views_list() {
242
+ // @todo use twig
243
+ if( $views = Types_Helper_Condition_Views_Views_Exist::get_views_of_post_type() ) {
244
+ $output = '<ul>';
245
+ foreach( $views as $view ) {
246
+ $view_edit_link = admin_url() . 'admin.php?page=views-editor&view_id=' . $view['id'];
247
+ $output .= '<li><a href="'. $view_edit_link . '">'. $view['name'].'</a></li>';
248
+ }
249
+ $output .= '</ul>';
250
+
251
+ return $output;
252
+ }
253
+
254
+ return __( 'No Views', 'types' );
255
+ }
256
+
257
+ private static function get_post_type_forms_list() {
258
+ // @todo use twig
259
+ if( $forms = Types_Helper_Condition_Cred_Forms_Exist::get_forms_of_post_type() ) {
260
+ $output = '<ul>';
261
+ foreach( $forms as $form ) {
262
+ $view_edit_link = get_edit_post_link( $form['id'] );
263
+ $output .= '<li><a href="'. $view_edit_link . '">'. $form['name'].'</a></li>';
264
+ }
265
+ $output .= '</ul>';
266
+
267
+ return $output;
268
+ }
269
+
270
+ return __( 'No Forms', 'types' );
271
+ }
272
+ }
application/models/helper/twig.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Twig {
5
+
6
+ private $filesystem;
7
+ private $twig;
8
+
9
+ public function __construct() {
10
+ $this->filesystem = new Twig_Loader_Filesystem();
11
+ $this->filesystem->addPath( TYPES_ABSPATH . '/application/views' );
12
+ $this->twig = new Twig_Environment( $this->filesystem );
13
+ }
14
+
15
+ public function render( $file, $data ) {
16
+ if( $this->filesystem->exists( $file ) )
17
+ return $this->twig->render( $file, $data );
18
+
19
+ return false;
20
+ }
21
+ }
application/models/helper/type_hinting.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Type_Hinting {
5
+
6
+ /**
7
+ * As we don't have type hinting in good old 5.2.4 here a little helper
8
+ * If a string is given for $object, the method check if class exists and than do the type check.
9
+ *
10
+ * @param $object string|object
11
+ * @param $type
12
+ *
13
+ * @return false|object
14
+ */
15
+ public static function valid( $object, $type ) {
16
+ if( ! is_object( $object ) ) {
17
+ if( ! class_exists( $object ) )
18
+ return false;
19
+
20
+ $object = new $object();
21
+ return self::valid( $object, $type );
22
+ }
23
+
24
+ // type hinting the old way
25
+ if( ! is_a( $object, $type ) )
26
+ return false;
27
+
28
+ return $object;
29
+ }
30
+ }
application/models/helper/url.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Helper_Url {
5
+
6
+ private static $utm_source = 'typesplugin';
7
+ private static $utm_campaign = 'types';
8
+
9
+ private static $utm_medium;
10
+ private static $utm_term;
11
+ private static $utm_content;
12
+
13
+ private static $urls = array();
14
+
15
+ public static function set_medium( $medium = false ) {
16
+ if( $medium ) {
17
+ self::$utm_medium = $medium;
18
+ return;
19
+ }
20
+
21
+ global $pagenow;
22
+ if( ! empty( $pagenow ) ) {
23
+ self::$utm_medium = $pagenow;
24
+ return;
25
+ }
26
+
27
+ self::$utm_medium = false;
28
+ }
29
+
30
+ private static function get_medium() {
31
+ if( self::$utm_medium === null )
32
+ self::set_medium();
33
+
34
+ return self::$utm_medium;
35
+ }
36
+
37
+ public static function add_urls( $urls ) {
38
+ if( is_array( $urls ))
39
+ self::$urls = array_merge( self::$urls, $urls );
40
+ }
41
+
42
+ private static function apply_analytics_arguments_to_url( $url ) {
43
+ if( ! self::get_medium() )
44
+ return $url;
45
+
46
+ $url_parts = parse_url( $url );
47
+
48
+ if( isset( $url_parts['fragment'] ) && !empty( $url_parts['fragment'] ) )
49
+ $url = str_replace( '#'.$url_parts['fragment'], '', $url );
50
+
51
+ $url .= !isset( $url_parts['query'] ) || empty( $url_parts['query'] ) ? '?' : '&';
52
+ $url .= 'utm_source='.self::$utm_source
53
+ .'&utm_campaign='.self::$utm_campaign
54
+ .'&utm_medium='.self::$utm_medium
55
+ .'&utm_term='.self::$utm_term
56
+ .'&utm_content='.self::$utm_content;
57
+
58
+ if( isset( $url_parts['fragment'] ) && !empty( $url_parts['fragment'] ) )
59
+ $url .= '#' . $url_parts['fragment'];
60
+
61
+ return $url;
62
+ }
63
+
64
+ public static function get_url( $key, $utm_content = false, $utm_term = false, $utm_medium = false ) {
65
+ if( !isset( self::$urls[$key] ) )
66
+ return '';
67
+
68
+ $url = self::$urls[$key];
69
+
70
+ // return url if no arguments
71
+ if( ! $utm_content )
72
+ return $url;
73
+
74
+ // add utm content
75
+ self::$utm_content = $utm_content;
76
+
77
+ // use key for term, if no term isset
78
+ if( ! $utm_term )
79
+ $utm_term = $key;
80
+
81
+ self::$utm_term = $utm_term;
82
+
83
+ // apply medium only if medium isset
84
+ if( $utm_medium )
85
+ self::set_medium( $utm_medium );
86
+
87
+ // apply arguments
88
+ $url = self::apply_analytics_arguments_to_url( $url );
89
+ return $url;
90
+
91
+ }
92
+ }
application/models/information/container.php ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Information_Container {
5
+ protected $id;
6
+ protected $messages = array();
7
+ protected $messages_filtered = array();
8
+ protected $output_container = false;
9
+
10
+ /**
11
+ * We need this option to show messages for hooks followed by a page reload.
12
+ * @var bool
13
+ */
14
+ protected $cached = false;
15
+
16
+ public function __construct( $id ) {
17
+ $this->id = $id;
18
+ }
19
+
20
+ // get id
21
+ public function get_id() {
22
+ return $this->id;
23
+ }
24
+
25
+ // add message
26
+ public function add_message( $message ) {
27
+ if( $message = Types_Helper_Type_Hinting::valid( $message, 'Types_Information_Message' ) )
28
+ $this->messages[] = $message;
29
+ }
30
+
31
+ public function get_messages() {
32
+ return $this->messages;
33
+ }
34
+
35
+ /**
36
+ * @return array|bool
37
+ */
38
+ public function get_descriptions() {
39
+ if( empty( $this->messages ) )
40
+ return false;
41
+
42
+ // check if descriptions were already filtered
43
+ if( isset( $this->messages_filtered['descriptions'] ) )
44
+ return $this->messages_filtered['descriptions'];
45
+
46
+ $descriptions = array();
47
+
48
+ foreach( $this->messages as $message ){
49
+ $descriptions[] = $message->get_description();
50
+ }
51
+
52
+ Types_Helper_Placeholder::replace( $descriptions );
53
+ $this->messages_filtered['descriptions'] = $descriptions;
54
+ return $descriptions;
55
+ }
56
+
57
+
58
+ /**
59
+ *
60
+ * @return bool
61
+ */
62
+ public function get_examples() {
63
+ if( empty( $this->messages ) )
64
+ return false;
65
+
66
+ // check if descriptions were already filtered
67
+ if( isset( $this->messages_filtered['view_example'] ) )
68
+ return $this->messages_filtered['view_example'];
69
+
70
+ $examples = array();
71
+
72
+ foreach( $this->messages as $message ) {
73
+ if( !empty( $examples ) ) {
74
+ $current_example = $message->get_example();
75
+
76
+ // check if the view example is already applied
77
+ foreach( $examples as $view ) {
78
+ // skip to next message
79
+ if( $view['label'] == $current_example['label'] )
80
+ continue 2;
81
+ }
82
+
83
+ // no duplication, add view example
84
+ $examples[] = $current_example;
85
+ continue;
86
+ }
87
+
88
+ // view example has no value yet
89
+ $examples[] = $message->get_example();
90
+ }
91
+
92
+ Types_Helper_Placeholder::replace( $examples );
93
+ $this->messages_filtered['view_example'] = $examples;
94
+ return $examples;
95
+ }
96
+
97
+ /**
98
+ * @param bool|string $output e.g., a rendered Twig template
99
+ *
100
+ * @return bool|string
101
+ */
102
+ public function render( $output = false ) {
103
+
104
+ $output = $output ? $output : '';
105
+
106
+ if( $this->cached && !$this->is_cached() )
107
+ return false;
108
+
109
+ // use message render function if no output is set
110
+ if( empty( $output ) && ! empty( $this->messages ) ) {
111
+ foreach( $this->messages as $message ) {
112
+ $output .= $message->render();
113
+ }
114
+ }
115
+
116
+ // send output to container (e.g., meta-box) and return full container output
117
+ if( $this->output_container ) {
118
+ $this->output_container->set_content( $output );
119
+ return $this->output_container->output();
120
+ }
121
+
122
+ return $output;
123
+ }
124
+
125
+ // set output container
126
+ public function set_output_container( $output ) {
127
+ // @todo type hinting Types_Helper_Output_Meta_Box
128
+ $this->output_container = $output;
129
+ }
130
+
131
+
132
+ // cache on hook
133
+ public function cache_on_hook( $hook ) {
134
+ $this->cached = true;
135
+ add_action( $hook, array( $this, 'cache' ) );
136
+ }
137
+
138
+ public function cache() {
139
+ $this->cached = true;
140
+
141
+ if( ! $this->id )
142
+ return false;
143
+
144
+ $db_messages = get_option( 'types_messages', array() );
145
+ $db_messages[$this->id] = 1;
146
+
147
+ update_option( 'types_messages', $db_messages );
148
+ }
149
+
150
+ /**
151
+ * Check if cached
152
+ *
153
+ * @return bool
154
+ */
155
+ private function is_cached() {
156
+ $db_messages = get_option( 'types_messages', array() );
157
+
158
+ if( ! isset( $db_messages[$this->id] ) || empty( $db_messages[$this->id] ) )
159
+ return false;
160
+
161
+ // disable message again
162
+ $db_messages[$this->id] = 0;
163
+ update_option( 'types_messages', $db_messages );
164
+
165
+ return true;
166
+ }
167
+
168
+ }
application/models/information/message.php ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Information_Message {
5
+
6
+ protected $id;
7
+ protected $type = false;
8
+ protected $conditions = array();
9
+
10
+ public $priority;
11
+ public $title;
12
+ public $description;
13
+
14
+ /**
15
+ * Type Set & Get
16
+ * @param $type
17
+ */
18
+ public function set_id( $id ) {
19
+ $this->id = $id;
20
+ }
21
+
22
+ public function get_id() {
23
+ return $this->id;
24
+ }
25
+
26
+ /**
27
+ * Type Set & Get
28
+ * @param $type
29
+ */
30
+ public function set_type( $type ) {
31
+ switch( $type ) {
32
+ case 'information':
33
+ case 'template':
34
+ case 'archive':
35
+ case 'views':
36
+ case 'forms':
37
+ $this->type = $type;
38
+ break;
39
+ }
40
+ }
41
+
42
+ public function get_type() {
43
+ return $this->type;
44
+ }
45
+
46
+ /**
47
+ * Use this to add multiple conditions at ounce.
48
+ *
49
+ * @param $conditions
50
+ *
51
+ * @return bool
52
+ */
53
+ public function add_conditions( $conditions ) {
54
+ if( $conditions === false )
55
+ return false;
56
+
57
+ if( is_array( $conditions ) ) {
58
+ foreach( $conditions as $condition ) {
59
+ $this->add_condition( $condition );
60
+ }
61
+ } else {
62
+ $this->add_condition( $conditions );
63
+ }
64
+ }
65
+
66
+
67
+ /**
68
+ * Add a condition to show the message.
69
+ *
70
+ * @param Types_Helper_Condition $condition
71
+ *
72
+ * @return bool
73
+ */
74
+ public function add_condition( $condition ) {
75
+ if( $condition = Types_Helper_Type_Hinting::valid( $condition, 'Types_Helper_Condition' ) )
76
+ $this->conditions[] = $condition;
77
+
78
+ return $this;
79
+ }
80
+
81
+ /**
82
+ * Check if all assigned conditions match
83
+ *
84
+ * @return bool
85
+ */
86
+ public function valid() {
87
+
88
+ foreach( $this->conditions as $condition ) {
89
+ if( ! $condition->valid() )
90
+ return false;
91
+ }
92
+
93
+ return true;
94
+ }
95
+
96
+ /**
97
+ * Title Set & Get
98
+ * @param $title
99
+ */
100
+ public function set_title( $title ) {
101
+ $this->title = $title;
102
+ }
103
+
104
+ public function get_title() {
105
+ return $this->title;
106
+ }
107
+
108
+ /**
109
+ * Description Set & Get
110
+ * @param $description
111
+ */
112
+ public function set_description( $description ) {
113
+ if( !is_array( $description ) ) {
114
+ $this->description = array(
115
+ array(
116
+ 'type' => 'paragraph',
117
+ 'content' => $description
118
+ )
119
+ );
120
+
121
+ return;
122
+ }
123
+
124
+ // @todo Remove once placeholder replace comes before Twig rendering
125
+ foreach( $description as &$element ) {
126
+ if( isset( $element['target'] ) ) {
127
+ switch( $element['target'] ) {
128
+ case '%POST-PERMALINK%':
129
+ $element['target'] = Types_Helper_Placeholder::get_permalink();
130
+ break;
131
+ case '%POST-ARCHIVE-PERMALINK%':
132
+ $element['target'] = Types_Helper_Placeholder::get_archive_permalink();
133
+ break;
134
+ }
135
+ }
136
+
137
+ }
138
+
139
+ $this->description = $description;
140
+ }
141
+
142
+ public function get_description() {
143
+ return $this->description;
144
+ }
145
+
146
+
147
+ /**
148
+ * Import data
149
+ * see /application/data/information
150
+ *
151
+ * @param array $data
152
+ *
153
+ * @return bool
154
+ */
155
+ public function data_import( $data ) {
156
+ if( ! is_array( $data ) )
157
+ return false;
158
+
159
+ $default = array(
160
+ 'id' => false,
161
+ 'type' => false,
162
+ 'conditions' => false,
163
+ 'title' => false,
164
+ 'description' => false,
165
+ 'priority' => false
166
+ );
167
+
168
+ $cfg = array_replace_recursive( $default, $data );
169
+
170
+ $this->set_id( $cfg['id'] );
171
+ $this->set_type( $cfg['type'] );
172
+ $this->add_conditions( $cfg['conditions'] );
173
+ $this->set_title( $cfg['title'] );
174
+ $this->set_description( $cfg['description'] );
175
+ $this->priority = $cfg['priority'];
176
+ }
177
+
178
+
179
+ /**
180
+ * Add link, used for example, documentation and how to resolve links
181
+ *
182
+ * @param $target
183
+ * @param $link
184
+ * @param bool $in_array
185
+ * false for $target = $link
186
+ * true for $target[] = $link
187
+ */
188
+ protected function add_link( &$target, $link, $in_array = false ) {
189
+
190
+ if( isset( $link['label'] ) && isset( $link['link'] ) ) {
191
+ $add = array(
192
+ 'label' => $link['label'],
193
+ 'link' => $link['link']
194
+ );
195
+ } elseif( isset( $link['label'] ) && isset( $link['dialog'] ) ) {
196
+ $add = array(
197
+ 'label' => $link['label'],
198
+ 'dialog' => $link['dialog']
199
+ );
200
+ } elseif( count( $link, COUNT_RECURSIVE ) == 2 ) {
201
+ $add = array(
202
+ 'label' => $link[0],
203
+ 'link' => $link[1]
204
+ );
205
+ }
206
+
207
+ if( isset( $link['class'] ) )
208
+ $add['class'] = $link['class'];
209
+
210
+ if( isset( $add ) ) {
211
+ if( $in_array ) {
212
+ $target[] = $add;
213
+ } else {
214
+ $target = $add;
215
+ }
216
+ }
217
+
218
+ }
219
+ }
application/models/information/table.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Types_Information_Table extends Types_Information_Container {
5
+
6
+ protected $template;
7
+ protected $archive;
8
+ protected $views;
9
+ protected $forms;
10
+
11
+ /**
12
+ * @param $message
13
+ *
14
+ * @return bool
15
+ */
16
+ public function add_message( $message ) {
17
+ if( ! $message = Types_Helper_Type_Hinting::valid( $message, 'Types_Information_Message' ) )
18
+ return false;
19
+
20
+ if( $message->get_type() )
21
+ switch( $message->get_type() ) {
22
+ case 'template':
23
+ if( $this->template === null && $message->valid() )
24
+ $this->template[] = $message;
25
+ break;
26
+ case 'archive':
27
+ if( $this->archive === null && $message->valid() )
28
+ $this->archive[] = $message;
29
+ break;
30
+ case 'views':
31
+ if( $this->views === null && $message->valid() )
32
+ $this->views[] = $message;
33
+ break;
34
+ case 'forms':
35
+ if( $this->forms === null && $message->valid() )
36
+ $this->forms[] = $message;
37
+ break;
38
+ }
39
+ }
40
+
41
+ public function get_template() {
42
+ return $this->template;
43
+ }
44
+
45
+ public function get_archive() {
46
+ $post_type = Types_Helper_Condition::get_post_type();
47
+ if( $post_type->name == 'post' || $post_type->name == 'page' )
48
+ return false;
49
+
50
+ return $this->archive;
51
+ }
52
+
53
+ public function get_views() {
54
+ return $this->views;
55
+ }
56
+
57
+ public function get_forms() {
58
+ return $this->forms;
59
+ }
60
+
61
+ }
application/views/help/basic.twig ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {#
2
+ Basic template for the help tab on admin pages.
3
+
4
+ It works with following context:
5
+ - string[] introductory_paragraphs
6
+ - string your_options: The string "your options for this page are..."
7
+ - array options: Each option needs to have "name" and "explanation" keys.
8
+ - string[] ending_paragraphs
9
+
10
+ @since 2.0
11
+ #}
12
+
13
+ {% for paragraph in introductory_paragraphs %}
14
+ <p>{{ paragraph|raw }}</p>
15
+ {% endfor %}
16
+ <h3>{{ your_options }}</h3>
17
+ <dl>
18
+ {% for option in options %}
19
+ <dt>{{ option.name }}</dt>
20
+ <dd>{{ option.explanation|raw }}</dd>
21
+ {% endfor %}
22
+ </dl>
23
+ {% for paragraph in ending_paragraphs %}
24
+ <p>{{ paragraph|raw }}</p>
25
+ {% endfor %}
application/views/information/description/dialog.twig ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <p class="types-information-link">
2
+ <a{% if description.class %} class="{{ description.class }}"{% endif %} href="javascript:void(0)"
3
+ data-types-open-dialog="types-dialog-{{ description.dialog.id }}">
4
+ {{ description.label }}
5
+ </a>
6
+ </p>
7
+
8
+ <div id="types-dialog-{{ description.dialog.id }}" style="display:none;">
9
+ <div class="types-message types-table-row">
10
+ <div class="types-message-icon types-table-cell">
11
+ <span class="icon-toolset-logo"></span>
12
+ </div>
13
+
14
+ <div class="types-message-content types-table-cell">
15
+ {% for description in description.dialog.description %}
16
+ {% if description.type %}
17
+ {% include 'information/description/' ~ description.type ~ '.twig' %}
18
+ {% endif %}
19
+ {% endfor %}
20
+ </div>
21
+ </div>
22
+ </div>
application/views/information/description/link.twig ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ {% if description.target and description.label %}
2
+ <p class="types-information-link">
3
+ <a{% if description.class or description.external %} class="{{ description.class }}{% if description.external %} types-external-link{% endif %}"{% endif %} href="{{ description.target }}"{% if description.external %} target="_blank"{% endif %}>{{ description.label }}</a>
4
+ </p>
5
+ {% endif %}
application/views/information/description/list.twig ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <ul>
2
+ {% for item in description.content %}
3
+ <li>{{ item|raw }}</li>
4
+ {% endfor %}
5
+ </ul>
application/views/information/description/paragraph.twig ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <p class="types-information-paragraph">
2
+ {{ description.content|raw }}
3
+ </p>
application/views/information/single.twig ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <div class="types-information types-table-row">
3
+ {% if icon %}
4
+ <div class="types-message-icon types-table-cell">
5
+ <span class="{{ icon }}"></span>
6
+ </div>
7
+ {% endif %}
8
+
9
+ <div class="types-message-content types-table-cell">
10
+ {% for message in information.get_messages() %}
11
+ {% for description in message.description %}
12
+ {% if description.type %}
13
+ {% include 'information/description/' ~ description.type ~ '.twig' %}
14
+ {% endif %}
15
+ {% endfor %}
16
+ {% endfor %}
17
+ </div>
18
+ </div>
application/views/information/table.twig ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <div class="types-information">
3
+ <table width="100%">
4
+ <thead>
5
+ <tr>
6
+ {% for cell in thead %}
7
+ <th width="{{ 100 / thead|length }}%">
8
+ {{ cell|raw }}
9
+ </th>
10
+ {% endfor %}
11
+ </tr>
12
+ </thead>
13
+ <tbody>
14
+ <tr>
15
+ <td>
16
+ {% for information in table.get_template() %}
17
+ {% include 'information/table/tbody-cell.twig' %}
18
+ {% endfor %}
19
+ </td>
20
+ {% if table.get_archive() %}
21
+ <td>
22
+ {% for information in table.get_archive() %}
23
+ {% include 'information/table/tbody-cell.twig' %}
24
+ {% endfor %}
25
+ </td>
26
+ {% endif %}
27
+ <td>
28
+ {% for information in table.get_views() %}
29
+ {% include 'information/table/tbody-cell.twig' %}
30
+ {% endfor %}
31
+ </td>
32
+ <td>
33
+ {% for information in table.get_forms() %}
34
+ {% include 'information/table/tbody-cell.twig' %}
35
+ {% endfor %}
36
+ </td>
37
+ </tr>
38
+ </tbody>
39
+ </table>
40
+ </div>
41
+
42
+
43
+
44
+
application/views/information/table/tbody-cell.twig ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <div class="types-information-td-inner {% if information.priority %} types-information-{{ information.priority }}{% endif %}">
2
+
3
+ {% for description in information.description %}
4
+ {% if description.type %}
5
+ {% include 'information/description/' ~ description.type ~ '.twig' %}
6
+ {% endif %}
7
+ {% endfor %}
8
+
9
+ </div>
application/views/information/table/thead-cell.twig ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {{ title }}
2
+
3
+ <a id="types-pointer-target-{{ id }}" href="javascript:void(0)" class="dashicons dashicons-editor-help"
4
+ data-types-open-pointer="types-pointer-{{ id }}" style="position:relative;"></a>
5
+
6
+ <div id="types-pointer-{{ id }}" style="display:none;">
7
+ <div class="types-pointer-inner">
8
+ <div class="types-message-content types-table-cell">
9
+
10
+ {% for description in description %}
11
+ {% if description.type %}
12
+ {% include 'information/description/' ~ description.type ~ '.twig' %}
13
+ {% endif %}
14
+ {% endfor %}
15
+ </div>
16
+ </div>
17
+ </div>
application/views/page/base.twig ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <div class="wrap">
2
+ {% block heading %}
3
+ <h1>{% block title %}{% endblock %}</h1>
4
+ {% endblock %}
5
+
6
+ <div id="types-page-content">{% block content %}{% endblock %}</div>
7
+
8
+ {% block footer %}{% endblock %}
9
+ </div>
application/views/page/field_control/bulk_change_management_status_dialog.twig ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {#
2
+ Dialog for confirming bulk action "manage/stop managing field with Types"
3
+
4
+ @since 2.0
5
+ #}
6
+ <p data-bind="visible: willBeManagedByTypes">{{ strings.youAreAboutToManageFields }}</p>
7
+ <p data-bind="visible: !willBeManagedByTypes()">{{ strings.youAreAboutToStopManagingFields }}</p>
8
+ <ul style="list-style: disc inside" data-bind="foreach: fieldDefinitions">
9
+ <li data-bind="text: displayName"></li>
10
+ </ul>
11
+ <p>{{ strings.confirmContinue }}</p>
application/views/page/field_control/change_assignment_dialog.twig ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {#
2
+ Dialog for changing the field groups where a field definition belongs.
3
+
4
+ @since 2.0
5
+ #}
6
+ {% if groups is empty %}
7
+ <p>{{ strings.noFieldGroups }}</p>
8
+ {% else %}
9
+ <ul>
10
+ {% for group in groups %}
11
+ <li style="float: left; width: 33%;">
12
+ <label>
13
+ <input type="checkbox" data-bind="checked: isGroupChecked('{{ group.slug }}')"/>
14
+ &nbsp;
15
+ {{ group.displayName|e }}
16
+ </label>
17
+ </li>
18
+ {% endfor %}
19
+ </ul>
20
+ {% endif %}
application/views/page/field_control/change_type_dialog.twig ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {#
2
+ Change field type dialog.
3
+
4
+ @since 2.0
5
+ #}
6
+
7
+ {#
8
+ Section for changing field type
9
+ #}
10
+ {{ strings.aboutFieldTypeChanging }}
11
+ <p><strong>{{ strings.potentiallyRiskyOperation }}</strong></p>
12
+ <div class="wpcf-choose-field">
13
+ {% for fieldType in fieldTypeDefinitions %}
14
+ <button type="button" class="types-choose-field-type-button wpcf-choose-field-button wpcf-form-button form-button button"
15
+ data-bind="
16
+ enable: canConvertTo('{{ fieldType.slug|e }}'),
17
+ highlightedBorder: isSelected('{{ fieldType.slug|e }}'),
18
+ click: function() { selectedType('{{ fieldType.slug|e }}'); }"
19
+ >
20
+ <i class="{{ fieldType.iconClasses|e }}"></i>
21
+ {{ fieldType.displayName }}
22
+ </button>
23
+ {% endfor %}
24
+ </div>
25
+ <p>{{ strings.someTypesAreDisabled }}</p>
26
+
27
+ <hr />
28
+
29
+ {#
30
+ Section for changing field cardinality
31
+ #}
32
+ <div>
33
+ <div style="float: left; width: 40%;">
34
+ <p><strong>{{ strings.singleOrRepeatingField }}</strong></p>
35
+ <div style="margin: 10px">
36
+ <label>
37
+ <input type="radio" value="single" name="types-field-cardinality" data-bind="checked: targetCardinality" />
38
+ {{ strings.singleField }}
39
+ </label>
40
+ </div>
41
+ <div style="margin: 10px">
42
+ <label>
43
+ <input type="radio" value="repetitive" name="types-field-cardinality" data-bind="checked: targetCardinality, enable: targetTypeCanBeRepetitive" />
44
+ {{ strings.repetitiveField }}
45
+ <span data-bind="visible: (! targetTypeCanBeRepetitive()) ">&nbsp; <small><em>{{ strings.targetSupportsSingleOnly }}</em></small></span>
46
+ </label>
47
+ </div>
48
+ </div>
49
+
50
+ {# Warning to be displayed only if changing from repeating to single field. #}
51
+ <div style="float: left; width: 60%;" data-bind="visible: reducingCardinality">
52
+ <div style="float: left; width: 92px">
53
+ <i class="fa fa-exclamation-triangle fa-4x" style="margin: 20px;"></i>
54
+ </div>
55
+ <div style="float: left; width: 345px;">
56
+ <p style="font-size: 11px;">{{ strings.repetitiveToSingleWarning|raw }}</p>
57
+ </div>
58
+ </div>
59
+ </div>
application/views/page/field_control/delete_dialog.twig ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {#
2
+ Dialog for deleting a single field (definition + values).
3
+
4
+ @since 2.0
5
+ #}
6
+
7
+ <div style="float: left; width: 145px;">
8
+ <i class="fa fa-exclamation-triangle fa-5x" style="margin: 40px;"></i>
9
+ </div>
10
+ <div style="float: left; width: 404px; padding-left: 16px;">
11
+ <p>{{ strings.deletingWillRemoveDefinitionAndData }}</p>
12
+ <p><strong>{{ strings.cannotBeUndone }}</strong></p>
13
+ <p>{{ strings.doYouReallyWantDelete }}</p>
14
+ </div>
application/views/page/field_control/main.twig ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "@generic_page/base.twig" %}
2
+
3
+ {% block title %}{{ strings.misc.pageTitle }}{% endblock %}
4
+
5
+ {% block content %}
6
+
7
+ <div id="message" data-bind="threeModeVisibility: messageVisibilityMode, attr: { class: 'notice is-dismissible ' + messageNagClass() }">
8
+ <p data-bind="html: displayedMessage().text"></p>
9
+ <button class="notice-dismiss" data-bind="click: removeDisplayedMessage"></button>
10
+ </div>
11
+
12
+ <div class="types-listing-spinner">
13
+ <img src="{{ assets.loaderOverlay }}" />
14
+ </div>
15
+
16
+ <div class="types-listing-wrapper" style="display: none;">
17
+ <div class="tablenav top">
18
+
19
+ <div class="alignleft actions bulkactions">
20
+ <select data-bind="options: bulkActions, optionsText: 'displayName', optionsValue: 'value', value: selectedBulkAction"></select>
21
+ <input id="doaction" class="button action" type="submit"
22
+ value="{{ strings.misc.applyBulkAction }}"
23
+ data-bind="click: onBulkAction, enable: isBulkActionAllowed"/>
24
+ <span class="spinner" data-bind="style: { visibility: (isSpinnerVisible() ? 'visible' : 'hidden') }"></span>
25
+ </div>
26
+
27
+ {#
28
+ Pagination, WordPress-style.
29
+
30
+ This might deserve moving into a separate Twig template with more universal "paginator" object to bind on.
31
+ That would be very easy to reuse.
32
+
33
+ @since 2.0
34
+ #}
35
+ <div class="alignright" style="margin-left: 10px;">
36
+ <div class='tablenav-pages'>
37
+ <span class="displaying-num"><span data-bind="text: itemCount"></span> {{ strings.misc.items }}</span>
38
+ <span class='pagination-links'>
39
+
40
+ {# enabled and disabled versions of both buttons #}
41
+ <a class='next-page' data-bind="visible: !isFirstPage(), click: gotoPage('first') "><span>&laquo;</span></a>
42
+ <a class='last-page' data-bind="visible: !isFirstPage(), click: gotoPage('previous')"><span>&lsaquo;</span></a>
43
+ <span class="tablenav-pages-navspan" data-bind="visible: isFirstPage">&laquo;</span>
44
+ <span class="tablenav-pages-navspan" data-bind="visible: isFirstPage">&lsaquo;</span>
45
+
46
+ <span class="paging-input">
47
+ <input data-bind="value: currentPageSafe" class='current-page' type='text' name='paged' size='1' />
48
+ {{ strings.misc.of }} <span data-bind="text: totalPages" class='total-pages'></span>
49
+ </span>
50
+
51
+ {# enabled and disabled versions of both buttons #}
52
+ <a class='next-page' data-bind="visible: !isLastPage(), click: gotoPage('next')"><span>&rsaquo;</span></a>
53
+ <a class='last-page' data-bind="visible: !isLastPage(), click: gotoPage('last')"><span>&raquo;</span></a>
54
+ <span class="tablenav-pages-navspan" data-bind="visible: isLastPage">&rsaquo;</span>
55
+ <span class="tablenav-pages-navspan" data-bind="visible: isLastPage">&raquo;</span>
56
+ </span>
57
+ </div>
58
+ </div>
59
+
60
+ <div class="alignright">
61
+ <p class="search-box">
62
+ <input type="search" class="types-field-search" placeholder="{{ strings.misc.searchPlaceholder }}" data-bind="textInput: searchString" />
63
+ </p>
64
+ </div>
65
+
66
+ </div>
67
+
68
+
69
+ <table class="wp-list-table widefat posts striped" cellspacing="0">
70
+ <thead>
71
+ {% block th %}
72
+ <tr>
73
+ <td scope="col" class="manage-column column-bulk-actions check-column">
74
+ <input type="checkbox" name="bulk_select" data-bind="
75
+ checked: allVisibleFieldDefinitionSelection,
76
+ disable: (fieldDefinitionsToShow().length == 0)" />
77
+ </td>
78
+ <td scope="col" class="manage-column">
79
+ <a class="sort-column" data-bind="click: onSort('displayName')">
80
+ {{ strings.column.name }}
81
+ <i data-bind="attr: { class: sortIconClass('displayName') }" ></i>
82
+ </a>
83
+ </td>
84
+ <td scope="col" class="manage-column">
85
+ {{ strings.column.groups }}
86
+ </td>
87
+ <td scope="col" class="manage-column">
88
+ <a class="sort-column" data-bind="click: onSort('slug')">
89
+ {{ strings.column.slug }}
90
+ <i data-bind="attr: { class: sortIconClass('slug') }" ></i>
91
+ </a>
92
+ </td>
93
+ <td scope="col" class="manage-column">
94
+ <a class="sort-column" data-bind="click: onSort('typeForSorting')">
95
+ {{ strings.column.type }}
96
+ <i data-bind="attr: { class: sortIconClass('typeForSorting') }" ></i>
97
+ </a>
98
+ </td>
99
+ <td scope="col" class="manage-column">
100
+ <a class="sort-column" data-bind="click: onSort('metaKey')">
101
+ {{ strings.column.metaKey }}
102
+ <i data-bind="attr: { class: sortIconClass('metaKey') }" ></i>
103
+ </a>
104
+ </td>
105
+ </tr>
106
+ {% endblock %}
107
+ </thead>
108
+
109
+ <!-- ko if: (fieldDefinitionsToShow().length > 0) -->
110
+ <tbody data-bind="foreach: fieldDefinitionsToShow">
111
+ <tr data-bind="attr: { class: trClass }">
112
+
113
+ <td>
114
+ <input type="checkbox" data-bind="checked: isSelectedForBulkAction" />
115
+ </td>
116
+
117
+ {# Definition name and row actions. #}
118
+ <td>
119
+ <span class="spinner" data-bind="style: { visibility: (isSpinnerVisible() ? 'visible' : 'hidden') }"></span>
120
+
121
+ <span data-bind="text: displayName"></span>
122
+
123
+ <div class="row-actions">
124
+ <span class="edit" data-bind="visible: isUnderTypesControl">
125
+ <a data-bind="click: onChangeAssignmentAction">{{ strings.rowAction.changeAssignment }}</a> |
126
+ </span>
127
+ <span class="edit" data-bind="visible: isUnderTypesControl">
128
+ <a data-bind="click: onChangeTypeAction">{{ strings.rowAction.changeType }}</a> |
129
+ </span>
130
+ <span class="edit">
131
+ <a data-bind="text: display.changeManagementStatusActionLabel, click: onChangeManagementStatusAction"></a>
132
+ </span>
133
+ {# <span class="edit" data-bind="visible: canChangeCardinality">
134
+ <a data-bind="click: onChangeCardinalityAction, text: display.changeCardinalityActionLabel">
135
+ <!-- turn into repetitive / turn into single -->
136
+ </a>
137
+ </span> #}
138
+ <span class="delete" data-bind="visible: isUnderTypesControl">
139
+ | <a data-bind="click: onDeleteAction">{{ strings.rowAction.delete }}</a>
140
+ </span>
141
+ </div>
142
+ </td>
143
+
144
+ {# List of groups the field belongs to (if managed by Types) #}
145
+ <td data-bind="html: display.groupList"></td>
146
+
147
+ <td>
148
+ <span data-bind="text: slug"></span>
149
+ </td>
150
+
151
+ <td>
152
+ <span data-bind="html: display.type"></span>
153
+ <span data-bind="visible: isRepetitive" title="{{ strings.misc.thisFieldIsRepeating }}">*</span>
154
+ </td>
155
+
156
+ <td>
157
+ <code><small data-bind="text: metaKey"></small></code>
158
+ </td>
159
+
160
+ </tr>
161
+ </tbody>
162
+ <!-- /ko -->
163
+
164
+ <!-- ko if: (fieldDefinitionsToShow().length == 0) -->
165
+ <tbody>
166
+ <tr>
167
+ <td>
168
+ <input type="checkbox" disabled />
169
+ </td>
170
+
171
+ <td colspan="5">{{ strings.misc.noItemsFound|e }}</td>
172
+ </tr>
173
+ </tbody>
174
+ <!-- /ko -->
175
+
176
+ <tfoot>
177
+ {{ block('th') }}
178
+ </tfoot>
179
+ </table>
180
+
181
+ </div>
182
+
183
+ {% endblock %}
184
+
185
+ {% block footer %}
186
+ <script id="types_model_data" type="text/plain">{{ js_model_data }}</script>
187
+ {% endblock %}
application/views/page/field_control/message_definition_list.html ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <%- message %>
2
+ <ol>
3
+ <%
4
+ _.each(fieldDefinitions, function(fieldDefinition) {
5
+ print('<li>' + fieldDefinition.displayName() + '</li>');
6
+ });
7
+ %>
8
+ </ol>
application/views/page/field_control/message_multiple.html ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <%= (typeof(mainMessage) != 'undefined' && 0 < mainMessage.length ? '<p>' + mainMessage + '</p>' : '' ) %>
2
+ <ol>
3
+ <%
4
+ _.each(messages, function(message) {
5
+ print('<li>' + message + '</li>');
6
+ });
7
+ %>
8
+ </ol>
embedded/admin.php DELETED
@@ -1,728 +0,0 @@
1
- <?php
2
- /**
3
- *
4
- *
5
- */
6
- require_once(WPCF_EMBEDDED_ABSPATH . '/toolset/toolset-common/visual-editor/editor-addon.class.php');
7
- require_once WPCF_EMBEDDED_ABSPATH . '/includes/post-relationship.php';
8
-
9
- if ( defined( 'DOING_AJAX' ) ) {
10
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/ajax.php';
11
- add_action( 'wp_ajax_wpcf_ajax', 'wpcf_ajax_embedded' );
12
- }
13
-
14
- /**
15
- * admin_init hook.
16
- */
17
- function wpcf_embedded_admin_init_hook() {
18
- // Add callbacks for post edit pages
19
- add_action( 'load-post.php', 'wpcf_admin_edit_screen_load_hook' );
20
- add_action( 'load-post-new.php', 'wpcf_admin_edit_screen_load_hook' );
21
-
22
- // Meta boxes hook
23
- add_action( 'add_meta_boxes', 'wpcf_admin_add_meta_boxes', 10, 2 );
24
-
25
- // Add callback for 'media-upload.php'
26
- add_filter( 'get_media_item_args', 'wpcf_get_media_item_args_filter' );
27
-
28
- // Add save_post callback
29
- add_action( 'save_post', 'wpcf_admin_save_post_hook', 10, 2 );
30
-
31
- // Add Media callback
32
- add_action( 'add_attachment', 'wpcf_admin_save_attachment_hook', 10 );
33
- add_action( 'add_attachment', 'wpcf_admin_add_attachment_hook', 10 );
34
- add_action( 'edit_attachment', 'wpcf_admin_save_attachment_hook', 10 );
35
-
36
- // Render messages
37
- wpcf_show_admin_messages();
38
-
39
- // Render JS settings
40
- add_action( 'admin_head', 'wpcf_admin_render_js_settings' );
41
-
42
- // Media insert code
43
- if ( (isset( $_GET['context'] ) && $_GET['context'] == 'wpcf-fields-media-insert')
44
- || (isset( $_SERVER['HTTP_REFERER'] )
45
- && strpos( $_SERVER['HTTP_REFERER'],
46
- 'context=wpcf-fields-media-insert' ) !== false)
47
- ) {
48
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields/file.php';
49
- // Add types button
50
- add_filter( 'attachment_fields_to_edit', 'wpcf_fields_file_attachment_fields_to_edit_filter', PHP_INT_MAX, 2 );
51
- // Filter media TABs
52
- add_filter( 'media_upload_tabs', 'wpcf_fields_file_media_upload_tabs_filter' );
53
- }
54
-
55
- register_post_type( TYPES_CUSTOM_FIELD_GROUP_CPT_NAME,
56
- array(
57
- 'public' => false,
58
- 'label' => 'Types Groups',
59
- 'can_export' => false,
60
- )
61
- );
62
- register_post_type( TYPES_USER_META_FIELD_GROUP_CPT_NAME,
63
- array(
64
- 'public' => false,
65
- 'label' => 'Types User Groups',
66
- 'can_export' => false,
67
- )
68
- );
69
-
70
- add_filter( 'icl_custom_fields_to_be_copied',
71
- 'wpcf_custom_fields_to_be_copied', 10, 2 );
72
-
73
- // WPML editor filters
74
- add_filter( 'icl_editor_cf_name', 'wpcf_icl_editor_cf_name_filter' );
75
- add_filter( 'icl_editor_cf_description',
76
- 'wpcf_icl_editor_cf_description_filter', 10, 2 );
77
- add_filter( 'icl_editor_cf_style', 'wpcf_icl_editor_cf_style_filter', 10, 2 );
78
- // Initialize translations
79
- if ( function_exists( 'icl_register_string' )
80
- && defined( 'WPML_ST_VERSION' )
81
- && !get_option( 'wpcf_strings_translation_initialized', false ) ) {
82
- wpcf_admin_bulk_string_translation();
83
- update_option( 'wpcf_strings_translation_initialized', 1 );
84
- }
85
- }
86
-
87
- /**
88
- * Add meta boxes hook.
89
- *
90
- * @param type $post_type
91
- * @param type $post
92
- */
93
- function wpcf_admin_add_meta_boxes( $post_type, $post ) {
94
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
95
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
96
-
97
- wpcf_add_meta_boxes( $post_type, $post );
98
- }
99
-
100
- /**
101
- * save_post hook.
102
- *
103
- * @param type $post_ID
104
- * @param type $post
105
- */
106
- function wpcf_admin_save_post_hook( $post_ID, $post ) {
107
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
108
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
109
- wpcf_admin_post_save_post_hook( $post_ID, $post );
110
- }
111
-
112
- /**
113
- * Save attachment hook.
114
- *
115
- * @param type $attachment_id
116
- */
117
- function wpcf_admin_add_attachment_hook( $attachment_id )
118
- {
119
- $post = get_post( $attachment_id );
120
- wpcf_admin_post_add_attachment_hook( $attachment_id, $post );
121
- }
122
-
123
- /**
124
- * Save attachment hook.
125
- *
126
- * @param type $attachment_id
127
- */
128
- function wpcf_admin_save_attachment_hook( $attachment_id ) {
129
- $post = get_post( $attachment_id );
130
- wpcf_admin_save_post_hook( $attachment_id, $post );
131
- }
132
-
133
- /**
134
- * Triggers post procceses.
135
- */
136
- function wpcf_admin_edit_screen_load_hook() {
137
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
138
- global $wpcf;
139
- $wpcf->post = wpcf_admin_get_edited_post();
140
- wpcf_admin_post_init( $wpcf->post );
141
- }
142
-
143
- /**
144
- * Add styles to admin fields groups
145
- */
146
- function wpcf_admin_fields_postfields_styles(){
147
-
148
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
149
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
150
-
151
- // $groups = wpcf_admin_fields_get_groups();
152
- $groups = wpcf_admin_post_get_post_groups_fields( wpcf_admin_get_edited_post() );
153
-
154
- if ( !empty( $groups ) ) {
155
- echo '<style type="text/css">';
156
- foreach ( $groups as $group ) {
157
- echo str_replace( "}", "}\n",
158
- wpcf_admin_get_groups_admin_styles_by_group( $group['id'] ) );
159
- }
160
- echo '</style>';
161
- }
162
- }
163
-
164
- /**
165
- * Add styles to userfields groups
166
- */
167
- function wpcf_admin_fields_userfields_styles(){
168
-
169
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/usermeta-post.php';
170
-
171
-
172
- // $groups = wpcf_admin_fields_get_groups();
173
- $groups = wpcf_admin_usermeta_get_groups_fields();
174
-
175
- if ( !empty( $groups ) ) {
176
- echo '<style type="text/css">';
177
- foreach ( $groups as $key => $group ) {
178
- echo str_replace( "}", "}\n",
179
- wpcf_admin_get_groups_admin_styles_by_group( $group['id'] ) );
180
- }
181
- echo '</style>';
182
- }
183
- }
184
-
185
- /** @noinspection PhpUndefinedClassInspection */
186
-
187
- /**
188
- * Initiates/returns specific form.
189
- *
190
- * @staticvar array $wpcf_forms
191
- * @param string $id
192
- * @param array $form
193
- * @return Enlimbo_Forms_Wpcf
194
- */
195
- function wpcf_form( $id, $form = array() ) {
196
- static $wpcf_forms = array();
197
-
198
- if ( isset( $wpcf_forms[ $id ] ) ) {
199
- return $wpcf_forms[ $id ];
200
- }
201
-
202
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/forms.php';
203
- /** @noinspection PhpUndefinedClassInspection */
204
-
205
- $new_form = new Enlimbo_Forms_Wpcf();
206
- $new_form->autoHandle( $id, $form );
207
-
208
- $wpcf_forms[ $id ] = $new_form;
209
-
210
- return $wpcf_forms[ $id ];
211
- }
212
-
213
- /**
214
- * Renders form elements.
215
- *
216
- * @staticvar string $form
217
- * @param type $elements
218
- * @return type
219
- */
220
- function wpcf_form_simple( $elements ) {
221
- static $form = NULL;
222
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/forms.php';
223
- if ( is_null( $form ) ) {
224
- $form = new Enlimbo_Forms_Wpcf();
225
- }
226
- return $form->renderElements( $elements );
227
- }
228
-
229
- /**
230
- * Validates form elements (simple).
231
- *
232
- * @staticvar string $form
233
- * @param type $elements
234
- * @return type
235
- */
236
- function wpcf_form_simple_validate( &$elements ) {
237
- static $form = NULL;
238
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/forms.php';
239
- if ( is_null( $form ) ) {
240
- $form = new Enlimbo_Forms_Wpcf();
241
- }
242
- $form->validate( $elements );
243
- return $form;
244
- }
245
-
246
- /**
247
- * Stores JS validation rules.
248
- *
249
- * @staticvar array $validation
250
- * @param type $element
251
- * @return array
252
- */
253
- function wpcf_form_add_js_validation( $element ) {
254
- static $validation = array();
255
- if ( $element == 'get' ) {
256
- $temp = $validation;
257
- $validation = array();
258
- return $temp;
259
- }
260
- $validation[$element['#id']] = $element;
261
- }
262
-
263
- /**
264
- * Renders JS validation rules.
265
- *
266
- * @global type $wpcf
267
- * @param type $selector Can be CSS class or element ID
268
- * @param type $echo
269
- * @return string
270
- */
271
- function wpcf_form_render_js_validation( $selector = '.wpcf-form-validate',
272
- $echo = true ) {
273
- $output = WPCF_Validation::renderJsonData( $selector );
274
- if ( $echo ) {
275
- echo $output;
276
- }
277
- return $output;
278
- }
279
-
280
- /**
281
- * wpcf_custom_fields_to_be_copied
282
- *
283
- * Hook the copy custom fields from WPML and remove any of the fields
284
- * that wpcf will copy.
285
- */
286
- function wpcf_custom_fields_to_be_copied( $copied_fields, $original_post_id ) {
287
-
288
- // see if this is one of our fields.
289
- $groups = wpcf_admin_post_get_post_groups_fields( get_post( $original_post_id ) );
290
-
291
- foreach ( $copied_fields as $id => $copied_field ) {
292
- foreach ( $groups as $group ) {
293
- if ( isset( $group['fields'] ) && is_array( $group['fields'] ) ) {
294
- foreach ( $group['fields'] as $field ) {
295
- if ( $copied_field == wpcf_types_get_meta_prefix( $field ) . $field['slug'] ) {
296
- unset( $copied_fields[$id] );
297
- }
298
- }
299
- }
300
- }
301
- }
302
- return $copied_fields;
303
- }
304
-
305
- /**
306
- * Holds validation messages.
307
- *
308
- * @param type $method
309
- * @return type
310
- */
311
- function wpcf_admin_validation_messages( $method = false, $sprintf = '' ) {
312
- $messages = array(
313
- 'required' => __( 'This field is required.', 'wpcf' ),
314
- 'email' => __( 'Please enter a valid email address.', 'wpcf' ),
315
- 'url' => __( 'Please enter a valid URL address.', 'wpcf' ),
316
- 'date' => __( 'Please enter a valid date.', 'wpcf' ),
317
- 'digits' => __( 'Please enter numeric data.', 'wpcf' ),
318
- 'number' => __( 'Please enter numeric data.', 'wpcf' ),
319
- 'alphanumeric' => __( 'Letters, numbers, spaces or underscores only please.', 'wpcf' ),
320
- 'nospecialchars' => __( 'Letters, numbers, spaces, underscores and dashes only please.', 'wpcf' ),
321
- 'rewriteslug' => __( 'Letters, numbers, slashes, underscores and dashes only please.', 'wpcf' ),
322
- 'negativeTimestamp' => __( 'Please enter a date after 1 January 1970.', 'wpcf' ),
323
- 'maxlength' => sprintf( __( 'Maximum of %s characters exceeded.', 'wpcf' ), strval( $sprintf ) ),
324
- 'minlength' => sprintf( __( 'Minimum of %s characters has not been reached.', 'wpcf' ), strval( $sprintf ) ),
325
- /**
326
- * see
327
- * https://support.skype.com/en/faq/FA10858/what-is-a-skype-name-and-how-do-i-find-mine
328
- */
329
- 'skype' => __( 'Letters, numbers, dashes, underscores, commas and periods only please.', 'wpcf' ),
330
- );
331
- if ( $method ) {
332
- return isset( $messages[$method] ) ? $messages[$method] : '';
333
- }
334
- return $messages;
335
- }
336
-
337
-
338
- /**
339
- * Sanitize admin notice.
340
- *
341
- * @param string $message
342
- * @return string
343
- */
344
- function wpcf_admin_message_sanitize( $message )
345
- {
346
- $allowed_tags = array(
347
- 'a' => array(
348
- 'href' => array(),
349
- 'title' => array()
350
- ),
351
- 'br' => array(),
352
- 'b' => array(),
353
- 'div' => array(),
354
- 'em' => array(),
355
- 'i' => array(),
356
- 'p' => array(),
357
- 'strong' => array(),
358
- );
359
- $message = wp_kses($message, $allowed_tags);
360
- return stripslashes(html_entity_decode($message, ENT_QUOTES));
361
- }
362
-
363
- /**
364
- * Adds admin notice.
365
- *
366
- * @param string $message
367
- * @param string $class
368
- * @param string $mode 'action'|'echo'
369
- */
370
- function wpcf_admin_message( $message, $class = 'updated', $mode = 'action' )
371
- {
372
- if ( 'action' == $mode ) {
373
- add_action( 'admin_notices',
374
- create_function( '$a=1, $class=\'' . $class . '\', $message=\''
375
- . htmlentities( $message, ENT_QUOTES ) . '\'',
376
- '$screen = get_current_screen(); if (!$screen->is_network) echo "<div class=\"message $class\"><p>" . wpcf_admin_message_sanitize ($message) . "</p></div>";' ) );
377
- } elseif ( 'echo' == $mode ) {
378
- printf(
379
- '<div class="message %s is-dismissible"><p>%s</p> <button type="button" class="notice-dismiss">
380
- <span class="screen-reader-text">
381
- '. __( 'Dismiss this notice.' ) .'
382
- </span>
383
- </button></div>',
384
- $class,
385
- wpcf_admin_message_sanitize($message)
386
- );
387
- }
388
- }
389
-
390
- /**
391
- * Shows stored messages.
392
- */
393
- function wpcf_show_admin_messages($mode = 'action')
394
- {
395
- $messages = get_option( 'wpcf-messages', array() );
396
- $messages_for_user = isset( $messages[get_current_user_id()] ) ? $messages[get_current_user_id()] : array();
397
- $dismissed = get_option( 'wpcf_dismissed_messages', array() );
398
- if ( !empty( $messages_for_user ) && is_array( $messages_for_user ) ) {
399
- foreach( $messages_for_user as $message_id => $message ) {
400
- if( ! in_array( $message['keep_id'], $dismissed ) ) {
401
- wpcf_admin_message( $message['message'], $message['class'], $mode );
402
- }
403
- if( empty( $message['keep_id'] )
404
- || in_array( $message['keep_id'], $dismissed )
405
- ) {
406
- unset( $messages[ get_current_user_id() ][ $message_id ] );
407
- }
408
- }
409
- }
410
- update_option( 'wpcf-messages', $messages );
411
- }
412
-
413
- /**
414
- * Stores admin notices if redirection is performed.
415
- *
416
- * @param string $message
417
- * @param string $class
418
- */
419
- function wpcf_admin_message_store( $message, $class = 'updated', $keep_id = false )
420
- {
421
- /**
422
- * Allow to store or note
423
- *
424
- * Filter allow to turn off storing messages in Types
425
- *
426
- * @since 1.6.6
427
- *
428
- * @param boolean $var default value is true to show messages
429
- */
430
- if (!apply_filters('wpcf_admin_message_store', true) ) {
431
- return;
432
- }
433
- $messages = get_option( 'wpcf-messages', array() );
434
- $messages[get_current_user_id()][md5( $message )] = array(
435
- 'message' => $message,
436
- 'class' => $class,
437
- 'keep_id' => $keep_id ? $keep_id : false,
438
- );
439
- update_option( 'wpcf-messages', $messages );
440
- }
441
-
442
- /**
443
- * Admin notice with dismiss button.
444
- *
445
- * @param type $ID
446
- * @param string $message
447
- * @param type $store
448
- * @return boolean
449
- */
450
- function wpcf_admin_message_dismiss( $ID, $message, $store = true ) {
451
- $dismissed = get_option( 'wpcf_dismissed_messages', array() );
452
- if ( in_array( $ID, $dismissed ) ) {
453
- return false;
454
- }
455
- $message = $message . '<div style="float:right; margin:-15px 0 0 15px;"><a onclick="jQuery(this).parent().parent().fadeOut();jQuery.get(\''
456
- . admin_url( 'admin-ajax.php?action=wpcf_ajax&amp;wpcf_action=dismiss_message&amp;id='
457
- . $ID . '&amp;_wpnonce=' . wp_create_nonce( 'dismiss_message' ) ) . '\');return false;"'
458
- . 'class="button-secondary" href="javascript:void(0);">'
459
- . __( 'Dismiss', 'wpcf' ) . '</a></div>';
460
- if ( $store ) {
461
- wpcf_admin_message_store( $message, 'updated', $ID );
462
- } else {
463
- wpcf_admin_message( $message );
464
- }
465
- }
466
-
467
- /**
468
- * Checks if message is dismissed.
469
- *
470
- * @param type $message_id
471
- * @return boolean
472
- */
473
- function wpcf_message_is_dismissed( $message_id ) {
474
- return in_array( $message_id,
475
- (array) get_option( '_wpcf_dismissed_messages', array() ) );
476
- }
477
-
478
- /**
479
- * Adds dismissed message to record.
480
- *
481
- * @param type $ID
482
- */
483
- function wpcf_admin_message_set_dismissed( $ID ) {
484
- $messages = get_option( 'wpcf_dismissed_messages', array() );
485
- if ( !in_array( $ID, $messages ) ) {
486
- $messages[] = $ID;
487
- update_option( 'wpcf_dismissed_messages', $messages );
488
- }
489
- }
490
-
491
- /**
492
- * Removes dismissed message from record.
493
- *
494
- * @param type $ID
495
- */
496
- function wpcf_admin_message_restore_dismissed( $ID ) {
497
- $messages = get_option( 'wpcf_dismissed_messages', array() );
498
- $key = array_search( $ID, $messages );
499
- if ( $key !== false ) {
500
- unset( $messages[$key] );
501
- update_option( 'wpcf_dismissed_messages', $messages );
502
- }
503
- }
504
-
505
- /**
506
- * Saves cookie.
507
- *
508
- * @param type $data
509
- */
510
- function wpcf_cookies_add( $data ) {
511
- if ( isset( $_COOKIE['wpcf'] ) ) {
512
- $data = array_merge( (array) $_COOKIE['wpcf'], $data );
513
- }
514
- setcookie( 'wpcf', $data, time() + $lifetime, COOKIEPATH, COOKIE_DOMAIN );
515
- }
516
-
517
- /**
518
- * Renders page head.
519
- *
520
- * @see WPCF_Template::ajax_header()
521
- * @global type $pagenow
522
- * @param type $title
523
- */
524
- function wpcf_admin_ajax_head( $title = '' ) {
525
-
526
- /*
527
- * Since Types 1.2 and WP 3.5
528
- * AJAX head is rendered differently
529
- */
530
- global $wp_version;
531
- if ( version_compare( $wp_version, '3.4', '>' ) ) {
532
- // WP Header
533
- include WPCF_EMBEDDED_ABSPATH . '/includes/ajax/admin-header.php';
534
- return true;
535
- }
536
-
537
- global $pagenow;
538
- $hook_suffix = $pagenow;
539
-
540
- ?>
541
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
542
- <html xmlns="http://www.w3.org/1999/xhtml" <?php do_action( 'admin_xml_ns' ); ?> <?php language_attributes(); ?>>
543
- <head>
544
- <meta http-equiv="Content-Type" content="<?php bloginfo( 'html_type' ); ?>; charset=<?php echo get_option( 'blog_charset' ); ?>" />
545
- <title><?php echo $title; ?></title>
546
- <?php
547
- if ( wpcf_compare_wp_version( '3.2.1', '<=' ) ) {
548
- wp_admin_css( 'global' );
549
- }
550
- wp_admin_css();
551
- wp_admin_css( 'colors' );
552
- wp_admin_css( 'ie' );
553
- // do_action('admin_enqueue_scripts', $hook_suffix);
554
- do_action( "admin_print_styles-$hook_suffix" );
555
- do_action( 'admin_print_styles' );
556
- // do_action("admin_print_scripts-$hook_suffix");
557
- do_action( 'admin_print_scripts' );
558
- // do_action("admin_head-$hook_suffix");
559
- // do_action('admin_head');
560
- do_action( 'admin_head_wpcf_ajax' );
561
-
562
- ?>
563
- <style type="text/css">
564
- html { height: auto; }
565
- </style>
566
-
567
- <script type="text/javascript">
568
- // <![CDATA[
569
- jQuery(document).ready(function(){
570
- // Position the help link in the title bar.
571
- var title = jQuery('#TB_closeAjaxWindow', window.parent.document);
572
- if (title.length != 0) {
573
- title.after(jQuery('.wpcf-help-link'));
574
- }
575
- });
576
- // ]]>
577
- </script>
578
-
579
- <link rel="stylesheet" href="<?php echo WPCF_EMBEDDED_RES_RELPATH . '/css/basic.css'; ?>" type="text/css" media="all" />
580
-
581
- </head>
582
- <body style="padding: 20px;">
583
- <?php
584
- }
585
-
586
- /**
587
- * Renders page footer
588
- *
589
- * @see WPCF_Template::ajax_footer()
590
- */
591
- function wpcf_admin_ajax_footer() {
592
-
593
- /*
594
- * Since Types 1.2 and WP 3.5
595
- * AJAX footer is rendered differently
596
- */
597
- global $wp_version, $wpcf;
598
- if ( version_compare( $wp_version, '3.4', '>' ) ) {
599
- // WP Footer
600
- do_action( 'admin_footer_wpcf_ajax' );
601
- include WPCF_EMBEDDED_ABSPATH . '/includes/ajax/admin-footer.php';
602
- return true;
603
- }
604
-
605
- global $pagenow;
606
- do_action( 'admin_footer_wpcf_ajax' );
607
- // do_action('admin_footer', '');
608
- // do_action('admin_print_footer_scripts');
609
- // do_action("admin_footer-" . $pagenow);
610
-
611
- ?>
612
- </body>
613
- </html>
614
-
615
- <?php
616
- }
617
-
618
- /**
619
- * Renders JS settings.
620
- *
621
- * @return type
622
- */
623
- function wpcf_admin_render_js_settings() {
624
- $settings = wpcf_admin_add_js_settings( 'get' );
625
- if ( empty( $settings ) ) {
626
- return '';
627
- }
628
-
629
- ?>
630
- <script type="text/javascript">
631
- //<![CDATA[
632
- <?php
633
- foreach ( $settings as $id => $setting ) {
634
- if ( is_string( $setting ) ) {
635
- $setting = trim( $setting, '\'' );
636
- $setting = "'" . esc_js( $setting ) . "'";
637
- } else {
638
- $setting = intval( $setting );
639
- }
640
- echo 'var ' . $id . ' = ' . $setting . ';' . "\r\n";
641
- }
642
-
643
- ?>
644
- //]]>
645
- </script>
646
- <?php
647
- }
648
-
649
- /**
650
- * wpcf_get_fields
651
- *
652
- * returns the fields handled by types
653
- *
654
- */
655
- function wpcf_get_post_meta_field_names() {
656
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
657
- $fields = wpcf_admin_fields_get_fields();
658
-
659
- $field_names = array();
660
- foreach ( $fields as $field ) {
661
- $field_names[] = wpcf_types_get_meta_prefix( $field ) . $field['slug'];
662
- }
663
-
664
- return $field_names;
665
- }
666
-
667
- /**
668
- * Forces 'Insert into post' link when called from our WYSIWYG.
669
- *
670
- * @param array $args
671
- * @return boolean
672
- */
673
- function wpcf_get_media_item_args_filter( $args ) {
674
- if ( strpos( $_SERVER['SCRIPT_NAME'], '/media-upload.php' ) === false ) {
675
- return $args;
676
- }
677
- if ( !empty( $_COOKIE['wpcfActiveEditor'] )
678
- && strpos( $_COOKIE['wpcfActiveEditor'], 'wpcf-wysiwyg-' ) !== false ) {
679
- $args['send'] = true;
680
- }
681
- return $args;
682
- }
683
-
684
- /**
685
- * Gets post.
686
- *
687
- * @return type
688
- */
689
- function wpcf_admin_get_edited_post() {
690
- // Global $post_ID holds post IDs for new posts too.
691
- global $post_ID;
692
- if ( !empty( $post_ID ) ) {
693
- $post_id = $post_ID;
694
- } else if ( isset( $_GET['post'] ) ) {
695
- $post_id = (int) $_GET['post'];
696
- } else if ( isset( $_POST['post_ID'] ) ) {
697
- $post_id = (int) $_POST['post_ID'];
698
- } else {
699
- $post_id = 0;
700
- }
701
- if ( $post_id ) {
702
- return get_post( $post_id );
703
- } else {
704
- return array();
705
- }
706
- }
707
-
708
- /**
709
- * Gets post type.
710
- *
711
- * @param type $post
712
- * @return boolean
713
- */
714
- function wpcf_admin_get_edited_post_type( $post = null ) {
715
- if ( !empty( $post->ID ) ) {
716
- $post_type = get_post_type( $post );
717
- } else {
718
- if ( !isset( $_GET['post_type'] ) ) {
719
- $post_type = 'post';
720
- } else if ( in_array( $_GET['post_type'],
721
- get_post_types( array('show_ui' => true) ) ) ) {
722
- $post_type = $_GET['post_type'];
723
- } else {
724
- $post_type = 'post';
725
- }
726
- }
727
- return $post_type;
728
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/bootstrap.php DELETED
@@ -1,431 +0,0 @@
1
- <?php
2
- /*
3
- * Bootstrap code.
4
- *
5
- * Types plugin or embedded code is initialized here.
6
- * Here is determined if code is used as plugin or embedded code.
7
- *
8
- * @since Types 1.2
9
- *
10
- *
11
- */
12
-
13
- // Main functions
14
- require_once dirname( __FILE__ ) . '/functions.php';
15
-
16
- /*
17
- *
18
- *
19
- * If WPCF_VERSION is not defined - we're running embedded code
20
- */
21
- if ( !defined( 'WPCF_VERSION' ) ) {
22
- // Mark that!
23
- define( 'WPCF_RUNNING_EMBEDDED', true );
24
- require_once dirname( __FILE__ ) . '/classes/loader.php';
25
- }
26
-
27
- /*
28
- *
29
- * Forced priority
30
- */
31
- if ( !defined( 'TYPES_INIT_PRIORITY' ) ) {
32
- // Early start ( some plugins use 'init' with priority 0 ).
33
- define( 'TYPES_INIT_PRIORITY', -1 );
34
- }
35
-
36
- /**
37
- * custom filed groups - post type
38
- */
39
- define('TYPES_CUSTOM_FIELD_GROUP_CPT_NAME', 'wp-types-group');
40
-
41
- /**
42
- * user meta filed groups - post type
43
- */
44
- define('TYPES_USER_META_FIELD_GROUP_CPT_NAME', 'wp-types-user-group');
45
-
46
- /**
47
- * user meta filed groups - post type
48
- */
49
- define('TYPES_TERM_META_FIELD_GROUP_CPT_NAME', 'wp-types-term-group');
50
-
51
- /**
52
- * default capability
53
- */
54
-
55
- define('TYPES_CAPABILITY', 'manage_options');
56
-
57
- /**
58
- * last author
59
- */
60
- if ( !defined('WPCF_AUTHOR' )){
61
- define( 'WPCF_AUTHOR', '_wpcf_author_id');
62
- }
63
-
64
- /*
65
- *
66
- * Init
67
- */
68
- add_action( 'init', 'wpcf_embedded_init', TYPES_INIT_PRIORITY );
69
-
70
- /**
71
- * register_post_type & register_taxonomy - must be with default pririty to
72
- * handle defult taxonomies
73
- */
74
- /**
75
- * Priotity for wpcf_init_custom_types_taxonomies()
76
- *
77
- * Priotity for function wpcf_init_custom_types_taxonomies() in init WP
78
- * action..
79
- *
80
- */
81
- add_action( 'init', 'wpcf_init_custom_types_taxonomies', apply_filters('wpcf_init_custom_types_taxonomies', 10));
82
-
83
- /*
84
- *
85
- *
86
- * Define necessary constants
87
- */
88
- define( 'WPCF_EMBEDDED_ABSPATH', dirname( __FILE__ ) );
89
- define( 'WPCF_EMBEDDED_INC_ABSPATH', WPCF_EMBEDDED_ABSPATH . '/includes' );
90
- define( 'WPCF_EMBEDDED_RES_ABSPATH', WPCF_EMBEDDED_ABSPATH . '/resources' );
91
-
92
- /*
93
- *
94
- * Always set DEBUG as false
95
- */
96
- if ( !defined( 'WPCF_DEBUG' ) ) {
97
- define( 'WPCF_DEBUG', false );
98
- }
99
- if ( !defined( 'TYPES_DEBUG' ) ) {
100
- define( 'TYPES_DEBUG', false );
101
- }
102
-
103
- /*
104
- *
105
- * Load common and local localization
106
- */
107
- if ( !defined( 'WPT_LOCALIZATION' ) ) {
108
- require_once( WPCF_EMBEDDED_ABSPATH . '/toolset/toolset-common/localization/wpt-localization.php' );
109
- }
110
- new WPToolset_Localization( 'wpcf', WPCF_EMBEDDED_ABSPATH . '/locale', 'types-%s' );
111
-
112
- /*
113
- *
114
- * Include common code.
115
- */
116
- if ( !defined( 'ICL_COMMON_FUNCTIONS' ) ) {
117
- require_once WPCF_EMBEDDED_ABSPATH . '/toolset/toolset-common/functions.php';
118
- if ( !defined( 'WPTOOLSET_COMMON_PATH' ) ) {
119
- define( 'WPTOOLSET_COMMON_PATH', WPCF_EMBEDDED_ABSPATH . '/toolset/toolset-common' );
120
- }
121
- } else if ( !defined( 'WPTOOLSET_COMMON_PATH' ) ) {
122
- //$__types_common_reflection = new ReflectionFunction( 'wpv_condition' );
123
- //define( 'WPTOOLSET_COMMON_PATH', dirname( $__types_common_reflection->getFileName() ) );
124
- define( 'WPTOOLSET_COMMON_PATH', WPCF_EMBEDDED_ABSPATH . '/toolset/toolset-common' );
125
- }
126
- if ( !defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
127
- require_once WPTOOLSET_COMMON_PATH . '/toolset-forms/bootstrap.php';
128
- }
129
-
130
- /*
131
- *
132
- * Register theme options
133
- */
134
- wpcf_embedded_after_setup_theme_hook();
135
-
136
- /*
137
- *
138
- *
139
- * Set $wpcf global var as generic class
140
- */
141
- $GLOBALS['wpcf'] = new stdClass();
142
-
143
-
144
-
145
- /**
146
- * Initialize the autoloader (for newer parts of code).
147
- */
148
- function wpcf_initialize_autoloader_embedded() {
149
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/autoloader.php';
150
- $autoloader = WPCF_Autoloader::get_instance();
151
- $autoloader->add_prefix( 'WPCF' );
152
-
153
- // This will trigger the loading mechanism for legacy classes.
154
- $autoloader->add_prefix( 'Types' );
155
- $autoloader->add_prefix( 'WPToolset' );
156
-
157
- $autoloader->add_path( WPCF_EMBEDDED_ABSPATH . '/classes' );
158
- }
159
-
160
- wpcf_initialize_autoloader_embedded();
161
-
162
-
163
- /**
164
- * Main init hook.
165
- *
166
- * All rest of init processes are continued here.
167
- * Sets locale, constants, includes...
168
- *
169
- * @todo Make sure plugin AND embedded code are calling this function on 'init'
170
- * @todo Test priorities
171
- */
172
- function wpcf_embedded_init() {
173
-
174
- global $types_instances, $wp_current_filter;
175
-
176
- // Record hook
177
- $types_instances['hook'] = $wp_current_filter;
178
- $types_instances['init_queued'] = '#' . did_action( 'init' );
179
- $types_instances['init_priority'] = TYPES_INIT_PRIORITY;
180
- $types_instances['forced_embedded'] = defined( 'TYPES_LOAD_EMBEDDED' ) && TYPES_LOAD_EMBEDDED;
181
-
182
- // Loader
183
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/loader.php';
184
-
185
- do_action( 'wpcf_before_init' );
186
- do_action( 'types_before_init' );
187
-
188
- // Define necessary constants if plugin is not present
189
- // This ones are skipped if used as embedded code!
190
- if ( !defined( 'WPCF_VERSION' ) ) {
191
- define( 'WPCF_VERSION', '1.9' );
192
- define( 'WPCF_META_PREFIX', 'wpcf-' );
193
- }
194
-
195
- // If forced embedded mode use path to __FILE__
196
- if ( ( defined( 'TYPES_LOAD_EMBEDDED' ) && TYPES_LOAD_EMBEDDED )
197
- || !defined('WPCF_RELPATH') ) {
198
- define( 'WPCF_EMBEDDED_RELPATH', wpcf_get_file_url( __FILE__, false ) );
199
- } else {
200
- define( 'WPCF_EMBEDDED_RELPATH', WPCF_RELPATH . '/embedded' );
201
- }
202
-
203
- // Define embedded paths
204
- define( 'WPCF_EMBEDDED_INC_RELPATH', WPCF_EMBEDDED_RELPATH . '/includes' );
205
- define( 'WPCF_EMBEDDED_RES_RELPATH', WPCF_EMBEDDED_RELPATH . '/resources' );
206
-
207
- // TODO INCLUDES!
208
- //
209
- // Please add all required includes here
210
- // Since Types 1.2 we can consider existing code as core.
211
- // All new functionalities should be added as includes HERE
212
- // and marked with @since Types $version.
213
- //
214
- // Thanks!
215
- //
216
-
217
- // Basic
218
- /*
219
- *
220
- * Mind class extensions queue
221
- */
222
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/fields.php';
223
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/field.php';
224
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/usermeta_field.php'; // Added by Gen, usermeta fields class
225
-
226
- // Repeater
227
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/repeater.php';
228
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/usermeta_repeater.php'; // Added by Gen, usermeta repeater class
229
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/repetitive-fields-ordering.php';
230
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/repetitive-usermetafields-ordering.php';
231
-
232
- // Relationship
233
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/relationship.php';
234
-
235
- // Conditional
236
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/conditional.php';
237
-
238
- // API
239
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/api.php';
240
-
241
- // Validation
242
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/validation.php';
243
-
244
- // Post Types
245
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/class.wpcf-post-types.php';
246
-
247
- // Import Export
248
- require_once WPCF_EMBEDDED_ABSPATH . '/classes/class.wpcf-import-export.php';
249
-
250
- // Module manager
251
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/module-manager.php';
252
-
253
- // WPML specific code
254
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/wpml.php';
255
-
256
- // CRED specific code.
257
- if ( defined( 'CRED_FE_VERSION' ) ) {
258
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/cred.php';
259
- }
260
-
261
- /*
262
- *
263
- *
264
- * TODO This is a must for now.
265
- * See if any fields need to be loaded.
266
- *
267
- * 1. Checkboxes - may be missing when submitted
268
- */
269
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields/checkbox.php';
270
-
271
-
272
- /*
273
- *
274
- *
275
- * Use this call to load basic scripts and styles if necesary
276
- * wpcf_enqueue_scripts();
277
- */
278
- require_once WPCF_EMBEDDED_ABSPATH . '/usermeta-init.php';
279
- // Include frontend or admin code
280
- if ( is_admin() ) {
281
-
282
- require_once WPCF_EMBEDDED_ABSPATH . '/admin.php';
283
-
284
- /*
285
- * TODO Check if called twice
286
- *
287
- * Watch this! This is actually called twice everytime
288
- * in both modes (plugin or embedded)
289
- */
290
- wpcf_embedded_admin_init_hook();
291
- } else {
292
- require_once WPCF_EMBEDDED_ABSPATH . '/frontend.php';
293
- }
294
-
295
- global $wpcf;
296
-
297
- // TODO since Types 1.2 Continue adding new functionalities HERE
298
- /*
299
- * Consider code already there as core.
300
- * Use hooks to add new functionalities
301
- *
302
- * Introduced new global object $wpcf
303
- * Holds useful objects like:
304
- * $wpcf->field - Field object (base item object)
305
- * $wpcf->repeater - Repetitive field object
306
- */
307
-
308
- // Set debugging
309
- if ( !defined( 'WPCF_DEBUG' ) ) {
310
- define( 'WPCF_DEBUG', false );
311
- } else if ( WPCF_DEBUG ) {
312
- wp_enqueue_script( 'jquery' );
313
- }
314
- $wpcf->debug = new stdClass();
315
- require WPCF_EMBEDDED_INC_ABSPATH . '/debug.php';
316
- add_action( 'wp_footer', 'wpcf_debug', PHP_INT_MAX);
317
- add_action( 'admin_footer', 'wpcf_debug', PHP_INT_MAX);
318
-
319
- // Set field object
320
- $wpcf->field = new WPCF_Field();
321
-
322
- // Set fields object
323
- $wpcf->fields = new WPCF_Fields();
324
-
325
- // Set usermeta field object
326
- $wpcf->usermeta_field = new WPCF_Usermeta_Field();
327
-
328
- // Set termmeta field object
329
- $wpcf->termmeta_field = new WPCF_Termmeta_Field();
330
-
331
- // Set repeater object
332
- $wpcf->repeater = new WPCF_Repeater();
333
-
334
- // Set usermeta repeater object
335
- $wpcf->usermeta_repeater = new WPCF_Usermeta_Repeater();
336
-
337
- // Set termmeta repeater object
338
- $wpcf->termmeta_repeater = new WPCF_Termmeta_Repeater();
339
-
340
- // Set relationship object
341
- $wpcf->relationship = new WPCF_Relationship();
342
-
343
- // Set conditional object
344
- $wpcf->conditional = new WPCF_Conditional();
345
-
346
- // Set validate object
347
- $wpcf->validation = new WPCF_Validation();
348
-
349
- // Set import export objects
350
- $wpcf->import = new WPCF_Import_Export();
351
- $wpcf->export = new WPCF_Import_Export();
352
-
353
- // Set post object
354
- $wpcf->post = new stdClass();
355
-
356
- // Set post types object
357
- $wpcf->post_types = new WPCF_Post_Types();
358
-
359
- // Define exceptions - privileged plugins and their data
360
- $wpcf->toolset_post_types = array(
361
- 'view', 'view-template', 'cred-form', 'cred-user-form'
362
- );
363
- // 'attachment' = Media
364
- //
365
- $wpcf->excluded_post_types = array(
366
- 'cred-form',
367
- 'cred-user-form',
368
- 'dd_layouts',
369
- 'deprecated_log',
370
- 'mediapage',
371
- 'nav_menu_item',
372
- 'revision',
373
- 'view',
374
- 'view-template',
375
- 'wp-types-group',
376
- 'wp-types-user-group',
377
- );
378
-
379
- /**
380
- * Do use this CPT in Toolset "actions"
381
- *
382
- * Filter allow to add own post types which will be not used in
383
- * Toolset plugins
384
- *
385
- * @since 1.9.0
386
- *
387
- * @param array $post_types array of post types slugs
388
- */
389
- $wpcf->excluded_post_types = apply_filters( 'toolset_filter_exclude_own_post_types', $wpcf->excluded_post_types );
390
-
391
- // Init loader
392
- WPCF_Loader::init();
393
-
394
- /*
395
- * TODO Check why we enabled this
396
- *
397
- * I think because of CRED or Views using Types admin functions on frontend
398
- * Does this need review?
399
- */
400
- if ( defined( 'DOING_AJAX' ) ) {
401
- require_once WPCF_EMBEDDED_ABSPATH . '/frontend.php';
402
- }
403
-
404
- // Check if import/export request is going on
405
- wpcf_embedded_check_import();
406
-
407
- // Initialize (new) parts of the GUI.
408
- // Btw. current_screen is being fired during admin_init.
409
- add_action( 'current_screen', 'wpcf_initialize_admin_gui' );
410
-
411
- do_action( 'types_after_init' );
412
- do_action( 'wpcf_after_init' );
413
- }
414
-
415
-
416
- /**
417
- * Initialize parts of GUI depending on current screen.
418
- *
419
- * @since 1.9
420
- */
421
- function wpcf_initialize_admin_gui() {
422
-
423
- $screen = get_current_screen();
424
-
425
- // Should be always true.
426
- if( $screen instanceof WP_Screen ) {
427
- if( in_array( $screen->base, array( 'edit-tags', 'term' ) ) ) {
428
- WPCF_GUI_Term_Field_Editing::initialize();
429
- }
430
- }
431
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field.php DELETED
@@ -1,990 +0,0 @@
1
- <?php
2
- /*
3
- * Field class.
4
- *
5
- *
6
- */
7
-
8
- /**
9
- * Base class.
10
- *
11
- * Fields are our core items and we'll use this class to sort them out a little.
12
- * Very useful, should be used to finish small tasks for field.
13
- *
14
- * Example:
15
- *
16
- * // Setup field
17
- * global $wpcf;
18
- * $my_field = new WPCF_Field();
19
- * $my_field->set($wpcf->post, wpcf_admin_fields_get_field('image'));
20
- *
21
- * // Use it
22
- * $my_field->save();
23
- *
24
- * // Generic instance can be found in global $wpcf.
25
- * global $wpcf;
26
- * $wpcf->field->set(...);
27
- *
28
- * !! BE CAREFUL !! not to disturb global instance if you suspect processing
29
- * current item is not finished. Core code sometimes use same instance over
30
- * few functions and places.
31
- *
32
- * @since Types 1.2
33
- * @package Types
34
- * @subpackage Classes
35
- * @version 0.1
36
- * @category core
37
- * @author srdjan <srdjan@icanlocalize.com>
38
- */
39
- class WPCF_Field
40
- {
41
-
42
- /**
43
- * Field structure
44
- *
45
- * This is actually a form array collected from files per specific field:
46
- * /embedded/includes/fields/$field_type.php
47
- * /includes/fields/$field_type.php
48
- *
49
- * @var type array
50
- */
51
- var $cf = array();
52
-
53
- /**
54
- * All Types created fields
55
- * @var type
56
- */
57
- var $fields = null;
58
-
59
- /**
60
- * Field saved data
61
- * @var type
62
- */
63
- var $meta = null;
64
-
65
- /**
66
- * Field config.
67
- *
68
- * Use it to set default configuration.
69
- *
70
- * @var type array
71
- */
72
- var $config = array(
73
- 'use_form' => false,
74
- );
75
-
76
- /**
77
- * Form object
78
- * @var type array
79
- */
80
- var $form = array();
81
-
82
- /**
83
- * Sets post
84
- */
85
- var $post;
86
-
87
- /**
88
- * CF slug
89
- * @var type string
90
- */
91
- var $slug = '';
92
-
93
- /**
94
- * Use cache flag
95
- * @var type boolean
96
- */
97
- var $use_cache = true;
98
-
99
- /**
100
- * Cache.DEPRECATED
101
- *
102
- * @var type
103
- */
104
- var $cache = array();
105
-
106
- /**
107
- * Add to editor flas
108
- * @var type boolean
109
- */
110
- var $add_to_editor = true;
111
-
112
- /**
113
- * Context in which class is called
114
- * @var type
115
- */
116
- var $context = 'group';
117
-
118
- /**
119
- * Invalid fields
120
- *
121
- * @todo Revise
122
- * @var type
123
- */
124
- var $invalid_fields = array();
125
-
126
- /**
127
- * ID
128
- */
129
- var $ID = '';
130
-
131
- /**
132
- * Unique ID
133
- */
134
- var $unique_id = '';
135
-
136
- function __construct( $config = array() ) {
137
- // Parse args
138
- extract( wp_parse_args( (array) $config, $this->config ) );
139
- }
140
-
141
- /**
142
- * Set current post and field.
143
- *
144
- * @param type $post
145
- * @param type $cf
146
- */
147
- function set( $post, $cf ) {
148
-
149
- global $wpcf;
150
-
151
- /*
152
- *
153
- * Check if $cf is string
154
- */
155
- if ( is_string( $cf ) ) {
156
- WPCF_Loader::loadInclude( 'fields' );
157
- $_cf = wpcf_admin_fields_get_field( $this->__get_slug_no_prefix( $cf ) );
158
- // Check if found without prefix
159
- if ( empty( $_cf ) ) {
160
- $_cf = wpcf_admin_fields_get_field( $cf );
161
- }
162
- if ( empty( $_cf ) ) {
163
- /*
164
- * TODO Check what happens if field is not found
165
- */
166
- $this->_reset();
167
- return false;
168
- }
169
- $cf = $_cf;
170
- }
171
-
172
- $this->post = is_integer( $post ) ? get_post( $post ) : $post;
173
- // If empty post it is new
174
- if ( empty( $this->post->ID ) ) {
175
- $this->post = new stdClass();
176
- $this->post->ID = 0;
177
- }
178
- $this->ID = $cf['id'];
179
- $this->cf = $cf;
180
- $this->slug = wpcf_types_get_meta_prefix( $this->cf ) . $this->cf['slug'];
181
- $this->meta = $this->_get_meta();
182
- $this->config = $this->_get_config();
183
- $this->unique_id = wpcf_unique_id( serialize( (array) $this ) );
184
- $this->cf['value'] = $this->meta;
185
-
186
- // Debug
187
- $wpcf->debug->fields[$this->unique_id] = $this->cf;
188
- $wpcf->debug->meta[$this->slug][] = $this->meta;
189
-
190
- // Load files
191
- $this->_include_file_by_field_type($this->cf['type']);
192
- if ( defined( 'WPCF_INC_ABSPATH' ) ) {
193
- $file = WPCF_INC_ABSPATH . '/fields/' . preg_replace('/[^\w]+/', '', $this->cf['type']) . '.php';
194
- if ( file_exists( $file ) ) {
195
- include_once $file;
196
- }
197
- }
198
- }
199
-
200
- /**
201
- * Reset on failure.
202
- */
203
- function _reset() {
204
- $this->ID = '';
205
- $this->cf = array();
206
- $this->post = new stdClass();
207
- $this->slug = '';
208
- $this->meta = '';
209
- $this->__meta = '';
210
- $this->config = array();
211
- $this->unique_id = '';
212
- $this->cf['value'] = '';
213
- }
214
-
215
- /**
216
- * Set needed but not required form elements.
217
- *
218
- * @param string $cf
219
- */
220
- function _parse_cf_form_element( $cf ) {
221
- $p = array('#before' => '', '#after' => '', '#description' => '');
222
- foreach ( $p as $_p => $param ) {
223
- if ( !isset( $cf[$_p] ) ) {
224
- $cf[$_p] = $param;
225
- }
226
- }
227
- return $cf;
228
- }
229
-
230
- /**
231
- * Fetch and sort fields.
232
- *
233
- * @global object $wpdb
234
- *
235
- */
236
- function _get_meta() {
237
- global $wpdb;
238
-
239
- $cache_key = md5( 'field::_get_meta' . $this->post->ID . $this->slug );
240
- $cache_group = 'types_cache';
241
- $cached_object = wp_cache_get( $cache_key, $cache_group );
242
- if ( $this->use_cache ) {
243
- if ( false != $cached_object && is_array( $cached_object ) && isset( $cached_object[0] ) ) {// WordPress cache
244
- $r = $cached_object[0];
245
- } else {
246
- // Cache all the postmeta for this same post
247
- $all_postmeta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->postmeta} WHERE post_id=%d", $this->post->ID), OBJECT );
248
- if ( !empty( $all_postmeta ) ) {
249
- $cache_key_keys = array();
250
- foreach ( $all_postmeta as $metarow ) {
251
- $mpid = intval($metarow->post_id);
252
- $mkey = $metarow->meta_key;
253
- $cache_key_keys[$mpid . $mkey][] = $metarow;
254
- $cache_key_looped = md5( 'field::_get_meta' . $mpid . $mkey );
255
- if ( $mkey == $this->slug ) {
256
- $r = $metarow;
257
- }
258
- }
259
- foreach ( $cache_key_keys as $single_meta_keys => $single_meta_values ) {
260
- $cache_key_looped_new = md5( 'field::_get_meta' . $single_meta_keys );
261
- wp_cache_add( $cache_key_looped_new, $single_meta_values, $cache_group );// WordPress cache
262
- }
263
- }
264
- }
265
- } else {
266
- // If not using cache, get straight from DB single value
267
- $r = $wpdb->get_row(
268
- $wpdb->prepare(
269
- "SELECT * FROM $wpdb->postmeta
270
- WHERE post_id=%d
271
- AND meta_key=%s",
272
- $this->post->ID, $this->slug )
273
- );
274
- // Cache it
275
- wp_cache_add( $cache_key, array( $r ), $cache_group );// WordPress cache
276
- }
277
-
278
- // Sort meta
279
- $meta = array();
280
- if ( !empty( $r ) ) {
281
- $meta = maybe_unserialize( $r->meta_value );
282
- $this->meta_object = $r;
283
- } else {
284
- $meta = null;
285
- $this->meta_object = new stdClass();
286
- $this->meta_object->meta_id = null;
287
- $this->meta_object->meta_key = null;
288
- $this->meta_object->meta_value = null;
289
- }
290
-
291
- /*
292
- * Secret public object :)
293
- * Keeps original data
294
- */
295
- $this->__meta = $meta;
296
-
297
- /*
298
- * Apply filters
299
- */
300
- $meta = apply_filters( 'wpcf_fields_value_get', $meta, $this );
301
- $meta = apply_filters( 'wpcf_fields_slug_' . $this->cf['slug'] . '_value_get', $meta, $this );
302
- $meta = apply_filters( 'wpcf_fields_type_' . $this->cf['type'] . '_value_get', $meta, $this );
303
-
304
- return $meta;
305
- }
306
-
307
- /**
308
- * Gets $_POST data.
309
- *
310
- * @return type
311
- */
312
- function get_submitted_data() {
313
- $posted = isset( $_POST['wpcf'][$this->cf['slug']] ) ? $_POST['wpcf'][$this->cf['slug']] : null;
314
- $value = apply_filters( 'types_field_get_submitted_data', $posted, $this );
315
- return $value;
316
- }
317
-
318
- /**
319
- * Save field.
320
- *
321
- * If $value is empty, $_POST will be checked.
322
- * 1.3.2 Reverted saving empty fields
323
- * removed - if ( !empty( $value ) || is_numeric( $value ) ) {
324
- *
325
- * @param type $value
326
- */
327
- function save( $value = null )
328
- {
329
- // If $value null, look for submitted data
330
- if ( is_null( $value ) ) {
331
- $value = $this->get_submitted_data();
332
- }
333
- /**
334
- *
335
- * Since Types 1.2
336
- * We completely rewrite meta.
337
- * It has no impact on frontend and covers a lot of cases
338
- * (e.g. user change mode from single to repetitive)
339
- *
340
- */
341
- do_action('wpcf_postmeta_before_delete', $this->post, $this->cf);
342
- delete_post_meta( $this->post->ID, $this->slug );
343
- do_action('wpcf_postmeta_after_delete', $this->post, $this->cf);
344
- // Trim
345
- if ( is_string( $value ) ) {
346
- $value = trim( $value );
347
- }
348
- /**
349
- * setup what save to database if needed
350
- */
351
- if (
352
- $value
353
- && array_key_exists( 'data', $this->cf )
354
- && array_key_exists( 'set_value', $this->cf['data'] )
355
- ) {
356
- $value = $this->cf['data']['set_value'];
357
- }
358
- /**
359
- * apply filters
360
- */
361
- $_value = $this->_filter_save_postmeta_value( $value );
362
- $_value = $this->_filter_save_value( $_value );
363
- /**
364
- * Save field if needed
365
- */
366
- if (
367
- (
368
- !( is_null( $value ) || $value === false || $value === '' )
369
- || (
370
- isset($this->cf['data']['save_empty'])
371
- && 'yes' == $this->cf['data']['save_empty']
372
- )
373
- )
374
- ||
375
- /**
376
- * handle "save zero as set value"
377
- */
378
- (
379
- array_key_exists( 'set_value', $this->cf['data'] )
380
- && preg_match( '/^0$/', $value )
381
- && preg_match( '/^0$/', $this->cf['data']['set_value'] )
382
- )
383
- ) {
384
- $mid = add_post_meta( $this->post->ID, $this->slug, $_value );
385
- /*
386
- * Use these hooks to add future functionality.
387
- * Do not add any more code to core.
388
- */
389
- $this->_action_save( $this->cf, $_value, $mid, $value );
390
- }
391
- }
392
-
393
- /**
394
- * Apply filters to saved value.
395
- *
396
- * @param type $value
397
- * @return type
398
- */
399
- function _filter_save_value( $value )
400
- {
401
- // Apply filters
402
- $value = apply_filters( 'wpcf_fields_value_save', $value, $this->cf['type'], $this->cf['slug'], $this->cf, $this );
403
- $value = apply_filters( 'wpcf_fields_slug_' . $this->cf['slug'] . '_value_save', $value, $this->cf, $this );
404
- $value = apply_filters( 'wpcf_fields_type_' . $this->cf['type'] . '_value_save', $value, $this->cf, $this );
405
-
406
- return $value;
407
- }
408
-
409
- function _filter_save_postmeta_value( $value )
410
- {
411
- $value = apply_filters( 'wpcf_fields_postmeta_value_save', $value, $this->cf['type'], $this->cf['slug'], $this->cf, $this );
412
- return $value;
413
- }
414
-
415
- function _filter_save_usermeta_value( $value )
416
- {
417
- $value = apply_filters( 'wpcf_fields_usermeta_value_save', $value, $this->cf['type'], $this->cf['slug'], $this->cf, $this );
418
- return $value;
419
- }
420
-
421
- function _filter_save_termmeta_value( $value )
422
- {
423
- $value = apply_filters( 'wpcf_fields_termmeta_value_save', $value, $this->cf['type'], $this->cf['slug'], $this->cf, $this );
424
- return $value;
425
- }
426
-
427
- /**
428
- * Use these hooks to add future functionality.
429
- * Do not add any more code to core.
430
- *
431
- * @param type $field
432
- * @param type $value
433
- * @param type $meta_id
434
- */
435
- function _action_save( $field, $value, $meta_id, $meta_value_original )
436
- {
437
- do_action( 'wpcf_fields_save', $value, $field, $this, $meta_id, $meta_value_original );
438
- do_action( 'wpcf_fields_slug_' . $field['slug'] . '_save', $value, $field, $this, $meta_id, $meta_value_original );
439
- do_action( 'wpcf_fields_type_' . $field['type'] . '_save', $value, $field, $this, $meta_id, $meta_value_original );
440
- }
441
-
442
- /**
443
- * Get file fullpath to include
444
- *
445
- * param @string $basename
446
- *
447
- * return @string
448
- *
449
- */
450
- function _include_file_by_field_type($basename)
451
- {
452
- $file = wpcf_get_fullpath_by_field_type($basename);
453
- if ( file_exists( $file ) ) {
454
- include_once $file;
455
- }
456
- return $file;
457
- }
458
-
459
- /**
460
- * Sets field config.
461
- *
462
- * @return type
463
- */
464
- function _get_config() {
465
- $this->_include_file_by_field_type($this->cf['type']);
466
- $func = 'wpcf_fields_' . $this->cf['type'];
467
- if ( is_callable( $func ) ) {
468
- return (object) call_user_func( $func );
469
- }
470
- return new stdClass();
471
- }
472
-
473
- /**
474
- * Discouraged usage.
475
- *
476
- * @return type
477
- */
478
- function _deprecated_inherited_allowed() {
479
- return array(
480
- 'image' => 'file',
481
- 'numeric' => 'textfield',
482
- 'email' => 'textfield',
483
- 'phone' => 'textfield',
484
- 'url' => 'textfield',
485
- );
486
- }
487
-
488
- /**
489
- * Sets field meta box form.
490
- *
491
- * @return type
492
- */
493
- function _get_meta_form( $meta_value = null, $meta_id = null, $wrap = true ) {
494
-
495
- /*
496
- * Note that field may be registered outside of Types.
497
- * In that case, it's on developer to make sure it's loaded.
498
- */
499
- $this->_include_file_by_field_type($this->cf['type']);
500
-
501
- /*
502
- * Set value
503
- *
504
- * IMPORTANT
505
- * Here we set values for form elements
506
- */
507
- $this->cf['value'] = is_null( $meta_value ) ? $this->meta : $meta_value;
508
-
509
- $form = array();
510
- $form_meta_box = array();
511
- $inherited = array();
512
- $this->__multiple = false;
513
-
514
- // Open main wrapper
515
- if ( $wrap ) {
516
- $form['__meta_form_OPEN'] = array(
517
- '#type' => 'markup',
518
- '#markup' => ''
519
- . '<div id="wpcf_wrapper_' . $this->unique_id
520
- . '" class="wpcf-wrap wpcf-meta-form">',
521
- );
522
- }
523
-
524
- /*
525
- *
526
- *
527
- *
528
- *
529
- * Since Types 1.2
530
- * Avoid using parent (inherited) type
531
- * $this->config->inherited_field_type
532
- */
533
- // See if inherited data and merge
534
- if ( isset( $this->config->inherited_field_type ) ) {
535
- if ( !array_key_exists( $this->cf['type'],
536
- $this->_deprecated_inherited_allowed() ) ) {
537
- // _deprecated_argument( 'inherited_field_type', '1.2',
538
- // 'Since Types 1.2 we encourage developers to completely define fields' );
539
- }
540
- $file = $this->_include_file_by_field_type($this->config->inherited_field_type);
541
-
542
- if ( file_exists( $file ) ) {
543
-
544
- if ( function_exists( 'wpcf_fields_'
545
- . $this->config->inherited_field_type
546
- . '_meta_box_form' ) ) {
547
- $inherited = call_user_func_array( 'wpcf_fields_'
548
- . $this->config->inherited_field_type
549
- . '_meta_box_form', array($this->cf, $this) );
550
- // If single form - convert to array of elements
551
- if ( isset( $inherited['#type'] ) ) {
552
- $inherited = array('wpcf_field_' . $this->unique_id => $inherited);
553
- }
554
-
555
- // One value?
556
- if ( count( $inherited ) > 1 ) {
557
- $this->__multiple = true;
558
- }
559
-
560
- $form = $form + $inherited;
561
- }
562
- }
563
- }
564
-
565
- $func = 'wpcf_fields_' . $this->cf['type'] . '_meta_box_form';
566
- if ( is_callable( $func ) ) {
567
- /*
568
- *
569
- * From Types 1.2 use complete form setup
570
- */
571
- $form_meta_box = call_user_func_array( 'wpcf_fields_'
572
- . $this->cf['type'] . '_meta_box_form',
573
- array($this->cf, $this) );
574
-
575
- // If single form - convert to array of elements
576
- if ( isset( $form_meta_box['#type'] ) ) {
577
- $form_meta_box = array('wpcf_field_' . $this->unique_id => $form_meta_box);
578
- }
579
-
580
- // One value?
581
- if ( count( $form_meta_box ) > 1 ) {
582
- $this->__multiple = true;
583
- }
584
-
585
- // Merge
586
- $form = array_merge( $form, $form_meta_box );
587
- }
588
-
589
- if ( !empty( $form ) ) {
590
-
591
- // Process each field
592
- foreach ( $form as $element_key => $element ) {
593
-
594
- /*
595
- *
596
- * Start using __ in keys to skip element
597
- */
598
- // Skip protected
599
- if ( strpos( $element_key, '__' ) === 0 ) {
600
- $form[$element_key] = $element;
601
- continue;
602
- }
603
-
604
- // Add title and description
605
- // TODO WPML
606
- if ( empty( $started ) ) {
607
- $_title = isset( $element['#title'] ) ? $element['#title'] : $this->cf['name'];
608
- $element['#title'] = wpcf_translate( 'field '
609
- . $this->cf['id'] . ' name', $_title );
610
-
611
- // Add asterisk for required fields
612
- if ( isset( $this->cf['data']['validate']['required'] ) ) {
613
- $element['#title'] .= '&#42;';
614
- }
615
-
616
- $_description = isset( $element['#description'] ) ? $element['#description'] : $this->cf['description'];
617
- $element['#description'] = wpautop( wpcf_translate( 'field '
618
- . $this->cf['id'] . ' description',
619
- $_description ) );
620
- $started = true;
621
- }
622
-
623
- // Set current element
624
- $this->__current_form_element = $element;
625
-
626
- // Process field
627
- $temp_processed = wpcf_admin_post_process_field( $this );
628
- if ( !empty( $temp_processed['element'] ) ) {
629
- $element = $temp_processed['element'];
630
- }
631
-
632
- // Set form element
633
- $form[$element_key] = apply_filters( 'wpcf_post_edit_field', $element, $this->cf, $this->post, $this->context );
634
- }
635
-
636
- // Add to editor
637
- if ( $this->add_to_editor ) {
638
- wpcf_admin_post_add_to_editor( $this->cf );
639
- }
640
-
641
- $this->enqueue_script();
642
- $this->enqueue_style();
643
- }
644
-
645
- // Close main wrapper
646
- if ( $wrap ) {
647
- $form['meta_form_CLOSE'] = array(
648
- '#type' => 'markup',
649
- '#markup' => ''
650
- . '</div>',
651
- );
652
- }
653
-
654
- // Add unique IDs
655
- foreach ( $form as $k => $v ) {
656
- $_form[$k . '_' . $this->unique_id] = $v;
657
- }
658
-
659
- return apply_filters( 'wpcf_meta_form', $_form );
660
- }
661
-
662
- /**
663
- * Enqueue all files from config
664
- */
665
- function enqueue_script( $config = null ) {
666
- // Use internal
667
- if ( is_null( $config ) ) {
668
- $config = $this->config;
669
- }
670
- $config = (object) $config;
671
- // Process JS
672
- if ( !empty( $config->meta_box_js ) ) {
673
- foreach ( $config->meta_box_js as $handle => $data_script ) {
674
- if ( isset( $data_script['inline'] ) ) {
675
- add_action( 'admin_footer', $data_script['inline'] );
676
- continue;
677
- }
678
- if ( !isset( $data_script['src'] ) ) {
679
- continue;
680
- }
681
- $deps = isset($data_script['deps']) && !empty( $data_script['deps'] ) ? $data_script['deps'] : array();
682
- $in_footer = isset($data_script['in_footer']) && $data_script['in_footer'];
683
- $ver = !empty( $data_script['ver'] ) ? $data_script['ver'] : WPCF_VERSION;
684
- wp_enqueue_script( $handle, $data_script['src'], $deps, $ver, $in_footer);
685
- }
686
- }
687
- }
688
-
689
- /**
690
- * Enqueue all files from config
691
- */
692
- function enqueue_style( $config = null ) {
693
- // Use internal
694
- if ( is_null( $config ) ) {
695
- $config = $this->config;
696
- }
697
- $config = (object) $config;
698
- if ( !empty( $config->meta_box_css ) ) {
699
- foreach ( $config->meta_box_css as $handle => $data_script ) {
700
- $deps = !empty( $data_script['deps'] ) ? $data_script['deps'] : array();
701
- if ( isset( $data_script['inline'] ) ) {
702
- add_action( 'admin_head', $data_script['inline'] );
703
- continue;
704
- }
705
- if ( !isset( $data_script['src'] ) ) {
706
- continue;
707
- }
708
- wp_enqueue_style( $handle, $data_script['src'], $deps,
709
- WPCF_VERSION );
710
- }
711
- }
712
- }
713
-
714
- /**
715
- * Use this function to add final filters to HTML output.
716
- *
717
- * @param type $output
718
- */
719
- function html( $html, $params )
720
- {
721
- /**
722
- * check input
723
- */
724
- if ( is_array($html) || is_object($html) ) {
725
- return '';
726
- }
727
- /**
728
- *
729
- * Exception when RAW = TRUE.
730
- * Return unchanged value.
731
- *
732
- */
733
- if ( isset( $params['raw'] ) && $params['raw'] == 'true' ) {
734
- return $html;
735
- } else {
736
- $html = stripslashes( $html );
737
- }
738
- // Process shortcodes too
739
- $html = do_shortcode( $html );
740
- return $html;
741
- }
742
-
743
- /**
744
- * Determines if field is created with Types.
745
- *
746
- * @param type $field_key
747
- */
748
- function is_under_control( $field_key ) {
749
- /*
750
- *
751
- * We force checking our meta prefix
752
- */
753
- $key = $this->__get_slug_no_prefix( $field_key );
754
- return WPCF_Fields::isUnderControl( $key );
755
- }
756
-
757
- /**
758
- * Return slug.
759
- *
760
- * @param type $meta_key
761
- * @return type
762
- */
763
- function __get_slug_no_prefix( $meta_key ) {
764
- return strpos( $meta_key, WPCF_META_PREFIX ) === 0 ? substr( $meta_key,
765
- strlen( WPCF_META_PREFIX ) ) : $meta_key;
766
- }
767
-
768
- /**
769
- * Returns altered element form name.
770
- *
771
- * Use $prefix to set name like:
772
- * wpcf_post_relationship[214][wpcf-my-checkbox]
773
- *
774
- * Or if multi array
775
- * wpcf_post_relationship[214][wpcf-my-date][datepicker]
776
- * wpcf_post_relationship[214][wpcf-my-date][hour]
777
- *
778
- * @param type $prefix
779
- * @param type $name
780
- * @return type
781
- */
782
- function alter_form_name( $prefix, $name ) {
783
- $temp = explode( '[', $name );
784
- $temp = array_pop( $temp );
785
- $__name = trim( strval( $temp ), ']' );
786
- /*
787
- * This means form is single-valued
788
- */
789
- if ( $__name == $this->cf['slug'] ) {
790
- return strval( $prefix ) . '['
791
- . $this->post->ID
792
- . '][' . $this->slug . ']';
793
- /*
794
- *
795
- * Multi array case
796
- */
797
- } else {
798
- return strval( $prefix ) . '['
799
- . $this->post->ID
800
- . '][' . $this->slug . '][' . $__name . ']';
801
- }
802
- }
803
-
804
- }
805
-
806
- /*
807
- * Usermeta Field class extends Field.
808
- */
809
-
810
- //require_once WPCF_EMBEDDED_ABSPATH . '/classes/field.php';
811
-
812
-
813
- class WPCF_Termmeta_Field extends WPCF_Field
814
- {
815
-
816
- /**
817
- * Set current post and field.
818
- *
819
- * @param type $post
820
- * @param type $cf
821
- */
822
- function set( $term_id, $cf ) {
823
-
824
- global $wpcf;
825
-
826
- /*
827
- *
828
- * Check if $cf is string
829
- */
830
- if ( is_string( $cf ) ) {
831
- WPCF_Loader::loadInclude( 'fields' );
832
- $cf = types_get_field( $this->__get_slug_no_prefix( $cf ), 'termmeta' );
833
- if ( empty( $cf ) ) {
834
- $this->_reset();
835
- return false;
836
- }
837
- }
838
-
839
- $this->term_id = $term_id;
840
- $this->ID = $cf['id'];
841
- $this->cf = $cf;
842
- $this->slug = wpcf_types_get_meta_prefix( $this->cf ) . $this->cf['slug'];
843
- $this->meta = $this->_get_meta();
844
- $this->config = $this->_get_config();
845
- $this->unique_id = wpcf_unique_id( serialize( (array) $this ) );
846
- $this->cf['value'] = $this->meta;
847
- // Debug
848
- $wpcf->debug->fieds[$this->unique_id] = $this->cf;
849
- $wpcf->debug->meta[$this->slug][] = $this->meta;
850
-
851
- // Load files
852
- if ( isset( $this->cf['type'] ) ) {
853
- $file = WPCF_EMBEDDED_INC_ABSPATH . '/fields/' . $this->cf['type'] . '.php';
854
- if ( file_exists( $file ) ) {
855
- include_once $file;
856
- }
857
- if ( defined( 'WPCF_INC_ABSPATH' ) ) {
858
- $file = WPCF_INC_ABSPATH . '/fields/' . $this->cf['type'] . '.php';
859
- if ( file_exists( $file ) ) {
860
- include_once $file;
861
- }
862
- }
863
- }
864
- }
865
-
866
- /**
867
- * Save usermeta field.
868
- *
869
- *
870
- * @param type $value
871
- */
872
- function termmeta_save( $value = null ) {
873
-
874
- // If $value null, look for submitted data
875
- if ( is_null( $value ) ) {
876
- $value = $this->get_submitted_data();
877
- }
878
- /*
879
- *
880
- *
881
- * Since Types 1.2
882
- * We completely rewrite meta.
883
- * It has no impact on frontend and covers a lot of cases
884
- * (e.g. user change mode from single to repetitive)
885
- */
886
-
887
- delete_term_meta( $this->term_id, $this->slug );
888
-
889
-
890
- // Save
891
- if ( !empty( $value ) || is_numeric( $value ) ) {
892
-
893
- // Trim
894
- if ( is_string( $value ) ) {
895
- $value = trim( $value );
896
- }
897
-
898
- // Apply filters
899
- $_value = $this->_filter_save_termmeta_value( $value );
900
- $_value = $this->_filter_save_value( $_value );
901
- if ( !empty( $_value ) || is_numeric( $_value ) ) {
902
- // Save field
903
- $mid = update_term_meta( $this->term_id, $this->slug, $_value );
904
- $this->_action_save( $this->cf, $_value, $mid, $value );
905
- }
906
- }
907
- }
908
-
909
- /**
910
- * Fetch and sort fields.
911
- *
912
- * @global object $wpdb
913
- *
914
- */
915
- function _get_meta() {
916
- global $wpdb;
917
-
918
- $cache_key = md5( 'termmeta::_get_meta' . $this->term_id . $this->slug );
919
- $cache_group = 'types_cache';
920
- $cached_object = wp_cache_get( $cache_key, $cache_group );
921
-
922
- if ( $this->use_cache ) {
923
- if ( false != $cached_object && is_array( $cached_object ) && isset( $cached_object[0] ) ) {// WordPress cache
924
- $r = $cached_object[0];
925
- } else {
926
- // Cache all the postmeta for this same user
927
- $all_termmeta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->termmeta} WHERE term_id=%d", $this->term_id), OBJECT );
928
- if ( !empty( $all_termmeta ) ) {
929
- $cache_key_keys = array();
930
- foreach ( $all_termmeta as $metarow ) {
931
- $mpid = intval($metarow->term_id);
932
- $mkey = $metarow->meta_key;
933
- $cache_key_keys[$mpid . $mkey][] = $metarow;
934
- $cache_key_looped = md5( 'termmeta::_get_meta' . $mpid . $mkey );
935
- if ( $mkey == $this->slug ) {
936
- $r = $metarow;
937
- }
938
- }
939
- foreach ( $cache_key_keys as $single_meta_keys => $single_meta_values ) {
940
- $cache_key_looped_new = md5( 'termmeta::_get_meta' . $single_meta_keys );
941
- wp_cache_add( $cache_key_looped_new, $single_meta_values, $cache_group );// WordPress cache
942
- }
943
- }
944
- }
945
- } else {
946
- // Get straight from DB single value
947
- $r = $wpdb->get_row(
948
- $wpdb->prepare(
949
- "SELECT * FROM {$wpdb->termmeta}
950
- WHERE term_id=%d
951
- AND meta_key=%s",
952
- $this->term_id, $this->slug )
953
- );
954
- // Cache it
955
- wp_cache_add( $cache_key, array( $r ), $cache_group );// WordPress cache
956
- }
957
-
958
- // Sort meta
959
- $meta = array();
960
- if ( !empty( $r ) ) {
961
- $meta = maybe_unserialize( $r->meta_value );
962
- $this->meta_object = $r;
963
- } else {
964
- $meta = null;
965
- $this->meta_object = new stdClass();
966
- $this->meta_object->meta_id = null;
967
- $this->meta_object->meta_key = null;
968
- $this->meta_object->meta_value = null;
969
- }
970
-
971
- /*
972
- * Secret public object :)
973
- * Keeps original data
974
- */
975
- $this->__meta = $meta;
976
-
977
- /*
978
- *
979
- * Apply filters
980
- * !!! IMPORTANT !!!
981
- * TODO Make this only place where field meta value is filtered
982
- */
983
- $meta = apply_filters( 'wpcf_fields_value_get', $meta, $this );
984
- $meta = apply_filters( 'wpcf_fields_slug_' . $this->cf['slug'] . '_value_get', $meta, $this );
985
- $meta = apply_filters( 'wpcf_fields_type_' . $this->cf['type'] . '_value_get', $meta, $this );
986
- return $meta;
987
- }
988
-
989
- }
990
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/data_saver.php DELETED
@@ -1,151 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Handles processing POST data from a toolset-forms form and updates a single field.
5
- *
6
- * @since 1.9
7
- */
8
- final class WPCF_Field_Data_Saver {
9
-
10
-
11
- /** @var WPCF_Field_Instance */
12
- private $field;
13
-
14
-
15
- /** @var string */
16
- private $form_id;
17
-
18
-
19
- /**
20
- * WPCF_Field_Data_Saver constructor.
21
- *
22
- * @param WPCF_Field_Instance $field_instance Field that should be updated.
23
- * @param string $form_id ID attribute of the form element that is being read from.
24
- * @throws InvalidArgumentException
25
- */
26
- public function __construct( $field_instance, $form_id ) {
27
- if( ! $field_instance instanceof WPCF_Field_Instance ) {
28
- throw new InvalidArgumentException( 'Invalid field instance (must be an field of existing object).' );
29
- }
30
-
31
- $this->field = $field_instance;
32
- $this->form_id = $form_id;
33
- }
34
-
35
-
36
- private $field_values = null;
37
-
38
-
39
- /**
40
- * Read the field values from $_POST.
41
- *
42
- * @return array Values in the "intermediate" format (see WPCF_Field_DataMapper_Abstract). For non-repetitive values,
43
- * it will be an array with a single item.
44
- */
45
- private function read_field_values() {
46
-
47
- if( null == $this->field_values ) {
48
- $definition = $this->field->get_definition();
49
-
50
- $form_data = wpcf_ensarr( wpcf_getpost( 'wpcf' ) );
51
-
52
- $values = wpcf_getarr( $form_data, $definition->get_slug() );
53
-
54
- // Handle single fields.
55
- if ( ! $definition->get_is_repetitive() ) {
56
- $values = array( $values );
57
- }
58
-
59
- // Map POST values to intermediate format.
60
- $this->field_values = array();
61
- $data_mapper = $definition->get_data_mapper();
62
- foreach( $values as $value ) {
63
- $this->field_values[] = $data_mapper->post_to_intermediate( $value, $form_data );
64
- }
65
- }
66
-
67
- return wpcf_ensarr( $this->field_values );
68
- }
69
-
70
-
71
- /**
72
- * @return array Array of true and WP_Error, one for each field value.
73
- */
74
- public function validate_field_data() {
75
-
76
- $field_config = WPCF_Field_Utils::get_toolset_forms_field_config( $this->field );
77
-
78
- $this->toggle_adding_field_names_to_error_messages( false );
79
-
80
- $values = $this->read_field_values();
81
- $results = array();
82
- foreach( $values as $key => $value ) {
83
- $results[ $key ] = $this->validate_single_field_value( $field_config, $value );
84
- }
85
-
86
- $this->toggle_adding_field_names_to_error_messages( true );
87
-
88
- return $results;
89
- }
90
-
91
-
92
- private function is_all_field_data_valid() {
93
- $validation_results = $this->validate_field_data();
94
- foreach( $validation_results as $validation_result ) {
95
- if( $validation_result instanceof WP_Error ) {
96
- return false;
97
- }
98
- }
99
-
100
- return true;
101
- }
102
-
103
-
104
- /**
105
- * Sets if toolset-forms will be adding field name to error messages (that will be returned as WP_Error objects).
106
- *
107
- * Default is to add field names, make sure you return to this state afterwards.
108
- *
109
- * @param bool $add_field_name True if field name should be added to error messages.
110
- */
111
- private function toggle_adding_field_names_to_error_messages( $add_field_name ) {
112
- if( false == $add_field_name ) {
113
- add_filter( 'toolset_common_validation_add_field_name_to_error', '__return_false' );
114
- } else {
115
- remove_filter( 'toolset_common_validation_add_field_name_to_error', '__return_false' );
116
- }
117
- }
118
-
119
-
120
- /**
121
- * @param $field_config
122
- * @param $value
123
- *
124
- * @return true|WP_Error
125
- */
126
- private function validate_single_field_value( $field_config, $value ) {
127
- return wptoolset_form_validate_field( $this->form_id, $field_config, $value );
128
- }
129
-
130
-
131
- /**
132
- * Update field value if it is valid.
133
- *
134
- * @return bool|WP_Error True on success, false or WP_Error on failure.
135
- */
136
- public function save_field_data() {
137
-
138
- if( !$this->is_all_field_data_valid() ) {
139
- return new WP_Error( 'Attempt to save a field with invalid value.' );
140
- }
141
-
142
- $values = $this->read_field_values();
143
-
144
- $is_success = $this->field->update_all_values( $values );
145
-
146
- return $is_success;
147
-
148
- }
149
-
150
-
151
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/datamapper/checkboxes.php DELETED
@@ -1,54 +0,0 @@
1
- <?php
2
-
3
- class WPCF_Field_DataMapper_Checkboxes extends WPCF_Field_DataMapper_Abstract {
4
-
5
-
6
- /** @var WPCF_Field_Definition */
7
- protected $field_definition;
8
-
9
-
10
- /**
11
- * @param WPCF_Field_Definition $field_definition Must be a definition of a checkboxes field.
12
- */
13
- public function __construct( $field_definition ) {
14
- parent::__construct( $field_definition );
15
-
16
- if( $field_definition->get_type()->get_slug() != WPCF_Field_Type_Definition_Factory::CHECKBOXES ) {
17
- throw new InvalidArgumentException( 'Wrong field definition type.' );
18
- }
19
- }
20
-
21
-
22
- /**
23
- * Theoretically this should be placed in self::post_to_intermediate(), but toolset-forms & legacy code
24
- * might expect the POST data instead what I think should be the intermediate format.
25
- *
26
- * First of all, $value is expected to be an array. If checkbox is checked, an element with its id as key and value
27
- * will be present. In that case it will be stored in the same way. If it's not checked, we either store nothing
28
- * or a zero, depending on the field definition setting "Save empty value".
29
- *
30
- * @param array|mixed $value
31
- *
32
- * @return array
33
- */
34
- public function intermediate_to_database( $value ) {
35
-
36
- $options = $this->field_definition->get_field_options();
37
-
38
- $result = array();
39
-
40
- foreach ( $options as $option_id => $ignored ) {
41
- $option_is_checked = isset( $value[ $option_id ] );
42
-
43
- if ( $option_is_checked ) {
44
- $result[ $option_id ] = $value[ $option_id ];
45
- } else if ( $this->field_definition->get_should_save_empty_value() ) {
46
- $result[ $option_id ] = 0;
47
- }
48
-
49
- }
50
-
51
- return $result;
52
- }
53
-
54
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/definition.php DELETED
@@ -1,362 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Definition of a field.
5
- *
6
- * Children of this class must be instantiated exclusively through a factory class inherited from WPCF_Field_Definition_Factory.
7
- *
8
- * Note about field definition identification: For historical reasons, there are several, possibly equal, values available:
9
- * The field key (key in the associative array of field definitions), slug, id and meta_key. While the meta_key's role
10
- * is clear - it determines how field's data are stored in postmeta -, the first three values seem to be completely
11
- * identical. Since the slug is used to organize fields into groups, we will use that as the main unique identifier
12
- * from now on.
13
- *
14
- * @since 1.9
15
- */
16
- abstract class WPCF_Field_Definition extends WPCF_Field_Definition_Abstract {
17
-
18
-
19
- /**
20
- * For a Types field, this is a default prefix to it's slug that defines the meta_key for storing this field's values.
21
- * Note that other custom fields that are brought under Types control additionally don't have to use this prefix
22
- * and can have completely arbitrary meta_keys.
23
- */
24
- const FIELD_META_KEY_PREFIX = 'wpcf-';
25
-
26
-
27
- /**
28
- * @var WPCF_Field_Type_Definition Type definition.
29
- */
30
- private $type;
31
-
32
-
33
- /**
34
- * @var array The underlying array with complete information about this field.
35
- * @todo We need a specification of everything that can be in it.
36
- */
37
- /*
38
-
39
- Example of an field definition:
40
-
41
- array (
42
- 'id' => 'field-1',
43
- 'slug' => 'field-1',
44
- 'type' => 'textfield',
45
- 'name' => 'Field 1',
46
- 'description' => '',
47
- 'data' => array
48
- (
49
- 'placeholder' => '',
50
- 'user_default_value' => '',
51
- 'repetitive' => '0',
52
- 'is_new' => '1',
53
- 'conditional_display' => array
54
- (
55
- 'custom_use' => '0',
56
- 'relation' => 'AND',
57
- 'custom' => '',
58
- ),
59
- 'submit-key' => 'textfield-1955088717',
60
- 'disabled_by_type' => 0,
61
- 'set_value' => ... (optional, presence is relevant)
62
- ),
63
- 'meta_key' => 'wpcf-field-1',
64
- 'meta_type' => 'postmeta',
65
- ),
66
- ); */
67
- private $definition_array;
68
-
69
-
70
- /**
71
- * @var string Field slug.
72
- */
73
- private $slug;
74
-
75
-
76
- /**
77
- * @var string Name of the field that can be displayed to the user.
78
- */
79
- private $name;
80
-
81
-
82
-
83
- /**
84
- * WPCF_Field_Definition constructor.
85
- *
86
- * @param WPCF_Field_Type_Definition $type Field type definition.
87
- * @param array $definition_array The underlying array with complete information about this field.
88
- * @throws InvalidArgumentException
89
- * @since 1.9
90
- */
91
- public function __construct( $type, $definition_array ) {
92
-
93
- if( ! $type instanceof WPCF_Field_Type_Definition ) {
94
- throw new InvalidArgumentException( 'Invalid field type.' );
95
- }
96
-
97
- $this->type = $type;
98
-
99
- $this->definition_array = wpcf_ensarr( $definition_array );
100
-
101
- $this->slug = wpcf_getarr( $definition_array, 'slug' );
102
- if( sanitize_title( $this->slug ) != $this->slug ) {
103
- throw new InvalidArgumentException( 'Invalid slug.' );
104
- }
105
-
106
- $this->name = sanitize_text_field( wpcf_getarr( $definition_array, 'name', $this->get_slug() ) );
107
- }
108
-
109
-
110
-
111
- public function get_slug() { return $this->slug; }
112
-
113
-
114
- public function get_name() { return $this->name; }
115
-
116
-
117
- /**
118
- * @return string Proper display name suitable for direct displaying to the user.
119
- *
120
- * Handles string translation and adds an asterisk if the field is required.
121
- *
122
- * @since 1.9
123
- */
124
- public function get_display_name() {
125
-
126
- // Try to translate through standard toolset-forms method
127
- $string_name = sprintf( 'field %s name', $this->get_slug() );
128
- $display_name = WPToolset_Types::translate( $string_name, $this->get_name() );
129
-
130
- // Add an asterisk if the field is required
131
- if( $this->get_is_required() && !empty( $display_name ) ) {
132
- $display_name .= '&#42;';
133
- }
134
- return $display_name;
135
- }
136
-
137
-
138
- /**
139
- * @return string Field description as provided by the user. Sanitized.
140
- */
141
- public function get_description() { return sanitize_text_field( wpcf_getarr( $this->definition_array, 'description' ) ); }
142
-
143
-
144
- /**
145
- * Determine whether the field is currently under Types control.
146
- *
147
- * If it's not, we are only holding on to this definition in case user decides to return it to Types control in the
148
- * future. In all other regards, such field definition should be handled as a generic one.
149
- *
150
- * @return bool
151
- */
152
- public function is_under_types_control() {
153
- $is_disabled = (bool) wpcf_getnest( $this->definition_array, array( 'data', 'disabled' ), false );
154
- return !$is_disabled;
155
- }
156
-
157
-
158
- private $meta_key = null;
159
-
160
-
161
- /**
162
- * @return string Meta_key use to store this field's values. Defaults to wpcf-$slug.
163
- */
164
- public function get_meta_key() {
165
- if( null == $this->meta_key ) {
166
- $this->meta_key = sanitize_title(
167
- wpcf_getarr( $this->definition_array, 'meta_key', self::FIELD_META_KEY_PREFIX . $this->get_slug() )
168
- );
169
- }
170
- return $this->meta_key;
171
- }
172
-
173
-
174
- private $is_repetitive = null;
175
-
176
-
177
- /**
178
- * @return bool True if the field is repetitive, false otherwise.
179
- */
180
- public function get_is_repetitive() {
181
- if( null === $this->is_repetitive ) {
182
- $this->is_repetitive = ( wpcf_getnest( $this->definition_array, array( 'data', 'repetitive' ), 0 ) != 0 );
183
- }
184
- return $this->is_repetitive;
185
- }
186
-
187
-
188
- /**
189
- * Get the underlying field definition array.
190
- *
191
- * Usage of this method is strongly discouraged, consider writing a custom (and safe) getter instead.
192
- *
193
- * @return array
194
- */
195
- public function get_definition_array() { return $this->definition_array; }
196
-
197
-
198
- public function get_type() { return $this->type; }
199
-
200
-
201
- /**
202
- * For binary fields (like checkbox), it is possible to specify a value that will be saved to the database
203
- * if the field is checked/selected/whatever.
204
- *
205
- * Stored in $cf['data']['set_save'].
206
- *
207
- * @return mixed|null The value or null if none is defined (make sure to compare with ===).
208
- * @since 1.9
209
- */
210
- public function get_forced_value() {
211
- return wpcf_getnest( $this->definition_array, array( 'data', 'set_value' ), null );
212
- }
213
-
214
-
215
- public function has_forced_value() {
216
- return ( null !== $this->get_forced_value() );
217
- }
218
-
219
-
220
- public function get_should_save_empty_value() {
221
- return ( 'yes' == wpcf_getnest( $this->definition_array, array( 'data', 'save_empty' ), 'no' ) );
222
- }
223
-
224
-
225
- public function get_is_required() {
226
- return ( 1 == wpcf_getnest( $this->definition_array, array( 'data', 'validate', 'required', 'active' ), 0 ) );
227
- }
228
-
229
-
230
- /**
231
- * Retrieve an array of option definitions.
232
- *
233
- * Allowed only for the checkboxes and radio field types.
234
- *
235
- * @throws RuntimeException when the field type is invalid
236
- * @throws InvalidArgumentException when option definitions are corrupted
237
- * @return WPCF_Field_Option_Checkboxes[] An option_id => option_data array.
238
- * @since 1.9
239
- */
240
- public function get_field_options() {
241
- $this->check_allowed_types(
242
- array(
243
- WPCF_Field_Type_Definition_Factory::CHECKBOXES,
244
- WPCF_Field_Type_Definition_Factory::RADIO,
245
- WPCF_Field_Type_Definition_Factory::SELECT
246
- )
247
- );
248
- $options_definition = wpcf_ensarr( wpcf_getnest( $this->definition_array, array( 'data', 'options' ) ) );
249
- $results = array();
250
-
251
- $has_default = array_key_exists( 'default', $options_definition );
252
- $default = wpcf_getarr( $options_definition, 'default', 'no-default' );
253
- if( $has_default ) {
254
- unset( $options_definition[ 'default' ] );
255
- }
256
-
257
- foreach( $options_definition as $option_id => $option_config ) {
258
- try {
259
- switch( $this->get_type()->get_slug() ) {
260
- case WPCF_Field_Type_Definition_Factory::RADIO:
261
- $option = new WPCF_Field_Option_Radio( $option_id, $option_config, $default, $this );
262
- break;
263
- case WPCF_Field_Type_Definition_Factory::SELECT:
264
- $option = new WPCF_Field_Option_Select( $option_id, $option_config, $default, $this );
265
- break;
266
- case WPCF_Field_Type_Definition_Factory::CHECKBOXES:
267
- $option = new WPCF_Field_Option_Checkboxes( $option_id, $option_config, $default );
268
- break;
269
- default:
270
- throw new InvalidArgumentException( 'Invalid field type' );
271
- }
272
- $results[ $option_id ] = $option;
273
- } catch( Exception $e ) {
274
- // Corrupted data, can't do anything but skip the option.
275
- }
276
- }
277
- return $results;
278
- }
279
-
280
-
281
- /**
282
- * Determines whether the field should display both time and date or date only.
283
- *
284
- * Allowed field type: date.
285
- *
286
- * @throws RuntimeException
287
- * @return string 'date'|'date_and_time' (note that for 'date_and_time' the actual value stored is 'and_time',
288
- * we're translating it to sound more sensible)
289
- * @since 1.9.1
290
- */
291
- public function get_datetime_option() {
292
- $this->check_allowed_types( WPCF_Field_Type_Definition_Factory::DATE );
293
- $value = wpcf_getnest( $this->definition_array, array( 'data', 'date_and_time' ) );
294
- return ( 'and_time' == $value ? 'date_and_time' : 'date' );
295
- }
296
-
297
-
298
-
299
- /**
300
- * Get an accessor for a specific field instance.
301
- *
302
- * @param WPCF_Field_Instance $field_instance Instance of the field the accessor should access.
303
- * @return WPCF_Field_Accessor_Abstract
304
- */
305
- public abstract function get_accessor( $field_instance );
306
-
307
-
308
-
309
-
310
- /**
311
- * Get a mapper object that helps translating field data between database and rest of Types.
312
- *
313
- * Note: This happens here and not in field type definition because the information about field type might not
314
- * be enough in the future.
315
- *
316
- * @todo This should probably be provided by type definition, no switch should be here.
317
- *
318
- * @return WPCF_Field_DataMapper_Abstract
319
- */
320
- public function get_data_mapper() {
321
- switch( $this->get_type()->get_slug() ) {
322
- case WPCF_Field_Type_Definition_Factory::CHECKBOXES:
323
- return new WPCF_Field_DataMapper_Checkboxes( $this );
324
- case WPCF_Field_Type_Definition_Factory::CHECKBOX:
325
- return new WPCF_Field_DataMapper_Checkbox( $this );
326
- default:
327
- return new WPCF_Field_DataMapper_Identity( $this );
328
- }
329
- }
330
-
331
-
332
- /**
333
- * Delete all field values!
334
- *
335
- * @return bool
336
- */
337
- public abstract function delete_all_fields();
338
-
339
-
340
- /**
341
- * Throw a RuntimeException if current field type doesn't match the list of allowed ones.
342
- *
343
- * @param string|string[] $allowed_field_types Field type slugs
344
- * @throws RuntimeException
345
- * @since 1.9.1
346
- */
347
- protected function check_allowed_types( $allowed_field_types ) {
348
-
349
- $allowed_field_types = wpcf_wraparr( $allowed_field_types );
350
-
351
- if( !in_array( $this->type->get_slug(), $allowed_field_types ) ) {
352
- throw new RuntimeException(
353
- sprintf(
354
- 'Invalid operation for this field type "%s", expected one of the following: %s.',
355
- $this->type->get_slug(),
356
- implode( ', ', $allowed_field_types )
357
- )
358
- );
359
- }
360
- }
361
-
362
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/definition_abstract.php DELETED
@@ -1,61 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Abstract of a field definition (common interface and code for generic and Types field definitions).
5
- */
6
- abstract class WPCF_Field_Definition_Abstract {
7
-
8
- /**
9
- * @return string Field definition slug.
10
- */
11
- public abstract function get_slug();
12
-
13
-
14
- /**
15
- * @return string Field definition display name.
16
- */
17
- public abstract function get_name();
18
-
19
-
20
- /**
21
- * @return string Description provided by the user.
22
- */
23
- public abstract function get_description();
24
-
25
-
26
- /**
27
- * @return string Meta key used to store values of these fields.
28
- */
29
- public abstract function get_meta_key();
30
-
31
- /**
32
- * Determine whether the field is currently under Types control.
33
- *
34
- * @return mixed
35
- */
36
- public abstract function is_under_types_control();
37
-
38
-
39
- /**
40
- * @return WPCF_Field_Group[]
41
- */
42
- public abstract function get_associated_groups();
43
-
44
-
45
- /**
46
- * Does the field definition match a certain string?
47
- *
48
- * Searches it's name and slug.
49
- *
50
- * @param string $search_string
51
- * @return bool
52
- */
53
- public function is_match( $search_string ) {
54
- return (
55
- WPCF_Utils::is_string_match( $search_string, $this->get_name() )
56
- || WPCF_Utils::is_string_match( $search_string, $this->get_slug() )
57
- );
58
- }
59
-
60
-
61
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/definition_factory.php DELETED
@@ -1,455 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Abstract factory for field definitions.
5
- *
6
- * Handles creation of the objects as well as their caching.
7
- */
8
- abstract class WPCF_Field_Definition_Factory {
9
-
10
- /**
11
- * Singleton parent.
12
- *
13
- * @link http://stackoverflow.com/questions/3126130/extending-singletons-in-php
14
- * @return WPCF_Field_Definition_Factory Instance of calling class.
15
- */
16
- final public static function get_instance() {
17
- static $instances = array();
18
- $called_class = get_called_class();
19
- if( !isset( $instances[ $called_class ] ) ) {
20
- $instances[ $called_class ] = new $called_class();
21
- }
22
- return $instances[ $called_class ];
23
- }
24
-
25
-
26
- final private function __construct() { }
27
-
28
-
29
- final private function __clone() { }
30
-
31
-
32
- /**
33
- * @return string Name of the option that should be used to obtain field definitions.
34
- */
35
- protected abstract function get_option_name();
36
-
37
-
38
- /**
39
- * @return string Name of the class that should be instantiated as a field definition. It MUST inherit from
40
- * WPCF_Field_Definition.
41
- */
42
- protected abstract function get_class_name();
43
-
44
-
45
- /**
46
- * @var array Existing instances of field definitions indexed by field slugs.
47
- */
48
- private $field_definitions = array();
49
-
50
-
51
- /**
52
- * Load an existing field definition.
53
- *
54
- * For now, we're using legacy code to read fields from the options table.
55
- *
56
- * @param string $field_key Key used to store the field configuration in options, or field slug (which should be
57
- * equal to the key).
58
- * @return null|WPCF_Field_Definition Field definition or null if it can't be loaded.
59
- */
60
- final public function load_field_definition( $field_key ) {
61
-
62
- if( !is_string( $field_key ) || empty( $field_key ) ) {
63
- return null;
64
- }
65
-
66
- // Can we use cached version?
67
- if( !in_array( $field_key, $this->field_definitions ) ) {
68
-
69
- // Get all field definitions for the option name we're using. No performance worries, it uses caching.
70
- $fields_from_options = $this->get_fields_from_options();
71
- $field_configuration = null;
72
- if( in_array( $field_key, array_keys( $fields_from_options ) ) ) {
73
- $field_configuration = $fields_from_options[ $field_key ];
74
- } else {
75
-
76
- // Theoretically, the field key may differ from the field slug (we have no invariants defined anywhere).
77
- // We can search the array and look for slugs.
78
- foreach( $fields_from_options as $field_from_options ) {
79
- if( wpcf_getarr( $field_from_options, 'slug' ) == $field_key ) {
80
- $field_configuration = $fields_from_options;
81
- break;
82
- }
83
- }
84
-
85
- if( null == $field_configuration ) {
86
- // No such field is defined.
87
- return null;
88
- }
89
- }
90
-
91
- // Prepare the field type information, fail if we can't.
92
- $field_type_slug = wpcf_getarr( $field_configuration, 'type', null );
93
- $field_type = WPCF_Field_Type_Definition_Factory::load( $field_type_slug );
94
- if( null == $field_type ) {
95
- return null;
96
- }
97
-
98
- // Create the object and save it to cache.
99
- try {
100
- $class_name = $this->get_class_name();
101
- /** @var WPCF_Field_Definition $field_definition */
102
- $field_definition = new $class_name( $field_type, $field_configuration );
103
- } catch( Exception $e ) {
104
- return null;
105
- }
106
-
107
- $this->field_definitions[ $field_key ] = $field_definition;
108
- }
109
-
110
- return $this->field_definitions[ $field_key ];
111
- }
112
-
113
-
114
- /**
115
- * Note: Consider using the builder pattern.
116
- */
117
- /*final protected function create_field_definition( ) {
118
-
119
- }*/
120
-
121
-
122
- /**
123
- * @return array Raw field definition data from the options.
124
- */
125
- private function get_fields_from_options() {
126
- return wpcf_admin_fields_get_fields( false, false, false, $this->get_option_name() );
127
- }
128
-
129
-
130
- /**
131
- * Removes a single field definition from the storage of existing instances.
132
- *
133
- * It also completely clears the cache of the (legacy) wpcf_admin_fields_get_fields.
134
- * Note that this method is public only temporarily and that this is not a mere cache clearing.
135
- *
136
- * @param string|null $field_slug If null, the cache will be emptied completely.
137
- */
138
- public function clear_definition_storage( $field_slug = null ) {
139
- if( null == $field_slug ) {
140
- $this->field_definitions = array();
141
- } else {
142
- unset( $this->field_definitions[ $field_slug ] );
143
- }
144
-
145
- wpcf_admin_fields_get_fields( false, false, false, $this->get_option_name(), false, true );
146
- }
147
-
148
-
149
- /**
150
- * Completely erase field definition from options and clear cache.
151
- *
152
- * @param string $field_slug
153
- */
154
- private function erase_field_definition_from_options( $field_slug ) {
155
-
156
- $fields_from_options = $this->get_fields_from_options();
157
- unset( $fields_from_options[ $field_slug ] );
158
- wpcf_admin_fields_save_fields( $fields_from_options, true, $this->get_option_name() );
159
-
160
- $this->clear_definition_storage( $field_slug );
161
- }
162
-
163
-
164
- /**
165
- * @return string[] Slugs of fields that have a definition in Types.
166
- */
167
- private function get_types_field_slugs() {
168
- $fields_from_options = $this->get_fields_from_options();
169
- $field_slugs = array();
170
- foreach ( $fields_from_options as $field_configuration ) {
171
- $slug = wpcf_getarr( $field_configuration, 'slug' );
172
- if( !empty( $slug ) ) {
173
- $field_slugs[] = $slug;
174
- }
175
- }
176
- return array_unique( $field_slugs );
177
- }
178
-
179
-
180
- /**
181
- * @param string $meta_key
182
- * @return bool True if there exists any Types field definition (within the domain) that uses this key.
183
- */
184
- private function meta_key_belongs_to_types_field( $meta_key ) {
185
- $field_definitions = $this->load_types_field_definitions();
186
- foreach( $field_definitions as $field_definition ) {
187
- if( $field_definition->get_meta_key() == $meta_key ) {
188
- return true;
189
- }
190
- }
191
- return false;
192
- }
193
-
194
-
195
- /**
196
- * @return WPCF_Field_Definition[] All existing Types field definitions.
197
- */
198
- private function load_types_field_definitions() {
199
- $field_slugs = $this->get_types_field_slugs();
200
- $field_definitions = array();
201
-
202
- foreach ( $field_slugs as $slug ) {
203
- $field_definition = $this->load_field_definition( $slug );
204
- if ( null != $field_definition ) {
205
- $field_definitions[] = $field_definition;
206
- }
207
- }
208
-
209
- return $field_definitions;
210
- }
211
-
212
-
213
- /**
214
- * @return string[] All meta keys that occur in the database (within the domain).
215
- */
216
- protected abstract function get_existing_meta_keys();
217
-
218
-
219
- /**
220
- * @var null|WPCF_Field_Definition_Generic[] Cache.
221
- */
222
- private $generic_field_definitions = null;
223
-
224
-
225
- /**
226
- * @return WPCF_Field_Definition_Generic[] Definitions of all generic fields that exist in the database within
227
- * current domain.
228
- */
229
- public function load_generic_field_definitions() {
230
-
231
- if( null == $this->generic_field_definitions ) {
232
- $existing_meta_keys = $this->get_existing_meta_keys();
233
-
234
- $results = array();
235
- foreach( $existing_meta_keys as $meta_key ) {
236
-
237
- if( $this->meta_key_belongs_to_types_field( $meta_key ) ) {
238
- continue;
239
- }
240
-
241
- $results[] = new WPCF_Field_Definition_Generic( $meta_key );
242
- }
243
-
244
- $this->generic_field_definitions = $results;
245
-
246
- }
247
-
248
- return $this->generic_field_definitions;
249
- }
250
-
251
-
252
- /**
253
- * @return WPCF_Field_Definition_Abstract[] All field definitions (generic and Types-controlled).
254
- */
255
- public function load_all_definitions() {
256
- return array_merge( $this->load_types_field_definitions(), $this->load_generic_field_definitions() );
257
- }
258
-
259
-
260
- /**
261
- * Reorder an array of field definitions.
262
- *
263
- * @param WPCF_Field_Definition_Abstract[] $definitions
264
- * @param string $orderby 'name'|'slug'|'is_under_types_control'|'field_type'
265
- * @param string $order 'asc'|'desc'
266
- *
267
- * @return WPCF_Field_Definition_Abstract[] Reordered array.
268
- */
269
- public function order_definitions( $definitions, $orderby = 'name', $order = 'asc' ) {
270
-
271
- $orderby_to_comparison_function = array(
272
- 'name' => 'compare_definitions_by_name',
273
- 'slug' => 'compare_definitions_by_slug',
274
- 'is_under_types_control' => 'compare_definition_by_types_control',
275
- 'field_type' => 'compare_definitions_by_field_type'
276
- );
277
-
278
- usort( $definitions, array( $this, wpcf_getarr( $orderby_to_comparison_function, $orderby, 'compare_definitions_by_name' ) ) );
279
-
280
- if( 'desc' == $order ) {
281
- $definitions = array_reverse( $definitions );
282
- }
283
-
284
- return $definitions;
285
- }
286
-
287
-
288
- /**
289
- * Compare function for ordering by name in order_definitions().
290
- *
291
- * @param $first WPCF_Field_Definition_Abstract
292
- * @param $second WPCF_Field_Definition_Abstract
293
- *
294
- * @return int
295
- */
296
- public function compare_definitions_by_name( $first, $second ) {
297
- return strcoll( strtolower( $first->get_name() ), strtolower( $second->get_name() ) );
298
- }
299
-
300
-
301
- /**
302
- * Compare function for ordering by slug in order_definitions().
303
- *
304
- * @param $first WPCF_Field_Definition_Abstract
305
- * @param $second WPCF_Field_Definition_Abstract
306
- *
307
- * @return int
308
- */
309
- public function compare_definitions_by_slug( $first, $second ) {
310
- return strcmp( $first->get_slug(), $second->get_slug() );
311
- }
312
-
313
-
314
- /**
315
- * Compare function for ordering by the Types control status in order_definitions().
316
- *
317
- * @param $first WPCF_Field_Definition_Abstract
318
- * @param $second WPCF_Field_Definition_Abstract
319
- *
320
- * @return int
321
- */
322
- public function compare_definition_by_types_control( $first, $second ) {
323
- if( $first->is_under_types_control() == $second->is_under_types_control() ) {
324
- return 0;
325
- } else {
326
- return $first->is_under_types_control() ? 1 : -1;
327
- }
328
- }
329
-
330
-
331
- /**
332
- * Compare function for ordering by field type in order_definitions().
333
- *
334
- * @param $first WPCF_Field_Definition_Abstract
335
- * @param $second WPCF_Field_Definition_Abstract
336
- *
337
- * @return int
338
- */
339
- public function compare_definitions_by_field_type( $first, $second ) {
340
- if( $first->is_under_types_control() == $second->is_under_types_control() ) {
341
- if( $first->is_under_types_control() ) {
342
- // Both are under Types control, compare their field types
343
- /** @var WPCF_Field_Definition $first_t */
344
- $first_t = $first;
345
- /** @var WPCF_Field_Definition $second_t */
346
- $second_t = $second;
347
- return strcmp( $first_t->get_type()->get_slug(), $second_t->get_type()->get_slug() );
348
- } else {
349
- // None are under Types control
350
- return 0;
351
- }
352
- } else {
353
- // The one that is under Types control wins.
354
- return $first->is_under_types_control() ? -1 : 1;
355
- }
356
- }
357
-
358
-
359
- /**
360
- * Query field definitions.
361
- *
362
- * @param array $args Following arguments are recognized:
363
- * - filter: What field definitions should be retrieved: 'types'|'generic'|'all'
364
- * - orderby: 'name'|'slug'|'is_under_types_control'|'field_type'
365
- * - order: 'asc'|'desc'
366
- * - search: String for fulltext search.
367
- *
368
- * @return WPCF_Field_Definition_Abstract[] Field definitions that match query arguments.
369
- */
370
- public function query_definitions( $args ) {
371
-
372
- $args = wp_parse_args( $args, array('filter' => 'all') );
373
-
374
- // Get only certain type of field definitions (generic, Types or both)
375
- switch( $args['filter'] ) {
376
- case 'types':
377
- $results = $this->load_types_field_definitions();
378
- break;
379
- case 'generic':
380
- $results = $this->load_generic_field_definitions();
381
- break;
382
- case 'all':
383
- $results = $this->load_all_definitions();
384
- break;
385
- default:
386
- $results = array();
387
- break;
388
- }
389
-
390
- // Perform fulltext search if needed
391
- $search_string = wpcf_getarr( $args, 'search', '' );
392
-
393
- if( !empty( $search_string ) ) {
394
- $matches = array();
395
- foreach( $results as $definition ) {
396
- if( $definition->is_match( $search_string ) ) {
397
- $matches[] = $definition;
398
- }
399
- }
400
- $results = $matches;
401
- }
402
-
403
- // Sort results
404
- $orderby = wpcf_getarr( $args, 'orderby', 'name' );
405
- $order = wpcf_getarr( $args, 'order', 'asc', array( 'asc', 'desc' ) );
406
-
407
- $results = $this->order_definitions( $results, $orderby, $order );
408
-
409
- return $results;
410
- }
411
-
412
-
413
- /**
414
- * Permanently delete field definition.
415
- *
416
- * That means:
417
- * - remove it from all field groups,
418
- * - delete field data from the database (sic!) and
419
- * - delete the definition itself.
420
- *
421
- * After calling this method, the field definition object passed as parameter should never be used again.
422
- *
423
- * @param WPCF_Field_Definition $field_definiton
424
- * @return bool
425
- */
426
- public function delete_definition( $field_definiton ) {
427
-
428
- // We accept only fields that are under Types control
429
- if( ! $field_definiton instanceof WPCF_Field_Definition ) {
430
- return false;
431
- }
432
-
433
- if( ! $field_definiton->is_under_types_control() ) {
434
- return false;
435
- }
436
-
437
- // Remove field from all groups
438
- $associated_groups = $field_definiton->get_associated_groups();
439
- foreach( $associated_groups as $group ) {
440
- $group->remove_field_definition( $field_definiton );
441
- }
442
-
443
- // Delete field data
444
- $is_success = $field_definiton->delete_all_fields();
445
-
446
- // Delete the definition
447
- $slug_to_delete = $field_definiton->get_slug();
448
- $this->erase_field_definition_from_options( $slug_to_delete );
449
-
450
- return $is_success;
451
-
452
- }
453
-
454
-
455
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/definition_term.php DELETED
@@ -1,67 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Field definition for term fields.
5
- *
6
- * @since 1.9
7
- */
8
- final class WPCF_Field_Definition_Term extends WPCF_Field_Definition {
9
-
10
-
11
- /**
12
- * Get an accessor for a specific field instance.
13
- *
14
- * @param WPCF_Field_Instance $field_instance Instance of the field the accessor should access.
15
- * @return WPCF_Field_Accessor_Termmeta_Field
16
- */
17
- public function get_accessor( $field_instance ) {
18
- return new WPCF_Field_Accessor_Termmeta_Field(
19
- $field_instance->get_object_id(),
20
- $this->get_meta_key(),
21
- $this->get_is_repetitive(),
22
- $field_instance
23
- );
24
- }
25
-
26
-
27
- /**
28
- * @return WPCF_Field_Group[]
29
- */
30
- public function get_associated_groups() {
31
- $term_field_groups = WPCF_Field_Group_Term_Factory::get_instance()->query_groups();
32
- $associated_groups = array();
33
- foreach ( $term_field_groups as $field_group ) {
34
- if ( $field_group->contains_field_definition( $this ) ) {
35
- $associated_groups[] = $field_group;
36
- }
37
- }
38
-
39
- return $associated_groups;
40
- }
41
-
42
-
43
- /**
44
- * Delete all field values!
45
- *
46
- * @return bool
47
- */
48
- public function delete_all_fields() {
49
- global $wpdb;
50
-
51
- $meta_key = $this->get_meta_key();
52
-
53
- $termmeta_records = $wpdb->get_results(
54
- $wpdb->prepare(
55
- "SELECT term_id FROM $wpdb->termmeta WHERE meta_key = %s",
56
- $meta_key
57
- )
58
- );
59
-
60
- // Delete one by one because we (probably) want all the WP hooks to fire.
61
- foreach ( $termmeta_records as $termmeta ) {
62
- delete_term_meta( $termmeta->term_id, $meta_key );
63
- }
64
-
65
- return true;
66
- }
67
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/group.php DELETED
@@ -1,338 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Abstract representation of a field group (without defined type).
5
- *
6
- * Descendants of this class allways must be instantiated through appropriate factory class inheriting
7
- * from WPCF_Field_Group_Factory.
8
- *
9
- * Any method that permanently changes any group data needs to call execute_group_updated_action() afterwards.
10
- */
11
- abstract class WPCF_Field_Group {
12
-
13
- /**
14
- * Stores the slugs of the fields that belong to this group, as a comma separated list.
15
- */
16
- const POSTMETA_FIELD_SLUGS_LIST = '_wp_types_group_fields';
17
-
18
-
19
- const FIELD_SLUG_DELIMITER = ',';
20
-
21
-
22
- /**
23
- * @var WP_Post Post object that represents the field group.
24
- */
25
- private $post;
26
-
27
-
28
- /**
29
- * WPCF_Field_Group constructor.
30
- *
31
- * Note that it is protected - inheriting classes have to implement an override that should, additionally, check
32
- * if the post has correct type.
33
- *
34
- * @param WP_Post $field_group_post Post object that represents the field group.
35
- * @throws InvalidArgumentException
36
- */
37
- protected function __construct( $field_group_post ) {
38
- if( ! $field_group_post instanceof WP_Post ) {
39
- throw new InvalidArgumentException( 'First argument is not a post.' );
40
- }
41
- $this->post = $field_group_post;
42
- }
43
-
44
-
45
- /**
46
- * @return WPCF_Field_Definition_Factory Field definition factory of the correct type.
47
- */
48
- protected abstract function get_field_definition_factory();
49
-
50
-
51
- /**
52
- * @return WP_Post Post object representing the field group.
53
- */
54
- protected function get_post() {
55
- return $this->post;
56
- }
57
-
58
-
59
- /**
60
- * @return int ID of the field group.
61
- */
62
- public function get_id() {
63
- return $this->get_post()->ID;
64
- }
65
-
66
-
67
- /**
68
- * @return string Unique name (post slug) of the field group.
69
- */
70
- public function get_slug() {
71
- return sanitize_title( $this->get_post()->post_name );
72
- }
73
-
74
-
75
- /**
76
- * @return string Field group description. Sanitized as a text field.
77
- */
78
- public function get_description() {
79
- return sanitize_text_field( $this->get_post()->post_content );
80
- }
81
-
82
-
83
- /**
84
- * Note that for displaying group name to the user you should use get_display_name() instead.
85
- *
86
- * @return string Field group title.
87
- */
88
- public function get_name() {
89
- return sanitize_text_field( $this->get_post()->post_title );
90
- }
91
-
92
-
93
- /**
94
- * Get group name as it should be displayed to the user.
95
- *
96
- * Handles string translation if applicable.
97
- */
98
- public function get_display_name() {
99
- return wpcf_translate(
100
- sprintf( 'group %d name', $this->get_id() ),
101
- $this->get_name()
102
- );
103
- }
104
-
105
-
106
- /**
107
- * @return bool True if the field group is active, false if deactivated.
108
- */
109
- public function is_active() {
110
- return ( $this->get_post()->post_status == 'publish' ? true : false );
111
- }
112
-
113
-
114
- /**
115
- * @return string Status of the underlying post. Limited to 'publish'|'draft' (default).
116
- */
117
- public function get_post_status() {
118
- return ( $this->is_active() ? 'publish' : 'draft' );
119
- }
120
-
121
-
122
- /**
123
- * @return int ID of the user who edited the field group last.
124
- */
125
- public function get_author() {
126
- return (int) $this->get_post()->post_author;
127
- }
128
-
129
-
130
- /*
131
- * $group['meta_box_context'] = 'normal';
132
- $group['meta_box_priority'] = 'high';
133
- $group['filters_association'] = get_post_meta( $post->ID, '_wp_types_group_filters_association', true );
134
- */
135
-
136
-
137
- /**
138
- * Change name of the field group.
139
- *
140
- * Do not confuse with the title. *All* changes of the name must happen through this method, otherwise
141
- * unexpected behaviour of the WPCF_Field_Group_Factory can occur.
142
- *
143
- * @param string $value New value of the post name. Note that it may be further modified by WordPress before saving.
144
- */
145
- public function set_name( $value ) {
146
- $updated_post_id = wp_update_post(
147
- array( 'ID' => $this->get_id(), 'post_name' => sanitize_title( $value ) )
148
- );
149
- if( 0 !== $updated_post_id ) {
150
- // Refresh the post object and notify about renaming field group.
151
- $this->post = WP_Post::get_instance( $updated_post_id );
152
- do_action( 'wpcf_field_group_renamed', $value, $this );
153
- $this->execute_group_updated_action();
154
- }
155
- }
156
-
157
-
158
- /**
159
- * @return string The underlying post type of the post representing the field group.
160
- */
161
- public function get_post_type() {
162
- return $this->post->post_type;
163
- }
164
-
165
-
166
- /**
167
- * @var null|array Array of field slugs that belong to this field group, or null if it was not loaded from database yet.
168
- */
169
- private $field_slugs = null;
170
-
171
-
172
- /**
173
- * Check if a field slug is valid and can be stored in the database.
174
- *
175
- * @param string $field_slug
176
- * @return bool True if the slug is valid.
177
- */
178
- public function is_valid_field_slug( $field_slug ) {
179
- return !empty( $field_slug ) && is_string( $field_slug ) && ( sanitize_title( $field_slug ) == $field_slug );
180
- }
181
-
182
-
183
- /**
184
- * Check if an array of field slugs is valid.
185
- *
186
- * @param array|mixed $field_slugs
187
- * @return bool True if an array of valid field slugs was provided.
188
- */
189
- protected function validate_field_slugs( $field_slugs ) {
190
- if( !is_array( $field_slugs ) ) {
191
- return false;
192
- }
193
-
194
- // Every element needs to be valid
195
- if( count( $field_slugs ) != count ( array_filter( $field_slugs, array( $this, 'is_valid_field_slug' ) ) ) ) {
196
- return false;
197
- }
198
-
199
- return true;
200
- }
201
-
202
-
203
- /**
204
- * @return array Slugs of fields that belong to this field group, or empty array when database doesn't contain
205
- * valid data.
206
- *
207
- * Consider using get_field_definitions() instead.
208
- */
209
- public function get_field_slugs() {
210
- if( null == $this->field_slugs ) {
211
- $field_slug_list = get_post_meta( $this->get_id(), self::POSTMETA_FIELD_SLUGS_LIST, true );
212
- $field_slugs = explode( self::FIELD_SLUG_DELIMITER, $field_slug_list );
213
-
214
- // Remove empty slugs
215
- foreach( $field_slugs as $key => $slug ) {
216
- if( empty( $slug ) ) {
217
- unset( $field_slugs[ $key ] );
218
- }
219
- }
220
-
221
- $this->field_slugs = $this->validate_field_slugs( $field_slugs ) ? $field_slugs : array();
222
- }
223
- return $this->field_slugs;
224
- }
225
-
226
-
227
- /**
228
- * Get all existing definitions of fields that belong to this group.
229
- *
230
- * @return WPCF_Field_Definition[]
231
- */
232
- public function get_field_definitions() {
233
- $slugs = $this->get_field_slugs();
234
- $field_definitions = array();
235
- $factory = $this->get_field_definition_factory();
236
- foreach( $slugs as $slug ) {
237
- $field_definition = $factory->load_field_definition( $slug );
238
- if( null != $field_definition ) {
239
- $field_definitions[] = $field_definition;
240
- }
241
- }
242
- return $field_definitions;
243
- }
244
-
245
-
246
- /**
247
- * Update the set of field slugs that belong to this field group.
248
- *
249
- * @param array $field_slugs Array of valid field slugs.
250
- * @return bool True if the database was updated successfully, false otherwise.
251
- */
252
- protected function set_field_slugs( $field_slugs ) {
253
- if( !$this->validate_field_slugs( $field_slugs ) ) {
254
- return false;
255
- }
256
-
257
- $this->field_slugs = $field_slugs;
258
-
259
- $field_slug_list = implode( self::FIELD_SLUG_DELIMITER, $field_slugs );
260
-
261
- $updated = update_post_meta( $this->get_id(), self::POSTMETA_FIELD_SLUGS_LIST, $field_slug_list );
262
-
263
- $this->execute_group_updated_action();
264
-
265
- return ( $updated != false );
266
- }
267
-
268
-
269
- /**
270
- * Remove field definition from this group.
271
- *
272
- * @param WPCF_Field_Definition $field_definition
273
- * @return bool
274
- */
275
- public function remove_field_definition( $field_definition ) {
276
-
277
- $field_slugs = $this->get_field_slugs();
278
-
279
- $slug_to_remove = $field_definition->get_slug();
280
- $key = array_search( $slug_to_remove, $field_slugs );
281
- if( $key !== false ) {
282
- unset( $field_slugs[ $key ] );
283
- }
284
-
285
- $is_success = $this->set_field_slugs( $field_slugs );
286
-
287
- return $is_success;
288
- }
289
-
290
-
291
- /**
292
- * Check if a string is contained within the field group definition.
293
- *
294
- * Searches in ID, slug, title and description. Case insensitive.
295
- *
296
- * @param string $search_string String to look for.
297
- * @return bool True if found.
298
- */
299
- public function is_match( $search_string ) {
300
- return (
301
- WPCF_Utils::is_string_match( $search_string, $this->get_id() )
302
- || WPCF_Utils::is_string_match( $search_string, $this->get_slug() )
303
- || WPCF_Utils::is_string_match( $search_string, $this->get_name() )
304
- || WPCF_Utils::is_string_match( $search_string, $this->get_display_name() )
305
- || WPCF_Utils::is_string_match( $search_string, $this->get_description() )
306
- );
307
- }
308
-
309
-
310
- public function contains_field_definition( $field_definition ) {
311
- if( $field_definition instanceof WPCF_Field_Definition ) {
312
- return in_array( $field_definition, $this->get_field_definitions() );
313
- } elseif( is_string( $field_definition ) ) {
314
- return in_array( $field_definition, $this->get_field_slugs() );
315
- } else {
316
- return false;
317
- }
318
- }
319
-
320
-
321
- /**
322
- * Execute the wpcf_group_updated action.
323
- *
324
- * Needs to be called after each (permanent) change to a group.
325
- */
326
- public function execute_group_updated_action() {
327
-
328
- /**
329
- * Executed after a group has been updated in the database.
330
- *
331
- * @param int $id Group ID.
332
- * @param WPCF_Field_Group $group The group object.
333
- * @since 1.9
334
- */
335
- do_action( 'wpcf_group_updated', $this->get_id(), $this );
336
- }
337
-
338
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/group_factory.php DELETED
@@ -1,259 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Abstract factory for field group classes.
5
- *
6
- * It ensures that each field group is instantiated only once and it keeps returning that one instance.
7
- *
8
- * Note: Cache is indexed by slugs, so if a field group can change it's slug, it is necessary to do
9
- * an 'wpcf_field_group_renamed' action immediately after renaming.
10
- */
11
- abstract class WPCF_Field_Group_Factory {
12
-
13
-
14
- /**
15
- * Singleton parent.
16
- *
17
- * @link http://stackoverflow.com/questions/3126130/extending-singletons-in-php
18
- * @return WPCF_Field_Group_Factory Instance of calling class.
19
- */
20
- public static function get_instance() {
21
- static $instances = array();
22
- $called_class = get_called_class();
23
- if( !isset( $instances[ $called_class ] ) ) {
24
- $instances[ $called_class ] = new $called_class();
25
- }
26
- return $instances[ $called_class ];
27
- }
28
-
29
-
30
- protected function __construct() {
31
- add_action( 'wpcf_field_group_renamed', array( $this, 'field_group_renamed' ), 10, 2 );
32
- }
33
-
34
-
35
- final private function __clone() { }
36
-
37
-
38
- /**
39
- * @return string Post type that holds information about this field group type.
40
- */
41
- abstract protected function get_post_type();
42
-
43
-
44
- /**
45
- * @return string Name of the class that represents this field group type (and that will be instantiated). It must
46
- * be a child of WPCF_Field_Group.
47
- */
48
- abstract protected function get_field_group_class_name();
49
-
50
-
51
- /**
52
- * Get a post object that represents a field group.
53
- *
54
- * @param int|string|WP_Post $field_group Numeric ID of the post, post slug or a post object.
55
- *
56
- * @return null|WP_Post Requested post object when the post exists and has correct post type. Null otherwise.
57
- */
58
- final protected function get_post( $field_group ) {
59
-
60
- $fg_post = null;
61
-
62
- // http://stackoverflow.com/questions/2559923/shortest-way-to-check-if-a-variable-contains-positive-integer-using-php
63
- if ( is_scalar( $field_group ) && ( $field_group == (int) $field_group ) && ( (int) $field_group > 0 ) ) {
64
- $fg_post = WP_Post::get_instance( $field_group );
65
- } else if ( is_string( $field_group ) ) {
66
- $query = new WP_Query( array( 'post_type' => $this->get_post_type(), 'name' => $field_group, 'posts_per_page' => 1 ) );
67
- if( $query->have_posts() ) {
68
- $fg_post = $query->get_posts();
69
- $fg_post = $fg_post[0];
70
- }
71
- } else {
72
- $fg_post = $field_group;
73
- }
74
-
75
- if( $fg_post instanceof WP_Post && $this->get_post_type() == $fg_post->post_type ) {
76
- return $fg_post;
77
- } else {
78
- return null;
79
- }
80
- }
81
-
82
-
83
- /**
84
- * @var array Array of field group instances for this post type, indexed by names (post slugs).
85
- */
86
- private $field_groups = array();
87
-
88
-
89
- /**
90
- * @param string $field_group_name Name of the field group.
91
- * @return null|WPCF_Field_Group Field group instance or null if it's not cached.
92
- */
93
- private function get_from_cache( $field_group_name ) {
94
- return wpcf_getarr( $this->field_groups, $field_group_name, null );
95
- }
96
-
97
-
98
- /**
99
- * Save a field group instance to cache.
100
- * @param WPCF_Field_Group $field_group
101
- */
102
- private function save_to_cache( $field_group ) {
103
- $this->field_groups[ $field_group->get_slug() ] = $field_group;
104
- }
105
-
106
-
107
- /**
108
- * Remove field group instance from cache.
109
- * @param string $field_group_name
110
- */
111
- private function clear_from_cache( $field_group_name ) {
112
- unset( $this->field_groups[ $field_group_name ] );
113
- }
114
-
115
-
116
- /**
117
- * Load a field group instance.
118
- *
119
- * @param int|string|WP_Post $field_group_source Post ID of the field group, it's name or a WP_Post object.
120
- *
121
- * @return null|WPCF_Field_Group Field group or null if it can't be loaded.
122
- */
123
- final public function load_field_group( $field_group_source ) {
124
-
125
- $post = null;
126
-
127
- // If we didn't get a field group name, we first need to get the post so we can look into the cache.
128
- if( !is_string( $field_group_source ) ) {
129
- $post = $this->get_post( $field_group_source );
130
- if( null == $post ) {
131
- // There is no such post (or has wrong type).
132
- return null;
133
- }
134
- $field_group_name = $post->post_name;
135
- } else {
136
- $field_group_name = $field_group_source;
137
- }
138
-
139
- // Try to get an existing instance.
140
- $field_group = $this->get_from_cache( $field_group_name );
141
- if( null != $field_group ) {
142
- return $field_group;
143
- }
144
-
145
- // We might already have the post by now.
146
- if( null == $post ) {
147
- $post = $this->get_post( $field_group_source );
148
- }
149
-
150
- // There is no such post (or has wrong type).
151
- if( null == $post ) {
152
- return null;
153
- }
154
-
155
- // Create new field group instance
156
- try {
157
- $class_name = $this->get_field_group_class_name();
158
- $field_group = new $class_name( $post );
159
- } catch( Exception $e ) {
160
- return null;
161
- }
162
-
163
- $this->save_to_cache( $field_group );
164
- return $field_group;
165
- }
166
-
167
-
168
- /**
169
- * Update cache after a field group is renamed.
170
- *
171
- * @param string $original_name The old name of the field group.
172
- * @param WPCF_Field_Group $field_group The field group involved, with already updated name.
173
- */
174
- public function field_group_renamed( $original_name, $field_group ) {
175
- if( $field_group->get_post_type() == $this->get_post_type() ) {
176
- $this->clear_from_cache( $original_name );
177
- $this->save_to_cache( $field_group );
178
- }
179
- }
180
-
181
-
182
- /**
183
- * Create new field group.
184
- *
185
- * @param string $name Sanitized field group name. Note that the final name may change when new post is inserted.
186
- * @param string $title Field group title.
187
- *
188
- * @return null|WPCF_Field_Group The new field group or null on error.
189
- */
190
- final public function create_field_group( $name, $title = '' ) {
191
-
192
- if( sanitize_title( $name ) != $name ) {
193
- return null;
194
- }
195
-
196
- $title = wp_strip_all_tags( $title );
197
-
198
- $post_id = wp_insert_post( array(
199
- 'post_type' => $this->get_post_type(),
200
- 'post_name' => $name,
201
- 'post_title' => empty( $title ) ? $name : $title
202
- ) );
203
-
204
- if( 0 == $post_id ) {
205
- return null;
206
- }
207
-
208
- // Store the mandatory postmeta, just to be safe. I'm not sure about invariants here.
209
- update_post_meta( $post_id, WPCF_Field_Group::POSTMETA_FIELD_SLUGS_LIST, '' );
210
-
211
- $field_group = $this->load_field_group( $post_id );
212
-
213
- $field_group->execute_group_updated_action();
214
-
215
- return $field_group;
216
- }
217
-
218
-
219
- /**
220
- * Get field groups based on query arguments.
221
- *
222
- * @param array $query_args Optional. Arguments for the WP_Query that will be applied on the underlying posts.
223
- * Post type query is added automatically.
224
- * @param null|string $search_string String for extended search. See WPCF_Field_Group::is_match() for details.
225
- * @return WPCF_Field_Group[]
226
- */
227
- public function query_groups( $query_args = array(), $search_string = null ) {
228
-
229
- // Query posts
230
- $query_args = array_merge( $query_args, array( 'post_type' => $this->get_post_type() ) );
231
- $query = new WP_Query( $query_args );
232
- $posts = $query->get_posts();
233
-
234
- // Transform posts into WPCF_Field_Group
235
- $all_groups = array();
236
- foreach( $posts as $post ) {
237
- $field_group = $this->load_field_group( $post );
238
- if( null != $field_group ) {
239
- $all_groups[] = $field_group;
240
- }
241
- }
242
-
243
- // Filter groups by the search string.
244
- $selected_groups = array();
245
- if( empty( $search_string ) ) {
246
- $selected_groups = $all_groups;
247
- } else {
248
- /** @var WPCF_Field_Group $group */
249
- foreach ( $all_groups as $group ) {
250
- if ( $group->is_match( $search_string ) ) {
251
- $selected_groups[] = $group;
252
- }
253
- }
254
- }
255
-
256
- return $selected_groups;
257
- }
258
-
259
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/group_term.php DELETED
@@ -1,115 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Term field group.
5
- *
6
- * @since 1.9
7
- */
8
- final class WPCF_Field_Group_Term extends WPCF_Field_Group {
9
-
10
-
11
- const POST_TYPE = 'wp-types-term-group';
12
-
13
-
14
- /**
15
- * Key for postmeta that holds slugs of taxonomies associated with this group. This is a "plural" postmeta,
16
- * each record contains one slug.
17
- */
18
- const POSTMETA_ASSOCIATED_TAXONOMY = '_wp_types_associated_taxonomy';
19
-
20
-
21
- /**
22
- * WPCF_Field_Group_Term constructor.
23
- *
24
- * @param WP_Post $field_group_post Post object representing a term field group.
25
- * @throws InvalidArgumentException
26
- */
27
- public function __construct( $field_group_post ) {
28
- parent::__construct( $field_group_post );
29
- if( self::POST_TYPE != $field_group_post->post_type ) {
30
- throw new InvalidArgumentException( 'incorrect post type' );
31
- }
32
- }
33
-
34
-
35
- /**
36
- * @return WPCF_Field_Definition_Factory Field definition factory of the correct type.
37
- */
38
- protected function get_field_definition_factory() {
39
- return WPCF_Field_Term_Definition_Factory::get_instance();
40
- }
41
-
42
-
43
- /**
44
- * Get taxonomies that are associated with this field group.
45
- *
46
- * @return string[] Taxonomy slugs. Empty array means that this group should be displayed with all taxonomies.
47
- */
48
- public function get_associated_taxonomies() {
49
- $postmeta = get_post_meta( $this->get_id(), self::POSTMETA_ASSOCIATED_TAXONOMY, false );
50
- return wpcf_ensarr( $postmeta );
51
- }
52
-
53
-
54
- /**
55
- * Quickly determine whether given taxonomy is associated with this group.
56
- *
57
- * @param string $taxonomy_slug
58
- * @return bool
59
- */
60
- public function has_associated_taxonomy( $taxonomy_slug ) {
61
- $taxonomies = $this->get_associated_taxonomies();
62
- return ( empty( $taxonomies ) || in_array( $taxonomy_slug, $taxonomies ) );
63
- }
64
-
65
-
66
- /**
67
- * Remove association with a single taxonomy from the database.
68
- *
69
- * @param string $taxonomy_slug Slug of the taxonomy.
70
- */
71
- private function remove_associated_taxonomy( $taxonomy_slug ) {
72
- if( empty( $taxonomy_slug ) ) {
73
- return;
74
- }
75
- delete_post_meta( $this->get_id(), self::POSTMETA_ASSOCIATED_TAXONOMY, $taxonomy_slug );
76
- $this->execute_group_updated_action();
77
- }
78
-
79
-
80
- /**
81
- * Add an association with a single taxonomy to the database.
82
- *
83
- * @param string $taxonomy_slug Slug of the taxonomy. If empty or not sanitized, the function does nothing.
84
- */
85
- private function add_associated_taxonomy( $taxonomy_slug ) {
86
- if( empty( $taxonomy_slug ) || $taxonomy_slug != sanitize_title( $taxonomy_slug )) {
87
- return;
88
- }
89
- add_post_meta( $this->get_id(), self::POSTMETA_ASSOCIATED_TAXONOMY, $taxonomy_slug );
90
- $this->execute_group_updated_action();
91
- }
92
-
93
-
94
- /**
95
- * Update the set of taxonomies associated with this field group.
96
- *
97
- * @param string[] $taxonomy_slugs Array of (sanitized) taxonomy slugs.
98
- */
99
- public function update_associated_taxonomies( $taxonomy_slugs ) {
100
- $current_taxonomies = $this->get_associated_taxonomies();
101
-
102
- // Remove taxonomies that are associated but shouldn't be.
103
- $to_remove = array_diff( $current_taxonomies, $taxonomy_slugs );
104
- foreach( $to_remove as $taxonomy_slug ) {
105
- $this->remove_associated_taxonomy( $taxonomy_slug );
106
- }
107
-
108
- // Add taxonomies that aren't associated but should be.
109
- $to_add = array_diff( $taxonomy_slugs, $current_taxonomies );
110
- foreach( $to_add as $taxonomy_slug ) {
111
- $this->add_associated_taxonomy( $taxonomy_slug );
112
- }
113
- }
114
-
115
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/group_term_factory.php DELETED
@@ -1,136 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Factory for the WPCF_Field_Group_Term class.
5
- *
6
- * @since 1.9
7
- */
8
- final class WPCF_Field_Group_Term_Factory extends WPCF_Field_Group_Factory {
9
-
10
-
11
- /**
12
- * @return WPCF_Field_Group_Term_Factory
13
- */
14
- public static function get_instance() {
15
- return parent::get_instance();
16
- }
17
-
18
- protected function __construct() {
19
- parent::__construct();
20
-
21
- add_action( 'wpcf_group_updated', array( $this, 'on_group_updated' ), 10, 2 );
22
- }
23
-
24
-
25
- /**
26
- * Load a field group instance.
27
- *
28
- * @param int|string|WP_Post $field_group Post ID of the field group, it's name or a WP_Post object.
29
- *
30
- * @return null|WPCF_Field_Group_Term Field group or null if it can't be loaded.
31
- */
32
- public static function load( $field_group ) {
33
- // we cannot use self::get_instance here, because of low PHP requirements and missing get_called_class function
34
- // we have a fallback class for get_called_class but that scans files by debug_backtrace and return 'self'
35
- // instead of WPCF_Field_Group_Term_Factory like the original get_called_class() function does
36
- // ends in an error because of parents (abstract) $var = new self();
37
- return WPCF_Field_Group_Term_Factory::get_instance()->load_field_group( $field_group );
38
- }
39
-
40
-
41
- /**
42
- * Create new field group.
43
- *
44
- * @param string $name Sanitized field group name. Note that the final name may change when new post is inserted.
45
- * @param string $title Field group title.
46
- *
47
- * @return null|WPCF_Field_Group The new field group or null on error.
48
- */
49
- public static function create( $name, $title = '' ) {
50
- // we cannot use self::get_instance here, because of low PHP requirements and missing get_called_class function
51
- // we have a fallback class for get_called_class but that scans files by debug_backtrace and return 'self'
52
- // instead of WPCF_Field_Group_Term_Factory like the original get_called_class() function does
53
- // ends in an error because of parents (abstract) $var = new self();
54
- return WPCF_Field_Group_Term_Factory::get_instance()->create_field_group( $name, $title );
55
- }
56
-
57
-
58
- protected function get_post_type() {
59
- return WPCF_Field_Group_Term::POST_TYPE;
60
- }
61
-
62
-
63
- protected function get_field_group_class_name() {
64
- return 'WPCF_Field_Group_Term';
65
- }
66
-
67
-
68
- /**
69
- * @var null|WPCF_Field_Group_Term[][] Cache for the get_groups_by_taxonomies() method.
70
- */
71
- private $taxonomy_assignment_cache = null;
72
-
73
-
74
- /**
75
- * Produce a list of all taxonomies with groups that belong to them.
76
- *
77
- * @return WPCF_Field_Group_Term[][] Associative array where keys are taxonomy slugs and values are arrays of field
78
- * groups that are associated with those taxonomies.
79
- */
80
- public function get_groups_by_taxonomies() {
81
- if( null == $this->taxonomy_assignment_cache ) {
82
- $groups = $this->query_groups();
83
- $taxonomies = get_taxonomies();
84
-
85
- $this->taxonomy_assignment_cache = array();
86
- foreach( $taxonomies as $taxonomy ) {
87
- $taxonomy_slug = $taxonomy;
88
- $groups_for_taxonomy = array();
89
-
90
- foreach( $groups as $group ) {
91
- if( $group instanceof WPCF_Field_Group_Term
92
- && $group->is_active()
93
- && $group->has_associated_taxonomy( $taxonomy_slug )
94
- ) {
95
- $groups_for_taxonomy[] = $group;
96
- }
97
- }
98
-
99
- $this->taxonomy_assignment_cache[ $taxonomy_slug ] = $groups_for_taxonomy;
100
- }
101
- }
102
-
103
- return $this->taxonomy_assignment_cache;
104
- }
105
-
106
-
107
- /**
108
- * Get array of groups that are associated with given taxonomy.
109
- *
110
- * @param string $taxonomy_slug Slug of the taxonomy
111
- * @return WPCF_Field_Group_Term[] Associated term field groups.
112
- */
113
- public function get_groups_by_taxonomy( $taxonomy_slug ) {
114
- $groups_by_taxonomies = $this->get_groups_by_taxonomies();
115
- return wpcf_ensarr( wpcf_getarr( $groups_by_taxonomies, $taxonomy_slug ) );
116
- }
117
-
118
-
119
- /**
120
- * This needs to be executed whenever a term group is updated.
121
- *
122
- * Hooked into the wpcf_group_updated action.
123
- * Erases cache for the get_groups_by_taxonomies() method.
124
- *
125
- * @param int $group_id Ignored
126
- * @param WPCF_Field_Group $group Field group that has been just updated.
127
- */
128
- public function on_group_updated( /** @noinspection PhpUnusedParameterInspection */ $group_id, $group ) {
129
- if( $group instanceof WPCF_Field_Group_Term ) {
130
- $this->taxonomy_assignment_cache = null;
131
- }
132
- }
133
-
134
-
135
-
136
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/renderer/factory.php DELETED
@@ -1,86 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Factory for field renderers.
5
- *
6
- * This is especially useful because in most cases different types of fields have to use different renderers in
7
- * different context. The logic for choosing the right renderer should be completely encapsulated in this class.
8
- *
9
- * @since 1.9.1
10
- */
11
- final class WPCF_Field_Renderer_Factory {
12
-
13
- private static $instance = null;
14
-
15
- private function __construct() { }
16
-
17
- public static function get_instance() {
18
- if( null == self::$instance ) {
19
- self::$instance = new self();
20
- }
21
- return self::$instance;
22
- }
23
-
24
-
25
- /**
26
- * Get a preview renderer for given field.
27
- *
28
- * @param WPCF_Field_Instance_Abstract $field
29
- * @param array $args Arguments for the preview renderer.
30
- * @return WPCF_Field_Renderer_Preview_Base Preview renderer for a specific field.
31
- * @throws InvalidArgumentException
32
- * @since 1.9.1
33
- */
34
- public function create_preview_renderer( $field, $args = array() ) {
35
-
36
- if( ! $field instanceof WPCF_Field_Instance_Abstract ) {
37
- throw new InvalidArgumentException( 'Not a field instance.' );
38
- }
39
-
40
- if( ! is_array( $args ) ) {
41
- throw new InvalidArgumentException( 'Not an array.' );
42
- }
43
-
44
- $field_type = $field->get_field_type();
45
- switch( $field_type->get_slug() ) {
46
-
47
- case WPCF_Field_Type_Definition_Factory::GOOGLE_ADDRESS:
48
- return new WPCF_Field_Renderer_Preview_Address( $field, $args );
49
-
50
- case WPCF_Field_Type_Definition_Factory::AUDIO:
51
- case WPCF_Field_Type_Definition_Factory::FILE:
52
- case WPCF_Field_Type_Definition_Factory::VIDEO:
53
- return new WPCF_Field_Renderer_Preview_File( $field, $args );
54
-
55
- case WPCF_Field_Type_Definition_Factory::COLORPICKER:
56
- return new WPCF_Field_Renderer_Preview_Colorpicker( $field, $args );
57
-
58
- case WPCF_Field_Type_Definition_Factory::DATE:
59
- return new WPCF_Field_Renderer_Preview_Date( $field, $args );
60
-
61
- case WPCF_Field_Type_Definition_Factory::EMBED:
62
- case WPCF_Field_Type_Definition_Factory::URL:
63
- return new WPCF_Field_Renderer_Preview_URL( $field, $args );
64
-
65
- case WPCF_Field_Type_Definition_Factory::CHECKBOX:
66
- return new WPCF_Field_Renderer_Preview_Checkbox( $field, $args );
67
-
68
- case WPCF_Field_Type_Definition_Factory::CHECKBOXES:
69
- return new WPCF_Field_Renderer_Preview_Checkboxes( $field, $args );
70
-
71
- case WPCF_Field_Type_Definition_Factory::IMAGE:
72
- return new WPCF_Field_Renderer_Preview_Image( $field, $args );
73
-
74
- case WPCF_Field_Type_Definition_Factory::RADIO:
75
- case WPCF_Field_Type_Definition_Factory::SELECT:
76
- return new WPCF_Field_Renderer_Preview_Radio( $field, $args );
77
-
78
- case WPCF_Field_Type_Definition_Factory::SKYPE:
79
- return new WPCF_Field_Renderer_Preview_Skype( $field, $args );
80
-
81
- default:
82
- return new WPCF_Field_Renderer_Preview_Textfield( $field, $args );
83
- break;
84
- }
85
- }
86
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/term_definition_factory.php DELETED
@@ -1,51 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Factory for term field definitions.
5
- */
6
- final class WPCF_Field_Term_Definition_Factory extends WPCF_Field_Definition_Factory {
7
-
8
- /**
9
- * Name of the option used to store term field definitions.
10
- */
11
- const FIELD_DEFINITIONS_OPTION = 'wpcf-termmeta';
12
-
13
-
14
- protected function get_option_name() {
15
- return self::FIELD_DEFINITIONS_OPTION;
16
- }
17
-
18
-
19
- protected function get_class_name() {
20
- return 'WPCF_Field_Definition_Term';
21
- }
22
-
23
-
24
- /**
25
- * Shortcut to load_field_definition().
26
- *
27
- * @param string $field_key
28
- * @return null|WPCF_Field_Definition
29
- */
30
- static function load( $field_key ) {
31
- // we cannot use self::get_instance here, because of low PHP requirements and missing get_called_class function
32
- // we have a fallback class for get_called_class but that scans files by debug_backtrace and return 'self'
33
- // instead of WPCF_Field_Term_Definition_Factory like the original get_called_class() function does
34
- // ends in an error because of parents (abstract) $var = new self();
35
- return WPCF_Field_Term_Definition_Factory::get_instance()->load_field_definition( $field_key );
36
- }
37
-
38
- /**
39
- * @return string[] All existing meta keys within the domain (= term meta).
40
- */
41
- protected function get_existing_meta_keys() {
42
- global $wpdb;
43
-
44
- $meta_keys = $wpdb->get_col(
45
- "SELECT meta_key FROM {$wpdb->termmeta} GROUP BY meta_key HAVING meta_key NOT LIKE '\_%' ORDER BY meta_key"
46
- );
47
-
48
- return $meta_keys;
49
- }
50
-
51
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/type_definition.php DELETED
@@ -1,79 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Field type definition.
5
- *
6
- * This represents a single field type like "email", "audio", "checkbox" and so on. This class must be instantiated
7
- * exclusively through WPCF_Field_Type_Definition_Factory.
8
- */
9
- final class WPCF_Field_Type_Definition {
10
-
11
-
12
- /**
13
- * @var string Slug of the registered field type.
14
- */
15
- private $field_type_slug;
16
-
17
-
18
- /**
19
- * @var string Name of the field type that can be displayed to the user.
20
- */
21
- private $display_name;
22
-
23
-
24
- /**
25
- * @var string Field description entered by the user.
26
- */
27
- private $description;
28
-
29
-
30
- /**
31
- * @var array Arguments defining the field type. Can contain some legacy values.
32
- */
33
- private $args;
34
-
35
-
36
- /**
37
- * WPCF_Field_Type_Definition constructor.
38
- *
39
- * @param string $field_type_slug Field type slug.
40
- * @param array $args Additional array of arguments which should contain at least 'display_name' (or 'title')
41
- * and 'description' elements, but omitting them is not critical.
42
- */
43
- public function __construct( $field_type_slug, $args ) {
44
-
45
- if( sanitize_title( $field_type_slug ) != $field_type_slug ) {
46
- throw new InvalidArgumentException( 'Invalid field type slug.' );
47
- }
48
-
49
- if( ! is_array( $args ) ) {
50
- throw new InvalidArgumentException( 'Wrong arguments provided.' );
51
- }
52
-
53
- $this->field_type_slug = $field_type_slug;
54
-
55
- // Try to fall back to legacy "title", and if even that fails, use id instead.
56
- $this->display_name = sanitize_text_field( wpcf_getarr( $args, 'display_name', wpcf_getarr( $args, 'title', $field_type_slug ) ) );
57
-
58
- $this->description = wpcf_getarr( $args, 'description', '' );
59
- $this->args = $args;
60
- }
61
-
62
-
63
- public function get_slug() { return $this->field_type_slug; }
64
-
65
- public function get_display_name() { return $this->display_name; }
66
-
67
- public function get_description() { return $this->description; }
68
-
69
-
70
- /**
71
- * Direct access to the field type configuration.
72
- *
73
- * It is strongly encouraged to write custom (and safe) getters for anything you need to get from it.
74
- *
75
- * @return array
76
- */
77
- public function get_args() { return $this->args; }
78
-
79
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/type_definition_factory.php DELETED
@@ -1,148 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Factory class for loading field type definitions.
5
- *
6
- * Handles creation of the objects as well as their caching.
7
- *
8
- * Currently it is only possible to load existing field types, not create new ones. We're depending on the legacy code
9
- * in WPCF_Fields and field types defined through specially named functions. But that is hidden from anyone who uses
10
- * this class.
11
- *
12
- * @since 1.9
13
- */
14
- final class WPCF_Field_Type_Definition_Factory {
15
-
16
- const AUDIO = 'audio';
17
- const COLORPICKER = 'colorpicker';
18
- const DATE = 'date';
19
- const EMBED = 'embed';
20
- const FILE = 'file';
21
- const GOOGLE_ADDRESS = 'google_address';
22
- const CHECKBOX = 'checkbox';
23
- const CHECKBOXES = 'checkboxes';
24
- const IMAGE = 'image';
25
- const RADIO = 'radio';
26
- const SELECT = 'select';
27
- const SKYPE = 'skype';
28
- const URL = 'url';
29
- const VIDEO = 'video';
30
-
31
- private static $instance = null;
32
-
33
- private function __construct() { }
34
-
35
- private function __clone() { }
36
-
37
-
38
- public static function get_instance() {
39
- if( null == self::$instance ) {
40
- self::$instance = new self();
41
- }
42
- return self::$instance;
43
- }
44
-
45
-
46
- /**
47
- * @var array Associative array of instantiated field type definitions, indexed by field type slugs ("checkbox",
48
- * "email" and such).
49
- */
50
- private $field_type_definitions = array();
51
-
52
-
53
- /**
54
- * @var null|array Cached array containing path to files (!) that contain specially named functions (!) that
55
- * can be used to return configuration array for a field type (!). We're caching it because
56
- * WPCF_Fields::getFieldsTypes() applies a filter each time it is called.
57
- */
58
- private $legacy_field_types = null;
59
-
60
-
61
- /**
62
- * @return array See $legacy_field_types.
63
- */
64
- private function get_legacy_field_types() {
65
- if( null == $this->legacy_field_types ) {
66
- $this->legacy_field_types = WPCF_Fields::getFieldsTypes();
67
- }
68
- return $this->legacy_field_types;
69
- }
70
-
71
-
72
- /**
73
- * Load a field type definition.
74
- *
75
- * @param string $field_type_slug Slug of the field type. If the function fails to find the field type and the slug
76
- * starts with a "wpcf-" prefix, it attempts to remove it and search again. This way, passing a field type ID,
77
- * which usually has this form, is also supported.
78
- * @return null|WPCF_Field_Type_Definition Field type definition or null if it can't be loaded.
79
- */
80
- public function load_field_type_definition( $field_type_slug ) {
81
-
82
- if( !is_string( $field_type_slug ) ) {
83
- return null;
84
- }
85
-
86
- // Check if we can use cached version.
87
- if( !array_key_exists( $field_type_slug, $this->field_type_definitions ) ) {
88
-
89
- // now it gets hacky
90
- $field_types = $this->get_legacy_field_types();
91
- if( !array_key_exists( $field_type_slug, $field_types ) ) {
92
- // Field slug not recognized. Maybe we got a field identifier instead. Check if we can remove
93
- // the wpcf- prefix and try again.
94
- $prefix = 'wpcf-';
95
- if( substr( $field_type_slug, 0, strlen( $prefix ) ) == $prefix ) {
96
- $field_type_slug = substr( $field_type_slug, strlen( $prefix ) );
97
- if( !array_key_exists( $field_type_slug, $field_types ) ) {
98
- // Removing prefix didn't help
99
- return null;
100
- }
101
- // Check the cache again (now with correct slug).
102
- if( array_key_exists( $field_type_slug, $this->field_type_definitions ) ) {
103
- return $this->field_type_definitions[ $field_type_slug ];
104
- }
105
- } else {
106
- // There was no prefix to remove.
107
- return null;
108
- }
109
- }
110
-
111
- // Not using getFieldTypeData() directly to avoid unnecessary getFieldsTypes() and filter applying.
112
- $field_type_configuration_path = $field_types[ $field_type_slug ];
113
- $field_type_configuration = WPCF_Fields::getFieldTypeConfig( $field_type_configuration_path );
114
-
115
- $field_type_id = wpcf_getarr( $field_type_configuration, 'id', null );
116
- if( null == $field_type_id ) {
117
- return null;
118
- }
119
-
120
- try {
121
- $field_type_definition = new WPCF_Field_Type_Definition( $field_type_slug, $field_type_configuration );
122
- } catch( Exception $e ) {
123
- return null;
124
- }
125
-
126
- // Save new instance to cache.
127
- $this->field_type_definitions[ $field_type_slug ] = $field_type_definition;
128
- }
129
-
130
- // Use cache.
131
- return $this->field_type_definitions[ $field_type_slug ];
132
- }
133
-
134
-
135
- /**
136
- * Static shortcut to load_field_type_definition.
137
- *
138
- * @param string $field_type_slug
139
- * @return null|WPCF_Field_Type_Definition
140
- */
141
- public static function load( $field_type_slug ) {
142
- // we cannot use self::get_instance here, because of low PHP requirements and missing get_called_class function
143
- // we have a fallback class for get_called_class but that scans files by debug_backtrace and return 'self'
144
- // instead of WPCF_Field_Type_Definition_Factory like the original get_called_class() function does
145
- // ends in an error because of parents (abstract) $var = new self();
146
- return WPCF_Field_Type_Definition_Factory::get_instance()->load_field_type_definition( $field_type_slug );
147
- }
148
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/field/utils.php DELETED
@@ -1,65 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Static class for shortcut functions related to field types, groups, definitions and instances.
5
- * @since 1.9
6
- */
7
- final class WPCF_Field_Utils {
8
-
9
- private function __construct() { }
10
-
11
-
12
- /**
13
- * Create a term field instance.
14
- *
15
- * @param string $field_slug Slug of existing field definition.
16
- * @param int $term_id ID of the term where the field belongs.
17
- *
18
- * @return null|WPCF_Field_Instance Field instance or null if an error occurs.
19
- * @since 1.9
20
- */
21
- public static function create_term_field_instance( $field_slug, $term_id ) {
22
- try {
23
- return new WPCF_Field_Instance_Term( WPCF_Field_Term_Definition_Factory::load( $field_slug ), $term_id );
24
- } catch( Exception $e ) {
25
- return null;
26
- }
27
- }
28
-
29
-
30
- /**
31
- * Obtain toolset-forms "field configuration", which is an array of settings for specific field instance.
32
- *
33
- * @param WPCF_Field_Instance $field
34
- * @since 1.9
35
- */
36
- public static function get_toolset_forms_field_config( $field ) {
37
- return wptoolset_form_filter_types_field(
38
- $field->get_definition()->get_definition_array(),
39
- $field->get_object_id()
40
- );
41
- }
42
-
43
-
44
- /**
45
- * Gather an unique array of field definitions from given groups.
46
- *
47
- * The groups are expected to belong to the same domain (term/post/user), otherwise problems may occur when
48
- * field slugs conflict.
49
- *
50
- * @param WPCF_Field_Group[] $field_groups
51
- * @return WPCF_Field_Definition[]
52
- * @since 1.9
53
- */
54
- public static function get_field_definitions_from_groups( $field_groups ) {
55
- $field_definitions = array();
56
- foreach( $field_groups as $group ) {
57
- $group_field_definitions = $group->get_field_definitions();
58
-
59
- foreach( $group_field_definitions as $field_definition ) {
60
- $field_definitions[ $field_definition->get_slug() ] = $field_definition;
61
- }
62
- }
63
- return $field_definitions;
64
- }
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/gui/term_field_editing.php DELETED
@@ -1,411 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Adds support for displaying and updating term fields on Edit Term page.
5
- *
6
- * Hooks into taxonomy-specific actions if there are some term field groups associated. Handles rendering fields
7
- * through toolset-forms (hidden inside the renderer).
8
- *
9
- * @since 1.9
10
- */
11
- final class WPCF_GUI_Term_Field_Editing {
12
-
13
-
14
- // This class is a singleton.
15
- private static $instance = null;
16
-
17
-
18
- /**
19
- * ID of the form for toolset-forms.
20
- *
21
- * The value is not arbitrary, it must match the actual ID of the form tag, otherwise JS validation will break
22
- * (and who knows what else). In this case the ID is dictated by the add and edit term pages.
23
- */
24
- const EDIT_FORM_ID = 'edittag';
25
- const ADD_FORM_ID = 'addtag';
26
-
27
-
28
- public static function initialize() {
29
- if( null == self::$instance ) {
30
- self::$instance = new self();
31
- }
32
- }
33
-
34
-
35
- private function __construct() {
36
- $this->add_hooks();
37
- }
38
-
39
-
40
- /**
41
- * Hooks into taxonomy-specific actions if there are some term field groups associated.
42
- */
43
- private function add_hooks() {
44
-
45
- $factory = WPCF_Field_Group_Term_Factory::get_instance();
46
- $groups_by_taxonomies = $factory->get_groups_by_taxonomies();
47
-
48
- $is_toolset_forms_support_needed = false;
49
-
50
- // Hooks for editing term fields
51
- foreach( $groups_by_taxonomies as $taxonomy => $groups ) {
52
- if( !empty( $groups ) ) {
53
-
54
- add_action( "{$taxonomy}_add_form_fields", array( $this, 'on_term_add' ) );
55
- add_action( "{$taxonomy}_edit_form_fields", array( $this, 'on_term_edit' ), 10, 2 );
56
- // add_action( "create_{$taxonomy}", array( $this, 'on_term_update' ), 10, 2 );
57
- add_action( "edit_{$taxonomy}", array( $this, 'on_term_update' ), 10, 2 );
58
-
59
- $is_toolset_forms_support_needed = true;
60
- }
61
- }
62
-
63
- // Columns on the term listing
64
- $is_term_listing_page = ( 'edit' != wpcf_getget( 'action' ) );
65
- if( $is_term_listing_page ) {
66
- $screen = get_current_screen();
67
- add_action( "manage_{$screen->id}_columns", array( $this, 'manage_term_listing_columns' ) );
68
- add_filter( "manage_{$screen->taxonomy}_custom_column", array( $this, 'manage_term_listing_cell'), 10, 3 );
69
- }
70
-
71
- if( $is_toolset_forms_support_needed ) {
72
- $this->add_toolset_forms_support();
73
- }
74
- }
75
-
76
-
77
- public function on_term_add( $taxonomy_slug ) {
78
- $groups = WPCF_Field_Group_Term_Factory::get_instance()->get_groups_by_taxonomy( $taxonomy_slug );
79
-
80
- if( !empty( $groups ) ) {
81
- printf(
82
- '<div class="wpcf-add-term-page-box"><strong>%s</strong></div>',
83
- __( 'This taxonomy has custom fields. You will be able to edit them after the term is saved.', 'wpcf' )
84
- );
85
- }
86
-
87
- /*if( empty( $groups ) ) {
88
- return;
89
- }
90
-
91
- foreach( $groups as $group ) {
92
- $this->render_field_group_add_page( $group, null );
93
- }*/
94
- }
95
-
96
-
97
- /**
98
- * This will be called when editing an existing term.
99
- *
100
- * Renders term field groups associated with the taxonomy with all their fields, via toolset-forms.
101
- *
102
- * @link https://developer.wordpress.org/reference/hooks/taxonomy_edit_form_fields/
103
- *
104
- * @param WP_Term $term Term that is being edited.
105
- * @param string $taxonomy_slug Taxonomy where the term belongs.
106
- */
107
- public function on_term_edit( $term, $taxonomy_slug ) {
108
- $groups = WPCF_Field_Group_Term_Factory::get_instance()->get_groups_by_taxonomy( $taxonomy_slug );
109
-
110
- if( empty( $groups ) ) {
111
- return;
112
- }
113
-
114
- foreach( $groups as $group ) {
115
- $this->render_field_group_edit_page( $group, $term->term_id );
116
- }
117
- }
118
-
119
-
120
- public function on_term_update( $term_id, $tt_id ) {
121
-
122
- // Get an array of fields that we need to update. We don't care about their groups here.
123
- $term = get_term_by( 'term_taxonomy_id', $tt_id );
124
- if( ! $term instanceof WP_Term ) {
125
- return;
126
- }
127
- $groups = WPCF_Field_Group_Term_Factory::get_instance()->get_groups_by_taxonomy( $term->taxonomy );
128
- if( empty( $groups ) ) {
129
- return;
130
- }
131
- $field_definitions = WPCF_Field_Utils::get_field_definitions_from_groups( $groups );
132
-
133
- $update_errors = $this->update_term_fields( $term_id, $field_definitions );
134
-
135
- // Display errors if we have any.
136
- if( !empty( $update_errors ) ) {
137
- foreach( $update_errors as $update_error ) {
138
- wpcf_admin_message_store( $update_error->get_error_message(), 'error' );
139
- }
140
- wpcf_admin_message_store(
141
- sprintf(
142
- '<strong>%s</strong>',
143
- __( 'There has been a problem while saving custom fields. Please fix it and try again.', 'wpcf' )
144
- ),
145
- 'error'
146
- );
147
- }
148
-
149
- }
150
-
151
-
152
- /**
153
- * Update fields for given term.
154
- *
155
- * @param int $term_id
156
- * @param WPCF_Field_Definition[] $field_definitions
157
- * @return WP_Error[]
158
- */
159
- private function update_term_fields( $term_id, $field_definitions ) {
160
- $update_results = array();
161
- foreach( $field_definitions as $field_definition ) {
162
- $update_results[] = $this->update_single_field( $field_definition, $term_id );
163
- }
164
- return $this->filter_wp_errors_flat( $update_results );
165
- }
166
-
167
-
168
- /**
169
- * From an array that can contain booleans, WP_Error and arrays of WP_Error, create an array containing all
170
- * WP_Error instances only.
171
- *
172
- * @param array $update_results
173
- * @return WP_Error[]
174
- */
175
- private function filter_wp_errors_flat( $update_results ) {
176
- $errors = array();
177
- foreach( $update_results as $update_result ) {
178
- if( $update_result instanceof WP_Error ) {
179
- $errors[] = $update_result;
180
- } else if( is_array( $update_result ) ) {
181
- foreach( $update_result as $error ) {
182
- if( $error instanceof WP_Error ) {
183
- $errors[] = $error;
184
- }
185
- }
186
- }
187
- }
188
- return $errors;
189
- }
190
-
191
-
192
- /**
193
- * @param WPCF_Field_Definition $field_definition
194
- * @param int $term_id
195
- *
196
- * @return WP_Error|WP_Error[]|true
197
- */
198
- private function update_single_field( $field_definition, $term_id ) {
199
- $field = new WPCF_Field_Instance_Term( $field_definition, $term_id );
200
- $saver = new WPCF_Field_Data_Saver( $field, self::EDIT_FORM_ID );
201
-
202
- $validation_results = $saver->validate_field_data();
203
-
204
- $errors = array();
205
- foreach( $validation_results as $index => $validation_result ) {
206
-
207
- if( $validation_result instanceof WP_Error ) {
208
- $error_message = sprintf( '%s %s',
209
- sprintf( __( 'Field "%s" not updated:', 'wpcf' ), $field_definition->get_name() ),
210
- implode( ', ', $validation_result->get_error_data() )
211
- );
212
- $errors[] = new WP_Error( 'wpcf_field_not_updated', $error_message );
213
- }
214
- }
215
-
216
- if( !empty( $errors ) ) {
217
- return $errors;
218
- }
219
-
220
- $saving_result = $saver->save_field_data();
221
-
222
- return $saving_result;
223
- }
224
-
225
-
226
- /**
227
- * Load various assets needed by the toolset-forms blob.
228
- *
229
- * @since 1.9
230
- */
231
- private function add_toolset_forms_support() {
232
- // JS and CSS assets related to fields - mostly generic ones.
233
- wpcf_edit_post_screen_scripts();
234
-
235
- // Needed for fields that have something to do with files
236
- WPToolset_Field_File::file_enqueue_scripts();
237
-
238
- // Extra enqueuing of media assets needed since WPToolset_Field_File doesn't know about termmeta.
239
- wp_enqueue_media();
240
-
241
- // We need to append form-specific data for the JS validation script.
242
- add_action( 'admin_footer', array( $this, 'render_js_validation_data' ) );
243
-
244
- // Pretend we're about to create new form via toolset-forms, even if we're not going to.
245
- // This will load some assets needed for image field preview (specifically the 'wptoolset-forms-admin' style).
246
- // Hacky, but better than re-registering the toolset-forms stylesheet elsewhere.
247
- $faux_form_bootstrap = new WPToolset_Forms_Bootstrap();
248
- $faux_form_bootstrap->form( 'faux' );
249
- }
250
-
251
-
252
- /**
253
- * Appends form-specific data for the JS validation script.
254
- *
255
- * @since 1.9
256
- */
257
- public function render_js_validation_data() {
258
- wpcf_form_render_js_validation( '.validate' );
259
- }
260
-
261
-
262
- /**
263
- * Render table rows with individual field group.
264
- *
265
- * @param WPCF_Field_Group_Term $field_group
266
- * @param int|null $term_id ID of the term whose fields are being rendered.
267
- */
268
- private function render_field_group_edit_page( $field_group, $term_id ) {
269
- $field_definitions = $field_group->get_field_definitions();
270
-
271
- printf(
272
- '<tr><th scope="row" colspan="2"><hr /><strong>%s</strong></th></tr>',
273
- $field_group->get_display_name()
274
- );
275
-
276
- /** @var WPCF_Field_Definition_Term $field_definition */
277
- foreach( $field_definitions as $field_definition ) {
278
- printf(
279
- '<tr class="form-field"><th scope="row">%s</th><td>%s</td></tr>',
280
- $field_definition->get_display_name(),
281
- $this->get_toolset_forms_field( $field_definition, self::EDIT_FORM_ID, $term_id, true )
282
- );
283
- }
284
- }
285
-
286
-
287
- /**
288
- * Render table rows with individual field group.
289
- *
290
- * @param WPCF_Field_Group_Term $field_group
291
- * @param int|null $term_id ID of the term whose fields are being rendered.
292
- */
293
- /*private function render_field_group_add_page( $field_group, $term_id ) {
294
- $field_definitions = $field_group->get_field_definitions();
295
-
296
- printf(
297
- '<hr /><h4>%s</h4>',
298
- $field_group->get_title()
299
- );
300
-
301
- /// @var WPCF_Field_Definition_Term $field_definition
302
- foreach( $field_definitions as $field_definition ) {
303
- printf(
304
- '<div class="form-field wpcf-add-term-form-field">%s</div>',
305
- $this->get_toolset_forms_field( $field_definition, self::ADD_FORM_ID, $term_id, false )
306
- );
307
- }
308
- }*/
309
-
310
-
311
- /**
312
- * Get the toolset-forms markup for an individual field.
313
- *
314
- * @param WPCF_Field_Definition_Term $field_definition
315
- * @param string $form_id ID of the form for toolset-forms.
316
- * @param int|null $term_id ID of the term whose fields are being rendered.
317
- * @param bool $hide_field_title Determine if toolset-forms title above the field should be displayed.
318
- *
319
- * @return string Markup with the field.
320
- */
321
- private function get_toolset_forms_field( $field_definition, $form_id, $term_id, $hide_field_title ) {
322
-
323
- if( null == $term_id ) {
324
- $field = new WPCF_Field_Instance_Unsaved( $field_definition );
325
- } else {
326
- $field = new WPCF_Field_Instance_Term( $field_definition, $term_id );
327
- }
328
-
329
- $tf_renderer = new WPCF_Field_Renderer_Toolset_Forms( $field, $form_id );
330
- $tf_renderer->setup( array( 'hide_field_title' => (bool) $hide_field_title ) );
331
-
332
- return $tf_renderer->render( false );
333
-
334
- }
335
-
336
-
337
- /** Prefix for column names so we have no conflicts beyond any doubt. */
338
- const LISTING_COLUMN_PREFIX = 'wpcf_field_';
339
-
340
-
341
- /**
342
- * Add a column for each term field on the term listing page.
343
- *
344
- * @param string[string] $columns Column definitions (column name => display name).
345
- * @return string[string] Updated column definitions.
346
- * @link https://make.wordpress.org/docs/plugin-developer-handbook/10-plugin-components/custom-list-table-columns/
347
- * @since 1.9.1
348
- */
349
- public function manage_term_listing_columns( $columns ) {
350
-
351
- $taxonomy_slug = wpcf_getget( 'taxonomy' );
352
- $groups = WPCF_Field_Group_Term_Factory::get_instance()->get_groups_by_taxonomy( $taxonomy_slug );
353
-
354
- $columns_to_insert = array();
355
- foreach( $groups as $group ) {
356
- foreach( $group->get_field_definitions() as $field_definition ) {
357
- $columns_to_insert[ self::LISTING_COLUMN_PREFIX . $field_definition->get_slug() ] = $field_definition->get_display_name();
358
- }
359
- }
360
-
361
- // Insert before the last column, which displays counts of posts using the term (that's probably why column
362
- // has the label "Count" and name "posts" :-P).
363
- $columns = WPCF_Utils::insert_at_position( $columns, $columns_to_insert, array( 'key' => 'posts', 'where' => 'before' ) );
364
- return $columns;
365
- }
366
-
367
-
368
- /**
369
- * Render single cell in a term listing table.
370
- *
371
- * Catch field columns by their name prefix and render field values with preview renderer.
372
- *
373
- * @param mixed $value ""
374
- * @param string $column_name
375
- * @param int $term_id
376
- * @link https://make.wordpress.org/docs/plugin-developer-handbook/10-plugin-components/custom-list-table-columns/
377
- * @return string Rendered HTML with the table cell content.
378
- * @since 1.9.1
379
- */
380
- public function manage_term_listing_cell( $value, $column_name, $term_id ) {
381
-
382
- // Deal only with our custom columns.
383
- $is_term_field_cell = ( substr( $column_name, 0, strlen( self::LISTING_COLUMN_PREFIX ) ) == self::LISTING_COLUMN_PREFIX );
384
-
385
- if( $is_term_field_cell ) {
386
-
387
- try {
388
-
389
- $field_slug = substr( $column_name, strlen( self::LISTING_COLUMN_PREFIX ) );
390
- $field_definition = WPCF_Field_Term_Definition_Factory::load( $field_slug );
391
- $field = new WPCF_Field_Instance_Term( $field_definition, $term_id );
392
-
393
- $renderer_args = array(
394
- 'maximum_item_count' => 5,
395
- 'maximum_item_length' => 30,
396
- 'maximum_total_length' => 100
397
- );
398
-
399
- $renderer = WPCF_Field_Renderer_Factory::get_instance()->create_preview_renderer( $field, $renderer_args );
400
-
401
- $value = $renderer->render();
402
-
403
- } catch( Exception $e ) {
404
- // Do nothing when we're unable to load the field.
405
- }
406
-
407
- }
408
-
409
- return $value;
410
- }
411
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/loader.php DELETED
@@ -1,335 +0,0 @@
1
- <?php
2
- /**
3
- *
4
- * Loader class
5
- *
6
- *
7
- */
8
-
9
- /**
10
- * Loader Class
11
- *
12
- * @since Types 1.2
13
- * @package Types
14
- * @subpackage Classes
15
- * @version 0.2
16
- * @category Loader
17
- * @author srdjan <srdjan@icanlocalize.com>
18
- */
19
- class WPCF_Loader
20
- {
21
-
22
- /**
23
- * Settings
24
- * @var array
25
- */
26
- private static $__settings = array();
27
-
28
- public static function init( $settings = array() ) {
29
- self::$__settings = (array) $settings;
30
- self::__registerScripts();
31
- self::__registerStyles();
32
- self::__toolset();
33
- add_action( 'admin_print_scripts', array('WPCF_Loader', 'renderJsSettings'), 5 );
34
- add_filter( 'the_posts', array('WPCF_Loader', 'wpcf_cache_complete_postmeta') );
35
- add_filter( 'wpcf_fields_postmeta_value_save', array( 'WPCF_Loader', 'wpcf_sanitize_postmeta_values_on_save' ) );
36
- add_filter( 'wpcf_fields_usermeta_value_save', array( 'WPCF_Loader', 'wpcf_sanitize_usermeta_values_on_save' ) );
37
- }
38
-
39
- /**
40
- * Sanitize fields values on save
41
- *
42
- */
43
-
44
- public static function wpcf_sanitize_postmeta_values_on_save( $value ) {
45
- if (
46
- current_user_can( 'unfiltered_html' )
47
- && wpcf_get_settings('postmeta_unfiltered_html') != 'off'
48
- ) {
49
- return $value;
50
- }
51
- if ( is_array( $value ) ) {
52
- // Recursion
53
- $value = array_map( array( 'WPCF_Loader', 'wpcf_sanitize_postmeta_values_on_save' ), $value );
54
- } else {
55
- $value = wp_filter_post_kses( $value );
56
- }
57
- return $value;
58
- }
59
-
60
- public static function wpcf_sanitize_usermeta_values_on_save( $value ) {
61
- if (
62
- current_user_can( 'unfiltered_html' )
63
- && wpcf_get_settings('usermeta_unfiltered_html') != 'off'
64
- ) {
65
- return $value;
66
- }
67
- if ( is_array( $value ) ) {
68
- // Recursion
69
- $value = array_map( array( 'WPCF_Loader', 'wpcf_sanitize_usermeta_values_on_save' ), $value );
70
- } else {
71
- $value = wp_filter_post_kses( $value );
72
- }
73
- return $value;
74
- }
75
-
76
- /**
77
- * Cache the postmeta for posts returned by a WP_Query
78
- *
79
- * @global object $wpdb
80
- *
81
- */
82
-
83
- public static function wpcf_cache_complete_postmeta( $posts ) {
84
- global $wpdb;
85
- if ( !$posts )
86
- return $posts;
87
- $post_ids = array();
88
- $cache_group_ids = 'types_cache_ids';
89
- $cache_group = 'types_cache';
90
- foreach ( $posts as $post ) {
91
- $cache_key_looped_post = md5( 'post::_is_cached' . $post->ID );
92
- $cached_object = wp_cache_get( $cache_key_looped_post, $cache_group_ids );
93
- if ( false === $cached_object ) {
94
- $post_ids[] = intval( $post->ID );
95
- wp_cache_add( $cache_key_looped_post, $post->ID, $cache_group_ids );
96
- }
97
- }
98
- if ( count( $post_ids ) > 0 ) {
99
- $id_list = join( ',', $post_ids );
100
- $all_postmeta = $wpdb->get_results( "SELECT * FROM {$wpdb->postmeta} WHERE post_id IN ($id_list)", OBJECT );
101
- if ( !empty( $all_postmeta ) ) {
102
- $cache_key_keys = array();
103
- foreach ( $all_postmeta as $metarow ) {
104
- $mpid = intval($metarow->post_id);
105
- $mkey = $metarow->meta_key;
106
- $cache_key_keys[$mpid . $mkey][] = $metarow;
107
- }
108
- foreach ( $cache_key_keys as $single_meta_keys => $single_meta_values ) {
109
- $cache_key_looped_new = md5( 'field::_get_meta' . $single_meta_keys );
110
- wp_cache_add( $cache_key_looped_new, $single_meta_values, $cache_group );// WordPress cache
111
- }
112
- }
113
- }
114
- return $posts;
115
- }
116
-
117
- /**
118
- * Register scripts.
119
- */
120
- private static function __registerScripts() {
121
- $min = '';//WPCF_DEBUG ? '-min' : '';
122
- wp_register_script( 'types', WPCF_EMBEDDED_RES_RELPATH . '/js/basic.js',
123
- array('jquery'), WPCF_VERSION, true );
124
- wp_register_script( 'types-knockout',
125
- WPCF_EMBEDDED_RES_RELPATH . '/js/knockout-2.2.1.js',
126
- array('jquery'), WPCF_VERSION, true );
127
- if ( !wp_script_is( 'toolset-colorbox', 'registered' ) ) {
128
- wp_register_script( 'toolset-colorbox',
129
- WPCF_EMBEDDED_RES_RELPATH . '/js/jquery.colorbox-min.js',
130
- array('jquery'), WPCF_VERSION, true );
131
- }
132
- wp_register_script( 'types-utils',
133
- WPCF_EMBEDDED_RES_RELPATH . "/js/utils{$min}.js", array('jquery'),
134
- WPCF_VERSION, true );
135
- wp_register_script( 'types-wp-views',
136
- WPCF_EMBEDDED_RES_RELPATH . '/js/wp-views.js', array('jquery'),
137
- WPCF_VERSION, true );
138
- global $pagenow;
139
- // Exclude on post edit screen
140
- if ( defined( 'WPTOOLSET_FORMS_ABSPATH' )
141
- && !in_array( $pagenow, array('edit.php', 'post.php', 'post-new.php') ) ) {
142
- wp_register_script( 'types-conditional',
143
- WPCF_EMBEDDED_RES_RELPATH . '/js/conditional.js',
144
- array('types-utils'), WPCF_VERSION, true );
145
- wp_register_script( 'types-validation',
146
- WPCF_EMBEDDED_RES_RELPATH . "/js/validation{$min}.js",
147
- array('jquery'), WPCF_VERSION, true );
148
- }
149
- // wp_register_script( 'types-jquery-validation',
150
- // WPCF_EMBEDDED_RES_RELPATH . '/js/jquery-form-validation/jquery.validate-1.11.1.min.js',
151
- // array('jquery'), WPCF_VERSION, true );
152
- // wp_register_script( 'types-jquery-validation-additional',
153
- // WPCF_EMBEDDED_RES_RELPATH . '/js/jquery-form-validation/additional-methods-1.11.1.min.js',
154
- // array('types-jquery-validation'), WPCF_VERSION, true );
155
- // wp_register_script( 'types-js-validation',
156
- // WPCF_EMBEDDED_RES_RELPATH . '/js/jquery-form-validation/types.js',
157
- // array('types-jquery-validation-additional'), WPCF_VERSION, true );
158
- }
159
-
160
- /**
161
- * Register styles.
162
- */
163
- private static function __registerStyles() {
164
- wp_register_style( 'types',
165
- WPCF_EMBEDDED_RES_RELPATH . '/css/basic.css', array(),
166
- WPCF_VERSION );
167
- if ( !wp_style_is( 'toolset-colorbox', 'registered' ) ) {
168
- wp_register_style( 'toolset-colorbox',
169
- WPCF_EMBEDDED_RES_RELPATH . '/css/colorbox.css', array(),
170
- WPCF_VERSION );
171
- }
172
- if ( !wp_style_is( 'font-awesome', 'registered' ) ) {
173
- wp_register_style(
174
- 'font-awesome',
175
- WPCF_EMBEDDED_RELPATH.'/toolset/toolset-common/utility/css/font-awesome/css/font-awesome.min.css',
176
- array(),
177
- '4.4.0'
178
- );
179
- }
180
- if ( !wp_style_is( 'toolset-dashicons', 'registered' ) ) {
181
- wp_register_style(
182
- 'toolset-dashicons',
183
- WPCF_EMBEDDED_RES_RELPATH . '/css/dashicons.css',
184
- array(),
185
- WPCF_VERSION
186
- );
187
- }
188
- }
189
-
190
- /**
191
- * Returns HTML formatted output.
192
- *
193
- * @param string $view
194
- * @param mixed $data
195
- * @return string
196
- */
197
- public static function view( $view, $data = array() ) {
198
- $file = WPCF_EMBEDDED_ABSPATH . '/views/'
199
- . strtolower( strval( $view ) ) . '.php';
200
- if ( !file_exists( $file ) ) {
201
- return '<code>missing_view</code>';
202
- }
203
- ob_start();
204
- include $file;
205
- $output = ob_get_contents();
206
- ob_get_clean();
207
-
208
- return apply_filters( 'wpcf_get_view', $output, $view, $data );
209
- }
210
-
211
- /**
212
- * Returns HTML formatted output.
213
- *
214
- * @param string $view
215
- * @param mixed $data
216
- * @return string
217
- */
218
- public static function loadView( $view ) {
219
- $file = WPCF_EMBEDDED_ABSPATH . '/views/'
220
- . strtolower( strval( $view ) ) . '.php';
221
- if ( !file_exists( $file ) ) {
222
- return new WP_Error( 'types_loader', 'missing view ' . $view );
223
- }
224
- require_once $file;
225
- }
226
-
227
- /**
228
- * Returns HTML formatted output.
229
- *
230
- * @param string $template
231
- * @param mixed $data
232
- * @return string
233
- */
234
- public static function template( $template, $data = array() ) {
235
- $file = WPCF_EMBEDDED_ABSPATH . '/views/templates/'
236
- . strtolower( strval( $template ) ) . '.tpl.php';
237
- if ( !file_exists( $file ) ) {
238
- return '<code>missing_template</code>';
239
- }
240
- ob_start();
241
- include $file;
242
- $output = ob_get_contents();
243
- ob_get_clean();
244
-
245
- return apply_filters( 'wpcf_get_template', $output, $template, $data );
246
- }
247
-
248
- /**
249
- * Loads model.
250
- *
251
- * @param string $template
252
- * @param mixed $data
253
- * @return string
254
- */
255
- public static function loadModel( $model ) {
256
- $file = WPCF_EMBEDDED_ABSPATH . '/models/'
257
- . strtolower( strval( $model ) ) . '.php';
258
- if ( !file_exists( $file ) ) {
259
- return new WP_Error( 'types_loader', 'missing model ' . $model );
260
- }
261
- require_once $file;
262
- }
263
-
264
- /**
265
- * Loads class.
266
- *
267
- * @param string $template
268
- * @param mixed $data
269
- * @return string
270
- */
271
- public static function loadClass( $class ) {
272
- $file = WPCF_EMBEDDED_ABSPATH . '/classes/'
273
- . strtolower( strval( $class ) ) . '.php';
274
- if ( !file_exists( $file ) ) {
275
- return new WP_Error( 'types_loader', 'missing class ' . $class );
276
- }
277
- require_once $file;
278
- }
279
-
280
- /**
281
- * Loads include.
282
- *
283
- * @param string $template
284
- * @param mixed $data
285
- * @return string
286
- */
287
- public static function loadInclude( $name, $mode = 'embedded' ) {
288
- $path = $mode == 'plugin' ? WPCF_ABSPATH : WPCF_EMBEDDED_ABSPATH;
289
- $file = $path . '/includes/' . strtolower( strval( $name ) ) . '.php';
290
- if ( !file_exists( $file ) ) {
291
- return new WP_Error( 'types_loader', 'missing include ' . $name );
292
- }
293
- require_once $file;
294
- }
295
-
296
- /**
297
- * Adds JS settings.
298
- *
299
- * @staticvar array $settings
300
- * @param type $id
301
- * @param type $setting
302
- */
303
- public static function addJsSetting( $id, $setting = '' ) {
304
- self::$__settings[$id] = $setting;
305
- }
306
-
307
- /**
308
- * Renders JS settings.
309
- */
310
- public static function renderJsSettings() {
311
- $settings = (array) self::$__settings;
312
- $settings['wpnonce'] = wp_create_nonce( '_typesnonce' );
313
- $settings['cookiedomain'] = COOKIE_DOMAIN;
314
- $settings['cookiepath'] = COOKIEPATH;
315
- $settings['validation'] = array();
316
- echo '
317
- <script type="text/javascript">
318
- //<![CDATA[
319
- var types = ' . json_encode( $settings ) . ';
320
- //]]>
321
- </script>';
322
- }
323
-
324
- /**
325
- * Toolset loading.
326
- */
327
- private static function __toolset() {
328
- // Views
329
- if ( defined( 'WPV_VERSION' ) ) {
330
- self::loadClass( 'wpviews' );
331
- WPCF_WPViews::init();
332
- }
333
- }
334
-
335
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/repeater.php DELETED
@@ -1,1196 +0,0 @@
1
- <?php
2
- /*
3
- *
4
- *
5
- * Repeater fields class.
6
- */
7
-
8
- /**
9
- * Repater class
10
- *
11
- * Very useful, should be used to finish small tasks for repeater field.
12
- *
13
- * Example:
14
- *
15
- * // Setup field
16
- * global $wpcf;
17
- * $my_field = new WPCF_Repeater();
18
- * $my_field->set($wpcf->post, wpcf_admin_fields_get_field('image'));
19
- *
20
- * // Use it
21
- * $my_field->save();
22
- *
23
- * Generic instance can be found in global $wpcf.
24
- * global $wpcf;
25
- * $wpcf->repeater->set(...);
26
- *
27
- * @since Types 1.2
28
- * @package Types
29
- * @subpackage Classes
30
- * @version 0.1
31
- * @category repeater
32
- * @author srdjan <srdjan@icanlocalize.com>
33
- */
34
- class WPCF_Repeater extends WPCF_Field
35
- {
36
-
37
- /**
38
- * Field order
39
- *
40
- * @var type
41
- */
42
- var $order;
43
-
44
- /**
45
- * Indexing
46
- *
47
- * Set counts when processing fields.
48
- *
49
- * @var type
50
- */
51
- var $index = 0;
52
-
53
- /**
54
- * Field title
55
- * @var type
56
- */
57
- var $title = '';
58
-
59
- /**
60
- * Field description.
61
- *
62
- * @var type
63
- */
64
- var $description = '';
65
-
66
- function __construct() {
67
- parent::__construct();
68
- if ( is_admin() ) {
69
- wpcf_admin_add_js_settings( 'wpcf_repetitive_last_warning',
70
- __( 'Sorry, can not delete all fields.', 'wpcf' ) );
71
- }
72
- }
73
-
74
- /**
75
- * Calls parent set func.
76
- *
77
- * @param type $post
78
- * @param type $field
79
- */
80
- function set( $post, $field ) {
81
- parent::set( $post, $field );
82
- $this->index = 0;
83
- }
84
-
85
- /**
86
- * Save fields
87
- *
88
- * If $data empty, $_POST will be checked
89
- *
90
- * @global type $wpcf
91
- * @param type $data
92
- * @return boolean
93
- */
94
- function save( $data = null ) {
95
-
96
- global $wpcf;
97
-
98
- // Delete all fields
99
- do_action('wpcf_postmeta_before_delete_repetitive', $this->post, $this->cf);
100
- delete_post_meta( $this->post->ID, $this->slug );
101
- do_action('wpcf_postmeta_after_delete_repetitive', $this->post, $this->cf);
102
-
103
- // Allow $data to replace $_POST
104
- if ( is_null( $data ) && isset( $_POST['wpcf'][$this->cf['slug']] ) ) {
105
- $data = $_POST['wpcf'][$this->cf['slug']];
106
- }
107
-
108
- // Set data
109
- if ( !empty( $data ) ) {
110
-
111
- do_action('wpcf_postmeta_before_add_repetitive', $this->post, $this->cf);
112
-
113
- // Insert new meta and collect all new mids
114
- $mids = array();
115
- $i = 1;
116
- foreach ( $data as $meta_value ) {
117
-
118
- /*
119
- *
120
- * Deprecated!
121
- */
122
- if ( is_array( $meta_value ) && isset( $meta_value['new_value'] ) ) {
123
- $meta_value = $meta_value['new_value'];
124
- $wpcf->debug->deprecated['repetitive_new_value_used'] = 'repetitive_new_value_used';
125
- }
126
-
127
- // Apply filters
128
- $meta_value = apply_filters( 'types_field_get_submitted_data',
129
- $meta_value, $this );
130
-
131
- // Apply other filters
132
- $_meta_value = $this->_filter_save_postmeta_value( $meta_value );
133
- $_meta_value = $this->_filter_save_value( $_meta_value );
134
-
135
- // Adding each field will return $mid
136
- if ( count($data) == $i++ ) {
137
- do_action('wpcf_postmeta_before_add_last_repetitive', $this->post, $this->cf);
138
- }
139
- $mid = add_post_meta( $this->post->ID, $this->slug, $_meta_value, false );
140
-
141
- $mids[] = $mid;
142
-
143
- // Call insert post actions on each field
144
- $this->_action_save( $this->cf, $_meta_value, $mid, $meta_value );
145
- }
146
-
147
- do_action('wpcf_postmeta_after_add_repetitive', $this->post, $this->cf);
148
-
149
- // Save order
150
- if ( !empty( $mids ) ) {
151
- update_post_meta( $this->post->ID, $this->order_meta_name, $mids );
152
- }
153
-
154
- // Return true - field found
155
- return true;
156
- }
157
-
158
- // Return false if field missed
159
- return false;
160
- }
161
-
162
- /**
163
- * Fetch and sort fields.
164
- *
165
- * @global object $wpdb
166
- */
167
- function _get_meta() {
168
- global $wpdb;
169
-
170
- $cache_key = md5( 'repeater::_get_meta' . $this->post->ID . $this->slug );
171
- $cache_group = 'types_cache';
172
- $cached_object = wp_cache_get( $cache_key, $cache_group );
173
-
174
- if ( $this->use_cache ) {
175
- if ( false != $cached_object && is_array( $cached_object ) ) {
176
- return $cached_object;
177
- }
178
- }
179
-
180
- $this->order_meta_name = '_' . $this->slug . '-sort-order';
181
- $_meta = parent::_get_meta();
182
- $ordered = array();
183
- $this->order = get_post_meta( $this->post->ID, $this->order_meta_name,
184
- true );
185
-
186
- $cache_key_field = md5( 'field::_get_meta' . $this->post->ID . $this->slug );
187
- $cached_object_field = wp_cache_get( $cache_key_field, $cache_group );
188
-
189
- if ( $this->use_cache ) {
190
- if ( false != $cached_object_field && is_array( $cached_object_field ) ) {// WordPress cache
191
- $r = $cached_object_field;
192
- } else {
193
- $r = $wpdb->get_results(
194
- $wpdb->prepare(
195
- "SELECT * FROM $wpdb->postmeta
196
- WHERE post_id=%d
197
- AND meta_key=%s",
198
- $this->post->ID, $this->slug )
199
- );
200
- }
201
- } else {
202
- // If not using cache, get straight from DB
203
- $r = $wpdb->get_results(
204
- $wpdb->prepare(
205
- "SELECT * FROM $wpdb->postmeta
206
- WHERE post_id=%d
207
- AND meta_key=%s",
208
- $this->post->ID, $this->slug )
209
- );
210
- }
211
- if ( !empty( $r ) ) {
212
- $_meta = array();
213
- $_meta['by_meta_id'] = array();
214
- $_meta['by_meta_key'] = array();
215
-
216
- // Default order
217
- foreach ( $r as $meta ) {
218
- // This will use last item in array if multiple values exist
219
- $_meta['single'] = maybe_unserialize( $meta->meta_value );
220
- // Sort by meta_id column
221
- $_meta['by_meta_id'][$meta->meta_id]
222
- = maybe_unserialize( $meta->meta_value );
223
- // Sort by meta_key
224
- $_meta['by_meta_key'][] = maybe_unserialize( $meta->meta_value );
225
- }
226
- ksort( $_meta['by_meta_id'] );
227
-
228
- // Custom order
229
- if ( !empty( $this->order ) ) {
230
- foreach ( $this->order as $meta_id ) {
231
- if ( isset( $_meta['by_meta_id'][$meta_id] ) ) {
232
- $_meta['custom_order'][$meta_id] = $_meta['by_meta_id'][$meta_id];
233
- }
234
- }
235
- // This ones are orphaned
236
- foreach ( $_meta['by_meta_id'] as $meta_id => $meta ) {
237
- if ( !isset( $ordered[$meta_id] ) ) {
238
- $_meta['custom_order'][$meta_id] = $meta;
239
- }
240
- }
241
- } else {
242
- $_meta['custom_order'] = $_meta['by_meta_id'];
243
- }
244
- } else if ( !empty( $this->meta_object->meta_id ) ) {
245
- $_meta = array();
246
- $_meta['single'] = maybe_unserialize( $this->meta_object->meta_value );
247
- // Sort by meta_id column
248
- $_meta['by_meta_id'][$this->meta_object->meta_id] = maybe_unserialize( $this->meta_object->meta_value );
249
- // Sort by meta_key
250
- $_meta['by_meta_key'][] = maybe_unserialize( $this->meta_object->meta_value );
251
- } else {
252
- $_meta = array();
253
- $_meta['single'] = '';
254
- $_meta['by_meta_id'] = array();
255
- $_meta['by_meta_key'] = array();
256
- }
257
-
258
- if ( empty( $_meta['custom_order'] ) ) {
259
- $_meta['custom_order'] = $_meta['by_meta_id'];
260
- }
261
-
262
- // Cache it
263
- wp_cache_add( $cache_key, $_meta, $cache_group );// WordPress cache
264
-
265
- return $_meta;
266
- }
267
-
268
- /**
269
- * Sets repetitive field form.
270
- *
271
- * @todo Make more distinction between $field_form and $form_field
272
- */
273
- function get_fields_form() {
274
- $form = array();
275
- $form_id = $this->cf['id'];
276
- $unique_id = wpcf_unique_id( serialize( $this->cf ) );
277
-
278
- // Process fields
279
- // Check if has any value
280
- if ( empty( $this->meta['by_meta_id'] ) ) {
281
-
282
- // To prevent passing array to field
283
- $this->meta = null;
284
- $this->__meta = null;
285
- $this->cf['value'] = null;
286
-
287
- $field_form = $this->get_field_form( '' );
288
-
289
- foreach ( $field_form as $field_key => $field ) {
290
- $form_field[$form_id . '_repetitive_0_' . $field_key] = $field;
291
- }
292
- } else {
293
- $ordered = !empty( $this->meta['custom_order'] ) ? $this->meta['custom_order'] : $this->meta['by_meta_id'];
294
- foreach ( $ordered as $meta_id => $meta_value ) {
295
-
296
- $this->cf['value'] = $meta_value;
297
- $this->meta_object->meta_id = $meta_id;
298
-
299
- // Set single field form
300
- $field_form = $this->get_field_form( $meta_value, $meta_id );
301
- foreach ( $field_form as $field_key => $field ) {
302
- $form_field[$form_id . '_repetitive_' . strval( $meta_id ) . '_' . $field_key] = $field;
303
- }
304
-
305
- $form_field[$form_id . '_repetitive_meta_id_' . strval( $meta_id )] = array(
306
- '#type' => 'hidden',
307
- '#name' => '',
308
- '#value' => $meta_id,
309
- );
310
- }
311
- }
312
-
313
- // Set main wrapper
314
- // Check if conditional
315
- global $wpcf;
316
-
317
- // Set style
318
- /*
319
- *
320
- *
321
- * Hide if field not passed check
322
- * TODO Move this to WPCF_Conditional
323
- */
324
- $show = true;
325
- if ( $wpcf->conditional->is_conditional( $this->cf ) ) {
326
- $wpcf->conditional->set( $this->post, $this->cf );
327
- $show = $wpcf->conditional->evaluate();
328
- }
329
- $css_cd = !$show ? 'display:none;' : '';
330
-
331
- /**
332
- *
333
- *
334
- *
335
- *
336
- * Set title and description
337
- * TODO See if can be improved getting main element
338
- *
339
- * Get first element and extract details
340
- * Pass emty string as value to avoid using meta as array
341
- */
342
- //
343
- $_c = array_values( parent::_get_meta_form( '' ) );
344
- array_shift( $_c );
345
- $_main_element = array_shift( $_c );
346
- // Set title and desc
347
- if ( !empty( $_main_element['#title'] ) ) {
348
- $this->title = $_main_element['#title'];
349
- }
350
- if ( !empty( $_main_element['#description'] ) ) {
351
- $this->description = $_main_element['#description'];
352
- }
353
-
354
- /*
355
- *
356
- *
357
- * Start wrapper
358
- */
359
- $form[$unique_id . '_repetitive_wrapper_open'] = array(
360
- '#type' => 'markup',
361
- '#markup' => ''
362
- . '<div id="wpcf_'
363
- . $form_id
364
- . '_repetitive_wrapper_' . $unique_id
365
- . '" class="wpcf-wrap wpcf-repetitive-wrapper" style="' . $css_cd . '">',
366
- );
367
-
368
- // Set title
369
- $form[$unique_id . '_main_title'] = array(
370
- '#type' => 'markup',
371
- '#markup' => '<strong>' . $this->title . '</strong><br/>',
372
- );
373
-
374
- // Set hidden mark field
375
- /*
376
- *
377
- *
378
- *
379
- * This actually marks field as repetitive
380
- * IMPORTANT!!! IF NOT marked field won't be saved at all!
381
- *
382
- * @see wpcf_admin_post_save_post_hook()
383
- */
384
- $form[$form_id . '_hidden_mark'] = array(
385
- '#type' => 'hidden',
386
- '#name' => '__wpcf_repetitive[' . $this->slug . ']',
387
- '#value' => 1,
388
- '#id' => $form_id . '_hidden_mark',
389
- );
390
-
391
- // Sortable
392
- $form[$form_id . '_repetitive_sortable_open'] = array(
393
- '#type' => 'markup',
394
- '#markup' => '<div id="wpcf_'
395
- . $form_id
396
- . '_repetitive_sortable_' . wpcf_unique_id( serialize( $this->cf ) )
397
- . '" class="wpcf-repetitive-sortable-wrapper">',
398
- '#id' => $form_id . '_repetitive_sortable_wrapper_open',
399
- );
400
-
401
- // Append field form
402
- $form = $form + $form_field;
403
-
404
- // Close sortable wrapper
405
- $form[$form_id . '_repetitive_sortable_close'] = array(
406
- '#type' => 'markup',
407
- '#markup' => '</div>',
408
- '#id' => $form_id . '_repetitive_sortable_close',
409
- );
410
-
411
- // Add AJAX response at the end of repetitive field
412
- // Show only on page load not when calling AJAX
413
- if ( !defined( 'DOING_AJAX' ) ) {
414
- $form[$form_id . '_repetitive_ajax_response'] = array(
415
- '#type' => 'markup',
416
- '#markup' => '<div class="wpcf-repetitive-response"></div>',
417
- '#id' => $form_id . '_repetitive_ajax_response',
418
- );
419
-
420
- // Add description
421
- $form[$unique_id . '_main_description'] = array(
422
- '#type' => 'markup',
423
- '#markup' => '<div class="wpcf-repetitive-description">'
424
- . wpautop( stripslashes( strip_tags( $this->description ) ) )
425
- . '</div>',
426
- );
427
-
428
- // 'Add' button
429
- $form[$form_id . '_repetitive_form'] = array(
430
- '#type' => 'markup',
431
- '#markup' => wpcf_repetitive_form( $this->cf, $this->post ),
432
- '#id' => $form_id . '_repetitive_form',
433
- );
434
- }
435
-
436
- // Close wrapper
437
- $form[$unique_id . '_repetitive_wrapper_close'] = array(
438
- '#type' => 'markup',
439
- '#markup' => '</div>',
440
- );
441
-
442
- return $form;
443
- }
444
-
445
- /**
446
- * Sete repetitive form for single field.
447
- *
448
- * @param type $meta
449
- * @return string
450
- */
451
- function get_field_form( $meta_value = null, $meta_id = null ) {
452
-
453
- $form = array();
454
- if ( is_null( $meta_value ) ) {
455
- $key = 'wpcf_field_' . wpcf_unique_id( md5( $this->index ) . $meta_id );
456
- } else {
457
- $key = 'wpcf_field_' . md5( maybe_serialize( $meta_value ) . $meta_id );
458
- }
459
- /*
460
- *
461
- *
462
- * TODO We prevented array because of some fails we had before.
463
- * Now it should work fine
464
- * Add debug log if meta_value['custom_order'] passed.
465
- * That means setting meta_value did not went well.
466
- */
467
- // if ( is_null( $meta_value ) || is_array( $meta_value ) ) {
468
- if ( is_null( $meta_value ) ||
469
- (is_array( $meta_value ) && isset( $meta_value['custom_order'] ) )
470
- ) {
471
- $meta_value = $this->meta['single'];
472
- }
473
-
474
- // Open drag div
475
- $form[$key . '_drag_open'] = array(
476
- '#type' => 'markup',
477
- '#markup' => '<div class="wpcf-repetitive-drag-and-drop">'
478
- );
479
-
480
- // Use WPCF_Field::get_field_form()
481
- $field_form = parent::_get_meta_form( $meta_value, $meta_id, false );
482
-
483
- /*
484
- *
485
- * Apply filters to each form element.
486
- * Here we add specific properties
487
- * e.g. Skype alters fields.
488
- */
489
- $_loop = false;
490
- foreach ( $field_form as $k => $field ) {
491
-
492
- /*
493
- *
494
- * IMPORTANT
495
- * We change name to hold array
496
- */
497
- if ( isset( $field['#name'] ) ) {
498
- $temp = explode( '[' . $this->cf['slug'] . ']', $field['#name'] );
499
-
500
- // Assign new name
501
- $field['#name'] = $temp[0] . '[' . $this->cf['slug'] . ']' . '['
502
- . $key . ']';
503
-
504
- // Append rest if any
505
- if ( isset( $temp[1] ) ) {
506
- $field['#name'] .= $temp[1];
507
- }
508
- }
509
-
510
- // Apply filters
511
- $field_form[$k] = apply_filters( 'wpcf_repetitive_field', $field,
512
- $this->post, $this->cf, $k );
513
-
514
- // BREAKPOINT
515
- /*
516
- * This is place where we clean display.
517
- * First item is displayed as it is, each after is reduced.
518
- * If called via AJAX - that means it added and should be reduced.
519
- */
520
- // if ( $_loop == true || defined( 'DOING_AJAX' ) ) {
521
- /*
522
- * See if field has Repeater pattern defined
523
- */
524
- if ( isset( $field['__repeater_restricted'] )
525
- && is_array( $field['__repeater_restricted'] ) ) {
526
- foreach ( $field['__repeater_restricted'] as $_e => $_v ) {
527
- if ( isset( $field[$_e] ) ) {
528
- unset( $field[$_e] );
529
- }
530
- }
531
- } else {
532
- unset( $field['#title'], $field['#description'] );
533
- }
534
- // Set main
535
- $field_form[$k] = $field;
536
- // }
537
- // $_loop = true;
538
- }
539
-
540
- // Just append form
541
- $form = $form + $field_form;
542
-
543
- // Open control div
544
- $form[$key . '_control_open'] = array(
545
- '#type' => 'markup',
546
- '#markup' => '<div class="wpcf-repetitive-control">'
547
- );
548
-
549
- // Drag button
550
- $form[$key . '_drag_button'] = array(
551
- '#type' => 'markup',
552
- '#markup' => wpcf_repetitive_drag_button( $this->cf, $this->post ),
553
- );
554
-
555
- // 'Delete' button
556
- $form[$key . '_delete_button'] = array(
557
- '#type' => 'markup',
558
- '#markup' => wpcf_repetitive_delete_button( $this->cf, $this->post,
559
- $meta_id ),
560
- );
561
-
562
- // Close control div
563
- $form[$key . '_control_close'] = array(
564
- '#type' => 'markup',
565
- '#markup' => '</div>',
566
- );
567
-
568
- // Close drag div
569
- $form[$key . '_drag_close'] = array(
570
- '#type' => 'markup',
571
- '#markup' => '</div>',
572
- );
573
-
574
- // Count it and set JS var
575
- $this->_set_form_count();
576
- wpcf_admin_add_js_settings( 'wpcf_repetitive_count_' . md5( $this->cf['id'] ),
577
- $this->index );
578
-
579
- return $form;
580
- }
581
-
582
- /**
583
- * Set counting elements.
584
- */
585
- function _set_form_count() {
586
- if ( $this->index === 0 ) {
587
- if ( defined( 'DOING_AJAX' ) && isset( $_POST['count'] ) ) {
588
- $this->index = intval( $_POST['count'] );
589
- }
590
- }
591
- $this->index += 1;
592
- }
593
-
594
- /**
595
- * Deletes meta.
596
- *
597
- * @global object $wpdb
598
- *
599
- * @param type $meta_key
600
- *
601
- */
602
- function delete( $meta_id ) {
603
- global $wpdb;
604
- $r = $wpdb->query(
605
- $wpdb->prepare(
606
- "DELETE FROM $wpdb->postmeta
607
- WHERE post_id = %d
608
- AND meta_id = %d",
609
- $this->post->ID, intval( $meta_id )
610
- )
611
- );
612
- if ( $r === false ) {
613
- return WP_Error( 'wpcf_repeater_delete_field',
614
- 'Repeater failed deleting post_ID: '
615
- . $this->post->ID . '; meta_ID: ' . intval( $meta_id ) );
616
- }
617
- return $r;
618
- }
619
-
620
- }
621
-
622
- /*
623
-
624
- */
625
-
626
- class WPCF_Termmeta_Repeater extends WPCF_Termmeta_Field
627
- {
628
-
629
- /**
630
- * Field order
631
- *
632
- * @var type
633
- */
634
- var $order;
635
-
636
- /**
637
- * Indexing
638
- *
639
- * Set counts when processing fields.
640
- *
641
- * @var type
642
- */
643
- var $index = 0;
644
-
645
- /**
646
- * Field title
647
- * @var type
648
- */
649
- var $title = '';
650
-
651
- /**
652
- * Field description.
653
- *
654
- * @var type
655
- */
656
- var $description = '';
657
-
658
- function __construct() {
659
- parent::__construct();
660
- if ( is_admin() ) {
661
- wpcf_admin_add_js_settings( 'wpcf_repetitive_last_warning',
662
- __( 'Sorry, can not delete all fields.', 'wpcf' ) );
663
- }
664
- }
665
-
666
- /**
667
- * Calls parent set func.
668
- *
669
- * @param type $post
670
- * @param type $field
671
- */
672
- function set( $term_id, $field ) {
673
- parent::set( $term_id, $field );
674
- $this->index = 0;
675
- }
676
-
677
- /**
678
- * Save fields
679
- *
680
- * If $data empty, $_POST will be checked
681
- *
682
- * @global type $wpcf
683
- * @param type $data
684
- * @return boolean
685
- */
686
- function save( $data = null ) {
687
-
688
- global $wpcf;
689
-
690
- // Delete all fields
691
- delete_term_meta( $this->term_id, $this->slug );
692
-
693
- // Allow $data to replace $_POST
694
- if ( is_null( $data ) && isset( $_POST['wpcf'][$this->cf['slug']] ) ) {
695
- $data = $_POST['wpcf'][$this->cf['slug']];
696
- }
697
-
698
- // Set data
699
- if ( !empty( $data ) ) {
700
-
701
- // Insert new meta and collect all new mids
702
- $mids = array();
703
- foreach ( $data as $meta_value ) {
704
-
705
- /*
706
- *
707
- * Deprecated!
708
- */
709
- if ( is_array( $meta_value ) && isset( $meta_value['new_value'] ) ) {
710
- $meta_value = $meta_value['new_value'];
711
- $wpcf->debug->deprecated['repetitive_new_value_used'] = 'repetitive_new_value_used';
712
- }
713
-
714
- // Apply filters
715
- $_meta_value = $this->_filter_save_termmeta_value( $meta_value );
716
- $_meta_value = $this->_filter_save_value( $_meta_value );
717
-
718
- // Adding each field will return $mid
719
- // $unique = false
720
- if ( !empty( $_meta_value ) ) {
721
- $mid = add_term_meta( $this->term_id, $this->slug,
722
- $_meta_value );
723
- $mids[] = $mid;
724
-
725
- // Call insert post actions on each field
726
- $this->_action_save( $this->cf, $_meta_value, $mid,
727
- $meta_value );
728
- }
729
- }
730
-
731
- // Save order
732
- if ( !empty( $mids ) ) {
733
- update_term_meta( $this->term_id, $this->order_meta_name,
734
- $mids );
735
- }
736
-
737
- // Return true - field found
738
- return true;
739
- }
740
-
741
- // Return false if field missed
742
- return false;
743
- }
744
-
745
- /**
746
- * Fetch and sort fields.
747
- *
748
- * @global object $wpdb
749
- */
750
- function _get_meta() {
751
- global $wpdb;
752
-
753
- $cache_key = md5( 'termmetarepeater::_get_meta' . $this->term_id . $this->slug );
754
- $cache_group = 'types_cache';
755
- $cached_object = wp_cache_get( $cache_key, $cache_group );
756
-
757
- if ( $this->use_cache ) {
758
- if ( false != $cached_object && is_array( $cached_object ) ) {
759
- return $cached_object;
760
- }
761
- }
762
-
763
- $this->order_meta_name = '_' . $this->slug . '-sort-order';
764
-
765
- $_meta = parent::_get_meta();
766
-
767
- $ordered = array();
768
- $this->order = get_term_meta( $this->term_id, $this->order_meta_name,
769
- true );
770
-
771
- $cache_key_termfield = md5( 'termmeta::_get_meta' . $this->term_id . $this->slug );
772
- $cached_object_termfield = wp_cache_get( $cache_key_termfield, $cache_group );
773
-
774
- if ( $this->use_cache ) {
775
- if ( false != $cached_object_termfield && is_array( $cached_object_termfield ) ) {// WordPress cache
776
- $r = $cached_object_termfield;
777
- } else {
778
- $r = $wpdb->get_results(
779
- $wpdb->prepare(
780
- "SELECT * FROM {$wpdb->termmeta}
781
- WHERE term_id=%d
782
- AND meta_key=%s",
783
- $this->term_id, $this->slug )
784
- );
785
- }
786
- }
787
-
788
- if ( !empty( $r ) ) {
789
- $_meta = array();
790
- $_meta['by_meta_id'] = array();
791
- $_meta['by_meta_key'] = array();
792
-
793
- // Default order
794
- foreach ( $r as $meta ) {
795
- //print_r($meta);exit;
796
- // This will use last item in array if multiple values exist
797
- $_meta['single'] = maybe_unserialize( $meta->meta_value );
798
- // Sort by meta_id column
799
- $_meta['by_meta_id'][$meta->meta_id]
800
- = maybe_unserialize( $meta->meta_value );
801
- // Sort by meta_key
802
- $_meta['by_meta_key'][] = maybe_unserialize( $meta->meta_value );
803
- }
804
- ksort( $_meta['by_meta_id'] );
805
-
806
- // Custom order
807
- if ( !empty( $this->order ) ) {
808
- foreach ( $this->order as $meta_id ) {
809
- if ( isset( $_meta['by_meta_id'][$meta_id] ) ) {
810
- $_meta['custom_order'][$meta_id] = $_meta['by_meta_id'][$meta_id];
811
- }
812
- }
813
- // This ones are orphaned
814
- foreach ( $_meta['by_meta_id'] as $meta_id => $meta ) {
815
- if ( !isset( $ordered[$meta_id] ) ) {
816
- $_meta['custom_order'][$meta_id] = $meta;
817
- }
818
- }
819
- } else {
820
- $_meta['custom_order'] = $_meta['by_meta_id'];
821
- }
822
- } else if ( !is_null( $this->meta_object ) ) {
823
- $_meta = array();
824
- $_meta['single'] = maybe_unserialize( $this->meta_object->meta_value );
825
- // Sort by meta_id column
826
- $_meta['by_meta_id'][$this->meta_object->meta_id] = maybe_unserialize( $this->meta_object->meta_value );
827
- // Sort by meta_key
828
- $_meta['by_meta_key'][] = maybe_unserialize( $this->meta_object->meta_value );
829
- } else {
830
- $_meta = array();
831
- $_meta['single'] = '';
832
- $_meta['by_meta_id'] = array();
833
- $_meta['by_meta_key'] = array();
834
- }
835
-
836
- if ( empty( $_meta['custom_order'] ) ) {
837
- $_meta['custom_order'] = $_meta['by_meta_id'];
838
- }
839
-
840
- wp_cache_add( $cache_key, $_meta, $cache_group );// WordPress cache
841
- return $_meta;
842
- }
843
-
844
- /**
845
- * Sets repetitive field form.
846
- *
847
- * @todo Make more distinction between $field_form and $form_field
848
- */
849
- function get_fields_form( $is_profile = '' ) {
850
- $form = array();
851
- $form_id = $this->cf['id'];
852
- $unique_id = wpcf_unique_id( serialize( $this->cf ) );
853
-
854
- // Process fields
855
- // Check if has any value
856
- if ( empty( $this->meta['single'] ) ) {
857
- // To prevent passing array to field
858
- $this->meta = null;
859
- $this->__meta = null;
860
- $this->cf['value'] = null;
861
-
862
- $field_form = $this->get_field_form( '' );
863
-
864
- foreach ( $field_form as $field_key => $field ) {
865
- $form_field[$form_id . '_repetitive_0_' . $field_key] = $field;
866
- }
867
- } else {
868
-
869
- $ordered = !empty( $this->meta['custom_order'] ) ? $this->meta['custom_order'] : $this->meta['by_meta_id'];
870
- foreach ( $ordered as $meta_id => $meta_value ) {
871
-
872
- $this->cf['value'] = $meta_value;
873
- $this->meta_object->meta_id = $meta_id;
874
-
875
- // Set single field form
876
-
877
- $field_form = $this->get_field_form( $meta_value, $meta_id );
878
-
879
- foreach ( $field_form as $field_key => $field ) {
880
- $form_field[$form_id . '_repetitive_' . strval( $meta_id ) . '_' . $field_key] = $field;
881
- }
882
-
883
- $form_field[$form_id . '_repetitive_meta_id_' . strval( $meta_id )] = array(
884
- '#type' => 'hidden',
885
- '#name' => '',
886
- '#value' => $meta_id,
887
- );
888
- }
889
- }
890
-
891
- // Set main wrapper
892
- // Check if conditional
893
- global $wpcf;
894
-
895
- // Set style
896
- /*
897
- *
898
- *
899
- * Hide if field not passed check
900
- * TODO Move this to WPCF_Conditional
901
- */
902
- $show = true;
903
- if ( $wpcf->conditional->is_conditional( $this->cf ) ) {
904
- $wpcf->conditional->set( $this->post, $this->cf );
905
- $show = $wpcf->conditional->evaluate();
906
- }
907
- $css_cd = !$show ? 'display:none;' : '';
908
-
909
- /**
910
- *
911
- *
912
- *
913
- *
914
- * Set title and description
915
- * TODO See if can be improved getting main element
916
- *
917
- * Get first element and extract details
918
- * Pass emty string as value to avoid using meta as array
919
- */
920
- //
921
- $_c = array_values( parent::_get_meta_form( '' ) );
922
- array_shift( $_c );
923
- $_main_element = array_shift( $_c );
924
- // Set title and desc
925
- if ( !empty( $_main_element['#title'] ) ) {
926
- $this->title = $_main_element['#title'];
927
- }
928
- if ( !empty( $_main_element['#description'] ) ) {
929
- $this->description = $_main_element['#description'];
930
- }
931
- $addTagHeaderStart = $addTagHeaderEnd = '';
932
- if ( $is_profile == 1 ) {
933
- $addTagHeaderStart = '<div class="wpcf-repeater-profile-line-left">';
934
- $addTagHeaderEnd = '</div><div class="wpcf-repeater-profile-line-right">';
935
- }
936
- // Set title
937
- $form[$unique_id . '_main_title'] = array(
938
- '#type' => 'markup',
939
- '#markup' => $addTagHeaderStart . '<strong>' . $this->title . '</strong><br/>' . $addTagHeaderEnd,
940
- );
941
-
942
- /*
943
- *
944
- *
945
- * Start wrapper
946
- */
947
- $form[$unique_id . '_repetitive_wrapper_open'] = array(
948
- '#type' => 'markup',
949
- '#markup' => ''
950
- . '<div id="wpcf_'
951
- . $form_id
952
- . '_repetitive_wrapper_' . $unique_id
953
- . '" class="wpcf-wrap wpcf-repetitive-wrapper" style="' . $css_cd . '">',
954
- );
955
-
956
- // Set hidden mark field
957
- /*
958
- *
959
- *
960
- *
961
- * This actually marks field as repetitive
962
- * IMPORTANT!!! IF NOT marked field won't be saved at all!
963
- *
964
- * @see wpcf_admin_post_save_post_hook()
965
- */
966
- $form[$form_id . '_hidden_mark'] = array(
967
- '#type' => 'hidden',
968
- '#name' => '__wpcf_repetitive[' . $this->slug . ']',
969
- '#value' => 1,
970
- '#id' => $form_id . '_hidden_mark',
971
- );
972
-
973
- // Sortable
974
- $form[$form_id . '_repetitive_sortable_open'] = array(
975
- '#type' => 'markup',
976
- '#markup' => '<div id="wpcf_'
977
- . $form_id
978
- . '_repetitive_sortable_' . wpcf_unique_id( serialize( $this->cf ) )
979
- . '" class="wpcf-repetitive-sortable-wrapper">',
980
- '#id' => $form_id . '_repetitive_sortable_wrapper_open',
981
- );
982
-
983
- // Append field form
984
- $form = $form + $form_field;
985
-
986
- // Close sortable wrapper
987
- $form[$form_id . '_repetitive_sortable_close'] = array(
988
- '#type' => 'markup',
989
- '#markup' => '</div>',
990
- '#id' => $form_id . '_repetitive_sortable_close',
991
- );
992
-
993
- // Add AJAX response at the end of repetitive field
994
- // Show only on page load not when calling AJAX
995
- if ( !defined( 'DOING_AJAX' ) ) {
996
- $form[$form_id . '_repetitive_ajax_response'] = array(
997
- '#type' => 'markup',
998
- '#markup' => '<div class="wpcf-repetitive-response"></div>',
999
- '#id' => $form_id . '_repetitive_ajax_response',
1000
- );
1001
-
1002
- // Add description
1003
- $form[$unique_id . '_main_description'] = array(
1004
- '#type' => 'markup',
1005
- '#markup' => '<div class="wpcf-repetitive-description">'
1006
- . wpautop( stripslashes( strip_tags( $this->description ) ) )
1007
- . '</div>',
1008
- );
1009
-
1010
- // 'Add' button
1011
- $form[$form_id . '_repetitive_form'] = array(
1012
- '#type' => 'markup',
1013
- '#markup' => wpcf_repetitive_umform( $this->cf,
1014
- $this->currentUID ),
1015
- '#id' => $form_id . '_repetitive_form',
1016
- );
1017
- }
1018
-
1019
- // Close wrapper
1020
- $form[$unique_id . '_repetitive_wrapper_close'] = array(
1021
- '#type' => 'markup',
1022
- '#markup' => '</div></div>',
1023
- );
1024
-
1025
- return $form;
1026
- }
1027
-
1028
- /**
1029
- * Sete repetitive form for single field.
1030
- *
1031
- * @param type $meta
1032
- * @return string
1033
- */
1034
- function get_field_form( $meta_value = null, $meta_id = null ) {
1035
-
1036
- $form = array();
1037
- if ( is_null( $meta_value ) ) {
1038
- $key = 'wpcf_field_' . wpcf_unique_id( md5( $this->index ) . $meta_id );
1039
- } else {
1040
- $key = 'wpcf_field_' . md5( maybe_serialize( $meta_value ) . $meta_id );
1041
- }
1042
-
1043
- if ( is_null( $meta_value ) ||
1044
- (is_array( $meta_value ) && isset( $meta_value['custom_order'] ) )
1045
- ) {
1046
- $meta_value = $this->meta['single'];
1047
- }
1048
-
1049
- // Open drag div
1050
- $form[$key . '_drag_open'] = array(
1051
- '#type' => 'markup',
1052
- '#markup' => '<div class="wpcf-repetitive-drag-and-drop">'
1053
- );
1054
-
1055
- // Use WPCF_Field::get_field_form()
1056
- $field_form = parent::_get_meta_form( $meta_value, $meta_id, false );
1057
-
1058
- /*
1059
- *
1060
- * Apply filters to each form element.
1061
- * Here we add specific properties
1062
- * e.g. Skype alters fields.
1063
- */
1064
- $_loop = false;
1065
- foreach ( $field_form as $k => $field ) {
1066
-
1067
- /*
1068
- *
1069
- * IMPORTANT
1070
- * We change name to hold array
1071
- */
1072
- if ( isset( $field['#name'] ) ) {
1073
- $temp = explode( '[' . $this->cf['slug'] . ']', $field['#name'] );
1074
-
1075
- // Assign new name
1076
- $field['#name'] = $temp[0] . '[' . $this->cf['slug'] . ']' . '['
1077
- . $key . ']';
1078
-
1079
- // Append rest if any
1080
- if ( isset( $temp[1] ) ) {
1081
- $field['#name'] .= $temp[1];
1082
- }
1083
- }
1084
-
1085
- // Apply filters
1086
- $field_form[$k] = apply_filters( 'wpcf_repetitive_field', $field,
1087
- $this->post, $this->cf, $k );
1088
-
1089
- // BREAKPOINT
1090
- /*
1091
- * This is place where we clean display.
1092
- * First item is displayed as it is, each after is reduced.
1093
- * If called via AJAX - that means it added and should be reduced.
1094
- */
1095
- // if ( $_loop == true || defined( 'DOING_AJAX' ) ) {
1096
- /*
1097
- * See if field has Repeater pattern defined
1098
- */
1099
- if ( isset( $field['__repeater_restricted'] )
1100
- && is_array( $field['__repeater_restricted'] ) ) {
1101
- foreach ( $field['__repeater_restricted'] as $_e => $_v ) {
1102
- if ( isset( $field[$_e] ) ) {
1103
- unset( $field[$_e] );
1104
- }
1105
- }
1106
- } else {
1107
- unset( $field['#title'], $field['#description'] );
1108
- }
1109
- // Set main
1110
- $field_form[$k] = $field;
1111
- // }
1112
- // $_loop = true;
1113
- }
1114
-
1115
- // Just append form
1116
- $form = $form + $field_form;
1117
-
1118
- // Open control div
1119
- $form[$key . '_control_open'] = array(
1120
- '#type' => 'markup',
1121
- '#markup' => '<div class="wpcf-repetitive-control">'
1122
- );
1123
-
1124
- // Drag button
1125
- $form[$key . '_drag_button'] = array(
1126
- '#type' => 'markup',
1127
- '#markup' => wpcf_repetitive_drag_button( $this->cf, $this->post ),
1128
- );
1129
-
1130
- // 'Delete' button
1131
- $form[$key . '_delete_button'] = array(
1132
- '#type' => 'markup',
1133
- '#markup' => wpcf_repetitive_delete_button( $this->cf, $this->post,
1134
- $meta_id ),
1135
- );
1136
-
1137
- // Close control div
1138
- $form[$key . '_control_close'] = array(
1139
- '#type' => 'markup',
1140
- '#markup' => '</div>',
1141
- );
1142
-
1143
- // Close drag div
1144
- $form[$key . '_drag_close'] = array(
1145
- '#type' => 'markup',
1146
- '#markup' => '</div>',
1147
- );
1148
-
1149
- // Count it and set JS var
1150
- $this->_set_form_count();
1151
- wpcf_admin_add_js_settings( 'wpcf_repetitive_count_' . md5( $this->cf['id'] ),
1152
- $this->index );
1153
-
1154
- return $form;
1155
- }
1156
-
1157
- /**
1158
- * Set counting elements.
1159
- */
1160
- function _set_form_count() {
1161
- if ( $this->index === 0 ) {
1162
- if ( defined( 'DOING_AJAX' ) && isset( $_POST['count'] ) ) {
1163
- $this->index = intval( $_POST['count'] );
1164
- }
1165
- }
1166
- $this->index += 1;
1167
- }
1168
-
1169
- /**
1170
- * Deletes meta.
1171
- *
1172
- * @global object $wpdb
1173
- *
1174
- * @param type $meta_key
1175
- *
1176
- */
1177
- function delete( $meta_id ) {
1178
- global $wpdb;
1179
- $r = $wpdb->query(
1180
- $wpdb->prepare(
1181
- "DELETE FROM {$wpdb->termmeta}
1182
- WHERE term_id = %d
1183
- AND meta_id = %d",
1184
- $this->term_id, intval( $meta_id )
1185
- )
1186
- );
1187
- if ( $r === false ) {
1188
- return WP_Error( 'wpcf_repeater_delete_field',
1189
- 'Repeater failed deleting term ID: '
1190
- . $this->term_id . '; meta_ID: ' . intval( $meta_id ) );
1191
- }
1192
- return $r;
1193
- }
1194
-
1195
- }
1196
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/usermeta_field.php DELETED
@@ -1,188 +0,0 @@
1
- <?php
2
- /*
3
- * Usermeta Field class extends Field.
4
- */
5
-
6
- //require_once WPCF_EMBEDDED_ABSPATH . '/classes/field.php';
7
-
8
-
9
- class WPCF_Usermeta_Field extends WPCF_Field
10
- {
11
-
12
- /**
13
- * Set current post and field.
14
- *
15
- * @param int $user_id
16
- * @param type $cf
17
- *
18
- * @return bool
19
- */
20
- function set( $user_id, $cf ) {
21
-
22
- global $wpcf;
23
-
24
- /*
25
- *
26
- * Check if $cf is string
27
- */
28
- if ( is_string( $cf ) ) {
29
- WPCF_Loader::loadInclude( 'fields' );
30
- $cf = wpcf_admin_fields_get_field( $this->__get_slug_no_prefix( $cf ) );
31
- if ( empty( $cf ) ) {
32
- $this->_reset();
33
- return false;
34
- }
35
- }
36
-
37
- $this->currentUID = $user_id;
38
- $this->ID = $cf['id'];
39
- $this->cf = $cf;
40
- $this->slug = wpcf_types_get_meta_prefix( $this->cf ) . $this->cf['slug'];
41
- $this->meta = $this->_get_meta();
42
- $this->config = $this->_get_config();
43
- $this->unique_id = wpcf_unique_id( serialize( (array) $this ) );
44
- $this->cf['value'] = $this->meta;
45
- // Debug
46
- $wpcf->debug->fieds[$this->unique_id] = $this->cf;
47
- $wpcf->debug->meta[$this->slug][] = $this->meta;
48
-
49
- // Load files
50
- if ( isset( $this->cf['type'] ) ) {
51
- $file = WPCF_EMBEDDED_INC_ABSPATH . '/fields/' . $this->cf['type'] . '.php';
52
- if ( file_exists( $file ) ) {
53
- include_once $file;
54
- }
55
- if ( defined( 'WPCF_INC_ABSPATH' ) ) {
56
- $file = WPCF_INC_ABSPATH . '/fields/' . $this->cf['type'] . '.php';
57
- if ( file_exists( $file ) ) {
58
- include_once $file;
59
- }
60
- }
61
- }
62
- }
63
-
64
- /**
65
- * Save usermeta field.
66
- *
67
- *
68
- * @param type $value
69
- */
70
- function usermeta_save( $value = null ) {
71
-
72
- // If $value null, look for submitted data
73
- if ( is_null( $value ) ) {
74
- $value = $this->get_submitted_data();
75
- }
76
- /*
77
- *
78
- *
79
- * Since Types 1.2
80
- * We completely rewrite meta.
81
- * It has no impact on frontend and covers a lot of cases
82
- * (e.g. user change mode from single to repetitive)
83
- */
84
-
85
- delete_user_meta( $this->currentUID, $this->slug );
86
-
87
-
88
- // Save
89
- if ( !empty( $value ) || is_numeric( $value ) ) {
90
-
91
- // Trim
92
- if ( is_string( $value ) ) {
93
- $value = trim( $value );
94
- }
95
-
96
- // Apply filters
97
- $_value = $this->_filter_save_usermeta_value( $value );
98
- $_value = $this->_filter_save_value( $_value );
99
- if ( !empty( $_value ) || is_numeric( $_value ) ) {
100
- // Save field
101
- $mid = update_user_meta( $this->currentUID, $this->slug, $_value );
102
- $this->_action_save( $this->cf, $_value, $mid, $value );
103
- }
104
- }
105
- }
106
-
107
- /**
108
- * Fetch and sort fields.
109
- *
110
- * @global object $wpdb
111
- *
112
- */
113
- function _get_meta() {
114
- global $wpdb;
115
-
116
- $cache_key = md5( 'usermeta::_get_meta' . $this->currentUID . $this->slug );
117
- $cache_group = 'types_cache';
118
- $cached_object = wp_cache_get( $cache_key, $cache_group );
119
-
120
- if ( $this->use_cache ) {
121
- if ( false != $cached_object && is_array( $cached_object ) && isset( $cached_object[0] ) ) {// WordPress cache
122
- $r = $cached_object[0];
123
- } else {
124
- // Cache all the postmeta for this same user
125
- $all_usermeta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->usermeta} WHERE user_id=%d", $this->currentUID), OBJECT );
126
- if ( !empty( $all_usermeta ) ) {
127
- $cache_key_keys = array();
128
- foreach ( $all_usermeta as $metarow ) {
129
- $mpid = intval($metarow->user_id);
130
- $mkey = $metarow->meta_key;
131
- $cache_key_keys[$mpid . $mkey][] = $metarow;
132
- $cache_key_looped = md5( 'usermeta::_get_meta' . $mpid . $mkey );
133
- if ( $mkey == $this->slug ) {
134
- $r = $metarow;
135
- }
136
- }
137
- foreach ( $cache_key_keys as $single_meta_keys => $single_meta_values ) {
138
- $cache_key_looped_new = md5( 'usermeta::_get_meta' . $single_meta_keys );
139
- wp_cache_add( $cache_key_looped_new, $single_meta_values, $cache_group );// WordPress cache
140
- }
141
- }
142
- }
143
- } else {
144
- //$r = get_user_meta( $this->currentUID, $this->slug, true);
145
- // Get straight from DB single value
146
- $r = $wpdb->get_row(
147
- $wpdb->prepare(
148
- "SELECT * FROM $wpdb->usermeta
149
- WHERE user_id=%d
150
- AND meta_key=%s",
151
- $this->currentUID, $this->slug )
152
- );
153
- // Cache it
154
- wp_cache_add( $cache_key, array( $r ), $cache_group );// WordPress cache
155
- }
156
-
157
- // Sort meta
158
- $meta = array();
159
- if ( !empty( $r ) ) {
160
- $meta = maybe_unserialize( $r->meta_value );
161
- $this->meta_object = $r;
162
- } else {
163
- $meta = null;
164
- $this->meta_object = new stdClass();
165
- $this->meta_object->umeta_id = null;
166
- $this->meta_object->meta_key = null;
167
- $this->meta_object->meta_value = null;
168
- }
169
-
170
- /*
171
- * Secret public object :)
172
- * Keeps original data
173
- */
174
- $this->__meta = $meta;
175
-
176
- /*
177
- *
178
- * Apply filters
179
- * !!! IMPORTANT !!!
180
- * TODO Make this only place where field meta value is filtered
181
- */
182
- $meta = apply_filters( 'wpcf_fields_value_get', $meta, $this );
183
- $meta = apply_filters( 'wpcf_fields_slug_' . $this->cf['slug'] . '_value_get', $meta, $this );
184
- $meta = apply_filters( 'wpcf_fields_type_' . $this->cf['type'] . '_value_get', $meta, $this );
185
- return $meta;
186
- }
187
-
188
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/usermeta_repeater.php DELETED
@@ -1,575 +0,0 @@
1
- <?php
2
- /*
3
-
4
- */
5
-
6
- class WPCF_Usermeta_Repeater extends WPCF_Usermeta_Field
7
- {
8
-
9
- /**
10
- * Field order
11
- *
12
- * @var type
13
- */
14
- var $order;
15
-
16
- /**
17
- * Indexing
18
- *
19
- * Set counts when processing fields.
20
- *
21
- * @var type
22
- */
23
- var $index = 0;
24
-
25
- /**
26
- * Field title
27
- * @var type
28
- */
29
- var $title = '';
30
-
31
- /**
32
- * Field description.
33
- *
34
- * @var type
35
- */
36
- var $description = '';
37
-
38
- function __construct() {
39
- parent::__construct();
40
- if ( is_admin() ) {
41
- wpcf_admin_add_js_settings( 'wpcf_repetitive_last_warning',
42
- __( 'Sorry, can not delete all fields.', 'wpcf' ) );
43
- }
44
- }
45
-
46
- /**
47
- * Calls parent set func.
48
- *
49
- * @param type $post
50
- * @param type $field
51
- */
52
- function set( $user_id, $field ) {
53
- parent::set( $user_id, $field );
54
- $this->index = 0;
55
- }
56
-
57
- /**
58
- * Save fields
59
- *
60
- * If $data empty, $_POST will be checked
61
- *
62
- * @global type $wpcf
63
- * @param type $data
64
- * @return boolean
65
- */
66
- function save( $data = null ) {
67
-
68
- global $wpcf;
69
-
70
- // Delete all fields
71
- delete_user_meta( $this->currentUID, $this->slug );
72
-
73
- // Allow $data to replace $_POST
74
- if ( is_null( $data ) && isset( $_POST['wpcf'][$this->cf['slug']] ) ) {
75
- $data = $_POST['wpcf'][$this->cf['slug']];
76
- }
77
-
78
- // Set data
79
- if ( !empty( $data ) ) {
80
-
81
- // Insert new meta and collect all new mids
82
- $mids = array();
83
- foreach ( $data as $meta_value ) {
84
-
85
- /*
86
- *
87
- * Deprecated!
88
- */
89
- if ( is_array( $meta_value ) && isset( $meta_value['new_value'] ) ) {
90
- $meta_value = $meta_value['new_value'];
91
- $wpcf->debug->deprecated['repetitive_new_value_used'] = 'repetitive_new_value_used';
92
- }
93
-
94
- // Apply filters
95
- $_meta_value = $this->_filter_save_usermeta_value( $meta_value );
96
- $_meta_value = $this->_filter_save_value( $_meta_value );
97
-
98
- // Adding each field will return $mid
99
- // $unique = false
100
- if ( !empty( $_meta_value ) ) {
101
- $mid = add_user_meta( $this->currentUID, $this->slug,
102
- $_meta_value );
103
- $mids[] = $mid;
104
-
105
- // Call insert post actions on each field
106
- $this->_action_save( $this->cf, $_meta_value, $mid,
107
- $meta_value );
108
- }
109
- }
110
-
111
- // Save order
112
- if ( !empty( $mids ) ) {
113
- update_user_meta( $this->currentUID, $this->order_meta_name,
114
- $mids );
115
- }
116
-
117
- // Return true - field found
118
- return true;
119
- }
120
-
121
- // Return false if field missed
122
- return false;
123
- }
124
-
125
- /**
126
- * Fetch and sort fields.
127
- *
128
- * @global object $wpdb
129
- */
130
- function _get_meta() {
131
- global $wpdb;
132
-
133
- $cache_key = md5( 'usermetarepeater::_get_meta' . $this->currentUID . $this->slug );
134
- $cache_group = 'types_cache';
135
- $cached_object = wp_cache_get( $cache_key, $cache_group );
136
-
137
- if ( $this->use_cache ) {
138
- if ( false != $cached_object && is_array( $cached_object ) ) {
139
- return $cached_object;
140
- }
141
- }
142
-
143
- $this->order_meta_name = '_' . $this->slug . '-sort-order';
144
-
145
- $_meta = parent::_get_meta();
146
-
147
- $ordered = array();
148
- $this->order = get_user_meta( $this->currentUID, $this->order_meta_name,
149
- true );
150
-
151
- $cache_key_userfield = md5( 'usermeta::_get_meta' . $this->currentUID . $this->slug );
152
- $cached_object_userfield = wp_cache_get( $cache_key_userfield, $cache_group );
153
-
154
- if ( $this->use_cache ) {
155
- if ( false != $cached_object_userfield && is_array( $cached_object_userfield ) ) {// WordPress cache
156
- $r = $cached_object_userfield;
157
- } else {
158
- $r = $wpdb->get_results(
159
- $wpdb->prepare(
160
- "SELECT * FROM $wpdb->usermeta
161
- WHERE user_id=%d
162
- AND meta_key=%s",
163
- $this->currentUID, $this->slug )
164
- );
165
- }
166
- }
167
-
168
- if ( !empty( $r ) ) {
169
- $_meta = array();
170
- $_meta['by_meta_id'] = array();
171
- $_meta['by_meta_key'] = array();
172
-
173
- // Default order
174
- foreach ( $r as $meta ) {
175
- //print_r($meta);exit;
176
- // This will use last item in array if multiple values exist
177
- $_meta['single'] = maybe_unserialize( $meta->meta_value );
178
- // Sort by meta_id column
179
- $_meta['by_meta_id'][$meta->umeta_id]
180
- = maybe_unserialize( $meta->meta_value );
181
- // Sort by meta_key
182
- $_meta['by_meta_key'][] = maybe_unserialize( $meta->meta_value );
183
- }
184
- ksort( $_meta['by_meta_id'] );
185
-
186
- // Custom order
187
- if ( !empty( $this->order ) ) {
188
- foreach ( $this->order as $meta_id ) {
189
- if ( isset( $_meta['by_meta_id'][$meta_id] ) ) {
190
- $_meta['custom_order'][$meta_id] = $_meta['by_meta_id'][$meta_id];
191
- }
192
- }
193
- // This ones are orphaned
194
- foreach ( $_meta['by_meta_id'] as $meta_id => $meta ) {
195
- if ( !isset( $ordered[$meta_id] ) ) {
196
- $_meta['custom_order'][$meta_id] = $meta;
197
- }
198
- }
199
- } else {
200
- $_meta['custom_order'] = $_meta['by_meta_id'];
201
- }
202
- } else if ( !is_null( $this->meta_object ) ) {
203
- $_meta = array();
204
- $_meta['single'] = maybe_unserialize( $this->meta_object->meta_value );
205
- // Sort by meta_id column
206
- $_meta['by_meta_id'][$this->meta_object->umeta_id] = maybe_unserialize( $this->meta_object->meta_value );
207
- // Sort by meta_key
208
- $_meta['by_meta_key'][] = maybe_unserialize( $this->meta_object->meta_value );
209
- } else {
210
- $_meta = array();
211
- $_meta['single'] = '';
212
- $_meta['by_meta_id'] = array();
213
- $_meta['by_meta_key'] = array();
214
- }
215
-
216
- if ( empty( $_meta['custom_order'] ) ) {
217
- $_meta['custom_order'] = $_meta['by_meta_id'];
218
- }
219
-
220
- wp_cache_add( $cache_key, $_meta, $cache_group );// WordPress cache
221
- return $_meta;
222
- }
223
-
224
- /**
225
- * Sets repetitive field form.
226
- *
227
- * @todo Make more distinction between $field_form and $form_field
228
- */
229
- function get_fields_form( $is_profile = '' ) {
230
- $form = array();
231
- $form_id = $this->cf['id'];
232
- $unique_id = wpcf_unique_id( serialize( $this->cf ) );
233
-
234
- // Process fields
235
- // Check if has any value
236
- if ( empty( $this->meta['single'] ) ) {
237
- // To prevent passing array to field
238
- $this->meta = null;
239
- $this->__meta = null;
240
- $this->cf['value'] = null;
241
-
242
- $field_form = $this->get_field_form( '' );
243
-
244
- foreach ( $field_form as $field_key => $field ) {
245
- $form_field[$form_id . '_repetitive_0_' . $field_key] = $field;
246
- }
247
- } else {
248
-
249
- $ordered = !empty( $this->meta['custom_order'] ) ? $this->meta['custom_order'] : $this->meta['by_meta_id'];
250
- foreach ( $ordered as $meta_id => $meta_value ) {
251
-
252
- $this->cf['value'] = $meta_value;
253
- $this->meta_object->umeta_id = $meta_id;
254
-
255
- // Set single field form
256
-
257
- $field_form = $this->get_field_form( $meta_value, $meta_id );
258
-
259
- foreach ( $field_form as $field_key => $field ) {
260
- $form_field[$form_id . '_repetitive_' . strval( $meta_id ) . '_' . $field_key] = $field;
261
- }
262
-
263
- $form_field[$form_id . '_repetitive_meta_id_' . strval( $meta_id )] = array(
264
- '#type' => 'hidden',
265
- '#name' => '',
266
- '#value' => $meta_id,
267
- );
268
- }
269
- }
270
-
271
- // Set main wrapper
272
- // Check if conditional
273
- global $wpcf;
274
-
275
- // Set style
276
- /*
277
- *
278
- *
279
- * Hide if field not passed check
280
- * TODO Move this to WPCF_Conditional
281
- */
282
- $show = true;
283
- if ( $wpcf->conditional->is_conditional( $this->cf ) ) {
284
- $wpcf->conditional->set( $this->post, $this->cf );
285
- $show = $wpcf->conditional->evaluate();
286
- }
287
- $css_cd = !$show ? 'display:none;' : '';
288
-
289
- /**
290
- *
291
- *
292
- *
293
- *
294
- * Set title and description
295
- * TODO See if can be improved getting main element
296
- *
297
- * Get first element and extract details
298
- * Pass emty string as value to avoid using meta as array
299
- */
300
- //
301
- $_c = array_values( parent::_get_meta_form( '' ) );
302
- array_shift( $_c );
303
- $_main_element = array_shift( $_c );
304
- // Set title and desc
305
- if ( !empty( $_main_element['#title'] ) ) {
306
- $this->title = $_main_element['#title'];
307
- }
308
- if ( !empty( $_main_element['#description'] ) ) {
309
- $this->description = $_main_element['#description'];
310
- }
311
- $addTagHeaderStart = $addTagHeaderEnd = '';
312
- if ( $is_profile == 1 ) {
313
- $addTagHeaderStart = '<div class="wpcf-repeater-profile-line-left">';
314
- $addTagHeaderEnd = '</div><div class="wpcf-repeater-profile-line-right">';
315
- }
316
- // Set title
317
- $form[$unique_id . '_main_title'] = array(
318
- '#type' => 'markup',
319
- '#markup' => $addTagHeaderStart . '<strong>' . $this->title . '</strong><br/>' . $addTagHeaderEnd,
320
- );
321
-
322
- /*
323
- *
324
- *
325
- * Start wrapper
326
- */
327
- $form[$unique_id . '_repetitive_wrapper_open'] = array(
328
- '#type' => 'markup',
329
- '#markup' => ''
330
- . '<div id="wpcf_'
331
- . $form_id
332
- . '_repetitive_wrapper_' . $unique_id
333
- . '" class="wpcf-wrap wpcf-repetitive-wrapper" style="' . $css_cd . '">',
334
- );
335
-
336
- // Set hidden mark field
337
- /*
338
- *
339
- *
340
- *
341
- * This actually marks field as repetitive
342
- * IMPORTANT!!! IF NOT marked field won't be saved at all!
343
- *
344
- * @see wpcf_admin_post_save_post_hook()
345
- */
346
- $form[$form_id . '_hidden_mark'] = array(
347
- '#type' => 'hidden',
348
- '#name' => '__wpcf_repetitive[' . $this->slug . ']',
349
- '#value' => 1,
350
- '#id' => $form_id . '_hidden_mark',
351
- );
352
-
353
- // Sortable
354
- $form[$form_id . '_repetitive_sortable_open'] = array(
355
- '#type' => 'markup',
356
- '#markup' => '<div id="wpcf_'
357
- . $form_id
358
- . '_repetitive_sortable_' . wpcf_unique_id( serialize( $this->cf ) )
359
- . '" class="wpcf-repetitive-sortable-wrapper">',
360
- '#id' => $form_id . '_repetitive_sortable_wrapper_open',
361
- );
362
-
363
- // Append field form
364
- $form = $form + $form_field;
365
-
366
- // Close sortable wrapper
367
- $form[$form_id . '_repetitive_sortable_close'] = array(
368
- '#type' => 'markup',
369
- '#markup' => '</div>',
370
- '#id' => $form_id . '_repetitive_sortable_close',
371
- );
372
-
373
- // Add AJAX response at the end of repetitive field
374
- // Show only on page load not when calling AJAX
375
- if ( !defined( 'DOING_AJAX' ) ) {
376
- $form[$form_id . '_repetitive_ajax_response'] = array(
377
- '#type' => 'markup',
378
- '#markup' => '<div class="wpcf-repetitive-response"></div>',
379
- '#id' => $form_id . '_repetitive_ajax_response',
380
- );
381
-
382
- // Add description
383
- $form[$unique_id . '_main_description'] = array(
384
- '#type' => 'markup',
385
- '#markup' => '<div class="wpcf-repetitive-description">'
386
- . wpautop( stripslashes( strip_tags( $this->description ) ) )
387
- . '</div>',
388
- );
389
-
390
- // 'Add' button
391
- $form[$form_id . '_repetitive_form'] = array(
392
- '#type' => 'markup',
393
- '#markup' => wpcf_repetitive_umform( $this->cf,
394
- $this->currentUID ),
395
- '#id' => $form_id . '_repetitive_form',
396
- );
397
- }
398
-
399
- // Close wrapper
400
- $form[$unique_id . '_repetitive_wrapper_close'] = array(
401
- '#type' => 'markup',
402
- '#markup' => '</div></div>',
403
- );
404
-
405
- return $form;
406
- }
407
-
408
- /**
409
- * Sete repetitive form for single field.
410
- *
411
- * @param type $meta
412
- * @return string
413
- */
414
- function get_field_form( $meta_value = null, $meta_id = null ) {
415
-
416
- $form = array();
417
- if ( is_null( $meta_value ) ) {
418
- $key = 'wpcf_field_' . wpcf_unique_id( md5( $this->index ) . $meta_id );
419
- } else {
420
- $key = 'wpcf_field_' . md5( maybe_serialize( $meta_value ) . $meta_id );
421
- }
422
-
423
- if ( is_null( $meta_value ) ||
424
- (is_array( $meta_value ) && isset( $meta_value['custom_order'] ) )
425
- ) {
426
- $meta_value = $this->meta['single'];
427
- }
428
-
429
- // Open drag div
430
- $form[$key . '_drag_open'] = array(
431
- '#type' => 'markup',
432
- '#markup' => '<div class="wpcf-repetitive-drag-and-drop">'
433
- );
434
-
435
- // Use WPCF_Field::get_field_form()
436
- $field_form = parent::_get_meta_form( $meta_value, $meta_id, false );
437
-
438
- /*
439
- *
440
- * Apply filters to each form element.
441
- * Here we add specific properties
442
- * e.g. Skype alters fields.
443
- */
444
- $_loop = false;
445
- foreach ( $field_form as $k => $field ) {
446
-
447
- /*
448
- *
449
- * IMPORTANT
450
- * We change name to hold array
451
- */
452
- if ( isset( $field['#name'] ) ) {
453
- $temp = explode( '[' . $this->cf['slug'] . ']', $field['#name'] );
454
-
455
- // Assign new name
456
- $field['#name'] = $temp[0] . '[' . $this->cf['slug'] . ']' . '['
457
- . $key . ']';
458
-
459
- // Append rest if any
460
- if ( isset( $temp[1] ) ) {
461
- $field['#name'] .= $temp[1];
462
- }
463
- }
464
-
465
- // Apply filters
466
- $field_form[$k] = apply_filters( 'wpcf_repetitive_field', $field,
467
- $this->post, $this->cf, $k );
468
-
469
- // BREAKPOINT
470
- /*
471
- * This is place where we clean display.
472
- * First item is displayed as it is, each after is reduced.
473
- * If called via AJAX - that means it added and should be reduced.
474
- */
475
- // if ( $_loop == true || defined( 'DOING_AJAX' ) ) {
476
- /*
477
- * See if field has Repeater pattern defined
478
- */
479
- if ( isset( $field['__repeater_restricted'] )
480
- && is_array( $field['__repeater_restricted'] ) ) {
481
- foreach ( $field['__repeater_restricted'] as $_e => $_v ) {
482
- if ( isset( $field[$_e] ) ) {
483
- unset( $field[$_e] );
484
- }
485
- }
486
- } else {
487
- unset( $field['#title'], $field['#description'] );
488
- }
489
- // Set main
490
- $field_form[$k] = $field;
491
- // }
492
- // $_loop = true;
493
- }
494
-
495
- // Just append form
496
- $form = $form + $field_form;
497
-
498
- // Open control div
499
- $form[$key . '_control_open'] = array(
500
- '#type' => 'markup',
501
- '#markup' => '<div class="wpcf-repetitive-control">'
502
- );
503
-
504
- // Drag button
505
- $form[$key . '_drag_button'] = array(
506
- '#type' => 'markup',
507
- '#markup' => wpcf_repetitive_drag_button( $this->cf, $this->post ),
508
- );
509
-
510
- // 'Delete' button
511
- $form[$key . '_delete_button'] = array(
512
- '#type' => 'markup',
513
- '#markup' => wpcf_repetitive_delete_button( $this->cf, $this->post,
514
- $meta_id ),
515
- );
516
-
517
- // Close control div
518
- $form[$key . '_control_close'] = array(
519
- '#type' => 'markup',
520
- '#markup' => '</div>',
521
- );
522
-
523
- // Close drag div
524
- $form[$key . '_drag_close'] = array(
525
- '#type' => 'markup',
526
- '#markup' => '</div>',
527
- );
528
-
529
- // Count it and set JS var
530
- $this->_set_form_count();
531
- wpcf_admin_add_js_settings( 'wpcf_repetitive_count_' . md5( $this->cf['id'] ),
532
- $this->index );
533
-
534
- return $form;
535
- }
536
-
537
- /**
538
- * Set counting elements.
539
- */
540
- function _set_form_count() {
541
- if ( $this->index === 0 ) {
542
- if ( defined( 'DOING_AJAX' ) && isset( $_POST['count'] ) ) {
543
- $this->index = intval( $_POST['count'] );
544
- }
545
- }
546
- $this->index += 1;
547
- }
548
-
549
- /**
550
- * Deletes meta.
551
- *
552
- * @global object $wpdb
553
- *
554
- * @param type $meta_key
555
- *
556
- */
557
- function delete( $meta_id ) {
558
- global $wpdb;
559
- $r = $wpdb->query(
560
- $wpdb->prepare(
561
- "DELETE FROM $wpdb->usermeta
562
- WHERE user_id = %d
563
- AND umeta_id = %d",
564
- $this->currentUID, intval( $meta_id )
565
- )
566
- );
567
- if ( $r === false ) {
568
- return WP_Error( 'wpcf_repeater_delete_field',
569
- 'Repeater failed deleting user_ID: '
570
- . $this->currentUID . '; meta_ID: ' . intval( $meta_id ) );
571
- }
572
- return $r;
573
- }
574
-
575
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/classes/validate.php DELETED
@@ -1,6 +0,0 @@
1
- <?php
2
- /**
3
- * moved to toolset-common
4
- * ../toolset/toolset-common/classes/validate.php
5
- */
6
- require_once dirname( __FILE__ ) . '/../toolset/toolset-common/classes/validate.php';
 
 
 
 
 
 
embedded/classes/validation-cakephp.php DELETED
@@ -1,1141 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Validation Class. Used for validation of model data
5
- *
6
- * PHP versions 4 and 5
7
- *
8
- * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
9
- * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
10
- *
11
- * Licensed under The MIT License
12
- * Redistributions of files must retain the above copyright notice.
13
- *
14
- * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
15
- * @link http://cakephp.org CakePHP(tm) Project
16
- * @package cake
17
- * @subpackage cake.cake.libs
18
- * @since CakePHP(tm) v 1.2.0.3830
19
- * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
20
- */
21
- //if (!class_exists('Multibyte')) {
22
- // App::import('Core', 'Multibyte', false);
23
- //}
24
- /**
25
- * Offers different validation methods.
26
- *
27
- * @package cake
28
- * @subpackage cake.cake.libs
29
- * @since CakePHP v 1.2.0.3830
30
- */
31
- //class Validation extends Object {
32
- class Wpcf_Cake_Validation
33
- {
34
-
35
- /**
36
- * Set the value of methods $check param.
37
- *
38
- * @var string
39
- * @access public
40
- */
41
- var $check = null;
42
-
43
- /**
44
- * Set to a valid regular expression in the class methods.
45
- * Can be set from $regex param also
46
- *
47
- * @var string
48
- * @access public
49
- */
50
- var $regex = null;
51
-
52
- /**
53
- * Some complex patterns needed in multiple places
54
- *
55
- * @var array
56
- * @access private
57
- */
58
- var $__pattern = array(
59
- 'hostname' => '(?:[a-z0-9][-a-z0-9]*\.)*(?:[a-z0-9][-a-z0-9]{0,62})\.(?:(?:[a-z]{2}\.)?[a-z]{2,4}|museum|travel)'
60
- );
61
-
62
- /**
63
- * Some class methods use a country to determine proper validation.
64
- * This can be passed to methods in the $country param
65
- *
66
- * @var string
67
- * @access public
68
- */
69
- var $country = null;
70
-
71
- /**
72
- * Some class methods use a deeper validation when set to true
73
- *
74
- * @var string
75
- * @access public
76
- */
77
- var $deep = null;
78
-
79
- /**
80
- * Some class methods use the $type param to determine which validation to perfom in the method
81
- *
82
- * @var string
83
- * @access public
84
- */
85
- var $type = null;
86
-
87
- /**
88
- * Holds an array of errors messages set in this class.
89
- * These are used for debugging purposes
90
- *
91
- * @var array
92
- * @access public
93
- */
94
- var $errors = array();
95
-
96
- /**
97
- * Gets a reference to the Validation object instance
98
- *
99
- * @return object Validation instance
100
- * @access public
101
- * @static
102
- */
103
- function &getInstance() {
104
- static $instance = array();
105
-
106
- if ( !$instance ) {
107
- $instance[0] = new Wpcf_Cake_Validation();
108
- }
109
- return $instance[0];
110
- }
111
-
112
- /**
113
- * Checks that a string contains something other than whitespace
114
- *
115
- * Returns true if string contains something other than whitespace
116
- *
117
- * $check can be passed as an array:
118
- * array('check' => 'valueToCheck');
119
- *
120
- * @param mixed $check Value to check
121
- * @return boolean Success
122
- * @access public
123
- */
124
- function notEmpty( $check ) {
125
- $_this = &Wpcf_Cake_Validation::getInstance();
126
- $_this->__reset();
127
- $_this->check = $check;
128
-
129
- if ( is_array( $check ) ) {
130
- $_this->_extract( $check );
131
- }
132
-
133
- if ( empty( $_this->check ) && $_this->check != '0' ) {
134
- return false;
135
- }
136
- $_this->regex = '/[^\s]+/m';
137
- return $_this->_check();
138
- }
139
-
140
- /**
141
- * Checks that a string contains only integer or letters
142
- *
143
- * Returns true if string contains only integer or letters
144
- *
145
- * $check can be passed as an array:
146
- * array('check' => 'valueToCheck');
147
- *
148
- * @param mixed $check Value to check
149
- * @return boolean Success
150
- * @access public
151
- */
152
- function alphaNumeric( $check ) {
153
- $_this = &Wpcf_Cake_Validation::getInstance();
154
- $_this->__reset();
155
- $_this->check = $check;
156
-
157
- if ( is_array( $check ) ) {
158
- $_this->_extract( $check );
159
- }
160
-
161
- if ( empty( $_this->check ) && $_this->check != '0' ) {
162
- return false;
163
- }
164
- $_this->regex = '/^[a-zA-Z0-9]*$/mu';
165
- $return = $_this->_check();
166
-
167
- if ( !$return ) {
168
- $_this->regex = '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]+$/mu';
169
- $return = $_this->_check();
170
- }
171
-
172
- return $_this->_check();
173
- }
174
-
175
- function alphaNumericWhitespaces( $check ) {
176
- $_this = &Wpcf_Cake_Validation::getInstance();
177
- $_this->__reset();
178
- $_this->check = $check;
179
-
180
- if ( is_array( $check ) ) {
181
- $_this->_extract( $check );
182
- }
183
-
184
- if ( empty( $_this->check ) && $_this->check != '0' ) {
185
- return false;
186
- }
187
- $_this->regex = '/^[a-zA-Z0-9\s\-\_]*$/mu';
188
- $return = $_this->_check();
189
-
190
- if ( !$return ) {
191
- $_this->regex = '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}\s\-\_]+$/mu';
192
- $return = $_this->_check();
193
- }
194
-
195
- return $return;
196
- }
197
-
198
- function skype( $check ) {
199
- $_this = &Wpcf_Cake_Validation::getInstance();
200
- $_this->__reset();
201
- $_this->check = $check;
202
-
203
- if ( is_array( $check ) ) {
204
- $_this->_extract( $check );
205
- }
206
-
207
- if ( empty( $_this->check ) && $_this->check != '0' ) {
208
- return false;
209
- }
210
- $_this->regex = '/^[a-zA-Z0-9\s\-\_]*$/mu';
211
- $return = $_this->_check();
212
-
213
- if ( !$return ) {
214
- $_this->regex = '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}\s\-\_]+$/mu';
215
- $return = $_this->_check();
216
- }
217
-
218
- return $return;
219
- }
220
-
221
- /**
222
- * Checks that a string length is within s specified range.
223
- * Spaces are included in the character count.
224
- * Returns true is string matches value min, max, or between min and max,
225
- *
226
- * @param string $check Value to check for length
227
- * @param integer $min Minimum value in range (inclusive)
228
- * @param integer $max Maximum value in range (inclusive)
229
- * @return boolean Success
230
- * @access public
231
- */
232
- function between( $check, $min, $max ) {
233
- $length = strlen( $check );
234
- return ($length >= $min && $length <= $max);
235
- }
236
-
237
- /**
238
- * Returns true if field is left blank -OR- only whitespace characters are present in it's value
239
- * Whitespace characters include Space, Tab, Carriage Return, Newline
240
- *
241
- * $check can be passed as an array:
242
- * array('check' => 'valueToCheck');
243
- *
244
- * @param mixed $check Value to check
245
- * @return boolean Success
246
- * @access public
247
- */
248
- function blank( $check ) {
249
- $_this = &Wpcf_Cake_Validation::getInstance();
250
- $_this->__reset();
251
- $_this->check = $check;
252
-
253
- if ( is_array( $check ) ) {
254
- $_this->_extract( $check );
255
- }
256
-
257
- $_this->regex = '/[^\\s]/';
258
- return !$_this->_check();
259
- }
260
-
261
- /**
262
- * Validation of credit card numbers.
263
- * Returns true if $check is in the proper credit card format.
264
- *
265
- * @param mixed $check credit card number to validate
266
- * @param mixed $type 'all' may be passed as a sting, defaults to fast which checks format of most major credit cards
267
- * if an array is used only the values of the array are checked.
268
- * Example: array('amex', 'bankcard', 'maestro')
269
- * @param boolean $deep set to true this will check the Luhn algorithm of the credit card.
270
- * @param string $regex A custom regex can also be passed, this will be used instead of the defined regex values
271
- * @return boolean Success
272
- * @access public
273
- * @see Wpcf_Cake_Validation::_luhn()
274
- */
275
- function cc( $check, $type = 'fast', $deep = false, $regex = null ) {
276
- $_this = &Wpcf_Cake_Validation::getInstance();
277
- $_this->__reset();
278
- $_this->check = $check;
279
- $_this->type = $type;
280
- $_this->deep = $deep;
281
- $_this->regex = $regex;
282
-
283
- if ( is_array( $check ) ) {
284
- $_this->_extract( $check );
285
- }
286
- $_this->check = str_replace( array('-', ' '), '', $_this->check );
287
-
288
- if ( strlen( $_this->check ) < 13 ) {
289
- return false;
290
- }
291
-
292
- if ( !is_null( $_this->regex ) ) {
293
- if ( $_this->_check() ) {
294
- return $_this->_luhn();
295
- }
296
- }
297
- $cards = array(
298
- 'all' => array(
299
- 'amex' => '/^3[4|7]\\d{13}$/',
300
- 'bankcard' => '/^56(10\\d\\d|022[1-5])\\d{10}$/',
301
- 'diners' => '/^(?:3(0[0-5]|[68]\\d)\\d{11})|(?:5[1-5]\\d{14})$/',
302
- 'disc' => '/^(?:6011|650\\d)\\d{12}$/',
303
- 'electron' => '/^(?:417500|4917\\d{2}|4913\\d{2})\\d{10}$/',
304
- 'enroute' => '/^2(?:014|149)\\d{11}$/',
305
- 'jcb' => '/^(3\\d{4}|2100|1800)\\d{11}$/',
306
- 'maestro' => '/^(?:5020|6\\d{3})\\d{12}$/',
307
- 'mc' => '/^5[1-5]\\d{14}$/',
308
- 'solo' => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/',
309
- 'switch' => '/^(?:49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})\\d{10}(\\d{2,3})?)|(?:564182\\d{10}(\\d{2,3})?)|(6(3(33[0-4][0-9])|759[0-9]{2})\\d{10}(\\d{2,3})?)$/',
310
- 'visa' => '/^4\\d{12}(\\d{3})?$/',
311
- 'voyager' => '/^8699[0-9]{11}$/'
312
- ),
313
- 'fast' => '/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$/'
314
- );
315
-
316
- if ( is_array( $_this->type ) ) {
317
- foreach ( $_this->type as $value ) {
318
- $_this->regex = $cards['all'][strtolower( $value )];
319
-
320
- if ( $_this->_check() ) {
321
- return $_this->_luhn();
322
- }
323
- }
324
- } elseif ( $_this->type == 'all' ) {
325
- foreach ( $cards['all'] as $value ) {
326
- $_this->regex = $value;
327
-
328
- if ( $_this->_check() ) {
329
- return $_this->_luhn();
330
- }
331
- }
332
- } else {
333
- $_this->regex = $cards['fast'];
334
-
335
- if ( $_this->_check() ) {
336
- return $_this->_luhn();
337
- }
338
- }
339
- }
340
-
341
- /**
342
- * Used to compare 2 numeric values.
343
- *
344
- * @param mixed $check1 if string is passed for a string must also be passed for $check2
345
- * used as an array it must be passed as array('check1' => value, 'operator' => 'value', 'check2' -> value)
346
- * @param string $operator Can be either a word or operand
347
- * is greater >, is less <, greater or equal >=
348
- * less or equal <=, is less <, equal to ==, not equal !=
349
- * @param integer $check2 only needed if $check1 is a string
350
- * @return boolean Success
351
- * @access public
352
- */
353
- function comparison( $check1, $operator = null, $check2 = null ) {
354
- if ( is_array( $check1 ) ) {
355
- extract( $check1, EXTR_OVERWRITE );
356
- }
357
- $operator = str_replace( array(' ', "\t", "\n", "\r", "\0", "\x0B"), '',
358
- strtolower( $operator ) );
359
-
360
- switch ( $operator ) {
361
- case 'isgreater':
362
- case '>':
363
- if ( $check1 > $check2 ) {
364
- return true;
365
- }
366
- break;
367
- case 'isless':
368
- case '<':
369
- if ( $check1 < $check2 ) {
370
- return true;
371
- }
372
- break;
373
- case 'greaterorequal':
374
- case '>=':
375
- if ( $check1 >= $check2 ) {
376
- return true;
377
- }
378
- break;
379
- case 'lessorequal':
380
- case '<=':
381
- if ( $check1 <= $check2 ) {
382
- return true;
383
- }
384
- break;
385
- case 'equalto':
386
- case '==':
387
- if ( $check1 == $check2 ) {
388
- return true;
389
- }
390
- break;
391
- case 'notequal':
392
- case '!=':
393
- if ( $check1 != $check2 ) {
394
- return true;
395
- }
396
- break;
397
- default:
398
- $_this = &Wpcf_Cake_Validation::getInstance();
399
- $_this->errors[] = __( 'You must define the $operator parameter for Wpcf_Cake_Validation::comparison()', 'wpcf' );
400
- break;
401
- }
402
- return false;
403
- }
404
-
405
- /**
406
- * Used when a custom regular expression is needed.
407
- *
408
- * @param mixed $check When used as a string, $regex must also be a valid regular expression.
409
- * As and array: array('check' => value, 'regex' => 'valid regular expression')
410
- * @param string $regex If $check is passed as a string, $regex must also be set to valid regular expression
411
- * @return boolean Success
412
- * @access public
413
- */
414
- function custom( $check, $regex = null ) {
415
- $_this = &Wpcf_Cake_Validation::getInstance();
416
- $_this->__reset();
417
- $_this->check = $check;
418
- $_this->regex = $regex;
419
- if ( is_array( $check ) ) {
420
- $_this->_extract( $check );
421
- }
422
- if ( $_this->regex === null ) {
423
- $_this->errors[] = __( 'You must define a regular expression for Wpcf_Cake_Validation::custom()', 'wpcf' );
424
- return false;
425
- }
426
- return $_this->_check();
427
- }
428
-
429
- /**
430
- * Date validation, determines if the string passed is a valid date.
431
- * keys that expect full month, day and year will validate leap years
432
- *
433
- * @param string $check a valid date string
434
- * @param mixed $format Use a string or an array of the keys below. Arrays should be passed as array('dmy', 'mdy', etc)
435
- * Keys: dmy 27-12-2006 or 27-12-06 separators can be a space, period, dash, forward slash
436
- * mdy 12-27-2006 or 12-27-06 separators can be a space, period, dash, forward slash
437
- * ymd 2006-12-27 or 06-12-27 separators can be a space, period, dash, forward slash
438
- * dMy 27 December 2006 or 27 Dec 2006
439
- * Mdy December 27, 2006 or Dec 27, 2006 comma is optional
440
- * My December 2006 or Dec 2006
441
- * my 12/2006 separators can be a space, period, dash, forward slash
442
- * @param string $regex If a custom regular expression is used this is the only validation that will occur.
443
- * @return boolean Success
444
- * @access public
445
- */
446
- function date( $check, $format = 'ymd', $regex = null ) {
447
-
448
- $date_format = wpcf_get_date_format();
449
- $cake_date_formats = array('F j, Y' => 'Mdy',
450
- 'Y/m/d' => 'ymd',
451
- 'm/d/Y' => 'mdy',
452
- 'd/m/Y' => 'dmy'
453
- );
454
- $format = $cake_date_formats[$date_format];
455
-
456
- $_this = &Wpcf_Cake_Validation::getInstance();
457
- $_this->__reset();
458
- $_this->check = $check;
459
- $_this->regex = $regex;
460
-
461
- if ( !is_null( $_this->regex ) ) {
462
- return $_this->_check();
463
- }
464
-
465
- $regex['dmy'] = '%^(?:(?:31(\\/|-|\\.|\\x20)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\\/|-|\\.|\\x20)(?:0?[1,3-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:29(\\/|-|\\.|\\x20)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/|-|\\.|\\x20)(?:(?:0?[1-9])|(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%';
466
- $regex['mdy'] = '%^(?:(?:(?:0?[13578]|1[02])(\\/|-|\\.|\\x20)31)\\1|(?:(?:0?[13-9]|1[0-2])(\\/|-|\\.|\\x20)(?:29|30)\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:0?2(\\/|-|\\.|\\x20)29\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\\/|-|\\.|\\x20)(?:0?[1-9]|1\\d|2[0-8])\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%';
467
- $regex['ymd'] = '%^(?:(?:(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(\\/|-|\\.|\\x20)(?:0?2\\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\\d)?\\d{2})(\\/|-|\\.|\\x20)(?:(?:(?:0?[13578]|1[02])\\2(?:31))|(?:(?:0?[1,3-9]|1[0-2])\\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\\2(?:0?[1-9]|1\\d|2[0-8]))))$%';
468
- $regex['dMy'] = '/^((31(?!\\ (Feb(ruary)?|Apr(il)?|June?|(Sep(?=\\b|t)t?|Nov)(ember)?)))|((30|29)(?!\\ Feb(ruary)?))|(29(?=\\ Feb(ruary)?\\ (((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))|(0?[1-9])|1\\d|2[0-8])\\ (Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)\\ ((1[6-9]|[2-9]\\d)\\d{2})$/';
469
- $regex['Mdy'] = '/^(?:(((Jan(uary)?|Ma(r(ch)?|y)|Jul(y)?|Aug(ust)?|Oct(ober)?|Dec(ember)?)\\ 31)|((Jan(uary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sept|Nov|Dec)(ember)?)\\ (0?[1-9]|([12]\\d)|30))|(Feb(ruary)?\\ (0?[1-9]|1\\d|2[0-8]|(29(?=,?\\ ((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))))\\,?\\ ((1[6-9]|[2-9]\\d)\\d{2}))$/';
470
- $regex['My'] = '%^(Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)[ /]((1[6-9]|[2-9]\\d)\\d{2})$%';
471
- $regex['my'] = '%^(((0[123456789]|10|11|12)([- /.])(([1][9][0-9][0-9])|([2][0-9][0-9][0-9]))))$%';
472
-
473
- $format = (is_array( $format )) ? array_values( $format ) : array($format);
474
- foreach ( $format as $key ) {
475
- $_this->regex = $regex[$key];
476
-
477
- if ( $_this->_check() === true ) {
478
- return true;
479
- }
480
- }
481
- return false;
482
- }
483
-
484
- /**
485
- * Time validation, determines if the string passed is a valid time.
486
- * Validates time as 24hr (HH:MM) or am/pm ([H]H:MM[a|p]m)
487
- * Does not allow/validate seconds.
488
- *
489
- * @param string $check a valid time string
490
- * @return boolean Success
491
- * @access public
492
- */
493
- function time( $check ) {
494
- $_this = &Wpcf_Cake_Validation::getInstance();
495
- $_this->__reset();
496
- $_this->check = $check;
497
- $_this->regex = '%^((0?[1-9]|1[012])(:[0-5]\d){0,2}([AP]M|[ap]m))$|^([01]\d|2[0-3])(:[0-5]\d){0,2}$%';
498
- return $_this->_check();
499
- }
500
-
501
- /**
502
- * Boolean validation, determines if value passed is a boolean integer or true/false.
503
- *
504
- * @param string $check a valid boolean
505
- * @return boolean Success
506
- * @access public
507
- */
508
- function boolean( $check ) {
509
- $booleanList = array(0, 1, '0', '1', true, false);
510
- return in_array( $check, $booleanList, true );
511
- }
512
-
513
- /**
514
- * Checks that a value is a valid decimal. If $places is null, the $check is allowed to be a scientific float
515
- * If no decimal point is found a false will be returned. Both the sign and exponent are optional.
516
- *
517
- * @param integer $check The value the test for decimal
518
- * @param integer $places if set $check value must have exactly $places after the decimal point
519
- * @param string $regex If a custom regular expression is used this is the only validation that will occur.
520
- * @return boolean Success
521
- * @access public
522
- */
523
- function decimal( $check, $places = null, $regex = null ) {
524
- $_this = &Wpcf_Cake_Validation::getInstance();
525
- $_this->__reset();
526
- $_this->regex = $regex;
527
- $_this->check = $check;
528
-
529
- if ( is_null( $_this->regex ) ) {
530
- if ( is_null( $places ) ) {
531
- $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]+(?:[eE][-+]?[0-9]+)?$/';
532
- } else {
533
- $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]{' . $places . '}$/';
534
- }
535
- }
536
- return $_this->_check();
537
- }
538
-
539
- /**
540
- * Validates for an email address.
541
- *
542
- * @param string $check Value to check
543
- * @param boolean $deep Perform a deeper validation (if true), by also checking availability of host
544
- * @param string $regex Regex to use (if none it will use built in regex)
545
- * @return boolean Success
546
- * @access public
547
- */
548
- function email( $check, $deep = false, $regex = null ) {
549
- $_this = &Wpcf_Cake_Validation::getInstance();
550
- $_this->__reset();
551
- $_this->check = $check;
552
- $_this->regex = $regex;
553
- $_this->deep = $deep;
554
-
555
- if ( is_array( $check ) ) {
556
- $_this->_extract( $check );
557
- }
558
-
559
- if ( is_null( $_this->regex ) ) {
560
- $_this->regex = '/^[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@' . $_this->__pattern['hostname'] . '$/i';
561
- }
562
- $return = $_this->_check();
563
-
564
- if ( $_this->deep === false || $_this->deep === null ) {
565
- return $return;
566
- }
567
-
568
- if ( $return === true && preg_match( '/@(' . $_this->__pattern['hostname'] . ')$/i',
569
- $_this->check, $regs ) ) {
570
- if ( function_exists( 'getmxrr' ) && getmxrr( $regs[1], $mxhosts ) ) {
571
- return true;
572
- }
573
- if ( function_exists( 'checkdnsrr' ) && checkdnsrr( $regs[1], 'MX' ) ) {
574
- return true;
575
- }
576
- return is_array( gethostbynamel( $regs[1] ) );
577
- }
578
- return false;
579
- }
580
-
581
- /**
582
- * Check that value is exactly $comparedTo.
583
- *
584
- * @param mixed $check Value to check
585
- * @param mixed $comparedTo Value to compare
586
- * @return boolean Success
587
- * @access public
588
- */
589
- function equalTo( $check, $comparedTo ) {
590
- return ($check === $comparedTo);
591
- }
592
-
593
- /**
594
- * Check that value has a valid file extension.
595
- *
596
- * @param mixed $check Value to check
597
- * @param array $extensions file extenstions to allow
598
- * @return boolean Success
599
- * @access public
600
- */
601
- function extension( $check, $extensions = array('gif', 'jpeg', 'png', 'jpg') ) {
602
- if ( is_array( $check ) ) {
603
- return Wpcf_Cake_Validation::extension( array_shift( $check ),
604
- $extensions );
605
- }
606
- $extension = strtolower( array_pop( explode( '.', $check ) ) );
607
- foreach ( $extensions as $value ) {
608
- if ( $extension == strtolower( $value ) ) {
609
- return true;
610
- }
611
- }
612
- return false;
613
- }
614
-
615
- /**
616
- * Validation of an IP address.
617
- *
618
- * Valid IP version strings for type restriction are:
619
- * - both: Check both IPv4 and IPv6, return true if the supplied address matches either version
620
- * - IPv4: Version 4 (Eg: 127.0.0.1, 192.168.10.123, 203.211.24.8)
621
- * - IPv6: Version 6 (Eg: ::1, 2001:0db8::1428:57ab)
622
- *
623
- * @param string $check The string to test.
624
- * @param string $type The IP Version to test against
625
- * @return boolean Success
626
- * @access public
627
- */
628
- function ip( $check, $type = 'both' ) {
629
- $_this = &Wpcf_Cake_Validation::getInstance();
630
- $success = false;
631
- $type = strtolower( $type );
632
- if ( $type === 'ipv4' || $type === 'both' ) {
633
- $success |= $_this->_ipv4( $check );
634
- }
635
- if ( $type === 'ipv6' || $type === 'both' ) {
636
- $success |= $_this->_ipv6( $check );
637
- }
638
- return $success;
639
- }
640
-
641
- /**
642
- * Validation of IPv4 addresses.
643
- *
644
- * @param string $check IP Address to test
645
- * @return boolean Success
646
- * @access protected
647
- */
648
- function _ipv4( $check ) {
649
- if ( function_exists( 'filter_var' ) ) {
650
- return filter_var( $check, FILTER_VALIDATE_IP,
651
- array('flags' => FILTER_FLAG_IPV4) ) !== false;
652
- }
653
- $this->__populateIp();
654
- $this->check = $check;
655
- $this->regex = '/^' . $this->__pattern['IPv4'] . '$/';
656
- return $this->_check();
657
- }
658
-
659
- /**
660
- * Validation of IPv6 addresses.
661
- *
662
- * @param string $check IP Address to test
663
- * @return boolean Success
664
- * @access protected
665
- */
666
- function _ipv6( $check ) {
667
- if ( function_exists( 'filter_var' ) ) {
668
- return filter_var( $check, FILTER_VALIDATE_IP,
669
- array('flags' => FILTER_FLAG_IPV6) ) !== false;
670
- }
671
- $this->__populateIp();
672
- $this->check = $check;
673
- $this->regex = '/^' . $this->__pattern['IPv6'] . '$/';
674
- return $this->_check();
675
- }
676
-
677
- /**
678
- * Checks whether the length of a string is greater or equal to a minimal length.
679
- *
680
- * @param string $check The string to test
681
- * @param integer $min The minimal string length
682
- * @return boolean Success
683
- * @access public
684
- */
685
- function minLength( $check, $min ) {
686
- $length = strlen( $check );
687
- return ($length >= $min);
688
- }
689
-
690
- /**
691
- * Checks whether the length of a string is smaller or equal to a maximal length..
692
- *
693
- * @param string $check The string to test
694
- * @param integer $max The maximal string length
695
- * @return boolean Success
696
- * @access public
697
- */
698
- function maxLength( $check, $max ) {
699
- $length = strlen( $check );
700
- return ($length <= $max);
701
- }
702
-
703
- /**
704
- * Checks that a value is a monetary amount.
705
- *
706
- * @param string $check Value to check
707
- * @param string $symbolPosition Where symbol is located (left/right)
708
- * @return boolean Success
709
- * @access public
710
- */
711
- function money( $check, $symbolPosition = 'left' ) {
712
- $_this = &Wpcf_Cake_Validation::getInstance();
713
- $_this->check = $check;
714
-
715
- if ( $symbolPosition == 'right' ) {
716
- $_this->regex = '/^(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?(?<!\x{00a2})\p{Sc}?$/u';
717
- } else {
718
- $_this->regex = '/^(?!\x{00a2})\p{Sc}?(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?$/u';
719
- }
720
- return $_this->_check();
721
- }
722
-
723
- /**
724
- * Validate a multiple select.
725
- *
726
- * Valid Options
727
- *
728
- * - in => provide a list of choices that selections must be made from
729
- * - max => maximun number of non-zero choices that can be made
730
- * - min => minimum number of non-zero choices that can be made
731
- *
732
- * @param mixed $check Value to check
733
- * @param mixed $options Options for the check.
734
- * @return boolean Success
735
- * @access public
736
- */
737
- function multiple( $check, $options = array() ) {
738
- $defaults = array('in' => null, 'max' => null, 'min' => null);
739
- $options = array_merge( $defaults, $options );
740
- $check = array_filter( (array) $check );
741
- if ( empty( $check ) ) {
742
- return false;
743
- }
744
- if ( $options['max'] && count( $check ) > $options['max'] ) {
745
- return false;
746
- }
747
- if ( $options['min'] && count( $check ) < $options['min'] ) {
748
- return false;
749
- }
750
- if ( $options['in'] && is_array( $options['in'] ) ) {
751
- foreach ( $check as $val ) {
752
- if ( !in_array( $val, $options['in'] ) ) {
753
- return false;
754
- }
755
- }
756
- }
757
- return true;
758
- }
759
-
760
- /**
761
- * Checks if a value is numeric.
762
- *
763
- * @param string $check Value to check
764
- * @return boolean Succcess
765
- * @access public
766
- */
767
- function numeric( $check ) {
768
- return is_numeric( $check );
769
- }
770
-
771
- /**
772
- * Check that a value is a valid phone number.
773
- *
774
- * @param mixed $check Value to check (string or array)
775
- * @param string $regex Regular expression to use
776
- * @param string $country Country code (defaults to 'all')
777
- * @return boolean Success
778
- * @access public
779
- */
780
- function phone( $check, $regex = null, $country = 'all' ) {
781
- $_this = &Wpcf_Cake_Validation::getInstance();
782
- $_this->check = $check;
783
- $_this->regex = $regex;
784
- $_this->country = $country;
785
- if ( is_array( $check ) ) {
786
- $_this->_extract( $check );
787
- }
788
-
789
- if ( is_null( $_this->regex ) ) {
790
- switch ( $_this->country ) {
791
- case 'us':
792
- case 'all':
793
- case 'can':
794
- // includes all NANPA members. see http://en.wikipedia.org/wiki/North_American_Numbering_Plan#List_of_NANPA_countries_and_territories
795
- $_this->regex = '/^(?:\+?1)?[-. ]?\\(?[2-9][0-8][0-9]\\)?[-. ]?[2-9][0-9]{2}[-. ]?[0-9]{4}$/';
796
- break;
797
- }
798
- }
799
- if ( empty( $_this->regex ) ) {
800
- return $_this->_pass( 'phone', $check, $country );
801
- }
802
- return $_this->_check();
803
- }
804
-
805
- /**
806
- * Checks that a given value is a valid postal code.
807
- *
808
- * @param mixed $check Value to check
809
- * @param string $regex Regular expression to use
810
- * @param string $country Country to use for formatting
811
- * @return boolean Success
812
- * @access public
813
- */
814
- function postal( $check, $regex = null, $country = null ) {
815
- $_this = &Wpcf_Cake_Validation::getInstance();
816
- $_this->check = $check;
817
- $_this->regex = $regex;
818
- $_this->country = $country;
819
- if ( is_array( $check ) ) {
820
- $_this->_extract( $check );
821
- }
822
- if ( empty( $country ) ) {
823
- $_this->country = 'us';
824
- }
825
-
826
- if ( is_null( $_this->regex ) ) {
827
- switch ( $_this->country ) {
828
- case 'uk':
829
- $_this->regex = '/\\A\\b[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}\\b\\z/i';
830
- break;
831
- case 'ca':
832
- $_this->regex = '/\\A\\b[ABCEGHJKLMNPRSTVXY][0-9][A-Z] ?[0-9][A-Z][0-9]\\b\\z/i';
833
- break;
834
- case 'it':
835
- case 'de':
836
- $_this->regex = '/^[0-9]{5}$/i';
837
- break;
838
- case 'be':
839
- $_this->regex = '/^[1-9]{1}[0-9]{3}$/i';
840
- break;
841
- case 'us':
842
- $_this->regex = '/\\A\\b[0-9]{5}(?:-[0-9]{4})?\\b\\z/i';
843
- break;
844
- }
845
- }
846
- if ( empty( $_this->regex ) ) {
847
- return $_this->_pass( 'postal', $check, $country );
848
- }
849
- return $_this->_check();
850
- }
851
-
852
- /**
853
- * Validate that a number is in specified range.
854
- * if $lower and $upper are not set, will return true if
855
- * $check is a legal finite on this platform
856
- *
857
- * @param string $check Value to check
858
- * @param integer $lower Lower limit
859
- * @param integer $upper Upper limit
860
- * @return boolean Success
861
- * @access public
862
- */
863
- function range( $check, $lower = null, $upper = null ) {
864
- if ( !is_numeric( $check ) ) {
865
- return false;
866
- }
867
- if ( isset( $lower ) && isset( $upper ) ) {
868
- return ($check > $lower && $check < $upper);
869
- }
870
- return is_finite( $check );
871
- }
872
-
873
- /**
874
- * Checks that a value is a valid Social Security Number.
875
- *
876
- * @param mixed $check Value to check
877
- * @param string $regex Regular expression to use
878
- * @param string $country Country
879
- * @return boolean Success
880
- * @access public
881
- */
882
- function ssn( $check, $regex = null, $country = null ) {
883
- $_this = &Wpcf_Cake_Validation::getInstance();
884
- $_this->check = $check;
885
- $_this->regex = $regex;
886
- $_this->country = $country;
887
- if ( is_array( $check ) ) {
888
- $_this->_extract( $check );
889
- }
890
-
891
- if ( is_null( $_this->regex ) ) {
892
- switch ( $_this->country ) {
893
- case 'dk':
894
- $_this->regex = '/\\A\\b[0-9]{6}-[0-9]{4}\\b\\z/i';
895
- break;
896
- case 'nl':
897
- $_this->regex = '/\\A\\b[0-9]{9}\\b\\z/i';
898
- break;
899
- case 'us':
900
- $_this->regex = '/\\A\\b[0-9]{3}-[0-9]{2}-[0-9]{4}\\b\\z/i';
901
- break;
902
- }
903
- }
904
- if ( empty( $_this->regex ) ) {
905
- return $_this->_pass( 'ssn', $check, $country );
906
- }
907
- return $_this->_check();
908
- }
909
-
910
- /**
911
- * Checks that a value is a valid uuid - http://tools.ietf.org/html/rfc4122
912
- *
913
- * @param string $check Value to check
914
- * @return boolean Success
915
- * @access public
916
- */
917
- function uuid( $check ) {
918
- $_this = &Wpcf_Cake_Validation::getInstance();
919
- $_this->check = $check;
920
- $_this->regex = '/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i';
921
- return $_this->_check();
922
- }
923
-
924
- /**
925
- * Checks that a value is a valid URL according to http://www.w3.org/Addressing/URL/url-spec.txt
926
- *
927
- * The regex checks for the following component parts:
928
- *
929
- * - a valid, optional, scheme
930
- * - a valid ip address OR
931
- * a valid domain name as defined by section 2.3.1 of http://www.ietf.org/rfc/rfc1035.txt
932
- * with an optional port number
933
- * - an optional valid path
934
- * - an optional query string (get parameters)
935
- * - an optional fragment (anchor tag)
936
- *
937
- * @param string $check Value to check
938
- * @param boolean $strict Require URL to be prefixed by a valid scheme (one of http(s)/ftp(s)/file/news/gopher)
939
- * @return boolean Success
940
- * @access public
941
- */
942
- function url( $check, $strict = false ) {
943
- $_this = &Wpcf_Cake_Validation::getInstance();
944
- $_this->__populateIp();
945
- $_this->check = $check;
946
- $validChars = '([' . preg_quote( '!"$&\'()*+,-.@_:;=~[]' ) . '\/0-9a-z\p{L}\p{N}]|(%[0-9a-f]{2}))';
947
- $_this->regex = '/^(?:(?:https?|ftps?|file|news|gopher):\/\/)' . (!empty( $strict ) ? '' : '?') .
948
- '(?:' . $_this->__pattern['IPv4'] . '|\[' . $_this->__pattern['IPv6'] . '\]|' . $_this->__pattern['hostname'] . ')' .
949
- '(?::[1-9][0-9]{0,4})?' .
950
- '(?:\/?|\/' . $validChars . '*)?' .
951
- '(?:\?' . $validChars . '*)?' .
952
- '(?:#' . $validChars . '*)?$/iu';
953
- return $_this->_check();
954
- }
955
-
956
- /**
957
- * Checks if a value is in a given list.
958
- *
959
- * @param string $check Value to check
960
- * @param array $list List to check against
961
- * @return boolean Succcess
962
- * @access public
963
- */
964
- function inList( $check, $list ) {
965
- return in_array( $check, $list );
966
- }
967
-
968
- /**
969
- * Runs an user-defined validation.
970
- *
971
- * @param mixed $check value that will be validated in user-defined methods.
972
- * @param object $object class that holds validation method
973
- * @param string $method class method name for validation to run
974
- * @param array $args arguments to send to method
975
- * @return mixed user-defined class class method returns
976
- * @access public
977
- */
978
- function userDefined( $check, $object, $method, $args = null ) {
979
- return call_user_func_array( array(&$object, $method),
980
- array($check, $args) );
981
- }
982
-
983
- function noSpecialChars( $check ) {
984
- return preg_match( '#[^a-zA-Z0-9\s\_\-]#', $check ) ? false : true;
985
- }
986
-
987
- function rewriteSlug( $check ) {
988
- return preg_match( '#[^a-zA-Z0-9\s\_\-\%]#', $check ) ? false : true;
989
- }
990
-
991
- /**
992
- * Attempts to pass unhandled Validation locales to a class starting with $classPrefix
993
- * and ending with Validation. For example $classPrefix = 'nl', the class would be
994
- * `NlValidation`.
995
- *
996
- * @param string $method The method to call on the other class.
997
- * @param mixed $check The value to check or an array of parameters for the method to be called.
998
- * @param string $classPrefix The prefix for the class to do the validation.
999
- * @return mixed Return of Passed method, false on failure
1000
- * @access protected
1001
- * */
1002
- function _pass( $method, $check, $classPrefix ) {
1003
- $className = ucwords( $classPrefix ) . 'Validation';
1004
- if ( !class_exists( $className ) ) {
1005
- trigger_error( sprintf( __( 'Could not find %s class, unable to complete validation.', 'wpcf' ), $className ), E_USER_WARNING );
1006
- return false;
1007
- }
1008
- if ( !is_callable( array($className, $method) ) ) {
1009
- trigger_error( sprintf( __( 'Method %s does not exist on %s unable to complete validation.', 'wpcf' ), $method, $className ),
1010
- E_USER_WARNING );
1011
- return false;
1012
- }
1013
- $check = (array) $check;
1014
- return call_user_func_array( array($className, $method), $check );
1015
- }
1016
-
1017
- /**
1018
- * Runs a regular expression match.
1019
- *
1020
- * @return boolean Success of match
1021
- * @access protected
1022
- */
1023
- function _check() {
1024
- $_this = &Wpcf_Cake_Validation::getInstance();
1025
- if ( preg_match( $_this->regex, $_this->check ) ) {
1026
- $_this->error[] = false;
1027
- return true;
1028
- } else {
1029
- $_this->error[] = true;
1030
- return false;
1031
- }
1032
- }
1033
-
1034
- /**
1035
- * Get the values to use when value sent to validation method is
1036
- * an array.
1037
- *
1038
- * @param array $params Parameters sent to validation method
1039
- * @return void
1040
- * @access protected
1041
- */
1042
- function _extract( $params ) {
1043
- $_this = &Wpcf_Cake_Validation::getInstance();
1044
- extract( $params, EXTR_OVERWRITE );
1045
-
1046
- if ( isset( $check ) ) {
1047
- $_this->check = $check;
1048
- }
1049
- if ( isset( $regex ) ) {
1050
- $_this->regex = $regex;
1051
- }
1052
- if ( isset( $country ) ) {
1053
- $_this->country = strtolower( $country );
1054
- }
1055
- if ( isset( $deep ) ) {
1056
- $_this->deep = $deep;
1057
- }
1058
- if ( isset( $type ) ) {
1059
- $_this->type = $type;
1060
- }
1061
- }
1062
-
1063
- /**
1064
- * Luhn algorithm
1065
- *
1066
- * @see http://en.wikipedia.org/wiki/Luhn_algorithm
1067
- * @return boolean Success
1068
- * @access protected
1069
- */
1070
- function _luhn() {
1071
- $_this = &Wpcf_Cake_Validation::getInstance();
1072
- if ( $_this->deep !== true ) {
1073
- return true;
1074
- }
1075
- if ( $_this->check == 0 ) {
1076
- return false;
1077
- }
1078
- $sum = 0;
1079
- $length = strlen( $_this->check );
1080
-
1081
- for ( $position = 1 - ($length % 2); $position < $length; $position += 2 ) {
1082
- $sum += $_this->check[$position];
1083
- }
1084
-
1085
- for ( $position = ($length % 2); $position < $length; $position += 2 ) {
1086
- $number = $_this->check[$position] * 2;
1087
- $sum += ($number < 10) ? $number : $number - 9;
1088
- }
1089
-
1090
- return ($sum % 10 == 0);
1091
- }
1092
-
1093
- /*
1094
- * Lazily popualate the IP address patterns used for validations
1095
- *
1096
- * @return void
1097
- * @access private
1098
- */
1099
-
1100
- function __populateIp() {
1101
- if ( !isset( $this->__pattern['IPv6'] ) ) {
1102
- $pattern = '((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}';
1103
- $pattern .= '(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})';
1104
- $pattern .= '|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})';
1105
- $pattern .= '(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)';
1106
- $pattern .= '{4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2}))';
1107
- $pattern .= '{3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}';
1108
- $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|';
1109
- $pattern .= '((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}';
1110
- $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2}))';
1111
- $pattern .= '{3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4})';
1112
- $pattern .= '{0,4}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)';
1113
- $pattern .= '|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]';
1114
- $pattern .= '\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4})';
1115
- $pattern .= '{1,2})))|(((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))(%.+)?';
1116
-
1117
- $this->__pattern['IPv6'] = $pattern;
1118
- }
1119
- if ( !isset( $this->__pattern['IPv4'] ) ) {
1120
- $pattern = '(?:(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])';
1121
- $this->__pattern['IPv4'] = $pattern;
1122
- }
1123
- }
1124
-
1125
- /**
1126
- * Reset internal variables for another validation run.
1127
- *
1128
- * @return void
1129
- * @access private
1130
- */
1131
- function __reset() {
1132
- $this->check = null;
1133
- $this->regex = null;
1134
- $this->country = null;
1135
- $this->deep = null;
1136
- $this->type = null;
1137
- $this->error = array();
1138
- $this->errors = array();
1139
- }
1140
-
1141
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installed.json DELETED
@@ -1,247 +0,0 @@
1
- [
2
- {
3
- "name": "composer/installers",
4
- "version": "v1.0.23",
5
- "version_normalized": "1.0.23.0",
6
- "source": {
7
- "type": "git",
8
- "url": "https://github.com/composer/installers.git",
9
- "reference": "6213d900e92647831f7a406d5c530ea1f3d4360e"
10
- },
11
- "dist": {
12
- "type": "zip",
13
- "url": "https://api.github.com/repos/composer/installers/zipball/6213d900e92647831f7a406d5c530ea1f3d4360e",
14
- "reference": "6213d900e92647831f7a406d5c530ea1f3d4360e",
15
- "shasum": ""
16
- },
17
- "require": {
18
- "composer-plugin-api": "^1.0"
19
- },
20
- "replace": {
21
- "roundcube/plugin-installer": "*",
22
- "shama/baton": "*"
23
- },
24
- "require-dev": {
25
- "composer/composer": "1.0.*@dev",
26
- "phpunit/phpunit": "4.1.*"
27
- },
28
- "time": "2016-01-27 12:54:22",
29
- "type": "composer-plugin",
30
- "extra": {
31
- "class": "Composer\\Installers\\Plugin",
32
- "branch-alias": {
33
- "dev-master": "1.0-dev"
34
- }
35
- },
36
- "installation-source": "dist",
37
- "autoload": {
38
- "psr-0": {
39
- "Composer\\Installers\\": "src/"
40
- }
41
- },
42
- "notification-url": "https://packagist.org/downloads/",
43
- "license": [
44
- "MIT"
45
- ],
46
- "authors": [
47
- {
48
- "name": "Kyle Robinson Young",
49
- "email": "kyle@dontkry.com",
50
- "homepage": "https://github.com/shama"
51
- }
52
- ],
53
- "description": "A multi-framework Composer library installer",
54
- "homepage": "http://composer.github.com/installers/",
55
- "keywords": [
56
- "Craft",
57
- "Dolibarr",
58
- "Hurad",
59
- "MODX Evo",
60
- "OXID",
61
- "SMF",
62
- "Thelia",
63
- "WolfCMS",
64
- "agl",
65
- "aimeos",
66
- "annotatecms",
67
- "bitrix",
68
- "cakephp",
69
- "chef",
70
- "codeigniter",
71
- "concrete5",
72
- "croogo",
73
- "dokuwiki",
74
- "drupal",
75
- "elgg",
76
- "fuelphp",
77
- "grav",
78
- "installer",
79
- "joomla",
80
- "kohana",
81
- "laravel",
82
- "lithium",
83
- "magento",
84
- "mako",
85
- "mediawiki",
86
- "modulework",
87
- "moodle",
88
- "phpbb",
89
- "piwik",
90
- "ppi",
91
- "puppet",
92
- "roundcube",
93
- "shopware",
94
- "silverstripe",
95
- "symfony",
96
- "typo3",
97
- "wordpress",
98
- "zend",
99
- "zikula"
100
- ]
101
- },
102
- {
103
- "name": "toolset/toolset-common",
104
- "version": "1.9",
105
- "version_normalized": "1.9.0.0",
106
- "source": {
107
- "type": "git",
108
- "url": "git@git.onthegosystems.com:toolset/toolset-common.git",
109
- "reference": "df19adf48f66dac1e0b0b15df1a5b5af172b4f12"
110
- },
111
- "require": {
112
- "php": ">=5.2.0"
113
- },
114
- "require-dev": {
115
- "phpunit/phpunit": "~4.5"
116
- },
117
- "time": "2016-02-15 15:34:04",
118
- "type": "library",
119
- "extra": {
120
- "branch-alias": {
121
- "dev-master": "1.6.x-dev",
122
- "dev-develop": "1.6.x-dev"
123
- }
124
- },
125
- "installation-source": "source",
126
- "scripts": {
127
- "test": [
128
- "phpunit"
129
- ]
130
- },
131
- "license": [
132
- "GPL-2.0"
133
- ],
134
- "authors": [
135
- {
136
- "name": "Bruce Pearson, Juan de Paco, Riccardo Strobbia, Marcin Pietrzack, Francesco Livolsi",
137
- "email": "riccardo.s@icanlocalize.com",
138
- "homepage": "http://www.wp-types.com"
139
- }
140
- ],
141
- "description": "A set of libraries for Toolset Plugins",
142
- "homepage": "https://git.onthegosystems.com/toolset/toolset-common",
143
- "keywords": [
144
- "models",
145
- "types-fields",
146
- "utils",
147
- "visual-editor"
148
- ]
149
- },
150
- {
151
- "name": "toolset/onthego-resources",
152
- "version": "dev-develop",
153
- "version_normalized": "dev-develop",
154
- "source": {
155
- "type": "git",
156
- "url": "git@git.onthegosystems.com:toolset/onthego-resources.git",
157
- "reference": "670727b099f3185aff33067e364129a544c07161"
158
- },
159
- "require": {
160
- "php": ">=5.2.0"
161
- },
162
- "require-dev": {
163
- "phpunit/phpunit": "~4.5"
164
- },
165
- "time": "2016-01-26 12:12:58",
166
- "type": "library",
167
- "extra": {
168
- "branch-alias": {
169
- "dev-master": "1.2.x-dev",
170
- "dev-develop": "1.2.x-dev"
171
- }
172
- },
173
- "installation-source": "source",
174
- "scripts": {
175
- "test": [
176
- "phpunit"
177
- ]
178
- },
179
- "license": [
180
- "GPL-2.0"
181
- ],
182
- "authors": [
183
- {
184
- "name": "Bruce Pearson, Juan de Paco, Riccardo Strobbia",
185
- "email": "riccardo.s@icanlocalize.com",
186
- "homepage": "http://www.wp-types.com"
187
- }
188
- ],
189
- "description": "Branding resources for Toolset plugins",
190
- "homepage": "https://git.onthegosystems.com/toolset/onthego-resources",
191
- "keywords": [
192
- "CSS",
193
- "icons",
194
- "utils",
195
- "vectors"
196
- ]
197
- },
198
- {
199
- "name": "otgs/installer",
200
- "version": "1.7.6",
201
- "version_normalized": "1.7.6.0",
202
- "source": {
203
- "type": "git",
204
- "url": "git@git.onthegosystems.com:installer/installer.git",
205
- "reference": "61f0d3178e84f9c96cd8580a5e28d30a84ff4e5a"
206
- },
207
- "require": {
208
- "composer/installers": "~1.0",
209
- "php": ">=5.2.0"
210
- },
211
- "require-dev": {
212
- "phpunit/phpunit": "~4.5"
213
- },
214
- "time": "2016-02-23 13:04:37",
215
- "type": "wordpress-plugin",
216
- "extra": {
217
- "branch-alias": {
218
- "dev-master": "1.6.x-dev",
219
- "dev-develop": "1.6.x-dev"
220
- }
221
- },
222
- "installation-source": "source",
223
- "scripts": {
224
- "test": [
225
- "phpunit"
226
- ]
227
- },
228
- "license": [
229
- "GPL-2.0"
230
- ],
231
- "authors": [
232
- {
233
- "name": "Mihai Grigori",
234
- "email": "mihai@wpml.org",
235
- "homepage": "http://www.wp-types.com"
236
- }
237
- ],
238
- "description": "Installs and updates WPML and Toolset dependencies automatically",
239
- "homepage": "https://git.onthegosystems.com/installer/installer",
240
- "keywords": [
241
- "install",
242
- "plugins",
243
- "update",
244
- "utils"
245
- ]
246
- }
247
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/.editorconfig DELETED
@@ -1,10 +0,0 @@
1
- ; top-most EditorConfig file
2
- root = true
3
-
4
- ; Unix-style newlines
5
- [*]
6
- end_of_line = LF
7
-
8
- [*.php]
9
- indent_style = space
10
- indent_size = 4
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/.travis.yml DELETED
@@ -1,21 +0,0 @@
1
- language: php
2
-
3
- php:
4
- - 5.3
5
- - 5.4
6
- - 5.5
7
- - 5.6
8
- - 7.0
9
- - hhvm
10
-
11
- matrix:
12
- fast_finish: true
13
- allow_failures:
14
- - php: 7.0
15
-
16
- before_script:
17
- - composer self-update
18
- - composer install
19
-
20
- script:
21
- - phpunit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/LICENSE DELETED
@@ -1,19 +0,0 @@
1
- Copyright (c) 2012 Kyle Robinson Young
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy
4
- of this software and associated documentation files (the "Software"), to deal
5
- in the Software without restriction, including without limitation the rights
6
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- copies of the Software, and to permit persons to whom the Software is furnished
8
- to do so, subject to the following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in all
11
- copies or substantial portions of the Software.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- THE SOFTWARE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/README.md DELETED
@@ -1,193 +0,0 @@
1
- # A Multi-Framework [Composer](http://getcomposer.org) Library Installer
2
-
3
- [![Build Status](http://img.shields.io/travis/composer/installers.svg)](http://travis-ci.org/composer/installers)
4
-
5
- This is for PHP package authors to require in their `composer.json`. It will
6
- install their package to the correct location based on the specified package
7
- type.
8
-
9
- The goal of `installers` is to be a simple package type to install path map.
10
- Users can also customize the install path per package and package authors can
11
- modify the package name upon installing.
12
-
13
- `installers` isn't intended on replacing all custom installers. If your
14
- package requires special installation handling then by all means, create a
15
- custom installer to handle it.
16
-
17
- **Natively Supported Frameworks**:
18
-
19
- The following frameworks natively work with Composer and will be
20
- installed to the default `vendor` directory. `composer/installers`
21
- is not needed to install packages with these frameworks:
22
-
23
- * Aura
24
- * Symfony2
25
- * Yii
26
- * Yii2
27
-
28
- **Current Supported Package Types**:
29
-
30
- > Stable types are marked as **bold**, this means that installation paths
31
- > for those type will not be changed. Any adjustment for those types would
32
- > require creation of brand new type that will cover required changes.
33
-
34
- | Framework | Types
35
- | --------- | -----
36
- | Aimeos | `aimeos-extension`
37
- | Asgard | `asgard-module`<br>`asgard-theme`
38
- | AGL | `agl-module`
39
- | Bonefish | `bonefish-package`
40
- | AnnotateCms | `annotatecms-module`<br>`annotatecms-component`<br>`annotatecms-service`
41
- | Bitrix | `bitrix-module`<br>`bitrix-component`<br>`bitrix-theme`
42
- | CakePHP 2+ | **`cakephp-plugin`**
43
- | Chef | `chef-cookbook`<br>`chef-role`
44
- | CCFramework | `ccframework-ship`<br>`ccframework-theme`
45
- | CodeIgniter | `codeigniter-library`<br>`codeigniter-third-party`<br>`codeigniter-module`
46
- | concrete5 | `concrete5-block`<br>`concrete5-package`<br>`concrete5-theme`<br>`concrete5-update`
47
- | Craft | `craft-plugin`
48
- | Croogo | `croogo-plugin`<br>`croogo-theme`
49
- | DokuWiki | `dokuwiki-plugin`<br>`dokuwiki-template`
50
- | Dolibarr | `dolibarr-module`
51
- | Drupal | <b>`drupal-module`<br>`drupal-theme`</b><br>`drupal-library`<br>`drupal-profile`<br>`drupal-drush`
52
- | Elgg | `elgg-plugin`
53
- | FuelPHP v1.x | `fuel-module`<br>`fuel-package`<br/>`fuel-theme`
54
- | FuelPHP v2.x | `fuelphp-component`
55
- | Grav | `grav-plugin`<br>`grav-theme`
56
- | Hurad | `hurad-plugin`<br>`hurad-theme`
57
- | Joomla | `joomla-component`<br>`joomla-module`<br>`joomla-template`<br>`joomla-plugin`<br>`joomla-library`
58
- | Kirby | **`kirby-plugin`**
59
- | KodiCMS | `kodicms-plugin`<br>`kodicms-media`
60
- | Kohana | **`kohana-module`**
61
- | Laravel | `laravel-library`
62
- | Lithium | **`lithium-library`<br>`lithium-source`**
63
- | Magento | `magento-library`<br>`magento-skin`<br>`magento-theme`
64
- | Mako | `mako-package`
65
- | MODX Evo | `modxevo-snippet`<br>`modxevo-plugin`<br>`modxevo-module`<br>`modxevo-template`<br>`modxevo-lib`
66
- | MediaWiki | `mediawiki-extension`
67
- | October | **`october-module`<br>`october-plugin`<br>`october-theme`**
68
- | OXID | `oxid-module`<br>`oxid-theme`<br>`oxid-out`
69
- | MODULEWork | `modulework-module`
70
- | Moodle | `moodle-*` (Please [check source](https://raw.githubusercontent.com/composer/installers/master/src/Composer/Installers/MoodleInstaller.php) for all supported types)
71
- | Piwik | `piwik-plugin`
72
- | phpBB | `phpbb-extension`<br>`phpbb-style`<br>`phpbb-language`
73
- | Pimcore | `pimcore-plugin`
74
- | PPI | **`ppi-module`**
75
- | Puppet | `puppet-module`
76
- | REDAXO | `redaxo-addon`
77
- | Roundcube | `roundcube-plugin`
78
- | shopware | `shopware-backend-plugin`<br/>`shopware-core-plugin`<br/>`shopware-frontend-plugin`<br/>`shopware-theme`
79
- | SilverStripe | `silverstripe-module`<br>`silverstripe-theme`
80
- | SMF | `smf-module`<br>`smf-theme`
81
- | symfony1 | **`symfony1-plugin`**
82
- | Tusk | `tusk-task`<br>`tusk-command`<br>`tusk-asset`
83
- | TYPO3 Flow | `typo3-flow-package`<br>`typo3-flow-framework`<br>`typo3-flow-plugin`<br>`typo3-flow-site`<br>`typo3-flow-boilerplate`<br>`typo3-flow-build`
84
- | TYPO3 CMS | `typo3-cms-extension`
85
- | Wolf CMS | `wolfcms-plugin`
86
- | WordPress | <b>`wordpress-plugin`<br>`wordpress-theme`</b><br>`wordpress-muplugin`
87
- | Zend | `zend-library`<br>`zend-extra`<br>`zend-module`
88
- | Zikula | `zikula-module`<br>`zikula-theme`
89
- | Prestashop | `prestashop-module`<br>`prestashop-theme`
90
-
91
- ## Example `composer.json` File
92
-
93
- This is an example for a CakePHP plugin. The only important parts to set in your
94
- composer.json file are `"type": "cakephp-plugin"` which describes what your
95
- package is and `"require": { "composer/installers": "~1.0" }` which tells composer
96
- to load the custom installers.
97
-
98
- ```json
99
- {
100
- "name": "you/ftp",
101
- "type": "cakephp-plugin",
102
- "require": {
103
- "composer/installers": "~1.0"
104
- }
105
- }
106
- ```
107
-
108
- This would install your package to the `Plugin/Ftp/` folder of a CakePHP app
109
- when a user runs `php composer.phar install`.
110
-
111
- So submit your packages to [packagist.org](http://packagist.org)!
112
-
113
- ## Custom Install Paths
114
-
115
- If you are consuming a package that uses the `composer/installers` you can
116
- override the install path with the following extra in your `composer.json`:
117
-
118
- ```json
119
- {
120
- "extra": {
121
- "installer-paths": {
122
- "your/custom/path/{$name}/": ["shama/ftp", "vendor/package"]
123
- }
124
- }
125
- }
126
- ```
127
-
128
- A package type can have a custom installation path with a `type:` prefix.
129
-
130
- ``` json
131
- {
132
- "extra": {
133
- "installer-paths": {
134
- "your/custom/path/{$name}/": ["type:wordpress-plugin"]
135
- }
136
- }
137
- }
138
- ```
139
-
140
- This would use your custom path for each of the listed packages. The available
141
- variables to use in your paths are: `{$name}`, `{$vendor}`, `{$type}`.
142
-
143
- ## Custom Install Names
144
-
145
- If you're a package author and need your package to be named differently when
146
- installed consider using the `installer-name` extra.
147
-
148
- For example you have a package named `shama/cakephp-ftp` with the type
149
- `cakephp-plugin`. Installing with `composer/installers` would install to the
150
- path `Plugin/CakephpFtp`. Due to the strict naming conventions, you as a
151
- package author actually need the package to be named and installed to
152
- `Plugin/Ftp`. Using the following config within your **package** `composer.json`
153
- will allow this:
154
-
155
- ```json
156
- {
157
- "name": "shama/cakephp-ftp",
158
- "type": "cakephp-plugin",
159
- "extra": {
160
- "installer-name": "Ftp"
161
- }
162
- }
163
- ```
164
-
165
- Please note the name entered into `installer-name` will be the final and will
166
- not be inflected.
167
-
168
- ## Contribute!
169
-
170
- * [Fork and clone](https://help.github.com/articles/fork-a-repo).
171
- * Run the command `php composer.phar install` to install the dependencies.
172
- This will also install the dev dependencies. See [Composer](https://getcomposer.org/doc/03-cli.md#install).
173
- * Use the command `phpunit` to run the tests. See [PHPUnit](http://phpunit.de).
174
- * Create a branch, commit, push and send us a
175
- [pull request](https://help.github.com/articles/using-pull-requests).
176
-
177
- To ensure a consistent code base, you should make sure the code follows the
178
- [Coding Standards](http://symfony.com/doc/2.0/contributing/code/standards.html)
179
- which we borrowed from Symfony.
180
-
181
- If you would like to help, please take a look at the list of
182
- [issues](https://github.com/composer/installers/issues).
183
-
184
- ### Should we allow dynamic package types or paths? No.
185
- What are they? The ability for a package author to determine where a package
186
- will be installed either through setting the path directly in their
187
- `composer.json` or through a dynamic package type: `"type":
188
- "framework-install-here"`.
189
-
190
- It has been proposed many times. Even implemented once early on and then
191
- removed. `installers` won't do this because it would allow a single package
192
- author to wipe out entire folders without the user's consent. That user would
193
- then come here to yell at us.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/phpunit.xml.dist DELETED
@@ -1,25 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
-
3
- <phpunit backupGlobals="false"
4
- backupStaticAttributes="false"
5
- colors="true"
6
- convertErrorsToExceptions="true"
7
- convertNoticesToExceptions="true"
8
- convertWarningsToExceptions="true"
9
- processIsolation="false"
10
- stopOnFailure="false"
11
- syntaxCheck="false"
12
- bootstrap="tests/bootstrap.php"
13
- >
14
- <testsuites>
15
- <testsuite name="Installers Test Suite">
16
- <directory>tests/Composer/Installers</directory>
17
- </testsuite>
18
- </testsuites>
19
-
20
- <filter>
21
- <whitelist>
22
- <directory>src/Composer/Installers</directory>
23
- </whitelist>
24
- </filter>
25
- </phpunit>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/AglInstaller.php DELETED
@@ -1,21 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class AglInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'More/{$name}/',
8
- );
9
-
10
- /**
11
- * Format package name to CamelCase
12
- */
13
- public function inflectPackageVars($vars)
14
- {
15
- $vars['name'] = preg_replace_callback('/(?:^|_|-)(.?)/', function ($matches) {
16
- return strtoupper($matches[1]);
17
- }, $vars['name']);
18
-
19
- return $vars;
20
- }
21
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/AimeosInstaller.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class AimeosInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'extension' => 'ext/{$name}/',
8
- );
9
- }
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php DELETED
@@ -1,11 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class AnnotateCmsInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'addons/modules/{$name}/',
8
- 'component' => 'addons/components/{$name}/',
9
- 'service' => 'addons/services/{$name}/',
10
- );
11
- }
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/AsgardInstaller.php DELETED
@@ -1,45 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class AsgardInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'Modules/{$name}/',
8
- 'theme' => 'Themes/{$name}/'
9
- );
10
-
11
- /**
12
- * Format package name.
13
- *
14
- * For package type asgard-module, cut off a trailing '-plugin' if present.
15
- *
16
- * For package type asgard-theme, cut off a trailing '-theme' if present.
17
- *
18
- */
19
- public function inflectPackageVars($vars)
20
- {
21
- if ($vars['type'] === 'asgard-module') {
22
- return $this->inflectPluginVars($vars);
23
- }
24
-
25
- if ($vars['type'] === 'asgard-theme') {
26
- return $this->inflectThemeVars($vars);
27
- }
28
-
29
- return $vars;
30
- }
31
-
32
- protected function inflectPluginVars($vars)
33
- {
34
- $vars['name'] = ucfirst(preg_replace('/-module/', '', $vars['name']));
35
-
36
- return $vars;
37
- }
38
-
39
- protected function inflectThemeVars($vars)
40
- {
41
- $vars['name'] = ucfirst(preg_replace('/-theme$/', '', $vars['name']));
42
-
43
- return $vars;
44
- }
45
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/BaseInstaller.php DELETED
@@ -1,135 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- use Composer\IO\IOInterface;
5
- use Composer\Composer;
6
- use Composer\Package\PackageInterface;
7
-
8
- abstract class BaseInstaller
9
- {
10
- protected $locations = array();
11
- protected $composer;
12
- protected $package;
13
- protected $io;
14
-
15
- /**
16
- * Initializes base installer.
17
- *
18
- * @param PackageInterface $package
19
- * @param Composer $composer
20
- * @param IOInterface $io
21
- */
22
- public function __construct(PackageInterface $package = null, Composer $composer = null, IOInterface $io = null)
23
- {
24
- $this->composer = $composer;
25
- $this->package = $package;
26
- $this->io = $io;
27
- }
28
-
29
- /**
30
- * Return the install path based on package type.
31
- *
32
- * @param PackageInterface $package
33
- * @param string $frameworkType
34
- * @return string
35
- */
36
- public function getInstallPath(PackageInterface $package, $frameworkType = '')
37
- {
38
- $type = $this->package->getType();
39
-
40
- $prettyName = $this->package->getPrettyName();
41
- if (strpos($prettyName, '/') !== false) {
42
- list($vendor, $name) = explode('/', $prettyName);
43
- } else {
44
- $vendor = '';
45
- $name = $prettyName;
46
- }
47
-
48
- $availableVars = $this->inflectPackageVars(compact('name', 'vendor', 'type'));
49
-
50
- $extra = $package->getExtra();
51
- if (!empty($extra['installer-name'])) {
52
- $availableVars['name'] = $extra['installer-name'];
53
- }
54
-
55
- if ($this->composer->getPackage()) {
56
- $extra = $this->composer->getPackage()->getExtra();
57
- if (!empty($extra['installer-paths'])) {
58
- $customPath = $this->mapCustomInstallPaths($extra['installer-paths'], $prettyName, $type);
59
- if ($customPath !== false) {
60
- return $this->templatePath($customPath, $availableVars);
61
- }
62
- }
63
- }
64
-
65
- $packageType = substr($type, strlen($frameworkType) + 1);
66
- $locations = $this->getLocations();
67
- if (!isset($locations[$packageType])) {
68
- throw new \InvalidArgumentException(sprintf('Package type "%s" is not supported', $type));
69
- }
70
-
71
- return $this->templatePath($locations[$packageType], $availableVars);
72
- }
73
-
74
- /**
75
- * For an installer to override to modify the vars per installer.
76
- *
77
- * @param array $vars
78
- * @return array
79
- */
80
- public function inflectPackageVars($vars)
81
- {
82
- return $vars;
83
- }
84
-
85
- /**
86
- * Gets the installer's locations
87
- *
88
- * @return array
89
- */
90
- public function getLocations()
91
- {
92
- return $this->locations;
93
- }
94
-
95
- /**
96
- * Replace vars in a path
97
- *
98
- * @param string $path
99
- * @param array $vars
100
- * @return string
101
- */
102
- protected function templatePath($path, array $vars = array())
103
- {
104
- if (strpos($path, '{') !== false) {
105
- extract($vars);
106
- preg_match_all('@\{\$([A-Za-z0-9_]*)\}@i', $path, $matches);
107
- if (!empty($matches[1])) {
108
- foreach ($matches[1] as $var) {
109
- $path = str_replace('{$' . $var . '}', $$var, $path);
110
- }
111
- }
112
- }
113
-
114
- return $path;
115
- }
116
-
117
- /**
118
- * Search through a passed paths array for a custom install path.
119
- *
120
- * @param array $paths
121
- * @param string $name
122
- * @param string $type
123
- * @return string
124
- */
125
- protected function mapCustomInstallPaths(array $paths, $name, $type)
126
- {
127
- foreach ($paths as $path => $names) {
128
- if (in_array($name, $names) || in_array('type:' . $type, $names)) {
129
- return $path;
130
- }
131
- }
132
-
133
- return false;
134
- }
135
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/BitrixInstaller.php DELETED
@@ -1,89 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- use Composer\Util\Filesystem;
5
-
6
- /**
7
- * Installer for Bitrix Framework
8
- *
9
- * @author Nik Samokhvalov <nik@samokhvalov.info>
10
- * @author Denis Kulichkin <onexhovia@gmail.com>
11
- */
12
- class BitrixInstaller extends BaseInstaller
13
- {
14
- protected $locations = array(
15
- 'module' => 'bitrix/modules/{$name}/',
16
- 'component' => 'bitrix/components/{$name}/',
17
- 'theme' => 'bitrix/templates/{$name}/',
18
- );
19
-
20
- /**
21
- * @var array Storage for informations about duplicates at all the time of installation packages
22
- */
23
- private static $checkedDuplicates = array();
24
-
25
- /**
26
- * {@inheritdoc}
27
- */
28
- protected function templatePath($path, array $vars = array())
29
- {
30
- $templatePath = parent::templatePath($path, $vars);
31
- $this->checkDuplicates($templatePath, $vars);
32
-
33
- return $templatePath;
34
- }
35
-
36
- /**
37
- * Duplicates search packages
38
- *
39
- * @param string $templatePath
40
- * @param array $vars
41
- */
42
- protected function checkDuplicates($templatePath, array $vars = array())
43
- {
44
- /**
45
- * Incorrect paths for backward compatibility
46
- */
47
- $oldLocations = array(
48
- 'module' => 'local/modules/{$name}/',
49
- 'component' => 'local/components/{$name}/',
50
- 'theme' => 'local/templates/{$name}/'
51
- );
52
-
53
- $packageType = substr($vars['type'], strlen('bitrix') + 1);
54
- $oldLocation = str_replace('{$name}', $vars['name'], $oldLocations[$packageType]);
55
-
56
- if (in_array($oldLocation, static::$checkedDuplicates)) {
57
- return;
58
- }
59
-
60
- if ($oldLocation !== $templatePath && file_exists($oldLocation) && $this->io && $this->io->isInteractive()) {
61
-
62
- $this->io->writeError(' <error>Duplication of packages:</error>');
63
- $this->io->writeError(' <info>Package ' . $oldLocation . ' will be called instead package ' . $templatePath . '</info>');
64
-
65
- while (true) {
66
- switch ($this->io->ask(' <info>Delete ' . $oldLocation . ' [y,n,?]?</info> ', '?')) {
67
- case 'y':
68
- $fs = new Filesystem();
69
- $fs->removeDirectory($oldLocation);
70
- break 2;
71
-
72
- case 'n':
73
- break 2;
74
-
75
- case '?':
76
- default:
77
- $this->io->writeError(array(
78
- ' y - delete package ' . $oldLocation . ' and to continue with the installation',
79
- ' n - don\'t delete and to continue with the installation',
80
- ));
81
- $this->io->writeError(' ? - print help');
82
- break;
83
- }
84
- }
85
- }
86
-
87
- static::$checkedDuplicates[] = $oldLocation;
88
- }
89
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/BonefishInstaller.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class BonefishInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'package' => 'Packages/{$vendor}/{$name}/'
8
- );
9
- }
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/CakePHPInstaller.php DELETED
@@ -1,84 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- use Composer\DependencyResolver\Pool;
5
- use Composer\Package\PackageInterface;
6
-
7
- class CakePHPInstaller extends BaseInstaller
8
- {
9
- protected $locations = array(
10
- 'plugin' => 'Plugin/{$name}/',
11
- );
12
-
13
- /**
14
- * Format package name to CamelCase
15
- */
16
- public function inflectPackageVars($vars)
17
- {
18
- if ($this->matchesCakeVersion('>=', '3.0.0')) {
19
- return $vars;
20
- }
21
-
22
- $nameParts = explode('/', $vars['name']);
23
- foreach ($nameParts as &$value) {
24
- $value = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $value));
25
- $value = str_replace(array('-', '_'), ' ', $value);
26
- $value = str_replace(' ', '', ucwords($value));
27
- }
28
- $vars['name'] = implode('/', $nameParts);
29
-
30
- return $vars;
31
- }
32
-
33
- /**
34
- * Change the default plugin location when cakephp >= 3.0
35
- */
36
- public function getLocations()
37
- {
38
- if ($this->matchesCakeVersion('>=', '3.0.0')) {
39
- $this->locations['plugin'] = $this->composer->getConfig()->get('vendor-dir') . '/{$vendor}/{$name}/';
40
- }
41
- return $this->locations;
42
- }
43
-
44
- /**
45
- * Check if CakePHP version matches against a version
46
- *
47
- * @param string $matcher
48
- * @param string $version
49
- * @return bool
50
- */
51
- protected function matchesCakeVersion($matcher, $version)
52
- {
53
- if (class_exists('Composer\Semver\Constraint\MultiConstraint')) {
54
- $multiClass = 'Composer\Semver\Constraint\MultiConstraint';
55
- $constraintClass = 'Composer\Semver\Constraint\Constraint';
56
- } else {
57
- $multiClass = 'Composer\Package\LinkConstraint\MultiConstraint';
58
- $constraintClass = 'Composer\Package\LinkConstraint\VersionConstraint';
59
- }
60
-
61
- $repositoryManager = $this->composer->getRepositoryManager();
62
- if ($repositoryManager) {
63
- $repos = $repositoryManager->getLocalRepository();
64
- if (!$repos) {
65
- return false;
66
- }
67
- $cake3 = new $multiClass(array(
68
- new $constraintClass($matcher, $version),
69
- new $constraintClass('!=', '9999999-dev'),
70
- ));
71
- $pool = new Pool('dev');
72
- $pool->addRepository($repos);
73
- $packages = $pool->whatProvides('cakephp/cakephp');
74
- foreach ($packages as $package) {
75
- $installed = new $constraintClass('=', $package->getVersion());
76
- if ($cake3->matches($installed)) {
77
- return true;
78
- break;
79
- }
80
- }
81
- }
82
- return false;
83
- }
84
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/ChefInstaller.php DELETED
@@ -1,11 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class ChefInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'cookbook' => 'Chef/{$vendor}/{$name}/',
8
- 'role' => 'Chef/roles/{$name}/',
9
- );
10
- }
11
-
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php DELETED
@@ -1,10 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class ClanCatsFrameworkInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'ship' => 'CCF/orbit/{$name}/',
8
- 'theme' => 'CCF/app/themes/{$name}/',
9
- );
10
- }
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php DELETED
@@ -1,11 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class CodeIgniterInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'library' => 'application/libraries/{$name}/',
8
- 'third-party' => 'application/third_party/{$name}/',
9
- 'module' => 'application/modules/{$name}/',
10
- );
11
- }
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/Concrete5Installer.php DELETED
@@ -1,12 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class Concrete5Installer extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'block' => 'blocks/{$name}/',
8
- 'package' => 'packages/{$name}/',
9
- 'theme' => 'themes/{$name}/',
10
- 'update' => 'updates/{$name}/',
11
- );
12
- }
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/CraftInstaller.php DELETED
@@ -1,35 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- /**
5
- * Installer for Craft Plugins
6
- */
7
- class CraftInstaller extends BaseInstaller
8
- {
9
- const NAME_PREFIX = 'craft';
10
- const NAME_SUFFIX = 'plugin';
11
-
12
- protected $locations = array(
13
- 'plugin' => 'craft/plugins/{$name}/',
14
- );
15
-
16
- /**
17
- * Strip `craft-` prefix and/or `-plugin` suffix from package names
18
- *
19
- * @param array $vars
20
- *
21
- * @return array
22
- */
23
- final public function inflectPackageVars($vars)
24
- {
25
- return $this->inflectPluginVars($vars);
26
- }
27
-
28
- private function inflectPluginVars($vars)
29
- {
30
- $vars['name'] = preg_replace('/-' . self::NAME_SUFFIX . '$/i', '', $vars['name']);
31
- $vars['name'] = preg_replace('/^' . self::NAME_PREFIX . '-/i', '', $vars['name']);
32
-
33
- return $vars;
34
- }
35
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/CroogoInstaller.php DELETED
@@ -1,21 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class CroogoInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'plugin' => 'Plugin/{$name}/',
8
- 'theme' => 'View/Themed/{$name}/',
9
- );
10
-
11
- /**
12
- * Format package name to CamelCase
13
- */
14
- public function inflectPackageVars($vars)
15
- {
16
- $vars['name'] = strtolower(str_replace(array('-', '_'), ' ', $vars['name']));
17
- $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
18
-
19
- return $vars;
20
- }
21
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/DokuWikiInstaller.php DELETED
@@ -1,50 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class DokuWikiInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'plugin' => 'lib/plugins/{$name}/',
8
- 'template' => 'lib/tpl/{$name}/',
9
- );
10
-
11
- /**
12
- * Format package name.
13
- *
14
- * For package type dokuwiki-plugin, cut off a trailing '-plugin',
15
- * or leading dokuwiki_ if present.
16
- *
17
- * For package type dokuwiki-template, cut off a trailing '-template' if present.
18
- *
19
- */
20
- public function inflectPackageVars($vars)
21
- {
22
-
23
- if ($vars['type'] === 'dokuwiki-plugin') {
24
- return $this->inflectPluginVars($vars);
25
- }
26
-
27
- if ($vars['type'] === 'dokuwiki-template') {
28
- return $this->inflectTemplateVars($vars);
29
- }
30
-
31
- return $vars;
32
- }
33
-
34
- protected function inflectPluginVars($vars)
35
- {
36
- $vars['name'] = preg_replace('/-plugin$/', '', $vars['name']);
37
- $vars['name'] = preg_replace('/^dokuwiki_?-?/', '', $vars['name']);
38
-
39
- return $vars;
40
- }
41
-
42
- protected function inflectTemplateVars($vars)
43
- {
44
- $vars['name'] = preg_replace('/-template$/', '', $vars['name']);
45
- $vars['name'] = preg_replace('/^dokuwiki_?-?/', '', $vars['name']);
46
-
47
- return $vars;
48
- }
49
-
50
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/DolibarrInstaller.php DELETED
@@ -1,16 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- /**
5
- * Class DolibarrInstaller
6
- *
7
- * @package Composer\Installers
8
- * @author Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
9
- */
10
- class DolibarrInstaller extends BaseInstaller
11
- {
12
- //TODO: Add support for scripts and themes
13
- protected $locations = array(
14
- 'module' => 'htdocs/custom/{$name}/',
15
- );
16
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/DrupalInstaller.php DELETED
@@ -1,14 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class DrupalInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'core' => 'core/',
8
- 'module' => 'modules/{$name}/',
9
- 'theme' => 'themes/{$name}/',
10
- 'library' => 'libraries/{$name}/',
11
- 'profile' => 'profiles/{$name}/',
12
- 'drush' => 'drush/{$name}/',
13
- );
14
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/ElggInstaller.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class ElggInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'plugin' => 'mod/{$name}/',
8
- );
9
- }
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/FuelInstaller.php DELETED
@@ -1,11 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class FuelInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'fuel/app/modules/{$name}/',
8
- 'package' => 'fuel/packages/{$name}/',
9
- 'theme' => 'fuel/app/themes/{$name}/',
10
- );
11
- }
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/FuelphpInstaller.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class FuelphpInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'component' => 'components/{$name}/',
8
- );
9
- }
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/GravInstaller.php DELETED
@@ -1,30 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class GravInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'plugin' => 'user/plugins/{$name}/',
8
- 'theme' => 'user/themes/{$name}/',
9
- );
10
-
11
- /**
12
- * Format package name
13
- *
14
- * @param array $vars
15
- *
16
- * @return array
17
- */
18
- public function inflectPackageVars($vars)
19
- {
20
- $restrictedWords = implode('|', array_keys($this->locations));
21
-
22
- $vars['name'] = strtolower($vars['name']);
23
- $vars['name'] = preg_replace('/^(?:grav-)?(?:(?:'.$restrictedWords.')-)?(.*?)(?:-(?:'.$restrictedWords.'))?$/ui',
24
- '$1',
25
- $vars['name']
26
- );
27
-
28
- return $vars;
29
- }
30
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/HuradInstaller.php DELETED
@@ -1,25 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class HuradInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'plugin' => 'plugins/{$name}/',
8
- 'theme' => 'plugins/{$name}/',
9
- );
10
-
11
- /**
12
- * Format package name to CamelCase
13
- */
14
- public function inflectPackageVars($vars)
15
- {
16
- $nameParts = explode('/', $vars['name']);
17
- foreach ($nameParts as &$value) {
18
- $value = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $value));
19
- $value = str_replace(array('-', '_'), ' ', $value);
20
- $value = str_replace(' ', '', ucwords($value));
21
- }
22
- $vars['name'] = implode('/', $nameParts);
23
- return $vars;
24
- }
25
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/Installer.php DELETED
@@ -1,176 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- use Composer\IO\IOInterface;
5
- use Composer\Installer\LibraryInstaller;
6
- use Composer\Package\PackageInterface;
7
- use Composer\Repository\InstalledRepositoryInterface;
8
-
9
- class Installer extends LibraryInstaller
10
- {
11
- /**
12
- * Package types to installer class map
13
- *
14
- * @var array
15
- */
16
- private $supportedTypes = array(
17
- 'aimeos' => 'AimeosInstaller',
18
- 'asgard' => 'AsgardInstaller',
19
- 'agl' => 'AglInstaller',
20
- 'annotatecms' => 'AnnotateCmsInstaller',
21
- 'bitrix' => 'BitrixInstaller',
22
- 'bonefish' => 'BonefishInstaller',
23
- 'cakephp' => 'CakePHPInstaller',
24
- 'chef' => 'ChefInstaller',
25
- 'ccframework' => 'ClanCatsFrameworkInstaller',
26
- 'codeigniter' => 'CodeIgniterInstaller',
27
- 'concrete5' => 'Concrete5Installer',
28
- 'craft' => 'CraftInstaller',
29
- 'croogo' => 'CroogoInstaller',
30
- 'dokuwiki' => 'DokuWikiInstaller',
31
- 'dolibarr' => 'DolibarrInstaller',
32
- 'drupal' => 'DrupalInstaller',
33
- 'elgg' => 'ElggInstaller',
34
- 'fuel' => 'FuelInstaller',
35
- 'fuelphp' => 'FuelphpInstaller',
36
- 'grav' => 'GravInstaller',
37
- 'hurad' => 'HuradInstaller',
38
- 'joomla' => 'JoomlaInstaller',
39
- 'kirby' => 'KirbyInstaller',
40
- 'kodicms' => 'KodiCMSInstaller',
41
- 'kohana' => 'KohanaInstaller',
42
- 'laravel' => 'LaravelInstaller',
43
- 'lithium' => 'LithiumInstaller',
44
- 'magento' => 'MagentoInstaller',
45
- 'mako' => 'MakoInstaller',
46
- 'mediawiki' => 'MediaWikiInstaller',
47
- 'microweber' => 'MicroweberInstaller',
48
- 'modulework' => 'MODULEWorkInstaller',
49
- 'modxevo' => 'MODXEvoInstaller',
50
- 'moodle' => 'MoodleInstaller',
51
- 'october' => 'OctoberInstaller',
52
- 'oxid' => 'OxidInstaller',
53
- 'phpbb' => 'PhpBBInstaller',
54
- 'pimcore' => 'PimcoreInstaller',
55
- 'piwik' => 'PiwikInstaller',
56
- 'ppi' => 'PPIInstaller',
57
- 'puppet' => 'PuppetInstaller',
58
- 'redaxo' => 'RedaxoInstaller',
59
- 'roundcube' => 'RoundcubeInstaller',
60
- 'shopware' => 'ShopwareInstaller',
61
- 'silverstripe' => 'SilverStripeInstaller',
62
- 'smf' => 'SMFInstaller',
63
- 'symfony1' => 'Symfony1Installer',
64
- 'thelia' => 'TheliaInstaller',
65
- 'tusk' => 'TuskInstaller',
66
- 'typo3-cms' => 'TYPO3CmsInstaller',
67
- 'typo3-flow' => 'TYPO3FlowInstaller',
68
- 'whmcs' => 'WHMCSInstaller',
69
- 'wolfcms' => 'WolfCMSInstaller',
70
- 'wordpress' => 'WordPressInstaller',
71
- 'zend' => 'ZendInstaller',
72
- 'zikula' => 'ZikulaInstaller',
73
- 'prestashop' => 'PrestashopInstaller'
74
- );
75
-
76
- /**
77
- * {@inheritDoc}
78
- */
79
- public function getInstallPath(PackageInterface $package)
80
- {
81
- $type = $package->getType();
82
- $frameworkType = $this->findFrameworkType($type);
83
-
84
- if ($frameworkType === false) {
85
- throw new \InvalidArgumentException(
86
- 'Sorry the package type of this package is not yet supported.'
87
- );
88
- }
89
-
90
- $class = 'Composer\\Installers\\' . $this->supportedTypes[$frameworkType];
91
- $installer = new $class($package, $this->composer, $this->getIO());
92
-
93
- return $installer->getInstallPath($package, $frameworkType);
94
- }
95
-
96
- public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
97
- {
98
- if (!$repo->hasPackage($package)) {
99
- throw new \InvalidArgumentException('Package is not installed: '.$package);
100
- }
101
-
102
- $repo->removePackage($package);
103
-
104
- $installPath = $this->getInstallPath($package);
105
- $this->io->write(sprintf('Deleting %s - %s', $installPath, $this->filesystem->removeDirectory($installPath) ? '<comment>deleted</comment>' : '<error>not deleted</error>'));
106
- }
107
-
108
- /**
109
- * {@inheritDoc}
110
- */
111
- public function supports($packageType)
112
- {
113
- $frameworkType = $this->findFrameworkType($packageType);
114
-
115
- if ($frameworkType === false) {
116
- return false;
117
- }
118
-
119
- $locationPattern = $this->getLocationPattern($frameworkType);
120
-
121
- return preg_match('#' . $frameworkType . '-' . $locationPattern . '#', $packageType, $matches) === 1;
122
- }
123
-
124
- /**
125
- * Finds a supported framework type if it exists and returns it
126
- *
127
- * @param string $type
128
- * @return string
129
- */
130
- protected function findFrameworkType($type)
131
- {
132
- $frameworkType = false;
133
-
134
- krsort($this->supportedTypes);
135
-
136
- foreach ($this->supportedTypes as $key => $val) {
137
- if ($key === substr($type, 0, strlen($key))) {
138
- $frameworkType = substr($type, 0, strlen($key));
139
- break;
140
- }
141
- }
142
-
143
- return $frameworkType;
144
- }
145
-
146
- /**
147
- * Get the second part of the regular expression to check for support of a
148
- * package type
149
- *
150
- * @param string $frameworkType
151
- * @return string
152
- */
153
- protected function getLocationPattern($frameworkType)
154
- {
155
- $pattern = false;
156
- if (!empty($this->supportedTypes[$frameworkType])) {
157
- $frameworkClass = 'Composer\\Installers\\' . $this->supportedTypes[$frameworkType];
158
- /** @var BaseInstaller $framework */
159
- $framework = new $frameworkClass(null, $this->composer, $this->getIO());
160
- $locations = array_keys($framework->getLocations());
161
- $pattern = $locations ? '(' . implode('|', $locations) . ')' : false;
162
- }
163
-
164
- return $pattern ? : '(\w+)';
165
- }
166
-
167
- /**
168
- * Get I/O object
169
- *
170
- * @return IOInterface
171
- */
172
- private function getIO()
173
- {
174
- return $this->io;
175
- }
176
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/JoomlaInstaller.php DELETED
@@ -1,15 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class JoomlaInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'component' => 'components/{$name}/',
8
- 'module' => 'modules/{$name}/',
9
- 'template' => 'templates/{$name}/',
10
- 'plugin' => 'plugins/{$name}/',
11
- 'library' => 'libraries/{$name}/',
12
- );
13
-
14
- // TODO: Add inflector for mod_ and com_ names
15
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/KirbyInstaller.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class KirbyInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'plugin' => 'site/plugins/{$name}/',
8
- );
9
- }
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/KodiCMSInstaller.php DELETED
@@ -1,10 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class KodiCMSInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'plugin' => 'cms/plugins/{$name}/',
8
- 'media' => 'cms/media/vendor/{$name}/'
9
- );
10
- }
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/KohanaInstaller.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class KohanaInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'modules/{$name}/',
8
- );
9
- }
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/LaravelInstaller.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class LaravelInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'library' => 'libraries/{$name}/',
8
- );
9
- }
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/LithiumInstaller.php DELETED
@@ -1,10 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class LithiumInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'library' => 'libraries/{$name}/',
8
- 'source' => 'libraries/_source/{$name}/',
9
- );
10
- }
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class MODULEWorkInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'modules/{$name}/',
8
- );
9
- }
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/MODXEvoInstaller.php DELETED
@@ -1,16 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- /**
5
- * An installer to handle MODX Evolution specifics when installing packages.
6
- */
7
- class MODXEvoInstaller extends BaseInstaller
8
- {
9
- protected $locations = array(
10
- 'snippet' => 'assets/snippets/{$name}/',
11
- 'plugin' => 'assets/plugins/{$name}/',
12
- 'module' => 'assets/modules/{$name}/',
13
- 'template' => 'assets/templates/{$name}/',
14
- 'lib' => 'assets/lib/{$name}/'
15
- );
16
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/MagentoInstaller.php DELETED
@@ -1,11 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class MagentoInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'theme' => 'app/design/frontend/{$name}/',
8
- 'skin' => 'skin/frontend/default/{$name}/',
9
- 'library' => 'lib/{$name}/',
10
- );
11
- }
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/MakoInstaller.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class MakoInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'package' => 'app/packages/{$name}/',
8
- );
9
- }
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/MediaWikiInstaller.php DELETED
@@ -1,50 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class MediaWikiInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'extension' => 'extensions/{$name}/',
8
- 'skin' => 'skins/{$name}/',
9
- );
10
-
11
- /**
12
- * Format package name.
13
- *
14
- * For package type mediawiki-extension, cut off a trailing '-extension' if present and transform
15
- * to CamelCase keeping existing uppercase chars.
16
- *
17
- * For package type mediawiki-skin, cut off a trailing '-skin' if present.
18
- *
19
- */
20
- public function inflectPackageVars($vars)
21
- {
22
-
23
- if ($vars['type'] === 'mediawiki-extension') {
24
- return $this->inflectExtensionVars($vars);
25
- }
26
-
27
- if ($vars['type'] === 'mediawiki-skin') {
28
- return $this->inflectSkinVars($vars);
29
- }
30
-
31
- return $vars;
32
- }
33
-
34
- protected function inflectExtensionVars($vars)
35
- {
36
- $vars['name'] = preg_replace('/-extension$/', '', $vars['name']);
37
- $vars['name'] = str_replace('-', ' ', $vars['name']);
38
- $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
39
-
40
- return $vars;
41
- }
42
-
43
- protected function inflectSkinVars($vars)
44
- {
45
- $vars['name'] = preg_replace('/-skin$/', '', $vars['name']);
46
-
47
- return $vars;
48
- }
49
-
50
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/MicroweberInstaller.php DELETED
@@ -1,111 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class MicroweberInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'userfiles/modules/{$name}/',
8
- 'module-skin' => 'userfiles/modules/{$name}/templates/',
9
- 'template' => 'userfiles/templates/{$name}/',
10
- 'element' => 'userfiles/elements/{$name}/',
11
- 'vendor' => 'vendor/{$name}/',
12
- 'components' => 'components/{$name}/'
13
- );
14
-
15
- /**
16
- * Format package name.
17
- *
18
- * For package type microweber-module, cut off a trailing '-module' if present
19
- *
20
- * For package type microweber-template, cut off a trailing '-template' if present.
21
- *
22
- */
23
- public function inflectPackageVars($vars)
24
- {
25
- if ($vars['type'] === 'microweber-template') {
26
- return $this->inflectTemplateVars($vars);
27
- }
28
- if ($vars['type'] === 'microweber-templates') {
29
- return $this->inflectTemplatesVars($vars);
30
- }
31
- if ($vars['type'] === 'microweber-core') {
32
- return $this->inflectCoreVars($vars);
33
- }
34
- if ($vars['type'] === 'microweber-adapter') {
35
- return $this->inflectCoreVars($vars);
36
- }
37
- if ($vars['type'] === 'microweber-module') {
38
- return $this->inflectModuleVars($vars);
39
- }
40
- if ($vars['type'] === 'microweber-modules') {
41
- return $this->inflectModulesVars($vars);
42
- }
43
- if ($vars['type'] === 'microweber-skin') {
44
- return $this->inflectSkinVars($vars);
45
- }
46
- if ($vars['type'] === 'microweber-element' or $vars['type'] === 'microweber-elements') {
47
- return $this->inflectElementVars($vars);
48
- }
49
-
50
- return $vars;
51
- }
52
-
53
- protected function inflectTemplateVars($vars)
54
- {
55
- $vars['name'] = preg_replace('/-template$/', '', $vars['name']);
56
- $vars['name'] = preg_replace('/template-$/', '', $vars['name']);
57
-
58
- return $vars;
59
- }
60
-
61
- protected function inflectTemplatesVars($vars)
62
- {
63
- $vars['name'] = preg_replace('/-templates$/', '', $vars['name']);
64
- $vars['name'] = preg_replace('/templates-$/', '', $vars['name']);
65
-
66
- return $vars;
67
- }
68
-
69
- protected function inflectCoreVars($vars)
70
- {
71
- $vars['name'] = preg_replace('/-providers$/', '', $vars['name']);
72
- $vars['name'] = preg_replace('/-provider$/', '', $vars['name']);
73
- $vars['name'] = preg_replace('/-adapter$/', '', $vars['name']);
74
-
75
- return $vars;
76
- }
77
-
78
- protected function inflectModuleVars($vars)
79
- {
80
- $vars['name'] = preg_replace('/-module$/', '', $vars['name']);
81
- $vars['name'] = preg_replace('/module-$/', '', $vars['name']);
82
-
83
- return $vars;
84
- }
85
-
86
- protected function inflectModulesVars($vars)
87
- {
88
- $vars['name'] = preg_replace('/-modules$/', '', $vars['name']);
89
- $vars['name'] = preg_replace('/modules-$/', '', $vars['name']);
90
-
91
- return $vars;
92
- }
93
-
94
- protected function inflectSkinVars($vars)
95
- {
96
- $vars['name'] = preg_replace('/-skin$/', '', $vars['name']);
97
- $vars['name'] = preg_replace('/skin-$/', '', $vars['name']);
98
-
99
- return $vars;
100
- }
101
-
102
- protected function inflectElementVars($vars)
103
- {
104
- $vars['name'] = preg_replace('/-elements$/', '', $vars['name']);
105
- $vars['name'] = preg_replace('/elements-$/', '', $vars['name']);
106
- $vars['name'] = preg_replace('/-element$/', '', $vars['name']);
107
- $vars['name'] = preg_replace('/element-$/', '', $vars['name']);
108
-
109
- return $vars;
110
- }
111
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/MoodleInstaller.php DELETED
@@ -1,56 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class MoodleInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'mod' => 'mod/{$name}/',
8
- 'admin_report' => 'admin/report/{$name}/',
9
- 'atto' => 'lib/editor/atto/plugins/{$name}/',
10
- 'tool' => 'admin/tool/{$name}/',
11
- 'assignment' => 'mod/assignment/type/{$name}/',
12
- 'assignsubmission' => 'mod/assign/submission/{$name}/',
13
- 'assignfeedback' => 'mod/assign/feedback/{$name}/',
14
- 'auth' => 'auth/{$name}/',
15
- 'availability' => 'availability/condition/{$name}/',
16
- 'block' => 'blocks/{$name}/',
17
- 'booktool' => 'mod/book/tool/{$name}/',
18
- 'cachestore' => 'cache/stores/{$name}/',
19
- 'cachelock' => 'cache/locks/{$name}/',
20
- 'calendartype' => 'calendar/type/{$name}/',
21
- 'format' => 'course/format/{$name}/',
22
- 'coursereport' => 'course/report/{$name}/',
23
- 'datafield' => 'mod/data/field/{$name}/',
24
- 'datapreset' => 'mod/data/preset/{$name}/',
25
- 'editor' => 'lib/editor/{$name}/',
26
- 'enrol' => 'enrol/{$name}/',
27
- 'filter' => 'filter/{$name}/',
28
- 'gradeexport' => 'grade/export/{$name}/',
29
- 'gradeimport' => 'grade/import/{$name}/',
30
- 'gradereport' => 'grade/report/{$name}/',
31
- 'gradingform' => 'grade/grading/form/{$name}/',
32
- 'local' => 'local/{$name}/',
33
- 'logstore' => 'admin/tool/log/store/{$name}/',
34
- 'ltisource' => 'mod/lti/source/{$name}/',
35
- 'ltiservice' => 'mod/lti/service/{$name}/',
36
- 'message' => 'message/output/{$name}/',
37
- 'mnetservice' => 'mnet/service/{$name}/',
38
- 'plagiarism' => 'plagiarism/{$name}/',
39
- 'portfolio' => 'portfolio/{$name}/',
40
- 'qbehaviour' => 'question/behaviour/{$name}/',
41
- 'qformat' => 'question/format/{$name}/',
42
- 'qtype' => 'question/type/{$name}/',
43
- 'quizaccess' => 'mod/quiz/accessrule/{$name}/',
44
- 'quiz' => 'mod/quiz/report/{$name}/',
45
- 'report' => 'report/{$name}/',
46
- 'repository' => 'repository/{$name}/',
47
- 'scormreport' => 'mod/scorm/report/{$name}/',
48
- 'theme' => 'theme/{$name}/',
49
- 'tinymce' => 'lib/editor/tinymce/plugins/{$name}/',
50
- 'profilefield' => 'user/profile/field/{$name}/',
51
- 'webservice' => 'webservice/{$name}/',
52
- 'workshopallocation' => 'mod/workshop/allocation/{$name}/',
53
- 'workshopeval' => 'mod/workshop/eval/{$name}/',
54
- 'workshopform' => 'mod/workshop/form/{$name}/'
55
- );
56
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/OctoberInstaller.php DELETED
@@ -1,46 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class OctoberInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'modules/{$name}/',
8
- 'plugin' => 'plugins/{$vendor}/{$name}/',
9
- 'theme' => 'themes/{$name}/'
10
- );
11
-
12
- /**
13
- * Format package name.
14
- *
15
- * For package type october-plugin, cut off a trailing '-plugin' if present.
16
- *
17
- * For package type october-theme, cut off a trailing '-theme' if present.
18
- *
19
- */
20
- public function inflectPackageVars($vars)
21
- {
22
- if ($vars['type'] === 'october-plugin') {
23
- return $this->inflectPluginVars($vars);
24
- }
25
-
26
- if ($vars['type'] === 'october-theme') {
27
- return $this->inflectThemeVars($vars);
28
- }
29
-
30
- return $vars;
31
- }
32
-
33
- protected function inflectPluginVars($vars)
34
- {
35
- $vars['name'] = preg_replace('/-plugin$/', '', $vars['name']);
36
-
37
- return $vars;
38
- }
39
-
40
- protected function inflectThemeVars($vars)
41
- {
42
- $vars['name'] = preg_replace('/-theme$/', '', $vars['name']);
43
-
44
- return $vars;
45
- }
46
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/OxidInstaller.php DELETED
@@ -1,59 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- use Composer\Package\PackageInterface;
5
-
6
- class OxidInstaller extends BaseInstaller
7
- {
8
- const VENDOR_PATTERN = '/^modules\/(?P<vendor>.+)\/.+/';
9
-
10
- protected $locations = array(
11
- 'module' => 'modules/{$name}/',
12
- 'theme' => 'application/views/{$name}/',
13
- 'out' => 'out/{$name}/',
14
- );
15
-
16
- /**
17
- * getInstallPath
18
- *
19
- * @param PackageInterface $package
20
- * @param string $frameworkType
21
- * @return void
22
- */
23
- public function getInstallPath(PackageInterface $package, $frameworkType = '')
24
- {
25
- $installPath = parent::getInstallPath($package, $frameworkType);
26
- $type = $this->package->getType();
27
- if ($type === 'oxid-module') {
28
- $this->prepareVendorDirectory($installPath);
29
- }
30
- return $installPath;
31
- }
32
-
33
- /**
34
- * prepareVendorDirectory
35
- *
36
- * Makes sure there is a vendormetadata.php file inside
37
- * the vendor folder if there is a vendor folder.
38
- *
39
- * @param string $installPath
40
- * @return void
41
- */
42
- protected function prepareVendorDirectory($installPath)
43
- {
44
- $matches = '';
45
- $hasVendorDirectory = preg_match(self::VENDOR_PATTERN, $installPath, $matches);
46
- if (!$hasVendorDirectory) {
47
- return;
48
- }
49
-
50
- $vendorDirectory = $matches['vendor'];
51
- $vendorPath = getcwd() . '/modules/' . $vendorDirectory;
52
- if (!file_exists($vendorPath)) {
53
- mkdir($vendorPath, 0755, true);
54
- }
55
-
56
- $vendorMetaDataPath = $vendorPath . '/vendormetadata.php';
57
- touch($vendorMetaDataPath);
58
- }
59
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/PPIInstaller.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class PPIInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'modules/{$name}/',
8
- );
9
- }
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/PhpBBInstaller.php DELETED
@@ -1,11 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class PhpBBInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'extension' => 'ext/{$vendor}/{$name}/',
8
- 'language' => 'language/{$name}/',
9
- 'style' => 'styles/{$name}/',
10
- );
11
- }
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/PimcoreInstaller.php DELETED
@@ -1,21 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class PimcoreInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'plugin' => 'plugins/{$name}/',
8
- );
9
-
10
- /**
11
- * Format package name to CamelCase
12
- */
13
- public function inflectPackageVars($vars)
14
- {
15
- $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name']));
16
- $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
17
- $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
18
-
19
- return $vars;
20
- }
21
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/PiwikInstaller.php DELETED
@@ -1,32 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- /**
5
- * Class PiwikInstaller
6
- *
7
- * @package Composer\Installers
8
- */
9
- class PiwikInstaller extends BaseInstaller
10
- {
11
- /**
12
- * @var array
13
- */
14
- protected $locations = array(
15
- 'plugin' => 'plugins/{$name}/',
16
- );
17
-
18
- /**
19
- * Format package name to CamelCase
20
- * @param array $vars
21
- *
22
- * @return array
23
- */
24
- public function inflectPackageVars($vars)
25
- {
26
- $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name']));
27
- $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
28
- $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
29
-
30
- return $vars;
31
- }
32
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/Plugin.php DELETED
@@ -1,17 +0,0 @@
1
- <?php
2
-
3
- namespace Composer\Installers;
4
-
5
- use Composer\Composer;
6
- use Composer\IO\IOInterface;
7
- use Composer\Plugin\PluginInterface;
8
-
9
- class Plugin implements PluginInterface
10
- {
11
-
12
- public function activate(Composer $composer, IOInterface $io)
13
- {
14
- $installer = new Installer($io, $composer);
15
- $composer->getInstallationManager()->addInstaller($installer);
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/PrestashopInstaller.php DELETED
@@ -1,10 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class PrestashopInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'modules/{$name}/',
8
- 'theme' => 'themes/{$name}/',
9
- );
10
- }
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/PuppetInstaller.php DELETED
@@ -1,11 +0,0 @@
1
- <?php
2
-
3
- namespace Composer\Installers;
4
-
5
- class PuppetInstaller extends BaseInstaller
6
- {
7
-
8
- protected $locations = array(
9
- 'module' => 'modules/{$name}/',
10
- );
11
- }
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/RedaxoInstaller.php DELETED
@@ -1,10 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class RedaxoInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'addon' => 'redaxo/include/addons/{$name}/',
8
- 'bestyle-plugin' => 'redaxo/include/addons/be_style/plugins/{$name}/'
9
- );
10
- }
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/RoundcubeInstaller.php DELETED
@@ -1,22 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class RoundcubeInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'plugin' => 'plugins/{$name}/',
8
- );
9
-
10
- /**
11
- * Lowercase name and changes the name to a underscores
12
- *
13
- * @param array $vars
14
- * @return array
15
- */
16
- public function inflectPackageVars($vars)
17
- {
18
- $vars['name'] = strtolower(str_replace('-', '_', $vars['name']));
19
-
20
- return $vars;
21
- }
22
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/SMFInstaller.php DELETED
@@ -1,10 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class SMFInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'Sources/{$name}/',
8
- 'theme' => 'Themes/{$name}/',
9
- );
10
- }
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/ShopwareInstaller.php DELETED
@@ -1,58 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- /**
5
- * Plugin/theme installer for shopware
6
- * @author Benjamin Boit
7
- */
8
- class ShopwareInstaller extends BaseInstaller
9
- {
10
- protected $locations = array(
11
- 'backend-plugin' => 'engine/Shopware/Plugins/Local/Backend/{$name}/',
12
- 'core-plugin' => 'engine/Shopware/Plugins/Local/Core/{$name}/',
13
- 'frontend-plugin' => 'engine/Shopware/Plugins/Local/Frontend/{$name}/',
14
- 'theme' => 'templates/{$name}/'
15
- );
16
-
17
- /**
18
- * Transforms the names
19
- * @param array $vars
20
- * @return array
21
- */
22
- public function inflectPackageVars($vars)
23
- {
24
- if ($vars['type'] === 'shopware-theme') {
25
- return $this->correctThemeName($vars);
26
- } else {
27
- return $this->correctPluginName($vars);
28
- }
29
- }
30
-
31
- /**
32
- * Changes the name to a camelcased combination of vendor and name
33
- * @param array $vars
34
- * @return array
35
- */
36
- private function correctPluginName($vars)
37
- {
38
- $camelCasedName = preg_replace_callback('/(-[a-z])/', function ($matches) {
39
- return strtoupper($matches[0][1]);
40
- }, $vars['name']);
41
-
42
- $vars['name'] = ucfirst($vars['vendor']) . ucfirst($camelCasedName);
43
-
44
- return $vars;
45
- }
46
-
47
- /**
48
- * Changes the name to a underscore separated name
49
- * @param array $vars
50
- * @return array
51
- */
52
- private function correctThemeName($vars)
53
- {
54
- $vars['name'] = str_replace('-', '_', $vars['name']);
55
-
56
- return $vars;
57
- }
58
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/SilverStripeInstaller.php DELETED
@@ -1,36 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- use Composer\Package\PackageInterface;
5
-
6
- class SilverStripeInstaller extends BaseInstaller
7
- {
8
- protected $locations = array(
9
- 'module' => '{$name}/',
10
- 'theme' => 'themes/{$name}/',
11
- );
12
-
13
- /**
14
- * Return the install path based on package type.
15
- *
16
- * Relies on built-in BaseInstaller behaviour with one exception: silverstripe/framework
17
- * must be installed to 'sapphire' and not 'framework' if the version is <3.0.0
18
- *
19
- * @param PackageInterface $package
20
- * @param string $frameworkType
21
- * @return string
22
- */
23
- public function getInstallPath(PackageInterface $package, $frameworkType = '')
24
- {
25
- if (
26
- $package->getName() == 'silverstripe/framework'
27
- && preg_match('/^\d+\.\d+\.\d+/', $package->getVersion())
28
- && version_compare($package->getVersion(), '2.999.999') < 0
29
- ) {
30
- return $this->templatePath($this->locations['module'], array('name' => 'sapphire'));
31
- } else {
32
- return parent::getInstallPath($package, $frameworkType);
33
- }
34
-
35
- }
36
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/Symfony1Installer.php DELETED
@@ -1,26 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- /**
5
- * Plugin installer for symfony 1.x
6
- *
7
- * @author Jérôme Tamarelle <jerome@tamarelle.net>
8
- */
9
- class Symfony1Installer extends BaseInstaller
10
- {
11
- protected $locations = array(
12
- 'plugin' => 'plugins/{$name}/',
13
- );
14
-
15
- /**
16
- * Format package name to CamelCase
17
- */
18
- public function inflectPackageVars($vars)
19
- {
20
- $vars['name'] = preg_replace_callback('/(-[a-z])/', function ($matches) {
21
- return strtoupper($matches[0][1]);
22
- }, $vars['name']);
23
-
24
- return $vars;
25
- }
26
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php DELETED
@@ -1,14 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- /**
5
- * Extension installer for TYPO3 CMS
6
- *
7
- * @author Sascha Egerer <sascha.egerer@dkd.de>
8
- */
9
- class TYPO3CmsInstaller extends BaseInstaller
10
- {
11
- protected $locations = array(
12
- 'extension' => 'typo3conf/ext/{$name}/',
13
- );
14
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php DELETED
@@ -1,38 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- /**
5
- * An installer to handle TYPO3 Flow specifics when installing packages.
6
- */
7
- class TYPO3FlowInstaller extends BaseInstaller
8
- {
9
- protected $locations = array(
10
- 'package' => 'Packages/Application/{$name}/',
11
- 'framework' => 'Packages/Framework/{$name}/',
12
- 'plugin' => 'Packages/Plugins/{$name}/',
13
- 'site' => 'Packages/Sites/{$name}/',
14
- 'boilerplate' => 'Packages/Boilerplates/{$name}/',
15
- 'build' => 'Build/{$name}/',
16
- );
17
-
18
- /**
19
- * Modify the package name to be a TYPO3 Flow style key.
20
- *
21
- * @param array $vars
22
- * @return array
23
- */
24
- public function inflectPackageVars($vars)
25
- {
26
- $autoload = $this->package->getAutoload();
27
- if (isset($autoload['psr-0']) && is_array($autoload['psr-0'])) {
28
- $namespace = key($autoload['psr-0']);
29
- $vars['name'] = str_replace('\\', '.', $namespace);
30
- }
31
- if (isset($autoload['psr-4']) && is_array($autoload['psr-4'])) {
32
- $namespace = key($autoload['psr-4']);
33
- $vars['name'] = rtrim(str_replace('\\', '.', $namespace), '.');
34
- }
35
-
36
- return $vars;
37
- }
38
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/TheliaInstaller.php DELETED
@@ -1,12 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class TheliaInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'local/modules/{$name}/',
8
- 'frontoffice-template' => 'templates/frontOffice/{$name}/',
9
- 'backoffice-template' => 'templates/backOffice/{$name}/',
10
- 'email-template' => 'templates/email/{$name}/',
11
- );
12
- }
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/TuskInstaller.php DELETED
@@ -1,14 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
- /**
4
- * Composer installer for 3rd party Tusk utilities
5
- * @author Drew Ewing <drew@phenocode.com>
6
- */
7
- class TuskInstaller extends BaseInstaller
8
- {
9
- protected $locations = array(
10
- 'task' => '.tusk/tasks/{$name}/',
11
- 'command' => '.tusk/commands/{$name}/',
12
- 'asset' => 'assets/tusk/{$name}/',
13
- );
14
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/WHMCSInstaller.php DELETED
@@ -1,10 +0,0 @@
1
- <?php
2
-
3
- namespace Composer\Installers;
4
-
5
- class WHMCSInstaller extends BaseInstaller
6
- {
7
- protected $locations = array(
8
- 'gateway' => 'modules/gateways/{$name}/',
9
- );
10
- }
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/WolfCMSInstaller.php DELETED
@@ -1,9 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class WolfCMSInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'plugin' => 'wolf/plugins/{$name}/',
8
- );
9
- }
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/WordPressInstaller.php DELETED
@@ -1,11 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class WordPressInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'plugin' => 'wp-content/plugins/{$name}/',
8
- 'theme' => 'wp-content/themes/{$name}/',
9
- 'muplugin' => 'wp-content/mu-plugins/{$name}/',
10
- );
11
- }
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/ZendInstaller.php DELETED
@@ -1,11 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class ZendInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'library' => 'library/{$name}/',
8
- 'extra' => 'extras/library/{$name}/',
9
- 'module' => 'module/{$name}/',
10
- );
11
- }
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/Composer/Installers/ZikulaInstaller.php DELETED
@@ -1,10 +0,0 @@
1
- <?php
2
- namespace Composer\Installers;
3
-
4
- class ZikulaInstaller extends BaseInstaller
5
- {
6
- protected $locations = array(
7
- 'module' => 'modules/{$vendor}-{$name}/',
8
- 'theme' => 'themes/{$vendor}-{$name}/'
9
- );
10
- }
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/src/bootstrap.php DELETED
@@ -1,13 +0,0 @@
1
- <?php
2
- function includeIfExists($file)
3
- {
4
- if (file_exists($file)) {
5
- return include $file;
6
- }
7
- }
8
- if ((!$loader = includeIfExists(__DIR__ . '/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__ . '/../../../autoload.php'))) {
9
- die('You must set up the project dependencies, run the following commands:'.PHP_EOL.
10
- 'curl -s http://getcomposer.org/installer | php'.PHP_EOL.
11
- 'php composer.phar install'.PHP_EOL);
12
- }
13
- return $loader;
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/Composer/Installers/Test/AsgardInstallerTest.php DELETED
@@ -1,61 +0,0 @@
1
- <?php
2
- namespace Composer\Installers\Test;
3
-
4
- use Composer\Installers\AsgardInstaller;
5
- use Composer\Package\Package;
6
- use Composer\Composer;
7
-
8
- class AsgardInstallerTest extends \PHPUnit_Framework_TestCase
9
- {
10
- /**
11
- * @var OctoberInstaller
12
- */
13
- private $installer;
14
-
15
- public function setUp()
16
- {
17
- $this->installer = new AsgardInstaller(
18
- new Package('NyanCat', '4.2', '4.2'),
19
- new Composer()
20
- );
21
- }
22
-
23
- /**
24
- * @dataProvider packageNameInflectionProvider
25
- */
26
- public function testInflectPackageVars($type, $name, $expected)
27
- {
28
- $this->assertEquals(
29
- $this->installer->inflectPackageVars(array('name' => $name, 'type' => $type)),
30
- array('name' => $expected, 'type' => $type)
31
- );
32
- }
33
-
34
- public function packageNameInflectionProvider()
35
- {
36
- return array(
37
- array(
38
- 'asgard-module',
39
- 'asgard-module',
40
- 'Asgard'
41
- ),
42
- array(
43
- 'asgard-module',
44
- 'blog',
45
- 'Blog'
46
- ),
47
- // tests that exactly one '-theme' is cut off
48
- array(
49
- 'asgard-theme',
50
- 'some-theme-theme',
51
- 'Some-theme',
52
- ),
53
- // tests that names without '-theme' suffix stay valid
54
- array(
55
- 'asgard-theme',
56
- 'someothertheme',
57
- 'Someothertheme',
58
- ),
59
- );
60
- }
61
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/Composer/Installers/Test/CakePHPInstallerTest.php DELETED
@@ -1,115 +0,0 @@
1
- <?php
2
- namespace Composer\Installers\Test;
3
-
4
- use Composer\Installers\CakePHPInstaller;
5
- use Composer\Repository\RepositoryManager;
6
- use Composer\Repository\InstalledArrayRepository;
7
- use Composer\Package\Package;
8
- use Composer\Package\RootPackage;
9
- use Composer\Package\Link;
10
- use Composer\Package\Version\VersionParser;
11
- use Composer\Composer;
12
- use Composer\Config;
13
-
14
- class CakePHPInstallerTest extends TestCase
15
- {
16
- private $composer;
17
- private $io;
18
-
19
- /**
20
- * setUp
21
- *
22
- * @return void
23
- */
24
- public function setUp()
25
- {
26
- $this->package = new Package('CamelCased', '1.0', '1.0');
27
- $this->io = $this->getMock('Composer\IO\PackageInterface');
28
- $this->composer = new Composer();
29
- $this->composer->setConfig(new Config(false));
30
- }
31
-
32
- /**
33
- * testInflectPackageVars
34
- *
35
- * @return void
36
- */
37
- public function testInflectPackageVars()
38
- {
39
- $installer = new CakePHPInstaller($this->package, $this->composer);
40
- $result = $installer->inflectPackageVars(array('name' => 'CamelCased'));
41
- $this->assertEquals($result, array('name' => 'CamelCased'));
42
-
43
- $installer = new CakePHPInstaller($this->package, $this->composer);
44
- $result = $installer->inflectPackageVars(array('name' => 'with-dash'));
45
- $this->assertEquals($result, array('name' => 'WithDash'));
46
-
47
- $installer = new CakePHPInstaller($this->package, $this->composer);
48
- $result = $installer->inflectPackageVars(array('name' => 'with_underscore'));
49
- $this->assertEquals($result, array('name' => 'WithUnderscore'));
50
-
51
- $installer = new CakePHPInstaller($this->package, $this->composer);
52
- $result = $installer->inflectPackageVars(array('name' => 'cake/acl'));
53
- $this->assertEquals($result, array('name' => 'Cake/Acl'));
54
-
55
- $installer = new CakePHPInstaller($this->package, $this->composer);
56
- $result = $installer->inflectPackageVars(array('name' => 'cake/debug-kit'));
57
- $this->assertEquals($result, array('name' => 'Cake/DebugKit'));
58
- }
59
-
60
- /**
61
- * Test getLocations returning appropriate values based on CakePHP version
62
- *
63
- */
64
- public function testGetLocations() {
65
- $package = new RootPackage('CamelCased', '1.0', '1.0');
66
- $composer = $this->composer;
67
- $rm = new RepositoryManager(
68
- $this->getMock('Composer\IO\IOInterface'),
69
- $this->getMock('Composer\Config')
70
- );
71
- $composer->setRepositoryManager($rm);
72
- $installer = new CakePHPInstaller($package, $composer);
73
-
74
- // 2.0 < cakephp < 3.0
75
- $this->setCakephpVersion($rm, '2.0.0');
76
- $result = $installer->getLocations();
77
- $this->assertContains('Plugin/', $result['plugin']);
78
-
79
- $this->setCakephpVersion($rm, '2.5.9');
80
- $result = $installer->getLocations();
81
- $this->assertContains('Plugin/', $result['plugin']);
82
-
83
- $this->setCakephpVersion($rm, '~2.5');
84
- $result = $installer->getLocations();
85
- $this->assertContains('Plugin/', $result['plugin']);
86
-
87
- // special handling for 2.x versions when 3.x is still in development
88
- $this->setCakephpVersion($rm, 'dev-master');
89
- $result = $installer->getLocations();
90
- $this->assertContains('Plugin/', $result['plugin']);
91
-
92
- $this->setCakephpVersion($rm, '>=2.5');
93
- $result = $installer->getLocations();
94
- $this->assertContains('Plugin/', $result['plugin']);
95
-
96
- // cakephp >= 3.0
97
- $this->setCakephpVersion($rm, '3.0.*-dev');
98
- $result = $installer->getLocations();
99
- $this->assertContains('vendor/{$vendor}/{$name}/', $result['plugin']);
100
-
101
- $this->setCakephpVersion($rm, '~8.8');
102
- $result = $installer->getLocations();
103
- $this->assertContains('vendor/{$vendor}/{$name}/', $result['plugin']);
104
- }
105
-
106
- protected function setCakephpVersion($rm, $version) {
107
- $parser = new VersionParser();
108
- list(, $version) = explode(' ', $parser->parseConstraints($version));
109
- $installed = new InstalledArrayRepository();
110
- $package = new Package('cakephp/cakephp', $version, $version);
111
- $installed->addPackage($package);
112
- $rm->setLocalRepository($installed);
113
- }
114
-
115
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/Composer/Installers/Test/CraftInstallerTest.php DELETED
@@ -1,83 +0,0 @@
1
- <?php
2
-
3
- namespace Composer\Installers\Test;
4
-
5
- use Composer\Installers\CraftInstaller;
6
-
7
- /**
8
- * Tests for the CraftInstaller Class
9
- *
10
- * @coversDefaultClass Composer\Installers\CraftInstaller
11
- */
12
- class CraftInstallerTest extends TestCase
13
- {
14
- /** @var CraftInstaller */
15
- private $installer;
16
-
17
- /**
18
- * Sets up the fixture, for example, instantiate the class-under-test.
19
- *
20
- * This method is called before a test is executed.
21
- */
22
- final public function setup()
23
- {
24
- $this->installer = new CraftInstaller();
25
- }
26
-
27
- /**
28
- * @param string $packageName
29
- * @param string $expectedName
30
- *
31
- * @covers ::inflectPackageVars
32
- *
33
- * @dataProvider provideExpectedInflectionResults
34
- */
35
- final public function testInflectPackageVars($packageName, $expectedName)
36
- {
37
- $installer = $this->installer;
38
-
39
- $vars = array('name' => $packageName);
40
- $expected = array('name' => $expectedName);
41
-
42
- $actual = $installer->inflectPackageVars($vars);
43
-
44
- $this->assertEquals($actual, $expected);
45
- }
46
-
47
- /**
48
- * Provides various names for packages and the expected result after inflection
49
- *
50
- * @return array
51
- */
52
- final public function provideExpectedInflectionResults()
53
- {
54
- return array(
55
- // lowercase
56
- array('foo', 'foo'),
57
- array('craftfoo', 'craftfoo'),
58
- array('fooplugin', 'fooplugin'),
59
- array('craftfooplugin', 'craftfooplugin'),
60
- // lowercase - dash
61
- array('craft-foo', 'foo'),
62
- array('foo-plugin', 'foo'),
63
- array('craft-foo-plugin', 'foo'),
64
- // lowercase - underscore
65
- array('craft_foo', 'craft_foo'),
66
- array('foo_plugin', 'foo_plugin'),
67
- array('craft_foo_plugin', 'craft_foo_plugin'),
68
- // CamelCase
69
- array('Foo', 'Foo'),
70
- array('CraftFoo', 'CraftFoo'),
71
- array('FooPlugin', 'FooPlugin'),
72
- array('CraftFooPlugin', 'CraftFooPlugin'),
73
- // CamelCase - Dash
74
- array('Craft-Foo', 'Foo'),
75
- array('Foo-Plugin', 'Foo'),
76
- array('Craft-Foo-Plugin', 'Foo'),
77
- // CamelCase - underscore
78
- array('Craft_Foo', 'Craft_Foo'),
79
- array('Foo_Plugin', 'Foo_Plugin'),
80
- array('Craft_Foo_Plugin', 'Craft_Foo_Plugin'),
81
- );
82
- }
83
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/Composer/Installers/Test/DokuWikiInstallerTest.php DELETED
@@ -1,89 +0,0 @@
1
- <?php
2
- namespace Composer\Installers\Test;
3
-
4
- use Composer\Installers\DokuWikiInstaller;
5
- use Composer\Package\Package;
6
- use Composer\Composer;
7
-
8
- class DokuWikiInstallerTest extends \PHPUnit_Framework_TestCase
9
- {
10
- /**
11
- * @var DokuWikiInstaller
12
- */
13
- private $installer;
14
-
15
- public function setUp()
16
- {
17
- $this->installer = new DokuWikiInstaller(
18
- new Package('NyanCat', '4.2', '4.2'),
19
- new Composer()
20
- );
21
- }
22
-
23
- /**
24
- * @dataProvider packageNameInflectionProvider
25
- */
26
- public function testInflectPackageVars($type, $name, $expected)
27
- {
28
- $this->assertEquals(
29
- $this->installer->inflectPackageVars(array('name' => $name, 'type'=>$type)),
30
- array('name' => $expected, 'type'=>$type)
31
- );
32
- }
33
-
34
- public function packageNameInflectionProvider()
35
- {
36
- return array(
37
- array(
38
- 'dokuwiki-plugin',
39
- 'dokuwiki-test-plugin',
40
- 'test',
41
- ),
42
- array(
43
- 'dokuwiki-plugin',
44
- 'test-plugin',
45
- 'test',
46
- ),
47
- array(
48
- 'dokuwiki-plugin',
49
- 'dokuwiki_test',
50
- 'test',
51
- ),
52
- array(
53
- 'dokuwiki-plugin',
54
- 'test',
55
- 'test',
56
- ),
57
- array(
58
- 'dokuwiki-plugin',
59
- 'test-template',
60
- 'test-template',
61
- ),
62
- array(
63
- 'dokuwiki-template',
64
- 'dokuwiki-test-template',
65
- 'test',
66
- ),
67
- array(
68
- 'dokuwiki-template',
69
- 'test-template',
70
- 'test',
71
- ),
72
- array(
73
- 'dokuwiki-template',
74
- 'dokuwiki_test',
75
- 'test',
76
- ),
77
- array(
78
- 'dokuwiki-template',
79
- 'test',
80
- 'test',
81
- ),
82
- array(
83
- 'dokuwiki-template',
84
- 'test-plugin',
85
- 'test-plugin',
86
- ),
87
- );
88
- }
89
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/Composer/Installers/Test/GravInstallerTest.php DELETED
@@ -1,63 +0,0 @@
1
- <?php
2
- namespace Composer\Installers\Test;
3
-
4
- use Composer\Composer;
5
- use Composer\Installers\GravInstaller;
6
-
7
- class GravInstallerTest extends TestCase
8
- {
9
- /* @var \Composer\Composer */
10
- protected $composer;
11
-
12
- public function setUp()
13
- {
14
- $this->composer = new Composer();
15
- }
16
-
17
- public function testInflectPackageVars()
18
- {
19
- $package = $this->getPackage('vendor/name', '0.0.0');
20
- $installer = new GravInstaller($package, $this->composer);
21
- $packageVars = $this->getPackageVars($package);
22
-
23
- $result = $installer->inflectPackageVars(array_merge($packageVars, array('name' => 'test')));
24
- $this->assertEquals('test', $result['name']);
25
-
26
- foreach ($installer->getLocations() as $name => $location) {
27
- $result = $installer->inflectPackageVars(array_merge($packageVars, array('name' => "$name-test")));
28
- $this->assertEquals('test', $result['name']);
29
- $result = $installer->inflectPackageVars(array_merge($packageVars, array('name' => "test-$name")));
30
- $this->assertEquals('test', $result['name']);
31
- $result = $installer->inflectPackageVars(array_merge($packageVars, array('name' => "$name-test-test")));
32
- $this->assertEquals('test-test', $result['name']);
33
- $result = $installer->inflectPackageVars(array_merge($packageVars, array('name' => "test-test-$name")));
34
- $this->assertEquals('test-test', $result['name']);
35
- $result = $installer->inflectPackageVars(array_merge($packageVars, array('name' => "grav-$name-test")));
36
- $this->assertEquals('test', $result['name']);
37
- $result = $installer->inflectPackageVars(array_merge($packageVars, array('name' => "grav-test-$name")));
38
- $this->assertEquals('test', $result['name']);
39
- $result = $installer->inflectPackageVars(array_merge($packageVars, array('name' => "grav-$name-test-test")));
40
- $this->assertEquals('test-test', $result['name']);
41
- $result = $installer->inflectPackageVars(array_merge($packageVars, array('name' => "grav-test-test-$name")));
42
- $this->assertEquals('test-test', $result['name']);
43
- }
44
- }
45
-
46
- /**
47
- * @param $package \Composer\Package\PackageInterface
48
- */
49
- public function getPackageVars($package)
50
- {
51
- $type = $package->getType();
52
-
53
- $prettyName = $package->getPrettyName();
54
- if (strpos($prettyName, '/') !== false) {
55
- list($vendor, $name) = explode('/', $prettyName);
56
- } else {
57
- $vendor = '';
58
- $name = $prettyName;
59
- }
60
-
61
- return compact('name', 'vendor', 'type');
62
- }
63
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/Composer/Installers/Test/InstallerTest.php DELETED
@@ -1,428 +0,0 @@
1
- <?php
2
- namespace Composer\Installers\Test;
3
-
4
- use Composer\Installers\Installer;
5
- use Composer\Util\Filesystem;
6
- use Composer\Package\Package;
7
- use Composer\Package\RootPackage;
8
- use Composer\Composer;
9
- use Composer\Config;
10
-
11
- class InstallerTest extends TestCase
12
- {
13
- private $composer;
14
- private $config;
15
- private $vendorDir;
16
- private $binDir;
17
- private $dm;
18
- private $repository;
19
- private $io;
20
- private $fs;
21
-
22
- /**
23
- * setUp
24
- *
25
- * @return void
26
- */
27
- public function setUp()
28
- {
29
- $this->fs = new Filesystem;
30
-
31
- $this->composer = new Composer();
32
- $this->config = new Config();
33
- $this->composer->setConfig($this->config);
34
-
35
- $this->vendorDir = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . 'baton-test-vendor';
36
- $this->ensureDirectoryExistsAndClear($this->vendorDir);
37
-
38
- $this->binDir = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . 'baton-test-bin';
39
- $this->ensureDirectoryExistsAndClear($this->binDir);
40
-
41
- $this->config->merge(array(
42
- 'config' => array(
43
- 'vendor-dir' => $this->vendorDir,
44
- 'bin-dir' => $this->binDir,
45
- ),
46
- ));
47
-
48
- $this->dm = $this->getMockBuilder('Composer\Downloader\DownloadManager')
49
- ->disableOriginalConstructor()
50
- ->getMock();
51
- $this->composer->setDownloadManager($this->dm);
52
-
53
- $this->repository = $this->getMock('Composer\Repository\InstalledRepositoryInterface');
54
- $this->io = $this->getMock('Composer\IO\IOInterface');
55
- }
56
-
57
- /**
58
- * tearDown
59
- *
60
- * @return void
61
- */
62
- public function tearDown()
63
- {
64
- $this->fs->removeDirectory($this->vendorDir);
65
- $this->fs->removeDirectory($this->binDir);
66
- }
67
-
68
- /**
69
- * testSupports
70
- *
71
- * @return void
72
- *
73
- * @dataProvider dataForTestSupport
74
- */
75
- public function testSupports($type, $expected)
76
- {
77
- $installer = new Installer($this->io, $this->composer);
78
- $this->assertSame($expected, $installer->supports($type), sprintf('Failed to show support for %s', $type));
79
- }
80
-
81
- /**
82
- * dataForTestSupport
83
- */
84
- public function dataForTestSupport()
85
- {
86
- return array(
87
- array('agl-module', true),
88
- array('aimeos-extension', true),
89
- array('annotatecms-module', true),
90
- array('annotatecms-component', true),
91
- array('annotatecms-service', true),
92
- array('bitrix-module', true),
93
- array('bitrix-component', true),
94
- array('bitrix-theme', true),
95
- array('bonefish-package', true),
96
- array('cakephp', false),
97
- array('cakephp-', false),
98
- array('cakephp-app', false),
99
- array('cakephp-plugin', true),
100
- array('chef-cookbook', true),
101
- array('chef-role', true),
102
- array('codeigniter-app', false),
103
- array('codeigniter-library', true),
104
- array('codeigniter-third-party', true),
105
- array('codeigniter-module', true),
106
- array('concrete5-block', true),
107
- array('concrete5-package', true),
108
- array('concrete5-theme', true),
109
- array('concrete5-update', true),
110
- array('craft-plugin', true),
111
- array('croogo-plugin', true),
112
- array('croogo-theme', true),
113
- array('dokuwiki-plugin', true),
114
- array('dokuwiki-template', true),
115
- array('drupal-module', true),
116
- array('dolibarr-module', true),
117
- array('elgg-plugin', true),
118
- array('fuel-module', true),
119
- array('fuel-package', true),
120
- array('fuel-theme', true),
121
- array('fuelphp-component', true),
122
- array('hurad-plugin', true),
123
- array('hurad-theme', true),
124
- array('joomla-library', true),
125
- array('kirby-plugin', true),
126
- array('kohana-module', true),
127
- array('laravel-library', true),
128
- array('lithium-library', true),
129
- array('magento-library', true),
130
- array('mako-package', true),
131
- array('modxevo-snippet', true),
132
- array('modxevo-plugin', true),
133
- array('modxevo-module', true),
134
- array('modxevo-template', true),
135
- array('modxevo-lib', true),
136
- array('mediawiki-extension', true),
137
- array('mediawiki-skin', true),
138
- array('microweber-module', true),
139
- array('modulework-module', true),
140
- array('moodle-mod', true),
141
- array('october-module', true),
142
- array('october-plugin', true),
143
- array('piwik-plugin', true),
144
- array('phpbb-extension', true),
145
- array('pimcore-plugin', true),
146
- array('ppi-module', true),
147
- array('prestashop-module', true),
148
- array('prestashop-theme', true),
149
- array('puppet-module', true),
150
- array('redaxo-addon', true),
151
- array('redaxo-bestyle-plugin', true),
152
- array('roundcube-plugin', true),
153
- array('shopware-backend-plugin', true),
154
- array('shopware-core-plugin', true),
155
- array('shopware-frontend-plugin', true),
156
- array('shopware-theme', true),
157
- array('silverstripe-module', true),
158
- array('silverstripe-theme', true),
159
- array('smf-module', true),
160
- array('smf-theme', true),
161
- array('symfony1-plugin', true),
162
- array('thelia-module', true),
163
- array('thelia-frontoffice-template', true),
164
- array('thelia-backoffice-template', true),
165
- array('thelia-email-template', true),
166
- array('tusk-task', true),
167
- array('tusk-asset', true),
168
- array('typo3-flow-plugin', true),
169
- array('typo3-cms-extension', true),
170
- array('whmcs-gateway', true),
171
- array('wolfcms-plugin', true),
172
- array('wordpress-plugin', true),
173
- array('wordpress-core', false),
174
- array('zend-library', true),
175
- array('zikula-module', true),
176
- array('zikula-theme', true),
177
- array('kodicms-plugin', true),
178
- array('kodicms-media', true),
179
- );
180
- }
181
-
182
- /**
183
- * testInstallPath
184
- *
185
- * @dataProvider dataForTestInstallPath
186
- */
187
- public function testInstallPath($type, $path, $name, $version = '1.0.0')
188
- {
189
- $installer = new Installer($this->io, $this->composer);
190
- $package = new Package($name, $version, $version);
191
-
192
- $package->setType($type);
193
- $result = $installer->getInstallPath($package);
194
- $this->assertEquals($path, $result);
195
- }
196
-
197
- /**
198
- * dataFormTestInstallPath
199
- */
200
- public function dataForTestInstallPath()
201
- {
202
- return array(
203
- array('agl-module', 'More/MyTestPackage/', 'agl/my_test-package'),
204
- array('aimeos-extension', 'ext/ai-test/', 'author/ai-test'),
205
- array('annotatecms-module', 'addons/modules/my_module/', 'vysinsky/my_module'),
206
- array('annotatecms-component', 'addons/components/my_component/', 'vysinsky/my_component'),
207
- array('annotatecms-service', 'addons/services/my_service/', 'vysinsky/my_service'),
208
- array('bitrix-module', 'bitrix/modules/my_module/', 'author/my_module'),
209
- array('bitrix-component', 'bitrix/components/my_component/', 'author/my_component'),
210
- array('bitrix-theme', 'bitrix/templates/my_theme/', 'author/my_theme'),
211
- array('bonefish-package', 'Packages/bonefish/package/', 'bonefish/package'),
212
- array('cakephp-plugin', 'Plugin/Ftp/', 'shama/ftp'),
213
- array('chef-cookbook', 'Chef/mre/my_cookbook/', 'mre/my_cookbook'),
214
- array('chef-role', 'Chef/roles/my_role/', 'mre/my_role'),
215
- array('codeigniter-library', 'application/libraries/my_package/', 'shama/my_package'),
216
- array('codeigniter-module', 'application/modules/my_package/', 'shama/my_package'),
217
- array('concrete5-block', 'blocks/concrete5_block/', 'remo/concrete5_block'),
218
- array('concrete5-package', 'packages/concrete5_package/', 'remo/concrete5_package'),
219
- array('concrete5-theme', 'themes/concrete5_theme/', 'remo/concrete5_theme'),
220
- array('concrete5-update', 'updates/concrete5/', 'concrete5/concrete5'),
221
- array('craft-plugin', 'craft/plugins/my_plugin/', 'mdcpepper/my_plugin'),
222
- array('croogo-plugin', 'Plugin/Sitemaps/', 'fahad19/sitemaps'),
223
- array('croogo-theme', 'View/Themed/Readable/', 'rchavik/readable'),
224
- array('dokuwiki-plugin', 'lib/plugins/someplugin/', 'author/someplugin'),
225
- array('dokuwiki-template', 'lib/tpl/sometemplate/', 'author/sometemplate'),
226
- array('dolibarr-module', 'htdocs/custom/my_module/', 'shama/my_module'),
227
- array('drupal-module', 'modules/my_module/', 'shama/my_module'),
228
- array('drupal-theme', 'themes/my_module/', 'shama/my_module'),
229
- array('drupal-profile', 'profiles/my_module/', 'shama/my_module'),
230
- array('drupal-drush', 'drush/my_module/', 'shama/my_module'),
231
- array('elgg-plugin', 'mod/sample_plugin/', 'test/sample_plugin'),
232
- array('fuel-module', 'fuel/app/modules/module/', 'fuel/module'),
233
- array('fuel-package', 'fuel/packages/orm/', 'fuel/orm'),
234
- array('fuel-theme', 'fuel/app/themes/theme/', 'fuel/theme'),
235
- array('fuelphp-component', 'components/demo/', 'fuelphp/demo'),
236
- array('hurad-plugin', 'plugins/Akismet/', 'atkrad/akismet'),
237
- array('hurad-theme', 'plugins/Hurad2013/', 'atkrad/Hurad2013'),
238
- array('joomla-plugin', 'plugins/my_plugin/', 'shama/my_plugin'),
239
- array('kirby-plugin', 'site/plugins/my_plugin/', 'shama/my_plugin'),
240
- array('kohana-module', 'modules/my_package/', 'shama/my_package'),
241
- array('laravel-library', 'libraries/my_package/', 'shama/my_package'),
242
- array('lithium-library', 'libraries/li3_test/', 'user/li3_test'),
243
- array('magento-library', 'lib/foo/', 'test/foo'),
244
- array('modxevo-snippet', 'assets/snippets/my_snippet/', 'shama/my_snippet'),
245
- array('modxevo-plugin', 'assets/plugins/my_plugin/', 'shama/my_plugin'),
246
- array('modxevo-module', 'assets/modules/my_module/', 'shama/my_module'),
247
- array('modxevo-template', 'assets/templates/my_template/', 'shama/my_template'),
248
- array('modxevo-lib', 'assets/lib/my_lib/', 'shama/my_lib'),
249
- array('mako-package', 'app/packages/my_package/', 'shama/my_package'),
250
- array('mediawiki-extension', 'extensions/APC/', 'author/APC'),
251
- array('mediawiki-extension', 'extensions/APC/', 'author/APC-extension'),
252
- array('mediawiki-extension', 'extensions/UploadWizard/', 'author/upload-wizard'),
253
- array('mediawiki-extension', 'extensions/SyntaxHighlight_GeSHi/', 'author/syntax-highlight_GeSHi'),
254
- array('mediawiki-skin', 'skins/someskin/', 'author/someskin-skin'),
255
- array('mediawiki-skin', 'skins/someskin/', 'author/someskin'),
256
- array('microweber-module', 'userfiles/modules/my-thing/', 'author/my-thing-module'),
257
- array('modulework-module', 'modules/my_package/', 'shama/my_package'),
258
- array('moodle-mod', 'mod/my_package/', 'shama/my_package'),
259
- array('october-module', 'modules/my_plugin/', 'shama/my_plugin'),
260
- array('october-plugin', 'plugins/shama/my_plugin/', 'shama/my_plugin'),
261
- array('october-theme', 'themes/my_theme/', 'shama/my_theme'),
262
- array('piwik-plugin', 'plugins/VisitSummary/', 'shama/visit-summary'),
263
- array('prestashop-module', 'modules/a-module/', 'vendor/a-module'),
264
- array('prestashop-theme', 'themes/a-theme/', 'vendor/a-theme'),
265
- array('phpbb-extension', 'ext/test/foo/', 'test/foo'),
266
- array('phpbb-style', 'styles/foo/', 'test/foo'),
267
- array('phpbb-language', 'language/foo/', 'test/foo'),
268
- array('pimcore-plugin', 'plugins/MyPlugin/', 'ubikz/my_plugin'),
269
- array('ppi-module', 'modules/foo/', 'test/foo'),
270
- array('puppet-module', 'modules/puppet-name/', 'puppet/puppet-name'),
271
- array('redaxo-addon', 'redaxo/include/addons/my_plugin/', 'shama/my_plugin'),
272
- array('redaxo-bestyle-plugin', 'redaxo/include/addons/be_style/plugins/my_plugin/', 'shama/my_plugin'),
273
- array('roundcube-plugin', 'plugins/base/', 'test/base'),
274
- array('roundcube-plugin', 'plugins/replace_dash/', 'test/replace-dash'),
275
- array('shopware-backend-plugin', 'engine/Shopware/Plugins/Local/Backend/ShamaMyBackendPlugin/', 'shama/my-backend-plugin'),
276
- array('shopware-core-plugin', 'engine/Shopware/Plugins/Local/Core/ShamaMyCorePlugin/', 'shama/my-core-plugin'),
277
- array('shopware-frontend-plugin', 'engine/Shopware/Plugins/Local/Frontend/ShamaMyFrontendPlugin/', 'shama/my-frontend-plugin'),
278
- array('shopware-theme', 'templates/my_theme/', 'shama/my-theme'),
279
- array('silverstripe-module', 'my_module/', 'shama/my_module'),
280
- array('silverstripe-module', 'sapphire/', 'silverstripe/framework', '2.4.0'),
281
- array('silverstripe-module', 'framework/', 'silverstripe/framework', '3.0.0'),
282
- array('silverstripe-module', 'framework/', 'silverstripe/framework', '3.0.0-rc1'),
283
- array('silverstripe-module', 'framework/', 'silverstripe/framework', 'my/branch'),
284
- array('silverstripe-theme', 'themes/my_theme/', 'shama/my_theme'),
285
- array('smf-module', 'Sources/my_module/', 'shama/my_module'),
286
- array('smf-theme', 'Themes/my_theme/', 'shama/my_theme'),
287
- array('symfony1-plugin', 'plugins/sfShamaPlugin/', 'shama/sfShamaPlugin'),
288
- array('symfony1-plugin', 'plugins/sfShamaPlugin/', 'shama/sf-shama-plugin'),
289
- array('thelia-module', 'local/modules/my_module/', 'shama/my_module'),
290
- array('thelia-frontoffice-template', 'templates/frontOffice/my_template_fo/', 'shama/my_template_fo'),
291
- array('thelia-backoffice-template', 'templates/backOffice/my_template_bo/', 'shama/my_template_bo'),
292
- array('thelia-email-template', 'templates/email/my_template_email/', 'shama/my_template_email'),
293
- array('tusk-task', '.tusk/tasks/my_task/', 'shama/my_task'),
294
- array('typo3-flow-package', 'Packages/Application/my_package/', 'shama/my_package'),
295
- array('typo3-flow-build', 'Build/my_package/', 'shama/my_package'),
296
- array('typo3-cms-extension', 'typo3conf/ext/my_extension/', 'shama/my_extension'),
297
- array('whmcs-gateway', 'modules/gateways/gateway_name/', 'vendor/gateway_name'),
298
- array('wolfcms-plugin', 'wolf/plugins/my_plugin/', 'shama/my_plugin'),
299
- array('wordpress-plugin', 'wp-content/plugins/my_plugin/', 'shama/my_plugin'),
300
- array('wordpress-muplugin', 'wp-content/mu-plugins/my_plugin/', 'shama/my_plugin'),
301
- array('zend-extra', 'extras/library/zend_test/', 'shama/zend_test'),
302
- array('zikula-module', 'modules/my-test_module/', 'my/test_module'),
303
- array('zikula-theme', 'themes/my-test_theme/', 'my/test_theme'),
304
- array('kodicms-media', 'cms/media/vendor/my_media/', 'shama/my_media'),
305
- array('kodicms-plugin', 'cms/plugins/my_plugin/', 'shama/my_plugin'),
306
- );
307
- }
308
-
309
- /**
310
- * testGetCakePHPInstallPathException
311
- *
312
- * @return void
313
- *
314
- * @expectedException \InvalidArgumentException
315
- */
316
- public function testGetCakePHPInstallPathException()
317
- {
318
- $installer = new Installer($this->io, $this->composer);
319
- $package = new Package('shama/ftp', '1.0.0', '1.0.0');
320
-
321
- $package->setType('cakephp-whoops');
322
- $result = $installer->getInstallPath($package);
323
- }
324
-
325
- /**
326
- * testCustomInstallPath
327
- */
328
- public function testCustomInstallPath()
329
- {
330
- $installer = new Installer($this->io, $this->composer);
331
- $package = new Package('shama/ftp', '1.0.0', '1.0.0');
332
- $package->setType('cakephp-plugin');
333
- $consumerPackage = new RootPackage('foo/bar', '1.0.0', '1.0.0');
334
- $this->composer->setPackage($consumerPackage);
335
- $consumerPackage->setExtra(array(
336
- 'installer-paths' => array(
337
- 'my/custom/path/{$name}/' => array(
338
- 'shama/ftp',
339
- 'foo/bar',
340
- ),
341
- ),
342
- ));
343
- $result = $installer->getInstallPath($package);
344
- $this->assertEquals('my/custom/path/Ftp/', $result);
345
- }
346
-
347
- /**
348
- * testCustomInstallerName
349
- */
350
- public function testCustomInstallerName()
351
- {
352
- $installer = new Installer($this->io, $this->composer);
353
- $package = new Package('shama/cakephp-ftp-plugin', '1.0.0', '1.0.0');
354
- $package->setType('cakephp-plugin');
355
- $package->setExtra(array(
356
- 'installer-name' => 'FTP',
357
- ));
358
- $result = $installer->getInstallPath($package);
359
- $this->assertEquals('Plugin/FTP/', $result);
360
- }
361
-
362
- /**
363
- * testCustomTypePath
364
- */
365
- public function testCustomTypePath()
366
- {
367
- $installer = new Installer($this->io, $this->composer);
368
- $package = new Package('slbmeh/my_plugin', '1.0.0', '1.0.0');
369
- $package->setType('wordpress-plugin');
370
- $consumerPackage = new RootPackage('foo/bar', '1.0.0', '1.0.0');
371
- $this->composer->setPackage($consumerPackage);
372
- $consumerPackage->setExtra(array(
373
- 'installer-paths' => array(
374
- 'my/custom/path/{$name}/' => array(
375
- 'type:wordpress-plugin'
376
- ),
377
- ),
378
- ));
379
- $result = $installer->getInstallPath($package);
380
- $this->assertEquals('my/custom/path/my_plugin/', $result);
381
- }
382
-
383
- /**
384
- * testNoVendorName
385
- */
386
- public function testNoVendorName()
387
- {
388
- $installer = new Installer($this->io, $this->composer);
389
- $package = new Package('sfPhpunitPlugin', '1.0.0', '1.0.0');
390
-
391
- $package->setType('symfony1-plugin');
392
- $result = $installer->getInstallPath($package);
393
- $this->assertEquals('plugins/sfPhpunitPlugin/', $result);
394
- }
395
-
396
- /**
397
- * testTypo3Inflection
398
- */
399
- public function testTypo3Inflection()
400
- {
401
- $installer = new Installer($this->io, $this->composer);
402
- $package = new Package('typo3/fluid', '1.0.0', '1.0.0');
403
-
404
- $package->setAutoload(array(
405
- 'psr-0' => array(
406
- 'TYPO3\\Fluid' => 'Classes',
407
- ),
408
- ));
409
-
410
- $package->setType('typo3-flow-package');
411
- $result = $installer->getInstallPath($package);
412
- $this->assertEquals('Packages/Application/TYPO3.Fluid/', $result);
413
- }
414
-
415
- public function testUninstallAndDeletePackageFromLocalRepo()
416
- {
417
- $package = new Package('foo', '1.0.0', '1.0.0');
418
-
419
- $installer = $this->getMock('Composer\Installers\Installer', array('getInstallPath'), array($this->io, $this->composer));
420
- $installer->expects($this->once())->method('getInstallPath')->with($package)->will($this->returnValue(sys_get_temp_dir().'/foo'));
421
-
422
- $repo = $this->getMock('Composer\Repository\InstalledRepositoryInterface');
423
- $repo->expects($this->once())->method('hasPackage')->with($package)->will($this->returnValue(true));
424
- $repo->expects($this->once())->method('removePackage')->with($package);
425
-
426
- $installer->uninstall($repo, $package);
427
- }
428
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/Composer/Installers/Test/MediaWikiInstallerTest.php DELETED
@@ -1,66 +0,0 @@
1
- <?php
2
- namespace Composer\Installers\Test;
3
-
4
- use Composer\Installers\MediaWikiInstaller;
5
- use Composer\Package\Package;
6
- use Composer\Composer;
7
-
8
- class MediaWikiInstallerTest extends \PHPUnit_Framework_TestCase
9
- {
10
- /**
11
- * @var MediaWikiInstaller
12
- */
13
- private $installer;
14
-
15
- public function setUp()
16
- {
17
- $this->installer = new MediaWikiInstaller(
18
- new Package('NyanCat', '4.2', '4.2'),
19
- new Composer()
20
- );
21
- }
22
-
23
- /**
24
- * @dataProvider packageNameInflectionProvider
25
- */
26
- public function testInflectPackageVars($type, $name, $expected)
27
- {
28
- $this->assertEquals(
29
- $this->installer->inflectPackageVars(array('name' => $name, 'type'=>$type)),
30
- array('name' => $expected, 'type'=>$type)
31
- );
32
- }
33
-
34
- public function packageNameInflectionProvider()
35
- {
36
- return array(
37
- array(
38
- 'mediawiki-extension',
39
- 'sub-page-list',
40
- 'SubPageList',
41
- ),
42
- array(
43
- 'mediawiki-extension',
44
- 'sub-page-list-extension',
45
- 'SubPageList',
46
- ),
47
- array(
48
- 'mediawiki-extension',
49
- 'semantic-mediawiki',
50
- 'SemanticMediawiki',
51
- ),
52
- // tests that exactly one '-skin' is cut off, and that skins do not get ucwords treatment like extensions
53
- array(
54
- 'mediawiki-skin',
55
- 'some-skin-skin',
56
- 'some-skin',
57
- ),
58
- // tests that names without '-skin' suffix stay valid
59
- array(
60
- 'mediawiki-skin',
61
- 'someotherskin',
62
- 'someotherskin',
63
- ),
64
- );
65
- }
66
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/Composer/Installers/Test/OctoberInstallerTest.php DELETED
@@ -1,66 +0,0 @@
1
- <?php
2
- namespace Composer\Installers\Test;
3
-
4
- use Composer\Installers\OctoberInstaller;
5
- use Composer\Package\Package;
6
- use Composer\Composer;
7
-
8
- class OctoberInstallerTest extends \PHPUnit_Framework_TestCase
9
- {
10
- /**
11
- * @var OctoberInstaller
12
- */
13
- private $installer;
14
-
15
- public function setUp()
16
- {
17
- $this->installer = new OctoberInstaller(
18
- new Package('NyanCat', '4.2', '4.2'),
19
- new Composer()
20
- );
21
- }
22
-
23
- /**
24
- * @dataProvider packageNameInflectionProvider
25
- */
26
- public function testInflectPackageVars($type, $name, $expected)
27
- {
28
- $this->assertEquals(
29
- $this->installer->inflectPackageVars(array('name' => $name, 'type' => $type)),
30
- array('name' => $expected, 'type' => $type)
31
- );
32
- }
33
-
34
- public function packageNameInflectionProvider()
35
- {
36
- return array(
37
- array(
38
- 'october-plugin',
39
- 'subpagelist',
40
- 'subpagelist',
41
- ),
42
- array(
43
- 'october-plugin',
44
- 'subpagelist-plugin',
45
- 'subpagelist',
46
- ),
47
- array(
48
- 'october-plugin',
49
- 'semanticoctober',
50
- 'semanticoctober',
51
- ),
52
- // tests that exactly one '-theme' is cut off
53
- array(
54
- 'october-theme',
55
- 'some-theme-theme',
56
- 'some-theme',
57
- ),
58
- // tests that names without '-theme' suffix stay valid
59
- array(
60
- 'october-theme',
61
- 'someothertheme',
62
- 'someothertheme',
63
- ),
64
- );
65
- }
66
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/Composer/Installers/Test/PimcoreInstallerTest.php DELETED
@@ -1,44 +0,0 @@
1
- <?php
2
- namespace Composer\Installers\Test;
3
-
4
- use Composer\Installers\PimcoreInstaller;
5
- use Composer\Package\Package;
6
- use Composer\Composer;
7
-
8
- class PimcoreInstallerTest extends TestCase
9
- {
10
- private $composer;
11
- private $io;
12
-
13
- /**
14
- * setUp
15
- *
16
- * @return void
17
- */
18
- public function setUp()
19
- {
20
- $this->package = new Package('CamelCased', '1.0', '1.0');
21
- $this->io = $this->getMock('Composer\IO\PackageInterface');
22
- $this->composer = new Composer();
23
- }
24
-
25
- /**
26
- * testInflectPackageVars
27
- *
28
- * @return void
29
- */
30
- public function testInflectPackageVars()
31
- {
32
- $installer = new PimcoreInstaller($this->package, $this->composer);
33
- $result = $installer->inflectPackageVars(array('name' => 'CamelCased'));
34
- $this->assertEquals($result, array('name' => 'CamelCased'));
35
-
36
- $installer = new PimcoreInstaller($this->package, $this->composer);
37
- $result = $installer->inflectPackageVars(array('name' => 'with-dash'));
38
- $this->assertEquals($result, array('name' => 'WithDash'));
39
-
40
- $installer = new PimcoreInstaller($this->package, $this->composer);
41
- $result = $installer->inflectPackageVars(array('name' => 'with_underscore'));
42
- $this->assertEquals($result, array('name' => 'WithUnderscore'));
43
- }
44
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/Composer/Installers/Test/PiwikInstallerTest.php DELETED
@@ -1,63 +0,0 @@
1
- <?php
2
- namespace Composer\Installers\Test;
3
-
4
- use Composer\Composer;
5
- use Composer\Installers\PiwikInstaller;
6
- use Composer\Package\Package;
7
- use Composer\Package\PackageInterface;
8
-
9
- /**
10
- * Class PiwikInstallerTest
11
- *
12
- * @package Composer\Installers\Test
13
- */
14
- class PiwikInstallerTest extends TestCase
15
- {
16
- /**
17
- * @varComposer
18
- */
19
- private $composer;
20
-
21
- /**
22
- * @var PackageInterface
23
- */
24
- private $io;
25
-
26
- /**
27
- * @var Package
28
- */
29
- private $package;
30
-
31
- /**
32
- * setUp
33
- *
34
- * @return void
35
- */
36
- public function setUp()
37
- {
38
- $this->package = new Package('VisitSummary', '1.0', '1.0');
39
- $this->io = $this->getMock('Composer\IO\PackageInterface');
40
- $this->composer = new Composer();
41
- }
42
-
43
- /**
44
- * testInflectPackageVars
45
- *
46
- * @return void
47
- */
48
- public function testInflectPackageVars()
49
- {
50
- $installer = new PiwikInstaller($this->package, $this->composer);
51
- $result = $installer->inflectPackageVars(array('name' => 'VisitSummary'));
52
- $this->assertEquals($result, array('name' => 'VisitSummary'));
53
-
54
- $installer = new PiwikInstaller($this->package, $this->composer);
55
- $result = $installer->inflectPackageVars(array('name' => 'visit-summary'));
56
- $this->assertEquals($result, array('name' => 'VisitSummary'));
57
-
58
- $installer = new PiwikInstaller($this->package, $this->composer);
59
- $result = $installer->inflectPackageVars(array('name' => 'visit_summary'));
60
- $this->assertEquals($result, array('name' => 'VisitSummary'));
61
- }
62
-
63
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/Composer/Installers/Test/TestCase.php DELETED
@@ -1,64 +0,0 @@
1
- <?php
2
-
3
- /*
4
- * This file is part of Composer.
5
- *
6
- * (c) Nils Adermann <naderman@naderman.de>
7
- * Jordi Boggiano <j.boggiano@seld.be>
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
-
13
- namespace Composer\Installers\Test;
14
-
15
- use Composer\Package\Version\VersionParser;
16
- use Composer\Package\Package;
17
- use Composer\Package\AliasPackage;
18
- use Composer\Package\LinkConstraint\VersionConstraint;
19
- use Composer\Util\Filesystem;
20
-
21
- abstract class TestCase extends \PHPUnit_Framework_TestCase
22
- {
23
- private static $parser;
24
-
25
- protected static function getVersionParser()
26
- {
27
- if (!self::$parser) {
28
- self::$parser = new VersionParser();
29
- }
30
-
31
- return self::$parser;
32
- }
33
-
34
- protected function getVersionConstraint($operator, $version)
35
- {
36
- return new VersionConstraint(
37
- $operator,
38
- self::getVersionParser()->normalize($version)
39
- );
40
- }
41
-
42
- protected function getPackage($name, $version)
43
- {
44
- $normVersion = self::getVersionParser()->normalize($version);
45
-
46
- return new Package($name, $normVersion, $version);
47
- }
48
-
49
- protected function getAliasPackage($package, $version)
50
- {
51
- $normVersion = self::getVersionParser()->normalize($version);
52
-
53
- return new AliasPackage($package, $normVersion, $version);
54
- }
55
-
56
- protected function ensureDirectoryExistsAndClear($directory)
57
- {
58
- $fs = new Filesystem();
59
- if (is_dir($directory)) {
60
- $fs->removeDirectory($directory);
61
- }
62
- mkdir($directory, 0777, true);
63
- }
64
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/composer/installers/tests/bootstrap.php DELETED
@@ -1,4 +0,0 @@
1
- <?php
2
-
3
- $loader = require __DIR__ . '/../src/bootstrap.php';
4
- $loader->add('Composer\Installers\Test', __DIR__);
 
 
 
 
embedded/frontend.php DELETED
@@ -1,1128 +0,0 @@
1
- <?php
2
- /*
3
- * Frontend functions.
4
- *
5
- *
6
- */
7
-
8
- global $wp_version;
9
-
10
- if ( version_compare( $wp_version, '3.3', '<' ) ) {
11
- // add a the_content filter to allow types shortcodes to be closed.
12
- // This is a bit of a HACK for version 3.2.1 and less
13
-
14
- add_filter( 'the_content', 'wpcf_fix_closed_types_shortcodes', 9, 1 );
15
- add_filter( 'the_content', 'wpcf_fix_closed_types_shortcodes_after', 11, 1 );
16
-
17
- function wpcf_fix_closed_types_shortcodes( $content ) {
18
- $content = str_replace( '][/types', ']###TYPES###[/types', $content );
19
- return $content;
20
- }
21
-
22
- function wpcf_fix_closed_types_shortcodes_after( $content ) {
23
- $content = str_replace( '###TYPES###', '', $content );
24
- return $content;
25
- }
26
-
27
- }
28
-
29
- add_shortcode( 'types', 'wpcf_shortcode' );
30
-
31
- /**
32
- * Shortcode processing.
33
- *
34
- * Called by WP when rendering post on frontend.
35
- * From here follow these:
36
- * @see types_render_field() Renders shortcode. Can be used other ways too.
37
- * @see types_render_field_single() Renders single field. Useful for Repeater.
38
- * Afterwards wrapping options.
39
- *
40
- * @param type $atts
41
- * @param type $content
42
- * @param type $code
43
- * @return string
44
- */
45
- function wpcf_shortcode( $atts, $content = null, $code = '' ) {
46
-
47
- global $wpcf;
48
-
49
- // Switch the post if there is an attribute of 'id' in the shortcode.
50
- $post_id_atts = new WPV_wpcf_switch_post_from_attr_id( $atts );
51
-
52
- if ( !is_array( $atts ) ) {
53
- $wpcf->errors['shortcode_malformed'][] = func_get_args();
54
- return '';
55
- }
56
-
57
- // Do not use shortcode_atts here as it shaves any attribute not defined with a default value
58
- $atts = array_merge(
59
- array(
60
- 'field' => false,
61
- 'usermeta' => false,
62
- 'termmeta' => false,
63
- 'style' => '',
64
- 'show_name' => false,
65
- 'raw' => false,
66
- ),
67
- $atts
68
- );
69
-
70
- if ( $atts['field'] ) {
71
- return types_render_field( $atts['field'], $atts, $content, $code );
72
- }
73
- if ( $atts['termmeta'] ) {
74
- return types_render_termmeta( $atts['termmeta'], $atts, $content, $code );
75
- }
76
- if ( $atts['usermeta'] ) {
77
- return types_render_usermeta( $atts['usermeta'], $atts, $content, $code );
78
- }
79
-
80
- return '';
81
- }
82
-
83
- /**
84
- * Calls view function for specific field type.
85
- *
86
- * @param type $field
87
- * @param type $atts
88
- * @return type
89
- */
90
- function types_render_field( $field_id = null, $params = array(), $content = null, $code = '' )
91
- {
92
- if ( empty($field_id) ) {
93
- return '';
94
- }
95
-
96
- global $wpcf;
97
-
98
- // HTML var holds actual output
99
- $html = '';
100
-
101
- // Set post ID to global
102
- $post_id = get_the_ID();
103
-
104
- // Check if other post required
105
- if ( isset( $params['post_id'] ) ) {
106
- // If numeric value
107
- if ( is_numeric( $params['post_id'] ) ) {
108
- $post_id = intval( $params['post_id'] );
109
-
110
- // WP parent
111
- } else if ( $params['post_id'] == '$parent' ) {
112
- $current_post = get_post( $post_id );
113
- if ( empty( $current_post->post_parent ) ) {
114
- return '';
115
- }
116
- $post_id = $current_post->post_parent;
117
-
118
- // Types parent
119
- } else if ( strpos( $params['post_id'], '$' ) === 0 ) {
120
- $post_id = intval( WPCF_Relationship::get_parent( $post_id, trim( $params['post_id'], '$' ) ) );
121
- }
122
- }
123
-
124
- if ( empty( $post_id ) ) {
125
- return '';
126
- }
127
-
128
- // Set post
129
- $post = get_post( $post_id );
130
-
131
- if ( empty( $post ) ) {
132
- return '';
133
- }
134
-
135
- // Get field
136
- $field = types_get_field( $field_id );
137
-
138
- // If field not found return empty string
139
- if ( empty( $field ) ) {
140
-
141
- // Log
142
- if ( !function_exists( 'wplogger' ) ) {
143
- require_once WPCF_EMBEDDED_ABSPATH . '/toolset/toolset-common/wplogger.php';
144
- }
145
- global $wplogger;
146
- $wplogger->log( 'types_render_field call for missing field \'' . $field_id . '\'', WPLOG_DEBUG );
147
-
148
- return '';
149
- }
150
-
151
- // Set field
152
- $wpcf->field->set( $post, $field );
153
-
154
- // See if repetitive
155
- if ( types_is_repetitive( $field ) ) {
156
- $wpcf->repeater->set( $post_id, $field );
157
- $_meta = $wpcf->repeater->_get_meta();
158
- $meta = $_meta['custom_order'];
159
-
160
- // Sometimes if meta is empty - array(0 => '') is returned
161
- if ( count( $meta ) == 1 && reset( $meta ) == '' ) {
162
- return '';
163
- }
164
- if ( !empty( $meta ) ) {
165
- $output = '';
166
-
167
- if ( isset( $params['index'] ) ) {
168
- $index = $params['index'];
169
- } else {
170
- $index = '';
171
- }
172
-
173
- // Allow wpv-for-each shortcode to set the index
174
- $index = apply_filters( 'wpv-for-each-index', $index );
175
-
176
- if ( $index === '' ) {
177
- $output = array();
178
- foreach ( $meta as $temp_key => $temp_value ) {
179
- $params['field_value'] = $temp_value;
180
- $temp_output = types_render_field_single( $field, $params, $content, $code, $temp_key );
181
- if ( !empty( $temp_output ) ) {
182
- $output[] = $temp_output;
183
- }
184
- }
185
- if ( !empty( $output ) && isset( $params['separator'] )
186
- && $params['separator'] !== '' ) {
187
- $output = implode( html_entity_decode( $params['separator'] ),
188
- $output );
189
- } else if ( !empty( $output ) ) {
190
- $output = implode( ' ', $output );
191
- } else {
192
- return '';
193
- }
194
- } else {
195
- // Make sure indexed right
196
- $_index = 0;
197
- foreach ( $meta as $temp_key => $temp_value ) {
198
- if ( $_index == $index ) {
199
- $params['field_value'] = $temp_value;
200
- return types_render_field_single( $field, $params, $content, $code, $temp_key );
201
- }
202
- $_index++;
203
- }
204
- // If missed index
205
- return '';
206
- }
207
- $html = $output;
208
- } else {
209
- return '';
210
- }
211
- } else {
212
-
213
- // Non-repetitive field
214
- $params['field_value'] = wpcf_get_post_meta( $post_id,
215
- wpcf_types_get_meta_prefix( $field ) . $field['slug'], true );
216
- if ( $params['field_value'] == '' && $field['type'] != 'checkbox' ) {
217
- return '';
218
- }
219
- $html = types_render_field_single( $field, $params, $content, $code, $wpcf->field->meta_object->meta_id );
220
- }
221
- return $wpcf->field->html( $html, $params );
222
- }
223
-
224
- function types_render_termmeta( $field_id, $params, $content = null, $code = '' ) {
225
-
226
- global $wpcf, $wpdb, $WP_Views;
227
- // HTML var holds actual output
228
- $html = '';
229
-
230
- //Get User id from views loop
231
- if (
232
- isset( $WP_Views->taxonomy_data['term']->term_id )
233
- && ! empty( $WP_Views->taxonomy_data['term']->term_id )
234
- ) {
235
- $params['term_id'] = $WP_Views->taxonomy_data['term']->term_id;
236
- }
237
-
238
- if (
239
- ! isset( $params['term_id'] )
240
- && (
241
- is_tax()
242
- || is_category()
243
- || is_tag()
244
- )
245
- ) {
246
- global $wp_query;
247
- $term = $wp_query->get_queried_object();
248
- if (
249
- $term
250
- && isset( $term->term_id )
251
- ) {
252
- $params['term_id'] = $term->term_id;
253
- }
254
- }
255
- //print_r($params);exit;
256
- //Get user By ID
257
- if ( isset( $params['term_id'] ) ) {
258
- $term_id = $params['term_id'];
259
- } else {
260
- return;
261
- }
262
-
263
- if ( empty( $term_id ) ) {
264
- return;
265
- }
266
- // Get field
267
- $field = types_get_field( $field_id, 'termmeta' );
268
-
269
- // If field not found return empty string
270
- if ( empty( $field ) ) {
271
-
272
- // Log
273
- if ( !function_exists( 'wplogger' ) ) {
274
- require_once WPCF_EMBEDDED_ABSPATH . '/toolset/toolset-common/wplogger.php';
275
- }
276
- global $wplogger;
277
- $wplogger->log( 'types_render_field call for missing field \''
278
- . $field_id . '\'', WPLOG_DEBUG );
279
-
280
- return '';
281
- }
282
-
283
- // See if repetitive
284
- if ( wpcf_admin_is_repetitive( $field ) ) {
285
-
286
- $wpcf->termmeta_repeater->set( $term_id, $field );
287
- $_meta = $wpcf->termmeta_repeater->_get_meta();
288
- $meta = '';
289
- if ( isset( $_meta['custom_order'] ) ) {
290
- $meta = $_meta['custom_order'];
291
- }
292
-
293
- if ( (count( $meta ) == 1 ) ) {
294
- $meta_id = key( $meta );
295
- $_temp = array_shift( $meta );
296
- if ( strval( $_temp ) == '' ) {
297
- return '';
298
- } else {
299
- $params['field_value'] = $_temp;
300
- return types_render_field_single( $field, $params, $content,
301
- $code, $meta_id );
302
- }
303
- } else if ( !empty( $meta ) ) {
304
- $output = '';
305
-
306
- if ( isset( $params['index'] ) ) {
307
- $index = $params['index'];
308
- } else {
309
- $index = '';
310
- }
311
-
312
- // Allow wpv-for-each shortcode to set the index
313
- $index = apply_filters( 'wpv-for-each-index', $index );
314
-
315
- if ( $index === '' ) {
316
- $output = array();
317
- foreach ( $meta as $temp_key => $temp_value ) {
318
- $params['field_value'] = $temp_value;
319
- $temp_output = types_render_field_single( $field, $params,
320
- $content, $code, $temp_key );
321
- if ( !empty( $temp_output ) ) {
322
- $output[] = $temp_output;
323
- }
324
- }
325
- if ( !empty( $output ) && isset( $params['separator'] ) ) {
326
- $output = implode( html_entity_decode( $params['separator'] ),
327
- $output );
328
- } else if ( !empty( $output ) ) {
329
- $output = implode( '', $output );
330
- } else {
331
- return '';
332
- }
333
- } else {
334
- // Make sure indexed right
335
- $_index = 0;
336
- foreach ( $meta as $temp_key => $temp_value ) {
337
- if ( $_index == $index ) {
338
- $params['field_value'] = $temp_value;
339
- $output = types_render_field_single( $field, $params,
340
- $content, $code, $temp_key );
341
- }
342
- $_index++;
343
- }
344
- }
345
- $html = $output;
346
- } else {
347
- return '';
348
- }
349
- } else {
350
- $params['field_value'] = get_term_meta( $term_id, wpcf_types_get_meta_prefix( $field ) . $field['slug'], true );
351
- if ( $params['field_value'] == '' && $field['type'] != 'checkbox' ) {
352
- return '';
353
- }
354
- $html = types_render_field_single( $field, $params, $content, $code );
355
- }
356
-
357
- // API filter
358
- $wpcf->termmeta_field->set( $term_id, $field );
359
- return $wpcf->termmeta_field->html( $html, $params );
360
- }
361
-
362
- /**
363
- * Calls view function for specific usermeta field type.
364
- *
365
- * @global object $wpdb
366
- *
367
- * @param type $field
368
- * @param type $atts (additional attributes: user_id, user_name, user_is_author, user_current)
369
- * @return type
370
- */
371
- function types_render_usermeta( $field_id, $params, $content = null, $code = '' ) {
372
-
373
- global $wpcf, $post, $wpdb, $WP_Views;
374
- // HTML var holds actual output
375
- $html = '';
376
- $current_user = wp_get_current_user();
377
- $current_user_id = $current_user->ID;
378
-
379
- // Set post ID
380
- // user_id, user_name, user_is_author, user_current
381
- if ( is_object( $post ) ) {
382
- $post_id = $post->ID;
383
- } else {
384
- $post_id = 0;
385
- }
386
- if ( isset( $params['post_id'] ) && !empty( $params['post_id'] ) ) {
387
- $post_id = $params['post_id'];
388
- }
389
-
390
- //Get User id from views loop
391
- if (
392
- isset( $WP_Views->users_data['term']->ID )
393
- && ! empty( $WP_Views->users_data['term']->ID )
394
- ) {
395
- $params['user_id'] = $WP_Views->users_data['term']->ID;
396
- }
397
- //print_r($params);exit;
398
- //Get user By ID
399
- if ( isset( $params['user_id'] ) ) {
400
- $user_id = $params['user_id'];
401
- } else if ( isset( $params['user_name'] ) ) { //Get user by login
402
- $user_id = $wpdb->get_var(
403
- $wpdb->prepare(
404
- "SELECT * FROM " . $wpdb->users . " WHERE user_login = %s",
405
- $params['user_name']
406
- )
407
- );
408
- } else if ( isset( $params['user_is_author'] ) ) { //Get Post author
409
- $user_id = $post->post_author;
410
- } else if ( isset( $params['user_current'] ) ) {//Get current logged user
411
- $user_id = $current_user_id;
412
- } else { //If empty get post author, if no post, return empty
413
- if ( !empty( $post_id ) ) {
414
- $user_id = $post->post_author;
415
- } else {
416
- return;
417
- }
418
- }
419
-
420
- if ( empty( $user_id ) ) {
421
- return;
422
- }
423
- // Get field
424
- $field = types_get_field( $field_id, 'usermeta' );
425
-
426
- // If field not found return empty string
427
- if ( empty( $field ) ) {
428
-
429
- // Log
430
- if ( !function_exists( 'wplogger' ) ) {
431
- require_once WPCF_EMBEDDED_ABSPATH . '/toolset/toolset-common/wplogger.php';
432
- }
433
- global $wplogger;
434
- $wplogger->log( 'types_render_field call for missing field \''
435
- . $field_id . '\'', WPLOG_DEBUG );
436
-
437
- return '';
438
- }
439
-
440
- // See if repetitive
441
- if ( wpcf_admin_is_repetitive( $field ) ) {
442
-
443
- $wpcf->usermeta_repeater->set( $user_id, $field );
444
- $_meta = $wpcf->usermeta_repeater->_get_meta();
445
- $meta = '';
446
- if ( isset( $_meta['custom_order'] ) ) {
447
- $meta = $_meta['custom_order'];
448
- }
449
-
450
- if ( (count( $meta ) == 1 ) ) {
451
- $meta_id = key( $meta );
452
- $_temp = array_shift( $meta );
453
- if ( strval( $_temp ) == '' ) {
454
- return '';
455
- } else {
456
- $params['field_value'] = $_temp;
457
- return types_render_field_single( $field, $params, $content,
458
- $code, $meta_id );
459
- }
460
- } else if ( !empty( $meta ) ) {
461
- $output = '';
462
-
463
- if ( isset( $params['index'] ) ) {
464
- $index = $params['index'];
465
- } else {
466
- $index = '';
467
- }
468
-
469
- // Allow wpv-for-each shortcode to set the index
470
- $index = apply_filters( 'wpv-for-each-index', $index );
471
-
472
- if ( $index === '' ) {
473
- $output = array();
474
- foreach ( $meta as $temp_key => $temp_value ) {
475
- $params['field_value'] = $temp_value;
476
- $temp_output = types_render_field_single( $field, $params,
477
- $content, $code, $temp_key );
478
- if ( !empty( $temp_output ) ) {
479
- $output[] = $temp_output;
480
- }
481
- }
482
- if ( !empty( $output ) && isset( $params['separator'] ) ) {
483
- $output = implode( html_entity_decode( $params['separator'] ),
484
- $output );
485
- } else if ( !empty( $output ) ) {
486
- $output = implode( '', $output );
487
- } else {
488
- return '';
489
- }
490
- } else {
491
- // Make sure indexed right
492
- $_index = 0;
493
- foreach ( $meta as $temp_key => $temp_value ) {
494
- if ( $_index == $index ) {
495
- $params['field_value'] = $temp_value;
496
- $output = types_render_field_single( $field, $params,
497
- $content, $code, $temp_key );
498
- }
499
- $_index++;
500
- }
501
- }
502
- $html = $output;
503
- } else {
504
- return '';
505
- }
506
- } else {
507
- $params['field_value'] = get_user_meta( $user_id, wpcf_types_get_meta_prefix( $field ) . $field['slug'], true );
508
- if ( $params['field_value'] == '' && $field['type'] != 'checkbox' ) {
509
- return '';
510
- }
511
- $html = types_render_field_single( $field, $params, $content, $code );
512
- }
513
-
514
- // API filter
515
- $wpcf->usermeta_field->set( $user_id, $field );
516
- return $wpcf->usermeta_field->html( $html, $params );
517
- }
518
-
519
- /**
520
- * Calls view function for specific field type by single field.
521
- *
522
- * @param type $field
523
- * @param type $atts
524
- * @return type
525
- */
526
- function types_render_field_single( $field, $params, $content = null, $code = '', $meta_id = null )
527
- {
528
- global $post;
529
-
530
- if ( empty( $post ) ) {
531
- $post = (object) array('ID' => '');
532
- }
533
-
534
- // Apply filters to field value
535
- if ( is_string( $params['field_value'] ) ) {
536
- $params['field_value'] = trim( $params['field_value'] );
537
- }
538
-
539
- $params = apply_filters( 'types_field_shortcode_parameters', $params,
540
- $field, $post, $meta_id );
541
-
542
- $params['field_value'] = apply_filters( 'wpcf_fields_value_display', $params['field_value'], $params, $post->ID, $field['id'], $meta_id );
543
-
544
- $params['field_value'] = apply_filters( 'wpcf_fields_slug_' . $field['slug'] . '_value_display', $params['field_value'], $params, $post->ID, $field['id'], $meta_id );
545
-
546
- $params['field_value'] = apply_filters( 'wpcf_fields_type_' . $field['type'] . '_value_display', $params['field_value'], $params, $post->ID, $field['id'], $meta_id );
547
- // To make sure
548
- if ( is_string( $params['field_value'] ) ) {
549
- $params['field_value'] = addslashes( stripslashes( strval( $params['field_value'] ) ) );
550
- }
551
-
552
- // Note that $params['field_value'] does NOT need translating
553
- // When a variable string or label output needs translating we do it on 'wpcf_fields_type_' . $field['type'] . '_value_display' on a field type basis
554
-
555
- $field['name'] = wpcf_translate( 'field ' . $field['id'] . ' name', $field['name'] );
556
- $params['field'] = $field;
557
- $params['#content'] = htmlspecialchars( $content );
558
- $params['#code'] = $code;
559
-
560
- // Set additional data
561
- $params['__meta_id'] = $meta_id;
562
- $params['field']['__meta_id'] = $meta_id;
563
-
564
- if ( (isset( $params['raw'] ) && $params['raw'] == 'true')
565
- || (isset( $params['output'] ) && $params['output'] == 'raw') ) {
566
- // Skype is array
567
- if ( $field['type'] == 'skype' && isset( $params['field_value']['skypename'] ) ) {
568
- $output = $params['field_value']['skypename'];
569
- } else if ($field['type'] == 'checkboxes' && is_array( $params['field_value'] ) ) {
570
- $output = '';
571
- foreach ($params['field_value'] as $value) {
572
- if ($output != '') {
573
- $output .= ', ';
574
- }
575
- $output .= $value[0];
576
- }
577
- } else {
578
- $output = $params['field_value'];
579
- }
580
- } else {
581
- /*
582
- * This is place where view function is called.
583
- * Returned data should be string.
584
- */
585
- $output = '';
586
- $_view_func = 'wpcf_fields_' . strtolower( $field['type'] ) . '_view';
587
- if ( is_callable( $_view_func ) ) {
588
- $output = strval( call_user_func( $_view_func, $params ) );
589
- }
590
-
591
- // If no output
592
- if ( empty( $output ) && isset( $params['field_value'] )
593
- && $params['field_value'] !== "" ) {
594
- $output = $params['field_value'];
595
- } else if ( $output == '__wpcf_skip_empty' ) {
596
- $output = '';
597
- }
598
-
599
- if (isset($params['output']) && $params['output'] == 'html') {
600
- $output = wpcf_frontend_compat_html_output( $output, $field, $content, $params );
601
- } else {
602
- // Prepend name if needed
603
- if ( !empty( $output ) && isset( $params['show_name'] )
604
- && $params['show_name'] == 'true' ) {
605
- $output = $params['field']['name'] . ': ' . $output;
606
- }
607
- }
608
- }
609
-
610
- // Apply filters
611
- $output = strval( apply_filters( 'types_view', $output,
612
- $params['field_value'], $field['type'], $field['slug'],
613
- $field['name'], $params ) );
614
-
615
- return stripslashes( strval( $output ) );
616
-
617
- }
618
-
619
- function wpcf_frontend_compat_html_output( $output, $field, $content, $params ) {
620
- // Count fields (if there are duplicates)
621
- static $count = array();
622
- // Count it
623
- if ( !isset( $count[$field['slug']] ) ) {
624
- $count[$field['slug']] = 1;
625
- } else {
626
- $count[$field['slug']] += 1;
627
- }
628
- // If no output
629
- if ( empty( $output ) && !empty( $params['field_value'] ) ) {
630
- $output = wpcf_frontend_wrap_field_value( $field,
631
- $params['field_value'], $params );
632
- $output = wpcf_frontend_wrap_field( $field, $output, $params );
633
- } else if ( $output != '__wpcf_skip_empty' ) {
634
- $output = wpcf_frontend_wrap_field_value( $field, $output, $params );
635
- $output = wpcf_frontend_wrap_field( $field, $output, $params );
636
- } else {
637
- $output = '';
638
- }
639
- // Add count
640
- if ( isset( $count[$field['slug']] ) && intval( $count[$field['slug']] ) > 1 ) {
641
- $add = '-' . intval( $count[$field['slug']] );
642
- $output = str_replace( 'id="wpcf-field-' . $field['slug'] . '"',
643
- 'id="wpcf-field-' . $field['slug'] . $add . '"', $output );
644
- }
645
- return $output;
646
- }
647
-
648
- /**
649
- * Wraps field content.
650
- *
651
- * @param type $field
652
- * @param type $content
653
- * @return type
654
- */
655
- function wpcf_frontend_wrap_field( $field, $content, $params = array() ) {
656
- if ( isset( $params['output'] ) && $params['output'] == 'html' ) {
657
- $class = array();
658
- if ( !empty( $params['class'] )
659
- && !in_array( $field['type'],
660
- array('file', 'image', 'email', 'url', 'wysiwyg') ) ) {
661
- $class[] = $params['class'];
662
- }
663
- $class[] = 'wpcf-field-' . $field['type'] . ' wpcf-field-'
664
- . $field['slug'];
665
- // Add name if needed
666
- if ( isset( $params['show_name'] ) && $params['show_name'] == 'true'
667
- && strpos( $content,
668
- 'class="wpcf-field-' . $field['type']
669
- . '-name ' ) === false ) {
670
- $content = wpcf_frontend_wrap_field_name( $field, $field['name'],
671
- $params ) . $content;
672
- }
673
- $output = '<div id="wpcf-field-' . $field['slug'] . '"'
674
- . ' class="' . implode( ' ', $class ) . '"';
675
- if ( !empty( $params['style'] )
676
- && !in_array( $field['type'],
677
- array('date', 'file', 'image', 'email', 'url', 'wysiwyg') ) ) {
678
- $output .= ' style="' . $params['style'] . '"';
679
- }
680
- $output .= '>' . $content . '</div>';
681
- return $output;
682
- } else {
683
- if ( isset( $params['show_name'] ) && $params['show_name'] == 'true'
684
- && strpos( $content, $field['name'] . ':' ) === false ) {
685
- $content = wpcf_frontend_wrap_field_name( $field,
686
- $params['field']['name'], $params ) . $content;
687
- }
688
- return $content;
689
- }
690
- }
691
-
692
- /**
693
- * Wraps field name.
694
- *
695
- * @param type $field
696
- * @param type $content
697
- * @return type
698
- */
699
- function wpcf_frontend_wrap_field_name( $field, $content, $params = array() ) {
700
- if ( isset( $params['output'] ) && $params['output'] == 'html' ) {
701
- $class = array();
702
- if ( $field['type'] == 'checkboxes' && isset( $params['option'] ) ) {
703
- if ( isset( $params['field']['data']['options'][$params['option']]['title'] ) ) {
704
- $content = $params['field']['data']['options'][$params['option']]['title'];
705
- }
706
- $class[] = $params['option'] . '-name';
707
- }
708
- if ( !in_array( $field['type'],
709
- array('file', 'image', 'email', 'url', 'wysiwyg') )
710
- && !empty( $params['class'] ) ) {
711
- $class[] = $params['class'];
712
- }
713
- $class[] = 'wpcf-field-name wpcf-field-' . $field['type'] . ' wpcf-field-'
714
- . $field['slug'] . '-name';
715
- if ( $field['type'] == 'wysiwyg' || $field['type'] == 'textarea' ) {
716
- $output = '<div class="' . implode( ' ', $class ) . '"';
717
- if ( !empty( $params['style'] ) ) {
718
- $output .= ' style="' . $params['style'] . '"';
719
- }
720
- $output .= '>' . stripslashes( strval( $content ) ) . ':</div> ';
721
- return $output;
722
- }
723
- $output = '<span class="' . implode( ' ', $class ) . '"';
724
- if ( !empty( $params['style'] )
725
- && !in_array( $field['type'],
726
- array('date', 'file', 'image', 'email', 'url', 'wysiwyg') ) ) {
727
- $output .= ' style="' . $params['style'] . '"';
728
- }
729
- $output .= '>' . stripslashes( strval( $content ) ) . ':</span> ';
730
- return $output;
731
- } else {
732
- return stripslashes( strval( $content ) ) . ': ';
733
- }
734
- }
735
-
736
- /**
737
- * Wraps field value.
738
- *
739
- * @param type $field
740
- * @param type $content
741
- * @return type
742
- */
743
- function wpcf_frontend_wrap_field_value( $field, $content, $params = array() ) {
744
- if ( isset( $params['output'] ) && $params['output'] == 'html' ) {
745
- $class = array();
746
- if ( $field['type'] == 'checkboxes' && isset( $params['option'] ) ) {
747
- $class[] = $params['option'] . '-value';
748
- }
749
- if ( !empty( $params['class'] )
750
- && !in_array( $field['type'],
751
- array('file', 'image', 'email', 'url', 'wysiwyg') ) ) {
752
- $class[] = $params['class'];
753
- }
754
-
755
- // add some default
756
- if ( !array_key_exists( 'style', $params ) )
757
- $params['style'] = '';
758
-
759
- $class[] = 'wpcf-field-value wpcf-field-' . $field['type']
760
- . '-value wpcf-field-' . $field['slug'] . '-value';
761
- if ( $field['type'] == 'skype' || $field['type'] == 'image' || ($field['type'] == 'date' && $params['style'] == 'calendar')
762
- || $field['type'] == 'wysiwyg' || $field['type'] == 'textarea' ) {
763
- $output = '<div class="' . implode( ' ', $class ) . '"';
764
- if ( !empty( $params['style'] )
765
- && !in_array( $field['type'],
766
- array('date', 'file', 'image', 'email', 'url', 'wysiwyg') ) ) {
767
- $output .= ' style="' . $params['style'] . '"';
768
- }
769
- $output .= '>' . stripslashes( strval( $content ) ) . '</div>';
770
- return $output;
771
- }
772
- $output = '<span class="' . implode( ' ', $class ) . '"';
773
- if ( !empty( $params['style'] )
774
- && !in_array( $field['type'],
775
- array('date', 'file', 'image', 'email', 'url', 'wysiwyg') ) ) {
776
- $output .= ' style="' . $params['style'] . '"';
777
- }
778
- $output .= '>' . stripslashes( strval( $content ) ) . '</span>';
779
- return $output;
780
- } else {
781
- return stripslashes( strval( $content ) );
782
- }
783
- }
784
-
785
- // Add a filter to handle Views queries with checkboxes.
786
-
787
- add_filter( 'wpv_filter_query', 'wpcf_views_post_query', 12, 2 ); // after custom fields.
788
- add_filter( 'wpv_filter_taxonomy_query', 'wpcf_views_term_query', 42, 2 ); // after termmeta fields.
789
- add_filter( 'wpv_filter_user_query', 'wpcf_views_user_query', 72, 2 ); // after usermeta fields.
790
-
791
- function wpcf_views_post_query( $query, $view_settings ) {
792
- $query = wpcf_views_query( $query, $view_settings, 'wpcf-fields' );
793
- return $query;
794
- }
795
-
796
- function wpcf_views_term_query( $query, $view_settings ) {
797
- $query = wpcf_views_query( $query, $view_settings, 'wpcf-termmeta' );
798
- return $query;
799
- }
800
-
801
- function wpcf_views_user_query( $query, $view_settings ) {
802
- $query = wpcf_views_query( $query, $view_settings, 'wpcf-usermeta' );
803
- return $query;
804
- }
805
-
806
- /**
807
- * Filter to handle Views queries with checkboxes.
808
- *
809
- * @todo DOCUMENT THIS!
810
- *
811
- * @param type $query
812
- * @param type $view_settings
813
- * @return string
814
- */
815
- function wpcf_views_query( $query, $view_settings, $meta_key = 'wpcf-fields' ) {
816
-
817
- if ( ! in_array( $meta_key, array( 'wpcf-fields', 'wpcf-usermeta', 'wpcf-termmeta' ) ) ) {
818
- return $query;
819
- }
820
-
821
- $meta_filter_required = false;
822
-
823
- $opt = get_option( $meta_key );
824
-
825
- if ( isset( $query['meta_query'] ) ) {
826
- foreach ( $query['meta_query'] as $index => $meta ) {
827
- if ( is_array( $meta ) && isset( $meta['key'] ) ) {
828
- $field_name = $meta['key'];
829
- if ( _wpcf_is_checkboxes_field( $field_name, $meta_key ) ) {
830
-
831
- $orginal = $query['meta_query'][$index];
832
-
833
- unset($query['meta_query'][$index]);
834
-
835
- // We'll use SQL regexp to find the checked items.
836
- // Note that we are creating something here that
837
- // then gets modified to a proper SQL REGEXP in
838
- // the get_meta_sql filter.
839
-
840
- $field_name = substr( $field_name, 5 );
841
-
842
- $meta_filter_required = true;
843
-
844
- /* According to http://codex.wordpress.org/Class_Reference/WP_Meta_Query#Accepted_Arguments,
845
- * $meta['value'] can be an array or a string. In case of a string we additionally allow
846
- * multiple comma-separated values. */
847
- if ( is_array( $meta['value'] ) ) {
848
- $values = $meta['value'];
849
- // Add comma-separated combinations of meta values, since a legit value containing a comma might have been removed
850
- $values = _wpcf_views_query_recursive_add_comma_meta_values( $values );
851
- } elseif ( is_string( $meta['value'] ) ) {
852
- $values = explode( ',', $meta['value'] );
853
- if ( count( $values ) > 1 ) {
854
- // Add comma-separated combinations of meta values, since a legit value containing a comma might have been removed
855
- $values = _wpcf_views_query_recursive_add_comma_meta_values( $values );
856
- // Also add the original one, as it might be a legitimate value containing several commas instead of a comma-separated list
857
- $values[] = $meta['value'];
858
- }
859
- } else {
860
- // This can happen if $meta['value'] is a number, for example.
861
- $values = array( $meta['value'] );
862
- }
863
- $options = $opt[$field_name]['data']['options'];
864
-
865
- global $wp_version;
866
-
867
- if ( version_compare( $wp_version, '4.1', '<' ) ) {
868
- // We can not use nested meta_query entries
869
- foreach ( $values as $value ) {
870
- foreach ( $options as $key => $option ) {
871
- if (
872
- $option['title'] == $value
873
- || (
874
- isset( $option['set_value'] )
875
- && $option['set_value'] == $value
876
- )
877
- ) {
878
- $query['meta_query'][] = array(
879
- 'key' => $meta['key'],
880
- 'compare' => in_array( $orginal['compare'], array( '!=', 'NOT LIKE', 'NOT IN' ) ) ? 'NOT LIKE' : 'LIKE',
881
- 'value' => $key,
882
- 'type' => 'CHAR',
883
- );
884
- break;
885
- }
886
- }
887
- }
888
- } else {
889
- // We can use nested meta_query entries
890
- if ( count( $values ) < 2 ) {
891
- // Only one value to filter by, so no need to add nested meta_query entries
892
- foreach ( $values as $value ) {
893
- foreach ( $options as $key => $option ) {
894
- if (
895
- $option['title'] == $value
896
- || (
897
- isset( $option['set_value'] )
898
- && $option['set_value'] == $value
899
- )
900
- ) {
901
- $query['meta_query'][] = array(
902
- 'key' => $meta['key'],
903
- 'compare' => in_array( $orginal['compare'], array( '!=', 'NOT LIKE', 'NOT IN' ) ) ? 'NOT LIKE' : 'LIKE',
904
- 'value' => $key,
905
- 'type' => 'CHAR',
906
- );
907
- break;
908
- }
909
- }
910
- }
911
- } else {
912
- // We will translate each value into a meta_query clause and add them all as a nested meta_query entry
913
- $inner_relation = in_array( $orginal['compare'], array( '!=', 'NOT LIKE', 'NOT IN' ) ) ? 'AND' : 'OR';
914
- $inner_compare = in_array( $orginal['compare'], array( '!=', 'NOT LIKE', 'NOT IN' ) ) ? 'NOT LIKE' : 'LIKE';
915
- $inner_meta_query = array(
916
- 'relation' => $inner_relation
917
- );
918
- foreach ( $values as $value ) {
919
- foreach ( $options as $key => $option ) {
920
- if (
921
- $option['title'] == $value
922
- || (
923
- isset( $option['set_value'] )
924
- && $option['set_value'] == $value
925
- )
926
- ) {
927
- $inner_meta_query[] = array(
928
- 'key' => $meta['key'],
929
- 'compare' => $inner_compare,
930
- 'value' => $key,
931
- 'type' => 'CHAR',
932
- );
933
- break;
934
- }
935
- }
936
- }
937
- $query['meta_query'][] = $inner_meta_query;
938
- }
939
- }
940
- }
941
- }
942
- }
943
- }
944
-
945
- if ( $meta_filter_required ) {
946
- add_filter( 'get_meta_sql', 'wpcf_views_get_meta_sql', 10, 6 );
947
- }
948
- return $query;
949
- }
950
-
951
- function _wpcf_is_checkboxes_field( $field_name, $key = 'wpcf-fields' ) {
952
- if ( ! in_array( $key, array( 'wpcf-fields', 'wpcf-usermeta', 'wpcf-termmeta' ) ) ) {
953
- return false;
954
- }
955
- $opt = get_option( $key );
956
- if ( $opt && strpos( $field_name, 'wpcf-' ) === 0 ) {
957
- $field_name = substr( $field_name, 5 );
958
- if ( isset( $opt[$field_name]['type'] ) ) {
959
- $field_type = strtolower( $opt[$field_name]['type'] );
960
- if ( $field_type == 'checkboxes' ) {
961
- return true;
962
- }
963
- }
964
- }
965
-
966
- return false;
967
- }
968
-
969
- function _wpcf_views_query_recursive_add_comma_meta_values( $values ) {
970
- $values_orig = array_reverse( $values );
971
- $values_aux = array();
972
- $values_end = array();
973
- if ( count( $values ) > 1 ) {
974
- foreach ( $values_orig as $v_key => $v_val ) {
975
- if ( count( $values_aux ) > 0 ) {
976
- foreach ( $values_aux as &$v_aux ) {
977
- $values_end[] = $v_val . ',' . $v_aux;
978
- $v_aux = $v_val . ',' . $v_aux;
979
- }
980
- }
981
- $values_end[] = $v_val;
982
- $values_aux[] = $v_val;
983
- }
984
- } else {
985
- $values_end = $values;
986
- }
987
- return $values_end;
988
- }
989
-
990
- /**
991
- * @todo Will someone document this?
992
- * @param type $clause
993
- * @param type $queries
994
- * @param type $type
995
- * @param type $primary_table
996
- * @param type $primary_id_column
997
- * @param type $context
998
- * @return type
999
- */
1000
- function wpcf_views_get_meta_sql( $clause, $queries, $type, $primary_table,
1001
- $primary_id_column, $context ) {
1002
-
1003
- // Look for the REGEXP code we added and covert it to a proper SQL REGEXP
1004
- $regex = '/= \'REGEXP\(([^\)]*)\)\'/siU';
1005
-
1006
- if ( preg_match_all( $regex, $clause['where'], $matches, PREG_SET_ORDER ) ) {
1007
- foreach ( $matches as $match ) {
1008
- $clause['where'] = str_replace( $match[0],
1009
- 'REGEXP \'' . $match[1] . '\'', $clause['where'] );
1010
- }
1011
- }
1012
-
1013
- remove_filter( 'get_meta_sql', 'wpcf_views_get_meta_sql', 10, 6 );
1014
-
1015
- return $clause;
1016
- }
1017
-
1018
-
1019
- /** Fix shortcode rendering for WP 4.2.3 security fixes.
1020
- * We now pre-process before the main do_shortcode fitler so that we
1021
- * can still use shortcodes in html attributes
1022
- * like <img src="[types field="image-field"][/types]">
1023
- * adding filter with priority 5 before do_shortcode and other WP standard filters
1024
- *
1025
- * Heavily inspired in do_shortcodes_in_html_tags
1026
- */
1027
-
1028
- add_filter( 'the_content', 'wpcf_preprocess_shortcodes_in_html_elements', 5 );
1029
-
1030
- function wpcf_preprocess_shortcodes_in_html_elements( $content ) {
1031
-
1032
- $shortcode = "/\\[types.*?\\](.*?)\\[\\/types\\]/is";
1033
-
1034
- // Normalize entities in unfiltered HTML before adding placeholders.
1035
- $trans = array( '&#91;' => '&#091;', '&#93;' => '&#093;' );
1036
- $content = strtr( $content, $trans );
1037
-
1038
- $textarr = wpcf_html_split( $content );
1039
-
1040
- foreach ( $textarr as &$element ) {
1041
- if ( '' == $element || '<' !== $element[0] ) {
1042
- continue;
1043
- }
1044
-
1045
- $noopen = false === strpos( $element, '[' );
1046
- $noclose = false === strpos( $element, ']' );
1047
- if ( $noopen || $noclose ) {
1048
- // This element does not contain shortcodes.
1049
- continue;
1050
- }
1051
-
1052
- if ( '<!--' === substr( $element, 0, 4 ) || '<![CDATA[' === substr( $element, 0, 9 ) ) {
1053
- continue;
1054
- }
1055
-
1056
- $counts = preg_match_all( $shortcode, $element, $matches );
1057
-
1058
- if ( $counts > 0 ) {
1059
- foreach ( $matches[0] as $index => &$match ) {
1060
-
1061
- $string_to_replace = $match;
1062
-
1063
- $inner_content = $matches[1][ $index ];
1064
- if ( $inner_content ) {
1065
- $new_inner_content = wpcf_preprocess_shortcodes_in_html_elements( $inner_content );
1066
- $match = str_replace( $inner_content, $new_inner_content, $match );
1067
- }
1068
-
1069
- $replacement = do_shortcode( $match );
1070
- $element = str_replace( $string_to_replace, $replacement, $element );
1071
-
1072
- }
1073
- }
1074
-
1075
- }
1076
-
1077
- $content = implode( '', $textarr );
1078
-
1079
- return $content;
1080
- }
1081
-
1082
- /**
1083
- * Separate HTML elements and comments from the text. Needed for wpcf_preprocess_shortcodes_in_html_elements.
1084
- *
1085
- * Heavily inspired in wp_html_split
1086
- *
1087
- * @param string $input The text which has to be formatted.
1088
- * @return array The formatted text.
1089
- */
1090
- function wpcf_html_split( $input ) {
1091
- static $regex;
1092
-
1093
- if ( ! isset( $regex ) ) {
1094
- $comments =
1095
- '!' // Start of comment, after the <.
1096
- . '(?:' // Unroll the loop: Consume everything until --> is found.
1097
- . '-(?!->)' // Dash not followed by end of comment.
1098
- . '[^\-]*+' // Consume non-dashes.
1099
- . ')*+' // Loop possessively.
1100
- . '(?:-->)?'; // End of comment. If not found, match all input.
1101
-
1102
- $cdata =
1103
- '!\[CDATA\[' // Start of comment, after the <.
1104
- . '[^\]]*+' // Consume non-].
1105
- . '(?:' // Unroll the loop: Consume everything until ]]> is found.
1106
- . '](?!]>)' // One ] not followed by end of comment.
1107
- . '[^\]]*+' // Consume non-].
1108
- . ')*+' // Loop possessively.
1109
- . '(?:]]>)?'; // End of comment. If not found, match all input.
1110
-
1111
- $regex =
1112
- '/(' // Capture the entire match.
1113
- . '<' // Find start of element.
1114
- . '(?(?=!--)' // Is this a comment?
1115
- . $comments // Find end of comment.
1116
- . '|'
1117
- . '(?(?=!\[CDATA\[)' // Is this a comment?
1118
- . $cdata // Find end of comment.
1119
- . '|'
1120
- . '[^>]*>?' // Find end of element. If not found, match all input.
1121
- . ')'
1122
- . ')'
1123
- . ')/s';
1124
- }
1125
-
1126
- return preg_split( $regex, $input, -1, PREG_SPLIT_DELIM_CAPTURE );
1127
- }
1128
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/functions.php DELETED
@@ -1,1076 +0,0 @@
1
- <?php
2
- /*
3
- * Basic and init functions.
4
- * Since Types 1.2 moved from /embedded/types.php
5
- *
6
- *
7
- */
8
-
9
- /**
10
- * Caches get_post_meta() calls.
11
- *
12
- * @staticvar array $cache
13
- * @param type $post_id
14
- * @param type $meta_key
15
- * @param type $single
16
- * @return string
17
- */
18
- function wpcf_get_post_meta($post_id, $meta_key, $single)
19
- {
20
- static $cache = array();
21
-
22
- if ( !isset( $cache[$post_id] ) ) {
23
- $cache[$post_id] = get_post_custom( $post_id );
24
- }
25
- if ( isset( $cache[$post_id][$meta_key] ) ) {
26
- if ( $single && isset( $cache[$post_id][$meta_key][0] ) ) {
27
- return maybe_unserialize( $cache[$post_id][$meta_key][0] );
28
- } elseif ( !$single && !empty( $cache[$post_id][$meta_key] ) ) {
29
- return maybe_unserialize( $cache[$post_id][$meta_key] );
30
- }
31
- }
32
- return '';
33
- }
34
-
35
- /**
36
- * Calculates relative path for given file.
37
- *
38
- * @param type $file Absolute path to file
39
- * @return string Relative path
40
- */
41
- function wpcf_get_file_relpath($file)
42
- {
43
- $is_https = isset( $_SERVER['HTTPS'] ) && strtolower( $_SERVER['HTTPS'] ) == 'on';
44
- $http_protocol = $is_https ? 'https' : 'http';
45
- $base_root = $http_protocol . '://' . $_SERVER['HTTP_HOST'];
46
- $base_url = $base_root;
47
- $dir = rtrim( dirname( $file ), '\/' );
48
- if ( $dir ) {
49
- $base_path = $dir;
50
- $base_url .= $base_path;
51
- $base_path .= '/';
52
- } else {
53
- $base_path = '/';
54
- }
55
- $relpath = $base_root
56
- . str_replace(
57
- str_replace( '\\', '/',
58
- realpath( $_SERVER['DOCUMENT_ROOT'] ) )
59
- , '', str_replace( '\\', '/', dirname( $file ) )
60
- );
61
- return $relpath;
62
- }
63
-
64
- /**
65
- * after_setup_theme hook.
66
- */
67
- function wpcf_embedded_after_setup_theme_hook()
68
- {
69
- $custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
70
- if ( !empty( $custom_types ) ) {
71
- foreach ( $custom_types as $post_type => $data ) {
72
- if ( !empty( $data['supports']['thumbnail'] ) ) {
73
- if ( !current_theme_supports( 'post-thumbnails' ) ) {
74
- add_theme_support( 'post-thumbnails' );
75
- remove_post_type_support( 'post', 'thumbnail' );
76
- remove_post_type_support( 'page', 'thumbnail' );
77
- } else {
78
- add_post_type_support( $post_type, 'thumbnail' );
79
- }
80
- }
81
- }
82
- }
83
- }
84
-
85
- /**
86
- * Inits custom types and taxonomies.
87
- */
88
- function wpcf_init_custom_types_taxonomies()
89
- {
90
- // register post types first
91
- $custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
92
- if ( !empty( $custom_types ) ) {
93
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/custom-types.php';
94
- wpcf_custom_types_init();
95
- }
96
-
97
- // and than taxonomies, because register_taxonomy_for_object_type() checks if post type is available
98
- $custom_taxonomies = get_option( WPCF_OPTION_NAME_CUSTOM_TAXONOMIES, array() );
99
- if ( !empty( $custom_taxonomies ) ) {
100
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/custom-taxonomies.php';
101
- wpcf_custom_taxonomies_init();
102
- }
103
-
104
- }
105
-
106
- /**
107
- * Returns meta_key type for specific field type.
108
- *
109
- * @param type $type
110
- * @return type
111
- */
112
- function types_get_field_type($type)
113
- {
114
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
115
- $data = wpcf_fields_type_action( $type );
116
- if ( !empty( $data['meta_key_type'] ) ) {
117
- return $data['meta_key_type'];
118
- }
119
- return 'CHAR';
120
- }
121
-
122
- /**
123
- * Imports settings.
124
- *
125
- * @fixme Are we touching this on EVERY page load?!
126
- * @since unknown
127
- */
128
- function wpcf_embedded_check_import()
129
- {
130
-
131
- if( !defined( 'WPCF_EMBEDDED_CONFIG_ABSPATH' ) ) {
132
-
133
- /**
134
- * Allow for overriding path to settings.php and settings.xml by a third party.
135
- *
136
- * Falls back to WPCF_EMBEDDED_ABSPATH if not defined.
137
- *
138
- * @since 1.9.1
139
- */
140
- define( 'WPCF_EMBEDDED_CONFIG_ABSPATH', WPCF_EMBEDDED_ABSPATH );
141
- }
142
-
143
- if ( file_exists( WPCF_EMBEDDED_CONFIG_ABSPATH . '/settings.php' ) ) {
144
- require_once WPCF_EMBEDDED_ABSPATH . '/admin.php';
145
- require_once WPCF_EMBEDDED_CONFIG_ABSPATH . '/settings.php';
146
- $dismissed = get_option( 'wpcf_dismissed_messages', array() );
147
- if ( in_array( $timestamp, $dismissed ) ) {
148
- return false;
149
- }
150
- if ( $timestamp > get_option( 'wpcf-types-embedded-import', 0 ) ) {
151
- if (
152
- isset( $_GET['types-embedded-import'] )
153
- && isset( $_GET['_wpnonce'] )
154
- && wp_verify_nonce( $_GET['_wpnonce'], 'embedded-import')
155
- ) {
156
- if ( file_exists( WPCF_EMBEDDED_CONFIG_ABSPATH . '/settings.xml' ) ) {
157
- $_POST['overwrite-groups'] = 1;
158
- $_POST['overwrite-fields'] = 1;
159
- $_POST['overwrite-types'] = 1;
160
- $_POST['overwrite-tax'] = 1;
161
- $_POST['post_relationship'] = 1;
162
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
163
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/import-export.php';
164
- $data = @file_get_contents( WPCF_EMBEDDED_CONFIG_ABSPATH . '/settings.xml' );
165
- wpcf_admin_import_data( $data, false, 'types-auto-import' );
166
- update_option( 'wpcf-types-embedded-import', $timestamp );
167
- wp_safe_redirect( esc_url_raw(admin_url() ));
168
- } else {
169
- $code = __( 'settings.xml file missing', 'wpcf' );
170
- wpcf_admin_message( $code, 'error' );
171
- }
172
- }
173
- else {
174
- $link = "<a href=\"" . admin_url( '?types-embedded-import=1&amp;_wpnonce=' . wp_create_nonce( 'embedded-import' ) ) . "\">";
175
- $text = sprintf( __( 'You have Types import pending. %sClick here to import.%s %sDismiss message.%s', 'wpcf' ), $link, '</a>',
176
- "<a onclick=\"jQuery(this).parent().parent().fadeOut();\" class=\"wpcf-ajax-link\" href=\""
177
- . admin_url( 'admin-ajax.php?action=wpcf_ajax&amp;wpcf_action=dismiss_message&amp;id='
178
- . $timestamp . '&amp;_wpnonce=' . wp_create_nonce( 'dismiss_message' ) ) . "\">",
179
- '</a>' );
180
- wpcf_admin_message( $text );
181
- }
182
- }
183
- }
184
- }
185
-
186
- /**
187
- * Actions for outside fields control.
188
- *
189
- * @param string $action
190
- * @param array $args
191
- * @param string $post_type
192
- * @param string $option_name
193
- *
194
- * @return bool|array
195
- */
196
- function wpcf_types_cf_under_control( $action = 'add', $args = array(),
197
- $post_type = TYPES_CUSTOM_FIELD_GROUP_CPT_NAME, $option_name = 'wpcf-fields' ) {
198
- global $wpcf_types_under_control;
199
- $wpcf_types_under_control['errors'] = array();
200
- switch ( $action ) {
201
- case 'add':
202
- $fields = wpcf_admin_fields_get_fields( false, true, false,
203
- $option_name, false );
204
- foreach ( $args['fields'] as $field_id ) {
205
- $field_type = !empty( $args['type'] ) ? $args['type'] : 'textfield';
206
- if ( strpos( $field_id, md5( 'wpcf_not_controlled' ) ) !== false ) {
207
- $field_id_name = str_replace( '_' . md5( 'wpcf_not_controlled' ), '', $field_id );
208
- $field_id_add = preg_replace( '/^wpcf\-/', '', $field_id_name );
209
- $adding_field_with_wpcf_prefix = $field_id_add != $field_id_name;
210
-
211
- // Activating field that previously existed in Types
212
- if ( array_key_exists( $field_id_add, $fields ) ) {
213
- $fields[$field_id_add]['data']['disabled'] = 0;
214
- } else { // Adding from outside
215
- $fields[$field_id_add]['id'] = $field_id_add;
216
- $fields[$field_id_add]['type'] = $field_type;
217
- if ($adding_field_with_wpcf_prefix) {
218
- $fields[$field_id_add]['name'] = $field_id_add;
219
- $fields[$field_id_add]['slug'] = $field_id_add;
220
- } else {
221
- $fields[$field_id_add]['name'] = $field_id_name;
222
- $fields[$field_id_add]['slug'] = $field_id_name;
223
- }
224
- $fields[$field_id_add]['description'] = '';
225
- $fields[$field_id_add]['data'] = array();
226
- if ($adding_field_with_wpcf_prefix) {
227
- // This was most probably a previous Types field
228
- // let's take full control
229
- $fields[$field_id_add]['data']['controlled'] = 0;
230
- } else {
231
- // @TODO WATCH THIS! MUST NOT BE DROPPED IN ANY CASE
232
- $fields[$field_id_add]['data']['controlled'] = 1;
233
- }
234
- }
235
- $unset_key = array_search( $field_id, $args['fields'] );
236
- if ( $unset_key !== false ) {
237
- unset( $args['fields'][$unset_key] );
238
- $args['fields'][$unset_key] = $field_id_add;
239
- }
240
- }
241
- }
242
- wpcf_admin_fields_save_fields( $fields, true, $option_name );
243
- return $args['fields'];
244
- break;
245
-
246
- case 'check_exists':
247
- $fields = wpcf_admin_fields_get_fields( false, true, false,
248
- $option_name, false );
249
- $field = $args;
250
- if ( array_key_exists( $field, $fields ) && empty( $fields[$field]['data']['disabled'] ) ) {
251
- return true;
252
- }
253
- return false;
254
- break;
255
-
256
- case 'check_outsider':
257
- $fields = wpcf_admin_fields_get_fields( false, true, false,
258
- $option_name, false );
259
- $field = $args;
260
- if ( array_key_exists( $field, $fields ) && !empty( $fields[$field]['data']['controlled'] ) ) {
261
- return true;
262
- }
263
- return false;
264
- break;
265
-
266
- default:
267
- break;
268
- }
269
- }
270
-
271
- /**
272
- * Controlls meta prefix.
273
- *
274
- * @param array $field
275
- */
276
- function wpcf_types_get_meta_prefix( $field = array() )
277
- {
278
- if ( empty( $field ) ) {
279
- return WPCF_META_PREFIX;
280
- }
281
- if ( !empty( $field['data']['controlled'] ) ) {
282
- return '';
283
- }
284
- return WPCF_META_PREFIX;
285
- }
286
-
287
- /**
288
- * Compares WP versions
289
- * @global type $wp_version
290
- * @param type $version
291
- * @param type $operator
292
- * @return type
293
- */
294
- function wpcf_compare_wp_version($version = '3.2.1', $operator = '>')
295
- {
296
- global $wp_version;
297
- return version_compare( $wp_version, $version, $operator );
298
- }
299
-
300
- /**
301
- * Gets post type with data to which belongs.
302
- *
303
- * @param type $post_type
304
- * @return type
305
- */
306
- function wpcf_pr_get_belongs($post_type)
307
- {
308
- require_once WPCF_EMBEDDED_ABSPATH . '/includes/post-relationship.php';
309
- return wpcf_pr_admin_get_belongs( $post_type );
310
- }
311
-
312
- /**
313
- * Gets all post types and data that owns.
314
- *
315
- * @param type $post_type
316
- * @return type
317
- */
318
- function wpcf_pr_get_has($post_type)
319
- {
320
- require_once WPCF_EMBEDDED_ABSPATH . '/includes/post-relationship.php';
321
- return wpcf_pr_admin_get_has( $post_type );
322
- }
323
-
324
- /**
325
- * Gets individual post ID to which queried post belongs.
326
- *
327
- * @param type $post_id
328
- * @param type $post_type Post Type of owner
329
- * @return type
330
- */
331
- function wpcf_pr_post_get_belongs($post_id, $post_type)
332
- {
333
- return get_post_meta( $post_id, '_wpcf_belongs_' . $post_type . '_id', true );
334
- }
335
-
336
- /**
337
- * Gets all posts that belong to queried post, grouped by post type.
338
- *
339
- * @param type $post_id
340
- * @param type $post_type
341
- * @return type
342
- */
343
- function wpcf_pr_post_get_has($post_id, $post_type_q = null)
344
- {
345
- $post_type = get_post_type( $post_id );
346
- $has = array_keys( wpcf_pr_get_has( $post_type ) );
347
- $add = is_null( $post_type_q ) ? '&post_type=any' : '&post_type=' . $post_type_q;
348
- $posts = get_posts( 'numberposts=-1&post_status=null&meta_key=_wpcf_belongs_'
349
- . $post_type . '_id&meta_value=' . $post_id . $add );
350
-
351
- $results = array();
352
- foreach ( $posts as $post ) {
353
- if ( !in_array( $post->post_type, $has ) ) {
354
- continue;
355
- }
356
- $results[$post->post_type][] = $post;
357
- }
358
- return is_null( $post_type_q ) ? $results : array_shift( $results );
359
- }
360
-
361
- /**
362
- * Gets settings.
363
- */
364
- function wpcf_get_settings($specific = false)
365
- {
366
- $defaults = array(
367
- 'add_resized_images_to_library' => 0,
368
- 'register_translations_on_import' => 1,
369
- 'images_remote' => 0,
370
- 'images_remote_cache_time' => '36',
371
- 'help_box' => 'by_types',
372
- 'hide_standard_custom_fields_metabox' => 'show',
373
- 'postmeta_unfiltered_html' => 'on',
374
- 'usermeta_unfiltered_html' => 'on',
375
- );
376
- $settings = wp_parse_args( get_option( 'wpcf_settings', array() ), $defaults );
377
- $settings = apply_filters( 'types_settings', $settings );
378
- if ( $specific ) {
379
- return isset( $settings[$specific] ) ? $settings[$specific] : false;
380
- }
381
- return $settings;
382
- }
383
-
384
- /**
385
- * Saves settings.
386
- */
387
- function wpcf_save_settings($settings)
388
- {
389
- update_option( 'wpcf_settings', $settings );
390
- }
391
-
392
- /**
393
- * Check if it can be repetitive
394
- * @param type $field
395
- * @return type
396
- */
397
- function wpcf_admin_can_be_repetitive($type)
398
- {
399
- return !in_array( $type,
400
- array('checkbox', 'checkboxes', 'wysiwyg', 'radio', 'select') );
401
- }
402
-
403
- /**
404
- * Check if field is repetitive
405
- * @param type $type
406
- * @return type
407
- */
408
- function wpcf_admin_is_repetitive($field)
409
- {
410
- if ( !isset( $field['data']['repetitive'] ) || !isset( $field['type'] ) ) {
411
- return false;
412
- }
413
- $check = intval( $field['data']['repetitive'] );
414
- return !empty( $check ) && wpcf_admin_can_be_repetitive( $field['type'] );
415
- }
416
-
417
- /**
418
- * Returns an unique string identifier every time it is called.
419
- *
420
- * @staticvar array $cache
421
- * @param string $cache_key
422
- * @return string Unique identifier
423
- * @since unknown
424
- */
425
- function wpcf_unique_id($cache_key) {
426
- $cache_key = md5( strval( $cache_key ) . strval( time() ) . rand() );
427
- static $cache = array();
428
- if ( ! isset( $cache[ $cache_key ] ) ) {
429
- $cache[ $cache_key ] = 1;
430
- } else {
431
- $cache[ $cache_key ] += 1;
432
- }
433
-
434
- return $cache_key . '-' . $cache[ $cache_key ];
435
- }
436
-
437
- /**
438
- * Determine if platform is Win
439
- *
440
- * @return type
441
- */
442
- function wpcf_is_windows()
443
- {
444
- global $wpcf;
445
- $is_windows = PHP_OS == "WIN32" || PHP_OS == "WINNT";
446
- if ( isset( $wpcf->debug ) ) {
447
- $wpcf->debug->is_windows = $is_windows;
448
- }
449
- return $is_windows;
450
- }
451
-
452
- /**
453
- * Parses array as string
454
- *
455
- * @param type $array
456
- */
457
- function wpcf_parse_array_to_string($array)
458
- {
459
- $s = '';
460
- foreach ( (array) $array as $param => $value ) {
461
- $s .= strval( $param ) . '=' . urlencode( strval( $value ) ) . '&';
462
- }
463
- return trim( $s, '&' );
464
- }
465
-
466
- /**
467
- * Get main post ID.
468
- *
469
- * @param type $context
470
- * @return type
471
- */
472
- function wpcf_get_post_id($context = 'group')
473
- {
474
- if ( !is_admin() ) {
475
- /*
476
- *
477
- * TODO Check if frontend is fine (rendering children).
478
- * get_post() previously WP 3.5 requires $post_id
479
- */
480
- $post_id = null;
481
- if ( wpcf_compare_wp_version( '3.5', '<' ) ) {
482
- global $post;
483
- $post_id = !empty( $post->ID ) ? $post->ID : -1;
484
- }
485
- $_post = get_post( $post_id );
486
- return !empty( $_post->ID ) ? $_post->ID : -1;
487
- }
488
- /*
489
- * TODO Explore possible usage for $context
490
- */
491
- $post = wpcf_admin_get_edited_post();
492
- return empty( $post->ID ) ? -1 : $post->ID;
493
- }
494
-
495
- /**
496
- * Basic scripts
497
- */
498
- function wpcf_enqueue_scripts()
499
- {
500
- if( !is_admin() )
501
- return;
502
-
503
- if ( !wpcf_is_embedded() ) {
504
- /**
505
- * Basic JS
506
- */
507
- wp_register_script(
508
- 'wpcf-js',
509
- WPCF_RES_RELPATH . '/js/basic.js',
510
- array('jquery', 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-tabs', 'toolset-colorbox'),
511
- WPCF_VERSION
512
- );
513
- wp_localize_script(
514
- 'wpcf-js',
515
- 'wpcf_js',
516
- array(
517
- 'close' => __('Close', 'wpcf'),
518
- )
519
- );
520
- wp_enqueue_script('wpcf-js');
521
-
522
- if( function_exists( 'wpcf_admin_add_js_settings' ) ) {
523
- wpcf_admin_add_js_settings( 'wpcf_nonce_toggle_group',
524
- '\'' . wp_create_nonce( 'group_form_collapsed' ) . '\'' );
525
- }
526
- }
527
- /**
528
- * Basic JS
529
- */
530
- wp_enqueue_script(
531
- 'wpcf-js-embedded',
532
- WPCF_EMBEDDED_RES_RELPATH . '/js/basic.js',
533
- array('jquery', 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-tabs', 'select2'),
534
- WPCF_VERSION
535
- );
536
- /*
537
- *
538
- * Basic CSS
539
- */
540
- wp_enqueue_style( 'wpcf-css-embedded' );
541
-
542
- /*
543
- *
544
- * Other components
545
- */
546
- if ( !defined( 'WPTOOLSET_FORMS_ABSPATH' ) ) {
547
- // Repetitive
548
- wp_enqueue_script(
549
- 'wpcf-repeater',
550
- WPCF_EMBEDDED_RES_RELPATH . '/js/repetitive.js',
551
- array('wpcf-js-embedded'), WPCF_VERSION
552
- );
553
- wp_enqueue_style(
554
- 'wpcf-repeater',
555
- WPCF_EMBEDDED_RES_RELPATH . '/css/repetitive.css',
556
- array('wpcf-css-embedded'), WPCF_VERSION
557
- );
558
- }
559
-
560
- // Conditional
561
- wp_enqueue_script( 'types-conditional' );
562
- // RTL
563
- if ( is_rtl() ) {
564
- wp_enqueue_style(
565
- 'wpcf-rtl', WPCF_EMBEDDED_RES_RELPATH . '/css/rtl.css',
566
- array('wpcf-css-embedded'), WPCF_VERSION
567
- );
568
- }
569
-
570
- /**
571
- * select2
572
- */
573
- $select2_version = '3.5.2';
574
- if ( !wp_script_is('select2', 'registered') ) {
575
- wp_register_script(
576
- 'select2',
577
- WPCF_EMBEDDED_RELPATH. '/toolset/toolset-common/utility/js/select2.min.js',
578
- array( 'jquery' ),
579
- $select2_version
580
- );
581
- }
582
- if ( !wp_style_is('select2', 'registered') ) {
583
- wp_register_style(
584
- 'select2',
585
- WPCF_EMBEDDED_RELPATH. '/toolset/toolset-common/utility/css/select2/select2.css',
586
- array(),
587
- $select2_version
588
- );
589
- }
590
- if ( !wp_style_is('select2') ) {
591
- wp_enqueue_style('select2');
592
- }
593
-
594
- // Add JS settings
595
- wpcf_admin_add_js_settings( 'wpcfFormUniqueValuesCheckText',
596
- '\'' . __( 'Warning: same values selected', 'wpcf' ) . '\'' );
597
- wpcf_admin_add_js_settings( 'wpcfFormUniqueNamesCheckText',
598
- '\'' . __( 'Warning: field name already used', 'wpcf' ) . '\'' );
599
- wpcf_admin_add_js_settings( 'wpcfFormUniqueSlugsCheckText',
600
- '\'' . __( 'Warning: field slug already used', 'wpcf' ) . '\'' );
601
- wpcf_admin_add_js_settings( 'wpcfFormUsedOrReservedSlug',
602
- '\'' . __( 'You cannot use this slug because it is already used or a reserved word. Please choose a different slug.', 'wpcf' ) . '\'' );
603
- }
604
-
605
- /**
606
- * Load all scripts required on edit post screen.
607
- *
608
- * @since 1.2.1
609
- * @todo Make loading JS more clear for all components.
610
- */
611
- function wpcf_edit_post_screen_scripts()
612
- {
613
- wpcf_enqueue_scripts();
614
- // TODO Switch to 1.11.1 jQuery Validation
615
- // wp_enqueue_script( 'types-js-validation' );
616
- if ( !defined( 'WPTOOLSET_FORMS_ABSPATH' ) ) {
617
- wp_enqueue_script( 'wpcf-form-validation',
618
- WPCF_EMBEDDED_RES_RELPATH . '/js/'
619
- . 'jquery-form-validation/jquery.validate.js', array('jquery'),
620
- WPCF_VERSION );
621
- wp_enqueue_script( 'wpcf-form-validation-additional',
622
- WPCF_EMBEDDED_RES_RELPATH . '/js/'
623
- . 'jquery-form-validation/additional-methods.min.js',
624
- array('jquery'), WPCF_VERSION );
625
- }
626
- wp_enqueue_style( 'wpcf-css-embedded',
627
- WPCF_EMBEDDED_RES_RELPATH . '/css/basic.css', array(), WPCF_VERSION );
628
- wp_enqueue_style( 'wpcf-fields-post',
629
- WPCF_EMBEDDED_RES_RELPATH . '/css/fields-post.css',
630
- array('wpcf-css-embedded'), WPCF_VERSION );
631
- wp_enqueue_style( 'wpcf-usermeta',
632
- WPCF_EMBEDDED_RES_RELPATH . '/css/usermeta.css',
633
- array('wpcf-css-embedded'), WPCF_VERSION );
634
- wp_enqueue_script( 'toolset-colorbox' );
635
- wp_enqueue_style( 'toolset-colorbox' );
636
- wp_enqueue_style( 'font-awesome' );
637
- }
638
-
639
- /**
640
- * Check if running embedded version.
641
- *
642
- * @return type
643
- */
644
- function wpcf_is_embedded()
645
- {
646
- return defined( 'WPCF_RUNNING_EMBEDDED' ) && WPCF_RUNNING_EMBEDDED;
647
- }
648
-
649
- /**
650
- * Returns post type settings.
651
- *
652
- * @param type $post_type
653
- * @return type
654
- */
655
- function wpcf_get_custom_post_type_settings($item)
656
- {
657
- $custom = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
658
- return !empty( $custom[$item] ) ? $custom[$item] : array();
659
- }
660
-
661
- /**
662
- * Returns Taxonomy settings.
663
- *
664
- * @param type $taxonomy
665
- * @return type
666
- */
667
- function wpcf_get_custom_taxonomy_settings($item)
668
- {
669
- $custom = get_option( WPCF_OPTION_NAME_CUSTOM_TAXONOMIES, array() );
670
- return !empty( $custom[$item] ) ? $custom[$item] : array();
671
- }
672
-
673
- /**
674
- * Load JS and CSS for field type.
675
- *
676
- * Core function. Works and stable. Do not move or change.
677
- * If required, add hooks only.
678
- *
679
- * @staticvar array $cache
680
- * @param string $type
681
- * @return string
682
- */
683
- function wpcf_field_enqueue_scripts($type)
684
- {
685
- global $wpcf;
686
- static $cache = array();
687
-
688
- $config = wpcf_fields_type_action( $type );
689
-
690
- if ( !empty( $config ) ) {
691
-
692
- // Check if cached
693
- if ( isset( $cache[$config['id']] ) ) {
694
- return $cache[$config['id']];
695
- }
696
-
697
- // Use field object
698
- $wpcf->field->enqueue_script( $config );
699
- $wpcf->field->enqueue_style( $config );
700
-
701
- $cache[$config['id']] = $config;
702
-
703
- return $config;
704
- } else {
705
- $wpcf->debug->errors['missing_type_config'][] = $type;
706
- return array();
707
- }
708
-
709
- }
710
-
711
- /**
712
- * Get file URL.
713
- *
714
- * @uses WPCF_Path (functions taken from CRED_Loader)
715
- * @param type $file
716
- * @return type
717
- */
718
- function wpcf_get_file_url($file, $use_baseurl = true)
719
- {
720
- WPCF_Loader::loadClass( 'path' );
721
- return WPCF_Path::getFileUrl( $file, $use_baseurl );
722
- }
723
-
724
- /**
725
- * Checks if timestamp supports negative values.
726
- *
727
- * @return type
728
- */
729
- function fields_date_timestamp_neg_supported()
730
- {
731
- return strtotime( 'Fri, 13 Dec 1950 20:45:54 UTC' ) === -601010046;
732
- }
733
-
734
- /**
735
- * Returns media size.
736
- *
737
- * @global type $content_width
738
- * @param type $widescreen
739
- * @return type
740
- */
741
- function wpcf_media_size($widescreen = false)
742
- {
743
- global $content_width;
744
- if ( !empty( $content_width ) ) {
745
- $height = $widescreen ? round( $content_width * 9 / 16 ) : round( $content_width * 3 / 4 );
746
- return array($content_width, $height);
747
- }
748
- return $widescreen ? array(450, 253) : array(450, 320);
749
- }
750
-
751
- /**
752
- * Validation wrapper.
753
- *
754
- * @param type $method
755
- * @param type $args
756
- * @return boolean
757
- */
758
- function types_validate($method, $args)
759
- {
760
- WPCF_Loader::loadClass( 'validation-cakephp' );
761
- if ( is_callable( array('Wpcf_Cake_Validation', $method) ) ) {
762
- if ( !is_array( $args ) ) {
763
- $args = array($args);
764
- }
765
- return @call_user_func_array( array('Wpcf_Cake_Validation', $method),
766
- $args );
767
- }
768
- return false;
769
- }
770
-
771
- /**
772
- * Gets post_types supported by specific group.
773
- *
774
- * @param int $group_id
775
- * @return array list of post types belongs to selected group
776
- */
777
- function wpcf_admin_get_post_types_by_group($group_id)
778
- {
779
- $post_types = get_post_meta( $group_id, '_wp_types_group_post_types', true );
780
- if ( $post_types == 'all' ) {
781
- return array();
782
- }
783
- $post_types = trim( $post_types, ',' );
784
- if ( empty($post_types) ) {
785
- return array();
786
- }
787
- $post_types = explode( ',', trim( $post_types, ',' ) );
788
- return $post_types;
789
- }
790
-
791
- /**
792
- * Filter return the array of Types fields
793
- *
794
- * Filter return the array of Types active fields
795
- *
796
- * @since x.x.x
797
- *
798
- * @param array fields Unused argument
799
- */
800
- add_filter('wpcf_get_all_fields_slugs', 'wpcf_get_all_fields_slugs');
801
-
802
- /**
803
- * Function return the array of Types fields.
804
- *
805
- * Function return the array of Types active fields slugs.
806
- *
807
- * @since x.x.x
808
- *
809
- * @return array List of slugs
810
- */
811
- function wpcf_get_all_fields_slugs($fields)
812
- {
813
- $post_meta_keys = array();
814
- foreach (wpcf_admin_fields_get_fields( true, true ) as $key => $data ) {
815
- $post_meta_keys[] = $data['meta_key'];
816
- }
817
- return $post_meta_keys;
818
- }
819
- /**
820
- * Get buuild in taxonomies.
821
- *
822
- * This is a wrapper for WordPress get_taxonomies() function. It gets public
823
- * build-in taxonomies.
824
- *
825
- * @since 1.9.0
826
- *
827
- * @param string $output The type of output to return, either taxonomy 'names'
828
- * or 'objects'. Default: 'names'
829
- *
830
- * @return array Array of taxonomies.
831
- *
832
- * @deprecated Use WPCF_Utils::get_builtin_taxonomies() instead.
833
- */
834
- function wpcf_get_builtin_in_taxonomies($output = 'names')
835
- {
836
- static $taxonomies = array();
837
- if ( empty( $taxonomies ) ) {
838
- $taxonomies = get_taxonomies(array('public' => true, '_builtin' => true), $output);
839
- }
840
- /**
841
- * remove post_format
842
- */
843
- if ( isset( $taxonomies['post_format'] ) ) {
844
- unset($taxonomies['post_format']);
845
- }
846
- return $taxonomies;
847
- }
848
-
849
- /**
850
- * Check is a build-in taxonomy
851
- *
852
- * Check is that build-in taxonomy?
853
- *
854
- * @since 1.9.0
855
- *
856
- * @parem string taxonomy slug
857
- * @return boolean is this build-in taxonomy
858
- */
859
- function wpcf_is_builtin_taxonomy($taxonomy)
860
- {
861
- switch($taxonomy) {
862
- case 'post_tag':
863
- case 'category':
864
- return true;
865
- }
866
- return in_array($taxonomy, wpcf_get_builtin_in_taxonomies());
867
- }
868
-
869
- function wpcf_get_builtin_in_post_types()
870
- {
871
- static $post_types = array();
872
- if ( empty( $post_types ) ) {
873
- $post_types = get_post_types(array('public' => true, '_builtin' => true));
874
- }
875
- return $post_types;
876
- }
877
-
878
- function wpcf_is_builtin_post_types($post_type)
879
- {
880
- $post_types = wpcf_get_builtin_in_post_types();
881
- return in_array($post_type, $post_types);
882
- }
883
-
884
- /**
885
- * Check is a build-in taxonomy
886
- *
887
- * Check is that build-in taxonomy?
888
- *
889
- * @since 1.9.0
890
- *
891
- * @parem string taxonomy slug
892
- * @return boolean is this build-in taxonomy
893
- */
894
- function wpcf_builtin_preview_only($ct, $form)
895
- {
896
- if ( isset($ct['_builtin']) && $ct['_builtin'] ) {
897
-
898
- foreach( $form as $key => $data ) {
899
- if ( !isset($data['#type'] ) ) {
900
- continue;
901
- }
902
- if ( isset($data['_builtin']) ) {
903
- switch( $data['#type'] ) {
904
- case 'textfield':
905
- case 'textarea':
906
- $form[$key]['#attributes']['readonly'] = 'readonly';
907
- break;
908
- default:
909
- }
910
- continue;
911
- }
912
- unset($form[$key]);
913
- }
914
- }
915
- return $form;
916
- }
917
-
918
-
919
- /**
920
- * Adds JS settings.
921
- *
922
- * @static array $settings
923
- * @param type $id
924
- * @param type $setting
925
- * @return string
926
- */
927
- function wpcf_admin_add_js_settings( $id, $setting = '' )
928
- {
929
- static $settings = array();
930
- $settings['wpcf_nonce_ajax_callback'] = '\'' . wp_create_nonce( 'execute' ) . '\'';
931
- $settings['wpcf_cookiedomain'] = '\'' . COOKIE_DOMAIN . '\'';
932
- $settings['wpcf_cookiepath'] = '\'' . COOKIEPATH . '\'';
933
- if ( $id == 'get' ) {
934
- $temp = $settings;
935
- $settings = array();
936
- return $temp;
937
- }
938
- $settings[$id] = $setting;
939
- }
940
-
941
- /**
942
- * Use sanitize_text_field recursively.
943
- *
944
- * @since 1.9.0
945
- *
946
- * @param mixed $data data to sanitize_text_field
947
- * @return mixed sanitized input
948
- */
949
- function sanitize_text_field_recursively($data)
950
- {
951
- if ( empty($data) ) {
952
- return $data;
953
- }
954
- if ( is_array( $data ) ) {
955
- foreach ( $data as $key => $value ) {
956
- if ( is_array( $value ) ) {
957
- $value = sanitize_text_field_recursively($value);
958
- } else {
959
- $value = sanitize_text_field($value);
960
- }
961
- $data[$key] = $value;
962
- }
963
- return $data;
964
- }
965
- return sanitize_text_field($data);
966
- }
967
-
968
- /**
969
- * Gets user roles supported by specific group.
970
- *
971
- * @param type $group_id
972
- * @return type
973
- */
974
- function wpcf_admin_get_groups_showfor_by_group($group_id) {
975
- $for_users = get_post_meta($group_id, '_wp_types_group_showfor', true);
976
- if (empty($for_users) || $for_users == 'all') {
977
- return array();
978
- }
979
- $for_users = explode(',', trim($for_users, ','));
980
- return $for_users;
981
- }
982
-
983
- // See wpv_get* counterparts in Views for description.
984
- // This is a temporary solution until these functions land in Toolset Common Library.
985
-
986
- function wpcf_getpost( $key, $default = '', $valid = null ) {
987
- return wpcf_getarr( $_POST, $key, $default, $valid );
988
- }
989
-
990
-
991
- function wpcf_getget( $key, $default = '', $valid = null ) {
992
- return wpcf_getarr( $_GET, $key, $default, $valid );
993
- }
994
-
995
-
996
- /**
997
- * @param mixed|array $source
998
- * @param string $key
999
- * @param mixed $default
1000
- * @param null|array $valid
1001
- *
1002
- * @return mixed
1003
- */
1004
- function wpcf_getarr( &$source, $key, $default = '', $valid = null ) {
1005
- if( isset( $source[ $key ] ) ) {
1006
- $val = $source[ $key ];
1007
- if( is_array( $valid ) && !in_array( $val, $valid ) ) {
1008
- return $default;
1009
- }
1010
-
1011
- return $val;
1012
- } else {
1013
- return $default;
1014
- }
1015
- }
1016
-
1017
-
1018
- /**
1019
- * Ensure that a variable is an array.
1020
- *
1021
- * @param mixed $array The original value.
1022
- * @param array $default Default value to use when no array is provided. This one should definitely be an array,
1023
- * otherwise the function doesn't make much sense.
1024
- * @return array The original array or a default value if no array is provided.
1025
- *
1026
- * @since 1.9
1027
- */
1028
- function wpcf_ensarr( $array, $default = array() ) {
1029
- return ( is_array( $array ) ? $array : $default );
1030
- }
1031
-
1032
-
1033
- /**
1034
- * Wrap a variable value in an array if it's not array already.
1035
- *
1036
- * @param mixed $input
1037
- * @return array
1038
- * @since 1.9.1
1039
- */
1040
- function wpcf_wraparr( $input ) {
1041
- return ( is_array( $input ) ? $input : array( $input ) );
1042
- }
1043
-
1044
-
1045
- /**
1046
- * Get a value from nested associative array.
1047
- *
1048
- * This function will try to traverse a nested associative array by the set of keys provided.
1049
- *
1050
- * E.g. if you have $source = array( 'a' => array( 'b' => array( 'c' => 'my_value' ) ) ) and want to reach 'my_value',
1051
- * you need to write: $my_value = wpcf_getnest( $source, array( 'a', 'b', 'c' ) );
1052
- *
1053
- * @param mixed|array $source The source array.
1054
- * @param string[] $keys Keys which will be used to access the final value.
1055
- * @param null|mixed $default Default value to return when the keys cannot be followed.
1056
- *
1057
- * @return mixed|null Value in the nested structure defined by keys or default value.
1058
- */
1059
- function wpcf_getnest( &$source, $keys = array(), $default = null ) {
1060
-
1061
- $current_value = $source;
1062
- while( !empty( $keys ) ) {
1063
- $current_key = array_shift( $keys );
1064
- $is_last_key = empty( $keys );
1065
-
1066
- $current_value = wpcf_getarr( $current_value, $current_key, null );
1067
-
1068
- if( $is_last_key ) {
1069
- return $current_value;
1070
- } elseif( !is_array( $current_value ) ) {
1071
- return $default;
1072
- }
1073
- }
1074
-
1075
- return $default;
1076
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/ajax.php DELETED
@@ -1,645 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * All AJAX calls go here.
5
- *
6
- * @todo auth
7
- */
8
- function wpcf_ajax_embedded() {
9
-
10
-
11
- if ( isset( $_REQUEST['_typesnonce'] ) ) {
12
- if ( !wp_verify_nonce( $_REQUEST['_typesnonce'], '_typesnonce' ) ) {
13
- die( 'Verification failed (1)' );
14
- }
15
- } else {
16
-
17
- if (
18
- !isset( $_REQUEST['_wpnonce'] )
19
- || !wp_verify_nonce( $_REQUEST['_wpnonce'], $_REQUEST['wpcf_action'] )
20
- ) {
21
- die( 'Verification failed (2)' );
22
- }
23
- }
24
-
25
- global $wpcf;
26
-
27
- switch ( $_REQUEST['wpcf_action'] ) {
28
-
29
- case 'insert_skype_button':
30
- if( ! current_user_can( 'edit_posts' ) ) {
31
- die( 'Authentication failed' );
32
- }
33
-
34
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields/skype.php';
35
- wpcf_fields_skype_meta_box_ajax();
36
- break;
37
-
38
- case 'editor_callback':
39
- if( ! current_user_can( 'edit_posts' ) ) {
40
- die( 'Authentication failed' );
41
- }
42
-
43
- // Determine Field type and context
44
- $views_meta = false;
45
- $field_id = sanitize_text_field( $_GET['field_id'] );
46
-
47
- // todo this could be written in like four lines
48
- if ( isset( $_GET['field_type'] ) && $_GET['field_type'] == 'usermeta' ) {
49
- // Group filter
50
- wp_enqueue_script( 'suggest' );
51
- $field = types_get_field( $field_id, 'usermeta' );
52
- $meta_type = 'usermeta';
53
- }
54
- elseif ( isset( $_GET['field_type'] ) && $_GET['field_type'] == 'views-usermeta' ){
55
- $field = types_get_field( $field_id, 'usermeta' );
56
- $meta_type = 'usermeta';
57
- $views_meta = true;
58
- }
59
- elseif ( isset( $_GET['field_type'] ) && $_GET['field_type'] == 'termmeta' ) {
60
- // Group filter
61
- wp_enqueue_script( 'suggest' );
62
- $field = types_get_field( $field_id, 'termmeta' );
63
- $meta_type = 'termmeta';
64
- }
65
- elseif ( isset( $_GET['field_type'] ) && $_GET['field_type'] == 'views-termmeta' ){
66
- $field = types_get_field( $field_id, 'termmeta' );
67
- $meta_type = 'termmeta';
68
- $views_meta = true;
69
- }else {
70
- $field = types_get_field( $field_id );
71
- $meta_type = 'postmeta';
72
- }
73
-
74
- $parent_post_id = isset( $_GET['post_id'] ) ? intval( $_GET['post_id'] ) : null;
75
- $shortcode = isset( $_GET['shortcode'] ) ? urldecode( $_GET['shortcode'] ) : null;
76
- $callback = isset( $_GET['callback'] ) ? sanitize_text_field( $_GET['callback'] ) : false;
77
- if ( !empty( $field ) ) {
78
- // Editor
79
- WPCF_Loader::loadClass( 'editor' );
80
- $editor = new WPCF_Editor();
81
- $editor->frame( $field, $meta_type, $parent_post_id, $shortcode,
82
- $callback, $views_meta );
83
- }
84
- break;
85
-
86
- case 'dismiss_message':
87
- if( ! is_user_logged_in() ) {
88
- die( 'Authentication failed' );
89
- }
90
-
91
- if ( isset( $_GET['id'] ) ) {
92
- $messages = get_option( 'wpcf_dismissed_messages', array() );
93
- $messages[] = sanitize_text_field( $_GET['id'] );
94
- update_option( 'wpcf_dismissed_messages', $messages );
95
- }
96
- break;
97
-
98
- case 'pr_add_child_post':
99
- global $current_user;
100
- $output = '<tr>' . __( 'Passed wrong parameters', 'wpcf' ) . '</tr>';
101
- $id = 0;
102
-
103
- $target_post_type = isset( $_GET['post_type_child'] ) ? sanitize_text_field( $_GET['post_type_child'] ) : '';
104
-
105
- $has_permissions = true;
106
- if (
107
- class_exists( 'Access_Helper' )
108
- && class_exists( 'TAccess_Loader' )
109
- && $target_post_type != ''
110
- ) {
111
- $model = TAccess_Loader::get('MODEL/Access');
112
- $settings_access = $model->getAccessTypes();
113
- if ( isset( $settings_access[$target_post_type] ) ) {
114
- $role = Access_Helper::wpcf_get_current_logged_user_role();
115
- if ( $role == '' ) {
116
- $role = 'guest';
117
- $user_level = 0;
118
- }
119
- if ( $role != 'administrator' ) {
120
- if ( $role != 'guest') {
121
- $user_level = Access_Helper::wpcf_get_current_logged_user_level( $current_user );
122
- }
123
- $has_permissions = Access_Helper::wpcf_access_check_if_user_can( $settings_access[$target_post_type]['permissions']['publish']['role'], $user_level );
124
- }
125
- } else if ( ! current_user_can( 'publish_posts' ) ) {
126
- $has_permissions = false;
127
- }
128
- } else {
129
- if ( ! current_user_can( 'publish_posts' ) ) {
130
- $has_permissions = false;
131
- }
132
- }
133
-
134
- if ( ! $has_permissions ) {
135
- $output = '<tr><td>' . __( 'You do not have rights to create new items', 'wpcf' ) . '</td></tr>';
136
- } else if (
137
- //current_user_can( 'edit_posts' )
138
- /*&&*/ isset( $_GET['post_id'] )
139
- && isset( $_GET['post_type_child'] )
140
- && isset( $_GET['post_type_parent'] ) )
141
- {
142
-
143
- $relationships = get_option( 'wpcf_post_relationship', array() );
144
- $parent_post_id = intval( $_GET['post_id'] );
145
- $parent_post = get_post( $parent_post_id );
146
- if ( !empty( $parent_post->ID ) ) {
147
- $post_type = sanitize_text_field( $_GET['post_type_child'] );
148
- $parent_post_type = sanitize_text_field( $_GET['post_type_parent'] );
149
- // @todo isset & error handling
150
- $data = $relationships[$parent_post_type][$post_type];
151
- /*
152
- * Since Types 1.1.5
153
- *
154
- * We save new post
155
- * CHECKPOINT
156
- */
157
- $id = $wpcf->relationship->add_new_child( $parent_post->ID, $post_type );
158
-
159
- if ( is_wp_error( $id ) ) {
160
- $output = '<tr>' . $id->get_error_message() . '</tr>';
161
- } else {
162
- /*
163
- * Here we set Relationship
164
- * CHECKPOINT
165
- */
166
- $parent = get_post( $parent_post_id );
167
- $child = get_post( $id );
168
- if ( !empty( $parent->ID ) && !empty( $child->ID ) ) {
169
-
170
- // Set post
171
- $wpcf->post = $child;
172
-
173
- // Set relationship :)
174
- $wpcf->relationship->_set( $parent, $child, $data );
175
-
176
- // Render new row
177
- $output = $wpcf->relationship->child_row( $parent_post->ID, $id, $data );
178
- } else {
179
- $output = '<tr>' . __( 'Error creating post relationship', 'wpcf' ) . '</tr>';
180
- }
181
- }
182
- } else {
183
- $output = '<tr>' . __( 'Error getting parent post', 'wpcf' ) . '</tr>';
184
- }
185
- }
186
- if ( !defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
187
- echo json_encode( array(
188
- 'output' => $output . wpcf_form_render_js_validation( '#post', false ),
189
- 'child_id' => $id,
190
- ) );
191
- } else {
192
- echo json_encode( array(
193
- 'output' => $output,
194
- 'conditionals' => array('#post' => wptoolset_form_get_conditional_data( 'post' )),
195
- 'child_id' => $id,
196
- ) );
197
- }
198
- break;
199
-
200
- case 'pr_save_all':
201
- ob_start(); // Try to catch any errors
202
- $output = '';
203
- if ( current_user_can( 'edit_posts' ) && isset( $_POST['post_id'] ) ) {
204
-
205
- $parent_id = intval( $_POST['post_id'] );
206
- $post_type = sanitize_text_field( $_POST['post_type'] );
207
- if ( isset( $_POST['wpcf_post_relationship'][$parent_id] ) ) {
208
-
209
- $children = wpcf_sanitize_post_realtionship_input( (array) $_POST['wpcf_post_relationship'][$parent_id] );
210
-
211
- $wpcf->relationship->save_children( $parent_id, $children );
212
- $output = $wpcf->relationship->child_meta_form(
213
- $parent_id, strval( $post_type )
214
- );
215
- }
216
- }
217
- if ( !defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
218
- // TODO Move to conditional
219
- $output .= '<script type="text/javascript">wpcfConditionalInit();</script>';
220
- }
221
- wpcf_show_admin_messages('echo');
222
- $errors = ob_get_clean();
223
- if ( !defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
224
- echo json_encode( array(
225
- 'output' => $output,
226
- 'errors' => $errors
227
- ) );
228
- } else {
229
- echo json_encode( array(
230
- 'output' => $output,
231
- 'conditionals' => array('#post' => wptoolset_form_get_conditional_data( 'post' )),
232
- 'errors' => $errors
233
- ) );
234
- }
235
- break;
236
-
237
- case 'pr_save_child_post':
238
- ob_start(); // Try to catch any errors
239
- $output = '';
240
- if ( current_user_can( 'edit_posts' ) && isset( $_GET['post_id'] )
241
- && isset( $_GET['parent_id'] )
242
- && isset( $_GET['post_type_parent'] )
243
- && isset( $_GET['post_type_child'] )
244
- && isset( $_POST['wpcf_post_relationship'] ) ) {
245
-
246
- $parent_id = intval( $_GET['parent_id'] );
247
- $child_id = intval( $_GET['post_id'] );
248
- $parent_post_type = sanitize_text_field( $_GET['post_type_parent'] );
249
- $child_post_type = sanitize_text_field( $_GET['post_type_child'] );
250
-
251
- if ( isset( $_POST['wpcf_post_relationship'][$parent_id][$child_id] ) ) {
252
- $fields = wpcf_sanitize_post_relationship_input_fields( (array) $_POST['wpcf_post_relationship'][$parent_id][$child_id] );
253
- $wpcf->relationship->save_child( $parent_id, $child_id, $fields );
254
-
255
- $output = $wpcf->relationship->child_row(
256
- $parent_id,
257
- $child_id,
258
- $wpcf->relationship->settings( $parent_post_type, $child_post_type ) );
259
-
260
- if ( !defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
261
- // TODO Move to conditional
262
- $output .= '<script type="text/javascript">wpcfConditionalInit(\'#types-child-row-' . $child_id . '\');</script>';
263
- }
264
- }
265
- }
266
- wpcf_show_admin_messages('echo');
267
- $errors = ob_get_clean();
268
- if ( !defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
269
- echo json_encode( array(
270
- 'output' => $output,
271
- 'errors' => $errors
272
- ) );
273
- } else {
274
- echo json_encode( array(
275
- 'output' => $output,
276
- 'errors' => $errors,
277
- 'conditionals' => array('#post' => wptoolset_form_get_conditional_data( 'post' )),
278
- ) );
279
- }
280
- break;
281
-
282
- case 'pr_delete_child_post':
283
- require_once WPCF_EMBEDDED_ABSPATH . '/includes/post-relationship.php';
284
- $output = 'Passed wrong parameters';
285
- if ( current_user_can( 'edit_posts' ) && isset( $_GET['post_id'] ) ) {
286
- $output = wpcf_pr_admin_delete_child_item( intval( $_GET['post_id'] ) );
287
- }
288
- echo json_encode( array(
289
- 'output' => $output,
290
- ) );
291
- break;
292
-
293
- case 'pr_pagination':
294
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
295
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
296
- require_once WPCF_EMBEDDED_ABSPATH . '/includes/post-relationship.php';
297
- $output = 'Passed wrong parameters';
298
- if ( current_user_can( 'edit_posts' ) && isset( $_GET['post_id'] ) && isset( $_GET['post_type'] ) ) {
299
- global $wpcf;
300
- $parent = get_post( intval( $_GET['post_id'] ) );
301
- $child_post_type = sanitize_text_field( $_GET['post_type'] );
302
-
303
- if ( !empty( $parent->ID ) ) {
304
-
305
- // Set post in loop
306
- $wpcf->post = $parent;
307
-
308
- // Save items_per_page
309
- $wpcf->relationship->save_items_per_page(
310
- $parent->post_type, $child_post_type,
311
- intval( $_GET[$wpcf->relationship->items_per_page_option_name] )
312
- );
313
-
314
- $output = $wpcf->relationship->child_meta_form(
315
- $parent->ID, $child_post_type
316
- );
317
- }
318
- }
319
- if ( !defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
320
- echo json_encode( array(
321
- 'output' => $output,
322
- ) );
323
- } else {
324
- echo json_encode( array(
325
- 'output' => $output,
326
- 'conditionals' => array('#post' => wptoolset_form_get_conditional_data( 'post' )),
327
- ) );
328
- }
329
- break;
330
-
331
- case 'pr_sort':
332
- $output = 'Passed wrong parameters';
333
- if ( current_user_can( 'edit_posts' ) && isset( $_GET['field'] ) && isset( $_GET['sort'] ) && isset( $_GET['post_id'] ) && isset( $_GET['post_type'] ) ) {
334
- $output = $wpcf->relationship->child_meta_form(
335
- intval( $_GET['post_id'] ), sanitize_text_field( $_GET['post_type'] )
336
- );
337
- }
338
- if ( !defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
339
- echo json_encode( array(
340
- 'output' => $output,
341
- ) );
342
- } else {
343
- echo json_encode( array(
344
- 'output' => $output,
345
- 'conditionals' => array('#post' => wptoolset_form_get_conditional_data( 'post' )),
346
- ) );
347
- }
348
- break;
349
-
350
- // Not used anywhere
351
- /*case 'pr_sort_parent':
352
- $output = 'Passed wrong parameters';
353
- if ( isset( $_GET['field'] ) && isset( $_GET['sort'] ) && isset( $_GET['post_id'] ) && isset( $_GET['post_type'] ) ) {
354
- $output = $wpcf->relationship->child_meta_form(
355
- intval( $_GET['post_id'] ), strval( $_GET['post_type'] )
356
- );
357
- }
358
- if ( !defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
359
- echo json_encode( array(
360
- 'output' => $output,
361
- ) );
362
- } else {
363
- echo json_encode( array(
364
- 'output' => $output,
365
- 'conditionals' => array('#post' => wptoolset_form_get_conditional_data( 'post' )),
366
- ) );
367
- }
368
- break;*/
369
- /* Usermeta */
370
- case 'um_repetitive_add':
371
-
372
- if ( isset( $_GET['user_id'] ) ) {
373
- $user_id = $_GET['user_id'];
374
- } else {
375
- $user_id = wpcf_usermeta_get_user();
376
- }
377
-
378
- if ( isset( $_GET['field_id'] )
379
- && current_user_can( 'edit_user', $user_id ) ) {
380
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
381
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
382
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/usermeta-post.php';
383
- $field = wpcf_admin_fields_get_field( sanitize_text_field( $_GET['field_id'] ), false,
384
- false, false, 'wpcf-usermeta' );
385
- global $wpcf;
386
- $wpcf->usermeta_repeater->set( $user_id, $field );
387
- /*
388
- *
389
- * Force empty values!
390
- */
391
- $wpcf->usermeta_repeater->cf['value'] = null;
392
- $wpcf->usermeta_repeater->meta = null;
393
- $form = $wpcf->usermeta_repeater->get_field_form( null, true );
394
-
395
- echo json_encode( array(
396
- 'output' => wpcf_form_simple( $form )
397
- . wpcf_form_render_js_validation( '#your-profile', false ),
398
- ) );
399
- } else {
400
- echo json_encode( array(
401
- 'output' => 'params missing',
402
- ) );
403
- }
404
- break;
405
-
406
- case 'um_repetitive_delete':
407
- if ( isset( $_POST['user_id'] )
408
- && isset( $_POST['field_id'] )
409
- && current_user_can( 'edit_user', intval( $_POST['user_id'] ) ) )
410
- {
411
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
412
- $user_id = intval( $_POST['user_id'] );
413
-
414
- $field = wpcf_admin_fields_get_field( sanitize_text_field( $_POST['field_id'] ), false,
415
- false, false, 'wpcf-usermeta' );
416
- $meta_id = intval( $_POST['meta_id'] );
417
-
418
- if ( !empty( $field ) && !empty( $user_id ) && !empty( $meta_id ) ) {
419
- /*
420
- *
421
- *
422
- * Changed.
423
- * Since Types 1.2
424
- */
425
- global $wpcf;
426
- $wpcf->usermeta_repeater->set( $user_id, $field );
427
- $wpcf->usermeta_repeater->delete( $meta_id );
428
-
429
- echo json_encode( array(
430
- 'output' => 'deleted',
431
- ) );
432
- } else {
433
- echo json_encode( array(
434
- 'output' => 'field or post not found',
435
- ) );
436
- }
437
- } else {
438
- echo json_encode( array(
439
- 'output' => 'params missing',
440
- ) );
441
- }
442
- break;
443
- /* End Usermeta */
444
- case 'repetitive_add':
445
- if ( current_user_can( 'edit_posts' ) && isset( $_GET['field_id'] ) ) {
446
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
447
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
448
- $field = wpcf_admin_fields_get_field( sanitize_text_field( $_GET['field_id'] ) );
449
- $parent_post_id = intval( $_GET['post_id'] );
450
-
451
- /*
452
- * When post is new - post_id is 0
453
- * We can safely set post_id to 1 cause
454
- * values compared are filtered anyway.
455
- */
456
- if ( $parent_post_id == 0 ) {
457
- $parent_post_id = 1;
458
- }
459
-
460
- $parent_post = get_post( $parent_post_id );
461
-
462
- global $wpcf;
463
- $wpcf->repeater->set( $parent_post, $field );
464
- /*
465
- *
466
- * Force empty values!
467
- */
468
- $wpcf->repeater->cf['value'] = null;
469
- $wpcf->repeater->meta = null;
470
- $form = $wpcf->repeater->get_field_form( null, true );
471
-
472
- echo json_encode( array(
473
- 'output' => wpcf_form_simple( $form )
474
- . wpcf_form_render_js_validation( '#post', false ),
475
- ) );
476
- } else {
477
- echo json_encode( array(
478
- 'output' => 'params missing',
479
- ) );
480
- }
481
- break;
482
-
483
- case 'repetitive_delete':
484
- if ( current_user_can( 'edit_posts' ) && isset( $_POST['post_id'] ) && isset( $_POST['field_id'] ) ) {
485
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
486
- $post_id = intval( $_POST['post_id'] );
487
- $parent_post = get_post( $post_id );
488
- $field = wpcf_admin_fields_get_field( sanitize_text_field( $_POST['field_id'] ) );
489
- $meta_id = intval( $_POST['meta_id'] );
490
- if ( !empty( $field ) && !empty( $parent_post->ID ) && !empty( $meta_id ) ) {
491
- /*
492
- *
493
- *
494
- * Changed.
495
- * Since Types 1.2
496
- */
497
- global $wpcf;
498
- $wpcf->repeater->set( $parent_post, $field );
499
- $wpcf->repeater->delete( $meta_id );
500
-
501
- echo json_encode( array(
502
- 'output' => 'deleted',
503
- ) );
504
- } else {
505
- echo json_encode( array(
506
- 'output' => 'field or post not found',
507
- ) );
508
- }
509
- } else {
510
- echo json_encode( array(
511
- 'output' => 'params missing',
512
- ) );
513
- }
514
- break;
515
-
516
- case 'wpcf_entry_search':
517
- if( current_user_can( 'edit_posts' ) && isset($_REQUEST['post_type'])) {
518
- $posts_per_page = apply_filters( 'wpcf_pr_belongs_post_numberposts', 10 );
519
-
520
- $args = array(
521
- 'posts_per_page' => apply_filters( 'wpcf_pr_belongs_post_posts_per_page', $posts_per_page ),
522
- 'post_status' => apply_filters( 'wpcf_pr_belongs_post_status', array( 'publish', 'private' ) ),
523
- 'post_type' => $_REQUEST['post_type'],
524
- 'suppress_filters' => 1,
525
- );
526
-
527
- if ( isset( $_REQUEST['s'] ) ) {
528
- $args['s'] = $_REQUEST['s'];
529
- }
530
-
531
- if ( isset( $_REQUEST['page'] ) && preg_match('/^\d+$/', $_REQUEST['page']) ) {
532
- $args['paged'] = intval($_REQUEST['page']);
533
- }
534
-
535
- $the_query = new WP_Query( $args );
536
-
537
- $posts = array(
538
- 'items' => array(),
539
- 'total_count' => $the_query->found_posts,
540
- 'incomplete_results' => $the_query->found_posts > $posts_per_page,
541
- 'posts_per_page' => $posts_per_page,
542
- );
543
-
544
- if ( $the_query->have_posts() ) {
545
- while ( $the_query->have_posts() ) {
546
- $the_query->the_post();
547
- $post_title = get_the_title();
548
- if ( empty($post_title) ) {
549
- $post_title = sprintf(
550
- __('[empty title] ID: %d', 'wpcf'),
551
- get_the_ID()
552
- );
553
- }
554
- $posts['items'][] = array(
555
- 'ID' => get_the_ID(),
556
- 'post_title' => $post_title,
557
- );
558
- }
559
- }
560
- /* Restore original Post Data */
561
- wp_reset_postdata();
562
-
563
- echo json_encode($posts);
564
- } else {
565
- echo json_encode( array(
566
- 'output' => 'params missing',
567
- ) );
568
- }
569
- break;
570
-
571
- case 'wpcf_entry_entry':
572
- if( current_user_can( 'edit_posts' ) && isset($_REQUEST['p'])) {
573
- $wpcf_post = get_post($_REQUEST['p'], ARRAY_A);
574
- if ( isset($wpcf_post['ID']) ) {
575
- $post_title = $wpcf_post['post_title'];
576
- if ( empty($post_title) ) {
577
- $post_title = sprintf(
578
- __('[empty title] ID: %d', 'wpcf'),
579
- $wpcf_post['ID']
580
- );
581
- }
582
- echo json_encode(
583
- array(
584
- 'ID' => $wpcf_post['ID'],
585
- 'post_title' => $wpcf_post['post_title'],
586
- )
587
- );
588
- } else {
589
- echo json_encode( array( 'output' => 'params missing',));
590
- }
591
- } else {
592
- echo json_encode( array(
593
- 'output' => 'params missing',
594
- ) );
595
- }
596
- break;
597
-
598
- default:
599
- break;
600
- }
601
- if ( function_exists( 'wpcf_ajax' ) ) {
602
- wpcf_ajax();
603
- }
604
- die();
605
- }
606
-
607
-
608
- /**
609
- * Sanitize input array with post children and their fields.
610
- *
611
- * @param array $children_raw See WPCF_Relationship::save_children().
612
- * @return array Data with the same structure as input, but sanitized.
613
- *
614
- * @todo since
615
- * @todo move to better location if such exists
616
- */
617
- function wpcf_sanitize_post_realtionship_input( $children_raw ) {
618
- $children = array();
619
- foreach( $children_raw as $child_id_raw => $child_fields_raw ) {
620
- $child_id = intval( $child_id_raw );
621
- $children[ $child_id ] = wpcf_sanitize_post_relationship_input_fields( $child_fields_raw );
622
- }
623
- return $children;
624
- }
625
-
626
-
627
- /**
628
- * Sanitize input array with post child fields.
629
- *
630
- * Note that only field keys are sanitized. Values can be arbitrary.
631
- *
632
- * @param array $fields_raw See WPCF_Relationship::save_child().
633
- * @return array Data with the same structure as input, but sanitized.
634
- *
635
- * @todo since
636
- * @todo move to better location if such exists
637
- */
638
- function wpcf_sanitize_post_relationship_input_fields( $fields_raw ) {
639
- $fields = array();
640
- foreach( $fields_raw as $field_key_raw => $field_value_raw ) {
641
- $field_key = sanitize_text_field( $field_key_raw );
642
- $fields[ $field_key ] = $field_value_raw;
643
- }
644
- return $fields;
645
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/autoloader.php DELETED
@@ -1,274 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Autoloader for Types classes.
5
- *
6
- * See:
7
- * @link https://git.onthegosystems.com/toolset/layouts/wikis/layouts-theme-integration#wpddl_theme_integration_autoloader
8
- *
9
- * Warning: Please be careful when using the autoloader for older code that is supposed to be loaded at certain time.
10
- * The autoloader might grab some classses too early.
11
- */
12
- final class WPCF_Autoloader {
13
-
14
- private static $instance;
15
-
16
- protected $paths = array();
17
-
18
- protected $prefixes = array();
19
-
20
-
21
- protected function __construct() {
22
- spl_autoload_register( array( $this, 'autoload' ) );
23
- }
24
-
25
-
26
- public static function get_instance() {
27
- if( self::$instance === null )
28
- self::$instance = new self;
29
-
30
- return self::$instance;
31
- }
32
-
33
-
34
- /**
35
- * Add base path to search for class files.
36
- *
37
- * @param string $path
38
- * @return bool True if path was added
39
- */
40
- public function add_path( $path ) {
41
-
42
- // check if path is readable
43
- if( is_readable( $path ) ) {
44
- array_push( $this->paths, $path );
45
- return true;
46
- }
47
-
48
- return false;
49
- }
50
-
51
-
52
- /**
53
- * Add multiple base paths.
54
- *
55
- * @param array $paths
56
- */
57
- public function add_paths( $paths ) {
58
- // run this->addPath for each value
59
- foreach( $paths as $path ) {
60
- $this->add_path( $path );
61
- }
62
- }
63
-
64
-
65
- public function get_paths() {
66
- return $this->paths;
67
- }
68
-
69
-
70
- public function add_prefix( $prefix ) {
71
- array_push( $this->prefixes, $prefix );
72
-
73
- // We assume that most specific (longest) prefixes will have higher probability of a match.
74
- // This is useful when one prefix is substring of another.
75
- rsort( $this->prefixes );
76
-
77
- return $this;
78
- }
79
-
80
-
81
- public function get_prefixes() {
82
- return $this->prefixes;
83
- }
84
-
85
-
86
- public function autoload( $class ) {
87
-
88
- if( class_exists( $class ) ) {
89
- return true;
90
- }
91
-
92
- foreach( $this->prefixes as $prefix ) {
93
-
94
- // Will be equal to $class if no replacement happens.
95
- $class_without_prefix = preg_replace( '#^'.$prefix.'_#', '', $class );
96
-
97
- if( $class != $class_without_prefix ) {
98
-
99
- $result = $this->try_autoload_without_prefix( $class, $class_without_prefix );
100
-
101
- // false means we should try with other prefixes
102
- if( false !== $result ) {
103
- return $result;
104
- }
105
- }
106
- }
107
-
108
- return false;
109
- }
110
-
111
-
112
- /**
113
- * Try to load class after matching it's prefix.
114
- *
115
- * @param string $full_class_name Full name of the class.
116
- * @param string $class_name_without_prefix Name of the class without the registered prefix.
117
- * @return bool|mixed include_once() result or false if the file was not found.
118
- */
119
- private function try_autoload_without_prefix( $full_class_name, $class_name_without_prefix ) {
120
-
121
- // explode class by _
122
- $explode_class = explode( '_' , $class_name_without_prefix );
123
-
124
- // get class filename
125
- $class_filename = array_pop( $explode_class );
126
- $class_filename = strtolower( $class_filename ) . '.php';
127
-
128
- // get class path
129
- $class_path = '';
130
- foreach( $explode_class as $path ) {
131
- $class_path .= strtolower( $path ) . '/';
132
- }
133
-
134
- $file = $class_path . $class_filename;
135
-
136
- // check for file in path
137
- foreach( $this->get_paths() as $path ) {
138
-
139
- $next_filename = $file;
140
-
141
- while( true ) {
142
- $candidate_filename = $next_filename;
143
-
144
- $candidate_path = $path . '/' . $candidate_filename;
145
-
146
- $result = $this->try_load_file( $candidate_path, $full_class_name );
147
- if( false !== $result ) {
148
- return $result;
149
- }
150
-
151
- // Replace the last slash by underscore.
152
- // This allows to use underscores in class filename instead of subfolders
153
- $next_filename = preg_replace( '/(\/(?!.*\/))/', '_', $candidate_filename );
154
-
155
- // If there was no change, we have tried all possibilities for this filename.
156
- if( $next_filename == $candidate_filename ) {
157
- break;
158
- }
159
-
160
- }
161
-
162
- }
163
-
164
- // Last attempt for legacy classes.
165
- return $this->try_load_legacy_class( $full_class_name );
166
- }
167
-
168
-
169
- /**
170
- * Try loading a legacy class.
171
- *
172
- * Uses several mechanisms to find a legacy class, for details see other try_load_* methods.
173
- *
174
- * @param string $full_class_name
175
- * @return bool|mixed include_once() result or false if the file was not found. Note that under some circumstances
176
- * you may get a false negative here.
177
- */
178
- private function try_load_legacy_class( $full_class_name ) {
179
- $loading_result = $this->try_load_generic_legacy_class( $full_class_name );
180
- if( false == $loading_result ) {
181
- $loading_result = $this->try_load_toolset_forms_class( $full_class_name );
182
- }
183
- return $loading_result;
184
- }
185
-
186
-
187
- /**
188
- * Try loading a toolset-forms class.
189
- *
190
- * Currently it recongnizes WPToolset_* and WPToolset_Field_* classes if they're named in
191
- * the class.*.php pattern and placed in toolset-forms class directory.
192
- *
193
- * @param $full_class_name
194
- * @return bool|mixed
195
- */
196
- private function try_load_toolset_forms_class( $full_class_name ) {
197
- // Bail if we don't have toolset-forms.
198
- if( ! defined( 'WPTOOLSET_FORMS_ABSPATH' ) ) {
199
- return false;
200
- }
201
-
202
- // Handle classes named WPToolset_Someting_Something*
203
- $explode_class = explode( '_' , $full_class_name );
204
- if( count( $explode_class ) >= 2 && 'WPToolset' == $explode_class[0] ) {
205
-
206
- // We will search for Something_Something*
207
- array_shift( $explode_class );
208
-
209
- // If we have Field_Something*, we will omit the "Field" part
210
- if( 'Field' == $explode_class[0] && count( $explode_class ) >= 2 ) {
211
- array_shift( $explode_class );
212
- }
213
-
214
- $filename = 'class.' . strtolower( implode( '.', $explode_class ) ) . '.php';
215
- $candidate_path = WPTOOLSET_FORMS_ABSPATH . '/classes/' . $filename;
216
-
217
- return $this->try_load_file( $candidate_path, $full_class_name );
218
-
219
- } else {
220
- return false;
221
- }
222
- }
223
-
224
-
225
- /**
226
- * Load a generic Types legacy class.
227
- *
228
- * Works for classes placed directly inside one of the base paths, whose names translate into filenames like this:
229
- * "Types_Some_Class" => "class.types.some.class.php". Disregards the set of defined prefixes - it would work for
230
- * any class.
231
- *
232
- * @param $full_class_name
233
- * @return bool|mixed
234
- */
235
- private function try_load_generic_legacy_class( $full_class_name ) {
236
- $explode_class = explode( '_' , $full_class_name );
237
- $filename = 'class.' . strtolower( implode( '.', $explode_class ) ) . '.php';
238
-
239
- foreach( $this->get_paths() as $path ) {
240
- $candidate_path = $path . '/' . $filename;
241
- $result = $this->try_load_file( $candidate_path, $full_class_name );
242
- if( false !== $result ) {
243
- return $result;
244
- }
245
- }
246
-
247
- // Class not found.
248
- return false;
249
- }
250
-
251
-
252
- /**
253
- * Try loading a file and check if given class exists afterwards.
254
- *
255
- * @param string $full_path Absolute path to the file.
256
- * @param string $full_class_name Full class name to be checked.
257
- *
258
- * @return bool|mixed include_once() result or false if the class couldn't be loaded. It may give false negatives.
259
- */
260
- private function try_load_file( $full_path, $full_class_name ) {
261
- if( is_file( $full_path ) ) {
262
- /** @noinspection PhpIncludeInspection */
263
- $result = include_once( $full_path ) ;
264
-
265
- // Do not stop trying if we load the file but it doesn't contain the requested class.
266
- if( class_exists( $full_class_name ) ) {
267
- return $result;
268
- }
269
- }
270
-
271
- return false;
272
- }
273
-
274
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/conditional-display.php DELETED
@@ -1,363 +0,0 @@
1
- <?php
2
- /*
3
- * Conditional display embedded code.
4
- */
5
-
6
- /*
7
- * Post page filters
8
- */
9
- add_filter( 'wpcf_post_edit_field', 'wpcf_cd_post_edit_field_filter', 10, 4 );
10
- add_filter( 'wpcf_post_groups', 'wpcf_cd_post_groups_filter', 10, 3 );
11
-
12
- /*
13
- *
14
- * These hooks check if conditional failed
15
- * but form allowed to be saved
16
- * Since Types 1.2
17
- */
18
- add_filter( 'wpcf_post_form_error', 'wpcf_conditional_post_form_error_filter',
19
- 10, 2 );
20
-
21
-
22
- /*
23
- * Logger
24
- */
25
- if ( !function_exists( 'wplogger' ) ) {
26
- require_once WPCF_EMBEDDED_ABSPATH . '/toolset/toolset-common/wplogger.php';
27
- }
28
- if ( !function_exists( 'wpv_filter_parse_date' ) ) {
29
- require_once WPCF_EMBEDDED_ABSPATH . '/toolset/toolset-common/wpv-filter-date-embedded.php';
30
- }
31
-
32
- require_once WPTOOLSET_FORMS_ABSPATH . '/classes/class.conditional.php';
33
- require_once WPTOOLSET_FORMS_ABSPATH . '/classes/class.types.php';
34
-
35
- /**
36
- * Filters groups on post edit page.
37
- *
38
- * @param type $groups
39
- * @param type $post
40
- * @return type
41
- */
42
- function wpcf_cd_post_groups_filter( $groups, $post, $context ) {
43
- if ( $context != 'group' ) {
44
- return $groups;
45
- }
46
-
47
-
48
- foreach ( $groups as $key => &$group ) {
49
-
50
- $conditions = null;
51
- if (
52
- array_key_exists( 'conditional_display', $group )
53
- && array_key_exists( 'conditions', $group['conditional_display'] )
54
- ) {
55
- $conditions = $group['conditional_display'];
56
- } else {
57
- $conditions = get_post_meta( $group['id'], '_wpcf_conditional_display', true );
58
- }
59
-
60
- if ( !empty( $conditions['conditions'] ) ) {
61
- $meta_box_id = "wpcf-group-{$group['slug']}";
62
- $prefix = 'wpcf-';
63
- $suffix = '';
64
-
65
- $cond = array();
66
- $cond_values = array();
67
- if (isset( $post->ID ) && $post->ID) {
68
- $cond_values = get_post_custom( $post->ID );
69
- }
70
- $_cond_values = array();
71
-
72
- foreach ( $cond_values as $k => $v ) {
73
- $v = maybe_unserialize( $v[0] );
74
- /**
75
- * if data is too complex - skip it
76
- */
77
- if ( is_array( $v) ) {
78
- $v = array_shift($v);
79
- if ( is_array($v) ) {
80
- continue;
81
- }
82
- $v = strval( $v);
83
- }
84
- $_cond_values[$k . $suffix] = $v;
85
- }
86
- unset( $cond_values );
87
- $cond = array();
88
- if ( !empty( $conditions['custom_use'] ) ) {
89
- if ( !empty( $conditions['custom'] ) ) {
90
- $custom = WPToolset_Types::getCustomConditional($conditions['custom']);
91
- $passed = WPToolset_Forms_Conditional::evaluateCustom($custom['custom'], $_cond_values);
92
- $cond = array(
93
- 'custom' => $custom['custom'],
94
- 'custom_use' => true
95
- );
96
- }
97
- } else {
98
- $cond = array(
99
- 'relation' => $conditions['relation'],
100
- 'conditions' => array(),
101
- 'values' => $_cond_values,
102
- );
103
- foreach ( $conditions['conditions'] as $d ) {
104
- $c_field = types_get_field( $d['field'] );
105
- if ( !empty( $c_field ) ) {
106
- $_c = array(
107
- 'id' => wpcf_types_get_meta_prefix( $c_field ) . $d['field'] . $suffix,
108
- 'type' => $c_field['type'],
109
- 'operator' => $d['operation'],
110
- 'args' => array($d['value']),
111
- );
112
- $cond['conditions'][] = $_c;
113
- }
114
- }
115
- $passed = wptoolset_form_conditional_check( array( 'conditional' => $cond ) );
116
- }
117
- $data = array(
118
- 'id' => $meta_box_id,
119
- 'conditional' => $cond,
120
- );
121
- wptoolset_form_add_conditional( 'post', $data );
122
- if ( !$passed ) {
123
- $group['_conditional_display'] = 'failed';
124
- } else {
125
- $group['_conditional_display'] = 'passed';
126
- }
127
- }
128
- }
129
- return $groups;
130
- }
131
-
132
- /**
133
- * Checks if there is conditional display.
134
- *
135
- * This function filters all fields that appear in form.
136
- * It checks if field is Check Trigger or Conditional.
137
- * Since Types 1.2 this functin is simplified and should stay that way.
138
- * It's important core action.
139
- *
140
- *
141
- * @param type $element
142
- * @param type $field
143
- * @param type $post
144
- * @return type
145
- */
146
- function wpcf_cd_post_edit_field_filter( $element, $field, $post,
147
- $context = 'group' ) {
148
-
149
- // Do not use on repetitive
150
- if ( defined( 'DOING_AJAX' ) && $context == 'repetitive' ) {
151
- return $element;
152
- }
153
-
154
- // Use only with postmeta
155
- if ( $field['meta_type'] != 'postmeta' ) {
156
- return $element;
157
- }
158
-
159
- global $wpcf;
160
-
161
- /*
162
- *
163
- *
164
- * Since Types 1.2
165
- * Automatically evaluates WPCF_Conditional::set()
166
- * Evaluation moved to WPCF_Conditional::evaluate()
167
- */
168
- if ( $wpcf->conditional->is_conditional( $field )
169
- || $wpcf->conditional->is_trigger( $field ) ) {
170
-
171
- wpcf_conditional_add_js();
172
- $wpcf->conditional->set( $post, $field );
173
-
174
- /*
175
- * Check if field is check trigger and wrap it
176
- * (add CSS class 'wpcf-conditonal-check-trigger')
177
- */
178
- if ( $wpcf->conditional->is_trigger( $field ) ) {
179
- $element = $wpcf->conditional->wrap_trigger( $element );
180
- }
181
-
182
- /*
183
- * If conditional
184
- */
185
- if ( $wpcf->conditional->is_conditional( $field ) ) {
186
- $element = $wpcf->conditional->wrap( $element );
187
- }
188
- }
189
-
190
- return $element;
191
- }
192
-
193
- /**
194
- * Operations.
195
- *
196
- * @return type
197
- */
198
- function wpcf_cd_admin_operations() {
199
- return array(
200
- '=' => '= (' . __( 'equal to', 'wpcf' ) . ')',
201
- '>' => '> (' . __( 'larger than', 'wpcf' ) . ')',
202
- '<' => '< (' . __( 'less than', 'wpcf' ) . ')',
203
- '>=' => '>= (' . __( 'larger or equal to', 'wpcf' ) . ')',
204
- '<=' => '<= (' . __( 'less or equal to', 'wpcf' ) . ')',
205
- '===' => '=== (' . __( 'identical to', 'wpcf' ) . ')',
206
- '<>' => '!= (' . __( 'not identical to', 'wpcf' ) . ')',
207
- '!==' => '!== (' . __( 'strictly not equal', 'wpcf' ) . ')',
208
- // 'between' => __('between', 'wpcf'),
209
- );
210
- }
211
-
212
- /**
213
- * Compares values.
214
- *
215
- * @param type $operation
216
- * @return type
217
- */
218
- function wpcf_cd_admin_compare( $operation ) {
219
- $args = func_get_args();
220
- switch ( $operation ) {
221
- case '=':
222
- return $args[1] == $args[2];
223
- break;
224
-
225
- case '>':
226
- return intval( $args[1] ) > intval( $args[2] );
227
- break;
228
-
229
- case '>=':
230
- return intval( $args[1] ) >= intval( $args[2] );
231
- break;
232
-
233
- case '<':
234
- return intval( $args[1] ) < intval( $args[2] );
235
- break;
236
-
237
- case '<=':
238
- return intval( $args[1] ) <= intval( $args[2] );
239
- break;
240
-
241
- case '===':
242
- return $args[1] === $args[2];
243
- break;
244
-
245
- case '!==':
246
- return $args[1] !== $args[2];
247
- break;
248
-
249
- case '<>':
250
- return $args[1] <> $args[2];
251
- break;
252
-
253
- case 'between':
254
- return intval( $args[1] ) > intval( $args[2] ) && intval( $args[1] ) < intval( $args[3] );
255
- break;
256
-
257
- default:
258
- break;
259
- }
260
- return true;
261
- }
262
-
263
- /**
264
- * Setsa all JS.
265
- */
266
- function wpcf_conditional_add_js() {
267
- wpcf_cd_add_field_js();
268
- }
269
-
270
- /**
271
- * JS for fields AJAX.
272
- */
273
- function wpcf_cd_add_field_js() {
274
- global $wpcf;
275
- $wpcf->conditional->add_js();
276
- }
277
-
278
-
279
- /**
280
- * Passes $_POST values for AJAX call.
281
- *
282
- * @todo still used by group.
283
- *
284
- * @param type $null
285
- * @param type $object_id
286
- * @param type $meta_key
287
- * @param type $single
288
- * @return type
289
- */
290
- function wpcf_cd_meta_ajax_validation_filter( $null, $object_id, $meta_key, $single )
291
- {
292
- $meta_key = str_replace( 'wpcf-', '', $meta_key );
293
- $field = wpcf_admin_fields_get_field( $meta_key );
294
- $value = !empty( $field ) && isset( $_POST['wpcf'][$meta_key] ) ? $_POST['wpcf'][$meta_key] : '';
295
- /**
296
- * be sure do not return string if array is expected!
297
- */
298
- if ( !$single && !is_array($value) ) {
299
- return array($value);
300
- }
301
- return $value;
302
- }
303
-
304
- /**
305
- * Post form error filter.
306
- *
307
- * Leave element as not_valid (it will prevent saving) just remove warning.
308
- *
309
- * @global type $wpcf
310
- * @param type $_error
311
- * @param type $_not_valid
312
- * @return boolean
313
- */
314
- function wpcf_conditional_post_form_error_filter( $_error, $_not_valid ) {
315
- if ( !empty( $_not_valid ) ) {
316
-
317
- global $wpcf;
318
-
319
- $count = 0;
320
- $count_non_conditional = 0;
321
- $error_conditional = false;
322
-
323
- foreach ( $_not_valid as $f ) {
324
- $field = $f['_field'];
325
- /*
326
- * Here we add simple check
327
- *
328
- * TODO Improve this check
329
- * We can not tell for sure if it failed except to again check
330
- * conditionals
331
- */
332
- // See if field is conditional
333
- if ( isset( $field->cf['data']['conditional_display'] ) ) {
334
-
335
- // Use Conditional class
336
- $test = new WPCF_Conditional();
337
- $test->set( $wpcf->post, $field->cf );
338
-
339
- // See if evaluated right
340
- $passed = $test->evaluate();
341
-
342
- // If evaluated FALSE that means error is expected
343
- if ( $passed ) {
344
- $error_conditional = true;
345
- }
346
-
347
- // Count it
348
- $count++;
349
- } else {
350
- $count_non_conditional++;
351
- }
352
- /*
353
- * If non-conditional fields are not valid - return $_error TRUE
354
- * If at least one conditional failed - return FALSE
355
- */
356
- if ( $count_non_conditional > 0 ) {
357
- return true;
358
- }
359
- return $error_conditional;
360
- }
361
- }
362
- return $_error;
363
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/custom-types.php DELETED
@@ -1,699 +0,0 @@
1
- <?php
2
- /**
3
- *
4
- * Post Types embedded code.
5
- *
6
- *
7
- */
8
- add_action( 'wpcf_type', 'wpcf_filter_type', 10, 2 );
9
-
10
- /**
11
- * Returns default custom type structure.
12
- *
13
- * @return array
14
- */
15
- function wpcf_custom_types_default() {
16
- return array(
17
- 'labels' => array(
18
- 'name' => '',
19
- 'singular_name' => '',
20
- 'add_new' => 'Add New',
21
- 'add_new_item' => 'Add New %s',
22
- // 'edit' => 'Edit',
23
- 'edit_item' => 'Edit %s',
24
- 'new_item' => 'New %s',
25
- // 'view' => 'View',
26
- 'view_item' => 'View %s',
27
- 'search_items' => 'Search %s',
28
- 'not_found' => 'No %s found',
29
- 'not_found_in_trash' => 'No %s found in Trash',
30
- 'parent_item_colon' => 'Parent %s',
31
- 'menu_name' => '%s',
32
- 'all_items' => '%s',
33
- ),
34
- 'slug' => '',
35
- 'description' => '',
36
- 'public' => true,
37
- 'capabilities' => false,
38
- 'menu_position' => null,
39
- 'menu_icon' => '',
40
- 'taxonomies' => array(
41
- 'category' => false,
42
- 'post_tag' => false,
43
- ),
44
- 'supports' => array(
45
- 'title' => true,
46
- 'editor' => true,
47
- 'trackbacks' => false,
48
- 'comments' => false,
49
- 'revisions' => false,
50
- 'author' => false,
51
- 'excerpt' => false,
52
- 'thumbnail' => false,
53
- 'custom-fields' => false,
54
- 'page-attributes' => false,
55
- 'post-formats' => false,
56
- ),
57
- 'rewrite' => array(
58
- 'enabled' => true,
59
- 'slug' => '',
60
- 'with_front' => true,
61
- 'feeds' => true,
62
- 'pages' => true,
63
- ),
64
- 'has_archive' => true,
65
- 'show_ui' => true,
66
- 'show_in_menu' => true,
67
- 'show_in_menu_page' => '',
68
- 'publicly_queryable' => true,
69
- 'exclude_from_search' => false,
70
- 'hierarchical' => false,
71
- 'query_var_enabled' => true,
72
- 'query_var' => '',
73
- 'can_export' => true,
74
- 'show_rest' => false,
75
- 'rest_base' => '',
76
- 'show_in_nav_menus' => true,
77
- 'register_meta_box_cb' => '',
78
- 'permalink_epmask' => 'EP_PERMALINK',
79
- 'update' => false,
80
- );
81
- }
82
-
83
- /**
84
- * Inits custom types.
85
- */
86
- function wpcf_custom_types_init() {
87
- $custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
88
- if ( !empty( $custom_types ) ) {
89
- foreach ( $custom_types as $post_type => $data ) {
90
- if ( empty($data) ) {
91
- continue;
92
- }
93
- if (
94
- ( isset($data['_builtin']) && $data['_builtin'] )
95
- || wpcf_is_builtin_post_types($post_type)
96
- ) {
97
- continue;
98
- }
99
- wpcf_custom_types_register( $post_type, $data );
100
- }
101
- }
102
-
103
- // rearrange menu items
104
- add_filter( 'custom_menu_order' , '__return_true');
105
- add_filter( 'menu_order', 'types_menu_order' );
106
- // rearrange menu items - end
107
-
108
- /** This filter is documented in wp-admin/wp-admin/edit-form-advanced.php */
109
- add_filter('enter_title_here', 'wpcf_filter_enter_title_here', 10, 2);
110
- }
111
-
112
- function types_menu_order( $menu ) {
113
- $custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
114
-
115
- if ( !empty( $custom_types ) ) {
116
- foreach( $custom_types as $post_type => $data ) {
117
- if( empty( $data )
118
- || !isset( $data['menu_position'] )
119
- || strpos( $data['menu_position'],'--wpcf-add-menu-after--' ) === false )
120
- continue;
121
-
122
- // at this point we have not only an integer as menu position
123
- $target_url = explode( '--wpcf-add-menu-after--', $data['menu_position'] );
124
-
125
- if( !isset( $target_url[1] ) || empty( $target_url[1] ) )
126
- continue;
127
-
128
- $target_url = $target_url[1];
129
-
130
- // current url
131
- switch( $data['slug'] ) {
132
- case 'post':
133
- $current_url = 'edit.php';
134
- break;
135
- case 'attachment':
136
- $current_url = 'upload.php';
137
- break;
138
- default:
139
- $current_url = 'edit.php?post_type=' . $data['slug'];
140
- break;
141
- }
142
-
143
- types_menu_order_item_sort( $menu, $current_url, $target_url );
144
-
145
- // store already reordered items
146
- $reordered[$target_url][] = array(
147
- 'current_url' => $current_url,
148
- 'menu_position' => $target_url
149
- );
150
-
151
- // sort previous sorted items which depend on current again
152
- if( isset( $reordered[$current_url] ) ) {
153
- foreach( $reordered[$current_url] as $post_type ) {
154
- types_menu_order_item_sort( $menu, $post_type['current_url'], $post_type['menu_position'] );
155
- }
156
-
157
- unset( $reordered[$current_url] );
158
- }
159
- }
160
- }
161
-
162
- return $menu;
163
- }
164
-
165
- /**
166
- * @param $menu
167
- * @param $data
168
- * @param $menu_position
169
- *
170
- * @return mixed
171
- */
172
- function types_menu_order_item_sort( &$menu, $current_url, $target_url ) {
173
-
174
- // current index
175
- $current_index = array_search( $current_url, $menu );
176
-
177
- // remove all items of $menu which are not matching selected menu
178
- $menu_filtered = array_keys( $menu, $target_url );
179
-
180
- // use last match for resorting
181
- // https://onthegosystems.myjetbrains.com/youtrack/issue/types-591
182
- $add_menu_after_index = array_pop( $menu_filtered );
183
-
184
- // if both found resort menu
185
- if( $current_index && $add_menu_after_index )
186
- wpcf_custom_types_menu_order_move( $menu, $current_index, $add_menu_after_index );return $menu;
187
- }
188
-
189
- /**
190
- * This function is be used to rearrange the admin menu order
191
- *
192
- * @param $menu
193
- * @param $item_move The item index which should be moved
194
- * @param $item_target The item index where $item_move should be placed after
195
- */
196
- function wpcf_custom_types_menu_order_move( &$menu, $item_move, $item_target ) {
197
-
198
- // if item move comes after target we have to select the next element,
199
- // otherwise the $item_move would be added before the target.
200
- if( $item_move > $item_target )
201
- $item_target++;
202
-
203
- // if $item_target is the last menu item, place $item_move to the end of the array
204
- if( !isset( $menu[$item_target]) ) {
205
- $tmp_menu_item = $menu[$item_move];
206
- unset( $menu[$item_move] );
207
- $menu[] = $tmp_menu_item;
208
-
209
- // $item_target is not the last menu, place $item_move after it
210
- } else {
211
- $cut_moving_element = array_splice( $menu, $item_move, 1 );
212
- array_splice( $menu, $item_target, 0, $cut_moving_element );
213
- }
214
-
215
- }
216
-
217
- /**
218
- * Registers post type.
219
- *
220
- * @param type $post_type
221
- * @param type $data
222
- */
223
- function wpcf_custom_types_register( $post_type, $data ) {
224
-
225
- global $wpcf;
226
-
227
- if ( !empty( $data['disabled'] ) ) {
228
- return false;
229
- }
230
- $data = apply_filters( 'types_post_type', $data, $post_type );
231
- // Set labels
232
- if ( !empty( $data['labels'] ) ) {
233
- if ( !isset( $data['labels']['name'] ) ) {
234
- $data['labels']['name'] = $post_type;
235
- }
236
- if ( !isset( $data['labels']['singular_name'] ) ) {
237
- $data['labels']['singular_name'] = $data['labels']['name'];
238
- }
239
- foreach ( $data['labels'] as $label_key => $label ) {
240
- $data['labels'][$label_key] = $label = stripslashes( $label );
241
- switch ( $label_key ) {
242
- case 'add_new_item':
243
- case 'edit_item':
244
- case 'new_item':
245
- case 'view_item':
246
- case 'parent_item_colon':
247
- $data['labels'][$label_key] = sprintf( $label,
248
- $data['labels']['singular_name'] );
249
- break;
250
-
251
- case 'search_items':
252
- case 'all_items':
253
- case 'not_found':
254
- case 'not_found_in_trash':
255
- case 'menu_name':
256
- $data['labels'][$label_key] = sprintf( $label,
257
- $data['labels']['name'] );
258
- break;
259
- }
260
- }
261
- }
262
- $data['description'] = !empty( $data['description'] ) ? htmlspecialchars( stripslashes( $data['description'] ),
263
- ENT_QUOTES ) : '';
264
- $data['public'] = (empty( $data['public'] ) || strval( $data['public'] ) == 'hidden') ? false : true;
265
- $data['publicly_queryable'] = !empty( $data['publicly_queryable'] );
266
- $data['exclude_from_search'] = !empty( $data['exclude_from_search'] );
267
- $data['show_ui'] = (empty( $data['show_ui'] ) || !$data['public']) ? false : true;
268
- if ( empty( $data['menu_position'] ) ) {
269
- unset( $data['menu_position'] );
270
- } else {
271
- $data['menu_position'] = intval( $data['menu_position'] );
272
- }
273
- $data['hierarchical'] = !empty( $data['hierarchical'] );
274
- $data['supports'] = !empty( $data['supports'] ) && is_array( $data['supports'] ) ? array_keys( $data['supports'] ) : array();
275
- $data['taxonomies'] = !empty( $data['taxonomies'] ) && is_array( $data['taxonomies'] ) ? array_keys( $data['taxonomies'] ) : array();
276
- $data['has_archive'] = !empty( $data['has_archive'] );
277
- $data['can_export'] = !empty( $data['can_export'] );
278
- $data['show_in_rest'] = !empty( $data['show_in_rest'] );
279
- $data['rest_base'] = !empty( $data['rest_base'] ) ? $data['rest_base'] : $post_type;
280
- $data['show_in_nav_menus'] = !empty( $data['show_in_nav_menus'] );
281
- $data['show_in_menu'] = !empty( $data['show_in_menu'] );
282
- if ( empty( $data['query_var_enabled'] ) ) {
283
- $data['query_var'] = false;
284
- } else if ( empty( $data['query_var'] ) ) {
285
- $data['query_var'] = true;
286
- }
287
- if ( !empty( $data['show_in_menu_page'] ) ) {
288
- $data['show_in_menu'] = $data['show_in_menu_page'];
289
- $data['labels']['all_items'] = $data['labels']['name'];
290
- }
291
- /**
292
- * menu_icon
293
- */
294
- if ( empty( $data['menu_icon'] ) ) {
295
- unset( $data['menu_icon'] );
296
- } else {
297
- $data['menu_icon'] = stripslashes( $data['menu_icon'] );
298
- if ( strpos( $data['menu_icon'], '[theme]' ) !== false ) {
299
- $data['menu_icon'] = str_replace( '[theme]',
300
- get_stylesheet_directory_uri(), $data['menu_icon'] );
301
- }
302
- }
303
- if ( empty($data['menu_icon'] ) && !empty( $data['icon'] ) ) {
304
- $data['menu_icon'] = sprintf( 'dashicons-%s', $data['icon'] );
305
- }
306
- /**
307
- * rewrite
308
- */
309
- if ( !empty( $data['rewrite']['enabled'] ) ) {
310
- $data['rewrite']['with_front'] = !empty( $data['rewrite']['with_front'] );
311
- $data['rewrite']['feeds'] = !empty( $data['rewrite']['feeds'] );
312
- $data['rewrite']['pages'] = !empty( $data['rewrite']['pages'] );
313
- if ( !empty( $data['rewrite']['custom'] ) && $data['rewrite']['custom'] != 'custom' ) {
314
- unset( $data['rewrite']['slug'] );
315
- }
316
- unset( $data['rewrite']['custom'] );
317
- } else {
318
- $data['rewrite'] = false;
319
- }
320
-
321
- // Set permalink_epmask
322
- if ( !empty( $data['permalink_epmask'] ) ) {
323
- $data['permalink_epmask'] = constant( $data['permalink_epmask'] );
324
- }
325
-
326
- /**
327
- * set default support options
328
- */
329
- $support_fields = array(
330
- 'editor' => false,
331
- 'author' => false,
332
- 'thumbnail' => false,
333
- 'excerpt' => false,
334
- 'trackbacks' => false,
335
- 'custom-fields' => false,
336
- 'comments' => false,
337
- 'revisions' => false,
338
- 'page-attributes' => false,
339
- 'post-formats' => false,
340
- );
341
- $data['supports'] = array_merge_recursive( $data['supports'], $support_fields );
342
-
343
- /**
344
- * custom slug for has_archive
345
- */
346
- if (
347
- isset($data['has_archive'])
348
- && $data['has_archive']
349
- && isset($data['has_archive_slug'])
350
- && $data['has_archive_slug']
351
- ) {
352
- $data['has_archive'] = $data['has_archive_slug'];
353
- }
354
-
355
- /**
356
- * check menu icon
357
- */
358
- if ( isset($data['menu_icon']) && empty($data['menu_icon']) ) {
359
- unset($data['menu_icon']);
360
- }
361
-
362
- // do not handle taxonomy assignments if we have customised taxonomies stored
363
- $stored_taxonomies = get_option( WPCF_OPTION_NAME_CUSTOM_TAXONOMIES, array() );
364
- if( isset( $data['taxonomies'] ) && !empty( $stored_taxonomies ) )
365
- unset( $data['taxonomies'] );
366
-
367
- $args = register_post_type( $post_type, apply_filters( 'wpcf_type', $data, $post_type ) );
368
-
369
- do_action( 'wpcf_type_registered', $args );
370
- }
371
-
372
- /**
373
- * Revised rewrite.
374
- *
375
- * We force slugs now. Submitted and sanitized slug. Set slugs localized (WPML).
376
- * More solid way to force WP slugs.
377
- *
378
- * @see https://icanlocalize.basecamphq.com/projects/7393061-wp-views/todo_items/153925180/comments
379
- * @since 1.1.3.2
380
- * @param type $data
381
- * @param type $post_type
382
- * @return boolean
383
- */
384
- function wpcf_filter_type( $data, $post_type ) {
385
- if ( !empty( $data['rewrite']['enabled'] ) ) {
386
- $data['rewrite']['with_front'] = !empty( $data['rewrite']['with_front'] );
387
- $data['rewrite']['feeds'] = !empty( $data['rewrite']['feeds'] );
388
- $data['rewrite']['pages'] = !empty( $data['rewrite']['pages'] );
389
-
390
- // If slug is not submitted use default slug
391
- if ( empty( $data['rewrite']['slug'] ) ) {
392
- $data['rewrite']['slug'] = $data['slug'];
393
- }
394
-
395
- // Also force default slug if rewrite mode is 'normal'
396
- if ( !empty( $data['rewrite']['custom'] ) && $data['rewrite']['custom'] != 'normal' ) {
397
- $data['rewrite']['slug'] = $data['rewrite']['slug'];
398
- }
399
-
400
- // Register with _x()
401
- $data['rewrite']['slug'] = _x( $data['rewrite']['slug'], 'URL slug',
402
- 'wpcf' );
403
- //
404
- // CHANGED leave it for reference if we need
405
- // to return handling slugs back to WP.
406
- //
407
- // We unset slug settings and leave WP to handle it himself.
408
- // Let WP decide what slugs should be!
409
- // if (!empty($data['rewrite']['custom']) && $data['rewrite']['custom'] != 'normal') {
410
- // unset($data['rewrite']['slug']);
411
- // }
412
- // Just discard non-WP property
413
- unset( $data['rewrite']['custom'] );
414
- } else {
415
- $data['rewrite'] = false;
416
- }
417
-
418
- return $data;
419
- }
420
-
421
- /**
422
- * Returns active post types.
423
- *
424
- * @return type
425
- */
426
- function wpcf_get_active_custom_types() {
427
- $types = get_option(WPCF_OPTION_NAME_CUSTOM_TYPES, array());
428
- foreach ($types as $type => $data) {
429
- if (!empty($data['disabled'])) {
430
- unset($types[$type]);
431
- }
432
- }
433
- return $types;
434
- }
435
-
436
- /** This action is documented in wp-admin/includes/dashboard.php */
437
- add_filter('dashboard_glance_items', 'wpcf_dashboard_glance_items');
438
-
439
- /**
440
- * Add CPT info to "At a Glance"
441
- *
442
- * Add to "At a Glance" WordPress admin dashboard widget information
443
- * about number of posts.
444
- *
445
- * @since 1.6.6
446
- *
447
- */
448
- function wpcf_dashboard_glance_items($elements)
449
- {
450
- // remove when https://core.trac.wordpress.org/ticket/27414 is fixed
451
- wp_register_style( 'wpcf-fix-wordpress-core', WPCF_EMBEDDED_RES_RELPATH . '/css/fix-wordpress-core.css', array(), WPCF_VERSION );
452
- wp_enqueue_style( 'wpcf-fix-wordpress-core' );
453
-
454
- $custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
455
- if ( empty( $custom_types ) ) {
456
- return $elements;
457
- }
458
- ksort($custom_types);
459
- foreach ( $custom_types as $post_type => $data ) {
460
- if ( !isset($data['dashboard_glance']) || !$data['dashboard_glance'] || $post_type == 'post' || $post_type == 'page' ) {
461
- continue;
462
- }
463
- if ( isset($data['disabled']) && $data['disabled'] ) {
464
- continue;
465
- }
466
-
467
- if( $post_type == 'attachment' )
468
- $data['icon'] = 'admin-media';
469
-
470
- $num_posts = wp_count_posts($post_type);
471
-
472
- $num = $post_type == 'attachment'
473
- ? number_format_i18n($num_posts->inherit)
474
- : number_format_i18n($num_posts->publish);
475
-
476
- $text = _n( $data['labels']['singular_name'], $data['labels']['name'], intval($num_posts->publish) );
477
- $elements[] = sprintf(
478
- '<a href="%s"%s>%d %s</a>',
479
- esc_url(
480
- add_query_arg(
481
- array(
482
- 'post_type' => $post_type,
483
- ),
484
- admin_url('edit.php')
485
- )
486
- ),
487
- isset($data['icon'])? sprintf('class="dashicons-%s"', $data['icon']):'',
488
- $num,
489
- $text
490
- );
491
- }
492
- return $elements;
493
- }
494
-
495
- /**
496
- * Summary.
497
- *
498
- * Description.
499
- *
500
- * @since x.x.x
501
- * @access (for functions: only use if private)
502
- *
503
- * @see Function/method/class relied on
504
- * @link URL
505
- * @global type $varname Description.
506
- * @global type $varname Description.
507
- *
508
- * @param type $var Description.
509
- * @param type $var Optional. Description.
510
- * @return type Description.
511
- */
512
- function wpcf_filter_enter_title_here($enter_title_here, $post)
513
- {
514
- if ( is_object($post) && isset( $post->post_type) ) {
515
- $custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
516
- if (
517
- true
518
- && isset($custom_types[$post->post_type])
519
- && isset($custom_types[$post->post_type]['labels'])
520
- && isset($custom_types[$post->post_type]['labels']['enter_title_here'])
521
- ) {
522
- $enter_title_here = trim($custom_types[$post->post_type]['labels']['enter_title_here']);
523
- }
524
- }
525
- if ( empty($enter_title_here) ) {
526
- $enter_title_here = __('Enter title here', 'wpcf');
527
- }
528
- return $enter_title_here;
529
- }
530
-
531
-
532
- /**
533
- * Function to search sub array and returning $array key
534
- *
535
- * @since 1.9
536
- *
537
- * @param array $array
538
- * @param string $search
539
- *
540
- * @return bool|int|string
541
- */
542
- function types_get_array_key_search_in_sub( $array, $search ) {
543
- foreach( $array as $key => $sub_array ) {
544
- if( in_array( $search, $sub_array ) )
545
- return $key;
546
- }
547
-
548
- return false;
549
- }
550
-
551
-
552
- /**
553
- * Change names of build-in post types in menu
554
- *
555
- * @since 1.9
556
- */
557
- function types_rename_build_in_post_types_menu() {
558
-
559
- $custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
560
-
561
- if ( !empty( $custom_types ) ) {
562
- global $menu, $submenu;
563
-
564
- foreach( $custom_types as $post_type => $data ) {
565
- if(
566
- isset( $data['_builtin'] )
567
- && $data['_builtin']
568
- && isset( $data['slug'] )
569
- && isset( $data['labels']['name'] )
570
- ) {
571
- // post
572
- if( $data['slug'] == 'post' ) {
573
- $post_edit_page = 'edit.php';
574
- $post_new_page = 'post-new.php';
575
- // page
576
- } elseif( $data['slug'] == 'page' ) {
577
- $post_edit_page = 'edit.php?post_type=page';
578
- $post_new_page = 'post-new.php?post_type=page';
579
- // attachment (Media)
580
- } elseif( $data['slug'] == 'attachment' ) {
581
- $post_edit_page = 'upload.php';
582
- $post_new_page = 'media-new.php';
583
- // abort
584
- } else {
585
- continue;
586
- }
587
-
588
- $post_menu_key = false;
589
-
590
- // find menu key
591
- $post_menu_key = types_get_array_key_search_in_sub( $menu, $post_edit_page );
592
-
593
- if( !$post_menu_key )
594
- continue;
595
-
596
- // change menu name
597
- $menu[$post_menu_key][0] = $data['labels']['name'];
598
-
599
-
600
- if( isset( $submenu[$post_edit_page] ) && $post_edit_page != 'upload.php' ) {
601
- $submenu_overview_key = $submenu_new_key = false;
602
-
603
- // post/page rename overview
604
- $submenu_overview_key = types_get_array_key_search_in_sub( $submenu[$post_edit_page], $post_edit_page );
605
-
606
- if( $submenu_overview_key )
607
- $submenu[$post_edit_page][$submenu_overview_key][0] = $data['labels']['name'];
608
-
609
- // post/page rename add new
610
- $submenu_new_key = types_get_array_key_search_in_sub( $submenu[$post_edit_page], $post_new_page );
611
-
612
- if( $submenu_new_key )
613
- $submenu[$post_edit_page][$submenu_new_key][0] = isset( $data['labels']['singular_name'] )
614
- ? 'Add ' . $data['labels']['singular_name']
615
- : 'Add ' . $data['labels']['name'];
616
-
617
- }
618
- }
619
- }
620
- }
621
- }
622
-
623
- add_action( 'admin_menu', 'types_rename_build_in_post_types_menu' );
624
-
625
- /**
626
- * Change labels of build-in post types
627
- *
628
- * @since 1.9
629
- */
630
- function types_rename_build_in_post_types() {
631
- global $wp_post_types;
632
- $custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
633
-
634
- if ( !empty( $custom_types ) ) {
635
- foreach ( $custom_types as $post_type => $data ) {
636
- // only for build_in
637
- if (
638
- isset( $data['_builtin'] )
639
- && $data['_builtin']
640
- && isset( $data['slug'] )
641
- && isset( $data['labels']['name'] )
642
- ) {
643
- // check if slug (post/page) exists
644
- if( isset( $wp_post_types[$data['slug']] ) ) {
645
- // refer $l to post labels
646
- $l = &$wp_post_types[$data['slug']]->labels;
647
-
648
- // change name
649
- $l->name = isset( $data['labels']['name'] ) ? $data['labels']['name'] : $l->name;
650
-
651
- // change singular name
652
- $l->singular_name = isset( $data['labels']['singular_name'] ) ? $data['labels']['singular_name'] : $l->singular_name;
653
-
654
- // change labels
655
- $l->add_new_item = 'Add New';
656
- $l->add_new = 'Add New ' . $l->singular_name;
657
- $l->edit_item = 'Edit ' . $l->singular_name;
658
- $l->new_item = 'New ' . $l->name ;
659
- $l->view_item = 'View ' . $l->name;
660
- $l->search_items = 'Search '. $l->name;
661
- $l->not_found = 'No ' . $l->name . ' found';
662
- $l->not_found_in_trash = 'No ' . $l->name . ' found in Trash';
663
- $l->parent_item_colon = 'Parent '. $l->name;
664
- $l->all_items = 'All ' . $l->name;
665
- $l->menu_name = $l->name;
666
- $l->name_admin_bar = $l->name;
667
-
668
- }
669
- }
670
- }
671
- }
672
- }
673
-
674
- add_action( 'init', 'types_rename_build_in_post_types' );
675
-
676
-
677
- /**
678
- * Visibility of inbuild types
679
- */
680
- function types_visibility_build_in_types() {
681
- $custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
682
-
683
- // Type: Posts
684
- if( isset( $custom_types['post']['public'] )
685
- && $custom_types['post']['public'] == 'hidden' )
686
- remove_menu_page( 'edit.php' );
687
-
688
- // Type: Pages
689
- if( isset( $custom_types['page']['public'] )
690
- && $custom_types['page']['public'] == 'hidden' )
691
- remove_menu_page( 'edit.php?post_type=page' );
692
-
693
- // Type: Media
694
- if( isset( $custom_types['attachment']['public'] )
695
- && $custom_types['attachment']['public'] == 'hidden' )
696
- remove_menu_page( 'upload.php' );
697
- }
698
-
699
- add_action( 'admin_menu', 'types_visibility_build_in_types' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/fields-post.php DELETED
@@ -1,1967 +0,0 @@
1
- <?php
2
-
3
- /*
4
- * Edit post page functions
5
- *
6
- *
7
- *
8
- * Core file with stable and working functions.
9
- * Please add hooks if adjustment needed, do not add any more new code here.
10
- *
11
- * Consider this file half-locked since Types 1.2
12
- */
13
-
14
- // Include conditional field code
15
- require_once WPCF_EMBEDDED_ABSPATH . '/includes/conditional-display.php';
16
-
17
- /**
18
- * Init functions for post edit pages.
19
- *
20
- * Core function. Works and stable. Do not move or change.
21
- * If required, add hooks only.
22
- *
23
- * @param type $post
24
- */
25
- function wpcf_admin_post_init( $post ) {
26
- add_action( 'admin_footer', 'wpcf_admin_fields_postfields_styles' );
27
- wpcf_admin_add_js_settings( 'wpcf_nonce_toggle_group',
28
- '\'' . wp_create_nonce( 'group_form_collapsed' ) . '\'' );
29
- wpcf_admin_add_js_settings( 'wpcf_nonce_toggle_fieldset',
30
- '\'' . wp_create_nonce( 'form_fieldset_toggle' ) . '\'' );
31
-
32
- // Get post_type
33
- $post_type = wpcf_admin_get_edited_post_type( $post );
34
-
35
- /*
36
- *
37
- * This is left to maintain compatibility with older versions
38
- * TODO Remove
39
- */
40
- // Add items to View dropdown
41
- if ( in_array( $post_type, array('view', 'view-template', 'cred-form', 'cred-user-form') ) ) {
42
- add_filter( 'editor_addon_menus_wpv-views',
43
- 'wpcf_admin_post_editor_addon_menus_filter' );
44
- add_action( 'admin_footer', 'wpcf_admin_post_js_validation' );
45
- wpcf_enqueue_scripts();
46
- wp_enqueue_script( 'toolset-colorbox' );
47
- wp_enqueue_style( 'toolset-colorbox' );
48
- }
49
- // Never show on 'Views' and 'Content Templates'
50
- if ( in_array( $post_type, array('view', 'view-template') ) ) {
51
- return false;
52
- }
53
-
54
- /**
55
- * remove custom field WordPress metabox
56
- */
57
- if ( 'hide' == wpcf_get_settings('hide_standard_custom_fields_metabox') ) {
58
- foreach( array( 'normal', 'advanced', 'side' ) as $context) {
59
- remove_meta_box('postcustom', $post_type, $context );
60
- }
61
- }
62
-
63
- // Add marketing box
64
- if( ! wpcf_is_client()
65
- && !in_array( $post_type, array('post', 'page', 'cred-form', 'cred-user-form') )
66
- && !defined( 'WPCF_RUNNING_EMBEDDED' ) ) {
67
-
68
- $settings_help_box = wpcf_get_settings( 'help_box' );
69
- $custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
70
-
71
- if( $settings_help_box == 'all'
72
- || array_key_exists( $post_type, $custom_types ) ) {
73
-
74
- $displaying_custom_content = include( WPCF_ABSPATH . '/marketing/displaying-custom-content/title-content.php' );
75
- add_meta_box( 'add_box_howto', $displaying_custom_content['title'], 'wpcf_admin_post_marketing_displaying_custom_content', $post_type, 'side', 'high' );
76
- }
77
- }
78
-
79
- // Are Types active?
80
- $wpcf_active = false;
81
-
82
- // Get groups
83
- $groups = wpcf_admin_post_get_post_groups_fields( $post );
84
-
85
- foreach ( $groups as $group ) {
86
-
87
- $only_preview = '';
88
-
89
- //If Access plugin activated
90
- if ( function_exists( 'wpcf_access_register_caps' ) ) {
91
- //If user can't view own profile fields
92
- if ( !current_user_can( 'view_fields_in_edit_page_' . $group['slug'] ) ) {
93
- continue;
94
- }
95
- //If user can modify current group in own profile
96
- if ( !current_user_can( 'modify_fields_in_edit_page_' . $group['slug'] ) ) {
97
- $only_preview = 1;
98
- }
99
- }
100
- if ( !empty( $group['fields'] ) && empty( $only_preview ) ) {
101
- $wpcf_active = true;
102
- break;
103
- }
104
- }
105
-
106
- // Activate scripts
107
- if ( $wpcf_active ) {
108
- add_action( 'admin_head', 'wpcf_post_preview_warning' );
109
- wpcf_edit_post_screen_scripts();
110
- }
111
-
112
- // Add validation
113
- add_action( 'admin_footer', 'wpcf_admin_post_js_validation' );
114
-
115
- /*
116
- * TODO Review
117
- * This is forced because of various Child cases
118
- * and when field are rendered via AJAX but not registered yet.
119
- *
120
- * Basically all fields that require additional JS should be added here.
121
- *
122
- * This is a must for now.
123
- * These fields need init JS in various cases.
124
- */
125
- wpcf_field_enqueue_scripts( 'date' );
126
- wpcf_field_enqueue_scripts( 'image' );
127
- wpcf_field_enqueue_scripts( 'file' );
128
- wpcf_field_enqueue_scripts( 'skype' );
129
- wpcf_field_enqueue_scripts( 'numeric' );
130
-
131
- do_action( 'wpcf_admin_post_init', $post_type, $post, $groups, $wpcf_active );
132
- }
133
-
134
- /**
135
- * Add meta boxes.
136
- *
137
- * @param type $post_type
138
- * @param type $post
139
- * @return boolean
140
- */
141
- function wpcf_add_meta_boxes( $post_type, $post )
142
- {
143
-
144
- $post_types_without_meta_boxes = array(
145
- 'view',
146
- 'view-template',
147
- );
148
-
149
- /**
150
- * Do not add metaboxes
151
- *
152
- * Filter allow to add post types which are immune to wpcf_add_meta_boxes()
153
- * function.
154
- *
155
- * @since 1.9.0
156
- *
157
- * @param array $post_types array of post types slugs
158
- */
159
- $post_types_without_meta_boxes = apply_filters(
160
- 'wpcf_exclude_meta_boxes_on_post_type',
161
- $post_types_without_meta_boxes
162
- );
163
-
164
- /** This action is documented in embedded/bootstrap.php */
165
- $post_types_without_meta_boxes = apply_filters(
166
- 'toolset_filter_exclude_own_post_types',
167
- $post_types_without_meta_boxes
168
- );
169
-
170
- /**
171
- * check
172
- */
173
- if ( !empty($post_types_without_meta_boxes) && in_array( $post_type, $post_types_without_meta_boxes ) ) {
174
- return false;
175
- }
176
-
177
- // Fix for empty $post (tabify)
178
- if ( empty( $post->ID ) ) {
179
- $post = get_default_post_to_edit( $post_type, false );
180
- }
181
-
182
- // Get groups
183
- $groups = wpcf_admin_post_get_post_groups_fields( $post );
184
-
185
- foreach ( $groups as $group ) {
186
-
187
- $only_preview = '';
188
-
189
- //If Access plugin activated
190
- if ( function_exists( 'wpcf_access_register_caps' ) ) {
191
- //If user can't view own profile fields
192
- if ( !current_user_can( 'view_fields_in_edit_page_' . $group['slug'] ) ) {
193
- continue;
194
- }
195
- //If user can modify current group in own profile
196
- if ( !current_user_can( 'modify_fields_in_edit_page_' . $group['slug'] ) ) {
197
- $only_preview = 1;
198
- }
199
- }
200
-
201
- // Process fields
202
- if ( !empty( $group['fields'] ) && empty( $only_preview ) ) {
203
- if ( defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
204
- $errors = get_post_meta( $post->ID, '__wpcf-invalid-fields', true );
205
- $group['html'] = array();
206
- foreach ( $group['fields'] as $field ) {
207
- wpcf_admin_post_add_to_editor( $field );
208
- // Note that the $single argument defaults to false, ergo $meta will be allways an array of metadata,
209
- // even for single fields.
210
- $meta = get_post_meta( $post->ID, $field['meta_key'] );
211
- $config = wptoolset_form_filter_types_field( $field, $post->ID );
212
- if ( $errors ) {
213
- $config['validate'] = true;
214
- }
215
- if ( $field['type'] == 'wysiwyg' ) {
216
- $group['html'][] = array('config' => $config, 'meta' => $meta);
217
- } else {
218
- $group['html'][] = wptoolset_form_field( 'post',
219
- $config, $meta );
220
- }
221
- }
222
- // OLD
223
- delete_post_meta( $post->ID, 'wpcf-invalid-fields' );
224
- delete_post_meta( $post->ID, '__wpcf-invalid-fields' );
225
- } else {
226
- // Process fields
227
- $group['fields'] = wpcf_admin_post_process_fields( $post,
228
- $group['fields'], true );
229
- }
230
- }
231
-
232
- // Check if hidden
233
- if ( !isset( $group['__show_meta_box'] ) || $group['__show_meta_box'] != false ) {
234
- // Add meta boxes
235
- if ( empty( $only_preview ) ) {
236
- add_meta_box( "wpcf-group-{$group['slug']}",
237
- wpcf_translate( 'group ' . $group['id'] . ' name',
238
- $group['name'] ), 'wpcf_admin_post_meta_box',
239
- $post_type, $group['meta_box_context'], 'high', $group );
240
- } else {
241
- add_meta_box( "wpcf-group-{$group['slug']}",
242
- wpcf_translate( 'group ' . $group['id'] . ' name',
243
- $group['name'] ),
244
- 'wpcf_admin_post_meta_box_preview', $post_type,
245
- $group['meta_box_context'], 'high', $group );
246
- }
247
- }
248
- }
249
- }
250
-
251
- /**
252
- * Renders meta box content (preview).
253
- *
254
- *
255
- *
256
- * @param type $post
257
- * @param type $group
258
- */
259
- function wpcf_admin_post_meta_box_preview( $post, $group, $echo = '' ){
260
-
261
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
262
- require_once WPCF_EMBEDDED_ABSPATH . '/frontend.php';
263
- global $wpcf;
264
-
265
- if ( isset( $group['args'] ) ) {
266
- $fields = $group['args']['fields'];
267
- } else {
268
- $fields = $group['fields'];
269
- }
270
- if ( isset( $group['slug'] ) ) {
271
- $slug = $group['slug'];
272
- $name = $group['name'];
273
- } else {
274
- $slug = $group['id'];
275
- $name = $group['title'];
276
- }
277
- /**
278
- * fake post object if need
279
- */
280
- $post = wpcf_admin_create_fake_post_if_need($post);
281
-
282
- $group_output = '';
283
- if ( !empty( $echo ) ) {
284
- $group_output = '<h3>This Preview generated for latest post "' . $post->post_title . '"</h3>';
285
- $group_output .= '<div id="test-field-group" class="postbox " >
286
- <h3 class=\'hndle\'><span>' . $name . '</span></h3>
287
- <div class="inside">';
288
- }
289
-
290
- $group_output .= '<table class="form-table fields-preview fields-preview-' . $slug . '">
291
- <tbody>' . "\n\n";
292
-
293
- $content = $code = '';
294
- if( !empty( $fields ) ) {
295
- foreach ( $fields as $field ) {
296
- $html = '';
297
- $params['separator'] = ', ';
298
- if ( wpcf_admin_is_repetitive( $field ) ) {
299
- $wpcf->repeater->set( $post, $field );
300
- $_meta = $wpcf->repeater->_get_meta();
301
- if ( isset( $_meta['custom_order'] ) ) {
302
- $meta = $_meta['custom_order'];
303
- } else {
304
- $meta = array();
305
- }
306
- $content = $code = '';
307
- // Sometimes if meta is empty - array(0 => '') is returned
308
- if ( (count( $meta ) == 1 ) ) {
309
- $meta_id = key( $meta );
310
- $_temp = array_shift( $meta );
311
- if (!is_array($_temp) && strval( $_temp ) == '' ) {
312
-
313
- } else {
314
- $params['field_value'] = $_temp;
315
- if ( !empty( $params['field_value'] ) ) {
316
- $html = types_render_field_single( $field, $params,
317
- $content, $code, $meta_id );
318
- }
319
- }
320
- } else if ( !empty( $meta ) ) {
321
- $output = '';
322
-
323
- if ( isset( $params['index'] ) ) {
324
- $index = $params['index'];
325
- } else {
326
- $index = '';
327
- }
328
-
329
- // Allow wpv-for-each shortcode to set the index
330
- $index = apply_filters( 'wpv-for-each-index', $index );
331
-
332
- if ( $index === '' ) {
333
- $output = array();
334
- foreach ( $meta as $temp_key => $temp_value ) {
335
- $params['field_value'] = $temp_value;
336
- if ( !empty( $params['field_value'] ) ) {
337
- $temp_output = types_render_field_single( $field,
338
- $params, $content, $code, $temp_key );
339
- }
340
- if ( !empty( $temp_output ) ) {
341
- $output[] = $temp_output;
342
- }
343
- }
344
- if ( !empty( $output ) && isset( $params['separator'] ) ) {
345
- $output = implode( html_entity_decode( $params['separator'] ),
346
- $output );
347
- } else if ( !empty( $output ) ) {
348
- $output = implode( '', $output );
349
- }
350
- } else {
351
- // Make sure indexed right
352
- $_index = 0;
353
- foreach ( $meta as $temp_key => $temp_value ) {
354
- if ( $_index == $index ) {
355
- $params['field_value'] = $temp_value;
356
- if ( !empty( $params['field_value'] ) ) {
357
- $output = types_render_field_single( $field,
358
- $params, $content, $code, $temp_key );
359
- }
360
- }
361
- $_index++;
362
- }
363
- }
364
- $html = $output;
365
- }
366
- } else {
367
- $params['field_value'] = get_post_meta( $post->ID,
368
- wpcf_types_get_meta_prefix( $field ) . $field['slug'], true );
369
-
370
- // $html = types_render_field_single( $field, $params, $content, $code );
371
- if ( !empty( $params['field_value'] ) && $field['type'] != 'date' ) {
372
- $html = types_render_field_single( $field, $params, $content,
373
- $code );
374
- }
375
- if ( $field['type'] == 'date' && !empty( $params['field_value'] ) ) {
376
- $html = types_render_field_single( $field, $params, $content,
377
- $code );
378
- if ( $field['data']['date_and_time'] == 'and_time' ) {
379
- $html .= ' ' . date( "H", $params['field_value'] ) . ':' . date( "i",
380
- $params['field_value'] );
381
- }
382
- }
383
- }
384
-
385
- // API filter
386
- $wpcf->field->set( $post, $field );
387
- $field_value = $wpcf->field->html( $html, array() );
388
- $group_output .= '<tr class="wpcf-profile-field-line-' . $field['slug'] . '">
389
- <td scope="row">' . $field['name'] . '</td>
390
- <td>' . $field_value . '</td>
391
- </tr>' . "\n\n";
392
- }
393
- }
394
-
395
- $group_output .= "\n\n</tbody>
396
- </table>";
397
- if ( empty( $echo ) ) {
398
- echo $group_output;
399
- } else {
400
- $group_output .= "\n\n</div></div>";
401
- return $group_output;
402
- }
403
-
404
-
405
-
406
-
407
- }
408
-
409
- /**
410
- * Renders meta box content.
411
- *
412
- * Core function. Works and stable.
413
- * If required, add hooks only.
414
- *
415
- * @todo Revise this 1.1.5
416
- *
417
- * @param type $post
418
- * @param type $group
419
- * @param type $echo
420
- * @param type boolean $open_style_editor if true use code for open style editor when edit group
421
- */
422
- function wpcf_admin_post_meta_box( $post, $group, $echo = '', $open_style_editor = false )
423
- {
424
-
425
- if (
426
- false === $open_style_editor
427
- && defined( 'WPTOOLSET_FORMS_VERSION' )
428
- ) {
429
- if ( isset( $group['args']['html'] ) ) {
430
- /**
431
- * show group description
432
- */
433
- if ( array_key_exists('description', $group['args'] ) && !empty($group['args']['description'])) {
434
- echo '<div class="wpcf-meta-box-description">';
435
- echo wpautop( wpcf_translate( 'group ' . $group['args']['id'] . ' description', $group['args']['description'] ) );
436
- echo '</div>';
437
- }
438
- foreach ( $group['args']['html'] as $field ) {
439
- echo is_array( $field ) ? wptoolset_form_field( 'post',
440
- $field['config'], $field['meta'] ) : $field;
441
- }
442
- }
443
- return;
444
- }
445
-
446
-
447
-
448
- global $wpcf;
449
- /**
450
- * fake post object if need
451
- */
452
- $post = wpcf_admin_create_fake_post_if_need($post);
453
-
454
- static $nonce_added = false;
455
- $group_output = '';
456
- if ( !isset( $group['title'] ) ) {
457
- $temp = $group;
458
- $group = '';
459
- $group['args'] = $temp;
460
- $group['id'] = $temp['slug'];
461
- $group['title'] = $temp['name'];
462
- $name = $temp['name'];
463
- }
464
- if ( !empty( $echo ) ) {
465
- $group_output = '<h3>This Preview generated for latest post "' . $post->post_title . '"</h3>' . "\n" .
466
- '<!-- Previous lines visible only in Admin Style Editor.-->' . "\n\n";
467
- $group_output .= '<div id="wpcf-group-' . $group['id'] . '" class="postbox " >
468
- <h3 class=\'hndle\'><span>' . $name . '</span></h3>
469
- <div class="inside">' . "\n";
470
- }
471
-
472
-
473
- /*
474
- * TODO Document where this is used
475
- */
476
- if ( !$nonce_added && empty( $echo ) ) {
477
- $nonce_action = 'update-' . $post->post_type . '_' . $post->ID;
478
- wp_nonce_field( $nonce_action, '_wpcf_post_wpnonce' );
479
- $nonce_added = true;
480
- }
481
- $group_output .= "\n\n" . '<div id="wpcf-group-metabox-id-' . $group['args']['slug'] . '">' . "\n";
482
- /*
483
- * TODO Move to Conditional code
484
- *
485
- * This is already checked. Use hook to add wrapper DIVS and apply CSS.
486
- */
487
- if ( !empty( $group['args']['_conditional_display'] ) ) {
488
- if ( $group['args']['_conditional_display'] == 'failed' ) {
489
- $group_output .= '<div class="wpcf-cd-group wpcf-cd-group-failed" style="display:none;">';
490
- } else {
491
- $group_output .= '<div class="wpcf-cd-group wpcf-cd-group-passed">';
492
- }
493
- }
494
-
495
-
496
- /*
497
- * TODO Move this into Field code
498
- * Process fields
499
- */
500
- if ( !empty( $group['args']['fields'] ) ) {
501
- // Display description
502
- if ( !empty( $group['args']['description'] ) ) {
503
- $group_output .= '<div class="wpcf-meta-box-description">'
504
- . wpautop( wpcf_translate( 'group ' . $group['args']['id'] . ' description',
505
- $group['args']['description'] ) ) . '</div>';
506
- }
507
- foreach ( $group['args']['fields'] as $field_slug => $field ) {
508
- if ( empty( $field ) || !is_array( $field ) ) {
509
- continue;
510
- }
511
-
512
- $field = $wpcf->field->_parse_cf_form_element( $field );
513
-
514
- if ( isset( $field['wpcf-type'] ) ) { // May be ignored
515
- $field = apply_filters( 'wpcf_fields_' . $field['wpcf-type'] . '_meta_box_form_value_display',
516
- $field );
517
- }
518
-
519
- if ( !isset( $field['#id'] ) ) {
520
- $field['#id'] = wpcf_unique_id( serialize( $field ) );
521
- }
522
- // Render form elements
523
- if (
524
- wpcf_compare_wp_version()
525
- && array_key_exists( '#type', $field )
526
- && 'wysiwyg' == $field['#type']
527
- && !isset( $field['#attributes']['disabled'] )
528
- ) {
529
- // if ( isset( $field['#attributes']['disabled'] ) ) {
530
- // $field['#editor_settings']['tinymce'] = false;
531
- // $field['#editor_settings']['teeny'] = false;
532
- // $field['#editor_settings']['media_buttons'] = false;
533
- // $field['#editor_settings']['quicktags'] = false;
534
- // $field['#editor_settings']['dfw'] = false;
535
- // }
536
- // Especially for WYSIWYG
537
- $group_output .= '<div class="wpcf-wysiwyg">';
538
- $group_output .= '<div id="wpcf-textarea-textarea-wrapper" class="form-item form-item-textarea wpcf-form-item wpcf-form-item-textarea">';
539
- $group_output .= isset( $field['#before'] ) ? $field['#before'] : '';
540
- $group_output .= '<label class="wpcf-form-label wpcf-form-textarea-label">'
541
- . stripslashes( $field['#title'] ) . '</label>';
542
- $group_output .= '<div class="description wpcf-form-description wpcf-form-description-textarea description-textarea">
543
- ' . wpautop( $field['#description'] ) . '</div>';
544
- ob_start();
545
- wp_editor( $field['#value'], $field['#id'],
546
- $field['#editor_settings'] );
547
- $group_output .= ob_get_clean() . "\n\n";
548
- $field['slug'] = str_replace( WPCF_META_PREFIX . 'wysiwyg-', '',
549
- $field_slug );
550
- $field['type'] = 'wysiwyg';
551
- $group_output .= '</div>';
552
- $group_output .= isset( $field['#after'] ) ? $field['#after'] : '';
553
- $group_output .= '</div>';
554
- } else {
555
- if (
556
- array_key_exists( '#type', $field )
557
- && 'wysiwyg' == $field['#type']
558
- ) {
559
- $field['#type'] = 'textarea';
560
- }
561
- if ( !empty( $echo ) ) {
562
- $field['#validate'] = '';
563
- }
564
- $group_output .= wpcf_form_simple( array($field['#id'] => $field) );
565
- }
566
- do_action( 'wpcf_fields_' . $field_slug . '_meta_box_form', $field );
567
- if ( isset( $field['wpcf-type'] ) ) { // May be ignored
568
- do_action( 'wpcf_fields_' . $field['wpcf-type'] . '_meta_box_form', $field );
569
- }
570
- }
571
- }
572
-
573
- /*
574
- * TODO Move to Conditional code
575
- *
576
- * This is already checked. Use hook to add wrapper DIVS and apply CSS.
577
- */
578
- if ( !empty( $group['args']['_conditional_display'] ) ) {
579
- $group_output .= '</div>';
580
- }
581
-
582
- $group_output .= '</div>';
583
-
584
- if ( !empty( $echo ) ) {
585
- $group_output .= "\n\n</div></div>";
586
- return $group_output;
587
- } else {
588
- echo $group_output;
589
- }
590
- }
591
-
592
- /**
593
- * Important save_post hook.
594
- *
595
- * Core function. Works and stable. Do not move or change.
596
- * If required, add hooks only.
597
- *
598
- * @param int $post_ID
599
- * @param WP_Post $post
600
- *
601
- * @return bool
602
- */
603
- function wpcf_admin_post_save_post_hook( $post_ID, $post )
604
- {
605
-
606
- if ( defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
607
-
608
- global $wpcf;
609
- $errors = false;
610
-
611
- // Do not save post if is type of
612
- if ( in_array( $post->post_type,
613
- array('revision', 'view', 'view-template', 'cred-form', 'cred-user-form' ,
614
- 'nav_menu_item', 'mediapage') ) ) {
615
- return false;
616
- }
617
-
618
- $_post_wpcf = array();
619
- if ( !empty( $_POST['wpcf'] ) ) {
620
- $_post_wpcf= $_POST['wpcf'];
621
- }
622
-
623
- // handle checkbox
624
- if ( array_key_exists( '_wptoolset_checkbox', $_POST ) && is_array($_POST['_wptoolset_checkbox']) ) {
625
- foreach ( $_POST['_wptoolset_checkbox'] as $key => $field_value ) {
626
- $field_slug = preg_replace( '/^wpcf\-/', '', $key );
627
- if ( array_key_exists( $field_slug, $_post_wpcf) ) {
628
- continue;
629
- }
630
- $_post_wpcf[$field_slug] = false;
631
- }
632
- }
633
-
634
- // handle radios
635
- if ( array_key_exists( '_wptoolset_radios', $_POST ) && is_array($_POST['_wptoolset_radios']) ) {
636
- foreach ( $_POST['_wptoolset_radios'] as $key => $field_value ) {
637
- $field_slug = preg_replace( '/^wpcf\-/', '', $key );
638
- if ( array_key_exists( $field_slug, $_post_wpcf) ) {
639
- continue;
640
- }
641
- $_post_wpcf[$field_slug] = false;
642
- }
643
- }
644
-
645
-
646
- if ( count( $_post_wpcf ) ) {
647
- $add_error_message = true;
648
- if ( isset( $_POST['post_id']) && $_POST['post_id'] != $post_ID ) {
649
- $add_error_message = false;
650
- }
651
- /**
652
- * check some attachment to delete
653
- */
654
- $delete_attachments = apply_filters( 'wpcf_delete_attachments', true );
655
- $images_to_delete = array();
656
- if ( $delete_attachments && isset($_POST['wpcf']) && array_key_exists( 'delete-image', $_POST['wpcf'] ) && is_array( $_POST['wpcf']['delete-image'] ) ) {
657
- foreach( $_POST['wpcf']['delete-image'] as $image ) {
658
- $images_to_delete[$image] = 1;
659
- }
660
- }
661
- foreach ( $_post_wpcf as $field_slug => $field_value ) {
662
- // Get field by slug
663
- $field = wpcf_fields_get_field_by_slug( $field_slug );
664
- if ( empty( $field ) ) {
665
- continue;
666
- }
667
- // Skip copied fields
668
- if ( isset( $_POST['wpcf_repetitive_copy'][$field['slug']] ) ) {
669
- continue;
670
- }
671
-
672
- $_field_value = !types_is_repetitive( $field ) ? array($field_value) : $field_value;
673
- // Set config
674
- $config = wptoolset_form_filter_types_field( $field, $post_ID, $_post_wpcf);
675
-
676
- /**
677
- * remove from images_to_delete if user add again
678
- */
679
- if ( $delete_attachments && 'image' == $config['type'] ) {
680
- $images = $_field_value;
681
- if ( !is_array( $images ) ) {
682
- $images = array( $images );
683
- }
684
- foreach( $images as $image ) {
685
- if ( array_key_exists( $image, $images_to_delete ) ) {
686
- unset($images_to_delete[$image]);
687
- }
688
- }
689
- }
690
-
691
- /**
692
- * add filter to remove field name from error message
693
- */
694
- /** This filter is toolset-common/toolset-forms/classes/class.validation.php */
695
- add_filter('toolset_common_validation_add_field_name_to_error', '__return_false', 1234, 1);
696
- foreach ( $_field_value as $_k => $_val ) {
697
- // Check if valid
698
- $validation = wptoolset_form_validate_field( 'post', $config, $_val );
699
- $conditional = wptoolset_form_conditional_check( $config );
700
- $not_valid = is_wp_error( $validation ) || !$conditional;
701
- if ($add_error_message && is_wp_error( $validation )) {
702
- $errors = true;
703
- $_errors = $validation->get_error_data();
704
- $_msg = sprintf( __( 'Field "%s" not updated:', 'wpcf' ), $field['name'] );
705
- wpcf_admin_message_store( $_msg . ' ' . implode( ', ', $_errors ), 'error' );
706
- }
707
- if ( $not_valid ) {
708
- if ( types_is_repetitive( $field ) ) {
709
- unset( $field_value[$_k] );
710
- } else {
711
- break;
712
- }
713
- }
714
- }
715
- remove_filter('toolset_common_validation_add_field_name_to_error', '__return_false', 1234, 1);
716
- // Save field
717
- if ( types_is_repetitive( $field ) ) {
718
- $wpcf->repeater->set( $post_ID, $field );
719
- $wpcf->repeater->save( $field_value );
720
- } else if ( !$not_valid ) {
721
- $wpcf->field->set( $post_ID, $field );
722
- $wpcf->field->save( $field_value );
723
- }
724
- do_action( 'wpcf_post_field_saved', $post_ID, $field );
725
- // TODO Move to checkboxes
726
- if ( $field['type'] == 'checkboxes' ) {
727
- if ( !empty( $field['data']['options'] ) ) {
728
- $update_data = array();
729
- foreach ( $field['data']['options'] as $option_id => $option_data ) {
730
- if ( !isset( $_POST['wpcf'][$field['id']][$option_id] ) ) {
731
- if ( isset( $field['data']['save_empty'] ) && $field['data']['save_empty'] == 'yes' ) {
732
- $update_data[$option_id] = 0;
733
- }
734
- } else {
735
- $update_data[$option_id] = $_POST['wpcf'][$field['id']][$option_id];
736
- }
737
- }
738
- update_post_meta( $post_ID, $field['meta_key'], $update_data );
739
- }
740
- }
741
- }
742
-
743
- /**
744
- * delete images
745
- */
746
- if ( $delete_attachments && !empty( $images_to_delete ) ) {
747
- $args = array(
748
- 'post_parent' => $post_ID,
749
- 'posts_per_page' => -1,
750
- );
751
- $children_array = get_children($args);
752
- foreach( $children_array as $child ) {
753
- if ( !array_key_exists( $child->guid, $images_to_delete ) ) {
754
- continue;
755
- }
756
- wp_delete_attachment($child->ID);
757
- }
758
- }
759
-
760
- }
761
- if ( $errors ) {
762
- update_post_meta( $post_ID, '__wpcf-invalid-fields', true );
763
- }
764
- do_action( 'wpcf_post_saved', $post_ID );
765
- return;
766
- }
767
-
768
-
769
-
770
- // OLD
771
-
772
- global $wpcf;
773
-
774
- // Basic cheks
775
- /*
776
- * Allow this hook to be triggered only if Types form is submitted
777
- */
778
- // if ( !isset( $_POST['_wpcf_post_wpnonce'] ) || !wp_verify_nonce( $_POST['_wpcf_post_wpnonce'],
779
- // 'update-' . $post->post_type . '_' . $post_ID ) ) {
780
- // return false;
781
- // }
782
- /*
783
- * Do not save post if is type of:
784
- * revision
785
- * attachment
786
- * wp-types-group
787
- * view
788
- * view-template
789
- * cred-form
790
- */
791
- if ( in_array( $post->post_type, $wpcf->excluded_post_types ) ) {
792
- return false;
793
- }
794
-
795
- /*
796
- *
797
- *
798
- * Get all groups connected to this $post
799
- */
800
- $groups = wpcf_admin_post_get_post_groups_fields( $post );
801
- if ( empty( $groups ) ) {
802
- return false;
803
- }
804
- $all_fields = array();
805
- $_not_valid = array();
806
- $_error = false;
807
-
808
- /*
809
- *
810
- *
811
- * Loop over each group
812
- *
813
- * TODO Document this
814
- * Connect 'wpcf-invalid-fields' with all fields
815
- */
816
- foreach ( $groups as $group ) {
817
- if ( isset( $group['fields'] ) ) {
818
- // Process fields
819
- $fields = wpcf_admin_post_process_fields( $post, $group['fields'],
820
- true, false, 'validation' );
821
- // Validate fields
822
- $form = wpcf_form_simple_validate( $fields );
823
- $all_fields = $all_fields + $fields;
824
- // Collect all not valid fields
825
- if ( $form->isError() ) {
826
- $_error = true; // Set error only to true
827
- $_not_valid = array_merge( $_not_valid,
828
- (array) $form->get_not_valid() );
829
- }
830
- }
831
- }
832
- // Set fields
833
- foreach ( $all_fields as $k => $v ) {
834
- // only Types field
835
- if ( empty( $v['wpcf-id'] ) ) {
836
- continue;
837
- }
838
- $_temp = new WPCF_Field();
839
- $_temp->set( $wpcf->post, $v['wpcf-id'] );
840
- $all_fields[$k]['_field'] = $_temp;
841
- }
842
- foreach ( $_not_valid as $k => $v ) {
843
- // only Types field
844
- if ( empty( $v['wpcf-id'] ) ) {
845
- continue;
846
- }
847
- $_temp = new WPCF_Field();
848
- $_temp->set( $wpcf->post, $v['wpcf-id'] );
849
- $_not_valid[$k]['_field'] = $_temp;
850
- }
851
-
852
- /*
853
- *
854
- * Allow interaction here.
855
- * Conditional will set $error to false if field is conditional
856
- * and not submitted.
857
- */
858
- $error = apply_filters( 'wpcf_post_form_error', $_error, $_not_valid, $all_fields );
859
- $not_valid = apply_filters( 'wpcf_post_form_not_valid', $_not_valid, $_error, $all_fields );
860
-
861
- // Notify user about error
862
- if ( $error ) {
863
- wpcf_admin_message_store(
864
- __( 'Please check your input data', 'wpcf' ), 'error' );
865
- }
866
-
867
- /*
868
- * Save invalid elements so user can be informed after redirect.
869
- */
870
- if ( !empty( $not_valid ) ) {
871
- update_post_meta( $post_ID, 'wpcf-invalid-fields', $not_valid );
872
- }
873
-
874
- /*
875
- *
876
- *
877
- *
878
- *
879
- * Save meta fields
880
- */
881
- if ( !empty( $_POST['wpcf'] ) ) {
882
- foreach ( $_POST['wpcf'] as $field_slug => $field_value ) {
883
-
884
- // Get field by slug
885
- $field = wpcf_fields_get_field_by_slug( $field_slug );
886
- if ( empty( $field ) ) {
887
- continue;
888
- }
889
-
890
- // Set field
891
- $wpcf->field->set( $post_ID, $field );
892
-
893
- // Skip copied fields
894
- // CHECKPOINT
895
- if ( isset( $_POST['wpcf_repetitive_copy'][$field['slug']] ) ) {
896
- continue;
897
- }
898
-
899
- // Don't save invalid
900
- // CHECKPOINT
901
- if ( isset( $not_valid[$field['slug']] ) ) {
902
- continue;
903
- }
904
-
905
-
906
- /*
907
- *
908
- *
909
- * Saving fields
910
- * @since 1.2
911
- *
912
- * We changed way repetitive fields are saved.
913
- * On each save fields are rewritten and order is saved in
914
- * '_$slug-sort-order' meta field.
915
- */
916
-
917
- /*
918
- *
919
- * We marked fields as repetitive in POST['__wpcf_repetitive']
920
- * Without this check we won't save any.
921
- * @see WPCF_Repeater::get_fields_form()
922
- */
923
- if ( isset( $_POST['__wpcf_repetitive'][$wpcf->field->slug] ) ) {
924
- /*
925
- * Use here WPCF_Repeater class.
926
- * WPCF_Repeater::set() - switches to current post
927
- * WPCF_Repeater::save() - saves repetitive field
928
- */
929
- $wpcf->repeater->set( $post_ID, $field );
930
- $wpcf->repeater->save();
931
- } else {
932
- /*
933
- * Use WPCF_Field::save()
934
- */
935
- $wpcf->field->save();
936
- }
937
-
938
- do_action( 'wpcf_post_field_saved', $post_ID, $field );
939
- }
940
- }
941
-
942
- /*
943
- * Process checkboxes
944
- *
945
- * TODO Revise and remove
946
- * Since Types 1.1.5 we moved this check to embedded/includes/checkbox.php
947
- * checkbox.php added permanently to bootstrap.
948
- */
949
- foreach ( $all_fields as $field ) {
950
- if ( !isset( $field['#type'] ) ) {
951
- continue;
952
- }
953
- // if ( $field['#type'] == 'checkbox'
954
- // && !isset( $_POST['wpcf'][$field['wpcf-slug']] ) ) {
955
- // $field_data = wpcf_admin_fields_get_field( $field['wpcf-id'] );
956
- // if ( isset( $field_data['data']['save_empty'] )
957
- // && $field_data['data']['save_empty'] == 'yes' ) {
958
- // update_post_meta( $post_ID,
959
- // wpcf_types_get_meta_prefix( $field ) . $field['wpcf-slug'],
960
- // 0 );
961
- // } else {
962
- // delete_post_meta( $post_ID,
963
- // wpcf_types_get_meta_prefix( $field ) . $field['wpcf-slug'] );
964
- // }
965
- // }
966
- if ( $field['#type'] == 'checkboxes' ) {
967
- $field_data = wpcf_admin_fields_get_field( $field['wpcf-id'] );
968
- if ( !empty( $field_data['data']['options'] ) ) {
969
- $update_data = array();
970
- foreach ( $field_data['data']['options'] as $option_id => $option_data ) {
971
- if ( !isset( $_POST['wpcf'][$field['wpcf-slug']][$option_id] ) ) {
972
- if ( isset( $field_data['data']['save_empty'] ) && $field_data['data']['save_empty'] == 'yes' ) {
973
- $update_data[$option_id] = 0;
974
- }
975
- } else {
976
- $update_data[$option_id] = $_POST['wpcf'][$field['wpcf-slug']][$option_id];
977
- }
978
- }
979
- update_post_meta( $post_ID, wpcf_types_get_meta_prefix( $field ) . $field['wpcf-slug'], $update_data );
980
- }
981
- }
982
- }
983
-
984
- do_action( 'wpcf_post_saved', $post_ID );
985
- }
986
-
987
- /**
988
- *
989
- * Only for attachments, only default checkboxes!
990
- *
991
- * @internal breakpoint
992
- * @param type $post_ID
993
- * @param type $post
994
- */
995
- function wpcf_admin_post_add_attachment_hook( $post_ID, $post )
996
- {
997
- global $wpcf;
998
- /**
999
- * Basic check: only attachment
1000
- */
1001
- if ( 'attachment' != $post->post_type ) {
1002
- return false;
1003
- }
1004
-
1005
- /**
1006
- * Get all groups connected to this $post
1007
- */
1008
- $groups = wpcf_admin_post_get_post_groups_fields( $post );
1009
- if ( empty( $groups ) ) {
1010
- return false;
1011
- }
1012
- $all_fields = array();
1013
- $_not_valid = array();
1014
- $_error = false;
1015
-
1016
-
1017
- /**
1018
- * Loop over each group
1019
- *
1020
- * TODO Document this
1021
- * Connect 'wpcf-invalid-fields' with all fields
1022
- */
1023
- foreach ( $groups as $group ) {
1024
- if ( isset( $group['fields'] ) ) {
1025
- // Process fields
1026
- $fields = wpcf_admin_post_process_fields( $post, $group['fields'],
1027
- true, false, 'validation' );
1028
- // Validate fields
1029
- $form = wpcf_form_simple_validate( $fields );
1030
- $all_fields = $all_fields + $fields;
1031
- // Collect all not valid fields
1032
- if ( $form->isError() ) {
1033
- $_error = true; // Set error only to true
1034
- $_not_valid = array_merge( $_not_valid,
1035
- (array) $form->get_not_valid() );
1036
- }
1037
- }
1038
- }
1039
- // Set fields
1040
- foreach ( $all_fields as $k => $v ) {
1041
- // only Types field
1042
- if ( empty( $v['wpcf-id'] ) ) {
1043
- continue;
1044
- }
1045
- $_temp = new WPCF_Field();
1046
- $_temp->set( $wpcf->post, $v['wpcf-id'] );
1047
- $all_fields[$k]['_field'] = $_temp;
1048
- }
1049
- foreach ( $_not_valid as $k => $v ) {
1050
- // only Types field
1051
- if ( empty( $v['wpcf-id'] ) ) {
1052
- continue;
1053
- }
1054
- $_temp = new WPCF_Field();
1055
- $_temp->set( $wpcf->post, $v['wpcf-id'] );
1056
- $_not_valid[$k]['_field'] = $_temp;
1057
- }
1058
-
1059
- /**
1060
- * Process all checkbox fields
1061
- */
1062
-
1063
- foreach ( $all_fields as $field ) {
1064
- /**
1065
- * only checkbox
1066
- */
1067
- if ( !isset( $field['#type'] ) || 'checkbox' != $field['#type'] ) {
1068
- continue;
1069
- }
1070
- $field_data = wpcf_admin_fields_get_field( $field['wpcf-id'] );
1071
- /**
1072
- * check is checked for new!
1073
- */
1074
- $checked = array_key_exists( 'checked', $field_data['data'] ) && $field_data['data']['checked'];
1075
- /**
1076
- * do not save empty and not checked? fine, go away...
1077
- */
1078
- if ( 'no' == $field_data['data']['save_empty'] && !$checked ) {
1079
- continue;
1080
- }
1081
- /**
1082
- * all other just save...
1083
- */
1084
- $update_data = 0;
1085
- if ( $checked ) {
1086
- $update_data = $field_data['data']['set_value'];
1087
- }
1088
- add_post_meta( $post_ID, wpcf_types_get_meta_prefix( $field ) . $field['wpcf-slug'], $update_data );
1089
- }
1090
- do_action( 'wpcf_attachement_add', $post_ID );
1091
- }
1092
- /**
1093
- * Renders JS validation script.
1094
- */
1095
- function wpcf_admin_post_js_validation() {
1096
- wpcf_form_render_js_validation( '#post' );
1097
- }
1098
-
1099
- /**
1100
- * Creates form elements.
1101
- *
1102
- * Core function. Works and stable. Do not move or change.
1103
- * If required, add hooks only.
1104
- *
1105
- * @param type $post
1106
- * @param type $fields
1107
- * @return type
1108
- */
1109
- function wpcf_admin_post_process_fields( $post = false, $fields = array(),
1110
- $use_cache = true, $add_to_editor = true, $context = 'group' ) {
1111
-
1112
- global $wpcf;
1113
-
1114
- $wpcf->field->use_cache = $use_cache;
1115
- $wpcf->field->add_to_editor = $add_to_editor;
1116
- $wpcf->repeater->use_cache = $use_cache;
1117
- $wpcf->repeater->add_to_editor = $add_to_editor;
1118
-
1119
- // Get cached
1120
- static $cache = array();
1121
- $cache_key = !empty( $post->ID ) ? $post->ID . md5( serialize( $fields ) ) : false;
1122
- if ( $use_cache && $cache_key && isset( $cache[$cache_key] ) ) {
1123
- return $cache[$cache_key];
1124
- }
1125
-
1126
- $fields_processed = array();
1127
-
1128
- // Get invalid fields (if submitted)
1129
- $invalid_fields = array();
1130
- if ( !empty( $post->ID ) ) {
1131
- $invalid_fields = get_post_meta( $post->ID, 'wpcf-invalid-fields', true );
1132
- delete_post_meta( $post->ID, 'wpcf-invalid-fields' );
1133
-
1134
- /*
1135
- *
1136
- * Add it to global $wpcf
1137
- * From now on take it there.
1138
- */
1139
- $wpcf->field->invalid_fields = $invalid_fields;
1140
- }
1141
-
1142
- // TODO WPML Get WPML original fields
1143
- $original_cf = array();
1144
- if ( function_exists( 'wpml_get_copied_fields_for_post_edit' ) && !wpcf_wpml_post_is_original( $post ) ) {
1145
- $__fields_slugs = array();
1146
- foreach ( $fields as $_f ) {
1147
- $__fields_slugs[] = $_f['meta_key'];
1148
- }
1149
- $original_cf = wpml_get_copied_fields_for_post_edit( $__fields_slugs );
1150
- }
1151
-
1152
- if( !empty( $fields ) ) {
1153
- foreach( $fields as $field ) {
1154
-
1155
- // Repetitive fields
1156
- if( wpcf_admin_is_repetitive( $field ) && $context != 'post_relationship' ) {
1157
- // First check if repetitive fields are copied using WPML
1158
- /*
1159
- * TODO All WPML specific code needs moving to
1160
- * /embedded/includes/wpml.php
1161
- *
1162
- * @since Types 1.2
1163
- */
1164
- // TODO WPML move
1165
- if( ! empty( $original_cf['fields'] ) && in_array( wpcf_types_get_meta_prefix( $field ) . $field['slug'],
1166
- $original_cf['fields'] )
1167
- ) {
1168
- /*
1169
- * See if repeater can handle copied fields
1170
- */
1171
- $wpcf->repeater->set( get_post( $original_cf['original_post_id'] ),
1172
- $field );
1173
- $fields_processed = $fields_processed + $wpcf->repeater->get_fields_form();
1174
- } else {
1175
- // Set repeater
1176
- /*
1177
- *
1178
- *
1179
- * @since Types 1.2
1180
- * Now we're using repeater class to handle repetitive forms.
1181
- * Main change is - use form from $field_meta_box_form() without
1182
- * re-processing form elements.
1183
- *
1184
- * Field should pass form as array:
1185
- * 'my_checkbox' => array('#type' => 'checkbox' ...),
1186
- * 'my_textfield' => array('#type' => 'textfield' ...),
1187
- *
1188
- * In form it should set values to be stored.
1189
- * Use hooks to adjust saved data.
1190
- */
1191
- $wpcf->repeater->set( $post, $field );
1192
- $fields_processed = $fields_processed + $wpcf->repeater->get_fields_form();
1193
- }
1194
- /*
1195
- *
1196
- *
1197
- *
1198
- *
1199
- *
1200
- *
1201
- *
1202
- *
1203
- *
1204
- *
1205
- *
1206
- *
1207
- *
1208
- *
1209
- *
1210
- * Non-repetitive fields
1211
- */
1212
- } else {
1213
-
1214
- /*
1215
- * meta_form will be treated as normal form.
1216
- * See if any obstacles prevent us from using completed
1217
- * form from config files.
1218
- *
1219
- * Main change is - use form from $field_meta_box_form() without
1220
- * re-processing form elements.
1221
- *
1222
- * Field should pass form as array:
1223
- * 'my_checkbox' => array('#type' => 'checkbox' ...),
1224
- * 'my_textfield' => array('#type' => 'textfield' ...),
1225
- *
1226
- * In form it should set values to be stored.
1227
- * Use hooks to adjust saved data.
1228
- */
1229
- $wpcf->field->set( $post, $field );
1230
-
1231
- // TODO WPML move Check if repetitive field is copied using WPML
1232
- if( ! empty( $original_cf['fields'] ) ) {
1233
- if( in_array( $wpcf->field->slug, $original_cf['fields'] ) ) {
1234
- // Switch to parent post
1235
- $wpcf->field->set( get_post( $original_cf['original_post_id'] ),
1236
- $field );
1237
- }
1238
- }
1239
- /*
1240
- * From Types 1.2 use complete form setup
1241
- */
1242
- $fields_processed = $fields_processed + $wpcf->field->_get_meta_form();
1243
- }
1244
- }
1245
- }
1246
-
1247
- // Cache results
1248
- if ( $cache_key ) {
1249
- $cache[$cache_key] = $fields_processed;
1250
- }
1251
-
1252
- return $fields_processed;
1253
- }
1254
-
1255
- /**
1256
- * Processes single field.
1257
- *
1258
- * Since Types 1.2 this function changed. It handles single form element.
1259
- * Form element is already fetched, also meta values using class WPCF_Field.
1260
- *
1261
- * Core function. Works and stable. Do not move or change.
1262
- * If required, add hooks only.
1263
- *
1264
- * @todo gradually remove usage of inherited fields
1265
- * @todo Cleanup
1266
- *
1267
- * @staticvar array $repetitive_started
1268
- * @param type $field_object
1269
- * @return mixed boolean|array
1270
- */
1271
- function wpcf_admin_post_process_field( $field_object ) {
1272
-
1273
- /*
1274
- * Since Types 1.2
1275
- * All data we need is stored in global $wpcf
1276
- */
1277
- global $wpcf;
1278
- $post = $wpcf->post;
1279
- $field = (array) $field_object->cf;
1280
- $context = $field_object->context;
1281
- $invalid_fields = $wpcf->field->invalid_fields;
1282
-
1283
- if ( !empty( $field ) ) {
1284
- /*
1285
- * Set Unique ID
1286
- */
1287
- $field_id = 'wpcf-' . $field['type'] . '-' . $field['slug'] . '-'
1288
- . wpcf_unique_id( serialize( $field_object->__current_form_element ) );
1289
-
1290
- /*
1291
- * Get inherited field
1292
- *
1293
- * TODO Deprecated
1294
- *
1295
- * Since Types 1.2 we encourage developers to completely define fields.
1296
- */
1297
- $inherited_field_data = false;
1298
- if ( isset( $field_object->config->inherited_field_type ) ) {
1299
- $_allowed = array(
1300
- 'image' => 'file',
1301
- 'numeric' => 'textfield',
1302
- 'email' => 'textfield',
1303
- 'phone' => 'textfield',
1304
- 'url' => 'textfield',
1305
- );
1306
- if ( !array_key_exists( $field_object->cf['type'], $_allowed ) ) {
1307
- // _deprecated_argument( 'inherited_field_type', '1.2',
1308
- // 'Since Types 1.2 we encourage developers to completely define fields' );
1309
- }
1310
- $inherited_field_data = wpcf_fields_type_action( $field_object->config->inherited_field_type );
1311
- }
1312
-
1313
-
1314
-
1315
- /*
1316
- * CHECKPOINT
1317
- * APPLY FILTERS
1318
- *
1319
- *
1320
- * Moved to WPCF_Field
1321
- * Field value should be already filtered
1322
- *
1323
- * Explanation:
1324
- * When WPCF_Field::set() is called, all these properties are set.
1325
- * WPCF_Field::$cf['value']
1326
- * WPCF_Field::$__meta (single value from DB)
1327
- * WPCF_Field::$meta (single or multiple values if single/repetitive)
1328
- *
1329
- * TODO Make sure value is already filtered and not overwritten
1330
- */
1331
-
1332
- /*
1333
- * Set generic values
1334
- *
1335
- * FUTURE BREAKPOINT
1336
- * Since Types 1.2 we do not encourage relying on generic field data.
1337
- * Only core fields should use this.
1338
- *
1339
- * TODO Open 3rd party fields dir
1340
- */
1341
- $_element = array(
1342
- '#type' => isset( $field_object->config->inherited_field_type ) ? $field_object->config->inherited_field_type : $field['type'],
1343
- '#id' => $field_id,
1344
- '#title' => $field['name'],
1345
- '#name' => 'wpcf[' . $field['slug'] . ']',
1346
- '#value' => isset( $field['value'] ) ? $field['value'] : '',
1347
- 'wpcf-id' => $field['id'],
1348
- 'wpcf-slug' => $field['slug'],
1349
- 'wpcf-type' => $field['type'],
1350
- );
1351
-
1352
- /*
1353
- * TODO Add explanation about creating duplicated fields
1354
- *
1355
- * NOT USED YET
1356
- *
1357
- * Explain users that fields are added if slug is changed
1358
- */
1359
- wpcf_admin_add_js_settings( 'wpcfFieldNewInstanceWarning',
1360
- __( 'If you change slug, new field will be created', 'wpcf' ) );
1361
-
1362
- /*
1363
- * Merge with default element
1364
- *
1365
- * Deprecated from Types 1.2
1366
- * Only core fields use this.
1367
- */
1368
- $element = array_merge( $_element, $field_object->__current_form_element );
1369
-
1370
-
1371
- /*
1372
- *
1373
- *
1374
- *
1375
- *
1376
- *
1377
- *
1378
- *
1379
- *
1380
- *
1381
- *
1382
- *
1383
- *
1384
- *
1385
- *
1386
- *
1387
- * TODO From this point code should be simplified.
1388
- */
1389
-
1390
- if ( isset( $field['description_extra'] ) ) {
1391
- $element['#description'] .= wpautop( $field['description_extra'] );
1392
- }
1393
-
1394
- // Set atributes #1
1395
- if ( isset( $field['disable'] ) ) {
1396
- $field['#disable'] = $field['disable'];
1397
- }
1398
- if ( !empty( $field['disable'] ) ) {
1399
- $field['#attributes']['disabled'] = 'disabled';
1400
- }
1401
- if ( !empty( $field['readonly'] ) ) {
1402
- $field['#attributes']['readonly'] = 'readonly';
1403
- }
1404
-
1405
- // Format description
1406
- if ( !empty( $element['#description'] ) ) {
1407
- $element['#description'] = wpautop( $element['#description'] );
1408
- }
1409
-
1410
- // Set validation element
1411
- if ( isset( $field['data']['validate'] ) ) {
1412
- /*
1413
- *
1414
- *
1415
- * TODO First two check are not needed anymore
1416
- */
1417
- // If array has more than one field - see which one is marked
1418
- if ( $field_object->__multiple && isset( $element['#_validate_this'] ) ) {
1419
- $element['#validate'] = $field['data']['validate'];
1420
- } else if ( !$field_object->__multiple ) {
1421
- $element['#validate'] = $field['data']['validate'];
1422
- }
1423
- }
1424
-
1425
- // Set atributes #2 (override)
1426
- if ( isset( $field['disable'] ) ) {
1427
- $element['#disable'] = $field['disable'];
1428
- }
1429
- if ( !empty( $field['disable'] ) ) {
1430
- $element['#attributes']['disabled'] = 'disabled';
1431
- }
1432
- if ( !empty( $field['readonly'] ) ) {
1433
- $element['#attributes']['readonly'] = 'readonly';
1434
- if ( !empty( $element['#options'] ) ) {
1435
- foreach ( $element['#options'] as $key => $option ) {
1436
- if ( !is_array( $option ) ) {
1437
- $element['#options'][$key] = array(
1438
- '#title' => $key,
1439
- '#value' => $option,
1440
- );
1441
- }
1442
- $element['#options'][$key]['#attributes']['readonly'] = 'readonly';
1443
- if ( $element['#type'] == 'select' ) {
1444
- $element['#options'][$key]['#attributes']['disabled'] = 'disabled';
1445
- }
1446
- }
1447
- }
1448
- if ( $element['#type'] == 'select' ) {
1449
- $element['#attributes']['disabled'] = 'disabled';
1450
- }
1451
- }
1452
-
1453
- // Check if it was invalid on submit and add error message
1454
- if ( $post && !empty( $invalid_fields ) ) {
1455
- if ( isset( $invalid_fields[$element['#id']]['#error'] ) ) {
1456
- $element['#error'] = $invalid_fields[$element['#id']]['#error'];
1457
- }
1458
- }
1459
-
1460
- // TODO WPML move Set WPML locked icon
1461
- if ( wpcf_wpml_field_is_copied( $field ) ) {
1462
- $element['#title'] .= '<img src="' . WPCF_EMBEDDED_RES_RELPATH . '/images/locked.png" alt="'
1463
- . __( 'This field is locked for editing because WPML will copy its value from the original language.', 'wpcf' ) . '" title="'
1464
- . __( 'This field is locked for editing because WPML will copy its value from the original language.', 'wpcf' ) . '" style="position:relative;left:2px;top:2px;" />';
1465
- }
1466
-
1467
- // Add repetitive class
1468
- // TODO WPML move
1469
- if ( types_is_repetitive( $field ) && $context != 'post_relationship' && wpcf_wpml_field_is_copied( $field ) ) {
1470
- if ( !empty( $element['#options'] ) && $element['#type'] != 'select' ) {
1471
- foreach ( $element['#options'] as $temp_key => $temp_value ) {
1472
- $element['#options'][$temp_key]['#attributes']['class'] = isset( $element['#attributes']['class'] ) ? $element['#attributes']['class'] . ' wpcf-repetitive' : 'wpcf-repetitive';
1473
- }
1474
- } else {
1475
- $element['#attributes']['class'] = isset( $element['#attributes']['class'] ) ? $element['#attributes']['class'] . ' wpcf-repetitive' : 'wpcf-repetitive';
1476
- }
1477
- /*
1478
- *
1479
- *
1480
- * Since Types 1.2 we allow same field values
1481
- *
1482
- * TODO Remove
1483
- *
1484
- * wpcf_admin_add_js_settings('wpcfFormRepetitiveUniqueValuesCheckText',
1485
- '\'' . __('Warning: same values set', 'wpcf') . '\'');
1486
- */
1487
- }
1488
-
1489
- // Set read-only if copied by WPML
1490
- // TODO WPML Move this to separate WPML code and use only hooks 1.1.5
1491
- if ( wpcf_wpml_field_is_copied( $field ) ) {
1492
- if ( isset( $element['#options'] ) ) {
1493
- foreach ( $element['#options'] as $temp_key => $temp_value ) {
1494
- if ( isset( $temp_value['#attributes'] ) ) {
1495
- $element['#options'][$temp_key]['#attributes']['readonly'] = 'readonly';
1496
- } else {
1497
- $element['#options'][$temp_key]['#attributes'] = array('readonly' => 'readonly');
1498
- }
1499
- }
1500
- }
1501
- if ( $field['type'] == 'select' ) {
1502
- if ( isset( $element['#attributes'] ) ) {
1503
- $element['#attributes']['disabled'] = 'disabled';
1504
- } else {
1505
- $element['#attributes'] = array('disabled' => 'disabled');
1506
- }
1507
- } else {
1508
- if ( isset( $element['#attributes'] ) ) {
1509
- $element['#attributes']['readonly'] = 'readonly';
1510
- } else {
1511
- $element['#attributes'] = array('readonly' => 'readonly');
1512
- }
1513
- }
1514
- }
1515
-
1516
- // Final filter for disabled if readonly
1517
- if ( isset( $element['#attributes']['readonly'] ) || isset( $element['#attributes']['disabled'] ) ) {
1518
- if ( types_is_repetitive( $field ) ) {
1519
- $element['#name'] .= '[]';
1520
- }
1521
- if ( $field['type'] == 'checkboxes' ) {
1522
- if ( isset( $element['#options'] ) ) {
1523
- foreach ( $element['#options'] as $temp_key => $temp_value ) {
1524
- $value = isset( $temp_value['#default_value'] ) ? $temp_value['#default_value'] : $temp_value['#value'];
1525
- $_after = "<input type=\"hidden\" name=\"{$temp_value['#name']}\" value=\"{$value}\" />";
1526
- $temp_value['#after'] = isset( $temp_value['#after'] ) ? $temp_value['#after'] . $_after : $_after;
1527
- $temp_value['#name'] = "wpcf-disabled[{$field['id']}_{$temp_value['#id']}]";
1528
- $temp_value['#attributes']['disabled'] = 'disabled';
1529
- $element['#options'][$temp_key] = $temp_value;
1530
- }
1531
- }
1532
- } else if ( in_array( $element['#type'],
1533
- array('checkbox', 'checkboxes', 'radios') ) ) {
1534
- if ( isset( $element['#options'] ) ) {
1535
- foreach ( $element['#options'] as $temp_key => $temp_value ) {
1536
- $element['#options'][$temp_key]['#attributes']['disabled'] = 'disabled';
1537
- }
1538
- }
1539
- $value = isset( $element['#default_value'] ) ? $element['#default_value'] : $element['#value'];
1540
- $_after = "<input type=\"hidden\" name=\"{$element['#name']}\" value=\"{$value}\" />";
1541
- $element['#after'] = isset( $element['#after'] ) ? $element['#after'] . $_after : $_after;
1542
- $element['#attributes']['disabled'] = 'disabled';
1543
- $element['#name'] = "wpcf-disabled[{$field['id']}_{$element['#id']}]";
1544
- } else {
1545
- $element['#attributes']['disabled'] = 'disabled';
1546
- if ( is_array( $element['#value'] ) ) {//$field['type'] == 'skype' ) {
1547
- $element['#value'] = array_shift( $element['#value'] );
1548
- }
1549
- $value = htmlentities( $element['#value'] );
1550
- $_after = "<input type=\"hidden\" name=\"{$element['#name']}\" value=\"{$value}\" />";
1551
- $element['#after'] = isset( $element['#after'] ) ? $element['#after'] . $_after : $_after;
1552
- $element['#name'] = "wpcf-disabled[{$field['id']}_{$element['#id']}]";
1553
- }
1554
- }
1555
- return array('field' => $field, 'element' => $element);
1556
- }
1557
- return false;
1558
- }
1559
-
1560
- /**
1561
- * Gets all groups and fields for post.
1562
- *
1563
- * Core function. Works and stable. Do not move or change.
1564
- * If required, add hooks only.
1565
- *
1566
- * @param type $post_ID
1567
- * @return type
1568
- */
1569
- function wpcf_admin_post_get_post_groups_fields( $post = false, $context = 'group' )
1570
- {
1571
- // Get post_type
1572
- /*
1573
- *
1574
- *
1575
- * Since WP 3.5 | Types 1.2
1576
- * Looks like $post is altered with get_post_type()
1577
- * We do not want that if post is already set
1578
- */
1579
- if ( !empty( $post->post_type ) ) {
1580
- $post_type = $post->post_type;
1581
- } else if ( !empty( $post ) ) {
1582
- $post_type = get_post_type( $post );
1583
- } else {
1584
- if ( !isset( $_GET['post_type'] ) ) {
1585
- $post_type = 'post';
1586
- } else if ( in_array( $_GET['post_type'], get_post_types( array('show_ui' => true) ) ) ) {
1587
- $post_type = $_GET['post_type'];
1588
- } else {
1589
- $post_type = 'post';
1590
- }
1591
- }
1592
-
1593
- // Get post terms
1594
- $support_terms = false;
1595
- if ( !empty( $post ) ) {
1596
- $post->_wpcf_post_terms = array();
1597
- $taxonomies = get_taxonomies( '', 'objects' );
1598
- if ( !empty( $taxonomies ) ) {
1599
- foreach ( $taxonomies as $tax_slug => $tax ) {
1600
- $temp_tax = get_taxonomy( $tax_slug );
1601
- if ( !in_array( $post_type, $temp_tax->object_type ) ) {
1602
- continue;
1603
- }
1604
- $support_terms = true;
1605
- $terms = wp_get_post_terms( $post->ID, $tax_slug,
1606
- array('fields' => 'all') );
1607
- foreach ( $terms as $term_id ) {
1608
- $post->_wpcf_post_terms[] = $term_id->term_taxonomy_id;
1609
- }
1610
- }
1611
- }
1612
- }
1613
-
1614
- // Get post template
1615
- if ( empty( $post ) ) {
1616
- $post = new stdClass();
1617
- $post->_wpcf_post_template = false;
1618
- $post->_wpcf_post_views_template = false;
1619
- } else {
1620
- $post->_wpcf_post_template = get_post_meta( $post->ID, '_wp_page_template', true );
1621
- $post->_wpcf_post_views_template = get_post_meta( $post->ID, '_views_template', true );
1622
- }
1623
-
1624
- if ( empty( $post->_wpcf_post_terms ) ) {
1625
- $post->_wpcf_post_terms = array();
1626
- }
1627
-
1628
- // Filter groups
1629
- $groups = array();
1630
- $groups_all = apply_filters( 'wpcf_post_groups_all', wpcf_admin_fields_get_groups(), $post, $context );
1631
- foreach ( $groups_all as $temp_key => $temp_group ) {
1632
- if ( empty( $temp_group['is_active'] ) ) {
1633
- unset( $groups_all[$temp_key] );
1634
- continue;
1635
- }
1636
- // Get filters
1637
- // Post Types
1638
- $groups_all[$temp_key]['_wp_types_group_post_types'] = explode( ',',
1639
- trim( get_post_meta( $temp_group['id'],
1640
- '_wp_types_group_post_types', true ), ',' ) );
1641
-
1642
- // Taxonomies
1643
- $groups_all[$temp_key]['_wp_types_group_terms'] = explode( ',',
1644
- trim( get_post_meta( $temp_group['id'], '_wp_types_group_terms',
1645
- true ), ',' ) );
1646
-
1647
- // Templates
1648
- $groups_all[$temp_key]['_wp_types_group_templates'] = explode( ',',
1649
- trim( get_post_meta( $temp_group['id'],
1650
- '_wp_types_group_templates', true ), ',' ) );
1651
-
1652
- // Data-Dependant
1653
- $groups_all[$temp_key]['_wpcf_conditional_display'] =
1654
- get_post_meta( $temp_group['id'], '_wpcf_conditional_display' );
1655
-
1656
- $post_type_filter = $groups_all[$temp_key]['_wp_types_group_post_types'][0] == 'all'
1657
- || empty( $groups_all[$temp_key]['_wp_types_group_post_types'][0] )
1658
- ? -1
1659
- : 0;
1660
- $taxonomy_filter = $groups_all[$temp_key]['_wp_types_group_terms'][0] == 'all'
1661
- || empty( $groups_all[$temp_key]['_wp_types_group_terms'][0] )
1662
- ? -1
1663
- : 0;
1664
- $template_filter = $groups_all[$temp_key]['_wp_types_group_templates'][0] == 'all'
1665
- || empty( $groups_all[$temp_key]['_wp_types_group_templates'][0] )
1666
- ? -1
1667
- : 0;
1668
-
1669
- $groups_all[$temp_key] = apply_filters( 'wpcf_post_group_filter_settings', $groups_all[$temp_key], $post, $context, $post->_wpcf_post_terms );
1670
-
1671
- // See if post type matches
1672
- if ( $post_type_filter == 0 && in_array( $post_type,
1673
- $groups_all[$temp_key]['_wp_types_group_post_types'] ) ) {
1674
- $post_type_filter = 1;
1675
- }
1676
-
1677
- // See if terms match
1678
- if ( $taxonomy_filter == 0 ) {
1679
- foreach ( $post->_wpcf_post_terms as $temp_post_term ) {
1680
- if ( in_array( $temp_post_term,
1681
- $groups_all[$temp_key]['_wp_types_group_terms'] ) ) {
1682
- $taxonomy_filter = 1;
1683
- }
1684
- }
1685
- }
1686
-
1687
- // See if template match
1688
- if ( $template_filter == 0 ) {
1689
- if ( (!empty( $post->_wpcf_post_template ) && in_array( $post->_wpcf_post_template,
1690
- $groups_all[$temp_key]['_wp_types_group_templates'] )) || (!empty( $post->_wpcf_post_views_template ) && in_array( $post->_wpcf_post_views_template,
1691
- $groups_all[$temp_key]['_wp_types_group_templates'] )) ) {
1692
- $template_filter = 1;
1693
- }
1694
- }
1695
-
1696
- /**
1697
- * if ALL must met
1698
- */
1699
- if( isset( $groups_all[$temp_key]['filters_association'] )
1700
- && $groups_all[$temp_key]['filters_association'] == 'all' ) {
1701
-
1702
- // if no conditions are set, do not display the group
1703
- // - this is important because ounce filter association is set to "all"
1704
- // it's not unset even if the user removes all conditions
1705
- if( $post_type_filter == 0
1706
- && $template_filter == 0
1707
- && $taxonomy_filter == -1
1708
- && empty( $groups_all[$temp_key]['_wpcf_conditional_display'] ) ) {
1709
- unset( $groups_all[$temp_key] );
1710
-
1711
- // there are conditions set
1712
- } else {
1713
- // post types
1714
- // accepted if none isset || one has to match (proofed above)
1715
- if( empty( $groups_all[$temp_key]['_wp_types_group_post_types'][0] ) )
1716
- $post_type_filter = 1;
1717
-
1718
- // taxonomies
1719
- // none isset || all have to match
1720
- if( empty( $groups_all[$temp_key]['_wp_types_group_terms'][0] )
1721
- || $groups_all[$temp_key]['_wp_types_group_terms'][0] == 'all' ) {
1722
- $taxonomy_filter = 1;
1723
- } else {
1724
- $taxonomy_filter = 1;
1725
- // check all terms which need to be active
1726
- foreach ( $groups_all[$temp_key]['_wp_types_group_terms'] as $term_has_to_match ) {
1727
- // break on first term not active
1728
- if( ! in_array( $term_has_to_match, $post->_wpcf_post_terms ) ) {
1729
- $taxonomy_filter = 0;
1730
- break;
1731
- }
1732
- }
1733
- }
1734
-
1735
- // templates
1736
- // one has to match (proofed above) || none isset
1737
- if( empty( $groups_all[$temp_key]['_wp_types_group_templates'][0] ) )
1738
- $template_filter = 1;
1739
- }
1740
- }
1741
-
1742
- // Filter by association
1743
- if ( empty( $groups_all[$temp_key]['filters_association'] ) ) {
1744
- $groups_all[$temp_key]['filters_association'] = 'any';
1745
- }
1746
- // If context is post_relationship allow all groups that match post type
1747
- if ( $context == 'post_relationships_header' ) {
1748
- $groups_all[$temp_key]['filters_association'] = 'any';
1749
- }
1750
-
1751
- if ( $post_type_filter == -1 && $taxonomy_filter == -1 && $template_filter == -1 ) {
1752
- $passed = 1;
1753
- } else if ( $groups_all[$temp_key]['filters_association'] == 'any' ) {
1754
- $passed = $post_type_filter == 1 || $taxonomy_filter == 1 || $template_filter == 1;
1755
- } else {
1756
- $passed = $post_type_filter != 0 && $taxonomy_filter != 0 && $template_filter != 0;
1757
- }
1758
- if ( !$passed ) {
1759
- unset( $groups_all[$temp_key] );
1760
- } else {
1761
- $groups_all[$temp_key]['fields'] = wpcf_admin_fields_get_fields_by_group( $temp_group['id'],
1762
- 'slug', true, false, true );
1763
- }
1764
- }
1765
- $groups = apply_filters( 'wpcf_post_groups', $groups_all, $post, $context );
1766
- return $groups;
1767
- }
1768
-
1769
- /**
1770
- * Stores fields for editor menu.
1771
- *
1772
- * Core function. Works and stable. Do not move or change.
1773
- * If required, add hooks only.
1774
- *
1775
- * @staticvar array $fields
1776
- * @param type $field
1777
- * @return array
1778
- */
1779
- function wpcf_admin_post_add_to_editor( $field ) {
1780
- static $fields = array();
1781
- if ( $field == 'get' ) {
1782
- return $fields;
1783
- }
1784
- if (
1785
- empty( $fields )
1786
- && ! (
1787
- apply_filters( 'toolset_is_views_available', false )
1788
- || apply_filters( 'toolset_is_views_embedded_available', false )
1789
- )
1790
- ) {
1791
- add_action( 'admin_enqueue_scripts', 'wpcf_admin_post_add_to_editor_js' );
1792
- }
1793
- $fields[$field['id']] = $field;
1794
- }
1795
-
1796
- /**
1797
- * Renders JS for editor menu.
1798
- *
1799
- * Core function. Works and stable. Do not move or change.
1800
- * If required, add hooks only.
1801
- *
1802
- * @return type
1803
- */
1804
- function wpcf_admin_post_add_to_editor_js() {
1805
-
1806
- // since 1.3 we do not use global $post
1807
- $post = wpcf_admin_get_edited_post();
1808
- if ( empty( $post ) ) {
1809
- $post = (object) array('ID' => -1);
1810
- $post->post_type = false;
1811
- }
1812
-
1813
- $fields = wpcf_admin_post_add_to_editor( 'get' );
1814
- $groups = wpcf_admin_post_get_post_groups_fields( $post );
1815
-
1816
-
1817
- if ( empty( $fields ) || empty( $groups ) ) {
1818
- /**
1819
- * check user fields too, but only when CF are empty
1820
- */
1821
- include_once dirname(__FILE__).'/usermeta-post.php';
1822
- $groups = wpcf_admin_usermeta_get_groups_fields();
1823
- if ( empty( $groups ) ) {
1824
- return false;
1825
- }
1826
- }
1827
- $editor_addon = new Editor_addon( 'types',
1828
- __( 'Insert Types Shortcode', 'wpcf' ),
1829
- WPCF_EMBEDDED_RES_RELPATH . '/js/types_editor_plugin.js',
1830
- '', true, 'icon-types-logo ont-icon-18 ont-color-gray' );
1831
-
1832
- foreach ( $groups as $group ) {
1833
- if ( empty( $group['fields'] ) ) {
1834
- continue;
1835
- }
1836
- foreach ( $group['fields'] as $group_field_id => $group_field ) {
1837
- if ( !isset( $fields[$group_field_id] ) ) {
1838
- continue;
1839
- }
1840
- $field = $fields[$group_field_id];
1841
- $callback = 'wpcfFieldsEditorCallback(\'' . $field['id']
1842
- . '\', \'postmeta\', ' . $post->ID . ')';
1843
-
1844
- $editor_addon->add_insert_shortcode_menu( stripslashes( $field['name'] ),
1845
- trim( wpcf_fields_get_shortcode( $field ), '[]' ),
1846
- $group['name'], $callback );
1847
- }
1848
- }
1849
- }
1850
-
1851
- /**
1852
- * Adds items to view dropdown.
1853
- *
1854
- * Core function. Works and stable. Do not move or change.
1855
- * If required, add hooks only.
1856
- *
1857
- * @todo Remove (to WPCF_WPViews)
1858
- *
1859
- * @param type $menu
1860
- * @return type
1861
- */
1862
- function wpcf_admin_post_editor_addon_menus_filter( $menu ) {
1863
-
1864
- global $wpcf;
1865
-
1866
- $post = wpcf_admin_get_edited_post();
1867
- if ( empty( $post ) ) {
1868
- $post = (object) array('ID' => -1);
1869
- }
1870
-
1871
- $groups = wpcf_admin_fields_get_groups( TYPES_CUSTOM_FIELD_GROUP_CPT_NAME, 'group_active' );
1872
- $all_post_types = implode( ' ', get_post_types( array('public' => true) ) );
1873
- $add = array();
1874
- if ( !empty( $groups ) ) {
1875
- // $group_id is blank therefore not equal to $group['id']
1876
- // use array for item key and CSS class
1877
- $item_styles = array();
1878
-
1879
- foreach ( $groups as $group_id => $group ) {
1880
- $fields = wpcf_admin_fields_get_fields_by_group( $group['id'],
1881
- 'slug', true, false, true );
1882
- if ( !empty( $fields ) ) {
1883
- // code from Types used here without breaking the flow
1884
- // get post types list for every group or apply all
1885
- $post_types = get_post_meta( $group['id'],
1886
- '_wp_types_group_post_types', true );
1887
- if ( $post_types == 'all' ) {
1888
- $post_types = $all_post_types;
1889
- }
1890
- $post_types = trim( str_replace( ',', ' ', $post_types ) );
1891
- $item_styles[$group['name']] = $post_types;
1892
-
1893
- foreach ( $fields as $field_id => $field ) {
1894
-
1895
- // Use field class
1896
- $wpcf->field->set( $wpcf->post, $field );
1897
-
1898
- // Get field data
1899
- $data = (array) $wpcf->field->config;
1900
- // Get inherited field
1901
- if ( isset( $data['inherited_field_type'] ) ) {
1902
- $inherited_field_data = wpcf_fields_type_action( $data['inherited_field_type'] );
1903
- }
1904
-
1905
- $callback = 'wpcfFieldsEditorCallback(\'' . $field['id']
1906
- . '\', \'postmeta\', ' . $post->ID . ')';
1907
-
1908
- $menu[$group['name']][stripslashes( $field['name'] )] = array(
1909
- stripslashes( $field['name'] ), trim( wpcf_fields_get_shortcode( $field ),
1910
- '[]' ), $group['name'], $callback);
1911
-
1912
- /*
1913
- * Since Types 1.2
1914
- * We use field class to enqueue JS and CSS
1915
- */
1916
- $wpcf->field->enqueue_script();
1917
- $wpcf->field->enqueue_style();
1918
- }
1919
- }
1920
- }
1921
- }
1922
-
1923
- return $menu;
1924
- }
1925
-
1926
- function wpcf_admin_post_marketing_displaying_custom_content() {
1927
- $displaying_custom_content = include( WPCF_ABSPATH . '/marketing/displaying-custom-content/title-content.php' );
1928
- echo $displaying_custom_content['content'];
1929
- }
1930
-
1931
- function wpcf_post_preview_warning() {
1932
- $post = wpcf_admin_get_edited_post();
1933
- // Add preview warning
1934
- if ( isset( $post->post_status ) && !in_array( $post->post_status,
1935
- array('auto-draft', 'draft') ) && !in_array( $post->post_type,
1936
- array('cred', 'view', 'view-template') ) ) {
1937
- wp_enqueue_style( 'wp-pointer' );
1938
- wp_enqueue_script( 'wp-pointer' );
1939
-
1940
- ?><script type="text/javascript">
1941
- if ( "undefined" != typeof typesPostScreen ) {
1942
- typesPostScreen.previewWarning(
1943
- '<?php esc_attr_e( __( 'Preview warning', 'wpcf' ) ); ?>',
1944
- '<?php esc_attr_e( sprintf( __( 'Custom field changes cannot be previewed until %s is updated', 'wpcf' ), $post->post_type ) ); ?>');
1945
- }
1946
- </script><?php
1947
- }
1948
- }
1949
-
1950
- /**
1951
- * Create fake post object.
1952
- *
1953
- * Create fake post object if in system is no post.
1954
- *
1955
- * @param mixed $post
1956
- * @return object
1957
- *
1958
- */
1959
- function wpcf_admin_create_fake_post_if_need($post)
1960
- {
1961
- if ( !is_object( $post ) ) {
1962
- $post = new stdClass();
1963
- $post->post_title = 'Lorem Ipsum';
1964
- $post->ID = 0;
1965
- }
1966
- return $post;
1967
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/fields.php DELETED
@@ -1,967 +0,0 @@
1
- <?php
2
-
3
- function wpcf_admin_fields_get_active_fields_by_post_type($post_type)
4
- {
5
- $custom_fields = array();
6
- $groups = wpcf_admin_fields_get_groups(TYPES_CUSTOM_FIELD_GROUP_CPT_NAME, true, true);
7
- if ( empty($groups) ) {
8
- return $custom_fields;
9
- }
10
- foreach ($groups as $group) {
11
- $types = wpcf_admin_get_post_types_by_group($group['id']);
12
- if ( !empty($types) && !in_array($post_type, $types) ) {
13
- continue;
14
- }
15
- if (isset($group['fields'])) {
16
- $custom_fields += $group['fields'];
17
- }
18
- }
19
- return $custom_fields;
20
- }
21
-
22
-
23
- /**
24
- * Gets all groups.
25
- *
26
- * @param string $post_type
27
- * @param boolean|string $only_active
28
- * @param boolean|string $add_fields - 'field_active', 'field_all', false (to omitt fields)
29
- * @return array array of custom fields definition
30
- */
31
- function wpcf_admin_fields_get_groups( $post_type = TYPES_CUSTOM_FIELD_GROUP_CPT_NAME, $only_active = false, $add_fields = false ) {
32
- $cache_group = 'types_cache_groups';
33
- $cache_key = md5( 'group::_get_group' . $post_type );
34
- $cached_object = wp_cache_get( $cache_key, $cache_group );
35
- if ( false === $cached_object ) {
36
- $groups = get_posts( 'numberposts=-1&post_type=' . $post_type . '&post_status=null' );
37
- wp_cache_add( $cache_key, $groups, $cache_group );
38
- } else {
39
- $groups = $cached_object;
40
- }
41
- $_groups = array();
42
- if ( !empty( $groups ) ) {
43
- foreach ( $groups as $k => $group ) {
44
- $group = wpcf_admin_fields_adjust_group( $group, $add_fields );
45
- if ( $only_active && !$group['is_active'] ) {
46
- continue;
47
- }
48
- $_groups[$k] = $group;
49
- }
50
- }
51
- return $_groups;
52
- }
53
-
54
- /**
55
- * Gets group by ID.
56
- *
57
- * Since 1.2 we enabled fetching by post title.
58
- *
59
- * @param $group_id
60
- * @param string $post_type
61
- * @param bool $add_fields
62
- * @return array
63
- */
64
- function wpcf_admin_fields_get_group( $group_id, $post_type = TYPES_CUSTOM_FIELD_GROUP_CPT_NAME,
65
- $add_fields = false ) {
66
- $group = get_post( $group_id );
67
- if ( empty( $group->ID ) ) {
68
- $group = get_page_by_title( $group_id, OBJECT, $post_type );
69
- }
70
- if ( empty( $group->ID ) ) {
71
- $group = get_page_by_path( $group_id, OBJECT, $post_type );
72
- }
73
- if ( empty( $group->ID ) || $group->post_type != $post_type ) {
74
- return array();
75
- }
76
- return wpcf_admin_fields_adjust_group( $group, $add_fields );
77
- }
78
-
79
- /**
80
- * Converts post data.
81
- *
82
- * @param $post
83
- * @param bool $add_fields
84
- * @return array
85
- */
86
- function wpcf_admin_fields_adjust_group( $post, $add_fields = false ) {
87
- if ( empty( $post ) ) {
88
- return false;
89
- }
90
- $group = array();
91
- $group['id'] = $post->ID;
92
- $group['slug'] = $post->post_name;
93
- $group['name'] = $post->post_title;
94
- $group['description'] = $post->post_content;
95
- $group['meta_box_context'] = 'normal';
96
- $group['meta_box_priority'] = 'high';
97
- $group['is_active'] = $post->post_status == 'publish' ? true : false;
98
- $group['filters_association'] = get_post_meta( $post->ID, '_wp_types_group_filters_association', true );
99
- $group[WPCF_AUTHOR] = $post->post_author;
100
-
101
- /**
102
- * add _wp_types_group_showfor
103
- *
104
- * "all" - for all groups
105
- * array() - if any
106
- */
107
- if ( TYPES_USER_META_FIELD_GROUP_CPT_NAME == $post->post_type ) {
108
- $data = get_post_meta($post->ID, '_wp_types_group_showfor', true);
109
- if ( 'all' != $data ) {
110
- $data = array_values(array_filter(explode(',',$data)));
111
- }
112
- if ( empty($data) ) {
113
- $data = 'all';
114
- }
115
- $group['_wp_types_group_showfor'] = $data;
116
- }
117
-
118
- // Attach fields if required (since 1.3)
119
- if ( $add_fields ) {
120
- $active = $add_fields == 'fields_active' ? true : false;
121
- $group['fields'] = wpcf_admin_fields_get_fields_by_group( $post->ID, 'slug', $active );
122
- }
123
-
124
- return $group;
125
- }
126
-
127
- /**
128
- * Gets Fields Admin Styles supported by specific group.
129
- *
130
- * @param int $group_id
131
- * @return string
132
- */
133
- function wpcf_admin_get_groups_admin_styles_by_group( $group_id ) {
134
- if (
135
- defined( 'TYPES_USE_STYLING_EDITOR' )
136
- && TYPES_USE_STYLING_EDITOR
137
- ) {
138
- $admin_styles = get_post_meta( $group_id, '_wp_types_group_admin_styles', true );
139
-
140
- return trim( $admin_styles );
141
- }
142
- }
143
-
144
- /**
145
- * Saves group's admin styles
146
- *
147
- * @param type $group_id
148
- * @param type $padmin_styles
149
- */
150
- function wpcf_admin_fields_save_group_admin_styles( $group_id, $admin_styles ) {
151
- update_post_meta( $group_id, '_wp_types_group_admin_styles', $admin_styles );
152
- }
153
-
154
- /**
155
- * Gets all fields.
156
- *
157
- * @todo Move to WPCF_Fields
158
- * @param bool $only_active
159
- * @param bool $disabled_by_type
160
- * @param bool $strictly_active
161
- * @param string $option_name
162
- * @param bool $use_cache
163
- * @param bool $clear_cache
164
- * @return array
165
- *
166
- * added param $use_cache by Gen (used when adding new fields to group)
167
- * added param $use_cache by Gen (used when adding new fields to group)
168
- */
169
- function wpcf_admin_fields_get_fields( $only_active = false,
170
- $disabled_by_type = false, $strictly_active = false,
171
- $option_name = 'wpcf-fields', $use_cache = true, $clear_cache = false ) {
172
-
173
- static $cache = array();
174
-
175
- if ( $clear_cache ) {
176
- $cache = array();
177
- }
178
-
179
- /**
180
- * Sanitize option name
181
- */
182
- switch( $option_name ) {
183
- case 'wpcf-usermeta':
184
- case 'wpcf-fields':
185
- case WPCF_Field_Term_Definition_Factory::FIELD_DEFINITIONS_OPTION:
186
- break;
187
- default:
188
- $option_name = 'wpcf-fields';
189
- break;
190
- }
191
-
192
- $cache_key = md5( $only_active . $disabled_by_type . $strictly_active . $option_name . $use_cache );
193
- if ( isset( $cache[$cache_key] ) && $use_cache == true ) {
194
- return $cache[$cache_key];
195
- }
196
- $required_data = array('id', 'name', 'type', 'slug');
197
- $fields = (array) get_option( $option_name, array() );
198
- foreach ( $fields as $k => $v ) {
199
- $failed = false;
200
- foreach ( $required_data as $required ) {
201
- if ( !isset( $v[$required] ) ) {
202
- $failed = true;
203
- continue;
204
- }
205
- if ( is_numeric($v[$required]) === true) {
206
- $failed = true;
207
- continue;
208
- }
209
- }
210
- if ( is_numeric($k) === true || $failed ) {
211
- unset( $fields[$k] );
212
- continue;
213
- }
214
- // This call loads config file
215
- $data = wpcf_fields_type_action( $v['type'] );
216
- if ( empty( $data ) ) {
217
- unset( $fields[$k] );
218
- continue;
219
- }
220
- if ( isset( $data['wp_version'] )
221
- && wpcf_compare_wp_version( $data['wp_version'], '<' ) ) {
222
- unset( $fields[$k] );
223
- continue;
224
- }
225
- if ( $strictly_active ) {
226
- if ( !empty( $v['data']['disabled'] ) || !empty( $v['data']['disabled_by_type'] ) ) {
227
- unset( $fields[$k] );
228
- continue;
229
- }
230
- } else {
231
- if ( ($only_active && !empty( $v['data']['disabled'] ) ) ) {
232
- unset( $fields[$k] );
233
- continue;
234
- }
235
- if ( !$disabled_by_type && !empty( $v['data']['disabled_by_type'] ) ) {
236
- unset( $fields[$k] );
237
- continue;
238
- }
239
- }
240
- $v['id'] = $k;
241
- $v['meta_key'] = wpcf_types_get_meta_prefix( $v ) . $k;
242
-
243
- $option_name_to_meta_type = array(
244
- 'wpcf-fields' => 'postmeta',
245
- 'wpcf-usermeta' => 'usermeta',
246
- WPCF_Field_Term_Definition_Factory::FIELD_DEFINITIONS_OPTION => 'termmeta'
247
- );
248
-
249
- $v['meta_type'] = $option_name_to_meta_type[ $option_name ];
250
- $fields[$k] = wpcf_sanitize_field( $v );
251
- }
252
- $cache[$cache_key] = apply_filters( 'types_fields', $fields );
253
- return $cache[$cache_key];
254
- }
255
-
256
- function wpcf_admin_fields_get_field_by_meta_key( $meta_key )
257
- {
258
- $fields = wpcf_admin_fields_get_fields();
259
- foreach( $fields as $field) {
260
- if ( $meta_key == $field['meta_key'] ) {
261
- return $field;
262
- }
263
- }
264
- }
265
-
266
- /**
267
- * Gets field by ID.
268
- * Modified by Gen, 13.02.2013
269
- *
270
- * @param string $field_id
271
- * @param bool $only_active
272
- * @param bool $disabled_by_type
273
- * @param bool $strictly_active
274
- * @param string $option_name
275
- * @return array
276
- */
277
- function wpcf_admin_fields_get_field( $field_id, $only_active = false,
278
- $disabled_by_type = false, $strictly_active = false,
279
- $option_name = 'wpcf-fields' ) {
280
- $fields = wpcf_admin_fields_get_fields( $only_active, $disabled_by_type,
281
- $strictly_active, $option_name );
282
- $field = !empty( $fields[$field_id] ) ? $fields[$field_id] : array();
283
- if ( !empty( $field ) ) {
284
- return apply_filters( 'wpcf_field', $field );
285
- }
286
- return array();
287
- }
288
-
289
- /**
290
- * Gets field by slug.
291
- * Modified by Gen, 13.02.2013
292
- *
293
- * @param type $slug
294
- * @return type
295
- */
296
- function wpcf_fields_get_field_by_slug( $slug, $meta_name = 'wpcf-fields' ) {
297
- return wpcf_admin_fields_get_field( $slug, false, false, false, $meta_name );
298
- }
299
-
300
- add_filter('wpcf_fields_by_group', 'wpcf_admin_fields_get_fields_by_group', 10, 1);
301
-
302
- /**
303
- * Gets all fields that belong to specific group.
304
- *
305
- * @param int $group_id
306
- * @param string $key
307
- * @param bool $only_active
308
- * @param bool $disabled_by_type
309
- * @param bool $strictly_active
310
- * @param string $post_type
311
- * @param string $option_name
312
- * @param bool $use_cache
313
- *
314
- * @return array
315
- */
316
- function wpcf_admin_fields_get_fields_by_group( $group_id, $key = 'slug',
317
- $only_active = false, $disabled_by_type = false,
318
- $strictly_active = false, $post_type = TYPES_CUSTOM_FIELD_GROUP_CPT_NAME,
319
- $option_name = 'wpcf-fields', $use_cache = true ) {
320
- static $cache = array();
321
- $cache_key = md5( serialize( func_get_args() ) );
322
- if ( $use_cache && isset( $cache[$cache_key] ) ) {
323
- return $cache[$cache_key];
324
- }
325
- $group_fields = get_post_meta( $group_id, '_wp_types_group_fields', true );
326
- if ( empty( $group_fields ) ) {
327
- return array();
328
- }
329
- $group_fields = explode( ',', trim( $group_fields, ',' ) );
330
- $fields = wpcf_admin_fields_get_fields( $only_active, $disabled_by_type,
331
- $strictly_active, $option_name );
332
- $results = array();
333
- foreach ( $group_fields as $field_id ) {
334
- if ( !isset( $fields[$field_id] ) ) {
335
- continue;
336
- }
337
- $results[$field_id] = $fields[$field_id];
338
- }
339
- if ( $use_cache ) {
340
- $cache[$cache_key] = $results;
341
- }
342
- return $results;
343
- }
344
-
345
- /**
346
- * Gets groups that have specific term.
347
- *
348
- * @param type $term_id
349
- * @param type $fetch_empty
350
- * @param type $only_active
351
- * @return type
352
- */
353
- function wpcf_admin_fields_get_groups_by_term( $term_id = false,
354
- $fetch_empty = true, $post_type = false, $only_active = true ) {
355
- $args = array();
356
- $args['post_type'] = TYPES_CUSTOM_FIELD_GROUP_CPT_NAME;
357
- $args['numberposts'] = -1;
358
- // Active
359
- if ( $only_active ) {
360
- $args['post_status'] = 'publish';
361
- }
362
- // Fetch empty
363
- if ( $fetch_empty ) {
364
- if ( $term_id ) {
365
- $args['meta_query']['relation'] = 'OR';
366
- $args['meta_query'][] = array(
367
- 'key' => '_wp_types_group_terms',
368
- 'value' => ',' . $term_id . ',',
369
- 'compare' => 'LIKE',
370
- );
371
- }
372
- $args['meta_query'][] = array(
373
- 'key' => '_wp_types_group_terms',
374
- 'value' => 'all',
375
- 'compare' => '=',
376
- );
377
- } else if ( $term_id ) {
378
- $args['meta_query'] = array(
379
- array(
380
- 'key' => '_wp_types_group_terms',
381
- 'value' => ',' . $term_id . ',',
382
- 'compare' => 'LIKE',
383
- ),
384
- );
385
- } else {
386
- return array();
387
- }
388
- $groups = get_posts( $args );
389
- foreach ( $groups as $k => $post ) {
390
- $temp = get_post_meta( $post->ID, '_wp_types_group_post_types', true );
391
- if ( $fetch_empty && $temp == 'all' ) {
392
- $groups[$k] = wpcf_admin_fields_adjust_group( $post );
393
- } else if ( strpos( $temp, ',' . $post_type . ',' ) !== false ) {
394
- $groups[$k] = wpcf_admin_fields_adjust_group( $post );
395
- } else {
396
- unset( $groups[$k] );
397
- }
398
- }
399
- return $groups;
400
- }
401
-
402
- add_filter('wpcf_get_groups_by_post_type', 'wpcf_admin_get_groups_by_post_type', 10, 1);
403
-
404
- /**
405
- * Gets groups that have specific post_type.
406
- *
407
- * @global object $wpdb
408
- * @param type $post_type
409
- * @param type $fetch_empty
410
- * @param type $only_active
411
- * @return type
412
- */
413
- function wpcf_admin_get_groups_by_post_type( $post_type, $fetch_empty = true, $terms = null, $only_active = true )
414
- {
415
- $args = array();
416
- $args['post_type'] = TYPES_CUSTOM_FIELD_GROUP_CPT_NAME;
417
- $args['numberposts'] = -1;
418
- // Active
419
- if ( $only_active ) {
420
- $args['post_status'] = 'publish';
421
- }
422
- // Fetch empty
423
- if ( $fetch_empty ) {
424
- $args['meta_query'] = array(
425
- 'relation' => 'OR',
426
- array(
427
- 'key' => '_wp_types_group_post_types',
428
- 'value' => ',' . $post_type . ',',
429
- 'compare' => 'LIKE',
430
- ),
431
- array(
432
- 'key' => '_wp_types_group_post_types',
433
- 'value' => 'all',
434
- 'compare' => '=',
435
- ),
436
- );
437
- } else {
438
- $args['meta_query'] = array(
439
- array(
440
- 'key' => '_wp_types_group_post_types',
441
- 'value' => ',' . $post_type . ',',
442
- 'compare' => 'LIKE',
443
- ),
444
- );
445
- }
446
-
447
- $results_by_post_type = array();
448
- $results_by_terms = array();
449
-
450
- // Get posts by post type
451
- $groups = get_posts( $args );
452
- if ( !empty( $groups ) ) {
453
- foreach ( $groups as $key => $group ) {
454
- $group = wpcf_admin_fields_adjust_group( $group );
455
- $results_by_post_type[$group['id']] = $group;
456
- }
457
- }
458
-
459
- // Distinct terms
460
- if ( !is_null( $terms ) ) {
461
- if ( !empty( $terms ) ) {
462
- $terms_sql = array();
463
- $add = '';
464
- if ( $fetch_empty ) {
465
- $add = " OR m.meta_value LIKE 'all'";
466
- }
467
- foreach ( $terms as $term ) {
468
- $terms_sql[] = esc_sql( $term );
469
- }
470
- $terms_sql = "AND (m.meta_value LIKE '%%," . implode( ",%%' OR m.meta_value LIKE '%%,", $terms_sql ) . ",%%' $add)";
471
- global $wpdb;
472
- $terms_sql = "SELECT * FROM $wpdb->posts p
473
- JOIN $wpdb->postmeta m
474
- WHERE p.post_type=".TYPES_CUSTOM_FIELD_GROUP_CPT_NAME." AND p.post_status='publish'
475
- AND p.ID = m.post_id AND m.meta_key='_wp_types_group_terms'
476
- $terms_sql";
477
- $groups = $wpdb->get_results( $terms_sql );
478
- if ( !empty( $groups ) ) {
479
- foreach ( $groups as $key => $group ) {
480
- $group = wpcf_admin_fields_adjust_group( $group );
481
- $results_by_terms[$group['id']] = $group;
482
- }
483
- }
484
- foreach ( $results_by_post_type as $key => $value ) {
485
- if ( !array_key_exists( $key, $results_by_terms ) ) {
486
- unset( $results_by_post_type[$key] );
487
- }
488
- }
489
- }
490
- }
491
-
492
- return $results_by_post_type;
493
- }
494
-
495
- /**
496
- * Gets groups that have specific template.
497
- *
498
- * @param type $post_type
499
- * @param type $fetch_empty
500
- * @param type $only_active
501
- * @return type
502
- */
503
- function wpcf_admin_get_groups_by_template( $templates = array('default'),
504
- $fetch_empty = true, $only_active = true ) {
505
- $args = array();
506
- $args['post_type'] = TYPES_CUSTOM_FIELD_GROUP_CPT_NAME;
507
- $args['numberposts'] = -1;
508
- $meta_query = array();
509
- // Active
510
- if ( $only_active ) {
511
- $args['post_status'] = 'publish';
512
- }
513
-
514
- // Fetch empty
515
- if ( $fetch_empty ) {
516
- $args['meta_query'] = array(
517
- 'relation' => 'OR',
518
- array(
519
- 'key' => '_wp_types_group_templates',
520
- 'value' => 'all',
521
- 'compare' => '=',
522
- ),
523
- );
524
- } else {
525
- $args['meta_query'] = array(
526
- 'relation' => 'OR');
527
- }
528
- foreach ( $templates as $template ) {
529
- $args['meta_query'][] = array(
530
- 'key' => '_wp_types_group_templates',
531
- 'value' => ',' . $template . ',',
532
- 'compare' => 'LIKE',
533
- );
534
- }
535
-
536
- $results_by_template = array();
537
-
538
- // Get posts by template
539
- $groups = get_posts( $args );
540
- if ( !empty( $groups ) ) {
541
- foreach ( $groups as $key => $group ) {
542
- $group = wpcf_admin_fields_adjust_group( $group );
543
- $results_by_template[$group['id']] = $group;
544
- }
545
- }
546
-
547
- return $results_by_template;
548
- }
549
-
550
- /**
551
- * Get file fullpath to include
552
- *
553
- * param @string $basename
554
- *
555
- * return @string
556
- *
557
- */
558
- function wpcf_get_fullpath_by_field_type($basename)
559
- {
560
- return sprintf(
561
- '%s/fields/%s.php',
562
- dirname( __FILE__ ),
563
- preg_replace('/[^\w]+/', '', $basename)
564
- );
565
- }
566
-
567
- /**
568
- * Loads type configuration file and calls action.
569
- *
570
- * @param type $type
571
- * @param type $action
572
- * @param type $args
573
- */
574
- function wpcf_fields_type_action( $type, $func = '', $args = array() ) {
575
- static $actions = array();
576
- $func_in = $func;
577
-
578
- $md5_args = md5( serialize( $args ) );
579
-
580
- if ( !isset( $actions[$type . '-' . $func_in . '-' . $md5_args] ) ) {
581
- $fields_registered = wpcf_admin_fields_get_available_types();
582
- if ( isset( $fields_registered[$type] ) && isset( $fields_registered[$type]['path'] ) ) {
583
- $file = $fields_registered[$type]['path'];
584
- } else if ( defined( 'WPCF_INC_ABSPATH' ) ) {
585
- $file = WPCF_INC_ABSPATH . '/fields/' . $type . '.php';
586
- } else {
587
- $file = '';
588
- }
589
- $file_embedded = wpcf_get_fullpath_by_field_type($type);
590
- if ( file_exists( $file ) || file_exists( $file_embedded ) ) {
591
- if ( file_exists( $file ) ) {
592
- require_once $file;
593
- }
594
- if ( file_exists( $file_embedded ) ) {
595
- require_once $file_embedded;
596
- }
597
- if ( empty( $func ) ) {
598
- $func = 'wpcf_fields_' . $type;
599
- } else {
600
- $func = 'wpcf_fields_' . $type . '_' . $func;
601
- }
602
- if ( function_exists( $func ) ) {
603
- $actions[$type . '-' . $func_in . '-' . $md5_args] = call_user_func( $func,
604
- $args );
605
- } else {
606
- $actions[$type . '-' . $func_in . '-' . $md5_args] = false;
607
- }
608
- } else {
609
- $actions[$type . '-' . $func_in . '-' . $md5_args] = false;
610
- }
611
- }
612
- return $actions[$type . '-' . $func_in . '-' . $md5_args];
613
- }
614
-
615
- /**
616
- * Returns shortcode for specified field.
617
- *
618
- * @param type $field
619
- * @param type $add Additional attributes
620
- * @param string $content
621
- */
622
- function wpcf_fields_get_shortcode( $field, $add = '', $content = '' )
623
- {
624
- $shortcode = '[';
625
- $shortcode .= 'types field="' . $field['slug'] . '"' . $add;
626
- $shortcode .= ']' . $content . '[/types]';
627
- $shortcode = apply_filters( 'wpcf_fields_shortcode', $shortcode, $field );
628
- $shortcode = apply_filters( 'wpcf_fields_shortcode_type_' . $field['type'], $shortcode, $field );
629
- $shortcode = apply_filters( 'wpcf_fields_shortcode_slug_' . $field['slug'], $shortcode, $field );
630
- return $shortcode;
631
- }
632
-
633
- function wpcf_termmeta_get_shortcode( $field, $add = '', $content = '' ) {
634
- $shortcode = '[';
635
- $shortcode .= 'types termmeta="' . $field['slug'] . '"' . $add;
636
- $shortcode .= ']' . $content . '[/types]';
637
- $shortcode = apply_filters( 'wpcf_fields_shortcode', $shortcode, $field );
638
- $shortcode = apply_filters( 'wpcf_fields_shortcode_type_' . $field['type'], $shortcode, $field );
639
- $shortcode = apply_filters( 'wpcf_fields_shortcode_slug_' . $field['slug'], $shortcode, $field );
640
- return $shortcode;
641
- }
642
-
643
- function wpcf_get_termmeta_form_addon_submit() {
644
- $add = '';
645
- if ( ! empty( $_POST['is_termmeta'] ) ) {
646
-
647
- }
648
- return $add;
649
- }
650
-
651
- /**
652
- * Returns shortcode for specified usermeta field.
653
- *
654
- * @param type $field
655
- * @param type $add Additional attributes
656
- */
657
- function wpcf_usermeta_get_shortcode( $field, $add = '', $content = '' ) {
658
- /*if ( isset($_GET['field_type']) && $_GET['field_type'] =='views-usermeta' ) {
659
- $add .= ' user_from_this_loop="true"';
660
- }*/
661
- $shortcode = '[';
662
- $shortcode .= 'types usermeta="' . $field['slug'] . '"' . $add;
663
- $shortcode .= ']' . $content . '[/types]';
664
- $shortcode = apply_filters( 'wpcf_fields_shortcode', $shortcode, $field );
665
- $shortcode = apply_filters( 'wpcf_fields_shortcode_type_' . $field['type'], $shortcode, $field );
666
- $shortcode = apply_filters( 'wpcf_fields_shortcode_slug_' . $field['slug'], $shortcode, $field );
667
- return $shortcode;
668
- }
669
-
670
- /*
671
- * Usermeta fields addon.
672
- * Add form user users
673
- *
674
- * @global object $wpdb
675
- *
676
- */
677
-
678
- function wpcf_get_usermeta_form_addon( $settings = array() ) {
679
- global $wpdb;
680
- $form = array();
681
- $users = $wpdb->get_results(
682
- "SELECT ID, user_login, display_name
683
- FROM {$wpdb->users}
684
- LIMIT 5"
685
- );
686
- $form[] = array(
687
- '#type' => 'hidden',
688
- '#value' => 'true',
689
- '#name' => 'is_usermeta',
690
- );
691
- $__default = 'post_autor';
692
- $form[] = array(
693
- '#type' => 'radio',
694
- '#before' => '<div class="fieldset"><p class="form-inline">',
695
- '#suffix' => '</p>',
696
- '#value' => 'post_autor',
697
- '#title' => 'Author of this post',
698
- '#name' => 'display_username_for',
699
- '#default_value' => isset( $settings['user_is_author'] ) && $settings['user_is_author'] == 'true' ? 'post_autor' : $__default,
700
- '#inline' => true,
701
- '#attributes' => array('onclick' => 'wpcf_showmore(false)')
702
- );
703
- $form[] = array(
704
- '#type' => 'radio',
705
- '#before' => '<p class="form-inline">',
706
- '#suffix' => '</p>',
707
- '#value' => 'current_user',
708
- '#title' => 'The current logged in user',
709
- '#name' => 'display_username_for',
710
- '#default_value' => isset( $settings['user_current'] ) && $settings['user_current'] == 'true' ? 'current_user' : $__default,
711
- '#inline' => true,
712
- '#attributes' => array('onclick' => 'wpcf_showmore(false)')
713
- );
714
- $form[] = array(
715
- '#type' => 'radio',
716
- '#before' => '<p class="form-inline">',
717
- '#suffix' => '</p>',
718
- '#title' => 'A specific user',
719
- '#value' => 'pecific_user',
720
- '#id' => 'display_username_for_suser',
721
- '#name' => 'display_username_for',
722
- '#default_value' => isset( $settings['user_id'] ) || isset( $settings['user_name'] ) ? 'pecific_user' : $__default,
723
- '#after' => '',
724
- '#inline' => true,
725
- '#attributes' => array('onclick' => 'wpcf_showmore(true)')
726
- );
727
- $__username = isset( $settings['user_name'] ) ? $settings['user_name'] : '';
728
- $__userid = isset( $settings['user_id'] ) ? intval( $settings['user_id'] ) : '';
729
- $__hidden = !isset( $settings['user_id'] ) && !isset( $settings['user_name'] ) ? ' style="display:none;"' : '';
730
- $__hiddenId = !isset( $settings['user_id'] ) && isset( $settings['user_name'] ) ? ' style="display:none;"' : '';
731
- $form[] = array(
732
- '#type' => 'radio',
733
- '#title' => 'User ID',
734
- '#value' => 'specific_user_by_id',
735
- '#id' => 'display_username_for_suser_id',
736
- '#name' => 'display_username_for_suser_selector',
737
- '#before' => '<div class="group-nested form-inline" id="specific_user_div"' . $__hidden . '><p>',
738
- '#after' => '<input type="text" class="wpcf-form-textfield form-textfield textfield" name="display_username_for_suser_id_value" value="' . $__userid . '"'.
739
- ' id="display_username_for_suser_id_value" value=""' . $__hiddenId . '></p>',
740
- '#default_value' => isset( $settings['user_id'] ) || !isset( $settings['user_name'] ) ? 'specific_user_by_id' : '',
741
- '#inline' => true,
742
- '#attributes' => array('onclick' => 'hideControls(\'display_username_for_suser_username_value\',\'display_username_for_suser_id_value\')')
743
- );
744
- $dropdown_users = '';
745
- foreach ($users as $u) {
746
- $dropdown_users .= '<option value="' . $u->user_login . '">' . $u->display_name . ' (' . $u->user_login . ')' . '</option>';
747
- }
748
- $__hidden = !isset( $settings['user_name'] ) ? ' style="display:none;"' : '';
749
- $form[] = array(
750
- '#type' => 'radio',
751
- '#title' => 'User name',
752
- '#value' => 'specific_user_by_username',
753
- '#id' => 'display_username_for_suser_username',
754
- '#name' => 'display_username_for_suser_selector',
755
- '#before' => '<p class="types-suggest-user types-suggest" id="types-suggest-user">',
756
- '#after' => '<input type="text" class="input wpcf-form-textfield form-textfield textfield"'. $__hidden .
757
- ' name="display_username_for_suser_username_value" id="display_username_for_suser_username_value" value="' . $__username . '"></p></div></div>',
758
- '#default_value' => isset( $settings['user_name'] ) ? 'specific_user_by_username' : '',
759
- '#inline' => true,
760
- '#attributes' => array('onclick' => 'hideControls(\'display_username_for_suser_id_value\',\'display_username_for_suser_username_value\')')
761
- );
762
-
763
- return $form;
764
- }
765
-
766
- /*
767
- * Callback sumit form usermeta addon
768
- */
769
-
770
- function wpcf_get_usermeta_form_addon_submit() {
771
- $add = '';
772
- if ( !empty( $_POST['is_usermeta'] ) ) {
773
- if ( $_POST['display_username_for'] == 'post_autor' ) {
774
- $add .= ' user_is_author="true"';
775
- } elseif ( $_POST['display_username_for'] == 'current_user' ) {
776
- $add .= ' user_current="true"';
777
- }
778
- else {
779
- if ( $_POST['display_username_for_suser_selector'] == 'specific_user_by_id' ) {
780
- $add .= ' user_id="' . sanitize_text_field($_POST['display_username_for_suser_id_value']) . '"';
781
- } else {
782
- $add .= ' user_name="' . sanitize_text_field($_POST['display_username_for_suser_username_value']) . '"';
783
- }
784
- }
785
- }
786
- return $add;
787
- }
788
-
789
- /**
790
- * Gets all available types and their config data.
791
- */
792
- function wpcf_admin_fields_get_available_types() {
793
- return WPCF_Fields::getFieldsTypesData();
794
- }
795
-
796
- /**
797
- * Sanitizes field.
798
- *
799
- * @param type $field
800
- */
801
- function wpcf_sanitize_field( $field ) {
802
- // Sanitize name
803
- if ( isset( $field['name'] ) ) {
804
- $field['name'] = sanitize_text_field( $field['name'] );
805
- }
806
- /**
807
- * autocreate name based on field type
808
- */
809
- if ( empty($field['name'] ) && isset($field['type']) ) {
810
- $field['name'] = sprintf(
811
- '%s - %s',
812
- ucfirst($field['type']),
813
- substr(md5(rand()), 0, 8)
814
- );
815
- }
816
- // Sanitize slug
817
- if ( !empty( $field['slug'] ) ) {
818
- $field['slug'] = sanitize_key( $field['slug'] );
819
- } else if ( isset( $field['name'] ) ) {
820
- $field['slug'] = sanitize_title( $field['name'] );
821
- }
822
- return $field;
823
- }
824
-
825
- /**
826
- * Gets all groups that contain specified field.
827
- *
828
- * @static $cache
829
- * @param type $field_id
830
- */
831
- function wpcf_admin_fields_get_groups_by_field( $field_id,
832
- $post_type = TYPES_CUSTOM_FIELD_GROUP_CPT_NAME ) {
833
- static $cache = array();
834
- $groups = wpcf_admin_fields_get_groups( $post_type );
835
- switch ( $post_type ) {
836
- case TYPES_TERM_META_FIELD_GROUP_CPT_NAME:
837
- $meta_name = 'wpcf-termmeta';
838
- break;
839
- case TYPES_USER_META_FIELD_GROUP_CPT_NAME:
840
- $meta_name = 'wpcf-usermeta';
841
- break;
842
- case TYPES_CUSTOM_FIELD_GROUP_CPT_NAME:
843
- default:
844
- $meta_name = 'wpcf-fields';
845
- break;
846
- }
847
- $return = array();
848
- foreach ( $groups as $group_id => $group ) {
849
- if ( isset( $cache['groups'][$group_id] ) ) {
850
- $fields = $cache['groups'][$group_id];
851
- } else {
852
- $fields = wpcf_admin_fields_get_fields_by_group( $group['id'],
853
- 'slug', false, false, false, $post_type, $meta_name );
854
- }
855
- if ( array_key_exists( $field_id, $fields ) ) {
856
- $return[$group['id']] = $group;
857
- }
858
- $cache['groups'][$group_id] = $fields;
859
- }
860
- return $return;
861
- }
862
-
863
- /**
864
- * Saves last field settings when inserting from toolbar.
865
- *
866
- * @param type $field_id
867
- * @param type $settings
868
- * @param type $append
869
- */
870
- function wpcf_admin_fields_save_field_last_settings( $field_id, $settings,
871
- $append = false, $overwrite = false ) {
872
- $data = get_user_meta( get_current_user_id(), 'wpcf-field-settings', true );
873
- if ( $append && isset( $data[$field_id] ) && is_array( $data[$field_id] ) ) {
874
- $data[$field_id] = $overwrite ? array_merge( $data[$field_id], $settings ) : array_merge( $settings,
875
- $data[$field_id] );
876
- } else {
877
- $data[$field_id] = $settings;
878
- }
879
- update_user_meta( get_current_user_id(), 'wpcf-field-settings', $data );
880
- }
881
-
882
- /**
883
- * Gets last field settings when inserting from toolbar.
884
- *
885
- * @param type $field_id
886
- */
887
- function wpcf_admin_fields_get_field_last_settings( $field_id ) {
888
- $data = get_user_meta( get_current_user_id(), 'wpcf-field-settings', true );
889
- if ( isset( $data[$field_id] ) ) {
890
- return $data[$field_id];
891
- }
892
- return array();
893
- }
894
-
895
- /**
896
- * Get active fields by post type
897
- *
898
- * Get active fields by post type chosing it from active groups and this
899
- * groups which are connected to certain post type.
900
- *
901
- * @since: 1.7
902
- *
903
- * @param string $post_type post type
904
- *
905
- * @return array allowed meta keys
906
- */
907
- function wpcf_admin_get_allowed_fields_by_post_type($post_type)
908
- {
909
- $allowed_fields = $active_groups = array();
910
- $all_groups = wpcf_admin_get_groups_by_post_type($post_type);
911
- foreach( $all_groups as $group_id => $group_data ) {
912
- $active_groups[] = $group_data['slug'];
913
- }
914
- $all_groups = wpcf_admin_fields_get_groups(TYPES_CUSTOM_FIELD_GROUP_CPT_NAME, true, true);
915
- foreach( $all_groups as $group ) {
916
- if ( !in_array($group['slug'], $active_groups) ) {
917
- continue;
918
- }
919
- foreach( $group['fields'] as $field_key => $field_data ) {
920
- $allowed_fields[] = $field_data['meta_key'];
921
- }
922
- }
923
- return $allowed_fields;
924
- }
925
-
926
- /**
927
- * Returns all used field slugs except current group
928
- */
929
- function wpcf_get_all_field_slugs_except_current_group( $current_group = false ) {
930
- $all_slugs = array();
931
- $all_post_fields = get_option( 'wpcf-fields', array() );
932
- $all_user_fields = get_option( 'wpcf-usermeta', array() );
933
- $all_term_fields = get_option( 'wpcf-termmeta', array() );
934
-
935
- $all_fields = array_merge( $all_post_fields, $all_user_fields, $all_term_fields );
936
-
937
- if( !empty( $all_fields ) ) {
938
- foreach( $all_fields as $field ) {
939
- $all_slugs[] = $field['slug'];
940
- }
941
- }
942
- if( !$current_group && isset( $_REQUEST['group_id'] ) )
943
- $current_group = $_REQUEST['group_id'];
944
-
945
- // if no new group
946
- if( $current_group && !empty( $all_fields ) ) {
947
-
948
- $current_group_fields = get_post_meta( $current_group, '_wp_types_group_fields', true );
949
- $current_group_fields = explode( ',', trim( $current_group_fields, ',' ) );
950
-
951
- if( !empty( $current_group_fields) ) {
952
- foreach( $current_group_fields as $field ) {
953
- $all_slugs = array_diff( $all_slugs, array( $field ) );
954
- }
955
- }
956
-
957
- }
958
- $all_slugs = array_values( $all_slugs );
959
- if( isset( $_POST['return'] )
960
- && $_POST['return'] == 'ajax-json' ) {
961
- echo json_encode( $all_slugs );
962
- die();
963
- }
964
-
965
- return $all_slugs;
966
- }
967
- add_action('wp_ajax_wpcf_get_all_field_slugs_except_current_group', 'wpcf_get_all_field_slugs_except_current_group');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/fields/checkboxes.php DELETED
@@ -1,385 +0,0 @@
1
- <?php
2
- /**
3
- * Register data (called automatically).
4
- *
5
- * @return type
6
- */
7
- function wpcf_fields_checkboxes() {
8
- return array(
9
- 'id' => 'wpcf-checkboxes',
10
- 'title' => __( 'Checkboxes', 'wpcf' ),
11
- 'description' => __( 'Checkboxes', 'wpcf' ),
12
- 'meta_key_type' => 'BINARY',
13
- 'types-field-image' => 'checkboxes',
14
- );
15
- }
16
-
17
- add_filter( 'wpcf_relationship_meta_form', 'wpcf_filds_checkboxes_relationship_form_filter' );
18
-
19
- // Add filter when using wpv_condition()
20
- add_filter( 'wpv_condition', 'wpcf_fields_checkboxes_wpv_conditional_trigger' );
21
- add_filter( 'wpv_condition_end',
22
- 'wpcf_fields_checkboxes_wpv_conditional_trigger_end' );
23
-
24
- /**
25
- * Form data for post edit page.
26
- *
27
- * @param type $field
28
- *
29
- * @deprecated seems
30
- */
31
- function wpcf_fields_checkboxes_meta_box_form( $field, $field_object ) {
32
- $options = array();
33
- if ( !empty( $field['data']['options'] ) ) {
34
- global $pagenow;
35
- foreach ( $field['data']['options'] as $option_key => $option ) {
36
- // Set value
37
- $options[$option_key] = array(
38
- '#value' => $option['set_value'],
39
- '#title' => wpcf_translate( 'field ' . $field['id'] . ' option '
40
- . $option_key . ' title', $option['title'] ),
41
- '#default_value' => (!empty( $field['value'][$option_key] )// Also check new post
42
- || ($pagenow == 'post-new.php' && !empty( $option['checked'] ))) ? 1 : 0,
43
- '#name' => 'wpcf[' . $field['id'] . '][' . $option_key . ']',
44
- '#id' => $option_key . '_'
45
- . wpcf_unique_id( serialize( $field ) ),
46
- '#inline' => true,
47
- '#after' => '<br />',
48
- );
49
- }
50
- }
51
- return array(
52
- '#type' => 'checkboxes',
53
- '#options' => $options,
54
- );
55
- }
56
-
57
- /**
58
- * Editor callback form.
59
- */
60
- function wpcf_fields_checkboxes_editor_callback( $field, $settings ) {
61
- $data = array();
62
- if ( !empty( $field['data']['options'] ) ) {
63
- $index = 0;
64
- foreach ( $field['data']['options'] as $option_key => $option ) {
65
- $data['checkboxes'][$option_key] = array(
66
- 'id' => $option_key,
67
- 'title' => $option['title'],
68
- 'selected' => isset( $settings['options'][$index]['selected'] ) ? $settings['options'][$index]['selected'] : htmlspecialchars( stripslashes( strval( ( $option['display_value_selected'] )))),
69
- 'not_selected' => isset( $settings['options'][$index]['not_selected'] ) ? $settings['options'][$index]['not_selected'] : htmlspecialchars(stripslashes( strval( $option['display_value_not_selected'] ))),
70
- );
71
- $index++;
72
- }
73
- }
74
- return array(
75
- 'supports' => array('style'),
76
- 'tabs' => array(
77
- 'display' => array(
78
- 'menu_title' => __( 'Display options', 'wpcf' ),
79
- 'title' => __( 'Display options for this field:', 'wpcf' ),
80
- 'content' => WPCF_Loader::template( 'editor-modal-checkboxes',
81
- $data ),
82
- )
83
- )
84
- );
85
- }
86
-
87
- /**
88
- * Editor callback form submit.
89
- */
90
- function wpcf_fields_checkboxes_editor_submit( $data, $field, $context ) {
91
- $add = '';
92
- $shortcode = '';
93
- if ( $context == 'usermeta' ) {
94
- $add .= wpcf_get_usermeta_form_addon_submit();
95
- } elseif ( $context == 'termmeta' ) {
96
- $add .= wpcf_get_termmeta_form_addon_submit();
97
- }
98
- if ( !empty( $data['options'] ) ) {
99
- if ( $data['display'] == 'display_all' ) {
100
- $separator = !empty( $data['cbs_separator'] ) ? $data['cbs_separator'] : '';
101
- $_add = $add . ' separator="' . $separator . '"';
102
- if ( $context == 'usermeta' ) {
103
- $shortcode .= wpcf_usermeta_get_shortcode( $field, $_add );
104
- } elseif ( $context == 'termmeta' ) {
105
- $shortcode = wpcf_termmeta_get_shortcode( $field, $add );
106
- } else {
107
- $shortcode .= wpcf_fields_get_shortcode( $field, $_add );
108
- }
109
- } else {
110
- $i = 0;
111
- foreach ( $data['options'] as $option ) {
112
- if ( $data['display'] == 'value' ) {
113
- $checked_add = $add . ' option="' . $i . '" state="checked"';
114
- $unchecked_add = $add . ' option="' . $i . '" state="unchecked"';
115
-
116
- if ( $context == 'usermeta' ) {
117
- $shortcode_checked = wpcf_usermeta_get_shortcode( $field,
118
- $checked_add, $option['selected'] );
119
- $shortcode_unchecked = wpcf_usermeta_get_shortcode( $field,
120
- $unchecked_add, $option['not_selected'] );
121
- } elseif ( $context == 'termmeta' ) {
122
- $shortcode_checked = wpcf_termmeta_get_shortcode( $field,
123
- $checked_add, $option['selected'] );
124
- $shortcode_unchecked = wpcf_termmeta_get_shortcode( $field,
125
- $unchecked_add, $option['not_selected'] );
126
- } else {
127
- $shortcode_checked = wpcf_fields_get_shortcode( $field,
128
- $checked_add, $option['selected'] );
129
- $shortcode_unchecked = wpcf_fields_get_shortcode( $field,
130
- $unchecked_add, $option['not_selected'] );
131
- }
132
- $shortcode .= $shortcode_checked . $shortcode_unchecked;
133
- } else {
134
- $add = ' option="' . $i . '"';
135
- if ( $context == 'usermeta' ) {
136
- $add .= wpcf_get_usermeta_form_addon_submit();
137
- $shortcode .= wpcf_usermeta_get_shortcode( $field, $add );
138
- } elseif ( $context == 'termmeta' ) {
139
- $add .= wpcf_get_termmeta_form_addon_submit();
140
- $shortcode = wpcf_termmeta_get_shortcode( $field, $add );
141
- } else {
142
- $shortcode .= wpcf_fields_get_shortcode( $field, $add );
143
- }
144
- }
145
- $i++;
146
- }
147
- }
148
- } else {
149
- if ( $context == 'usermeta' ) {
150
- $shortcode .= wpcf_usermeta_get_shortcode( $field, $add );
151
- } elseif ( $context == 'termmeta' ) {
152
- $shortcode = wpcf_termmeta_get_shortcode( $field, $add );
153
- } else {
154
- $shortcode .= wpcf_fields_get_shortcode( $field, $add );
155
- }
156
- }
157
- return $shortcode;
158
- }
159
-
160
- /**
161
- * View function.
162
- *
163
- * @param type $params
164
- */
165
- function wpcf_fields_checkboxes_view( $params ) {
166
- $option = array();
167
- // Basic checks
168
- if ( empty( $params['field']['data']['options'] )
169
- || !is_array( $params['field_value'] ) ) {
170
- return '__wpcf_skip_empty';
171
- }
172
-
173
- /*
174
- *
175
- * NO OPTION specified
176
- * loop over all options and display all of them
177
- */
178
- if ( !isset( $params['option'] ) ) {
179
- $separator = isset( $params['separator'] ) ? html_entity_decode( $params['separator'] ) : ', ';
180
- foreach ( $params['field_value'] as $name => &$value ) {
181
- /*
182
- *
183
- * Set option
184
- */
185
- if ( isset( $params['field']['data']['options'][$name] ) ) {
186
- $option = $params['field']['data']['options'][$name];
187
- } else {
188
- // Unset if not valid
189
- unset( $params['field_value'][$name] );
190
- continue;
191
- }
192
- /*
193
- *
194
- * Set output according to settings.
195
- * 'db' or 'value'
196
- */
197
- if ( $option['display'] == 'db'
198
- && !empty( $option['set_value'] ) && !empty( $value ) ) {
199
- // We need to translate here because the stored value is on the original language
200
- // When updaing the value in the Field group, we might have problems
201
- $value = $option['set_value'];
202
- $value = wpcf_translate( 'field ' . $params['field']['id'] . ' option ' . $name . ' value', $value );
203
- } else if ( $option['display'] == 'value' ) {
204
- if ( isset( $option['display_value_selected'] ) && !empty( $value ) ) {
205
- // We need to translate here because the stored value is on the original language
206
- // When updaing the value in the Field group, we might have problems
207
- $value = $option['display_value_selected'];
208
- $value = wpcf_translate( 'field ' . $params['field']['id'] . ' option ' . $name . ' display value selected', $value );
209
- } else {
210
- // We need to translate here because the stored value is on the original language
211
- // When updaing the value in the Field group, we might have problems
212
- $value = $option['display_value_not_selected'];
213
- $value = wpcf_translate( 'field ' . $params['field']['id'] . ' option ' . $name . ' display value not selected', $value );
214
- }
215
- } else {
216
- unset( $params['field_value'][$name] );
217
- }
218
- }
219
- $output = implode( array_values( $params['field_value'] ), $separator );
220
- return empty( $output ) ? '__wpcf_skip_empty' : stripslashes($output);
221
- }
222
-
223
- /*
224
- *
225
- *
226
- * OPTION specified - set required option.
227
- */
228
- $i = 0;
229
- foreach ( $params['field']['data']['options'] as $option_key => $option_value ) {
230
- if ( intval( $params['option'] ) == $i ) {
231
- $option['key'] = $option_key;
232
- $option['data'] = $option_value;
233
- $option['value'] = !empty( $params['field_value'][$option_key] ) ? $params['field_value'][$option_key] : '__wpcf_unchecked';
234
- break;
235
- }
236
- $i++;
237
- }
238
-
239
- $output = '';
240
-
241
- /*
242
- * STATE set - use #content is as render value.
243
- * If setings are faulty - return '__wpcf_skip_empty'.
244
- */
245
- if ( isset( $params['state'] ) ) {
246
- $content = !empty( $params['#content'] ) ? htmlspecialchars_decode( $params['#content'] ) : '__wpcf_skip_empty';
247
- if ( $params['state'] == 'checked'
248
- && $option['value'] != '__wpcf_unchecked' ) {
249
- return $content;
250
- } else if ( $params['state'] == 'unchecked'
251
- && $option['value'] == '__wpcf_unchecked' ) {
252
- return $content;
253
- } else if ( isset( $params['state'] ) ) {
254
- return '__wpcf_skip_empty';
255
- }
256
- }
257
-
258
- /*
259
- *
260
- * MAIN settings
261
- * 'db' - Use 'set_value' as render value
262
- * 'value' - Use values set in Group form data 'display_value_selected'
263
- * or 'display_value_not_selected'
264
- *
265
- * Only set if it matches settings.
266
- * Otherwise leave empty and '__wpcf_skip_empty' will be returned.
267
- *
268
- */
269
-
270
- if ( isset($option['data']) && $option['data']['display'] == 'db' ) {
271
- /*
272
- *
273
- * Only if NOT unchecked!
274
- */
275
- if ( !empty( $option['data']['set_value'] )
276
- && $option['value'] != '__wpcf_unchecked' ) {
277
- // We need to translate here because the stored value is on the original language
278
- // When updaing the value in the Field group, we might have problems
279
- $output = $option['data']['set_value'];
280
- $output = wpcf_translate( 'field ' . $params['field']['id'] . ' option ' . $option['key'] . ' value', $output );
281
- }
282
- } else if ( isset($option['data']) && $option['data']['display'] == 'value' ) {
283
- /*
284
- *
285
- * Checked
286
- */
287
- if ( $option['value'] != '__wpcf_unchecked' ) {
288
- if ( isset( $option['data']['display_value_selected'] ) ) {
289
- // We need to translate here because the stored value is on the original language
290
- // When updaing the value in the Field group, we might have problems
291
- $output = $option['data']['display_value_selected'];
292
- $output = wpcf_translate( 'field ' . $params['field']['id'] . ' option ' . $option['key'] . ' display value selected', $output );
293
- }
294
- /*
295
- *
296
- *
297
- * Un-checked
298
- */
299
- } else if ( isset( $option['data']['display_value_not_selected'] ) ) {
300
- // We need to translate here because the stored value is on the original language
301
- // When updaing the value in the Field group, we might have problems
302
- $output = $option['data']['display_value_not_selected'];
303
- $output = wpcf_translate( 'field ' . $params['field']['id'] . ' option ' . $option['key'] . ' display value not selected', $output );
304
- }
305
- }
306
-
307
- if ( empty( $output ) ) {
308
- return '__wpcf_skip_empty';
309
- }
310
-
311
- return $output;
312
- }
313
-
314
- /**
315
- * This marks child posts checkboxes.
316
- *
317
- * Because if all unchecked, on submit there won't be any data.
318
- *
319
- * @param string $form
320
- * @param type $cf
321
- * @return string
322
- */
323
- function wpcf_filds_checkboxes_relationship_form_filter( $form, $cf ) {
324
- if ( $cf->cf['type'] == 'checkboxes' ) {
325
- $form[wpcf_unique_id( serialize( $cf ) . 'rel_child' )] = array(
326
- '#type' => 'hidden',
327
- '#name' => '_wpcf_check_checkboxes[' . $cf->post->ID . ']['
328
- . $cf->slug . ']',
329
- '#value' => '1'
330
- );
331
- }
332
- return $form;
333
- }
334
-
335
- /**
336
- * Triggers post_meta filter.
337
- *
338
- * @param type $post
339
- * @return type
340
- */
341
- function wpcf_fields_checkboxes_wpv_conditional_trigger( $post ) {
342
- add_filter( 'get_post_metadata',
343
- 'wpcf_fields_checkboxes_conditional_filter_post_meta', 10, 4 );
344
- }
345
-
346
- /**
347
- * Returns string.
348
- *
349
- * @global type $wpcf
350
- * @param type $null
351
- * @param type $object_id
352
- * @param type $meta_key
353
- * @param type $single
354
- * @return type
355
- */
356
- function wpcf_fields_checkboxes_conditional_filter_post_meta( $null, $object_id,
357
- $meta_key, $single ) {
358
- global $wpcf;
359
- $field = wpcf_admin_fields_get_field( $wpcf->field->__get_slug_no_prefix( $meta_key ) );
360
- if ( !empty( $field ) && $field['type'] == 'checkboxes' ) {
361
- $_meta = maybe_unserialize( wpcf_get_post_meta( $object_id, $meta_key,
362
- $single ) );
363
- if ( is_array( $_meta ) ) {
364
- $null = empty( $_meta ) ? '1' : '';
365
- }
366
- /**
367
- * be sure do not return string if array is expected!
368
- */
369
- if ( !$single && !is_array($null) ) {
370
- return array($null);
371
- }
372
- }
373
- return $null;
374
- }
375
-
376
- /**
377
- * Triggers post_meta filter.
378
- *
379
- * @param type $post
380
- * @return type
381
- */
382
- function wpcf_fields_checkboxes_wpv_conditional_trigger_end( $post ) {
383
- remove_filter( 'get_post_metadata',
384
- 'wpcf_fields_checkboxes_conditional_filter_post_meta', 10, 4 );
385
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/fields/date.php DELETED
@@ -1,559 +0,0 @@
1
- <?php
2
- /**
3
- * Register data (called automatically).
4
- *
5
- * @return type
6
- */
7
- function wpcf_fields_date() {
8
- $settings = array(
9
- 'id' => 'wpcf-date',
10
- 'title' => __( 'Date', 'wpcf' ),
11
- 'description' => __( 'Date', 'wpcf' ),
12
- 'validate' => array(
13
- 'required' => array(
14
- 'form-settings' => include( dirname( __FILE__ ) . '/patterns/validate/form-settings/required.php' )
15
- ),
16
- 'date' => array(
17
- 'form-settings' => array_replace_recursive(
18
- include( dirname( __FILE__ ) . '/patterns/validate/form-settings/default.php' ),
19
- array(
20
- 'control' => array(
21
- '#label' => __( 'Date', 'wpcf' ),
22
- '#title' => __( 'Validation', 'wpcf' ),
23
- )
24
- )
25
- )
26
- )
27
- ),
28
- 'meta_key_type' => 'TIME',
29
- 'version' => '1.2',
30
- 'font-awesome' => 'calendar',
31
- );
32
-
33
- if ( !defined( 'WPTOOLSET_FORMS_ABSPATH' ) ) {
34
- // Allow localized Datepicker if date format does not need translating
35
- $localized_date_formats = array(
36
- 'Y/m/d', // 2011/12/23
37
- 'm/d/Y', // 12/23/2011
38
- 'd/m/Y', // 23/22/2011
39
- 'd/m/y', // 23/22/11
40
- );
41
-
42
- $date_format = wpcf_get_date_format();
43
- $localized_js = array();
44
-
45
- if ( in_array( $date_format, $localized_date_formats ) ) {
46
- $locale = str_replace( '_', '-', strtolower( get_locale() ) );
47
- $localized_js = array(
48
- 'src' => file_exists( WPCF_EMBEDDED_RES_ABSPATH . '/js/i18n/jquery.ui.datepicker-'
49
- . $locale . '.js' ) ? WPCF_EMBEDDED_RES_RELPATH . '/js/i18n/jquery.ui.datepicker-'
50
- . $locale . '.js' : '',
51
- 'deps' => array('jquery-ui-core'),
52
- );
53
- }
54
- $settings['meta_box_js'] = array(
55
- 'wpcf-jquery-fields-date' => array(
56
- 'src' => WPCF_EMBEDDED_RES_RELPATH . '/js/jquery.ui.datepicker.min.js',
57
- 'deps' => array('jquery-ui-core'),
58
- ),
59
- 'wpcf-jquery-fields-date-inline' => array(
60
- 'inline' => 'wpcf_fields_date_meta_box_js_inline',
61
- ),
62
- 'wpcf-jquery-fields-date-localization' => $localized_js,
63
- );
64
- $settings['meta_box_css'] = array(
65
- 'wpcf-jquery-ui' => array(
66
- 'src' => WPCF_EMBEDDED_RES_RELPATH
67
- . '/css/jquery-ui/jquery-ui-1.9.2.custom.min.css',
68
- ),
69
- );
70
- }
71
- return $settings;
72
- }
73
-
74
- /*
75
- *
76
- * Date Field
77
- */
78
-
79
- // Set date formats
80
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields/date/date-formats.php';
81
-
82
- // Include helper functions
83
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields/date/functions.php';
84
-
85
- // Include calendar
86
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields/date/calendar.php';
87
-
88
- // Include JS
89
- require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields/date/js.php';
90
-
91
- // Parsing date function
92
- if ( !function_exists( 'wpv_filter_parse_date' ) ) {
93
- require_once WPCF_EMBEDDED_ABSPATH . '/toolset/toolset-common/wpv-filter-date-embedded.php';
94
- }
95
-
96
- /*
97
- *
98
- *
99
- *
100
- *
101
- *
102
- * Filters
103
- */
104
- /*
105
- *
106
- *
107
- * This one is called to convert stored timestamp to array,
108
- * appending Hour and Minute data too.
109
- *
110
- * Called from WPCF_Field:: _get_meta()
111
- *
112
- * Returns array(
113
- * 'timestamp' => 14435346,
114
- * 'datepicker' => 'April 9, 2012',
115
- * 'hour' => 8,
116
- * 'minute' => 9
117
- */
118
- add_filter( 'wpcf_fields_type_date_value_get',
119
- 'wpcf_fields_date_value_get_filter', 10, 4 );
120
-
121
- /*
122
- *
123
- * Used to convert submitted data (array) to timestamp before saving field.
124
- * Called from WPCF_Field::_filter_save_value()
125
- *
126
- * Returns timestamp
127
- */
128
- add_filter( 'wpcf_fields_type_date_value_save',
129
- 'wpcf_fields_date_value_save_filter', 10, 3 );
130
-
131
- /*
132
- *
133
- * Built-in Types Conditinal check hook.
134
- * Used for Conditional value.
135
- * If array - convert to timestamp.
136
- *
137
- * Returns timestamp
138
- */
139
- add_filter( 'wpcf_conditional_display_compare_condition_value',
140
- 'wpcf_fields_date_conditional_condition_filter', 10, 5 );
141
- /*
142
- * This only applied when Checking in AJAX call
143
- */
144
- if ( defined( 'DOING_AJAX' ) ) {
145
- add_filter( 'wpcf_conditional_display_compare_meta_value',
146
- 'wpcf_fields_date_conditional_value_filter', 10, 5 );
147
- }
148
-
149
- /*
150
- *
151
- * This is added for Custom Conditional Statement.
152
- * Use more specific hook in evaluate.php
153
- */
154
- //add_action( 'types_custom_conditional_statement',
155
- // 'wpcf_fields_custom_conditional_statement_hook' );
156
- /*
157
- * 1.3 Changed to use 'wpv_condition' hook.
158
- */
159
- add_action( 'wpv_condition', 'wpcf_fields_custom_conditional_statement_hook' );
160
-
161
- /**
162
- * From data for post edit page.
163
- *
164
- * @param type $field
165
- * @param type $data
166
- * @param type $field_object Field instance
167
- */
168
- function wpcf_fields_date_meta_box_form( $field, $field_object = null ) {
169
-
170
- /*
171
- * Added extra fields 'hour' and 'minute'.
172
- *
173
- * If value is not array it is assumed that DB entry is timestamp()
174
- * and data is converted to array.
175
- */
176
- $value = $field['value'] = wpcf_fields_date_value_get_filter( $field['value'],
177
- $field_object );
178
-
179
- // TODO WPML Set disable_in_form or similar to true, use hook for WPML
180
- if ( wpcf_wpml_field_is_copied( $field ) ) {
181
- $attributes = array('style' => 'width:150px;');
182
- } else {
183
- $attributes = array('class' => 'wpcf-datepicker', 'style' => 'width:150px;');
184
- }
185
-
186
- /*
187
- *
188
- * Do not forget to trigger datepicker script
189
- * Only trigger on AJAX call (inserting new)
190
- */
191
- $js_trigger = defined( 'DOING_AJAX' ) ? '<script type="text/javascript">wpcfFieldsDateInit(\'\');</script>' : '';
192
-
193
- /*
194
- *
195
- *
196
- * Set Form
197
- */
198
- $unique_id = wpcf_unique_id( serialize( $field ) );
199
- $form = array();
200
- $form[$unique_id . '-datepicker'] = array(
201
- '#type' => 'textfield',
202
- '#title' => '&nbsp;' . $field['name'],
203
- '#attributes' => $attributes,
204
- '#name' => 'wpcf[' . $field['slug'] . '][datepicker]',
205
- '#id' => 'wpcf-date-' . $field['slug'] . '-datepicker-' . $unique_id,
206
- '#value' => $value['datepicker'],
207
- // '#inline' => true,
208
- '#after' => '' . $js_trigger, // Append JS trigger
209
- '#_validate_this' => true, // Important when H and M are used too
210
- );
211
-
212
- // Add warning about supported timestamp
213
- if ( !fields_date_timestamp_neg_supported() ) {
214
- $_visible = !empty( $value['datepicker'] )
215
- && intval( $value['timestamp'] ) < 0 ? '' : ' style="display:none;"';
216
- $form[$unique_id . '-warning'] = array(
217
- '#type' => 'markup',
218
- '#markup' => '<div class="wpcf-form-error"' . $_visible
219
- . '><p>' . __( 'Please enter a date after 1 January 1970', 'wpcf' )
220
- . '</p></div>',
221
- );
222
- }
223
-
224
- /*
225
- *
226
- * If set 'date_and_time' add time
227
- */
228
- if ( !empty( $field['data']['date_and_time'] )
229
- && $field['data']['date_and_time'] == 'and_time' ) {
230
-
231
- // Set parent CSS inline
232
- $form[$unique_id . '-datepicker']['#inline'] = true;
233
-
234
- $hours = 24;
235
- $minutes = 60;
236
- $options = array();
237
-
238
- // Hour
239
- for ( $index = 0; $index < $hours; $index++ ) {
240
- $prefix = $index < 10 ? '0' : '';
241
- $options[$index] = array(
242
- '#title' => $prefix . strval( $index ),
243
- '#value' => $index,
244
- );
245
- }
246
- $form[$unique_id . 'time_hour'] = array(
247
- '#type' => 'select',
248
- '#title' => __( 'Hour', 'wpcf' ),
249
- '#inline' => true,
250
- '#before' => '<br />',
251
- '#after' => '&nbsp;&nbsp;',
252
- '#options' => $options,
253
- '#default_value' => $value['hour'],
254
- '#name' => 'wpcf[' . $field['slug'] . '][hour]',
255
- '#id' => 'wpcf-date-' . $field['slug'] . '-select-hour-'
256
- . $unique_id,
257
- '#inline' => true,
258
- );
259
-
260
- // Minutes
261
- for ( $index = 1; $index < $minutes; $index++ ) {
262
- $prefix = $index < 10 ? '0' : '';
263
- $options[$index] = array(
264
- '#title' => $prefix . strval( $index ),
265
- '#value' => $index,
266
- );
267
- }
268
- $form[$unique_id . 'time_minute'] = array(
269
- '#type' => 'select',
270
- '#title' => __( 'Minute', 'wpcf' ),
271
- '#after' => '<br /><br />',
272
- '#inline' => true,
273
- '#options' => $options,
274
- '#default_value' => $value['minute'],
275
- '#name' => 'wpcf[' . $field['slug'] . '][minute]',
276
- '#id' => 'wpcf-date-' . $field['slug'] . '-minute-'
277
- . $unique_id,
278
- );
279
- }
280
-
281
- return $form;
282
- }
283
-
284
- /**
285
- * Parses date meta.
286
- *
287
- * Use this as main function.
288
- *
289
- * @param int $value timestamp
290
- * @param type $field Field data
291
- * $param string $return Specify to return array or specific element of same array
292
- * ( timestamp, datepicker, hour, minute )
293
- * @return mixed array | custom parameter
294
- */
295
- function wpcf_fields_date_value_get_filter( $value, $field, $return = 'array',
296
- $context = 'get', $use_cache = true ) {
297
- global $wpcf;
298
-
299
- /*
300
- *
301
- * Fix for leftover
302
- */
303
- if ( $context != 'check_leftover' ) {
304
- $value = __wpcf_fields_date_check_leftover( $value, $field );
305
- }
306
-
307
- // Check if cached
308
- static $cache = array();
309
- $cache_key = md5( serialize( $value ) );
310
-
311
- if ( isset( $cache[$cache_key] ) && $use_cache ) {
312
- // Set return data if necessary
313
- if ( $return != 'array' ) {
314
- if ( isset( $cache[$cache_key][strval( $return )] ) ) {
315
- return $cache[$cache_key][strval( $return )];
316
- }
317
- } else {
318
- return $cache[$cache_key];
319
- }
320
- }
321
-
322
- $value_cloned = $value;
323
- $date_format = wpcf_get_date_format();
324
-
325
- if ( empty( $value ) ) {
326
- $value = array(
327
- 'timestamp' => null,
328
- 'hour' => 8,
329
- 'minute' => 0,
330
- 'datepicker' => '',
331
- );
332
- } else if ( is_array( $value ) ) {
333
- /*
334
- * Consider this already parsed
335
- * but check anyway.
336
- */
337
- if (
338
- array_key_exists('datepicker', $value)
339
- && !array_key_exists('timestamp', $value)
340
- //Fix date pre-1970 issue
341
- //https://wp-types.com/forums/topic/pre-1971-dates-throw-error/#post-288989
342
- //https://icanlocalize.basecamphq.com/projects/7393061-toolset/todo_items/194818870/comments
343
- && (
344
- preg_match( '/^\d+$/', $value['datepicker'] )
345
- || (
346
- -12219292800 <= $value['datepicker']
347
- && $value['datepicker'] <= 32535215940
348
- )
349
- )
350
- ) {
351
- $value['timestamp'] = $value['datepicker'];
352
- unset($value['datepicker']);
353
- }
354
- $value = wpcf_fields_date_value_check( $value );
355
- } else {
356
- $value = array(
357
- 'timestamp' => $value,
358
- 'hour' => adodb_date( 'H', $value ),
359
- 'minute' => adodb_date( 'i', $value ),
360
- 'datepicker' => adodb_date( $date_format, $value ),
361
- );
362
- $value = wpcf_fields_date_value_check( $value );
363
- }
364
-
365
- // Debug
366
- $wpcf->debug->dates[] = array(
367
- 'original_value' => $value_cloned,
368
- 'value' => $value,
369
- 'field' => $field,
370
- 'context' => $context,
371
- );
372
-
373
- // Cache it
374
- if ( $use_cache ) {
375
- $cache[$cache_key] = $value;
376
- }
377
-
378
- // Set return data if necessary
379
- if ( $return != 'array' ) {
380
- $value = isset( $value[strval( $return )] ) ? $value[strval( $return )] : null;
381
- }
382
-
383
- return $value;
384
- }
385
-
386
- /**
387
- * View function.
388
- *
389
- * @param type $params
390
- */
391
- function wpcf_fields_date_view( $params ) {
392
-
393
- global $wp_locale;
394
-
395
- $defaults = array(
396
- 'format' => get_option( 'date_format' ),
397
- 'style' => '' // add default value
398
- );
399
- $params = wp_parse_args( $params, $defaults );
400
- $output = '';
401
-
402
- // Make sure value is right
403
- $__timestamp = wpcf_fields_date_value_get_filter( $params['field_value'],
404
- $params['field'], 'timestamp' );
405
- if ( is_null( $__timestamp ) ) {
406
- return '';
407
- } else {
408
- $params['field_value'] = $__timestamp;
409
- }
410
-
411
- switch ( $params['style'] ) {
412
- case 'calendar':
413
- $output .= wpcf_fields_date_get_calendar( $params, true, false );
414
- break;
415
-
416
- default:
417
- $field_name = '';
418
-
419
-
420
- // Extract the Full month and Short month from the format.
421
- // We'll replace with the translated months if possible.
422
- $format = $params['format'];
423
- //$format = str_replace( 'F', '#111111#', $format );
424
- //$format = str_replace( 'M', '#222222#', $format );
425
-
426
- // Same for the Days
427
- //$format = str_replace( 'D', '#333333#', $format );
428
- //$format = str_replace( 'l', '#444444#', $format );
429
-
430
- $date_out = adodb_date( $format, $params['field_value'] );
431
-
432
- //$month = adodb_date( 'm', $params['field_value'] );
433
- //$month_full = $wp_locale->get_month( $month );
434
- //$date_out = str_replace( '#111111#', $month_full, $date_out );
435
- //$month_short = $wp_locale->get_month_abbrev( $month_full );
436
- //$date_out = str_replace( '#222222#', $month_short, $date_out );
437
-
438
- //$day = adodb_date( 'w', $params['field_value'] );
439
- //$day_full = $wp_locale->get_weekday( $day );
440
- //$date_out = str_replace( '#444444#', $day_full, $date_out );
441
- //$day_short = $wp_locale->get_weekday_abbrev( $day_full );
442
- //$date_out = str_replace( '#333333#', $day_short, $date_out );
443
-
444
- $output .= $date_out;
445
- break;
446
- }
447
-
448
- return $output;
449
- }
450
-
451
- /**
452
- * TinyMCE editor form.
453
- */
454
- function wpcf_fields_date_editor_callback( $field, $settings ) {
455
-
456
- $data = array(
457
- 'date_formats' => array(),
458
- );
459
- $date_formats = apply_filters( 'date_formats',
460
- array(
461
- __( 'F j, Y', 'wpcf' ),
462
- 'Y/m/d',
463
- 'm/d/Y',
464
- 'd/m/Y',
465
- 'd/m/y',
466
- )
467
- );
468
-
469
- // Custom format
470
- $data['custom'] = isset( $settings['custom'] ) ? $settings['custom'] : get_option( 'date_format' );
471
-
472
- /**
473
- * date with hour and minutes
474
- */
475
- if (
476
- isset($field['data'])
477
- && isset( $field['data']['date_and_time'])
478
- && 'and_time' == $field['data']['date_and_time']
479
- ) {
480
- $date_formats = apply_filters( 'date_formats',
481
- array(
482
- __( 'F j, Y g:i a', 'wpcf' ),
483
- 'Y/m/d g:i a',
484
- 'm/d/Y h:i a',
485
- 'd/m/Y G:i',
486
- 'd/m/y H:i',
487
- )
488
- );
489
- // Custom format
490
- $data['custom'] = sprintf(
491
- '%s %s',
492
- get_option('date_format'),
493
- get_option('time_format')
494
- );
495
- }
496
-
497
- $data['default'] = 'custom';
498
-
499
- foreach ( $date_formats as $k => $format ) {
500
- $title = date( $format, time() );
501
- $data['date_formats'][$k] = array(
502
- 'id' => sanitize_title( $format ),
503
- 'title' => $title,
504
- 'format' => $format,
505
- 'default' => isset( $settings['format'] ) && $format == $settings['format'] ? true : false,
506
- );
507
- if ( $data['date_formats'][$k]['default'] ) {
508
- $data['default'] = $data['date_formats'][$k]['id'];
509
- }
510
- }
511
- return array(
512
- 'supports' => array('styling'),
513
- 'tabs' => array(
514
- 'display' => array(
515
- 'menu_title' => __( 'Display options', 'wpcf' ),
516
- 'title' => __( 'Display options for this field:', 'wpcf' ),
517
- 'content' => WPCF_Loader::template( 'editor-modal-date', $data ),
518
- ),
519
- )
520
- );
521
- }
522
-
523
- /**
524
- * Inserts shortcode in editor.
525
- *
526
- * @return type
527
- */
528
- function wpcf_fields_date_editor_submit( $data, $field, $context ) {
529
-
530
- $add = ' ';
531
- $raw = !empty( $data['raw_mode'] );
532
- $format = get_option( 'date_format' );
533
- $style = isset( $data['style'] ) ? $data['style'] : 'text';
534
-
535
- if ( !$raw ) {
536
- $add .= 'style="' . $style . '"';
537
- if ( $style == 'text' ) {
538
- if ( isset( $data['format'] ) ) {
539
- if ( $data['format'] == 'custom' && isset( $data['custom'] ) ) {
540
- $format = $data['custom'];
541
- } else {
542
- $format = $data['format'];
543
- }
544
- }
545
- $add .= ' format="' . $format . '"';
546
- }
547
- }
548
- if ( $context == 'usermeta' ) {
549
- $add .= wpcf_get_usermeta_form_addon_submit();
550
- $shortcode = wpcf_usermeta_get_shortcode( $field, $add );
551
- } elseif ( $context == 'termmeta' ) {
552
- $add .= wpcf_get_termmeta_form_addon_submit();
553
- $shortcode = wpcf_termmeta_get_shortcode( $field, $add );
554
- } else {
555
- $shortcode = wpcf_fields_get_shortcode( $field, $add );
556
- }
557
-
558
- return $shortcode;
559
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/fields/date/functions.php DELETED
@@ -1,521 +0,0 @@
1
- <?php
2
- /*
3
- * Various functions for Date Field.
4
- */
5
-
6
- /**
7
- * Calculate time
8
- *
9
- * @param array $value Full data
10
- */
11
- function wpcf_fields_date_calculate_time( $value ) {
12
-
13
- extract( $value );
14
-
15
- // Empty is only on new post
16
- if ( empty( $timestamp ) ) {
17
- return null;
18
- }
19
-
20
- // Fix hour and minute
21
- if ( empty( $hour ) || strval( $hour ) == '00' ) {
22
- $hour = 0;
23
- }
24
- if ( empty( $minute ) || strval( $minute ) == '00' ) {
25
- $minute = 0;
26
- }
27
-
28
- $timestamp_date = adodb_date( 'dmY', $timestamp );
29
- $date = adodb_mktime( intval( $hour ), intval( $minute ), 0, substr( $timestamp_date, 2, 2 ), substr( $timestamp_date, 0, 2 ), substr( $timestamp_date, 4, 4 ) );
30
- $timestamp = $date;
31
-
32
- // Add Hour and minute
33
- //$timestamp = $timestamp + (60 * 60 * intval( $hour )) + (60 * intval( $minute ));
34
-
35
- return $timestamp;
36
- }
37
-
38
- /**
39
- * Converts date to time on post saving.
40
- *
41
- * @param array $value Use 'datepicker' to convert to timestamp.
42
- * @param $field
43
- * @param $field_object WPCF_Field|WPCF_Usermeta_Field|null Since 1.9, this can also be null (because of term fields).
44
- *
45
- * @return int timestamp
46
- *
47
- * @todo This needs some review. Is there a situation when this filter is executed and we _don't_ have toolset-forms
48
- * @todo loaded? I don't think so but you can never be sure...
49
- */
50
- function wpcf_fields_date_value_save_filter( $value, $field, $field_object ) {
51
-
52
- if ( defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
53
- if ( empty( $value ) || empty( $value['datepicker'] ) ) {
54
- return false;
55
- }
56
- if ( is_numeric( $value['datepicker'] ) ) {
57
- $timestamp = $value['datepicker'];
58
- } else {
59
- $timestamp = wptoolset_strtotime( $value['datepicker'] );
60
- }
61
- // Append Hour and Minute
62
- if ( $timestamp !== false && isset( $value['hour'] ) && isset( $value['minute'] ) ) {
63
- $timestamp_date = adodb_date( 'dmY', $timestamp );
64
- $date = adodb_mktime( intval( $value['hour'] ), intval( $value['minute'] ), 0, substr( $timestamp_date, 2, 2 ), substr( $timestamp_date, 0, 2 ), substr( $timestamp_date, 4, 4 ) );
65
- $timestamp = $date;
66
- /*
67
- $date = new DateTime( $value['datepicker'] );
68
- try {
69
- $date->add( new DateInterval( 'PT' . intval( $value['hour'] ) . 'H' . intval( $value['minute'] ) . 'M' ) );
70
- } catch (Exception $e) {
71
- return $timestamp;
72
- }
73
- $timestamp = $date->format( "U" );
74
- */
75
- }
76
- return $timestamp;
77
- }
78
- // I understand this below is not executed anymore?
79
- global $wpcf;
80
-
81
- // Remove additional meta if any
82
- if ( ( null != $field_object ) && isset( $field_object->post->ID ) ) {
83
- delete_post_meta(
84
- $field_object->post->ID,
85
- '_wpcf_' . $field_object->cf['id'] . '_hour_and_minute' );
86
- }
87
-
88
- if ( empty( $value ) || empty( $value['datepicker'] ) ) {
89
- return false;
90
- }
91
-
92
- $value['timestamp'] = wpcf_fields_date_convert_datepicker_to_timestamp( $value['datepicker'] );
93
-
94
- if ( !wpcf_fields_date_timestamp_is_valid( $value['timestamp'] ) ) {
95
- $wpcf->debug->errors['date_save_failed'][] = array(
96
- 'value' => $value,
97
- 'field' => $field,
98
- );
99
- return false;
100
- }
101
-
102
- // Append Hour and Minute
103
- if ( isset( $value['hour'] ) && isset( $value['minute'] ) ) {
104
- $value['timestamp'] = wpcf_fields_date_calculate_time( $value );
105
- }
106
-
107
- return $value['timestamp'];
108
- }
109
-
110
- /**
111
- * Filters conditional edited field value for built-in Types Conditinal check.
112
- *
113
- * @param type $value
114
- * @param type $field
115
- * @param type $operation
116
- * @param type $conditional_field
117
- * @param type $post
118
- * @return type
119
- */
120
- function wpcf_fields_date_conditional_value_filter( $value, $field, $operation,
121
- $field_compared, $post ) {
122
-
123
- global $wpcf;
124
-
125
- $field = wpcf_admin_fields_get_field( $wpcf->field->__get_slug_no_prefix( $field ) );
126
- if ( !empty( $field ) && isset( $field['type'] ) && $field['type'] == 'date' && isset($value['datepicker']) ) {
127
- $value['timestamp'] = wpcf_fields_date_convert_datepicker_to_timestamp( $value['datepicker'] );
128
- $value = wpcf_fields_date_calculate_time( $value );
129
- }
130
- return $value;
131
- }
132
-
133
- /**
134
- * Filters conditional condition value - converts dates to timestamps.
135
- *
136
- * @param type $value
137
- * @param type $field
138
- * @param type $operation
139
- * @param type $field_compared
140
- * @param type $post
141
- */
142
- function wpcf_fields_date_conditional_condition_filter( $value, $field,
143
- $operation, $field_compared, $post ) {
144
- global $wpcf;
145
-
146
- $field = wpcf_admin_fields_get_field( $wpcf->field->__get_slug_no_prefix( $field ) );
147
- if ( !empty( $field ) && isset( $field['type'] ) && $field['type'] == 'date' ) {
148
- $_value = wpcf_fields_date_convert_datepicker_to_timestamp( $value );
149
- if ( $_value ) {
150
- $value = $_value;
151
- } else {
152
- $value = wpcf_fields_date_value_get_filter( $value, $field,
153
- 'timestamp' );
154
- }
155
- }
156
- return $value;
157
- }
158
-
159
- /**
160
- * Add post meta hook if Custom Conditinal Statement used.
161
- */
162
- function wpcf_fields_custom_conditional_statement_hook() {
163
- // Enqueue after first filters in evaluate.php
164
- add_filter( 'get_post_metadata',
165
- 'wpcf_fields_date_custom_conditional_statement_filter', 20, 4 );
166
- }
167
-
168
- /**
169
- * Custom Conditinal Statement hook returns timestamp if array.
170
- *
171
- * NOTE that $null is already filtered to use $_POST values
172
- * at priority 10.
173
- *
174
- * @param type $null
175
- * @param type $object_id
176
- * @param type $meta_key
177
- * @param type $single
178
- * @return mixed timestamp or $null
179
- */
180
- function wpcf_fields_date_custom_conditional_statement_filter( $null,
181
- $object_id, $meta_key, $single ) {
182
-
183
- global $wpcf;
184
-
185
- $field = wpcf_admin_fields_get_field( $wpcf->field->__get_slug_no_prefix( $meta_key ) );
186
-
187
- if ( !empty( $null ) && !empty( $field ) && isset( $field['type'] ) && $field['type'] == 'date' ) {
188
- if ( is_array( $null ) && !isset( $null['datepicker'] ) ) {
189
- $null = array_shift( $null );
190
- }
191
- $null = wpcf_fields_date_value_get_filter( $null, $field, 'timestamp' );
192
- if ( !is_numeric( $null ) ) {
193
- $null = -1;
194
- }
195
- /**
196
- * be sure do not return string if array is expected!
197
- */
198
- if ( !$single && !is_array($null) ) {
199
- return array($null);
200
- }
201
- }
202
- return $null;
203
- }
204
-
205
- /**
206
- * Returns most suitable date format.
207
- *
208
- * @global type $supported_date_formats
209
- * @return string
210
- */
211
- function wpcf_get_date_format() {
212
- global $supported_date_formats;
213
-
214
- $date_format = get_option( 'date_format' );
215
- if ( !in_array( $date_format, $supported_date_formats ) ) {
216
- // Choose the Month day, Year fromat
217
- $date_format = 'F j, Y';
218
- }
219
-
220
- return $date_format;
221
- }
222
-
223
- /*
224
- *
225
- *
226
- * TODO DOCUMENT
227
- */
228
-
229
- function wpcf_get_date_format_text() {
230
- global $supported_date_formats, $supported_date_formats_text;
231
-
232
- $date_format = get_option( 'date_format' );
233
- if ( !in_array( $date_format, $supported_date_formats ) ) {
234
- // Choose the Month day, Year fromat
235
- $date_format = 'F j, Y';
236
- }
237
-
238
- return $supported_date_formats_text[$date_format];
239
- }
240
-
241
- function _wpcf_date_convert_wp_to_js( $date_format ) {
242
- $date_format = str_replace( 'd', 'dd', $date_format );
243
- $date_format = str_replace( 'j', 'd', $date_format );
244
- $date_format = str_replace( 'l', 'DD', $date_format );
245
- $date_format = str_replace( 'm', 'mm', $date_format );
246
- $date_format = str_replace( 'n', 'm', $date_format );
247
- $date_format = str_replace( 'F', 'MM', $date_format );
248
- $date_format = str_replace( 'Y', 'yy', $date_format );
249
-
250
- return $date_format;
251
- }
252
-
253
- /**
254
- *
255
- * Convert a format from date() to strftime() format
256
- *
257
- */
258
- function wpcf_date_to_strftime( $format ) {
259
-
260
- $format = str_replace( 'd', '%d', $format );
261
- $format = str_replace( 'D', '%a', $format );
262
- $format = str_replace( 'j', '%e', $format );
263
- $format = str_replace( 'l', '%A', $format );
264
- $format = str_replace( 'N', '%u', $format );
265
- $format = str_replace( 'w', '%w', $format );
266
-
267
- $format = str_replace( 'W', '%W', $format );
268
-
269
- $format = str_replace( 'F', '%B', $format );
270
- $format = str_replace( 'm', '%m', $format );
271
- $format = str_replace( 'M', '%b', $format );
272
- $format = str_replace( 'n', '%m', $format );
273
-
274
- $format = str_replace( 'o', '%g', $format );
275
- $format = str_replace( 'Y', '%Y', $format );
276
- $format = str_replace( 'y', '%y', $format );
277
-
278
- return $format;
279
- }
280
-
281
- /**
282
- * Checks if Date value array has all required elements.
283
- *
284
- * It will re-create missing elements if possible.
285
- * If not possible - will return empty Date.
286
- *
287
- * @param array $a
288
- * @return null
289
- */
290
- function wpcf_fields_date_value_check( $a ) {
291
-
292
- $required = array('timestamp', 'datepicker', 'hour', 'minute');
293
- $empty_date = array(
294
- 'timestamp' => null,
295
- 'hour' => 8,
296
- 'minute' => 0,
297
- 'datepicker' => '',
298
- );
299
-
300
- // Return empty date if can not be calculated
301
- if ( empty( $a['timestamp'] ) && empty( $a['datepicker'] ) ) {
302
- return $empty_date;
303
- }
304
-
305
- // Loop over and check if some missing or need fix
306
- foreach ( $required as $key ) {
307
- switch ( $key ) {
308
- case 'timestamp':
309
- // If not set or malformed - create from datepicker
310
- if ( !isset( $a[$key] ) || !wpcf_fields_date_timestamp_is_valid( $a[$key] ) ) {
311
- $_t = wpcf_fields_date_convert_datepicker_to_timestamp( $a['datepicker'] );
312
- if ( !$_t ) {
313
- // Failed converting
314
- return $empty_date;
315
- }
316
- $a['timestamp'] = $_t;
317
- }
318
- $a['timestamp'] = $a['timestamp'];
319
- break;
320
-
321
- case 'datepicker':
322
- // If not set - create it from timestamp.
323
- if ( empty( $a[$key] ) ) {
324
- $_d = wpcf_fields_date_convert_timestamp_to_datepicker( $a['timestamp'] );
325
- if ( !$_d ) {
326
- // Failed converting
327
- return $empty_date;
328
- }
329
- $a['datepicker'] = $_d;
330
- }
331
- // Check if valid (already set value)
332
- /*
333
- if ( !wpcf_fields_date_datepicker_is_valid( $a['datepicker'] ) ) {
334
- return $empty_date;
335
- }
336
- */
337
- $a['datepicker'] = strval( $a['datepicker'] );
338
- break;
339
-
340
- case 'hour':
341
- $_h = adodb_date( 'H', $a['timestamp'] );
342
- $a['hour'] = $_h;
343
- break;
344
-
345
- case 'minute':
346
- $_m = adodb_date( 'i', $a['timestamp'] );
347
- $a['minute'] = $_m;
348
- break;
349
-
350
- default:
351
- break;
352
- }
353
- }
354
-
355
- // Final test - make sure timestamp matches Datepicker
356
- if ( adodb_date( wpcf_get_date_format(), $a['timestamp'] ) != $a['datepicker'] ) {
357
- // In this case we'll give advantage to timestamp
358
- $a['datepicker'] = wpcf_fields_date_convert_timestamp_to_datepicker( $a['timestamp'] );
359
- if ( !$a['timestamp'] ) {
360
- // Failed converting
361
- return $empty_date;
362
- }
363
- }
364
-
365
- ksort( $a );
366
- return $a;
367
- }
368
-
369
- /**
370
- * Converts timestamp to Datepicker and checks if valid.
371
- *
372
- * @param type $timestamp
373
- * @return boolean
374
- */
375
- function wpcf_fields_date_convert_timestamp_to_datepicker( $timestamp ) {
376
- // Check if timestamp valid
377
- if ( !wpcf_fields_date_timestamp_is_valid( $timestamp ) ) {
378
- return false;
379
- }
380
- $_d = adodb_date( wpcf_get_date_format(), $timestamp );
381
- /*
382
- if ( !wpcf_fields_date_datepicker_is_valid( $_d ) ) {
383
- // Failed converting
384
- return false;
385
- }
386
- */
387
- return $_d;
388
- }
389
-
390
- /**
391
- * Converts Datepicker to timestamp and checks if valid.
392
- * @param type $datepicker
393
- * @return boolean
394
- */
395
- function wpcf_fields_date_convert_datepicker_to_timestamp( $datepicker ) {
396
- $date_format = wpcf_get_date_format();
397
- if ( $date_format == 'd/m/Y' ) {
398
- // strtotime requires a dash or dot separator to determine dd/mm/yyyy format
399
- $datepicker = str_replace( '/', '-', $datepicker );
400
- }
401
- $_t = strtotime( strval( $datepicker ) );
402
- if ( $_t == false || !wpcf_fields_date_timestamp_is_valid( $_t ) ) {
403
- // Failed converting
404
- return false;
405
- }
406
- return $_t;
407
- }
408
-
409
- /**
410
- * Checks if timestamp is numeric and within range.
411
- *
412
- * @param type $timestamp
413
- * @return type
414
- */
415
- function wpcf_fields_date_timestamp_is_valid( $timestamp ) {
416
- /*
417
- * http://php.net/manual/en/function.strtotime.php
418
- * The valid range of a timestamp is typically
419
- * from Fri, 13 Dec 1901 20:45:54 UTC
420
- * to Tue, 19 Jan 2038 03:14:07 UTC.
421
- * (These are the dates that correspond to the minimum
422
- * and maximum values for a 32-bit signed integer.)
423
- * Additionally, not all platforms support negative timestamps,
424
- * therefore your date range may be limited to no earlier than
425
- * the Unix epoch.
426
- * This means that e.g. dates prior to Jan 1, 1970 will not
427
- * work on Windows, some Linux distributions,
428
- * and a few other operating systems.
429
- * PHP 5.1.0 and newer versions overcome this limitation though.
430
- */
431
- // MIN 'Jan 1, 1970' - 0 | Fri, 13 Dec 1901 20:45:54 UTC
432
- $_min_timestamp = fields_date_timestamp_neg_supported() ? -2147483646 : 0;
433
- // MAX 'Tue, 19 Jan 2038 03:14:07 UTC' - 2147483647
434
- $_max_timestamp = 2147483647;
435
- return WPToolset_Field_Date_Scripts::_isTimestampInRange($timestamp);
436
- //return is_numeric( $timestamp ) && $_min_timestamp <= $timestamp && $timestamp <= $_max_timestamp;
437
- }
438
-
439
- /**
440
- * Checks if Datepicker is valid by converting it to timestamp.
441
- * @param type $datepicker
442
- * @return boolean
443
- */
444
- function wpcf_fields_date_datepicker_is_valid( $datepicker ) {
445
- return (bool) wpcf_fields_date_convert_datepicker_to_timestamp( $datepicker );
446
- }
447
-
448
- /**
449
- * Fix due to a bug saving date as array.
450
- *
451
- * BUGS
452
- * 'timestamp' is saved without Hour and Minute appended.
453
- *
454
- * @param type $value
455
- * @param type $field
456
- */
457
- function __wpcf_fields_date_check_leftover( $value, $field, $use_cache = true ) {
458
-
459
- if ( empty( $value )) {
460
- return $value;
461
- }
462
-
463
- if ( !is_object( $field ) ) {
464
- $post_id = wpcf_get_post_id();
465
- $field_id = isset( $field['id'] ) ? $field['id'] : false;
466
- $meta_id = isset( $field['__meta_id'] ) ? $field['__meta_id'] : false;
467
- } else {
468
- $post_id = isset( $field->meta_object->post_id ) ? $field->meta_object->post_id : false;
469
- $field_id = isset( $field->cf['id'] ) ? $field->cf['id'] : false;
470
- $meta_id = isset( $field->meta_object->meta_id ) ? $field->meta_object->meta_id : false;
471
- }
472
-
473
- if ( empty( $post_id ) || empty( $meta_id ) || empty( $field_id ) ) {
474
- return $value;
475
- }
476
-
477
- $field_slug = wpcf_types_get_meta_prefix() . $field_id;
478
-
479
- // Check if cached
480
- static $cache = array();
481
- $cache_key = $meta_id;
482
-
483
- if ( isset( $cache[$cache_key] ) && $use_cache ) {
484
- return $cache[$cache_key];
485
- }
486
-
487
- $_meta = wpcf_get_post_meta( $post_id,
488
- '_wpcf_' . $field_id . '_hour_and_minute', true );
489
-
490
- /*
491
- * If meta exists - it's outdated value
492
- * and Hour and Minute should be appended and removed.
493
- */
494
- if ( !empty( $_meta ) && is_array( $_meta ) && isset( $_meta[$meta_id] ) ) {
495
-
496
- $meta = $_meta[$meta_id];
497
-
498
- // Return empty date if can not be calculated
499
- if ( !empty( $meta['timestamp'] ) || !empty( $meta['datepicker'] ) ) {
500
-
501
- $meta['timestamp'] = wpcf_fields_date_value_get_filter( $meta,
502
- $field, 'timestamp', 'check_leftover' );
503
-
504
- // Check if calculation needed
505
- if ( (isset( $meta['hour'] )
506
- && $meta['hour'] != adodb_date( 'H', $meta['timestamp'] ) )
507
- || (isset( $meta['minute'] )
508
- && $meta['minute'] != adodb_date( 'i', $meta['timestamp'] ) ) ) {
509
-
510
- $value = wpcf_fields_date_calculate_time( $meta );
511
- }
512
- }
513
- }
514
-
515
- // Cache it
516
- if ( $use_cache ) {
517
- $cache[$cache_key] = $value;
518
- }
519
-
520
- return $value;
521
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/fields/email.php DELETED
@@ -1,97 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Register data (called automatically).
5
- *
6
- * @return type
7
- */
8
- function wpcf_fields_email() {
9
-
10
- return array(
11
- 'id' => 'wpcf-email',
12
- 'title' => __( 'Email', 'wpcf' ),
13
- 'description' => __( 'Email', 'wpcf' ),
14
- 'validate' => array(
15
- 'required' => array(
16
- 'form-settings' =>
17
- include( dirname( __FILE__ ) . '/patterns/validate/form-settings/required.php' ),
18
- ),
19
- 'email' => array(
20
- 'form-settings' => array_replace_recursive(
21
- include( dirname( __FILE__ ) . '/patterns/validate/form-settings/default.php' ),
22
- array(
23
- 'control' => array(
24
- '#title' => __('Validation', 'wpcf' ),
25
- '#label' => 'Email',
26
- )
27
- )
28
- )
29
- )
30
- ),
31
- 'inherited_field_type' => 'textfield',
32
- 'font-awesome' => 'envelope',
33
- );
34
- }
35
-
36
- /**
37
- * View function.
38
- *
39
- * @param type $params
40
- */
41
- function wpcf_fields_email_view( $params ) {
42
- $add = '';
43
- if ( !empty( $params['title'] ) ) {
44
- $add .= ' title="' . $params['title'] . '"';
45
- $title = $params['title'];
46
- } else {
47
- $add .= ' title="' . $params['field_value'] . '"';
48
- $title = $params['field_value'];
49
- }
50
- if ( !empty( $params['class'] ) ) {
51
- $add .= ' class="' . $params['class'] . '"';
52
- }
53
- if ( !empty( $params['style'] ) ) {
54
- $add .= ' style="' . $params['style'] . '"';
55
- }
56
- $output = '<a href="mailto:' . $params['field_value'] . '"' . $add . '>'
57
- . $title . '</a>';
58
- return $output;
59
- }
60
-
61
- /**
62
- * Editor callback form.
63
- */
64
- function wpcf_fields_email_editor_callback( $field, $settings ) {
65
- return array(
66
- 'supports' => array('styling', 'style'),
67
- 'tabs' => array(
68
- 'display' => array(
69
- 'menu_title' => __( 'Display options', 'wpcf' ),
70
- 'title' => __( 'Display options for this field:', 'wpcf' ),
71
- 'content' => WPCF_Loader::template( 'editor-modal-email',
72
- $settings ),
73
- )
74
- )
75
- );
76
- }
77
-
78
- /**
79
- * Editor callback form submit.
80
- */
81
- function wpcf_fields_email_editor_submit( $data, $field, $context ) {
82
- $add = '';
83
- if ( !empty( $data['title'] ) ) {
84
- $add = ' title="' . strval( $data['title'] ) . '"';
85
- }
86
- if ( $context == 'usermeta' ) {
87
- $add .= wpcf_get_usermeta_form_addon_submit();
88
- $shortcode = wpcf_usermeta_get_shortcode( $field, $add );
89
- } elseif ( $context == 'termmeta' ) {
90
- $add .= wpcf_get_termmeta_form_addon_submit();
91
- $shortcode = wpcf_termmeta_get_shortcode( $field, $add );
92
- } else {
93
- $shortcode = wpcf_fields_get_shortcode( $field, $add );
94
- }
95
-
96
- return $shortcode;
97
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/fields/entry.php DELETED
@@ -1,266 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Register data (called automatically).
5
- *
6
- * @return array field definition
7
- */
8
- function wpcf_fields_entry() {
9
- return array(
10
- 'id' => 'wpcf-entry',
11
- 'title' => __( 'Entry', 'wpcf' ),
12
- 'description' => __( 'Entry', 'wpcf' ),
13
- 'validate' => array(
14
- 'required' => array(
15
- 'form-settings' => include( dirname( __FILE__ ) . '/patterns/validate/form-settings/required.php' )
16
- )
17
- ),
18
- 'font-awesome' => 'file-text-o',
19
- );
20
- }
21
-
22
- /**
23
- * Meta box form.
24
- *
25
- * @param type $field
26
- * @return string
27
- */
28
- function wpcf_fields_entry_meta_box_form( $field ) {
29
- $form = array();
30
- $form['name'] = array(
31
- '#type' => 'textfield',
32
- '#name' => 'wpcf[' . $field['slug'] . ']',
33
- );
34
- return $form;
35
- }
36
-
37
- /**
38
- * Editor callback form.
39
- */
40
- function wpcf_fields_entry_editor_callback($field, $settings)
41
- {
42
- $post_type = get_post_type_object( $field['data']['post_type'] );
43
- if ( empty($post_type ) ) {
44
- return;
45
- }
46
-
47
- $data = wpcf_fields_entry_get_options();
48
-
49
- foreach( $data['options'] as $key => $field_data ) {
50
- if ( wpcf_fields_entry_check_is_available( $field['data']['post_type'], $field_data ) ) {
51
- continue;
52
- }
53
- unset($data['options'][$key]);
54
- }
55
-
56
- return array(
57
- 'supports' => array('style'),
58
- 'tabs' => array(
59
- 'display' => array(
60
- 'menu_title' => __( 'Display options', 'wpcf' ),
61
- 'title' => __( 'Display options for this field:', 'wpcf' ),
62
- 'content' => WPCF_Loader::template( 'editor-modal-entry', $data),
63
- )
64
- ),
65
- );
66
- }
67
-
68
- /**
69
- * Editor callback form submit.
70
- */
71
- function wpcf_fields_entry_editor_submit($data, $field, $context)
72
- {
73
- $shortcode = '';
74
- if (
75
- isset($data['display'])
76
- && preg_match('/^post-[\-a-z]+$/', $data['display'])
77
- ) {
78
- $add = sprintf(' display="%s"', $data['display']);
79
- if ( $context == 'usermeta' ) {
80
- $shortcode = wpcf_usermeta_get_shortcode( $field, $add );
81
- } else {
82
- $shortcode = wpcf_fields_get_shortcode( $field, $add );
83
- }
84
- }
85
- return $shortcode;
86
- }
87
-
88
- /**
89
- * View function.
90
- *
91
- * @param type $params
92
- */
93
- function wpcf_fields_entry_view($params)
94
- {
95
- if (
96
- !isset($params['field'])
97
- || !isset($params['display'])
98
- || !isset($params['field_value'])
99
- || empty($params['field_value'])
100
- ) {
101
- return '__wpcf_skip_empty';
102
- }
103
- /**
104
- * use cache
105
- */
106
- static $wpcf_fields_entry_view_cache;
107
- if (
108
- isset($wpcf_fields_entry_view_cache[$params['field']['id']])
109
- && isset($wpcf_fields_entry_view_cache[$params['field']['id']][$params['display']])
110
- ) {
111
- return $wpcf_fields_entry_view_cache[$params['field']['id']][$params['display']];
112
- }
113
- $post = get_post($params['field_value']);
114
- $data = wpcf_fields_entry_get_options();
115
- foreach( $data['options'] as $key => $field_data ) {
116
- if ( wpcf_fields_entry_check_is_available( $post->post_type, $field_data ) ) {
117
- $value = '__wpcf_skip_empty';
118
- switch( $key ) {
119
- case 'post-title':
120
- $value = apply_filters('post_title', $post->post_title);
121
- break;
122
- case 'post-link':
123
- $value = sprintf(
124
- '<a href="%s" title="%s">%s</a>',
125
- esc_attr(get_permalink($post)),
126
- esc_attr(apply_filters('post_title', $post->post_title)),
127
- apply_filters('post_title', $post->post_title)
128
- );
129
- break;
130
- case 'post-url':
131
- $value = get_permalink($post);
132
- break;
133
- case 'post-body':
134
- $value = apply_filters('the_content', $post->post_content);
135
- break;
136
- case 'post-excerpt':
137
- $value = apply_filters('the_excerpt', $post->post_excerpt);
138
- break;
139
- case 'post-date':
140
- $value = get_the_date(null, $post->ID);
141
- break;
142
- case 'post-author':
143
- $value = get_the_author_meta('display_name', $post->author_id);
144
- break;
145
- case 'post-featured-image':
146
- $value = get_the_post_thumbnail($post->ID);
147
- break;
148
- case 'post-slug':
149
- $value = $post->post_name;
150
- break;
151
- case 'post-type':
152
- $value = $post->post_type;
153
- break;
154
- case 'post-status':
155
- $value = $post->post_status;
156
- break;
157
- case 'post-class':
158
- $value = implode(' ', get_post_class('', $post->ID));
159
- break;
160
- case 'post-edit-link':
161
- $value = get_edit_post_link($post->ID);
162
- break;
163
- default:
164
- $value = $key;
165
- }
166
- $wpcf_fields_entry_view_cache[$params['field_value']][$key] = $value;
167
- } else {
168
- d(array($post->post_type, $key, $field_data));
169
- $wpcf_fields_entry_view_cache[$params['field_value']][$key] = '__wpcf_skip_empty';
170
- }
171
- }
172
- return $wpcf_fields_entry_view_cache[$params['field_value']][$params['display']];
173
- }
174
-
175
- function wpcf_fields_entry_check_is_available($post_type, $field)
176
- {
177
- /**
178
- * remove some option if certain post type do not supports it
179
- */
180
- if( isset( $field['support_field'] ) ) {
181
- if ( !post_type_supports( $post_type, $field['support_field'])) {
182
- return false;
183
- }
184
- }
185
- /**
186
- * remove some option if certain post type definition not match
187
- */
188
- if( isset( $field['post_type'] ) ) {
189
- $post_type = get_post_type_object($post_type);
190
- if (
191
- !isset($post_type->$field['post_type'])
192
- || empty($post_type->$field['post_type'])
193
- ) {
194
- return false;
195
- }
196
- }
197
- return true;
198
- }
199
-
200
- function wpcf_fields_entry_get_options()
201
- {
202
- return array(
203
- 'options' => array(
204
- 'post-title' => array(
205
- 'support_field' => 'title',
206
- 'label' => __('Post title', 'wpcf'),
207
- ),
208
- 'post-link' => array(
209
- 'support_field' => 'title',
210
- 'post_type' => 'public',
211
- 'label' => __('Post title with a link', 'wpcf'),
212
- ),
213
- 'post-url' => array(
214
- 'post_type' => 'public',
215
- 'label' => __('Post URL', 'wpcf'),
216
- ),
217
- 'post-body' => array(
218
- 'support_field' => 'editor',
219
- 'label' => __('Post body', 'wpcf'),
220
- ),
221
- 'post-excerpt' => array(
222
- 'support_field' => 'excerpt',
223
- 'label' => __('Post excerpt', 'wpcf'),
224
- ),
225
- 'post-date' => array(
226
- 'label' => __('Post date', 'wpcf'),
227
- ),
228
- 'post-author' => array(
229
- 'support_field' => 'author',
230
- 'label' => __('Post author', 'wpcf'),
231
- ),
232
- 'post-featured-image' => array(
233
- 'support_field' => 'thumbnail',
234
- 'label' => __('Post featured image', 'wpcf'),
235
- ),
236
- 'post-id' => array(
237
- 'label' => __('Post ID', 'wpcf'),
238
- ),
239
- 'post-slug' => array(
240
- 'label' => __('Post slug', 'wpcf'),
241
- ),
242
- 'post-type' => array(
243
- 'label' => __('Post type', 'wpcf'),
244
- ),
245
- 'post-format' => array(
246
- 'support_field' => 'post-formats',
247
- 'label' => __('Post format', 'wpcf'),
248
- ),
249
- 'post-status' => array(
250
- 'label' => __('Post status', 'wpcf'),
251
- ),
252
- 'post-comments-number' => array(
253
- 'support_field' => 'comments',
254
- 'label' => __('Post comments number', 'wpcf'),
255
- ),
256
- 'post-class' => array(
257
- 'label' => __('Post class', 'wpcf'),
258
- ),
259
- 'post-edit-link' => array(
260
- 'label' => __('Post edit link', 'wpcf'),
261
- ),
262
- ),
263
- 'default' => 'post-title',
264
- );
265
- }
266
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/fields/file.php DELETED
@@ -1,248 +0,0 @@
1
- <?php
2
- /*
3
- *
4
- *
5
- */
6
- /**
7
- * Register data (called automatically).
8
- *
9
- * @return type
10
- */
11
- function wpcf_fields_file() {
12
- return array(
13
- 'id' => 'wpcf-file',
14
- 'title' => __( 'File', 'wpcf' ),
15
- 'description' => __( 'File', 'wpcf' ),
16
- 'validate' => array(
17
- 'required' => array(
18
- 'form-settings' => include( dirname( __FILE__ ) . '/patterns/validate/form-settings/required.php' )
19
- )
20
- ),
21
- 'font-awesome' => 'file',
22
- );
23
- }
24
-
25
- /**
26
- * Form data for post edit page.
27
- *
28
- * @global object $wpdb
29
- *
30
- * @param type $field
31
- */
32
- function wpcf_fields_file_meta_box_form( $field ) {
33
- add_thickbox();
34
- $button_text = sprintf( __( 'Select %s', 'wpcf' ), $field['type'] );
35
- // Set ID
36
- $element_id = 'wpcf-fields-' . wpcf_unique_id( serialize( func_get_args() ) );
37
- $attachment_id = false;
38
-
39
- // Get attachment by guid
40
- global $wpdb;
41
- if ( !empty( $field['value'] ) ) {
42
- $attachment_id = $wpdb->get_var(
43
- $wpdb->prepare(
44
- "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND guid=%s",
45
- $field['value']
46
- )
47
- );
48
- }
49
-
50
- // Set preview
51
- $preview = '';
52
- // TODO WPML move
53
- if ( !wpcf_wpml_field_is_copied( $field ) ) {
54
- if ( !empty( $attachment_id ) ) {
55
- $preview = wp_get_attachment_image( $attachment_id, 'thumbnail' );
56
- } else {
57
- // If external image set preview
58
- $file_path = parse_url( $field['value'] );
59
- if ( $file_path && isset( $file_path['path'] ) )
60
- $file = pathinfo( $file_path['path'] );
61
- else
62
- $file = pathinfo( $field['value'] );
63
- if ( isset( $file['extension'] )
64
- && in_array( strtolower( $file['extension'] ),
65
- array('jpg', 'jpeg', 'gif', 'png') ) ) {
66
- $preview = '<img alt="" src="' . $field['value'] . '" />';
67
- }
68
- }
69
- }
70
-
71
- // Set button
72
- // TODO WPML move
73
- if ( !wpcf_wpml_field_is_copied( $field ) ) {
74
- if ( !empty( $field['#attributes']['readonly'] ) || !empty( $field['#attributes']['disabled'] ) ) {
75
- $button = '';
76
- } else {
77
- $button = '<a href="javascript:void(0);"'
78
- . ' class="wpcf-fields-'
79
- . ( $field['type'] == 'image' ? 'image' : 'file' )
80
- . '-upload-link button-secondary"'
81
- . ' id="' . $element_id . '-upload" '
82
- . "data-types='{\"type\":\"{$field['type']}\",\"id\":\"{$field['id']}\"}'>"
83
- . $button_text . '</a>';
84
- }
85
- } else {
86
- $button = '';
87
- }
88
-
89
- // Set form
90
- $form = array(
91
- '#type' => 'textfield',
92
- '#id' => $element_id . '-upload-holder',
93
- '#name' => 'wpcf[' . $field['slug'] . ']',
94
- '#suffix' => '&nbsp;' . $button,
95
- '#after' => '<div id="' . $element_id
96
- . '-upload-holder-preview"'
97
- . ' class="wpcf-fields-file-preview">' . $preview . '</div>',
98
- '#attributes' => array('class' => 'wpcf-fields-file-textfield'),
99
- );
100
-
101
- return $form;
102
- }
103
-
104
- /**
105
- * Adds 'Types' column to media item table.
106
- *
107
- * @param type $form_fields
108
- * @param type $post
109
- * @return type
110
- */
111
- function wpcf_fields_file_attachment_fields_to_edit_filter( $form_fields, $post ) {
112
- // Reset form
113
- $form_fields = array();
114
- $type = (strpos( $post->post_mime_type, 'image/' ) !== false) ? 'image' : 'file';
115
- /*
116
- * Since Types 1.3.2 we use wp_get_attachment_url()
117
- * See
118
- * /wp-includes/post.php
119
- * wp_get_attachment_url()
120
- * line #4228
121
- * If any of the above options failed, Fallback on the GUID as used pre-2.7,
122
- * not recommended to rely upon this.
123
- */
124
- // $url = $post->guid;
125
- $url = wp_get_attachment_url( $post->ID );
126
- $form_fields['wpcf_fields_file'] = array(
127
- 'label' => __( 'Types', 'wpcf' ),
128
- 'input' => 'html',
129
- 'html' => '<a href="#" title="' . $url
130
- . '" class="wpcf-fields-file-insert-button'
131
- . ' button-primary" onclick="wpcfFieldsFileMediaTrigger(\''
132
- . $url . '\', \'' . $type . '\')">'
133
- . __( 'Use as field value', 'wpcf' ) . '</a><br /><br />',
134
- );
135
- return $form_fields;
136
- }
137
-
138
- /**
139
- * View function.
140
- *
141
- * @param type $params
142
- */
143
- function wpcf_fields_file_view( $params ) {
144
- $output = '';
145
- if ( isset( $params['link'] ) && $params['link'] == 'true' ) {
146
- $title = '';
147
- $add = '';
148
- if ( !empty( $params['title'] ) ) {
149
- $add .= ' title="' . $params['title'] . '"';
150
- $title .= $params['title'];
151
- } else {
152
- $add .= ' title="' . $params['field_value'] . '"';
153
- $title .= $params['field_value'];
154
- }
155
- if ( !empty( $params['class'] ) ) {
156
- $add .= ' class="' . $params['class'] . '"';
157
- }
158
- if ( !empty( $params['style'] ) ) {
159
- $add .= ' style="' . $params['style'] . '"';
160
- }
161
- $output = '<a href="' . $params['field_value'] . '"' . $add . '>'
162
- . $title . '</a>';
163
- } else {
164
- $output = $params['field_value'];
165
- }
166
-
167
- return $output;
168
- }
169
-
170
- /**
171
- * Editor callback form.
172
- *
173
- * @global object $wpdb
174
- *
175
- */
176
- function wpcf_fields_file_editor_callback( $field, $data, $meta_type, $post ) {
177
-
178
- // Get attachment
179
- $attachment_id = false;
180
- if ( !empty( $post->ID ) ) {
181
- $file = get_post_meta( $post->ID,
182
- wpcf_types_get_meta_prefix( $field ) . $field['slug'], true );
183
- if ( empty( $file ) ) {
184
- $user_id = wpcf_usermeta_get_user();
185
- $file = get_user_meta( $user_id,
186
- wpcf_types_get_meta_prefix( $field ) . $field['slug'], true );
187
- }
188
- if ( !empty( $file ) ) {
189
- // Get attachment by guid
190
- global $wpdb;
191
- $attachment_id = $wpdb->get_var(
192
- $wpdb->prepare(
193
- "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND guid=%s",
194
- $file
195
- )
196
- );
197
- }
198
- }
199
-
200
- // Set data
201
- $data['attachment_id'] = $attachment_id;
202
- $data['file'] = !empty($file) ? $file : '';
203
-
204
- return array(
205
- 'supports' => array('styling', 'style'),
206
- 'tabs' => array(
207
- 'display' => array(
208
- 'menu_title' => __( 'Display options', 'wpcf' ),
209
- 'title' => __( 'Display options for this field:', 'wpcf' ),
210
- 'content' => WPCF_Loader::template( 'editor-modal-file', $data ),
211
- )
212
- ),
213
- 'settings' => $data,
214
- );
215
- }
216
-
217
- /**
218
- * Editor callback form submit.
219
- */
220
- function wpcf_fields_file_editor_submit( $data, $field, $context ) {
221
- $add = '';
222
- $add .= ' link="true"';
223
- if ( !empty( $data['title'] ) ) {
224
- $add .= ' title="' . strval( $data['title'] ) . '"';
225
- }
226
- if ( $context == 'usermeta' ) {
227
- $add .= wpcf_get_usermeta_form_addon_submit();
228
- $shortcode = wpcf_usermeta_get_shortcode( $field, $add );
229
- } elseif ( $context == 'termmeta' ) {
230
- $add .= wpcf_get_termmeta_form_addon_submit();
231
- $shortcode = wpcf_termmeta_get_shortcode( $field, $add );
232
- } else {
233
- $shortcode = wpcf_fields_get_shortcode( $field, $add );
234
- }
235
-
236
- return $shortcode;
237
- }
238
-
239
- /**
240
- * Filters media TABs.
241
- *
242
- * @param type $tabs
243
- * @return type
244
- */
245
- function wpcf_fields_file_media_upload_tabs_filter( $tabs ) {
246
- unset( $tabs['type_url'] );
247
- return $tabs;
248
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/fields/image.php DELETED
@@ -1,1087 +0,0 @@
1
- <?php
2
- /**
3
- * Register data (called automatically).
4
- * @return type
5
- */
6
- function wpcf_fields_image() {
7
- return array(
8
- 'id' => 'wpcf-image',
9
- 'title' => __( 'Image', 'wpcf' ),
10
- 'description' => __( 'Image', 'wpcf' ),
11
- 'validate' => array(
12
- 'required' => array(
13
- 'form-settings' => include( dirname( __FILE__ ) . '/patterns/validate/form-settings/required.php' )
14
- )
15
- ),
16
- 'inherited_field_type' => 'file',
17
- 'font-awesome' => 'picture-o',
18
- );
19
- }
20
-
21
- /**
22
- *
23
- *
24
- */
25
-
26
- add_filter( 'wpcf_fields_type_image_value_get', 'wpcf_fields_image_value_filter' );
27
- add_filter( 'wpcf_fields_type_image_value_save', 'wpcf_fields_image_value_filter' );
28
-
29
- // Do not wrap if 'url' is TRUE
30
- add_filter( 'types_view', 'wpcf_fields_image_view_filter', 10, 6 );
31
-
32
- /**
33
- * return array of valid extensions
34
- *
35
- * @since 1.8
36
- *
37
- * @return array
38
- */
39
- function wpcf_fields_image_valid_extension()
40
- {
41
- return array(
42
- 'bmp',
43
- 'gif',
44
- 'ico',
45
- 'jpeg',
46
- 'jpg',
47
- 'png',
48
- 'svg',
49
- 'webp',
50
- );
51
- }
52
-
53
- /**
54
- * Editor callback form.
55
- *
56
- * @global object $wpdb
57
- *
58
- */
59
- function wpcf_fields_image_editor_callback( $field, $data, $context, $post ) {
60
-
61
- // Get post_ID
62
- $post_ID = !empty( $post->ID ) ? $post->ID : false;
63
-
64
- // Get attachment
65
- $image = false;
66
- $attachment_id = false;
67
- if ( $post_ID ) {
68
- $image = get_post_meta( $post_ID,
69
- wpcf_types_get_meta_prefix( $field ) . $field['slug'], true );
70
- if ( empty( $image ) ) {
71
- $user_id = wpcf_usermeta_get_user();
72
- $image = get_user_meta( $user_id,
73
- wpcf_types_get_meta_prefix( $field ) . $field['slug'], true );
74
- }
75
- if ( !empty( $image ) ) {
76
- // Get attachment by guid
77
- global $wpdb;
78
- $attachment_id = $wpdb->get_var(
79
- $wpdb->prepare(
80
- "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND guid=%s",
81
- $image
82
- )
83
- );
84
- }
85
- }
86
- $data['image'] = $image;
87
- $data['attachment_id'] = $attachment_id;
88
-
89
- // Set post type
90
- $post_type = !empty( $post->post_type ) ? $post->post_type : '';
91
-
92
- // Set image_data
93
- $image_data = wpcf_fields_image_get_data( $image );
94
- if ( !in_array( $post_type, array('view', 'view-template') ) ) {
95
- // We must ignore errors here and treat image as outsider
96
- if ( !empty( $image_data['error'] ) ) {
97
- $image_data['is_outsider'] = 1;
98
- $image_data['is_attachment'] = 0;
99
- }
100
- } else {
101
- if ( !empty( $image_data['error'] ) ) {
102
- $image_data['is_outsider'] = 0;
103
- $image_data['is_attachment'] = 0;
104
- }
105
- }
106
-
107
- $data['preview'] = $attachment_id ? wp_get_attachment_image( $attachment_id,
108
- 'thumbnail' ) : '';
109
-
110
- // Title and Alt
111
- if ( $attachment_id ) {
112
- $alt = trim( strip_tags( get_post_meta( $attachment_id,
113
- '_wp_attachment_image_alt', true ) ) );
114
- $attachment_post = get_post( $attachment_id );
115
- if ( !empty( $attachment_post ) ) {
116
- $title = trim( strip_tags( $attachment_post->post_title ) );
117
- } else if ( !empty( $alt ) ) {
118
- $title = $alt;
119
- }
120
- if ( empty( $alt ) ) {
121
- $alt = $title;
122
- }
123
- if ( !isset( $data['title'] ) ) {
124
- $data['title'] = $title;
125
- }
126
- if ( !isset( $data['alt'] ) ) {
127
- $data['alt'] = $alt;
128
- }
129
- }
130
-
131
- // Align options
132
- $data['alignment_options'] = array(
133
- 'none' => __( 'None', 'wpcf' ),
134
- 'left' => __( 'Left', 'wpcf' ),
135
- 'center' => __( 'Center', 'wpcf' ),
136
- 'right' => __( 'Right', 'wpcf' ),
137
- );
138
-
139
- // Remote images settings
140
- $fetch_remote = (bool) wpcf_get_settings( 'images_remote' );
141
- $data['warning_remote'] = false;
142
- if ( !types_is_repetitive( $field )
143
- && $image_data['is_outsider'] && !$fetch_remote && !empty( $data['image'] ) ) {
144
- $data['warning_remote'] = true;
145
- }
146
-
147
- // Size settings
148
- $data['size_options'] = array(
149
- 'thumbnail' => sprintf( __( 'Thumbnail - %s', 'wpcf' ),
150
- get_option( 'thumbnail_size_w' ) . 'x' . get_option( 'thumbnail_size_h' ) ),
151
- 'medium' => sprintf( __( 'Medium - %s', 'wpcf' ),
152
- get_option( 'medium_size_w' ) . 'x' . get_option( 'medium_size_h' ) ),
153
- 'large' => sprintf( __( 'Large - %s', 'wpcf' ),
154
- get_option( 'large_size_w' ) . 'x' . get_option( 'large_size_h' ) ),
155
- 'full' => __( 'Original image', 'wpcf' ),
156
- );
157
- $wp_image_sizes = (array) get_intermediate_image_sizes();
158
- foreach ( $wp_image_sizes as $wp_size ) {
159
- if ( $wp_size != 'post-thumbnail'
160
- && !array_key_exists( $wp_size, $data['size_options'] ) ) {
161
- $data['size_options'][$wp_size] = $wp_size;
162
- }
163
- }
164
- $data['size_options']['wpcf-custom'] = __( 'Custom size...', 'wpcf' );
165
-
166
- // Get saved settings
167
- $data = array_merge( wpcf_admin_fields_get_field_last_settings( $field['id'] ),
168
- $data );
169
-
170
- return array(
171
- 'supports' => array('styling', 'style'),
172
- 'tabs' => array(
173
- 'display' => array(
174
- 'menu_title' => __( 'Display options', 'wpcf' ),
175
- 'title' => __( 'Display options for this field:', 'wpcf' ),
176
- 'content' => WPCF_Loader::template( 'editor-modal-image', $data ),
177
- )
178
- ),
179
- 'settings' => $data,
180
- );
181
- }
182
-
183
- /**
184
- * Editor callback form submit.
185
- */
186
- function wpcf_fields_image_editor_submit( $data, $field, $context ) {
187
-
188
- // Saved settings
189
- $settings = array();
190
-
191
- $add = '';
192
- if ( !empty( $data['alt'] ) ) {
193
- $add .= ' alt="' . strval( $data['alt'] ) . '"';
194
- }
195
- if ( !empty( $data['title'] ) ) {
196
- $add .= ' title="' . strval( $data['title'] ) . '"';
197
- }
198
- $size = !empty( $data['image_size'] ) ? $data['image_size'] : false;
199
- if ( $size == 'wpcf-custom' ) {
200
- if ( !empty( $data['width'] ) ) {
201
- $add .= ' width="' . intval( $data['width'] ) . '"';
202
- }
203
- if ( !empty( $data['height'] ) ) {
204
- $add .= ' height="' . intval( $data['height'] ) . '"';
205
- }
206
- } else if ( !empty( $size ) ) {
207
- $add .= ' size="' . $size . '"';
208
- $settings['image_size'] = $size;
209
- }
210
- if ( !empty( $data['alignment'] ) ) {
211
- $add .= ' align="' . $data['alignment'] . '"';
212
- $settings['alignment'] = $data['alignment'];
213
- }
214
- if ( !empty( $data['url'] ) ) {
215
- $add .= ' url="true"';
216
- }
217
- if ( !empty( $data['onload'] ) ) {
218
- $add .= ' onload="' . $data['onload'] . '"';
219
- }
220
-
221
- if ( array_key_exists('image_size', $data) && $data['image_size'] != 'full' ) {
222
- if ( !empty( $data['proportional'] ) ) {
223
- $settings['resize'] = isset( $data['resize'] ) ? $data['resize'] : 'proportional';
224
- $add .= " resize=\"{$settings['resize']}\"";
225
- if ( $settings['resize'] == 'pad' ) {
226
- if ( isset( $data['padding_transparent'] ) ) {
227
- $data['padding_color'] = 'transparent';
228
- }
229
- if ( empty( $data['padding_color'] ) ) {
230
- $data['padding_color'] = '#FFF';
231
- }
232
- if ( ( strpos( $data['padding_color'], '#' ) !== 0 || !( strlen( $data['padding_color'] ) == 4 || strlen( $data['padding_color'] ) == 7 ) ) && $data['padding_color'] != 'transparent' ) {
233
- $data['padding_color'] = '#FFF';
234
- }
235
- $settings['padding_color'] = $data['padding_color'];
236
- $add .= " padding_color=\"{$data['padding_color']}\"";
237
- }
238
- } else if ( !isset( $data['raw_mode'] ) ) {
239
- $settings['resize'] = 'stretch';
240
- $add .= ' resize="stretch"';
241
- }
242
- }
243
-
244
- $field = apply_filters( 'wpcf_fields_image_editor_submit_field', $field );
245
-
246
- // Save settings
247
- wpcf_admin_fields_save_field_last_settings( $field['id'], $settings );
248
-
249
- if ( $context == 'usermeta' ) {
250
- $add .= wpcf_get_usermeta_form_addon_submit();
251
- $shortcode = wpcf_usermeta_get_shortcode( $field, $add );
252
- } elseif ( $context == 'termmeta' ) {
253
- $add .= wpcf_get_termmeta_form_addon_submit();
254
- $shortcode = wpcf_termmeta_get_shortcode( $field, $add );
255
- } else {
256
- $shortcode = wpcf_fields_get_shortcode( $field, $add );
257
- }
258
-
259
- return $shortcode;
260
- }
261
-
262
- /**
263
- * View function.
264
- *
265
- * @param type $params
266
- */
267
- function wpcf_fields_image_view( $params ) {
268
-
269
- global $wpcf;
270
-
271
- $output = '';
272
- $alt = false;
273
- $title = false;
274
- $class = array();
275
- $style = array();
276
-
277
- // Get image data
278
- $image_data = wpcf_fields_image_get_data( $params['field_value'] );
279
-
280
- // Error
281
- if ( !empty( $image_data['error'] ) ) {
282
- return '__wpcf_skip_empty';
283
- }
284
-
285
- // Set alt
286
- if ( isset( $params['alt'] ) ) {
287
- $alt = $params['alt'];
288
- }
289
-
290
- // Set title
291
- if ( isset( $params['title'] ) ) {
292
- $title = $params['title'];
293
- }
294
-
295
- // Set attachment class
296
- if ( !empty( $params['size'] ) ) {
297
- $class[] = 'attachment-' . $params['size'];
298
- }
299
-
300
- // Set align class
301
- if ( !empty( $params['align'] ) && $params['align'] != 'none' ) {
302
- $class[] = 'align' . $params['align'];
303
- }
304
-
305
- if ( !empty( $params['class'] ) ) {
306
- $class[] = $params['class'];
307
- }
308
- if ( !empty( $params['style'] ) ) {
309
- $style[] = $params['style'];
310
- }
311
-
312
- // Compatibility with old parameters
313
- $old_param = isset( $params['proportional'] ) && $params['proportional'] == 'true' ? 'proportional' : 'crop';
314
- $resize = isset( $params['resize'] ) ? $params['resize'] : $old_param;
315
-
316
- // Pre-configured size (use WP function) IF NOT CROPPED
317
- if ( $resize == 'crop' && $image_data['is_attachment'] && !empty( $params['size'] ) ) {
318
- //print_r('is_attachment');
319
- if ( isset( $params['url'] ) && $params['url'] == 'true' ) {
320
- //print_r('is_url');
321
- $image_url = wp_get_attachment_image_src( $image_data['is_attachment'], $params['size'] );
322
- if ( !empty( $image_url[0] ) ) {
323
- $output = $image_url[0];
324
- } else {
325
- $output = $params['field_value'];
326
- }
327
-
328
- // TODO This is current fix, should be re-designed
329
- $wpcf->__images_wrap_fix[md5( serialize( $params ) )] = $output;
330
- } else {
331
- //print_r('is_not_url');
332
- $output = wp_get_attachment_image( $image_data['is_attachment'],
333
- $params['size'], false,
334
- array(
335
- 'class' => implode( ' ', $class ),
336
- 'style' => implode( ' ', $style ),
337
- 'alt' => $alt,
338
- 'title' => $title
339
- )
340
- );
341
- }
342
- } else { // Custom size
343
- //print_r('custom_size');
344
- $width = !empty( $params['width'] ) ? intval( $params['width'] ) : null;
345
- $height = !empty( $params['height'] ) ? intval( $params['height'] ) : null;
346
-
347
- //////////////////////////
348
- // If width and height are not set then check the size parameter.
349
- // This handles the case when the image is not an attachment.
350
- if ( empty( $width ) && empty( $height ) && !empty( $params['size'] ) ) {
351
- //print_r('no_width_no_height_and_size');
352
- switch ( $params['size'] ) {
353
- case 'thumbnail':
354
- $width = get_option( 'thumbnail_size_w' );
355
- $height = get_option( 'thumbnail_size_h' );
356
- if ( empty( $params['proportional'] ) ) {
357
- $crop = get_option( 'thumbnail_crop' );
358
- }
359
- break;
360
-
361
- case 'medium':
362
- $width = get_option( 'medium_size_w' );
363
- $height = get_option( 'medium_size_h' );
364
- break;
365
-
366
- case 'large':
367
- $width = get_option( 'large_size_w' );
368
- $height = get_option( 'large_size_h' );
369
- break;
370
-
371
- default:
372
- global $_wp_additional_image_sizes;
373
- if ( isset( $_wp_additional_image_sizes[$params['size']] )
374
- && is_array( $_wp_additional_image_sizes[$params['size']] ) ) {
375
- extract( $_wp_additional_image_sizes[$params['size']] );
376
- }
377
- }
378
- }
379
-
380
-
381
- // Check if image is outsider and require $width and $height
382
- if ( (!empty( $width ) || !empty( $height )) && !$image_data['is_outsider'] ) {
383
-
384
- // Resize args
385
- $args = array(
386
- 'resize' => $resize,
387
- 'padding_color' => isset( $params['padding_color'] ) ? $params['padding_color'] : '#FFF',
388
- 'width' => $width,
389
- 'height' => $height,
390
- 'return' => 'object',
391
- 'suppress_errors' => false,
392
- 'clear_cache' => false,
393
- );
394
- WPCF_Loader::loadView( 'image' );
395
- $__resized_image = types_image_resize( $image_data['fullabspath'],
396
- $args );
397
-
398
- if ( is_wp_error( $__resized_image ) ) {
399
- $resized_image = $params['field_value'];
400
- } else {
401
- $resized_image = $__resized_image->url;
402
- $image_abspath = $__resized_image->path;
403
- if ( wpcf_get_settings( 'add_resized_images_to_library' )
404
- && !wpcf_image_is_attachment( $__resized_image->url )
405
- && $image_data['is_in_upload_path'] ) {
406
- global $post;
407
- wpcf_image_add_to_library( $post, $image_abspath );
408
- }
409
- }
410
- } else {
411
- $resized_image = $params['field_value'];
412
- }
413
- if ( isset( $params['url'] ) && $params['url'] == 'true' ) {
414
- // TODO This is current fix, should be re-designed
415
- $wpcf->__images_wrap_fix[md5( serialize( $params ) )] = $resized_image;
416
-
417
- return $resized_image;
418
- }
419
-
420
- $output = sprintf( '<img alt="%s" ', $output .= $alt !== false ? esc_attr($alt) : '');
421
- if ( $title !== false ) {
422
- $output .= sprintf(' title="%s"', esc_attr($title));
423
- }
424
- $output .=!empty( $params['onload'] ) ? ' onload="' . esc_attr($params['onload']) . '"' : '';
425
- $output .=!empty( $class ) ? ' class="' . esc_attr(implode( ' ', $class )) . '"' : '';
426
- $output .=!empty( $style ) ? ' style="' . esc_attr(implode( ' ', $style )) . '"' : '';
427
- $output .= sprintf(' src="%s" />', esc_attr($resized_image));
428
- }
429
-
430
- return $output;
431
- }
432
-
433
- /**
434
- * Resizes image using WP image_resize() function.
435
- *
436
- * Caches return data if called more than one time in one pass.
437
- *
438
- * @staticvar array $cached Caches calls in one pass
439
- * @param <type> $url_path Full URL path (works only with images on same domain)
440
- * @param <type> $width
441
- * @param <type> $height
442
- * @param <type> $refresh Set to true if you want image re-created or not cached
443
- * @param <type> $crop Set to true if you want apspect ratio to be preserved
444
- * @param string $suffix Optional (default 'wpcf_$widthxheight)
445
- * @param <type> $dest_path Optional (defaults to original image)
446
- * @param <type> $quality
447
- * @return array
448
- */
449
- function wpcf_fields_image_resize_image( $url_path, $width = 300, $height = 200,
450
- $return = 'relpath', $refresh = FALSE, $crop = TRUE, $suffix = '',
451
- $dest_path = NULL, $quality = 75 ) {
452
-
453
- if ( empty( $url_path ) ) {
454
- //print_r('return url path');
455
- return $url_path;
456
- }
457
-
458
- // Get image data
459
- $image_data = wpcf_fields_image_get_data( $url_path );
460
-
461
- if ( empty( $image_data['fullabspath'] ) || !empty( $image_data['error'] ) ) {
462
- //print_r('return url path no full or error');
463
- return $url_path;
464
- }
465
-
466
- // Set cache
467
- static $cached = array();
468
- $cache_key = md5( $url_path . $width . $height . intval( $crop ) . $suffix . $dest_path );
469
-
470
- // Check if cached in this call
471
- if ( !$refresh && isset( $cached[$cache_key][$return] ) ) {
472
- //print_r('return cached');
473
- return $cached[$cache_key][$return];
474
- }
475
-
476
- $width = intval( $width );
477
- $height = intval( $height );
478
-
479
- // Get size of new file
480
- $size = @getimagesize( $image_data['fullabspath'] );
481
- if ( !$size ) {
482
- //print_r('not size');
483
- return $url_path;
484
- }
485
- list($orig_w, $orig_h, $orig_type) = $size;
486
- $dims = image_resize_dimensions( $orig_w, $orig_h, $width, $height, $crop );
487
- if ( !$dims ) {
488
- //print_r('not dims');
489
- return $url_path;
490
- }
491
- list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $dims;
492
-
493
- // Set suffix
494
- if ( empty( $suffix ) ) {
495
- $suffix = 'wpcf_' . $dst_w . 'x' . $dst_h;
496
- } else {
497
- $suffix .= '_wpcf_' . $dst_w . 'x' . $dst_h;
498
- }
499
-
500
- $image_data['extension'] = in_array( strtolower( $image_data['extension'] ), wpcf_fields_image_valid_extension() ) ? $image_data['extension'] : 'jpg';
501
-
502
- $image_relpath = $image_data['relpath'] . '/' . $image_data['image_name'] . '-'
503
- . $suffix . '.' . $image_data['extension'];
504
- $image_abspath = $image_data['abspath'] . DIRECTORY_SEPARATOR
505
- . $image_data['image_name'] . '-' . $suffix . '.'
506
- . $image_data['extension'];
507
-
508
- // Check if already resized
509
- if ( !$refresh && file_exists( $image_abspath ) ) {
510
- //print_r('file exists');
511
- // Cache it
512
- $cached[$cache_key]['relpath'] = $image_relpath;
513
- $cached[$cache_key]['abspath'] = $image_abspath;
514
- return $return == 'relpath' ? $image_relpath : $image_abspath;
515
- }
516
-
517
- // If original file don't exists
518
- if ( !file_exists( $image_data['fullabspath'] ) ) {
519
- //print_r('not file exists');
520
- return $url_path;
521
- }
522
-
523
- // Resize image
524
- $resized_image = @wpcf_image_resize(
525
- $image_data['fullabspath'], $width, $height, $crop, $suffix,
526
- $dest_path, $quality
527
- );
528
-
529
- // Check if error
530
- if ( is_wp_error( $resized_image ) ) {
531
- //print_r('resized wp error');
532
- //print_r($resized_image);
533
- return $url_path;
534
- }
535
-
536
- $image_abspath = $resized_image;
537
-
538
- // Cache it
539
- $cached[$cache_key]['relpath'] = $image_relpath;
540
- $cached[$cache_key]['abspath'] = $image_abspath;
541
-
542
- return $return == 'relpath' ? $image_relpath : $image_abspath;
543
- }
544
-
545
- /**
546
- * Gets all necessary data for processed image.
547
- *
548
- * @param type $image
549
- * @return type
550
- */
551
- function wpcf_fields_image_get_data( $image ) {
552
-
553
- global $wpcf;
554
-
555
- // Check if already cached
556
- static $cache = array();
557
- $cache_key = md5( $image );
558
- if ( isset( $cache[$cache_key] ) ) {
559
- return $cache[$cache_key];
560
- }
561
-
562
- WPCF_Loader::loadView( 'image' );
563
- $utils = Types_Image_Utils::getInstance();
564
-
565
- // Defaults
566
- $data = array(
567
- 'image' => basename( $image ),
568
- 'image_name' => '',
569
- 'extension' => '',
570
- 'abspath' => '',
571
- 'relpath' => dirname( $image ),
572
- 'fullabspath' => '',
573
- 'fullrelpath' => $image,
574
- 'is_outsider' => 1,
575
- 'is_in_upload_path' => 0,
576
- 'is_attachment' => 0,
577
- 'error' => '',
578
- );
579
-
580
- // Strip GET vars
581
- if ( !apply_filters('wpcf_allow_questionmark_in_image_url', false) ) {
582
- $image = strtok( $image, '?' );
583
- }
584
-
585
- // Basic URL check
586
- if ( strpos( $image, 'http' ) != 0 ) {
587
- return array('error' => sprintf( __( 'Image %s not valid', 'wpcf' ),
588
- $image ));
589
- }
590
- // Extension check
591
- $data['extension'] = pathinfo( $image, PATHINFO_EXTENSION );
592
- if ( !in_array( strtolower( $data['extension'] ), wpcf_fields_image_valid_extension() ) ) {
593
- return array('error' => sprintf( __( 'Image %s not valid', 'wpcf' ), $image ));
594
- }
595
-
596
- // Check if it's on same domain
597
- $data['is_outsider'] = !$utils->onDomain($image);
598
-
599
- if ( empty($data['is_outsider']) ) {
600
- $data['is_in_upload_path'] = $utils->inUploadPath($image);
601
- $data['fullabspath'] = $utils->getAbsPath($image);
602
- $data['abspath'] = dirname( $data['fullabspath'] );
603
-
604
- // Check if it's attachment
605
- $data['is_attachment'] = wpcf_image_is_attachment( $image );
606
- }
607
-
608
- // DEbug
609
- $wpcf_debug = array(
610
- 'image' => $image,
611
- 'docroot' => $_SERVER['DOCUMENT_ROOT'],
612
- );
613
-
614
- // Set remote if enabled
615
- if ( $data['is_outsider'] && wpcf_get_settings( 'images_remote' ) ) {
616
- $remote = wpcf_fields_image_get_remote( $image );
617
-
618
- // DEbug
619
- $wpcf_debug['remote'] = $remote;
620
-
621
- if ( !is_wp_error( $remote ) ) {
622
- $data['is_outsider'] = 0;
623
- $data['is_in_upload_path'] = 1;
624
- $data['abspath'] = dirname( $remote['abspath'] );
625
- $data['fullabspath'] = $remote['abspath'];
626
- $data['image'] = basename($remote['relpath']);
627
- $data['relpath'] = dirname( $remote['relpath'] );
628
- $data['fullrelpath'] = $remote['relpath'];
629
- $data['remotely_fetched'] = true;
630
- }
631
- }
632
-
633
- // Set rest of data
634
- $data['image_name'] = basename( $data['image'], '.' . $data['extension'] );
635
- $abspath_realpath = realpath( $data['abspath'] );
636
- $data['abspath'] = $abspath_realpath ? $abspath_realpath : $data['abspath'];
637
- $fullabspath_realpath = realpath( $data['fullabspath'] );
638
- $data['fullabspath'] = $fullabspath_realpath ? $fullabspath_realpath : $data['fullabspath'];
639
-
640
- // Cache it
641
- $cache[$cache_key] = $data;
642
-
643
- // DEbug
644
- $wpcf_debug['data'] = $data;
645
- $wpcf->debug->images['processed'][md5( $image )] = $wpcf_debug;
646
-
647
- return $data;
648
- }
649
-
650
- /**
651
- * Strips GET vars from value.
652
- *
653
- * @param type $value
654
- * @return type
655
- */
656
- function wpcf_fields_image_value_filter( $value ) {
657
- if ( is_string( $value ) && !apply_filters('wpcf_allow_questionmark_in_image_url', false) ) {
658
- return strtok( $value, '?' );
659
- }
660
- return $value;
661
- }
662
-
663
- /**
664
- * Gets cache directory.
665
- *
666
- * @return \WP_Error
667
- */
668
- function wpcf_fields_image_get_cache_directory( $suppress_filters = false ) {
669
- WPCF_Loader::loadView( 'image' );
670
- $utils = Types_Image_Utils::getInstance();
671
- $cache_dir = $utils->getWritablePath();
672
- if ( is_wp_error( $cache_dir ) ) {
673
- return $cache_dir;
674
- }
675
- if ( !$suppress_filters ) {
676
- $cache_dir = apply_filters( 'types_image_cache_dir', $cache_dir );
677
- if ( !wp_mkdir_p( $cache_dir ) ) {
678
- return new WP_Error(
679
- 'wpcf_image_cache_dir',
680
- sprintf(
681
- __( 'Image cache directory %s could not be created', 'wpcf' ),
682
- '<strong>' . $cache_dir . '</strong>'
683
- )
684
- );
685
- }
686
- }
687
- return $cache_dir;
688
- }
689
-
690
- function wpcf_image_http_request_timeout( $timeout ) {
691
- return 20;
692
- }
693
-
694
- /**
695
- * Fetches remote images.
696
- *
697
- * @param type $url
698
- * @return \WP_Error
699
- */
700
- function wpcf_fields_image_get_remote( $url ) {
701
-
702
- global $wpcf;
703
-
704
- $refresh = false;
705
-
706
- // Set directory
707
- $cache_dir = wpcf_fields_image_get_cache_directory();
708
- if ( is_wp_error( $cache_dir ) ) {
709
- return $cache_dir;
710
- }
711
-
712
- // Validate image
713
- $extension = pathinfo( $url, PATHINFO_EXTENSION );
714
- if ( !in_array( strtolower( $extension ), wpcf_fields_image_valid_extension() ) ) {
715
- return new WP_Error( 'wpcf_image_cache_not_valid', sprintf( __( 'Image %s not valid', 'wpcf' ), $url ) );
716
- }
717
-
718
- $image = $cache_dir . md5( $url ) . '.' . $extension;
719
-
720
- // Refresh if necessary
721
- $refresh_time = intval( wpcf_get_settings( 'images_remote_cache_time' ) );
722
- if ( $refresh_time != 0 && file_exists( $image ) ) {
723
- $time_modified = filemtime( $image );
724
- if ( time() - $time_modified > $refresh_time * 60 * 60 ) {
725
- $refresh = true;
726
- $files = glob( $cache_dir . DIRECTORY_SEPARATOR . md5( $url ) . "-*" );
727
- if ( $files ) {
728
- foreach ( $files as $filename ) {
729
- @unlink( $filename );
730
- }
731
- }
732
- }
733
- }
734
-
735
- // Check if image is fetched
736
- if ( $refresh || !file_exists( $image ) ) {
737
-
738
- // fetch the remote url and write it to the placeholder file
739
- add_filter( 'http_request_timeout', 'wpcf_image_http_request_timeout',
740
- 10, 1 );
741
- $resp = wp_safe_remote_get( $url );
742
-
743
- // Check if response type is expected
744
- if ( is_object( $resp ) ) {
745
- return new WP_Error(
746
- 'wpcf_image_cache_file_error',
747
- sprintf( __( 'Remote server returned error response %1$d %2$s', 'wpcf' ),
748
- esc_html( $resp->errors["http_request_failed"][0] ),
749
- get_status_header_desc( $resp->errors["http_request_failed"][0] )
750
- )
751
- );
752
- }
753
-
754
- remove_filter( 'http_request_timeout',
755
- 'wpcf_image_http_request_timeout', 10, 1 );
756
- // make sure the fetch was successful
757
- if ( $resp['response']['code'] != '200' ) {
758
- return new WP_Error( 'wpcf_image_cache_file_error',
759
- sprintf(
760
- __( 'Remote server returned error response %1$d %2$s', 'wpcf' ),
761
- esc_html( $resp['response'] ),
762
- get_status_header_desc( $resp['response'] )
763
- )
764
- );
765
- }
766
- if ( !isset( $resp['headers']['content-length'] )
767
- || strlen( $resp['body'] ) != $resp['headers']['content-length'] ) {
768
- return new WP_Error( 'wpcf_image_cache_file_error', __( 'Remote file is incorrect size', 'wpcf' ) );
769
- }
770
-
771
- $out_fp = fopen( $image, 'w' );
772
- if ( !$out_fp ) {
773
- return new WP_Error( 'wpcf_image_cache_file_error', __( 'Could not create cache file', 'wpcf' ) );
774
- }
775
-
776
- fwrite( $out_fp, $resp['body'] );
777
- fclose( $out_fp );
778
-
779
- $max_size = (int) apply_filters( 'import_attachment_size_limit', 0 );
780
- $filesize = filesize( $image );
781
- if ( !empty( $max_size ) && $filesize > $max_size ) {
782
- @unlink( $image );
783
- return new WP_Error( 'wpcf_image_cache_file_error', sprintf( __( 'Remote file is too large, limit is %s', 'wpcf' ), size_format( $max_size ) ) );
784
- }
785
- }
786
-
787
- return array(
788
- 'abspath' => $image,
789
- 'relpath' => wpcf_image_attachment_url( $image ),
790
- );
791
- }
792
-
793
- /**
794
- * Clears remote image cache.
795
- *
796
- * @param type $action
797
- */
798
- function wpcf_fields_image_clear_cache( $cache_dir = null, $action = 'outdated' ) {
799
- if ( is_null( $cache_dir ) ) {
800
- $cache_dir = wpcf_fields_image_get_cache_directory();
801
- }
802
- $refresh_time = intval( wpcf_get_settings( 'images_remote_cache_time' ) );
803
- if ( $refresh_time == 0 && $action != 'all' ) {
804
- return true;
805
- }
806
- foreach ( glob( $cache_dir . DIRECTORY_SEPARATOR . "*" ) as $filename ) {
807
- if ( $action == 'all' ) {
808
- @unlink( $filename );
809
- } else {
810
- $time_modified = filemtime( $filename );
811
- if ( time() - $time_modified > $refresh_time * 60 * 60 ) {
812
- @unlink( $filename );
813
- // Clear resized images
814
- $path = pathinfo( $filename );
815
- foreach ( glob( $path['dirname'] . DIRECTORY_SEPARATOR . $path['filename'] . "-*" ) as $resized ) {
816
- @unlink( $resized );
817
- }
818
- }
819
- }
820
- }
821
- }
822
-
823
- /**
824
- * Filters upload paths (to fix Windows issues).
825
- *
826
- * @param type $args
827
- * @return type
828
- */
829
- function wpcf_fields_image_uploads_realpath( $args ) {
830
-
831
- global $wpcf;
832
-
833
- $fixes = array('path', 'subdir', 'basedir');
834
- foreach ( $fixes as $fix ) {
835
- if ( isset( $args[$fix] ) ) {
836
- /*
837
- * Since 1.1.5
838
- *
839
- * We need realpath(), open_basedir restriction check
840
- *
841
- * Suppressing warnings, checking realpath returning FALSE, check
842
- * if open_basedir ini is set.
843
- *
844
- * https://icanlocalize.basecamphq.com/projects/7393061-wp-views/todo_items/153462252/comments
845
- * http://php.net/manual/en/ini.sect.safe-mode.php
846
- * http://php.net/manual/en/ini.core.php#ini.open-basedir
847
- */
848
- $realpath = @realpath( $args[$fix] );
849
-
850
- $wpcf->debug->images['relpath_fixes'][$fix] = array(
851
- 'realpath' => $realpath,
852
- 'args' => $args[$fix],
853
- 'altered' => $realpath != $args[$fix] && $realpath !== false ? 'TRUE' : 'FALSE',
854
- );
855
-
856
- // $open_basedir = @ini_get( 'open_basedir' );
857
- if ( $realpath !== false ) {
858
- $args[$fix] = $realpath;
859
- }
860
- }
861
- }
862
- return $args;
863
- }
864
-
865
- /**
866
- * i18n friendly version of basename(), copy from wp-includes/formatting.php
867
- * to solve bug with windows
868
- *
869
- * @since 3.1.0
870
- *
871
- * @param string $path A path.
872
- * @param string $suffix If the filename ends in suffix this will also be cut off.
873
- * @return string
874
- */
875
- function wpcf_basename( $path, $suffix = '' ) {
876
- return urldecode( basename( str_replace( array('%2F', '%5C'), '/',
877
- urlencode( $path ) ), $suffix ) );
878
- }
879
-
880
- /**
881
- * Copy from wp-includes/media.php
882
- * Scale down an image to fit a particular size and save a new copy of the image.
883
- *
884
- * The PNG transparency will be preserved using the function, as well as the
885
- * image type. If the file going in is PNG, then the resized image is going to
886
- * be PNG. The only supported image types are PNG, GIF, and JPEG.
887
- *
888
- * Some functionality requires API to exist, so some PHP version may lose out
889
- * support. This is not the fault of WordPress (where functionality is
890
- * downgraded, not actual defects), but of your PHP version.
891
- *
892
- * @since 2.5.0
893
- *
894
- * @param string $file Image file path.
895
- * @param int $max_w Maximum width to resize to.
896
- * @param int $max_h Maximum height to resize to.
897
- * @param bool $crop Optional. Whether to crop image or resize.
898
- * @param string $suffix Optional. File suffix.
899
- * @param string $dest_path Optional. New image file path.
900
- * @param int $jpeg_quality Optional, default is 90. Image quality percentage.
901
- * @return mixed WP_Error on failure. String with new destination path.
902
- */
903
- function wpcf_image_resize( $file, $max_w, $max_h, $crop = false,
904
- $suffix = null, $dest_path = null, $jpeg_quality = 90 ) {
905
-
906
- $image = wp_load_image( $file );
907
- if ( !is_resource( $image ) )
908
- return new WP_Error( 'error_loading_image', $image, $file );
909
-
910
- $size = @getimagesize( $file );
911
- if ( !$size )
912
- return new WP_Error( 'invalid_image', __( 'Could not read image size', 'wpcf' ), $file );
913
- list($orig_w, $orig_h, $orig_type) = $size;
914
-
915
- $dims = image_resize_dimensions( $orig_w, $orig_h, $max_w, $max_h, $crop );
916
- if ( !$dims )
917
- return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions', 'wpcf' ) );
918
- list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $dims;
919
-
920
- $newimage = wp_imagecreatetruecolor( $dst_w, $dst_h );
921
-
922
- imagecopyresampled( $newimage, $image, $dst_x, $dst_y, $src_x, $src_y,
923
- $dst_w, $dst_h, $src_w, $src_h );
924
-
925
- // convert from full colors to index colors, like original PNG.
926
- if ( IMAGETYPE_PNG == $orig_type && function_exists( 'imageistruecolor' ) && !imageistruecolor( $image ) )
927
- imagetruecolortopalette( $newimage, false, imagecolorstotal( $image ) );
928
-
929
- // we don't need the original in memory anymore
930
- imagedestroy( $image );
931
-
932
- // $suffix will be appended to the destination filename, just before the extension
933
- if ( !$suffix )
934
- $suffix = "{$dst_w}x{$dst_h}";
935
-
936
- $info = pathinfo( $file );
937
- $dir = $info['dirname'];
938
- $ext = $info['extension'];
939
- $name = wpcf_basename( $file, ".$ext" ); // use fix here for windows
940
-
941
- if ( !is_null( $dest_path ) and $_dest_path = realpath( $dest_path ) )
942
- $dir = $_dest_path;
943
- $destfilename = "{$dir}/{$name}-{$suffix}.{$ext}";
944
-
945
- if ( IMAGETYPE_GIF == $orig_type ) {
946
- if ( !imagegif( $newimage, $destfilename ) )
947
- return new WP_Error( 'resize_path_invalid', __( 'Resize path invalid', 'wpcf' ) );
948
- } elseif ( IMAGETYPE_PNG == $orig_type ) {
949
- if ( !imagepng( $newimage, $destfilename ) )
950
- return new WP_Error( 'resize_path_invalid', __( 'Resize path invalid', 'wpcf' ) );
951
- } else {
952
- // all other formats are converted to jpg
953
- if ( 'jpg' != $ext && 'jpeg' != $ext )
954
- $destfilename = "{$dir}/{$name}-{$suffix}.jpg";
955
- if ( !imagejpeg( $newimage, $destfilename,
956
- apply_filters( 'jpeg_quality', $jpeg_quality,
957
- 'image_resize' ) ) )
958
- return new WP_Error( 'resize_path_invalid', __( 'Resize path invalid', 'wpcf' ) );
959
- }
960
-
961
- imagedestroy( $newimage );
962
-
963
- // Set correct file permissions
964
- $stat = stat( dirname( $destfilename ) );
965
- $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
966
- @ chmod( $destfilename, $perms );
967
-
968
- return $destfilename;
969
- }
970
-
971
- /**
972
- * Fixes for Win.
973
- *
974
- * For now we fix file path to have unified type slashes.
975
- *
976
- * @param type $file
977
- * @param type $attachment_id
978
- * @return type
979
- */
980
- function wpcf_fields_image_win32_update_attached_file_filter( $file,
981
- $attachment_id ) {
982
-
983
- global $wpcf;
984
-
985
- $return = str_replace( '\\', '/', $file );
986
- $wpcf->debug->images['Win']['update_attached_file_filter'][] = array(
987
- 'file' => $file,
988
- 'return' => $return,
989
- 'attachment_id' => $attachment_id,
990
- );
991
-
992
- return $return;
993
- }
994
-
995
- /**
996
- * Filters image view.
997
- *
998
- * This is added to handle image 'url' parameter.
999
- * We need to unwrap value. Also added to avoid cludging frontend.php.
1000
- *
1001
- * @param boolean $params
1002
- * @param type $field
1003
- * @return boolean
1004
- */
1005
- function wpcf_fields_image_view_filter( $output, $value, $type, $slug, $name,
1006
- $params ) {
1007
-
1008
- global $wpcf;
1009
-
1010
- if ( $type == 'image' ) {
1011
- // If 'url' param is used, force return un-wrapped
1012
- if ( isset( $params['url'] ) && $params['url'] != 'false' ) {
1013
- $cache_key = md5( serialize( $params ) );
1014
- if ( isset( $wpcf->__images_wrap_fix[$cache_key] ) ) {
1015
- $output = $wpcf->__images_wrap_fix[$cache_key];
1016
- }
1017
- }
1018
- }
1019
-
1020
- return $output;
1021
- }
1022
-
1023
- /**
1024
- * Adds image to library.
1025
- *
1026
- * @param type $post
1027
- * @param type $abspath
1028
- */
1029
- function wpcf_image_add_to_library( $post, $abspath ){
1030
- $guid = wpcf_image_attachment_url( $abspath );
1031
- if ( !wpcf_image_is_attachment( $guid ) ) {
1032
- $wp_filetype = wp_check_filetype( basename( $abspath ), null );
1033
- $attachment = array(
1034
- 'post_mime_type' => $wp_filetype['type'],
1035
- 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $abspath ) ),
1036
- 'post_content' => '',
1037
- 'post_status' => 'inherit',
1038
- 'guid' => $guid,
1039
- );
1040
- $attach_id = wp_insert_attachment( $attachment, $abspath, $post->ID );
1041
- require_once(ABSPATH . "wp-admin" . '/includes/image.php');
1042
- $attach_data = wp_generate_attachment_metadata( $attach_id, $abspath );
1043
- $attach_data['file'] = str_replace( '\\', '/',
1044
- wpcf_image_normalize_attachment( $attach_data['file'] ) );
1045
- wp_update_attachment_metadata( $attach_id, $attach_data );
1046
- update_attached_file( $attach_id, $attach_data['file'] );
1047
- }
1048
- }
1049
-
1050
- /**
1051
- * Checks if image is attachment.
1052
- *
1053
- * @global object $wpdb
1054
- * @param type $guid
1055
- * @return type
1056
- */
1057
- function wpcf_image_is_attachment( $guid ) {
1058
- global $wpdb;
1059
- return $wpdb->get_var(
1060
- $wpdb->prepare(
1061
- "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND guid=%s",
1062
- $guid
1063
- )
1064
- );
1065
- }
1066
-
1067
- /**
1068
- * Gets attachment URL (in uploads, root or date structure).
1069
- *
1070
- * @param type $abspath
1071
- * @return type
1072
- */
1073
- function wpcf_image_attachment_url( $abspath ) {
1074
- WPCF_Loader::loadView( 'image' );
1075
- return Types_Image_Utils::getInstance()->normalizeAttachmentUrl( $abspath );
1076
- }
1077
-
1078
- /**
1079
- * Returns path to attachment relative to upload_dir.
1080
- *
1081
- * @param type $abspath
1082
- * @return string '2014/01/img.jpg'
1083
- */
1084
- function wpcf_image_normalize_attachment( $abspath ) {
1085
- WPCF_Loader::loadView( 'image' );
1086
- return Types_Image_Utils::getInstance()->normalizeAttachment( $abspath );
1087
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
embedded/includes/fields/numeric.php DELETED
@@ -1,144 +0,0 @@
1
- <?php
2
- /*
3
- * Numeric field.
4
- */
5
-
6
- // Filters
7
- add_filter( 'wpcf_fields_type_numeric_value_save',
8
- 'wpcf_fields_numeric_value_save_filter', 10, 3 );
9
- add_filter( 'wpcf_fields_type_numeric_value_display',
10
- 'wpcf_fields_type_numeric_value_display_by_locale', 10, 3 );
11
- add_filter( 'wpcf_fields_numeric_meta_box_form_value_display',
12
- 'wpcf_fields_numeric_meta_box_form_value_display_by_locale', 10, 3 );
13
-
14
- /**
15
- * Register data (called automatically).
16
- *
17
- * @return type
18
- */
19
- function wpcf_fields_numeric() {
20
-
21
- return array(
22
- 'id' => 'wpcf-numeric',
23
- 'title' => __( 'Numeric', 'wpcf' ),
24
- 'description' => __( 'Numeric', 'wpcf' ),
25
- 'validate' => array(
26
- 'required' => array(
27
- 'form-settings' => include( dirname( __FILE__ ) . '/patterns/validate/form-settings/required.php' ),
28
- ),
29
- 'number' => array(
30
- 'forced' => true,
31
- 'form-settings' => include( dirname( __FILE__ ) . '/patterns/validate/form-settings/numeric.php' )
32
- )
33
- ),
34
- 'inherited_field_type' => 'textfield',
35
- 'meta_key_type' => 'NUMERIC',
36
- 'meta_box_js' => array('wpcf_field_number_validation_fix' => array(
37
- 'inline' => 'wpcf_field_number_validation_fix')
38
- ),
39
- 'font-awesome' => 'calculator',
40
- );
41
- }
42
-
43
- function wpcf_fields_numeric_meta_box_form_va