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

Version Description

  • Added ability to add extra options by filter wpt_field_options to fields with "options".
  • Added ability to create custom post type with the same singular and plural name.
  • Added ability to select menu icon for custom post type.
  • Added delete attached repetitive files.
  • Added filter "wpcf_pr_belongs_post_status" that allows to change post_status for parent/child posts.
  • Added sanitization for uploaded file names, to remove non-latin1 characters.
  • Added debug page to help retrieving debug information.
  • Fixed export problem if system temporary directory is not allowed to write by open_basedir restriction.
  • Fixed export problem, when temporary directory is full or not available.
  • Fixed import of slug for custom fields.
  • Fixed problems with calling static method in PHP 5.2
  • Fixed problems with embedding scripts when WordPress works on non-standard port.
  • Fixed problems with getting not existing array keys when register new post type.
  • Fixed problems with manage more than one flat taxonomy on one CRED screen.
  • Improved import button, which is disabled until user select a import file.
  • Improved custom display logic UI for conditional display in custom fields edit screen.
  • Prevent raising group chose overlay on "Custom Fields Control" screen if there is no group.
  • Remove serialize/unserialize for exported relationships to avoid object injection.
  • Removed Zebra library and created new Toolset fields library.
  • Tweak import/export screen when is something wrong with imported file
  • Fix several security issues
  • Unify code with other Toolset plugins
  • Add debug information output for improved customer support
  • Add "required" validation audio, file and video fields
Download this release

Release Info

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

Version 1.6

Files changed (88) hide show
  1. admin.php +1032 -0
  2. embedded/admin.php +727 -0
  3. embedded/bootstrap.php +328 -0
  4. embedded/classes/class.wpcf-import-export.php +220 -0
  5. embedded/classes/class.wpcf-post-types.php +79 -0
  6. embedded/classes/conditional.php +234 -0
  7. embedded/classes/editor.php +520 -0
  8. embedded/classes/evaluate.php +350 -0
  9. embedded/classes/field.php +789 -0
  10. embedded/classes/fields.php +192 -0
  11. embedded/classes/forms.php +964 -0
  12. embedded/classes/helper.ajax.php +132 -0
  13. embedded/classes/loader.php +296 -0
  14. embedded/classes/path.php +356 -0
  15. embedded/classes/post-types/messages.php +15 -0
  16. embedded/classes/relationship.php +496 -0
  17. embedded/classes/relationship/form-child.php +729 -0
  18. embedded/classes/relationship/form-parent.php +7 -0
  19. embedded/classes/repeater.php +616 -0
  20. embedded/classes/usermeta_field.php +189 -0
  21. embedded/classes/usermeta_repeater.php +571 -0
  22. embedded/classes/validate.php +435 -0
  23. embedded/classes/validation-cakephp.php +1122 -0
  24. embedded/classes/validation.php +123 -0
  25. embedded/classes/wpviews.php +122 -0
  26. embedded/common/WPML/wpml-string-shortcode.php +34 -0
  27. embedded/common/Zip.php +861 -0
  28. embedded/common/array2xml.php +55 -0
  29. embedded/common/classes/control_forms.php +28 -0
  30. embedded/common/classes/forms.php +969 -0
  31. embedded/common/classes/validate.php +425 -0
  32. embedded/common/classes/validation-cakephp.php +1126 -0
  33. embedded/common/debug/debug-information.php +28 -0
  34. embedded/common/debug/functions_debug_information.php +154 -0
  35. embedded/common/expression-parser/js/parser.js +2923 -0
  36. embedded/common/expression-parser/parser.php +2892 -0
  37. embedded/common/functions.php +671 -0
  38. embedded/common/localization/locale/orig/views.po +4528 -0
  39. embedded/common/localization/locale/views-ar.mo +0 -0
  40. embedded/common/localization/locale/views-bg_BG.mo +0 -0
  41. embedded/common/localization/locale/views-de_DE.mo +0 -0
  42. embedded/common/localization/locale/views-el.mo +0 -0
  43. embedded/common/localization/locale/views-es_ES.mo +0 -0
  44. embedded/common/localization/locale/views-fr_FR.mo +0 -0
  45. embedded/common/localization/locale/views-he_IL.mo +0 -0
  46. embedded/common/localization/locale/views-it_IT.mo +0 -0
  47. embedded/common/localization/locale/views-ja.mo +0 -0
  48. embedded/common/localization/locale/views-ko_KR.mo +0 -0
  49. embedded/common/localization/locale/views-nl_NL.mo +0 -0
  50. embedded/common/localization/locale/views-pl_PL.mo +0 -0
  51. embedded/common/localization/locale/views-pt_BR.mo +0 -0
  52. embedded/common/localization/locale/views-pt_PT.mo +0 -0
  53. embedded/common/localization/locale/views-ru_RU.mo +0 -0
  54. embedded/common/localization/locale/views-sv_SE.mo +0 -0
  55. embedded/common/localization/locale/views-vi.mo +0 -0
  56. embedded/common/localization/locale/views-zh_CN.mo +0 -0
  57. embedded/common/localization/locale/views-zh_TW.mo +0 -0
  58. embedded/common/localization/wpt-localization.php +61 -0
  59. embedded/common/res/css/toolset-common.css +62 -0
  60. embedded/common/res/css/toolset-menu-icon.css +29 -0
  61. embedded/common/res/css/wpv-wp-pointer.css +4 -0
  62. embedded/common/res/images/question.png +0 -0
  63. embedded/common/res/js/wpv-wp-pointer.js +17 -0
  64. embedded/common/toolset-forms/TODO +2 -0
  65. embedded/common/toolset-forms/__index.php +24 -0
  66. embedded/common/toolset-forms/api.php +59 -0
  67. embedded/common/toolset-forms/bootstrap.php +200 -0
  68. embedded/common/toolset-forms/classes/abstract.field.php +34 -0
  69. embedded/common/toolset-forms/classes/abstract.form.php +48 -0
  70. embedded/common/toolset-forms/classes/class.audio.php +45 -0
  71. embedded/common/toolset-forms/classes/class.button.php +25 -0
  72. embedded/common/toolset-forms/classes/class.checkbox.php +63 -0
  73. embedded/common/toolset-forms/classes/class.checkboxes.php +70 -0
  74. embedded/common/toolset-forms/classes/class.colorpicker.php +92 -0
  75. embedded/common/toolset-forms/classes/class.conditional.php +536 -0
  76. embedded/common/toolset-forms/classes/class.cred.php +88 -0
  77. embedded/common/toolset-forms/classes/class.credaudio.php +33 -0
  78. embedded/common/toolset-forms/classes/class.credfile.php +148 -0
  79. embedded/common/toolset-forms/classes/class.credimage.php +31 -0
  80. embedded/common/toolset-forms/classes/class.credvideo.php +33 -0
  81. embedded/common/toolset-forms/classes/class.custom_conditional.php +226 -0
  82. embedded/common/toolset-forms/classes/class.date.php +406 -0
  83. embedded/common/toolset-forms/classes/class.date.scripts.php +173 -0
  84. embedded/common/toolset-forms/classes/class.eforms.php +1279 -0
  85. embedded/common/toolset-forms/classes/class.email.php +12 -0
  86. embedded/common/toolset-forms/classes/class.embed.php +14 -0
  87. embedded/common/toolset-forms/classes/class.field_factory.php +135 -0
  88. embedded/common/toolset-forms/classes/class.fieldconfig.php +215 -0
admin.php ADDED
@@ -0,0 +1,1032 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ * Admin functions
5
+ *
6
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/cck/tags/1.6/admin.php $
7
+ * $LastChangedDate: 2014-08-12 10:19:36 +0800 (Tue, 12 Aug 2014) $
8
+ * $LastChangedRevision: 25849 $
9
+ * $LastChangedBy: bruce $
10
+ *
11
+ */
12
+ require_once WPCF_ABSPATH . '/marketing.php';
13
+ /*
14
+ * This needs to be called after main 'init' hook.
15
+ * Main init hook calls required Types code for frontend.
16
+ * Admin init hook only in admin area.
17
+ *
18
+ * TODO Revise it to change to 'admin_init'
19
+ */
20
+ add_action( 'admin_init', 'wpcf_admin_init_hook', 11 );
21
+ add_action( 'admin_menu', 'wpcf_admin_menu_hook' );
22
+ add_action( 'wpcf_admin_page_init', 'wpcf_enqueue_scripts' );
23
+
24
+ wpcf_admin_load_teasers( array('types-access.php') );
25
+ if ( defined( 'DOING_AJAX' ) ) {
26
+ require_once WPCF_INC_ABSPATH . '/ajax.php';
27
+ }
28
+
29
+ /**
30
+ * admin_init hook.
31
+ */
32
+ function wpcf_admin_init_hook() {
33
+ wpcf_types_plugin_redirect();
34
+ wp_enqueue_style( 'wpcf-promo-tabs',
35
+ WPCF_EMBEDDED_RES_RELPATH . '/css/tabs.css', array(), WPCF_VERSION );
36
+ /* wp_enqueue_style('wpcf-promo-tabs',
37
+ WPCF_RES_RELPATH . '/css/tabs.css', array(), WPCF_VERSION); */
38
+ wp_enqueue_style('toolset-dashicons');
39
+ }
40
+
41
+ /**
42
+ * admin_menu hook.
43
+ */
44
+ function wpcf_admin_menu_hook()
45
+ {
46
+ $wpcf_capability = apply_filters( 'wpcf_capability', 'manage_options' );
47
+
48
+ add_menu_page(
49
+ __( 'Types', 'wpcf' ),
50
+ __( 'Types', 'wpcf' ),
51
+ $wpcf_capability,
52
+ 'wpcf',
53
+ 'wpcf_admin_menu_summary',
54
+ 'none'
55
+ );
56
+
57
+ $subpages = array(
58
+
59
+ // Custom types and tax
60
+ 'wpcf-ctt' => array(
61
+ 'page_title' => __( 'Custom Types and Taxonomies', 'wpcf' ),
62
+ 'menu_title' => __( 'Types &amp; Taxonomies', 'wpcf' ),
63
+ 'function' => 'wpcf_admin_menu_summary_ctt',
64
+ ),
65
+
66
+ // Custom fields
67
+ 'wpcf-cf' => array(
68
+ 'page_title' => __( 'Custom Fields', 'wpcf' ),
69
+ 'menu_title' => __( 'Custom Fields', 'wpcf' ),
70
+ 'function' => 'wpcf_admin_menu_summary',
71
+ ),
72
+ // Custom Fields Control
73
+ 'wpcf-custom-fields-control' => array(
74
+ 'page_title' => __( 'Custom Fields Control', 'wpcf' ),
75
+ 'menu_title' => __( 'Custom Fields Control', 'wpcf' ),
76
+ 'function' => 'wpcf_admin_menu_custom_fields_control',
77
+ ),
78
+ // User Meta
79
+ 'wpcf-um' => array(
80
+ 'page_title' => __( 'User Fields', 'wpcf' ),
81
+ 'menu_title' => __( 'User Fields', 'wpcf' ),
82
+ 'function' => 'wpcf_usermeta_summary',
83
+ 'load-hook' => 'wpcf_admin_menu_summary_hook',
84
+ ),
85
+ // User Fields Control
86
+ 'wpcf-user-fields-control' => array(
87
+ 'page_title' => __( 'User Fields Control', 'wpcf' ),
88
+ 'menu_title' => __( 'User Fields Control', 'wpcf' ),
89
+ 'function' => 'wpcf_admin_menu_user_fields_control',
90
+ ),
91
+
92
+ // Import/Export
93
+ 'wpcf-import-export' => array(
94
+ 'page_title' => __( 'Import/Export', 'wpcf' ),
95
+ 'menu_title' => __( 'Import/Export', 'wpcf' ),
96
+ 'function' => 'wpcf_admin_menu_import_export',
97
+ ),
98
+ // Settings
99
+ 'wpcf-custom-settings' => array(
100
+ 'page_title' => __( 'Settings', 'wpcf' ),
101
+ 'menu_title' => __( 'Settings', 'wpcf' ),
102
+ 'function' => 'wpcf_admin_menu_settings',
103
+ ),
104
+
105
+ // Introduction
106
+ 'wpcf-help' => array(
107
+ 'page_title' => __( 'Help', 'wpcf' ),
108
+ 'menu_title' => __( 'Help', 'wpcf' ),
109
+ 'function' => 'wpcf_admin_menu_introduction',
110
+ 'submenu' => array(
111
+ 'wpcf-debug-information' => array(
112
+ 'page_title' => __( 'Debug information', 'wpcf' ),
113
+ 'menu_title' => __( 'Debug information', 'wpcf' ),
114
+ 'function' => 'wpcf_admin_menu_debug_information',
115
+ ),
116
+ ),
117
+ ),
118
+
119
+ );
120
+
121
+ foreach( $subpages as $menu_slug => $data ) {
122
+ $hook = add_submenu_page(
123
+ 'wpcf',
124
+ $data['page_title'],
125
+ $data['menu_title'],
126
+ $wpcf_capability,
127
+ $menu_slug,
128
+ $data['function']
129
+ );
130
+ if ( array_key_exists('submenu', $data ) ) {
131
+ foreach( $data['submenu'] as $submenu_slug => $submenu ) {
132
+ add_submenu_page(
133
+ $hook,
134
+ $submenu['page_title'],
135
+ $submenu['menu_title'],
136
+ $wpcf_capability,
137
+ $submenu_slug,
138
+ $submenu['function']
139
+ );
140
+ }
141
+ }
142
+ if ( !array_key_exists('load-hook', $data ) ) {
143
+ $data['load-hook'] = sprintf( '%s_hook', $data['function'] );
144
+ }
145
+ wpcf_admin_plugin_help( $hook, $menu_slug );
146
+ add_action( 'load-' . $hook, $data['load-hook'] );
147
+ }
148
+
149
+ if ( isset( $_GET['page'] ) ) {
150
+ switch ( $_GET['page'] ) {
151
+ case 'wpcf-edit':
152
+ $title = isset( $_GET['group_id'] ) ? __( 'Edit Group', 'wpcf' ) : __( 'Add New Group',
153
+ 'wpcf' );
154
+ $hook = add_submenu_page( 'wpcf', $title, $title,
155
+ 'manage_options', 'wpcf-edit',
156
+ 'wpcf_admin_menu_edit_fields' );
157
+ add_action( 'load-' . $hook, 'wpcf_admin_menu_edit_fields_hook' );
158
+ wpcf_admin_plugin_help( $hook, 'wpcf-edit' );
159
+ break;
160
+
161
+ case 'wpcf-edit-type':
162
+ $title = isset( $_GET['wpcf-post-type'] ) ? __( 'Edit Custom Post Type',
163
+ 'wpcf' ) : __( 'Add New Custom Post Type',
164
+ 'wpcf' );
165
+ $hook = add_submenu_page( 'wpcf', $title, $title,
166
+ 'manage_options', 'wpcf-edit-type',
167
+ 'wpcf_admin_menu_edit_type' );
168
+ add_action( 'load-' . $hook, 'wpcf_admin_menu_edit_type_hook' );
169
+ wpcf_admin_plugin_help( $hook, 'wpcf-edit-type' );
170
+ break;
171
+
172
+ case 'wpcf-edit-tax':
173
+ $title = isset( $_GET['wpcf-tax'] ) ? __( 'Edit Taxonomy',
174
+ 'wpcf' ) : __( 'Add New Taxonomy', 'wpcf' );
175
+ $hook = add_submenu_page( 'wpcf', $title, $title,
176
+ 'manage_options', 'wpcf-edit-tax',
177
+ 'wpcf_admin_menu_edit_tax' );
178
+ add_action( 'load-' . $hook, 'wpcf_admin_menu_edit_tax_hook' );
179
+ wpcf_admin_plugin_help( $hook, 'wpcf-edit-tax' );
180
+ break;
181
+ case 'wpcf-edit-usermeta':
182
+ $title = isset( $_GET['group_id'] ) ? __( 'Edit User Fields Group', 'wpcf' ) : __( 'Add New User Fields Group',
183
+ 'wpcf' );
184
+ $hook = add_submenu_page( 'wpcf', $title, $title,
185
+ 'manage_options', 'wpcf-edit-usermeta',
186
+ 'wpcf_admin_menu_edit_user_fields' );
187
+ add_action( 'load-' . $hook, 'wpcf_admin_menu_edit_user_fields_hook' );
188
+ wpcf_admin_plugin_help( $hook, 'wpcf-edit-usermeta' );
189
+ break;
190
+ }
191
+ }
192
+
193
+ // Check if migration from other plugin is needed
194
+ if ( class_exists( 'Acf' ) || defined( 'CPT_VERSION' ) ) {
195
+ $hook = add_submenu_page( 'wpcf', __( 'Migration', 'wpcf' ),
196
+ __( 'Migration', 'wpcf' ), 'manage_options', 'wpcf-migration',
197
+ 'wpcf_admin_menu_migration' );
198
+ add_action( 'load-' . $hook, 'wpcf_admin_menu_migration_hook' );
199
+ wpcf_admin_plugin_help( $hook, 'wpcf-migration' );
200
+ }
201
+
202
+ do_action( 'wpcf_menu_plus' );
203
+
204
+ // remove the repeating Types submenu
205
+ remove_submenu_page( 'wpcf', 'wpcf' );
206
+ }
207
+
208
+ /**
209
+ * Menu page hook.
210
+ */
211
+ function wpcf_admin_menu_introduction_hook() {
212
+ do_action( 'wpcf_admin_page_init' );
213
+ }
214
+
215
+ /**
216
+ * Menu page display.
217
+ */
218
+ function wpcf_admin_menu_introduction() {
219
+ require_once WPCF_INC_ABSPATH . '/introduction.php';
220
+ }
221
+
222
+ /**
223
+ * Menu page hook.
224
+ */
225
+ function wpcf_admin_menu_debug_information()
226
+ {
227
+ require_once WPCF_EMBEDDED_ABSPATH.'/common/debug/debug-information.php';
228
+ }
229
+
230
+ /**
231
+ * Menu page hook.
232
+ */
233
+ function wpcf_admin_menu_summary_hook() {
234
+ do_action( 'wpcf_admin_page_init' );
235
+ wpcf_admin_load_collapsible();
236
+ }
237
+
238
+ /**
239
+ * Menu page display.
240
+ */
241
+ function wpcf_admin_menu_summary() {
242
+ echo wpcf_add_admin_header( __( 'Custom Fields', 'wpcf' ) );
243
+ require_once WPCF_INC_ABSPATH . '/fields.php';
244
+ require_once WPCF_INC_ABSPATH . '/fields-list.php';
245
+ $to_display = wpcf_admin_fields_get_fields();
246
+ if ( !empty( $to_display ) ) {
247
+ add_action( 'wpcf_groups_list_table_after',
248
+ 'wpcf_admin_promotional_text' );
249
+ }
250
+ wpcf_admin_fields_list();
251
+ echo wpcf_add_admin_footer();
252
+ }
253
+
254
+ /**
255
+ * Menu page hook.
256
+ */
257
+ function wpcf_admin_menu_edit_fields_hook() {
258
+ do_action( 'wpcf_admin_page_init' );
259
+
260
+ /*
261
+ * Enqueue scripts
262
+ */
263
+ // Group filter
264
+ wp_enqueue_script( 'wpcf-filter-js',
265
+ WPCF_EMBEDDED_RES_RELPATH
266
+ . '/js/custom-fields-form-filter.js', array('jquery'), WPCF_VERSION );
267
+ // Form
268
+ wp_enqueue_script( 'wpcf-form-validation',
269
+ WPCF_EMBEDDED_RES_RELPATH . '/js/'
270
+ . 'jquery-form-validation/jquery.validate.min.js', array('jquery'),
271
+ WPCF_VERSION );
272
+ wp_enqueue_script( 'wpcf-form-validation-additional',
273
+ WPCF_EMBEDDED_RES_RELPATH . '/js/'
274
+ . 'jquery-form-validation/additional-methods.min.js',
275
+ array('jquery'), WPCF_VERSION );
276
+ // Scroll
277
+ wp_enqueue_script( 'wpcf-scrollbar',
278
+ WPCF_EMBEDDED_RELPATH . '/common/visual-editor/res/js/scrollbar.js',
279
+ array('jquery') );
280
+ wp_enqueue_script( 'wpcf-mousewheel',
281
+ WPCF_EMBEDDED_RELPATH . '/common/visual-editor/res/js/mousewheel.js',
282
+ array('wpcf-scrollbar') );
283
+ // MAIN
284
+ wp_enqueue_script( 'wpcf-fields-form',
285
+ WPCF_EMBEDDED_RES_RELPATH
286
+ . '/js/fields-form.js', array('wpcf-js') );
287
+
288
+ /*
289
+ * Enqueue styles
290
+ */
291
+ wp_enqueue_style( 'wpcf-scroll',
292
+ WPCF_EMBEDDED_RELPATH . '/common/visual-editor/res/css/scroll.css' );
293
+
294
+ //Css editor
295
+ wp_enqueue_script( 'wpcf-form-codemirror' ,
296
+ WPCF_RELPATH . '/resources/js/codemirror234/lib/codemirror.js', array('wpcf-js'));
297
+ wp_enqueue_script( 'wpcf-form-codemirror-css-editor' ,
298
+ WPCF_RELPATH . '/resources/js/codemirror234/mode/css/css.js', array('wpcf-js'));
299
+ wp_enqueue_script( 'wpcf-form-codemirror-html-editor' ,
300
+ WPCF_RELPATH . '/resources/js/codemirror234/mode/xml/xml.js', array('wpcf-js'));
301
+ wp_enqueue_script( 'wpcf-form-codemirror-html-editor2' ,
302
+ WPCF_RELPATH . '/resources/js/codemirror234/mode/htmlmixed/htmlmixed.js', array('wpcf-js'));
303
+ wp_enqueue_script( 'wpcf-form-codemirror-editor-resize' ,
304
+ WPCF_RELPATH . '/resources/js/jquery_ui/jquery.ui.resizable.min.js', array('wpcf-js'));
305
+
306
+
307
+
308
+ wp_enqueue_style( 'wpcf-css-editor',
309
+ WPCF_RELPATH . '/resources/js/codemirror234/lib/codemirror.css' );
310
+ wp_enqueue_style( 'wpcf-css-editor-resize',
311
+ WPCF_RELPATH . '/resources/js/jquery_ui/jquery.ui.theme.min.css' );
312
+ wp_enqueue_style( 'wpcf-usermeta',
313
+ WPCF_EMBEDDED_RES_RELPATH . '/css/usermeta.css' );
314
+
315
+ add_action( 'admin_footer', 'wpcf_admin_fields_form_js_validation' );
316
+ require_once WPCF_INC_ABSPATH . '/fields.php';
317
+ require_once WPCF_INC_ABSPATH . '/fields-form.php';
318
+ $form = wpcf_admin_fields_form();
319
+ wpcf_form( 'wpcf_form_fields', $form );
320
+ }
321
+
322
+ /**
323
+ * Menu page display.
324
+ */
325
+ function wpcf_admin_menu_edit_fields() {
326
+ if ( isset( $_GET['group_id'] ) ) {
327
+ $title = __( 'Edit Group', 'wpcf' );
328
+ } else {
329
+ $title = __( 'Add New Group', 'wpcf' );
330
+ }
331
+ echo wpcf_add_admin_header( $title );
332
+ wpcf_wpml_warning();
333
+ $form = wpcf_form( 'wpcf_form_fields' );
334
+
335
+ ?>
336
+ <script type="text/javascript">
337
+ function wpcf_group_submit() {
338
+ if (jQuery('#wpcf-group-name').val() == 'Enter group title') {
339
+ jQuery('#wpcf-group-name').val('');
340
+ }
341
+ if (jQuery('#wpcf-group-description').val() == 'Enter a description for this group') {
342
+ jQuery('#wpcf-group-description').val('');
343
+ }
344
+ jQuery('.wpcf-forms-set-legend').each(function(){
345
+ if (jQuery(this).val() == 'Enter field name') {
346
+ jQuery(this).val('');
347
+ }
348
+ if (jQuery(this).next().val() == 'Enter field slug') {
349
+ jQuery(this).next().val('');
350
+ }
351
+ if (jQuery(this).next().next().val() == 'Describe this field') {
352
+ jQuery(this).next().next().val('');
353
+ }
354
+ });
355
+ }
356
+ </script>
357
+
358
+ <br /><form method="post" action="" class="wpcf-fields-form wpcf-form-validate" onsubmit="wpcf_group_submit()">
359
+ <?php echo $form->renderForm(); ?>
360
+ </form>
361
+ <?php
362
+ echo wpcf_add_admin_footer();
363
+ }
364
+
365
+ /**
366
+ * Menu page hook.
367
+ */
368
+ function wpcf_admin_menu_summary_ctt_hook() {
369
+ do_action( 'wpcf_admin_page_init' );
370
+ wp_enqueue_style( 'wpcf-promo-tabs', WPCF_RES_RELPATH . '/css/tabs.css',
371
+ array(), WPCF_VERSION );
372
+ wpcf_admin_load_collapsible();
373
+ require_once WPCF_INC_ABSPATH . '/custom-types.php';
374
+ require_once WPCF_INC_ABSPATH . '/custom-taxonomies.php';
375
+ require_once WPCF_INC_ABSPATH . '/custom-types-taxonomies-list.php';
376
+ }
377
+
378
+ /**
379
+ * Menu page display.
380
+ */
381
+ function wpcf_admin_menu_summary_ctt() {
382
+ echo wpcf_add_admin_header( __( 'Custom Post Types and Taxonomies', 'wpcf' ) );
383
+ $to_display_posts = get_option( 'wpcf-custom-types', array() );
384
+ $to_display_tax = get_option( 'wpcf-custom-taxonomies', array() );
385
+ if ( !empty( $to_display_posts ) || !empty( $to_display_tax ) ) {
386
+ add_action( 'wpcf_types_tax_list_table_after',
387
+ 'wpcf_admin_promotional_text' );
388
+ }
389
+ wpcf_admin_ctt_list();
390
+ echo wpcf_add_admin_footer();
391
+ }
392
+
393
+ /**
394
+ * Menu page hook.
395
+ */
396
+ function wpcf_admin_menu_edit_type_hook() {
397
+ do_action( 'wpcf_admin_page_init' );
398
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/custom-types.php';
399
+ require_once WPCF_INC_ABSPATH . '/custom-types-form.php';
400
+ require_once WPCF_INC_ABSPATH . '/post-relationship.php';
401
+ wp_enqueue_script( 'wpcf-custom-types-form',
402
+ WPCF_RES_RELPATH . '/js/'
403
+ . 'custom-types-form.js', array('jquery'), WPCF_VERSION );
404
+ wp_enqueue_script( 'wpcf-form-validation',
405
+ WPCF_RES_RELPATH . '/js/'
406
+ . 'jquery-form-validation/jquery.validate.min.js', array('jquery'),
407
+ WPCF_VERSION );
408
+ wp_enqueue_script( 'wpcf-form-validation-additional',
409
+ WPCF_RES_RELPATH . '/js/'
410
+ . 'jquery-form-validation/additional-methods.min.js',
411
+ array('jquery'), WPCF_VERSION );
412
+ add_action( 'admin_footer', 'wpcf_admin_types_form_js_validation' );
413
+ wpcf_post_relationship_init();
414
+ $form = wpcf_admin_custom_types_form();
415
+ wpcf_form( 'wpcf_form_types', $form );
416
+ }
417
+
418
+ /**
419
+ * Menu page display.
420
+ */
421
+ function wpcf_admin_menu_edit_type() {
422
+ if ( isset( $_GET['wpcf-post-type'] ) ) {
423
+ $title = __( 'Edit Custom Post Type', 'wpcf' );
424
+ } else {
425
+ $title = __( 'Add New Custom Post Type', 'wpcf' );
426
+ }
427
+ echo wpcf_add_admin_header( $title );
428
+ wpcf_wpml_warning();
429
+ $form = wpcf_form( 'wpcf_form_types' );
430
+ echo '<br /><form method="post" action="" class="wpcf-types-form '
431
+ . 'wpcf-form-validate">';
432
+ echo $form->renderForm();
433
+ echo '</form>';
434
+ echo wpcf_add_admin_footer();
435
+ }
436
+
437
+ /**
438
+ * Menu page hook.
439
+ */
440
+ function wpcf_admin_menu_edit_tax_hook() {
441
+ do_action( 'wpcf_admin_page_init' );
442
+ wp_enqueue_script( 'wpcf-form-validation',
443
+ WPCF_RES_RELPATH . '/js/'
444
+ . 'jquery-form-validation/jquery.validate.min.js', array('jquery'),
445
+ WPCF_VERSION );
446
+ wp_enqueue_script( 'wpcf-form-validation-additional',
447
+ WPCF_RES_RELPATH . '/js/'
448
+ . 'jquery-form-validation/additional-methods.min.js',
449
+ array('jquery'), WPCF_VERSION );
450
+ add_action( 'admin_footer', 'wpcf_admin_tax_form_js_validation' );
451
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/custom-taxonomies.php';
452
+ require_once WPCF_INC_ABSPATH . '/custom-taxonomies-form.php';
453
+ $form = wpcf_admin_custom_taxonomies_form();
454
+ wpcf_form( 'wpcf_form_tax', $form );
455
+ }
456
+
457
+ /**
458
+ * Menu page display.
459
+ */
460
+ function wpcf_admin_menu_edit_tax() {
461
+ if ( isset( $_GET['wpcf-tax'] ) ) {
462
+ $title = __( 'Edit Taxonomy', 'wpcf' );
463
+ } else {
464
+ $title = __( 'Add New Taxonomy', 'wpcf' );
465
+ }
466
+ echo wpcf_add_admin_header( $title );
467
+ wpcf_wpml_warning();
468
+ $form = wpcf_form( 'wpcf_form_tax' );
469
+ echo '<br /><form method="post" action="" class="wpcf-tax-form '
470
+ . 'wpcf-form-validate">';
471
+ echo $form->renderForm();
472
+ echo '</form>';
473
+ echo wpcf_add_admin_footer();
474
+ }
475
+
476
+ /**
477
+ * Menu page hook.
478
+ */
479
+ function wpcf_admin_menu_import_export_hook() {
480
+ do_action( 'wpcf_admin_page_init' );
481
+ require_once WPCF_INC_ABSPATH . '/fields.php';
482
+ require_once WPCF_INC_ABSPATH . '/import-export.php';
483
+ if ( extension_loaded( 'simplexml' ) && isset( $_POST['export'] )
484
+ && wp_verify_nonce( $_POST['_wpnonce'], 'wpcf_import' ) ) {
485
+ wpcf_admin_export_data();
486
+ die();
487
+ }
488
+ }
489
+
490
+ /**
491
+ * Menu page display.
492
+ */
493
+ function wpcf_admin_menu_import_export() {
494
+ echo wpcf_add_admin_header( __( 'Import/Export', 'wpcf' ) );
495
+ echo '<br /><form method="post" action="" class="wpcf-import-export-form '
496
+ . 'wpcf-form-validate" enctype="multipart/form-data">';
497
+ echo wpcf_form_simple( wpcf_admin_import_export_form() );
498
+ echo '</form>';
499
+ echo wpcf_add_admin_footer();
500
+ }
501
+
502
+ /**
503
+ * Menu page hook.
504
+ */
505
+ function wpcf_admin_menu_custom_fields_control_hook() {
506
+ do_action( 'wpcf_admin_page_init' );
507
+ add_action( 'admin_head', 'wpcf_admin_custom_fields_control_js' );
508
+ add_thickbox();
509
+ require_once WPCF_INC_ABSPATH . '/fields.php';
510
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
511
+ require_once WPCF_INC_ABSPATH . '/fields-control.php';
512
+
513
+ if ( isset( $_REQUEST['_wpnonce'] )
514
+ && wp_verify_nonce( $_REQUEST['_wpnonce'],
515
+ 'custom_fields_control_bulk' )
516
+ && (isset( $_POST['action'] ) || isset( $_POST['action2'] )) && !empty( $_POST['fields'] ) ) {
517
+ $action = $_POST['action'] == '-1' ? $_POST['action2'] : $_POST['action'];
518
+ wpcf_admin_custom_fields_control_bulk_actions( $action );
519
+ }
520
+
521
+ global $wpcf_control_table;
522
+ $wpcf_control_table = new WPCF_Custom_Fields_Control_Table( array(
523
+ 'ajax' => true,
524
+ 'singular' => __( 'Custom Field', 'wpcf' ),
525
+ 'plural' => __( 'Custom Fields', 'wpcf' ),
526
+ ) );
527
+ $wpcf_control_table->prepare_items();
528
+ }
529
+
530
+ /**
531
+ * Menu page display.
532
+ */
533
+ function wpcf_admin_menu_custom_fields_control() {
534
+ global $wpcf_control_table;
535
+ echo wpcf_add_admin_header( __( 'Custom Fields Control', 'wpcf' ) );
536
+ echo '<form method="post" action="" id="wpcf-custom-fields-control-form" class="wpcf-custom-fields-control-form '
537
+ . 'wpcf-form-validate" enctype="multipart/form-data">';
538
+ echo wpcf_admin_custom_fields_control_form( $wpcf_control_table );
539
+ wp_nonce_field( 'custom_fields_control_bulk' );
540
+ echo '</form>';
541
+ echo wpcf_add_admin_footer();
542
+ }
543
+
544
+ /**
545
+ * Menu page hook.
546
+ */
547
+ function wpcf_admin_menu_migration_hook() {
548
+ do_action( 'wpcf_admin_page_init' );
549
+ require_once WPCF_INC_ABSPATH . '/fields.php';
550
+ require_once WPCF_INC_ABSPATH . '/custom-types.php';
551
+ require_once WPCF_INC_ABSPATH . '/custom-taxonomies.php';
552
+ require_once WPCF_INC_ABSPATH . '/migration.php';
553
+ $form = wpcf_admin_migration_form();
554
+ wpcf_form( 'wpcf_form_migration', $form );
555
+ }
556
+
557
+ /**
558
+ * Menu page display.
559
+ */
560
+ function wpcf_admin_menu_migration() {
561
+ echo wpcf_add_admin_header( __( 'Migration', 'wpcf' ) );
562
+ echo '<br /><form method="post" action="" id="wpcf-migration-form" class="wpcf-migration-form '
563
+ . 'wpcf-form-validate" enctype="multipart/form-data">';
564
+ $form = wpcf_form( 'wpcf_form_migration' );
565
+ echo $form->renderForm();
566
+ echo '</form>';
567
+ echo wpcf_add_admin_footer();
568
+ }
569
+
570
+ /**
571
+ * Menu page hook.
572
+ */
573
+ function wpcf_admin_menu_settings_hook() {
574
+ do_action( 'wpcf_admin_page_init' );
575
+ require_once WPCF_INC_ABSPATH . '/settings.php';
576
+ $form = wpcf_admin_image_settings_form();
577
+ wpcf_form( 'wpcf_form_image_settings', $form );
578
+ $form = wpcf_admin_general_settings_form();
579
+ wpcf_form( 'wpcf_form_general_settings', $form );
580
+ }
581
+
582
+ /**
583
+ * Menu page display.
584
+ */
585
+ function wpcf_admin_menu_settings() {
586
+ ob_start();
587
+ echo wpcf_add_admin_header( __( 'Settings', 'wpcf' ) );
588
+
589
+ ?>
590
+ <p style="font-weight: bold;"><?php
591
+ _e( 'This screen contains the Types settings for your site.', 'wpcf' );
592
+
593
+ ?></p>
594
+ <ul class="horlist">
595
+ <li><a href="#types-image-settings"><?php
596
+ _e( 'Image Settings', 'wpcf' );
597
+
598
+ ?></a></li>
599
+ <li><a href="#types-general-settings"><?php
600
+ _e( 'General Setings', 'wpcf' );
601
+
602
+ ?></a></li>
603
+ </ul>
604
+ <br style='clear:both'/><br /><br />
605
+ <a id="types-image-settings"></a>
606
+ <table class="widefat" id="types_image_settings_table">
607
+ <thead>
608
+ <tr>
609
+ <th><?php
610
+ _e( 'Image Settings', 'wpcf' );
611
+
612
+ ?></th>
613
+ </tr>
614
+ </thead>
615
+ <tbody>
616
+ <tr>
617
+ <td>
618
+ <?php
619
+ echo '<br /><form method="post" action="" id="wpcf-image-settings-form" class="wpcf-settings-form '
620
+ . 'wpcf-form-validate">';
621
+ $form = wpcf_form( 'wpcf_form_image_settings' );
622
+ echo $form->renderForm();
623
+ echo '</form>';
624
+
625
+ ?>
626
+ </td>
627
+ </tr>
628
+ </tbody>
629
+ </table>
630
+ <br /><br />
631
+ <a id="types-general-settings"></a>
632
+ <table class="widefat" id="types_general_settings_table">
633
+ <thead>
634
+ <tr>
635
+ <th><?php
636
+ _e( 'General Settings', 'wpcf' );
637
+
638
+ ?></th>
639
+ </tr>
640
+ </thead>
641
+ <tbody>
642
+ <tr>
643
+ <td>
644
+ <?php
645
+ echo '<br /><form method="post" action="" id="wpcf-general-settings-form" class="wpcf-settings-form '
646
+ . 'wpcf-form-validate">';
647
+ $form = wpcf_form( 'wpcf_form_general_settings' );
648
+ echo $form->renderForm();
649
+ echo '</form>';
650
+
651
+ ?>
652
+ </td>
653
+ </tr>
654
+ </tbody>
655
+ </table>
656
+ <?php
657
+ echo wpcf_add_admin_footer();
658
+
659
+ echo ob_get_clean();
660
+ }
661
+
662
+ /**
663
+ * Adds typical header on admin pages.
664
+ *
665
+ * @param string $title
666
+ * @param string $icon_id Custom icon
667
+ * @return string
668
+ */
669
+ function wpcf_add_admin_header( $title, $icon_id = 'icon-wpcf' )
670
+ {
671
+ global $wp_version;
672
+ if ( version_compare( '3.8', $wp_version ) ) {
673
+ echo PHP_EOL;
674
+ printf('<div class="wrap"><div id="%s" class="icon32"><br /></div>', $icon_id );
675
+ }
676
+ printf('<h2>%s</h2>', $title );
677
+ do_action( 'wpcf_admin_header' );
678
+ do_action( 'wpcf_admin_header_' . $_GET['page'] );
679
+ }
680
+
681
+ /**
682
+ * Adds footer on admin pages.
683
+ *
684
+ * <b>Strongly recomended</b> if wpcf_add_admin_header() is called before.
685
+ * Otherwise invalid HTML formatting will occur.
686
+ */
687
+ function wpcf_add_admin_footer() {
688
+ do_action( 'wpcf_admin_footer_' . $_GET['page'] );
689
+ do_action( 'wpcf_admin_footer' );
690
+ echo "\r\n" . '</div>' . "\r\n";
691
+ }
692
+
693
+ /**
694
+ * Returns HTML formatted 'widefat' table.
695
+ *
696
+ * @param type $ID
697
+ * @param type $header
698
+ * @param type $rows
699
+ * @param type $empty_message
700
+ */
701
+ function wpcf_admin_widefat_table( $ID, $header, $rows = array(),
702
+ $empty_message = 'No results' ) {
703
+ $head = '';
704
+ $footer = '';
705
+ foreach ( $header as $key => $value ) {
706
+ $head .= '<th id="wpcf-table-' . $key . '">' . $value . '</th>' . "\r\n";
707
+ $footer .= '<th>' . $value . '</th>' . "\r\n";
708
+ }
709
+ echo '<table id="' . $ID . '" class="widefat" cellspacing="0">
710
+ <thead>
711
+ <tr>
712
+ ' . $head . '
713
+ </tr>
714
+ </thead>
715
+ <tfoot>
716
+ <tr>
717
+ ' . $footer . '
718
+ </tr>
719
+ </tfoot>
720
+ <tbody>
721
+ ';
722
+ $row = '';
723
+ if ( empty( $rows ) ) {
724
+ echo '<tr><td colspan="' . count( $header ) . '">' . $empty_message
725
+ . '</td></tr>';
726
+ } else {
727
+ foreach ( $rows as $row ) {
728
+ echo '<tr>';
729
+ foreach ( $row as $column_name => $column_value ) {
730
+ echo '<td class="wpcf-table-column-' . $column_name . '">';
731
+ echo $column_value;
732
+ echo '</td>' . "\r\n";
733
+ }
734
+ echo '</tr>' . "\r\n";
735
+ }
736
+ }
737
+ echo '
738
+ </tbody>
739
+ </table>' . "\r\n";
740
+ }
741
+
742
+ /**
743
+ * Admin tabs.
744
+ *
745
+ * @param type $tabs
746
+ * @param type $page
747
+ * @param type $default
748
+ * @param type $current
749
+ * @return string
750
+ */
751
+ function wpcf_admin_tabs( $tabs, $page, $default = '', $current = '' ) {
752
+ if ( empty( $current ) && isset( $_GET['tab'] ) ) {
753
+ $current = $_GET['tab'];
754
+ } else {
755
+ $current = $default;
756
+ }
757
+ $output = '<h2 class="nav-tab-wrapper">';
758
+ foreach ( $tabs as $tab => $name ) {
759
+ $class = ( $tab == $current ) ? ' nav-tab-active' : '';
760
+ $output .= "<a class='nav-tab$class' href='?page=$page&tab=$tab'>$name</a>";
761
+ }
762
+ $output .= '</h2>';
763
+ return $output;
764
+ }
765
+
766
+ /**
767
+ * Saves open fieldsets.
768
+ *
769
+ * @param type $action
770
+ * @param type $fieldset
771
+ */
772
+ function wpcf_admin_form_fieldset_save_toggle( $action, $fieldset ) {
773
+ $data = get_user_meta( get_current_user_id(), 'wpcf-form-fieldsets-toggle',
774
+ true );
775
+ if ( $action == 'open' ) {
776
+ $data[$fieldset] = 1;
777
+ } else if ( $action == 'close' ) {
778
+ unset( $data[$fieldset] );
779
+ }
780
+ update_user_meta( get_current_user_id(), 'wpcf-form-fieldsets-toggle', $data );
781
+ }
782
+
783
+ /**
784
+ * Check if fieldset is saved as open.
785
+ *
786
+ * @param type $fieldset
787
+ */
788
+ function wpcf_admin_form_fieldset_is_collapsed( $fieldset ) {
789
+ $data = get_user_meta( get_current_user_id(), 'wpcf-form-fieldsets-toggle',
790
+ true );
791
+ if ( empty( $data ) ) {
792
+ return true;
793
+ }
794
+ return array_key_exists( $fieldset, $data ) ? false : true;
795
+ }
796
+
797
+ /**
798
+ * Adds help on admin pages.
799
+ *
800
+ * @param type $contextual_help
801
+ * @param type $screen_id
802
+ * @param type $screen
803
+ * @return type
804
+ */
805
+ function wpcf_admin_plugin_help( $hook, $page ) {
806
+ global $wp_version;
807
+ $call = false;
808
+ $contextual_help = '';
809
+ $page = $page;
810
+ if ( isset( $page ) && isset( $_GET['page'] ) && $_GET['page'] == $page ) {
811
+ switch ( $page ) {
812
+ case 'wpcf-cf':
813
+ $call = 'custom_fields';
814
+ break;
815
+
816
+ case 'wpcf-ctt':
817
+ $call = 'custom_types_and_taxonomies';
818
+ break;
819
+
820
+ case 'wpcf-import-export':
821
+ $call = 'import_export';
822
+ break;
823
+
824
+ case 'wpcf-edit':
825
+ $call = 'edit_group';
826
+ break;
827
+
828
+ case 'wpcf-edit-type':
829
+ $call = 'edit_type';
830
+ break;
831
+
832
+ case 'wpcf-edit-tax':
833
+ $call = 'edit_tax';
834
+ break;
835
+ case 'wpcf':
836
+ $call = 'wpcf';
837
+ break;
838
+ }
839
+ }
840
+ if ( $call ) {
841
+ require_once WPCF_ABSPATH . '/help.php';
842
+ $contextual_help = wpcf_admin_help( $call, $contextual_help );
843
+ // WP 3.3 changes
844
+ if ( version_compare( $wp_version, '3.2.1', '>' ) ) {
845
+ set_current_screen( $hook );
846
+ $screen = get_current_screen();
847
+ if ( !is_null( $screen ) ) {
848
+ $args = array(
849
+ 'title' => __( 'Types', 'wpcf' ),
850
+ 'id' => 'wpcf',
851
+ 'content' => $contextual_help,
852
+ 'callback' => false,
853
+ );
854
+ $screen->add_help_tab( $args );
855
+ }
856
+ } else {
857
+ add_contextual_help( $hook, $contextual_help );
858
+ }
859
+ }
860
+ }
861
+
862
+ /**
863
+ * Promo texts
864
+ *
865
+ * @todo Move!
866
+ */
867
+ function wpcf_admin_promotional_text() {
868
+ $promo_tabs = get_option( '_wpcf_promo_tabs', false );
869
+ // random selection every one hour
870
+ if ( $promo_tabs ) {
871
+ $time = time();
872
+ $time_check = intval( $promo_tabs['time'] ) + 60 * 60;
873
+ if ( $time > $time_check ) {
874
+ $selected = mt_rand( 0, 3 );
875
+ $promo_tabs['selected'] = $selected;
876
+ $promo_tabs['time'] = $time;
877
+ update_option( '_wpcf_promo_tabs', $promo_tabs );
878
+ } else {
879
+ $selected = $promo_tabs['selected'];
880
+ }
881
+ } else {
882
+ $promo_tabs = array();
883
+ $selected = mt_rand( 0, 3 );
884
+ $promo_tabs['selected'] = $selected;
885
+ $promo_tabs['time'] = time();
886
+ update_option( '_wpcf_promo_tabs', $promo_tabs );
887
+ }
888
+ include WPCF_ABSPATH . '/marketing/helpful-links.php';
889
+ }
890
+
891
+ /**
892
+ * Collapsible scripts.
893
+ */
894
+ function wpcf_admin_load_collapsible() {
895
+ wp_enqueue_script( 'wpcf-collapsible',
896
+ WPCF_RES_RELPATH . '/js/collapsible.js', array('jquery'),
897
+ WPCF_VERSION );
898
+ wp_enqueue_style( 'wpcf-collapsible',
899
+ WPCF_RES_RELPATH . '/css/collapsible.css', array(), WPCF_VERSION );
900
+ $option = get_option( 'wpcf_toggle', array() );
901
+ if ( !empty( $option ) ) {
902
+ $setting = 'new Array("' . implode( '", "', array_keys( $option ) ) . '")';
903
+ wpcf_admin_add_js_settings( 'wpcf_collapsed', $setting );
904
+ }
905
+ }
906
+
907
+ /**
908
+ * Toggle button.
909
+ *
910
+ * @param type $div_id
911
+ * @return type
912
+ */
913
+ function wpcf_admin_toggle_button( $div_id ) {
914
+ return '<a href="'
915
+ . admin_url( 'admin-ajax.php?action=wpcf_ajax&wpcf_action=toggle&div='
916
+ . $div_id . '-toggle&_wpnonce='
917
+ . wp_create_nonce( 'toggle' ) )
918
+ . '" id="' . $div_id
919
+ . '" class="wpcf-collapsible-button"></a>';
920
+ }
921
+
922
+ /**
923
+ * Various delete/deactivate content actions.
924
+ *
925
+ * @param type $type
926
+ * @param type $arg
927
+ * @param type $action
928
+ */
929
+ function wpcf_admin_deactivate_content( $type, $arg, $action = 'delete' ) {
930
+ switch ( $type ) {
931
+ case 'post_type':
932
+ // Clean tax relations
933
+ if ( $action == 'delete' ) {
934
+ $custom = get_option( 'wpcf-custom-taxonomies', array() );
935
+ foreach ( $custom as $post_type => $data ) {
936
+ if ( empty( $data['supports'] ) ) {
937
+ continue;
938
+ }
939
+ if ( array_key_exists( $arg, $data['supports'] ) ) {
940
+ unset( $custom[$post_type]['supports'][$arg] );
941
+ }
942
+ }
943
+ update_option( 'wpcf-custom-taxonomies', $custom );
944
+ }
945
+ break;
946
+
947
+ case 'taxonomy':
948
+ // Clean post relations
949
+ if ( $action == 'delete' ) {
950
+ $custom = get_option( 'wpcf-custom-types', array() );
951
+ foreach ( $custom as $post_type => $data ) {
952
+ if ( empty( $data['taxonomies'] ) ) {
953
+ continue;
954
+ }
955
+ if ( array_key_exists( $arg, $data['taxonomies'] ) ) {
956
+ unset( $custom[$post_type]['taxonomies'][$arg] );
957
+ }
958
+ }
959
+ update_option( 'wpcf-custom-types', $custom );
960
+ }
961
+ break;
962
+
963
+ default:
964
+ break;
965
+ }
966
+ }
967
+
968
+ /**
969
+ * Loads teasers.
970
+ *
971
+ * @param type $teasers
972
+ */
973
+ function wpcf_admin_load_teasers( $teasers ) {
974
+ foreach ( $teasers as $teaser ) {
975
+ $file = WPCF_ABSPATH . '/plus/' . $teaser;
976
+ if ( file_exists( $file ) ) {
977
+ require_once $file;
978
+ }
979
+ }
980
+ }
981
+
982
+ /**
983
+ * Get temporary directory
984
+ *
985
+ * @return
986
+ */
987
+
988
+ function wpcf_get_temporary_directory()
989
+ {
990
+ $dir = sys_get_temp_dir();
991
+ if ( !empty( $dir ) && is_dir( $dir ) && is_writable( $dir ) ) {
992
+ return $dir;
993
+ }
994
+ $dir = wp_upload_dir();
995
+ $dir = $dir['basedir'];
996
+ return $dir;
997
+ }
998
+
999
+ function wpcf_welcome_panel()
1000
+ {
1001
+ if ( isset( $_GET['welcome'] ) ) {
1002
+ update_user_meta( get_current_user_id(), 'hide_wpcf_welcome_panel', 1 );
1003
+ }
1004
+ $classes = 'welcome-panel';
1005
+ $option = get_user_meta( get_current_user_id(), 'hide_wpcf_welcome_panel', true );
1006
+ if ( !empty($option) ) {
1007
+ $classes .= ' hidden';
1008
+ }
1009
+ ?>
1010
+ <div id="welcome-panel" class="<?php echo esc_attr( $classes ); ?>">
1011
+ <a class="welcome-panel-close" href="<?php echo esc_url( add_query_arg( 'welcome', 'hide' ) ); ?>"><?php _e( 'Dismiss' ); ?></a>
1012
+ <div class="welcome-panel-content">
1013
+ <h3><?php _e( 'Security improvement', 'wpcf' ); ?></h3>
1014
+ <p><?php _e( 'This version of Types has improved security when importing Types settings. Types settings that were saved with the older version of Types may not import all the data. You should export new Types settings if needed.', 'wpcf' ); ?></p>
1015
+ </div>
1016
+ </div>
1017
+ <?php
1018
+ }
1019
+
1020
+ /**
1021
+ * add types configuration to debug
1022
+ */
1023
+
1024
+ function wpcf_get_extra_debug_info($extra_debug)
1025
+ {
1026
+ $extra_debug['types'] = wpcf_get_settings();
1027
+ return $extra_debug;
1028
+ }
1029
+
1030
+ add_action( 'wpcf_admin_header', 'wpcf_welcome_panel', PHP_INT_SIZE );
1031
+ add_filter( 'icl_get_extra_debug_info', 'wpcf_get_extra_debug_info' );
1032
+
embedded/admin.php ADDED
@@ -0,0 +1,727 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ * $HeadURL: http://plugins.svn.wordpress.org/types/tags/1.6/embedded/admin.php $
5
+ * $LastChangedDate: 2014-08-22 01:02:43 +0000 (Fri, 22 Aug 2014) $
6
+ * $LastChangedRevision: 970205 $
7
+ * $LastChangedBy: brucepearson $
8
+ *
9
+ */
10
+ require_once(WPCF_EMBEDDED_ABSPATH . '/common/visual-editor/editor-addon.class.php');
11
+ require_once WPCF_EMBEDDED_ABSPATH . '/includes/post-relationship.php';
12
+
13
+ if ( defined( 'DOING_AJAX' ) ) {
14
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/ajax.php';
15
+ add_action( 'wp_ajax_wpcf_ajax', 'wpcf_ajax_embedded' );
16
+ }
17
+
18
+ /**
19
+ * admin_init hook.
20
+ */
21
+ function wpcf_embedded_admin_init_hook() {
22
+ // Add callbacks for post edit pages
23
+ add_action( 'load-post.php', 'wpcf_admin_edit_screen_load_hook' );
24
+ add_action( 'load-post-new.php', 'wpcf_admin_edit_screen_load_hook' );
25
+
26
+ // Meta boxes hook
27
+ add_action( 'add_meta_boxes', 'wpcf_admin_add_meta_boxes', 10, 2 );
28
+
29
+ // Add callback for 'media-upload.php'
30
+ add_filter( 'get_media_item_args', 'wpcf_get_media_item_args_filter' );
31
+
32
+ // Add save_post callback
33
+ add_action( 'save_post', 'wpcf_admin_save_post_hook', 10, 2 );
34
+
35
+ // Add Media callback
36
+ add_action( 'add_attachment', 'wpcf_admin_save_attachment_hook', 10 );
37
+ add_action( 'add_attachment', 'wpcf_admin_add_attachment_hook', 10 );
38
+ add_action( 'edit_attachment', 'wpcf_admin_save_attachment_hook', 10 );
39
+
40
+ // Render messages
41
+ wpcf_show_admin_messages();
42
+
43
+ // Render JS settings
44
+ add_action( 'admin_head', 'wpcf_admin_render_js_settings' );
45
+
46
+ // Media insert code
47
+ if ( (isset( $_GET['context'] ) && $_GET['context'] == 'wpcf-fields-media-insert')
48
+ || (isset( $_SERVER['HTTP_REFERER'] )
49
+ && strpos( $_SERVER['HTTP_REFERER'],
50
+ 'context=wpcf-fields-media-insert' ) !== false)
51
+ ) {
52
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields/file.php';
53
+ // Add types button
54
+ add_filter( 'attachment_fields_to_edit', 'wpcf_fields_file_attachment_fields_to_edit_filter', PHP_INT_MAX, 2 );
55
+ // Add JS
56
+ add_action( 'admin_head', 'wpcf_fields_file_media_admin_head' );
57
+ // Filter media TABs
58
+ add_filter( 'media_upload_tabs',
59
+ 'wpcf_fields_file_media_upload_tabs_filter' );
60
+ }
61
+
62
+ register_post_type( 'wp-types-group',
63
+ array(
64
+ 'public' => false,
65
+ 'label' => 'Types Groups',
66
+ 'can_export' => false,
67
+ )
68
+ );
69
+ register_post_type( 'wp-types-user-group',
70
+ array(
71
+ 'public' => false,
72
+ 'label' => 'Types User Groups',
73
+ 'can_export' => false,
74
+ )
75
+ );
76
+
77
+ add_filter( 'icl_custom_fields_to_be_copied',
78
+ 'wpcf_custom_fields_to_be_copied', 10, 2 );
79
+
80
+ // WPML editor filters
81
+ add_filter( 'icl_editor_cf_name', 'wpcf_icl_editor_cf_name_filter' );
82
+ add_filter( 'icl_editor_cf_description',
83
+ 'wpcf_icl_editor_cf_description_filter', 10, 2 );
84
+ add_filter( 'icl_editor_cf_style', 'wpcf_icl_editor_cf_style_filter', 10, 2 );
85
+ // Initialize translations
86
+ if ( function_exists( 'icl_register_string' )
87
+ && defined( 'WPML_ST_VERSION' )
88
+ && !get_option( 'wpcf_strings_translation_initialized', false ) ) {
89
+ wpcf_admin_bulk_string_translation();
90
+ update_option( 'wpcf_strings_translation_initialized', 1 );
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Add meta boxes hook.
96
+ *
97
+ * @param type $post_type
98
+ * @param type $post
99
+ */
100
+ function wpcf_admin_add_meta_boxes( $post_type, $post ) {
101
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
102
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
103
+
104
+ wpcf_add_meta_boxes( $post_type, $post );
105
+ }
106
+
107
+ /**
108
+ * save_post hook.
109
+ *
110
+ * @param type $post_ID
111
+ * @param type $post
112
+ */
113
+ function wpcf_admin_save_post_hook( $post_ID, $post ) {
114
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
115
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
116
+ wpcf_admin_post_save_post_hook( $post_ID, $post );
117
+ }
118
+
119
+ /**
120
+ * Save attachment hook.
121
+ *
122
+ * @param type $attachment_id
123
+ */
124
+ function wpcf_admin_add_attachment_hook( $attachment_id )
125
+ {
126
+ $post = get_post( $attachment_id );
127
+ wpcf_admin_post_add_attachment_hook( $attachment_id, $post );
128
+ }
129
+
130
+ /**
131
+ * Save attachment hook.
132
+ *
133
+ * @param type $attachment_id
134
+ */
135
+ function wpcf_admin_save_attachment_hook( $attachment_id ) {
136
+ $post = get_post( $attachment_id );
137
+ wpcf_admin_save_post_hook( $attachment_id, $post );
138
+ }
139
+
140
+ /**
141
+ * Triggers post procceses.
142
+ */
143
+ function wpcf_admin_edit_screen_load_hook() {
144
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
145
+ global $wpcf;
146
+ $wpcf->post = wpcf_admin_get_edited_post();
147
+ wpcf_admin_post_init( $wpcf->post );
148
+ }
149
+
150
+ /**
151
+ * Add styles to admin fields groups
152
+ */
153
+ function wpcf_admin_fields_postfields_styles(){
154
+
155
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
156
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
157
+
158
+ // $groups = wpcf_admin_fields_get_groups();
159
+ $groups = wpcf_admin_post_get_post_groups_fields( wpcf_admin_get_edited_post() );
160
+ echo '<style type="text/css">';
161
+ if ( !empty( $groups ) ) {
162
+ foreach ( $groups as $group ) {
163
+ echo str_replace( "}", "}\n",
164
+ wpcf_admin_get_groups_admin_styles_by_group( $group['id'] ) );
165
+ }
166
+ }
167
+ echo '</style>';
168
+ }
169
+
170
+ /**
171
+ * Initiates/returns specific form.
172
+ *
173
+ * @staticvar array $wpcf_forms
174
+ * @param type $id
175
+ * @param type $form
176
+ * @return array
177
+ */
178
+ function wpcf_form( $id, $form = array() ) {
179
+ static $wpcf_forms = array();
180
+ if ( isset( $wpcf_forms[$id] ) ) {
181
+ return $wpcf_forms[$id];
182
+ }
183
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/forms.php';
184
+ $new_form = new Enlimbo_Forms_Wpcf();
185
+ $new_form->autoHandle( $id, $form );
186
+ $wpcf_forms[$id] = $new_form;
187
+ return $wpcf_forms[$id];
188
+ }
189
+
190
+ /**
191
+ * Add submit button, cancel button and help link to the popup.
192
+ *
193
+ */
194
+ function wpcf_form_popup_helper( $form, $submit_text = '', $cancel_text = '',
195
+ $help = array() ) {
196
+ if ( $submit_text ) {
197
+ $form['submit'] = array(
198
+ '#type' => 'submit',
199
+ '#name' => 'submit',
200
+ '#value' => $submit_text,
201
+ '#attributes' => array('class' => 'button-primary'),
202
+ );
203
+ }
204
+ if ( $cancel_text ) {
205
+ $form['cancel'] = array(
206
+ '#type' => 'button',
207
+ '#name' => 'cancel',
208
+ '#value' => $cancel_text,
209
+ '#attributes' => array('class' => 'button-secondary',
210
+ 'onclick' => 'window.parent.jQuery(\'#TB_closeWindowButton\').click();return true;'),
211
+ '#before' => ' ',
212
+ );
213
+ }
214
+ if ( $help ) {
215
+ $form = array_reverse( $form, true );
216
+ $form['help'] = array(
217
+ '#type' => 'markup',
218
+ '#markup' => '<a class="wpcf-help-link" href="' . $help['url'] . '" target="_blank">' . $help['text'] . '</a>',
219
+ );
220
+ $form = array_reverse( $form, true );
221
+ }
222
+
223
+ return $form;
224
+ }
225
+
226
+ /**
227
+ * Renders form elements.
228
+ *
229
+ * @staticvar string $form
230
+ * @param type $elements
231
+ * @return type
232
+ */
233
+ function wpcf_form_simple( $elements ) {
234
+ static $form = NULL;
235
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/forms.php';
236
+ if ( is_null( $form ) ) {
237
+ $form = new Enlimbo_Forms_Wpcf();
238
+ }
239
+ return $form->renderElements( $elements );
240
+ }
241
+
242
+ /**
243
+ * Validates form elements (simple).
244
+ *
245
+ * @staticvar string $form
246
+ * @param type $elements
247
+ * @return type
248
+ */
249
+ function wpcf_form_simple_validate( &$elements ) {
250
+ static $form = NULL;
251
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/forms.php';
252
+ if ( is_null( $form ) ) {
253
+ $form = new Enlimbo_Forms_Wpcf();
254
+ }
255
+ $form->validate( $elements );
256
+ return $form;
257
+ }
258
+
259
+ /**
260
+ * Stores JS validation rules.
261
+ *
262
+ * @staticvar array $validation
263
+ * @param type $element
264
+ * @return array
265
+ */
266
+ function wpcf_form_add_js_validation( $element ) {
267
+ static $validation = array();
268
+ if ( $element == 'get' ) {
269
+ $temp = $validation;
270
+ $validation = array();
271
+ return $temp;
272
+ }
273
+ $validation[$element['#id']] = $element;
274
+ }
275
+
276
+ /**
277
+ * Renders JS validation rules.
278
+ *
279
+ * @global type $wpcf
280
+ * @param type $selector Can be CSS class or element ID
281
+ * @param type $echo
282
+ * @return string
283
+ */
284
+ function wpcf_form_render_js_validation( $selector = '.wpcf-form-validate',
285
+ $echo = true ) {
286
+ $output = WPCF_Validation::renderJsonData( $selector );
287
+ if ( $echo ) {
288
+ echo $output;
289
+ }
290
+ return $output;
291
+ }
292
+
293
+ /**
294
+ * wpcf_custom_fields_to_be_copied
295
+ *
296
+ * Hook the copy custom fields from WPML and remove any of the fields
297
+ * that wpcf will copy.
298
+ */
299
+ function wpcf_custom_fields_to_be_copied( $copied_fields, $original_post_id ) {
300
+
301
+ // see if this is one of our fields.
302
+ $groups = wpcf_admin_post_get_post_groups_fields( get_post( $original_post_id ) );
303
+
304
+ foreach ( $copied_fields as $id => $copied_field ) {
305
+ foreach ( $groups as $group ) {
306
+ if ( isset( $group['fields'] ) && is_array( $group['fields'] ) ) {
307
+ foreach ( $group['fields'] as $field ) {
308
+ if ( $copied_field == wpcf_types_get_meta_prefix( $field ) . $field['slug'] ) {
309
+ unset( $copied_fields[$id] );
310
+ }
311
+ }
312
+ }
313
+ }
314
+ }
315
+ return $copied_fields;
316
+ }
317
+
318
+ /**
319
+ * Holds validation messages.
320
+ *
321
+ * @param type $method
322
+ * @return type
323
+ */
324
+ function wpcf_admin_validation_messages( $method = false, $sprintf = '' ) {
325
+ $messages = array(
326
+ 'required' => __( 'This field is required', 'wpcf' ),
327
+ 'email' => __( 'Please enter a valid email address', 'wpcf' ),
328
+ 'url' => __( 'Please enter a valid URL address', 'wpcf' ),
329
+ 'date' => __( 'Please enter a valid date', 'wpcf' ),
330
+ 'digits' => __( 'Please enter numeric data', 'wpcf' ),
331
+ 'number' => __( 'Please enter numeric data', 'wpcf' ),
332
+ 'alphanumeric' => __( 'Letters, numbers, spaces or underscores only please',
333
+ 'wpcf' ),
334
+ 'nospecialchars' => __( 'Letters, numbers, spaces, underscores and dashes only please',
335
+ 'wpcf' ),
336
+ 'rewriteslug' => __( 'Letters, numbers, slashes, underscores and dashes only please',
337
+ 'wpcf' ),
338
+ 'negativeTimestamp' => __( 'Please enter a date after 1 January 1970.',
339
+ 'wpcf' ),
340
+ 'maxlength' => sprintf( __( 'Maximum of %s characters exceeded.', 'wpcf' ),
341
+ strval( $sprintf ) ),
342
+ );
343
+ if ( $method ) {
344
+ return isset( $messages[$method] ) ? $messages[$method] : '';
345
+ }
346
+ return $messages;
347
+ }
348
+
349
+ /**
350
+ * Adds admin notice.
351
+ *
352
+ * @param type $message
353
+ * @param type $class
354
+ */
355
+ function wpcf_admin_message( $message, $class = 'updated' ) {
356
+ add_action( 'admin_notices',
357
+ create_function( '$a=1, $class=\'' . $class . '\', $message=\''
358
+ . htmlentities( $message, ENT_QUOTES ) . '\'',
359
+ '$screen = get_current_screen(); if (!$screen->is_network) echo "<div class=\"message $class\"><p>" . stripslashes(html_entity_decode($message, ENT_QUOTES)) . "</p></div>";' ) );
360
+ }
361
+
362
+ /**
363
+ * Shows stored messages.
364
+ */
365
+ function wpcf_show_admin_messages() {
366
+ $messages = get_option( 'wpcf-messages', array() );
367
+ $messages_for_user = isset( $messages[get_current_user_id()] ) ? $messages[get_current_user_id()] : array();
368
+ $dismissed = get_option( 'wpcf_dismissed_messages', array() );
369
+ if ( !empty( $messages_for_user ) && is_array( $messages_for_user ) ) {
370
+ foreach ( $messages_for_user as $message_id => $message ) {
371
+ if ( !in_array( $message['keep_id'], $dismissed ) ) {
372
+ wpcf_admin_message( $message['message'], $message['class'] );
373
+ }
374
+ if ( empty( $message['keep_id'] )
375
+ || in_array( $message['keep_id'], $dismissed ) ) {
376
+ unset( $messages[get_current_user_id()][$message_id] );
377
+ }
378
+ }
379
+ }
380
+ update_option( 'wpcf-messages', $messages );
381
+ }
382
+
383
+ /**
384
+ * Stores admin notices if redirection is performed.
385
+ *
386
+ * @param type $message
387
+ * @param type $class
388
+ * @return type
389
+ */
390
+ function wpcf_admin_message_store( $message, $class = 'updated',
391
+ $keep_id = false ) {
392
+ $messages = get_option( 'wpcf-messages', array() );
393
+ $messages[get_current_user_id()][md5( $message )] = array(
394
+ 'message' => $message,
395
+ 'class' => $class,
396
+ 'keep_id' => $keep_id ? $keep_id : false,
397
+ );
398
+ update_option( 'wpcf-messages', $messages );
399
+ }
400
+
401
+ /**
402
+ * Admin notice with dismiss button.
403
+ *
404
+ * @param type $ID
405
+ * @param string $message
406
+ * @param type $store
407
+ * @return boolean
408
+ */
409
+ function wpcf_admin_message_dismiss( $ID, $message, $store = true ) {
410
+ $dismissed = get_option( 'wpcf_dismissed_messages', array() );
411
+ if ( in_array( $ID, $dismissed ) ) {
412
+ return false;
413
+ }
414
+ $message = $message . '<div style="float:right; margin:-15px 0 0 15px;"><a onclick="jQuery(this).parent().parent().fadeOut();jQuery.get(\''
415
+ . admin_url( 'admin-ajax.php?action=wpcf_ajax&amp;wpcf_action=dismiss_message&amp;id='
416
+ . $ID . '&amp;_wpnonce=' . wp_create_nonce( 'dismiss_message' ) ) . '\');return false;"'
417
+ . 'class="button-secondary" href="javascript:void(0);">'
418
+ . __( 'Dismiss', 'wpcf' ) . '</a></div>';
419
+ if ( $store ) {
420
+ wpcf_admin_message_store( $message, 'updated', $ID );
421
+ } else {
422
+ wpcf_admin_message( $message );
423
+ }
424
+ }
425
+
426
+ /**
427
+ * Checks if message is dismissed.
428
+ *
429
+ * @param type $message_id
430
+ * @return boolean
431
+ */
432
+ function wpcf_message_is_dismissed( $message_id ) {
433
+ return in_array( $message_id,
434
+ (array) get_option( '_wpcf_dismissed_messages', array() ) );
435
+ }
436
+
437
+ /**
438
+ * Adds dismissed message to record.
439
+ *
440
+ * @param type $ID
441
+ */
442
+ function wpcf_admin_message_set_dismissed( $ID ) {
443
+ $messages = get_option( 'wpcf_dismissed_messages', array() );
444
+ if ( !in_array( $ID, $messages ) ) {
445
+ $messages[] = $ID;
446
+ update_option( 'wpcf_dismissed_messages', $messages );
447
+ }
448
+ }
449
+
450
+ /**
451
+ * Removes dismissed message from record.
452
+ *
453
+ * @param type $ID
454
+ */
455
+ function wpcf_admin_message_restore_dismissed( $ID ) {
456
+ $messages = get_option( 'wpcf_dismissed_messages', array() );
457
+ $key = array_search( $ID, $messages );
458
+ if ( $key !== false ) {
459
+ unset( $messages[$key] );
460
+ update_option( 'wpcf_dismissed_messages', $messages );
461
+ }
462
+ }
463
+
464
+ /**
465
+ * Saves cookie.
466
+ *
467
+ * @param type $data
468
+ */
469
+ function wpcf_cookies_add( $data ) {
470
+ if ( isset( $_COOKIE['wpcf'] ) ) {
471
+ $data = array_merge( (array) $_COOKIE['wpcf'], $data );
472
+ }
473
+ setcookie( 'wpcf', $data, time() + $lifetime, COOKIEPATH, COOKIE_DOMAIN );
474
+ }
475
+
476
+ /**
477
+ * Renders page head.
478
+ *
479
+ * @see WPCF_Template::ajax_header()
480
+ * @global type $pagenow
481
+ * @param type $title
482
+ */
483
+ function wpcf_admin_ajax_head( $title = '' ) {
484
+
485
+ /*
486
+ * Since Types 1.2 and WP 3.5
487
+ * AJAX head is rendered differently
488
+ */
489
+ global $wp_version;
490
+ if ( version_compare( $wp_version, '3.4', '>' ) ) {
491
+ // WP Header
492
+ include WPCF_EMBEDDED_ABSPATH . '/includes/ajax/admin-header.php';
493
+ return true;
494
+ }
495
+
496
+ global $pagenow;
497
+ $hook_suffix = $pagenow;
498
+
499
+ ?>
500
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
501
+ <html xmlns="http://www.w3.org/1999/xhtml" <?php do_action( 'admin_xml_ns' ); ?> <?php language_attributes(); ?>>
502
+ <head>
503
+ <meta http-equiv="Content-Type" content="<?php bloginfo( 'html_type' ); ?>; charset=<?php echo get_option( 'blog_charset' ); ?>" />
504
+ <title><?php echo $title; ?></title>
505
+ <?php
506
+ if ( wpcf_compare_wp_version( '3.2.1', '<=' ) ) {
507
+ wp_admin_css( 'global' );
508
+ }
509
+ wp_admin_css();
510
+ wp_admin_css( 'colors' );
511
+ wp_admin_css( 'ie' );
512
+ // do_action('admin_enqueue_scripts', $hook_suffix);
513
+ do_action( "admin_print_styles-$hook_suffix" );
514
+ do_action( 'admin_print_styles' );
515
+ // do_action("admin_print_scripts-$hook_suffix");
516
+ do_action( 'admin_print_scripts' );
517
+ // do_action("admin_head-$hook_suffix");
518
+ // do_action('admin_head');
519
+ do_action( 'admin_head_wpcf_ajax' );
520
+
521
+ ?>
522
+ <style type="text/css">
523
+ html { height: auto; }
524
+ </style>
525
+
526
+ <script type="text/javascript">
527
+ // <![CDATA[
528
+ jQuery(document).ready(function(){
529
+ // Position the help link in the title bar.
530
+ var title = jQuery('#TB_closeAjaxWindow', window.parent.document);
531
+ if (title.length != 0) {
532
+ title.after(jQuery('.wpcf-help-link'));
533
+ }
534
+ });
535
+ // ]]>
536
+ </script>
537
+
538
+ <link rel="stylesheet" href="<?php echo WPCF_EMBEDDED_RES_RELPATH . '/css/basic.css'; ?>" type="text/css" media="all" />
539
+
540
+ </head>
541
+ <body style="padding: 20px;">
542
+ <?php
543
+ }
544
+
545
+ /**
546
+ * Renders page footer
547
+ *
548
+ * @see WPCF_Template::ajax_footer()
549
+ */
550
+ function wpcf_admin_ajax_footer() {
551
+
552
+ /*
553
+ * Since Types 1.2 and WP 3.5
554
+ * AJAX footer is rendered differently
555
+ */
556
+ global $wp_version, $wpcf;
557
+ if ( version_compare( $wp_version, '3.4', '>' ) ) {
558
+ // WP Footer
559
+ do_action( 'admin_footer_wpcf_ajax' );
560
+ include WPCF_EMBEDDED_ABSPATH . '/includes/ajax/admin-footer.php';
561
+ return true;
562
+ }
563
+
564
+ global $pagenow;
565
+ do_action( 'admin_footer_wpcf_ajax' );
566
+ // do_action('admin_footer', '');
567
+ // do_action('admin_print_footer_scripts');
568
+ // do_action("admin_footer-" . $pagenow);
569
+
570
+ ?>
571
+ </body>
572
+ </html>
573
+
574
+ <?php
575
+ }
576
+
577
+ /**
578
+ * Gets var from $_SERVER['HTTP_REFERER'].
579
+ *
580
+ * @param type $var
581
+ */
582
+ function wpcf_admin_get_var_from_referer( $var ) {
583
+ $value = false;
584
+ if ( isset( $_SERVER['HTTP_REFERER'] ) ) {
585
+ $parts = explode( '?', $_SERVER['HTTP_REFERER'] );
586
+ if ( !empty( $parts[1] ) ) {
587
+ parse_str( $parts[1], $vars );
588
+ if ( isset( $vars[$var] ) ) {
589
+ $value = $vars[$var];
590
+ }
591
+ }
592
+ }
593
+ return $value;
594
+ }
595
+
596
+ /**
597
+ * Adds JS settings.
598
+ *
599
+ * @staticvar array $settings
600
+ * @param type $id
601
+ * @param type $setting
602
+ * @return string
603
+ */
604
+ function wpcf_admin_add_js_settings( $id, $setting = '' ) {
605
+ static $settings = array();
606
+ $settings['wpcf_nonce_ajax_callback'] = '\'' . wp_create_nonce( 'execute' ) . '\'';
607
+ $settings['wpcf_cookiedomain'] = '\'' . COOKIE_DOMAIN . '\'';
608
+ $settings['wpcf_cookiepath'] = '\'' . COOKIEPATH . '\'';
609
+ if ( $id == 'get' ) {
610
+ $temp = $settings;
611
+ $settings = array();
612
+ return $temp;
613
+ }
614
+ $settings[$id] = $setting;
615
+ }
616
+
617
+ /**
618
+ * Renders JS settings.
619
+ *
620
+ * @return type
621
+ */
622
+ function wpcf_admin_render_js_settings() {
623
+ $settings = wpcf_admin_add_js_settings( 'get' );
624
+ if ( empty( $settings ) ) {
625
+ return '';
626
+ }
627
+
628
+ ?>
629
+ <script type="text/javascript">
630
+ //<![CDATA[
631
+ <?php
632
+ foreach ( $settings as $id => $setting ) {
633
+ if ( is_string( $setting ) ) {
634
+ $setting = trim( $setting, '\'' );
635
+ $setting = "'" . esc_js( $setting ) . "'";
636
+ } else {
637
+ $setting = intval( $setting );
638
+ }
639
+ echo 'var ' . $id . ' = ' . $setting . ';' . "\r\n";
640
+ }
641
+
642
+ ?>
643
+ //]]>
644
+ </script>
645
+ <?php
646
+ }
647
+
648
+ /**
649
+ * wpcf_get_fields
650
+ *
651
+ * returns the fields handled by types
652
+ *
653
+ */
654
+ function wpcf_get_post_meta_field_names() {
655
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
656
+ $fields = wpcf_admin_fields_get_fields();
657
+
658
+ $field_names = array();
659
+ foreach ( $fields as $field ) {
660
+ $field_names[] = wpcf_types_get_meta_prefix( $field ) . $field['slug'];
661
+ }
662
+
663
+ return $field_names;
664
+ }
665
+
666
+ /**
667
+ * Forces 'Insert into post' link when called from our WYSIWYG.
668
+ *
669
+ * @param array $args
670
+ * @return boolean
671
+ */
672
+ function wpcf_get_media_item_args_filter( $args ) {
673
+ if ( strpos( $_SERVER['SCRIPT_NAME'], '/media-upload.php' ) === false ) {
674
+ return $args;
675
+ }
676
+ if ( !empty( $_COOKIE['wpcfActiveEditor'] )
677
+ && strpos( $_COOKIE['wpcfActiveEditor'], 'wpcf-wysiwyg-' ) !== false ) {
678
+ $args['send'] = true;
679
+ }
680
+ return $args;
681
+ }
682
+
683
+ /**
684
+ * Gets post.
685
+ *
686
+ * @return type
687
+ */
688
+ function wpcf_admin_get_edited_post() {
689
+ // Global $post_ID holds post IDs for new posts too.
690
+ global $post_ID;
691
+ if ( !empty( $post_ID ) ) {
692
+ $post_id = $post_ID;
693
+ } else if ( isset( $_GET['post'] ) ) {
694
+ $post_id = (int) $_GET['post'];
695
+ } else if ( isset( $_POST['post_ID'] ) ) {
696
+ $post_id = (int) $_POST['post_ID'];
697
+ } else {
698
+ $post_id = 0;
699
+ }
700
+ if ( $post_id ) {
701
+ return get_post( $post_id );
702
+ } else {
703
+ return array();
704
+ }
705
+ }
706
+
707
+ /**
708
+ * Gets post type.
709
+ *
710
+ * @param type $post
711
+ * @return boolean
712
+ */
713
+ function wpcf_admin_get_edited_post_type( $post = null ) {
714
+ if ( !empty( $post->ID ) ) {
715
+ $post_type = get_post_type( $post );
716
+ } else {
717
+ if ( !isset( $_GET['post_type'] ) ) {
718
+ $post_type = 'post';
719
+ } else if ( in_array( $_GET['post_type'],
720
+ get_post_types( array('show_ui' => true) ) ) ) {
721
+ $post_type = $_GET['post_type'];
722
+ } else {
723
+ $post_type = 'post';
724
+ }
725
+ }
726
+ return $post_type;
727
+ }
embedded/bootstrap.php ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/cck/tags/1.6/embedded/bootstrap.php $
11
+ * $LastChangedDate: 2014-08-20 09:26:19 +0800 (Wed, 20 Aug 2014) $
12
+ * $LastChangedRevision: 26150 $
13
+ * $LastChangedBy: bruce $
14
+ *
15
+ */
16
+
17
+ // Main functions
18
+ require_once dirname( __FILE__ ) . '/functions.php';
19
+
20
+ /*
21
+ *
22
+ *
23
+ * If WPCF_VERSION is not defined - we're running embedded code
24
+ */
25
+ if ( !defined( 'WPCF_VERSION' ) ) {
26
+ // Mark that!
27
+ define( 'WPCF_RUNNING_EMBEDDED', true );
28
+ require_once dirname( __FILE__ ) . '/classes/loader.php';
29
+ }
30
+
31
+ /*
32
+ *
33
+ * Forced priority
34
+ */
35
+ if ( !defined( 'TYPES_INIT_PRIORITY' ) ) {
36
+ // Early start ( some plugins use 'init' with priority 0 ).
37
+ define( 'TYPES_INIT_PRIORITY', -1 );
38
+ }
39
+
40
+ /*
41
+ *
42
+ * Init
43
+ */
44
+ add_action( 'init', 'wpcf_embedded_init', TYPES_INIT_PRIORITY );
45
+
46
+ /*
47
+ *
48
+ *
49
+ * Define necessary constants
50
+ */
51
+ define( 'WPCF_EMBEDDED_ABSPATH', dirname( __FILE__ ) );
52
+ define( 'WPCF_EMBEDDED_INC_ABSPATH', WPCF_EMBEDDED_ABSPATH . '/includes' );
53
+ define( 'WPCF_EMBEDDED_RES_ABSPATH', WPCF_EMBEDDED_ABSPATH . '/resources' );
54
+
55
+ /*
56
+ *
57
+ * Always set DEBUG as false
58
+ */
59
+ if ( !defined( 'WPCF_DEBUG' ) ) {
60
+ define( 'WPCF_DEBUG', false );
61
+ }
62
+ if ( !defined( 'TYPES_DEBUG' ) ) {
63
+ define( 'TYPES_DEBUG', false );
64
+ }
65
+
66
+ /*
67
+ *
68
+ * Load common and local localization
69
+ */
70
+ if ( !defined( 'WPT_LOCALIZATION' ) ) {
71
+ require_once( WPCF_EMBEDDED_ABSPATH . '/common/localization/wpt-localization.php' );
72
+ }
73
+ new WPToolset_Localization( 'wpcf', WPCF_EMBEDDED_ABSPATH . '/locale', 'types-%s' );
74
+
75
+ /*
76
+ *
77
+ * Include common code.
78
+ */
79
+ if ( !defined( 'ICL_COMMON_FUNCTIONS' ) ) {
80
+ require_once WPCF_EMBEDDED_ABSPATH . '/common/functions.php';
81
+ if ( !defined( 'WPTOOLSET_COMMON_PATH' ) ) {
82
+ define( 'WPTOOLSET_COMMON_PATH', WPCF_EMBEDDED_ABSPATH . '/common' );
83
+ }
84
+ } else if ( !defined( 'WPTOOLSET_COMMON_PATH' ) ) {
85
+ //$__types_common_reflection = new ReflectionFunction( 'wpv_condition' );
86
+ //define( 'WPTOOLSET_COMMON_PATH', dirname( $__types_common_reflection->getFileName() ) );
87
+ define( 'WPTOOLSET_COMMON_PATH', WPCF_EMBEDDED_ABSPATH . '/common' );
88
+ }
89
+ if ( !defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
90
+ require_once WPTOOLSET_COMMON_PATH . '/toolset-forms/bootstrap.php';
91
+ }
92
+
93
+ /*
94
+ *
95
+ * Register theme options
96
+ */
97
+ wpcf_embedded_after_setup_theme_hook();
98
+
99
+ /*
100
+ *
101
+ *
102
+ * Set $wpcf global var as generic class
103
+ */
104
+ $GLOBALS['wpcf'] = new stdClass();
105
+
106
+ /**
107
+ * Main init hook.
108
+ *
109
+ * All rest of init processes are continued here.
110
+ * Sets locale, constants, includes...
111
+ *
112
+ * @todo Make sure plugin AND embedded code are calling this function on 'init'
113
+ * @todo Test priorities
114
+ */
115
+ function wpcf_embedded_init() {
116
+
117
+ global $types_instances, $wp_current_filter;
118
+
119
+ // Record hook
120
+ $types_instances['hook'] = $wp_current_filter;
121
+ $types_instances['init_queued'] = '#' . did_action( 'init' );
122
+ $types_instances['init_priority'] = TYPES_INIT_PRIORITY;
123
+ $types_instances['forced_embedded'] = defined( 'TYPES_LOAD_EMBEDDED' ) && TYPES_LOAD_EMBEDDED;
124
+
125
+ // Loader
126
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/loader.php';
127
+
128
+ do_action( 'wpcf_before_init' );
129
+ do_action( 'types_before_init' );
130
+
131
+ // Define necessary constants if plugin is not present
132
+ // This ones are skipped if used as embedded code!
133
+ if ( !defined( 'WPCF_VERSION' ) ) {
134
+ define( 'WPCF_VERSION', '1.6' );
135
+ define( 'WPCF_META_PREFIX', 'wpcf-' );
136
+ }
137
+
138
+ // If forced embedded mode use path to __FILE__
139
+ if ( ( defined( 'TYPES_LOAD_EMBEDDED' ) && TYPES_LOAD_EMBEDDED )
140
+ || !defined('WPCF_RELPATH') ) {
141
+ define( 'WPCF_EMBEDDED_RELPATH', wpcf_get_file_url( __FILE__, false ) );
142
+ } else {
143
+ define( 'WPCF_EMBEDDED_RELPATH', WPCF_RELPATH . '/embedded' );
144
+ }
145
+
146
+ // Define embedded paths
147
+ define( 'WPCF_EMBEDDED_INC_RELPATH', WPCF_EMBEDDED_RELPATH . '/includes' );
148
+ define( 'WPCF_EMBEDDED_RES_RELPATH', WPCF_EMBEDDED_RELPATH . '/resources' );
149
+
150
+ // TODO INCLUDES!
151
+ //
152
+ // Please add all required includes here
153
+ // Since Types 1.2 we can consider existing code as core.
154
+ // All new functionalities should be added as includes HERE
155
+ // and marked with @since Types $version.
156
+ //
157
+ // Thanks!
158
+ //
159
+
160
+ // Basic
161
+ /*
162
+ *
163
+ * Mind class extensions queue
164
+ */
165
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/fields.php';
166
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/field.php';
167
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/usermeta_field.php'; // Added by Gen, usermeta fields class
168
+
169
+ // Repeater
170
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/repeater.php';
171
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/usermeta_repeater.php'; // Added by Gen, usermeta repeater class
172
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/repetitive-fields-ordering.php';
173
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/repetitive-usermetafields-ordering.php';
174
+
175
+ // Relationship
176
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/relationship.php';
177
+
178
+ // Conditional
179
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/conditional.php';
180
+
181
+ // API
182
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/api.php';
183
+
184
+ // Validation
185
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/validation.php';
186
+
187
+ // Post Types
188
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/class.wpcf-post-types.php';
189
+
190
+ // Import Export
191
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/class.wpcf-import-export.php';
192
+
193
+ // Module manager
194
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/module-manager.php';
195
+
196
+ // WPML specific code
197
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/wpml.php';
198
+
199
+ // CRED specific code.
200
+ if ( defined( 'CRED_FE_VERSION' ) ) {
201
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/cred.php';
202
+ }
203
+
204
+ /*
205
+ *
206
+ *
207
+ * TODO This is a must for now.
208
+ * See if any fields need to be loaded.
209
+ *
210
+ * 1. Checkboxes - may be missing when submitted
211
+ */
212
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields/checkbox.php';
213
+
214
+
215
+ /*
216
+ *
217
+ *
218
+ * Use this call to load basic scripts and styles if necesary
219
+ * wpcf_enqueue_scripts();
220
+ */
221
+ require_once WPCF_EMBEDDED_ABSPATH . '/usermeta-init.php';
222
+ // Include frontend or admin code
223
+ if ( is_admin() ) {
224
+
225
+ require_once WPCF_EMBEDDED_ABSPATH . '/admin.php';
226
+
227
+ /*
228
+ * TODO Check if called twice
229
+ *
230
+ * Watch this! This is actually called twice everytime
231
+ * in both modes (plugin or embedded)
232
+ */
233
+ wpcf_embedded_admin_init_hook();
234
+ } else {
235
+ require_once WPCF_EMBEDDED_ABSPATH . '/frontend.php';
236
+ }
237
+
238
+ global $wpcf;
239
+
240
+ // TODO since Types 1.2 Continue adding new functionalities HERE
241
+ /*
242
+ * Consider code already there as core.
243
+ * Use hooks to add new functionalities
244
+ *
245
+ * Introduced new global object $wpcf
246
+ * Holds useful objects like:
247
+ * $wpcf->field - Field object (base item object)
248
+ * $wpcf->repeater - Repetitive field object
249
+ */
250
+
251
+ // Set debugging
252
+ if ( !defined( 'WPCF_DEBUG' ) ) {
253
+ define( 'WPCF_DEBUG', false );
254
+ } else if ( WPCF_DEBUG ) {
255
+ wp_enqueue_script( 'jquery' );
256
+ }
257
+ $wpcf->debug = new stdClass();
258
+ require WPCF_EMBEDDED_INC_ABSPATH . '/debug.php';
259
+ add_action( 'wp_footer', 'wpcf_debug', PHP_INT_MAX);
260
+ add_action( 'admin_footer', 'wpcf_debug', PHP_INT_MAX);
261
+
262
+ // Set field object
263
+ $wpcf->field = new WPCF_Field();
264
+
265
+ // Set fields object
266
+ $wpcf->fields = new WPCF_Fields();
267
+
268
+ // Set usermeta field object
269
+ $wpcf->usermeta_field = new WPCF_Usermeta_Field();
270
+
271
+ // Set repeater object
272
+ $wpcf->usermeta_repeater = new WPCF_Usermeta_Repeater();
273
+
274
+ // Set repeater object
275
+ $wpcf->repeater = new WPCF_Repeater();
276
+
277
+ // Set relationship object
278
+ $wpcf->relationship = new WPCF_Relationship();
279
+
280
+ // Set conditional object
281
+ $wpcf->conditional = new WPCF_Conditional();
282
+
283
+ // Set validate object
284
+ $wpcf->validation = new WPCF_Validation();
285
+
286
+ // Set import export objects
287
+ $wpcf->import = new WPCF_Import_Export();
288
+ $wpcf->export = new WPCF_Import_Export();
289
+
290
+ // Set post object
291
+ $wpcf->post = new stdClass();
292
+
293
+ // Set post types object
294
+ $wpcf->post_types = new WPCF_Post_Types();
295
+
296
+ // Define exceptions - privileged plugins and their data
297
+ $wpcf->toolset_post_types = array(
298
+ 'view', 'view-template', 'cred-form'
299
+ );
300
+ // 'attachment' = Media
301
+ //
302
+ $wpcf->excluded_post_types = array(
303
+ 'revision', 'view', 'view-template', 'cred-form', 'nav_menu_item', 'mediapage',
304
+ );
305
+
306
+ // Init loader
307
+ WPCF_Loader::init();
308
+
309
+ // Init custom types and taxonomies
310
+ wpcf_init_custom_types_taxonomies();
311
+
312
+
313
+ /*
314
+ * TODO Check why we enabled this
315
+ *
316
+ * I think because of CRED or Views using Types admin functions on frontend
317
+ * Does this need review?
318
+ */
319
+ if ( defined( 'DOING_AJAX' ) ) {
320
+ require_once WPCF_EMBEDDED_ABSPATH . '/frontend.php';
321
+ }
322
+
323
+ // Check if import/export request is going on
324
+ wpcf_embedded_check_import();
325
+
326
+ do_action( 'types_after_init' );
327
+ do_action( 'wpcf_after_init' );
328
+ }
embedded/classes/class.wpcf-import-export.php ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Import Export Class
4
+ */
5
+
6
+ /**
7
+ * Import Export Class
8
+ *
9
+ * @since Types 1.2
10
+ * @package Types
11
+ * @subpackage Import Export
12
+ * @version 0.1
13
+ * @category core
14
+ * @author srdjan <srdjan@icanlocalize.com>
15
+ */
16
+ class WPCF_Import_Export
17
+ {
18
+
19
+ /**
20
+ * Meta keys that are used to generate checksum.
21
+ *
22
+ * @var type
23
+ */
24
+ var $group_meta_keys = array(
25
+ '_wpcf_conditional_display',
26
+ '_wp_types_group_fields',
27
+ '_wp_types_group_post_types',
28
+ '_wp_types_group_templates',
29
+ '_wp_types_group_terms',
30
+ );
31
+
32
+ /**
33
+ * Restricted data - ommited from checksum, applies to all content types.
34
+ *
35
+ * @var type
36
+ */
37
+ var $_remove_data_keys = array('id', 'ID', 'menu_icon', 'wpml_action',
38
+ 'wpcf-post-type', 'wpcf-tax', 'hash', 'checksum');
39
+
40
+ /**
41
+ * Required Group meta keys
42
+ *
43
+ * @todo Make sure only this is used to fetch required meta_keys
44
+ * @return type
45
+ */
46
+ function get_group_meta_keys() {
47
+ return $this->group_meta_keys;
48
+ }
49
+
50
+ /**
51
+ * Fetches required meta ny meta_key
52
+ *
53
+ * @param type $group_id
54
+ * @return type
55
+ */
56
+ function get_group_checksum_data( $group_id ) {
57
+
58
+ $checksum = array();
59
+ $group = wpcf_admin_fields_get_group( $group_id );
60
+
61
+ if ( !empty( $group ) ) {
62
+ unset( $group['slug'], $group['name'] );
63
+ $checksum = $group;
64
+ foreach ( $this->group_meta_keys as $meta_key ) {
65
+ $meta = get_post_meta( $group['id'], $meta_key, true );
66
+ if ( !empty( $meta ) ) {
67
+ $checksum[$meta_key] = $meta;
68
+ }
69
+ }
70
+ }
71
+
72
+ return $checksum;
73
+ }
74
+
75
+ /**
76
+ * Sort by key recursively.
77
+ *
78
+ * @param type $data
79
+ * @return type
80
+ */
81
+ function ksort_by_string( $data ) {
82
+ if ( is_array( $data ) ) {
83
+ ksort( $data, SORT_STRING );
84
+ foreach ( $data as $k => $v ) {
85
+ $data[$k] = $this->ksort_by_string( $v );
86
+ }
87
+ }
88
+ return $data;
89
+ }
90
+
91
+ /**
92
+ * Generates checksums for defined content types.
93
+ *
94
+ * @param type $type
95
+ * @param type $item_id
96
+ * @return type
97
+ */
98
+ function generate_checksum( $type, $item_id = null ) {
99
+ switch ( $type ) {
100
+ case 'group':
101
+ $checksum = $this->get_group_checksum_data( $item_id );
102
+ break;
103
+
104
+ case 'field':
105
+ $checksum = wpcf_admin_fields_get_field( $item_id );
106
+ ksort( $checksum, SORT_STRING );
107
+ break;
108
+
109
+ case 'custom_post_type':
110
+ $checksum = wpcf_get_custom_post_type_settings( $item_id );
111
+
112
+ break;
113
+
114
+ case 'custom_taxonomy':
115
+ $checksum = wpcf_get_custom_taxonomy_settings( $item_id );
116
+ break;
117
+
118
+ default:
119
+ /*
120
+ * Enable $this->generate_checksum('test');
121
+ */
122
+ $checksum = $type;
123
+ break;
124
+ }
125
+
126
+ // Unset various not wanted data
127
+ foreach ( $this->_remove_data_keys as $key ) {
128
+ if ( isset( $checksum[$key] ) ) {
129
+ unset( $checksum[$key] );
130
+ }
131
+
132
+ }
133
+
134
+ //EMERSON: Remove empty conditional_display for consistent checksum computation with Module manager 1.1 during import
135
+ if (isset($checksum['data']['conditional_display'])) {
136
+ if (empty($checksum['data']['conditional_display'])) {
137
+
138
+ unset($checksum['data']['conditional_display']);
139
+ }
140
+ }
141
+
142
+ //EMERSON: Convert to integer value to provide correct checksum computation of this field during Module manager 1.1. import
143
+ if (isset($checksum['data']['repetitive'])) {
144
+
145
+ $checksum['data']['repetitive']=(integer)$checksum['data']['repetitive'];
146
+ }
147
+
148
+ //EMERSON: Remove __types_id and __types_title to provide correct checksum computation of CPT during Module manager 1.1. import
149
+ if ((isset($checksum['__types_id'])) || (isset($checksum['__types_title']))) {
150
+
151
+ unset($checksum['__types_id']);
152
+ unset($checksum['__types_title']);
153
+ }
154
+
155
+ //EMERSON: Change custom taxonomies data type to integer to provide correct hashes for MM 1.1.
156
+ if ((isset($checksum['taxonomies'])) && (!(empty($checksum['taxonomies'])))) {
157
+
158
+ foreach ($checksum['taxonomies'] as $tax_module_passed_name=>$tax_module_passed_value) {
159
+
160
+ if ($tax_module_passed_name!='category') {
161
+
162
+ $checksum['taxonomies'][$tax_module_passed_name]=(integer)$checksum['taxonomies'][$tax_module_passed_name];
163
+
164
+ }
165
+
166
+ }
167
+
168
+ }
169
+
170
+ return md5( maybe_serialize( $this->ksort_by_string( $checksum ) ) );
171
+ }
172
+
173
+ /**
174
+ * Generates and compares checksums.
175
+ *
176
+ * @param type $type
177
+ * @param type $item_id
178
+ * @param type $import_checksum Imported checksum
179
+ * @return type
180
+ */
181
+ function checksum( $type, $item_id, $import_checksum ) {
182
+ // Generate checksum of installed content
183
+ $checksum = $this->generate_checksum( $type, $item_id );
184
+ // Compare
185
+ return $checksum == strval( $import_checksum );
186
+ }
187
+
188
+ /**
189
+ * Checks if item exists.
190
+ *
191
+ * @param type $type
192
+ * @param type $item_id
193
+ * @return boolean
194
+ */
195
+ function item_exists( $type, $item_id ) {
196
+ switch ( $type ) {
197
+ case 'group':
198
+ $check = wpcf_admin_fields_get_group( $item_id );
199
+ break;
200
+
201
+ case 'field':
202
+ $check = wpcf_admin_fields_get_field( $item_id );
203
+ break;
204
+
205
+ case 'custom_post_type':
206
+ $check = wpcf_get_custom_post_type_settings( $item_id );
207
+ break;
208
+
209
+ case 'custom_taxonomy':
210
+ $check = wpcf_get_custom_taxonomy_settings( $item_id );
211
+ break;
212
+
213
+ default:
214
+ return false;
215
+ break;
216
+ }
217
+ return !empty( $check );
218
+ }
219
+
220
+ }
embedded/classes/class.wpcf-post-types.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ * Post Types Class
5
+ *
6
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/cck/tags/1.6/embedded/classes/class.wpcf-post-types.php $
7
+ * $LastChangedDate: 2014-05-13 18:49:25 +0800 (Tue, 13 May 2014) $
8
+ * $LastChangedRevision: 22267 $
9
+ * $LastChangedBy: marcin $
10
+ *
11
+ */
12
+
13
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/custom-types.php';
14
+
15
+ /**
16
+ * Post Types Class
17
+ *
18
+ * @since Types 1.2
19
+ * @package Types
20
+ * @subpackage Classes
21
+ * @version 0.1
22
+ * @category Post Type
23
+ * @author srdjan <srdjan@icanlocalize.com>
24
+ */
25
+ class WPCF_Post_Types
26
+ {
27
+
28
+ var $data;
29
+ var $settings;
30
+ var $messages = null;
31
+
32
+ function set($post_type, $settings = null)
33
+ {
34
+ $data = get_post_type_object( $post_type );
35
+ if ( empty( $data ) ) {
36
+
37
+ }
38
+ $this->data = $data;
39
+ $this->settings = is_null( $settings ) ? $this->get_settings( $post_type ) : (array) $settings;
40
+ }
41
+
42
+ function _get_labels($data)
43
+ {
44
+ $data = (array) $data;
45
+ return isset( $data['labels'] ) ? (object) $data['labels'] : new stdClass();
46
+ }
47
+
48
+ function check_singular_plural_match($data = null)
49
+ {
50
+ if ( is_null( $data ) ) {
51
+ $data = $this->data;
52
+ }
53
+ $labels = $this->_get_labels( $data );
54
+ if ( array_key_exists( 'ignore', $labels ) && 'on' == $labels->ignore ) {
55
+ return false;
56
+ }
57
+ return strtolower( $labels->singular_name ) == strtolower( $labels->name );
58
+ }
59
+
60
+ function message($message_id)
61
+ {
62
+ $this->_set_messenger();
63
+ return isset( $this->messages[$message_id] ) ? $this->messages[$message_id] : 'Howdy!';
64
+ }
65
+
66
+ function _set_messenger()
67
+ {
68
+ if ( is_null( $this->messages ) ) {
69
+ include dirname( __FILE__ ) . '/post-types/messages.php';
70
+ $this->messages = $messages;
71
+ }
72
+ }
73
+
74
+ function get_settings($post_type)
75
+ {
76
+ return wpcf_get_custom_post_type_settings( $post_type );
77
+ }
78
+
79
+ }
embedded/classes/conditional.php ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Conditional class
4
+ *
5
+ * Few break-points summarized:
6
+ * 1. Wrapping fields when in form
7
+ * 2. Filtering AJAX check
8
+ * 3. Calling JS
9
+ */
10
+
11
+ /**
12
+ * Conditional class.
13
+ *
14
+ * Very useful, should be used to finish small tasks for conditional field.
15
+ *
16
+ * Example:
17
+ *
18
+ * // Setup field
19
+ * global $wpcf;
20
+ * $my_field = new WPCF_Conditional();
21
+ * $my_field->set($wpcf->post, wpcf_admin_fields_get_field('image'));
22
+ *
23
+ * // Use it
24
+ * $is_valid = $my_field->evaluate();
25
+ *
26
+ * Generic instance can be found in global $wpcf.
27
+ * global $wpcf;
28
+ * $wpcf->conditional->set(...);
29
+ *
30
+ * @since Types 1.2
31
+ * @package Types
32
+ * @subpackage Classes
33
+ * @version 0.1
34
+ * @category core
35
+ * @author srdjan <srdjan@icanlocalize.com>
36
+ */
37
+ class WPCF_Conditional extends WPCF_Field
38
+ {
39
+
40
+ /**
41
+ * Holds all processed fields using one instance.
42
+ */
43
+ var $collected = null;
44
+
45
+ /**
46
+ * Holds all triggers on which check should fire.
47
+ *
48
+ * @var type
49
+ */
50
+ var $triggers = null;
51
+
52
+ /**
53
+ * Marks if currently processed field is valid.
54
+ *
55
+ *
56
+ * @var type
57
+ */
58
+ var $passed = true;
59
+
60
+ /**
61
+ * Trigger CSS class.
62
+ * @var type
63
+ */
64
+ var $css_class_trigger = 'wpcf-conditional-check-trigger';
65
+
66
+ /**
67
+ * Field CSS class.
68
+ * @var type
69
+ */
70
+ var $css_class_field = 'wpcf-conditional';
71
+
72
+ /**
73
+ * Evaluate object.
74
+ *
75
+ * @var type
76
+ */
77
+ var $evaluate = null;
78
+
79
+ function __construct() {
80
+ parent::__construct();
81
+ }
82
+
83
+ function set( $post, $cf ) {
84
+ parent::set( $post, $cf );
85
+ }
86
+
87
+ /**
88
+ * Collect all fields and conditions.
89
+ */
90
+ function collect() {
91
+ if ( is_null( $this->triggers ) ) {
92
+ $this->collected = array();
93
+ $this->triggers = array();
94
+ $fields = WPCF_Fields::getFields();
95
+ if ( is_array( $fields ) && !empty( $fields ) ) {
96
+ foreach ( $fields as $f_id => $f ) {
97
+ if ( !empty( $f['data']['conditional_display']['conditions'] ) ) {
98
+ foreach ( $f['data']['conditional_display']['conditions'] as $condition ) {
99
+ $this->collected[$f_id] = $condition;
100
+ if ( !empty( $condition['field'] ) ) {
101
+ $this->triggers[$condition['field']][$f_id][] = $condition;
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Checks if field is conditional.
112
+ *
113
+ * @param type $field
114
+ * @return type
115
+ */
116
+ function is_conditional( $field = array() ) {
117
+ if ( is_array( $field ) ) {
118
+ return !empty( $field['data']['conditional_display']['conditions'] );
119
+ } else {
120
+ $this->collect();
121
+ $field_id = $this->__get_slug_no_prefix( strval( $field ) );
122
+ return isset( $this->collected[$field_id] );
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Checks if field is check trigger.
128
+ *
129
+ * @param type $field
130
+ * @return type
131
+ */
132
+ function is_trigger( $field = array() ) {
133
+ $this->collect();
134
+ return !empty( $this->triggers[$field['id']] );
135
+ }
136
+
137
+ /**
138
+ * Enqueues scripts.
139
+ */
140
+ function add_js() {
141
+ wp_enqueue_script( 'types-conditional' );
142
+ wpcf_admin_add_js_settings( 'wpcfConditionalVerify_nonce',
143
+ wp_create_nonce( 'cd_verify' )
144
+ );
145
+ }
146
+
147
+ /**
148
+ * Wraps each trigger check field with $this->css_class_trigger
149
+ * and corespondive classes.
150
+ *
151
+ * @param type $element
152
+ * @return type
153
+ */
154
+ function wrap_trigger( $element = array() ) {
155
+
156
+ // Set attribute class to $this->css_class_trigger
157
+ if ( isset( $element['#attributes']['class'] ) ) {
158
+ $element['#attributes']['class'] .= ' ' . $this->css_class_trigger;
159
+ } else {
160
+ $element['#attributes']['class'] = $this->css_class_trigger;
161
+ }
162
+
163
+ /*
164
+ *
165
+ * Radios needs per option
166
+ */
167
+ if ( $element['#type'] == 'radios'
168
+ && ( isset( $element['#options'] ) && is_array( $element['#options'] )) ) {
169
+ foreach ( $element['#options'] as $_k => $_v ) {
170
+ if ( isset( $_v['#attributes']['class'] ) ) {
171
+ $element['#options'][$_k]['#attributes']['class'] .= ' ' . $this->css_class_trigger;
172
+ } else {
173
+ $element['#options'][$_k]['#attributes']['class'] = $this->css_class_trigger;
174
+ }
175
+ }
176
+ }
177
+
178
+ return apply_filters( 'types_conditional_field_trigger', $element, $this );
179
+ }
180
+
181
+ /**
182
+ * Wraps each field with $this->css_class_field and corespondive classes.
183
+ *
184
+ * @param type $element
185
+ * @return type
186
+ */
187
+ function wrap( $element = array() ) {
188
+ if ( !empty( $element ) ) {
189
+ $passed = $this->evaluate();
190
+ if ( !$passed ) {
191
+ $wrap = '<div class="' . $this->css_class_field . ' '
192
+ . $this->css_class_field . '-failed" style="display:none;">';
193
+ } else {
194
+ $wrap = '<div class="' . $this->css_class_field . ' '
195
+ . $this->css_class_field . '-passed">';
196
+ }
197
+ if ( isset( $element['#before'] ) ) {
198
+ $element['#before'] = $wrap . $element['#before'];
199
+ } else {
200
+ $element['#before'] = $wrap;
201
+ }
202
+ if ( isset( $element['#after'] ) ) {
203
+ $element['#after'] = $element['#after'] . '</div>';
204
+ } else {
205
+ $element['#after'] = '</div>';
206
+ }
207
+ }
208
+
209
+ return apply_filters( 'types_conditional_field', $element, $this );
210
+ }
211
+
212
+ /**
213
+ * Evaluates if check passed.
214
+ *
215
+ * @return type
216
+ */
217
+ function evaluate() {
218
+ WPCF_Loader::loadClass( 'evaluate' );
219
+ $this->passed = WPCF_Evaluate::evaluate( $this );
220
+ return $this->passed;
221
+ }
222
+
223
+ /**
224
+ * Processes AJAX call 'cd_verify'.
225
+ *
226
+ * @param type $data
227
+ * @return type
228
+ */
229
+ function ajaxVerify( $data ) {
230
+ WPCF_Loader::loadClass( 'helper.ajax' );
231
+ return WPCF_Helper_Ajax::conditionalVerify( $data );
232
+ }
233
+
234
+ }
embedded/classes/editor.php ADDED
@@ -0,0 +1,520 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * WP Post Editor class.
4
+ */
5
+
6
+ /**
7
+ * WP Post Editor class.
8
+ *
9
+ * @since Types 1.3.2
10
+ * @package Types
11
+ * @subpackage Classes
12
+ * @version 0.1
13
+ * @category Field
14
+ * @author srdjan <srdjan@icanlocalize.com>
15
+ */
16
+ class WPCF_Editor
17
+ {
18
+
19
+ /**
20
+ * Settings.
21
+ * @var type
22
+ */
23
+ private $_settings = array();
24
+
25
+ /**
26
+ * Active Field.
27
+ * @var type
28
+ */
29
+ var $field = array();
30
+
31
+ /**
32
+ * Context (postmeta|usermeta).
33
+ * @var type
34
+ */
35
+ private $_meta_type = 'post';
36
+
37
+ /**
38
+ * Post object.
39
+ * @var type
40
+ */
41
+ private $_post;
42
+
43
+ /**
44
+ * Collected data.
45
+ * @var type
46
+ */
47
+ private $_data = array();
48
+
49
+ /**
50
+ * Construct function.
51
+ */
52
+ function __construct() {
53
+ wp_register_script( 'types-editor',
54
+ WPCF_EMBEDDED_RES_RELPATH . '/js/editor.js',
55
+ array('jquery', 'types-knockout'), WPCF_VERSION, true );
56
+ wp_register_style( 'types-editor',
57
+ WPCF_EMBEDDED_RES_RELPATH . '/css/editor.css',
58
+ array('admin-bar', 'wp-admin', 'buttons', 'media-views', 'toolset-font-awesome'),
59
+ WPCF_VERSION );
60
+ wp_register_style( 'types-editor-cloned',
61
+ WPCF_EMBEDDED_RES_RELPATH . '/css/editor-cloned.css', array(),
62
+ WPCF_VERSION );
63
+ }
64
+
65
+ /**
66
+ * Renders Thickbox content.
67
+ *
68
+ * Field should provide callback function
69
+ * that will be called automatically.
70
+ *
71
+ * Function should be named like:
72
+ * 'wpcf_fields_' . $field_type . '_editor_callback'
73
+ * e.g. 'wpcf_fields_checkbox__editor_callback'
74
+ *
75
+ * Function should return array with elements:
76
+ * 'supports' - parameters or other feature supported, e.g. 'styling' will
77
+ * enable 'Styling' options
78
+ *
79
+ * Tabs is array with elements:
80
+ * 'menu_title' - used for menu title
81
+ * 'title' - used for main title
82
+ * 'content' - HTML content of tab
83
+ *
84
+ * @param type $field
85
+ * @param type $meta_type
86
+ * @param type $post_id
87
+ * @param string $shortcode
88
+ */
89
+ function frame( $field, $meta_type = 'postmeta', $post_id = -1,
90
+ $shortcode = null, $callback = false, $views_usermeta = false ) {
91
+
92
+ global $wp_version, $wpcf;
93
+
94
+ // Queue rendering JS settings
95
+ add_action( 'admin_print_footer_scripts',
96
+ array($this, 'renderTedSettings'), 1 );
97
+
98
+ wp_enqueue_script( 'types' );
99
+ wp_enqueue_script( 'types-knockout' );
100
+ wp_enqueue_script( 'types-editor' );
101
+ wp_enqueue_script( 'wp-pointer' );
102
+ wp_enqueue_style( 'types-editor' );
103
+ wp_enqueue_style( 'wp-pointer' );
104
+ wp_enqueue_style( 'toolset-font-awesome' );
105
+
106
+ // Load cloned WP Media Modal CSS
107
+ if ( version_compare( $wp_version, '3.5', '<' ) ) {
108
+ wp_enqueue_style( 'types-editor-cloned' );
109
+ }
110
+
111
+ $this->field = $field;
112
+ $this->_meta_type = $meta_type;
113
+ $this->_post = get_post( $post_id );
114
+ $this->_settings = is_null( $shortcode ) ? array() : $this->shortcodeToParameters( $shortcode );
115
+ $this->callback = $callback;
116
+ $this->_data = array(
117
+ 'meta_type' => $meta_type,
118
+ 'field' => $field,
119
+ 'field_type_data' => WPCF_Fields::getFieldTypeData( $field['type'] ),
120
+ 'settings' => array(),
121
+ 'tabs' => array(),
122
+ 'supports' => array(),
123
+ 'post' => $this->_post,
124
+ 'post_types' => get_post_types( array('show_ui' => true) ),
125
+ 'style' => isset( $this->_settings['style'] ) ? $this->_settings['style'] : '',
126
+ 'class' => isset( $this->_settings['class'] ) ? $this->_settings['class'] : '',
127
+ 'output' => 'html',
128
+ 'user_form' => '',
129
+ );
130
+
131
+ // Set title if updated
132
+ if ( !is_null( $shortcode ) ) {
133
+ $this->_data['title'] = sprintf( __( 'Update %s', 'wpcf' ),
134
+ $this->_data['field_type_data']['title'] );
135
+ $this->_data['submit_button_title'] = __( 'Update shortcode', 'wpcf' );
136
+ }
137
+
138
+ // Exclude post types
139
+ foreach ( $wpcf->excluded_post_types as $_post_type ) {
140
+ unset( $this->_data['post_types'][$_post_type] );
141
+ }
142
+
143
+ /*
144
+ * Callback
145
+ */
146
+ $function = 'wpcf_fields_' . $field['type'] . '_editor_callback';
147
+ if ( function_exists( $function ) ) {
148
+ // Main callback
149
+ $callback = call_user_func( $function, $field, $this->_settings,
150
+ $this->_meta_type, $this->_post );
151
+ // Add supports
152
+ if ( !empty( $callback['supports'] ) && is_array( $callback['supports'] ) ) {
153
+ $this->_data['supports'] = $callback['supports'];
154
+ }
155
+ // Add tabs
156
+ if ( !empty( $callback['tabs'] ) && is_array( $callback['tabs'] ) ) {
157
+ $this->_data['tabs'] = $callback['tabs'];
158
+ }
159
+ // Unify settings
160
+ if ( !empty( $callback['settings'] ) && is_array( $callback['settings'] ) ) {
161
+ $this->_settings = array_merge( $this->_settings,
162
+ self::sanitizeParams( $callback['settings'], 'array' ) );
163
+ }
164
+ }
165
+
166
+ // If no tabs
167
+ if ( empty( $this->_data['tabs'] ) ) {
168
+ $this->_data['tabs']['display'] = array(
169
+ 'menu_title' => __( 'Display', 'wpcf' ),
170
+ 'title' => __( 'Display', 'wpcf' ),
171
+ 'content' => sprintf( __( 'There are no additional display options for the %s field.',
172
+ 'wpcf' ),
173
+ $this->_data['field_type_data']['title'] ),
174
+ );
175
+ }
176
+
177
+ // Add User ID form
178
+ if ( $this->_meta_type == 'usermeta' ) {
179
+ if ( !$views_usermeta ){
180
+ $this->_data['user_form'] = wpcf_form_simple( wpcf_get_usermeta_form_addon( $this->_settings ) );
181
+ $this->_data['supports'][] = 'user_id';
182
+ }
183
+
184
+ } else {
185
+ // Add Post ID form
186
+ $this->_data['supports'][] = 'post_id';
187
+ }
188
+
189
+ // Get parents
190
+ if ( !empty( $this->_post->ID ) ) {
191
+ $this->_data['parents'] = WPCF_Relationship::get_parents( $this->_post );
192
+ }
193
+
194
+ // Set icons
195
+ $icons = array(
196
+ 'audio' => 'icon-music',
197
+ 'checkbox' => 'icon-check',
198
+ 'checkboxes' => 'icon-checkboxes',
199
+ 'colorpicker' => 'icon-tint',
200
+ 'date' => 'icon-calendar',
201
+ 'email' => 'icon-envelope-alt',
202
+ 'embed' => 'icon-youtube-play',
203
+ 'file' => 'icon-file-alt',
204
+ 'image' => 'icon-picture',
205
+ 'map' => 'icon-map-marker',
206
+ 'numeric' => 'icon-numeric',
207
+ 'phone' => 'icon-phone',
208
+ 'radio' => 'icon-radio-button',
209
+ 'select' => 'icon-select-box',
210
+ 'skype' => 'icon-skype',
211
+ 'textarea' => 'icon-text-area',
212
+ 'textfield' => 'icon-text-field',
213
+ 'url' => 'icon-link',
214
+ 'video' => 'icon-film',
215
+ 'wysiwyg' => 'icon-wysiwyg',
216
+ );
217
+ $this->_data['icon_class'] = isset( $icons[$field['type']] ) ? $icons[$field['type']] : 'icon-text-field';
218
+
219
+ // Is repetitive
220
+ $this->_data['is_repetitive'] = (bool) types_is_repetitive( $field );
221
+ if ( $this->_data['is_repetitive'] ) {
222
+ $this->_data['supports'][] = 'separator';
223
+ }
224
+
225
+ // Render header
226
+ wpcf_admin_ajax_head();
227
+
228
+ // Check if submitted
229
+ $this->_thickbox_check_submit();
230
+
231
+ // Render form
232
+ echo '<form method="post" action="" id="types-editor-modal-form">';
233
+ echo WPCF_Loader::view( 'editor-modal-window', $this->_data );
234
+ wp_nonce_field( 'types_editor_frame', '__types_editor_nonce' );
235
+ echo '</form>';
236
+
237
+ // Render footer
238
+ wpcf_admin_ajax_footer();
239
+ }
240
+
241
+ /**
242
+ * Renders JS settings queued after editor.js
243
+ */
244
+ function renderTedSettings() {
245
+ $_field = $this->field;
246
+ echo "\r\n" . "\r\n" . '<script type="text/javascript">' . "\r\n"
247
+ . '//<![CDATA[' . "\r\n"
248
+ . 'var ted = {' . "\r\n"
249
+ . ' fieldID: ' . json_encode( sanitize_title( $_field['id'] ) ) . ',' . "\r\n"
250
+ . ' fieldType: ' . json_encode( sanitize_title( $_field['type'] ) ) . ',' . "\r\n"
251
+ . ' fieldTitle: ' . json_encode( strval( self::sanitizeParams( $_field['name'] ) ) ) . ',' . "\r\n"
252
+ . ' params: ' . json_encode( $this->_settings ) . ',' . "\r\n"
253
+ . ' repetitive: ' . json_encode( $this->_data['is_repetitive'] ) . ',' . "\r\n"
254
+ . ' metaType: ' . json_encode( $this->_meta_type ) . ',' . "\r\n"
255
+ . ' postID: ' . json_encode( !empty( $this->_post->ID ) ? (int) $this->_post->ID : -1 ) . ',' . "\r\n"
256
+ . ' callback: ' . json_encode( $this->callback ) . ',' . "\r\n"
257
+ . ' supports: ' . json_encode( $this->_data['supports'] ) . '' . "\r\n"
258
+ . '};' . "\r\n"
259
+ . '//]]>' . "\r\n"
260
+ . '</script>' . "\r\n" . "\r\n";
261
+ }
262
+
263
+ /**
264
+ * Process if submitted.
265
+ *
266
+ * Field should provide callback function
267
+ * that will be called automatically.
268
+ *
269
+ * Function should be named like:
270
+ * 'wpcf_fields_' . $field_type . '_editor_submit'
271
+ * e.g. 'wpcf_fields_checkbox_editor_submit'
272
+ *
273
+ * Function should return shortcode string.
274
+ */
275
+ function _thickbox_check_submit() {
276
+ if ( !empty( $_POST['__types_editor_nonce'] )
277
+ && wp_verify_nonce( $_POST['__types_editor_nonce'],
278
+ 'types_editor_frame' ) ) {
279
+
280
+ $function = 'wpcf_fields_' . strtolower( $this->field['type'] )
281
+ . '_editor_submit';
282
+
283
+ if ( function_exists( $function ) ) {
284
+ /*
285
+ * Callback
286
+ */
287
+ $shortcode = call_user_func( $function, $_POST, $this->field,
288
+ $this->_meta_type );
289
+ } else {
290
+ /*
291
+ * Generic
292
+ */
293
+ if ( $this->_meta_type == 'usermeta' ) {
294
+ $add = wpcf_get_usermeta_form_addon_submit();
295
+ $shortcode = wpcf_usermeta_get_shortcode( $this->field, $add );
296
+ } else {
297
+ $shortcode = wpcf_fields_get_shortcode( $this->field );
298
+ }
299
+ }
300
+
301
+ if ( !empty( $shortcode ) ) {
302
+ /**
303
+ * remove <script> tag from all data
304
+ * remove not allowed tags from shortcode using wp_kses_post
305
+ */
306
+ $shortcode = preg_replace( '@</?script[^>]*>@im', '', wp_kses_post($shortcode) );
307
+ // Add additional parameters if required
308
+ $shortcode = $this->_add_parameters_to_shortcode( $shortcode,
309
+ $_POST );
310
+ // Insert shortcode
311
+ echo '<script type="text/javascript">jQuery(function(){tedFrame.close(\''
312
+ . $shortcode . '\', \'' . esc_js( $shortcode ) . '\');});</script>';
313
+ } else {
314
+ echo '<div class="message error"><p>'
315
+ . __( 'Shortcode generation failed', 'wpcf' ) . '</p></div>';
316
+ }
317
+
318
+ wpcf_admin_ajax_footer();
319
+ die();
320
+ }
321
+ }
322
+
323
+ /**
324
+ * Adds additional parameters if required.
325
+ *
326
+ * @param type $shortcode
327
+ * @param type $data
328
+ * @return type
329
+ */
330
+ function _add_parameters_to_shortcode( $shortcode, $data ) {
331
+ $raw_mode = isset( $data['raw_mode'] ) && $data['raw_mode'] == '1';
332
+ if ( !$raw_mode ) {
333
+ if ( isset( $data['class'] ) && $data['class'] != '' ) {
334
+ $shortcode = preg_replace( '/\[types([^\]]*)/',
335
+ '$0 class="' . esc_attr(strip_tags($data['class'])) . '"', $shortcode );
336
+ }
337
+ if ( $this->supports( 'style' ) && isset( $data['style'] ) && $data['style'] != '' ) {
338
+ $shortcode = preg_replace( '/\[types([^\]]*)/',
339
+ '$0 style="' . esc_attr(strip_tags($data['style'])) . '"', $shortcode );
340
+ }
341
+ if ( isset( $data['output'] ) && $data['output'] == 'html' ) {
342
+ $shortcode = preg_replace( '/\[types([^\]]*)/',
343
+ '$0 output="html"', $shortcode );
344
+ }
345
+ }
346
+ if ( !empty( $data['separator'] ) ) {
347
+ if ( $data['separator'] == 'custom' ) {
348
+ $data['separator'] = isset( $data['separator_custom'] ) ? wp_kses_post($data['separator_custom']) : '';
349
+ }
350
+ $shortcode = preg_replace( '/\[types([^\]]*)/',
351
+ '$0 separator="'
352
+ . htmlentities( $data['separator'] ) . '"', $shortcode );
353
+ }
354
+ if ( isset( $data['show_name'] ) && $data['show_name'] == '1' ) {
355
+ $shortcode = preg_replace( '/\[types([^\]]*)/',
356
+ '$0 show_name="true"', $shortcode );
357
+ }
358
+ if ( isset( $data['raw_mode'] ) && $data['raw_mode'] == '1' ) {
359
+ $shortcode = preg_replace( '/\[types([^\]]*)/', '$0 output="raw"',
360
+ $shortcode );
361
+ }
362
+ if ( isset( $data['post_id'] ) && $data['post_id'] != 'current' ) {
363
+ $post_id = 'id=';
364
+ if ( $data['post_id'] == 'post_id' ) {
365
+ $post_id .= '"' . preg_replace( '/[^\d]+/', '', $data['specific_post_id'] ) . '"';
366
+ } else if ( $data['post_id'] == 'parent' ) {
367
+ $post_id .= '"$parent"';
368
+ } else if ( $data['post_id'] == 'related' ) {
369
+ $post_id .= '"$' . esc_attr(trim( strval( $data['related_post'] ) )) . '"';
370
+ } else {
371
+ $post_id .= '"' . preg_replace( '/[^\d]+/', '', $data['post_id'] ) . '"';
372
+ }
373
+ $shortcode = preg_replace( '/\[types([^\]]*)/', '$0 ' . $post_id,
374
+ $shortcode );
375
+ }
376
+ return $shortcode;
377
+ }
378
+
379
+ /**
380
+ * Checks if feature is supported.
381
+ *
382
+ * @param type $feature
383
+ * @return type
384
+ */
385
+ function supports( $feature ) {
386
+ return in_array( $feature, $this->_data['supports'] );
387
+ }
388
+
389
+ /**
390
+ * Converts shortcode string to array of parameters.
391
+ *
392
+ * @param type $shortcode
393
+ */
394
+ function shortcodeToParameters( $shortcode ) {
395
+
396
+ if ( !is_string( $shortcode ) ) {
397
+ return is_array( $shortcode ) ? $shortcode : array();
398
+ }
399
+
400
+ $params = array();
401
+ $pattern = get_shortcode_regex();
402
+ preg_match_all( "/$pattern/s", stripslashes( $shortcode ), $matches );
403
+
404
+ if ( !empty( $matches[3] ) ) {
405
+ $options = array();
406
+ foreach ( $matches[3] as $index => $match ) {
407
+ $_params = shortcode_parse_atts( trim( $match, '[]' ) );
408
+ switch ( $this->field['type'] ) {
409
+ case 'checkbox':
410
+ $_params['mode'] = 'db';
411
+ if ( isset( $_params['state'] ) ) {
412
+ $_params['mode'] = 'value';
413
+ if ( $_params['state'] == 'checked' ) {
414
+ $_params['selected'] = $matches[5][$index];
415
+ } else if ( $_params['state'] == 'unchecked' ) {
416
+ $_params['not_selected'] = $matches[5][$index];
417
+ }
418
+ }
419
+ $params = array_merge( $params, $_params );
420
+ break;
421
+
422
+ case 'checkboxes':
423
+ $_params['mode'] = isset( $_params['separator'] ) ? 'display_all' : 'db';
424
+ if ( isset( $_params['option'] ) ) {
425
+ $_option = $_params['option'];
426
+ $_params['mode'] = 'value';
427
+ $_params['state'] = isset( $_params['state'] ) ? $_params['state'] : 'checked';
428
+ if ( $_params['state'] == 'unchecked' ) {
429
+ $options[$_option]['not_selected'] = $matches[5][$index];
430
+ } else {
431
+ $options[$_option]['selected'] = $matches[5][$index];
432
+ }
433
+ unset( $_params['option'], $_params['state'] );
434
+ }
435
+ $params = array_merge( $params, $_params );
436
+ break;
437
+
438
+ case 'radio':
439
+ $_params['mode'] = 'db';
440
+ if ( isset( $_params['option'] ) ) {
441
+ $_option = $_params['option'];
442
+ $_params['mode'] = 'value';
443
+ $options[$_option] = $matches[5][$index];
444
+ unset( $_params['option'] );
445
+ }
446
+ $params = array_merge( $params, $_params );
447
+ break;
448
+
449
+ case 'image':
450
+ if ( isset( $_params['width'] ) || isset( $_params['height'] ) ) {
451
+ $_params['image_size'] = 'wpcf-custom';
452
+ }
453
+ $params = array_merge( $params, $_params );
454
+ break;
455
+
456
+ default:
457
+ $params = shortcode_parse_atts( $matches[3][0] );
458
+ break;
459
+ }
460
+ }
461
+ if ( !empty( $options ) ) {
462
+ $params['options'] = $options;
463
+ }
464
+ }
465
+
466
+ if ( !is_array( $params ) ) {
467
+ return array();
468
+ }
469
+
470
+ while ( $next = next( $params ) ) {
471
+ $param = key( $params );
472
+ $value = $params[$param];
473
+ switch ( $param ) {
474
+ case 'id':
475
+ if ( is_numeric( $value ) ) {
476
+ $params['post_id'] = 'post_id';
477
+ $params['specific_post_id'] = intval( $value );
478
+ } else {
479
+ if ( $value === '$parent' ) {
480
+ $params['post_id'] = 'parent';
481
+ } else if ( $value === 'current' ) {
482
+ $params['post_id'] = self::sanitizeParams( $value );
483
+ } else {
484
+ $params['post_id'] = 'related';
485
+ $params['related_post'] = trim( self::sanitizeParams( $value ),
486
+ '$' );
487
+ }
488
+ }
489
+ $params[$param] = self::sanitizeParams( $value );
490
+ break;
491
+
492
+ case 'options':
493
+ $params[$param] = self::sanitizeParams( $value, 'array' );
494
+ break;
495
+
496
+ default:
497
+ $params[$param] = self::sanitizeParams( $value );
498
+ break;
499
+ }
500
+ }
501
+ return $params;
502
+ }
503
+
504
+ /**
505
+ * Sanitize value before writing to JS.
506
+ *
507
+ * @param type $value
508
+ * @return type
509
+ */
510
+ public static function sanitizeParams( $value, $is_array = false ) {
511
+ if ( $is_array === 'array' && is_array( $value ) ) {
512
+ foreach ( $value as $k => $v ) {
513
+ $value[$k] = self::sanitizeParams( $v, 'array' );
514
+ }
515
+ return $value;
516
+ }
517
+ return htmlentities( stripslashes( strval( $value ) ), ENT_QUOTES );
518
+ }
519
+
520
+ }
embedded/classes/evaluate.php ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Evaluate class.
4
+ */
5
+
6
+ /**
7
+ * Evaluate class.
8
+ *
9
+ * Applies filters:
10
+ * 'relationship_custom_statement_meta_ajax_validation_filter'
11
+ * 'meta_ajax_validation_filter'
12
+ *
13
+ * @since Types 1.2
14
+ * @package Types
15
+ * @subpackage Conditional
16
+ * @version 0.1
17
+ * @category core
18
+ * @author srdjan <srdjan@icanlocalize.com>
19
+ */
20
+ class WPCF_Evaluate
21
+ {
22
+
23
+ /**
24
+ * Main conditinal evaluation function.
25
+ *
26
+ * @since 1.2
27
+ * @version 0.2
28
+ * @param type $o
29
+ * @return boolean
30
+ */
31
+ public static function evaluate( $o ) {
32
+
33
+ // Set vars
34
+ $post = $o->post;
35
+ $field = $o->cf;
36
+
37
+ /*
38
+ *
39
+ * Since Types 1.2
40
+ * We force initial value to be FALSE.
41
+ * Better to have restricted than allowed because of sensitive data.
42
+ * If conditional is set on field and it goes wrong - better to abort
43
+ * so user can report bug without exposing his content.
44
+ */
45
+ $passed = false;
46
+
47
+ if ( empty( $post->ID ) ) {
48
+ /*
49
+ *
50
+ * Keep all forbidden if post is not saved.
51
+ */
52
+ $passed = false;
53
+ /*
54
+ *
55
+ *
56
+ *
57
+ *
58
+ *
59
+ *
60
+ *
61
+ *
62
+ *
63
+ * VIEWS
64
+ *
65
+ * Custom call uses Views code
66
+ * wpv_filter_parse_date()
67
+ * wpv_condition()
68
+ */
69
+ } else if ( isset( $field['data']['conditional_display']['custom_use'] ) ) {
70
+ /*
71
+ *
72
+ *
73
+ * More malformed forbids
74
+ */
75
+ if ( empty( $field['data']['conditional_display']['custom'] ) ) {
76
+ return false;
77
+ }
78
+
79
+ /*
80
+ *
81
+ *
82
+ * Filter meta values (switch them with $_POST values)
83
+ * Used by Views, Types do not need it.
84
+ */
85
+
86
+ if ( $o->context == 'relationship' ) {
87
+ add_filter( 'get_post_metadata',
88
+ array('WPCF_Evaluate', 'relationship_custom_statement_meta_ajax_validation_filter'),
89
+ 10, 4 );
90
+ } else {
91
+ add_filter( 'get_post_metadata',
92
+ array('WPCF_Evaluate', 'meta_ajax_validation_filter'),
93
+ 10, 4 );
94
+ }
95
+ do_action( 'types_custom_conditional_statement', $o );
96
+
97
+ /*
98
+ *
99
+ * Set statement
100
+ */
101
+ $evaluate = trim( stripslashes( $field['data']['conditional_display']['custom'] ) );
102
+ // Check dates
103
+ $evaluate = wpv_filter_parse_date( $evaluate );
104
+ // Add quotes = > < >= <= === <> !==
105
+ $strings_count = preg_match_all( '/[=|==|===|<=|<==|<===|>=|>==|>===|\!===|\!==|\!=|<>]\s(?!\$)(\w*)[\)|\$|\W]/',
106
+ $evaluate, $matches );
107
+ if ( !empty( $matches[1] ) ) {
108
+ foreach ( $matches[1] as $temp_match ) {
109
+ $temp_replace = is_numeric( $temp_match ) ? $temp_match : '\'' . $temp_match . '\'';
110
+ $evaluate = str_replace( ' ' . $temp_match . ')',
111
+ ' ' . $temp_replace . ')', $evaluate );
112
+ }
113
+ }
114
+ preg_match_all( '/\$([^\s]*)/',
115
+ $field['data']['conditional_display']['custom'], $matches );
116
+
117
+
118
+
119
+ if ( empty( $matches ) ) {
120
+ /*
121
+ *
122
+ * If statement false
123
+ */
124
+ $passed = false;
125
+ } else {
126
+ /*
127
+ *
128
+ *
129
+ * If statement right, check condition
130
+ */
131
+ $fields = array();
132
+ foreach ( $matches[1] as $field_name ) {
133
+ /*
134
+ *
135
+ *
136
+ * This field value is checked
137
+ */
138
+ $f = wpcf_admin_fields_get_field( trim( strval( $field_name ) ) );
139
+ if ( empty( $f ) ) {
140
+ return false;
141
+ }
142
+
143
+ $c = new WPCF_Field();
144
+ $c->set( $post, $f );
145
+
146
+ // Set field
147
+ $fields[$field_name] = $c->slug;
148
+ }
149
+ $fields['evaluate'] = $evaluate;
150
+ $check = wpv_condition( $fields, $post );
151
+
152
+ /*
153
+ *
154
+ *
155
+ * Views return string malformed,
156
+ * boolean if call completed.
157
+ */
158
+ if ( !is_bool( $check ) ) {
159
+ $passed = false;
160
+ } else {
161
+ $passed = $check;
162
+ }
163
+ }
164
+
165
+ /*
166
+ *
167
+ *
168
+ * Remove filter meta values
169
+ */
170
+ if ( $o->context == 'relationship' ) {
171
+ remove_filter( 'get_post_metadata',
172
+ array('WPCF_Evaluate', 'relationship_custom_statement_meta_ajax_validation_filter'),
173
+ 10, 4 );
174
+ } else {
175
+ remove_filter( 'get_post_metadata',
176
+ array('WPCF_Evaluate', 'meta_ajax_validation_filter'),
177
+ 10, 4 );
178
+ }
179
+ } else {
180
+ /*
181
+ *
182
+ *
183
+ *
184
+ *
185
+ *
186
+ *
187
+ *
188
+ *
189
+ * TYPES
190
+ *
191
+ * If not custom code, use Types built-in check.
192
+ * wpcf_cd_admin_compare()
193
+ */
194
+ $passed_all = true;
195
+ $passed_one = false;
196
+
197
+ // Basic check
198
+ if ( empty( $field['data']['conditional_display']['conditions'] ) ) {
199
+ return false;
200
+ }
201
+
202
+ // Keep count to see if OR/AND relation needed
203
+ $count = count( $field['data']['conditional_display']['conditions'] );
204
+
205
+ foreach ( $field['data']['conditional_display']['conditions'] as $condition ) {
206
+ /*
207
+ *
208
+ *
209
+ * Malformed condition and should be treated as forbidden
210
+ */
211
+ if ( !isset( $condition['field'] ) || !isset( $condition['operation'] )
212
+ || !isset( $condition['value'] ) ) {
213
+ $passed_one = false;
214
+ continue;
215
+ }
216
+ /*
217
+ *
218
+ *
219
+ * This field value is checked
220
+ */
221
+ $f = wpcf_admin_fields_get_field( trim( strval( $condition['field'] ) ) );
222
+ if ( empty( $f ) ) {
223
+ return false;
224
+ }
225
+
226
+ $c = new WPCF_Field();
227
+ $c->set( $post, $f );
228
+
229
+ /*
230
+ *
231
+ * Since Types 1.2
232
+ * meta is property of WPCF_Field::$__meta
233
+ *
234
+ * BREAKPOINT
235
+ * This is where values for evaluation are set.
236
+ * Please do not allow other places - use hooks.
237
+ *
238
+ * TODO Monitor this
239
+ * 1.3 Change use of $c->_get_meta( 'POST' )
240
+ * to $c->get_submitted_data()
241
+ */
242
+ // $value = defined( 'DOING_AJAX' ) ? $c->_get_meta( 'POST' ) : $c->__meta;
243
+ $value = defined( 'DOING_AJAX' ) ? $c->get_submitted_data() : $c->__meta;
244
+
245
+ /*
246
+ *
247
+ * Apply filters
248
+ */
249
+ $value = apply_filters( 'wpcf_conditional_display_compare_meta_value',
250
+ $value, $c->cf['id'], $condition['operation'], $c->slug,
251
+ $post );
252
+ $condition['value'] = apply_filters( 'wpcf_conditional_display_compare_condition_value',
253
+ $condition['value'], $c->cf['id'],
254
+ $condition['operation'], $c->slug, $post );
255
+
256
+ /*
257
+ *
258
+ *
259
+ * Call built-in Types compare func
260
+ */
261
+ WPCF_Loader::loadInclude( 'conditional-display' );
262
+ $passed = wpcf_cd_admin_compare( $condition['operation'],
263
+ $value, $condition['value'] );
264
+
265
+ if ( !$passed ) {
266
+ $passed_all = false;
267
+ } else {
268
+ $passed_one = true;
269
+ }
270
+ }
271
+
272
+ /*
273
+ *
274
+ *
275
+ * Check OR/AND relation
276
+ */
277
+ if ( $count > 1 ) {
278
+ if ( $field['data']['conditional_display']['relation'] == 'AND' ) {
279
+ $passed = $passed_all;
280
+ } else if ( $field['data']['conditional_display']['relation'] == 'OR' ) {
281
+ $passed = $passed_one;
282
+ }
283
+ }
284
+ }
285
+
286
+ return (bool) $passed;
287
+ }
288
+
289
+ /**
290
+ * Filters $_POST for relationship.
291
+ *
292
+ * @global type $wpcf
293
+ * @param type $null
294
+ * @param type $object_id
295
+ * @param type $meta_key
296
+ * @param type $single
297
+ * @return type
298
+ */
299
+ public static function relationship_custom_statement_meta_ajax_validation_filter( $null,
300
+ $object_id, $meta_key, $single ){
301
+
302
+ global $wpcf;
303
+
304
+ $value = $wpcf->relationship->get_submitted_data(
305
+ $wpcf->relationship->parent->ID, $wpcf->relationship->child->ID,
306
+ $meta_key );
307
+
308
+ $null = is_null( $value ) ? $null : $value;
309
+
310
+ // Date
311
+ if ( !empty( $null ) && !empty( $field ) && $field['type'] == 'date' ) {
312
+ $time = strtotime( $null );
313
+ if ( $time ) {
314
+ $null = $time;
315
+ }
316
+ /**
317
+ * be sure do not return string if array is expected!
318
+ */
319
+ if ( !$single && !is_array($null) ) {
320
+ return array($null);
321
+ }
322
+ }
323
+
324
+ return $null;
325
+ }
326
+
327
+ /**
328
+ * Filters $_POST values for AJAX call.
329
+ *
330
+ * @param type $null
331
+ * @param type $object_id
332
+ * @param type $meta_key
333
+ * @param type $single
334
+ * @return type
335
+ */
336
+ public static function meta_ajax_validation_filter( $null, $object_id,
337
+ $meta_key, $single ) {
338
+ $meta_key = str_replace( 'wpcf-', '', $meta_key );
339
+ $field = wpcf_admin_fields_get_field( $meta_key );
340
+ $value = !empty( $field ) && isset( $_POST['wpcf'][$meta_key] ) ? $_POST['wpcf'][$meta_key] : '';
341
+ /**
342
+ * be sure do not return string if array is expected!
343
+ */
344
+ if ( !$single && !is_array($value) ) {
345
+ return array($value);
346
+ }
347
+ return $value;
348
+ }
349
+
350
+ }
embedded/classes/field.php ADDED
@@ -0,0 +1,789 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Field class.
4
+ *
5
+ * $HeadURL: http://plugins.svn.wordpress.org/types/tags/1.6/embedded/classes/field.php $
6
+ * $LastChangedDate: 2014-08-22 01:02:43 +0000 (Fri, 22 Aug 2014) $
7
+ * $LastChangedRevision: 970205 $
8
+ * $LastChangedBy: brucepearson $
9
+ *
10
+ */
11
+
12
+ /**
13
+ * Base class.
14
+ *
15
+ * Fields are our core items and we'll use this class to sort them out a little.
16
+ * Very useful, should be used to finish small tasks for field.
17
+ *
18
+ * Example:
19
+ *
20
+ * // Setup field
21
+ * global $wpcf;
22
+ * $my_field = new WPCF_Field();
23
+ * $my_field->set($wpcf->post, wpcf_admin_fields_get_field('image'));
24
+ *
25
+ * // Use it
26
+ * $my_field->save();
27
+ *
28
+ * // Generic instance can be found in global $wpcf.
29
+ * global $wpcf;
30
+ * $wpcf->field->set(...);
31
+ *
32
+ * !! BE CAREFUL !! not to disturb global instance if you suspect processing
33
+ * current item is not finished. Core code sometimes use same instance over
34
+ * few functions and places.
35
+ *
36
+ * @since Types 1.2
37
+ * @package Types
38
+ * @subpackage Classes
39
+ * @version 0.1
40
+ * @category core
41
+ * @author srdjan <srdjan@icanlocalize.com>
42
+ */
43
+ class WPCF_Field
44
+ {
45
+
46
+ /**
47
+ * Field structure
48
+ *
49
+ * This is actually a form array collected from files per specific field:
50
+ * /embedded/includes/fields/$field_type.php
51
+ * /includes/fields/$field_type.php
52
+ *
53
+ * @var type array
54
+ */
55
+ var $cf = array();
56
+
57
+ /**
58
+ * All Types created fields
59
+ * @var type
60
+ */
61
+ var $fields = null;
62
+
63
+ /**
64
+ * Field saved data
65
+ * @var type
66
+ */
67
+ var $meta = null;
68
+
69
+ /**
70
+ * Field config.
71
+ *
72
+ * Use it to set default configuration.
73
+ *
74
+ * @var type array
75
+ */
76
+ var $config = array(
77
+ 'use_form' => false,
78
+ );
79
+
80
+ /**
81
+ * Form object
82
+ * @var type array
83
+ */
84
+ var $form = array();
85
+
86
+ /**
87
+ * Sets post
88
+ */
89
+ var $post;
90
+
91
+ /**
92
+ * CF slug
93
+ * @var type string
94
+ */
95
+ var $slug = '';
96
+
97
+ /**
98
+ * Use cache flag
99
+ * @var type boolean
100
+ */
101
+ var $use_cache = true;
102
+
103
+ /**
104
+ * Cache.DEPRECATED
105
+ *
106
+ * @var type
107
+ */
108
+ var $cache = array();
109
+
110
+ /**
111
+ * Add to editor flas
112
+ * @var type boolean
113
+ */
114
+ var $add_to_editor = true;
115
+
116
+ /**
117
+ * Context in which class is called
118
+ * @var type
119
+ */
120
+ var $context = 'group';
121
+
122
+ /**
123
+ * Invalid fields
124
+ *
125
+ * @todo Revise
126
+ * @var type
127
+ */
128
+ var $invalid_fields = array();
129
+
130
+ /**
131
+ * ID
132
+ */
133
+ var $ID = '';
134
+
135
+ /**
136
+ * Unique ID
137
+ */
138
+ var $unique_id = '';
139
+
140
+ function __construct( $config = array() ) {
141
+ // Parse args
142
+ extract( wp_parse_args( (array) $config, $this->config ) );
143
+ }
144
+
145
+ /**
146
+ * Set current post and field.
147
+ *
148
+ * @param type $post
149
+ * @param type $cf
150
+ */
151
+ function set( $post, $cf ) {
152
+
153
+ global $wpcf;
154
+
155
+ /*
156
+ *
157
+ * Check if $cf is string
158
+ */
159
+ if ( is_string( $cf ) ) {
160
+ WPCF_Loader::loadInclude( 'fields' );
161
+ $_cf = wpcf_admin_fields_get_field( $this->__get_slug_no_prefix( $cf ) );
162
+ // Check if found without prefix
163
+ if ( empty( $_cf ) ) {
164
+ $_cf = wpcf_admin_fields_get_field( $cf );
165
+ }
166
+ if ( empty( $_cf ) ) {
167
+ /*
168
+ * TODO Check what happens if field is not found
169
+ */
170
+ $this->_reset();
171
+ return false;
172
+ }
173
+ $cf = $_cf;
174
+ }
175
+
176
+ $this->post = is_integer( $post ) ? get_post( $post ) : $post;
177
+ // If empty post it is new
178
+ if ( empty( $this->post->ID ) ) {
179
+ $this->post = new stdClass();
180
+ $this->post->ID = 0;
181
+ }
182
+ $this->ID = $cf['id'];
183
+ $this->cf = $cf;
184
+ $this->slug = wpcf_types_get_meta_prefix( $this->cf ) . $this->cf['slug'];
185
+ $this->meta = $this->_get_meta();
186
+ $this->config = $this->_get_config();
187
+ $this->unique_id = wpcf_unique_id( serialize( (array) $this ) );
188
+ $this->cf['value'] = $this->meta;
189
+
190
+ // Debug
191
+ $wpcf->debug->fields[$this->unique_id] = $this->cf;
192
+ $wpcf->debug->meta[$this->slug][] = $this->meta;
193
+
194
+ // Load files
195
+ $this->_include_file_by_field_type($this->cf['type']);
196
+ if ( defined( 'WPCF_INC_ABSPATH' ) ) {
197
+ $file = WPCF_INC_ABSPATH . '/fields/' . preg_replace('/[^\w]+/', '', $this->cf['type']) . '.php';
198
+ if ( file_exists( $file ) ) {
199
+ include_once $file;
200
+ }
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Reset on failure.
206
+ */
207
+ function _reset() {
208
+ $this->ID = '';
209
+ $this->cf = array();
210
+ $this->post = new stdClass();
211
+ $this->slug = '';
212
+ $this->meta = '';
213
+ $this->__meta = '';
214
+ $this->config = array();
215
+ $this->unique_id = '';
216
+ $this->cf['value'] = '';
217
+ }
218
+
219
+ /**
220
+ * Set needed but not required form elements.
221
+ *
222
+ * @param string $cf
223
+ */
224
+ function _parse_cf_form_element( $cf ) {
225
+ $p = array('#before' => '', '#after' => '', '#description' => '');
226
+ foreach ( $p as $_p => $param ) {
227
+ if ( !isset( $cf[$_p] ) ) {
228
+ $cf[$_p] = $param;
229
+ }
230
+ }
231
+ return $cf;
232
+ }
233
+
234
+ /**
235
+ * Fetch and sort fields.
236
+ *
237
+ * @global type $wpdb
238
+ */
239
+ function _get_meta() {
240
+ global $wpdb;
241
+
242
+ $cache_key = md5( 'field::_get_meta' . $this->post->ID . $this->slug );
243
+ $cache_group = 'types_cache';
244
+ $cached_object = wp_cache_get( $cache_key, $cache_group );
245
+ if ( $this->use_cache ) {
246
+ if ( false != $cached_object && is_array( $cached_object ) && isset( $cached_object[0] ) ) {// WordPress cache
247
+ $r = $cached_object[0];
248
+ } else {
249
+ // Cache all the postmeta for this same post
250
+ $all_postmeta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->postmeta} WHERE post_id=%d", $this->post->ID), OBJECT );
251
+ if ( !empty( $all_postmeta ) ) {
252
+ $cache_key_keys = array();
253
+ foreach ( $all_postmeta as $metarow ) {
254
+ $mpid = intval($metarow->post_id);
255
+ $mkey = $metarow->meta_key;
256
+ $cache_key_keys[$mpid . $mkey][] = $metarow;
257
+ $cache_key_looped = md5( 'field::_get_meta' . $mpid . $mkey );
258
+ if ( $mkey == $this->slug ) {
259
+ $r = $metarow;
260
+ }
261
+ }
262
+ foreach ( $cache_key_keys as $single_meta_keys => $single_meta_values ) {
263
+ $cache_key_looped_new = md5( 'field::_get_meta' . $single_meta_keys );
264
+ wp_cache_add( $cache_key_looped_new, $single_meta_values, $cache_group );// WordPress cache
265
+ }
266
+ }
267
+ }
268
+ } else {
269
+ // If not using cache, get straight from DB single value
270
+ $r = $wpdb->get_row(
271
+ $wpdb->prepare(
272
+ "SELECT * FROM $wpdb->postmeta
273
+ WHERE post_id=%d
274
+ AND meta_key=%s",
275
+ $this->post->ID, $this->slug )
276
+ );
277
+ // Cache it
278
+ wp_cache_add( $cache_key, array( $r ), $cache_group );// WordPress cache
279
+ }
280
+
281
+ // Sort meta
282
+ $meta = array();
283
+ if ( !empty( $r ) ) {
284
+ $meta = maybe_unserialize( $r->meta_value );
285
+ $this->meta_object = $r;
286
+ } else {
287
+ $meta = null;
288
+ $this->meta_object = new stdClass();
289
+ $this->meta_object->meta_id = null;
290
+ $this->meta_object->meta_key = null;
291
+ $this->meta_object->meta_value = null;
292
+ }
293
+
294
+ /*
295
+ * Secret public object :)
296
+ * Keeps original data
297
+ */
298
+ $this->__meta = $meta;
299
+
300
+ /*
301
+ * Apply filters
302
+ */
303
+ $meta = apply_filters( 'wpcf_fields_value_get', $meta, $this );
304
+ $meta = apply_filters( 'wpcf_fields_slug_' . $this->cf['slug']
305
+ . '_value_get', $meta, $this );
306
+ $meta = apply_filters( 'wpcf_fields_type_' . $this->cf['type']
307
+ . '_value_get', $meta, $this );
308
+
309
+ return $meta;
310
+ }
311
+
312
+ /**
313
+ * Gets $_POST data.
314
+ *
315
+ * @return type
316
+ */
317
+ function get_submitted_data() {
318
+ $posted = isset( $_POST['wpcf'][$this->cf['slug']] ) ? $_POST['wpcf'][$this->cf['slug']] : null;
319
+ $value = apply_filters( 'types_field_get_submitted_data', $posted, $this );
320
+ return $value;
321
+ }
322
+
323
+ /**
324
+ * Save field.
325
+ *
326
+ * If $value is empty, $_POST will be checked.
327
+ * 1.3.2 Reverted saving empty fields
328
+ * removed - if ( !empty( $value ) || is_numeric( $value ) ) {
329
+ *
330
+ * @param type $value
331
+ */
332
+ function save( $value = null )
333
+ {
334
+ // If $value null, look for submitted data
335
+ if ( is_null( $value ) ) {
336
+ $value = $this->get_submitted_data();
337
+ }
338
+ /**
339
+ *
340
+ * Since Types 1.2
341
+ * We completely rewrite meta.
342
+ * It has no impact on frontend and covers a lot of cases
343
+ * (e.g. user change mode from single to repetitive)
344
+ *
345
+ */
346
+ do_action('wpcf_postmeta_before_delete', $this->post, $this->cf);
347
+ delete_post_meta( $this->post->ID, $this->slug );
348
+ do_action('wpcf_postmeta_after_delete', $this->post, $this->cf);
349
+ // Trim
350
+ if ( is_string( $value ) ) {
351
+ $value = trim( $value );
352
+ }
353
+ /**
354
+ * setup what save to database if needed
355
+ */
356
+ if (
357
+ $value
358
+ && array_key_exists( 'data', $this->cf )
359
+ && array_key_exists( 'set_value', $this->cf['data'] )
360
+ ) {
361
+ $value = $this->cf['data']['set_value'];
362
+ }
363
+ /**
364
+ * apply filters
365
+ */
366
+ $_value = $this->_filter_save_value( $value );
367
+ /**
368
+ * Save field if needed
369
+ */
370
+ if (
371
+ (
372
+ !( is_null( $value ) || $value === false || $value === '' )
373
+ || (
374
+ isset($this->cf['data']['save_empty'])
375
+ && 'yes' == $this->cf['data']['save_empty']
376
+ )
377
+ )
378
+ ||
379
+ /**
380
+ * handle "save zero as set value"
381
+ */
382
+ (
383
+ array_key_exists( 'set_value', $this->cf['data'] )
384
+ && preg_match( '/^0$/', $value )
385
+ && preg_match( '/^0$/', $this->cf['data']['set_value'] )
386
+ )
387
+ ) {
388
+ $mid = add_post_meta( $this->post->ID, $this->slug, $_value );
389
+ /*
390
+ * Use these hooks to add future functionality.
391
+ * Do not add any more code to core.
392
+ */
393
+ $this->_action_save( $this->cf, $_value, $mid, $value );
394
+ }
395
+ }
396
+
397
+ /**
398
+ * Apply filters to saved value.
399
+ *
400
+ * @param type $value
401
+ * @return type
402
+ */
403
+ function _filter_save_value( $value ) {
404
+ // Apply filters
405
+ $value = apply_filters( 'wpcf_fields_value_save', $value,
406
+ $this->cf['type'], $this->cf['slug'], $this->cf, $this );
407
+ $value = apply_filters( 'wpcf_fields_slug_' . $this->cf['slug']
408
+ . '_value_save', $value, $this->cf, $this );
409
+ $value = apply_filters( 'wpcf_fields_type_' . $this->cf['type']
410
+ . '_value_save', $value, $this->cf, $this );
411
+
412
+ return $value;
413
+ }
414
+
415
+ /**
416
+ * Use these hooks to add future functionality.
417
+ * Do not add any more code to core.
418
+ *
419
+ * @param type $field
420
+ * @param type $value
421
+ * @param type $meta_id
422
+ */
423
+ function _action_save( $field, $value, $meta_id, $meta_value_original ) {
424
+ do_action( 'wpcf_fields_save', $value, $field, $this, $meta_id,
425
+ $meta_value_original );
426
+ do_action( 'wpcf_fields_slug_' . $field['slug'] . '_save', $value,
427
+ $field, $this, $meta_id, $meta_value_original );
428
+ do_action( 'wpcf_fields_type_' . $field['type'] . '_save', $value,
429
+ $field, $this, $meta_id, $meta_value_original );
430
+ }
431
+
432
+ /**
433
+ * Get file fullpath to include
434
+ *
435
+ * param @string $basename
436
+ *
437
+ * return @string
438
+ *
439
+ */
440
+ function _include_file_by_field_type($basename)
441
+ {
442
+ $file = wpcf_get_fullpath_by_field_type($basename);
443
+ if ( file_exists( $file ) ) {
444
+ include_once $file;
445
+ }
446
+ return $file;
447
+ }
448
+
449
+ /**
450
+ * Sets field config.
451
+ *
452
+ * @return type
453
+ */
454
+ function _get_config() {
455
+ $this->_include_file_by_field_type($this->cf['type']);
456
+ $func = 'wpcf_fields_' . $this->cf['type'];
457
+ if ( is_callable( $func ) ) {
458
+ return (object) call_user_func( $func );
459
+ }
460
+ return new stdClass();
461
+ }
462
+
463
+ /**
464
+ * Discouraged usage.
465
+ *
466
+ * @return type
467
+ */
468
+ function _deprecated_inherited_allowed() {
469
+ return array(
470
+ 'image' => 'file',
471
+ 'numeric' => 'textfield',
472
+ 'email' => 'textfield',
473
+ 'phone' => 'textfield',
474
+ 'url' => 'textfield',
475
+ );
476
+ }
477
+
478
+ /**
479
+ * Sets field meta box form.
480
+ *
481
+ * @return type
482
+ */
483
+ function _get_meta_form( $meta_value = null, $meta_id = null, $wrap = true ) {
484
+
485
+ /*
486
+ * Note that field may be registered outside of Types.
487
+ * In that case, it's on developer to make sure it's loaded.
488
+ */
489
+ $this->_include_file_by_field_type($this->cf['type']);
490
+
491
+ /*
492
+ * Set value
493
+ *
494
+ * IMPORTANT
495
+ * Here we set values for form elements
496
+ */
497
+ $this->cf['value'] = is_null( $meta_value ) ? $this->meta : $meta_value;
498
+
499
+ $form = array();
500
+ $form_meta_box = array();
501
+ $inherited = array();
502
+ $this->__multiple = false;
503
+
504
+ // Open main wrapper
505
+ if ( $wrap ) {
506
+ $form['__meta_form_OPEN'] = array(
507
+ '#type' => 'markup',
508
+ '#markup' => ''
509
+ . '<div id="wpcf_wrapper_' . $this->unique_id
510
+ . '" class="wpcf-wrap wpcf-meta-form">',
511
+ );
512
+ }
513
+
514
+ /*
515
+ *
516
+ *
517
+ *
518
+ *
519
+ * Since Types 1.2
520
+ * Avoid using parent (inherited) type
521
+ * $this->config->inherited_field_type
522
+ */
523
+ // See if inherited data and merge
524
+ if ( isset( $this->config->inherited_field_type ) ) {
525
+ if ( !array_key_exists( $this->cf['type'],
526
+ $this->_deprecated_inherited_allowed() ) ) {
527
+ // _deprecated_argument( 'inherited_field_type', '1.2',
528
+ // 'Since Types 1.2 we encourage developers to completely define fields' );
529
+ }
530
+ $file = $this->_include_file_by_field_type($this->config->inherited_field_type);
531
+
532
+ if ( file_exists( $file ) ) {
533
+
534
+ if ( function_exists( 'wpcf_fields_'
535
+ . $this->config->inherited_field_type
536
+ . '_meta_box_form' ) ) {
537
+ $inherited = call_user_func_array( 'wpcf_fields_'
538
+ . $this->config->inherited_field_type
539
+ . '_meta_box_form', array($this->cf, $this) );
540
+ // If single form - convert to array of elements
541
+ if ( isset( $inherited['#type'] ) ) {
542
+ $inherited = array('wpcf_field_' . $this->unique_id => $inherited);
543
+ }
544
+
545
+ // One value?
546
+ if ( count( $inherited ) > 1 ) {
547
+ $this->__multiple = true;
548
+ }
549
+
550
+ $form = $form + $inherited;
551
+ }
552
+ }
553
+ }
554
+
555
+ $func = 'wpcf_fields_' . $this->cf['type'] . '_meta_box_form';
556
+ if ( is_callable( $func ) ) {
557
+ /*
558
+ *
559
+ * From Types 1.2 use complete form setup
560
+ */
561
+ $form_meta_box = call_user_func_array( 'wpcf_fields_'
562
+ . $this->cf['type'] . '_meta_box_form',
563
+ array($this->cf, $this) );
564
+
565
+ // If single form - convert to array of elements
566
+ if ( isset( $form_meta_box['#type'] ) ) {
567
+ $form_meta_box = array('wpcf_field_' . $this->unique_id => $form_meta_box);
568
+ }
569
+
570
+ // One value?
571
+ if ( count( $form_meta_box ) > 1 ) {
572
+ $this->__multiple = true;
573
+ }
574
+
575
+ // Merge
576
+ $form = array_merge( $form, $form_meta_box );
577
+ }
578
+
579
+ if ( !empty( $form ) ) {
580
+
581
+ // Process each field
582
+ foreach ( $form as $element_key => $element ) {
583
+
584
+ /*
585
+ *
586
+ * Start using __ in keys to skip element
587
+ */
588
+ // Skip protected
589
+ if ( strpos( $element_key, '__' ) === 0 ) {
590
+ $form[$element_key] = $element;
591
+ continue;
592
+ }
593
+
594
+ // Add title and description
595
+ // TODO WPML
596
+ if ( empty( $started ) ) {
597
+ $_title = isset( $element['#title'] ) ? $element['#title'] : $this->cf['name'];
598
+ $element['#title'] = wpcf_translate( 'field '
599
+ . $this->cf['id'] . ' name', $_title );
600
+
601
+ // Add asterisk for required fields
602
+ if ( isset( $this->cf['data']['validate']['required'] ) ) {
603
+ $element['#title'] .= '&#42;';
604
+ }
605
+
606
+ $_description = isset( $element['#description'] ) ? $element['#description'] : $this->cf['description'];
607
+ $element['#description'] = wpautop( wpcf_translate( 'field '
608
+ . $this->cf['id'] . ' description',
609
+ $_description ) );
610
+ $started = true;
611
+ }
612
+
613
+ // Set current element
614
+ $this->__current_form_element = $element;
615
+
616
+ // Process field
617
+ $temp_processed = wpcf_admin_post_process_field( $this );
618
+ if ( !empty( $temp_processed['element'] ) ) {
619
+ $element = $temp_processed['element'];
620
+ }
621
+
622
+ // Set form element
623
+ $form[$element_key] = apply_filters( 'wpcf_post_edit_field',
624
+ $element, $this->cf, $this->post, $this->context );
625
+ }
626
+
627
+ // Add to editor
628
+ if ( $this->add_to_editor ) {
629
+ wpcf_admin_post_add_to_editor( $this->cf );
630
+ }
631
+
632
+ $this->enqueue_script();
633
+ $this->enqueue_style();
634
+ }
635
+
636
+ // Close main wrapper
637
+ if ( $wrap ) {
638
+ $form['meta_form_CLOSE'] = array(
639
+ '#type' => 'markup',
640
+ '#markup' => ''
641
+ . '</div>',
642
+ );
643
+ }
644
+
645
+ // Add unique IDs
646
+ foreach ( $form as $k => $v ) {
647
+ $_form[$k . '_' . $this->unique_id] = $v;
648
+ }
649
+
650
+ return apply_filters( 'wpcf_meta_form', $_form );
651
+ }
652
+
653
+ /**
654
+ * Enqueue all files from config
655
+ */
656
+ function enqueue_script( $config = null ) {
657
+ // Use internal
658
+ if ( is_null( $config ) ) {
659
+ $config = $this->config;
660
+ }
661
+ $config = (object) $config;
662
+ // Process JS
663
+ if ( !empty( $config->meta_box_js ) ) {
664
+ foreach ( $config->meta_box_js as $handle => $data_script ) {
665
+ if ( isset( $data_script['inline'] ) ) {
666
+ add_action( 'admin_footer', $data_script['inline'] );
667
+ continue;
668
+ }
669
+ if ( !isset( $data_script['src'] ) ) {
670
+ continue;
671
+ }
672
+ $deps = !empty( $data_script['deps'] ) ? $data_script['deps'] : array();
673
+ wp_enqueue_script( $handle, $data_script['src'], $deps,
674
+ WPCF_VERSION );
675
+ }
676
+ }
677
+ }
678
+
679
+ /**
680
+ * Enqueue all files from config
681
+ */
682
+ function enqueue_style( $config = null ) {
683
+ // Use internal
684
+ if ( is_null( $config ) ) {
685
+ $config = $this->config;
686
+ }
687
+ $config = (object) $config;
688
+ if ( !empty( $config->meta_box_css ) ) {
689
+ foreach ( $config->meta_box_css as $handle => $data_script ) {
690
+ $deps = !empty( $data_script['deps'] ) ? $data_script['deps'] : array();
691
+ if ( isset( $data_script['inline'] ) ) {
692
+ add_action( 'admin_head', $data_script['inline'] );
693
+ continue;
694
+ }
695
+ if ( !isset( $data_script['src'] ) ) {
696
+ continue;
697
+ }
698
+ wp_enqueue_style( $handle, $data_script['src'], $deps,
699
+ WPCF_VERSION );
700
+ }
701
+ }
702
+ }
703
+
704
+ /**
705
+ * Use this function to add final filters to HTML output.
706
+ *
707
+ * @param type $output
708
+ */
709
+ function html( $html, $params ) {
710
+ /**
711
+ *
712
+ * Exception when RAW = TRUE.
713
+ * Return unchanged value.
714
+ *
715
+ */
716
+ if ( isset( $params['raw'] ) && $params['raw'] == 'true' ) {
717
+ return $html;
718
+ } else {
719
+ $html = esc_attr( $html );
720
+ }
721
+ // Process shortcodes too
722
+ // $shortcode = do_shortcode( $html );
723
+ $html = do_shortcode( htmlspecialchars_decode( $html ) );
724
+
725
+ return $html;
726
+ }
727
+
728
+ /**
729
+ * Determines if field is created with Types.
730
+ *
731
+ * @param type $field_key
732
+ */
733
+ function is_under_control( $field_key ) {
734
+ /*
735
+ *
736
+ * We force checking our meta prefix
737
+ */
738
+ $key = $this->__get_slug_no_prefix( $field_key );
739
+ return WPCF_Fields::isUnderControl( $key );
740
+ }
741
+
742
+ /**
743
+ * Return slug.
744
+ *
745
+ * @param type $meta_key
746
+ * @return type
747
+ */
748
+ function __get_slug_no_prefix( $meta_key ) {
749
+ return strpos( $meta_key, WPCF_META_PREFIX ) === 0 ? substr( $meta_key,
750
+ strlen( WPCF_META_PREFIX ) ) : $meta_key;
751
+ }
752
+
753
+ /**
754
+ * Returns altered element form name.
755
+ *
756
+ * Use $prefix to set name like:
757
+ * wpcf_post_relationship[214][wpcf-my-checkbox]
758
+ *
759
+ * Or if multi array
760
+ * wpcf_post_relationship[214][wpcf-my-date][datepicker]
761
+ * wpcf_post_relationship[214][wpcf-my-date][hour]
762
+ *
763
+ * @param type $prefix
764
+ * @param type $name
765
+ * @return type
766
+ */
767
+ function alter_form_name( $prefix, $name ) {
768
+ $temp = explode( '[', $name );
769
+ $temp = array_pop( $temp );
770
+ $__name = trim( strval( $temp ), ']' );
771
+ /*
772
+ * This means form is single-valued
773
+ */
774
+ if ( $__name == $this->cf['slug'] ) {
775
+ return strval( $prefix ) . '['
776
+ . $this->post->ID
777
+ . '][' . $this->slug . ']';
778
+ /*
779
+ *
780
+ * Multi array case
781
+ */
782
+ } else {
783
+ return strval( $prefix ) . '['
784
+ . $this->post->ID
785
+ . '][' . $this->slug . '][' . $__name . ']';
786
+ }
787
+ }
788
+
789
+ }
embedded/classes/fields.php ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Fields class.
4
+ *
5
+ * $HeadURL: http://plugins.svn.wordpress.org/types/tags/1.6/embedded/classes/fields.php $
6
+ * $LastChangedDate: 2014-05-07 06:56:23 +0000 (Wed, 07 May 2014) $
7
+ * $LastChangedRevision: 909470 $
8
+ * $LastChangedBy: iworks $
9
+ *
10
+ */
11
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
12
+
13
+ /**
14
+ * Fields class.
15
+ *
16
+ * @since Types 1.2
17
+ * @package Types
18
+ * @subpackage Classes
19
+ * @version 0.1
20
+ * @category core
21
+ * @author srdjan <srdjan@icanlocalize.com>
22
+ */
23
+ class WPCF_Fields
24
+ {
25
+
26
+ /**
27
+ * Holds all available field types and their config data.
28
+ *
29
+ * @var type
30
+ */
31
+ static $fieldTypesData = null;
32
+
33
+ /**
34
+ * Returns array of available (registered) field types
35
+ * and paths to config files.
36
+ *
37
+ * @return type
38
+ */
39
+ public static function getFieldsTypes() {
40
+ $fields = array(
41
+ 'audio' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/audio.php',
42
+ 'checkbox' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/checkbox.php',
43
+ 'checkboxes' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/checkboxes.php',
44
+ 'colorpicker' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/colorpicker.php',
45
+ 'date' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/date.php',
46
+ 'email' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/email.php',
47
+ 'embed' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/embed.php',
48
+ 'file' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/file.php',
49
+ 'image' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/image.php',
50
+ 'map' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/map.php',
51
+ 'numeric' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/numeric.php',
52
+ 'phone' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/phone.php',
53
+ 'radio' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/radio.php',
54
+ 'select' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/select.php',
55
+ 'skype' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/skype.php',
56
+ 'textarea' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/textarea.php',
57
+ 'textfield' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/textfield.php',
58
+ 'twitter' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/twitter.php',
59
+ 'url' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/url.php',
60
+ 'video' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/video.php',
61
+ 'wysiwyg' => WPCF_EMBEDDED_INC_ABSPATH . '/fields/wysiwyg.php',
62
+ );
63
+ return apply_filters( 'types_register_fields', $fields );
64
+ }
65
+
66
+ /**
67
+ * Returns array of available (registered) field types
68
+ * and their config data.
69
+ *
70
+ * @return type
71
+ */
72
+ public static function getFieldsTypesData() {
73
+ if ( !is_null( self::$fieldTypesData ) ) {
74
+ return self::$fieldTypesData;
75
+ }
76
+ self::$fieldTypesData = self::getFieldsTypes();
77
+ foreach ( self::$fieldTypesData as $type => $path ) {
78
+ $data = self::getFieldTypeConfig( $path );
79
+ if ( !empty( $data ) ) {
80
+ self::$fieldTypesData[$type] = $data;
81
+ } else {
82
+ unset( self::$fieldTypesData[$type] );
83
+ }
84
+ if ( isset($data['wp_version'])
85
+ && wpcf_compare_wp_version( $data['wp_version'], '<' ) ) {
86
+ unset( self::$fieldTypesData[$type] );
87
+ }
88
+ }
89
+ return self::$fieldTypesData;
90
+ }
91
+
92
+ /**
93
+ * Get field type data.
94
+ *
95
+ * @param type $type
96
+ * @return type
97
+ */
98
+ public static function getFieldTypeData( $type ) {
99
+ $fields = self::getFieldsTypes();
100
+ return isset( $fields[$type] ) ? self::getFieldTypeConfig( $fields[$type] ) : array();
101
+ }
102
+
103
+ /**
104
+ * Returns data for certain field type.
105
+ *
106
+ * @param type $type
107
+ * @return type
108
+ */
109
+ public static function getFieldTypeConfig( $path ) {
110
+ if ( !is_string( $path ) ) {
111
+ return array();
112
+ }
113
+ if ( file_exists( $path ) ) {
114
+ require_once $path;
115
+ if ( function_exists( 'wpcf_fields_' . basename( $path, '.php' ) ) ) {
116
+ return call_user_func( 'wpcf_fields_' . basename( $path, '.php' ) );
117
+ }
118
+ }
119
+ return array();
120
+ }
121
+
122
+ /**
123
+ * Get fields.
124
+ *
125
+ * Parameters for
126
+ * wpcf_admin_fields_get_fields()
127
+ *
128
+ * $only_active = false
129
+ * $disabled_by_type = false
130
+ * $strictly_active = false
131
+ *
132
+ * @return \stdClass
133
+ */
134
+ public static function getFields( $args = array(), $toolset = 'types' ) {
135
+ $active = isset( $args['active'] ) ? (bool) $args['active'] : true;
136
+ return wpcf_admin_fields_get_fields( $active );
137
+ }
138
+
139
+ /**
140
+ * Checks if field is under control.
141
+ *
142
+ * @param type $field_key
143
+ * @return type
144
+ */
145
+ public static function isUnderControl( $field_key ) {
146
+ $fields = self::getFields();
147
+ return !empty( $fields[$field_key] );
148
+ }
149
+
150
+ /**
151
+ * Enqueue all files from config
152
+ */
153
+ public static function enqueueScript( $field ) {
154
+ $config = (object) self::getFieldTypeData( $field );
155
+ if ( !empty( $config->meta_box_js ) ) {
156
+ foreach ( $config->meta_box_js as $handle => $data_script ) {
157
+ if ( isset( $data_script['inline'] ) ) {
158
+ add_action( 'admin_footer', $data_script['inline'] );
159
+ continue;
160
+ }
161
+ if ( !isset( $data_script['src'] ) ) {
162
+ continue;
163
+ }
164
+ $deps = !empty( $data_script['deps'] ) ? $data_script['deps'] : array();
165
+ wp_enqueue_script( $handle, $data_script['src'], $deps,
166
+ WPCF_VERSION );
167
+ }
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Enqueue all files from config
173
+ */
174
+ public static function enqueueStyle( $field ) {
175
+ $config = (object) self::getFieldTypeData( $field );
176
+ if ( !empty( $config->meta_box_css ) ) {
177
+ foreach ( $config->meta_box_css as $handle => $data_script ) {
178
+ $deps = !empty( $data_script['deps'] ) ? $data_script['deps'] : array();
179
+ if ( isset( $data_script['inline'] ) ) {
180
+ add_action( 'admin_head', $data_script['inline'] );
181
+ continue;
182
+ }
183
+ if ( !isset( $data_script['src'] ) ) {
184
+ continue;
185
+ }
186
+ wp_enqueue_style( $handle, $data_script['src'], $deps,
187
+ WPCF_VERSION );
188
+ }
189
+ }
190
+ }
191
+
192
+ }
embedded/classes/forms.php ADDED
@@ -0,0 +1,964 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ *
5
+ * Returns HTML formatted output for elements and handles form submission.
6
+ *
7
+ * $HeadURL: http://plugins.svn.wordpress.org/types/tags/1.6/embedded/classes/forms.php $
8
+ * $LastChangedDate: 2014-08-22 01:02:43 +0000 (Fri, 22 Aug 2014) $
9
+ * $LastChangedRevision: 970205 $
10
+ * $LastChangedBy: brucepearson $
11
+ *
12
+ *
13
+ * @version 1.0
14
+ */
15
+ class Enlimbo_Forms_Wpcf
16
+ {
17
+
18
+ /**
19
+ * @var string
20
+ */
21
+ private $_id;
22
+
23
+ /**
24
+ * @var array
25
+ */
26
+ private $_errors = array();
27
+
28
+ /**
29
+ * @var array
30
+ */
31
+ private $_elements = array();
32
+
33
+ /**
34
+ * Failed elements.
35
+ *
36
+ * @var type
37
+ */
38
+ private $_elements_not_valid = array();
39
+
40
+ /**
41
+ * @var array
42
+ */
43
+ private $_count = array();
44
+
45
+ /**
46
+ * @var string
47
+ */
48
+ public $css_class = 'wpcf-form';
49
+
50
+ /**
51
+ * Auto handler
52
+ *
53
+ * Renders.
54
+ *
55
+ * @param array $element
56
+ * @return HTML formatted output
57
+ */
58
+ public function autoHandle( $id, $form )
59
+ {
60
+ // Auto-add wpnonce field
61
+ $form['_wpnonce'] = array(
62
+ '#type' => 'markup',
63
+ '#markup' => wp_nonce_field( $id, '_wpnonce_wpcf', true, false )
64
+ );
65
+
66
+ $this->_id = $id;
67
+ $this->_elements = $form;
68
+
69
+ do_action( 'wpcf_form_autohandle', $id, $form, $this );
70
+ do_action( 'wpcf_form_autohandle_' . $id, $form, $this );
71
+
72
+ // get submitted data
73
+ if ( $this->isSubmitted() ) {
74
+
75
+ do_action( 'wpcf_form_autohandle_submit', $id, $form, $this );
76
+ do_action( 'wpcf_form_autohandle_submit_' . $id, $form, $this );
77
+
78
+ // check if errors (validation)
79
+ $this->validate( $this->_elements );
80
+
81
+ do_action( 'wpcf_form_autohandle_validate', $id, $form, $this );
82
+ do_action( 'wpcf_form_autohandle_validate_' . $id, $form, $this );
83
+
84
+ // callback
85
+ if ( empty( $this->_errors ) ) {
86
+
87
+ if ( isset( $form['#form']['callback'] ) ) {
88
+ if ( is_array( $form['#form']['callback'] ) ) {
89
+ foreach ( $form['#form']['callback'] as $callback ) {
90
+ if ( is_callable( $callback ) ) {
91
+ call_user_func( $callback, $this );
92
+ }
93
+ }
94
+ } else {
95
+ if ( is_callable( $form['#form']['callback'] ) ) {
96
+ call_user_func( $form['#form']['callback'], $this );
97
+ }
98
+ }
99
+ }
100
+ // Maybe triggered by callback function
101
+ if ( empty( $this->_errors ) ) {
102
+ // redirect
103
+ do_action( 'wpcf_form_autohandle_redirection', $id, $form,
104
+ $this );
105
+ do_action( 'wpcf_form_autohandle_redirection_' . $id, $form,
106
+ $this );
107
+ if ( !isset( $form['#form']['redirection'] ) ) {
108
+ header( 'Location: ' . $_SERVER['REQUEST_URI'] );
109
+ } else if ( $form['#form']['redirection'] != false ) {
110
+ header( 'Location: ' . $form['#form']['redirection'] );
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Checks if form is submitted.
119
+ *
120
+ * @param type $id
121
+ * @return type
122
+ */
123
+ public function isSubmitted( $id = '' )
124
+ {
125
+ if ( empty( $id ) ) {
126
+ $id = $this->_id;
127
+ }
128
+ return (isset( $_REQUEST['_wpnonce_wpcf'] )
129
+ && wp_verify_nonce( $_REQUEST['_wpnonce_wpcf'], $id ));
130
+ }
131
+
132
+ /**
133
+ * Loops over elements and validates them.
134
+ *
135
+ * @param type $elements
136
+ */
137
+ public function validate( &$elements )
138
+ {
139
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/validate.php';
140
+ foreach ( $elements as $key => &$element ) {
141
+ if ( !isset( $element['#type'] )
142
+ || !$this->_isValidType( $element['#type'] ) ) {
143
+ continue;
144
+ }
145
+ if ( $element['#type'] != 'fieldset' ) {
146
+ if ( isset( $element['#name'] )
147
+ && !in_array( $element['#type'],
148
+ array('submit', 'reset') ) ) {
149
+ // Set submitted data
150
+ if ( !in_array( $element['#type'], array('checkboxes') )
151
+ && empty( $element['#forced_value'] ) ) {
152
+ $element['#value'] = $this->getSubmittedData( $element );
153
+ } else if ( !empty( $element['#options'] )
154
+ && empty( $element['#forced_value'] ) ) {
155
+ foreach ( $element['#options'] as $option_key => $option ) {
156
+ $option['#type'] = 'checkbox';
157
+ $element['#options'][$option_key]['#value'] = $this->getSubmittedData( $option );
158
+ }
159
+ }
160
+ }
161
+ // Validate
162
+ if ( isset( $element['#validate'] ) ) {
163
+ $this->validateElement( $element );
164
+ }
165
+ } else if ( isset( $element['#type'] )
166
+ && $element['#type'] == 'fieldset' ) {
167
+ $this->validate( $element );
168
+ } else if ( is_array( $element ) ) {
169
+ $this->validate( $element );
170
+ }
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Validates element.
176
+ *
177
+ * @param type $element
178
+ */
179
+ public function validateElement( &$element )
180
+ {
181
+ $check = Wpcf_Validate::check( $element['#validate'], $element['#value'] );
182
+ if ( isset( $check['error'] ) ) {
183
+ $this->_errors = true;
184
+ $element['#error'] = $check['message'];
185
+ if ( isset( $element['wpcf-id'] ) ) {
186
+ $this->_elements_not_valid[$element['wpcf-id']] = $element;
187
+ }
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Returns not valid elements.
193
+ *
194
+ * @return type
195
+ */
196
+ public function get_not_valid() {
197
+ return $this->_elements_not_valid;
198
+ }
199
+
200
+ /**
201
+ * Checks if there are errors.
202
+ *
203
+ * @return type
204
+ */
205
+ public function isError()
206
+ {
207
+ return $this->_errors;
208
+ }
209
+
210
+ /**
211
+ * Sets errors to true.
212
+ */
213
+ public function triggerError()
214
+ {
215
+ $this->_errors = true;
216
+ }
217
+
218
+ /**
219
+ * Renders form.
220
+ *
221
+ * @return type
222
+ */
223
+ public function renderForm()
224
+ {
225
+ // loop over elements and render them
226
+ return $this->renderElements( $this->_elements );
227
+ }
228
+
229
+ /**
230
+ * Counts element types.
231
+ *
232
+ * @param type $type
233
+ * @return type
234
+ */
235
+ private function _count( $type ) {
236
+ if ( !isset( $this->_count[$type] ) ) {
237
+ $this->_count[$type] = 0;
238
+ }
239
+ $this->_count[$type] += 1;
240
+ return $this->_count[$type];
241
+ }
242
+
243
+ /**
244
+ * Check if element is of valid type
245
+ *
246
+ * @param string $type
247
+ * @return boolean
248
+ */
249
+ private function _isValidType( $type )
250
+ {
251
+ return in_array( $type,
252
+ array('select', 'checkboxes', 'checkbox', 'radios',
253
+ 'radio', 'textfield', 'textarea', 'file', 'submit', 'reset',
254
+ 'hidden', 'fieldset', 'markup', 'button') );
255
+ }
256
+
257
+ /**
258
+ * Renders elements.
259
+ *
260
+ * @param type $elements
261
+ * @return type
262
+ */
263
+ public function renderElements( $elements )
264
+ {
265
+ $output = '';
266
+ foreach ( $elements as $key => $element ) {
267
+ if ( !isset( $element['#type'] )
268
+ || !$this->_isValidType( $element['#type'] ) ) {
269
+ continue;
270
+ }
271
+ if ( $element['#type'] != 'fieldset' ) {
272
+ $output .= $this->renderElement( $element );
273
+ } else if ( isset( $element['#type'] )
274
+ && $element['#type'] == 'fieldset' ) {
275
+ $buffer = $this->renderElements( $element );
276
+ $output .= $this->fieldset( $element, 'wrap', $buffer );
277
+ } else if ( is_array( $element ) ) {
278
+ $output .= $this->renderElements( $element );
279
+ }
280
+ }
281
+ return $output;
282
+ }
283
+
284
+ /**
285
+ * Renders element.
286
+ *
287
+ * Depending on element type, it calls class methods.
288
+ *
289
+ * @param array $element
290
+ * @return HTML formatted output
291
+ */
292
+ public function renderElement( $element )
293
+ {
294
+ $method = $element['#type'];
295
+ if ( !isset( $element['#name'] ) && $element['#type'] != 'markup' ) {
296
+ if ( !isset( $element['#attributes']['name'] ) ) {
297
+ return '#name or #attributes[\'name\'] required!';
298
+ } else {
299
+ $element['#name'] = $element['#attributes']['name'];
300
+ }
301
+ }
302
+ if ( is_callable( array($this, $method) ) ) {
303
+ if ( !isset( $element['#id'] ) ) {
304
+ if ( isset( $element['#attributes']['id'] ) ) {
305
+ $element['#id'] = $element['#attributes']['id'];
306
+ } else {
307
+ $element['#id'] = $element['#type'] . '-'
308
+ . $this->_count( $element['#type'] );
309
+ }
310
+ }
311
+ if ( isset( $this->_errors[$element['#id']] ) ) {
312
+ $element['#error'] = $this->_errors[$element['#id']];
313
+ }
314
+ // Add JS validation
315
+ if ( !empty( $element['#validate'] ) ) {
316
+ wpcf_form_add_js_validation( $element );
317
+ }
318
+ return $this->{$method}( $element );
319
+ }
320
+ }
321
+
322
+ /**
323
+ * Sets other element attributes.
324
+ *
325
+ * @param array $element
326
+ * @return string
327
+ */
328
+ private function _setElementAttributes( $element )
329
+ {
330
+ $attributes = '';
331
+ $error_class = isset( $element['#error'] ) ? ' ' . $this->css_class . '-error ' . $this->css_class . '-' . $element['#type'] . '-error ' . ' form-' . $element['#type'] . '-error ' . $element['#type'] . '-error form-error ' : '';
332
+ $class = $this->css_class . '-' . $element['#type']
333
+ . ' form-' . $element['#type'] . ' ' . $element['#type'];
334
+ // Add JS validation
335
+ // if ( !empty( $element['#validate'] ) ) {
336
+ // $class .= ' js-types-validate';
337
+ // }
338
+ if ( isset( $element['#attributes'] ) ) {
339
+ foreach ( $element['#attributes'] as $attribute => $value ) {
340
+ // Prevent undesired elements
341
+ if ( in_array( $attribute, array('id', 'name') ) ) {
342
+ continue;
343
+ }
344
+ // Don't set disabled for checkbox
345
+ // if ( $attribute == 'disabled' && $element['#type'] == 'checkbox' ) {
346
+ // continue;
347
+ // }
348
+ // Append class values
349
+ if ( $attribute == 'class' ) {
350
+ $value = $value . ' ' . $class . $error_class;
351
+ }
352
+ // Set return string
353
+ $attributes .= ' ' . $attribute . '="' . $value . '"';
354
+ }
355
+ }
356
+ if ( !isset( $element['#attributes']['class'] ) ) {
357
+ $attributes .= ' class="' . $class . $error_class . '"';
358
+ }
359
+ return $attributes;
360
+ }
361
+
362
+ /**
363
+ * Sets render elements.
364
+ *
365
+ * @param array $element
366
+ */
367
+ private function _setRender( $element )
368
+ {
369
+ if ( !isset( $element['#id'] ) ) {
370
+ if ( isset( $element['#attributes']['id'] ) ) {
371
+ $element['#id'] = $element['#attributes']['id'];
372
+ } else {
373
+ $element['#id'] = 'form-' . md5( serialize( $element ) ) . '-'
374
+ . $this->_count( $element['#type'] );
375
+ }
376
+ }
377
+ $element['_attributes_string'] = $this->_setElementAttributes( $element );
378
+ $element['_render'] = array();
379
+ $element['_render']['prefix'] = isset( $element['#prefix'] ) ? $element['#prefix'] . "\r\n" : '';
380
+ $element['_render']['suffix'] = isset( $element['#suffix'] ) ? $element['#suffix'] . "\r\n" : '';
381
+ $element['_render']['before'] = isset( $element['#before'] ) ? $element['#before'] . "\r\n" : '';
382
+ $element['_render']['after'] = isset( $element['#after'] ) ? $element['#after'] . "\r\n" : '';
383
+ $element['_render']['label'] = isset( $element['#title'] ) ? '<label class="'
384
+ . $this->css_class . '-label ' . $this->css_class . '-'
385
+ . $element['#type'] . '-label" for="' . $element['#id'] . '">'
386
+ . stripslashes( $element['#title'] )
387
+ . '</label>' . "\r\n" : '';
388
+ $element['_render']['title'] = $this->_setElementTitle( $element );
389
+ $element['_render']['description'] = !empty( $element['#description'] ) ? $this->_setElementDescription( $element ) : '';
390
+ $element['_render']['error'] = $this->renderError( $element ) . "\r\n";
391
+
392
+ return $element;
393
+ }
394
+
395
+ /**
396
+ * Applies pattern to output.
397
+ *
398
+ * Pass element property #pattern to get custom renedered element.
399
+ *
400
+ * @param array $pattern
401
+ * Accepts: <prefix><suffix><label><title><desription><error>
402
+ * @param array $element
403
+ */
404
+ private function _pattern( $pattern, $element )
405
+ {
406
+ foreach ( $element['_render'] as $key => $value ) {
407
+ $pattern = str_replace( '<' . strtoupper( $key ) . '>', $value,
408
+ $pattern );
409
+ }
410
+ return $pattern;
411
+ }
412
+
413
+ /**
414
+ * Wrapps element in <div></div>.
415
+ *
416
+ * @param arrat $element
417
+ * @param string $output
418
+ * @return string
419
+ */
420
+ private function _wrapElement( $element, $output )
421
+ {
422
+ if ( empty( $element['#inline'] ) ) {
423
+ $wrapped = '<div id="' . $element['#id'] . '-wrapper"'
424
+ . ' class="form-item form-item-' . $element['#type'] . ' '
425
+ . $this->css_class . '-item '
426
+ . $this->css_class . '-item-' . $element['#type']
427
+ . '">' . $output . '</div>';
428
+ return $wrapped;
429
+ }
430
+ return $output;
431
+ }
432
+
433
+ /**
434
+ * Returns HTML formatted output for element's title.
435
+ *
436
+ * @param string $element
437
+ * @return string
438
+ */
439
+ private function _setElementTitle( $element )
440
+ {
441
+ $output = '';
442
+ if ( isset( $element['#title'] ) ) {
443
+ $output .= '<div class="title '
444
+ . $this->css_class . '-title '
445
+ . $this->css_class . '-title-' . $element['#type'] . ' '
446
+ . 'title-' . $element['#type'] . '">'
447
+ . stripslashes( $element['#title'] )
448
+ . "</div>\r\n";
449
+ }
450
+ return $output;
451
+ }
452
+
453
+ /**
454
+ * Returns HTML formatted output for element's description.
455
+ *
456
+ * @param array $element
457
+ * @return string
458
+ */
459
+ private function _setElementDescription( $element )
460
+ {
461
+ $element['#description'] = stripslashes( $element['#description'] );
462
+ $output = "\r\n"
463
+ . '<div class="description '
464
+ . $this->css_class . '-description '
465
+ . $this->css_class . '-description-' . $element['#type'] . ' '
466
+ . 'description-' . $element['#type'] . '">'
467
+ . $element['#description'] . "</div>\r\n";
468
+ return $output;
469
+ }
470
+
471
+ /**
472
+ * Returns HTML formatted element's error message.
473
+ *
474
+ * Pass #supress_errors in #form element to avoid error rendering.
475
+ *
476
+ * @param array $element
477
+ * @return string
478
+ */
479
+ public function renderError( $element )
480
+ {
481
+ if ( !isset( $element['#error'] ) ) {
482
+ return '';
483
+ }
484
+ $output = '<div class="form-error '
485
+ . $this->css_class . '-error '
486
+ . $this->css_class . '-form-error '
487
+ . $this->css_class . '-' . $element['#type'] . '-error '
488
+ . $element['#type'] . '-error form-error-label'
489
+ . '">' . $element['#error'] . '</div>'
490
+ . "\r\n";
491
+ return $output;
492
+ }
493
+
494
+ /**
495
+ * Returns HTML formatted output for fieldset.
496
+ *
497
+ * @param array $element
498
+ * @param string $action open|close|wrap
499
+ * @param string $wrap_content HTML formatted output of child elements
500
+ * @return string
501
+ */
502
+ public function fieldset( $element, $action = 'open', $wrap_content = '' )
503
+ {
504
+ $collapsible_open = '<div class="fieldset-wrapper">';
505
+ $collapsible_close = '</div>';
506
+ $legend_class = '';
507
+ if ( !isset( $element['#id'] ) ) {
508
+ $element['#id'] = 'fieldset-' . $this->_count( 'fieldset' );
509
+ }
510
+ if ( !isset( $element['_attributes_string'] ) ) {
511
+ $element['_attributes_string'] = $this->_setElementAttributes( $element );
512
+ }
513
+ if ( (isset( $element['#collapsible'] ) && $element['#collapsible'])
514
+ || (isset( $element['#collapsed'] ) && $element['#collapsed']) ) {
515
+ $collapsible_open = '<div class="collapsible fieldset-wrapper">';
516
+ $collapsible_close = '</div>';
517
+ $legend_class = ' class="legend-expanded"';
518
+ }
519
+ if ( isset( $element['#collapsed'] ) && $element['#collapsed'] ) {
520
+ $collapsible_open = str_replace( 'class="', 'class="collapsed ',
521
+ $collapsible_open );
522
+ $legend_class = ' class="legend-collapsed"';
523
+ }
524
+ $output = '';
525
+ switch ( $action ) {
526
+ case 'close':
527
+ $output .= $collapsible_close . "</fieldset>\r\n";
528
+ $output .= isset( $element['#suffix'] ) ? $element['#suffix']
529
+ . "\r\n" : '';
530
+ $output .= "\n\r";
531
+ break;
532
+
533
+ case 'open':
534
+ $output .= $collapsible_open;
535
+ $output .= isset( $element['#prefix'] ) ? $element['#prefix']
536
+ . "\r\n" : '';
537
+ $output .= '<fieldset' . $element['_attributes_string']
538
+ . ' id="' . $element['#id'] . '">' . "\r\n";
539
+ $output .= isset( $element['#title'] ) ? '<legend'
540
+ . $legend_class . '>'
541
+ . stripslashes( $element['#title'] )
542
+ . "</legend>\r\n" : '';
543
+ $output .=
544
+ !empty( $element['#description'] ) ? $this->_setElementDescription( $element ) : '';
545
+ $output .= "\n\r";
546
+ break;
547
+
548
+ case 'wrap':
549
+ if ( !empty( $wrap_content ) ) {
550
+ $output .= isset( $element['#prefix'] ) ? $element['#prefix'] : '';
551
+ $output .= '<fieldset' . $element['_attributes_string']
552
+ . ' id="' . $element['#id'] . '">' . "\r\n";
553
+ $output .= '<legend' . $legend_class . '>'
554
+ . stripslashes( $element['#title'] )
555
+ . "</legend>\r\n"
556
+ . $collapsible_open;
557
+ $output .=!empty( $element['#description'] ) ? $this->_setElementDescription( $element ) : '';
558
+ $output .= $wrap_content . $collapsible_close
559
+ . "</fieldset>\r\n";
560
+ $output .=
561
+ isset( $element['#suffix'] ) ? $element['#suffix'] : '';
562
+ $output .= "\n\r";
563
+ }
564
+ break;
565
+ }
566
+ return $output;
567
+ }
568
+
569
+ /**
570
+ * Returns HTML formatted output for checkbox element.
571
+ *
572
+ * @param array $element
573
+ * @return string
574
+ */
575
+ public function checkbox( $element )
576
+ {
577
+ $element['#type'] = 'checkbox';
578
+ $element = $this->_setRender( $element );
579
+ $element['_render']['element'] = '<input type="checkbox" id="'
580
+ . $element['#id'] . '" name="'
581
+ . $element['#name'] . '" value="';
582
+ // Specific: if value is empty force 1 to be rendered
583
+ $element['_render']['element'] .=
584
+ !empty( $element['#value'] ) ? htmlspecialchars( $element['#value'] ) : 1;
585
+ $element['_render']['element'] .= '"' . $element['_attributes_string'];
586
+ $element['_render']['element'] .= ((!$this->isSubmitted()
587
+ && !empty( $element['#default_value'] ))
588
+ || ($this->isSubmitted()
589
+ && !empty( $element['#value'] ))) ? ' checked="checked"' : '';
590
+ // Removed because not checkboxes can be disabled
591
+ // if ( !empty( $element['#attributes']['disabled'] ) || !empty( $element['#disable'] ) ) {
592
+ // $element['_render']['element'] .= ' onclick="javascript:return false; if(this.checked == 1){this.checked=1; return true;}else{this.checked=0; return false;}"';
593
+ // }
594
+ $element['_render']['element'] .= ' />';
595
+ $pattern = isset( $element['#pattern'] ) ? $element['#pattern'] : '<BEFORE><PREFIX><ELEMENT>&nbsp;<LABEL><ERROR><SUFFIX><DESCRIPTION><AFTER>';
596
+ $output = $this->_pattern( $pattern, $element );
597
+ $output = $this->_wrapElement( $element, $output );
598
+ return $output . "\r\n";
599
+ }
600
+
601
+ /**
602
+ * Returns HTML formatted output for checkboxes element.
603
+ *
604
+ * Renders more than one checkboxes provided as elements in '#options'
605
+ * array element.
606
+ *
607
+ * @param array $element
608
+ * @return string
609
+ */
610
+ public function checkboxes( $element )
611
+ {
612
+ $element['#type'] = 'checkboxes';
613
+ $element = $this->_setRender( $element );
614
+ $clone = $element;
615
+ $clone['#type'] = 'checkbox';
616
+ $element['_render']['element'] = '';
617
+ foreach ( $element['#options'] as $ID => $value ) {
618
+ if ( !is_array( $value ) ) {
619
+ $value = array('#title' => $ID, '#value' => $value, '#name' => $element['#name'] . '[]');
620
+ }
621
+ $element['_render']['element'] .= $this->checkbox( $value );
622
+ }
623
+ $pattern = isset( $element['#pattern'] ) ? $element['#pattern'] : '<BEFORE><PREFIX><TITLE><DESCRIPTION><ELEMENT><SUFFIX><AFTER>';
624
+ $output = $this->_pattern( $pattern, $element );
625
+ $output = $this->_wrapElement( $element, $output );
626
+ return $output;
627
+ }
628
+
629
+ /**
630
+ * Returns HTML formatted output for radio element.
631
+ *
632
+ * @param array $element
633
+ * @return string
634
+ */
635
+ public function radio( $element )
636
+ {
637
+ $element['#type'] = 'radio';
638
+ $element = $this->_setRender( $element );
639
+ $element['_render']['element'] = '<input type="radio" id="'
640
+ . $element['#id'] . '" name="'
641
+ . $element['#name'] . '" value="';
642
+ $element['_render']['element'] .= isset( $element['#value'] ) ? htmlspecialchars( $element['#value'] ) : $this->_count['radio'];
643
+ $element['_render']['element'] .= '"';
644
+ $element['_render']['element'] .= $element['_attributes_string'];
645
+ $element['_render']['element'] .= ( isset( $element['#value'] )
646
+ && $element['#value'] === $element['#default_value']) ? ' checked="checked"' : '';
647
+ if ( isset( $element['#disable'] ) && $element['#disable'] ) {
648
+ $element['_render']['element'] .= ' disabled="disabled"';
649
+ }
650
+ $element['_render']['element'] .= ' />';
651
+ $pattern = isset( $element['#pattern'] ) ? $element['#pattern'] : '<BEFORE><PREFIX><ELEMENT>&nbsp;<LABEL><ERROR><SUFFIX><DESCRIPTION><AFTER>';
652
+ $output = $this->_pattern( $pattern, $element );
653
+ $output = $this->_wrapElement( $element, $output );
654
+ return $output . "\r\n";
655
+ }
656
+
657
+ /**
658
+ * Returns HTML formatted output for radios elements.
659
+ *
660
+ * Radios are provided via #options array.
661
+ * Requires #name value.
662
+ *
663
+ * @param array $element
664
+ * @return string
665
+ */
666
+ public function radios( $element )
667
+ {
668
+ if ( !isset( $element['#name'] ) || empty( $element['#name'] ) ) {
669
+ return FALSE;
670
+ }
671
+ $element['#type'] = 'radios';
672
+ $element = $this->_setRender( $element );
673
+ $element['_render']['element'] = '';
674
+ foreach ( $element['#options'] as $ID => $value ) {
675
+ $this->_count( 'radio' );
676
+ if ( !is_array( $value ) ) {
677
+ $value = array('#title' => $ID, '#value' => $value);
678
+ $value['#inline'] = true;
679
+ $value['#after'] = '<br />';
680
+ }
681
+ $value['#name'] = $element['#name'];
682
+ $value['#default_value'] = isset( $element['#default_value'] ) ? $element['#default_value'] : $value['#value'];
683
+ $value['#disable'] = isset( $element['#disable'] ) ? $element['#disable'] : false;
684
+ $element['_render']['element'] .= $this->radio( $value );
685
+ }
686
+ $pattern = isset( $element['#pattern'] ) ? $element['#pattern'] : '<BEFORE><PREFIX><TITLE><DESCRIPTION><ELEMENT><SUFFIX><AFTER>';
687
+ $output = $this->_pattern( $pattern, $element );
688
+ $output = $this->_wrapElement( $element, $output );
689
+ return $output;
690
+ }
691
+
692
+ /**
693
+ * Returns HTML formatted output for select element.
694
+ *
695
+ * @param array $element
696
+ * @return string
697
+ */
698
+ public function select( $element )
699
+ {
700
+ $element['#type'] = 'select';
701
+ $element = $this->_setRender( $element );
702
+ $element['_render']['element'] = '<select id="' . $element['#id']
703
+ . '" name="' . $element['#name'] . '"'
704
+ . $element['_attributes_string'] . ">\r\n";
705
+ $count = 1;
706
+ foreach ( $element['#options'] as $id => $value ) {
707
+ if ( !is_array( $value ) ) {
708
+ $value = array('#title' => $id, '#value' => $value);
709
+ }
710
+ if ( !isset( $value['#value'] ) ) {
711
+ $value['#value'] = $this->_count['select'] . '-' . $count;
712
+ $count += 1;
713
+ }
714
+ $value['#type'] = 'option';
715
+ $element['_render']['element'] .= '<option value="'
716
+ . htmlspecialchars( $value['#value'] ) . '"';
717
+ $element['_render']['element'] .= ( $element['#default_value']
718
+ == $value['#value']) ? ' selected="selected"' : '';
719
+ $element['_render']['element'] .= $this->_setElementAttributes( $value );
720
+ $element['_render']['element'] .= '>';
721
+ $element['_render']['element'] .= $this->strip( isset( $value['#title'] ) ? $value['#title'] : $value['#value'] );
722
+ $element['_render']['element'] .= "</option>\r\n";
723
+ }
724
+ $element['_render']['element'] .= "</select>\r\n";
725
+ $pattern = isset( $element['#pattern'] ) ? $element['#pattern'] : '<BEFORE><LABEL><DESCRIPTION><ERROR><PREFIX><ELEMENT><SUFFIX><AFTER>';
726
+ $output = $this->_pattern( $pattern, $element );
727
+ $output = $this->_wrapElement( $element, $output );
728
+ return $output;
729
+ }
730
+
731
+ /**
732
+ * Returns HTML formatted output for textfield element.
733
+ *
734
+ * @param array $element
735
+ * @return string
736
+ */
737
+ public function textfield( $element )
738
+ {
739
+ $element['#type'] = 'textfield';
740
+ $element = $this->_setRender( $element );
741
+ $element['_render']['element'] = '<input type="text" id="'
742
+ . $element['#id'] . '" name="' . $element['#name'] . '" value="';
743
+ $element['_render']['element'] .= isset( $element['#value'] ) ? htmlspecialchars( stripslashes( $element['#value'] ) ) : '';
744
+ $element['_render']['element'] .= '"' . $element['_attributes_string'];
745
+ if ( isset( $element['#disable'] ) && $element['#disable'] ) {
746
+ $element['_render']['element'] .= ' disabled="disabled"';
747
+ }
748
+ $element['_render']['element'] .= ' />';
749
+ $pattern = isset( $element['#pattern'] ) ? $element['#pattern'] : '<BEFORE><LABEL><ERROR><PREFIX><ELEMENT><SUFFIX><DESCRIPTION><AFTER>';
750
+ $output = $this->_pattern( $pattern, $element );
751
+ $output = $this->_wrapElement( $element, $output );
752
+ return $output . "\r\n";
753
+ }
754
+
755
+ /**
756
+ * Returns HTML formatted output for textfield element.
757
+ *
758
+ * @param array $element
759
+ * @return string
760
+ */
761
+ public function password( $element )
762
+ {
763
+ $element['#type'] = 'password';
764
+ $element = $this->_setRender( $element );
765
+ $element['_render']['element'] = '<input type="password" id="'
766
+ . $element['#id'] . '" name="' . $element['#name'] . '" value="';
767
+ $element['_render']['element'] .= isset( $element['#value'] ) ? $element['#value'] : '';
768
+ $element['_render']['element'] .= '"' . $element['_attributes_string'];
769
+ if ( isset( $element['#disable'] ) && $element['#disable'] ) {
770
+ $element['_render']['element'] .= ' disabled="disabled"';
771
+ }
772
+ $element['_render']['element'] .= ' />';
773
+ $pattern = isset( $element['#pattern'] ) ? $element['#pattern'] : '<BEFORE><LABEL><ERROR><PREFIX><ELEMENT><SUFFIX><DESCRIPTION><AFTER>';
774
+ $output = $this->_pattern( $pattern, $element );
775
+ $output = $this->_wrapElement( $element, $output );
776
+ return $output . "\r\n";
777
+ }
778
+
779
+ /**
780
+ * Returns HTML formatted output for textarea element.
781
+ *
782
+ * @param array $element
783
+ * @return string
784
+ */
785
+ public function textarea( $element )
786
+ {
787
+ $element['#type'] = 'textarea';
788
+ if ( !isset( $element['#attributes']['rows'] ) ) {
789
+ $element['#attributes']['rows'] = 5;
790
+ }
791
+ if ( !isset( $element['#attributes']['cols'] ) ) {
792
+ $element['#attributes']['cols'] = 1;
793
+ }
794
+ $element = $this->_setRender( $element );
795
+ $element['_render']['element'] = '<textarea id="' . $element['#id']
796
+ . '" name="' . $element['#name'] . '"'
797
+ . $element['_attributes_string'] . '>';
798
+ $element['_render']['element'] .= isset( $element['#value'] ) ? htmlspecialchars( stripslashes( $element['#value'] ) ) : '';
799
+ $element['_render']['element'] .= '</textarea>' . "\r\n";
800
+ $pattern = isset( $element['#pattern'] ) ? $element['#pattern'] : '<BEFORE><LABEL><DESCRIPTION><ERROR><PREFIX><ELEMENT><SUFFIX><AFTER>';
801
+ $output = $this->_pattern( $pattern, $element );
802
+ $output = $this->_wrapElement( $element, $output );
803
+ return $output . "\r\n";
804
+ }
805
+
806
+ /**
807
+ * Returns HTML formatted output for file upload element.
808
+ *
809
+ * @param array $element
810
+ * @return string
811
+ */
812
+ public function file( $element )
813
+ {
814
+ $element['#type'] = 'file';
815
+ $element = $this->_setRender( $element );
816
+ $element['_render']['element'] = '<input type="file" id="'
817
+ . $element['#id'] . '" name="' . $element['#name'] . '"'
818
+ . $element['_attributes_string'];
819
+ if ( isset( $element['#disable'] ) && $element['#disable'] ) {
820
+ $element['_render']['element'] .= ' disabled="disabled"';
821
+ }
822
+ $element['_render']['element'] .= ' />';
823
+ $pattern = isset( $element['#pattern'] ) ? $element['#pattern'] : '<BEFORE><LABEL><ERROR><PREFIX><ELEMENT><DESCRIPTION><SUFFIX><AFTER>';
824
+ $output = $this->_pattern( $pattern, $element );
825
+ $output = $this->_wrapElement( $element, $output );
826
+ return $output;
827
+ }
828
+
829
+ /**
830
+ * Returns HTML formatted output for markup element.
831
+ *
832
+ * @param array $element
833
+ * @return string
834
+ */
835
+ public function markup( $element )
836
+ {
837
+ return $element['#markup'];
838
+ }
839
+
840
+ /**
841
+ * Returns HTML formatted output for hidden element.
842
+ *
843
+ * @param array $element
844
+ * @return string
845
+ */
846
+ public function hidden( $element )
847
+ {
848
+ $element['#type'] = 'hidden';
849
+ $element = $this->_setRender( $element );
850
+ $output = '<input type="hidden" ';
851
+ foreach( array('id', 'name' ) as $key ) {
852
+ $output .= sprintf( '%s="%s" ', $key, $element['#'.$key] );
853
+ }
854
+ $output .= sprintf( 'value="%s" ', isset( $element['#value'] ) ? $element['#value'] : 1 );
855
+ $output .= $element['_attributes_string'];
856
+ $output .= ' />';
857
+ return $output;
858
+ }
859
+
860
+ /**
861
+ * Returns HTML formatted output for reset button element.
862
+ *
863
+ * @param array $element
864
+ * @return string
865
+ */
866
+ public function reset( $element )
867
+ {
868
+ return $this->submit( $element, 'reset', 'Reset' );
869
+ }
870
+
871
+ /**
872
+ * Returns HTML formatted output for button element.
873
+ *
874
+ * @param array $element
875
+ * @return string
876
+ */
877
+ public function button( $element )
878
+ {
879
+ return $this->submit( $element, 'button', 'Button' );
880
+ }
881
+
882
+ /**
883
+ * Returns HTML formatted output for radio element.
884
+ *
885
+ * Used by reset and button.
886
+ *
887
+ * @param array $element
888
+ * @param string $type
889
+ * @param string $title
890
+ * @return string
891
+ */
892
+ public function submit( $element, $type = 'submit', $title = 'Submit' )
893
+ {
894
+ $element['#type'] = $type;
895
+ $element = $this->_setRender( $element );
896
+ $element['_render']['element'] = '<input type="' . $type . '" id="'
897
+ . $element['#id'] . '" name="' . $element['#name'] . '" value="';
898
+ $element['_render']['element'] .= isset( $element['#value'] ) ? $element['#value'] : $title;
899
+ $element['_render']['element'] .= '"' . $element['_attributes_string']
900
+ . ' />';
901
+ $pattern = isset( $element['#pattern'] ) ? $element['#pattern'] : '<BEFORE><PREFIX><ELEMENT><SUFFIX><AFTER>';
902
+ $output = $this->_pattern( $pattern, $element );
903
+ return $output;
904
+ }
905
+
906
+ /**
907
+ * Searches and returns submitted data for element.
908
+ *
909
+ * @param type $element
910
+ * @return type mixed
911
+ */
912
+ public function getSubmittedData( $element )
913
+ {
914
+ $name = $element['#name'];
915
+ if ( strpos( $name, '[' ) === false ) {
916
+ if ( $element['#type'] == 'file' ) {
917
+ return $_FILES[$name]['tmp_name'];
918
+ }
919
+ return isset( $_REQUEST[$name] ) ? $_REQUEST[$name] : in_array( $element['#type'],
920
+ array('textfield', 'textarea') ) ? '' : 0;
921
+ }
922
+
923
+ $parts = explode( '[', $name );
924
+ $parts = array_map( create_function( '&$a', 'return trim($a, \']\');' ),
925
+ $parts );
926
+ if ( !isset( $_REQUEST[$parts[0]] ) ) {
927
+ return in_array( $element['#type'], array('textfield', 'textarea') ) ? '' : 0;
928
+ }
929
+ $search = $_REQUEST[$parts[0]];
930
+ for ( $index = 0; $index < count( $parts ); $index++ ) {
931
+ $key = $parts[$index];
932
+ // We're at the end but no data retrieved
933
+ if ( !isset( $parts[$index + 1] ) ) {
934
+ return in_array( $element['#type'],
935
+ array('textfield', 'textarea') ) ? '' : 0;
936
+ }
937
+ $key_next = $parts[$index + 1];
938
+ if ( $index > 0 ) {
939
+ if ( !isset( $search[$key] ) ) {
940
+ return in_array( $element['#type'],
941
+ array('textfield', 'textarea') ) ? '' : 0;
942
+ } else {
943
+ $search = $search[$key];
944
+ }
945
+ }
946
+ if ( is_array( $search ) && array_key_exists( $key_next, $search ) ) {
947
+ if ( !is_array( $search[$key_next] ) ) {
948
+ return $search[$key_next];
949
+ }
950
+ }
951
+ }
952
+ return 0;
953
+ }
954
+
955
+ private function strip($value)
956
+ {
957
+ if ( empty( $value ) ) {
958
+ return $value;
959
+ }
960
+ $re = array( "/\\\\'/", '/\\\\"/' );
961
+ $to = array( "'", '"' );
962
+ return esc_attr( preg_replace( $re, $to, $value ) );
963
+ }
964
+ }
embedded/classes/helper.ajax.php ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Conditional class.
4
+ */
5
+
6
+ /**
7
+ * Conditional class.
8
+ */
9
+ class WPCF_Helper_Ajax
10
+ {
11
+
12
+ /**
13
+ * Process AJAX conditional verify.
14
+ *
15
+ * @global type $wpcf
16
+ * @param type $data
17
+ * @return boolean|string
18
+ */
19
+ public static function conditionalVerify( $data ) {
20
+
21
+ WPCF_Loader::loadInclude( 'fields' );
22
+ WPCF_Loader::loadInclude( 'fields-post' );
23
+ WPCF_Loader::loadInclude( 'conditional-display' );
24
+
25
+ global $wpcf;
26
+ $js_execute = '';
27
+ $_flag_relationship = false;
28
+ /*
29
+ *
30
+ * Determine post.
31
+ */
32
+ if ( empty( $data['wpcf'] ) && !empty( $data['wpcf_post_relationship'] ) ) {
33
+ /*
34
+ * Relationship case
35
+ */
36
+ $_temp = $data['wpcf_post_relationship'];
37
+ $parent_id = key( $_temp );
38
+ $_data = array_shift( $_temp );
39
+ $post_id = key( $_data );
40
+ $post = get_post( $post_id );
41
+ $posted_fields = $_data[$post_id];
42
+ $_flag_relationship = true;
43
+ /*
44
+ *
45
+ * Regular submission
46
+ */
47
+ } else {
48
+ if ( isset( $data['wpcf_main_post_id'] ) ) {
49
+ $post_id = intval( $data['wpcf_main_post_id'] );
50
+ $post = get_post( $post_id );
51
+ }
52
+ }
53
+
54
+ // No post
55
+ if ( empty( $post->ID ) ) {
56
+ return false;
57
+ }
58
+
59
+ // Get Groups (Fields) for current post
60
+ $groups = wpcf_admin_post_get_post_groups_fields( $post );
61
+
62
+ $_processed = array();
63
+ foreach ( $groups as $group ) {
64
+ if ( !empty( $group['fields'] ) ) {
65
+ foreach ( $group['fields'] as $field_id => $field ) {
66
+
67
+ // Check if already processed
68
+ if ( isset( $_processed[$field_id] ) ) {
69
+ continue;
70
+ }
71
+
72
+ if ( $wpcf->conditional->is_conditional( $field_id ) ) {
73
+ if ( $_flag_relationship ) {
74
+ // Process only submitted fields
75
+ if ( !isset( $posted_fields[WPCF_META_PREFIX . $field_id] ) ) {
76
+ continue;
77
+ }
78
+ $wpcf->conditional->set( $post, $field_id );
79
+ $wpcf->conditional->context = 'relationship';
80
+ $_relationship_name = false;
81
+ // Set name and other values processed by hooks
82
+ $parent = get_post( $parent_id );
83
+ if ( !empty( $parent->ID ) ) {
84
+ $wpcf->relationship->set( $parent, $post );
85
+ $wpcf->relationship->cf->set( $post, $field_id );
86
+ $_child = $wpcf->relationship->get_child();
87
+ $_child->form->cf->set( $post, $field_id );
88
+ $_relationship_name = $_child->form->alter_form_name( 'wpcf[' . $wpcf->conditional->cf['id'] . ']' );
89
+ }
90
+ if ( !$_relationship_name ) {
91
+ continue;
92
+ }
93
+ /*
94
+ * BREAKPOINT
95
+ * Adds filtering regular evaluation (not wpv_conditional)
96
+ */
97
+ add_filter( 'types_field_get_submitted_data',
98
+ 'wpcf_relationship_ajax_data_filter', 10, 2 );
99
+
100
+ $name = $_relationship_name;
101
+ } else {
102
+ $wpcf->conditional->set( $post, $field_id );
103
+ $name = 'wpcf[' . $wpcf->conditional->cf['id'] . ']';
104
+ }
105
+
106
+ // Evaluate
107
+ $passed = $wpcf->conditional->evaluate();
108
+
109
+ if ( $passed ) {
110
+ $js_execute .= 'jQuery(\'[name^="' . $name . '"]\').parents(\'.'
111
+ . 'wpcf-conditional' . '\').show().removeClass(\''
112
+ . 'wpcf-conditional' . '-failed\').addClass(\''
113
+ . 'wpcf-conditional' . '-passed\');' . " ";
114
+ $js_execute .= 'jQuery(\'[name^="' . $name
115
+ . '"]\').parents(\'.wpcf-repetitive-wrapper\').show();';
116
+ } else {
117
+ $js_execute .= 'jQuery(\'[name^="' . $name
118
+ . '"]\').parents(\'.wpcf-repetitive-wrapper\').hide();';
119
+ $js_execute .= 'jQuery(\'[name^="' . $name . '"]\').parents(\'.'
120
+ . 'wpcf-conditional' . '\').hide().addClass(\''
121
+ . 'wpcf-conditional' . '-failed\').removeClass(\''
122
+ . 'wpcf-conditional' . '-passed\');' . " ";
123
+ }
124
+ }
125
+ $_processed[$field_id] = true;
126
+ }
127
+ }
128
+ }
129
+ return $js_execute;
130
+ }
131
+
132
+ }
embedded/classes/loader.php ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ * Loader class
5
+ *
6
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/cck/tags/1.6/embedded/classes/loader.php $
7
+ * $LastChangedDate: 2014-06-27 01:13:20 +0800 (Fri, 27 Jun 2014) $
8
+ * $LastChangedRevision: 24403 $
9
+ * $LastChangedBy: juan $
10
+ *
11
+ */
12
+
13
+ /**
14
+ * Loader Class
15
+ *
16
+ * @since Types 1.2
17
+ * @package Types
18
+ * @subpackage Classes
19
+ * @version 0.2
20
+ * @category Loader
21
+ * @author srdjan <srdjan@icanlocalize.com>
22
+ */
23
+ class WPCF_Loader
24
+ {
25
+
26
+ /**
27
+ * Settings
28
+ * @var array
29
+ */
30
+ private static $__settings = array();
31
+
32
+ public static function init( $settings = array() ) {
33
+ self::$__settings = (array) $settings;
34
+ self::__registerScripts();
35
+ self::__registerStyles();
36
+ self::__toolset();
37
+ add_action( 'admin_print_scripts',
38
+ array('WPCF_Loader', 'renderJsSettings'), 5 );
39
+ add_filter( 'the_posts', array('WPCF_Loader', 'wpcf_cache_complete_postmeta') );
40
+ }
41
+
42
+ /**
43
+ * Cache the postmeta for posts returned by a WP_Query
44
+ */
45
+
46
+ public static function wpcf_cache_complete_postmeta( $posts ) {
47
+ global $wpdb;
48
+ if ( !$posts )
49
+ return $posts;
50
+ $post_ids = array();
51
+ $cache_group_ids = 'types_cache_ids';
52
+ $cache_group = 'types_cache';
53
+ foreach ( $posts as $post ) {
54
+ $cache_key_looped_post = md5( 'post::_is_cached' . $post->ID );
55
+ $cached_object = wp_cache_get( $cache_key_looped_post, $cache_group_ids );
56
+ if ( false === $cached_object ) {
57
+ $post_ids[] = $post->ID;
58
+ wp_cache_add( $cache_key_looped_post, $post->ID, $cache_group_ids );
59
+ }
60
+ }
61
+ if ( count( $post_ids ) > 0 ) {
62
+ $id_list = join( ',', $post_ids );
63
+ $all_postmeta = $wpdb->get_results( "SELECT * FROM {$wpdb->postmeta} WHERE post_id IN ($id_list)", OBJECT );
64
+ if ( !empty( $all_postmeta ) ) {
65
+ $cache_key_keys = array();
66
+ foreach ( $all_postmeta as $metarow ) {
67
+ $mpid = intval($metarow->post_id);
68
+ $mkey = $metarow->meta_key;
69
+ $cache_key_keys[$mpid . $mkey][] = $metarow;
70
+ }
71
+ foreach ( $cache_key_keys as $single_meta_keys => $single_meta_values ) {
72
+ $cache_key_looped_new = md5( 'field::_get_meta' . $single_meta_keys );
73
+ wp_cache_add( $cache_key_looped_new, $single_meta_values, $cache_group );// WordPress cache
74
+ }
75
+ }
76
+ }
77
+ return $posts;
78
+ }
79
+
80
+ /**
81
+ * Register scripts.
82
+ */
83
+ private static function __registerScripts() {
84
+ $min = '';//WPCF_DEBUG ? '-min' : '';
85
+ wp_register_script( 'types', WPCF_EMBEDDED_RES_RELPATH . '/js/basic.js',
86
+ array('jquery'), WPCF_VERSION, true );
87
+ wp_register_script( 'types-knockout',
88
+ WPCF_EMBEDDED_RES_RELPATH . '/js/knockout-2.2.1.js',
89
+ array('jquery'), WPCF_VERSION, true );
90
+ if ( !wp_script_is( 'toolset-colorbox', 'registered' ) ) {
91
+ wp_register_script( 'toolset-colorbox',
92
+ WPCF_EMBEDDED_RES_RELPATH . '/js/jquery.colorbox-min.js',
93
+ array('jquery'), WPCF_VERSION, true );
94
+ }
95
+ wp_register_script( 'types-utils',
96
+ WPCF_EMBEDDED_RES_RELPATH . "/js/utils{$min}.js", array('jquery'),
97
+ WPCF_VERSION, true );
98
+ wp_register_script( 'types-wp-views',
99
+ WPCF_EMBEDDED_RES_RELPATH . '/js/wp-views.js', array('jquery'),
100
+ WPCF_VERSION, true );
101
+ global $pagenow;
102
+ // Exclude on post edit screen
103
+ if ( defined( 'WPTOOLSET_FORMS_ABSPATH' )
104
+ && !in_array( $pagenow, array('edit.php', 'post.php', 'post-new.php') ) ) {
105
+ wp_register_script( 'types-conditional',
106
+ WPCF_EMBEDDED_RES_RELPATH . '/js/conditional.js',
107
+ array('types-utils'), WPCF_VERSION, true );
108
+ wp_register_script( 'types-validation',
109
+ WPCF_EMBEDDED_RES_RELPATH . "/js/validation{$min}.js",
110
+ array('jquery'), WPCF_VERSION, true );
111
+ }
112
+ // wp_register_script( 'types-jquery-validation',
113
+ // WPCF_EMBEDDED_RES_RELPATH . '/js/jquery-form-validation/jquery.validate-1.11.1.min.js',
114
+ // array('jquery'), WPCF_VERSION, true );
115
+ // wp_register_script( 'types-jquery-validation-additional',
116
+ // WPCF_EMBEDDED_RES_RELPATH . '/js/jquery-form-validation/additional-methods-1.11.1.min.js',
117
+ // array('types-jquery-validation'), WPCF_VERSION, true );
118
+ // wp_register_script( 'types-js-validation',
119
+ // WPCF_EMBEDDED_RES_RELPATH . '/js/jquery-form-validation/types.js',
120
+ // array('types-jquery-validation-additional'), WPCF_VERSION, true );
121
+ }
122
+
123
+ /**
124
+ * Register styles.
125
+ */
126
+ private static function __registerStyles() {
127
+ wp_register_style( 'types',
128
+ WPCF_EMBEDDED_RES_RELPATH . '/css/basic.css', array(),
129
+ WPCF_VERSION );
130
+ if ( !wp_style_is( 'toolset-colorbox', 'registered' ) ) {
131
+ wp_register_style( 'toolset-colorbox',
132
+ WPCF_EMBEDDED_RES_RELPATH . '/css/colorbox.css', array(),
133
+ WPCF_VERSION );
134
+ }
135
+ if ( !wp_style_is( 'toolset-font-awesome', 'registered' ) ) {
136
+ wp_register_style( 'toolset-font-awesome',
137
+ WPCF_EMBEDDED_RES_RELPATH . '/css/font-awesome/css/font-awesome.min.css',
138
+ array('admin-bar', 'wp-admin', 'buttons', 'media-views'),
139
+ WPCF_VERSION );
140
+ }
141
+ if ( !wp_style_is( 'toolset-dashicons', 'registered' ) ) {
142
+ wp_register_style(
143
+ 'toolset-dashicons',
144
+ WPCF_EMBEDDED_RES_RELPATH . '/css/dashicons.css',
145
+ array(),
146
+ WPCF_VERSION
147
+ );
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Returns HTML formatted output.
153
+ *
154
+ * @param string $view
155
+ * @param mixed $data
156
+ * @return string
157
+ */
158
+ public static function view( $view, $data = array() ) {
159
+ $file = WPCF_EMBEDDED_ABSPATH . '/views/'
160
+ . strtolower( strval( $view ) ) . '.php';
161
+ if ( !file_exists( $file ) ) {
162
+ return '<code>missing_view</code>';
163
+ }
164
+ ob_start();
165
+ include $file;
166
+ $output = ob_get_contents();
167
+ ob_get_clean();
168
+
169
+ return apply_filters( 'wpcf_get_view', $output, $view, $data );
170
+ }
171
+
172
+ /**
173
+ * Returns HTML formatted output.
174
+ *
175
+ * @param string $view
176
+ * @param mixed $data
177
+ * @return string
178
+ */
179
+ public static function loadView( $view ) {
180
+ $file = WPCF_EMBEDDED_ABSPATH . '/views/'
181
+ . strtolower( strval( $view ) ) . '.php';
182
+ if ( !file_exists( $file ) ) {
183
+ return new WP_Error( 'types_loader', 'missing view ' . $view );
184
+ }
185
+ require_once $file;
186
+ }
187
+
188
+ /**
189
+ * Returns HTML formatted output.
190
+ *
191
+ * @param string $template
192
+ * @param mixed $data
193
+ * @return string
194
+ */
195
+ public static function template( $template, $data = array() ) {
196
+ $file = WPCF_EMBEDDED_ABSPATH . '/views/templates/'
197
+ . strtolower( strval( $template ) ) . '.tpl.php';
198
+ if ( !file_exists( $file ) ) {
199
+ return '<code>missing_template</code>';
200
+ }
201
+ ob_start();
202
+ include $file;
203
+ $output = ob_get_contents();
204
+ ob_get_clean();
205
+
206
+ return apply_filters( 'wpcf_get_template', $output, $template, $data );
207
+ }
208
+
209
+ /**
210
+ * Loads model.
211
+ *
212
+ * @param string $template
213
+ * @param mixed $data
214
+ * @return string
215
+ */
216
+ public static function loadModel( $model ) {
217
+ $file = WPCF_EMBEDDED_ABSPATH . '/models/'
218
+ . strtolower( strval( $model ) ) . '.php';
219
+ if ( !file_exists( $file ) ) {
220
+ return new WP_Error( 'types_loader', 'missing model ' . $model );
221
+ }
222
+ require_once $file;
223
+ }
224
+
225
+ /**
226
+ * Loads class.
227
+ *
228
+ * @param string $template
229
+ * @param mixed $data
230
+ * @return string
231
+ */
232
+ public static function loadClass( $class ) {
233
+ $file = WPCF_EMBEDDED_ABSPATH . '/classes/'
234
+ . strtolower( strval( $class ) ) . '.php';
235
+ if ( !file_exists( $file ) ) {
236
+ return new WP_Error( 'types_loader', 'missing class ' . $class );
237
+ }
238
+ require_once $file;
239
+ }
240
+
241
+ /**
242
+ * Loads include.
243
+ *
244
+ * @param string $template
245
+ * @param mixed $data
246
+ * @return string
247
+ */
248
+ public static function loadInclude( $name, $mode = 'embedded' ) {
249
+ $path = $mode == 'plugin' ? WPCF_ABSPATH : WPCF_EMBEDDED_ABSPATH;
250
+ $file = $path . '/includes/' . strtolower( strval( $name ) ) . '.php';
251
+ if ( !file_exists( $file ) ) {
252
+ return new WP_Error( 'types_loader', 'missing include ' . $name );
253
+ }
254
+ require_once $file;
255
+ }
256
+
257
+ /**
258
+ * Adds JS settings.
259
+ *
260
+ * @staticvar array $settings
261
+ * @param type $id
262
+ * @param type $setting
263
+ */
264
+ public static function addJsSetting( $id, $setting = '' ) {
265
+ self::$__settings[$id] = $setting;
266
+ }
267
+
268
+ /**
269
+ * Renders JS settings.
270
+ */
271
+ public static function renderJsSettings() {
272
+ $settings = (array) self::$__settings;
273
+ $settings['wpnonce'] = wp_create_nonce( '_typesnonce' );
274
+ $settings['cookiedomain'] = COOKIE_DOMAIN;
275
+ $settings['cookiepath'] = COOKIEPATH;
276
+ $settings['validation'] = array();
277
+ echo '
278
+ <script type="text/javascript">
279
+ //<![CDATA[
280
+ var types = ' . json_encode( $settings ) . ';
281
+ //]]>
282
+ </script>';
283
+ }
284
+
285
+ /**
286
+ * Toolset loading.
287
+ */
288
+ private static function __toolset() {
289
+ // Views
290
+ if ( defined( 'WPV_VERSION' ) ) {
291
+ self::loadClass( 'wpviews' );
292
+ WPCF_WPViews::init();
293
+ }
294
+ }
295
+
296
+ }
embedded/classes/path.php ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WPCF_Path
4
+ *
5
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/cck/tags/1.6/embedded/classes/path.php $
6
+ * $LastChangedDate: 2014-05-12 22:47:19 +0800 (Mon, 12 May 2014) $
7
+ * $LastChangedRevision: 22250 $
8
+ * $LastChangedBy: marcin $
9
+ *
10
+ */
11
+ final class WPCF_Path
12
+ {
13
+
14
+ /**
15
+ * Fix $_SERVER variables for various setups.
16
+ *
17
+ * @access private
18
+ * @since 3.0.0
19
+ */
20
+ public static function fixServerVars()
21
+ {
22
+ global $PHP_SELF;
23
+ static $fixedvars = false;
24
+
25
+ if ( $fixedvars )
26
+ return;
27
+
28
+ $default_server_values = array(
29
+ 'SERVER_SOFTWARE' => '',
30
+ 'REQUEST_URI' => '',
31
+ );
32
+
33
+ $_SERVER = array_merge( $default_server_values, $_SERVER );
34
+
35
+ // Fix for IIS when running with PHP ISAPI
36
+ if ( empty( $_SERVER['REQUEST_URI'] ) || ( php_sapi_name() != 'cgi-fcgi' && preg_match( '/^Microsoft-IIS\//',
37
+ $_SERVER['SERVER_SOFTWARE'] ) ) ) {
38
+
39
+ // IIS Mod-Rewrite
40
+ if ( isset( $_SERVER['HTTP_X_ORIGINAL_URL'] ) ) {
41
+ $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_ORIGINAL_URL'];
42
+ }
43
+ // IIS Isapi_Rewrite
44
+ else if ( isset( $_SERVER['HTTP_X_REWRITE_URL'] ) ) {
45
+ $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL'];
46
+ } else {
47
+ // Use ORIG_PATH_INFO if there is no PATH_INFO
48
+ if ( !isset( $_SERVER['PATH_INFO'] ) && isset( $_SERVER['ORIG_PATH_INFO'] ) )
49
+ $_SERVER['PATH_INFO'] = $_SERVER['ORIG_PATH_INFO'];
50
+
51
+ // Some IIS + PHP configurations puts the script-name in the path-info (No need to append it twice)
52
+ if ( isset( $_SERVER['PATH_INFO'] ) ) {
53
+ if ( $_SERVER['PATH_INFO'] == $_SERVER['SCRIPT_NAME'] )
54
+ $_SERVER['REQUEST_URI'] = $_SERVER['PATH_INFO'];
55
+ else
56
+ $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO'];
57
+ }
58
+
59
+ // Append the query string if it exists and isn't null
60
+ if ( !empty( $_SERVER['QUERY_STRING'] ) ) {
61
+ $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
62
+ }
63
+ }
64
+ }
65
+
66
+ // Fix for PHP as CGI hosts that set SCRIPT_FILENAME to something ending in php.cgi for all requests
67
+ if ( isset( $_SERVER['SCRIPT_FILENAME'] ) && ( strpos( $_SERVER['SCRIPT_FILENAME'],
68
+ 'php.cgi' ) == strlen( $_SERVER['SCRIPT_FILENAME'] ) - 7 ) )
69
+ $_SERVER['SCRIPT_FILENAME'] = $_SERVER['PATH_TRANSLATED'];
70
+
71
+ // Fix for Dreamhost and other PHP as CGI hosts
72
+ if ( strpos( $_SERVER['SCRIPT_NAME'], 'php.cgi' ) !== false )
73
+ unset( $_SERVER['PATH_INFO'] );
74
+
75
+ // Fix empty PHP_SELF
76
+ $PHP_SELF = $_SERVER['PHP_SELF'];
77
+ if ( empty( $PHP_SELF ) )
78
+ $_SERVER['PHP_SELF'] = $PHP_SELF = preg_replace( '/(\?.*)?$/', '',
79
+ $_SERVER["REQUEST_URI"] );
80
+
81
+ $fixedvars = true;
82
+ }
83
+
84
+ // http://stackoverflow.com/questions/4049856/replace-phps-realpath
85
+ public static function truepath( $path )
86
+ {
87
+ if ( function_exists( 'realpath' ) )
88
+ return realpath( $path );
89
+
90
+ // whether $path is unix or not
91
+ $unipath = strlen( $path ) == 0 || $path{0} != '/';
92
+
93
+ // attempts to detect if path is relative in which case, add cwd
94
+ if ( strpos( $path, ':' ) === false && $unipath )
95
+ $path = getcwd() . DIRECTORY_SEPARATOR . $path;
96
+
97
+ // resolve path parts (single dot, double dot and double delimiters)
98
+ $path = str_replace( array('/', '\\'), DIRECTORY_SEPARATOR, $path );
99
+ $parts = array_filter( explode( DIRECTORY_SEPARATOR, $path ), 'strlen' );
100
+
101
+ $absolutes = array();
102
+ foreach ( $parts as $part ) {
103
+ if ( '.' == $part )
104
+ continue;
105
+ if ( '..' == $part )
106
+ array_pop( $absolutes );
107
+ else
108
+ $absolutes[] = $part;
109
+ }
110
+ $path = implode( DIRECTORY_SEPARATOR, $absolutes );
111
+
112
+ // resolve any symlinks
113
+ if ( file_exists( $path ) && linkinfo( $path ) > 0 )
114
+ $path = readlink( $path );
115
+
116
+ // put initial separator that could have been lost
117
+ $path = !$unipath ? '/' . $path : $path;
118
+
119
+ return $path;
120
+ }
121
+
122
+ // http://gr2.php.net/php_uname
123
+ // http://stackoverflow.com/questions/5879043/php-script-detect-whether-running-under-linux-or-windows
124
+ // http://stackoverflow.com/questions/1482260/how-to-get-the-os-on-which-php-is-running
125
+ public static function getOS()
126
+ {
127
+ return (object) array(
128
+ 'isNIX' => (bool) ('/' == DIRECTORY_SEPARATOR && ':' == PATH_SEPARATOR),
129
+ 'isMAC' => (bool) ('/' == DIRECTORY_SEPARATOR && ':' == PATH_SEPARATOR),
130
+ 'isWIN' => (bool) ('\\' == DIRECTORY_SEPARATOR && ';' == PATH_SEPARATOR)
131
+ );
132
+ }
133
+
134
+ // http://www.helicron.net/php-document-root/
135
+ // http://php.net/manual/en/reserved.variables.server.php
136
+ // http://php.net/manual/en/function.realpath.php
137
+ // http://stackoverflow.com/questions/9151949/root-directory-with-php-on-apache-and-iis
138
+ // variation used here
139
+ public static function getDocRoot( $manual = false )
140
+ {
141
+ static $cache = array();
142
+ $cache_key = $manual ? 'manual' : 'auto';
143
+ if ( isset( $cache[$cache_key] ) ) {
144
+ return $cache[$cache_key];
145
+ }
146
+
147
+
148
+ self::fixServerVars();
149
+
150
+ /*
151
+ * Found issue with amazon server.
152
+ * https://icanlocalize.basecamphq.com/projects/7393061-toolset/todo_items/164974335/comments#comment_237904711
153
+ * https://icanlocalize.basecamphq.com/projects/7393061-toolset/todo_items/159425489/comments
154
+ * Server settings aren't quite right so force manual check.
155
+ * docroot is determined manually if file do not match docroot.
156
+ */
157
+
158
+ // not available in IIS
159
+ if ( $manual === false && isset( $_SERVER['DOCUMENT_ROOT'] ) ) {
160
+ $docroot = $_SERVER['DOCUMENT_ROOT'];
161
+ } else {
162
+ // for IIS
163
+ // these should always be available, Apache, IIS, .., PHP 4.1.0+, ..
164
+ if ( !empty( $_SERVER['SCRIPT_FILENAME'] ) ) {
165
+ //$docroot = str_replace( '\\', '/', substr($_SERVER['SCRIPT_FILENAME'], 0, 0 - strlen($_SERVER['PHP_SELF'])));
166
+ $docroot = str_replace( '\\', '/',
167
+ self::str_before( $_SERVER['SCRIPT_FILENAME'],
168
+ $_SERVER['SCRIPT_NAME'] ) );
169
+ } elseif ( !empty( $_SERVER['PATH_TRANSLATED'] ) ) {
170
+ //$docroot = str_replace( '\\', '/', substr(str_replace('\\\\', '\\', $_SERVER['PATH_TRANSLATED']), 0, 0 - strlen($_SERVER['PHP_SELF'])));
171
+ $docroot = str_replace( '\\', '/',
172
+ self::str_before( str_replace( '\\\\', '\\',
173
+ $_SERVER['PATH_TRANSLATED'] ),
174
+ $_SERVER['SCRIPT_NAME'] ) );
175
+ }
176
+ else
177
+ $docroot = '';
178
+ //$docroot=str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $docroot);
179
+ }
180
+
181
+ $cache[$cache_key] = $docroot;
182
+ return $docroot;
183
+ }
184
+
185
+ public static function getHostUrl( $with_port = true,
186
+ $trailing_slash = false )
187
+ {
188
+ // try to determine the url manually
189
+ // as robustly as possile
190
+ self::fixServerVars();
191
+
192
+ $url = 'http';
193
+
194
+ if ( isset( $_SERVER["HTTPS"] ) && "on" == $_SERVER["HTTPS"] )
195
+ $url .= "s";
196
+
197
+ $url .= "://" . $_SERVER['HTTP_HOST']/* $_SERVER["SERVER_NAME"] */;
198
+
199
+ if ( $with_port && isset( $_SERVER["SERVER_PORT"] ) && "80" != $_SERVER["SERVER_PORT"] ) {
200
+ $re = sprintf( '/:%d$/', $_SERVER['SERVER_PORT'] );
201
+ if ( !preg_match( $re, $url ) ) {
202
+ $url .= ":" . $_SERVER["SERVER_PORT"];
203
+ }
204
+ }
205
+
206
+ if ( $trailing_slash )
207
+ $url .= '/';
208
+
209
+ return $url;
210
+ }
211
+
212
+ private static function getCommonPath( $p1, $p2 )
213
+ {
214
+ return implode( '/',
215
+ array_intersect( explode( '/', $p1 ),
216
+ explode( '/', $p2 ) ) );
217
+ }
218
+
219
+ public static function getUSymlink()
220
+ {
221
+ self::fixServerVars();
222
+
223
+ // these should always be available, Apache, IIS, .., PHP 4.1.0+, ..
224
+ $script_name = $_SERVER['SCRIPT_NAME'];
225
+ $local = str_replace( '\\', '/', $script_name );
226
+ if ( false !== strpos( $local, '~' ) && isset( $_SERVER['SCRIPT_FILENAME'] ) ) {
227
+ $script_filename = $_SERVER['SCRIPT_FILENAME'];
228
+ $file = str_replace( '\\', '/', /* self::truepath( */
229
+ $script_filename/* ) */ );
230
+ $common = self::getCommonPath( $local, $file );
231
+ $usymlink = self::str_before( $local, $common );
232
+ $uabslink = self::str_before( $file, $common );
233
+ $map = array($usymlink, $uabslink);
234
+ } else {
235
+ $map = array();
236
+ }
237
+ // get request, remove query string
238
+ //$request=self::str_before($request_uri, '?');
239
+
240
+ return $map;
241
+ }
242
+
243
+ // http://stackoverflow.com/questions/176712/how-can-i-find-an-applications-base-url
244
+ // http://stackoverflow.com/questions/5493075/apache-rewrite-get-original-url-in-php
245
+ // variation used here
246
+ public static function getBaseUrl( $trailing_slash = false )
247
+ {
248
+ self::fixServerVars();
249
+
250
+ // these should always be available, Apache, IIS, .., PHP 4.1.0+, ..
251
+ $local = str_replace( '\\', '/', $_SERVER['SCRIPT_NAME'] );
252
+ // get request, remove query string
253
+ $request = self::str_before( $_SERVER['REQUEST_URI'], '?' );
254
+
255
+ // no need to check for complete rewrited urls (with eg multisite subfolder and rewritten request url)
256
+ // since when called the file is determined and base url can be found (with any virtual path also)
257
+
258
+ $url = self::getHostUrl() . self::str_before( $request, $local );
259
+
260
+ if ( $trailing_slash )
261
+ $url .= '/';
262
+
263
+ return $url;
264
+ }
265
+
266
+ public static function getFileUrl( $__FILE__ = null, $use_baseurl = true )
267
+ {
268
+ self::fixServerVars();
269
+
270
+ if ( !$__FILE__ )
271
+ $__FILE__ = (string) __FILE__;
272
+
273
+ $__FILE__ = str_replace( '\\', '/', dirname( $__FILE__ ) );
274
+
275
+ $manual = false;
276
+ if ( isset( $_SERVER['DOCUMENT_ROOT'] ) ) {
277
+ $manual = strpos( $__FILE__, $_SERVER['DOCUMENT_ROOT'] ) !== 0 ? true : false;
278
+ }
279
+
280
+ $docroot = self::getDocRoot( $manual );
281
+
282
+ $baseurl = $use_baseurl ? self::getBaseUrl() : self::getHostUrl();
283
+
284
+ if ( 0 === strpos( $__FILE__, $docroot ) ) {
285
+ return self::_join_paths( $baseurl, self::str_after( $__FILE__, $docroot ) );
286
+ } else {
287
+ $map = self::getUSymlink( /* $_SERVER['SCRIPT_NAME'], $_SERVER['SCRIPT_FILENAME'] */ );
288
+ if ( !empty( $map ) && false !== strpos( $__FILE__, $map[1] ) ) {
289
+ return self::_join_paths( $baseurl, str_replace( $map[1], $map[0], $__FILE__ ) );
290
+ } else {
291
+ return icl_get_file_relpath( $__FILE__ . DIRECTORY_SEPARATOR . 'dummy.php' );
292
+ // finally here
293
+ return self::_join_paths( $baseurl, $__FILE__ );
294
+ }
295
+ }
296
+ }
297
+
298
+ private static function _join_paths( $part1, $part2 ) {
299
+ return trailingslashit( $part1 ) . ltrim( $part2, '/' );
300
+ }
301
+
302
+ public static function getCurrentUrl( $q = true )
303
+ {
304
+ self::fixServerVars();
305
+
306
+ if ( !$q )
307
+ return $_SERVER['REQUEST_URI'];
308
+
309
+ return self::getHostUrl() . $_SERVER['REQUEST_URI'];
310
+ }
311
+
312
+ private static function str_before( $h, $n, $s = 0 )
313
+ {
314
+ $pos = strpos( $h, $n );
315
+ return (false !== $pos) ? substr( $h, $s, $pos ) : $h;
316
+ }
317
+
318
+ private static function str_after( $h, $n )
319
+ {
320
+ $pos = strpos( $h, $n );
321
+ return (false !== $pos) ? substr( $h, $pos + strlen( $n ) ) : $h;
322
+ }
323
+
324
+ private static function get_file( $path )
325
+ {
326
+
327
+ if ( function_exists( 'realpath' ) )
328
+ $path = realpath( $path );
329
+
330
+ if ( !$path || !@is_file( $path ) )
331
+ return '';
332
+
333
+ return @file_get_contents( $path );
334
+ }
335
+
336
+ private static function buildAbsPath( $rel, $base )
337
+ {
338
+ // is relative path
339
+ if ( 0 === strpos( $rel, '.' ) ) {
340
+ $parts = explode( '/', str_replace( '\\', '/', $rel ) );
341
+ foreach ( array_keys( $parts ) as $ii ) {
342
+ if ( '.' == $parts[$ii] ) {
343
+ unset( $parts[$ii] );
344
+ } elseif ( '..' == $parts[$ii] ) {
345
+ $base = dirname( $base );
346
+ unset( $parts[$ii] );
347
+ }
348
+ }
349
+ $parts = array_values( $parts );
350
+ array_unshift( $parts, $base );
351
+ $rel = implode( '/', $parts );
352
+ }
353
+ return $rel;
354
+ }
355
+
356
+ }
embedded/classes/post-types/messages.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Messages.
4
+ *
5
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/cck/tags/1.6/embedded/classes/post-types/messages.php $
6
+ * $LastChangedDate: 2014-05-13 18:49:25 +0800 (Tue, 13 May 2014) $
7
+ * $LastChangedRevision: 22267 $
8
+ * $LastChangedBy: marcin $
9
+ *
10
+ */
11
+
12
+ $messages = array(
13
+ 'warning_singular_plural_match' => __( "It is not recommended to have same plural and singular name for a post type. Please use a different name for the singular and plural names.", 'wpcf' ),
14
+ 'warning_singular_plural_match_ignore' => __( 'Ignore this warning.', 'wpcf' ),
15
+ );
embedded/classes/relationship.php ADDED
@@ -0,0 +1,496 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Post relationship class.
4
+ *
5
+ * $HeadURL: http://plugins.svn.wordpress.org/types/tags/1.6/embedded/classes/relationship.php $
6
+ * $LastChangedDate: 2014-08-22 01:02:43 +0000 (Fri, 22 Aug 2014) $
7
+ * $LastChangedRevision: 970205 $
8
+ * $LastChangedBy: brucepearson $
9
+ *
10
+ */
11
+
12
+ /**
13
+ * Post relationship class
14
+ *
15
+ * @since Types 1.2
16
+ * @package Types
17
+ * @subpackage Classes
18
+ * @version 0.1
19
+ * @category Relationship
20
+ * @author srdjan <srdjan@icanlocalize.com>
21
+ *
22
+ */
23
+ class WPCF_Relationship
24
+ {
25
+ /**
26
+ * Custom field
27
+ *
28
+ * @var type
29
+ */
30
+ var $cf = array();
31
+ var $data = array();
32
+
33
+ /**
34
+ * Settings
35
+ *
36
+ * @var type
37
+ */
38
+ var $settings = array();
39
+ var $items_per_page = 5;
40
+ var $items_per_page_option_name = '_wpcf_relationship_items_per_page';
41
+ var $child_form = null;
42
+
43
+ /**
44
+ * Construct function.
45
+ */
46
+ function __construct()
47
+ {
48
+ $this->cf = new WPCF_Field;
49
+ $this->settings = get_option( 'wpcf_post_relationship', array() );
50
+ add_action( 'wp_ajax_add-types_reltax_add',
51
+ array($this, 'ajaxAddTax') );
52
+ }
53
+
54
+ /**
55
+ * Sets current data.
56
+ *
57
+ * @param type $parent
58
+ * @param type $child
59
+ * @param type $field
60
+ * @param type $data
61
+ */
62
+ function set( $parent, $child, $data = array() )
63
+ {
64
+ return $this->_set( $parent, $child, $data );
65
+ }
66
+
67
+ /**
68
+ * Sets current data.
69
+ *
70
+ * @param type $parent
71
+ * @param type $child
72
+ * @param type $field
73
+ * @param type $data
74
+ */
75
+ function _set( $parent, $child, $data = array() )
76
+ {
77
+ $this->parent = $parent;
78
+ $this->child = $child;
79
+ $this->cf = new WPCF_Field;
80
+ // TODO Revise usage
81
+ $this->data = $data;
82
+ }
83
+
84
+ /**
85
+ * Meta box form on post edit page.
86
+ *
87
+ * @param type $parent Parent post
88
+ * @param type $post_type Child post type
89
+ * @return type string HTML formatted form table
90
+ */
91
+ function child_meta_form($parent, $post_type)
92
+ {
93
+ if ( is_integer( $parent ) ) {
94
+ $parent = get_post( $parent );
95
+ }
96
+ $output = '';
97
+ require_once dirname( __FILE__ ) . '/relationship/form-child.php';
98
+ $this->child_form = new WPCF_Relationship_Child_Form(
99
+ $parent,
100
+ $post_type,
101
+ $this->settings( $parent->post_type, $post_type )
102
+ );
103
+ $output .= $this->child_form->render();
104
+
105
+ return $output;
106
+ }
107
+
108
+ /**
109
+ * Child row rendered on AJAX 'Add New Child' call.
110
+ *
111
+ * @param type $parent_id
112
+ * @param type $child_id
113
+ * @return type
114
+ */
115
+ function child_row($parent_id, $child_id)
116
+ {
117
+ $parent = get_post( intval( $parent_id ) );
118
+ $child = get_post( intval( $child_id ) );
119
+ if ( empty( $parent ) || empty( $child ) ) {
120
+ return new WP_Error( 'wpcf-relationship-save-child', 'no parent/child post' );
121
+ }
122
+ $output = '';
123
+ $this->child_form = $this->_get_child_form( $parent, $child );
124
+ $output .= $this->child_form->child_row( $child );
125
+
126
+ return $output;
127
+ }
128
+
129
+ /**
130
+ * Returns HTML formatted form.
131
+ *
132
+ * @param type $parent
133
+ * @param type $child
134
+ * @return \WPCF_Relationship_Child_Form
135
+ */
136
+ function _get_child_form($parent, $child)
137
+ {
138
+ require_once dirname( __FILE__ ) . '/relationship/form-child.php';
139
+ return new WPCF_Relationship_Child_Form(
140
+ $parent,
141
+ $child->post_type,
142
+ $this->settings( $parent->post_type, $child->post_type )
143
+ );
144
+ }
145
+
146
+ function get_child()
147
+ {
148
+ $r = $this->child;
149
+ $r->parent = $this->parent;
150
+ $r->form = $this->_get_child_form( $r->parent, $this->child );
151
+ return $r;
152
+ }
153
+
154
+ /**
155
+ * Save items_per_page settings.
156
+ *
157
+ * @param type $parent
158
+ * @param type $child
159
+ * @param int $num
160
+ */
161
+ function save_items_per_page($parent, $child, $num)
162
+ {
163
+ if ( post_type_exists( $parent ) && post_type_exists( $child ) ) {
164
+ $option_name = $this->items_per_page_option_name . '_' . $parent . '_' . $child;
165
+ if ( $num == 'all' ) {
166
+ $num = 9999999999999999;
167
+ }
168
+ update_option( $option_name, intval( $num ) );
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Return items_per_page settings
174
+ *
175
+ * @param type $parent
176
+ * @param type $child
177
+ * @return type
178
+ */
179
+ function get_items_per_page($parent, $child)
180
+ {
181
+ $per_page = get_option( $this->items_per_page_option_name . '_' . $parent . '_' . $child,
182
+ $this->items_per_page );
183
+ return empty( $per_page ) ? $this->items_per_page : $per_page;
184
+ }
185
+
186
+ /**
187
+ * Adjusts post name when saving.
188
+ *
189
+ * @todo Revise (not used?)
190
+ * @param type $post
191
+ * @return type
192
+ */
193
+ function get_insert_post_name($post)
194
+ {
195
+ if ( empty( $post->post_title ) ) {
196
+ return $post->post_type . '-' . $post->ID;
197
+ }
198
+ return $post->post_title;
199
+ }
200
+
201
+ /**
202
+ * Bulk saving children.
203
+ *
204
+ * @param type $parent_id
205
+ * @param type $children
206
+ */
207
+ function save_children($parent_id, $children)
208
+ {
209
+ foreach ( $children as $child_id => $fields ) {
210
+ $this->save_child( $parent_id, $child_id, $fields );
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Unified save child function.
216
+ *
217
+ * @param type $child_id
218
+ * @param type $parent_id
219
+ */
220
+ function save_child( $parent_id, $child_id, $save_fields = array() )
221
+ {
222
+ global $wpdb;
223
+
224
+ $parent = get_post( intval( $parent_id ) );
225
+ $child = get_post( intval( $child_id ) );
226
+ $post_data = array();
227
+
228
+ if ( empty( $parent ) || empty( $child ) ) {
229
+ return new WP_Error( 'wpcf-relationship-save-child', 'no parent/child post' );
230
+ }
231
+
232
+ // Save relationship
233
+ update_post_meta( $child->ID,
234
+ '_wpcf_belongs_' . $parent->post_type . '_id', $parent->ID );
235
+
236
+ // Check if added via AJAX
237
+ $check = get_post_meta( $child->ID, '_wpcf_relationship_new', true );
238
+ $new = !empty( $check );
239
+ delete_post_meta( $child->ID, '_wpcf_relationship_new' );
240
+
241
+ // Set post data
242
+ $post_data['ID'] = $child->ID;
243
+
244
+ // Title needs to be checked if submitted at all
245
+ if ( !isset( $save_fields['_wp_title'] ) ) {
246
+ // If not submitted that means it is not offered to be edited
247
+ if ( !empty( $child->post_title ) ) {
248
+ $post_title = $child->post_title;
249
+ } else {
250
+ // DO NOT LET IT BE EMPTY
251
+ $post_title = $child->post_type . ' ' . $child->ID;
252
+ }
253
+ } else {
254
+ $post_title = $save_fields['_wp_title'];
255
+ }
256
+
257
+ $post_data['post_title'] = $post_title;
258
+ $post_data['post_content'] = isset( $save_fields['_wp_body'] ) ? $save_fields['_wp_body'] : $child->post_content;
259
+ $post_data['post_type'] = $child->post_type;
260
+
261
+ // Check post status - if new, convert to 'publish' else keep remaining
262
+ if ( $new ) {
263
+ $post_data['post_status'] = 'publish';
264
+ } else {
265
+ $post_data['post_status'] = get_post_status( $child->ID );
266
+ }
267
+
268
+ /*
269
+ *
270
+ *
271
+ *
272
+ *
273
+ *
274
+ *
275
+ * UPDATE POST
276
+ */
277
+
278
+ $updated_id = wp_update_post( $post_data );
279
+ if ( empty( $updated_id ) ) {
280
+ return new WP_Error( 'relationship-update-post-failed', 'Updating post failed' );
281
+ }
282
+
283
+ // Save parents
284
+ if ( !empty( $save_fields['parents'] ) ) {
285
+ foreach ( $save_fields['parents'] as $parent_post_type => $parent_post_id ) {
286
+ update_post_meta( $child->ID,
287
+ '_wpcf_belongs_' . $parent_post_type . '_id',
288
+ $parent_post_id );
289
+ }
290
+ }
291
+
292
+ // Update taxonomies
293
+ if ( !empty( $save_fields['taxonomies'] ) && is_array( $save_fields['taxonomies'] ) ) {
294
+ $_save_data = array();
295
+ foreach ( $save_fields['taxonomies'] as $taxonomy => $t ) {
296
+ if ( !is_taxonomy_hierarchical( $taxonomy ) ) {
297
+ $_save_data[$taxonomy] = strval( $t );
298
+ continue;
299
+ }
300
+ foreach ( $t as $term_id ) {
301
+ if ( $term_id != '-1' ) {
302
+ $term = get_term( $term_id, $taxonomy );
303
+ if ( empty( $term ) ) {
304
+ continue;
305
+ }
306
+ $_save_data[$taxonomy][] = $term_id;
307
+ }
308
+ }
309
+ }
310
+ wp_delete_object_term_relationships( $child->ID,
311
+ array_keys( $save_fields['taxonomies'] ) );
312
+ foreach ( $_save_data as $_taxonomy => $_terms ) {
313
+ wp_set_post_terms( $child->ID, $_terms, $_taxonomy,
314
+ $append = false );
315
+ }
316
+ }
317
+
318
+ // Unset non-types
319
+ unset( $save_fields['_wp_title'], $save_fields['_wp_body'],
320
+ $save_fields['parents'], $save_fields['taxonomies'] );
321
+ /*
322
+ *
323
+ *
324
+ *
325
+ *
326
+ *
327
+ *
328
+ * UPDATE Loop over fields
329
+ */
330
+ foreach ( $save_fields as $slug => $value ) {
331
+ if ( defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
332
+ // Get field by slug
333
+ $field = wpcf_fields_get_field_by_slug( str_replace( WPCF_META_PREFIX,
334
+ '', $slug ) );
335
+ if ( empty( $field ) ) {
336
+ continue;
337
+ }
338
+ // Set config
339
+ $config = wptoolset_form_filter_types_field( $field, $child->ID );
340
+ // Check if valid
341
+ $valid = wptoolset_form_validate_field( 'post', $config, $value );
342
+ if ( is_wp_error( $valid ) ) {
343
+ $errors = $valid->get_error_data();
344
+ $msg = sprintf( __( 'Child post "%s" field "%s" not updated:',
345
+ 'wpcf' ), $child->post_title, $field['name'] );
346
+ wpcf_admin_message_store( $msg . ' ' . implode( ', ',
347
+ $errors ), 'error' );
348
+ continue;
349
+ }
350
+ }
351
+ $this->cf->set( $child, $field );
352
+ $this->cf->context = 'post_relationship';
353
+ $this->cf->save( $value );
354
+ }
355
+
356
+ do_action( 'wpcf_relationship_save_child', $child, $parent );
357
+
358
+ clean_post_cache( $parent->ID );
359
+ clean_post_cache( $child->ID );
360
+ // Added because of caching meta 1.5.4
361
+ wp_cache_flush();
362
+
363
+ return true;
364
+ }
365
+
366
+ /**
367
+ * Saves new child.
368
+ *
369
+ * @param type $parent_id
370
+ * @param type $post_type
371
+ * @return type
372
+ */
373
+ function add_new_child($parent_id, $post_type)
374
+ {
375
+ global $wpdb;
376
+
377
+ $parent = get_post( $parent_id );
378
+ if ( empty( $parent ) ) {
379
+ return new WP_Error( 'wpcf-relationship-no-parent', 'No parent' );
380
+ }
381
+ $new_post = array(
382
+ 'post_title' => ' ', // WP requires at least title with space
383
+ 'post_type' => $post_type,
384
+ 'post_status' => 'draft',
385
+ );
386
+ $id = wp_insert_post( $new_post, true );
387
+ if ( !is_wp_error( $id ) ) {
388
+ // Mark that it is new post
389
+ update_post_meta( $id, '_wpcf_relationship_new', 1 );
390
+ // Save relationship
391
+ update_post_meta( $id,
392
+ '_wpcf_belongs_' . $parent->post_type . '_id', $parent->ID );
393
+ // Fix title
394
+ $wpdb->update( $wpdb->posts,
395
+ array('post_title' => $post_type . ' ' . $id),
396
+ array('ID' => $id), array('%s'), array('%d') );
397
+ do_action( 'wpcf_relationship_add_child', get_post( $id ), $parent );
398
+ wp_cache_flush();
399
+ }
400
+ return $id;
401
+ }
402
+
403
+ /**
404
+ * Saved relationship settings.
405
+ *
406
+ * @param type $parent
407
+ * @param type $child
408
+ * @return type
409
+ */
410
+ function settings($parent, $child)
411
+ {
412
+ return isset( $this->settings[$parent][$child] ) ? $this->settings[$parent][$child] : array();
413
+ }
414
+
415
+ /**
416
+ * Fetches submitted data.
417
+ *
418
+ * @param type $parent_id
419
+ * @param type $child_id
420
+ * @return type
421
+ */
422
+ function get_submitted_data($parent_id, $child_id, $field)
423
+ {
424
+ if ( !is_string( $field ) ) {
425
+ $_field_slug = $field->slug;
426
+ } else {
427
+ $_field_slug = $field;
428
+ }
429
+ return isset( $_POST['wpcf_post_relationship'][$parent_id][$child_id][$_field_slug] ) ? $_POST['wpcf_post_relationship'][$parent_id][$child_id][$_field_slug] : null;
430
+ }
431
+
432
+ /**
433
+ * Gets all parents per post type.
434
+ *
435
+ * @param type $child
436
+ * @return type
437
+ */
438
+ public static function get_parents($child)
439
+ {
440
+ $parents = array();
441
+ $item_parents = wpcf_pr_admin_get_belongs( $child->post_type );
442
+ if ( $item_parents ) {
443
+ foreach ( $item_parents as $post_type => $data ) {
444
+
445
+ // Get parent ID
446
+ $meta = wpcf_get_post_meta( $child->ID,
447
+ '_wpcf_belongs_' . $post_type . '_id', true );
448
+
449
+ if ( !empty( $meta ) ) {
450
+
451
+ $parent_post = get_post( $meta );
452
+
453
+ if ( !empty( $parent_post ) ) {
454
+ $parents[$parent_post->post_type] = $parent_post;
455
+ }
456
+ }
457
+ }
458
+ }
459
+ return $parents;
460
+ }
461
+
462
+ /**
463
+ * Gets post parent by post type.
464
+ *
465
+ * @param type $post_id
466
+ * @param type $parent_post_type
467
+ * @return type
468
+ */
469
+ public static function get_parent($post_id, $parent_post_type)
470
+ {
471
+ return wpcf_get_post_meta( $post_id,
472
+ '_wpcf_belongs_' . $parent_post_type . '_id', true );
473
+ }
474
+
475
+ /**
476
+ * AJAX adding taxonomies
477
+ */
478
+ public function ajaxAddTax()
479
+ {
480
+ if ( isset( $_POST['types_reltax'] ) ) {
481
+ $data = array_shift( $_POST['types_reltax'] );
482
+ $tax = key( $data );
483
+ $val = array_shift( $data );
484
+ $__nonce = array_shift( $_POST['types_reltax_nonce'] );
485
+ $nonce = array_shift( $__nonce );
486
+ $_POST['action'] = 'add-' . $tax;
487
+ $_POST['post_category'][$tax] = $val;
488
+ $_POST['tax_input'][$tax] = $val;
489
+ $_POST['new'.$tax] = $val;
490
+ $_REQUEST["_ajax_nonce-add-{$tax}"] = $nonce;
491
+ _wp_ajax_add_hierarchical_term();
492
+ }
493
+ die();
494
+ }
495
+
496
+ }
embedded/classes/relationship/form-child.php ADDED
@@ -0,0 +1,729 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Relationship form class.
4
+ *
5
+ * Used to render child forms
6
+ */
7
+ require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields-post.php';
8
+
9
+ /**
10
+ * Relationship form class.
11
+ *
12
+ * Used on post edit page to show children rows
13
+ */
14
+ class WPCF_Relationship_Child_Form
15
+ {
16
+
17
+ /**
18
+ * Current post.
19
+ *
20
+ * @var type object
21
+ */
22
+ var $post;
23
+
24
+ /**
25
+ * Field object.
26
+ *
27
+ * @var type array
28
+ */
29
+ var $cf = array();
30
+
31
+ /**
32
+ * Saved data.
33
+ *
34
+ * @var type array
35
+ */
36
+ var $data = array();
37
+
38
+ /**
39
+ * Child post object.
40
+ *
41
+ * @var type
42
+ */
43
+ var $child_post_type_object;
44
+ var $parent;
45
+ var $parent_post_type;
46
+ var $child_post_type;
47
+ var $model;
48
+ var $children;
49
+ var $headers = array();
50
+ var $_dummy_post = false;
51
+ private $__params = array('page', '_wpcf_relationship_items_per_page', 'sort',
52
+ 'field');
53
+ private $__urlParams = array();
54
+
55
+ /**
56
+ * Construct function.
57
+ */
58
+ function __construct( $parent_post, $child_post_type, $data ) {
59
+ WPCF_Loader::loadModel( 'relationship' );
60
+ $this->parent = $parent_post;
61
+ $this->parent_post_type = $parent_post->post_type;
62
+ $this->child_post_type = $child_post_type;
63
+ $this->data = $data;
64
+ // Clean data
65
+ if ( empty( $this->data['fields_setting'] ) ) {
66
+ $this->data['fields_setting'] = 'all_cf';
67
+ }
68
+ $this->cf = new WPCF_Field();
69
+ $this->cf->context = 'relationship';
70
+ $this->children = WPCF_Relationship_Model::getChildrenByPostType( $this->parent,
71
+ $this->child_post_type, $this->data, $_GET );
72
+ // If no children - use dummy post
73
+ if ( empty( $this->children ) ) {
74
+ $_dummy_post = get_default_post_to_edit( $this->child_post_type,
75
+ false );
76
+ $this->children = array($_dummy_post);
77
+ $this->_dummy_post = true;
78
+ }
79
+ $this->child_post_type_object = get_post_type_object( $this->child_post_type );
80
+
81
+ // Collect params from request
82
+ foreach ( $this->__params as $__param ) {
83
+ if ( isset( $_GET[$__param] ) ) {
84
+ $this->__urlParams[$__param] = $_GET[$__param];
85
+ }
86
+ }
87
+ }
88
+
89
+ function getParamsQuery() {
90
+ return count( $this->__urlParams ) ? '&amp;' . http_build_query( $this->__urlParams,
91
+ '', '&amp;' ) : '';
92
+ }
93
+
94
+ /**
95
+ * Sets form.
96
+ *
97
+ * @param type $o
98
+ */
99
+ function _set( $child ) {
100
+ $this->child = $child;
101
+ }
102
+
103
+ /**
104
+ * Returns HTML formatted form.
105
+ *
106
+ * Renders children per row.
107
+ *
108
+ * @todo move all here
109
+ *
110
+ * @return type string (HTML formatted)
111
+ */
112
+ function render() {
113
+ static $count = false;
114
+ if ( !$count ) {
115
+ $count = 1;
116
+ }
117
+
118
+ /*
119
+ * Pagination will slice children
120
+ */
121
+ $this->pagination();
122
+ $rows = $this->rows();
123
+ $headers = $this->headers();
124
+
125
+ // Capture template output
126
+ ob_start();
127
+ include WPCF_EMBEDDED_INC_ABSPATH . '/relationship/child-table.php';
128
+ $table = ob_get_contents();
129
+ ob_end_clean();
130
+
131
+ $count++;
132
+ return $table;
133
+ }
134
+
135
+ /**
136
+ * Pagination
137
+ */
138
+ function pagination() {
139
+
140
+ global $wpcf;
141
+
142
+ // Pagination
143
+ $total_items = count( $this->children );
144
+ $per_page = $wpcf->relationship->get_items_per_page( $this->parent_post_type,
145
+ $this->child_post_type );
146
+ $page = isset( $_GET['page'] ) ? intval( $_GET['page'] ) : 1;
147
+ $numberposts = $page == 1 ? 1 : ($page - 1) * $per_page;
148
+ $slice = $page == 1 ? 0 : ($page - 1) * $per_page;
149
+ $next = count( $this->children ) > $numberposts + $per_page;
150
+ $prev = $page == 1 ? false : true;
151
+ if ( $total_items > $per_page ) {
152
+ $this->children = array_splice( $this->children, $slice, $per_page );
153
+ }
154
+
155
+ $this->pagination_top = wpcf_pr_admin_has_pagination( $this->parent,
156
+ $this->child_post_type, $page, $prev, $next, $per_page,
157
+ $total_items );
158
+ /*
159
+ *
160
+ *
161
+ * Add pagination bottom
162
+ */
163
+ $options = array(__( 'All', 'wpcf' ) => 'all', 5 => 5, 10 => 10, 15 => 15);
164
+ // Add sorting
165
+ $add_data = isset( $_GET['sort'] ) && isset( $_GET['field'] ) ? '&sort=' . strval( $_GET['sort'] ) . '&field='
166
+ . strval( $_GET['field'] ) : '';
167
+ if ( isset( $_GET['post_type_sort_parent'] ) ) {
168
+ $add_data .= '&post_type_sort_parent=' . $_GET['post_type_sort_parent'];
169
+ }
170
+ $this->pagination_bottom = wpcf_form_simple( array(
171
+ 'pagination' => array(
172
+ '#type' => 'select',
173
+ '#before' => __( 'Show', 'wpcf' ),
174
+ '#after' => $this->child_post_type_object->labels->name,
175
+ '#id' => 'wpcf_relationship_num_' . wpcf_unique_id( serialize( $this->children ) ),
176
+ '#name' => $wpcf->relationship->items_per_page_option_name,
177
+ '#options' => $options,
178
+ '#default_value' => $per_page,
179
+ '#attributes' => array(
180
+ 'class' => 'wpcf-relationship-items-per-page',
181
+ 'data-action' => 'action=wpcf_ajax&wpcf_action=pr_pagination'
182
+ . '&post_id=' . $this->parent->ID . '&post_type='
183
+ . $this->child_post_type
184
+ . '&_wpnonce=' . wp_create_nonce( 'pr_pagination' ) . $add_data,
185
+ ),
186
+ ),
187
+ ) );
188
+ }
189
+
190
+ /**
191
+ * Returns rows.
192
+ *
193
+ * @return type
194
+ */
195
+ function rows() {
196
+ $rows = array();
197
+ foreach ( $this->children as $child ) {
198
+ $this->_set( $child );
199
+ $rows[$child->ID] = $this->row();
200
+ }
201
+ return $rows;
202
+ }
203
+
204
+ /**
205
+ * Returns HTML formatted row
206
+ *
207
+ * While generating rows we collect headers too.
208
+ *
209
+ * @return type
210
+ */
211
+ function row() {
212
+ /*
213
+ * Start output.
214
+ * Output is returned as array - each element is <td> content.
215
+ */
216
+ $row = array();
217
+
218
+ /*
219
+ * LOOP over fields
220
+ * Custom settings (specific)
221
+ */
222
+ if ( $this->data['fields_setting'] == 'specific'
223
+ && !empty( $this->data['fields'] ) ) {
224
+ // Set title
225
+ if ( isset( $this->data['fields']['_wp_title'] ) ) {
226
+ $this->headers[] = '_wp_title';
227
+ $row[] = $this->title();
228
+ }
229
+ // Set body
230
+ if ( isset( $this->data['fields']['_wp_body'] ) ) {
231
+ $this->headers[] = '_wp_body';
232
+ $row[] = $this->body();
233
+ }
234
+ // Loop over Types fields
235
+ foreach ( $this->data['fields'] as $field_key => $true ) {
236
+ // If field belongs only to disabled group - remove it.
237
+ $groups = wpcf_admin_fields_get_groups_by_field( $this->cf->__get_slug_no_prefix( $field_key ) );
238
+ if ( empty($groups ) ) {
239
+ continue;
240
+ }
241
+ $_continue = false;
242
+ // If at least one active - proceed
243
+ foreach ( $groups as $group ) {
244
+ if ( $group['is_active'] ) {
245
+ $_continue = true;
246
+ }
247
+ }
248
+ if ( !$_continue ) {
249
+ continue;
250
+ }
251
+ // Skip parents
252
+ if ( in_array( $field_key,
253
+ array('_wp_title', '_wp_body', '_wpcf_pr_parents', '_wpcf_pr_taxonomies') ) ) {
254
+ continue;
255
+ } else {
256
+ /*
257
+ * Set field
258
+ */
259
+ // $field_key = $this->cf->__get_slug_no_prefix( $field_key );
260
+ $this->cf->set( $this->child, $field_key );
261
+ $row[] = $this->field_form();
262
+ $this->_field_triggers();
263
+ // Add to header
264
+ // $this->headers[] = WPCF_META_PREFIX . $field_key;
265
+ $this->headers[] = $field_key;
266
+ }
267
+ }
268
+ // Add parent forms
269
+ if ( !empty( $this->data['fields']['_wpcf_pr_parents'] ) ) {
270
+ $_temp = (array) $this->data['fields']['_wpcf_pr_parents'];
271
+ foreach ( $_temp as $_parent => $_true ) {
272
+ $row[] = $this->_parent_form( $_parent );
273
+ // Add to header
274
+ $this->headers['__parents'][$_parent] = $_true;
275
+ }
276
+ }
277
+ // Add taxonomies forms
278
+ if ( !empty( $this->data['fields']['_wpcf_pr_taxonomies'] ) ) {
279
+ $_temp = (array) $this->data['fields']['_wpcf_pr_taxonomies'];
280
+ foreach ( $_temp as $taxonomy => $_true ) {
281
+ $_taxonomy = get_taxonomy($taxonomy);
282
+ if ( !empty( $_taxonomy ) ) {
283
+ $row[] = $this->taxonomy_form( $_taxonomy );
284
+ // Add to header
285
+ $this->headers['__taxonomies'][$taxonomy] = $_taxonomy->label;
286
+ }
287
+ }
288
+ }
289
+ /*
290
+ *
291
+ *
292
+ *
293
+ *
294
+ * DEFAULT SETTINGS
295
+ */
296
+ } else {
297
+ // Set title
298
+ $row[] = $this->title();
299
+ $this->headers[] = '_wp_title';
300
+
301
+ // Set body if needed
302
+ if ( $this->data['fields_setting'] == 'all_cf_standard' ) {
303
+ $this->headers[] = '_wp_body';
304
+ $row[] = $this->body();
305
+ }
306
+ /*
307
+ * Loop over groups and fields
308
+ */
309
+ // Get groups
310
+ $groups = wpcf_admin_post_get_post_groups_fields( $this->child,
311
+ 'post_relationships' );
312
+ foreach ( $groups as $group ) {
313
+ if ( empty( $group['fields'] ) ) {
314
+ continue;
315
+ }
316
+ /*
317
+ * Loop fields
318
+ */
319
+ foreach ( $group['fields'] as $field_key => $field ) {
320
+ /*
321
+ * Set field
322
+ */
323
+ $field_key = $this->cf->__get_slug_no_prefix( $field_key );
324
+ $this->cf->set( $this->child, $field_key );
325
+ $row[] = $this->field_form();
326
+ $this->_field_triggers();
327
+ // Add to header{
328
+ $this->headers[] = WPCF_META_PREFIX . $field_key;
329
+ }
330
+ }
331
+
332
+ // Add parent forms
333
+ if ( $this->data['fields_setting'] == 'all_cf' ) {
334
+ $this->data['fields']['_wpcf_pr_parents'] = wpcf_pr_admin_get_belongs( $this->child_post_type );
335
+ if ( !empty( $this->data['fields']['_wpcf_pr_parents'] ) ) {
336
+ $_temp = (array) $this->data['fields']['_wpcf_pr_parents'];
337
+ foreach ( $_temp as $_parent => $_true ) {
338
+ if ( $_parent == $this->parent_post_type ) {
339
+ continue;
340
+ }
341
+ $row[] = $this->_parent_form( $_parent );
342
+ // Add to header
343
+ $this->headers['__parents'][$_parent] = $_true;
344
+ }
345
+ }
346
+ }
347
+ }
348
+
349
+ return $row;
350
+ }
351
+
352
+ /**
353
+ * Add here various triggers for field
354
+ */
355
+ function _field_triggers() {
356
+ /*
357
+ * Check if repetitive - add warning
358
+ */
359
+ if ( wpcf_admin_is_repetitive( $this->cf->cf ) ) {
360
+ $this->repetitive_warning = true;
361
+ }
362
+ /*
363
+ * Check if date - trigger it
364
+ * TODO Move to date
365
+ */
366
+ if ( $this->cf->cf['type'] == 'date' ) {
367
+ $this->trigger_date = true;
368
+ }
369
+ }
370
+
371
+ /**
372
+ * Returns HTML formatted title field.
373
+ *
374
+ * @param type $post
375
+ * @return type
376
+ */
377
+ function title() {
378
+ return wpcf_form_simple(
379
+ array('field' => array(
380
+ '#type' => 'textfield',
381
+ '#id' => 'wpcf_post_relationship_'
382
+ . $this->child->ID . '_wp_title',
383
+ '#name' => 'wpcf_post_relationship['
384
+ . $this->parent->ID . ']['
385
+ . $this->child->ID . '][_wp_title]',
386
+ '#value' => trim( $this->child->post_title ),
387
+ '#inline' => true,
388
+ )
389
+ )
390
+ );
391
+ }
392
+
393
+ /**
394
+ * Returns HTML formatted body field.
395
+ *
396
+ * @return type
397
+ */
398
+ function body() {
399
+ return wpcf_form_simple(
400
+ array('field' => array(
401
+ '#type' => 'textarea',
402
+ '#id' => 'wpcf_post_relationship_'
403
+ . $this->child->ID . '_wp_body',
404
+ '#name' => 'wpcf_post_relationship['
405
+ . $this->parent->ID . ']['
406
+ . $this->child->ID . '][_wp_body]',
407
+ '#value' => $this->child->post_content,
408
+ '#attributes' => array('style' => 'width:300px;height:100px;'),
409
+ '#inline' => true,
410
+ )
411
+ )
412
+ );
413
+ }
414
+
415
+ /**
416
+ * Returns HTML formatted taxonomy form.
417
+ *
418
+ * @param type $taxonomy
419
+ * @return type
420
+ */
421
+ function taxonomy_form( $taxonomy, $simple = false ) {
422
+ // SIMPLIFIED VERSION
423
+ if ( $simple ) {
424
+ $terms = wp_get_post_terms( $this->child->ID, $taxonomy->name, array() );
425
+ $selected = ( !empty( $terms ) ) ? array_shift($terms)->term_id : -1;
426
+ $output = wp_dropdown_categories( array(
427
+ 'taxonomy' => $taxonomy->name,
428
+ 'selected' => $selected,
429
+ 'echo' => false,
430
+ 'hide_empty' => false,
431
+ 'hide_if_empty' => true,
432
+ 'show_option_none' => sprintf( __( 'No %s', 'wpcf' ),
433
+ $taxonomy->name ),
434
+ 'name' => 'wpcf_post_relationship['
435
+ . $this->parent->ID . '][' . $this->child->ID
436
+ . '][taxonomies][' . $taxonomy->name . ']',
437
+ 'id' => 'wpcf_pr_' . $this->child->ID . '_' . $taxonomy->name,
438
+ 'hierarchical' => true,
439
+ 'depth' => 9999
440
+ )
441
+ );
442
+
443
+ return empty( $output ) ? sprintf( __( 'No %s', 'wpcf' ),
444
+ $taxonomy->label ) : $output;
445
+ }
446
+
447
+ $data = array(
448
+ 'post' => $this->child,
449
+ 'taxonomy' => $taxonomy->name,
450
+ );
451
+ if ( $taxonomy->name == 'category' ) {
452
+ $data['_wpcf_name'] = "wpcf_post_relationship[{$this->parent->ID}][{$this->child->ID}][taxonomies][{$taxonomy->name}][]";
453
+ $output = WPCF_Loader::template('child-tax-category', $data);
454
+ // Reduce JS processing
455
+ return str_replace( "name=\"post_category[]",
456
+ "name=\"{$data['_wpcf_name']}", $output );
457
+ }
458
+ if ( $taxonomy->hierarchical ) {
459
+ $data['_wpcf_name'] = "wpcf_post_relationship[{$this->parent->ID}][{$this->child->ID}][taxonomies][{$taxonomy->name}][]";
460
+ $output = WPCF_Loader::template('child-tax-category', $data);
461
+ // Reduce JS processing
462
+ return str_replace( "name=\"tax_input[{$taxonomy->name}][]",
463
+ "name=\"{$data['_wpcf_name']}", $output );
464
+ }
465
+ $data['_wpcf_name'] = "wpcf_post_relationship[{$this->parent->ID}][{$this->child->ID}][taxonomies][{$taxonomy->name}]";
466
+ $output = WPCF_Loader::template('child-tax-tag', $data);
467
+ // Reduce JS processing
468
+ return str_replace( "name=\"tax_input[{$taxonomy->name}]",
469
+ "name=\"{$data['_wpcf_name']}", $output );
470
+ }
471
+
472
+ /**
473
+ * Returns element form as array.
474
+ *
475
+ * This is done per field.
476
+ *
477
+ * @param type $key Field key as stored
478
+ * @return array
479
+ */
480
+ function field_form() {
481
+ if ( defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
482
+ $field = $this->cf->cf;
483
+ $meta = get_post_meta( $this->child->ID, $field['meta_key'] );
484
+ $field['suffix'] = "-{$this->child->ID}";
485
+ $config = wptoolset_form_filter_types_field( $field, $this->child->ID );
486
+ // Do not allow repetitive
487
+ $config['repetitive'] = false;
488
+ $config['name'] = $this->cf->alter_form_name( 'wpcf_post_relationship['
489
+ . $this->parent->ID . ']', $config['name'] );
490
+ if ( !empty( $config['options'] ) ) {
491
+ foreach ( $config['options'] as &$v ) {
492
+ if ( isset( $v['name'] ) ) {
493
+ $v['name'] = $this->alter_form_name( $v['name'] );
494
+ }
495
+ }
496
+ }
497
+ if ( $config['type'] == 'wysiwyg' ) {
498
+ $config['type'] = 'textarea';
499
+ }
500
+ return wptoolset_form_field( 'post', $config, $meta );
501
+ }
502
+ /*
503
+ *
504
+ * Get meta form for field
505
+ */
506
+ $form = $this->cf->_get_meta_form( $this->cf->__meta,
507
+ $this->cf->meta_object->meta_id, false );
508
+ /*
509
+ *
510
+ * Filter form
511
+ */
512
+ $_filtered_form = $this->__filter_meta_form( $form );
513
+
514
+ return wpcf_form_simple( apply_filters( 'wpcf_relationship_child_meta_form',
515
+ $_filtered_form, $this->cf ) );
516
+ }
517
+
518
+ /**
519
+ * Filters meta form.
520
+ *
521
+ * IMPORTANT: This is place where look of child form is altered.
522
+ * Try not to spread it over other code.
523
+ *
524
+ * @param string $form
525
+ * @return string
526
+ */
527
+ function __filter_meta_form( $form = array() ) {
528
+ foreach ( $form as $k => &$e ) {
529
+ /*
530
+ *
531
+ * Filter name
532
+ */
533
+ if ( isset( $e['#name'] ) ) {
534
+ $e['#name'] = $this->cf->alter_form_name( 'wpcf_post_relationship['
535
+ . $this->parent->ID . ']', $e['#name'] );
536
+ }
537
+ /*
538
+ * Some fields have #options and names set there.
539
+ * Loop over them and adjust.
540
+ */
541
+ if ( !empty( $e['#options'] ) ) {
542
+ foreach ( $e['#options'] as $_k => $_v ) {
543
+ if ( isset( $_v['#name'] ) ) {
544
+ $e['#options'][$_k]['#name'] = $this->alter_form_name( $_v['#name'] );
545
+ }
546
+ }
547
+ }
548
+ if ( isset( $e['#title'] ) ) {
549
+ unset( $e['#title'] );
550
+ }
551
+ if ( isset( $e['#description'] ) ) {
552
+ unset( $e['#description'] );
553
+ }
554
+ $e['#inline'] = true;
555
+ }
556
+
557
+ return $form;
558
+ }
559
+
560
+ function alter_form_name( $name, $parent_id = null ){
561
+ if ( is_null( $parent_id ) ) {
562
+ $parent_id = $this->parent->ID;
563
+ }
564
+ return $this->cf->alter_form_name(
565
+ 'wpcf_post_relationship[' . $parent_id . ']', $name
566
+ );
567
+ }
568
+
569
+ /**
570
+ * Content for choose parent column.
571
+ *
572
+ * @return boolean
573
+ */
574
+ function _parent_form( $post_parent = '' ) {
575
+ $item_parents = wpcf_pr_admin_get_belongs( $this->child_post_type );
576
+ if ( $item_parents ) {
577
+ foreach ( $item_parents as $parent => $temp_data ) {
578
+
579
+ // Skip if only current available
580
+ if ( $parent == $this->parent_post_type ) {
581
+ continue;
582
+ }
583
+
584
+ if ( !empty( $post_parent ) && $parent != $post_parent ) {
585
+ continue;
586
+ }
587
+
588
+ // Get parent ID
589
+ $meta = get_post_meta( $this->child->ID,
590
+ '_wpcf_belongs_' . $parent . '_id', true );
591
+ $meta = empty( $meta ) ? 0 : $meta;
592
+
593
+ // Get form
594
+ $belongs_data = array('belongs' => array($parent => $meta));
595
+ $temp_form = wpcf_pr_admin_post_meta_box_belongs_form( $this->child,
596
+ $parent, $belongs_data );
597
+
598
+ if ( empty( $temp_form ) ) {
599
+ return '<span class="types-small-italic">' . __( 'No parents available',
600
+ 'wpcf' ) . '</span>';
601
+ }
602
+ unset(
603
+ $temp_form[$parent]['#suffix'],
604
+ $temp_form[$parent]['#prefix'],
605
+ $temp_form[$parent]['#title']
606
+ );
607
+ $temp_form[$parent]['#name'] = 'wpcf_post_relationship['
608
+ . $this->parent->ID . '][' . $this->child->ID
609
+ . '][parents][' . $parent . ']';
610
+ // Return HTML formatted output
611
+ return wpcf_form_simple( $temp_form );
612
+ }
613
+ }
614
+ return '<span class="types-small-italic">' . __( 'No parents available',
615
+ 'wpcf' ) . '</span>';
616
+ }
617
+
618
+ /**
619
+ * HTML formatted row.
620
+ *
621
+ * @return type
622
+ */
623
+ function child_row( $child ) {
624
+ $child_id = $child->ID;
625
+ $this->_set( $child );
626
+ $row = $this->row();
627
+ ob_start();
628
+ include WPCF_EMBEDDED_INC_ABSPATH . '/relationship/child-table-row.php';
629
+ $o = ob_get_contents();
630
+ ob_end_clean();
631
+ return $o;
632
+ }
633
+
634
+ /**
635
+ * Header HTML formatted output.
636
+ *
637
+ * Each header <th> is array element. Sortable.
638
+ *
639
+ * @return array 'header_id' => html
640
+ */
641
+ function headers() {
642
+
643
+ // Sorting
644
+ $dir = isset( $_GET['sort'] ) && $_GET['sort'] == 'ASC' ? 'DESC' : 'ASC';
645
+ $dir_default = 'ASC';
646
+ $sort_field = isset( $_GET['field'] ) ? $_GET['field'] : '';
647
+
648
+ // Set values
649
+ $post = $this->parent;
650
+ $post_type = $this->child_post_type;
651
+ $parent_post_type = $this->parent_post_type;
652
+ $data = $this->data;
653
+
654
+ $wpcf_fields = wpcf_admin_fields_get_fields( true );
655
+ $headers = array();
656
+
657
+ foreach ( $this->headers as $k => $header ) {
658
+ if ( $k === '__parents' || $k === '__taxonomies' ) {
659
+ continue;
660
+ }
661
+
662
+ if ( $header == '_wp_title' ) {
663
+ $title_dir = $sort_field == '_wp_title' ? $dir : 'ASC';
664
+ $headers[$header] = '';
665
+ $headers[$header] .= $sort_field == '_wp_title' ? '<div class="wpcf-pr-sort-' . $dir . '"></div>' : '';
666
+ $headers[$header] .= '<a href="' . admin_url( 'admin-ajax.php?action=wpcf_ajax&amp;wpcf_action=pr_sort&amp;field='
667
+ . '_wp_title&amp;sort=' . $title_dir . '&amp;post_id=' . $post->ID . '&amp;post_type='
668
+ . $post_type . '&amp;_wpnonce='
669
+ . wp_create_nonce( 'pr_sort' ) ) . '">' . __( 'Post Title' ) . '</a>';
670
+ } else if ( $header == '_wp_body' ) {
671
+ $body_dir = $sort_field == '_wp_body' ? $dir : $dir_default;
672
+ $headers[$header] = '';
673
+ $headers[$header] .= $sort_field == '_wp_body' ? '<div class="wpcf-pr-sort-' . $dir . '"></div>' : '';
674
+ $headers[$header] .= '<a href="' . admin_url( 'admin-ajax.php?action=wpcf_ajax&amp;wpcf_action=pr_sort&amp;field='
675
+ . '_wp_body&amp;sort=' . $body_dir . '&amp;post_id=' . $post->ID . '&amp;post_type='
676
+ . $post_type . '&amp;_wpnonce='
677
+ . wp_create_nonce( 'pr_sort' ) ) . '">' . __( 'Post Body' ) . '</a>';
678
+ } else if ( strpos( $header, WPCF_META_PREFIX ) === 0
679
+ && isset( $wpcf_fields[str_replace( WPCF_META_PREFIX, '',
680
+ $header )] ) ) {
681
+ wpcf_field_enqueue_scripts( $wpcf_fields[str_replace( WPCF_META_PREFIX,
682
+ '', $header )]['type'] );
683
+ $field_dir = $sort_field == $header ? $dir : $dir_default;
684
+ $headers[$header] = '';
685
+ $headers[$header] .= $sort_field == $header ? '<div class="wpcf-pr-sort-' . $dir . '"></div>' : '';
686
+ $headers[$header] .= '<a href="' . admin_url( 'admin-ajax.php?action=wpcf_ajax&amp;wpcf_action=pr_sort&amp;field='
687
+ . $header . '&amp;sort=' . $field_dir . '&amp;post_id=' . $post->ID . '&amp;post_type='
688
+ . $post_type . '&amp;_wpnonce='
689
+ . wp_create_nonce( 'pr_sort' ) ) . '">' . stripslashes( $wpcf_fields[str_replace( WPCF_META_PREFIX,
690
+ '', $header )]['name'] ) . '</a>';
691
+ } else {
692
+ $field_dir = $sort_field == $header ? $dir : $dir_default;
693
+ $headers[$header] = '';
694
+ $headers[$header] .= $sort_field == $header ? '<div class="wpcf-pr-sort-' . $dir . '"></div>' : '';
695
+ $headers[$header] .= '<a href="' . admin_url( 'admin-ajax.php?action=wpcf_ajax&amp;wpcf_action=pr_sort&amp;field='
696
+ . $header . '&amp;sort=' . $field_dir . '&amp;post_id=' . $post->ID . '&amp;post_type='
697
+ . $post_type . '&amp;_wpnonce='
698
+ . wp_create_nonce( 'pr_sort' ) ) . '">'
699
+ . stripslashes( $header ) . '</a>';
700
+ }
701
+ }
702
+ if ( !empty( $this->headers['__parents'] ) ) {
703
+ foreach ( $this->headers['__parents'] as $_parent => $data ) {
704
+ if ( $_parent == $parent_post_type ) {
705
+ continue;
706
+ }
707
+ $temp_parent_type = get_post_type_object( $_parent );
708
+ if ( empty( $temp_parent_type ) ) {
709
+ continue;
710
+ }
711
+ $parent_dir = $sort_field == '_wpcf_pr_parent' ? $dir : $dir_default;
712
+ $headers['_wpcf_pr_parent_' . $_parent] = $sort_field == '_wpcf_pr_parent' ? '<div class="wpcf-pr-sort-' . $dir . '"></div>' : '';
713
+ $headers['_wpcf_pr_parent_' . $_parent] .= '<a href="' . admin_url( 'admin-ajax.php?action=wpcf_ajax&amp;wpcf_action=pr_sort&amp;field='
714
+ . '_wpcf_pr_parent&amp;sort='
715
+ . $parent_dir . '&amp;post_id=' . $post->ID . '&amp;post_type='
716
+ . $post_type . '&amp;post_type_sort_parent='
717
+ . $_parent . '&amp;_wpnonce='
718
+ . wp_create_nonce( 'pr_sort' ) ) . '">' . $temp_parent_type->label . '</a>';
719
+ }
720
+ }
721
+ if ( !empty( $this->headers['__taxonomies'] ) ) {
722
+ foreach ( $this->headers['__taxonomies'] as $tax_id => $taxonomy ) {
723
+ $headers["_wpcf_pr_taxonomy_$tax_id"] = $taxonomy;
724
+ }
725
+ }
726
+ return $headers;
727
+ }
728
+
729
+ }
embedded/classes/relationship/form-parent.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * To change this template, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+
7
+ ?>
embedded/classes/repeater.php ADDED
@@ -0,0 +1,616 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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_value( $meta_value );
133
+
134
+ // Adding each field will return $mid
135
+ if ( count($data) == $i++ ) {
136
+ do_action('wpcf_postmeta_before_add_last_repetitive', $this->post, $this->cf);
137
+ }
138
+ $mid = add_post_meta( $this->post->ID, $this->slug, $_meta_value, false );
139
+
140
+ $mids[] = $mid;
141
+
142
+ // Call insert post actions on each field
143
+ $this->_action_save( $this->cf, $_meta_value, $mid, $meta_value );
144
+ }
145
+
146
+ do_action('wpcf_postmeta_after_add_repetitive', $this->post, $this->cf);
147
+
148
+ // Save order
149
+ if ( !empty( $mids ) ) {
150
+ update_post_meta( $this->post->ID, $this->order_meta_name, $mids );
151
+ }
152
+
153
+ // Return true - field found
154
+ return true;
155
+ }
156
+
157
+ // Return false if field missed
158
+ return false;
159
+ }
160
+
161
+ /**
162
+ * Fetch and sort fields.
163
+ *
164
+ * @global type $wpdb
165
+ */
166
+ function _get_meta() {
167
+ global $wpdb;
168
+
169
+ $cache_key = md5( 'repeater::_get_meta' . $this->post->ID . $this->slug );
170
+ $cache_group = 'types_cache';
171
+ $cached_object = wp_cache_get( $cache_key, $cache_group );
172
+
173
+ if ( $this->use_cache ) {
174
+ if ( false != $cached_object && is_array( $cached_object ) ) {
175
+ return $cached_object;
176
+ }
177
+ }
178
+
179
+ $this->order_meta_name = '_' . $this->slug . '-sort-order';
180
+ $_meta = parent::_get_meta();
181
+ $ordered = array();
182
+ $this->order = get_post_meta( $this->post->ID, $this->order_meta_name,
183
+ true );
184
+
185
+ $cache_key_field = md5( 'field::_get_meta' . $this->post->ID . $this->slug );
186
+ $cached_object_field = wp_cache_get( $cache_key_field, $cache_group );
187
+
188
+ if ( $this->use_cache ) {
189
+ if ( false != $cached_object_field && is_array( $cached_object_field ) ) {// WordPress cache
190
+ $r = $cached_object_field;
191
+ } else {
192
+ $r = $wpdb->get_results(
193
+ $wpdb->prepare(
194
+ "SELECT * FROM $wpdb->postmeta
195
+ WHERE post_id=%d
196
+ AND meta_key=%s",
197
+ $this->post->ID, $this->slug )
198
+ );
199
+ }
200
+ } else {
201
+ // If not using cache, get straight from DB
202
+ $r = $wpdb->get_results(
203
+ $wpdb->prepare(
204
+ "SELECT * FROM $wpdb->postmeta
205
+ WHERE post_id=%d
206
+ AND meta_key=%s",
207
+ $this->post->ID, $this->slug )
208
+ );
209
+ }
210
+ if ( !empty( $r ) ) {
211
+ $_meta = array();
212
+ $_meta['by_meta_id'] = array();
213
+ $_meta['by_meta_key'] = array();
214
+
215
+ // Default order
216
+ foreach ( $r as $meta ) {
217
+ // This will use last item in array if multiple values exist
218
+ $_meta['single'] = maybe_unserialize( $meta->meta_value );
219
+ // Sort by meta_id column
220
+ $_meta['by_meta_id'][$meta->meta_id]
221
+ = maybe_unserialize( $meta->meta_value );
222
+ // Sort by meta_key
223
+ $_meta['by_meta_key'][] = maybe_unserialize( $meta->meta_value );
224
+ }
225
+ ksort( $_meta['by_meta_id'] );
226
+
227
+ // Custom order
228
+ if ( !empty( $this->order ) ) {
229
+ foreach ( $this->order as $meta_id ) {
230
+ if ( isset( $_meta['by_meta_id'][$meta_id] ) ) {
231
+ $_meta['custom_order'][$meta_id] = $_meta['by_meta_id'][$meta_id];
232
+ }
233
+ }
234
+ // This ones are orphaned
235
+ foreach ( $_meta['by_meta_id'] as $meta_id => $meta ) {
236
+ if ( !isset( $ordered[$meta_id] ) ) {
237
+ $_meta['custom_order'][$meta_id] = $meta;
238
+ }
239
+ }
240
+ } else {
241
+ $_meta['custom_order'] = $_meta['by_meta_id'];
242
+ }
243
+ } else if ( !empty( $this->meta_object->meta_id ) ) {
244
+ $_meta = array();
245
+ $_meta['single'] = maybe_unserialize( $this->meta_object->meta_value );
246
+ // Sort by meta_id column
247
+ $_meta['by_meta_id'][$this->meta_object->meta_id] = maybe_unserialize( $this->meta_object->meta_value );
248
+ // Sort by meta_key
249
+ $_meta['by_meta_key'][] = maybe_unserialize( $this->meta_object->meta_value );
250
+ } else {
251
+ $_meta = array();
252
+ $_meta['single'] = '';
253
+ $_meta['by_meta_id'] = array();
254
+ $_meta['by_meta_key'] = array();
255
+ }
256
+
257
+ if ( empty( $_meta['custom_order'] ) ) {
258
+ $_meta['custom_order'] = $_meta['by_meta_id'];
259
+ }
260
+
261
+ // Cache it
262
+ wp_cache_add( $cache_key, $_meta, $cache_group );// WordPress cache
263
+
264
+ return $_meta;
265
+ }
266
+
267
+ /**
268
+ * Sets repetitive field form.
269
+ *
270
+ * @todo Make more distinction between $field_form and $form_field
271
+ */
272
+ function get_fields_form() {
273
+ $form = array();
274
+ $form_id = $this->cf['id'];
275
+ $unique_id = wpcf_unique_id( serialize( $this->cf ) );
276
+
277
+ // Process fields
278
+ // Check if has any value
279
+ if ( empty( $this->meta['by_meta_id'] ) ) {
280
+
281
+ // To prevent passing array to field
282
+ $this->meta = null;
283
+ $this->__meta = null;
284
+ $this->cf['value'] = null;
285
+
286
+ $field_form = $this->get_field_form( '' );
287
+
288
+ foreach ( $field_form as $field_key => $field ) {
289
+ $form_field[$form_id . '_repetitive_0_' . $field_key] = $field;
290
+ }
291
+ } else {
292
+ $ordered = !empty( $this->meta['custom_order'] ) ? $this->meta['custom_order'] : $this->meta['by_meta_id'];
293
+ foreach ( $ordered as $meta_id => $meta_value ) {
294
+
295
+ $this->cf['value'] = $meta_value;
296
+ $this->meta_object->meta_id = $meta_id;
297
+
298
+ // Set single field form
299
+ $field_form = $this->get_field_form( $meta_value, $meta_id );
300
+ foreach ( $field_form as $field_key => $field ) {
301
+ $form_field[$form_id . '_repetitive_' . strval( $meta_id ) . '_' . $field_key] = $field;
302
+ }
303
+
304
+ $form_field[$form_id . '_repetitive_meta_id_' . strval( $meta_id )] = array(
305
+ '#type' => 'hidden',
306
+ '#name' => '',
307
+ '#value' => $meta_id,
308
+ );
309
+ }
310
+ }
311
+
312
+ // Set main wrapper
313
+ // Check if conditional
314
+ global $wpcf;
315
+
316
+ // Set style
317
+ /*
318
+ *
319
+ *
320
+ * Hide if field not passed check
321
+ * TODO Move this to WPCF_Conditional
322
+ */
323
+ $show = true;
324
+ if ( $wpcf->conditional->is_conditional( $this->cf ) ) {
325
+ $wpcf->conditional->set( $this->post, $this->cf );
326
+ $show = $wpcf->conditional->evaluate();
327
+ }
328
+ $css_cd = !$show ? 'display:none;' : '';
329
+
330
+ /**
331
+ *
332
+ *
333
+ *
334
+ *
335
+ * Set title and description
336
+ * TODO See if can be improved getting main element
337
+ *
338
+ * Get first element and extract details
339
+ * Pass emty string as value to avoid using meta as array
340
+ */
341
+ //
342
+ $_c = array_values( parent::_get_meta_form( '' ) );
343
+ array_shift( $_c );
344
+ $_main_element = array_shift( $_c );
345
+ // Set title and desc
346
+ if ( !empty( $_main_element['#title'] ) ) {
347
+ $this->title = $_main_element['#title'];
348
+ }
349
+ if ( !empty( $_main_element['#description'] ) ) {
350
+ $this->description = $_main_element['#description'];
351
+ }
352
+
353
+ /*
354
+ *
355
+ *
356
+ * Start wrapper
357
+ */
358
+ $form[$unique_id . '_repetitive_wrapper_open'] = array(
359
+ '#type' => 'markup',
360
+ '#markup' => ''
361
+ . '<div id="wpcf_'
362
+ . $form_id
363
+ . '_repetitive_wrapper_' . $unique_id
364
+ . '" class="wpcf-wrap wpcf-repetitive-wrapper" style="' . $css_cd . '">',
365
+ );
366
+
367
+ // Set title
368
+ $form[$unique_id . '_main_title'] = array(
369
+ '#type' => 'markup',
370
+ '#markup' => '<strong>' . $this->title . '</strong><br/>',
371
+ );
372
+
373
+ // Set hidden mark field
374
+ /*
375
+ *
376
+ *
377
+ *
378
+ * This actually marks field as repetitive
379
+ * IMPORTANT!!! IF NOT marked field won't be saved at all!
380
+ *
381
+ * @see wpcf_admin_post_save_post_hook()
382
+ */
383
+ $form[$form_id . '_hidden_mark'] = array(
384
+ '#type' => 'hidden',
385
+ '#name' => '__wpcf_repetitive[' . $this->slug . ']',
386
+ '#value' => 1,
387
+ '#id' => $form_id . '_hidden_mark',
388
+ );
389
+
390
+ // Sortable
391
+ $form[$form_id . '_repetitive_sortable_open'] = array(
392
+ '#type' => 'markup',
393
+ '#markup' => '<div id="wpcf_'
394
+ . $form_id
395
+ . '_repetitive_sortable_' . wpcf_unique_id( serialize( $this->cf ) )
396
+ . '" class="wpcf-repetitive-sortable-wrapper">',
397
+ '#id' => $form_id . '_repetitive_sortable_wrapper_open',
398
+ );
399
+
400
+ // Append field form
401
+ $form = $form + $form_field;
402
+
403
+ // Close sortable wrapper
404
+ $form[$form_id . '_repetitive_sortable_close'] = array(
405
+ '#type' => 'markup',
406
+ '#markup' => '</div>',
407
+ '#id' => $form_id . '_repetitive_sortable_close',
408
+ );
409
+
410
+ // Add AJAX response at the end of repetitive field
411
+ // Show only on page load not when calling AJAX
412
+ if ( !defined( 'DOING_AJAX' ) ) {
413
+ $form[$form_id . '_repetitive_ajax_response'] = array(
414
+ '#type' => 'markup',
415
+ '#markup' => '<div class="wpcf-repetitive-response"></div>',
416
+ '#id' => $form_id . '_repetitive_ajax_response',
417
+ );
418
+
419
+ // Add description
420
+ $form[$unique_id . '_main_description'] = array(
421
+ '#type' => 'markup',
422
+ '#markup' => '<div class="wpcf-repetitive-description">'
423
+ . wpautop( stripslashes( strip_tags( $this->description ) ) )
424
+ . '</div>',
425
+ );
426
+
427
+ // 'Add' button
428
+ $form[$form_id . '_repetitive_form'] = array(
429
+ '#type' => 'markup',
430
+ '#markup' => wpcf_repetitive_form( $this->cf, $this->post ),
431
+ '#id' => $form_id . '_repetitive_form',
432
+ );
433
+ }
434
+
435
+ // Close wrapper
436
+ $form[$unique_id . '_repetitive_wrapper_close'] = array(
437
+ '#type' => 'markup',
438
+ '#markup' => '</div>',
439
+ );
440
+
441
+ return $form;
442
+ }
443
+
444
+ /**
445
+ * Sete repetitive form for single field.
446
+ *
447
+ * @param type $meta
448
+ * @return string
449
+ */
450
+ function get_field_form( $meta_value = null, $meta_id = null ) {
451
+
452
+ $form = array();
453
+ if ( is_null( $meta_value ) ) {
454
+ $key = 'wpcf_field_' . wpcf_unique_id( md5( $this->index ) . $meta_id );
455
+ } else {
456
+ $key = 'wpcf_field_' . md5( maybe_serialize( $meta_value ) . $meta_id );
457
+ }
458
+ /*
459
+ *
460
+ *
461
+ * TODO We prevented array because of some fails we had before.
462
+ * Now it should work fine
463
+ * Add debug log if meta_value['custom_order'] passed.
464
+ * That means setting meta_value did not went well.
465
+ */
466
+ // if ( is_null( $meta_value ) || is_array( $meta_value ) ) {
467
+ if ( is_null( $meta_value ) ||
468
+ (is_array( $meta_value ) && isset( $meta_value['custom_order'] ) )
469
+ ) {
470
+ $meta_value = $this->meta['single'];
471
+ }
472
+
473
+ // Open drag div
474
+ $form[$key . '_drag_open'] = array(
475
+ '#type' => 'markup',
476
+ '#markup' => '<div class="wpcf-repetitive-drag-and-drop">'
477
+ );
478
+
479
+ // Use WPCF_Field::get_field_form()
480
+ $field_form = parent::_get_meta_form( $meta_value, $meta_id, false );
481
+
482
+ /*
483
+ *
484
+ * Apply filters to each form element.
485
+ * Here we add specific properties
486
+ * e.g. Skype alters fields.
487
+ */
488
+ $_loop = false;
489
+ foreach ( $field_form as $k => $field ) {
490
+
491
+ /*
492
+ *
493
+ * IMPORTANT
494
+ * We change name to hold array
495
+ */
496
+ if ( isset( $field['#name'] ) ) {
497
+ $temp = explode( '[' . $this->cf['slug'] . ']', $field['#name'] );
498
+
499
+ // Assign new name
500
+ $field['#name'] = $temp[0] . '[' . $this->cf['slug'] . ']' . '['
501
+ . $key . ']';
502
+
503
+ // Append rest if any
504
+ if ( isset( $temp[1] ) ) {
505
+ $field['#name'] .= $temp[1];
506
+ }
507
+ }
508
+
509
+ // Apply filters
510
+ $field_form[$k] = apply_filters( 'wpcf_repetitive_field', $field,
511
+ $this->post, $this->cf, $k );
512
+
513
+ // BREAKPOINT
514
+ /*
515
+ * This is place where we clean display.
516
+ * First item is displayed as it is, each after is reduced.
517
+ * If called via AJAX - that means it added and should be reduced.
518
+ */
519
+ // if ( $_loop == true || defined( 'DOING_AJAX' ) ) {
520
+ /*
521
+ * See if field has Repeater pattern defined
522
+ */
523
+ if ( isset( $field['__repeater_restricted'] )
524
+ && is_array( $field['__repeater_restricted'] ) ) {
525
+ foreach ( $field['__repeater_restricted'] as $_e => $_v ) {
526
+ if ( isset( $field[$_e] ) ) {
527
+ unset( $field[$_e] );
528
+ }
529
+ }
530
+ } else {
531
+ unset( $field['#title'], $field['#description'] );
532
+ }
533
+ // Set main
534
+ $field_form[$k] = $field;
535
+ // }
536
+ // $_loop = true;
537
+ }
538
+
539
+ // Just append form
540
+ $form = $form + $field_form;
541
+
542
+ // Open control div
543
+ $form[$key . '_control_open'] = array(
544
+ '#type' => 'markup',
545
+ '#markup' => '<div class="wpcf-repetitive-control">'
546
+ );
547
+
548
+ // Drag button
549
+ $form[$key . '_drag_button'] = array(
550
+ '#type' => 'markup',
551
+ '#markup' => wpcf_repetitive_drag_button( $this->cf, $this->post ),
552
+ );
553
+
554
+ // 'Delete' button
555
+ $form[$key . '_delete_button'] = array(
556
+ '#type' => 'markup',
557
+ '#markup' => wpcf_repetitive_delete_button( $this->cf, $this->post,
558
+ $meta_id ),
559
+ );
560
+
561
+ // Close control div
562
+ $form[$key . '_control_close'] = array(
563
+ '#type' => 'markup',
564
+ '#markup' => '</div>',
565
+ );
566
+
567
+ // Close drag div
568
+ $form[$key . '_drag_close'] = array(
569
+ '#type' => 'markup',
570
+ '#markup' => '</div>',
571
+ );
572
+
573
+ // Count it and set JS var
574
+ $this->_set_form_count();
575
+ wpcf_admin_add_js_settings( 'wpcf_repetitive_count_' . md5( $this->cf['id'] ),
576
+ $this->index );
577
+
578
+ return $form;
579
+ }
580
+
581
+ /**
582
+ * Set counting elements.
583
+ */
584
+ function _set_form_count() {
585
+ if ( $this->index === 0 ) {
586
+ if ( defined( 'DOING_AJAX' ) && isset( $_POST['count'] ) ) {
587
+ $this->index = intval( $_POST['count'] );
588
+ }
589
+ }
590
+ $this->index += 1;
591
+ }
592
+
593
+ /**
594
+ * Deletes meta.
595
+ *
596
+ * @param type $meta_key
597
+ */
598
+ function delete( $meta_id ) {
599
+ global $wpdb;
600
+ $r = $wpdb->query(
601
+ $wpdb->prepare(
602
+ "DELETE FROM $wpdb->postmeta
603
+ WHERE post_id = %d
604
+ AND meta_id = %d",
605
+ $this->post->ID, intval( $meta_id )
606
+ )
607
+ );
608
+ if ( $r === false ) {
609
+ return WP_Error( 'wpcf_repeater_delete_field',
610
+ 'Repeater failed deleting post_ID: '
611
+ . $this->post->ID . '; meta_ID: ' . intval( $meta_id ) );
612
+ }
613
+ return $r;
614
+ }
615
+
616
+ }
embedded/classes/usermeta_field.php ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ *
4
+ *
5
+ * Usermeta Field class extends Field.
6
+ */
7
+
8
+ //require_once WPCF_EMBEDDED_ABSPATH . '/classes/field.php';
9
+
10
+
11
+ class WPCF_Usermeta_Field extends WPCF_Field
12
+ {
13
+
14
+ /**
15
+ * Set current post and field.
16
+ *
17
+ * @param type $post
18
+ * @param type $cf
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_value( $value );
98
+ if ( !empty( $_value ) || is_numeric( $_value ) ) {
99
+ // Save field
100
+ $mid = update_user_meta( $this->currentUID, $this->slug, $_value );
101
+ $this->_action_save( $this->cf, $_value, $mid, $value );
102
+ }
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Fetch and sort fields.
108
+ *
109
+ *
110
+ */
111
+ function _get_meta() {
112
+ global $wpdb;
113
+
114
+
115
+ $cache_key = md5( 'usermeta::_get_meta' . $this->currentUID . $this->slug );
116
+ $cache_group = 'types_cache';
117
+ $cached_object = wp_cache_get( $cache_key, $cache_group );
118
+
119
+ if ( $this->use_cache ) {
120
+ if ( false != $cached_object && is_array( $cached_object ) && isset( $cached_object[0] ) ) {// WordPress cache
121
+ $r = $cached_object[0];
122
+ } else {
123
+ // Cache all the postmeta for this same user
124
+ $all_usermeta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->usermeta} WHERE user_id=%d", $this->currentUID), OBJECT );
125
+ if ( !empty( $all_usermeta ) ) {
126
+ $cache_key_keys = array();
127
+ foreach ( $all_usermeta as $metarow ) {
128
+ $mpid = intval($metarow->user_id);
129
+ $mkey = $metarow->meta_key;
130
+ $cache_key_keys[$mpid . $mkey][] = $metarow;
131
+ $cache_key_looped = md5( 'usermeta::_get_meta' . $mpid . $mkey );
132
+ if ( $mkey == $this->slug ) {
133
+ $r = $metarow;
134
+ }
135
+ }
136
+ foreach ( $cache_key_keys as $single_meta_keys => $single_meta_values ) {
137
+ $cache_key_looped_new = md5( 'usermeta::_get_meta' . $single_meta_keys );
138
+ wp_cache_add( $cache_key_looped_new, $single_meta_values, $cache_group );// WordPress cache
139
+ }
140
+ }
141
+ }
142
+ } else {
143
+ //$r = get_user_meta( $this->currentUID, $this->slug, true);
144
+ // Get straight from DB single value
145
+ $r = $wpdb->get_row(
146
+ $wpdb->prepare(
147
+ "SELECT * FROM $wpdb->usermeta
148
+ WHERE user_id=%d
149
+ AND meta_key=%s",
150
+ $this->currentUID, $this->slug )
151
+ );
152
+ // Cache it
153
+ wp_cache_add( $cache_key, array( $r ), $cache_group );// WordPress cache
154
+ }
155
+
156
+ // Sort meta
157
+ $meta = array();
158
+ if ( !empty( $r ) ) {
159
+ $meta = maybe_unserialize( $r->meta_value );
160
+ $this->meta_object = $r;
161
+ } else {
162
+ $meta = null;
163
+ $this->meta_object = new stdClass();
164
+ $this->meta_object->umeta_id = null;
165
+ $this->meta_object->meta_key = null;
166
+ $this->meta_object->meta_value = null;
167
+ }
168
+
169
+ /*
170
+ * Secret public object :)
171
+ * Keeps original data
172
+ */
173
+ $this->__meta = $meta;
174
+
175
+ /*
176
+ *
177
+ * Apply filters
178
+ * !!! IMPORTANT !!!
179
+ * TODO Make this only place where field meta value is filtered
180
+ */
181
+ $meta = apply_filters( 'wpcf_fields_value_get', $meta, $this );
182
+ $meta = apply_filters( 'wpcf_fields_slug_' . $this->cf['slug']
183
+ . '_value_get', $meta, $this );
184
+ $meta = apply_filters( 'wpcf_fields_type_' . $this->cf['type']
185
+ . '_value_get', $meta, $this );
186
+ return $meta;
187
+ }
188
+
189
+ }
embedded/classes/usermeta_repeater.php ADDED
@@ -0,0 +1,571 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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_value( $meta_value );
96
+
97
+ // Adding each field will return $mid
98
+ // $unique = false
99
+ if ( !empty( $_meta_value ) ) {
100
+ $mid = add_user_meta( $this->currentUID, $this->slug,
101
+ $_meta_value );
102
+ $mids[] = $mid;
103
+
104
+ // Call insert post actions on each field
105
+ $this->_action_save( $this->cf, $_meta_value, $mid,
106
+ $meta_value );
107
+ }
108
+ }
109
+
110
+ // Save order
111
+ if ( !empty( $mids ) ) {
112
+ update_user_meta( $this->currentUID, $this->order_meta_name,
113
+ $mids );
114
+ }
115
+
116
+ // Return true - field found
117
+ return true;
118
+ }
119
+
120
+ // Return false if field missed
121
+ return false;
122
+ }
123
+
124
+ /**
125
+ * Fetch and sort fields.
126
+ *
127
+ * @global type $wpdb
128
+ */
129
+ function _get_meta() {
130
+ global $wpdb;
131
+
132
+ $cache_key = md5( 'usermetarepeater::_get_meta' . $this->currentUID . $this->slug );
133
+ $cache_group = 'types_cache';
134
+ $cached_object = wp_cache_get( $cache_key, $cache_group );
135
+
136
+ if ( $this->use_cache ) {
137
+ if ( false != $cached_object && is_array( $cached_object ) ) {
138
+ return $cached_object;
139
+ }
140
+ }
141
+
142
+ $this->order_meta_name = '_' . $this->slug . '-sort-order';
143
+
144
+ $_meta = parent::_get_meta();
145
+
146
+ $ordered = array();
147
+ $this->order = get_user_meta( $this->currentUID, $this->order_meta_name,
148
+ true );
149
+
150
+ $cache_key_userfield = md5( 'usermeta::_get_meta' . $this->currentUID . $this->slug );
151
+ $cached_object_userfield = wp_cache_get( $cache_key_userfield, $cache_group );
152
+
153
+ if ( $this->use_cache ) {
154
+ if ( false != $cached_object_userfield && is_array( $cached_object_userfield ) ) {// WordPress cache
155
+ $r = $cached_object_userfield;
156
+ } else {
157
+ $r = $wpdb->get_results(
158
+ $wpdb->prepare(
159
+ "SELECT * FROM $wpdb->usermeta
160
+ WHERE user_id=%d
161
+ AND meta_key=%s",
162
+ $this->currentUID, $this->slug )
163
+ );
164
+ }
165
+ }
166
+
167
+ if ( !empty( $r ) ) {
168
+ $_meta = array();
169
+ $_meta['by_meta_id'] = array();
170
+ $_meta['by_meta_key'] = array();
171
+
172
+ // Default order
173
+ foreach ( $r as $meta ) {
174
+ //print_r($meta);exit;
175
+ // This will use last item in array if multiple values exist
176
+ $_meta['single'] = maybe_unserialize( $meta->meta_value );
177
+ // Sort by meta_id column
178
+ $_meta['by_meta_id'][$meta->umeta_id]
179
+ = maybe_unserialize( $meta->meta_value );
180
+ // Sort by meta_key
181
+ $_meta['by_meta_key'][] = maybe_unserialize( $meta->meta_value );
182
+ }
183
+ ksort( $_meta['by_meta_id'] );
184
+
185
+ // Custom order
186
+ if ( !empty( $this->order ) ) {
187
+ foreach ( $this->order as $meta_id ) {
188
+ if ( isset( $_meta['by_meta_id'][$meta_id] ) ) {
189
+ $_meta['custom_order'][$meta_id] = $_meta['by_meta_id'][$meta_id];
190
+ }
191
+ }
192
+ // This ones are orphaned
193
+ foreach ( $_meta['by_meta_id'] as $meta_id => $meta ) {
194
+ if ( !isset( $ordered[$meta_id] ) ) {
195
+ $_meta['custom_order'][$meta_id] = $meta;
196
+ }
197
+ }
198
+ } else {
199
+ $_meta['custom_order'] = $_meta['by_meta_id'];
200
+ }
201
+ } else if ( !is_null( $this->meta_object ) ) {
202
+ $_meta = array();
203
+ $_meta['single'] = maybe_unserialize( $this->meta_object->meta_value );
204
+ // Sort by meta_id column
205
+ $_meta['by_meta_id'][$this->meta_object->umeta_id] = maybe_unserialize( $this->meta_object->meta_value );
206
+ // Sort by meta_key
207
+ $_meta['by_meta_key'][] = maybe_unserialize( $this->meta_object->meta_value );
208
+ } else {
209
+ $_meta = array();
210
+ $_meta['single'] = '';
211
+ $_meta['by_meta_id'] = array();
212
+ $_meta['by_meta_key'] = array();
213
+ }
214
+
215
+ if ( empty( $_meta['custom_order'] ) ) {
216
+ $_meta['custom_order'] = $_meta['by_meta_id'];
217
+ }
218
+
219
+ wp_cache_add( $cache_key, $_meta, $cache_group );// WordPress cache
220
+ return $_meta;
221
+ }
222
+
223
+ /**
224
+ * Sets repetitive field form.
225
+ *
226
+ * @todo Make more distinction between $field_form and $form_field
227
+ */
228
+ function get_fields_form( $is_profile = '' ) {
229
+ $form = array();
230
+ $form_id = $this->cf['id'];
231
+ $unique_id = wpcf_unique_id( serialize( $this->cf ) );
232
+
233
+ // Process fields
234
+ // Check if has any value
235
+ if ( empty( $this->meta['single'] ) ) {
236
+ // To prevent passing array to field
237
+ $this->meta = null;
238
+ $this->__meta = null;
239
+ $this->cf['value'] = null;
240
+
241
+ $field_form = $this->get_field_form( '' );
242
+
243
+ foreach ( $field_form as $field_key => $field ) {
244
+ $form_field[$form_id . '_repetitive_0_' . $field_key] = $field;
245
+ }
246
+ } else {
247
+
248
+ $ordered = !empty( $this->meta['custom_order'] ) ? $this->meta['custom_order'] : $this->meta['by_meta_id'];
249
+ foreach ( $ordered as $meta_id => $meta_value ) {
250
+
251
+ $this->cf['value'] = $meta_value;
252
+ $this->meta_object->umeta_id = $meta_id;
253
+
254
+ // Set single field form
255
+
256
+ $field_form = $this->get_field_form( $meta_value, $meta_id );
257
+
258
+ foreach ( $field_form as $field_key => $field ) {
259
+ $form_field[$form_id . '_repetitive_' . strval( $meta_id ) . '_' . $field_key] = $field;
260
+ }
261
+
262
+ $form_field[$form_id . '_repetitive_meta_id_' . strval( $meta_id )] = array(
263
+ '#type' => 'hidden',
264
+ '#name' => '',
265
+ '#value' => $meta_id,
266
+ );
267
+ }
268
+ }
269
+
270
+ // Set main wrapper
271
+ // Check if conditional
272
+ global $wpcf;
273
+
274
+ // Set style
275
+ /*
276
+ *
277
+ *
278
+ * Hide if field not passed check
279
+ * TODO Move this to WPCF_Conditional
280
+ */
281
+ $show = true;
282
+ if ( $wpcf->conditional->is_conditional( $this->cf ) ) {
283
+ $wpcf->conditional->set( $this->post, $this->cf );
284
+ $show = $wpcf->conditional->evaluate();
285
+ }
286
+ $css_cd = !$show ? 'display:none;' : '';
287
+
288
+ /**
289
+ *
290
+ *
291
+ *
292
+ *
293
+ * Set title and description
294
+ * TODO See if can be improved getting main element
295
+ *
296
+ * Get first element and extract details
297
+ * Pass emty string as value to avoid using meta as array
298
+ */
299
+ //
300
+ $_c = array_values( parent::_get_meta_form( '' ) );
301
+ array_shift( $_c );
302
+ $_main_element = array_shift( $_c );
303
+ // Set title and desc
304
+ if ( !empty( $_main_element['#title'] ) ) {
305
+ $this->title = $_main_element['#title'];
306
+ }
307
+ if ( !empty( $_main_element['#description'] ) ) {
308
+ $this->description = $_main_element['#description'];
309
+ }
310
+ $addTagHeaderStart = $addTagHeaderEnd = '';
311
+ if ( $is_profile == 1 ) {
312
+ $addTagHeaderStart = '<div class="wpcf-repeater-profile-line-left">';
313
+ $addTagHeaderEnd = '</div><div class="wpcf-repeater-profile-line-right">';
314
+ }
315
+ // Set title
316
+ $form[$unique_id . '_main_title'] = array(
317
+ '#type' => 'markup',
318
+ '#markup' => $addTagHeaderStart . '<strong>' . $this->title . '</strong><br/>' . $addTagHeaderEnd,
319
+ );
320
+
321
+ /*
322
+ *
323
+ *
324
+ * Start wrapper
325
+ */
326
+ $form[$unique_id . '_repetitive_wrapper_open'] = array(
327
+ '#type' => 'markup',
328
+ '#markup' => ''
329
+ . '<div id="wpcf_'
330
+ . $form_id
331
+ . '_repetitive_wrapper_' . $unique_id
332
+ . '" class="wpcf-wrap wpcf-repetitive-wrapper" style="' . $css_cd . '">',
333
+ );
334
+
335
+ // Set hidden mark field
336
+ /*
337
+ *
338
+ *
339
+ *
340
+ * This actually marks field as repetitive
341
+ * IMPORTANT!!! IF NOT marked field won't be saved at all!
342
+ *
343
+ * @see wpcf_admin_post_save_post_hook()
344
+ */
345
+ $form[$form_id . '_hidden_mark'] = array(
346
+ '#type' => 'hidden',
347
+ '#name' => '__wpcf_repetitive[' . $this->slug . ']',
348
+ '#value' => 1,
349
+ '#id' => $form_id . '_hidden_mark',
350
+ );
351
+
352
+ // Sortable
353
+ $form[$form_id . '_repetitive_sortable_open'] = array(
354
+ '#type' => 'markup',
355
+ '#markup' => '<div id="wpcf_'
356
+ . $form_id
357
+ . '_repetitive_sortable_' . wpcf_unique_id( serialize( $this->cf ) )
358
+ . '" class="wpcf-repetitive-sortable-wrapper">',
359
+ '#id' => $form_id . '_repetitive_sortable_wrapper_open',
360
+ );
361
+
362
+ // Append field form
363
+ $form = $form + $form_field;
364
+
365
+ // Close sortable wrapper
366
+ $form[$form_id . '_repetitive_sortable_close'] = array(
367
+ '#type' => 'markup',
368
+ '#markup' => '</div>',
369
+ '#id' => $form_id . '_repetitive_sortable_close',
370
+ );
371
+
372
+ // Add AJAX response at the end of repetitive field
373
+ // Show only on page load not when calling AJAX
374
+ if ( !defined( 'DOING_AJAX' ) ) {
375
+ $form[$form_id . '_repetitive_ajax_response'] = array(
376
+ '#type' => 'markup',
377
+ '#markup' => '<div class="wpcf-repetitive-response"></div>',
378
+ '#id' => $form_id . '_repetitive_ajax_response',
379
+ );
380
+
381
+ // Add description
382
+ $form[$unique_id . '_main_description'] = array(
383
+ '#type' => 'markup',
384
+ '#markup' => '<div class="wpcf-repetitive-description">'
385
+ . wpautop( stripslashes( strip_tags( $this->description ) ) )
386
+ . '</div>',
387
+ );
388
+
389
+ // 'Add' button
390
+ $form[$form_id . '_repetitive_form'] = array(
391
+ '#type' => 'markup',
392
+ '#markup' => wpcf_repetitive_umform( $this->cf,
393
+ $this->currentUID ),
394
+ '#id' => $form_id . '_repetitive_form',
395
+ );
396
+ }
397
+
398
+ // Close wrapper
399
+ $form[$unique_id . '_repetitive_wrapper_close'] = array(
400
+ '#type' => 'markup',
401
+ '#markup' => '</div></div>',
402
+ );
403
+
404
+ return $form;
405
+ }
406
+
407
+ /**
408
+ * Sete repetitive form for single field.
409
+ *
410
+ * @param type $meta
411
+ * @return string
412
+ */
413
+ function get_field_form( $meta_value = null, $meta_id = null ) {
414
+
415
+ $form = array();
416
+ if ( is_null( $meta_value ) ) {
417
+ $key = 'wpcf_field_' . wpcf_unique_id( md5( $this->index ) . $meta_id );
418
+ } else {
419
+ $key = 'wpcf_field_' . md5( maybe_serialize( $meta_value ) . $meta_id );
420
+ }
421
+
422
+ if ( is_null( $meta_value ) ||
423
+ (is_array( $meta_value ) && isset( $meta_value['custom_order'] ) )
424
+ ) {
425
+ $meta_value = $this->meta['single'];
426
+ }
427
+
428
+ // Open drag div
429
+ $form[$key . '_drag_open'] = array(
430
+ '#type' => 'markup',
431
+ '#markup' => '<div class="wpcf-repetitive-drag-and-drop">'
432
+ );
433
+
434
+ // Use WPCF_Field::get_field_form()
435
+ $field_form = parent::_get_meta_form( $meta_value, $meta_id, false );
436
+
437
+ /*
438
+ *
439
+ * Apply filters to each form element.
440
+ * Here we add specific properties
441
+ * e.g. Skype alters fields.
442
+ */
443
+ $_loop = false;
444
+ foreach ( $field_form as $k => $field ) {
445
+
446
+ /*
447
+ *
448
+ * IMPORTANT
449
+ * We change name to hold array
450
+ */
451
+ if ( isset( $field['#name'] ) ) {
452
+ $temp = explode( '[' . $this->cf['slug'] . ']', $field['#name'] );
453
+
454
+ // Assign new name
455
+ $field['#name'] = $temp[0] . '[' . $this->cf['slug'] . ']' . '['
456
+ . $key . ']';
457
+
458
+ // Append rest if any
459
+ if ( isset( $temp[1] ) ) {
460
+ $field['#name'] .= $temp[1];
461
+ }
462
+ }
463
+
464
+ // Apply filters
465
+ $field_form[$k] = apply_filters( 'wpcf_repetitive_field', $field,
466
+ $this->post, $this->cf, $k );
467
+
468
+ // BREAKPOINT
469
+ /*
470
+ * This is place where we clean display.
471
+ * First item is displayed as it is, each after is reduced.
472
+ * If called via AJAX - that means it added and should be reduced.
473
+ */
474
+ // if ( $_loop == true || defined( 'DOING_AJAX' ) ) {
475
+ /*
476
+ * See if field has Repeater pattern defined
477
+ */
478
+ if ( isset( $field['__repeater_restricted'] )
479
+ && is_array( $field['__repeater_restricted'] ) ) {
480
+ foreach ( $field['__repeater_restricted'] as $_e => $_v ) {
481
+ if ( isset( $field[$_e] ) ) {
482
+ unset( $field[$_e] );
483
+ }
484
+ }
485
+ } else {
486
+ unset( $field['#title'], $field['#description'] );
487
+ }
488
+ // Set main
489
+ $field_form[$k] = $field;
490
+ // }
491
+ // $_loop = true;
492
+ }
493
+
494
+ // Just append form
495
+ $form = $form + $field_form;
496
+
497
+ // Open control div
498
+ $form[$key . '_control_open'] = array(
499
+ '#type' => 'markup',
500
+ '#markup' => '<div class="wpcf-repetitive-control">'
501
+ );
502
+
503
+ // Drag button
504
+ $form[$key . '_drag_button'] = array(
505
+ '#type' => 'markup',
506
+ '#markup' => wpcf_repetitive_drag_button( $this->cf, $this->post ),
507
+ );
508
+
509
+ // 'Delete' button
510
+ $form[$key . '_delete_button'] = array(
511
+ '#type' => 'markup',
512
+ '#markup' => wpcf_repetitive_delete_button( $this->cf, $this->post,
513
+ $meta_id ),
514
+ );
515
+
516
+ // Close control div
517
+ $form[$key . '_control_close'] = array(
518
+ '#type' => 'markup',
519
+ '#markup' => '</div>',
520
+ );
521
+
522
+ // Close drag div
523
+ $form[$key . '_drag_close'] = array(
524
+ '#type' => 'markup',
525
+ '#markup' => '</div>',
526
+ );
527
+
528
+ // Count it and set JS var
529
+ $this->_set_form_count();
530
+ wpcf_admin_add_js_settings( 'wpcf_repetitive_count_' . md5( $this->cf['id'] ),
531
+ $this->index );
532
+
533
+ return $form;
534
+ }
535
+
536
+ /**
537
+ * Set counting elements.
538
+ */
539
+ function _set_form_count() {
540
+ if ( $this->index === 0 ) {
541
+ if ( defined( 'DOING_AJAX' ) && isset( $_POST['count'] ) ) {
542
+ $this->index = intval( $_POST['count'] );
543
+ }
544
+ }
545
+ $this->index += 1;
546
+ }
547
+
548
+ /**
549
+ * Deletes meta.
550
+ *
551
+ * @param type $meta_key
552
+ */
553
+ function delete( $meta_id ) {
554
+ global $wpdb;
555
+ $r = $wpdb->query(
556
+ $wpdb->prepare(
557
+ "DELETE FROM $wpdb->usermeta
558
+ WHERE user_id = %d
559
+ AND umeta_id = %d",
560
+ $this->currentUID, intval( $meta_id )
561
+ )
562
+ );
563
+ if ( $r === false ) {
564
+ return WP_Error( 'wpcf_repeater_delete_field',
565
+ 'Repeater failed deleting user_ID: '
566
+ . $this->currentUID . '; meta_ID: ' . intval( $meta_id ) );
567
+ }
568
+ return $r;
569
+ }
570
+
571
+ }
embedded/classes/validate.php ADDED
@@ -0,0 +1,435 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once dirname( __FILE__ ) . '/validation-cakephp.php';
3
+
4
+ /**
5
+ * Validation class
6
+ *
7
+ * @version 1.0
8
+ */
9
+ class Wpcf_Validate
10
+ {
11
+
12
+ /**
13
+ * Holds generic messages.
14
+ * @var type
15
+ */
16
+ public static $messages = null;
17
+
18
+ /**
19
+ * Holds function names.
20
+ * @var type
21
+ */
22
+ private static $_cake_aliases = array(
23
+ 'digits' => 'numeric',
24
+ 'number' => 'numeric',
25
+ 'alphanumeric' => 'alphaNumericWhitespaces',
26
+ 'nospecialchars' => 'noSpecialChars',
27
+ 'maxlength' => 'maxLength',
28
+ );
29
+
30
+ /**
31
+ * Current validation has 'required' method.
32
+ * @var type
33
+ */
34
+ private static $_is_required = false;
35
+ private static $_validation_object = null;
36
+
37
+ /**
38
+ * Sets calls.
39
+ *
40
+ * @param type $args
41
+ * @param type $value
42
+ * @return type
43
+ */
44
+ public static function check( $args, $value )
45
+ {
46
+ // Init validation object
47
+ if ( is_null( self::$_validation_object ) ) {
48
+ self::$_validation_object = new Wpcf_Cake_Validation();
49
+ }
50
+ // Check if there is 'required' method
51
+ if ( array_key_exists( 'required', $args ) ) {
52
+ self::$_is_required = true;
53
+ }
54
+
55
+ // Loop over validation array
56
+ foreach ( $args as $method => $v ) {
57
+ // Use this class method
58
+ if ( is_callable( array('Wpcf_Validate', $method) ) ) {
59
+ $check = call_user_func_array( array('Wpcf_Validate', $method),
60
+ array($v, $value) );
61
+ // Use CakePHP method
62
+ } else if ( (isset( self::$_cake_aliases[$method] )
63
+ && is_callable( array('Wpcf_Cake_Validation', self::$_cake_aliases[$method]) ))
64
+ || is_callable( array('Wpcf_Cake_Validation', $method) ) ) {
65
+
66
+ // Check if validation pattern is set
67
+ if ( isset( $v['pattern'] ) ) {
68
+ $pattern = array_flip( explode( '.', $v['pattern'] ) );
69
+ foreach ( $pattern as $arg_key => $arg_value ) {
70
+ if ( isset( $v[$arg_key] ) ) {
71
+ $pattern[$arg_key] = $v[$arg_key];
72
+ }
73
+ }
74
+ $pattern['check'] = $value;
75
+ $v = $pattern;
76
+ // Apply simple pattern (check, value)
77
+ } else {
78
+ unset( $v['active'], $v['message'] );
79
+ $v = array($value) + $v;
80
+ }
81
+
82
+ // Validate
83
+ if ( isset( self::$_cake_aliases[$method] ) && is_callable( array('Wpcf_Cake_Validation', self::$_cake_aliases[$method]) ) ) {
84
+ // $check = @call_user_func_array(array('Wpcf_Cake_Validation', self::$_cake_aliases[$method]),
85
+ // array_values($v));
86
+ $check = @call_user_func_array( array(self::$_validation_object, self::$_cake_aliases[$method]),
87
+ array_values( $v ) );
88
+ } else {
89
+ // $check = @call_user_func_array(array('Wpcf_Cake_Validation', $method),
90
+ // array_values($v));
91
+ $check = @call_user_func_array( array(self::$_validation_object, $method),
92
+ array_values( $v ) );
93
+ }
94
+ if ( !$check ) {
95
+ $check = array();
96
+ $check['error'] = 1;
97
+ }
98
+ // No method available
99
+ } else {
100
+ return array('error' => 1, 'message' => 'No validation method');
101
+ }
102
+
103
+ // Set error
104
+ if ( isset( $check['error'] ) ) {
105
+ // Don't return error if it's empty but not required
106
+ if ( (!empty( $value ) && $method != 'required' && self::$_is_required)
107
+ || (empty( $value ) && $method == 'required') ) {
108
+ $sprintf = isset($v['value']) ? $v['value'] : '';
109
+ $check['message'] = !empty( $v['message'] ) ? $v['message'] : self::get_message($method, $sprintf);
110
+ return $check;
111
+ }
112
+ }
113
+ }
114
+
115
+ return true;
116
+ }
117
+
118
+ /**
119
+ * Checks if method is available.
120
+ *
121
+ * @param type $method
122
+ * @return type
123
+ */
124
+ public static function canValidate( $method )
125
+ {
126
+ return (is_callable( array('Wpcf_Validate', $method) )
127
+ || (isset( self::$_cake_aliases[$method] )
128
+ && is_callable( array('Wpcf_Cake_Validation', self::$_cake_aliases[$method]) ))
129
+ || is_callable( array('Wpcf_Cake_Validation', $method) ));
130
+ }
131
+
132
+ /**
133
+ * Checks if method has form data.
134
+ *
135
+ * @param type $method
136
+ * @return type
137
+ */
138
+ public static function hasForm( $method )
139
+ {
140
+ return is_callable( array('Wpcf_Validate', $method . '_form') );
141
+ }
142
+
143
+ /**
144
+ * Inits messages.
145
+ */
146
+ private static function _set_messages()
147
+ {
148
+ // Set outside in /admin.php
149
+ self::$messages = wpcf_admin_validation_messages();
150
+ }
151
+
152
+ /**
153
+ * Return method invalid message.
154
+ *
155
+ * @param type $method
156
+ * @return type
157
+ */
158
+ public static function get_message( $method, $sprintf = '' )
159
+ {
160
+ return wpcf_admin_validation_messages($method, $sprintf);
161
+ if ( is_null( self::$messages ) ) {
162
+ self::_set_messages();
163
+ }
164
+ if ( isset( self::$messages[$method] ) ) {
165
+ return self::$messages[$method];
166
+ }
167
+ return null;
168
+ }
169
+
170
+ /**
171
+ * Checks 'required'.
172
+ *
173
+ * @param type $args
174
+ * @param type $value
175
+ * @return type
176
+ */
177
+ public static function required( $args, $value )
178
+ {
179
+ if ( empty( $value ) && $value !== 0 && $value !== '0' ) {
180
+ return array(
181
+ 'error' => 1,
182
+ );
183
+ }
184
+ return true;
185
+ }
186
+
187
+ /**
188
+ * Returns form data.
189
+ *
190
+ * @param type $field
191
+ * @param type $data
192
+ * @return array
193
+ */
194
+ public static function required_form( $field, $data = array() )
195
+ {
196
+ $form = array();
197
+ $form['required-checkbox'] = array(
198
+ '#type' => 'checkbox',
199
+ '#title' => __( 'Required', 'wpcf' ),
200
+ '#name' => $field['#name'] . '[active]',
201
+ '#default_value' => isset( $data['active'] ) ? 1 : 0,
202
+ '#inline' => true,
203
+ '#suffix' => '<br />',
204
+ );
205
+ $form['required-value'] = array(
206
+ '#type' => 'hidden',
207
+ '#value' => 'true',
208
+ '#name' => $field['#name'] . '[value]',
209
+ );
210
+ $form['required-message'] = self::get_custom_message( $field,
211
+ self::get_message( 'required' ), $data );
212
+ return $form;
213
+ }
214
+
215
+ /**
216
+ * Checks 'email'.
217
+ *
218
+ * @param type $args
219
+ * @param type $value
220
+ * @return type
221
+ */
222
+ public static function email( $args, $value )
223
+ {
224
+ if ( !is_email( $value ) ) {
225
+ return array(
226
+ 'error' => 1,
227
+ );
228
+ }
229
+ return true;
230
+ }
231
+
232
+ /**
233
+ * Checks 'rewriteslug'.
234
+ *
235
+ * @param type $args
236
+ * @param type $value
237
+ * @return type
238
+ */
239
+ public static function rewriteslug( $args, $value )
240
+ {
241
+ if ( preg_match( '#[^a-zA-Z0-9\/\_\-\%]#', $value ) === false ) {
242
+ return array(
243
+ 'error' => 1,
244
+ );
245
+ }
246
+ return true;
247
+ }
248
+
249
+ /**
250
+ * Returns form data.
251
+ *
252
+ * @param type $field
253
+ * @param type $data
254
+ * @return array
255
+ */
256
+ public static function email_form( $field, $data = array() )
257
+ {
258
+ $form = array();
259
+ $form['email-checkbox'] = array(
260
+ '#type' => 'checkbox',
261
+ '#title' => __( 'Email', 'wpcf' ),
262
+ '#name' => $field['#name'] . '[active]',
263
+ '#default_value' => isset( $data['active'] ) ? 1 : 0,
264
+ '#inline' => true,
265
+ '#suffix' => '<br />',
266
+ );
267
+
268
+ $form['email-message'] = self::get_custom_message( $field,
269
+ self::get_message( 'email' ), $data );
270
+ return $form;
271
+ }
272
+
273
+ /**
274
+ * Returns form data.
275
+ *
276
+ * @param type $field
277
+ * @param type $data
278
+ * @return array
279
+ */
280
+ public static function url_form( $field, $data = array() )
281
+ {
282
+ $form = array();
283
+ $form['url-checkbox'] = array(
284
+ '#type' => 'checkbox',
285
+ '#title' => 'URL',
286
+ '#name' => $field['#name'] . '[active]',
287
+ '#default_value' => isset( $data['active'] ) ? 1 : 0,
288
+ '#inline' => true,
289
+ '#suffix' => '<br />',
290
+ );
291
+
292
+ $form['url-checkbox'] = self::setForced( $form['url-checkbox'],
293
+ $field, $data );
294
+
295
+ $form['url-message'] = self::get_custom_message( $field,
296
+ self::get_message( 'url' ), $data );
297
+ return $form;
298
+ }
299
+
300
+ /**
301
+ * Returns form data.
302
+ *
303
+ * @param type $field
304
+ * @param type $data
305
+ * @return array
306
+ */
307
+ public static function date_form( $field, $data = array() )
308
+ {
309
+ $form = array();
310
+ $form['date-checkbox'] = array(
311
+ '#type' => 'checkbox',
312
+ '#title' => __( 'Date', 'wpcf' ),
313
+ '#name' => $field['#name'] . '[active]',
314
+ '#default_value' => isset( $data['active'] ) ? 1 : 0,
315
+ '#inline' => true,
316
+ '#suffix' => '<br />',
317
+ );
318
+ $form['date-format'] = array(
319
+ '#type' => 'hidden',
320
+ '#value' => 'mdy',
321
+ '#name' => $field['#name'] . '[format]',
322
+ );
323
+ $form['date-pattern'] = array(
324
+ '#type' => 'hidden',
325
+ '#value' => 'check.format',
326
+ '#name' => $field['#name'] . '[pattern]',
327
+ );
328
+ $form['url-message'] = self::get_custom_message( $field,
329
+ self::get_message( 'date' ), $data );
330
+ return $form;
331
+ }
332
+
333
+ /**
334
+ * Returns form data.
335
+ *
336
+ * @param type $field
337
+ * @param type $data
338
+ * @return array
339
+ */
340
+ public static function digits_form( $field, $data = array() )
341
+ {
342
+ $form = array();
343
+ $attributes = array();
344
+ $default_value = isset( $data['active'] ) ? 1 : 0;
345
+ $form['digits-checkbox'] = array(
346
+ '#type' => 'checkbox',
347
+ '#title' => __( 'Digits', 'wpcf' ),
348
+ '#name' => $field['#name'] . '[active]',
349
+ '#default_value' => $default_value,
350
+ '#inline' => true,
351
+ '#suffix' => '<br />',
352
+ '#attributes' => $attributes,
353
+ );
354
+ $form['digits-checkbox'] = self::setForced( $form['digits-checkbox'],
355
+ $field, $data );
356
+
357
+ $form['digits-message'] = self::get_custom_message( $field,
358
+ self::get_message( 'digits' ), $data );
359
+ return $form;
360
+ }
361
+
362
+ /**
363
+ * Returns form data.
364
+ *
365
+ * @param type $field
366
+ * @param type $data
367
+ * @return array
368
+ */
369
+ public static function number_form( $field, $data = array() )
370
+ {
371
+ $form = array();
372
+ $attributes = array();
373
+ $default_value = isset( $data['active'] ) ? 1 : 0;
374
+ $form['number-checkbox'] = array(
375
+ '#type' => 'checkbox',
376
+ '#title' => __( 'Numeric', 'wpcf' ),
377
+ '#name' => $field['#name'] . '[active]',
378
+ '#default_value' => $default_value,
379
+ '#inline' => true,
380
+ '#suffix' => '<br />',
381
+ '#attributes' => $attributes,
382
+ );
383
+ $form['number-checkbox'] = self::setForced( $form['number-checkbox'],
384
+ $field, $data );
385
+
386
+ $form['number-message'] = self::get_custom_message( $field,
387
+ self::get_message( 'number' ), $data );
388
+ return $form;
389
+ }
390
+
391
+ public static function setForced( $element, $field, $data = array() )
392
+ {
393
+ $attributes = array();
394
+ $default_value = isset( $data['active'] ) ? 1 : 0;
395
+ if ( !empty( $data['method_data']['forced'] ) ) {
396
+ if ( !isset( $element['#attributes'] ) ) {
397
+ $element['#attributes'] = array();
398
+ }
399
+ $element['#attributes']['readonly'] = 'readonly';
400
+ $element['#attributes']['onclick'] = 'jQuery(this).attr(\'checked\', \'checked\');';
401
+ $element['#default_value'] = 1;
402
+ }
403
+ return $element;
404
+ }
405
+
406
+ /**
407
+ * Returns 'custom message' field.
408
+ *
409
+ * @param type $field
410
+ * @param type $default
411
+ * @param type $data
412
+ * @return type
413
+ */
414
+ public static function get_custom_message( $field, $default, $data )
415
+ {
416
+ return array(
417
+ '#type' => 'textfield',
418
+ // '#title' => __('Custom message', 'wpcf'),
419
+ '#name' => $field['#name'] . '[message]',
420
+ '#value' => !empty( $data['message'] ) ? $data['message'] : $default,
421
+ '#inline' => true,
422
+ // '#suffix' => '<br /><br />',
423
+ );
424
+ }
425
+
426
+ public static function negativeTimestamp( $args, $value ) {
427
+ if ( !fields_date_timestamp_neg_supported() && intval( $value ) < 0 ) {
428
+ return array(
429
+ 'error' => 1,
430
+ );
431
+ }
432
+ return true;
433
+ }
434
+
435
+ }
embedded/classes/validation-cakephp.php ADDED
@@ -0,0 +1,1122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ /**
199
+ * Checks that a string length is within s specified range.
200
+ * Spaces are included in the character count.
201
+ * Returns true is string matches value min, max, or between min and max,
202
+ *
203
+ * @param string $check Value to check for length
204
+ * @param integer $min Minimum value in range (inclusive)
205
+ * @param integer $max Maximum value in range (inclusive)
206
+ * @return boolean Success
207
+ * @access public
208
+ */
209
+ function between( $check, $min, $max ) {
210
+ $length = strlen( $check );
211
+ return ($length >= $min && $length <= $max);
212
+ }
213
+
214
+ /**
215
+ * Returns true if field is left blank -OR- only whitespace characters are present in it's value
216
+ * Whitespace characters include Space, Tab, Carriage Return, Newline
217
+ *
218
+ * $check can be passed as an array:
219
+ * array('check' => 'valueToCheck');
220
+ *
221
+ * @param mixed $check Value to check
222
+ * @return boolean Success
223
+ * @access public
224
+ */
225
+ function blank( $check ) {
226
+ $_this = &Wpcf_Cake_Validation::getInstance();
227
+ $_this->__reset();
228
+ $_this->check = $check;
229
+
230
+ if ( is_array( $check ) ) {
231
+ $_this->_extract( $check );
232
+ }
233
+
234
+ $_this->regex = '/[^\\s]/';
235
+ return !$_this->_check();
236
+ }
237
+
238
+ /**
239
+ * Validation of credit card numbers.
240
+ * Returns true if $check is in the proper credit card format.
241
+ *
242
+ * @param mixed $check credit card number to validate
243
+ * @param mixed $type 'all' may be passed as a sting, defaults to fast which checks format of most major credit cards
244
+ * if an array is used only the values of the array are checked.
245
+ * Example: array('amex', 'bankcard', 'maestro')
246
+ * @param boolean $deep set to true this will check the Luhn algorithm of the credit card.
247
+ * @param string $regex A custom regex can also be passed, this will be used instead of the defined regex values
248
+ * @return boolean Success
249
+ * @access public
250
+ * @see Wpcf_Cake_Validation::_luhn()
251
+ */
252
+ function cc( $check, $type = 'fast', $deep = false, $regex = null ) {
253
+ $_this = &Wpcf_Cake_Validation::getInstance();
254
+ $_this->__reset();
255
+ $_this->check = $check;
256
+ $_this->type = $type;
257
+ $_this->deep = $deep;
258
+ $_this->regex = $regex;
259
+
260
+ if ( is_array( $check ) ) {
261
+ $_this->_extract( $check );
262
+ }
263
+ $_this->check = str_replace( array('-', ' '), '', $_this->check );
264
+
265
+ if ( strlen( $_this->check ) < 13 ) {
266
+ return false;
267
+ }
268
+
269
+ if ( !is_null( $_this->regex ) ) {
270
+ if ( $_this->_check() ) {
271
+ return $_this->_luhn();
272
+ }
273
+ }
274
+ $cards = array(
275
+ 'all' => array(
276
+ 'amex' => '/^3[4|7]\\d{13}$/',
277
+ 'bankcard' => '/^56(10\\d\\d|022[1-5])\\d{10}$/',
278
+ 'diners' => '/^(?:3(0[0-5]|[68]\\d)\\d{11})|(?:5[1-5]\\d{14})$/',
279
+ 'disc' => '/^(?:6011|650\\d)\\d{12}$/',
280
+ 'electron' => '/^(?:417500|4917\\d{2}|4913\\d{2})\\d{10}$/',
281
+ 'enroute' => '/^2(?:014|149)\\d{11}$/',
282
+ 'jcb' => '/^(3\\d{4}|2100|1800)\\d{11}$/',
283
+ 'maestro' => '/^(?:5020|6\\d{3})\\d{12}$/',
284
+ 'mc' => '/^5[1-5]\\d{14}$/',
285
+ 'solo' => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/',
286
+ '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})?)$/',
287
+ 'visa' => '/^4\\d{12}(\\d{3})?$/',
288
+ 'voyager' => '/^8699[0-9]{11}$/'
289
+ ),
290
+ '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})$/'
291
+ );
292
+
293
+ if ( is_array( $_this->type ) ) {
294
+ foreach ( $_this->type as $value ) {
295
+ $_this->regex = $cards['all'][strtolower( $value )];
296
+
297
+ if ( $_this->_check() ) {
298
+ return $_this->_luhn();
299
+ }
300
+ }
301
+ } elseif ( $_this->type == 'all' ) {
302
+ foreach ( $cards['all'] as $value ) {
303
+ $_this->regex = $value;
304
+
305
+ if ( $_this->_check() ) {
306
+ return $_this->_luhn();
307
+ }
308
+ }
309
+ } else {
310
+ $_this->regex = $cards['fast'];
311
+
312
+ if ( $_this->_check() ) {
313
+ return $_this->_luhn();
314
+ }
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Used to compare 2 numeric values.
320
+ *
321
+ * @param mixed $check1 if string is passed for a string must also be passed for $check2
322
+ * used as an array it must be passed as array('check1' => value, 'operator' => 'value', 'check2' -> value)
323
+ * @param string $operator Can be either a word or operand
324
+ * is greater >, is less <, greater or equal >=
325
+ * less or equal <=, is less <, equal to ==, not equal !=
326
+ * @param integer $check2 only needed if $check1 is a string
327
+ * @return boolean Success
328
+ * @access public
329
+ */
330
+ function comparison( $check1, $operator = null, $check2 = null ) {
331
+ if ( is_array( $check1 ) ) {
332
+ extract( $check1, EXTR_OVERWRITE );
333
+ }
334
+ $operator = str_replace( array(' ', "\t", "\n", "\r", "\0", "\x0B"), '',
335
+ strtolower( $operator ) );
336
+
337
+ switch ( $operator ) {
338
+ case 'isgreater':
339
+ case '>':
340
+ if ( $check1 > $check2 ) {
341
+ return true;
342
+ }
343
+ break;
344
+ case 'isless':
345
+ case '<':
346
+ if ( $check1 < $check2 ) {
347
+ return true;
348
+ }
349
+ break;
350
+ case 'greaterorequal':
351
+ case '>=':
352
+ if ( $check1 >= $check2 ) {
353
+ return true;
354
+ }
355
+ break;
356
+ case 'lessorequal':
357
+ case '<=':
358
+ if ( $check1 <= $check2 ) {
359
+ return true;
360
+ }
361
+ break;
362
+ case 'equalto':
363
+ case '==':
364
+ if ( $check1 == $check2 ) {
365
+ return true;
366
+ }
367
+ break;
368
+ case 'notequal':
369
+ case '!=':
370
+ if ( $check1 != $check2 ) {
371
+ return true;
372
+ }
373
+ break;
374
+ default:
375
+ $_this = &Wpcf_Cake_Validation::getInstance();
376
+ $_this->errors[] = __( 'You must define the $operator parameter for Wpcf_Cake_Validation::comparison()',
377
+ 'wpcf' );
378
+ break;
379
+ }
380
+ return false;
381
+ }
382
+
383
+ /**
384
+ * Used when a custom regular expression is needed.
385
+ *
386
+ * @param mixed $check When used as a string, $regex must also be a valid regular expression.
387
+ * As and array: array('check' => value, 'regex' => 'valid regular expression')
388
+ * @param string $regex If $check is passed as a string, $regex must also be set to valid regular expression
389
+ * @return boolean Success
390
+ * @access public
391
+ */
392
+ function custom( $check, $regex = null ) {
393
+ $_this = &Wpcf_Cake_Validation::getInstance();
394
+ $_this->__reset();
395
+ $_this->check = $check;
396
+ $_this->regex = $regex;
397
+ if ( is_array( $check ) ) {
398
+ $_this->_extract( $check );
399
+ }
400
+ if ( $_this->regex === null ) {
401
+ $_this->errors[] = __( 'You must define a regular expression for Wpcf_Cake_Validation::custom()',
402
+ 'wpcf' );
403
+ return false;
404
+ }
405
+ return $_this->_check();
406
+ }
407
+
408
+ /**
409
+ * Date validation, determines if the string passed is a valid date.
410
+ * keys that expect full month, day and year will validate leap years
411
+ *
412
+ * @param string $check a valid date string
413
+ * @param mixed $format Use a string or an array of the keys below. Arrays should be passed as array('dmy', 'mdy', etc)
414
+ * Keys: dmy 27-12-2006 or 27-12-06 separators can be a space, period, dash, forward slash
415
+ * mdy 12-27-2006 or 12-27-06 separators can be a space, period, dash, forward slash
416
+ * ymd 2006-12-27 or 06-12-27 separators can be a space, period, dash, forward slash
417
+ * dMy 27 December 2006 or 27 Dec 2006
418
+ * Mdy December 27, 2006 or Dec 27, 2006 comma is optional
419
+ * My December 2006 or Dec 2006
420
+ * my 12/2006 separators can be a space, period, dash, forward slash
421
+ * @param string $regex If a custom regular expression is used this is the only validation that will occur.
422
+ * @return boolean Success
423
+ * @access public
424
+ */
425
+ function date( $check, $format = 'ymd', $regex = null ) {
426
+
427
+ $date_format = wpcf_get_date_format();
428
+ $cake_date_formats = array('F j, Y' => 'Mdy',
429
+ 'Y/m/d' => 'ymd',
430
+ 'm/d/Y' => 'mdy',
431
+ 'd/m/Y' => 'dmy'
432
+ );
433
+ $format = $cake_date_formats[$date_format];
434
+
435
+ $_this = &Wpcf_Cake_Validation::getInstance();
436
+ $_this->__reset();
437
+ $_this->check = $check;
438
+ $_this->regex = $regex;
439
+
440
+ if ( !is_null( $_this->regex ) ) {
441
+ return $_this->_check();
442
+ }
443
+
444
+ $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})$%';
445
+ $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})$%';
446
+ $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]))))$%';
447
+ $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})$/';
448
+ $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}))$/';
449
+ $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})$%';
450
+ $regex['my'] = '%^(((0[123456789]|10|11|12)([- /.])(([1][9][0-9][0-9])|([2][0-9][0-9][0-9]))))$%';
451
+
452
+ $format = (is_array( $format )) ? array_values( $format ) : array($format);
453
+ foreach ( $format as $key ) {
454
+ $_this->regex = $regex[$key];
455
+
456
+ if ( $_this->_check() === true ) {
457
+ return true;
458
+ }
459
+ }
460
+ return false;
461
+ }
462
+
463
+ /**
464
+ * Time validation, determines if the string passed is a valid time.
465
+ * Validates time as 24hr (HH:MM) or am/pm ([H]H:MM[a|p]m)
466
+ * Does not allow/validate seconds.
467
+ *
468
+ * @param string $check a valid time string
469
+ * @return boolean Success
470
+ * @access public
471
+ */
472
+ function time( $check ) {
473
+ $_this = &Wpcf_Cake_Validation::getInstance();
474
+ $_this->__reset();
475
+ $_this->check = $check;
476
+ $_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}$%';
477
+ return $_this->_check();
478
+ }
479
+
480
+ /**
481
+ * Boolean validation, determines if value passed is a boolean integer or true/false.
482
+ *
483
+ * @param string $check a valid boolean
484
+ * @return boolean Success
485
+ * @access public
486
+ */
487
+ function boolean( $check ) {
488
+ $booleanList = array(0, 1, '0', '1', true, false);
489
+ return in_array( $check, $booleanList, true );
490
+ }
491
+
492
+ /**
493
+ * Checks that a value is a valid decimal. If $places is null, the $check is allowed to be a scientific float
494
+ * If no decimal point is found a false will be returned. Both the sign and exponent are optional.
495
+ *
496
+ * @param integer $check The value the test for decimal
497
+ * @param integer $places if set $check value must have exactly $places after the decimal point
498
+ * @param string $regex If a custom regular expression is used this is the only validation that will occur.
499
+ * @return boolean Success
500
+ * @access public
501
+ */
502
+ function decimal( $check, $places = null, $regex = null ) {
503
+ $_this = &Wpcf_Cake_Validation::getInstance();
504
+ $_this->__reset();
505
+ $_this->regex = $regex;
506
+ $_this->check = $check;
507
+
508
+ if ( is_null( $_this->regex ) ) {
509
+ if ( is_null( $places ) ) {
510
+ $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]+(?:[eE][-+]?[0-9]+)?$/';
511
+ } else {
512
+ $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]{' . $places . '}$/';
513
+ }
514
+ }
515
+ return $_this->_check();
516
+ }
517
+
518
+ /**
519
+ * Validates for an email address.
520
+ *
521
+ * @param string $check Value to check
522
+ * @param boolean $deep Perform a deeper validation (if true), by also checking availability of host
523
+ * @param string $regex Regex to use (if none it will use built in regex)
524
+ * @return boolean Success
525
+ * @access public
526
+ */
527
+ function email( $check, $deep = false, $regex = null ) {
528
+ $_this = &Wpcf_Cake_Validation::getInstance();
529
+ $_this->__reset();
530
+ $_this->check = $check;
531
+ $_this->regex = $regex;
532
+ $_this->deep = $deep;
533
+
534
+ if ( is_array( $check ) ) {
535
+ $_this->_extract( $check );
536
+ }
537
+
538
+ if ( is_null( $_this->regex ) ) {
539
+ $_this->regex = '/^[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@' . $_this->__pattern['hostname'] . '$/i';
540
+ }
541
+ $return = $_this->_check();
542
+
543
+ if ( $_this->deep === false || $_this->deep === null ) {
544
+ return $return;
545
+ }
546
+
547
+ if ( $return === true && preg_match( '/@(' . $_this->__pattern['hostname'] . ')$/i',
548
+ $_this->check, $regs ) ) {
549
+ if ( function_exists( 'getmxrr' ) && getmxrr( $regs[1], $mxhosts ) ) {
550
+ return true;
551
+ }
552
+ if ( function_exists( 'checkdnsrr' ) && checkdnsrr( $regs[1], 'MX' ) ) {
553
+ return true;
554
+ }
555
+ return is_array( gethostbynamel( $regs[1] ) );
556
+ }
557
+ return false;
558
+ }
559
+
560
+ /**
561
+ * Check that value is exactly $comparedTo.
562
+ *
563
+ * @param mixed $check Value to check
564
+ * @param mixed $comparedTo Value to compare
565
+ * @return boolean Success
566
+ * @access public
567
+ */
568
+ function equalTo( $check, $comparedTo ) {
569
+ return ($check === $comparedTo);
570
+ }
571
+
572
+ /**
573
+ * Check that value has a valid file extension.
574
+ *
575
+ * @param mixed $check Value to check
576
+ * @param array $extensions file extenstions to allow
577
+ * @return boolean Success
578
+ * @access public
579
+ */
580
+ function extension( $check, $extensions = array('gif', 'jpeg', 'png', 'jpg') ) {
581
+ if ( is_array( $check ) ) {
582
+ return Wpcf_Cake_Validation::extension( array_shift( $check ),
583
+ $extensions );
584
+ }
585
+ $extension = strtolower( array_pop( explode( '.', $check ) ) );
586
+ foreach ( $extensions as $value ) {
587
+ if ( $extension == strtolower( $value ) ) {
588
+ return true;
589
+ }
590
+ }
591
+ return false;
592
+ }
593
+
594
+ /**
595
+ * Validation of an IP address.
596
+ *
597
+ * Valid IP version strings for type restriction are:
598
+ * - both: Check both IPv4 and IPv6, return true if the supplied address matches either version
599
+ * - IPv4: Version 4 (Eg: 127.0.0.1, 192.168.10.123, 203.211.24.8)
600
+ * - IPv6: Version 6 (Eg: ::1, 2001:0db8::1428:57ab)
601
+ *
602
+ * @param string $check The string to test.
603
+ * @param string $type The IP Version to test against
604
+ * @return boolean Success
605
+ * @access public
606
+ */
607
+ function ip( $check, $type = 'both' ) {
608
+ $_this = &Wpcf_Cake_Validation::getInstance();
609
+ $success = false;
610
+ $type = strtolower( $type );
611
+ if ( $type === 'ipv4' || $type === 'both' ) {
612
+ $success |= $_this->_ipv4( $check );
613
+ }
614
+ if ( $type === 'ipv6' || $type === 'both' ) {
615
+ $success |= $_this->_ipv6( $check );
616
+ }
617
+ return $success;
618
+ }
619
+
620
+ /**
621
+ * Validation of IPv4 addresses.
622
+ *
623
+ * @param string $check IP Address to test
624
+ * @return boolean Success
625
+ * @access protected
626
+ */
627
+ function _ipv4( $check ) {
628
+ if ( function_exists( 'filter_var' ) ) {
629
+ return filter_var( $check, FILTER_VALIDATE_IP,
630
+ array('flags' => FILTER_FLAG_IPV4) ) !== false;
631
+ }
632
+ $this->__populateIp();
633
+ $this->check = $check;
634
+ $this->regex = '/^' . $this->__pattern['IPv4'] . '$/';
635
+ return $this->_check();
636
+ }
637
+
638
+ /**
639
+ * Validation of IPv6 addresses.
640
+ *
641
+ * @param string $check IP Address to test
642
+ * @return boolean Success
643
+ * @access protected
644
+ */
645
+ function _ipv6( $check ) {
646
+ if ( function_exists( 'filter_var' ) ) {
647
+ return filter_var( $check, FILTER_VALIDATE_IP,
648
+ array('flags' => FILTER_FLAG_IPV6) ) !== false;
649
+ }
650
+ $this->__populateIp();
651
+ $this->check = $check;
652
+ $this->regex = '/^' . $this->__pattern['IPv6'] . '$/';
653
+ return $this->_check();
654
+ }
655
+
656
+ /**
657
+ * Checks whether the length of a string is greater or equal to a minimal length.
658
+ *
659
+ * @param string $check The string to test
660
+ * @param integer $min The minimal string length
661
+ * @return boolean Success
662
+ * @access public
663
+ */
664
+ function minLength( $check, $min ) {
665
+ $length = strlen( $check );
666
+ return ($length >= $min);
667
+ }
668
+
669
+ /**
670
+ * Checks whether the length of a string is smaller or equal to a maximal length..
671
+ *
672
+ * @param string $check The string to test
673
+ * @param integer $max The maximal string length
674
+ * @return boolean Success
675
+ * @access public
676
+ */
677
+ function maxLength( $check, $max ) {
678
+ $length = strlen( $check );
679
+ return ($length <= $max);
680
+ }
681
+
682
+ /**
683
+ * Checks that a value is a monetary amount.
684
+ *
685
+ * @param string $check Value to check
686
+ * @param string $symbolPosition Where symbol is located (left/right)
687
+ * @return boolean Success
688
+ * @access public
689
+ */
690
+ function money( $check, $symbolPosition = 'left' ) {
691
+ $_this = &Wpcf_Cake_Validation::getInstance();
692
+ $_this->check = $check;
693
+
694
+ if ( $symbolPosition == 'right' ) {
695
+ $_this->regex = '/^(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?(?<!\x{00a2})\p{Sc}?$/u';
696
+ } else {
697
+ $_this->regex = '/^(?!\x{00a2})\p{Sc}?(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?$/u';
698
+ }
699
+ return $_this->_check();
700
+ }
701
+
702
+ /**
703
+ * Validate a multiple select.
704
+ *
705
+ * Valid Options
706
+ *
707
+ * - in => provide a list of choices that selections must be made from
708
+ * - max => maximun number of non-zero choices that can be made
709
+ * - min => minimum number of non-zero choices that can be made
710
+ *
711
+ * @param mixed $check Value to check
712
+ * @param mixed $options Options for the check.
713
+ * @return boolean Success
714
+ * @access public
715
+ */
716
+ function multiple( $check, $options = array() ) {
717
+ $defaults = array('in' => null, 'max' => null, 'min' => null);
718
+ $options = array_merge( $defaults, $options );
719
+ $check = array_filter( (array) $check );
720
+ if ( empty( $check ) ) {
721
+ return false;
722
+ }
723
+ if ( $options['max'] && count( $check ) > $options['max'] ) {
724
+ return false;
725
+ }
726
+ if ( $options['min'] && count( $check ) < $options['min'] ) {
727
+ return false;
728
+ }
729
+ if ( $options['in'] && is_array( $options['in'] ) ) {
730
+ foreach ( $check as $val ) {
731
+ if ( !in_array( $val, $options['in'] ) ) {
732
+ return false;
733
+ }
734
+ }
735
+ }
736
+ return true;
737
+ }
738
+
739
+ /**
740
+ * Checks if a value is numeric.
741
+ *
742
+ * @param string $check Value to check
743
+ * @return boolean Succcess
744
+ * @access public
745
+ */
746
+ function numeric( $check ) {
747
+ return is_numeric( $check );
748
+ }
749
+
750
+ /**
751
+ * Check that a value is a valid phone number.
752
+ *
753
+ * @param mixed $check Value to check (string or array)
754
+ * @param string $regex Regular expression to use
755
+ * @param string $country Country code (defaults to 'all')
756
+ * @return boolean Success
757
+ * @access public
758
+ */
759
+ function phone( $check, $regex = null, $country = 'all' ) {
760
+ $_this = &Wpcf_Cake_Validation::getInstance();
761
+ $_this->check = $check;
762
+ $_this->regex = $regex;
763
+ $_this->country = $country;
764
+ if ( is_array( $check ) ) {
765
+ $_this->_extract( $check );
766
+ }
767
+
768
+ if ( is_null( $_this->regex ) ) {
769
+ switch ( $_this->country ) {
770
+ case 'us':
771
+ case 'all':
772
+ case 'can':
773
+ // includes all NANPA members. see http://en.wikipedia.org/wiki/North_American_Numbering_Plan#List_of_NANPA_countries_and_territories
774
+ $_this->regex = '/^(?:\+?1)?[-. ]?\\(?[2-9][0-8][0-9]\\)?[-. ]?[2-9][0-9]{2}[-. ]?[0-9]{4}$/';
775
+ break;
776
+ }
777
+ }
778
+ if ( empty( $_this->regex ) ) {
779
+ return $_this->_pass( 'phone', $check, $country );
780
+ }
781
+ return $_this->_check();
782
+ }
783
+
784
+ /**
785
+ * Checks that a given value is a valid postal code.
786
+ *
787
+ * @param mixed $check Value to check
788
+ * @param string $regex Regular expression to use
789
+ * @param string $country Country to use for formatting
790
+ * @return boolean Success
791
+ * @access public
792
+ */
793
+ function postal( $check, $regex = null, $country = null ) {
794
+ $_this = &Wpcf_Cake_Validation::getInstance();
795
+ $_this->check = $check;
796
+ $_this->regex = $regex;
797
+ $_this->country = $country;
798
+ if ( is_array( $check ) ) {
799
+ $_this->_extract( $check );
800
+ }
801
+ if ( empty( $country ) ) {
802
+ $_this->country = 'us';
803
+ }
804
+
805
+ if ( is_null( $_this->regex ) ) {
806
+ switch ( $_this->country ) {
807
+ case 'uk':
808
+ $_this->regex = '/\\A\\b[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}\\b\\z/i';
809
+ break;
810
+ case 'ca':
811
+ $_this->regex = '/\\A\\b[ABCEGHJKLMNPRSTVXY][0-9][A-Z] ?[0-9][A-Z][0-9]\\b\\z/i';
812
+ break;
813
+ case 'it':
814
+ case 'de':
815
+ $_this->regex = '/^[0-9]{5}$/i';
816
+ break;
817
+ case 'be':
818
+ $_this->regex = '/^[1-9]{1}[0-9]{3}$/i';
819
+ break;
820
+ case 'us':
821
+ $_this->regex = '/\\A\\b[0-9]{5}(?:-[0-9]{4})?\\b\\z/i';
822
+ break;
823
+ }
824
+ }
825
+ if ( empty( $_this->regex ) ) {
826
+ return $_this->_pass( 'postal', $check, $country );
827
+ }
828
+ return $_this->_check();
829
+ }
830
+
831
+ /**
832
+ * Validate that a number is in specified range.
833
+ * if $lower and $upper are not set, will return true if
834
+ * $check is a legal finite on this platform
835
+ *
836
+ * @param string $check Value to check
837
+ * @param integer $lower Lower limit
838
+ * @param integer $upper Upper limit
839
+ * @return boolean Success
840
+ * @access public
841
+ */
842
+ function range( $check, $lower = null, $upper = null ) {
843
+ if ( !is_numeric( $check ) ) {
844
+ return false;
845
+ }
846
+ if ( isset( $lower ) && isset( $upper ) ) {
847
+ return ($check > $lower && $check < $upper);
848
+ }
849
+ return is_finite( $check );
850
+ }
851
+
852
+ /**
853
+ * Checks that a value is a valid Social Security Number.
854
+ *
855
+ * @param mixed $check Value to check
856
+ * @param string $regex Regular expression to use
857
+ * @param string $country Country
858
+ * @return boolean Success
859
+ * @access public
860
+ */
861
+ function ssn( $check, $regex = null, $country = null ) {
862
+ $_this = &Wpcf_Cake_Validation::getInstance();
863
+ $_this->check = $check;
864
+ $_this->regex = $regex;
865
+ $_this->country = $country;
866
+ if ( is_array( $check ) ) {
867
+ $_this->_extract( $check );
868
+ }
869
+
870
+ if ( is_null( $_this->regex ) ) {
871
+ switch ( $_this->country ) {
872
+ case 'dk':
873
+ $_this->regex = '/\\A\\b[0-9]{6}-[0-9]{4}\\b\\z/i';
874
+ break;
875
+ case 'nl':
876
+ $_this->regex = '/\\A\\b[0-9]{9}\\b\\z/i';
877
+ break;
878
+ case 'us':
879
+ $_this->regex = '/\\A\\b[0-9]{3}-[0-9]{2}-[0-9]{4}\\b\\z/i';
880
+ break;
881
+ }
882
+ }
883
+ if ( empty( $_this->regex ) ) {
884
+ return $_this->_pass( 'ssn', $check, $country );
885
+ }
886
+ return $_this->_check();
887
+ }
888
+
889
+ /**
890
+ * Checks that a value is a valid uuid - http://tools.ietf.org/html/rfc4122
891
+ *
892
+ * @param string $check Value to check
893
+ * @return boolean Success
894
+ * @access public
895
+ */
896
+ function uuid( $check ) {
897
+ $_this = &Wpcf_Cake_Validation::getInstance();
898
+ $_this->check = $check;
899
+ $_this->regex = '/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i';
900
+ return $_this->_check();
901
+ }
902
+
903
+ /**
904
+ * Checks that a value is a valid URL according to http://www.w3.org/Addressing/URL/url-spec.txt
905
+ *
906
+ * The regex checks for the following component parts:
907
+ *
908
+ * - a valid, optional, scheme
909
+ * - a valid ip address OR
910
+ * a valid domain name as defined by section 2.3.1 of http://www.ietf.org/rfc/rfc1035.txt
911
+ * with an optional port number
912
+ * - an optional valid path
913
+ * - an optional query string (get parameters)
914
+ * - an optional fragment (anchor tag)
915
+ *
916
+ * @param string $check Value to check
917
+ * @param boolean $strict Require URL to be prefixed by a valid scheme (one of http(s)/ftp(s)/file/news/gopher)
918
+ * @return boolean Success
919
+ * @access public
920
+ */
921
+ function url( $check, $strict = false ) {
922
+ $_this = &Wpcf_Cake_Validation::getInstance();
923
+ $_this->__populateIp();
924
+ $_this->check = $check;
925
+ $validChars = '([' . preg_quote( '!"$&\'()*+,-.@_:;=~[]' ) . '\/0-9a-z\p{L}\p{N}]|(%[0-9a-f]{2}))';
926
+ $_this->regex = '/^(?:(?:https?|ftps?|file|news|gopher):\/\/)' . (!empty( $strict ) ? '' : '?') .
927
+ '(?:' . $_this->__pattern['IPv4'] . '|\[' . $_this->__pattern['IPv6'] . '\]|' . $_this->__pattern['hostname'] . ')' .
928
+ '(?::[1-9][0-9]{0,4})?' .
929
+ '(?:\/?|\/' . $validChars . '*)?' .
930
+ '(?:\?' . $validChars . '*)?' .
931
+ '(?:#' . $validChars . '*)?$/iu';
932
+ return $_this->_check();
933
+ }
934
+
935
+ /**
936
+ * Checks if a value is in a given list.
937
+ *
938
+ * @param string $check Value to check
939
+ * @param array $list List to check against
940
+ * @return boolean Succcess
941
+ * @access public
942
+ */
943
+ function inList( $check, $list ) {
944
+ return in_array( $check, $list );
945
+ }
946
+
947
+ /**
948
+ * Runs an user-defined validation.
949
+ *
950
+ * @param mixed $check value that will be validated in user-defined methods.
951
+ * @param object $object class that holds validation method
952
+ * @param string $method class method name for validation to run
953
+ * @param array $args arguments to send to method
954
+ * @return mixed user-defined class class method returns
955
+ * @access public
956
+ */
957
+ function userDefined( $check, $object, $method, $args = null ) {
958
+ return call_user_func_array( array(&$object, $method),
959
+ array($check, $args) );
960
+ }
961
+
962
+ function noSpecialChars( $check ) {
963
+ return preg_match( '#[^a-zA-Z0-9\s\_\-]#', $check ) ? false : true;
964
+ }
965
+
966
+ function rewriteSlug( $check ) {
967
+ return preg_match( '#[^a-zA-Z0-9\s\_\-\%]#', $check ) ? false : true;
968
+ }
969
+
970
+ /**
971
+ * Attempts to pass unhandled Validation locales to a class starting with $classPrefix
972
+ * and ending with Validation. For example $classPrefix = 'nl', the class would be
973
+ * `NlValidation`.
974
+ *
975
+ * @param string $method The method to call on the other class.
976
+ * @param mixed $check The value to check or an array of parameters for the method to be called.
977
+ * @param string $classPrefix The prefix for the class to do the validation.
978
+ * @return mixed Return of Passed method, false on failure
979
+ * @access protected
980
+ * */
981
+ function _pass( $method, $check, $classPrefix ) {
982
+ $className = ucwords( $classPrefix ) . 'Validation';
983
+ if ( !class_exists( $className ) ) {
984
+ trigger_error( sprintf( __( 'Could not find %s class, unable to complete validation.',
985
+ true ), $className ), E_USER_WARNING );
986
+ return false;
987
+ }
988
+ if ( !is_callable( array($className, $method) ) ) {
989
+ trigger_error( sprintf( __( 'Method %s does not exist on %s unable to complete validation.',
990
+ true ), $method, $className ),
991
+ E_USER_WARNING );
992
+ return false;
993
+ }
994
+ $check = (array) $check;
995
+ return call_user_func_array( array($className, $method), $check );
996
+ }
997
+
998
+ /**
999
+ * Runs a regular expression match.
1000
+ *
1001
+ * @return boolean Success of match
1002
+ * @access protected
1003
+ */
1004
+ function _check() {
1005
+ $_this = &Wpcf_Cake_Validation::getInstance();
1006
+ if ( preg_match( $_this->regex, $_this->check ) ) {
1007
+ $_this->error[] = false;
1008
+ return true;
1009
+ } else {
1010
+ $_this->error[] = true;
1011
+ return false;
1012
+ }
1013
+ }
1014
+
1015
+ /**
1016
+ * Get the values to use when value sent to validation method is
1017
+ * an array.
1018
+ *
1019
+ * @param array $params Parameters sent to validation method
1020
+ * @return void
1021
+ * @access protected
1022
+ */
1023
+ function _extract( $params ) {
1024
+ $_this = &Wpcf_Cake_Validation::getInstance();
1025
+ extract( $params, EXTR_OVERWRITE );
1026
+
1027
+ if ( isset( $check ) ) {
1028
+ $_this->check = $check;
1029
+ }
1030
+ if ( isset( $regex ) ) {
1031
+ $_this->regex = $regex;
1032
+ }
1033
+ if ( isset( $country ) ) {
1034
+ $_this->country = strtolower( $country );
1035
+ }
1036
+ if ( isset( $deep ) ) {
1037
+ $_this->deep = $deep;
1038
+ }
1039
+ if ( isset( $type ) ) {
1040
+ $_this->type = $type;
1041
+ }
1042
+ }
1043
+
1044
+ /**
1045
+ * Luhn algorithm
1046
+ *
1047
+ * @see http://en.wikipedia.org/wiki/Luhn_algorithm
1048
+ * @return boolean Success
1049
+ * @access protected
1050
+ */
1051
+ function _luhn() {
1052
+ $_this = &Wpcf_Cake_Validation::getInstance();
1053
+ if ( $_this->deep !== true ) {
1054
+ return true;
1055
+ }
1056
+ if ( $_this->check == 0 ) {
1057
+ return false;
1058
+ }
1059
+ $sum = 0;
1060
+ $length = strlen( $_this->check );
1061
+
1062
+ for ( $position = 1 - ($length % 2); $position < $length; $position += 2 ) {
1063
+ $sum += $_this->check[$position];
1064
+ }
1065
+
1066
+ for ( $position = ($length % 2); $position < $length; $position += 2 ) {
1067
+ $number = $_this->check[$position] * 2;
1068
+ $sum += ($number < 10) ? $number : $number - 9;
1069
+ }
1070
+
1071
+ return ($sum % 10 == 0);
1072
+ }
1073
+
1074
+ /*
1075
+ * Lazily popualate the IP address patterns used for validations
1076
+ *
1077
+ * @return void
1078
+ * @access private
1079
+ */
1080
+
1081
+ function __populateIp() {
1082
+ if ( !isset( $this->__pattern['IPv6'] ) ) {
1083
+ $pattern = '((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}';
1084
+ $pattern .= '(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})';
1085
+ $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})';
1086
+ $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}:)';
1087
+ $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}))';
1088
+ $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}';
1089
+ $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|';
1090
+ $pattern .= '((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}';
1091
+ $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2}))';
1092
+ $pattern .= '{3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4})';
1093
+ $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})?)';
1094
+ $pattern .= '|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]';
1095
+ $pattern .= '\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4})';
1096
+ $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})))(%.+)?';
1097
+
1098
+ $this->__pattern['IPv6'] = $pattern;
1099
+ }
1100
+ if ( !isset( $this->__pattern['IPv4'] ) ) {
1101
+ $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])';
1102
+ $this->__pattern['IPv4'] = $pattern;
1103
+ }
1104
+ }
1105
+
1106
+ /**
1107
+ * Reset internal variables for another validation run.
1108
+ *
1109
+ * @return void
1110
+ * @access private
1111
+ */
1112
+ function __reset() {
1113
+ $this->check = null;
1114
+ $this->regex = null;
1115
+ $this->country = null;
1116
+ $this->deep = null;
1117
+ $this->type = null;
1118
+ $this->error = array();
1119
+ $this->errors = array();
1120
+ }
1121
+
1122
+ }
embedded/classes/validation.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Validation class.
4
+ */
5
+
6
+ /**
7
+ * Validation class.
8
+ *
9
+ * @since Types 1.1.5
10
+ * @package Types
11
+ * @subpackage Validation
12
+ * @version 0.1.2
13
+ * @category core
14
+ * @author srdjan <srdjan@icanlocalize.com>
15
+ */
16
+ class WPCF_Validation
17
+ {
18
+
19
+ function __construct() {
20
+ add_filter( 'wpcf_field', array($this, 'filter_field') );
21
+ }
22
+
23
+ /**
24
+ * Filters each field.
25
+ *
26
+ * Uses 'wpcf_field' hook. Filters field settings.
27
+ *
28
+ * @param type $field
29
+ * @return int
30
+ */
31
+ function filter_field( $field ) {
32
+ if ( $field['type'] == 'date' ) {
33
+ if ( !fields_date_timestamp_neg_supported() ) {
34
+ if ( !isset( $field['data']['validate'] )
35
+ || !is_array( $field['data']['validate'] ) ) {
36
+ $field['data']['validate'] = array();
37
+ }
38
+ $field['data']['validate']['negativeTimestamp'] = array(
39
+ 'active' => 1,
40
+ 'value' => 'true',
41
+ 'message' => wpcf_admin_validation_messages( 'negativeTimestamp' ),
42
+ );
43
+ }
44
+ }
45
+ return $field;
46
+ }
47
+
48
+ /**
49
+ * Returns formatted JSON validation data.
50
+ *
51
+ * @param type $selector Can be CSS class or element ID
52
+ * @return string
53
+ */
54
+ static function renderJsonData( $selector = '.wpcf-form-validate' ) {
55
+
56
+ // Get collected validation rules
57
+ $elements = wpcf_form_add_js_validation( 'get' );
58
+
59
+ // Not collected!
60
+ if ( empty( $elements ) ) {
61
+ return '';
62
+ }
63
+
64
+ $json = array('selector' => $selector, 'elements' => array());
65
+
66
+ foreach ( $elements as $id => $element ) {
67
+ // Basic check or skip read-only
68
+ if ( empty( $element['#validate'] ) || isset( $element['#attributes']['readonly'] ) ) {
69
+ continue;
70
+ }
71
+
72
+ $json['elements'][$id] = array('id' => $id);
73
+
74
+ // Set selectors
75
+ if ( in_array( $element['#type'], array('radios') ) ) {
76
+ $json['elements'][$id]['selector'] = "input[name=\"{$element['#name']}\"]";
77
+ } else {
78
+ $json['elements'][$id]['selector'] = "#{$id}";
79
+ }
80
+
81
+ foreach ( $element['#validate'] as $method => $args ) {
82
+ $args['value'] = !isset( $args['value'] ) ? 'true' : $args['value'];
83
+ if ( empty( $args['message'] ) ) {
84
+ $args['message'] = wpcf_admin_validation_messages( $method,
85
+ $args['value'] );
86
+ }
87
+ //Check if wordpress date format is d/m/Y and use ITA validation
88
+ if ( $method == 'date' && isset( $element['wpcf-type'] ) && $element['wpcf-type'] == 'date' && get_option( 'date_format' ) == 'd/m/Y' ) {
89
+ $method = 'dateITA:true';
90
+ }
91
+ // Set JSON data
92
+ $json['elements'][$id]['rules'][] = array(
93
+ 'method' => $method,
94
+ 'value' => $args['value'],
95
+ 'message' => $args['message'],
96
+ );
97
+ }
98
+ }
99
+ ob_start();
100
+
101
+ ?>
102
+
103
+ <script type="text/javascript">
104
+ //<![CDATA[
105
+ types.validation.push(<?php echo json_encode( $json ); ?>);
106
+ <?php if ( defined ('DOING_AJAX') ): ?>
107
+ jQuery(document).ready(function($) {
108
+ typesValidation.setRules();
109
+ });
110
+ <?php endif; ?>
111
+ /* ]]> */
112
+ </script>
113
+
114
+ <?php
115
+ $output = ob_get_contents();
116
+ ob_get_clean();
117
+
118
+ wp_enqueue_script( 'types-validation' );
119
+
120
+ return $output;
121
+ }
122
+
123
+ }
embedded/classes/wpviews.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WPCF_WPViews
4
+ {
5
+
6
+ /**
7
+ * Init called from WPCF_Loader.
8
+ */
9
+ public static function init() {
10
+ add_action( 'views_edit_screen', array('WPCF_WPViews', 'editScreenInit') );
11
+ add_action( 'layouts_edit_screen', array('WPCF_WPViews', 'editScreenInit') );
12
+ add_action( 'views_ct_inline_editor',
13
+ array('WPCF_WPViews', 'addEditorDropdownFilter') );
14
+ }
15
+
16
+ /**
17
+ * Actions for Views edit screens.
18
+ */
19
+ public static function editScreenInit() {
20
+ wp_enqueue_script( 'types' );
21
+ wp_enqueue_script( 'types-wp-views' );
22
+ wp_enqueue_script( 'toolset-colorbox' );
23
+ wp_enqueue_style( 'toolset-colorbox' );
24
+ self::addEditorDropdownFilter();
25
+ }
26
+
27
+ /**
28
+ * Adds filtering editor dropdown items.
29
+ */
30
+ public static function addEditorDropdownFilter() {
31
+ add_filter( 'editor_addon_menus_wpv-views',
32
+ array('WPCF_WPViews', 'editorDropdownFilter') );
33
+ add_filter( 'editor_addon_menus_wpv-views',
34
+ 'wpcf_admin_post_add_usermeta_to_editor_js' );
35
+ }
36
+
37
+ /**
38
+ * Adds items to view dropdown.
39
+ *
40
+ * @param type $items
41
+ * @return type
42
+ */
43
+ public static function editorDropdownFilter( $items ) {
44
+ $post = wpcf_admin_get_edited_post();
45
+ if ( empty( $post ) ) {
46
+ $post = (object) array('ID' => -1);
47
+ }
48
+ $groups = wpcf_admin_fields_get_groups( 'wp-types-group', 'group_active' );
49
+ $all_post_types = implode( ' ',
50
+ get_post_types( array('public' => true) ) );
51
+ $add = array();
52
+ if ( !empty( $groups ) ) {
53
+ // $group_id is blank therefore not equal to $group['id']
54
+ // use array for item key and CSS class
55
+ $item_styles = array();
56
+
57
+ foreach ( $groups as $group ) {
58
+ $fields = wpcf_admin_fields_get_fields_by_group( $group['id'],
59
+ 'slug', true, false, true );
60
+ if ( !empty( $fields ) ) {
61
+ // code from Types used here without breaking the flow
62
+ // get post types list for every group or apply all
63
+ $post_types = get_post_meta( $group['id'],
64
+ '_wp_types_group_post_types', true );
65
+ if ( $post_types == 'all' ) {
66
+ $post_types = $all_post_types;
67
+ }
68
+ $post_types = trim( str_replace( ',', ' ', $post_types ) );
69
+ $item_styles[$group['name']] = $post_types;
70
+
71
+ foreach ( $fields as $field ) {
72
+ $callback = 'wpcfFieldsEditorCallback(\'' . $field['id']
73
+ . '\', \'postmeta\', ' . $post->ID . ')';
74
+ $add[$group['name']][stripslashes( $field['name'] )] = array(stripslashes( $field['name'] ), trim( wpcf_fields_get_shortcode( $field ),
75
+ '[]' ), $group['name'], $callback);
76
+ // TODO Remove - it's not post edit screen (meta box JS and CSS)
77
+ WPCF_Fields::enqueueScript( $field['type'] );
78
+ WPCF_Fields::enqueueStyle( $field['type'] );
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ $search_key = '';
85
+
86
+ // Iterate all items to be displayed in the "V" menu
87
+ foreach ( $items as $key => $item ) {
88
+ if ( $key == __( 'Basic', 'wpv-views' ) ) {
89
+ $search_key = 'found';
90
+ continue;
91
+ }
92
+ if ( $search_key == 'found' ) {
93
+ $search_key = $key;
94
+ }
95
+
96
+ if ( $key == __( 'Field', 'wpv-views' ) && isset( $item[trim( wpcf_types_get_meta_prefix(),
97
+ '-' )] ) ) {
98
+ unset( $items[$key][trim( wpcf_types_get_meta_prefix(), '-' )] );
99
+ }
100
+ }
101
+ if ( empty( $search_key ) || $search_key == 'found' ) {
102
+ $search_key = count( $items );
103
+ }
104
+
105
+ $insert_position = array_search( $search_key, array_keys( $items ) );
106
+ $part_one = array_slice( $items, 0, $insert_position );
107
+ $part_two = array_slice( $items, $insert_position );
108
+ $items = $part_one + $add + $part_two;
109
+
110
+ // apply CSS styles to each item based on post types
111
+ foreach ( $items as $key => $value ) {
112
+ if ( isset( $item_styles[$key] ) ) {
113
+ $items[$key]['css'] = $item_styles[$key];
114
+ } else {
115
+ $items[$key]['css'] = $all_post_types;
116
+ }
117
+ }
118
+
119
+ return $items;
120
+ }
121
+
122
+ }
embedded/common/WPML/wpml-string-shortcode.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /** provide default implementation of [wpml-string] shortcode for when
3
+ * wpml plugin is not active.
4
+ */
5
+
6
+ if (!isset($wpml_string_sub_active)) {
7
+
8
+ add_action('init', 'stub_wpml_add_shortcode', 100);
9
+
10
+ $wpml_string_sub_active = true;
11
+
12
+ if( !function_exists('stub_wpml_add_shortcode') )
13
+ {
14
+ function stub_wpml_add_shortcode() {
15
+ global $WPML_String_Translation;
16
+
17
+ if (!isset($WPML_String_Translation)) {
18
+ // WPML string translation is not active
19
+ // Add our own do nothing shortcode
20
+
21
+ add_shortcode('wpml-string', 'stub_wpml_string_shortcode');
22
+
23
+ }
24
+ }
25
+ }
26
+
27
+ if( !function_exists('stub_wpml_string_shortcode') )
28
+ {
29
+ function stub_wpml_string_shortcode($atts, $value) {
30
+ // return un-processed.
31
+ return do_shortcode($value);
32
+ }
33
+ }
34
+ }
embedded/common/Zip.php ADDED
@@ -0,0 +1,861 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class to create and manage a Zip file.
4
+ *
5
+ * Initially inspired by CreateZipFile by Rochak Chauhan www.rochakchauhan.com (http://www.phpclasses.org/browse/package/2322.html)
6
+ * and
7
+ * http://www.pkware.com/documents/casestudies/APPNOTE.TXT Zip file specification.
8
+ *
9
+ * License: GNU LGPL 2.1.
10
+ *
11
+ * @author A. Grandt <php@grandt.com>
12
+ * @copyright 2009-2014 A. Grandt
13
+ * @license GNU LGPL 2.1
14
+ * @link http://www.phpclasses.org/package/6110
15
+ * @link https://github.com/Grandt/PHPZip
16
+ * @version 1.62
17
+ */
18
+ class Zip {
19
+ const VERSION = 1.62;
20
+
21
+ const ZIP_LOCAL_FILE_HEADER = "\x50\x4b\x03\x04"; // Local file header signature
22
+ const ZIP_CENTRAL_FILE_HEADER = "\x50\x4b\x01\x02"; // Central file header signature
23
+ const ZIP_END_OF_CENTRAL_DIRECTORY = "\x50\x4b\x05\x06\x00\x00\x00\x00"; //end of Central directory record
24
+
25
+ const EXT_FILE_ATTR_DIR = 010173200020; // Permission 755 drwxr-xr-x = (((S_IFDIR | 0755) << 16) | S_DOS_D);
26
+ const EXT_FILE_ATTR_FILE = 020151000040; // Permission 644 -rw-r--r-- = (((S_IFREG | 0644) << 16) | S_DOS_A);
27
+
28
+ const ATTR_VERSION_TO_EXTRACT = "\x14\x00"; // Version needed to extract
29
+ const ATTR_MADE_BY_VERSION = "\x1E\x03"; // Made By Version
30
+
31
+ // UID 1000, GID 0
32
+ const EXTRA_FIELD_NEW_UNIX_GUID = "\x75\x78\x0B\x00\x01\x04\xE8\x03\x00\x00\x04\x00\x00\x00\x00";
33
+
34
+ // Unix file types
35
+ const S_IFIFO = 0010000; // named pipe (fifo)
36
+ const S_IFCHR = 0020000; // character special
37
+ const S_IFDIR = 0040000; // directory
38
+ const S_IFBLK = 0060000; // block special
39
+ const S_IFREG = 0100000; // regular
40
+ const S_IFLNK = 0120000; // symbolic link
41
+ const S_IFSOCK = 0140000; // socket
42
+
43
+ // setuid/setgid/sticky bits, the same as for chmod:
44
+
45
+ const S_ISUID = 0004000; // set user id on execution
46
+ const S_ISGID = 0002000; // set group id on execution
47
+ const S_ISTXT = 0001000; // sticky bit
48
+
49
+ // And of course, the other 12 bits are for the permissions, the same as for chmod:
50
+ // When addding these up, you can also just write the permissions as a simgle octal number
51
+ // ie. 0755. The leading 0 specifies octal notation.
52
+ const S_IRWXU = 0000700; // RWX mask for owner
53
+ const S_IRUSR = 0000400; // R for owner
54
+ const S_IWUSR = 0000200; // W for owner
55
+ const S_IXUSR = 0000100; // X for owner
56
+ const S_IRWXG = 0000070; // RWX mask for group
57
+ const S_IRGRP = 0000040; // R for group
58
+ const S_IWGRP = 0000020; // W for group
59
+ const S_IXGRP = 0000010; // X for group
60
+ const S_IRWXO = 0000007; // RWX mask for other
61
+ const S_IROTH = 0000004; // R for other
62
+ const S_IWOTH = 0000002; // W for other
63
+ const S_IXOTH = 0000001; // X for other
64
+ const S_ISVTX = 0001000; // save swapped text even after use
65
+
66
+ // Filetype, sticky and permissions are added up, and shifted 16 bits left BEFORE adding the DOS flags.
67
+
68
+ // DOS file type flags, we really only use the S_DOS_D flag.
69
+
70
+ const S_DOS_A = 0000040; // DOS flag for Archive
71
+ const S_DOS_D = 0000020; // DOS flag for Directory
72
+ const S_DOS_V = 0000010; // DOS flag for Volume
73
+ const S_DOS_S = 0000004; // DOS flag for System
74
+ const S_DOS_H = 0000002; // DOS flag for Hidden
75
+ const S_DOS_R = 0000001; // DOS flag for Read Only
76
+
77
+ private $zipMemoryThreshold = 1048576; // Autocreate tempfile if the zip data exceeds 1048576 bytes (1 MB)
78
+
79
+ private $zipData = NULL;
80
+ private $zipFile = NULL;
81
+ private $zipComment = NULL;
82
+ private $cdRec = array(); // central directory
83
+ private $offset = 0;
84
+ private $isFinalized = FALSE;
85
+ private $addExtraField = TRUE;
86
+
87
+ private $streamChunkSize = 65536;
88
+ private $streamFilePath = NULL;
89
+ private $streamTimestamp = NULL;
90
+ private $streamFileComment = NULL;
91
+ private $streamFile = NULL;
92
+ private $streamData = NULL;
93
+ private $streamFileLength = 0;
94
+ private $streamExtFileAttr = null;
95
+ /**
96
+ * A custom temporary folder, or a callable that returns a custom temporary file.
97
+ * @var string|callable
98
+ */
99
+ public static $temp = null;
100
+
101
+ /**
102
+ * Constructor.
103
+ *
104
+ * @param boolean $useZipFile Write temp zip data to tempFile? Default FALSE
105
+ */
106
+ function __construct($useZipFile = FALSE) {
107
+ if ($useZipFile) {
108
+ $this->zipFile = tmpfile();
109
+ } else {
110
+ $this->zipData = "";
111
+ }
112
+ }
113
+
114
+ function __destruct() {
115
+ if (is_resource($this->zipFile)) {
116
+ fclose($this->zipFile);
117
+ }
118
+ $this->zipData = NULL;
119
+ }
120
+
121
+ /**
122
+ * Extra fields on the Zip directory records are Unix time codes needed for compatibility on the default Mac zip archive tool.
123
+ * These are enabled as default, as they do no harm elsewhere and only add 26 bytes per file added.
124
+ *
125
+ * @param bool $setExtraField TRUE (default) will enable adding of extra fields, anything else will disable it.
126
+ */
127
+ function setExtraField($setExtraField = TRUE) {
128
+ $this->addExtraField = ($setExtraField === TRUE);
129
+ }
130
+
131
+ /**
132
+ * Set Zip archive comment.
133
+ *
134
+ * @param string $newComment New comment. NULL to clear.
135
+ * @return bool $success
136
+ */
137
+ public function setComment($newComment = NULL) {
138
+ if ($this->isFinalized) {
139
+ return FALSE;
140
+ }
141
+ $this->zipComment = $newComment;
142
+
143
+ return TRUE;
144
+ }
145
+
146
+ /**
147
+ * Set zip file to write zip data to.
148
+ * This will cause all present and future data written to this class to be written to this file.
149
+ * This can be used at any time, even after the Zip Archive have been finalized. Any previous file will be closed.
150
+ * Warning: If the given file already exists, it will be overwritten.
151
+ *
152
+ * @param string $fileName
153
+ * @return bool $success
154
+ */
155
+ public function setZipFile($fileName) {
156
+ if (is_file($fileName)) {
157
+ unlink($fileName);
158
+ }
159
+ $fd=fopen($fileName, "x+b");
160
+ if (is_resource($this->zipFile)) {
161
+ rewind($this->zipFile);
162
+ while (!feof($this->zipFile)) {
163
+ fwrite($fd, fread($this->zipFile, $this->streamChunkSize));
164
+ }
165
+
166
+ fclose($this->zipFile);
167
+ } else {
168
+ fwrite($fd, $this->zipData);
169
+ $this->zipData = NULL;
170
+ }
171
+ $this->zipFile = $fd;
172
+
173
+ return TRUE;
174
+ }
175
+
176
+ /**
177
+ * Add an empty directory entry to the zip archive.
178
+ * Basically this is only used if an empty directory is added.
179
+ *
180
+ * @param string $directoryPath Directory Path and name to be added to the archive.
181
+ * @param int $timestamp (Optional) Timestamp for the added directory, if omitted or set to 0, the current time will be used.
182
+ * @param string $fileComment (Optional) Comment to be added to the archive for this directory. To use fileComment, timestamp must be given.
183
+ * @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
184
+ * @return bool $success
185
+ */
186
+ public function addDirectory($directoryPath, $timestamp = 0, $fileComment = NULL, $extFileAttr = self::EXT_FILE_ATTR_DIR) {
187
+ if ($this->isFinalized) {
188
+ return FALSE;
189
+ }
190
+ $directoryPath = str_replace("\\", "/", $directoryPath);
191
+ $directoryPath = rtrim($directoryPath, "/");
192
+
193
+ if (strlen($directoryPath) > 0) {
194
+ $this->buildZipEntry($directoryPath.'/', $fileComment, "\x00\x00", "\x00\x00", $timestamp, "\x00\x00\x00\x00", 0, 0, $extFileAttr);
195
+ return TRUE;
196
+ }
197
+ return FALSE;
198
+ }
199
+
200
+ /**
201
+ * Add a file to the archive at the specified location and file name.
202
+ *
203
+ * @param string $data File data.
204
+ * @param string $filePath Filepath and name to be used in the archive.
205
+ * @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
206
+ * @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
207
+ * @param bool $compress (Optional) Compress file, if set to FALSE the file will only be stored. Default TRUE.
208
+ * @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
209
+ * @return bool $success
210
+ */
211
+ public function addFile($data, $filePath, $timestamp = 0, $fileComment = NULL, $compress = TRUE, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
212
+ if ($this->isFinalized) {
213
+ return FALSE;
214
+ }
215
+
216
+ if (is_resource($data) && get_resource_type($data) == "stream") {
217
+ $this->addLargeFile($data, $filePath, $timestamp, $fileComment, $extFileAttr);
218
+ return FALSE;
219
+ }
220
+
221
+ $gzData = "";
222
+ $gzType = "\x08\x00"; // Compression type 8 = deflate
223
+ $gpFlags = "\x00\x00"; // General Purpose bit flags for compression type 8 it is: 0=Normal, 1=Maximum, 2=Fast, 3=super fast compression.
224
+ $dataLength = strlen($data);
225
+ $fileCRC32 = pack("V", crc32($data));
226
+
227
+ if ($compress) {
228
+ $gzTmp = gzcompress($data);
229
+ $gzData = substr(substr($gzTmp, 0, strlen($gzTmp) - 4), 2); // gzcompress adds a 2 byte header and 4 byte CRC we can't use.
230
+ // The 2 byte header does contain useful data, though in this case the 2 parameters we'd be interrested in will always be 8 for compression type, and 2 for General purpose flag.
231
+ $gzLength = strlen($gzData);
232
+ } else {
233
+ $gzLength = $dataLength;
234
+ }
235
+
236
+ if ($gzLength >= $dataLength) {
237
+ $gzLength = $dataLength;
238
+ $gzData = $data;
239
+ $gzType = "\x00\x00"; // Compression type 0 = stored
240
+ $gpFlags = "\x00\x00"; // Compression type 0 = stored
241
+ }
242
+
243
+ if (!is_resource($this->zipFile) && ($this->offset + $gzLength) > $this->zipMemoryThreshold) {
244
+ $this->zipflush();
245
+ }
246
+
247
+ $this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr);
248
+
249
+ $this->zipwrite($gzData);
250
+
251
+ return TRUE;
252
+ }
253
+
254
+ /**
255
+ * Add the content to a directory.
256
+ *
257
+ * @author Adam Schmalhofer <Adam.Schmalhofer@gmx.de>
258
+ * @author A. Grandt
259
+ *
260
+ * @param string $realPath Path on the file system.
261
+ * @param string $zipPath Filepath and name to be used in the archive.
262
+ * @param bool $recursive Add content recursively, default is TRUE.
263
+ * @param bool $followSymlinks Follow and add symbolic links, if they are accessible, default is TRUE.
264
+ * @param array &$addedFiles Reference to the added files, this is used to prevent duplicates, efault is an empty array.
265
+ * If you start the function by parsing an array, the array will be populated with the realPath
266
+ * and zipPath kay/value pairs added to the archive by the function.
267
+ * @param bool $overrideFilePermissions Force the use of the file/dir permissions set in the $extDirAttr
268
+ * and $extFileAttr parameters.
269
+ * @param int $extDirAttr Permissions for directories.
270
+ * @param int $extFileAttr Permissions for files.
271
+ */
272
+ public function addDirectoryContent($realPath, $zipPath, $recursive = TRUE, $followSymlinks = TRUE, &$addedFiles = array(),
273
+ $overrideFilePermissions = FALSE, $extDirAttr = self::EXT_FILE_ATTR_DIR, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
274
+ if (file_exists($realPath) && !isset($addedFiles[realpath($realPath)])) {
275
+ if (is_dir($realPath)) {
276
+ if ($overrideFilePermissions) {
277
+ $this->addDirectory($zipPath, 0, null, $extDirAttr);
278
+ } else {
279
+ $this->addDirectory($zipPath, 0, null, self::getFileExtAttr($realPath));
280
+ }
281
+ }
282
+
283
+ $addedFiles[realpath($realPath)] = $zipPath;
284
+
285
+ $iter = new DirectoryIterator($realPath);
286
+ foreach ($iter as $file) {
287
+ if ($file->isDot()) {
288
+ continue;
289
+ }
290
+ $newRealPath = $file->getPathname();
291
+ $newZipPath = self::pathJoin($zipPath, $file->getFilename());
292
+
293
+ if (file_exists($newRealPath) && ($followSymlinks === TRUE || !is_link($newRealPath))) {
294
+ if ($file->isFile()) {
295
+ $addedFiles[realpath($newRealPath)] = $newZipPath;
296
+ if ($overrideFilePermissions) {
297
+ $this->addLargeFile($newRealPath, $newZipPath, 0, null, $extFileAttr);
298
+ } else {
299
+ $this->addLargeFile($newRealPath, $newZipPath, 0, null, self::getFileExtAttr($newRealPath));
300
+ }
301
+ } else if ($recursive === TRUE) {
302
+ $this->addDirectoryContent($newRealPath, $newZipPath, $recursive, $followSymlinks, $addedFiles, $overrideFilePermissions, $extDirAttr, $extFileAttr);
303
+ } else {
304
+ if ($overrideFilePermissions) {
305
+ $this->addDirectory($zipPath, 0, null, $extDirAttr);
306
+ } else {
307
+ $this->addDirectory($zipPath, 0, null, self::getFileExtAttr($newRealPath));
308
+ }
309
+ }
310
+ }
311
+ }
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Add a file to the archive at the specified location and file name.
317
+ *
318
+ * @param string $dataFile File name/path.
319
+ * @param string $filePath Filepath and name to be used in the archive.
320
+ * @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
321
+ * @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
322
+ * @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
323
+ * @return bool $success
324
+ */
325
+ public function addLargeFile($dataFile, $filePath, $timestamp = 0, $fileComment = NULL, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
326
+ if ($this->isFinalized) {
327
+ return FALSE;
328
+ }
329
+
330
+ if (is_string($dataFile) && is_file($dataFile)) {
331
+ $this->processFile($dataFile, $filePath, $timestamp, $fileComment, $extFileAttr);
332
+ } else if (is_resource($dataFile) && get_resource_type($dataFile) == "stream") {
333
+ $fh = $dataFile;
334
+ $this->openStream($filePath, $timestamp, $fileComment, $extFileAttr);
335
+
336
+ while (!feof($fh)) {
337
+ $this->addStreamData(fread($fh, $this->streamChunkSize));
338
+ }
339
+ $this->closeStream($this->addExtraField);
340
+ }
341
+ return TRUE;
342
+ }
343
+
344
+ /**
345
+ * Create a stream to be used for large entries.
346
+ *
347
+ * @param string $filePath Filepath and name to be used in the archive.
348
+ * @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
349
+ * @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
350
+ * @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
351
+ * @throws Exception Throws an exception in case of errors
352
+ * @return bool $success
353
+ */
354
+ public function openStream($filePath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
355
+ if (!function_exists('sys_get_temp_dir')) {
356
+ throw new Exception("Zip " . self::VERSION . " requires PHP version 5.2.1 or above if large files are used.");
357
+ }
358
+
359
+ if ($this->isFinalized) {
360
+ return FALSE;
361
+ }
362
+
363
+ $this->zipflush();
364
+
365
+ if (strlen($this->streamFilePath) > 0) {
366
+ $this->closeStream();
367
+ }
368
+
369
+ $this->streamFile = self::getTemporaryFile();
370
+ $this->streamData = fopen($this->streamFile, "wb");
371
+ $this->streamFilePath = $filePath;
372
+ $this->streamTimestamp = $timestamp;
373
+ $this->streamFileComment = $fileComment;
374
+ $this->streamFileLength = 0;
375
+ $this->streamExtFileAttr = $extFileAttr;
376
+
377
+ return TRUE;
378
+ }
379
+
380
+ /**
381
+ * Add data to the open stream.
382
+ *
383
+ * @param string $data
384
+ * @throws Exception Throws an exception in case of errors
385
+ * @return mixed length in bytes added or FALSE if the archive is finalized or there are no open stream.
386
+ */
387
+ public function addStreamData($data) {
388
+ if ($this->isFinalized || strlen($this->streamFilePath) == 0) {
389
+ return FALSE;
390
+ }
391
+
392
+ $length = fwrite($this->streamData, $data, strlen($data));
393
+ if ($length != strlen($data)) {
394
+ throw new Exception("File IO: Error writing; Length mismatch: Expected " . strlen($data) . " bytes, wrote " . ($length === FALSE ? "NONE!" : $length));
395
+ }
396
+ $this->streamFileLength += $length;
397
+
398
+ return $length;
399
+ }
400
+
401
+ /**
402
+ * Close the current stream.
403
+ *
404
+ * @return bool $success
405
+ */
406
+ public function closeStream() {
407
+ if ($this->isFinalized || strlen($this->streamFilePath) == 0) {
408
+ return FALSE;
409
+ }
410
+
411
+ fflush($this->streamData);
412
+ fclose($this->streamData);
413
+
414
+ $this->processFile($this->streamFile, $this->streamFilePath, $this->streamTimestamp, $this->streamFileComment, $this->streamExtFileAttr);
415
+
416
+ $this->streamData = null;
417
+ $this->streamFilePath = null;
418
+ $this->streamTimestamp = null;
419
+ $this->streamFileComment = null;
420
+ $this->streamFileLength = 0;
421
+ $this->streamExtFileAttr = null;
422
+
423
+ // Windows is a little slow at times, so a millisecond later, we can unlink this.
424
+ unlink($this->streamFile);
425
+
426
+ $this->streamFile = null;
427
+
428
+ return TRUE;
429
+ }
430
+
431
+ private function processFile($dataFile, $filePath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
432
+ if ($this->isFinalized) {
433
+ return FALSE;
434
+ }
435
+
436
+ $tempzip = self::getTemporaryFile();
437
+
438
+ $zip = new ZipArchive;
439
+ if ($zip->open($tempzip) === TRUE) {
440
+ $zip->addFile($dataFile, 'file');
441
+ $zip->close();
442
+ }
443
+
444
+ $file_handle = fopen($tempzip, "rb");
445
+ $stats = fstat($file_handle);
446
+ $eof = $stats['size']-72;
447
+
448
+ fseek($file_handle, 6);
449
+
450
+ $gpFlags = fread($file_handle, 2);
451
+ $gzType = fread($file_handle, 2);
452
+ fread($file_handle, 4);
453
+ $fileCRC32 = fread($file_handle, 4);
454
+ $v = unpack("Vval", fread($file_handle, 4));
455
+ $gzLength = $v['val'];
456
+ $v = unpack("Vval", fread($file_handle, 4));
457
+ $dataLength = $v['val'];
458
+
459
+ $this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr);
460
+
461
+ fseek($file_handle, 34);
462
+ $pos = 34;
463
+
464
+ while (!feof($file_handle) && $pos < $eof) {
465
+ $datalen = $this->streamChunkSize;
466
+ if ($pos + $this->streamChunkSize > $eof) {
467
+ $datalen = $eof-$pos;
468
+ }
469
+ $data = fread($file_handle, $datalen);
470
+ $pos += $datalen;
471
+
472
+ $this->zipwrite($data);
473
+ }
474
+
475
+ fclose($file_handle);
476
+
477
+ unlink($tempzip);
478
+ }
479
+
480
+ /**
481
+ * Close the archive.
482
+ * A closed archive can no longer have new files added to it.
483
+ *
484
+ * @return bool $success
485
+ */
486
+ public function finalize() {
487
+ if (!$this->isFinalized) {
488
+ if (strlen($this->streamFilePath) > 0) {
489
+ $this->closeStream();
490
+ }
491
+ $cd = implode("", $this->cdRec);
492
+
493
+ $cdRecSize = pack("v", sizeof($this->cdRec));
494
+ $cdRec = $cd . self::ZIP_END_OF_CENTRAL_DIRECTORY
495
+ . $cdRecSize . $cdRecSize
496
+ . pack("VV", strlen($cd), $this->offset);
497
+ if (!empty($this->zipComment)) {
498
+ $cdRec .= pack("v", strlen($this->zipComment)) . $this->zipComment;
499
+ } else {
500
+ $cdRec .= "\x00\x00";
501
+ }
502
+
503
+ $this->zipwrite($cdRec);
504
+
505
+ $this->isFinalized = TRUE;
506
+ $this->cdRec = NULL;
507
+
508
+ return TRUE;
509
+ }
510
+ return FALSE;
511
+ }
512
+
513
+ /**
514
+ * Get the handle ressource for the archive zip file.
515
+ * If the zip haven't been finalized yet, this will cause it to become finalized
516
+ *
517
+ * @return zip file handle
518
+ */
519
+ public function getZipFile() {
520
+ if (!$this->isFinalized) {
521
+ $this->finalize();
522
+ }
523
+
524
+ $this->zipflush();
525
+
526
+ rewind($this->zipFile);
527
+
528
+ return $this->zipFile;
529
+ }
530
+
531
+ /**
532
+ * Get the zip file contents
533
+ * If the zip haven't been finalized yet, this will cause it to become finalized
534
+ *
535
+ * @return zip data
536
+ */
537
+ public function getZipData() {
538
+ if (!$this->isFinalized) {
539
+ $this->finalize();
540
+ }
541
+ if (!is_resource($this->zipFile)) {
542
+ return $this->zipData;
543
+ } else {
544
+ rewind($this->zipFile);
545
+ $filestat = fstat($this->zipFile);
546
+ return fread($this->zipFile, $filestat['size']);
547
+ }
548
+ }
549
+
550
+ /**
551
+ * Send the archive as a zip download
552
+ *
553
+ * @param String $fileName The name of the Zip archive, in ISO-8859-1 (or ASCII) encoding, ie. "archive.zip". Optional, defaults to NULL, which means that no ISO-8859-1 encoded file name will be specified.
554
+ * @param String $contentType Content mime type. Optional, defaults to "application/zip".
555
+ * @param String $utf8FileName The name of the Zip archive, in UTF-8 encoding. Optional, defaults to NULL, which means that no UTF-8 encoded file name will be specified.
556
+ * @param bool $inline Use Content-Disposition with "inline" instead of "attached". Optional, defaults to FALSE.
557
+ * @throws Exception Throws an exception in case of errors
558
+ * @return bool Always returns true (for backward compatibility).
559
+ */
560
+ function sendZip($fileName = null, $contentType = "application/zip", $utf8FileName = null, $inline = false) {
561
+ if (!$this->isFinalized) {
562
+ $this->finalize();
563
+ }
564
+ $headerFile = null;
565
+ $headerLine = null;
566
+ if(headers_sent($headerFile, $headerLine)) {
567
+ throw new Exception("Unable to send file '$fileName'. Headers have already been sent from '$headerFile' in line $headerLine");
568
+ }
569
+ if(ob_get_contents() !== false && strlen(ob_get_contents())) {
570
+ throw new Exception("Unable to send file '$fileName'. Output buffer contains the following text (typically warnings or errors):\n" . ob_get_contents());
571
+ }
572
+ if(@ini_get('zlib.output_compression')) {
573
+ @ini_set('zlib.output_compression', 'Off');
574
+ }
575
+ header("Pragma: public");
576
+ header("Last-Modified: " . @gmdate("D, d M Y H:i:s T"));
577
+ header("Expires: 0");
578
+ header("Accept-Ranges: bytes");
579
+ header("Connection: close");
580
+ header("Content-Type: " . $contentType);
581
+ $cd = "Content-Disposition: ";
582
+ if ($inline) {
583
+ $cd .= "inline";
584
+ } else {
585
+ $cd .= "attached";
586
+ }
587
+ if ($fileName) {
588
+ $cd .= '; filename="' . $fileName . '"';
589
+ }
590
+ if ($utf8FileName) {
591
+ $cd .= "; filename*=UTF-8''" . rawurlencode($utf8FileName);
592
+ }
593
+ header($cd);
594
+ header("Content-Length: ". $this->getArchiveSize());
595
+ if (!is_resource($this->zipFile)) {
596
+ echo $this->zipData;
597
+ } else {
598
+ rewind($this->zipFile);
599
+ while (!feof($this->zipFile)) {
600
+ echo fread($this->zipFile, $this->streamChunkSize);
601
+ }
602
+ }
603
+ return true;
604
+ }
605
+
606
+ /**
607
+ * Return the current size of the archive
608
+ *
609
+ * @return $size Size of the archive
610
+ */
611
+ public function getArchiveSize() {
612
+ if (!is_resource($this->zipFile)) {
613
+ return strlen($this->zipData);
614
+ }
615
+ $filestat = fstat($this->zipFile);
616
+
617
+ return $filestat['size'];
618
+ }
619
+
620
+ /**
621
+ * Calculate the 2 byte dostime used in the zip entries.
622
+ *
623
+ * @param int $timestamp
624
+ * @return 2-byte encoded DOS Date
625
+ */
626
+ private function getDosTime($timestamp = 0) {
627
+ $timestamp = (int)$timestamp;
628
+ $oldTZ = @date_default_timezone_get();
629
+ date_default_timezone_set('UTC');
630
+ $date = ($timestamp == 0 ? getdate() : getdate($timestamp));
631
+ date_default_timezone_set($oldTZ);
632
+ if ($date["year"] >= 1980) {
633
+ return pack("V", (($date["mday"] + ($date["mon"] << 5) + (($date["year"]-1980) << 9)) << 16) |
634
+ (($date["seconds"] >> 1) + ($date["minutes"] << 5) + ($date["hours"] << 11)));
635
+ }
636
+ return "\x00\x00\x00\x00";
637
+ }
638
+
639
+ /**
640
+ * Build the Zip file structures
641
+ *
642
+ * @param string $filePath
643
+ * @param string $fileComment
644
+ * @param string $gpFlags
645
+ * @param string $gzType
646
+ * @param int $timestamp
647
+ * @param string $fileCRC32
648
+ * @param int $gzLength
649
+ * @param int $dataLength
650
+ * @param int $extFileAttr Use self::EXT_FILE_ATTR_FILE for files, self::EXT_FILE_ATTR_DIR for Directories.
651
+ */
652
+ private function buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr) {
653
+ $filePath = str_replace("\\", "/", $filePath);
654
+ $fileCommentLength = (empty($fileComment) ? 0 : strlen($fileComment));
655
+ $timestamp = (int)$timestamp;
656
+ $timestamp = ($timestamp == 0 ? time() : $timestamp);
657
+
658
+ $dosTime = $this->getDosTime($timestamp);
659
+ $tsPack = pack("V", $timestamp);
660
+
661
+ if (!isset($gpFlags) || strlen($gpFlags) != 2) {
662
+ $gpFlags = "\x00\x00";
663
+ }
664
+
665
+ $isFileUTF8 = mb_check_encoding($filePath, "UTF-8") && !mb_check_encoding($filePath, "ASCII");
666
+ $isCommentUTF8 = !empty($fileComment) && mb_check_encoding($fileComment, "UTF-8") && !mb_check_encoding($fileComment, "ASCII");
667
+
668
+ $localExtraField = "";
669
+ $centralExtraField = "";
670
+
671
+ if ($this->addExtraField) {
672
+ $localExtraField .= "\x55\x54\x09\x00\x03" . $tsPack . $tsPack . Zip::EXTRA_FIELD_NEW_UNIX_GUID;
673
+ $centralExtraField .= "\x55\x54\x05\x00\x03" . $tsPack . Zip::EXTRA_FIELD_NEW_UNIX_GUID;
674
+ }
675
+
676
+ if ($isFileUTF8 || $isCommentUTF8) {
677
+ $flag = 0;
678
+ $gpFlagsV = unpack("vflags", $gpFlags);
679
+ if (isset($gpFlagsV['flags'])) {
680
+ $flag = $gpFlagsV['flags'];
681
+ }
682
+ $gpFlags = pack("v", $flag | (1 << 11));
683
+
684
+ if ($isFileUTF8) {
685
+ $utfPathExtraField = "\x75\x70"
686
+ . pack ("v", (5 + strlen($filePath)))
687
+ . "\x01"
688
+ . pack("V", crc32($filePath))
689
+ . $filePath;
690
+
691
+ $localExtraField .= $utfPathExtraField;
692
+ $centralExtraField .= $utfPathExtraField;
693
+ }
694
+ if ($isCommentUTF8) {
695
+ $centralExtraField .= "\x75\x63" // utf8 encoded file comment extra field
696
+ . pack ("v", (5 + strlen($fileComment)))
697
+ . "\x01"
698
+ . pack("V", crc32($fileComment))
699
+ . $fileComment;
700
+ }
701
+ }
702
+
703
+ $header = $gpFlags . $gzType . $dosTime. $fileCRC32
704
+ . pack("VVv", $gzLength, $dataLength, strlen($filePath)); // File name length
705
+
706
+ $zipEntry = self::ZIP_LOCAL_FILE_HEADER
707
+ . self::ATTR_VERSION_TO_EXTRACT
708
+ . $header
709
+ . pack("v", strlen($localExtraField)) // Extra field length
710
+ . $filePath // FileName
711
+ . $localExtraField; // Extra fields
712
+
713
+ $this->zipwrite($zipEntry);
714
+
715
+ $cdEntry = self::ZIP_CENTRAL_FILE_HEADER
716
+ . self::ATTR_MADE_BY_VERSION
717
+ . ($dataLength === 0 ? "\x0A\x00" : self::ATTR_VERSION_TO_EXTRACT)
718
+ . $header
719
+ . pack("v", strlen($centralExtraField)) // Extra field length
720
+ . pack("v", $fileCommentLength) // File comment length
721
+ . "\x00\x00" // Disk number start
722
+ . "\x00\x00" // internal file attributes
723
+ . pack("V", $extFileAttr) // External file attributes
724
+ . pack("V", $this->offset) // Relative offset of local header
725
+ . $filePath // FileName
726
+ . $centralExtraField; // Extra fields
727
+
728
+ if (!empty($fileComment)) {
729
+ $cdEntry .= $fileComment; // Comment
730
+ }
731
+
732
+ $this->cdRec[] = $cdEntry;
733
+ $this->offset += strlen($zipEntry) + $gzLength;
734
+ }
735
+
736
+ private function zipwrite($data) {
737
+ if (!is_resource($this->zipFile)) {
738
+ $this->zipData .= $data;
739
+ } else {
740
+ fwrite($this->zipFile, $data);
741
+ fflush($this->zipFile);
742
+ }
743
+ }
744
+
745
+ private function zipflush() {
746
+ if (!is_resource($this->zipFile)) {
747
+ $this->zipFile = tmpfile();
748
+ fwrite($this->zipFile, $this->zipData);
749
+ $this->zipData = NULL;
750
+ }
751
+ }
752
+
753
+ /**
754
+ * Join $file to $dir path, and clean up any excess slashes.
755
+ *
756
+ * @param string $dir
757
+ * @param string $file
758
+ */
759
+ public static function pathJoin($dir, $file) {
760
+ if (empty($dir) || empty($file)) {
761
+ return self::getRelativePath($dir . $file);
762
+ }
763
+ return self::getRelativePath($dir . '/' . $file);
764
+ }
765
+
766
+ /**
767
+ * Clean up a path, removing any unnecessary elements such as /./, // or redundant ../ segments.
768
+ * If the path starts with a "/", it is deemed an absolute path and any /../ in the beginning is stripped off.
769
+ * The returned path will not end in a "/".
770
+ *
771
+ * Sometimes, when a path is generated from multiple fragments,
772
+ * you can get something like "../data/html/../images/image.jpeg"
773
+ * This will normalize that example path to "../data/images/image.jpeg"
774
+ *
775
+ * @param string $path The path to clean up
776
+ * @return string the clean path
777
+ */
778
+ public static function getRelativePath($path) {
779
+ $path = preg_replace("#/+\.?/+#", "/", str_replace("\\", "/", $path));
780
+ $dirs = explode("/", rtrim(preg_replace('#^(?:\./)+#', '', $path), '/'));
781
+
782
+ $offset = 0;
783
+ $sub = 0;
784
+ $subOffset = 0;
785
+ $root = "";
786
+
787
+ if (empty($dirs[0])) {
788
+ $root = "/";
789
+ $dirs = array_splice($dirs, 1);
790
+ } else if (preg_match("#[A-Za-z]:#", $dirs[0])) {
791
+ $root = strtoupper($dirs[0]) . "/";
792
+ $dirs = array_splice($dirs, 1);
793
+ }
794
+
795
+ $newDirs = array();
796
+ foreach ($dirs as $dir) {
797
+ if ($dir !== "..") {
798
+ $subOffset--;
799
+ $newDirs[++$offset] = $dir;
800
+ } else {
801
+ $subOffset++;
802
+ if (--$offset < 0) {
803
+ $offset = 0;
804
+ if ($subOffset > $sub) {
805
+ $sub++;
806
+ }
807
+ }
808
+ }
809
+ }
810
+
811
+ if (empty($root)) {
812
+ $root = str_repeat("../", $sub);
813
+ }
814
+ return $root . implode("/", array_slice($newDirs, 0, $offset));
815
+ }
816
+
817
+ /**
818
+ * Create the file permissions for a file or directory, for use in the extFileAttr parameters.
819
+ *
820
+ * @param int $owner Unix permisions for owner (octal from 00 to 07)
821
+ * @param int $group Unix permisions for group (octal from 00 to 07)
822
+ * @param int $other Unix permisions for others (octal from 00 to 07)
823
+ * @param bool $isFile
824
+ * @return EXTRERNAL_REF field.
825
+ */
826
+ public static function generateExtAttr($owner = 07, $group = 05, $other = 05, $isFile = true) {
827
+ $fp = $isFile ? self::S_IFREG : self::S_IFDIR;
828
+ $fp |= (($owner & 07) << 6) | (($group & 07) << 3) | ($other & 07);
829
+
830
+ return ($fp << 16) | ($isFile ? self::S_DOS_A : self::S_DOS_D);
831
+ }
832
+
833
+ /**
834
+ * Get the file permissions for a file or directory, for use in the extFileAttr parameters.
835
+ *
836
+ * @param string $filename
837
+ * @return external ref field, or FALSE if the file is not found.
838
+ */
839
+ public static function getFileExtAttr($filename) {
840
+ if (file_exists($filename)) {
841
+ $fp = fileperms($filename) << 16;
842
+ return $fp | (is_dir($filename) ? self::S_DOS_D : self::S_DOS_A);
843
+ }
844
+ return FALSE;
845
+ }
846
+ /**
847
+ * Returns the path to a temporary file.
848
+ * @return string
849
+ */
850
+ private static function getTemporaryFile() {
851
+ if(is_callable(self::$temp)) {
852
+ $temporaryFile = @call_user_func(self::$temp);
853
+ if(is_string($temporaryFile) && strlen($temporaryFile) && is_writable($temporaryFile)) {
854
+ return $temporaryFile;
855
+ }
856
+ }
857
+ $temporaryDirectory = (is_string(self::$temp) && strlen(self::$temp)) ? self::$temp : sys_get_temp_dir();
858
+ return tempnam($temporaryDirectory, 'Zip');
859
+ }
860
+ }
861
+
embedded/common/array2xml.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!class_exists('ICL_Array2XML')) {
4
+
5
+ /**
6
+ * Converts array to XML
7
+ */
8
+ class ICL_Array2XML
9
+ {
10
+
11
+ var $text;
12
+ var $arrays, $keys, $node_flag, $depth, $xml_parser;
13
+
14
+ function array2xml($array, $root) {
15
+ $this->depth = 1;
16
+ $this->text = "<?xml version=\"1.0\" encoding=\""
17
+ . get_option('blog_charset'). "\"?>\r\n<$root>\r\n";
18
+ $this->text .= $this->array_transform($array);
19
+ $this->text .="</$root>";
20
+ return $this->text;
21
+ }
22
+
23
+ function array_transform($array) {
24
+ $output = '';
25
+ $indent = str_repeat(' ', $this->depth * 4);
26
+ $child_key = false;
27
+ if (isset($array['__key'])) {
28
+ $child_key = $array['__key'];
29
+ unset($array['__key']);
30
+ }
31
+ foreach ($array as $key => $value) {
32
+ $key = str_replace(' ', '___032___', $key); // encode spaces
33
+ if (!is_array($value)) {
34
+ if (empty($key)) {
35
+ continue;
36
+ }
37
+ $key = $child_key ? $child_key : $key;
38
+ $output .= $indent . "<$key>" . htmlspecialchars($value, ENT_QUOTES) . "</$key>\r\n";
39
+ } else {
40
+ $this->depth++;
41
+ $key = $child_key ? $child_key : $key;
42
+ $output_temp = $this->array_transform($value);
43
+ if (!empty($output_temp)) {
44
+ $output .= $indent . "<$key>\r\n";
45
+ $output .= $output_temp;
46
+ $output .= $indent . "</$key>\r\n";
47
+ }
48
+ $this->depth--;
49
+ }
50
+ }
51
+ return $output;
52
+ }
53
+
54
+ }
55
+ }
embedded/common/classes/control_forms.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include_once 'forms.php';
4
+
5
+ class Enlimbo_Control_Forms extends Enlimbo_Forms_Wpcf {
6
+
7
+ private $_urlParam = '';
8
+
9
+ public function isSubmitted($id = '') {
10
+ if(!empty($id)) {
11
+ $this->_urlParam = $id;
12
+ }
13
+
14
+ if(empty($this->_urlParam)) {
15
+ return false;
16
+ }
17
+
18
+ return isset($_GET[$this->_urlParam]);
19
+ }
20
+
21
+ public function renderElements($elements) {
22
+ if(isset($elements['field'])) {
23
+ $this->_urlParam = $elements['field']['#name'];
24
+ }
25
+
26
+ return parent::renderElements($elements);
27
+ }
28
+ }
embedded/common/classes/forms.php ADDED
@@ -0,0 +1,969 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Returns HTML formatted output for elements and handles form submission.
4
+ *
5
+ * $HeadURL: http://plugins.svn.wordpress.org/types/tags/1.6/embedded/common/classes/forms.php $
6
+ * $LastChangedDate: 2014-05-29 08:44:10 +0000 (Thu, 29 May 2014) $
7
+ * $LastChangedRevision: 922956 $
8
+ * $LastChangedBy: iworks $
9
+ *
10
+ * @version 1.0
11
+ */
12
+ if (!class_exists('Enlimbo_Forms_Wpcf')) {
13
+
14
+ class Enlimbo_Forms_Wpcf
15
+ {
16
+
17
+ /**
18
+ * @var string
19
+ */
20
+ private $_id;
21
+
22
+ /**
23
+ * @var array
24
+ */
25
+ private $_errors = array();
26
+
27
+ /**
28
+ * @var array
29
+ */
30
+ private $_elements = array();
31
+
32
+ /**
33
+ * @var array
34
+ */
35
+ private $_count = array();
36
+
37
+ /**
38
+ * @var string
39
+ */
40
+ public $css_class = 'wpcf-form';
41
+
42
+ /**
43
+ * Auto handler
44
+ *
45
+ * Renders.
46
+ *
47
+ * @param array $element
48
+ * @return HTML formatted output
49
+ */
50
+ public function getId() {
51
+ return $this->_id;
52
+ }
53
+
54
+ public function autoHandle($id, $form)
55
+ {
56
+ // Auto-add wpnonce field
57
+ $form['_wpnonce'] = array(
58
+ '#type' => 'markup',
59
+ '#markup' => wp_nonce_field($id, '_wpnonce_wpcf', true, false)
60
+ );
61
+
62
+ $this->_id = $id;
63
+ $this->_elements = $form;
64
+
65
+ do_action('wpcf_form_autohandle', $id, $form, $this);
66
+ do_action('wpcf_form_autohandle_' . $id, $form, $this);
67
+
68
+ // get submitted data
69
+ if ($this->isSubmitted()) {
70
+
71
+ do_action('wpcf_form_autohandle_submit', $id, $form, $this);
72
+ do_action('wpcf_form_autohandle_submit_' . $id, $form, $this);
73
+
74
+ // check if errors (validation)
75
+ $this->validate($this->_elements);
76
+
77
+ do_action('wpcf_form_autohandle_validate', $id, $form, $this);
78
+ do_action('wpcf_form_autohandle_validate_' . $id, $form, $this);
79
+
80
+ // callback
81
+ if (empty($this->_errors)) {
82
+
83
+ if (isset($form['#form']['callback'])) {
84
+ if (is_array($form['#form']['callback'])) {
85
+ foreach ($form['#form']['callback'] as $callback) {
86
+ if (is_callable($callback)) {
87
+ call_user_func($callback, $this);
88
+ }
89
+ }
90
+ } else {
91
+ if (is_callable($form['#form']['callback'])) {
92
+ call_user_func($form['#form']['callback'], $this);
93
+ }
94
+ }
95
+ }
96
+ // Maybe triggered by callback function
97
+ if (empty($this->_errors)) {
98
+ // redirect
99
+ do_action('wpcf_form_autohandle_redirection', $id,
100
+ $form, $this);
101
+ do_action('wpcf_form_autohandle_redirection_' . $id,
102
+ $form, $this);
103
+ if (!isset($form['#form']['redirection'])) {
104
+ header('Location: ' . $_SERVER['REQUEST_URI']);
105
+ } else if ($form['#form']['redirection'] != false) {
106
+ header('Location: ' . $form['#form']['redirection']);
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Checks if form is submitted.
115
+ *
116
+ * @param type $id
117
+ * @return type
118
+ */
119
+ public function isSubmitted($id = '')
120
+ {
121
+ if (empty($id)) {
122
+ $id = $this->_id;
123
+ }
124
+ return (isset($_REQUEST['_wpnonce_wpcf'])
125
+ && wp_verify_nonce($_REQUEST['_wpnonce_wpcf'], $id));
126
+ }
127
+
128
+ /**
129
+ * Loops over elements and validates them.
130
+ *
131
+ * @param type $elements
132
+ */
133
+ public function validate(&$elements)
134
+ {
135
+ require_once WPCF_EMBEDDED_ABSPATH . '/classes/validate.php';
136
+ foreach ($elements as $key => &$element) {
137
+ if (!isset($element['#type'])
138
+ || !$this->_isValidType($element['#type'])) {
139
+ continue;
140
+ }
141
+ if ($element['#type'] != 'fieldset') {
142
+ if (isset($element['#name'])
143
+ && !in_array($element['#type'],
144
+ array('submit', 'reset'))) {
145
+ // Set submitted data
146
+ if (!in_array($element['#type'], array('checkboxes'))
147
+ && empty($element['#forced_value'])) {
148
+ $element['#value'] = $this->getSubmittedData($element);
149
+ } else if (!empty($element['#options'])
150
+ && empty($element['#forced_value'])) {
151
+ foreach ($element['#options'] as $option_key => $option) {
152
+ $option['#type'] = 'checkbox';
153
+ $element['#options'][$option_key]['#value'] = $this->getSubmittedData($option);
154
+ }
155
+ }
156
+ }
157
+ // Validate
158
+ if (isset($element['#validate'])) {
159
+ $this->validateElement($element);
160
+ }
161
+ } else if (isset($element['#type'])
162
+ && $element['#type'] == 'fieldset') {
163
+ $this->validate($element);
164
+ } else if (is_array($element)) {
165
+ $this->validate($element);
166
+ }
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Validates element.
172
+ *
173
+ * @param type $element
174
+ */
175
+ public function validateElement(&$element)
176
+ {
177
+ $check = Wpcf_Validate::check($element['#validate'],
178
+ $element['#value']);
179
+ if (isset($check['error'])) {
180
+ $this->_errors = true;
181
+ $element['#error'] = $check['message'];
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Checks if there are errors.
187
+ *
188
+ * @return type
189
+ */
190
+ public function isError()
191
+ {
192
+ return $this->_errors;
193
+ }
194
+
195
+ /**
196
+ * Sets errors to true.
197
+ */
198
+ public function triggerError()
199
+ {
200
+ $this->_errors = true;
201
+ }
202
+
203
+ /**
204
+ * Renders form.
205
+ *
206
+ * @return type
207
+ */
208
+ public function renderForm()
209
+ {
210
+ // loop over elements and render them
211
+ return $this->renderElements($this->_elements);
212
+ }
213
+
214
+ /**
215
+ * Counts element types.
216
+ *
217
+ * @param type $type
218
+ * @return type
219
+ */
220
+ private function _count($type) {
221
+ if (!isset($this->_count[$type])) {
222
+ $this->_count[$type] = 0;
223
+ }
224
+ $this->_count[$type] += 1;
225
+ return $this->_count[$type];
226
+ }
227
+
228
+ /**
229
+ * Check if element is of valid type
230
+ *
231
+ * @param string $type
232
+ * @return boolean
233
+ */
234
+ private function _isValidType($type)
235
+ {
236
+ return in_array($type,
237
+ array('select', 'checkboxes', 'checkbox', 'radios',
238
+ 'radio', 'textfield', 'textarea', 'file', 'submit', 'reset',
239
+ 'hidden', 'fieldset', 'markup', 'button'));
240
+ }
241
+
242
+ /**
243
+ * Renders elements.
244
+ *
245
+ * @param type $elements
246
+ * @return type
247
+ */
248
+ public function renderElements($elements)
249
+ {
250
+ $output = '';
251
+ foreach ($elements as $key => $element) {
252
+ if (!isset($element['#type'])
253
+ || !$this->_isValidType($element['#type'])) {
254
+ continue;
255
+ }
256
+ if ($element['#type'] != 'fieldset') {
257
+ $output .= $this->renderElement($element);
258
+ } else if (isset($element['#type'])
259
+ && $element['#type'] == 'fieldset') {
260
+ $buffer = $this->renderElements($element);
261
+ $output .= $this->fieldset($element, 'wrap', $buffer);
262
+ } else if (is_array($element)) {
263
+ $output .= $this->renderElements($element);
264
+ }
265
+ }
266
+ return $output;
267
+ }
268
+
269
+ /**
270
+ * Renders element.
271
+ *
272
+ * Depending on element type, it calls class methods.
273
+ *
274
+ * @param array $element
275
+ * @return HTML formatted output
276
+ */
277
+ public function renderElement($element)
278
+ {
279
+ $method = $element['#type'];
280
+ if (!isset($element['#name']) && $element['#type'] != 'markup') {
281
+ if (!isset($element['#attributes']['name'])) {
282
+ return '#name or #attributes[\'name\'] required!';
283
+ } else {
284
+ $element['#name'] = $element['#attributes']['name'];
285
+ }
286
+ }
287
+ if (is_callable(array($this, $method))) {
288
+ if (!isset($element['#id'])) {
289
+ if (isset($element['#attributes']['id'])) {
290
+ $element['#id'] = $element['#attributes']['id'];
291
+ } else {
292
+ $element['#id'] = $element['#type'] . '-'
293
+ . $this->_count($element['#type']);
294
+ }
295
+ }
296
+ if (isset($this->_errors[$element['#id']])) {
297
+ $element['#error'] = $this->_errors[$element['#id']];
298
+ }
299
+ // Add JS validation
300
+ if (!empty($element['#validate'])) {
301
+ wpcf_form_add_js_validation($element);
302
+ }
303
+ return $this->{$method}($element);
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Sets other element attributes.
309
+ *
310
+ * @param array $element
311
+ * @return string
312
+ */
313
+ private function _setElementAttributes($element)
314
+ {
315
+ $attributes = '';
316
+ $error_class = isset($element['#error']) ? ' ' . $this->css_class . '-error ' . $this->css_class . '-' . $element['#type'] . '-error ' . ' form-' . $element['#type'] . '-error ' . $element['#type'] . '-error form-error ' : '';
317
+ $class = $this->css_class . '-' . $element['#type']
318
+ . ' form-' . $element['#type'] . ' ' . $element['#type'];
319
+ if (isset($element['#attributes'])) {
320
+ foreach ($element['#attributes'] as $attribute => $value) {
321
+ // Prevent undesired elements
322
+ if (in_array($attribute, array('id', 'name'))) {
323
+ continue;
324
+ }
325
+ // Don't set disabled for checkbox
326
+ if ($attribute == 'disabled' && $element['#type'] == 'checkbox') {
327
+ continue;
328
+ }
329
+ // Append class values
330
+ if ($attribute == 'class') {
331
+ $value = $value . ' ' . $class . $error_class;
332
+
333
+ }
334
+ // Set return string
335
+ $attributes .= ' ' . $attribute . '="' . $value . '"';
336
+ }
337
+ }
338
+ if (!isset($element['#attributes']['class'])) {
339
+ $is_default_element = isset( $element['#default_value'] ) && $element['#default_value'] ? ' wpcf-default-value-input' : '';
340
+
341
+ $attributes .= ' class="' . $class . $error_class . $is_default_element . '"';
342
+ }
343
+ return $attributes;
344
+ }
345
+
346
+ /**
347
+ * Sets render elements.
348
+ *
349
+ * @param array $element
350
+ */
351
+ private function _setRender($element)
352
+ {
353
+ if (!isset($element['#id'])) {
354
+ if (isset($element['#attributes']['id'])) {
355
+ $element['#id'] = $element['#attributes']['id'];
356
+ } else {
357
+ $element['#id'] = 'form-' . md5(serialize($element)) . '-'
358
+ . $this->_count($element['#type']);
359
+ }
360
+ }
361
+ $element['_attributes_string'] = $this->_setElementAttributes($element);
362
+ $element['_render'] = array();
363
+ $element['_render']['prefix'] = isset($element['#prefix']) ? $element['#prefix'] . "\r\n" : '';
364
+ $element['_render']['suffix'] = isset($element['#suffix']) ? $element['#suffix'] . "\r\n" : '';
365
+ $element['_render']['before'] = isset($element['#before']) ? $element['#before'] . "\r\n" : '';
366
+ $element['_render']['after'] = isset($element['#after']) ? $element['#after'] . "\r\n" : '';
367
+ $labelclass = '';
368
+ if ( isset( $element['#labelclass'] ) ) {
369
+ $labelclass = $element['#labelclass'] . ' ';
370
+ }
371
+ $element['_render']['label'] = isset($element['#title']) ? '<label class="'
372
+ . $labelclass
373
+ . $this->css_class . '-label ' . $this->css_class . '-'
374
+ . $element['#type'] . '-label" for="' . $element['#id'] . '">'
375
+ . stripslashes($element['#title'])
376
+ . '</label>' . "\r\n" : '';
377
+ $element['_render']['title'] = $this->_setElementTitle($element);
378
+ $element['_render']['description'] = isset($element['#description']) ? $this->_setElementDescription($element) : '';
379
+ $element['_render']['error'] = $this->renderError($element) . "\r\n";
380
+
381
+ return $element;
382
+ }
383
+
384
+ /**
385
+ * Applies pattern to output.
386
+ *
387
+ * Pass element property #pattern to get custom renedered element.
388
+ *
389
+ * @param array $pattern
390
+ * Accepts: <prefix><suffix><label><title><desription><error>
391
+ * @param array $element
392
+ */
393
+ private function _pattern($pattern, $element)
394
+ {
395
+ $pattern = strtolower($pattern);
396
+ foreach ($element['_render'] as $key => $value) {
397
+ $pattern = str_replace('<' . strtolower($key) . '>', $value,
398
+ $pattern);
399
+ }
400
+ return $pattern;
401
+ }
402
+
403
+ /**
404
+ * Wrapps element in <div></div>.
405
+ *
406
+ * @param arrat $element
407
+ * @param string $output
408
+ * @return string
409
+ */
410
+ private function _wrapElement($element, $output)
411
+ {
412
+ if (empty($element['#inline'])) {
413
+ $wrapped = '<div id="' . $element['#id'] . '-wrapper"'
414
+ . ' class="form-item form-item-' . $element['#type'] . ' '
415
+ . $this->css_class . '-item '
416
+ . $this->css_class . '-item-' . $element['#type']
417
+ . '">' . $output . '</div>';
418
+ return $wrapped;
419
+ }
420
+ return $output;
421
+ }
422
+
423
+ /**
424
+ * Returns HTML formatted output for element's title.
425
+ *
426
+ * @param string $element
427
+ * @return string
428
+ */
429
+ private function _setElementTitle($element)
430
+ {
431
+ $output = '';
432
+ if (isset($element['#title'])) {
433
+ $output .= '<div class="title '
434
+ . $this->css_class . '-title '
435
+ . $this->css_class . '-title-' . $element['#type'] . ' '
436
+ . 'title-' . $element['#type'] . '">'
437
+ . stripslashes($element['#title'])
438
+ . "</div>\r\n";
439
+ }
440
+ return $output;
441
+ }
442
+
443
+ /**
444
+ * Returns HTML formatted output for element's description.
445
+ *
446
+ * @param array $element
447
+ * @return string
448
+ */
449
+ private function _setElementDescription($element)
450
+ {
451
+ $element['#description'] = stripslashes($element['#description']);
452
+ $output = "\r\n"
453
+ . '<div class="description '
454
+ . $this->css_class . '-description '
455
+ . $this->css_class . '-description-' . $element['#type'] . ' '
456
+ . 'description-' . $element['#type'] . '">'
457
+ . $element['#description'] . "</div>\r\n";
458
+ return $output;
459
+ }
460
+
461
+ /**
462
+ * Returns HTML formatted element's error message.
463
+ *
464
+ * Pass #supress_errors in #form element to avoid error rendering.
465
+ *
466
+ * @param array $element
467
+ * @return string
468
+ */
469
+ public function renderError($element)
470
+ {
471
+ if (!isset($element['#error'])) {
472
+ return '';
473
+ }
474
+ $output = '<div class="form-error '
475
+ . $this->css_class . '-error '
476
+ . $this->css_class . '-form-error '
477
+ . $this->css_class . '-' . $element['#type'] . '-error '
478
+ . $element['#type'] . '-error form-error-label'
479
+ . '">' . $element['#error'] . '</div>'
480
+ . "\r\n";
481
+ return $output;
482
+ }
483
+
484
+ /**
485
+ * Returns HTML formatted output for fieldset.
486
+ *
487
+ * @param array $element
488
+ * @param string $action open|close|wrap
489
+ * @param string $wrap_content HTML formatted output of child elements
490
+ * @return string
491
+ */
492
+ public function fieldset($element, $action = 'open', $wrap_content = '')
493
+ {
494
+ $collapsible_open = '<div class="fieldset-wrapper">';
495
+ $collapsible_close = '</div>';
496
+ $legend_class = '';
497
+ if (!isset($element['#id'])) {
498
+ $element['#id'] = 'fieldset-' . $this->_count('fieldset');
499
+ }
500
+ if (!isset($element['_attributes_string'])) {
501
+ $element['_attributes_string'] = $this->_setElementAttributes($element);
502
+ }
503
+ if ((isset($element['#collapsible']) && $element['#collapsible'])
504
+ || (isset($element['#collapsed']) && $element['#collapsed'])) {
505
+ $collapsible_open = '<div class="collapsible fieldset-wrapper">';
506
+ $collapsible_close = '</div>';
507
+ $legend_class = ' class="legend-expanded"';
508
+ }
509
+ if (isset($element['#collapsed']) && $element['#collapsed']) {
510
+ $collapsible_open = str_replace('class="', 'class="collapsed ',
511
+ $collapsible_open);
512
+ $legend_class = ' class="legend-collapsed"';
513
+ }
514
+ $output = '';
515
+ switch ($action) {
516
+ case 'close':
517
+ $output .= $collapsible_close . "</fieldset>\r\n";
518
+ $output .= isset($element['#suffix']) ? $element['#suffix']
519
+ . "\r\n" : '';
520
+ $output .= "\n\r";
521
+ break;
522
+
523
+ case 'open':
524
+ $output .= $collapsible_open;
525
+ $output .= isset($element['#prefix']) ? $element['#prefix']
526
+ . "\r\n" : '';
527
+ $output .= '<fieldset' . $element['_attributes_string']
528
+ . ' id="' . $element['#id'] . '">' . "\r\n";
529
+ $output .= isset($element['#title']) ? '<legend'
530
+ . $legend_class . '>'
531
+ . stripslashes($element['#title'])
532
+ . "</legend>\r\n" : '';
533
+ $output .=
534
+ isset($element['#description']) ? $this->_setElementDescription($element) : '';
535
+ $output .= "\n\r";
536
+ break;
537
+
538
+ case 'wrap':
539
+ if (!empty($wrap_content)) {
540
+ $output .= isset($element['#prefix']) ? $element['#prefix'] : '';
541
+ $output .= '<fieldset' . $element['_attributes_string']
542
+ . ' id="' . $element['#id'] . '">' . "\r\n";
543
+ $output .= '<legend' . $legend_class . '>'
544
+ . stripslashes($element['#title'])
545
+ . "</legend>\r\n"
546
+ . $collapsible_open;
547
+ $output .= isset($element['#description']) ? $this->_setElementDescription($element) : '';
548
+ $output .= $wrap_content . $collapsible_close
549
+ . "</fieldset>\r\n";
550
+ $output .=
551
+ isset($element['#suffix']) ? $element['#suffix'] : '';
552
+ $output .= "\n\r";
553
+ }
554
+ break;
555
+ }
556
+ return $output;
557
+ }
558
+
559
+ /**
560
+ * Returns HTML formatted output for checkbox element.
561
+ *
562
+ * @param array $element
563
+ * @return string
564
+ */
565
+ public function checkbox($element)
566
+ {
567
+
568
+ $element['#type'] = 'checkbox';
569
+ $element = $this->_setRender($element);
570
+ $element['_render']['element'] = '<input type="checkbox" id="'
571
+ . $element['#id'] . '" name="'
572
+ . $element['#name'] . '" value="';
573
+ // Specific: if value is empty force 1 to be rendered
574
+ // Juan: removed this 1 forced value since it broke the default value in checkboxes filter controls
575
+ $element['_render']['element'] .=
576
+ !empty($element['#value']) ? htmlspecialchars($element['#value']) : '';
577
+ $element['_render']['element'] .= '"' . $element['_attributes_string'];
578
+ $element['_render']['element'] .= ((!$this->isSubmitted()
579
+ && !empty($element['#default_value']))
580
+ || ($this->isSubmitted()
581
+ && !empty($element['#value']))) ? ' checked="checked"' : '';
582
+ if (!empty($element['#attributes']['disabled']) || !empty($element['#disable'])) {
583
+ $element['_render']['element'] .= ' onclick="javascript:return false; if(this.checked == 1){this.checked=1; return true;}else{this.checked=0; return false;}"';
584
+ }
585
+ if (!empty($element['#attributes']['#disabled'])) {
586
+ $element['_render']['element'] .= ' disabled="disabled""';
587
+ }
588
+
589
+ $element['_render']['element'] .= ' />';
590
+ $pattern = isset($element['#pattern']) ? $element['#pattern'] : '<BEFORE><PREFIX><ELEMENT>&nbsp;<LABEL><ERROR><SUFFIX><DESCRIPTION><AFTER>';
591
+ $output = $this->_pattern($pattern, $element);
592
+ $output = $this->_wrapElement($element, $output);
593
+ return $output . "\r\n";
594
+ }
595
+
596
+ /**
597
+ * Returns HTML formatted output for checkboxes element.
598
+ *
599
+ * Renders more than one checkboxes provided as elements in '#options'
600
+ * array element.
601
+ *
602
+ * @param array $element
603
+ * @return string
604
+ */
605
+ public function checkboxes($element)
606
+ {
607
+ $element['#type'] = 'checkboxes';
608
+ $element = $this->_setRender($element);
609
+ $clone = $element;
610
+ $clone['#type'] = 'checkbox';
611
+ $element['_render']['element'] = '';
612
+ foreach ($element['#options'] as $ID => $value) {
613
+ if (!is_array($value)) {
614
+ $value = array('#title' => $ID, '#value' => $value, '#name' => $element['#name'] . '[]');
615
+ }
616
+ $element['_render']['element'] .= $this->checkbox($value);
617
+ }
618
+ $pattern = isset($element['#pattern']) ? $element['#pattern'] : '<BEFORE><PREFIX><TITLE><DESCRIPTION><ELEMENT><SUFFIX><AFTER>';
619
+ $output = $this->_pattern($pattern, $element);
620
+ $output = $this->_wrapElement($element, $output);
621
+ return $output;
622
+ }
623
+
624
+ /**
625
+ * Returns HTML formatted output for radio element.
626
+ *
627
+ * @param array $element
628
+ * @return string
629
+ */
630
+ public function radio($element)
631
+ {
632
+ $element['#type'] = 'radio';
633
+ $element = $this->_setRender($element);
634
+ $element['_render']['element'] = '<input type="radio" id="'
635
+ . $element['#id'] . '" name="'
636
+ . $element['#name'] . '" value="';
637
+ $element['_render']['element'] .= isset($element['#value']) ? htmlspecialchars($element['#value']) : $this->_count['radio'];
638
+ $element['_render']['element'] .= '"';
639
+ $element['_render']['element'] .= $element['_attributes_string'];
640
+ $element['_render']['element'] .= ( isset($element['#value'])
641
+ && $element['#value'] === $element['#default_value']) ? ' checked="checked"' : '';
642
+ if (isset($element['#disable']) && $element['#disable']) {
643
+ $element['_render']['element'] .= ' disabled="disabled"';
644
+ }
645
+ $element['_render']['element'] .= ' />';
646
+ $pattern = isset($element['#pattern']) ? $element['#pattern'] : '<BEFORE><PREFIX><ELEMENT>&nbsp;<LABEL><ERROR><SUFFIX><DESCRIPTION><AFTER>';
647
+ $output = $this->_pattern($pattern, $element);
648
+ $output = $this->_wrapElement($element, $output);
649
+ return $output . "\r\n";
650
+ }
651
+
652
+ /**
653
+ * Returns HTML formatted output for radios elements.
654
+ *
655
+ * Radios are provided via #options array.
656
+ * Requires #name value.
657
+ *
658
+ * @param array $element
659
+ * @return string
660
+ */
661
+ public function radios($element)
662
+ {
663
+ if (!isset($element['#name']) || empty($element['#name'])) {
664
+ return FALSE;
665
+ }
666
+ $element['#type'] = 'radios';
667
+ $element = $this->_setRender($element);
668
+ $element['_render']['element'] = '';
669
+ foreach ($element['#options'] as $ID => $value) {
670
+ $this->_count('radio');
671
+ if (!is_array($value)) {
672
+ $value = array('#title' => $ID, '#value' => $value);
673
+ $value['#inline'] = true;
674
+ $value['#after'] = '<br />';
675
+ }
676
+ $value['#name'] = $element['#name'];
677
+ $value['#default_value'] = isset($element['#default_value']) ? $element['#default_value'] : $value['#value'];
678
+ if ( !isset( $value['#disable'] ) ) {
679
+ $value['#disable'] = isset($element['#disable']) ? $element['#disable'] : false;
680
+ }
681
+ if ( isset( $element['#attributes'] ) && !isset( $value['#attributes'] ) ) {
682
+ $value['#attributes'] = $element['#attributes'];
683
+ }
684
+ $element['_render']['element'] .= $this->radio($value);
685
+ }
686
+ $pattern = isset($element['#pattern']) ? $element['#pattern'] : '<BEFORE><PREFIX><TITLE><DESCRIPTION><ELEMENT><SUFFIX><AFTER>';
687
+ $output = $this->_pattern($pattern, $element);
688
+ $output = $this->_wrapElement($element, $output);
689
+ return $output;
690
+ }
691
+
692
+ /**
693
+ * Returns HTML formatted output for select element.
694
+ *
695
+ * @param array $element
696
+ * @return string
697
+ */
698
+ public function select($element)
699
+ {
700
+ $element['#type'] = 'select';
701
+ $element = $this->_setRender($element);
702
+ $multiple = isset( $element['#multiple'] ) ? $element['#multiple'] : '';
703
+
704
+ $element['_render']['element'] = '<select '.$multiple.' id="' . $element['#id']
705
+ . '" name="' . $element['#name'] . '"'
706
+ . $element['_attributes_string'] . ">\r\n";
707
+ $count = 1;
708
+ foreach ($element['#options'] as $id => $value) {
709
+ if (!is_array($value)) {
710
+ $value = array('#title' => $id, '#value' => $value);
711
+ }
712
+ if (!isset($value['#value'])) {
713
+ $value['#value'] = $this->_count['select'] . '-' . $count;
714
+ $count += 1;
715
+ }
716
+
717
+ $value['#type'] = 'option';
718
+ $element['_render']['element'] .= '<option value="'
719
+ . htmlspecialchars($value['#value']) . '"';
720
+
721
+ if( is_array( $element['#default_value'] ) )
722
+ {
723
+ $element['_render']['element'] .= in_array( $value['#value'], $element['#default_value'] ) ? ' selected="selected"' : '';
724
+ }
725
+ else
726
+ {
727
+ $element['_render']['element'] .= ( $element['#default_value']
728
+ == $value['#value']) ? ' selected="selected"' : '';
729
+ }
730
+ if ( isset( $value['#disable'] ) ) {
731
+ $element['_render']['element'] .= ' disabled="disabled"';
732
+ }
733
+
734
+ $element['_render']['element'] .= $this->_setElementAttributes($value);
735
+ $element['_render']['element'] .= '>';
736
+ $element['_render']['element'] .= isset($value['#title']) ? $value['#title'] : $value['#value'];
737
+ $element['_render']['element'] .= "</option>\r\n";
738
+ }
739
+ $element['_render']['element'] .= "</select>\r\n";
740
+ $pattern = isset($element['#pattern']) ? $element['#pattern'] : '<BEFORE><LABEL><DESCRIPTION><ERROR><PREFIX><ELEMENT><SUFFIX><AFTER>';
741
+ $output = $this->_pattern($pattern, $element);
742
+ $output = $this->_wrapElement($element, $output);
743
+ return $output;
744
+ }
745
+
746
+ /**
747
+ * Returns HTML formatted output for textfield element.
748
+ *
749
+ * @param array $element
750
+ * @return string
751
+ */
752
+ public function textfield($element)
753
+ {
754
+ $element['#type'] = 'textfield';
755
+ $element = $this->_setRender($element);
756
+ $element['_render']['element'] = '<input type="text" id="'
757
+ . $element['#id'] . '" name="' . $element['#name'] . '" value="';
758
+ $element['_render']['element'] .= isset($element['#value']) ? htmlspecialchars(stripslashes($element['#value'])) : '';
759
+ $element['_render']['element'] .= '"' . $element['_attributes_string'];
760
+ if (isset($element['#disable']) && $element['#disable']) {
761
+ $element['_render']['element'] .= ' disabled="disabled"';
762
+ }
763
+ $element['_render']['element'] .= ' />';
764
+ $pattern = isset($element['#pattern']) ? $element['#pattern'] : '<BEFORE><LABEL><ERROR><PREFIX><ELEMENT><SUFFIX><DESCRIPTION><AFTER>';
765
+ $output = $this->_pattern($pattern, $element);
766
+ $output = $this->_wrapElement($element, $output);
767
+ return $output . "\r\n";
768
+ }
769
+
770
+ /**
771
+ * Returns HTML formatted output for textfield element.
772
+ *
773
+ * @param array $element
774
+ * @return string
775
+ */
776
+ public function password($element)
777
+ {
778
+ $element['#type'] = 'password';
779
+ $element = $this->_setRender($element);
780
+ $element['_render']['element'] = '<input type="password" id="'
781
+ . $element['#id'] . '" name="' . $element['#name'] . '" value="';
782
+ $element['_render']['element'] .= isset($element['#value']) ? $element['#value'] : '';
783
+ $element['_render']['element'] .= '"' . $element['_attributes_string'];
784
+ if (isset($element['#disable']) && $element['#disable']) {
785
+ $element['_render']['element'] .= ' disabled="disabled"';
786
+ }
787
+ $element['_render']['element'] .= ' />';
788
+ $pattern = isset($element['#pattern']) ? $element['#pattern'] : '<BEFORE><LABEL><ERROR><PREFIX><ELEMENT><SUFFIX><DESCRIPTION><AFTER>';
789
+ $output = $this->_pattern($pattern, $element);
790
+ $output = $this->_wrapElement($element, $output);
791
+ return $output . "\r\n";
792
+ }
793
+
794
+ /**
795
+ * Returns HTML formatted output for textarea element.
796
+ *
797
+ * @param array $element
798
+ * @return string
799
+ */
800
+ public function textarea($element)
801
+ {
802
+ $element['#type'] = 'textarea';
803
+ if (!isset($element['#attributes']['rows'])) {
804
+ $element['#attributes']['rows'] = 5;
805
+ }
806
+ if (!isset($element['#attributes']['cols'])) {
807
+ $element['#attributes']['cols'] = 1;
808
+ }
809
+ $element = $this->_setRender($element);
810
+ $element['_render']['element'] = '<textarea id="' . $element['#id']
811
+ . '" name="' . $element['#name'] . '"'
812
+ . $element['_attributes_string'] . '>';
813
+ $element['_render']['element'] .= isset($element['#value']) ? htmlspecialchars(stripslashes($element['#value'])) : '';
814
+ $element['_render']['element'] .= '</textarea>' . "\r\n";
815
+ $pattern = isset($element['#pattern']) ? $element['#pattern'] : '<BEFORE><LABEL><DESCRIPTION><ERROR><PREFIX><ELEMENT><SUFFIX><AFTER>';
816
+ $output = $this->_pattern($pattern, $element);
817
+ $output = $this->_wrapElement($element, $output);
818
+ return $output . "\r\n";
819
+ }
820
+
821
+ /**
822
+ * Returns HTML formatted output for file upload element.
823
+ *
824
+ * @param array $element
825
+ * @return string
826
+ */
827
+ public function file($element)
828
+ {
829
+ $element['#type'] = 'file';
830
+ $element = $this->_setRender($element);
831
+ $element['_render']['element'] = '<input type="file" id="'
832
+ . $element['#id'] . '" name="' . $element['#name'] . '"'
833
+ . $element['_attributes_string'];
834
+ if (isset($element['#disable']) && $element['#disable']) {
835
+ $element['_render']['element'] .= ' disabled="disabled"';
836
+ }
837
+ $element['_render']['element'] .= ' />';
838
+ $pattern = isset($element['#pattern']) ? $element['#pattern'] : '<BEFORE><LABEL><ERROR><PREFIX><ELEMENT><DESCRIPTION><SUFFIX><AFTER>';
839
+ $output = $this->_pattern($pattern, $element);
840
+ $output = $this->_wrapElement($element, $output);
841
+ return $output;
842
+ }
843
+
844
+ /**
845
+ * Returns HTML formatted output for markup element.
846
+ *
847
+ * @param array $element
848
+ * @return string
849
+ */
850
+ public function markup($element)
851
+ {
852
+ return $element['#markup'];
853
+ }
854
+
855
+ /**
856
+ * Returns HTML formatted output for hidden element.
857
+ *
858
+ * @param array $element
859
+ * @return string
860
+ */
861
+ public function hidden($element)
862
+ {
863
+ $element['#type'] = 'hidden';
864
+ $output = '<input type="hidden" id="' . $element['#id'] . '" name="'
865
+ . $element['#name'] . '" value="';
866
+ $output .= isset($element['#value']) ? $element['#value'] : 1;
867
+ $output .= '" />';
868
+ return $output;
869
+ }
870
+
871
+ /**
872
+ * Returns HTML formatted output for reset button element.
873
+ *
874
+ * @param array $element
875
+ * @return string
876
+ */
877
+ public function reset($element)
878
+ {
879
+ return $this->submit($element, 'reset', 'Reset');
880
+ }
881
+
882
+ /**
883
+ * Returns HTML formatted output for button element.
884
+ *
885
+ * @param array $element
886
+ * @return string
887
+ */
888
+ public function button($element)
889
+ {
890
+ return $this->submit($element, 'button', 'Button');
891
+ }
892
+
893
+ /**
894
+ * Returns HTML formatted output for radio element.
895
+ *
896
+ * Used by reset and button.
897
+ *
898
+ * @param array $element
899
+ * @param string $type
900
+ * @param string $title
901
+ * @return string
902
+ */
903
+ public function submit($element, $type = 'submit', $title = 'Submit')
904
+ {
905
+ $element['#type'] = $type;
906
+ $element = $this->_setRender($element);
907
+ $element['_render']['element'] = '<input type="' . $type . '" id="'
908
+ . $element['#id'] . '" name="' . $element['#name'] . '" value="';
909
+ $element['_render']['element'] .= isset($element['#value']) ? $element['#value'] : $title;
910
+ $element['_render']['element'] .= '"' . $element['_attributes_string']
911
+ . ' />';
912
+ $pattern = isset($element['#pattern']) ? $element['#pattern'] : '<BEFORE><PREFIX><ELEMENT><SUFFIX><AFTER>';
913
+ $output = $this->_pattern($pattern, $element);
914
+ return $output;
915
+ }
916
+
917
+ /**
918
+ * Searches and returns submitted data for element.
919
+ *
920
+ * @param type $element
921
+ * @return type mixed
922
+ */
923
+ public function getSubmittedData($element)
924
+ {
925
+ $name = $element['#name'];
926
+ if (strpos($name, '[') === false) {
927
+ if ($element['#type'] == 'file') {
928
+ return $_FILES[$name]['tmp_name'];
929
+ }
930
+ return isset($_REQUEST[$name]) ? $_REQUEST[$name] : in_array($element['#type'],
931
+ array('textfield', 'textarea')) ? '' : 0;
932
+ }
933
+
934
+ $parts = explode('[', $name);
935
+ $parts = array_map(create_function('&$a', 'return trim($a, \']\');'),
936
+ $parts);
937
+ if (!isset($_REQUEST[$parts[0]])) {
938
+ return in_array($element['#type'],
939
+ array('textfield', 'textarea')) ? '' : 0;
940
+ }
941
+ $search = $_REQUEST[$parts[0]];
942
+ for ($index = 0; $index < count($parts); $index++) {
943
+ $key = $parts[$index];
944
+ // We're at the end but no data retrieved
945
+ if (!isset($parts[$index + 1])) {
946
+ return in_array($element['#type'],
947
+ array('textfield', 'textarea')) ? '' : 0;
948
+ }
949
+ $key_next = $parts[$index + 1];
950
+ if ($index > 0) {
951
+ if (!isset($search[$key])) {
952
+ return in_array($element['#type'],
953
+ array('textfield', 'textarea')) ? '' : 0;
954
+ } else {
955
+ $search = $search[$key];
956
+ }
957
+ }
958
+ if (is_array($search) && array_key_exists($key_next, $search)) {
959
+ if (!is_array($search[$key_next])) {
960
+ return $search[$key_next];
961
+ }
962
+ }
963
+ }
964
+ return 0;
965
+ }
966
+
967
+ }
968
+
969
+ }
embedded/common/classes/validate.php ADDED
@@ -0,0 +1,425 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once dirname(__FILE__) . '/validation-cakephp.php';
3
+
4
+ /**
5
+ * Validation class
6
+ *
7
+ * @version 1.0
8
+ */
9
+
10
+ if(!class_exists('Wpcf_Validate')) {
11
+ class Wpcf_Validate
12
+ {
13
+
14
+ /**
15
+ * Holds generic messages.
16
+ * @var type
17
+ */
18
+ public static $messages = null;
19
+ /**
20
+ * Holds function names.
21
+ * @var type
22
+ */
23
+ private static $_cake_aliases = array(
24
+ 'digits' => 'numeric',
25
+ 'number' => 'numeric',
26
+ 'alphanumeric' => 'alphaNumericWhitespaces',
27
+ 'nospecialchars' => 'noSpecialChars',
28
+ );
29
+ /**
30
+ * Current validation has 'required' method.
31
+ * @var type
32
+ */
33
+ private static $_is_required = false;
34
+
35
+ private static $_validation_object = null;
36
+
37
+ /**
38
+ * Sets calls.
39
+ *
40
+ * @param type $args
41
+ * @param type $value
42
+ * @return type
43
+ */
44
+ public static function check($args, $value)
45
+ {
46
+ // Init validation object
47
+ if (is_null(self::$_validation_object)) {
48
+ self::$_validation_object = new Wpcf_Cake_Validation();
49
+ }
50
+
51
+ // Init messages
52
+ if (is_null(self::$messages)) {
53
+ self::_set_messages();
54
+ }
55
+ // Check if there is 'required' method
56
+ if (array_key_exists('required', $args)) {
57
+ self::$_is_required = true;
58
+ }
59
+
60
+ // Loop over validation array
61
+ foreach ($args as $method => $v) {
62
+ // Use this class method
63
+ if (is_callable(array('Wpcf_Validate', $method))) {
64
+ $check = call_user_func_array(array('Wpcf_Validate', $method),
65
+ array($v, $value));
66
+ // Use CakePHP method
67
+ } else if ((isset(self::$_cake_aliases[$method])
68
+ && is_callable(array('Wpcf_Cake_Validation', self::$_cake_aliases[$method])))
69
+ || is_callable(array('Wpcf_Cake_Validation', $method))) {
70
+
71
+ // Check if validation pattern is set
72
+ if (isset($v['pattern'])) {
73
+ $pattern = array_flip(explode('.', $v['pattern']));
74
+ foreach ($pattern as $arg_key => $arg_value) {
75
+ if (isset($v[$arg_key])) {
76
+ $pattern[$arg_key] = $v[$arg_key];
77
+ }
78
+ }
79
+ $pattern['check'] = $value;
80
+ $v = $pattern;
81
+ // Apply simple pattern (check, value)
82
+ } else {
83
+ unset($v['active'], $v['message']);
84
+ $v = array($value) + $v;
85
+ }
86
+
87
+ // Validate
88
+ if (isset(self::$_cake_aliases[$method]) && is_callable(array('Wpcf_Cake_Validation', self::$_cake_aliases[$method]))) {
89
+ // $check = @call_user_func_array(array('Wpcf_Cake_Validation', self::$_cake_aliases[$method]),
90
+ // array_values($v));
91
+ $check = @call_user_func_array(array(self::$_validation_object, self::$_cake_aliases[$method]),
92
+ array_values($v));
93
+ } else {
94
+ // $check = @call_user_func_array(array('Wpcf_Cake_Validation', $method),
95
+ // array_values($v));
96
+ $check = @call_user_func_array(array(self::$_validation_object, $method),
97
+ array_values($v));
98
+ }
99
+ if (!$check) {
100
+ $check = array();
101
+ $check['error'] = 1;
102
+ }
103
+ // No method available
104
+ } else {
105
+ return array('error' => 1, 'message' => 'No validation method');
106
+ }
107
+
108
+ // Set error
109
+ if (isset($check['error'])) {
110
+ // Don't return error if it's empty but not required
111
+ if ((!empty($value) && $method != 'required' && self::$_is_required)
112
+ || (empty($value) && $method == 'required')) {
113
+ $check['message'] = !empty($v['message']) ? $v['message'] : self::$messages[$method];
114
+ return $check;
115
+ }
116
+ }
117
+ }
118
+
119
+ return true;
120
+ }
121
+
122
+ /**
123
+ * Checks if method is available.
124
+ *
125
+ * @param type $method
126
+ * @return type
127
+ */
128
+ public static function canValidate($method)
129
+ {
130
+ return (is_callable(array('Wpcf_Validate', $method))
131
+ || (isset(self::$_cake_aliases[$method])
132
+ && is_callable(array('Wpcf_Cake_Validation', self::$_cake_aliases[$method])))
133
+ || is_callable(array('Wpcf_Cake_Validation', $method)));
134
+ }
135
+
136
+ /**
137
+ * Checks if method has form data.
138
+ *
139
+ * @param type $method
140
+ * @return type
141
+ */
142
+ public static function hasForm($method)
143
+ {
144
+ return is_callable(array('Wpcf_Validate', $method . '_form'));
145
+ }
146
+
147
+ /**
148
+ * Inits messages.
149
+ */
150
+ private static function _set_messages()
151
+ {
152
+ // Set outside in /admin.php
153
+ self::$messages = wpcf_admin_validation_messages();
154
+ }
155
+
156
+ /**
157
+ * Return method invalid message.
158
+ *
159
+ * @param type $method
160
+ * @return type
161
+ */
162
+ public static function get_message($method)
163
+ {
164
+ if (is_null(self::$messages)) {
165
+ self::_set_messages();
166
+ }
167
+ if (isset(self::$messages[$method])) {
168
+ return self::$messages[$method];
169
+ }
170
+ return null;
171
+ }
172
+
173
+ /**
174
+ * Checks 'required'.
175
+ *
176
+ * @param type $args
177
+ * @param type $value
178
+ * @return type
179
+ */
180
+ public static function required($args, $value)
181
+ {
182
+ if (empty($value) && $value !== 0 && $value !== '0') {
183
+ return array(
184
+ 'error' => 1,
185
+ );
186
+ }
187
+ return true;
188
+ }
189
+
190
+ /**
191
+ * Returns form data.
192
+ *
193
+ * @param type $field
194
+ * @param type $data
195
+ * @return array
196
+ */
197
+ public static function required_form($field, $data = array())
198
+ {
199
+ $form = array();
200
+ $form['required-checkbox'] = array(
201
+ '#type' => 'checkbox',
202
+ '#title' => __('Required', 'wpcf'),
203
+ '#name' => $field['#name'] . '[active]',
204
+ '#default_value' => isset($data['active']) ? 1 : 0,
205
+ '#inline' => true,
206
+ '#suffix' => '<br />',
207
+ );
208
+ $form['required-value'] = array(
209
+ '#type' => 'hidden',
210
+ '#value' => 'true',
211
+ '#name' => $field['#name'] . '[value]',
212
+ );
213
+ $form['required-message'] = self::get_custom_message($field,
214
+ self::get_message('required'), $data);
215
+ return $form;
216
+ }
217
+
218
+ /**
219
+ * Checks 'email'.
220
+ *
221
+ * @param type $args
222
+ * @param type $value
223
+ * @return type
224
+ */
225
+ public static function email($args, $value)
226
+ {
227
+ if (!is_email($value)) {
228
+ return array(
229
+ 'error' => 1,
230
+ );
231
+ }
232
+ return true;
233
+ }
234
+
235
+ /**
236
+ * Checks 'rewriteslug'.
237
+ *
238
+ * @param type $args
239
+ * @param type $value
240
+ * @return type
241
+ */
242
+ public static function rewriteslug($args, $value)
243
+ {
244
+ if (preg_match('#[^a-zA-Z0-9\/\_\-\%]#', $value) === false) {
245
+ return array(
246
+ 'error' => 1,
247
+ );
248
+ }
249
+ return true;
250
+ }
251
+
252
+ /**
253
+ * Returns form data.
254
+ *
255
+ * @param type $field
256
+ * @param type $data
257
+ * @return array
258
+ */
259
+ public static function email_form($field, $data = array())
260
+ {
261
+ $form = array();
262
+ $form['email-checkbox'] = array(
263
+ '#type' => 'checkbox',
264
+ '#title' => __('Email', 'wpcf'),
265
+ '#name' => $field['#name'] . '[active]',
266
+ '#default_value' => isset($data['active']) ? 1 : 0,
267
+ '#inline' => true,
268
+ '#suffix' => '<br />',
269
+ );
270
+
271
+ $form['email-message'] = self::get_custom_message($field,
272
+ self::get_message('email'), $data);
273
+ return $form;
274
+ }
275
+
276
+ /**
277
+ * Returns form data.
278
+ *
279
+ * @param type $field
280
+ * @param type $data
281
+ * @return array
282
+ */
283
+ public static function url_form($field, $data = array())
284
+ {
285
+ $form = array();
286
+ $form['url-checkbox'] = array(
287
+ '#type' => 'checkbox',
288
+ '#title' => 'URL',
289
+ '#name' => $field['#name'] . '[active]',
290
+ '#default_value' => isset($data['active']) ? 1 : 0,
291
+ '#inline' => true,
292
+ '#suffix' => '<br />',
293
+ );
294
+
295
+ $form['url-message'] = self::get_custom_message($field,
296
+ self::get_message('url'), $data);
297
+ return $form;
298
+ }
299
+
300
+ /**
301
+ * Returns form data.
302
+ *
303
+ * @param type $field
304
+ * @param type $data
305
+ * @return array
306
+ */
307
+ public static function date_form($field, $data = array())
308
+ {
309
+ $form = array();
310
+ $form['date-checkbox'] = array(
311
+ '#type' => 'checkbox',
312
+ '#title' => __('Date', 'wpcf'),
313
+ '#name' => $field['#name'] . '[active]',
314
+ '#default_value' => isset($data['active']) ? 1 : 0,
315
+ '#inline' => true,
316
+ '#suffix' => '<br />',
317
+ );
318
+ $form['date-format'] = array(
319
+ '#type' => 'hidden',
320
+ '#value' => 'mdy',
321
+ '#name' => $field['#name'] . '[format]',
322
+ );
323
+ $form['date-pattern'] = array(
324
+ '#type' => 'hidden',
325
+ '#value' => 'check.format',
326
+ '#name' => $field['#name'] . '[pattern]',
327
+ );
328
+ $form['url-message'] = self::get_custom_message($field,
329
+ self::get_message('date'), $data);
330
+ return $form;
331
+ }
332
+
333
+ /**
334
+ * Returns form data.
335
+ *
336
+ * @param type $field
337
+ * @param type $data
338
+ * @return array
339
+ */
340
+ public static function digits_form($field, $data = array())
341
+ {
342
+ $form = array();
343
+ $attributes = array();
344
+ $default_value = isset($data['active']) ? 1 : 0;
345
+ $form['digits-checkbox'] = array(
346
+ '#type' => 'checkbox',
347
+ '#title' => __('Digits', 'wpcf'),
348
+ '#name' => $field['#name'] . '[active]',
349
+ '#default_value' => $default_value,
350
+ '#inline' => true,
351
+ '#suffix' => '<br />',
352
+ '#attributes' => $attributes,
353
+ );
354
+ $form['digits-checkbox'] = self::setForced($form['digits-checkbox'], $field, $data);
355
+
356
+ $form['digits-message'] = self::get_custom_message($field,
357
+ self::get_message('digits'), $data);
358
+ return $form;
359
+ }
360
+
361
+ /**
362
+ * Returns form data.
363
+ *
364
+ * @param type $field
365
+ * @param type $data
366
+ * @return array
367
+ */
368
+ public static function number_form($field, $data = array())
369
+ {
370
+ $form = array();
371
+ $attributes = array();
372
+ $default_value = isset($data['active']) ? 1 : 0;
373
+ $form['number-checkbox'] = array(
374
+ '#type' => 'checkbox',
375
+ '#title' => __('Numeric', 'wpcf'),
376
+ '#name' => $field['#name'] . '[active]',
377
+ '#default_value' => $default_value,
378
+ '#inline' => true,
379
+ '#suffix' => '<br />',
380
+ '#attributes' => $attributes,
381
+ );
382
+ $form['number-checkbox'] = self::setForced($form['number-checkbox'], $field, $data);
383
+
384
+ $form['number-message'] = self::get_custom_message($field,
385
+ self::get_message('number'), $data);
386
+ return $form;
387
+ }
388
+
389
+ public static function setForced($element, $field, $data = array())
390
+ {
391
+ $attributes = array();
392
+ $default_value = isset($data['active']) ? 1 : 0;
393
+ if (!empty($data['method_data']['forced'])) {
394
+ if (!isset($element['#attributes'])) {
395
+ $element['#attributes'] = array();
396
+ }
397
+ $element['#attributes']['readonly'] = 'readonly';
398
+ $element['#attributes']['onclick'] = 'jQuery(this).attr(\'checked\', \'checked\');';
399
+ $element['#default_value'] = 1;
400
+ }
401
+ return $element;
402
+ }
403
+
404
+ /**
405
+ * Returns 'custom message' field.
406
+ *
407
+ * @param type $field
408
+ * @param type $default
409
+ * @param type $data
410
+ * @return type
411
+ */
412
+ public static function get_custom_message($field, $default, $data)
413
+ {
414
+ return array(
415
+ '#type' => 'textfield',
416
+ // '#title' => __('Custom message', 'wpcf'),
417
+ '#name' => $field['#name'] . '[message]',
418
+ '#value' => !empty($data['message']) ? $data['message'] : $default,
419
+ '#inline' => true,
420
+ // '#suffix' => '<br /><br />',
421
+ );
422
+ }
423
+
424
+ }
425
+ }
embedded/common/classes/validation-cakephp.php ADDED
@@ -0,0 +1,1126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ if(!class_exists('Wpcf_Cake_Validation')) {
33
+ class Wpcf_Cake_Validation
34
+ {
35
+
36
+ /**
37
+ * Set the value of methods $check param.
38
+ *
39
+ * @var string
40
+ * @access public
41
+ */
42
+ var $check = null;
43
+
44
+ /**
45
+ * Set to a valid regular expression in the class methods.
46
+ * Can be set from $regex param also
47
+ *
48
+ * @var string
49
+ * @access public
50
+ */
51
+ var $regex = null;
52
+
53
+ /**
54
+ * Some complex patterns needed in multiple places
55
+ *
56
+ * @var array
57
+ * @access private
58
+ */
59
+ var $__pattern = array(
60
+ 'hostname' => '(?:[a-z0-9][-a-z0-9]*\.)*(?:[a-z0-9][-a-z0-9]{0,62})\.(?:(?:[a-z]{2}\.)?[a-z]{2,4}|museum|travel)'
61
+ );
62
+
63
+ /**
64
+ * Some class methods use a country to determine proper validation.
65
+ * This can be passed to methods in the $country param
66
+ *
67
+ * @var string
68
+ * @access public
69
+ */
70
+ var $country = null;
71
+
72
+ /**
73
+ * Some class methods use a deeper validation when set to true
74
+ *
75
+ * @var string
76
+ * @access public
77
+ */
78
+ var $deep = null;
79
+
80
+ /**
81
+ * Some class methods use the $type param to determine which validation to perfom in the method
82
+ *
83
+ * @var string
84
+ * @access public
85
+ */
86
+ var $type = null;
87
+
88
+ /**
89
+ * Holds an array of errors messages set in this class.
90
+ * These are used for debugging purposes
91
+ *
92
+ * @var array
93
+ * @access public
94
+ */
95
+ var $errors = array();
96
+
97
+ /**
98
+ * Gets a reference to the Validation object instance
99
+ *
100
+ * @return object Validation instance
101
+ * @access public
102
+ * @static
103
+ */
104
+ function &getInstance() {
105
+ static $instance = array();
106
+
107
+ if (!$instance) {
108
+ $instance[0] = new Wpcf_Cake_Validation();
109
+ }
110
+ return $instance[0];
111
+ }
112
+
113
+ /**
114
+ * Checks that a string contains something other than whitespace
115
+ *
116
+ * Returns true if string contains something other than whitespace
117
+ *
118
+ * $check can be passed as an array:
119
+ * array('check' => 'valueToCheck');
120
+ *
121
+ * @param mixed $check Value to check
122
+ * @return boolean Success
123
+ * @access public
124
+ */
125
+ function notEmpty($check) {
126
+ $_this = & Wpcf_Cake_Validation::getInstance();
127
+ $_this->__reset();
128
+ $_this->check = $check;
129
+
130
+ if (is_array($check)) {
131
+ $_this->_extract($check);
132
+ }
133
+
134
+ if (empty($_this->check) && $_this->check != '0') {
135
+ return false;
136
+ }
137
+ $_this->regex = '/[^\s]+/m';
138
+ return $_this->_check();
139
+ }
140
+
141
+ /**
142
+ * Checks that a string contains only integer or letters
143
+ *
144
+ * Returns true if string contains only integer or letters
145
+ *
146
+ * $check can be passed as an array:
147
+ * array('check' => 'valueToCheck');
148
+ *
149
+ * @param mixed $check Value to check
150
+ * @return boolean Success
151
+ * @access public
152
+ */
153
+ function alphaNumeric($check) {
154
+ $_this = & Wpcf_Cake_Validation::getInstance();
155
+ $_this->__reset();
156
+ $_this->check = $check;
157
+
158
+ if (is_array($check)) {
159
+ $_this->_extract($check);
160
+ }
161
+
162
+ if (empty($_this->check) && $_this->check != '0') {
163
+ return false;
164
+ }
165
+ $_this->regex = '/^[a-zA-Z0-9]*$/mu';
166
+ $return = $_this->_check();
167
+
168
+ if (!$return) {
169
+ $_this->regex = '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]+$/mu';
170
+ $return = $_this->_check();
171
+ }
172
+
173
+ return $_this->_check();
174
+ }
175
+
176
+ function alphaNumericWhitespaces($check) {
177
+ $_this = & Wpcf_Cake_Validation::getInstance();
178
+ $_this->__reset();
179
+ $_this->check = $check;
180
+
181
+ if (is_array($check)) {
182
+ $_this->_extract($check);
183
+ }
184
+
185
+ if (empty($_this->check) && $_this->check != '0') {
186
+ return false;
187
+ }
188
+ $_this->regex = '/^[a-zA-Z0-9\s\-\_]*$/mu';
189
+ $return = $_this->_check();
190
+
191
+ if (!$return) {
192
+ $_this->regex = '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}\s\-\_]+$/mu';
193
+ $return = $_this->_check();
194
+ }
195
+
196
+ return $return;
197
+ }
198
+
199
+ /**
200
+ * Checks that a string length is within s specified range.
201
+ * Spaces are included in the character count.
202
+ * Returns true is string matches value min, max, or between min and max,
203
+ *
204
+ * @param string $check Value to check for length
205
+ * @param integer $min Minimum value in range (inclusive)
206
+ * @param integer $max Maximum value in range (inclusive)
207
+ * @return boolean Success
208
+ * @access public
209
+ */
210
+ function between($check, $min, $max) {
211
+ $length = strlen($check);
212
+ return ($length >= $min && $length <= $max);
213
+ }
214
+
215
+ /**
216
+ * Returns true if field is left blank -OR- only whitespace characters are present in it's value
217
+ * Whitespace characters include Space, Tab, Carriage Return, Newline
218
+ *
219
+ * $check can be passed as an array:
220
+ * array('check' => 'valueToCheck');
221
+ *
222
+ * @param mixed $check Value to check
223
+ * @return boolean Success
224
+ * @access public
225
+ */
226
+ function blank($check) {
227
+ $_this = & Wpcf_Cake_Validation::getInstance();
228
+ $_this->__reset();
229
+ $_this->check = $check;
230
+
231
+ if (is_array($check)) {
232
+ $_this->_extract($check);
233
+ }
234
+
235
+ $_this->regex = '/[^\\s]/';
236
+ return!$_this->_check();
237
+ }
238
+
239
+ /**
240
+ * Validation of credit card numbers.
241
+ * Returns true if $check is in the proper credit card format.
242
+ *
243
+ * @param mixed $check credit card number to validate
244
+ * @param mixed $type 'all' may be passed as a sting, defaults to fast which checks format of most major credit cards
245
+ * if an array is used only the values of the array are checked.
246
+ * Example: array('amex', 'bankcard', 'maestro')
247
+ * @param boolean $deep set to true this will check the Luhn algorithm of the credit card.
248
+ * @param string $regex A custom regex can also be passed, this will be used instead of the defined regex values
249
+ * @return boolean Success
250
+ * @access public
251
+ * @see Wpcf_Cake_Validation::_luhn()
252
+ */
253
+ function cc($check, $type = 'fast', $deep = false, $regex = null) {
254
+ $_this = & Wpcf_Cake_Validation::getInstance();
255
+ $_this->__reset();
256
+ $_this->check = $check;
257
+ $_this->type = $type;
258
+ $_this->deep = $deep;
259
+ $_this->regex = $regex;
260
+
261
+ if (is_array($check)) {
262
+ $_this->_extract($check);
263
+ }
264
+ $_this->check = str_replace(array('-', ' '), '', $_this->check);
265
+
266
+ if (strlen($_this->check) < 13) {
267
+ return false;
268
+ }
269
+
270
+ if (!is_null($_this->regex)) {
271
+ if ($_this->_check()) {
272
+ return $_this->_luhn();
273
+ }
274
+ }
275
+ $cards = array(
276
+ 'all' => array(
277
+ 'amex' => '/^3[4|7]\\d{13}$/',
278
+ 'bankcard' => '/^56(10\\d\\d|022[1-5])\\d{10}$/',
279
+ 'diners' => '/^(?:3(0[0-5]|[68]\\d)\\d{11})|(?:5[1-5]\\d{14})$/',
280
+ 'disc' => '/^(?:6011|650\\d)\\d{12}$/',
281
+ 'electron' => '/^(?:417500|4917\\d{2}|4913\\d{2})\\d{10}$/',
282
+ 'enroute' => '/^2(?:014|149)\\d{11}$/',
283
+ 'jcb' => '/^(3\\d{4}|2100|1800)\\d{11}$/',
284
+ 'maestro' => '/^(?:5020|6\\d{3})\\d{12}$/',
285
+ 'mc' => '/^5[1-5]\\d{14}$/',
286
+ 'solo' => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/',
287
+ '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})?)$/',
288
+ 'visa' => '/^4\\d{12}(\\d{3})?$/',
289
+ 'voyager' => '/^8699[0-9]{11}$/'
290
+ ),
291
+ '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})$/'
292
+ );
293
+
294
+ if (is_array($_this->type)) {
295
+ foreach ($_this->type as $value) {
296
+ $_this->regex = $cards['all'][strtolower($value)];
297
+
298
+ if ($_this->_check()) {
299
+ return $_this->_luhn();
300
+ }
301
+ }
302
+ } elseif ($_this->type == 'all') {
303
+ foreach ($cards['all'] as $value) {
304
+ $_this->regex = $value;
305
+
306
+ if ($_this->_check()) {
307
+ return $_this->_luhn();
308
+ }
309
+ }
310
+ } else {
311
+ $_this->regex = $cards['fast'];
312
+
313
+ if ($_this->_check()) {
314
+ return $_this->_luhn();
315
+ }
316
+ }
317
+ }
318
+
319
+ /**
320
+ * Used to compare 2 numeric values.
321
+ *
322
+ * @param mixed $check1 if string is passed for a string must also be passed for $check2
323
+ * used as an array it must be passed as array('check1' => value, 'operator' => 'value', 'check2' -> value)
324
+ * @param string $operator Can be either a word or operand
325
+ * is greater >, is less <, greater or equal >=
326
+ * less or equal <=, is less <, equal to ==, not equal !=
327
+ * @param integer $check2 only needed if $check1 is a string
328
+ * @return boolean Success
329
+ * @access public
330
+ */
331
+ function comparison($check1, $operator = null, $check2 = null) {
332
+ if (is_array($check1)) {
333
+ extract($check1, EXTR_OVERWRITE);
334
+ }
335
+ $operator = str_replace(array(' ', "\t", "\n", "\r", "\0", "\x0B"), '',
336
+ strtolower($operator));
337
+
338
+ switch ($operator) {
339
+ case 'isgreater':
340
+ case '>':
341
+ if ($check1 > $check2) {
342
+ return true;
343
+ }
344
+ break;
345
+ case 'isless':
346
+ case '<':
347
+ if ($check1 < $check2) {
348
+ return true;
349
+ }
350
+ break;
351
+ case 'greaterorequal':
352
+ case '>=':
353
+ if ($check1 >= $check2) {
354
+ return true;
355
+ }
356
+ break;
357
+ case 'lessorequal':
358
+ case '<=':
359
+ if ($check1 <= $check2) {
360
+ return true;
361
+ }
362
+ break;
363
+ case 'equalto':
364
+ case '==':
365
+ if ($check1 == $check2) {
366
+ return true;
367
+ }
368
+ break;
369
+ case 'notequal':
370
+ case '!=':
371
+ if ($check1 != $check2) {
372
+ return true;
373
+ }
374
+ break;
375
+ default:
376
+ $_this = & Wpcf_Cake_Validation::getInstance();
377
+ $_this->errors[] = __('You must define the $operator parameter for Wpcf_Cake_Validation::comparison()',
378
+ 'wpcf');
379
+ break;
380
+ }
381
+ return false;
382
+ }
383
+
384
+ /**
385
+ * Used when a custom regular expression is needed.
386
+ *
387
+ * @param mixed $check When used as a string, $regex must also be a valid regular expression.
388
+ * As and array: array('check' => value, 'regex' => 'valid regular expression')
389
+ * @param string $regex If $check is passed as a string, $regex must also be set to valid regular expression
390
+ * @return boolean Success
391
+ * @access public
392
+ */
393
+ function custom($check, $regex = null) {
394
+ $_this = & Wpcf_Cake_Validation::getInstance();
395
+ $_this->__reset();
396
+ $_this->check = $check;
397
+ $_this->regex = $regex;
398
+ if (is_array($check)) {
399
+ $_this->_extract($check);
400
+ }
401
+ if ($_this->regex === null) {
402
+ $_this->errors[] = __('You must define a regular expression for Wpcf_Cake_Validation::custom()',
403
+ 'wpcf');
404
+ return false;
405
+ }
406
+ return $_this->_check();
407
+ }
408
+
409
+ /**
410
+ * Date validation, determines if the string passed is a valid date.
411
+ * keys that expect full month, day and year will validate leap years
412
+ *
413
+ * @param string $check a valid date string
414
+ * @param mixed $format Use a string or an array of the keys below. Arrays should be passed as array('dmy', 'mdy', etc)
415
+ * Keys: dmy 27-12-2006 or 27-12-06 separators can be a space, period, dash, forward slash
416
+ * mdy 12-27-2006 or 12-27-06 separators can be a space, period, dash, forward slash
417
+ * ymd 2006-12-27 or 06-12-27 separators can be a space, period, dash, forward slash
418
+ * dMy 27 December 2006 or 27 Dec 2006
419
+ * Mdy December 27, 2006 or Dec 27, 2006 comma is optional
420
+ * My December 2006 or Dec 2006
421
+ * my 12/2006 separators can be a space, period, dash, forward slash
422
+ * @param string $regex If a custom regular expression is used this is the only validation that will occur.
423
+ * @return boolean Success
424
+ * @access public
425
+ */
426
+ function date($check, $format = 'ymd', $regex = null) {
427
+
428
+ $date_format = wpcf_get_date_format();
429
+ $cake_date_formats = array(
430
+ 'F j, Y' => 'Mdy',
431
+ 'Y/m/d' => 'ymd',
432
+ 'm/d/Y' => 'mdy',
433
+ 'd/m/Y' => 'dmy',
434
+ 'd/m/y' => 'dmy',
435
+ );
436
+
437
+ $format = $cake_date_formats[$date_format];
438
+
439
+ $_this = & Wpcf_Cake_Validation::getInstance();
440
+ $_this->__reset();
441
+ $_this->check = $check;
442
+ $_this->regex = $regex;
443
+
444
+ if (!is_null($_this->regex)) {
445
+ return $_this->_check();
446
+ }
447
+
448
+ $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})$%';
449
+ $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})$%';
450
+ $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]))))$%';
451
+ $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})$/';
452
+ $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}))$/';
453
+ $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})$%';
454
+ $regex['my'] = '%^(((0[123456789]|10|11|12)([- /.])(([1][9][0-9][0-9])|([2][0-9][0-9][0-9]))))$%';
455
+
456
+ $format = (is_array($format)) ? array_values($format) : array($format);
457
+ foreach ($format as $key) {
458
+ $_this->regex = $regex[$key];
459
+
460
+ if ($_this->_check() === true) {
461
+ return true;
462
+ }
463
+ }
464
+ return false;
465
+ }
466
+
467
+ /**
468
+ * Time validation, determines if the string passed is a valid time.
469
+ * Validates time as 24hr (HH:MM) or am/pm ([H]H:MM[a|p]m)
470
+ * Does not allow/validate seconds.
471
+ *
472
+ * @param string $check a valid time string
473
+ * @return boolean Success
474
+ * @access public
475
+ */
476
+ function time($check) {
477
+ $_this = & Wpcf_Cake_Validation::getInstance();
478
+ $_this->__reset();
479
+ $_this->check = $check;
480
+ $_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}$%';
481
+ return $_this->_check();
482
+ }
483
+
484
+ /**
485
+ * Boolean validation, determines if value passed is a boolean integer or true/false.
486
+ *
487
+ * @param string $check a valid boolean
488
+ * @return boolean Success
489
+ * @access public
490
+ */
491
+ function boolean($check) {
492
+ $booleanList = array(0, 1, '0', '1', true, false);
493
+ return in_array($check, $booleanList, true);
494
+ }
495
+
496
+ /**
497
+ * Checks that a value is a valid decimal. If $places is null, the $check is allowed to be a scientific float
498
+ * If no decimal point is found a false will be returned. Both the sign and exponent are optional.
499
+ *
500
+ * @param integer $check The value the test for decimal
501
+ * @param integer $places if set $check value must have exactly $places after the decimal point
502
+ * @param string $regex If a custom regular expression is used this is the only validation that will occur.
503
+ * @return boolean Success
504
+ * @access public
505
+ */
506
+ function decimal($check, $places = null, $regex = null) {
507
+ $_this = & Wpcf_Cake_Validation::getInstance();
508
+ $_this->__reset();
509
+ $_this->regex = $regex;
510
+ $_this->check = $check;
511
+
512
+ if (is_null($_this->regex)) {
513
+ if (is_null($places)) {
514
+ $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]+(?:[eE][-+]?[0-9]+)?$/';
515
+ } else {
516
+ $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]{' . $places . '}$/';
517
+ }
518
+ }
519
+ return $_this->_check();
520
+ }
521
+
522
+ /**
523
+ * Validates for an email address.
524
+ *
525
+ * @param string $check Value to check
526
+ * @param boolean $deep Perform a deeper validation (if true), by also checking availability of host
527
+ * @param string $regex Regex to use (if none it will use built in regex)
528
+ * @return boolean Success
529
+ * @access public
530
+ */
531
+ function email($check, $deep = false, $regex = null) {
532
+ $_this = & Wpcf_Cake_Validation::getInstance();
533
+ $_this->__reset();
534
+ $_this->check = $check;
535
+ $_this->regex = $regex;
536
+ $_this->deep = $deep;
537
+
538
+ if (is_array($check)) {
539
+ $_this->_extract($check);
540
+ }
541
+
542
+ if (is_null($_this->regex)) {
543
+ $_this->regex = '/^[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@' . $_this->__pattern['hostname'] . '$/i';
544
+ }
545
+ $return = $_this->_check();
546
+
547
+ if ($_this->deep === false || $_this->deep === null) {
548
+ return $return;
549
+ }
550
+
551
+ if ($return === true && preg_match('/@(' . $_this->__pattern['hostname'] . ')$/i',
552
+ $_this->check, $regs)) {
553
+ if (function_exists('getmxrr') && getmxrr($regs[1], $mxhosts)) {
554
+ return true;
555
+ }
556
+ if (function_exists('checkdnsrr') && checkdnsrr($regs[1], 'MX')) {
557
+ return true;
558
+ }
559
+ return is_array(gethostbynamel($regs[1]));
560
+ }
561
+ return false;
562
+ }
563
+
564
+ /**
565
+ * Check that value is exactly $comparedTo.
566
+ *
567
+ * @param mixed $check Value to check
568
+ * @param mixed $comparedTo Value to compare
569
+ * @return boolean Success
570
+ * @access public
571
+ */
572
+ function equalTo($check, $comparedTo) {
573
+ return ($check === $comparedTo);
574
+ }
575
+
576
+ /**
577
+ * Check that value has a valid file extension.
578
+ *
579
+ * @param mixed $check Value to check
580
+ * @param array $extensions file extenstions to allow
581
+ * @return boolean Success
582
+ * @access public
583
+ */
584
+ function extension($check, $extensions = array('gif', 'jpeg', 'png', 'jpg')) {
585
+ if (is_array($check)) {
586
+ return Wpcf_Cake_Validation::extension(array_shift($check),
587
+ $extensions);
588
+ }
589
+ $extension = strtolower(array_pop(explode('.', $check)));
590
+ foreach ($extensions as $value) {
591
+ if ($extension == strtolower($value)) {
592
+ return true;
593
+ }
594
+ }
595
+ return false;
596
+ }
597
+
598
+ /**
599
+ * Validation of an IP address.
600
+ *
601
+ * Valid IP version strings for type restriction are:
602
+ * - both: Check both IPv4 and IPv6, return true if the supplied address matches either version
603
+ * - IPv4: Version 4 (Eg: 127.0.0.1, 192.168.10.123, 203.211.24.8)
604
+ * - IPv6: Version 6 (Eg: ::1, 2001:0db8::1428:57ab)
605
+ *
606
+ * @param string $check The string to test.
607
+ * @param string $type The IP Version to test against
608
+ * @return boolean Success
609
+ * @access public
610
+ */
611
+ function ip($check, $type = 'both') {
612
+ $_this = & Wpcf_Cake_Validation::getInstance();
613
+ $success = false;
614
+ $type = strtolower($type);
615
+ if ($type === 'ipv4' || $type === 'both') {
616
+ $success |= $_this->_ipv4($check);
617
+ }
618
+ if ($type === 'ipv6' || $type === 'both') {
619
+ $success |= $_this->_ipv6($check);
620
+ }
621
+ return $success;
622
+ }
623
+
624
+ /**
625
+ * Validation of IPv4 addresses.
626
+ *
627
+ * @param string $check IP Address to test
628
+ * @return boolean Success
629
+ * @access protected
630
+ */
631
+ function _ipv4($check) {
632
+ if (function_exists('filter_var')) {
633
+ return filter_var($check, FILTER_VALIDATE_IP,
634
+ array('flags' => FILTER_FLAG_IPV4)) !== false;
635
+ }
636
+ $this->__populateIp();
637
+ $this->check = $check;
638
+ $this->regex = '/^' . $this->__pattern['IPv4'] . '$/';
639
+ return $this->_check();
640
+ }
641
+
642
+ /**
643
+ * Validation of IPv6 addresses.
644
+ *
645
+ * @param string $check IP Address to test
646
+ * @return boolean Success
647
+ * @access protected
648
+ */
649
+ function _ipv6($check) {
650
+ if (function_exists('filter_var')) {
651
+ return filter_var($check, FILTER_VALIDATE_IP,
652
+ array('flags' => FILTER_FLAG_IPV6)) !== false;
653
+ }
654
+ $this->__populateIp();
655
+ $this->check = $check;
656
+ $this->regex = '/^' . $this->__pattern['IPv6'] . '$/';
657
+ return $this->_check();
658
+ }
659
+
660
+ /**
661
+ * Checks whether the length of a string is greater or equal to a minimal length.
662
+ *
663
+ * @param string $check The string to test
664
+ * @param integer $min The minimal string length
665
+ * @return boolean Success
666
+ * @access public
667
+ */
668
+ function minLength($check, $min) {
669
+ $length = strlen($check);
670
+ return ($length >= $min);
671
+ }
672
+
673
+ /**
674
+ * Checks whether the length of a string is smaller or equal to a maximal length..
675
+ *
676
+ * @param string $check The string to test
677
+ * @param integer $max The maximal string length
678
+ * @return boolean Success
679
+ * @access public
680
+ */
681
+ function maxLength($check, $max) {
682
+ $length = strlen($check);
683
+ return ($length <= $max);
684
+ }
685
+
686
+ /**
687
+ * Checks that a value is a monetary amount.
688
+ *
689
+ * @param string $check Value to check
690
+ * @param string $symbolPosition Where symbol is located (left/right)
691
+ * @return boolean Success
692
+ * @access public
693
+ */
694
+ function money($check, $symbolPosition = 'left') {
695
+ $_this = & Wpcf_Cake_Validation::getInstance();
696
+ $_this->check = $check;
697
+
698
+ if ($symbolPosition == 'right') {
699
+ $_this->regex = '/^(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?(?<!\x{00a2})\p{Sc}?$/u';
700
+ } else {
701
+ $_this->regex = '/^(?!\x{00a2})\p{Sc}?(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?$/u';
702
+ }
703
+ return $_this->_check();
704
+ }
705
+
706
+ /**
707
+ * Validate a multiple select.
708
+ *
709
+ * Valid Options
710
+ *
711
+ * - in => provide a list of choices that selections must be made from
712
+ * - max => maximun number of non-zero choices that can be made
713
+ * - min => minimum number of non-zero choices that can be made
714
+ *
715
+ * @param mixed $check Value to check
716
+ * @param mixed $options Options for the check.
717
+ * @return boolean Success
718
+ * @access public
719
+ */
720
+ function multiple($check, $options = array()) {
721
+ $defaults = array('in' => null, 'max' => null, 'min' => null);
722
+ $options = array_merge($defaults, $options);
723
+ $check = array_filter((array) $check);
724
+ if (empty($check)) {
725
+ return false;
726
+ }
727
+ if ($options['max'] && count($check) > $options['max']) {
728
+ return false;
729
+ }
730
+ if ($options['min'] && count($check) < $options['min']) {
731
+ return false;
732
+ }
733
+ if ($options['in'] && is_array($options['in'])) {
734
+ foreach ($check as $val) {
735
+ if (!in_array($val, $options['in'])) {
736
+ return false;
737
+ }
738
+ }
739
+ }
740
+ return true;
741
+ }
742
+
743
+ /**
744
+ * Checks if a value is numeric.
745
+ *
746
+ * @param string $check Value to check
747
+ * @return boolean Succcess
748
+ * @access public
749
+ */
750
+ function numeric($check) {
751
+ return is_numeric($check);
752
+ }
753
+
754
+ /**
755
+ * Check that a value is a valid phone number.
756
+ *
757
+ * @param mixed $check Value to check (string or array)
758
+ * @param string $regex Regular expression to use
759
+ * @param string $country Country code (defaults to 'all')
760
+ * @return boolean Success
761
+ * @access public
762
+ */
763
+ function phone($check, $regex = null, $country = 'all') {
764
+ $_this = & Wpcf_Cake_Validation::getInstance();
765
+ $_this->check = $check;
766
+ $_this->regex = $regex;
767
+ $_this->country = $country;
768
+ if (is_array($check)) {
769
+ $_this->_extract($check);
770
+ }
771
+
772
+ if (is_null($_this->regex)) {
773
+ switch ($_this->country) {
774
+ case 'us':
775
+ case 'all':
776
+ case 'can':
777
+ // includes all NANPA members. see http://en.wikipedia.org/wiki/North_American_Numbering_Plan#List_of_NANPA_countries_and_territories
778
+ $_this->regex = '/^(?:\+?1)?[-. ]?\\(?[2-9][0-8][0-9]\\)?[-. ]?[2-9][0-9]{2}[-. ]?[0-9]{4}$/';
779
+ break;
780
+ }
781
+ }
782
+ if (empty($_this->regex)) {
783
+ return $_this->_pass('phone', $check, $country);
784
+ }
785
+ return $_this->_check();
786
+ }
787
+
788
+ /**
789
+ * Checks that a given value is a valid postal code.
790
+ *
791
+ * @param mixed $check Value to check
792
+ * @param string $regex Regular expression to use
793
+ * @param string $country Country to use for formatting
794
+ * @return boolean Success
795
+ * @access public
796
+ */
797
+ function postal($check, $regex = null, $country = null) {
798
+ $_this = & Wpcf_Cake_Validation::getInstance();
799
+ $_this->check = $check;
800
+ $_this->regex = $regex;
801
+ $_this->country = $country;
802
+ if (is_array($check)) {
803
+ $_this->_extract($check);
804
+ }
805
+ if (empty($country)) {
806
+ $_this->country = 'us';
807
+ }
808
+
809
+ if (is_null($_this->regex)) {
810
+ switch ($_this->country) {
811
+ case 'uk':
812
+ $_this->regex = '/\\A\\b[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}\\b\\z/i';
813
+ break;
814
+ case 'ca':
815
+ $_this->regex = '/\\A\\b[ABCEGHJKLMNPRSTVXY][0-9][A-Z] ?[0-9][A-Z][0-9]\\b\\z/i';
816
+ break;
817
+ case 'it':
818
+ case 'de':
819
+ $_this->regex = '/^[0-9]{5}$/i';
820
+ break;
821
+ case 'be':
822
+ $_this->regex = '/^[1-9]{1}[0-9]{3}$/i';
823
+ break;
824
+ case 'us':
825
+ $_this->regex = '/\\A\\b[0-9]{5}(?:-[0-9]{4})?\\b\\z/i';
826
+ break;
827
+ }
828
+ }
829
+ if (empty($_this->regex)) {
830
+ return $_this->_pass('postal', $check, $country);
831
+ }
832
+ return $_this->_check();
833
+ }
834
+
835
+ /**
836
+ * Validate that a number is in specified range.
837
+ * if $lower and $upper are not set, will return true if
838
+ * $check is a legal finite on this platform
839
+ *
840
+ * @param string $check Value to check
841
+ * @param integer $lower Lower limit
842
+ * @param integer $upper Upper limit
843
+ * @return boolean Success
844
+ * @access public
845
+ */
846
+ function range($check, $lower = null, $upper = null) {
847
+ if (!is_numeric($check)) {
848
+ return false;
849
+ }
850
+ if (isset($lower) && isset($upper)) {
851
+ return ($check > $lower && $check < $upper);
852
+ }
853
+ return is_finite($check);
854
+ }
855
+
856
+ /**
857
+ * Checks that a value is a valid Social Security Number.
858
+ *
859
+ * @param mixed $check Value to check
860
+ * @param string $regex Regular expression to use
861
+ * @param string $country Country
862
+ * @return boolean Success
863
+ * @access public
864
+ */
865
+ function ssn($check, $regex = null, $country = null) {
866
+ $_this = & Wpcf_Cake_Validation::getInstance();
867
+ $_this->check = $check;
868
+ $_this->regex = $regex;
869
+ $_this->country = $country;
870
+ if (is_array($check)) {
871
+ $_this->_extract($check);
872
+ }
873
+
874
+ if (is_null($_this->regex)) {
875
+ switch ($_this->country) {
876
+ case 'dk':
877
+ $_this->regex = '/\\A\\b[0-9]{6}-[0-9]{4}\\b\\z/i';
878
+ break;
879
+ case 'nl':
880
+ $_this->regex = '/\\A\\b[0-9]{9}\\b\\z/i';
881
+ break;
882
+ case 'us':
883
+ $_this->regex = '/\\A\\b[0-9]{3}-[0-9]{2}-[0-9]{4}\\b\\z/i';
884
+ break;
885
+ }
886
+ }
887
+ if (empty($_this->regex)) {
888
+ return $_this->_pass('ssn', $check, $country);
889
+ }
890
+ return $_this->_check();
891
+ }
892
+
893
+ /**
894
+ * Checks that a value is a valid uuid - http://tools.ietf.org/html/rfc4122
895
+ *
896
+ * @param string $check Value to check
897
+ * @return boolean Success
898
+ * @access public
899
+ */
900
+ function uuid($check) {
901
+ $_this = & Wpcf_Cake_Validation::getInstance();
902
+ $_this->check = $check;
903
+ $_this->regex = '/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i';
904
+ return $_this->_check();
905
+ }
906
+
907
+ /**
908
+ * Checks that a value is a valid URL according to http://www.w3.org/Addressing/URL/url-spec.txt
909
+ *
910
+ * The regex checks for the following component parts:
911
+ *
912
+ * - a valid, optional, scheme
913
+ * - a valid ip address OR
914
+ * a valid domain name as defined by section 2.3.1 of http://www.ietf.org/rfc/rfc1035.txt
915
+ * with an optional port number
916
+ * - an optional valid path
917
+ * - an optional query string (get parameters)
918
+ * - an optional fragment (anchor tag)
919
+ *
920
+ * @param string $check Value to check
921
+ * @param boolean $strict Require URL to be prefixed by a valid scheme (one of http(s)/ftp(s)/file/news/gopher)
922
+ * @return boolean Success
923
+ * @access public
924
+ */
925
+ function url($check, $strict = false) {
926
+ $_this = & Wpcf_Cake_Validation::getInstance();
927
+ $_this->__populateIp();
928
+ $_this->check = $check;
929
+ $validChars = '([' . preg_quote('!"$&\'()*+,-.@_:;=~[]') . '\/0-9a-z\p{L}\p{N}]|(%[0-9a-f]{2}))';
930
+ $_this->regex = '/^(?:(?:https?|ftps?|file|news|gopher):\/\/)' . (!empty($strict) ? '' : '?') .
931
+ '(?:' . $_this->__pattern['IPv4'] . '|\[' . $_this->__pattern['IPv6'] . '\]|' . $_this->__pattern['hostname'] . ')' .
932
+ '(?::[1-9][0-9]{0,4})?' .
933
+ '(?:\/?|\/' . $validChars . '*)?' .
934
+ '(?:\?' . $validChars . '*)?' .
935
+ '(?:#' . $validChars . '*)?$/iu';
936
+ return $_this->_check();
937
+ }
938
+
939
+ /**
940
+ * Checks if a value is in a given list.
941
+ *
942
+ * @param string $check Value to check
943
+ * @param array $list List to check against
944
+ * @return boolean Succcess
945
+ * @access public
946
+ */
947
+ function inList($check, $list) {
948
+ return in_array($check, $list);
949
+ }
950
+
951
+ /**
952
+ * Runs an user-defined validation.
953
+ *
954
+ * @param mixed $check value that will be validated in user-defined methods.
955
+ * @param object $object class that holds validation method
956
+ * @param string $method class method name for validation to run
957
+ * @param array $args arguments to send to method
958
+ * @return mixed user-defined class class method returns
959
+ * @access public
960
+ */
961
+ function userDefined($check, $object, $method, $args = null) {
962
+ return call_user_func_array(array(&$object, $method),
963
+ array($check, $args));
964
+ }
965
+
966
+ function noSpecialChars($check) {
967
+ return preg_match('#[^a-zA-Z0-9\s\_\-]#', $check) ? false : true;
968
+ }
969
+
970
+ function rewriteSlug($check) {
971
+ return preg_match('#[^a-zA-Z0-9\s\_\-\%]#', $check) ? false : true;
972
+ }
973
+
974
+ /**
975
+ * Attempts to pass unhandled Validation locales to a class starting with $classPrefix
976
+ * and ending with Validation. For example $classPrefix = 'nl', the class would be
977
+ * `NlValidation`.
978
+ *
979
+ * @param string $method The method to call on the other class.
980
+ * @param mixed $check The value to check or an array of parameters for the method to be called.
981
+ * @param string $classPrefix The prefix for the class to do the validation.
982
+ * @return mixed Return of Passed method, false on failure
983
+ * @access protected
984
+ * */
985
+ function _pass($method, $check, $classPrefix) {
986
+ $className = ucwords($classPrefix) . 'Validation';
987
+ if (!class_exists($className)) {
988
+ trigger_error(sprintf(__('Could not find %s class, unable to complete validation.',
989
+ true), $className), E_USER_WARNING);
990
+ return false;
991
+ }
992
+ if (!is_callable(array($className, $method))) {
993
+ trigger_error(sprintf(__('Method %s does not exist on %s unable to complete validation.',
994
+ true), $method, $className), E_USER_WARNING);
995
+ return false;
996
+ }
997
+ $check = (array) $check;
998
+ return call_user_func_array(array($className, $method), $check);
999
+ }
1000
+
1001
+ /**
1002
+ * Runs a regular expression match.
1003
+ *
1004
+ * @return boolean Success of match
1005
+ * @access protected
1006
+ */
1007
+ function _check() {
1008
+ $_this = & Wpcf_Cake_Validation::getInstance();
1009
+ if (preg_match($_this->regex, $_this->check)) {
1010
+ $_this->error[] = false;
1011
+ return true;
1012
+ } else {
1013
+ $_this->error[] = true;
1014
+ return false;
1015
+ }
1016
+ }
1017
+
1018
+ /**
1019
+ * Get the values to use when value sent to validation method is
1020
+ * an array.
1021
+ *
1022
+ * @param array $params Parameters sent to validation method
1023
+ * @return void
1024
+ * @access protected
1025
+ */
1026
+ function _extract($params) {
1027
+ $_this = & Wpcf_Cake_Validation::getInstance();
1028
+ extract($params, EXTR_OVERWRITE);
1029
+
1030
+ if (isset($check)) {
1031
+ $_this->check = $check;
1032
+ }
1033
+ if (isset($regex)) {
1034
+ $_this->regex = $regex;
1035
+ }
1036
+ if (isset($country)) {
1037
+ $_this->country = strtolower($country);
1038
+ }
1039
+ if (isset($deep)) {
1040
+ $_this->deep = $deep;
1041
+ }
1042
+ if (isset($type)) {
1043
+ $_this->type = $type;
1044
+ }
1045
+ }
1046
+
1047
+ /**
1048
+ * Luhn algorithm
1049
+ *
1050
+ * @see http://en.wikipedia.org/wiki/Luhn_algorithm
1051
+ * @return boolean Success
1052
+ * @access protected
1053
+ */
1054
+ function _luhn() {
1055
+ $_this = & Wpcf_Cake_Validation::getInstance();
1056
+ if ($_this->deep !== true) {
1057
+ return true;
1058
+ }
1059
+ if ($_this->check == 0) {
1060
+ return false;
1061
+ }
1062
+ $sum = 0;
1063
+ $length = strlen($_this->check);
1064
+
1065
+ for ($position = 1 - ($length % 2); $position < $length; $position += 2) {
1066
+ $sum += $_this->check[$position];
1067
+ }
1068
+
1069
+ for ($position = ($length % 2); $position < $length; $position += 2) {
1070
+ $number = $_this->check[$position] * 2;
1071
+ $sum += ($number < 10) ? $number : $number - 9;
1072
+ }
1073
+
1074
+ return ($sum % 10 == 0);
1075
+ }
1076
+
1077
+ /*
1078
+ * Lazily popualate the IP address patterns used for validations
1079
+ *
1080
+ * @return void
1081
+ * @access private
1082
+ */
1083
+
1084
+ function __populateIp() {
1085
+ if (!isset($this->__pattern['IPv6'])) {
1086
+ $pattern = '((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}';
1087
+ $pattern .= '(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})';
1088
+ $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})';
1089
+ $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}:)';
1090
+ $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}))';
1091
+ $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}';
1092
+ $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|';
1093
+ $pattern .= '((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}';
1094
+ $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2}))';
1095
+ $pattern .= '{3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4})';
1096
+ $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})?)';
1097
+ $pattern .= '|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]';
1098
+ $pattern .= '\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4})';
1099
+ $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})))(%.+)?';
1100
+
1101
+ $this->__pattern['IPv6'] = $pattern;
1102
+ }
1103
+ if (!isset($this->__pattern['IPv4'])) {
1104
+ $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])';
1105
+ $this->__pattern['IPv4'] = $pattern;
1106
+ }
1107
+ }
1108
+
1109
+ /**
1110
+ * Reset internal variables for another validation run.
1111
+ *
1112
+ * @return void
1113
+ * @access private
1114
+ */
1115
+ function __reset() {
1116
+ $this->check = null;
1117
+ $this->regex = null;
1118
+ $this->country = null;
1119
+ $this->deep = null;
1120
+ $this->type = null;
1121
+ $this->error = array();
1122
+ $this->errors = array();
1123
+ }
1124
+
1125
+ }
1126
+ }
embedded/common/debug/debug-information.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * produce debug information
5
+ *
6
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/common/tags/august-release/debug/debug-information.php $
7
+ * $LastChangedDate: 2014-08-13 09:38:06 +0800 (Wed, 13 Aug 2014) $
8
+ * $LastChangedRevision: 25892 $
9
+ * $LastChangedBy: bruce $
10
+ *
11
+ */
12
+
13
+ include_once dirname(__FILE__) . '/functions_debug_information.php';
14
+ $debug_information = new ICL_Debug_Information();
15
+ $debug_data = $debug_information->get_debug_info();
16
+ ?>
17
+ <div class="wrap">
18
+ <h2><?php _e('Debug information', 'wpv-views');?></h2>
19
+ <div id="poststuff">
20
+ <div id="toolset-debug-info" class="postbox">
21
+ <h3 class="handle"><span><?php _e( 'Debug information', 'wpv-views' ) ?></span></h3>
22
+ <div class="inside">
23
+ <p><?php _e( 'This information allows our support team to see the versions of WordPress, plugins and theme on your site. Provide this information if requested in our support forum. No passwords or other confidential information is included.', 'sitepress', 'wpv-views' ) ?></p><br/>
24
+ <textarea style="font-size:10px;width:100%;height:250px;" rows="26" readonly="readonly"><?php echo esc_html( $debug_information->do_json_encode( $debug_data ) );?></textarea>
25
+ </div>
26
+ </div>
27
+ </div>
28
+ </div>
embedded/common/debug/functions_debug_information.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * produce debug information
4
+ *
5
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/common/tags/august-release/debug/functions_debug_information.php $
6
+ * $LastChangedDate: 2014-08-12 23:40:07 +0800 (Tue, 12 Aug 2014) $
7
+ * $LastChangedRevision: 25886 $
8
+ * $LastChangedBy: marcin $
9
+ *
10
+ */
11
+
12
+ class ICL_Debug_Information
13
+ {
14
+ function __construct() {
15
+ }
16
+ function __destruct() {
17
+ }
18
+
19
+ function get_debug_info($info=array()) {
20
+ if (!is_array($info)) {
21
+ $info = explode(',', $info);
22
+ }
23
+ if (empty($info)) {
24
+ $info = array('core', 'plugins', 'theme', 'extra-debug');
25
+ }
26
+
27
+ $output = array();
28
+ foreach ($info as $type) {
29
+ switch ($type) {
30
+ case 'core':
31
+ $output['core'] = $this->get_core_info();
32
+ break;
33
+ case 'plugins':
34
+ $output['plugins'] = $this->get_plugins_info();
35
+ break;
36
+ case 'theme':
37
+ $output['theme'] = $this->get_theme_info();
38
+ break;
39
+ case 'extra-debug':
40
+ $output['extra-debug'] = apply_filters('icl_get_extra_debug_info', array());
41
+ break;
42
+ }
43
+ }
44
+ return $output;
45
+ }
46
+
47
+ function get_core_info() {
48
+
49
+ global $wpdb;
50
+
51
+ $core = array(
52
+ 'Wordpress' => array(
53
+ 'Multisite' => is_multisite() ? 'Yes' : 'No',
54
+ 'SiteURL' => site_url(),
55
+ 'HomeURL' => home_url(),
56
+ 'Version' => get_bloginfo( 'version' ),
57
+ 'PermalinkStructure' => get_option( 'permalink_structure' ),
58
+ 'PostTypes' => implode( ', ', get_post_types( '', 'names' ) ),
59
+ 'PostSatus' => implode( ', ', get_post_stati() )
60
+ ),
61
+ 'Server' => array(
62
+ 'jQueryVersion' => wp_script_is( 'jquery', 'registered' ) ? $GLOBALS['wp_scripts']->registered['jquery']->ver : __( 'n/a', 'wpv-views' ),
63
+ 'PHPVersion' => phpversion(),
64
+ 'MySQLVersion' => $wpdb->db_version(),
65
+ 'ServerSoftware' => $_SERVER['SERVER_SOFTWARE']
66
+ ),
67
+ 'PHP' => array(
68
+ 'MemoryLimit' => ini_get( 'memory_limit' ),
69
+ 'UploadMax' => ini_get( 'upload_max_filesize' ),
70
+ 'PostMax' => ini_get( 'post_max_size' ),
71
+ 'TimeLimit' => ini_get( 'max_execution_time' ),
72
+ 'MaxInputVars' => ini_get( 'max_input_vars' ),
73
+ ),
74
+ );
75
+
76
+ return $core;
77
+ }
78
+
79
+ function get_plugins_info() {
80
+
81
+ if ( ! function_exists( 'get_plugins' ) ) {
82
+ $admin_includes_path = str_replace( site_url('/', 'admin'), ABSPATH, admin_url('includes/', 'admin') );
83
+ require_once $admin_includes_path . 'plugin.php';
84
+ }
85
+
86
+ $plugins = get_plugins();
87
+ $active_plugins = get_option('active_plugins');
88
+ $active_plugins_info = array();
89
+ foreach ($active_plugins as $plugin) {
90
+ if (isset($plugins[$plugin])) {
91
+ unset($plugins[$plugin]['Description']);
92
+ $active_plugins_info[$plugin] = $plugins[$plugin];
93
+ }
94
+ }
95
+
96
+ $mu_plugins = get_mu_plugins();
97
+
98
+ $dropins = get_dropins();
99
+
100
+ $output =array(
101
+ 'active_plugins' => $active_plugins_info,
102
+ 'mu_plugins' => $mu_plugins,
103
+ 'dropins' => $dropins,
104
+ );
105
+
106
+ return $output;
107
+ }
108
+
109
+ function get_theme_info() {
110
+
111
+ if ( get_bloginfo( 'version' ) < '3.4' ) {
112
+ $current_theme = get_theme_data( get_stylesheet_directory() . '/style.css' );
113
+ $theme = $current_theme;
114
+ unset($theme['Description']);
115
+ unset($theme['Satus']);
116
+ unset($theme['Tags']);
117
+ } else {
118
+ $current_theme = wp_get_theme();
119
+ $theme = array(
120
+ 'Name' => $current_theme->Name,
121
+ 'ThemeURI' => $current_theme->ThemeURI,
122
+ 'Author' => $current_theme->Author,
123
+ 'AuthorURI' => $current_theme->AuthorURI,
124
+ 'Template' => $current_theme->Template,
125
+ 'Version' => $current_theme->Version,
126
+ 'TextDomain' => $current_theme->TextDomain,
127
+ 'DomainPath' => $current_theme->DomainPath,
128
+ );
129
+ }
130
+
131
+ return $theme;
132
+ }
133
+
134
+
135
+ function do_json_encode($data) {
136
+ $json_options = 0;
137
+ if (defined('JSON_HEX_TAG')) {
138
+ $json_options += JSON_HEX_TAG;
139
+ }
140
+ if (defined('JSON_HEX_APOS')) {
141
+ $json_options += JSON_HEX_APOS;
142
+ }
143
+ if (defined('JSON_HEX_QUOT')) {
144
+ $json_options += JSON_HEX_QUOT;
145
+ }
146
+ if (defined('JSON_HEX_AMP')) {
147
+ $json_options += JSON_HEX_AMP;
148
+ }
149
+ if (defined('JSON_UNESCAPED_UNICODE')) {
150
+ $json_options += JSON_UNESCAPED_UNICODE;
151
+ }
152
+ return json_encode($data, $json_options);
153
+ }
154
+ }
embedded/common/expression-parser/js/parser.js ADDED
@@ -0,0 +1,2923 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ *
3
+ * Toolset Parser, advanced parser for arithmetic,logical and comparision expressions
4
+ * by Nikos M. <nikos.m@icanlocalize.com>
5
+ *
6
+ * Main Features:
7
+ * + user variables
8
+ * + support mathematical, and date functions
9
+ * + limited date parsing
10
+ *
11
+ * Additional Features:
12
+ * + typed tokens
13
+ * + typed user variables
14
+ * + added string literals
15
+ * + support advanced mathematical, string and date functions
16
+ * + support advanced date operations (like (date + 3 days) or (3 days=date1-date2)) (not yet)
17
+ * + support typecasting
18
+ * + can parse and format every localized PHP date format
19
+ * + precompilation of expressions into functions
20
+ * + faster, optimized code
21
+ * + use of closures for encapsulation and better access
22
+ * + heavy refactoring, and various bug fixes
23
+ *
24
+ * inspired by
25
+ * JS Expression Evaluator by Prasad P. Khandekar
26
+ *
27
+ **/
28
+
29
+ // js closure paradise (or maybe hell?)
30
+ (function(window){
31
+ window.ToolsetParser=window.ToolsetParser ||
32
+
33
+ (function(window){
34
+
35
+ var keywords;
36
+
37
+ var Functions=(function(){
38
+ var _cookies=false;
39
+ var _regexs={};
40
+ var _params={
41
+ user:{
42
+ ID:0,
43
+ role:'',
44
+ roles:[],
45
+ login:'',
46
+ display_name:''
47
+ }
48
+ };
49
+
50
+ function _setParams(params)
51
+ {
52
+ for (var n in params)
53
+ {
54
+ if (params.hasOwnProperty(n))
55
+ _params[n]=params[n];
56
+ }
57
+ }
58
+
59
+ function _Cookie(name)
60
+ {
61
+ var i,c,C;
62
+
63
+ if (!_cookies)
64
+ {
65
+ c = document.cookie.split(/;\s*/);
66
+ _cookies = {};
67
+
68
+ i=c.length;
69
+ while(--i>=0)
70
+ {
71
+ C = c[i].split('=');
72
+ _cookies[C[0]] = C[1];
73
+ }
74
+ }
75
+ return (_cookies[name])?_cookies[name]:'';
76
+ }
77
+
78
+ function _User(att)
79
+ {
80
+ att=att.toUpperCase();
81
+
82
+ switch (att)
83
+ {
84
+ case 'ID':
85
+ return _params['user']['ID']+'';
86
+ case 'NAME':
87
+ return _params['user']['display_name'];
88
+ case 'ROLE':
89
+ return _params['user']['role'];
90
+ case 'LOGIN':
91
+ return _params['user']['login'];
92
+ default:
93
+ return '';
94
+ }
95
+ return '';
96
+ }
97
+
98
+ function _Regex(rx, opts)
99
+ {
100
+ // cache regexes
101
+ var _prefix='__REGEX_' /*,flags, pattern, inputRX*/;
102
+
103
+ // replace flags not supported in JS
104
+ opts=opts.replace(/[^gimy]/,'');
105
+
106
+ // !opts && (opts='');
107
+ if (!_regexs[_prefix+rx+opts])
108
+ {
109
+ /*inputRX=rx;
110
+ flags = inputRX.replace(/.*\/([gimy]*)$/, '$1');
111
+ pattern = inputRX.replace(new RegExp('^/(.*?)/'+flags+'$'), '$1');*/
112
+ _regexs[_prefix+rx+opts]=new RegExp(rx /*pattern*/, /*flags+*/opts);
113
+ //console.log(_regexs[_prefix+rx+opts]);
114
+ }
115
+ return _regexs[_prefix+rx+opts];
116
+ }
117
+
118
+ function _Contains(a,v)
119
+ {
120
+ var found=false;
121
+ var ii=a.length;
122
+ while(--ii>=0)
123
+ {
124
+ if (a[ii]==v)
125
+ {
126
+ found=true;
127
+ break;
128
+ }
129
+ }
130
+ return found;
131
+ }
132
+
133
+ return {
134
+ setParams : _setParams,
135
+ User : _User,
136
+ Cookie : _Cookie,
137
+ Regex : _Regex,
138
+ Contains : _Contains
139
+ };
140
+ })();
141
+
142
+ // private class
143
+ var DateParser = (function(){
144
+
145
+ // private members
146
+ var
147
+ _ZONE_NAMES = {'AM' : 'AM','PM' : 'PM'},
148
+
149
+ //_MONTH_NAMES = {'January':'January','February':'February','March':'March','April':'April','May':'May','June':'June','July':'July','August':'August','September':'September','October':'October','November':'November','December':'December'},
150
+
151
+ //_DAY_NAMES = {'Sunday':'Sunday','Monday':'Monday','Tuesday':'Tuesday','Wednesday':'Wednesday','Thursday':'Thursday','Friday':'Friday','Saturday':'Saturday'},
152
+
153
+ _MONTH_NAMES = ['January','February','March','April','May','June','July','August','September','October','November','December'],
154
+
155
+ _DAY_NAMES = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
156
+
157
+ _ENGLISH_MONTH_NAMES = new Array('January','February','March','April','May','June','July','August','September','October','November','December'),
158
+
159
+ _ENGLISH_DAY_NAMES = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'),
160
+
161
+ _to_int = function(str)
162
+ {
163
+ // return the integer representation of the string given as argument
164
+ return parseInt(str , 10);
165
+ },
166
+
167
+ _escape_regexp = function(str)
168
+ {
169
+ // return string with special characters escaped
170
+ return str.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
171
+ },
172
+
173
+ _str_pad = function(n, c)
174
+ {
175
+ if ((n = n + '').length < c)
176
+ {
177
+ return new Array((++c) - n.length).join('0') + n;
178
+ }
179
+ return n;
180
+ },
181
+
182
+ _is_string = function(s)
183
+ {
184
+ if (typeof(s)=='string' ||
185
+ (typeof(s)=='object' && ((s instanceof String) || Object.prototype.toString.call(s) === '[object String]')))
186
+ return true;
187
+ return false;
188
+ };
189
+
190
+
191
+ var _parseDate = function(date, supposed_format)
192
+ {
193
+ // if already a date object
194
+ if (typeof(date)!='undefined' && ((date instanceof Date) || Object.prototype.toString.call(date) === '[object Date]'))
195
+ {
196
+ date.setHours(0,0,0,0); // normalize time part
197
+ return date;
198
+ }
199
+
200
+ if (
201
+ typeof(date)=='undefined' ||
202
+ date==null ||
203
+ !_is_string(date) ||
204
+ typeof(supposed_format)=='undefined' ||
205
+ supposed_format==null ||
206
+ !_is_string(supposed_format)
207
+ )
208
+ return false;
209
+
210
+ // treat argument as a string
211
+ str_date = date + '';
212
+ supposed_format = supposed_format+'';
213
+
214
+ // if value is given
215
+ if (str_date != '' && supposed_format != '')
216
+ {
217
+
218
+ var
219
+ // prepare the format by removing white space from it
220
+ // and also escape characters that could have special meaning in a regular expression
221
+ format = _escape_regexp(supposed_format.replace(/\s/g, '')),
222
+
223
+ // allowed characters in date's format
224
+ format_chars = ['d','D','j','l','N','S','w','F','m','M','n','Y','y'],
225
+
226
+ // "matches" will contain the characters defining the date's format
227
+ matches = new Array,
228
+
229
+ // "regexp" will contain the regular expression built for each of the characters used in the date's format
230
+ regexp = new Array;
231
+
232
+ // iterate through the allowed characters in date's format
233
+ for (var i = 0; i < format_chars.length; i++)
234
+ {
235
+ // if character is found in the date's format
236
+ if ((position = format.indexOf(format_chars[i])) > -1)
237
+
238
+ // save it, alongside the character's position
239
+ matches.push({character: format_chars[i], position: position});
240
+ }
241
+
242
+ // sort characters defining the date's format based on their position, ascending
243
+ matches.sort(function(a, b){ return a.position - b.position });
244
+
245
+ // iterate through the characters defining the date's format
246
+ for (var index=0; index<matches.length; index++)
247
+ {
248
+ var match=matches[index];
249
+
250
+ // add to the array of regular expressions, based on the character
251
+ switch (match.character)
252
+ {
253
+
254
+ case 'd': regexp.push('0[1-9]|[12][0-9]|3[01]'); break;
255
+ case 'D': regexp.push('[a-z]{3}'); break;
256
+ case 'j': regexp.push('[1-9]|[12][0-9]|3[01]'); break;
257
+ case 'l': regexp.push('[a-z]+'); break;
258
+ case 'N': regexp.push('[1-7]'); break;
259
+ case 'S': regexp.push('st|nd|rd|th'); break;
260
+ case 'w': regexp.push('[0-6]'); break;
261
+ case 'F': regexp.push('[a-z]+'); break;
262
+ case 'm': regexp.push('0[1-9]|1[012]+'); break;
263
+ case 'M': regexp.push('[a-z]{3}'); break;
264
+ case 'n': regexp.push('[1-9]|1[012]'); break;
265
+ case 'Y': regexp.push('[0-9]{4}'); break;
266
+ case 'y': regexp.push('[0-9]{2}'); break;
267
+
268
+ }
269
+ }
270
+
271
+ // if we have an array of regular expressions
272
+ if (regexp.length)
273
+ {
274
+
275
+ // we will replace characters in the date's format in reversed order
276
+ matches.reverse();
277
+
278
+ // iterate through the characters in date's format
279
+ for (var index=0; index<matches.length; index++)
280
+ {
281
+ var match=matches[index];
282
+
283
+ // replace each character with the appropriate regular expression
284
+ format = format.replace(match.character, '(' + regexp[regexp.length - index - 1] + ')');
285
+ }
286
+
287
+ // the final regular expression
288
+ regexp = new RegExp('^' + format + '$', 'ig');
289
+
290
+ // if regular expression was matched
291
+ if ((segments = regexp.exec(str_date.replace(/\s/g, ''))))
292
+ {
293
+
294
+ // check if date is a valid date (i.e. there's no February 31)
295
+ var original_day,
296
+ original_month,
297
+ original_year,
298
+ english_days = _ENGLISH_DAY_NAMES, //['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
299
+ english_months = _ENGLISH_MONTH_NAMES,//['January','February','March','April','May','June','July','August','September','October','November','December'],
300
+ iterable,
301
+
302
+ // by default, we assume the date is valid
303
+ valid = true;
304
+
305
+ // reverse back the characters in the date's format
306
+ matches.reverse();
307
+
308
+ // iterate through the characters in the date's format
309
+ for (var index=0; index<matches.length; index++)
310
+ {
311
+ var match=matches[index];
312
+
313
+ // if the date is not valid, don't look further
314
+ if (!valid) break; //return true;
315
+
316
+ // based on the character
317
+ switch (match.character)
318
+ {
319
+
320
+ case 'm':
321
+ case 'n':
322
+
323
+ // extract the month from the value entered by the user
324
+ original_month = _to_int(segments[index + 1]);
325
+
326
+ break;
327
+
328
+ case 'd':
329
+ case 'j':
330
+
331
+ // extract the day from the value entered by the user
332
+ original_day = _to_int(segments[index + 1]);
333
+
334
+ break;
335
+
336
+ case 'D':
337
+ case 'l':
338
+ case 'F':
339
+ case 'M':
340
+
341
+ // if day is given as day name, we'll check against the names in the used language
342
+ if (match.character == 'D' || match.character == 'l') iterable = _DAY_NAMES;
343
+
344
+ // if month is given as month name, we'll check against the names in the used language
345
+ else iterable = _MONTH_NAMES;
346
+
347
+ // by default, we assume the day or month was not entered correctly
348
+ valid = false;
349
+
350
+ // iterate through the month/days in the used language
351
+ for (var key=0; key<iterable.length; key++)
352
+ {
353
+ // if month/day was entered correctly, don't look further
354
+ if (valid) break; //return true;
355
+
356
+ var value=iterable[key];
357
+
358
+ // if month/day was entered correctly
359
+ if (segments[index + 1].toLowerCase() == value.substring(0, (match.character == 'D' || match.character == 'M' ? 3 : value.length)).toLowerCase())
360
+ {
361
+
362
+ // extract the day/month from the value entered by the user
363
+ switch (match.character)
364
+ {
365
+
366
+ case 'D': segments[index + 1] = english_days[key].substring(0, 3); break;
367
+ case 'l': segments[index + 1] = english_days[key]; break;
368
+ case 'F': segments[index + 1] = english_months[key]; original_month = key + 1; break;
369
+ case 'M': segments[index + 1] = english_months[key].substring(0, 3); original_month = key + 1; break;
370
+
371
+ }
372
+
373
+ // day/month value is valid
374
+ valid = true;
375
+
376
+ }
377
+
378
+ }
379
+
380
+ break;
381
+
382
+ case 'Y':
383
+
384
+ // extract the year from the value entered by the user
385
+ original_year = _to_int(segments[index + 1]);
386
+
387
+ break;
388
+
389
+ case 'y':
390
+
391
+ // extract the year from the value entered by the user
392
+ original_year = '19' + _to_int(segments[index + 1]);
393
+
394
+ break;
395
+
396
+ }
397
+ }
398
+
399
+ // if everything is ok so far
400
+ if (valid)
401
+ {
402
+ // generate a Date object using the values entered by the user
403
+ // (handle also the case when original_month and/or original_day are undefined - i.e date format is "Y-m" or "Y")
404
+ var date = new Date(original_year, (original_month || 1) - 1, original_day || 1);
405
+
406
+ // if, after that, the date is the same as the date entered by the user
407
+ if (date.getFullYear() == original_year && date.getDate() == (original_day || 1) && date.getMonth() == ((original_month || 1) - 1))
408
+ {
409
+ // normalize time part, only date part checked
410
+ date.setHours(0,0,0,0);
411
+ // return the date as JavaScript date object
412
+ return date;
413
+ }
414
+ }
415
+ }
416
+ }
417
+ }
418
+ // if script gets this far, return false as something must've went wrong
419
+ return false;
420
+ };
421
+
422
+ var _formatDate = function(date, format)
423
+ {
424
+
425
+ // if not a date object
426
+ if (typeof(date)=='undefined' || date==null || !(date instanceof Date) || Object.prototype.toString.call(date) !== '[object Date]')
427
+ {
428
+ return '';
429
+ }
430
+
431
+ date.setHours(0,0,0,0); // normalize time
432
+
433
+ if (format=='')
434
+ return date.toString();
435
+
436
+ var result = '',
437
+
438
+ // extract parts of the date:
439
+ // day number, 1 - 31
440
+ j = date.getDate(),
441
+
442
+ // day of the week, 0 - 6, Sunday - Saturday
443
+ w = date.getDay(),
444
+
445
+ // the name of the day of the week Sunday - Saturday
446
+ l = _DAY_NAMES[w],
447
+
448
+ // the month number, 1 - 12
449
+ n = date.getMonth() + 1,
450
+
451
+ // the month name, January - December
452
+ f = _MONTH_NAMES[n - 1],
453
+
454
+ // the year (as a string)
455
+ y = date.getFullYear() + '';
456
+
457
+ // iterate through the characters in the format
458
+ for (var i = 0; i < format.length; i++)
459
+ {
460
+
461
+ // extract the current character
462
+ var chr = format.charAt(i);
463
+
464
+ // see what character it is
465
+ switch(chr)
466
+ {
467
+ // year as two digits
468
+ case 'y': y = y.substr(2);
469
+
470
+ // year as four digits
471
+ case 'Y': result += y; break;
472
+
473
+ // month number, prefixed with 0
474
+ case 'm': n = _str_pad(n, 2);
475
+
476
+ // month number, not prefixed with 0
477
+ case 'n': result += n; break;
478
+
479
+ // month name, three letters
480
+ case 'M': f = f.substr(0, 3);
481
+
482
+ // full month name
483
+ case 'F': result += f; break;
484
+
485
+ // day number, prefixed with 0
486
+ case 'd': j = _str_pad(j, 2);
487
+
488
+ // day number not prefixed with 0
489
+ case 'j': result += j; break;
490
+
491
+ // day name, three letters
492
+ case 'D': l = l.substr(0, 3);
493
+
494
+ // full day name
495
+ case 'l': result += l; break;
496
+
497
+ // ISO-8601 numeric representation of the day of the week, 1 - 7
498
+ case 'N': w++;
499
+
500
+ // day of the week, 0 - 6
501
+ case 'w': result += w; break;
502
+
503
+ // English ordinal suffix for the day of the month, 2 characters
504
+ // (st, nd, rd or th (works well with j))
505
+ case 'S':
506
+
507
+ if (j % 10 == 1 && j != '11') result += 'st';
508
+
509
+ else if (j % 10 == 2 && j != '12') result += 'nd';
510
+
511
+ else if (j % 10 == 3 && j != '13') result += 'rd';
512
+
513
+ else result += 'th';
514
+
515
+ break;
516
+
517
+ // this is probably the separator
518
+ default: result += chr;
519
+
520
+ }
521
+
522
+ }
523
+ // return formated date
524
+ return result;
525
+ };
526
+
527
+ // public (static) methods
528
+ return {
529
+
530
+ setDateLocaleStrings : function(dn, mn, zn)
531
+ {
532
+ if (typeof mn != 'undefined')
533
+ {
534
+ _MONTH_NAMES = mn;
535
+ }
536
+ if (typeof dn != 'undefined')
537
+ {
538
+ _DAY_NAMES = dn;
539
+ }
540
+ if (typeof zn != 'undefined')
541
+ _ZONE_NAMES = zn;
542
+ },
543
+
544
+ parseDate : _parseDate,
545
+ formatDate : _formatDate,
546
+
547
+ isDate : function (val, format, getDate)
548
+ {
549
+ var date=_parseDate(val,format);
550
+ if (date!==false)
551
+ {
552
+ if (typeof(getDate)!='undefined' && typeof(getDate)=='object')
553
+ {
554
+ getDate.date=date;
555
+ }
556
+ return true;
557
+ }
558
+ return false;
559
+ },
560
+
561
+ currentDate : function()
562
+ {
563
+ var _now=new Date();
564
+ _now.setHours(0,0,0,0); // normalize time part
565
+ return _now;
566
+ }
567
+ };
568
+ })();
569
+
570
+ var Stack = (function(){
571
+ // Converts stack contents into a comma separated string
572
+ function _dumpStack()
573
+ {
574
+ var intCntr = 0;
575
+ var strRet = "";
576
+ if (this.intIndex == 0) return null;
577
+ for (intCntr = 0; intCntr < this.intIndex; intCntr++)
578
+ {
579
+ if (strRet.length == 0)
580
+ strRet += this.arrStack[intCntr].val;
581
+ else
582
+ strRet += "," + this.arrStack[intCntr].val;
583
+ }
584
+ return strRet;
585
+ }
586
+
587
+ // Returns size of stack
588
+ function _getSize()
589
+ {
590
+ return this.intIndex;
591
+ }
592
+
593
+ // This method tells us if this Stack object is empty
594
+ function _isStackEmpty()
595
+ {
596
+ if (this.intIndex == 0)
597
+ return true;
598
+ else
599
+ return false;
600
+ }
601
+
602
+ // This method pushes a new element onto the top of the stack
603
+ function _pushElement(newData)
604
+ {
605
+ // Assign our new element to the top
606
+ //debugAssert ("Pushing " + newData);
607
+ this.arrStack[this.intIndex++] = newData;
608
+ //this.intIndex++;
609
+ }
610
+
611
+ // This method pops the top element off of the stack
612
+ function _popElement()
613
+ {
614
+ var retVal;
615
+
616
+ retVal = null;
617
+ if (this.intIndex > 0)
618
+ {
619
+ // Assign our new element to the top
620
+ //this.intIndex--;
621
+ retVal = this.arrStack[--this.intIndex];
622
+ }
623
+ return retVal;
624
+ }
625
+
626
+ // Gets an element at a particular offset from top of the stack
627
+ function _getElement(intPos)
628
+ {
629
+ var retVal;
630
+
631
+ //alert ("Size : " + this.intIndex + ", Index " + intPos);
632
+ if (intPos >= 0 && intPos < this.intIndex)
633
+ retVal = this.arrStack[this.intIndex - intPos - 1];
634
+ return retVal;
635
+ }
636
+ // Stack object constructor
637
+ return function()
638
+ {
639
+ this.arrStack = new Array();
640
+ this.intIndex = 0;
641
+
642
+ this.Size = _getSize;
643
+ this.IsEmpty = _isStackEmpty;
644
+ this.Push = _pushElement;
645
+ this.Pop = _popElement;
646
+ this.Get = _getElement;
647
+ this.toString = _dumpStack;
648
+ };
649
+ })();
650
+
651
+ var Tokenizer = (function(DateParser){
652
+
653
+ // private members
654
+ var _tok_map_prefix = '__TOKEN_MAP_PREFIX__',
655
+ _Alpha = "abcdefghijklmnopqrstuvwxyz",
656
+ _lstAlpha = _Alpha + _Alpha.toUpperCase(),
657
+ _lstVariablePrefix = '_$' + _lstAlpha,
658
+ _lstDigits = "0123456789",
659
+ _lstArithOps = ["^","*","/","%","+","-"],
660
+ _lstLogicOps = ["NOT","!","OR","|","AND","&"],
661
+ _lstCompaOps = ["<","<=",">",">=","<>","=","lt","lte","gt","gte","ne","eq"],
662
+ _lstFuncOps = ["AVG","ABS","ACOS","ARRAY","ASC","ASIN","ATAN","CHR","CONTAINS","COOKIE","COS","DATE","FIX","HEX","IIF","LCASE","LEN","LEFT","LOG","MAX","MID","MIN","NUM","RAND","REGEX","RIGHT","ROUND","SIN","SQRT","STR","TAN","TODAY","UCASE","USER", "EMPTY", "empty"],
663
+
664
+ _UNARY_NEGATIVE = "-",
665
+ _UNARY_NEGATION = "!",
666
+ _ARG_TERMINAL = "?",
667
+
668
+ _aritOpMap = {},
669
+ _logiOpMap = {},
670
+ _compOpMap = {},
671
+ _funcMap = {},
672
+
673
+ _TOKEN_TYPES = { __DEFAULT__:0, STRING_LITERAL:8, REGEX: 83, ARRAY:81, ARRAY_LITERAL:82, DATE:1, ARITHMETIC_OP:2, LOGICAL_OP:3, COMPARISON_OP:4, NUMBER:5, BOOLEAN:6, VARIABLE:7, FUNCTION:9, COMMA:10, LEFT_PAREN:11, LEFT_BRACKET:111, RIGHT_PAREN:12, RIGHT_BRACKET:122, ARG_TERMINAL:13, UNARY_NEGATIVE:14, UNARY_NEGATION:15, EMPTY_TOKEN:30, UNKNOWN:40 },
674
+
675
+ _isDefined = function(s)
676
+ {
677
+ return ((typeof(s)=='undefined' || s==null)?false:true);
678
+ },
679
+ _isDigit = function(c)
680
+ {
681
+ if (!_isDefined(c))
682
+ return false;
683
+ return ((c!='' && _lstDigits.indexOf(c) >= 0)?true:false);
684
+ },
685
+ _isAlpha = function(c)
686
+ {
687
+ if (!_isDefined(c))
688
+ return false;
689
+ return ((c!='' && _lstAlpha.indexOf(c) >= 0)?true:false);
690
+ },
691
+ _isOperator = function(s)
692
+ {
693
+ if (!_isDefined(s))
694
+ return false;
695
+ return ((_aritOpMap[_tok_map_prefix + s])?true:false);
696
+ },
697
+ _isLogicOperator = function(s)
698
+ {
699
+ if (!_isDefined(s))
700
+ return false;
701
+ return ((_logiOpMap[_tok_map_prefix + s])?true:false);
702
+ },
703
+ _isCompOperator = function(s)
704
+ {
705
+ if (!_isDefined(s))
706
+ return false;
707
+ return ((_compOpMap[_tok_map_prefix + s])?true:false);
708
+ },
709
+ _isFunction = function(s)
710
+ {
711
+ if (!_isDefined(s))
712
+ return false;
713
+ return ((_funcMap[_tok_map_prefix + s])?true:false);
714
+ },
715
+ _isVariableName = function(s)
716
+ {
717
+ if (!_isDefined(s))
718
+ return false;
719
+ c=(s=='')?'':s.charAt(0);
720
+ return ((c!='' && _lstVariablePrefix.indexOf(c) >= 0)?true:false);
721
+ },
722
+ _isDateInstance = function(s)
723
+ {
724
+ if (!_isDefined(s))
725
+ return false;
726
+ if (typeof(s)=='object' && ((s instanceof Date) || Object.prototype.toString.call(s) == '[object Date]'))
727
+ return true;
728
+ return false;
729
+ },
730
+ _isArrayInstance = function(s)
731
+ {
732
+ if (!_isDefined(s))
733
+ return false;
734
+ if (typeof(s)=='object' && ((s instanceof Array) || Object.prototype.toString.call(s) == '[object Array]'))
735
+ return true;
736
+ return false;
737
+ },
738
+ _isRegExpInstance = function(s)
739
+ {
740
+ if (!_isDefined(s))
741
+ return false;
742
+ if (typeof(s)=='object' && ((s instanceof RegExp) || Object.prototype.toString.call(s) == '[object RegExp]'))
743
+ return true;
744
+ return false;
745
+ },
746
+ _isNumber = function(s)
747
+ {
748
+ var type_s=typeof(s);
749
+ if (!_isDefined(s)) return false;
750
+ if (_isDateInstance(s) || _isRegExpInstance(s) || _isArrayInstance(s)) return false;
751
+ if ((type_s=='number' || (type_s=='object' && Object.prototype.toString.call(s) !== '[object Number]')) /*&& !isNaN(s)*/)
752
+ return true;
753
+ var dblNo = Number.NaN;
754
+ dblNo = new Number(s);
755
+ return ((isNaN(dblNo))?false:true);
756
+ },
757
+ _isBoolean = function(s)
758
+ {
759
+ if (!_isDefined(s))
760
+ return false;
761
+
762
+ var varType = typeof(s);
763
+ var strTmp = s;
764
+
765
+ if (varType == "boolean") return true;
766
+ if (varType == "number" || varType == "function" || varType == 'undefined') return false;
767
+ if (_isNumber(s) || _isDateInstance(s) || _isRegExpInstance(s) || _isArrayInstance(s)) return false;
768
+ if (varType == "object") strTmp = strTmp.toString();
769
+ if (strTmp.toUpperCase && (strTmp.toUpperCase() == "TRUE" || strTmp.toUpperCase() == "FALSE")) return true;
770
+ return false;
771
+ },
772
+ _rtrim = function(s, ch)
773
+ {
774
+ var w_space;
775
+ if (typeof ch == 'undefined')
776
+ w_space = String.fromCharCode(32);
777
+ else
778
+ w_space = ch;
779
+ var v_length = s.length;
780
+ var strTemp = "";
781
+ if(v_length < 0)
782
+ {
783
+ return"";
784
+ }
785
+ var iTemp = v_length - 1;
786
+
787
+ while(iTemp > -1)
788
+ {
789
+ if(s.charAt(iTemp) == w_space)
790
+ {
791
+ }
792
+ else
793
+ {
794
+ strTemp = s.substring(0, iTemp + 1);
795
+ break;
796
+ }
797
+ iTemp = iTemp - 1;
798
+ }
799
+ return strTemp;
800
+ },
801
+ _ltrim = function (s, ch)
802
+ {
803
+ var w_space;
804
+ if (typeof ch == 'undefined')
805
+ w_space = String.fromCharCode(32);
806
+ else
807
+ w_space = ch;
808
+ if(v_length < 1)
809
+ {
810
+ return "";
811
+ }
812
+ var v_length = s.length;
813
+ var strTemp = "";
814
+ var iTemp = 0;
815
+
816
+ while(iTemp < v_length)
817
+ {
818
+ if(s.charAt(iTemp) == w_space)
819
+ {
820
+ }
821
+ else
822
+ {
823
+ strTemp = s.substring(iTemp, v_length);
824
+ break;
825
+ }
826
+ iTemp = iTemp + 1;
827
+ }
828
+ return strTemp;
829
+ },
830
+ _trim = function(s, ch)
831
+ {
832
+ if (s.length < 1) return "";
833
+
834
+ s = _rtrim(_ltrim(s, ch), ch);
835
+ if (s == "")
836
+ return "";
837
+ else
838
+ return s;
839
+ };
840
+
841
+ // build maps for fast lookup
842
+ var _buildMaps=function()
843
+ {
844
+ var i;
845
+
846
+ for (i=0; i<_lstArithOps.length; i++)
847
+ {
848
+ _aritOpMap[_tok_map_prefix + _lstArithOps[i]]=true;
849
+ }
850
+ for (i=0; i<_lstLogicOps.length; i++)
851
+ {
852
+ _logiOpMap[_tok_map_prefix + _lstLogicOps[i]]=true;
853
+ }
854
+ for (i=0; i<_lstCompaOps.length; i++)
855
+ {
856
+ _compOpMap[_tok_map_prefix + _lstCompaOps[i]]=true;
857
+ }
858
+ for (i=0; i<_lstFuncOps.length; i++)
859
+ {
860
+ _funcMap[_tok_map_prefix + _lstFuncOps[i]]=true;
861
+ }
862
+ };
863
+
864
+ var _makeToken = function(tok, force_type)
865
+ {
866
+ var token={val:tok, type:_TOKEN_TYPES.UNKNOWN};
867
+ var typeoftok=typeof(tok);
868
+
869
+ if (typeof(force_type) == 'undefined' || force_type==null || force_type=='')
870
+ force_type=_TOKEN_TYPES.__DEFAULT__;
871
+
872
+ switch (force_type)
873
+ {
874
+ case _TOKEN_TYPES.EMPTY_TOKEN:
875
+ token.type=_TOKEN_TYPES.EMPTY_TOKEN;
876
+ token.isEmpty=true;
877
+ token.val='';
878
+ break;
879
+ case _TOKEN_TYPES.STRING_LITERAL:
880
+ token.type=_TOKEN_TYPES.STRING_LITERAL;
881
+ token.isStringLiteral=true;
882
+ token.val=tok.toString();
883
+ break;
884
+ case _TOKEN_TYPES.DATE:
885
+ if (_isDateInstance(tok))
886
+ {
887
+ token.type=_TOKEN_TYPES.DATE;
888
+ token.isDate=true;
889
+ }
890
+ break;
891
+ case _TOKEN_TYPES.ARRAY:
892
+ if (!_isArrayInstance(tok))
893
+ {
894
+ token.val=[tok];
895
+ }
896
+ token.type=_TOKEN_TYPES.ARRAY;
897
+ token.isArray=true;
898
+ break;
899
+ case _TOKEN_TYPES.REGEX:
900
+ if (!_isRegExpInstance(tok))
901
+ {
902
+ token.val=Functions.Regex(tok);
903
+ }
904
+ token.type=_TOKEN_TYPES.REGEX;
905
+ token.isRegex=true;
906
+ break;
907
+ case _TOKEN_TYPES.COMMA:
908
+ token.type=_TOKEN_TYPES.COMMA;
909
+ token.isComma=true;
910
+ token.val=',';
911
+ break;
912
+ case _TOKEN_TYPES.LEFT_PAREN:
913
+ token.type=_TOKEN_TYPES.LEFT_PAREN;
914
+ token.isLeftParen=true;
915
+ token.isParen=true;
916
+ token.val='(';
917
+ break;
918
+ case _TOKEN_TYPES.RIGHT_PAREN:
919
+ token.type=_TOKEN_TYPES.RIGHT_PAREN;
920
+ token.isRightParen=true;
921
+ token.isParen=true;
922
+ token.val=')';
923
+ break;
924
+ case _TOKEN_TYPES.ARG_TERMINAL:
925
+ token.type=_TOKEN_TYPES.ARG_TERMINAL;
926
+ token.isArgTerminal=true;
927
+ token.val=_ARG_TERMINAL;
928
+ break;
929
+ case _TOKEN_TYPES.UNARY_NEGATIVE:
930
+ token.type=_TOKEN_TYPES.UNARY_NEGATIVE;
931
+ token.isUnaryNegative=true;
932
+ token.val=_UNARY_NEGATIVE;
933
+ token.isArithmeticOp=true;
934
+ token.isOp=true;
935
+ break;
936
+ case _TOKEN_TYPES.UNARY_NEGATION:
937
+ token.type=_TOKEN_TYPES.UNARY_NEGATION;
938
+ token.isUnaryNegation=true;
939
+ token.val=_UNARY_NEGATION;
940
+ token.isLogicOp=true;
941
+ token.isOp=true;
942
+ break;
943
+ case _TOKEN_TYPES.NUMBER:
944
+ token.type=_TOKEN_TYPES.NUMBER;
945
+ token.isNumber=true;
946
+ if (typeoftok=='string')
947
+ token.val=new Number(tok);
948
+ else if (typeoftok=='number')
949
+ token.val=tok;
950
+ else if (typeoftok=='boolean')
951
+ token.val=(tok==true)?1:0;
952
+ else if (typeoftok=='object')
953
+ token.val=new Number(tok.toString());
954
+ break;
955
+ case _TOKEN_TYPES.BOOLEAN:
956
+ token.type=_TOKEN_TYPES.BOOLEAN;
957
+ token.isBoolean=true;
958
+ if (typeoftok=='boolean')
959
+ token.val=tok;
960
+ else if (typeoftok=='string')
961
+ token.val=(tok.toUpperCase()=='TRUE')?true:false;
962
+ else if (typeoftok=='number')
963
+ token.val=(tok != 0)?true:false;
964
+ else if (Object.prototype.toString.call(tok) === '[object Number]')
965
+ token.val=(tok.valueOf() != 0)?true:false;
966
+ else if (typeoftok=='object')
967
+ token.val=(tok.toString().toUpperCase()=='TRUE')?true:false;
968
+ break;
969
+ case _TOKEN_TYPES.VARIABLE:
970
+ token.type=_TOKEN_TYPES.VARIABLE;
971
+ token.isVariable=true;
972
+ break;
973
+ case _TOKEN_TYPES.__DEFAULT__:
974
+ default:
975
+ if (
976
+ (typeoftok=='object' &&
977
+ ((tok instanceof String) || Object.prototype.toString.call(tok) === '[object String]') &&
978
+ tok._isStringLiteral)
979
+ )
980
+ {
981
+ token.type=_TOKEN_TYPES.STRING_LITERAL;
982
+ token.isStringLiteral=true;
983
+ token.val=tok.toString();
984
+ }
985
+ // date token
986
+ else if (_isDateInstance(tok))
987
+ {
988
+ token.type=_TOKEN_TYPES.DATE;
989
+ token.isDate=true;
990
+ }
991
+ // array token
992
+ else if (_isArrayInstance(tok))
993
+ {
994
+ token.type=_TOKEN_TYPES.ARRAY;
995
+ token.isArray=true;
996
+ }
997
+ // regex token
998
+ else if (_isRegExpInstance(tok))
999
+ {
1000
+ token.type=_TOKEN_TYPES.REGEX;
1001
+ token.isRegex=true;
1002
+ }
1003
+ else if (tok==',')
1004
+ {
1005
+ token.type=_TOKEN_TYPES.COMMA;
1006
+ token.isComma=true;
1007
+ token.val=',';
1008
+ }
1009
+ else if (tok=='(')
1010
+ {
1011
+ token.type=_TOKEN_TYPES.LEFT_PAREN;
1012
+ token.isLeftParen=true;
1013
+ token.isParen=true;
1014
+ token.val='(';
1015
+ token.isOp=true;
1016
+ }
1017
+ else if (tok==')')
1018
+ {
1019
+ token.type=_TOKEN_TYPES.RIGHT_PAREN;
1020
+ token.isRightParen=true;
1021
+ token.isParen=true;
1022
+ token.val=')';
1023
+ //token.isOp=true;
1024
+ }
1025
+ /*else if (tok=='{')
1026
+ {
1027
+ token.type=_TOKEN_TYPES.LEFT_BRACKET;
1028
+ token.isLeftBracket=true;
1029
+ token.isBracket=true;
1030
+ token.val='{';
1031
+ token.isOp=true;
1032
+ }
1033
+ else if (tok=='}')
1034
+ {
1035
+ token.type=_TOKEN_TYPES.RIGHT_BRACKET;
1036
+ token.isRightBracket=true;
1037
+ token.isBracket=true;
1038
+ token.val='}';
1039
+ //token.isOp=true;
1040
+ }*/
1041
+ else if (_isNumber(tok))
1042
+ {
1043
+ token.type=_TOKEN_TYPES.NUMBER;
1044
+ token.isNumber=true;
1045
+ if (typeoftok=='string')
1046
+ token.val=new Number(tok).valueOf();
1047
+ else if (typeoftok=='number')
1048
+ token.val=tok;
1049
+ else if (typeoftok=='boolean')
1050
+ token.val=(tok==true)?1:0;
1051
+ else if (typeoftok=='object')
1052
+ token.val=new Number(tok.toString()).valueOf();
1053
+ }
1054
+ else if (_isBoolean(tok))
1055
+ {
1056
+ token.type=_TOKEN_TYPES.BOOLEAN;
1057
+ token.isBoolean=true;
1058
+ if (typeoftok=='boolean')
1059
+ token.val=tok;
1060
+ else if (typeoftok=='string')
1061
+ token.val=(tok.toUpperCase()=='TRUE')?true:false;
1062
+ else if (typeoftok=='number')
1063
+ token.val=(tok != 0)?true:false;
1064
+ else if (Object.prototype.toString.call(tok) === '[object Number]')
1065
+ token.val=(tok.valueOf() != 0)?true:false;
1066
+ else if (typeoftok=='object')
1067
+ token.val=(tok.toString().toUpperCase()=='TRUE')?true:false;
1068
+ }
1069
+ else if (_isOperator(tok))
1070
+ {
1071
+ token.type=_TOKEN_TYPES.ARITHMETIC_OP;
1072
+ token.isArithmeticOp=true;
1073
+ token.isOp=true;
1074
+
1075
+ }
1076
+ else if (_isLogicOperator(tok))
1077
+ {
1078
+ token.type=_TOKEN_TYPES.LOGICAL_OP;
1079
+ token.isLogicOp=true;
1080
+ token.isOp=true;
1081
+ }
1082
+ else if (_isCompOperator(tok))
1083
+ {
1084
+ token.type=_TOKEN_TYPES.COMPARISON_OP;
1085
+ token.isCompOp=true;
1086
+ token.isOp=true;
1087
+ }
1088
+ else if (_isFunction(tok))
1089
+ {
1090
+ token.type=_TOKEN_TYPES.FUNCTION;
1091
+ token.isFunction=true;
1092
+ token.val=tok;
1093
+ }
1094
+ else if (_isVariableName(tok))
1095
+ {
1096
+ token.type=_TOKEN_TYPES.VARIABLE;
1097
+ token.isVariable=true;
1098
+ }
1099
+ break;
1100
+ }
1101
+ if (token.isOp || token.isFunction)
1102
+ {
1103
+ var intRet = 0;
1104
+
1105
+ switch(token.val)
1106
+ {
1107
+ case "+" :
1108
+ case "-" :
1109
+ intRet = 50;
1110
+ break;
1111
+ case "*" :
1112
+ case "/" :
1113
+ case "%" :
1114
+ intRet = 60;
1115
+ break;
1116
+ case "^" :
1117
+ intRet = 70;
1118
+ break;
1119
+ case _UNARY_NEGATIVE:
1120
+ case _UNARY_NEGATION:
1121
+ case "!" :
1122
+ case "NOT" :
1123
+ intRet = 100;
1124
+ break;
1125
+ case "(" :
1126
+ intRet = 1000;
1127
+ break;
1128
+ /*case "{" :
1129
+ intRet = 500; // as function
1130
+ break;*/
1131
+ case "AND" :
1132
+ case "&" :
1133
+ intRet = 35;
1134
+ break;
1135
+ case "OR" :
1136
+ case "|" :
1137
+ intRet = 30;
1138
+ break;
1139
+ case ">" :
1140
+ case ">=" :
1141
+ case "<" :
1142
+ case "<=" :
1143
+ case "=" :
1144
+ case "<>" :
1145
+ case "gt" :
1146
+ case "gte" :
1147
+ case "lt" :
1148
+ case "lte" :
1149
+ case "eq" :
1150
+ case "ne" :
1151
+ intRet = 40;
1152
+ break;
1153
+ default :
1154
+ if (token.isFunction)
1155
+ intRet = 500;
1156
+ else
1157
+ intRet = 0;
1158
+ break;
1159
+ }
1160
+ token.precedence=intRet;
1161
+ }
1162
+ else
1163
+ token.precedence=0;
1164
+
1165
+ //console.log(token);
1166
+ return token;
1167
+ };
1168
+
1169
+ var _EMPTY_TOKEN = _makeToken('', _TOKEN_TYPES.EMPTY_TOKEN);
1170
+ var _EMPTY_STRING = _makeToken('', _TOKEN_TYPES.STRING_LITERAL);
1171
+
1172
+ // public (static) methods
1173
+ return {
1174
+
1175
+ makeToken : _makeToken,
1176
+
1177
+ cloneToken : function(tok)
1178
+ {
1179
+ var newtok={};
1180
+
1181
+ for (var at in tok)
1182
+ {
1183
+ if (tok.hasOwnProperty(at))
1184
+ {
1185
+ if (_isDateInstance(tok[at]))
1186
+ newtok[at]=new Date(tok[at].getTime());
1187
+ else
1188
+ newtok[at]=tok[at];
1189
+ }
1190
+ }
1191
+ return newtok;
1192
+ },
1193
+
1194
+ TOKEN_TYPE : _TOKEN_TYPES,
1195
+
1196
+ EMPTY_TOKEN : _EMPTY_TOKEN,
1197
+
1198
+ EMPTY_STRING : _EMPTY_STRING,
1199
+
1200
+ UNARY_NEGATIVE : _makeToken(_UNARY_NEGATIVE, _TOKEN_TYPES.UNARY_NEGATIVE),
1201
+
1202
+ UNARY_NEGATION : _makeToken(_UNARY_NEGATION, _TOKEN_TYPES.UNARY_NEGATION),
1203
+
1204
+ ARG_TERMINAL : _makeToken(_ARG_TERMINAL, _TOKEN_TYPES.ARG_TERMINAL),
1205
+
1206
+ isBoolean : _isBoolean,
1207
+
1208
+ isNumber : _isNumber,
1209
+
1210
+ isString : function(a)
1211
+ {
1212
+ if (!_isDefined(a)) return false;
1213
+ var typeofa=typeof(a);
1214
+ if (_isNumber(a) || _isBoolean(a) || _isArrayInstance(a) || _isDateInstance(a) || _isRegExpInstance(a)) return false;
1215
+
1216
+ if (
1217
+ typeofa=='string' ||
1218
+ (
1219
+ typeofa=='object' &&
1220
+ ((a instanceof String) || Object.prototype.toString.call(a) === '[object String]')
1221
+ )
1222
+ )
1223
+ return true;
1224
+ return false;
1225
+ },
1226
+
1227
+ isDateInstance : _isDateInstance,
1228
+
1229
+ isArrayInstance : _isArrayInstance,
1230
+
1231
+ isRegExpInstance : _isRegExpInstance,
1232
+
1233
+ isDate : function(pstrVal, format, getDate)
1234
+ {
1235
+ if (!_isDefined(pstrVal))
1236
+ return false;
1237
+ if (_isDateInstance(pstrVal))
1238
+ {
1239
+ if (typeof(getDate)!='undefined')
1240
+ getDate.date=pstrVal;
1241
+ return true;
1242
+ }
1243
+ return DateParser.isDate(pstrVal, format, getDate);
1244
+ },
1245
+
1246
+ toArray : function(v)
1247
+ {
1248
+ if (_isArrayInstance(v))
1249
+ return v;
1250
+ else return [v];
1251
+ },
1252
+
1253
+ toNumber : function(pobjVal)
1254
+ {
1255
+ var dblRet = Number.NaN;
1256
+
1257
+ if (typeof(pobjVal) == "number")
1258
+ return pobjVal;
1259
+ else
1260
+ {
1261
+ dblRet = new Number(pobjVal);
1262
+ return dblRet.valueOf();
1263
+ }
1264
+ },
1265
+
1266
+ toBoolean : function(pobjVal)
1267
+ {
1268
+ var dblNo = Number.NaN;
1269
+ var strTmp = null;
1270
+
1271
+ if (pobjVal == null || pobjVal == undefined)
1272
+ throw "Boolean value is not defined!";
1273
+ else if (typeof(pobjVal) == "boolean")
1274
+ return pobjVal;
1275
+ else if (typeof(pobjVal) == "number")
1276
+ return (pobjVal != 0);
1277
+ else if (_isNumber(pobjVal))
1278
+ {
1279
+ dblNo = Tokenizer.toNumber(pobjVal);
1280
+ if (isNaN(dblNo))
1281
+ return null;
1282
+ else
1283
+ return (dblNo != 0);
1284
+ }
1285
+ else if (typeof(pobjVal) == "object")
1286
+ {
1287
+ strTmp = pobjVal.toString();
1288
+ if (strTmp.toUpperCase() == "TRUE")
1289
+ return true;
1290
+ else if (strTmp.toUpperCase() == "FALSE")
1291
+ return false;
1292
+ else
1293
+ return null;
1294
+ }
1295
+ else if (typeof(pobjVal) == "string")
1296
+ {
1297
+ if (pobjVal.toUpperCase() == "TRUE")
1298
+ return true;
1299
+ else if (pobjVal.toUpperCase() == "FALSE")
1300
+ return false;
1301
+ else
1302
+ return null;
1303
+ }
1304
+ else
1305
+ return null;
1306
+ },
1307
+
1308
+ Tokanize : function(pstrExpression)
1309
+ {
1310
+
1311
+ var intCntr, intBraces;
1312
+ var arrTokens;
1313
+ var intIndex, intPos;
1314
+ var chrChar, chrNext;
1315
+ var strToken, prevToken;
1316
+
1317
+ // build fast lookup maps
1318
+ _buildMaps();
1319
+
1320
+ intCntr = 0;
1321
+ intBraces = 0;
1322
+ intBrackets = 0;
1323
+ intIndex = 0;
1324
+ strToken = "";
1325
+ arrTokens = new Array();
1326
+ pstrExpression = _trim(pstrExpression);
1327
+ while (intCntr < pstrExpression.length)
1328
+ {
1329
+ prevToken = _EMPTY_TOKEN;
1330
+ chrChar = pstrExpression.substr(intCntr, 1);
1331
+ switch (chrChar)
1332
+ {
1333
+ case " " :
1334
+ if (strToken.length > 0)
1335
+ {
1336
+ arrTokens[intIndex] = _makeToken(strToken);
1337
+ intIndex++;
1338
+ strToken = "";
1339
+ }
1340
+ break;
1341
+ //case "{":
1342
+ case "(":
1343
+ //(chrChar=='(')?intBraces++:intBrackets++;
1344
+ intBraces++;
1345
+ if (strToken.length > 0)
1346
+ {
1347
+ arrTokens[intIndex] = _makeToken(strToken);
1348
+ intIndex++;
1349
+ strToken = "";
1350
+ }
1351
+ arrTokens[intIndex] = _makeToken(chrChar);
1352
+ intIndex++;
1353
+ break;
1354
+ //case "}" :
1355
+ case ")" :
1356
+ //(chrChar==')')?intBraces--:intBrackets--;
1357
+ intBraces--;
1358
+ if (strToken.length > 0)
1359
+ {
1360
+ arrTokens[intIndex] = _makeToken(strToken);
1361
+ intIndex++;
1362
+ strToken = "";
1363
+ }
1364
+ arrTokens[intIndex] = _makeToken(chrChar);
1365
+ intIndex++;
1366
+ break;
1367
+ case "^" :
1368
+ case "*" :
1369
+ case "/" :
1370
+ case "%" :
1371
+ case "&" :
1372
+ case "|" :
1373
+ case "," :
1374
+ case "!" :
1375
+ if (strToken.length > 0)
1376
+ {
1377
+ arrTokens[intIndex] = _makeToken(strToken);
1378
+ intIndex++;
1379
+ strToken = "";
1380
+ }
1381
+ arrTokens[intIndex] = _makeToken(chrChar);
1382
+ intIndex++;
1383
+ break;
1384
+ case "-" :
1385
+ if (strToken.length > 0)
1386
+ {
1387
+ arrTokens[intIndex] = _makeToken(strToken);
1388
+ intIndex++;
1389
+ strToken = "";
1390
+ }
1391
+ chrNext = pstrExpression.substr(intCntr + 1, 1);
1392
+ if (arrTokens.length > 0)
1393
+ prevToken = arrTokens[intIndex - 1];
1394
+ if (/*intCntr == 0 ||*/((prevToken.isArithmeticOp ||
1395
+ prevToken.isLeftParen || prevToken.isComma) &&
1396
+ (_isDigit(chrNext) || chrNext == "(")))
1397
+ {
1398
+ // Negative Number
1399
+ strToken += chrChar;
1400
+ }
1401
+ else
1402
+ {
1403
+ arrTokens[intIndex] = _makeToken(chrChar);
1404
+ intIndex++;
1405
+ strToken = "";
1406
+ }
1407
+ break;
1408
+ case "+" :
1409
+ if (strToken.length > 0)
1410
+ {
1411
+ arrTokens[intIndex] = _makeToken(strToken);
1412
+ intIndex++;
1413
+ strToken = "";
1414
+ }
1415
+ chrNext = pstrExpression.substr(intCntr + 1, 1);
1416
+ if (arrTokens.length > 0)
1417
+ prevToken = arrTokens[intIndex - 1];
1418
+ if (/*intCntr == 0 ||*/ ((prevToken.isArithmeticOp ||
1419
+ prevToken.isLeftParen || prevToken.isComma) &&
1420
+ (_isDigit(chrNext) || chrNext == "(")))
1421
+ {
1422
+ // positive Number
1423
+ strToken += chrChar;
1424
+ }
1425
+ else
1426
+ {
1427
+ arrTokens[intIndex] = _makeToken(chrChar);
1428
+ intIndex++;
1429
+ strToken = "";
1430
+ }
1431
+ break;
1432
+ case "<" :
1433
+ chrNext = pstrExpression.substr(intCntr + 1, 1);
1434
+ if (strToken.length > 0)
1435
+ {
1436
+ arrTokens[intIndex] = _makeToken(strToken);
1437
+ intIndex++;
1438
+ strToken = "";
1439
+ }
1440
+ if (chrNext == "=")
1441
+ {
1442
+ arrTokens[intIndex] = _makeToken(chrChar + "=");
1443
+ intIndex++;
1444
+ intCntr++;
1445
+ }
1446
+ else if (chrNext == ">")
1447
+ {
1448
+ arrTokens[intIndex] = _makeToken(chrChar + ">");
1449
+ intIndex++;
1450
+ intCntr++;
1451
+ }
1452
+ else
1453
+ {
1454
+ arrTokens[intIndex] = _makeToken(chrChar);
1455
+ intIndex++;
1456
+ }
1457
+ break;
1458
+ case ">" :
1459
+ chrNext = pstrExpression.substr(intCntr + 1, 1);
1460
+ if (strToken.length > 0)
1461
+ {
1462
+ arrTokens[intIndex] = _makeToken(strToken);
1463
+ intIndex++;
1464
+ strToken = "";
1465
+ }
1466
+ if (chrNext == "=")
1467
+ {
1468
+ arrTokens[intIndex] = _makeToken(chrChar + "=");
1469
+ intIndex++;
1470
+ intCntr++;
1471
+ }
1472
+ else
1473
+ {
1474
+ arrTokens[intIndex] = _makeToken(chrChar);
1475
+ intIndex++;
1476
+ }
1477
+ break;
1478
+ case "=" :
1479
+ if (strToken.length > 0)
1480
+ {
1481
+ arrTokens[intIndex] = _makeToken(strToken);
1482
+ intIndex++;
1483
+ strToken = "";
1484
+ }
1485
+ arrTokens[intIndex] = _makeToken(chrChar);
1486
+ intIndex++;
1487
+ break;
1488
+ case "'" :
1489
+ case "\"" :
1490
+ if (strToken.length > 0)
1491
+ {
1492
+ arrTokens[intIndex] = _makeToken(strToken);
1493
+ intIndex++;
1494
+ strToken = "";
1495
+ }
1496
+
1497
+ intPos = pstrExpression.indexOf(chrChar, intCntr + 1);
1498
+ if (intPos < 0)
1499
+ throw "Unterminated string constant";
1500
+ else
1501
+ {
1502
+ strToken += pstrExpression.substring(intCntr + 1, intPos);
1503
+ strToken=new String(strToken);
1504
+ strToken._isStringLiteral=true;
1505
+ arrTokens[intIndex] = _makeToken(strToken);
1506
+ intIndex++;
1507
+ strToken = "";
1508
+ intCntr = intPos;
1509
+ }
1510
+ break;
1511
+ default :
1512
+ strToken += chrChar;
1513
+ break;
1514
+ }
1515
+ intCntr++;
1516
+ }
1517
+ if (intBraces > 0)
1518
+ throw "Unbalanced parenthesis!";
1519
+
1520
+ if (strToken.length > 0)
1521
+ arrTokens[intIndex] = _makeToken(strToken);
1522
+ return arrTokens;
1523
+ }
1524
+ }
1525
+ })(DateParser);
1526
+
1527
+ /*------------------------------------------------------------------------------
1528
+ * NAME : HandleFunctions
1529
+ * PURPOSE : Execute built-in functions
1530
+ * PARAMETERS : pstrTok - The current function name
1531
+ * pStack - Operand stack
1532
+ * RETURNS : Nothing, the result is pushed back onto the stack.
1533
+ *----------------------------------------------------------------------------*/
1534
+ function _HandleFunctions(pstrTok, pStack, pdtFormat, parrVars)
1535
+ {
1536
+ var varTmp, varTerm, varTerm2, objTmp, varFormat;
1537
+ var objOp1, objOp2, objFormat;
1538
+ var arrArgs;
1539
+ var intCntr;
1540
+
1541
+
1542
+
1543
+ if (!pstrTok.isFunction)
1544
+ throw "Unsupported function token [" + pstrTok.val + "]";
1545
+
1546
+ varTmp = pstrTok.val;
1547
+ arrArgs = new Array();
1548
+ varTerm = Tokenizer.ARG_TERMINAL;
1549
+ while ( !pStack.IsEmpty() )
1550
+ {
1551
+ varTerm = pStack.Pop();
1552
+ if (!varTerm.isArgTerminal)
1553
+ arrArgs[arrArgs.length] = varTerm;
1554
+ else
1555
+ break;
1556
+ }
1557
+
1558
+ // console.log( 'testing functions ', varTmp, arrArgs );
1559
+
1560
+ switch (varTmp)
1561
+ {
1562
+ case "ARRAY" :
1563
+ var arrArray=new Array();
1564
+
1565
+ objTmp = 0;
1566
+ intCntr = arrArgs.length;
1567
+ while (--intCntr >= 0)
1568
+ {
1569
+ varTerm = arrArgs[intCntr];
1570
+ if (varTerm.isVariable)
1571
+ {
1572
+ objTmp = parrVars[varTerm.val];
1573
+ if (objTmp == undefined || objTmp == null)
1574
+ throw "Variable [" + varTerm.val + "] not defined";
1575
+ else
1576
+ varTerm = objTmp;
1577
+ }
1578
+ arrArray=arrArray.concat(Tokenizer.toArray(varTerm.val));
1579
+ }
1580
+ pStack.Push(Tokenizer.makeToken(arrArray,Tokenizer.TOKEN_TYPE.ARRAY));
1581
+ break;
1582
+ case "TODAY" :
1583
+ pStack.Push(Tokenizer.makeToken(DateParser.currentDate(), Tokenizer.TOKEN_TYPE.DATE));
1584
+ break;
1585
+ case "ACOS" :
1586
+ case "ASIN" :
1587
+ case "ATAN" :
1588
+ throw "Function [" + varTmp + "] is not implemented!";
1589
+ break;
1590
+ case "ABS" :
1591
+ case "CHR" :
1592
+ case "COS" :
1593
+ case "FIX" :
1594
+ case "HEX" :
1595
+ case "LOG" :
1596
+ case "RAND" :
1597
+ case "ROUND" :
1598
+ case "SIN" :
1599
+ case "SQRT" :
1600
+ case "TAN" :
1601
+
1602
+ if (varTmp != "RAND")
1603
+ {
1604
+ if (arrArgs.length < 1)
1605
+ throw varTmp + " requires atleast one argument!";
1606
+ else if (arrArgs.length > 1)
1607
+ throw varTmp + " requires only one argument!";
1608
+ }
1609
+ else
1610
+ {
1611
+ if (arrArgs.length < 1)
1612
+ throw varTmp + " requires atleast one argument!";
1613
+ else if (arrArgs.length > 2)
1614
+ throw varTmp + " requires at most two arguments!";
1615
+ }
1616
+ varTerm = arrArgs[0];
1617
+ if (varTerm.isVariable)
1618
+ {
1619
+ objTmp = parrVars[varTerm.val];
1620
+ if (objTmp == undefined || objTmp == null)
1621
+ throw "Variable [" + varTerm.val + "] not defined";
1622
+ else
1623
+ varTerm = objTmp;
1624
+ }
1625
+
1626
+ objTmp = varTerm.val;
1627
+
1628
+ if( varTerm.val !== 0 && !varTerm.val )
1629
+ throw varTmp + " operates on numeric operands only!";
1630
+
1631
+ else if ( isNaN( +varTerm.val ) )
1632
+ throw varTmp + " operates on numeric operands only!";
1633
+ else
1634
+ {
1635
+
1636
+ objTmp = Tokenizer.toNumber(varTerm.val);
1637
+ if (varTmp == "RAND")
1638
+ {
1639
+ rand_max=Math.floor(objTmp);
1640
+ if (arrArgs.length == 2)
1641
+ {
1642
+ varTerm = arrArgs[1];
1643
+ if (varTerm.isVariable)
1644
+ {
1645
+ objTmp = parrVars[varTerm.val];
1646
+ if (objTmp == undefined || objTmp == null)
1647
+ throw "Variable [" + varTerm.val + "] not defined";
1648
+ else
1649
+ varTerm = objTmp;
1650
+ }
1651
+
1652
+ if (!varTerm.isNumber)
1653
+ throw varTmp + " operates on numeric operands only!";
1654
+
1655
+ objTmp = Tokenizer.toNumber(varTerm.val);
1656
+
1657
+ rand_min=Math.floor(objTmp);
1658
+ }
1659
+ }
1660
+ }
1661
+
1662
+ if (varTmp == "ABS")
1663
+ pStack.Push(Tokenizer.makeToken(Math.abs(objTmp),Tokenizer.TOKEN_TYPE.NUMBER));
1664
+ else if (varTmp == "CHR"){
1665
+ // TODO check what happens when $objTmp is empty; what does fromCharCode() return?
1666
+
1667
+ pStack.Push(Tokenizer.makeToken(String.fromCharCode(objTmp),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
1668
+ }
1669
+ else if (varTmp == "COS")
1670
+ pStack.Push(Tokenizer.makeToken(Math.cos(objTmp),Tokenizer.TOKEN_TYPE.NUMBER));
1671
+ else if (varTmp == "FIX")
1672
+ pStack.Push(Tokenizer.makeToken(Math.floor(objTmp),Tokenizer.TOKEN_TYPE.NUMBER));
1673
+ else if (varTmp == "HEX")
1674
+ pStack.Push(Tokenizer.makeToken(objTmp.toString(16),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
1675
+ else if (varTmp == "LOG")
1676
+ pStack.Push(Tokenizer.makeToken(Math.log(objTmp),Tokenizer.TOKEN_TYPE.NUMBER));
1677
+ else if (varTmp == "RAND")
1678
+ pStack.Push(Tokenizer.makeToken(Math.round(rand_min+(rand_max-rand_min)*Math.random()),Tokenizer.TOKEN_TYPE.NUMBER));
1679
+ else if (varTmp == "ROUND")
1680
+ pStack.Push(Tokenizer.makeToken(Math.round(objTmp),Tokenizer.TOKEN_TYPE.NUMBER));
1681
+ else if (varTmp == "SIN")
1682
+ pStack.Push(Tokenizer.makeToken(Math.sin(objTmp),Tokenizer.TOKEN_TYPE.NUMBER));
1683
+ else if (varTmp == "SQRT")
1684
+ pStack.Push(Tokenizer.makeToken(Math.sqrt(objTmp),Tokenizer.TOKEN_TYPE.NUMBER));
1685
+ else if (varTmp == "TAN")
1686
+ pStack.Push(Tokenizer.makeToken(Math.tan(objTmp),Tokenizer.TOKEN_TYPE.NUMBER));
1687
+ break;
1688
+ case "STR" :
1689
+ if (arrArgs.length < 1)
1690
+ throw varTmp + " requires atleast one argument!";
1691
+ else if (arrArgs.length > 2)
1692
+ throw varTmp + " requires at most two arguments!";
1693
+ varTerm = arrArgs[arrArgs.length-1];
1694
+ if (varTerm.isVariable)
1695
+ {
1696
+ objTmp = parrVars[varTerm.val];
1697
+ if (objTmp == undefined || objTmp == null)
1698
+ throw "Variable [" + varTerm.val + "] not defined";
1699
+ else
1700
+ varTerm = objTmp;
1701
+ }
1702
+ // if date, output formated date string
1703
+ if (varTerm.isDate)
1704
+ {
1705
+ var format='';
1706
+ if (arrArgs.length==2)
1707
+ {
1708
+ varFormat = arrArgs[0];
1709
+ if (varFormat.isVariable)
1710
+ {
1711
+ objTmp = parrVars[varFormat.val];
1712
+ if (objTmp == undefined || objTmp == null)
1713
+ throw "Variable [" + varFormat.val + "] not defined";
1714
+ else
1715
+ varFormat = objTmp;
1716
+ }
1717
+
1718
+ if (!varFormat.isStringLiteral)
1719
+ throw "format argument for " + varTmp + " must be a string!";
1720
+ format=varFormat.val;
1721
+ }
1722
+ pStack.Push(Tokenizer.makeToken(DateParser.formatDate(varTerm.val, format),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
1723
+ }
1724
+ else // just convert to string
1725
+ pStack.Push(Tokenizer.makeToken(varTerm.val.toString(),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
1726
+ break;
1727
+ case "ASC" :
1728
+
1729
+ if (arrArgs.length > 1)
1730
+ throw varTmp + " requires only one argument!";
1731
+ else if (arrArgs.length < 1)
1732
+ throw varTmp + " requires atleast one argument!";
1733
+ varTerm = arrArgs[0];
1734
+ if (varTerm.isVariable)
1735
+ {
1736
+ objTmp = parrVars[varTerm.val];
1737
+ if (objTmp == undefined || objTmp == null)
1738
+ throw "Variable [" + varTerm.val + "] not defined";
1739
+ else
1740
+ varTerm = objTmp;
1741
+ }
1742
+ if( varTerm.isNumber )
1743
+ {
1744
+ varTerm.val = varTerm.val.toString();
1745
+ varTerm.isStringLiteral = true;
1746
+ }
1747
+
1748
+ if (!varTerm.isStringLiteral)
1749
+ throw varTmp + " requires a string type operand!";
1750
+ else
1751
+ {
1752
+ if ( varTerm.val ) {
1753
+ pStack.Push(Tokenizer.makeToken(varTerm.val.charCodeAt(0),Tokenizer.TOKEN_TYPE.NUMBER));
1754
+ } else {
1755
+ pStack.Push(Tokenizer.makeToken(0,Tokenizer.TOKEN_TYPE.NUMBER));
1756
+ }
1757
+ }
1758
+ break;
1759
+ case "REGEX" :
1760
+ if (arrArgs.length < 1)
1761
+ throw varTmp + " requires atleast one argument!";
1762
+ else if (arrArgs.length > 2)
1763
+ throw varTmp + " requires at most two arguments!";
1764
+
1765
+ varTerm = arrArgs[arrArgs.length-1];
1766
+ if (varTerm.isVariable)
1767
+ {
1768
+ objTmp = parrVars[varTerm.val];
1769
+ if (objTmp == undefined || objTmp == null)
1770
+ throw "Variable [" + varTerm.val + "] not defined";
1771
+ else
1772
+ varTerm = objTmp;
1773
+ }
1774
+
1775
+ if (!varTerm.isStringLiteral)
1776
+ throw varTmp + " operates on string type operands!";
1777
+
1778
+ var opts=Tokenizer.EMPTY_STRING;
1779
+ if (arrArgs.length==2)
1780
+ {
1781
+ opts = arrArgs[0];
1782
+ if (opts.isVariable)
1783
+ {
1784
+ objTmp = parrVars[opts.val];
1785
+ if (objTmp == undefined || objTmp == null)
1786
+ throw "Variable [" + opts.val + "] not defined";
1787
+ else
1788
+ opts = objTmp;
1789
+ }
1790
+
1791
+ if (!opts.isStringLiteral)
1792
+ throw varTmp + " operates on string type operands!";
1793
+ }
1794
+ pStack.Push(Tokenizer.makeToken(Functions.Regex(varTerm.val.toString(), opts.val.toString()),Tokenizer.TOKEN_TYPE.REGEX));
1795
+ break;
1796
+ case "LCASE" :
1797
+ case "UCASE" :
1798
+ case "NUM" :
1799
+
1800
+ if (arrArgs.length < 1)
1801
+ throw varTmp + " requires atleast one argument!";
1802
+ else if (arrArgs.length > 1)
1803
+ throw varTmp + " requires only one argument!";
1804
+
1805
+ varTerm = arrArgs[0];
1806
+ if (varTerm.isVariable)
1807
+ {
1808
+ objTmp = parrVars[varTerm.val];
1809
+ if (objTmp == undefined || objTmp == null)
1810
+ throw "Variable [" + varTerm.val + "] not defined";
1811
+ else
1812
+ varTerm = objTmp;
1813
+ }
1814
+
1815
+ if( varTerm.isNumber )
1816
+ {
1817
+ varTerm.val = varTerm.val.toString();
1818
+ varTerm.isStringLiteral = true;
1819
+ }
1820
+
1821
+ if (!varTerm.isStringLiteral && varTmp != "NUM")
1822
+ throw varTmp + " requires a string type operand!";
1823
+ else
1824
+ {
1825
+ if (varTmp == "LCASE")
1826
+ {
1827
+ pStack.Push(Tokenizer.makeToken(varTerm.val.toLowerCase(),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
1828
+ }
1829
+ else if (varTmp == "UCASE")
1830
+ {
1831
+ pStack.Push(Tokenizer.makeToken(varTerm.val.toUpperCase(),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
1832
+ }
1833
+ else if (varTmp == "NUM")
1834
+ {
1835
+ objTmp=Tokenizer.toNumber(varTerm.val)+0.0;
1836
+ if (isNaN(objTmp))
1837
+ throw varTmp + " cannot convert [" + varTerm.val + "] to number!";
1838
+ pStack.Push(Tokenizer.makeToken(objTmp,Tokenizer.TOKEN_TYPE.NUMBER));
1839
+ }
1840
+ }
1841
+ break;
1842
+ case "LEN" :
1843
+ if (arrArgs.length < 1)
1844
+ throw varTmp + " requires atleast one argument!";
1845
+ else if (arrArgs.length > 1)
1846
+ throw varTmp + " requires only one argument!";
1847
+
1848
+ varTerm = arrArgs[0];
1849
+ if (varTerm.isVariable)
1850
+ {
1851
+ objTmp = parrVars[varTerm.val];
1852
+ if (objTmp == undefined || objTmp == null)
1853
+ throw "Variable [" + varTerm.val + "] not defined";
1854
+ else
1855
+ varTerm = objTmp;
1856
+ }
1857
+
1858
+ if (!varTerm.isArray && !varTerm.isStringLiteral)
1859
+ throw varTmp + " requires a string or array type operand!";
1860
+ else
1861
+ {
1862
+ pStack.Push(Tokenizer.makeToken(varTerm.val.length,Tokenizer.TOKEN_TYPE.NUMBER));
1863
+ }
1864
+ break;
1865
+ case "USER" :
1866
+ if (arrArgs.length < 1)
1867
+ throw varTmp + " requires atleast one argument!";
1868
+ else if (arrArgs.length > 1)
1869
+ throw varTmp + " requires only one argument!";
1870
+
1871
+ varTerm = arrArgs[0];
1872
+ if (varTerm.isVariable)
1873
+ {
1874
+ objTmp = parrVars[varTerm.val];
1875
+ if (objTmp == undefined || objTmp == null)
1876
+ throw "Variable [" + varTerm.val + "] not defined";
1877
+ else
1878
+ varTerm = objTmp;
1879
+ }
1880
+
1881
+ if (!varTerm.isStringLiteral)
1882
+ throw varTmp + " requires a string type operand!";
1883
+ else
1884
+ {
1885
+ pStack.Push(Tokenizer.makeToken(Functions.User(varTerm.val),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
1886
+ }
1887
+ break;
1888
+ case "COOKIE" :
1889
+ if (arrArgs.length < 1)
1890
+ throw varTmp + " requires atleast one argument!";
1891
+ else if (arrArgs.length > 1)
1892
+ throw varTmp + " requires only one argument!";
1893
+
1894
+ varTerm = arrArgs[0];
1895
+ if (varTerm.isVariable)
1896
+ {
1897
+ objTmp = parrVars[varTerm.val];
1898
+ if (objTmp == undefined || objTmp == null)
1899
+ throw "Variable [" + varTerm.val + "] not defined";
1900
+ else
1901
+ varTerm = objTmp;
1902
+ }
1903
+
1904
+ if (!varTerm.isStringLiteral)
1905
+ throw varTmp + " requires a string type operand!";
1906
+ else
1907
+ {
1908
+ //console.log(varTerm.val,varTerm.val.length);
1909
+ pStack.Push(Tokenizer.makeToken(Functions.Cookie(varTerm.val),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
1910
+ }
1911
+ break;
1912
+ case "CONTAINS" :
1913
+ // console.log( 'testing functions ', varTmp, arrArgs );
1914
+ if (arrArgs.length < 2)
1915
+ throw varTmp + " requires atleast two arguments!";
1916
+ else if (arrArgs.length > 2)
1917
+ throw varTmp + " requires only two arguments!";
1918
+
1919
+ varTerm = arrArgs[1];
1920
+ if (varTerm.isVariable)
1921
+ {
1922
+ objTmp = parrVars[varTerm.val];
1923
+ if (objTmp == undefined || objTmp == null)
1924
+ throw "Variable [" + varTerm.val + "] not defined";
1925
+ else
1926
+ varTerm = objTmp;
1927
+ }
1928
+ varTerm2 = arrArgs[0];
1929
+ if (varTerm2.isVariable)
1930
+ {
1931
+ objTmp = parrVars[varTerm2.val];
1932
+ if (objTmp == undefined || objTmp == null)
1933
+ throw "Variable [" + varTerm2.val + "] not defined";
1934
+ else
1935
+ varTerm2 = objTmp;
1936
+ }
1937
+
1938
+ if ( !varTerm.isArray )
1939
+ throw varTmp + " requires an array as first argument!";
1940
+ else
1941
+ {
1942
+ var found=false;
1943
+ /*var ii=varTerm.val.length;
1944
+ while(--ii>=0)
1945
+ {
1946
+ if (varTerm.val[ii]==varTerm2.val)
1947
+ {
1948
+ found=true;
1949
+ break;
1950
+ }
1951
+ }*/
1952
+ found=Functions.Contains(varTerm.val, varTerm2.val);
1953
+ pStack.Push(Tokenizer.makeToken(found,Tokenizer.TOKEN_TYPE.BOOLEAN));
1954
+ }
1955
+ break;
1956
+ case "DATE" :
1957
+ if (arrArgs.length < 2)
1958
+ throw varTmp + " requires atleast two arguments!";
1959
+ else if (arrArgs.length > 2)
1960
+ throw varTmp + " requires only two arguments!";
1961
+
1962
+ varTerm = arrArgs[1];
1963
+ if (varTerm.isVariable)
1964
+ {
1965
+ objTmp = parrVars[varTerm.val];
1966
+ if (objTmp == undefined || objTmp == null)
1967
+ throw "Variable [" + varTerm.val + "] not defined";
1968
+ else
1969
+ varTerm = objTmp;
1970
+ }
1971
+ varFormat = arrArgs[0];
1972
+ if (varFormat.isVariable)
1973
+ {
1974
+ objFormat = parrVars[varFormat.val];
1975
+ if (objFormat == undefined || objFormat == null)
1976
+ throw "Variable [" + varFormat.val + "] not defined";
1977
+ else
1978
+ varFormat = objFormat;
1979
+ }
1980
+
1981
+ var dateobj={};
1982
+ if (
1983
+ (!varTerm.isStringLiteral) ||
1984
+ (!varFormat.isStringLiteral)
1985
+ )
1986
+ throw varTmp + " requires string type operands!";
1987
+ else if (!Tokenizer.isDate(varTerm.val, varFormat.val, dateobj))
1988
+ throw varTmp + " can not convert [" + varTerm.val + "] to a valid date with format [" + varFormat.val + "]!";
1989
+ else
1990
+ {
1991
+ if (dateobj.date)
1992
+ pStack.Push(Tokenizer.makeToken(dateobj.date,Tokenizer.TOKEN_TYPE.DATE));
1993
+ else
1994
+ throw varTmp + " unknown error";
1995
+ }
1996
+ break;
1997
+ case "empty":
1998
+ case "EMPTY":
1999
+ if (arrArgs.length < 1)
2000
+ throw varTmp + " requires at least one arguments!";
2001
+ else if (arrArgs.length > 1)
2002
+ throw varTmp + " requires only one arguments!";
2003
+
2004
+ varFormat = arrArgs[0];
2005
+
2006
+
2007
+ if( varFormat.isEmpty === true )
2008
+ {
2009
+ pStack.Push( Tokenizer.makeToken(true,Tokenizer.TOKEN_TYPE.BOOLEAN) );
2010
+ }
2011
+ else if( varFormat.isArray === true && varFormat.val.length === 0 )
2012
+ {
2013
+ pStack.Push( Tokenizer.makeToken(true,Tokenizer.TOKEN_TYPE.BOOLEAN) );
2014
+ }
2015
+ else if( varFormat.isStringLiteral === true && varFormat.val === "" )
2016
+ {
2017
+ pStack.Push( Tokenizer.makeToken(true,Tokenizer.TOKEN_TYPE.BOOLEAN) );
2018
+ }
2019
+ else if( varFormat.isDate && !varFormat.val )
2020
+ {
2021
+ pStack.Push( Tokenizer.makeToken(true,Tokenizer.TOKEN_TYPE.BOOLEAN) );
2022
+ }
2023
+ else
2024
+ {
2025
+ pStack.Push( Tokenizer.makeToken(false,Tokenizer.TOKEN_TYPE.BOOLEAN) );
2026
+ }
2027
+
2028
+
2029
+ break;
2030
+ case "LEFT" :
2031
+ case "RIGHT" :
2032
+ if (arrArgs.length < 2)
2033
+ throw varTmp + " requires atleast two arguments!";
2034
+ else if (arrArgs.length > 2)
2035
+ throw varTmp + " requires only two arguments!";
2036
+
2037
+ for (intCntr = 0; intCntr < arrArgs.length; intCntr++)
2038
+ {
2039
+ varTerm = arrArgs[intCntr];
2040
+ if (varTerm.isVariable)
2041
+ {
2042
+ objTmp = parrVars[varTerm.val];
2043
+ if (objTmp == undefined || objTmp == null)
2044
+ throw "Variable [" + varTerm.val + "] not defined";
2045
+ else
2046
+ varTerm = objTmp;
2047
+ }
2048
+
2049
+ if( varTerm.isNumber )
2050
+ {
2051
+ arrArgs[1].val = arrArgs[1].val.toString()
2052
+ varTerm.isStringLiteral = true;
2053
+ }
2054
+
2055
+ if (intCntr == 0 && !varTerm.isNumber)
2056
+ throw varTmp + " operator requires numeric length!";
2057
+ else if (intCntr == 1 && !varTerm.isStringLiteral)
2058
+ throw varTmp + " operator requires a string operand!";
2059
+ arrArgs[intCntr] = varTerm;
2060
+ }
2061
+ varTerm = arrArgs[1].val.toString();
2062
+ objTmp = Tokenizer.toNumber(arrArgs[0].val);
2063
+ if (varTmp == "LEFT")
2064
+ {
2065
+ pStack.Push(Tokenizer.makeToken(varTerm.substring(0, objTmp),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
2066
+ }
2067
+ else
2068
+ {
2069
+ pStack.Push(Tokenizer.makeToken(varTerm.substr((varTerm.length - objTmp), objTmp),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
2070
+ }
2071
+ break;
2072
+ case "MID" :
2073
+ case "IIF" :
2074
+
2075
+ if (arrArgs.length < 3)
2076
+ throw varTmp + " requires atleast three arguments!";
2077
+ else if (arrArgs.length > 3)
2078
+ throw varTmp + " requires only three arguments!";
2079
+
2080
+
2081
+
2082
+ for (intCntr = 0; intCntr < arrArgs.length; intCntr++)
2083
+ {
2084
+ varTerm = arrArgs[intCntr];
2085
+ if (varTerm.isVariable)
2086
+ {
2087
+ objTmp = parrVars[varTerm.val];
2088
+ if (objTmp == undefined || objTmp == null)
2089
+ throw "Variable [" + varTerm.val + "] not defined";
2090
+ else
2091
+ varTerm = objTmp;
2092
+ }
2093
+
2094
+ if( varTerm.isNumber )
2095
+ {
2096
+ arrArgs[2].val = arrArgs[2].val.toString()
2097
+ varTerm.isStringLiteral = true;
2098
+ }
2099
+
2100
+ if (varTmp == "MID" && intCntr <= 1 && !varTerm.isNumber)
2101
+ throw varTmp + " operator requires numeric lengths!";
2102
+ else if (varTmp == "MID" && intCntr == 2 && !varTerm.isStringLiteral)
2103
+ throw varTmp + " operator requires a string input!";
2104
+ //else if (varTmp == "IIF" && intCntr == 2 && !varTerm.isBoolean && !varTerm.isNumber)
2105
+ //throw varTmp + " operator requires boolean condition!";
2106
+ arrArgs[intCntr] = varTerm;
2107
+ }
2108
+ if (varTmp == "MID")
2109
+ {
2110
+ varTerm = arrArgs[2].val.toString();
2111
+ objOp1 = Tokenizer.toNumber(arrArgs[1].val);
2112
+ objOp2 = Tokenizer.toNumber(arrArgs[0].val);
2113
+ pStack.Push(Tokenizer.makeToken(varTerm.substring(objOp1, objOp2),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
2114
+ }
2115
+ else
2116
+ {
2117
+
2118
+ varTerm = Tokenizer.toBoolean(arrArgs[2].val);
2119
+
2120
+ if (varTerm)
2121
+ {
2122
+ objOp1 = arrArgs[1];
2123
+ }
2124
+
2125
+ else
2126
+ {
2127
+ objOp1 = arrArgs[0];
2128
+ }
2129
+
2130
+ pStack.Push(objOp1);
2131
+ }
2132
+ break;
2133
+ case "AVG" :
2134
+ case "MAX" :
2135
+ case "MIN" :
2136
+ if (arrArgs.length < 1)
2137
+ throw varTmp + " requires atleast one operand!";
2138
+
2139
+ var _arr=[];
2140
+ intCntr = arrArgs.length;
2141
+ while (--intCntr>=0)
2142
+ {
2143
+ varTerm = arrArgs[intCntr];
2144
+ if (varTerm.isVariable)
2145
+ {
2146
+ objTmp = parrVars[varTerm.val];
2147
+ if (objTmp == undefined || objTmp == null)
2148
+ throw "Variable [" + varTerm.val + "] not defined";
2149
+ else
2150
+ varTerm = objTmp;
2151
+ }
2152
+
2153
+ if( jQuery.isArray( varTerm.val ) )
2154
+ {
2155
+ varTerm.isArray = true;
2156
+ }
2157
+ else if( varTerm.val !== '' || isNaN( +varTerm.val ) === false )
2158
+ {
2159
+ varTerm.isNumber = true;
2160
+ }
2161
+
2162
+ if (!varTerm.isNumber && !varTerm.isArray)
2163
+ throw varTmp + " requires numeric or array operands only!";
2164
+
2165
+ if (!varTerm.isArray)
2166
+ _arr=_arr.concat(Tokenizer.toArray(Tokenizer.toNumber(varTerm.val)));
2167
+ else
2168
+ _arr=_arr.concat(varTerm.val);
2169
+ }
2170
+ intCntr = -1;
2171
+ objTmp = 0;
2172
+ while (++intCntr < _arr.length)
2173
+ {
2174
+ varTerm = _arr[intCntr];
2175
+ if (varTmp == "AVG")
2176
+ objTmp += varTerm;
2177
+ else if (varTmp == "MAX")
2178
+ {
2179
+ if (intCntr == 0)
2180
+ objTmp = varTerm;
2181
+ else if (objTmp < varTerm)
2182
+ objTmp = varTerm;
2183
+ }
2184
+ else if (varTmp == "MIN")
2185
+ {
2186
+ if (intCntr == 0)
2187
+ objTmp = varTerm;
2188
+ else if (objTmp > varTerm)
2189
+ objTmp = varTerm;
2190
+ }
2191
+ }
2192
+ if (varTmp == "AVG" && _arr.length)
2193
+ pStack.Push(Tokenizer.makeToken(objTmp/_arr.length,Tokenizer.TOKEN_TYPE.NUMBER));
2194
+ else if (varTmp == "AVG")
2195
+ pStack.Push(Tokenizer.makeToken(0,Tokenizer.TOKEN_TYPE.NUMBER));
2196
+ else
2197
+ pStack.Push(Tokenizer.makeToken(objTmp,Tokenizer.TOKEN_TYPE.NUMBER));
2198
+ break;
2199
+ }
2200
+ };
2201
+
2202
+ /*------------------------------------------------------------------------------
2203
+ * NAME : InFixToPostFix
2204
+ * PURPOSE : Convert an Infix expression into a postfix (RPN) equivalent
2205
+ * PARAMETERS : Infix expression element array
2206
+ * RETURNS : array containing postfix expression element tokens
2207
+ *----------------------------------------------------------------------------*/
2208
+ function _InFixToPostFix(arrToks)
2209
+ {
2210
+ //console.log('post');
2211
+ var myStack;
2212
+ var intCntr, intIndex;
2213
+ var strTok, strTop, strNext, strPrev;
2214
+ var blnStart;
2215
+
2216
+ blnStart = false;
2217
+ intIndex = 0;
2218
+ arrPFix = new Array();
2219
+ myStack = new Stack();
2220
+
2221
+ // Infix to postfix converter
2222
+ for (intCntr = 0; intCntr < arrToks.length; intCntr++)
2223
+ {
2224
+ //console.log(arrPFix);
2225
+ //console.log(myStack.toString());
2226
+ strTok = arrToks[intCntr];
2227
+ switch (strTok.type)
2228
+ {
2229
+ case Tokenizer.TOKEN_TYPE.LEFT_PAREN :
2230
+ if (myStack.Size() > 0 && myStack.Get(0).isFunction)
2231
+ {
2232
+ arrPFix[intIndex] = Tokenizer.ARG_TERMINAL;
2233
+ intIndex++;
2234
+ }
2235
+ myStack.Push(strTok);
2236
+ break;
2237
+ case Tokenizer.TOKEN_TYPE.RIGHT_PAREN :
2238
+ blnStart = true;
2239
+ while (!myStack.IsEmpty())
2240
+ {
2241
+ strTok = myStack.Pop();
2242
+ if (!strTok.isLeftParen)
2243
+ {
2244
+ arrPFix[intIndex] = strTok;
2245
+ intIndex++;
2246
+ }
2247
+ else
2248
+ {
2249
+ blnStart = false;
2250
+ break;
2251
+ }
2252
+ }
2253
+ if (myStack.IsEmpty() && blnStart)
2254
+ throw "Unbalanced parenthesis!";
2255
+ break;
2256
+ case Tokenizer.TOKEN_TYPE.COMMA :
2257
+ while (!myStack.IsEmpty())
2258
+ {
2259
+ strTok = myStack.Get(0);
2260
+ if (strTok.isLeftParen) break;
2261
+ arrPFix[intIndex] = myStack.Pop();
2262
+ intIndex++;
2263
+ }
2264
+ break;
2265
+ //case Tokenizer.TOKEN_TYPE.UNARY_NEGATIVE :
2266
+ //case Tokenizer.TOKEN_TYPE.UNARY_NEGATION :
2267
+ case Tokenizer.TOKEN_TYPE.ARITHMETIC_OP :
2268
+ case Tokenizer.TOKEN_TYPE.LOGICAL_OP :
2269
+ case Tokenizer.TOKEN_TYPE.COMPARISON_OP :
2270
+ switch (strTok.val)
2271
+ {
2272
+ /*case "-" :
2273
+ case "+" :
2274
+ case "NOT" :
2275
+ case "!" :
2276
+ case "^" :
2277
+ case "*" :
2278
+ case "/" :
2279
+ case "%" :
2280
+ case "AND" :
2281
+ case "&" :
2282
+ case "OR" :
2283
+ case "|" :
2284
+ case ">" :
2285
+ case "<" :
2286
+ case "=" :
2287
+ case ">=" :
2288
+ case "<=" :
2289
+ case "<>" :*/
2290
+ default:
2291
+ if (strTok.val=='-')
2292
+ {
2293
+ // check for unary negative operator.
2294
+ strPrev = null;
2295
+ if (intCntr > 0)
2296
+ strPrev = arrToks[intCntr - 1];
2297
+ strNext = arrToks[intCntr + 1];
2298
+ if (strPrev == null || strPrev.isArithmeticOp || strPrev.isLeftParen || strPrev.isComma)
2299
+ {
2300
+ strTok = Tokenizer.UNARY_NEGATIVE;
2301
+ }
2302
+ }
2303
+ if (strTok.val=='+')
2304
+ {
2305
+ // check for unary + addition operator, we need to ignore this.
2306
+ strPrev = null;
2307
+ if (intCntr > 0)
2308
+ strPrev = arrToks[intCntr - 1];
2309
+ strNext = arrToks[intCntr + 1];
2310
+ if (strPrev == null || strPrev.isArithmeticOp || strPrev.isLeftParen || strPrev.isComma)
2311
+ {
2312
+ break;
2313
+ }
2314
+ }
2315
+ strTop = Tokenizer.EMPTY_TOKEN;
2316
+ if (!myStack.IsEmpty()) strTop = myStack.Get(0);
2317
+ if (myStack.IsEmpty() || (!myStack.IsEmpty() && strTop.isLeftParen))
2318
+ {
2319
+ myStack.Push(strTok);
2320
+ }
2321
+ else if (strTok.precedence >= strTop.precedence)
2322
+ {
2323
+ myStack.Push(strTok);
2324
+ }
2325
+ else
2326
+ {
2327
+ // Pop operators with precedence >= operator strTok
2328
+ while (!myStack.IsEmpty())
2329
+ {
2330
+ strTop = myStack.Get(0);
2331
+ if (strTop.isLeftParen || strTop.precedence < strTok.precedence)
2332
+ {
2333
+ break;
2334
+ }
2335
+ else
2336
+ {
2337
+ arrPFix[intIndex] = myStack.Pop();
2338
+ intIndex++;
2339
+ }
2340
+ }
2341
+ myStack.Push(strTok);
2342
+ }
2343
+ break;
2344
+ }
2345
+ break;
2346
+ default :
2347
+ if (strTok.type!=Tokenizer.TOKEN_TYPE.FUNCTION)
2348
+ {
2349
+ arrPFix[intIndex] = strTok;
2350
+ intIndex++;
2351
+ }
2352
+ else
2353
+ {
2354
+ strTop = Tokenizer.EMPTY_TOKEN;
2355
+ if (!myStack.IsEmpty()) strTop = myStack.Get(0);
2356
+ if (myStack.IsEmpty() || (!myStack.IsEmpty() && strTop.isLeftParen))
2357
+ {
2358
+ myStack.Push(strTok);
2359
+ }
2360
+ else if (strTok.precedence >= strTop.precedence)
2361
+ {
2362
+ myStack.Push(strTok);
2363
+ }
2364
+ else
2365
+ {
2366
+ // Pop operators with precedence >= operator in strTok
2367
+ while (!myStack.IsEmpty())
2368
+ {
2369
+ strTop = myStack.Get(0);
2370
+ if (strTop.val == "(" || strTop.precedence < strTok.precedence)
2371
+ {
2372
+ break;
2373
+ }
2374
+ else
2375
+ {
2376
+ arrPFix[intIndex] = myStack.Pop();
2377
+ intIndex++;
2378
+ }
2379
+ }
2380
+ myStack.Push(strTok);
2381
+ }
2382
+ }
2383
+ break;
2384
+ }
2385
+ }
2386
+
2387
+ // Pop remaining operators from stack.
2388
+ while (!myStack.IsEmpty())
2389
+ {
2390
+ arrPFix[intIndex] = myStack.Pop();
2391
+ intIndex++;
2392
+ }
2393
+ //console.log(arrPFix);
2394
+ return arrPFix;
2395
+ };
2396
+
2397
+ // public methods
2398
+ return (function(Tokenizer,DateParser){
2399
+
2400
+ return {
2401
+ // delegate here
2402
+ setParams : function(params)
2403
+ {
2404
+ Functions.setParams(params);
2405
+ },
2406
+
2407
+ Expression : function(pstrExp)
2408
+ {
2409
+ var strInFix = null;
2410
+ var arrVars = [];
2411
+ var arrTokens = null;
2412
+ var arrPostFix = null;
2413
+ var dtFormat = "d/m/Y";
2414
+ var thiss=this;
2415
+
2416
+ if (typeof(pstrExp)!='undefined' && pstrExp)
2417
+ strInFix=pstrExp;
2418
+
2419
+ // public methods
2420
+ this.dateLocales=function(a,b,c){DateParser.setDateLocaleStrings(a,b,c); return thiss;}
2421
+ this.dateFormat = function(df){dtFormat = df; return thiss;};
2422
+ this.expression = function(exp){strInFix = exp; arrTokens=arrPostFix=null; return thiss;};
2423
+ this.addVar = function(_var){_AddNewVariable(_var, arrVars); return thiss;};
2424
+ this.parse = function(){arrPostFix=_ParseExpression(); return _dumpPostFix(arrPostFix);};
2425
+ this.eval = function(){return _EvaluateExpression(arrPostFix, arrVars);};
2426
+ this.reset = function(){arrVars = [];strInFix=arrTokens=arrPostFix=null; return thiss;};
2427
+ this.dump = function(){return _dumpPostFix(arrPostFix);};
2428
+ this.preCompile = function(_exp){if (typeof(_exp)=='undefined') _exp=strInFix; return _getPrecompiledExpression(_exp);};
2429
+
2430
+ function _AddNewVariable(varObj, varArr)
2431
+ {
2432
+ if (typeof(varArr)=='undefined')
2433
+ varArr = arrVars;
2434
+
2435
+ if (varArr == null || varArr == undefined)
2436
+ varArr = new Array();
2437
+
2438
+ varName=varObj.name;
2439
+ varToken=null;
2440
+ if (varObj.withType)
2441
+ {
2442
+ switch(varObj.withType)
2443
+ {
2444
+ case 'boolean':
2445
+ varToken=Tokenizer.makeToken(varObj.val,Tokenizer.TOKEN_TYPE.BOOLEAN); //Tokenizer.toBoolean(varObj.val);
2446
+ break;
2447
+ case 'number':
2448
+ varToken=Tokenizer.makeToken(varObj.val,Tokenizer.TOKEN_TYPE.NUMBER); //Tokenizer.toNumber(varObj.val);
2449
+ break;
2450
+ case 'array':
2451
+ varToken=Tokenizer.makeToken(varObj.val,Tokenizer.TOKEN_TYPE.ARRAY); //Tokenizer.toArray(varObj.val);
2452
+ break;
2453
+ case 'date':
2454
+ var format;
2455
+ if (varObj.format)
2456
+ format=varObj.format;
2457
+ else
2458
+ format=dtFormat;
2459
+ //varValue=DateParser.parseDate(varObj.val, format);
2460
+ varToken=Tokenizer.makeToken(DateParser.parseDate(varObj.val, format),Tokenizer.TOKEN_TYPE.DATE); //
2461
+ break;
2462
+ case 'string':
2463
+ default:
2464
+ varToken=Tokenizer.makeToken(varObj.val,Tokenizer.TOKEN_TYPE.STRING_LITERAL); //
2465
+ break;
2466
+ }
2467
+ }
2468
+ else
2469
+ varToken=Tokenizer.makeToken(varObj.val,Tokenizer.TOKEN_TYPE.STRING_LITERAL); //
2470
+
2471
+ varArr[varName] = varToken;
2472
+ }
2473
+
2474
+ function _dumpPostFix(pf)
2475
+ {
2476
+ var out='';
2477
+ for (var i=0; i<pf.length; i++)
2478
+ out+=pf[i].val+',';
2479
+ return out;
2480
+ }
2481
+
2482
+ function _clonePostFix(pf)
2483
+ {
2484
+ var newpf=new Array(pf.length);
2485
+ for (var i=0; i<pf.length; i++)
2486
+ newpf[i]=Tokenizer.cloneToken(pf[i]);
2487
+ return newpf;
2488
+ }
2489
+
2490
+ function _createFunction(myarrPostFix)
2491
+ {
2492
+ return function(vars)
2493
+ {
2494
+ // init internal closure vars
2495
+ var myvarsArray=[];
2496
+ // add user vars at run-time
2497
+ if (typeof(vars)!='undefined' && vars)
2498
+ {
2499
+ for (var i=0; i<vars.length; i++)
2500
+ _AddNewVariable(vars[i], myvarsArray);
2501
+ }
2502
+ //console.log(_dumpPostFix(myarrPostFix));
2503
+ // return evaluated result
2504
+ return _EvaluateExpression(_clonePostFix(myarrPostFix), myvarsArray);
2505
+ }
2506
+ }
2507
+
2508
+ function _getPrecompiledExpression(exp)
2509
+ {
2510
+ var myarrTokens = Tokenizer.Tokanize(exp);
2511
+ if (myarrTokens == null || myarrTokens == undefined)
2512
+ throw "Unable to tokanize the expression!";
2513
+ if (myarrTokens.length <= 0)
2514
+ throw "Unable to tokanize the expression!";
2515
+
2516
+ var myarrPostFix0 = _InFixToPostFix(myarrTokens);
2517
+ if (myarrPostFix0 == null || myarrPostFix0 == undefined)
2518
+ throw "Unable to convert the expression to postfix form!";
2519
+ if (myarrPostFix0.length <= 0)
2520
+ throw "Unable to convert the expression to postfix form!";
2521
+
2522
+ // return precompiled dynamic function
2523
+ return _createFunction(myarrPostFix0);
2524
+ }
2525
+
2526
+ function _ParseExpression()
2527
+ {
2528
+ arrTokens = Tokenizer.Tokanize(strInFix);
2529
+ if (arrTokens == null || arrTokens == undefined)
2530
+ throw "Unable to tokanize the expression!";
2531
+ if (arrTokens.length <= 0)
2532
+ throw "Unable to tokanize the expression!";
2533
+
2534
+ var myarrPostFix = _InFixToPostFix(arrTokens);
2535
+ if (myarrPostFix == null || myarrPostFix == undefined)
2536
+ throw "Unable to convert the expression to postfix form!";
2537
+ if (myarrPostFix.length <= 0)
2538
+ throw "Unable to convert the expression to postfix form!";
2539
+ return myarrPostFix;
2540
+ }
2541
+
2542
+ function _getVariable(strVarName, varArr)
2543
+ {
2544
+ var retVal;
2545
+
2546
+ if (typeof(varArr)=='undefined')
2547
+ varArr=arrVars;
2548
+
2549
+ if (varArr == null || varArr == undefined)
2550
+ throw "Variable values are not supplied!";
2551
+
2552
+ retVal = varArr[strVarName];
2553
+ if (typeof(varArr[strVarName])=='undefined' || retVal == undefined || retVal == null)
2554
+ throw "Variable [" + strVarName + "] not defined";
2555
+ return retVal;
2556
+ }
2557
+
2558
+ // postfix function evaluator
2559
+ function _EvaluateExpression(myarrPostFix, myvarArr)
2560
+ {
2561
+
2562
+ var intIndex;
2563
+ var myStack;
2564
+ var strTok, strOp;
2565
+ var objOp1, objOp2, objTmp1, objTmp2;
2566
+ var dblNo, dblVal1, dblVal2;
2567
+
2568
+ if (myarrPostFix == null || myarrPostFix == undefined)
2569
+ myarrPostFix=_ParseExpression();
2570
+ if (myarrPostFix.length == 0)
2571
+ throw "Unable to parse the expression!";
2572
+ if (myarrPostFix == null || myarrPostFix == undefined || myarrPostFix.length == 0)
2573
+ {
2574
+ throw "Invalid postfix expression!";
2575
+ return;
2576
+ }
2577
+
2578
+ intIndex = 0;
2579
+ myStack = new Stack();
2580
+ //console.log(myarrPostFix);
2581
+ while (intIndex < myarrPostFix.length)
2582
+ {
2583
+ //console.log(myStack.toString());
2584
+ strTok = myarrPostFix[intIndex];
2585
+ switch (strTok.type)
2586
+ {
2587
+ case Tokenizer.TOKEN_TYPE.ARG_TERMINAL :
2588
+ myStack.Push(strTok);
2589
+ break;
2590
+ case Tokenizer.TOKEN_TYPE.UNARY_NEGATIVE :
2591
+ if (myStack.IsEmpty())
2592
+ throw "No operand to negate!";
2593
+
2594
+ objOp1 = null;
2595
+ objOp2 = null;
2596
+ objOp1 = myStack.Pop();
2597
+ if (objOp1.isVariable)
2598
+ objOp1 = _getVariable(objOp1.val, myvarArr);
2599
+
2600
+ dblNo = Tokenizer.toNumber(objOp1.val);
2601
+ if (isNaN(dblNo))
2602
+ throw "Not a numeric value!";
2603
+ else
2604
+ {
2605
+ dblNo = (0 - dblNo);
2606
+ myStack.Push(Tokenizer.makeToken(dblNo,Tokenizer.TOKEN_TYPE.NUMBER));
2607
+ }
2608
+ break;
2609
+ case Tokenizer.TOKEN_TYPE.UNARY_NEGATION :
2610
+ if (myStack.IsEmpty())
2611
+ throw "No operand on stack!";
2612
+
2613
+ objOp1 = null;
2614
+ objOp2 = null;
2615
+ objOp1 = myStack.Pop();
2616
+ if (objOp1.isVariable)
2617
+ objOp1 = _getVariable(objOp1.val, myvarArr);
2618
+
2619
+ objOp1 = Tokenizer.toBoolean(objOp1.val);
2620
+ if (objOp1 == null)
2621
+ throw strTok.val + " applied not on a boolean value!";
2622
+ else
2623
+ myStack.Push(Tokenizer.makeToken(!(objOp1),Tokenizer.TOKEN_TYPE.BOOLEAN));
2624
+ break;
2625
+ case Tokenizer.TOKEN_TYPE.ARITHMETIC_OP :
2626
+ switch(strTok.val)
2627
+ {
2628
+ case "*" :
2629
+ case "/" :
2630
+ case "%" :
2631
+ case "^" :
2632
+ if (myStack.IsEmpty() || myStack.Size() < 2)
2633
+ throw "Stack is empty, can not perform [" + strTok.val + "]";
2634
+ objOp1 = null;
2635
+ objOp2 = null;
2636
+ objTmp = null;
2637
+ objOp2 = myStack.Pop();
2638
+ objOp1 = myStack.Pop();
2639
+ if (objOp1.isVariable)
2640
+ objOp1 = _getVariable(objOp1.val, myvarArr);
2641
+ if (objOp2.isVariable)
2642
+ objOp2 = _getVariable(objOp2.val, myvarArr);
2643
+
2644
+ if (!objOp1.iNumber || !objOp2.isNumber)
2645
+ throw "Either one of the operand is not a number can not perform [" + strTok.val + "]";
2646
+
2647
+ dblVal1 = Tokenizer.toNumber(objOp1.val);
2648
+ dblVal2 = Tokenizer.toNumber(objOp2.val);
2649
+ if (isNaN(dblVal1) || isNaN(dblVal2))
2650
+ throw "Either one of the operand is not a number can not perform [" + strTok.val + "]";
2651
+
2652
+ if (strTok.val == "^")
2653
+ myStack.Push(Tokenizer.makeToken(Math.pow(dblVal1, dblVal2),Tokenizer.TOKEN_TYPE.NUMBER));
2654
+ else if (strTok.val == "*")
2655
+ myStack.Push(Tokenizer.makeToken((dblVal1 * dblVal2),Tokenizer.TOKEN_TYPE.NUMBER));
2656
+ else if (strTok.val == "/")
2657
+ myStack.Push(Tokenizer.makeToken((dblVal1 / dblVal2),Tokenizer.TOKEN_TYPE.NUMBER));
2658
+ else
2659
+ myStack.Push(Tokenizer.makeToken((dblVal1 % dblVal2),Tokenizer.TOKEN_TYPE.NUMBER));
2660
+ break;
2661
+ case "+" :
2662
+ case "-" :
2663
+ if (myStack.IsEmpty() || myStack.Size() < 2)
2664
+ throw "Stack is empty, can not perform [" + strTok.val + "]";
2665
+
2666
+ objOp1 = null;
2667
+ objOp2 = null;
2668
+ objTmp1 = null;
2669
+ objTmp2 = null;
2670
+ strOp = ((strTok.val == "+") ? "Addition" : "Substraction");
2671
+ objOp2 = myStack.Pop();
2672
+ objOp1 = myStack.Pop();
2673
+ if (objOp1.isVariable)
2674
+ objOp1 = _getVariable(objOp1.val, myvarArr);
2675
+ if (objOp2.isVariable)
2676
+ objOp2 = _getVariable(objOp2.val, myvarArr);
2677
+
2678
+ if (objOp1.isNumber && objOp2.isNumber)
2679
+ {
2680
+ // Number addition
2681
+ dblVal1 = Tokenizer.toNumber(objOp1.val);
2682
+ dblVal2 = Tokenizer.toNumber(objOp2.val);
2683
+ if (strTok.val == "+")
2684
+ myStack.Push(Tokenizer.makeToken((dblVal1 + dblVal2),Tokenizer.TOKEN_TYPE.NUMBER));
2685
+ else
2686
+ myStack.Push(Tokenizer.makeToken((dblVal1 - dblVal2),Tokenizer.TOKEN_TYPE.NUMBER));
2687
+ }
2688
+ else if (objOp1.isStringLiteral && objOp2.isStringLiteral)
2689
+ {
2690
+ if (strTok.val == "+")
2691
+ myStack.Push(Tokenizer.makeToken((objOp1.val + objOp2.val),Tokenizer.TOKEN_TYPE.STRING_LITERAL));
2692
+ else
2693
+ throw strOp + " not supported for strings!"
2694
+ }
2695
+ else
2696
+ throw strOp + " not supported for other types than numbers and strings!"
2697
+ break;
2698
+ }
2699
+ break;
2700
+ case Tokenizer.TOKEN_TYPE.COMPARISON_OP :
2701
+ switch(strTok.val)
2702
+ {
2703
+ case "=" :
2704
+ case "<" :
2705
+ case ">" :
2706
+ case "<>" :
2707
+ case "<=" :
2708
+ case ">=" :
2709
+ case "eq" :
2710
+ case "lt" :
2711
+ case "gt" :
2712
+ case "ne" :
2713
+ case "lte" :
2714
+ case "gte" :
2715
+ if (myStack.IsEmpty() || myStack.Size() < 2)
2716
+ throw "Stack is empty, can not perform [" + strTok.val + "]";
2717
+ objOp1 = null;
2718
+ objOp2 = null;
2719
+ objTmp1 = null;
2720
+ objTmp2 = null;
2721
+ objOp2 = myStack.Pop();
2722
+ objOp1 = myStack.Pop();
2723
+
2724
+ if (objOp1.isVariable)
2725
+ objOp1 = _getVariable(objOp1.val, myvarArr);
2726
+ if (objOp2.isVariable)
2727
+ objOp2 = _getVariable(objOp2.val, myvarArr);
2728
+
2729
+ if (objOp1.isStringLiteral && objOp2.isNumber)
2730
+ {
2731
+ dblVal1 = objOp1.val.toString();
2732
+ dblVal2 = objOp2.val.toString();
2733
+ }
2734
+ else if (objOp1.isNumber && objOp2.isStringLiteral)
2735
+ {
2736
+ dblVal1 = objOp1.val.toString();
2737
+ dblVal2 = objOp2.val.toString();
2738
+ }
2739
+ else if (objOp1.isNumber && objOp2.isNumber)
2740
+ {
2741
+ dblVal1 = Tokenizer.toNumber(objOp1.val);
2742
+ dblVal2 = Tokenizer.toNumber(objOp2.val);
2743
+ }
2744
+ else if (objOp1.isNumber && objOp2.isBoolean)
2745
+ {
2746
+ dblVal1 = Tokenizer.toNumber(objOp1.val);
2747
+ dblVal2 = Tokenizer.toNumber(objOp2.val);
2748
+ }
2749
+ else if (objOp2.isNumber && objOp1.isBoolean)
2750
+ {
2751
+ dblVal1 = Tokenizer.toNumber(objOp1.val);
2752
+ dblVal2 = Tokenizer.toNumber(objOp2.val);
2753
+ }
2754
+ else if (objOp1.isDate && objOp2.isDate)
2755
+ {
2756
+ dblVal1 = objOp1.val.getTime();
2757
+ dblVal2 = objOp2.val.getTime();
2758
+ }
2759
+ else if (objOp1.isStringLiteral && objOp2.isStringLiteral)
2760
+ {
2761
+ dblVal1=objOp1.val.toString();
2762
+ dblVal2=objOp2.val.toString();
2763
+ /*
2764
+ if (!isNaN(dblVal1))
2765
+ {
2766
+ dblVal1=parseFloat(dblVal1);
2767
+ }
2768
+ if (!isNaN(dblVal2))
2769
+ {
2770
+ dblVal2=parseFloat(dblVal2);
2771
+ }
2772
+ dblVal1=parseFloat(objOp1.val.toString());
2773
+ dblVal2=parseFloat(objOp2.val.toString());
2774
+ */
2775
+ }
2776
+ else if (objOp1.isBoolean && objOp2.isBoolean)
2777
+ {
2778
+ if (strTok.val == "=" || strTok.val == "<>" || strTok.val == "eq" || strTok.val == "ne")
2779
+ {
2780
+ dblVal1 = Tokenizer.toBoolean(objOp1.val);
2781
+ dblVal2 = Tokenizer.toBoolean(objOp2.val);
2782
+ }
2783
+ else
2784
+ throw strTok.val + " not supported for boolean values!";
2785
+ }
2786
+ else if (
2787
+ (strTok.val=='=' || strTok.val=='<>' || strTok.val=='eq' || strTok.val=='ne') &&
2788
+ (objOp1.isStringLiteral && objOp2.isRegex)
2789
+ )
2790
+ {
2791
+ if (strTok.val=='=' || strTok.val=='eq')
2792
+ myStack.Push(Tokenizer.makeToken((objOp2.val.test(objOp1.val.toString())),Tokenizer.TOKEN_TYPE.BOOLEAN));
2793
+ else
2794
+ myStack.Push(Tokenizer.makeToken(!(objOp2.val.test(objOp1.val.toString())),Tokenizer.TOKEN_TYPE.BOOLEAN));
2795
+ break;
2796
+ }
2797
+ else if (
2798
+ (strTok.val=='=' || strTok.val=='<>' || strTok.val=='eq' || strTok.val=='ne') &&
2799
+ (objOp2.isStringLiteral && objOp1.isRegex)
2800
+ )
2801
+ {
2802
+ if (strTok.val=='=' || strTok.val=='eq')
2803
+ myStack.Push(Tokenizer.makeToken((objOp1.val.test(objOp2.val.toString())),Tokenizer.TOKEN_TYPE.BOOLEAN));
2804
+ else
2805
+ myStack.Push(Tokenizer.makeToken(!(objOp1.val.test(objOp2.val.toString())),Tokenizer.TOKEN_TYPE.BOOLEAN));
2806
+ break;
2807
+ }
2808
+ else if (
2809
+ (strTok.val=='=' || strTok.val=='<>' || strTok.val=='eq' || strTok.val=='ne') &&
2810
+ (objOp1.isArray && (objOp2.isStringLiteral || objOp2.isNumber))
2811
+ )
2812
+ {
2813
+ if (strTok.val=='=' || strTok.val=='eq')
2814
+ myStack.Push(Tokenizer.makeToken(Functions.Contains(objOp1.val,objOp2.val),Tokenizer.TOKEN_TYPE.BOOLEAN));
2815
+ else
2816
+ myStack.Push(Tokenizer.makeToken(!Functions.Contains(objOp1.val,objOp2.val),Tokenizer.TOKEN_TYPE.BOOLEAN));
2817
+ break;
2818
+ }
2819
+ else if (
2820
+ (strTok.val=='=' || strTok.val=='<>' || strTok.val=='eq' || strTok.val=='ne') &&
2821
+ (objOp2.isArray && (objOp1.isStringLiteral || objOp1.isNumber))
2822
+ )
2823
+ {
2824
+ if (strTok.val=='=' || strTok.val=='eq')
2825
+ myStack.Push(Tokenizer.makeToken(Functions.Contains(objOp2.val,objOp1.val),Tokenizer.TOKEN_TYPE.BOOLEAN));
2826
+ else
2827
+ myStack.Push(Tokenizer.makeToken(!Functions.Contains(objOp2.val,objOp1.val),Tokenizer.TOKEN_TYPE.BOOLEAN));
2828
+ break;
2829
+ }
2830
+ else
2831
+ throw "For " + strTok.val + " operator LHS & RHS should be of same data type!";
2832
+
2833
+ if (strTok.val=='=' || strTok.val=='eq')// TODO check here, might need to use === instead of ==
2834
+ myStack.Push(Tokenizer.makeToken((dblVal1 == dblVal2),Tokenizer.TOKEN_TYPE.BOOLEAN));
2835
+ else if (strTok.val == "<>" || strTok.val == "ne")// TODO check here, might need to use !== instead of !=
2836
+ myStack.Push(Tokenizer.makeToken((dblVal1 != dblVal2),Tokenizer.TOKEN_TYPE.BOOLEAN));
2837
+ else if (strTok.val == ">" || strTok.val == "gt")
2838
+ myStack.Push(Tokenizer.makeToken((dblVal1 > dblVal2),Tokenizer.TOKEN_TYPE.BOOLEAN));
2839
+ else if (strTok.val == "<" || strTok.val == "lt")
2840
+ myStack.Push(Tokenizer.makeToken((dblVal1 < dblVal2),Tokenizer.TOKEN_TYPE.BOOLEAN));
2841
+ else if (strTok.val == "<=" || strTok.val == "lte")
2842
+ myStack.Push(Tokenizer.makeToken((dblVal1 <= dblVal2),Tokenizer.TOKEN_TYPE.BOOLEAN));
2843
+ else if (strTok.val == ">=" || strTok.val == "gte")
2844
+ myStack.Push(Tokenizer.makeToken((dblVal1 >= dblVal2),Tokenizer.TOKEN_TYPE.BOOLEAN));
2845
+ break;
2846
+ }
2847
+ break;
2848
+ case Tokenizer.TOKEN_TYPE.LOGICAL_OP :
2849
+ switch(strTok.val)
2850
+ {
2851
+ case 'NOT' :
2852
+ case '!' :
2853
+ if (myStack.IsEmpty())
2854
+ throw "No operand on stack!";
2855
+
2856
+ objOp1 = null;
2857
+ objOp2 = null;
2858
+ objOp1 = myStack.Pop();
2859
+ if (objOp1.isVariable)
2860
+ objOp1 = _getVariable(objOp1.val, myvarArr);
2861
+
2862
+ objOp1 = Tokenizer.toBoolean(objOp1.val);
2863
+ if (objOp1 == null)
2864
+ throw strTok.val + " applied not on a boolean value!";
2865
+ else
2866
+ myStack.Push(Tokenizer.makeToken(!(objOp1),Tokenizer.TOKEN_TYPE.BOOLEAN));
2867
+ break;
2868
+ case "AND" :
2869
+ case "&" :
2870
+ case "OR" :
2871
+ case "|" :
2872
+ if (myStack.IsEmpty() || myStack.Size() < 2)
2873
+ throw "Stack is empty, can not perform [" + strTok.val + "]";
2874
+ objOp1 = null;
2875
+ objOp2 = null;
2876
+ objTmp1 = null;
2877
+ objTmp2 = null;
2878
+ objOp2 = myStack.Pop();
2879
+ objOp1 = myStack.Pop();
2880
+ if (objOp1.isVariable)
2881
+ objOp1 = _getVariable(objOp1.val, myvarArr);
2882
+ if (objOp2.isVariable)
2883
+ objOp2 = _getVariable(objOp2.val, myvarArr);
2884
+
2885
+ if (
2886
+ (objOp1.isBoolean && objOp2.isBoolean) ||
2887
+ (objOp1.isNumber && objOp2.isNumber) ||
2888
+ (objOp1.isNumber && objOp2.isBoolean) ||
2889
+ (objOp1.isBoolean && objOp2.isNumber)
2890
+ )
2891
+ {
2892
+ objTmp1 = Tokenizer.toBoolean(objOp1.val);
2893
+ objTmp2 = Tokenizer.toBoolean(objOp2.val);
2894
+ if (strTok.val == "AND" || strTok.val == "&")
2895
+ myStack.Push(Tokenizer.makeToken((objTmp1 && objTmp2),Tokenizer.TOKEN_TYPE.BOOLEAN));
2896
+ else if (strTok.val == "OR" || strTok.val == "|")
2897
+ myStack.Push(Tokenizer.makeToken((objTmp1 || objTmp2),Tokenizer.TOKEN_TYPE.BOOLEAN));
2898
+ }
2899
+ else
2900
+ throw "Logical operator requires LHS & RHS of boolean type!";
2901
+ break;
2902
+ }
2903
+ break;
2904
+ case Tokenizer.TOKEN_TYPE.FUNCTION :
2905
+ _HandleFunctions(strTok, myStack, dtFormat, myvarArr);
2906
+ break;
2907
+ default :
2908
+ myStack.Push(strTok);
2909
+ break;
2910
+ }
2911
+ intIndex++;
2912
+ }
2913
+ if (myStack.IsEmpty() || myStack.Size() > 1 || myStack.Get(0).isVariable)
2914
+ throw "Unable to evaluate expression!";
2915
+ else
2916
+ return myStack.Pop().val;
2917
+ }
2918
+ }
2919
+ };})(Tokenizer,DateParser);
2920
+ })(window);
2921
+
2922
+
2923
+ })(window);
embedded/common/expression-parser/parser.php ADDED
@@ -0,0 +1,2892 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ * Toolset Parser, advanced parser for arithmetic,logical and comparision expressions
5
+ * by Nikos M. <nikos.m@icanlocalize.com>
6
+ *
7
+ * Main Features:
8
+ * + user variables
9
+ * + support mathematical, and date functions
10
+ * + limited date parsing
11
+ *
12
+ * Additional Features:
13
+ * + typed tokens
14
+ * + typed user variables
15
+ * + added string literals
16
+ * + support advanced mathematical, string and date functions
17
+ * + support advanced date operations (like (date + 3 days) or (3 days=date1-date2)) (not yet)
18
+ * + support typecasting
19
+ * + can parse and format every localized PHP date format
20
+ * + precompilation of expressions into functions
21
+ * + faster, optimized code
22
+ * + use of closures for encapsulation and better access
23
+ * + heavy refactoring, and various bug fixes
24
+ *
25
+ * adapted to PHP form Toolset_Parser js version
26
+ * inspired by JS Expression Evaluator by Prasad P. Khandekar
27
+ *
28
+ **/
29
+
30
+ class Toolset_Regex
31
+ {
32
+ private $_regex='';
33
+
34
+ public function Toolset_Regex($rx,$opts='')
35
+ {
36
+ // remove flags not supported by PHP
37
+ $this->_regex='/'.$rx.'/'.str_replace('g','',$opts); // PHP does not support 'g' modifier
38
+ }
39
+
40
+ public function test($str)
41
+ {
42
+ return (preg_match($this->_regex,$str)==1);
43
+ }
44
+ }
45
+
46
+ class Toolset_Functions
47
+ {
48
+ private static $_cookies=null;
49
+ private static $_regexs=array();
50
+ private static $_params=array(
51
+ 'user'=>array(
52
+ 'ID'=>0,
53
+ 'role'=>'',
54
+ 'roles'=>array(),
55
+ 'login'=>'',
56
+ 'display_name'=>''
57
+ )
58
+ );
59
+
60
+ public static function setParams($params)
61
+ {
62
+ self::$_params=array_merge(self::$_params,$params);
63
+ }
64
+
65
+ public static function Cookie($name)
66
+ {
67
+ if (!isset($_cookies)) $_cookies=&$_COOKIE;
68
+
69
+ return (isset($_cookies[$name]))?$_cookies[$name]:'';
70
+ }
71
+
72
+ public static function User($att='')
73
+ {
74
+ $att=strtoupper($att);
75
+
76
+ switch ($att)
77
+ {
78
+ case 'ID':
79
+ return (string)(self::$_params['user']['ID'].'');
80
+ case 'NAME':
81
+ return self::$_params['user']['display_name'];
82
+ case 'ROLE':
83
+ return self::$_params['user']['role'];
84
+ case 'LOGIN':
85
+ return self::$_params['user']['login'];
86
+ default:
87
+ return '';
88
+ }
89
+ return '';
90
+ }
91
+
92
+ public static function Regex($rx, $opts='') {return new Toolset_Regex($rx, $opts);}
93
+
94
+ public static function Contains(&$a, $v) {return in_array($v,$a);}
95
+ }
96
+
97
+ class Toolset_Date
98
+ {
99
+ private $_timestamp;
100
+
101
+ /* getdate params
102
+ "seconds" Numeric representation of seconds 0 to 59
103
+ "minutes" Numeric representation of minutes 0 to 59
104
+ "hours" Numeric representation of hours 0 to 23
105
+ "mday" Numeric representation of the day of the month 1 to 31
106
+ "wday" Numeric representation of the day of the week 0 (for Sunday) through 6 (for Saturday)
107
+ "mon" Numeric representation of a month 1 through 12
108
+ "year" A full numeric representation of a year, 4 digits Examples: 1999 or 2003
109
+ "yday" Numeric representation of the day of the year 0 through 365
110
+ "weekday" A full textual representation of the day of the week Sunday through Saturday
111
+ "month" A full textual representation of a month, such as January or March
112
+ */
113
+ private $_date=array(
114
+ 'hour'=>0,
115
+ 'min'=>0,
116
+ 'sec'=>0,
117
+ 'day_of_month'=>0,
118
+ 'day_of_week'=>0,
119
+ 'day_of_year'=>0,
120
+ 'day_of_week_string'=>'',
121
+ 'month_string'=>'',
122
+ 'month'=>0,
123
+ 'year'=>0
124
+ );
125
+
126
+ private static $_today=false;
127
+
128
+ public static function setToday($date)
129
+ {
130
+ self::$_today=$date;
131
+ }
132
+
133
+ public static function getToday()
134
+ {
135
+ if (self::$_today)
136
+ return new Toolset_Date(self::$_today);
137
+
138
+ $today=new Toolset_Date();
139
+ return $today->setDateByTimestamp();
140
+ }
141
+
142
+ public function Toolset_Date($date=null)
143
+ {
144
+ if (isset($date))
145
+ $this->setDate($date);
146
+ }
147
+
148
+
149
+ public function getDate($key=null)
150
+ {
151
+ if (!isset($key) || !in_array($key, array_keys($this->_date)))
152
+ return $this->_date;
153
+ else
154
+ return $this->_date[$key];
155
+ }
156
+
157
+ public function setDate($date)
158
+ {
159
+ $hasYear=false;
160
+ $hasMonth=false;
161
+ $hasDay=false;
162
+
163
+ foreach ($date as $k=>$v)
164
+ {
165
+ if ($k=='year') $hasYear=true;
166
+ if ($k=='month') $hasMonth=true;
167
+ if ($k=='day_of_year') $hasDay=true;
168
+
169
+ if (isset($this->_date[$k]))
170
+ $this->_date[$k]=$v;
171
+ }
172
+
173
+ // fill all values
174
+ if ($hasYear && $hasMonth && $hasDay)
175
+ $this->setDateByTimestamp($this->getTimestamp());
176
+
177
+ return $this;
178
+ }
179
+
180
+ public function getTimestamp()
181
+ {
182
+ if (class_exists("DateTime")) {
183
+ $date = new DateTime("{$this->_date['year']}-{$this->_date['month']}-{$this->_date['day_of_month']} {$this->_date['hour']}:{$this->_date['min']}:{$this->_date['sec']}");
184
+ return (method_exists('DateTime', 'getTimestamp')) ? $date->getTimestamp() : $date->format('U');
185
+ } else
186
+ return mktime ($this->_date['hour'], $this->_date['min'], $this->_date['sec'], $this->_date['month'], $this->_date['day_of_month'], $this->_date['year'] /*[, int $is_dst = -1 ]*/);
187
+ }
188
+
189
+ public function getNormalizedTimestamp()
190
+ {
191
+ if (class_exists("DateTime")) {
192
+ $date = new DateTime("{$this->_date['year']}-{$this->_date['month']}-{$this->_date['day_of_month']}");
193
+ return (method_exists('DateTime', 'getTimestamp')) ? $date->getTimestamp() : $date->format('U');
194
+ } else
195
+ return mktime (0, 0, 0, $this->_date['day_of_month'], $this->_date['month'], $this->_date['year'] /*[, int $is_dst = -1 ]*/);
196
+ }
197
+
198
+ public function setDateByTimestamp($time=null)
199
+ {
200
+ if (!isset($time)) $time=time();
201
+
202
+ $dat=getdate($time);
203
+ $date=array(
204
+ 'hour'=>0,
205
+ 'min'=>0,
206
+ 'sec'=>0,
207
+ 'month'=>$dat['mon'],
208
+ 'month_string'=>$dat['month'],
209
+ 'day_of_month'=>$dat['mday'],
210
+ 'day_of_week'=>$dat['wday'],
211
+ 'day_of_week_string'=>$dat['weekday'],
212
+ 'day_of_year'=>$dat['yday'],
213
+ 'year'=>$dat['year']
214
+ );
215
+
216
+ $this->_date=$date;
217
+
218
+ return $this;
219
+ }
220
+
221
+ public function format($format)
222
+ {
223
+ //return date($format, $this->getTimestamp());
224
+
225
+ // handle localized format
226
+ return Toolset_DateParser::formatDate($this, $format);
227
+ }
228
+ }
229
+
230
+ class Toolset_DateParser
231
+ {
232
+ private static $_ZONE_NAMES = array('AM' => 'AM','PM' => 'PM');
233
+ private static $_MONTH_NAMES = array('January','February','March','April','May','June','July','August','September','October','November','December');
234
+ private static $_DAY_NAMES = array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
235
+ private static $_ENGLISH_MONTH_NAMES = array('January','February','March','April','May','June','July','August','September','October','November','December');
236
+ private static $_ENGLISH_DAY_NAMES = array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
237
+
238
+ private static function _to_int($str)
239
+ {
240
+ // return the integer representation of the string given as argument
241
+ return intval($str);
242
+ }
243
+
244
+ private static function _escape_regexp($str)
245
+ {
246
+ // return string with special characters escaped
247
+ //return preg_replace('#([\-\.\*\+\?\^\$\{\}\(\)\|\[\]\/\\])#', '\\$1', $str);
248
+ return preg_quote($str, "/");
249
+ }
250
+
251
+ private static function _str_pad($n, $c)
252
+ {
253
+ if (strlen($n = $n . '') < $c)
254
+ {
255
+ return implode('0',array_fill((++$c) - strlen($n))). $n;
256
+ }
257
+ return $n;
258
+ }
259
+
260
+ private static function _is_string($s)
261
+ {
262
+ return is_string($s)?true:false;
263
+ }
264
+
265
+ public static function cmp($a, $b){ return $a['position'] - $b['position']; }
266
+
267
+ public static function parseDate($date, $supposed_format)
268
+ {
269
+ // if already a date object
270
+ if ($date instanceof Toolset_Date)
271
+ {
272
+ $date->setDate(array('hour'=>0,'min'=>0,'sec'=>0)); // normalize time part
273
+ return $date;
274
+ }
275
+
276
+ if (
277
+ !isset($date) ||
278
+ !self::_is_string($date) ||
279
+ !isset($supposed_format) ||
280
+ !self::_is_string($supposed_format)
281
+ )
282
+ return false;
283
+
284
+ // treat argument as a string
285
+ $str_date = (string)$date . '';
286
+ $supposed_format = (string)$supposed_format.'';
287
+
288
+ // if value is given
289
+ if ($str_date != '' && $supposed_format != '')
290
+ {
291
+ //echo '<br/>Date given<br />';
292
+ // prepare the format by removing white space from it
293
+ // and also escape characters that could have special meaning in a regular expression
294
+ $format = self::_escape_regexp(preg_replace('/\s/','',$supposed_format));
295
+
296
+ // allowed characters in date's format
297
+ $format_chars = array('d','D','j','l','N','S','w','F','m','M','n','Y','y');
298
+
299
+ // "matches" will contain the characters defining the date's format
300
+ $matches = array();
301
+
302
+ // "regexp" will contain the regular expression built for each of the characters used in the date's format
303
+ $regexp = array();
304
+
305
+ // iterate through the allowed characters in date's format
306
+ for ($i = 0; $i < count($format_chars); $i++)
307
+ {
308
+ // if character is found in the date's format
309
+ if (($position = strpos($format,$format_chars[$i])) > -1)
310
+
311
+ // save it, alongside the character's position
312
+ $matches[]=array('character'=> $format_chars[$i], 'position'=> $position);
313
+ }
314
+
315
+ // sort characters defining the date's format based on their position, ascending
316
+ usort($matches,array('Toolset_DateParser','cmp'));
317
+
318
+ // iterate through the characters defining the date's format
319
+ for ($index=0; $index<count($matches); $index++)
320
+ {
321
+ $match=$matches[$index];
322
+
323
+ // add to the array of regular expressions, based on the character
324
+ switch ($match['character'])
325
+ {
326
+
327
+ case 'd': $regexp[]='0[1-9]|[12][0-9]|3[01]'; break;
328
+ case 'D': $regexp[]='[a-z]{3}'; break;
329
+ case 'j': $regexp[]='[1-9]|[12][0-9]|3[01]'; break;
330
+ case 'l': $regexp[]='[a-z]+'; break;
331
+ case 'N': $regexp[]='[1-7]'; break;
332
+ case 'S': $regexp[]='st|nd|rd|th'; break;
333
+ case 'w': $regexp[]='[0-6]'; break;
334
+ case 'F': $regexp[]='[a-z]+'; break;
335
+ case 'm': $regexp[]='0[1-9]|1[012]+'; break;
336
+ case 'M': $regexp[]='[a-z]{3}'; break;
337
+ case 'n': $regexp[]='[1-9]|1[012]'; break;
338
+ case 'Y': $regexp[]='[0-9]{4}'; break;
339
+ case 'y': $regexp[]='[0-9]{2}'; break;
340
+
341
+ }
342
+ }
343
+
344
+ // if we have an array of regular expressions
345
+ if (!empty($regexp))
346
+ {
347
+
348
+ // we will replace characters in the date's format in reversed order
349
+ $matches=array_reverse($matches);
350
+
351
+ // iterate through the characters in date's format
352
+ for ($index=0; $index<count($matches); $index++)
353
+ {
354
+ $match=$matches[$index];
355
+
356
+ // replace each character with the appropriate regular expression
357
+ $format = str_replace($match['character'],'(' . $regexp[count($regexp) - $index - 1] . ')', $format);
358
+ }
359
+
360
+ // the final regular expression
361
+ //$regexp = '/^' . $format . '$/ig';
362
+ $regexp = '/^' . $format . '$/i';
363
+
364
+ //echo '<br /><textarea>'.$regexp.'</textarea><br />';
365
+
366
+ //preg_match_all('/^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[012]+)\/([0-9]{2})$/i','13/10/12',$foo);
367
+ //print_r($foo);
368
+
369
+ // if regular expression was matched
370
+ if (preg_match_all($regexp, preg_replace('/\s/', '', $str_date),$segments))
371
+ {
372
+ //echo '<br/>Regex matched<br />';
373
+ //print_r($segments);
374
+
375
+ // check if date is a valid date (i.e. there's no February 31)
376
+ $english_days = self::$_ENGLISH_DAY_NAMES;
377
+ $english_months = self::$_ENGLISH_MONTH_NAMES;
378
+
379
+ // by default, we assume the date is valid
380
+ $valid = true;
381
+
382
+ // reverse back the characters in the date's format
383
+ $matches=array_reverse($matches);
384
+
385
+ // iterate through the characters in the date's format
386
+ for ($index=0; $index<count($matches); $index++)
387
+ {
388
+ $match=$matches[$index];
389
+
390
+ // if the date is not valid, don't look further
391
+ if (!$valid) break; //return true;
392
+
393
+ // based on the character
394
+ switch ($match['character'])
395
+ {
396
+
397
+ case 'm':
398
+ case 'n':
399
+
400
+ // extract the month from the value entered by the user
401
+ $original_month = self::_to_int($segments[$index+1][0]);
402
+
403
+ break;
404
+
405
+ case 'd':
406
+ case 'j':
407
+
408
+ // extract the day from the value entered by the user
409
+ $original_day = self::_to_int($segments[$index+1][0]);
410
+
411
+ break;
412
+
413
+ case 'D':
414
+ case 'l':
415
+ case 'F':
416
+ case 'M':
417
+
418
+ // if day is given as day name, we'll check against the names in the used language
419
+ if ($match['character'] == 'D' || $match['character'] == 'l') $iterable = self::$_DAY_NAMES;
420
+
421
+ // if month is given as month name, we'll check against the names in the used language
422
+ else $iterable = self::$_MONTH_NAMES;
423
+
424
+ // by default, we assume the day or month was not entered correctly
425
+ $valid = false;
426
+
427
+ // iterate through the month/days in the used language
428
+ for ($key=0; $key<count($iterable); $key++)
429
+ {
430
+ // if month/day was entered correctly, don't look further
431
+ if ($valid) break; //return true;
432
+
433
+ $value=$iterable[$key];
434
+
435
+ // if month/day was entered correctly
436
+ if (strtolower($segments[$index+1][0]) == strtolower(substr($value, 0, ($match['character'] == 'D' || $match['character'] == 'M' ? 3 : strlen($value)))))
437
+ {
438
+
439
+ // extract the day/month from the value entered by the user
440
+ switch ($match['character'])
441
+ {
442
+
443
+ case 'D': $segments[$index+1][0] = substr($english_days[$key],0, 3); break;
444
+ case 'l': $segments[$index+1][0] = $english_days[$key]; break;
445
+ case 'F': $segments[$index+1][0] = $english_months[$key]; $original_month = $key + 1; break;
446
+ case 'M': $segments[$index+1][0] = substr($english_months[$key],0, 3); $original_month = $key + 1; break;
447
+
448
+ }
449
+
450
+ // day/month value is valid
451
+ $valid = true;
452
+
453
+ }
454
+
455
+ }
456
+
457
+ break;
458
+
459
+ case 'Y':
460
+
461
+ // extract the year from the value entered by the user
462
+ $original_year = self::_to_int($segments[$index+1][0]);
463
+
464
+ break;
465
+
466
+ case 'y':
467
+
468
+ // extract the year from the value entered by the user
469
+ $original_year = '19' + self::_to_int($segments[$index+1][0]);
470
+
471
+ break;
472
+
473
+ }
474
+ }
475
+
476
+ // if everything is ok so far
477
+ if ($valid)
478
+ {
479
+ //echo '<br/>Date valid 1<br />';
480
+
481
+ // generate a Date object using the values entered by the user
482
+ // (handle also the case when original_month and/or original_day are undefined - i.e date format is "Y-m" or "Y")
483
+ /* print_r(array(
484
+ 'year'=>$original_year,
485
+ 'month'=>$original_month,
486
+ 'day'=>$original_day,
487
+ ));*/
488
+
489
+ // if, after that, the date is the same as the date entered by the user
490
+ //if (date.getFullYear() == original_year && date.getDate() == (original_day || 1) && date.getMonth() == ((original_month || 1) - 1))
491
+ //var_dump(checkdate(10, 12, 2012));
492
+ if (checkdate ((int)$original_month, (int)$original_day, (int)$original_year))
493
+ {
494
+ // normalize time part, only date part checked
495
+ $date = new Toolset_Date(array(
496
+ 'year'=>$original_year,
497
+ 'month'=>$original_month,
498
+ 'day_of_month'=>$original_day,
499
+ ));
500
+ $date->setDate(array('hour'=>0,'min'=>0,'sec'=>0));
501
+ // return the date as our date object
502
+ //echo '<br/>Date valid 2<br />';
503
+ return $date;
504
+ }
505
+ }
506
+ }
507
+ }
508
+ }
509
+ // if script gets this far, return false as something must've went wrong
510
+ return false;
511
+ }
512
+
513
+ public static function formatDate($date, $format, $isTimestamp=false)
514
+ {
515
+
516
+ // if not a date object
517
+ /*if (!isset($date) || !($date instanceof Toolset_Date))
518
+ {
519
+ return '';
520
+ }
521
+ $date->setDate(array('hour'=>0,'min'=>0,'sec'=>0)); // normalize time
522
+ return $date->format($format);*/
523
+
524
+ if ($isTimestamp)
525
+ {
526
+ $dat=new Toolset_Date();
527
+ $date=$dat->setDateByTimestamp($date);
528
+ }
529
+
530
+ // if not a date object
531
+ if (!isset($date) || !($date instanceof Toolset_Date))
532
+ {
533
+ return '';
534
+ }
535
+
536
+ $date->setDate(array('hour'=>0,'min'=>0,'sec'=>0)); // normalize time part
537
+
538
+ $result = '';
539
+
540
+ // extract parts of the date:
541
+ // day number, 1 - 31
542
+ $j = $date->getDate('day_of_month');
543
+
544
+ // day of the week, 0 - 6, Sunday - Saturday
545
+ $w = $date->getDate('day_of_week');
546
+
547
+ // the name of the day of the week Sunday - Saturday
548
+ $l = self::$_DAY_NAMES[$w];
549
+
550
+ // the month number, 1 - 12
551
+ $n = $date->getDate('month');// + 1;
552
+
553
+ // the month name, January - December
554
+ $f = self::$_MONTH_NAMES[$n - 1];
555
+
556
+ // the year (as a string)
557
+ $y = (string)$date->getDate('year') . '';
558
+
559
+ // iterate through the characters in the format
560
+ for ($i = 0; $i < strlen($format); $i++)
561
+ {
562
+
563
+ // extract the current character
564
+ $chr = $format[$i];
565
+
566
+ // see what character it is
567
+ switch($chr)
568
+ {
569
+ // year as two digits
570
+ case 'y': $y = substr($y,2);
571
+
572
+ // year as four digits
573
+ case 'Y': $result .= $y; break;
574
+
575
+ // month number, prefixed with 0
576
+ case 'm': $n = self::_str_pad($n, 2);
577
+
578
+ // month number, not prefixed with 0
579
+ case 'n': $result .= $n; break;
580
+
581
+ // month name, three letters
582
+ case 'M': $f = substr($f,0,3);
583
+
584
+ // full month name
585
+ case 'F': $result .= $f; break;
586
+
587
+ // day number, prefixed with 0
588
+ case 'd': $j = self::_str_pad($j, 2);
589
+
590
+ // day number not prefixed with 0
591
+ case 'j': $result .= $j; break;
592
+
593
+ // day name, three letters
594
+ case 'D': $l = substr($l, 0, 3);
595
+
596
+ // full day name
597
+ case 'l': $result .= $l; break;
598
+
599
+ // ISO-8601 numeric representation of the day of the week, 1 - 7
600
+ case 'N': $w++;
601
+
602
+ // day of the week, 0 - 6
603
+ case 'w': $result .= $w; break;
604
+
605
+ // English ordinal suffix for the day of the month, 2 characters
606
+ // (st, nd, rd or th (works well with j))
607
+ case 'S':
608
+
609
+ if ($j % 10 == 1 && $j != '11') $result .= 'st';
610
+
611
+ else if ($j % 10 == 2 && $j != '12') $result .= 'nd';
612
+
613
+ else if ($j % 10 == 3 && $j != '13') $result .= 'rd';
614
+
615
+ else $result .= 'th';
616
+
617
+ break;
618
+
619
+ // this is probably the separator
620
+ default: $result .= $chr;
621
+
622
+ }
623
+
624
+ }
625
+ // return formated date
626
+ return $result;
627
+ }
628
+
629
+ public static function setDateLocaleStrings($dn=null, $mn=null, $zn=null)
630
+ {
631
+ if (isset($mn))
632
+ {
633
+ self::$_MONTH_NAMES = $mn;
634
+ }
635
+ if (isset($dn))
636
+ {
637
+ self::$_DAY_NAMES = $dn;
638
+ }
639
+ if (isset($zn))
640
+ self::$_ZONE_NAMES = $zn;
641
+ }
642
+
643
+ public static function isDate($val, $format, &$getDate=null)
644
+ {
645
+ $date=self::parseDate($val,$format);
646
+ if ($date!==false)
647
+ {
648
+ //echo '<hr />Date correct<hr />';
649
+ if (isset($getDate))
650
+ {
651
+ $getDate['date']=$date;
652
+ }
653
+ return true;
654
+ }
655
+ return false;
656
+ }
657
+
658
+ public static function currentDate()
659
+ {
660
+ return Toolset_Date::getToday();
661
+ }
662
+ }
663
+
664
+ class Toolset_Stack
665
+ {
666
+ // Stack object constructor
667
+ private $arrStack=array();
668
+ private $intIndex=0;
669
+
670
+ // Converts stack contents into a comma separated string
671
+ public function toString()
672
+ {
673
+ $intCntr = 0;
674
+ $strRet = "";
675
+ if ($this->intIndex == 0) return null;
676
+ for ($intCntr = 0; $intCntr < $this->intIndex; $intCntr++)
677
+ {
678
+ if ($strRet == '')
679
+ $strRet .= print_r($this->arrStack[$intCntr]->val,true);
680
+ else
681
+ $strRet .= "," . print_r($this->arrStack[$intCntr]->val,true);
682
+ }
683
+ return $strRet;
684
+ }
685
+
686
+ // Returns size of stack
687
+ public function Size()
688
+ {
689
+ return $this->intIndex;
690
+ }
691
+
692
+ // This method tells us if this Stack object is empty
693
+ public function IsEmpty()
694
+ {
695
+ return ($this->intIndex == 0)?true:false;
696
+ }
697
+
698
+ // This method pushes a new element onto the top of the stack
699
+ public function Push($newData)
700
+ {
701
+ $this->arrStack[$this->intIndex++] = $newData;
702
+ }
703
+
704
+ // This method pops the top element off of the stack
705
+ public function Pop()
706
+ {
707
+ $retVal = null;
708
+ if ($this->intIndex > 0)
709
+ {
710
+ $retVal = $this->arrStack[--$this->intIndex];
711
+ }
712
+ return $retVal;
713
+ }
714
+
715
+ // Gets an element at a particular offset from top of the stack
716
+ function Get($intPos)
717
+ {
718
+ if ($intPos >= 0 && $intPos < $this->intIndex)
719
+ $retVal = $this->arrStack[$this->intIndex - $intPos - 1];
720
+ return $retVal;
721
+ }
722
+ }
723
+
724
+ class Toolset_Tokenizer
725
+ {
726
+
727
+ // private members
728
+ private static $_tok_map_prefix = '__TOKEN_MAP_PREFIX__';
729
+ private static $_Alpha = '';
730
+ private static $_lstAlpha = '';
731
+ private static $_lstVariablePrefix = '';
732
+ private static $_lstDigits = "0123456789";
733
+ private static $_lstArithOps = array("^","*","/","%","+","-");
734
+ private static $_lstLogicOps = array("NOT","!","OR","|","AND","&");
735
+ private static $_lstCompaOps = array("<","<=",">",">=","<>","=","lt","lte","gt","gte","ne","eq");
736
+ private static $_lstFuncOps = array(
737
+ "AVG","ABS","ACOS","ARRAY","ASC","ASIN","ATAN",
738
+ "CHR","CONTAINS","COOKIE","COS",
739
+ "DATE","FIX","HEX","IIF","LCASE","LEN","LEFT","LOG",
740
+ "MAX","MID","MIN","NUM","RAND","REGEX","RIGHT","ROUND",
741
+ "SIN","SQRT","STR","TAN","TODAY","UCASE","USER", "EMPTY", "empty"
742
+ );
743
+
744
+ private static $_UNARY_NEGATIVE = "-";
745
+ private static $_UNARY_NEGATION = "!";
746
+ private static $_ARG_TERMINAL = "?";
747
+ private static $_EMPTY_TOKEN;
748
+ private static $_EMPTY_STRING;
749
+ private static $_TOKEN_TYPES = array(
750
+ '__DEFAULT__'=>0,
751
+ 'STRING_LITERAL'=>8,
752
+ 'REGEX'=> 83,
753
+ 'ARRAY'=>81,
754
+ 'ARRAY_LITERAL'=>82,
755
+ 'DATE'=>1,
756
+ 'ARITHMETIC_OP'=>2,
757
+ 'LOGICAL_OP'=>3,
758
+ 'COMPARISON_OP'=>4,
759
+ 'NUMBER'=>5,
760
+ 'BOOLEAN'=>6,
761
+ 'VARIABLE'=>7,
762
+ 'FUNCTION'=>9,
763
+ 'COMMA'=>10,
764
+ 'LEFT_PAREN'=>11,
765
+ 'LEFT_BRACKET'=>111,
766
+ 'RIGHT_PAREN'=>12,
767
+ 'RIGHT_BRACKET'=>122,
768
+ 'ARG_TERMINAL'=>13,
769
+ 'UNARY_NEGATIVE'=>14,
770
+ 'UNARY_NEGATION'=>15,
771
+ 'EMPTY_TOKEN'=>30,
772
+ 'UNKNOWN'=>40
773
+ );
774
+
775
+ public static $TOKEN_TYPE;
776
+ public static $EMPTY_TOKEN;
777
+ public static $EMPTY_STRING;
778
+ public static $UNARY_NEGATIVE;
779
+ public static $UNARY_NEGATION;
780
+ public static $ARG_TERMINAL;
781
+
782
+ private static function _isDefined($s)
783
+ {
784
+ return (isset($s));
785
+ }
786
+
787
+ private static function _isDigit($c)
788
+ {
789
+ if (!self::_isDefined($c))
790
+ return false;
791
+ return (($c!='' && strpos(self::$_lstDigits,$c) >= 0)?true:false);
792
+ }
793
+
794
+ private static function _isAlpha($c)
795
+ {
796
+ if (!self::_isDefined($c))
797
+ return false;
798
+ return (($c!='' && strpos(self::$_lstAlpha,$c) >= 0)?true:false);
799
+ }
800
+
801
+ private static function _isOperator($s)
802
+ {
803
+ if (!self::_isDefined($s))
804
+ return false;
805
+ return (in_array($s,self::$_lstArithOps)?true:false);
806
+ }
807
+
808
+ private static function _isLogicOperator($s)
809
+ {
810
+ if (!self::_isDefined($s))
811
+ return false;
812
+ return (in_array($s,self::$_lstLogicOps)?true:false);
813
+ }
814
+
815
+ private static function _isCompOperator($s)
816
+ {
817
+ if (!self::_isDefined($s))
818
+ return false;
819
+ return (in_array($s,self::$_lstCompaOps)?true:false);
820
+ }
821
+
822
+ private static function _isFunction($s)
823
+ {
824
+ if (!self::_isDefined($s))
825
+ return false;
826
+ return (in_array($s,self::$_lstFuncOps)?true:false);
827
+ }
828
+
829
+ private static function _isVariableName($s)
830
+ {
831
+ if (!self::_isDefined($s))
832
+ return false;
833
+ $c=($s=='')?'':$s{0};
834
+ return (($c!='' && strpos(self::$_lstVariablePrefix,$c) >= 0)?true:false);
835
+ }
836
+
837
+ public static function isDateInstance($s)
838
+ {
839
+ if (!self::_isDefined($s))
840
+ return false;
841
+ if ($s instanceof Toolset_Date)
842
+ return true;
843
+ return false;
844
+ }
845
+
846
+ public static function isArrayInstance($s)
847
+ {
848
+ if (!self::_isDefined($s))
849
+ return false;
850
+ if (is_array($s))
851
+ return true;
852
+ return false;
853
+ }
854
+
855
+ public static function isRegExpInstance($s)
856
+ {
857
+ if (!self::_isDefined($s))
858
+ return false;
859
+ if ($s instanceof Toolset_Regex)
860
+ return true;
861
+ return false;
862
+ }
863
+
864
+ public static function isNumber($s)
865
+ {
866
+ if (!self::_isDefined($s)) return false;
867
+ //if (_isDateInstance(s) || _isRegExpInstance(s) || _isArrayInstance(s)) return false;
868
+ if (is_numeric($s) && !is_nan((float)$s))
869
+ return true;
870
+ return false;
871
+ }
872
+
873
+ public static function isBoolean($s)
874
+ {
875
+ if (!self::_isDefined($s))
876
+ return false;
877
+
878
+ if (is_bool($s)) return true;
879
+
880
+ if (strtoupper((string)$s)=='TRUE' || strtoupper((string)$s)=='FALSE')
881
+ return true;
882
+
883
+ return false;
884
+ }
885
+
886
+ private static function _ltrim($s, $ch=' ')
887
+ {
888
+ return ltrim($s,$ch);
889
+ }
890
+
891
+ private static function _rtrim($s, $ch=' ')
892
+ {
893
+ return rtrim($s,$ch);
894
+ }
895
+
896
+ private static function _trim($s, $ch=' ')
897
+ {
898
+ return trim($s,$ch);
899
+ }
900
+
901
+ // build maps for fast lookup
902
+ private static function _buildMaps()
903
+ {
904
+ self::$_Alpha = "abcdefghijklmnopqrstuvwxyz";
905
+ self::$_lstAlpha = self::$_Alpha . strtoupper(self::$_Alpha);
906
+ self::$_lstVariablePrefix = '_$' . self::$_lstAlpha;
907
+ }
908
+
909
+ public static function init()
910
+ {
911
+ static $isInited=false;
912
+
913
+ if (!$isInited)
914
+ {
915
+ self::_buildMaps();
916
+ self::$TOKEN_TYPE = self::$_TOKEN_TYPES;
917
+ self::$_EMPTY_TOKEN = self::makeToken('', self::$_TOKEN_TYPES['EMPTY_TOKEN']);
918
+ self::$_EMPTY_STRING = self::makeToken('', self::$_TOKEN_TYPES['STRING_LITERAL']);
919
+ self::$EMPTY_TOKEN = self::$_EMPTY_TOKEN;
920
+ self::$EMPTY_STRING = self::$_EMPTY_STRING;
921
+ self::$UNARY_NEGATIVE = self::makeToken(self::$_UNARY_NEGATIVE, self::$_TOKEN_TYPES['UNARY_NEGATIVE']);
922
+ self::$UNARY_NEGATION = self::makeToken(self::$_UNARY_NEGATION, self::$_TOKEN_TYPES['UNARY_NEGATION']);
923
+ self::$ARG_TERMINAL = self::makeToken(self::$_ARG_TERMINAL, self::$_TOKEN_TYPES['ARG_TERMINAL']);
924
+ $isInited=true;
925
+ }
926
+ }
927
+
928
+ public static function makeToken($tok, $force_type=null/*, $debug=false*/)
929
+ {
930
+ /*if ($debug)
931
+ {
932
+ cred_log($force_type);
933
+ }*/
934
+ $token=(object)array(
935
+ 'val'=>$tok,
936
+ 'type'=>self::$_TOKEN_TYPES['UNKNOWN'],
937
+ 'isStringLiteral'=>false,
938
+ 'isArray'=>false,
939
+ 'isRegex'=>false,
940
+ 'isDate'=>false,
941
+ 'isFunction'=>false,
942
+ 'isNumber'=>false,
943
+ 'isBoolean'=>false,
944
+ 'isOp'=>false,
945
+ 'isArithmeticOp'=>false,
946
+ 'isLogicOp'=>false,
947
+ 'isCompOp'=>false,
948
+ 'isParen'=>false,
949
+ 'isLeftParen'=>false,
950
+ 'isRightParen'=>false,
951
+ 'isComma'=>false,
952
+ 'isVariable'=>false,
953
+ 'isArgTerminal'=>false,
954
+ 'isUnaryNegative'=>false,
955
+ 'isUnaryNegation'=>false,
956
+ 'isEmpty'=>false,
957
+ );
958
+
959
+ if (!isset($force_type))
960
+ $force_type=self::$_TOKEN_TYPES['__DEFAULT__'];
961
+
962
+ switch ($force_type)
963
+ {
964
+ case self::$_TOKEN_TYPES['EMPTY_TOKEN']:
965
+ $token->type=self::$_TOKEN_TYPES['EMPTY_TOKEN'];
966
+ $token->isEmpty=true;
967
+ $token->val='';
968
+ break;
969
+ case self::$_TOKEN_TYPES['STRING_LITERAL']:
970
+ $token->type=self::$_TOKEN_TYPES['STRING_LITERAL'];
971
+ $token->isStringLiteral=true;
972
+ $token->val=(string)$tok;
973
+ /*if ($debug)
974
+ {
975
+ cred_log('---------');
976
+ cred_log($token);
977
+ cred_log('---------');
978
+ }*/
979
+ break;
980
+ case self::$_TOKEN_TYPES['DATE']:
981
+ if (self::isDateInstance($tok))
982
+ {
983
+ $token->type=self::$_TOKEN_TYPES['DATE'];
984
+ $token->isDate=true;
985
+ }
986
+ break;
987
+ case self::$_TOKEN_TYPES['ARRAY']:
988
+ if (!self::isArrayInstance($tok))
989
+ {
990
+ $token->val=array($tok);
991
+ }
992
+ $token->type=self::$_TOKEN_TYPES['ARRAY'];
993
+ $token->isArray=true;
994
+ break;
995
+ case self::$_TOKEN_TYPES['REGEX']:
996
+ if (!self::isRegExpInstance($tok))
997
+ {
998
+ $token->val=new Toolset_Regex($tok);
999
+ }
1000
+ $token->type=self::$_TOKEN_TYPES['REGEX'];
1001
+ $token->isRegex=true;
1002
+ break;
1003
+ case self::$_TOKEN_TYPES['COMMA']:
1004
+ $token->type=self::$_TOKEN_TYPES['COMMA'];
1005
+ $token->isComma=true;
1006
+ $token->val=',';
1007
+ break;
1008
+ case self::$_TOKEN_TYPES['LEFT_PAREN']:
1009
+ $token->type=self::$_TOKEN_TYPES['LEFT_PAREN'];
1010
+ $token->isLeftParen=true;
1011
+ $token->isParen=true;
1012
+ $token->val='(';
1013
+ break;
1014
+ case self::$_TOKEN_TYPES['RIGHT_PAREN']:
1015
+ $token->type=self::$_TOKEN_TYPES['RIGHT_PAREN'];
1016
+ $token->isRightParen=true;
1017
+ $token->isParen=true;
1018
+ $token->val=')';
1019
+ break;
1020
+ case self::$_TOKEN_TYPES['ARG_TERMINAL']:
1021
+ $token->type=self::$_TOKEN_TYPES['ARG_TERMINAL'];
1022
+ $token->isArgTerminal=true;
1023
+ $token->val=self::$_ARG_TERMINAL;
1024
+ break;
1025
+ case self::$_TOKEN_TYPES['UNARY_NEGATIVE']:
1026
+ $token->type=self::$_TOKEN_TYPES['UNARY_NEGATIVE'];
1027
+ $token->isUnaryNegative=true;
1028
+ $token->val=self::$_UNARY_NEGATIVE;
1029
+ $token->isArithmeticOp=true;
1030
+ $token->isOp=true;
1031
+ break;
1032
+ case self::$_TOKEN_TYPES['UNARY_NEGATION']:
1033
+ $token->type=self::$_TOKEN_TYPES['UNARY_NEGATION'];
1034
+ $token->isUnaryNegation=true;
1035
+ $token->val=self::$_UNARY_NEGATION;
1036
+ $token->isLogicOp=true;
1037
+ $token->isOp=true;
1038
+ break;
1039
+ case self::$_TOKEN_TYPES['NUMBER']:
1040
+ $token->type=self::$_TOKEN_TYPES['NUMBER'];
1041
+ $token->isNumber=true;
1042
+ if (is_string($tok))
1043
+ $token->val=(float)($tok);
1044
+ elseif (is_bool($tok))
1045
+ $token->val=((bool)$tok===true)?1:0;
1046
+ else
1047
+ $token->val=(float)$tok;
1048
+ break;
1049
+ case self::$_TOKEN_TYPES['BOOLEAN']:
1050
+ $token->type=self::$_TOKEN_TYPES['BOOLEAN'];
1051
+ $token->isBoolean=true;
1052
+ if (is_bool($tok))
1053
+ $token->val=(bool)$tok;
1054
+ elseif (is_string($tok))
1055
+ $token->val=(strtoupper($tok)=='TRUE')?true:false;
1056
+ elseif (is_numeric($tok))
1057
+ $token->val=((float)$tok != 0)?true:false;
1058
+ else
1059
+ $token->val=(bool)$tok;
1060
+ break;
1061
+ case self::$_TOKEN_TYPES['VARIABLE']:
1062
+ $token->type=self::$_TOKEN_TYPES['VARIABLE'];
1063
+ $token->isVariable=true;
1064
+ break;
1065
+ case self::$_TOKEN_TYPES['__DEFAULT__']:
1066
+ default:
1067
+ if (
1068
+ (is_object($tok) && isset($tok->_isStringLiteral) && $tok->_isStringLiteral)
1069
+ )
1070
+ {
1071
+ $token->type=self::$_TOKEN_TYPES['STRING_LITERAL'];
1072
+ $token->isStringLiteral=true;
1073
+ $token->val=(string)$tok->val;
1074
+ }
1075
+ // date token
1076
+ elseif (self::isDateInstance($tok))
1077
+ {
1078
+ $token->type=self::$_TOKEN_TYPES['DATE'];
1079
+ $token->isDate=true;
1080
+ }
1081
+ // array token
1082
+ elseif (self::isArrayInstance($tok))
1083
+ {
1084
+ $token->type=self::$_TOKEN_TYPES['ARRAY'];
1085
+ $token->isArray=true;
1086
+ }
1087
+ // regex token
1088
+ elseif (self::isRegExpInstance($tok))
1089
+ {
1090
+ $token->type=self::$_TOKEN_TYPES['REGEX'];
1091
+ $token->isRegex=true;
1092
+ }
1093
+ elseif ($tok==',')
1094
+ {
1095
+ $token->type=self::$_TOKEN_TYPES['COMMA'];
1096
+ $token->isComma=true;
1097
+ $token->val=',';
1098
+ }
1099
+ elseif ($tok=='(')
1100
+ {
1101
+ $token->type=self::$_TOKEN_TYPES['LEFT_PAREN'];
1102
+ $token->isLeftParen=true;
1103
+ $token->isParen=true;
1104
+ $token->val='(';
1105
+ $token->isOp=true;
1106
+ }
1107
+ elseif ($tok==')')
1108
+ {
1109
+ $token->type=self::$_TOKEN_TYPES['RIGHT_PAREN'];
1110
+ $token->isRightParen=true;
1111
+ $token->isParen=true;
1112
+ $token->val=')';
1113
+ //token.isOp=true;
1114
+ }
1115
+ /*else if (tok=='{')
1116
+ {
1117
+ token.type=_TOKEN_TYPES.LEFT_BRACKET;
1118
+ token.isLeftBracket=true;
1119
+ token.isBracket=true;
1120
+ token.val='{';
1121
+ token.isOp=true;
1122
+ }
1123
+ else if (tok=='}')
1124
+ {
1125
+ token.type=_TOKEN_TYPES.RIGHT_BRACKET;
1126
+ token.isRightBracket=true;
1127
+ token.isBracket=true;
1128
+ token.val='}';
1129
+ //token.isOp=true;
1130
+ }*/
1131
+ elseif (self::isNumber($tok))
1132
+ {
1133
+ $token->type=self::$_TOKEN_TYPES['NUMBER'];
1134
+ $token->isNumber=true;
1135
+ if (is_string($tok))
1136
+ $token->val=(float)($tok);
1137
+ else if (is_bool($tok))
1138
+ $token->val=((bool)$tok===true)?1:0;
1139
+ else
1140
+ $token->val=(float)$tok;
1141
+ }
1142
+ elseif (self::isBoolean($tok))
1143
+ {
1144
+ $token->type=self::$_TOKEN_TYPES['BOOLEAN'];
1145
+ $token->isBoolean=true;
1146
+ if (is_bool($tok))
1147
+ $token->val=(bool)$tok;
1148
+ else if (is_string($tok))
1149
+ $token->val=(strtoupper($tok)=='TRUE')?true:false;
1150
+ else if (is_numeric($tok))
1151
+ $token->val=((float)$tok != 0)?true:false;
1152
+ else
1153
+ $token->val=(bool)$tok;
1154
+ }
1155
+ elseif (self::_isOperator($tok))
1156
+ {
1157
+ $token->type=self::$_TOKEN_TYPES['ARITHMETIC_OP'];
1158
+ $token->isArithmeticOp=true;
1159
+ $token->isOp=true;
1160
+
1161
+ }
1162
+ elseif (self::_isLogicOperator($tok))
1163
+ {
1164
+ $token->type=self::$_TOKEN_TYPES['LOGICAL_OP'];
1165
+ $token->isLogicOp=true;
1166
+ $token->isOp=true;
1167
+ }
1168
+ elseif (self::_isCompOperator($tok))
1169
+ {
1170
+ $token->type=self::$_TOKEN_TYPES['COMPARISON_OP'];
1171
+ $token->isCompOp=true;
1172
+ $token->isOp=true;
1173
+ }
1174
+ elseif (self::_isFunction($tok))
1175
+ {
1176
+ $token->type=self::$_TOKEN_TYPES['FUNCTION'];
1177
+ $token->isFunction=true;
1178
+ $token->val=(string)$tok;
1179
+ }
1180
+ elseif (self::_isVariableName($tok))
1181
+ {
1182
+ $token->type=self::$_TOKEN_TYPES['VARIABLE'];
1183
+ $token->isVariable=true;
1184
+ }
1185
+ break;
1186
+ }
1187
+ if ($token->isOp || $token->isFunction)
1188
+ {
1189
+ $intRet = 0;
1190
+
1191
+ switch($token->val)
1192
+ {
1193
+ case "+" :
1194
+ case "-" :
1195
+ $intRet = 50;
1196
+ break;
1197
+ case "*" :
1198
+ case "/" :
1199
+ case "%" :
1200
+ $intRet = 60;
1201
+ break;
1202
+ case "^" :
1203
+ $intRet = 70;
1204
+ break;
1205
+ case self::$_UNARY_NEGATIVE:
1206
+ case self::$_UNARY_NEGATION:
1207
+ case "!" :
1208
+ case "NOT" :
1209
+ $intRet = 100;
1210
+ break;
1211
+ case "(" :
1212
+ $intRet = 1000;
1213
+ break;
1214
+ /*case "{" :
1215
+ intRet = 500; // as function
1216
+ break;*/
1217
+ case "AND" :
1218
+ case "&" :
1219
+ $intRet = 35;
1220
+ break;
1221
+ case "OR" :
1222
+ case "|" :
1223
+ $intRet = 30;
1224
+ break;
1225
+ case ">" :
1226
+ case ">=" :
1227
+ case "<" :
1228
+ case "<=" :
1229
+ case "=" :
1230
+ case "<>" :
1231
+ case "gt" :
1232
+ case "gte" :
1233
+ case "lt" :
1234
+ case "lte" :
1235
+ case "eq" :
1236
+ case "ne" :
1237
+ $intRet = 40;
1238
+ break;
1239
+ default :
1240
+ if ($token->isFunction)
1241
+ $intRet = 500;
1242
+ else
1243
+ $intRet = 0;
1244
+ break;
1245
+ }
1246
+ $token->precedence=$intRet;
1247
+ }
1248
+ else
1249
+ $token->precedence=0;
1250
+ return $token;
1251
+ }
1252
+
1253
+ public static function cloneToken($tok)
1254
+ {
1255
+ $newtok=(object)array();
1256
+
1257
+ foreach ($tok as $at=>$val)
1258
+ {
1259
+ if (self::isDateInstance($tok->$at))
1260
+ $newtok->$at=new Toolset_Date($tok->$at->getDate());
1261
+ else
1262
+ $newtok->$at=$tok->$at;
1263
+ }
1264
+ return $newtok;
1265
+ }
1266
+
1267
+ public static function isString($a)
1268
+ {
1269
+ if (!self::_isDefined($a)) return false;
1270
+ return (is_string($a))?true:false;
1271
+ }
1272
+
1273
+ public static function isDate($pstrVal, $format, &$getDate)
1274
+ {
1275
+ if (!self::_isDefined($pstrVal))
1276
+ return false;
1277
+ if (self::isDateInstance($pstrVal))
1278
+ {
1279
+ if (isset($getDate))
1280
+ $getDate['date']=$pstrVal;
1281
+ return true;
1282
+ }
1283
+ return Toolset_DateParser::isDate($pstrVal, $format, $getDate);
1284
+ }
1285
+
1286
+ public static function toArray($v)
1287
+ {
1288
+ if (self::isArrayInstance($v))
1289
+ return $v;
1290
+ else return array($v);
1291
+ }
1292
+
1293
+ public static function toNumber($pobjVal)
1294
+ {
1295
+ if (is_numeric($pobjVal))
1296
+ return (float)$pobjVal;
1297
+ else
1298
+ {
1299
+ $dblRet = (float)$pobjVal;
1300
+ return $dblRet;
1301
+ }
1302
+ }
1303
+
1304
+ public static function toBoolean($pobjVal)
1305
+ {
1306
+ //var_dump($pobjVal);
1307
+ if (!isset($pobjVal))
1308
+ throw new Exception("Boolean value is not defined!");
1309
+ else if (is_bool($pobjVal))
1310
+ return(bool)$pobjVal;
1311
+ else if (is_numeric($pobjVal))
1312
+ return (bool)(((float)$pobjVal) != 0.0);
1313
+ else if (strtoupper((string)$pobjVal)=='TRUE')
1314
+ return true;
1315
+ else if (strtoupper((string)$pobjVal)=='FALSE')
1316
+ return false;
1317
+ return null;
1318
+ }
1319
+
1320
+ public static function Tokanize($pstrExpression)
1321
+ {
1322
+ // build fast lookup maps
1323
+ self::init();
1324
+
1325
+ $intCntr = 0;
1326
+ $intBraces = 0;
1327
+ $intBrackets = 0;
1328
+ $intIndex = 0;
1329
+ $strToken = "";
1330
+ $arrTokens = array();
1331
+ $pstrExpression = self::_trim($pstrExpression);
1332
+ while ($intCntr < strlen($pstrExpression))
1333
+ {
1334
+ $prevToken = self::$_EMPTY_TOKEN;
1335
+ $chrChar = substr($pstrExpression,$intCntr, 1);
1336
+ switch ($chrChar)
1337
+ {
1338
+ case " " :
1339
+ if ($strToken!= '')
1340
+ {
1341
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1342
+ $intIndex++;
1343
+ $strToken = "";
1344
+ }
1345
+ break;
1346
+ //case "{":
1347
+ case "(":
1348
+ //(chrChar=='(')?intBraces++:intBrackets++;
1349
+ $intBraces++;
1350
+ if ($strToken!='')
1351
+ {
1352
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1353
+ $intIndex++;
1354
+ $strToken = "";
1355
+ }
1356
+ $arrTokens[$intIndex] = self::makeToken($chrChar);
1357
+ $intIndex++;
1358
+ break;
1359
+ //case "}" :
1360
+ case ")" :
1361
+ //(chrChar==')')?intBraces--:intBrackets--;
1362
+ $intBraces--;
1363
+ if ($strToken!='')
1364
+ {
1365
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1366
+ $intIndex++;
1367
+ $strToken = "";
1368
+ }
1369
+ $arrTokens[$intIndex] = self::makeToken($chrChar);
1370
+ $intIndex++;
1371
+ break;
1372
+ case "^" :
1373
+ case "*" :
1374
+ case "/" :
1375
+ case "%" :
1376
+ case "&" :
1377
+ case "|" :
1378
+ case "," :
1379
+ case "!" :
1380
+ if ($strToken!='')
1381
+ {
1382
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1383
+ $intIndex++;
1384
+ $strToken = "";
1385
+ }
1386
+ $arrTokens[$intIndex] = self::makeToken($chrChar);
1387
+ $intIndex++;
1388
+ break;
1389
+ case "-" :
1390
+ if ($strToken!='')
1391
+ {
1392
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1393
+ $intIndex++;
1394
+ $strToken = "";
1395
+ }
1396
+ $chrNext = substr($pstrExpression,$intCntr + 1, 1);
1397
+ if (count($arrTokens) > 0)
1398
+ $prevToken = $arrTokens[$intIndex - 1];
1399
+ if (/*intCntr == 0 ||*/(($prevToken->isArithmeticOp ||
1400
+ $prevToken->isLeftParen || $prevToken->isComma) &&
1401
+ (self::_isDigit($chrNext) || $chrNext == "(")))
1402
+ {
1403
+ // Negative Number
1404
+ $strToken .= $chrChar;
1405
+ }
1406
+ else
1407
+ {
1408
+ $arrTokens[$intIndex] = self::makeToken($chrChar);
1409
+ $intIndex++;
1410
+ $strToken = "";
1411
+ }
1412
+ break;
1413
+ case "+" :
1414
+ if ($strToken!='')
1415
+ {
1416
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1417
+ $intIndex++;
1418
+ $strToken = "";
1419
+ }
1420
+ $chrNext = substr($pstrExpression,$intCntr + 1, 1);
1421
+ if (count($arrTokens) > 0)
1422
+ $prevToken = $arrTokens[$intIndex - 1];
1423
+ if (/*intCntr == 0 ||*/ (($prevToken->isArithmeticOp ||
1424
+ $prevToken->isLeftParen || $prevToken->isComma) &&
1425
+ (self::_isDigit($chrNext) || $chrNext == "(")))
1426
+ {
1427
+ // positive Number
1428
+ $strToken .= $chrChar;
1429
+ }
1430
+ else
1431
+ {
1432
+ $arrTokens[$intIndex] = self::makeToken($chrChar);
1433
+ $intIndex++;
1434
+ $strToken = "";
1435
+ }
1436
+ break;
1437
+ case "<" :
1438
+ $chrNext = substr($pstrExpression,$intCntr + 1, 1);
1439
+ if ($strToken!='')
1440
+ {
1441
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1442
+ $intIndex++;
1443
+ $strToken = "";
1444
+ }
1445
+ if ($chrNext == "=")
1446
+ {
1447
+ $arrTokens[$intIndex] = self::makeToken($chrChar . "=");
1448
+ $intIndex++;
1449
+ $intCntr++;
1450
+ }
1451
+ else if ($chrNext == ">")
1452
+ {
1453
+ $arrTokens[$intIndex] = self::makeToken($chrChar . ">");
1454
+ $intIndex++;
1455
+ $intCntr++;
1456
+ }
1457
+ else
1458
+ {
1459
+ $arrTokens[$intIndex] = self::makeToken($chrChar);
1460
+ $intIndex++;
1461
+ }
1462
+ break;
1463
+ case ">" :
1464
+ $chrNext = substr($pstrExpression,$intCntr + 1, 1);
1465
+ if ($strToken!='')
1466
+ {
1467
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1468
+ $intIndex++;
1469
+ $strToken = "";
1470
+ }
1471
+ if ($chrNext == "=")
1472
+ {
1473
+ $arrTokens[$intIndex] = self::makeToken($chrChar . "=");
1474
+ $intIndex++;
1475
+ $intCntr++;
1476
+ }
1477
+ else
1478
+ {
1479
+ $arrTokens[$intIndex] = self::makeToken($chrChar);
1480
+ $intIndex++;
1481
+ }
1482
+ break;
1483
+ case "=" :
1484
+ if ($strToken!='')
1485
+ {
1486
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1487
+ $intIndex++;
1488
+ $strToken = "";
1489
+ }
1490
+ $arrTokens[$intIndex] = self::makeToken($chrChar);
1491
+ $intIndex++;
1492
+ break;
1493
+ case "'" :
1494
+ case "\"" :
1495
+ if ($strToken!='')
1496
+ {
1497
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1498
+ $intIndex++;
1499
+ $strToken = "";
1500
+ }
1501
+ /*
1502
+ var found=false;
1503
+ var initCnt=intCntr;
1504
+ while (!found)
1505
+ {
1506
+ intPos = pstrExpression.indexOf(chrChar, intCntr + 1);
1507
+ if (intPos < 0)
1508
+ throw "Unterminated string constant";
1509
+ else
1510
+ {
1511
+ if (pstrExpression.charAt(intPos-1)!='\\') // not escape quote
1512
+ {
1513
+ found=true;
1514
+ strToken += pstrExpression.substring(initCnt + 1, intPos);
1515
+ // replace all escaped quotes inside string
1516
+ var strTok2=strToken.replace('\\'+chrChar,chrChar);
1517
+ while (strToken!=strTok2)
1518
+ {
1519
+ strToken=strTok2
1520
+ strTok2=strToken.replace('\\'+chrChar,chrChar);
1521
+ }
1522
+ strToken=new String(strTok2);
1523
+ strToken._isStringLiteral=true;
1524
+ arrTokens[intIndex] = _makeToken(strToken);
1525
+ intIndex++;
1526
+ strToken = "";
1527
+ intCntr = intPos;
1528
+ }
1529
+ else
1530
+ {
1531
+ intCntr=intPos;
1532
+ }
1533
+ }
1534
+ }*/
1535
+ $intPos = strpos($pstrExpression,$chrChar, $intCntr + 1);
1536
+ if ($intPos < 0)
1537
+ throw new Exception("Unterminated string constant");
1538
+ else
1539
+ {
1540
+ $strToken .= substr($pstrExpression,$intCntr + 1, $intPos-$intCntr-1);
1541
+ $strToken=(object)array('val'=>$strToken,'_isStringLiteral'=>true);
1542
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1543
+ $intIndex++;
1544
+ $strToken = "";
1545
+ $intCntr = $intPos;
1546
+ }
1547
+ break;
1548
+ default :
1549
+ $strToken .= $chrChar;
1550
+ break;
1551
+ }
1552
+ $intCntr++;
1553
+ }
1554
+ if ($intBraces > 0)
1555
+ throw new Exception("Unbalanced parenthesis!");
1556
+
1557
+ if ($strToken!='')
1558
+ $arrTokens[$intIndex] = self::makeToken($strToken);
1559
+ return $arrTokens;
1560
+ }
1561
+ }
1562
+
1563
+
1564
+
1565
+ class Toolset_Parser
1566
+ {
1567
+
1568
+ private $strInFix = null;
1569
+ private $arrVars = array();
1570
+ private $arrTokens = null;
1571
+ private $arrPostFix = null;
1572
+ private $dtFormat = "d/m/Y";
1573
+
1574
+ /*------------------------------------------------------------------------------
1575
+ * NAME : HandleFunctions
1576
+ * PURPOSE : Execute built-in functions
1577
+ * PARAMETERS : pstrTok - The current function name
1578
+ * pStack - Operand stack
1579
+ * RETURNS : Nothing, the result is pushed back onto the stack.
1580
+ *----------------------------------------------------------------------------*/
1581
+ private function _HandleFunctions($pstrTok, &$pStack, $pdtFormat, &$parrVars)
1582
+ {
1583
+ if (!$pstrTok->isFunction)
1584
+ throw new Exception("Unsupported function token [" . $pstrTok->val . "]");
1585
+
1586
+ $varTmp = $pstrTok->val;
1587
+ $arrArgs = array();
1588
+ $varTerm = Toolset_Tokenizer::$ARG_TERMINAL;
1589
+ while (!$pStack->IsEmpty())
1590
+ {
1591
+ $varTerm = $pStack->Pop();
1592
+ if (!$varTerm->isArgTerminal)
1593
+ $arrArgs[] = $varTerm;
1594
+ else
1595
+ break;
1596
+ }
1597
+
1598
+ switch ($varTmp)
1599
+ {
1600
+ case "ARRAY" :
1601
+
1602
+ $arrArray=array();
1603
+
1604
+ $objTmp = 0;
1605
+ $intCntr = count($arrArgs);
1606
+ while (--$intCntr >= 0)
1607
+ {
1608
+ $varTerm = $arrArgs[$intCntr];
1609
+ if ($varTerm->isVariable)
1610
+ {
1611
+ if (!isset($parrVars[$varTerm->val]))
1612
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1613
+ else
1614
+ $varTerm = $parrVars[$varTerm->val];
1615
+ }
1616
+ $arrArray=array_merge($arrArray,Toolset_Tokenizer::toArray($varTerm->val));
1617
+ }
1618
+ $pStack->Push(Toolset_Tokenizer::makeToken($arrArray,Toolset_Tokenizer::$TOKEN_TYPE['ARRAY']));
1619
+ break;
1620
+ case "TODAY" :
1621
+ $pStack->Push(Toolset_Tokenizer::makeToken(Toolset_DateParser::currentDate(), Toolset_Tokenizer::$TOKEN_TYPE['DATE']));
1622
+ break;
1623
+ case "ACOS" :
1624
+ case "ASIN" :
1625
+ case "ATAN" :
1626
+ throw new Exception("Function [" . $varTmp . "] is not implemented!");
1627
+ break;
1628
+ case "ABS" :
1629
+ case "CHR" :
1630
+ case "COS" :
1631
+ case "FIX" :
1632
+ case "HEX" :
1633
+ case "LOG" :
1634
+ case "RAND" :
1635
+ case "ROUND" :
1636
+ case "SIN" :
1637
+ case "SQRT" :
1638
+ case "TAN" :
1639
+ if ($varTmp != "RAND")
1640
+ {
1641
+ if (count($arrArgs) < 1)
1642
+ throw new Exception($varTmp . " requires atleast one argument!");
1643
+ else if (count($arrArgs) > 1)
1644
+ throw new Exception($varTmp . " requires only one argument!");
1645
+ }
1646
+ else
1647
+ {
1648
+ if (count($arrArgs) < 1)
1649
+ throw new Exception($varTmp . " requires atleast one argument!");
1650
+ else if (count($arrArgs) > 2)
1651
+ throw new Exception($varTmp . " requires at most two arguments!");
1652
+ }
1653
+ $varTerm = $arrArgs[0];
1654
+ if ($varTerm->isVariable)
1655
+ {
1656
+ if (!isset($parrVars[$varTerm->val]))
1657
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1658
+ else
1659
+ $varTerm = $parrVars[$varTerm->val];
1660
+ }
1661
+
1662
+ $objTmp=$varTerm->val;
1663
+
1664
+ $rand_min=$rand_max=0;
1665
+
1666
+ if ( is_numeric( $objTmp ) === false )
1667
+ throw new Exception($varTmp . " operates on numeric operands only!");
1668
+ else
1669
+ {
1670
+ $objTmp = Toolset_Tokenizer::toNumber($varTerm->val);
1671
+ if ($varTmp == "RAND")
1672
+ {
1673
+ $rand_max=floor($objTmp);
1674
+ if (count($arrArgs) == 2)
1675
+ {
1676
+ $varTerm = $arrArgs[1];
1677
+ if ($varTerm->isVariable)
1678
+ {
1679
+ if (!isset($parrVars[$varTerm->val]))
1680
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1681
+ else
1682
+ $varTerm = $parrVars[$varTerm->val];
1683
+ }
1684
+
1685
+ if (!$varTerm->isNumber)
1686
+ throw new Exception($varTmp . " operates on numeric operands only!");
1687
+
1688
+ $objTmp = Toolset_Tokenizer::toNumber($varTerm->val);
1689
+
1690
+ $rand_min=floor($objTmp);
1691
+ }
1692
+ }
1693
+ }
1694
+
1695
+ if ($varTmp == "ABS")
1696
+ $pStack->Push(Toolset_Tokenizer::makeToken(abs($objTmp),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1697
+ else if ($varTmp == "CHR")// TODO check what happens when $objTmp is empty; what does chr() return?
1698
+ $pStack->Push(Toolset_Tokenizer::makeToken(chr($objTmp),Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
1699
+ else if ($varTmp == "COS")
1700
+ $pStack->Push(Toolset_Tokenizer::makeToken(cos($objTmp),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1701
+ else if ($varTmp == "FIX")
1702
+ $pStack->Push(Toolset_Tokenizer::makeToken(floor($objTmp),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1703
+ else if ($varTmp == "HEX")
1704
+ $pStack->Push(Toolset_Tokenizer::makeToken(dechex($objTmp),Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
1705
+ else if ($varTmp == "LOG")
1706
+ $pStack->Push(Toolset_Tokenizer::makeToken(log($objTmp),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1707
+ else if ($varTmp == "RAND")
1708
+ $pStack->Push(Toolset_Tokenizer::makeToken(mt_rand($rand_min,$rand_max),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1709
+ else if ($varTmp == "ROUND")
1710
+ $pStack->Push(Toolset_Tokenizer::makeToken(round($objTmp),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1711
+ else if ($varTmp == "SIN")
1712
+ $pStack->Push(Toolset_Tokenizer::makeToken(sin($objTmp),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1713
+ else if ($varTmp == "SQRT")
1714
+ $pStack->Push(Toolset_Tokenizer::makeToken(sqrt($objTmp),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1715
+ else if ($varTmp == "TAN")
1716
+ $pStack->Push(Toolset_Tokenizer::makeToken(tan($objTmp),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1717
+ break;
1718
+ case "STR" :
1719
+ if (count($arrArgs) < 1)
1720
+ throw new Exception($varTmp . " requires atleast one argument!");
1721
+ else if (count($arrArgs) > 2)
1722
+ throw new Exception($varTmp . " requires at most two arguments!");
1723
+ $varTerm = $arrArgs[count($arrArgs)-1];
1724
+ if ($varTerm->isVariable)
1725
+ {
1726
+ if (!isset($parrVars[$varTerm->val]))
1727
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1728
+ else
1729
+ $varTerm = $parrVars[$varTerm->val];
1730
+ }
1731
+ // if date, output formated date string
1732
+ if ($varTerm->isDate)
1733
+ {
1734
+ $format='';
1735
+ if (count($arrArgs)==2)
1736
+ {
1737
+ $varFormat = $arrArgs[0];
1738
+ if ($varFormat->isVariable)
1739
+ {
1740
+ if (!isset($parrVars[$varFormat->val]))
1741
+ throw new Exception("Variable [" . $varFormat->val . "] not defined");
1742
+ else
1743
+ $varFormat = $parrVars[$varFormat->val];
1744
+ }
1745
+
1746
+ if (!$varFormat->isStringLiteral)
1747
+ throw new Exception("format argument for " . $varTmp . " must be a string!");
1748
+ $format=$varFormat->val;
1749
+ }
1750
+ $pStack->Push(Toolset_Tokenizer::makeToken(Toolset_DateParser::formatDate($varTerm->val, $format),Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
1751
+ }
1752
+ else // just convert to string
1753
+ $pStack->Push(Toolset_Tokenizer::makeToken((string)$varTerm->val.'',Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
1754
+ break;
1755
+ case "ASC" :
1756
+ if (count($arrArgs) > 1)
1757
+ throw new Exception($varTmp . " requires only one argument!");
1758
+ else if (count($arrArgs) < 1)
1759
+ throw new Exception($varTmp . " requires atleast one argument!");
1760
+ $varTerm = $arrArgs[0];
1761
+ if ($varTerm->isVariable)
1762
+ {
1763
+ if (!isset($parrVars[$varTerm->val]))
1764
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1765
+ else
1766
+ $varTerm = $parrVars[$varTerm]->val;
1767
+ }
1768
+
1769
+ if( $varTerm->isNumber )
1770
+ {
1771
+ $varTerm->val = (string) $varTerm->val;
1772
+ $varTerm->isStringLiteral = true;
1773
+ }
1774
+
1775
+ if (!$varTerm->isStringLiteral)
1776
+ {
1777
+ throw new Exception($varTmp . " requires a string type operand!");
1778
+ }
1779
+ else
1780
+ {
1781
+ if ( strlen( $varTerm->val ) > 0 )
1782
+ {
1783
+ $ascii_char = ord($varTerm->val{0});
1784
+ }
1785
+ else
1786
+ {
1787
+ $ascii_char = 0;
1788
+ }
1789
+ $pStack->Push(Toolset_Tokenizer::makeToken($ascii_char,Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1790
+ }
1791
+ break;
1792
+ case "REGEX" :
1793
+ if (count($arrArgs) < 1)
1794
+ throw new Exception($varTmp . " requires atleast one argument!");
1795
+ else if (count($arrArgs) > 2)
1796
+ throw new Exception($varTmp . " requires at most two arguments!");
1797
+
1798
+ $varTerm = $arrArgs[count($arrArgs)-1];
1799
+ if ($varTerm->isVariable)
1800
+ {
1801
+ if (!isset($parrVars[$varTerm->val]))
1802
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1803
+ else
1804
+ $varTerm = $parrVars[$varTerm->val];
1805
+ }
1806
+
1807
+ if (!$varTerm->isStringLiteral)
1808
+ throw new Exception($varTmp . " operates on string type operands!");
1809
+
1810
+ $opts=Toolset_Tokenizer::$EMPTY_STRING;
1811
+ if (count($arrArgs)==2)
1812
+ {
1813
+ $opts = $arrArgs[0];
1814
+ if ($opts->isVariable)
1815
+ {
1816
+ if (!isset($parrVars[$opts->val]))
1817
+ throw new Exception("Variable [" . $opts->val . "] not defined");
1818
+ else
1819
+ $opts = $parrVars[$opts->val];
1820
+ }
1821
+
1822
+ if (!$opts->isStringLiteral)
1823
+ throw new Exception($varTmp . " operates on string type operands!");
1824
+ }
1825
+ $pStack->Push(Toolset_Tokenizer::makeToken(Toolset_Functions::Regex($varTerm->val, $opts->val),Toolset_Tokenizer::$TOKEN_TYPE['REGEX']));
1826
+ break;
1827
+ case "LCASE" :
1828
+ case "UCASE" :
1829
+ case "NUM" :
1830
+ if (count($arrArgs) < 1)
1831
+ throw new Exception($varTmp . " requires atleast one argument!");
1832
+ else if (count($arrArgs) > 1)
1833
+ throw new Exception($varTmp . " requires only one argument!");
1834
+
1835
+ $varTerm = $arrArgs[0];
1836
+ if ($varTerm->isVariable)
1837
+ {
1838
+ if (!isset($parrVars[$varTerm->val]))
1839
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1840
+ else
1841
+ $varTerm = $parrVars[$varTerm->val];
1842
+ }
1843
+
1844
+ if( $varTerm->isNumber )
1845
+ {
1846
+ $varTerm->val = (string) $varTerm->val;
1847
+ $varTerm->isStringLiteral = true;
1848
+ }
1849
+
1850
+ if (!$varTerm->isStringLiteral && $varTmp != "NUM")
1851
+ throw new Exception($varTmp . " requires a string type operand!");
1852
+ else
1853
+ {
1854
+ if ($varTmp == "LCASE")
1855
+ {
1856
+ $pStack->Push(Toolset_Tokenizer::makeToken(strtolower($varTerm->val),Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
1857
+ }
1858
+ else if ($varTmp == "UCASE")
1859
+ {
1860
+ $pStack->Push(Toolset_Tokenizer::makeToken(strtoupper($varTerm->val),Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
1861
+ }
1862
+ else if ($varTmp == "NUM")
1863
+ {
1864
+ $objTmp=Toolset_Tokenizer::toNumber($varTerm->val)+0.0;
1865
+ if (is_nan($objTmp))
1866
+ throw new Exception($varTmp . " cannot convert [" . $varTerm->val . "] to number!");
1867
+ $pStack->Push(Toolset_Tokenizer::makeToken($objTmp,Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1868
+ }
1869
+ }
1870
+ break;
1871
+ case "LEN" :
1872
+ if (count($arrArgs) < 1)
1873
+ throw new Exception($varTmp . " requires atleast one argument!");
1874
+ else if (count($arrArgs) > 1)
1875
+ throw new Exception($varTmp . " requires only one argument!");
1876
+
1877
+ $varTerm = $arrArgs[0];
1878
+ if ($varTerm->isVariable)
1879
+ {
1880
+ if (!isset($parrVars[$varTerm->val]))
1881
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1882
+ else
1883
+ $varTerm = $parrVars[$varTerm->val];
1884
+ }
1885
+
1886
+ if (!$varTerm->isArray && !$varTerm->isStringLiteral)
1887
+ throw new Exception($varTmp . " requires a string or array type operand!");
1888
+ else
1889
+ {
1890
+ if ($varTerm->isStringLiteral)
1891
+ $pStack->Push(Toolset_Tokenizer::makeToken(strlen($varTerm->val),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1892
+ else
1893
+ $pStack->Push(Toolset_Tokenizer::makeToken(count($varTerm->val),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
1894
+ }
1895
+ break;
1896
+ case "USER" :
1897
+ if (count($arrArgs) < 1)
1898
+ throw new Exception($varTmp . " requires atleast one argument!");
1899
+ else if (count($arrArgs) > 1)
1900
+ throw new Exception($varTmp . " requires only one argument!");
1901
+
1902
+ $varTerm = $arrArgs[0];
1903
+ if ($varTerm->isVariable)
1904
+ {
1905
+ if (!isset($parrVars[$varTerm->val]))
1906
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1907
+ else
1908
+ $varTerm = $parrVars[$varTerm->val];
1909
+ }
1910
+
1911
+ if (!$varTerm->isStringLiteral)
1912
+ throw new Exception($varTmp . " requires a string type operand!");
1913
+ else
1914
+ {
1915
+ $pStack->Push(Toolset_Tokenizer::makeToken(Toolset_Functions::User($varTerm->val),Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
1916
+ }
1917
+ break;
1918
+ case "COOKIE" :
1919
+ if (count($arrArgs) < 1)
1920
+ throw new Exception($varTmp . " requires atleast one argument!");
1921
+ else if (count($arrArgs) > 1)
1922
+ throw new Exception($varTmp . " requires only one argument!");
1923
+
1924
+ $varTerm = $arrArgs[0];
1925
+ if ($varTerm->isVariable)
1926
+ {
1927
+ if (!isset($parrVars[$varTerm->val]))
1928
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1929
+ else
1930
+ $varTerm = $parrVars[$varTerm->val];
1931
+ }
1932
+
1933
+ if (!$varTerm->isStringLiteral)
1934
+ throw new Exception($varTmp . " requires a string type operand!");
1935
+ else
1936
+ {
1937
+ $pStack->Push(Toolset_Tokenizer::makeToken(Toolset_Functions::Cookie($varTerm->val),Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
1938
+ }
1939
+ break;
1940
+ case "CONTAINS" :
1941
+ if (count($arrArgs) < 2)
1942
+ throw new Exception($varTmp . " requires atleast two arguments!");
1943
+ else if (count($arrArgs) > 2)
1944
+ throw new Exception($varTmp . " requires only two arguments!");
1945
+
1946
+ $varTerm = $arrArgs[1];
1947
+ if ($varTerm->isVariable)
1948
+ {
1949
+ if (!isset($parrVars[$varTerm->val]))
1950
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1951
+ else
1952
+ $varTerm = $parrVars[$varTerm->val];
1953
+ }
1954
+ $varTerm2 = $arrArgs[0];
1955
+ if ($varTerm2->isVariable)
1956
+ {
1957
+ if (!isset($parrVars[$varTerm2->val]))
1958
+ throw new Exception("Variable [" . $varTerm2->val . "] not defined");
1959
+ else
1960
+ $varTerm2 = $parrVars[$varTerm2->val];
1961
+ }
1962
+
1963
+ if ( !$varTerm->isArray )
1964
+ throw new Exception($varTmp . " requires an array as first argument!");
1965
+ else
1966
+ {
1967
+ $found=Toolset_Functions::Contains($varTerm->val, $varTerm2->val); //in_array($varTerm2->val,$varTerm->val);
1968
+ $pStack->Push(Toolset_Tokenizer::makeToken($found,Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
1969
+ }
1970
+ break;
1971
+ case "DATE" :
1972
+ if (count($arrArgs) < 2)
1973
+ throw new Exception($varTmp . " requires atleast two arguments!");
1974
+ else if (count($arrArgs) > 2)
1975
+ throw new Exception($varTmp . " requires only two arguments!");
1976
+
1977
+ $varTerm = $arrArgs[1];
1978
+ if ($varTerm->isVariable)
1979
+ {
1980
+ if (!isset($parrVars[$varTerm->val]))
1981
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
1982
+ else
1983
+ $varTerm = $parrVars[$varTerm->val];
1984
+ }
1985
+ $varFormat = $arrArgs[0];
1986
+ if ($varFormat->isVariable)
1987
+ {
1988
+ if (!isset($parrVars[$varFormat->val]))
1989
+ throw new Exception("Variable [" . $varFormat->val . "] not defined");
1990
+ else
1991
+ $varFormat = $parrVars[$varFormat->val];
1992
+ }
1993
+
1994
+ $dateobj=array();
1995
+ if (
1996
+ (!$varTerm->isStringLiteral) ||
1997
+ (!$varFormat->isStringLiteral)
1998
+ )
1999
+ throw new Exception($varTmp . " requires string type operands!");
2000
+ else if (!Toolset_Tokenizer::isDate($varTerm->val, $varFormat->val, $dateobj))
2001
+ throw new Exception($varTmp . " can not convert [" . $varTerm->val . "] to a valid date with format [" . $varFormat->val . "]!");
2002
+ else
2003
+ {
2004
+ if (isset($dateobj['date']))
2005
+ $pStack->Push(Toolset_Tokenizer::makeToken($dateobj['date'],Toolset_Tokenizer::$TOKEN_TYPE['DATE']));
2006
+ else
2007
+ throw new Exception($varTmp . " unknown error");
2008
+ }
2009
+ break;
2010
+ case "empty" :
2011
+ case "EMPTY" :
2012
+ if (count($arrArgs) < 1)
2013
+ throw new Exception($varTmp . " requires atleast one argument!");
2014
+ else if (count($arrArgs) > 1)
2015
+ throw new Exception($varTmp . " requires only one arguments!");
2016
+
2017
+ $varFormat = $arrArgs[0];
2018
+
2019
+ if( $varFormat->isEmpty )
2020
+ {
2021
+ $pStack->Push(Toolset_Tokenizer::makeToken(true,Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2022
+ }
2023
+ elseif( $varFormat->isStringLiteral && $varFormat->val === '' )
2024
+ {
2025
+ $pStack->Push(Toolset_Tokenizer::makeToken(true,Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2026
+ }
2027
+ elseif( $varFormat->isArray && count( $varFormat->val ) === 0 )
2028
+ {
2029
+ $pStack->Push(Toolset_Tokenizer::makeToken(true,Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2030
+ }
2031
+ elseif( $varFormat->isDate && !$varFormat->val )
2032
+ {
2033
+ $pStack->Push(Toolset_Tokenizer::makeToken(true,Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2034
+ }
2035
+ else
2036
+ {
2037
+ $pStack->Push(Toolset_Tokenizer::makeToken(false,Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2038
+ }
2039
+
2040
+ break;
2041
+ case "LEFT" :
2042
+ case "RIGHT" :
2043
+ if (count($arrArgs) < 2)
2044
+ throw new Exception($varTmp . " requires atleast two arguments!");
2045
+ else if (count($arrArgs) > 2)
2046
+ throw new Exception($varTmp . " requires only two arguments!");
2047
+
2048
+ for ($intCntr = 0; $intCntr < count($arrArgs); $intCntr++)
2049
+ {
2050
+ $varTerm = $arrArgs[$intCntr];
2051
+ if ($varTerm->isVariable)
2052
+ {
2053
+ if (!isset($parrVars[$varTerm->val]))
2054
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
2055
+ else
2056
+ $varTerm = $parrVars[$varTerm->val];
2057
+ }
2058
+
2059
+ if( $varTerm->isNumber )
2060
+ {
2061
+ $arrArgs[1]->val = (string) $arrArgs[1]->val;
2062
+ $varTerm->isStringLiteral = true;
2063
+ }
2064
+
2065
+ if ($intCntr == 0 && !$varTerm->isNumber)
2066
+ throw new Exception($varTmp . " operator requires numeric length!");
2067
+ else if ($intCntr == 1 && !$varTerm->isStringLiteral)
2068
+ throw new Exception($varTmp . " operator requires a string operand!");
2069
+ $arrArgs[$intCntr] = $varTerm;
2070
+ }
2071
+ $varTerm = $arrArgs[1]->val;
2072
+ $objTmp = Toolset_Tokenizer::toNumber($arrArgs[0]->val);
2073
+ if ($varTmp == "LEFT")
2074
+ {
2075
+ $pStack->Push(Toolset_Tokenizer::makeToken(substr($varTerm,0, $objTmp),Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
2076
+ }
2077
+ else
2078
+ {
2079
+ $pStack->Push(Toolset_Tokenizer::makeToken(substr($varTerm,(strlen($varTerm) - $objTmp), $objTmp),Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
2080
+ }
2081
+ break;
2082
+ case "MID" :
2083
+ case "IIF" :
2084
+ if (count($arrArgs) < 3)
2085
+ throw new Exception($varTmp . " requires atleast three arguments!");
2086
+ else if (count($arrArgs) > 3)
2087
+ throw new Exception($varTmp . " requires only three arguments!");
2088
+
2089
+ for ($intCntr = 0; $intCntr < count($arrArgs); $intCntr++)
2090
+ {
2091
+ $varTerm = $arrArgs[$intCntr];
2092
+ if ($varTerm->isVariable)
2093
+ {
2094
+ if (!isset($parrVars[$varTerm->val]))
2095
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
2096
+ else
2097
+ $varTerm = $parrVars[$varTerm->val];
2098
+ }
2099
+
2100
+ if( $varTerm->isNumber )
2101
+ {
2102
+ $arrArgs[2]->val = (string) $arrArgs[2]->val;
2103
+ $varTerm->isStringLiteral = true;
2104
+ }
2105
+
2106
+ if ($varTmp == "MID" && $intCntr <= 1 && !$varTerm->isNumber)
2107
+ throw new Exception($varTmp . " operator requires numeric lengths!");
2108
+ else if ($varTmp == "MID" && $intCntr == 2 && !$varTerm->isStringLiteral)
2109
+ throw new Exception($varTmp . " operator requires a string input!");
2110
+ // else if ($varTmp == "IIF" && $intCntr == 2 && !$varTerm->isBoolean && !$varTerm->isNumber)
2111
+ // throw new Exception($varTmp . " operator requires boolean condition!");
2112
+ $arrArgs[$intCntr] = $varTerm;
2113
+ }
2114
+ if ($varTmp == "MID")
2115
+ {
2116
+ $varTerm = $arrArgs[2]->val;
2117
+ $objOp1 = Toolset_Tokenizer::toNumber($arrArgs[1]->val);
2118
+ $objOp2 = Toolset_Tokenizer::toNumber($arrArgs[0]->val);
2119
+ $pStack->Push(Toolset_Tokenizer::makeToken(substr($varTerm,$objOp1, $objOp2-$objOp1),Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
2120
+ }
2121
+ else
2122
+ {
2123
+ $varTerm = Toolset_Tokenizer::toBoolean($arrArgs[2]->val);
2124
+ if ($varTerm)
2125
+ $objOp1 = $arrArgs[1];
2126
+ else
2127
+ $objOp1 = $arrArgs[0];
2128
+ $pStack->Push($objOp1);
2129
+ }
2130
+ break;
2131
+ case "AVG" :
2132
+ case "MAX" :
2133
+ case "MIN" :
2134
+ if (count($arrArgs) < 1)
2135
+ throw new Exception($varTmp . " requires atleast one operand!");
2136
+
2137
+ $_arr=array();
2138
+ $intCntr = count($arrArgs);
2139
+ while (--$intCntr>=0)
2140
+ {
2141
+ $varTerm = $arrArgs[$intCntr];
2142
+ if ($varTerm->isVariable)
2143
+ {
2144
+ if (!isset($parrVars[$varTerm->val]))
2145
+ throw new Exception("Variable [" . $varTerm->val . "] not defined");
2146
+ else
2147
+ $varTerm = $parrVars[$varTerm->val];
2148
+ }
2149
+ if (!$varTerm->isNumber && !$varTerm->isArray)
2150
+ throw new Exception($varTmp . " requires numeric or array operands only!");
2151
+
2152
+ if (!$varTerm->isArray)
2153
+ $_arr=array_merge($_arr,Toolset_Tokenizer::toArray(Toolset_Tokenizer::toNumber($varTerm->val)));
2154
+ else
2155
+ $_arr=array_merge($_arr,$varTerm->val);
2156
+ }
2157
+ $intCntr = -1;
2158
+ $objTmp = 0;
2159
+ while (++$intCntr < count($_arr))
2160
+ {
2161
+ $varTerm = $_arr[$intCntr];
2162
+ if ($varTmp == "AVG")
2163
+ $objTmp += $varTerm;
2164
+ else if ($varTmp == "MAX")
2165
+ {
2166
+ if ($intCntr == 0)
2167
+ $objTmp = $varTerm;
2168
+ else if ($objTmp < $varTerm)
2169
+ $objTmp = $varTerm;
2170
+ }
2171
+ else if ($varTmp == "MIN")
2172
+ {
2173
+ if ($intCntr == 0)
2174
+ $objTmp = $varTerm;
2175
+ else if ($objTmp > $varTerm)
2176
+ $objTmp = $varTerm;
2177
+ }
2178
+ }
2179
+ if ($varTmp == "AVG" && !empty($_arr))
2180
+ $pStack->Push(Toolset_Tokenizer::makeToken($objTmp/count($_arr),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
2181
+ else if ($varTmp == "AVG")
2182
+ $pStack->Push(Toolset_Tokenizer::makeToken(0,Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
2183
+ else
2184
+ $pStack->Push(Toolset_Tokenizer::makeToken($objTmp,Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
2185
+ unset($_arr);
2186
+ break;
2187
+ }
2188
+ }
2189
+
2190
+ /*------------------------------------------------------------------------------
2191
+ * NAME : InFixToPostFix
2192
+ * PURPOSE : Convert an Infix expression into a postfix (RPN) equivalent
2193
+ * PARAMETERS : Infix expression element array
2194
+ * RETURNS : array containing postfix expression element tokens
2195
+ *----------------------------------------------------------------------------*/
2196
+ private function _InFixToPostFix($arrToks)
2197
+ {
2198
+ $blnStart = false;
2199
+ $intIndex = 0;
2200
+ $arrPFix = array();
2201
+ $myStack = new Toolset_Stack();
2202
+
2203
+ // Infix to postfix converter
2204
+ for ($intCntr = 0; $intCntr < count($arrToks); $intCntr++)
2205
+ {
2206
+ /*echo '<br />Tok: <br />';
2207
+ print_r($arrToks);
2208
+ echo '<br />PF: <br />';
2209
+ print_r($arrPFix);
2210
+ echo '<br />';*/
2211
+
2212
+ $strTok = $arrToks[$intCntr];
2213
+ switch ($strTok->type)
2214
+ {
2215
+ case Toolset_Tokenizer::$TOKEN_TYPE['LEFT_PAREN'] :
2216
+ if ($myStack->Size() > 0 && $myStack->Get(0)->isFunction)
2217
+ {
2218
+ $arrPFix[$intIndex] = Toolset_Tokenizer::$ARG_TERMINAL;
2219
+ $intIndex++;
2220
+ }
2221
+ $myStack->Push($strTok);
2222
+ break;
2223
+ case Toolset_Tokenizer::$TOKEN_TYPE['RIGHT_PAREN'] :
2224
+ $blnStart = true;
2225
+ while (!$myStack->IsEmpty())
2226
+ {
2227
+ $strTok = $myStack->Pop();
2228
+ if (!$strTok->isLeftParen)
2229
+ {
2230
+ $arrPFix[$intIndex] = $strTok;
2231
+ $intIndex++;
2232
+ }
2233
+ else
2234
+ {
2235
+ $blnStart = false;
2236
+ break;
2237
+ }
2238
+ }
2239
+ if ($myStack->IsEmpty() && $blnStart)
2240
+ throw new Exception("Unbalanced parenthesis!");
2241
+ break;
2242
+ case Toolset_Tokenizer::$TOKEN_TYPE['COMMA'] :
2243
+ while (!$myStack->IsEmpty())
2244
+ {
2245
+ $strTok = $myStack->Get(0);
2246
+ if ($strTok->isLeftParen) break;
2247
+ $arrPFix[$intIndex] = $myStack->Pop();
2248
+ $intIndex++;
2249
+ }
2250
+ break;
2251
+ //case Tokenizer.TOKEN_TYPE.UNARY_NEGATIVE :
2252
+ //case Tokenizer.TOKEN_TYPE.UNARY_NEGATION :
2253
+ case Toolset_Tokenizer::$TOKEN_TYPE['ARITHMETIC_OP'] :
2254
+ case Toolset_Tokenizer::$TOKEN_TYPE['LOGICAL_OP'] :
2255
+ case Toolset_Tokenizer::$TOKEN_TYPE['COMPARISON_OP'] :
2256
+ switch ($strTok->val)
2257
+ {
2258
+ /*case "-" :
2259
+ case "+" :
2260
+ case "NOT" :
2261
+ case "!" :
2262
+ case "^" :
2263
+ case "*" :
2264
+ case "/" :
2265
+ case "%" :
2266
+ case "AND" :
2267
+ case "&" :
2268
+ case "OR" :
2269
+ case "|" :
2270
+ case ">" :
2271
+ case "<" :
2272
+ case "=" :
2273
+ case ">=" :
2274
+ case "<=" :
2275
+ case "<>" :*/
2276
+ default:
2277
+ if ($strTok->val=='-')
2278
+ {
2279
+ // check for unary negative operator.
2280
+ $strPrev = null;
2281
+ if ($intCntr > 0)
2282
+ $strPrev = $arrToks[$intCntr - 1];
2283
+ //$strNext = $arrToks[$intCntr + 1];
2284
+ if ($strPrev === null || $strPrev->isArithmeticOp || $strPrev->isLeftParen || $strPrev->isComma)
2285
+ {
2286
+ $strTok = Toolset_Tokenizer::$UNARY_NEGATIVE;
2287
+ }
2288
+ }
2289
+ if ($strTok->val=='+')
2290
+ {
2291
+ // check for unary + addition operator, we need to ignore this.
2292
+ $strPrev = null;
2293
+ if ($intCntr > 0)
2294
+ $strPrev = $arrToks[$intCntr - 1];
2295
+ //$strNext = $arrToks[$intCntr + 1];
2296
+ if ($strPrev === null || $strPrev->isArithmeticOp || $strPrev->isLeftParen || $strPrev->isComma)
2297
+ {
2298
+ break;
2299
+ }
2300
+ }
2301
+ $strTop = Toolset_Tokenizer::$EMPTY_TOKEN;
2302
+ if (!$myStack->IsEmpty()) $strTop = $myStack->Get(0);
2303
+ if ($myStack->IsEmpty() || (!$myStack->IsEmpty() && $strTop->isLeftParen))
2304
+ {
2305
+ $myStack->Push($strTok);
2306
+ }
2307
+ else if ($strTok->precedence >= $strTop->precedence)
2308
+ {
2309
+ $myStack->Push($strTok);
2310
+ }
2311
+ else
2312
+ {
2313
+ // Pop operators with precedence >= operator strTok
2314
+ while (!$myStack->IsEmpty())
2315
+ {
2316
+ $strTop = $myStack->Get(0);
2317
+ if ($strTop->isLeftParen || $strTop->precedence < $strTok->precedence)
2318
+ {
2319
+ break;
2320
+ }
2321
+ else
2322
+ {
2323
+ $arrPFix[$intIndex] = $myStack->Pop();
2324
+ $intIndex++;
2325
+ }
2326
+ }
2327
+ $myStack->Push($strTok);
2328
+ }
2329
+ break;
2330
+ }
2331
+ break;
2332
+ default :
2333
+ if ($strTok->type!=Toolset_Tokenizer::$TOKEN_TYPE['FUNCTION'])
2334
+ {
2335
+ $arrPFix[$intIndex] = $strTok;
2336
+ $intIndex++;
2337
+ }
2338
+ else
2339
+ {
2340
+ $strTop = Toolset_Tokenizer::$EMPTY_TOKEN;
2341
+ if (!$myStack->IsEmpty()) $strTop = $myStack->Get(0);
2342
+ if ($myStack->IsEmpty() || (!$myStack->IsEmpty() && $strTop->isLeftParen))
2343
+ {
2344
+ $myStack->Push($strTok);
2345
+ }
2346
+ else if ($strTok->precedence >= $strTop->precedence)
2347
+ {
2348
+ $myStack->Push($strTok);
2349
+ }
2350
+ else
2351
+ {
2352
+ // Pop operators with precedence >= operator in strTok
2353
+ while (!$myStack->IsEmpty())
2354
+ {
2355
+ $strTop = $myStack->Get(0);
2356
+ if ($strTop->val == "(" || $strTop->precedence < $strTok->precedence)
2357
+ {
2358
+ break;
2359
+ }
2360
+ else
2361
+ {
2362
+ $arrPFix[$intIndex] = $myStack->Pop();
2363
+ $intIndex++;
2364
+ }
2365
+ }
2366
+ $myStack->Push($strTok);
2367
+ }
2368
+ }
2369
+ break;
2370
+ }
2371
+ }
2372
+
2373
+ // Pop remaining operators from stack.
2374
+ while (!$myStack->IsEmpty())
2375
+ {
2376
+ $arrPFix[$intIndex] = $myStack->Pop();
2377
+ $intIndex++;
2378
+ }
2379
+ return $arrPFix;
2380
+ }
2381
+
2382
+ private function _AddNewVariable($varObj, &$varArr=null)
2383
+ {
2384
+ //cred_log($varObj);
2385
+ if (!isset($varArr))
2386
+ $varArr = &$this->arrVars;
2387
+
2388
+ if (!isset($varArr))
2389
+ $varArr = array();
2390
+
2391
+ $varName=$varObj['name'];
2392
+ $varToken=null;
2393
+ if (isset($varObj['withType']))
2394
+ {
2395
+ //cred_log($varObj['withType']);
2396
+ switch($varObj['withType'])
2397
+ {
2398
+ case 'boolean':
2399
+ $varToken=Toolset_Tokenizer::makeToken($varObj['val'],Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']);
2400
+ break;
2401
+ case 'number':
2402
+ $varToken=Toolset_Tokenizer::makeToken($varObj['val'],Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']);
2403
+ break;
2404
+ case 'array':
2405
+ $varToken=Toolset_Tokenizer::makeToken($varObj['val'],Toolset_Tokenizer::$TOKEN_TYPE['ARRAY']);
2406
+ break;
2407
+ case 'date':
2408
+ if (isset($varObj['format']))
2409
+ $format=$varObj['format'];
2410
+ else
2411
+ $format=$this->dtFormat;
2412
+ $varToken=Toolset_Tokenizer::makeToken(Toolset_DateParser::parseDate($varObj['val'], $format),Toolset_Tokenizer::$TOKEN_TYPE['DATE']);
2413
+ break;
2414
+ case 'string':
2415
+ default:
2416
+ //cred_log('STRING');
2417
+ //cred_log(Toolset_Tokenizer::$TOKEN_TYPE);
2418
+ $varToken=Toolset_Tokenizer::makeToken($varObj['val'],Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']/*, true*/);
2419
+ break;
2420
+ }
2421
+ }
2422
+ else
2423
+ $varToken=Toolset_Tokenizer::makeToken($varObj['val'],Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']);
2424
+
2425
+ //cred_log($varToken);
2426
+ $varArr[$varName] = $varToken;
2427
+ }
2428
+
2429
+ private function _dumpPostFix($pf)
2430
+ {
2431
+ $out='';
2432
+ for ($i=0; $i<count($pf); $i++)
2433
+ $out.=$pf[$i]->val.',';
2434
+ return $out;
2435
+ }
2436
+
2437
+ private function _clonePostFix($pf)
2438
+ {
2439
+ $newpf=array();
2440
+ for ($i=0; $i<count($pf); $i++)
2441
+ $newpf[$i]=Toolset_Tokenizer::cloneToken($pf[$i]);
2442
+ return $newpf;
2443
+ }
2444
+
2445
+ private function _ParseExpression()
2446
+ {
2447
+ $arrTokens = Toolset_Tokenizer::Tokanize($this->strInFix);
2448
+ if (!isset($arrTokens))
2449
+ throw new Exception("Unable to tokanize the expression!");
2450
+ if (count($arrTokens) <= 0)
2451
+ throw new Exception("Unable to tokanize the expression!");
2452
+
2453
+ //print_r($arrTokens);
2454
+
2455
+ $myarrPostFix = $this->_InFixToPostFix($arrTokens);
2456
+ if (!isset($myarrPostFix))
2457
+ throw new Exception("Unable to convert the expression to postfix form!");
2458
+ if (count($myarrPostFix) <= 0)
2459
+ throw new Exception("Unable to convert the expression to postfix form!");
2460
+ //print_r($myarrPostFix);
2461
+ return $myarrPostFix;
2462
+ }
2463
+
2464
+ private function _getVariable($strVarName, &$varArr=null)
2465
+ {
2466
+ if (!isset($varArr))
2467
+ $varArr=$this->arrVars;
2468
+
2469
+ if (!isset($varArr))
2470
+ throw new Exception("Variable values are not supplied!");
2471
+
2472
+ if (!isset($varArr[$strVarName]))
2473
+ throw new Exception("Variable [" . $strVarName . "] not defined");
2474
+
2475
+ //cred_log($varArr);
2476
+ return $varArr[$strVarName];
2477
+ }
2478
+
2479
+ // postfix function evaluator
2480
+ private function _EvaluateExpression(&$myarrPostFix, &$myvarArr)
2481
+ {
2482
+ if (!isset($myarrPostFix))
2483
+ $myarrPostFix=$this->_ParseExpression();
2484
+ if (count($myarrPostFix) == 0)
2485
+ throw new Exception("Unable to parse the expression!");
2486
+ if (!isset($myarrPostFix) || count($myarrPostFix)==0)
2487
+ {
2488
+ throw new Exception("Invalid postfix expression!");
2489
+ }
2490
+
2491
+ $intIndex = 0;
2492
+ $myStack = new Toolset_Stack();
2493
+
2494
+ //echo $this->_dumpPostFix($myarrPostFix);
2495
+
2496
+ while ($intIndex < count($myarrPostFix))
2497
+ {
2498
+ //echo $myStack->toString();
2499
+
2500
+ $strTok = $myarrPostFix[$intIndex];
2501
+ switch ($strTok->type)
2502
+ {
2503
+ case Toolset_Tokenizer::$TOKEN_TYPE['ARG_TERMINAL'] :
2504
+ $myStack->Push($strTok);
2505
+ break;
2506
+ case Toolset_Tokenizer::$TOKEN_TYPE['UNARY_NEGATIVE'] :
2507
+ if ($myStack->IsEmpty())
2508
+ throw new Exception("No operand to negate!");
2509
+
2510
+ $objOp1 = null;
2511
+ $objOp2 = null;
2512
+ $objOp1 = $myStack->Pop();
2513
+ if ($objOp1->isVariable)
2514
+ $objOp1 = $this->_getVariable($objOp1->val, $myvarArr);
2515
+
2516
+ $dblNo = Toolset_Tokenizer::toNumber($objOp1->val);
2517
+ if (is_nan($dblNo))
2518
+ throw new Exception("Not a numeric value!");
2519
+ else
2520
+ {
2521
+ $dblNo = (0 - $dblNo);
2522
+ $myStack->Push(Toolset_Tokenizer::makeToken($dblNo,Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
2523
+ }
2524
+ break;
2525
+ case Toolset_Tokenizer::$TOKEN_TYPE['UNARY_NEGATION'] :
2526
+ if ($myStack->IsEmpty())
2527
+ throw new Exception("No operand on stack!");
2528
+
2529
+ $objOp1 = null;
2530
+ $objOp2 = null;
2531
+ $objOp1 = $myStack->Pop();
2532
+ if ($objOp1->isVariable)
2533
+ $objOp1 = $this->_getVariable($objOp1->val, $myvarArr);
2534
+
2535
+ $objOp1 = Toolset_Tokenizer::toBoolean($objOp1->val);
2536
+ if ($objOp1 === null)
2537
+ throw new Exception($strTok->val . " applied not on a boolean value!");
2538
+ else
2539
+ $myStack->Push(Toolset_Tokenizer::makeToken(!($objOp1),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2540
+ break;
2541
+ case Toolset_Tokenizer::$TOKEN_TYPE['ARITHMETIC_OP'] :
2542
+ switch($strTok->val)
2543
+ {
2544
+ case "*" :
2545
+ case "/" :
2546
+ case "%" :
2547
+ case "^" :
2548
+ if ($myStack->IsEmpty() || $myStack->Size() < 2)
2549
+ throw new Exception("Stack is empty, can not perform [" . $strTok->val . "]");
2550
+ $objOp1 = null;
2551
+ $objOp2 = null;
2552
+ $objTmp = null;
2553
+ $objOp2 = $myStack->Pop();
2554
+ $objOp1 = $myStack->Pop();
2555
+ if ($objOp1->isVariable)
2556
+ $objOp1 = $this->_getVariable($objOp1->val, $myvarArr);
2557
+ if ($objOp2->isVariable)
2558
+ $objOp2 = $this->_getVariable($objOp2->val, $myvarArr);
2559
+
2560
+ if (!$objOp1->isNumber || !$objOp2->isNumber)
2561
+ throw new Exception("Either one of the operand is not a number can not perform [" . $strTok->val . "]");
2562
+
2563
+ $dblVal1 = Toolset_Tokenizer::toNumber($objOp1->val);
2564
+ $dblVal2 = Toolset_Tokenizer::toNumber($objOp2->val);
2565
+ if (is_nan($dblVal1) || is_nan($dblVal2))
2566
+ throw new Exception("Either one of the operand is not a number can not perform [" . $strTok->val . "]");
2567
+
2568
+ if ($strTok->val == "^")
2569
+ $myStack->Push(Toolset_Tokenizer::makeToken(pow($dblVal1, $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
2570
+ else if ($strTok->val == "*")
2571
+ $myStack->Push(Toolset_Tokenizer::makeToken(($dblVal1 * $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
2572
+ else if ($strTok->val == "/")
2573
+ $myStack->Push(Toolset_Tokenizer::makeToken(($dblVal1 / $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
2574
+ else
2575
+ $myStack->Push(Toolset_Tokenizer::makeToken(($dblVal1 % $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
2576
+ break;
2577
+ case "+" :
2578
+ case "-" :
2579
+ if ($myStack->IsEmpty() || $myStack->Size() < 2)
2580
+ throw new Exception("Stack is empty, can not perform [" . $strTok->val . "]");
2581
+
2582
+ $objOp1 = null;
2583
+ $objOp2 = null;
2584
+ $objTmp1 = null;
2585
+ $objTmp2 = null;
2586
+ $strOp = (($strTok->val == "+") ? "Addition" : "Substraction");
2587
+ $objOp2 = $myStack->Pop();
2588
+ $objOp1 = $myStack->Pop();
2589
+ if ($objOp1->isVariable)
2590
+ $objOp1 = $this->_getVariable($objOp1->val, $myvarArr);
2591
+ if ($objOp2->isVariable)
2592
+ $objOp2 = $this->_getVariable($objOp2->val, $myvarArr);
2593
+
2594
+ if ($objOp1->isNumber && $objOp2->isNumber)
2595
+ {
2596
+ // Number addition
2597
+ $dblVal1 = Toolset_Tokenizer::toNumber($objOp1->val);
2598
+ $dblVal2 = Toolset_Tokenizer::toNumber($objOp2->val);
2599
+ if ($strTok->val == "+")
2600
+ $myStack->Push(Toolset_Tokenizer::makeToken(($dblVal1 + $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
2601
+ else
2602
+ $myStack->Push(Toolset_Tokenizer::makeToken(($dblVal1 - $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['NUMBER']));
2603
+ }
2604
+ else if ($objOp1->isStringLiteral && $objOp2->isStringLiteral)
2605
+ {
2606
+ if ($strTok->val == "+")
2607
+ $myStack->Push(Toolset_Tokenizer::makeToken(($objOp1->val . $objOp2->val),Toolset_Tokenizer::$TOKEN_TYPE['STRING_LITERAL']));
2608
+ else
2609
+ throw new Exception($strOp . " not supported for strings!");
2610
+ }
2611
+ else
2612
+ throw new Exception($strOp . " not supported for other types than numbers and strings!");
2613
+ break;
2614
+ }
2615
+ break;
2616
+ case Toolset_Tokenizer::$TOKEN_TYPE['COMPARISON_OP'] :
2617
+ switch($strTok->val)
2618
+ {
2619
+ case "=" :
2620
+ case "<" :
2621
+ case ">" :
2622
+ case "<>" :
2623
+ case "<=" :
2624
+ case ">=" :
2625
+ case "eq" :
2626
+ case "lt" :
2627
+ case "gt" :
2628
+ case "ne" :
2629
+ case "lte" :
2630
+ case "gte" :
2631
+
2632
+ if ($myStack->IsEmpty() || $myStack->Size() < 2)
2633
+ throw new Exception("Stack is empty, can not perform [" . $strTok->val . "]");
2634
+ $objOp1 = null;
2635
+ $objOp2 = null;
2636
+ $objTmp1 = null;
2637
+ $objTmp2 = null;
2638
+ $objOp2 = $myStack->Pop();
2639
+ $objOp1 = $myStack->Pop();
2640
+ //cred_log(array($objOp1, $objOp2));
2641
+ if ($objOp1->isVariable)
2642
+ $objOp1 = $this->_getVariable($objOp1->val, $myvarArr);
2643
+ if ($objOp2->isVariable)
2644
+ $objOp2 = $this->_getVariable($objOp2->val, $myvarArr);
2645
+
2646
+ //cred_log(array($objOp1, $objOp2));
2647
+ if ($objOp1->isStringLiteral && $objOp2->isNumber)
2648
+ {
2649
+ $dblVal1 = (string)$objOp1->val;
2650
+ $dblVal2 = (string)$objOp2->val;
2651
+ }
2652
+ else if ($objOp1->isNumber && $objOp2->isStringLiteral)
2653
+ {
2654
+ $dblVal1 = (string)$objOp1->val;
2655
+ $dblVal2 = (string)$objOp2->val;
2656
+ }
2657
+ else if ($objOp1->isNumber && $objOp2->isNumber)
2658
+ {
2659
+ $dblVal1 = Toolset_Tokenizer::toNumber($objOp1->val);
2660
+ $dblVal2 = Toolset_Tokenizer::toNumber($objOp2->val);
2661
+ }
2662
+ else if ($objOp1->isNumber && $objOp2->isBoolean)
2663
+ {
2664
+ $dblVal1 = Toolset_Tokenizer::toNumber($objOp1->val);
2665
+ $dblVal2 = Toolset_Tokenizer::toNumber($objOp2->val);
2666
+ }
2667
+ else if ($objOp2->isNumber && $objOp1->isBoolean)
2668
+ {
2669
+ $dblVal1 = Toolset_Tokenizer::toNumber($objOp1->val);
2670
+ $dblVal2 = Toolset_Tokenizer::toNumber($objOp2->val);
2671
+ }
2672
+ else if ($objOp1->isDate && $objOp2->isDate)
2673
+ {
2674
+ $dblVal1 = $objOp1->val->getNormalizedTimestamp();
2675
+ $dblVal2 = $objOp2->val->getNormalizedTimestamp();
2676
+ }
2677
+ else if ($objOp1->isStringLiteral && $objOp2->isStringLiteral)
2678
+ {
2679
+ $dblVal1=(string)$objOp1->val;
2680
+ $dblVal2=(string)$objOp2->val;
2681
+ }
2682
+ else if ($objOp1->isBoolean && $objOp2->isBoolean)
2683
+ {
2684
+ if ($strTok->val == "=" || $strTok->val == "<>" || $strTok->val == "eq" || $strTok->val == "ne")
2685
+ {
2686
+ $dblVal1 = Toolset_Tokenizer::toBoolean($objOp1->val);
2687
+ $dblVal2 = Toolset_Tokenizer::toBoolean($objOp2->val);
2688
+ }
2689
+ else
2690
+ throw new Exception($strTok->val + " not supported for boolean values!");
2691
+ }
2692
+ else if (
2693
+ ($strTok->val=='=' || $strTok->val=='<>' || $strTok->val=='eq' || $strTok->val=='ne') &&
2694
+ ($objOp1->isStringLiteral && $objOp2->isRegex)
2695
+ )
2696
+ {
2697
+ if ($strTok->val=='=' || $strTok->val=='eq')
2698
+ $myStack->Push(Toolset_Tokenizer::makeToken(($objOp2->val->test((string)$objOp1->val)),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2699
+ else
2700
+ $myStack->Push(Toolset_Tokenizer::makeToken(!($objOp2->val->test((string)$objOp1->val)),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2701
+ break;
2702
+ }
2703
+ else if (
2704
+ ($strTok->val=='=' || $strTok->val=='<>' || $strTok->val=='eq' || $strTok->val=='ne') &&
2705
+ ($objOp2->isStringLiteral && $objOp1->isRegex)
2706
+ )
2707
+ {
2708
+ if ($strTok->val=='=' || $strTok->val=='eq')
2709
+ $myStack->Push(Toolset_Tokenizer::makeToken(($objOp1->val->test((string)$objOp2->val)),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2710
+ else
2711
+ $myStack->Push(Toolset_Tokenizer::makeToken(!($objOp1->val->test((string)$objOp2->val)),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2712
+ break;
2713
+ }
2714
+ else if (
2715
+ ($strTok->val=='=' || $strTok->val=='<>' || $strTok->val=='eq' || $strTok->val=='ne') &&
2716
+ ($objOp1->isArray && ($objOp2->isStringLiteral || $objOp2->isNumber))
2717
+ )
2718
+ {
2719
+ if ($strTok->val=='=' || $strTok->val=='eq')
2720
+ $myStack->Push(Toolset_Tokenizer::makeToken(Toolset_Functions::Contains($objOp1->val,$objOp2->val),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2721
+ else
2722
+ $myStack->Push(Toolset_Tokenizer::makeToken(!Toolset_Functions::Contains($objOp1->val,$objOp2->val),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2723
+ break;
2724
+ }
2725
+ else if (
2726
+ ($strTok->val=='=' || $strTok->val=='<>' || $strTok->val=='eq' || $strTok->val=='ne') &&
2727
+ ($objOp2->isArray && ($objOp1->isStringLiteral || $objOp1->isNumber))
2728
+ )
2729
+ {
2730
+ if ($strTok->val=='=' || $strTok->val=='eq')
2731
+ $myStack->Push(Toolset_Tokenizer::makeToken(Toolset_Functions::Contains($objOp2->val,$objOp1->val),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2732
+ else
2733
+ $myStack->Push(Toolset_Tokenizer::makeToken(!Toolset_Functions::Contains($objOp2->val,$objOp1->val),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2734
+ break;
2735
+ }
2736
+ else
2737
+ throw new Exception("For " . $strTok->val . " operator LHS & RHS should be of same data type!");
2738
+
2739
+ if ($strTok->val == "=" || $strTok->val == "eq")
2740
+ $myStack->Push(Toolset_Tokenizer::makeToken(($dblVal1 == $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2741
+ else if ($strTok->val == "<>" || $strTok->val == "ne")
2742
+ $myStack->Push(Toolset_Tokenizer::makeToken(($dblVal1 != $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2743
+ else if ($strTok->val == ">" || $strTok->val == "gt")
2744
+ $myStack->Push(Toolset_Tokenizer::makeToken(($dblVal1 > $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2745
+ else if ($strTok->val == "<" || $strTok->val == "lt")
2746
+ $myStack->Push(Toolset_Tokenizer::makeToken(($dblVal1 < $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2747
+ else if ($strTok->val == "<=" || $strTok->val == "lte")
2748
+ $myStack->Push(Toolset_Tokenizer::makeToken(($dblVal1 <= $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2749
+ else if ($strTok->val == ">=" || $strTok->val == "gte")
2750
+ $myStack->Push(Toolset_Tokenizer::makeToken(($dblVal1 >= $dblVal2),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2751
+ break;
2752
+ }
2753
+ break;
2754
+ case Toolset_Tokenizer::$TOKEN_TYPE['LOGICAL_OP'] :
2755
+ switch($strTok->val)
2756
+ {
2757
+ case 'NOT' :
2758
+ case '!' :
2759
+ if ($myStack->IsEmpty())
2760
+ throw new Exception("No operand on stack!");
2761
+
2762
+ $objOp1 = null;
2763
+ $objOp2 = null;
2764
+ $objOp1 = $myStack->Pop();
2765
+ if ($objOp1->isVariable)
2766
+ $objOp1 = $this->_getVariable($objOp1->val, $myvarArr);
2767
+
2768
+ $objOp1 = Toolset_Tokenizer::toBoolean($objOp1->val);
2769
+ if ($objOp1 === null)
2770
+ throw new Exception($strTok->val . " applied not on a boolean value!");
2771
+ else
2772
+ $myStack->Push(Toolset_Tokenizer::makeToken(!($objOp1),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2773
+ break;
2774
+ case "AND" :
2775
+ case "&" :
2776
+ case "OR" :
2777
+ case "|" :
2778
+ if ($myStack->IsEmpty() || $myStack->Size() < 2)
2779
+ throw new Exception("Stack is empty, can not perform [" . $strTok->val . "]");
2780
+ $objOp1 = null;
2781
+ $objOp2 = null;
2782
+ $objTmp1 = null;
2783
+ $objTmp2 = null;
2784
+ $objOp2 = $myStack->Pop();
2785
+ $objOp1 = $myStack->Pop();
2786
+ if ($objOp1->isVariable)
2787
+ $objOp1 = $this->_getVariable($objOp1->val, $myvarArr);
2788
+ if ($objOp2->isVariable)
2789
+ $objOp2 = $this->_getVariable($objOp2->val, $myvarArr);
2790
+
2791
+ if (
2792
+ ($objOp1->isBoolean && $objOp2->isBoolean) ||
2793
+ ($objOp1->isNumber && $objOp2->isNumber) ||
2794
+ ($objOp1->isNumber && $objOp2->isBoolean) ||
2795
+ ($objOp1->isBoolean && $objOp2->isNumber)
2796
+ )
2797
+ {
2798
+ $objTmp1 = Toolset_Tokenizer::toBoolean($objOp1->val);
2799
+ $objTmp2 = Toolset_Tokenizer::toBoolean($objOp2->val);
2800
+ if ($strTok->val == "AND" || $strTok->val == "&")
2801
+ $myStack->Push(Toolset_Tokenizer::makeToken(($objTmp1 && $objTmp2),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2802
+ else if ($strTok->val == "OR" || $strTok->val == "|")
2803
+ $myStack->Push(Toolset_Tokenizer::makeToken(($objTmp1 || $objTmp2),Toolset_Tokenizer::$TOKEN_TYPE['BOOLEAN']));
2804
+ }
2805
+ else
2806
+ throw new Exception("Logical operator requires LHS & RHS of boolean type!");
2807
+ break;
2808
+ }
2809
+ break;
2810
+ case Toolset_Tokenizer::$TOKEN_TYPE['FUNCTION'] :
2811
+ $this->_HandleFunctions($strTok, $myStack, $this->dtFormat, $myvarArr);
2812
+ break;
2813
+ default :
2814
+ $myStack->Push($strTok);
2815
+ break;
2816
+ }
2817
+ $intIndex++;
2818
+
2819
+ //echo (string)$myStack->toString();
2820
+ }
2821
+ if ($myStack->IsEmpty() || $myStack->Size() > 1 || $myStack->Get(0)->isVariable)
2822
+ throw new Exception("Unable to evaluate expression!");
2823
+ else
2824
+ return $myStack->Pop()->val;
2825
+ }
2826
+
2827
+ // delegate here
2828
+ public static function setParams($params)
2829
+ {
2830
+ Toolset_Functions::setParams((array)$params);
2831
+ }
2832
+
2833
+ public function Toolset_Parser($exp=null)
2834
+ {
2835
+ if (isset($exp) && $exp!==null)
2836
+ {
2837
+ $this->strInFix = $exp;
2838
+ $this->arrTokens=$this->arrPostFix=null;
2839
+ }
2840
+ // init tokenizer here, else tokens become undefined on addVar
2841
+ Toolset_Tokenizer::init();
2842
+ }
2843
+
2844
+ public function dateLocales($a=null,$b=null,$c=null)
2845
+ {
2846
+ Toolset_DateParser::setDateLocaleStrings($a,$b,$c);
2847
+ return $this;
2848
+ }
2849
+
2850
+ public function dateFormat($df)
2851
+ {
2852
+ $this->dtFormat = $df;
2853
+ return $this;
2854
+ }
2855
+
2856
+ public function expression($exp)
2857
+ {
2858
+ $this->strInFix = $exp;
2859
+ $this->arrTokens=$this->arrPostFix=null;
2860
+ return $this;
2861
+ }
2862
+
2863
+ public function addVar($_var)
2864
+ {
2865
+ $this->_AddNewVariable($_var, $this->arrVars);
2866
+ return $this;
2867
+ }
2868
+
2869
+ public function parse()
2870
+ {
2871
+ $this->arrPostFix=$this->_ParseExpression();
2872
+ return $this->_dumpPostFix($this->arrPostFix);
2873
+ }
2874
+
2875
+ public function evaluate()
2876
+ {
2877
+ return $this->_EvaluateExpression($this->arrPostFix, $this->arrVars);
2878
+ }
2879
+
2880
+ public function reset()
2881
+ {
2882
+ $this->arrVars = array();
2883
+ $this->strInFix=$this->arrTokens=$this->arrPostFix=null;
2884
+ return $this;
2885
+ }
2886
+
2887
+ public function dump()
2888
+ {
2889
+ return $this->_dumpPostFix($this->arrPostFix);
2890
+ }
2891
+ //this.preCompile = function(_exp){if (typeof(_exp)=='undefined') _exp=strInFix; return _getPrecompiledExpression(_exp);};
2892
+ }
embedded/common/functions.php ADDED
@@ -0,0 +1,671 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Common functions.
4
+ */
5
+ define( 'ICL_COMMON_FUNCTIONS', true );
6
+
7
+ /**
8
+ * Calculates relative path for given file.
9
+ *
10
+ * @param type $file Absolute path to file
11
+ * @return string Relative path
12
+ */
13
+ function icl_get_file_relpath( $file ) {
14
+ $is_https = isset( $_SERVER['HTTPS'] ) && strtolower( $_SERVER['HTTPS'] ) == 'on';
15
+ $http_protocol = $is_https ? 'https' : 'http';
16
+ $base_root = $http_protocol . '://' . $_SERVER['HTTP_HOST'];
17
+ $base_url = $base_root;
18
+ $dir = rtrim( dirname( $file ), '\/' );
19
+ if ( $dir ) {
20
+ $base_path = $dir;
21
+ $base_url .= $base_path;
22
+ $base_path .= '/';
23
+ } else {
24
+ $base_path = '/';
25
+ }
26
+ $relpath = $base_root
27
+ . str_replace(
28
+ str_replace( '\\', '/',
29
+ realpath( $_SERVER['DOCUMENT_ROOT'] ) )
30
+ , '', str_replace( '\\', '/', dirname( $file ) )
31
+ );
32
+ return $relpath;
33
+ }
34
+
35
+ /**
36
+ * Fix WP's multiarray parsing.
37
+ *
38
+ * @param type $arg
39
+ * @param type $defaults
40
+ * @return type
41
+ */
42
+ function wpv_parse_args_recursive( $arg, $defaults ) {
43
+ $temp = false;
44
+ if ( isset( $arg[0] ) ) {
45
+ $temp = $arg[0];
46
+ } else if ( isset( $defaults[0] ) ) {
47
+ $temp = $defaults[0];
48
+ }
49
+ $arg = wp_parse_args( $arg, $defaults );
50
+ if ( $temp ) {
51
+ $arg[0] = $temp;
52
+ }
53
+ foreach ( $defaults as $default_setting_parent => $default_setting ) {
54
+ if ( !is_array( $default_setting ) ) {
55
+ if ( !isset( $arg[$default_setting_parent] ) ) {
56
+ $arg[$default_setting_parent] = $default_setting;
57
+ }
58
+ continue;
59
+ }
60
+ if ( !isset( $arg[$default_setting_parent] ) ) {
61
+ $arg[$default_setting_parent] = $defaults[$default_setting_parent];
62
+ }
63
+ $arg[$default_setting_parent] = wpv_parse_args_recursive( $arg[$default_setting_parent],
64
+ $defaults[$default_setting_parent] );
65
+ }
66
+
67
+ return $arg;
68
+ }
69
+
70
+ /*
71
+ * Extra check for date for shortcode in shortcode. Called as filter in wpv_condition bellow.
72
+ */
73
+
74
+ function wpv_add_time_functions( $value ) {
75
+ return wpv_filter_parse_date( $value );
76
+ }
77
+
78
+ /**
79
+ * Condition function to evaluate and display given block based on expressions
80
+ * 'args' => arguments for evaluation fields
81
+ *
82
+ * Supported actions and symbols:
83
+ *
84
+ * Integer and floating-point numbers
85
+ * Math operators: +, -, *, /
86
+ * Comparison operators: &lt;, &gt;, =, &lt;=, &gt;=, !=
87
+ * Boolean operators: AND, OR, NOT
88
+ * Nested expressions - several levels of brackets
89
+ * Variables defined as shortcode parameters starting with a dollar sign
90
+ * empty() function that checks for blank or non-existing fields
91
+ *
92
+ *
93
+ */
94
+ function wpv_condition( $atts, $post_to_check = null ) {
95
+ extract(
96
+ shortcode_atts( array('evaluate' => FALSE), $atts )
97
+ );
98
+
99
+ // Do not overwrite global post
100
+ // global $post;
101
+
102
+ // if in admin, get the post from the URL
103
+ if ( is_admin() ) {
104
+ if ( empty($post_to_check->ID) ) {
105
+ // Get post
106
+ if ( isset( $_GET['post'] ) ) {
107
+ $post_id = (int) $_GET['post'];
108
+ } else if ( isset( $_POST['post_ID'] ) ) {
109
+ $post_id = (int) $_POST['post_ID'];
110
+ } else {
111
+ $post_id = 0;
112
+ }
113
+ if ( $post_id ) {
114
+ $post = get_post( $post_id );
115
+ }
116
+ } else {
117
+ $post = $post_to_check;
118
+ }
119
+ }
120
+ if ( empty($post->ID) ) {
121
+ global $post;
122
+ }
123
+ $has_post = true;
124
+ if ( empty($post->ID) ) {
125
+ // Will not execute any condition that involves custom fields
126
+ $has_post = false;
127
+ }
128
+
129
+ global $wplogger;
130
+
131
+ if ( $has_post ) {
132
+ do_action( 'wpv_condition', $post );
133
+ }
134
+
135
+ $logging_string = "Original expression: " . $evaluate;
136
+
137
+ add_filter( 'wpv-extra-condition-filters', 'wpv_add_time_functions' );
138
+ $evaluate = apply_filters( 'wpv-extra-condition-filters', $evaluate );
139
+
140
+ // evaluate empty() statements for variables
141
+ if ( $has_post ) {
142
+ $empties = preg_match_all( "/empty\(\s*\\$(\w+)\s*\)/", $evaluate, $matches );
143
+ if ( $empties && $empties > 0 ) {
144
+ for ( $i = 0; $i < $empties; $i++ ) {
145
+ $match_var = get_post_meta( $post->ID, $atts[$matches[1][$i]], true );
146
+ $is_empty = '1=0';
147
+
148
+ // mark as empty only nulls and ""
149
+ // if ( is_null( $match_var ) || strlen( $match_var ) == 0 ) {
150
+ if ( is_null( $match_var )
151
+ || ( is_string( $match_var ) && strlen( $match_var ) == 0 )
152
+ || ( is_array( $match_var ) && empty( $match_var ) ) ) {
153
+ $is_empty = '1=1';
154
+ }
155
+
156
+ $evaluate = str_replace( $matches[0][$i], $is_empty, $evaluate );
157
+ }
158
+ }
159
+ }
160
+
161
+ // find variables that are to be used as strings.
162
+ // eg '$f1'
163
+ // will replace $f1 with the actual field value
164
+ if ( $has_post ) {
165
+ $strings_count = preg_match_all( '/(\'[\$\w^\']*\')/', $evaluate, $matches );
166
+ if ( $strings_count && $strings_count > 0 ) {
167
+ for ( $i = 0; $i < $strings_count; $i++ ) {
168
+ $string = $matches[1][$i];
169
+ // remove single quotes from string literals to get value only
170
+ $string = (strpos( $string, '\'' ) === 0) ? substr( $string, 1,
171
+ strlen( $string ) - 2 ) : $string;
172
+ if ( strpos( $string, '$' ) === 0 ) {
173
+ $variable_name = substr( $string, 1 ); // omit dollar sign
174
+ if ( isset( $atts[$variable_name] ) ) {
175
+ $string = get_post_meta( $post->ID, $atts[$variable_name],
176
+ true );
177
+ $evaluate = str_replace( $matches[1][$i],
178
+ "'" . $string . "'", $evaluate );
179
+ }
180
+ }
181
+ }
182
+ }
183
+ }
184
+
185
+ // find string variables and evaluate
186
+ $strings_count = preg_match_all( '/((\$\w+)|(\'[^\']*\'))\s*([\!<>\=]+)\s*((\$\w+)|(\'[^\']*\'))/',
187
+ $evaluate, $matches );
188
+
189
+ // get all string comparisons - with variables and/or literals
190
+ if ( $strings_count && $strings_count > 0 ) {
191
+ for ( $i = 0; $i < $strings_count; $i++ ) {
192
+
193
+ // get both sides and sign
194
+ $first_string = $matches[1][$i];
195
+ $second_string = $matches[5][$i];
196
+ $math_sign = $matches[4][$i];
197
+
198
+ // remove single quotes from string literals to get value only
199
+ $first_string = (strpos( $first_string, '\'' ) === 0) ? substr( $first_string,
200
+ 1, strlen( $first_string ) - 2 ) : $first_string;
201
+ $second_string = (strpos( $second_string, '\'' ) === 0) ? substr( $second_string,
202
+ 1, strlen( $second_string ) - 2 ) : $second_string;
203
+
204
+ // replace variables with text representation
205
+ if ( strpos( $first_string, '$' ) === 0 && $has_post ) {
206
+ $variable_name = substr( $first_string, 1 ); // omit dollar sign
207
+ if ( isset( $atts[$variable_name] ) ) {
208
+ $first_string = get_post_meta( $post->ID,
209
+ $atts[$variable_name], true );
210
+ } else {
211
+ $first_string = '';
212
+ }
213
+ }
214
+ if ( strpos( $second_string, '$' ) === 0 && $has_post ) {
215
+ $variable_name = substr( $second_string, 1 );
216
+ if ( isset( $atts[$variable_name] ) ) {
217
+ $second_string = get_post_meta( $post->ID,
218
+ $atts[$variable_name], true );
219
+ } else {
220
+ $second_string = '';
221
+ }
222
+ }
223
+
224
+ // don't do string comparison if variables are numbers
225
+ if ( !(is_numeric( $first_string ) && is_numeric( $second_string )) ) {
226
+ // compare string and return true or false
227
+ $compared_str_result = wpv_compare_strings( $first_string,
228
+ $second_string, $math_sign );
229
+
230
+ if ( $compared_str_result ) {
231
+ $evaluate = str_replace( $matches[0][$i], '1=1', $evaluate );
232
+ } else {
233
+ $evaluate = str_replace( $matches[0][$i], '1=0', $evaluate );
234
+ }
235
+ } else {
236
+ $evaluate = str_replace( $matches[1][$i], $first_string,
237
+ $evaluate );
238
+ $evaluate = str_replace( $matches[5][$i], $second_string,
239
+ $evaluate );
240
+ }
241
+ }
242
+ }
243
+
244
+ // find remaining strings that maybe numeric values.
245
+ // This handles 1='1'
246
+ $strings_count = preg_match_all( '/(\'[^\']*\')/', $evaluate, $matches );
247
+ if ( $strings_count && $strings_count > 0 ) {
248
+ for ( $i = 0; $i < $strings_count; $i++ ) {
249
+ $string = $matches[1][$i];
250
+ // remove single quotes from string literals to get value only
251
+ $string = (strpos( $string, '\'' ) === 0) ? substr( $string, 1,
252
+ strlen( $string ) - 2 ) : $string;
253
+ if ( is_numeric( $string ) ) {
254
+ $evaluate = str_replace( $matches[1][$i], $string, $evaluate );
255
+ }
256
+ }
257
+ }
258
+
259
+
260
+ // find all variable placeholders in expression
261
+ if ( $has_post ) {
262
+ $count = preg_match_all( '/\$(\w+)/', $evaluate, $matches );
263
+
264
+ $logging_string .= "; Variable placeholders: " . var_export( $matches[1],
265
+ true );
266
+
267
+ // replace all variables with their values listed as shortcode parameters
268
+ if ( $count && $count > 0 ) {
269
+ // sort array by length desc, fix str_replace incorrect replacement
270
+ $matches[1] = wpv_sort_matches_by_length( $matches[1] );
271
+
272
+ foreach ( $matches[1] as $match ) {
273
+ if ( isset( $atts[$match] ) ) {
274
+ $meta = get_post_meta( $post->ID, $atts[$match], true );
275
+ if ( empty( $meta ) ) {
276
+ $meta = "0";
277
+ }
278
+ } else {
279
+ $meta = "0";
280
+ }
281
+ $evaluate = str_replace( '$' . $match, $meta, $evaluate );
282
+ }
283
+ }
284
+ }
285
+
286
+ $logging_string .= "; End evaluated expression: " . $evaluate;
287
+
288
+ $wplogger->log( $logging_string, WPLOG_DEBUG );
289
+ // evaluate the prepared expression using the custom eval script
290
+ $result = wpv_evaluate_expression( $evaluate );
291
+
292
+ if ( $has_post ) {
293
+ do_action( 'wpv_condition_end', $post );
294
+ }
295
+
296
+ // return true, false or error string to the conditional caller
297
+ return $result;
298
+ }
299
+
300
+ function wpv_eval_check_syntax( $code ) {
301
+ return @eval( 'return true;' . $code );
302
+ }
303
+
304
+ /**
305
+ *
306
+ * Sort matches array by length so evaluate longest variable names first
307
+ *
308
+ * Otherwise the str_replace would break a field named $f11 if there is another field named $f1
309
+ *
310
+ * @param array $matches all variable names
311
+ */
312
+ function wpv_sort_matches_by_length( $matches ) {
313
+ $length = count( $matches );
314
+ for ( $i = 0; $i < $length; $i++ ) {
315
+ $max = strlen( $matches[$i] );
316
+ $max_index = $i;
317
+
318
+ // find the longest variable
319
+ for ( $j = $i + 1; $j < $length; $j++ ) {
320
+ if ( strlen( $matches[$j] ) > $max ) {
321
+ $max = $matches[$j];
322
+ $max_index = $j;
323
+ }
324
+ }
325
+
326
+ // swap
327
+ $temp = $matches[$i];
328
+ $matches[$i] = $matches[$max_index];
329
+ $matches[$max_index] = $temp;
330
+ }
331
+
332
+ return $matches;
333
+
334
+ }
335
+
336
+ /**
337
+ * Boolean function for string comparison
338
+ *
339
+ * @param string $first first string to be compared
340
+ * @param string $second second string for comparison
341
+ *
342
+ *
343
+ */
344
+ function wpv_compare_strings( $first, $second, $sign ) {
345
+ // get comparison results
346
+ $comparison = strcmp( $first, $second );
347
+
348
+ // verify cases 'less than' and 'less than or equal': <, <=
349
+ if ( $comparison < 0 && ($sign == '<' || $sign == '<=') ) {
350
+ return true;
351
+ }
352
+
353
+ // verify cases 'greater than' and 'greater than or equal': >, >=
354
+ if ( $comparison > 0 && ($sign == '>' || $sign == '>=') ) {
355
+ return true;
356
+ }
357
+
358
+ // verify equal cases: =, <=, >=
359
+ if ( $comparison == 0 && ($sign == '=' || $sign == '<=' || $sign == '>=') ) {
360
+ return true;
361
+ }
362
+
363
+ // verify != case
364
+ if ( $comparison != 0 && $sign == '!=' ) {
365
+ return true;
366
+ }
367
+
368
+ // or result is incorrect
369
+ return false;
370
+ }
371
+
372
+ /**
373
+ *
374
+ * Function that prepares the expression and calls eval()
375
+ * Validates the input for a list of whitechars and handles internal errors if any
376
+ *
377
+ * @param string $expression the expression to be evaluated
378
+ */
379
+ function wpv_evaluate_expression( $expression ){
380
+ //Replace AND, OR, ==
381
+ $expression = strtoupper( $expression );
382
+ $expression = str_replace( "AND", "&&", $expression );
383
+ $expression = str_replace( "OR", "||", $expression );
384
+ $expression = str_replace( "NOT", "!", $expression );
385
+ $expression = str_replace( "=", "==", $expression );
386
+ $expression = str_replace( "<==", "<=", $expression );
387
+ $expression = str_replace( ">==", ">=", $expression );
388
+ $expression = str_replace( "!==", "!=", $expression ); // due to the line above
389
+ // validate against allowed input characters
390
+ $count = preg_match( '/[0-9+-\=\*\/<>&\!\|\s\(\)]+/', $expression, $matches );
391
+
392
+ // find out if there is full match for the entire expression
393
+ if ( $count > 0 ) {
394
+ if ( strlen( $matches[0] ) == strlen( $expression ) ) {
395
+ $valid_eval = wpv_eval_check_syntax( "return $expression;" );
396
+ if ( $valid_eval ) {
397
+ return eval( "return $expression;" );
398
+ } else {
399
+ return __( "Error while parsing the evaluate expression",
400
+ 'wpv-views' );
401
+ }
402
+ } else {
403
+ return __( "Conditional expression includes illegal characters",
404
+ 'wpv-views' );
405
+ }
406
+ } else {
407
+ return __( "Correct conditional expression has not been found",
408
+ 'wpv-views' );
409
+ }
410
+
411
+ }
412
+
413
+ /**
414
+ * class WPV_wpcf_switch_post_from_attr_id
415
+ *
416
+ * This class handles the "id" attribute in a wpv-post-xxxxx shortcode
417
+ * and sets the global $id, $post, and $authordata
418
+ *
419
+ * It also handles types. eg [types field='my-field' id='233']
420
+ *
421
+ * id can be a integer to refer directly to a post
422
+ * id can be $parent to refer to the parent
423
+ * id can be $current_page or refer to the current page
424
+ *
425
+ * id can also refer to a related post type
426
+ * eg. for a stay the related post types could be guest and room
427
+ * [types field='my-field' id='$guest']
428
+ * [types field='my-field' id='$room']
429
+ */
430
+ class WPV_wpcf_switch_post_from_attr_id
431
+ {
432
+
433
+ function __construct( $atts ){
434
+ $this->found = false;
435
+
436
+ if ( isset( $atts['id'] ) ) {
437
+
438
+ global $post, $authordata, $id, $WPV_wpcf_post_relationship;
439
+
440
+ $post_id = 0;
441
+
442
+ if ( strpos( $atts['id'], '$' ) === 0 ) {
443
+ // Handle the parent if the id is $parent
444
+ if ( $atts['id'] == '$parent' && isset( $post->post_parent ) ) {
445
+ $post_id = $post->post_parent;
446
+ } else if ( $atts['id'] == '$current_page' ) {
447
+ if ( is_single() || is_page() ) {
448
+ global $wp_query;
449
+
450
+ if ( isset( $wp_query->posts[0] ) ) {
451
+ $current_post = $wp_query->posts[0];
452
+ $post_id = $current_post->ID;
453
+ }
454
+ }
455
+ } else {
456
+ // See if Views has the variable
457
+ global $WP_Views;
458
+ if ( isset( $WP_Views ) ) {
459
+ $post_id = $WP_Views->get_variable( $atts['id'] . '_id' );
460
+ }
461
+ if ( $post_id == 0 ) {
462
+ // Try the local storage.
463
+ if ( isset( $WPV_wpcf_post_relationship[$atts['id'] . '_id'] ) ) {
464
+ $post_id = $WPV_wpcf_post_relationship[$atts['id'] . '_id'];
465
+ }
466
+ }
467
+ }
468
+ } else {
469
+ $post_id = intval( $atts['id'] );
470
+ }
471
+
472
+ if ( $post_id > 0 ) {
473
+
474
+ $this->found = true;
475
+
476
+ // save original post
477
+ $this->post = isset( $post ) ? clone $post : null;
478
+ if ( $authordata ) {
479
+ $this->authordata = clone $authordata;
480
+ } else {
481
+ $this->authordata = null;
482
+ }
483
+ $this->id = $id;
484
+
485
+ // set the global post values
486
+ $id = $post_id;
487
+ $post = get_post( $id );
488
+ $authordata = new WP_User( $post->post_author );
489
+ }
490
+ }
491
+
492
+ }
493
+
494
+ function __destruct(){
495
+ if ( $this->found ) {
496
+ global $post, $authordata, $id;
497
+
498
+ // restore the global post values.
499
+ $post = isset( $this->post ) ? clone $this->post : null;
500
+ if ( $this->authordata ) {
501
+ $authordata = clone $this->authordata;
502
+ } else {
503
+ $authordata = null;
504
+ }
505
+ $id = $this->id;
506
+ }
507
+
508
+ }
509
+
510
+ }
511
+
512
+ // Add a filter on the content so that we can record any related posts.
513
+ // These can then be used ine id of Types and Views shortcodes
514
+ // eg. for a stay we can have
515
+ // [types field='my-field' id="$room"] displays my-field from the related room
516
+ // [wpv-post-title id="$room"] display the title of the related room
517
+
518
+ add_filter( 'the_content', 'WPV_wpcf_record_post_relationship_belongs', 0, 1 );
519
+
520
+ $WPV_wpcf_post_relationship = Array();
521
+
522
+ function WPV_wpcf_record_post_relationship_belongs( $content ) {
523
+
524
+ global $post, $WPV_wpcf_post_relationship;
525
+ static $related = array();
526
+
527
+ if ( !empty( $post->ID ) && function_exists( 'wpcf_pr_get_belongs' ) ) {
528
+
529
+ if ( !isset( $related[$post->post_type] ) ) {
530
+ $related[$post->post_type] = wpcf_pr_get_belongs( $post->post_type );
531
+ }
532
+ if ( is_array( $related[$post->post_type] ) ) {
533
+ foreach ( $related[$post->post_type] as $post_type => $data ) {
534
+ $related_id = wpcf_pr_post_get_belongs( $post->ID, $post_type );
535
+ if ( $related_id ) {
536
+ $WPV_wpcf_post_relationship['$' . $post_type . '_id'] = $related_id;
537
+ } else {
538
+ $WPV_wpcf_post_relationship['$' . $post_type . '_id'] = 0;
539
+ }
540
+ }
541
+ }
542
+ }
543
+
544
+
545
+ return $content;
546
+ }
547
+
548
+ /**
549
+ * Form for Enlimbo calls for wpv-control shortcode calls
550
+ *
551
+ * @param unknown_type $elements
552
+ */
553
+ function wpv_form_control( $elements ) {
554
+ static $form = NULL;
555
+ require_once 'classes/control_forms.php';
556
+ if ( is_null( $form ) ) {
557
+ $form = new Enlimbo_Control_Forms();
558
+ }
559
+ return $form->renderElements( $elements );
560
+ }
561
+
562
+ /**
563
+ * Dismiss message.
564
+ *
565
+ * @param type $message_id
566
+ * @param string $message
567
+ * @param type $class
568
+ */
569
+ function wpv_add_dismiss_message( $message_id, $message,
570
+ $clear_dismissed = false, $class = 'updated' ) {
571
+ $dismissed_messages = get_option( 'wpv-dismissed-messages', array() );
572
+ if ( $clear_dismissed ) {
573
+ if ( isset( $dismissed_messages[$message_id] ) ) {
574
+ unset( $dismissed_messages[$message_id] );
575
+ update_option( 'wpv-dismissed-messages', $dismissed_messages );
576
+ }
577
+ }
578
+ if ( !array_key_exists( $message_id, $dismissed_messages ) ) {
579
+ $message = $message . '<div style="float:right; margin:-15px 0 0 15px;"><a onclick="jQuery(this).parent().parent().fadeOut();jQuery.get(\''
580
+ . admin_url( 'admin-ajax.php?action=wpv_dismiss_message&amp;message_id='
581
+ . $message_id . '&amp;_wpnonce='
582
+ . wp_create_nonce( 'dismiss_message' ) ) . '\');return false;"'
583
+ . 'class="button-secondary" href="javascript:void(0);">'
584
+ . __( "Don't show this message again", 'wpv-views' ) . '</a></div>';
585
+ wpv_admin_message_store( $message_id, $message, false );
586
+ }
587
+ }
588
+
589
+ add_action( 'wp_ajax_wpv_dismiss_message', 'wpv_dismiss_message_ajax' );
590
+
591
+ /**
592
+ * Dismiss message AJAX.
593
+ */
594
+ function wpv_dismiss_message_ajax() {
595
+ if ( isset( $_GET['message_id'] ) && isset( $_GET['_wpnonce'] )
596
+ && wp_verify_nonce( $_GET['_wpnonce'], 'dismiss_message' ) ) {
597
+ $dismissed_messages = get_option( 'wpv-dismissed-messages', array() );
598
+ $dismissed_image_val = isset( $_GET['timestamp'] ) ? $_GET['timestamp'] : 1;
599
+ $dismissed_messages[strval( $_GET['message_id'] )] = $dismissed_image_val;
600
+ update_option( 'wpv-dismissed-messages', $dismissed_messages );
601
+ }
602
+ die( 'ajax' );
603
+ }
604
+
605
+ // disable the admin messages for now. They are causing problems.
606
+ //add_action('admin_head', 'wpv_show_admin_messages');
607
+
608
+ /**
609
+ * Shows stored admin messages.
610
+ */
611
+ function wpv_show_admin_messages() {
612
+ $messages = get_option( 'wpv-messages', array() );
613
+ $dismissed_messages = get_option( 'wpv-dismissed-messages', array() );
614
+ foreach ( $messages as $message_id => $message ) {
615
+ if ( array_key_exists( $message_id, $dismissed_messages ) ) {
616
+ unset( $messages[$message_id] );
617
+ continue;
618
+ }
619
+ // update the nonce
620
+ $text = $message['message'];
621
+ $nonce = preg_match_all( "/_wpnonce=[^']+/", $text, $matches );
622
+
623
+ if ( $nonce ) {
624
+ $text = str_replace( $matches[0][0],
625
+ '_wpnonce=' . wp_create_nonce( 'dismiss_message' ), $text );
626
+ }
627
+
628
+ wpv_admin_message( $message_id, $text, $message['class'] );
629
+ if ( $show_once ) {
630
+ unset( $messages[$message_id] );
631
+ }
632
+ }
633
+ update_option( 'wpv-messages', $messages );
634
+ }
635
+
636
+ /**
637
+ * Stores admin messages.
638
+ *
639
+ * @param type $message_id
640
+ * @param type $message
641
+ * @param type $show_once
642
+ * @param type $class
643
+ */
644
+ function wpv_admin_message_store( $message_id, $message, $show_once = true,
645
+ $class = 'updated' ) {
646
+ $messages = get_option( 'wpv-messages', array() );
647
+ $messages[strval( $message_id )] = array(
648
+ 'message' => strval( $message ),
649
+ 'class' => strval( $class ),
650
+ 'show_once' => $show_once,
651
+ );
652
+ update_option( 'wpv-messages', $messages );
653
+ }
654
+
655
+ /**
656
+ * Shows admin message.
657
+ *
658
+ * @param type $message_id
659
+ * @param type $message
660
+ * @param type $class
661
+ */
662
+ function wpv_admin_message( $message_id, $message, $class = 'updated' ) {
663
+ if ( apply_filters( 'wpv-show-message', true, $message_id ) ) {
664
+ add_action( 'admin_notices',
665
+ create_function( '$a=1, $message_id=\'' . strval( $message_id )
666
+ . '\', $class=\'' . strval( $class )
667
+ . '\', $message=\''
668
+ . htmlentities( strval( $message ), ENT_QUOTES ) . '\'',
669
+ '$screen = get_current_screen(); if (!$screen->is_network) echo "<div class=\"message $class\" id=\"wpv-message-$message_id\"><p>" . html_entity_decode($message, ENT_QUOTES) . "</p></div>";' ) );
670
+ }
671
+ }
embedded/common/localization/locale/orig/views.po ADDED
@@ -0,0 +1,4528 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file was generated by WPML
2
+ # WPML is a WordPress plugin that can turn any WordPress site into a full featured multilingual content management system.
3
+ # https://wpml.org
4
+ msgid ""
5
+ msgstr ""
6
+ "Content-Type: text/plain; charset=utf-8\n"
7
+ "Content-Transfer-Encoding: 8bit\n"
8
+ "Project-Id-Version: \n"
9
+ "POT-Creation-Date: \n"
10
+ "PO-Revision-Date: \n"
11
+ "Last-Translator: \n"
12
+ "Language-Team: \n"
13
+ "MIME-Version: 1.0\n"
14
+
15
+ msgid "Required"
16
+ msgstr ""
17
+
18
+ msgid "Email"
19
+ msgstr ""
20
+
21
+ msgid "Date"
22
+ msgstr ""
23
+
24
+ msgid "Digits"
25
+ msgstr ""
26
+
27
+ msgid "Numeric"
28
+ msgstr ""
29
+
30
+ msgid "You must define the $operator parameter for Wpcf_Cake_Validation::comparison()"
31
+ msgstr ""
32
+
33
+ msgid "You must define a regular expression for Wpcf_Cake_Validation::custom()"
34
+ msgstr ""
35
+
36
+ msgid "Could not find %s class, unable to complete validation."
37
+ msgstr ""
38
+
39
+ msgid "Method %s does not exist on %s unable to complete validation."
40
+ msgstr ""
41
+
42
+ msgid "Error while parsing the evaluate expression"
43
+ msgstr ""
44
+
45
+ msgid "Conditional expression includes illegal characters"
46
+ msgstr ""
47
+
48
+ msgid "Correct conditional expression has not been found"
49
+ msgstr ""
50
+
51
+ msgid "Don't show this message again"
52
+ msgstr ""
53
+
54
+ msgid "Clear"
55
+ msgstr ""
56
+
57
+ msgid "Default"
58
+ msgstr ""
59
+
60
+ msgid "Select Color"
61
+ msgstr ""
62
+
63
+ msgid "Delete"
64
+ msgstr ""
65
+
66
+ msgid "Hour"
67
+ msgstr ""
68
+
69
+ msgid "Minute"
70
+ msgstr ""
71
+
72
+ msgid "Select date"
73
+ msgstr ""
74
+
75
+ msgid "Input format: %s"
76
+ msgstr ""
77
+
78
+ msgid "Select file"
79
+ msgstr ""
80
+
81
+ msgid "Select %s"
82
+ msgstr ""
83
+
84
+ msgid "Toolset"
85
+ msgstr ""
86
+
87
+ msgid "Use as field value"
88
+ msgstr ""
89
+
90
+ msgid "Please note that not all video and audio formats are supported by the WordPress media player. Before you upload media files, have a look at %ssupported media formats%s."
91
+ msgstr ""
92
+
93
+ msgid "Edit Skype button"
94
+ msgstr ""
95
+
96
+ msgid "Enter your Skype Name"
97
+ msgstr ""
98
+
99
+ msgid "Select a button from below"
100
+ msgstr ""
101
+
102
+ msgid "Skype buttons with status"
103
+ msgstr ""
104
+
105
+ msgid "If you choose to show your Skype status, your Skype button will always reflect your availability on Skype. This status will be shown to everyone, whether they’re in your contact list or not."
106
+ msgstr ""
107
+
108
+ msgid "Save"
109
+ msgstr ""
110
+
111
+ msgid "You must define the $operator parameter for WPToolset_Cake_Validation::comparison()"
112
+ msgstr ""
113
+
114
+ msgid "You must define a regular expression for WPToolset_Cake_Validation::custom()"
115
+ msgstr ""
116
+
117
+ msgid "Delete %s"
118
+ msgstr ""
119
+
120
+ msgid "Add new %s"
121
+ msgstr ""
122
+
123
+ msgid "Get Types and Views"
124
+ msgstr ""
125
+
126
+ msgid "Once you have installed the full versions of Types and Views you'll be able to create and edit your own content types, layouts and listings."
127
+ msgstr ""
128
+
129
+ msgid "<a href=\"%s\" target=\"_blank\">Learn more</a>"
130
+ msgstr ""
131
+
132
+ msgid "Your theme was created using <strong>Types</strong> and <strong>Views</strong>. Developers use these two plugins to build complex websites, without coding."
133
+ msgstr ""
134
+
135
+ msgid "Right now, you're using the embedded version, which creates the layout but doesn't include the editing interface. You can upgrade to the full version and customize your site yourself - you don't even need to know how to program!"
136
+ msgstr ""
137
+
138
+ msgid "Every purchase of Views entitles you to commercial-grade support and upgrades for one year."
139
+ msgstr ""
140
+
141
+ msgid "You can use Types and Views for as many themes and websites as you like."
142
+ msgstr ""
143
+
144
+ msgid "View templates"
145
+ msgstr ""
146
+
147
+ msgid "Post View"
148
+ msgstr ""
149
+
150
+ msgid "Taxonomy View"
151
+ msgstr ""
152
+
153
+ msgid "User View"
154
+ msgstr ""
155
+
156
+ msgid "Views"
157
+ msgstr ""
158
+
159
+ msgid "Types"
160
+ msgstr ""
161
+
162
+ msgid "Fields"
163
+ msgstr ""
164
+
165
+ msgid "Go to"
166
+ msgstr ""
167
+
168
+ msgid "User ID"
169
+ msgstr ""
170
+
171
+ msgid "Basic"
172
+ msgstr ""
173
+
174
+ msgid "User Email"
175
+ msgstr ""
176
+
177
+ msgid "User Login"
178
+ msgstr ""
179
+
180
+ msgid "First Name"
181
+ msgstr ""
182
+
183
+ msgid "Last Name"
184
+ msgstr ""
185
+
186
+ msgid "Nickname"
187
+ msgstr ""
188
+
189
+ msgid "Display Name"
190
+ msgstr ""
191
+
192
+ msgid "Description"
193
+ msgstr ""
194
+
195
+ msgid "Yahoo IM"
196
+ msgstr ""
197
+
198
+ msgid "Jabber"
199
+ msgstr ""
200
+
201
+ msgid "AIM"
202
+ msgstr ""
203
+
204
+ msgid "User Url"
205
+ msgstr ""
206
+
207
+ msgid "Registration Date"
208
+ msgstr ""
209
+
210
+ msgid "User Status"
211
+ msgstr ""
212
+
213
+ msgid "User Spam Status"
214
+ msgstr ""
215
+
216
+ msgid "Translatable string"
217
+ msgstr ""
218
+
219
+ msgid "Users fields"
220
+ msgstr ""
221
+
222
+ msgid "User fields"
223
+ msgstr ""
224
+
225
+ msgid "Types fields"
226
+ msgstr ""
227
+
228
+ msgid "Post View"
229
+ msgstr ""
230
+
231
+ msgid "Taxonomy View"
232
+ msgstr ""
233
+
234
+ msgid "User View"
235
+ msgstr ""
236
+
237
+ msgid "Field"
238
+ msgstr ""
239
+
240
+ msgid "View"
241
+ msgstr ""
242
+
243
+ msgid "Taxonomy"
244
+ msgstr ""
245
+
246
+ msgid "Other Fields"
247
+ msgstr ""
248
+
249
+ msgid "Search"
250
+ msgstr ""
251
+
252
+ msgid "Clear"
253
+ msgstr ""
254
+
255
+ msgid "Some pointer hints have been hidden on this page. %sShow them again%s"
256
+ msgstr ""
257
+
258
+ msgid "Do you want to apply to all?"
259
+ msgstr ""
260
+
261
+ msgid "%d %s uses a different Content Template."
262
+ msgstr ""
263
+
264
+ msgid "%d %s use a different Content Template."
265
+ msgstr ""
266
+
267
+ msgid "Update %s now"
268
+ msgstr ""
269
+
270
+ msgid "Success!"
271
+ msgstr ""
272
+
273
+ msgid "All %ss were updated"
274
+ msgstr ""
275
+
276
+ msgid "Close"
277
+ msgstr ""
278
+
279
+ msgid "This View does not list posts"
280
+ msgstr ""
281
+
282
+ msgid "Filter MetaHTML is empty"
283
+ msgstr ""
284
+
285
+ msgid "Something on the filter_controls_mode is broken"
286
+ msgstr ""
287
+
288
+ msgid "post relationship"
289
+ msgstr ""
290
+
291
+ msgid "Your View contains more URL based filters than parametric search controls in the Filter HTML textarea"
292
+ msgstr ""
293
+
294
+ msgid "Your View contains more parametric search controls in the Filter HTML textarea than URL based filters"
295
+ msgstr ""
296
+
297
+ msgid "Cancel"
298
+ msgstr ""
299
+
300
+ msgid "Add New Content Template"
301
+ msgstr ""
302
+
303
+ msgid "Edit Content Template"
304
+ msgstr ""
305
+
306
+ msgid "New Content Template"
307
+ msgstr ""
308
+
309
+ msgid "View Views-Templates"
310
+ msgstr ""
311
+
312
+ msgid "Search Content Templates"
313
+ msgstr ""
314
+
315
+ msgid "No Content Templates found"
316
+ msgstr ""
317
+
318
+ msgid "No Content Templates found in Trash"
319
+ msgstr ""
320
+
321
+ msgid "Content Template"
322
+ msgstr ""
323
+
324
+ msgid "None"
325
+ msgstr ""
326
+
327
+ msgid "<strong>Content template debug: </strong>Calling function is <strong>%s</strong>"
328
+ msgstr ""
329
+
330
+ msgid "Insert Views Shortcode"
331
+ msgstr ""
332
+
333
+ msgid "Convert URLs to point to translated content in Views and Content Templates"
334
+ msgstr ""
335
+
336
+ msgid "Save"
337
+ msgstr ""
338
+
339
+ msgid "Settings Saved"
340
+ msgstr ""
341
+
342
+ msgid "A View loads content from the database and displays it anyway you choose."
343
+ msgstr ""
344
+
345
+ msgid "The Query section lets you choose the content to load."
346
+ msgstr ""
347
+
348
+ msgid "A basic query selects all items of a chosen type."
349
+ msgstr ""
350
+
351
+ msgid "You can refine the selection by adding filters."
352
+ msgstr ""
353
+
354
+ msgid "At the bottom of this page you will find the Layout section, where you control the output."
355
+ msgstr ""
356
+
357
+ msgid "The Front-end Filter section includes the pagination controls, allowing visitors to choose which results page to show."
358
+ msgstr ""
359
+
360
+ msgid "Creating paginated listings with Views"
361
+ msgstr ""
362
+
363
+ msgid "The Front-end Filter section includes the slider controls, allowing visitors switch between slides."
364
+ msgstr ""
365
+
366
+ msgid "At the bottom of this page you will find a slide Content Template, where you design slides."
367
+ msgstr ""
368
+
369
+ msgid "Creating sliders with Views"
370
+ msgstr ""
371
+
372
+ msgid "Building a View for a parametric search:"
373
+ msgstr ""
374
+
375
+ msgid "Select which content to load in the 'Content selection' section."
376
+ msgstr ""
377
+
378
+ msgid "Add filter inputs to the 'Filter HTML/CSS/JS' section."
379
+ msgstr ""
380
+
381
+ msgid "Select advanced search options in the 'Parametric search settings' section."
382
+ msgstr ""
383
+
384
+ msgid "Design the search results output in the 'Layout HTML/CSS/JS' section."
385
+ msgstr ""
386
+
387
+ msgid "Remember to click on Update after you complete each section and before you continue to the next section."
388
+ msgstr ""
389
+
390
+ msgid "Creating parametric searches with Views"
391
+ msgstr ""
392
+
393
+ msgid "The Front-end filter section lets you add pagination, slider controls and parametric search to the View."
394
+ msgstr ""
395
+
396
+ msgid "The pagination section lets you break the results into separate pages."
397
+ msgstr ""
398
+
399
+ msgid "This way, you can display a large number of results, in shorter pages."
400
+ msgstr ""
401
+
402
+ msgid "You can insert next/previous links and page selectors, for navigating directly to a specific page."
403
+ msgstr ""
404
+
405
+ msgid "The first part of this section lets you choose how pagination works."
406
+ msgstr ""
407
+
408
+ msgid "Select how many results to show in each page and how pages transition."
409
+ msgstr ""
410
+
411
+ msgid "The second part of this section lets you design the pagination controls that would appear on the page for visitors."
412
+ msgstr ""
413
+
414
+ msgid "The toolbar above the HTML editor includes buttons for inserting various controls."
415
+ msgstr ""
416
+
417
+ msgid "Besides pagination, you can also insert parametric search filters and content search controls."
418
+ msgstr ""
419
+
420
+ msgid "The pagination section lets you build sliders with Views."
421
+ msgstr ""
422
+
423
+ msgid "The View will display each slide at a time and allow visitors to switch between slides using next/previous links and slide selectors."
424
+ msgstr ""
425
+
426
+ msgid "The first part of this section lets you choose how the slider pagination works."
427
+ msgstr ""
428
+
429
+ msgid "Select how many results to show in each slide and how slides transition."
430
+ msgstr ""
431
+
432
+ msgid "The second part of this section lets you design the transition controls for the slider."
433
+ msgstr ""
434
+
435
+ msgid "The toolbar above the HTML editor includes buttons for inserting the slide transition controls."
436
+ msgstr ""
437
+
438
+ msgid "Using pagination you can also implement sliders."
439
+ msgstr ""
440
+
441
+ msgid "Learn how to create sliders with Views."
442
+ msgstr ""
443
+
444
+ msgid "Besides pagination and slider transition controls, you can also insert parametric search filters and content search controls."
445
+ msgstr ""
446
+
447
+ msgid "Learn how to create parametric searches with Views."
448
+ msgstr ""
449
+
450
+ msgid "To create a parametric search, position the cursor between the %s and %s shortcodes and click on the ‘Filters’ button to insert filter elements."
451
+ msgstr ""
452
+
453
+ msgid "Your parametric search can contain any custom field or taxonomy that this View queries."
454
+ msgstr ""
455
+
456
+ msgid "You can also click on the \"Search\" button to add a search box for visitors"
457
+ msgstr ""
458
+
459
+ msgid "Use HTML and CSS to style the filter."
460
+ msgstr ""
461
+
462
+ msgid "Remember to include the ‘Submit’ button for the form."
463
+ msgstr ""
464
+
465
+ msgid "This View uses pagination, but pagination controls are still not inserted into the filter HTML section."
466
+ msgstr ""
467
+
468
+ msgid "Would you like to insert them now?"
469
+ msgstr ""
470
+
471
+ msgid "Automatically insert pagination controls"
472
+ msgstr ""
473
+
474
+ msgid "No - I will add pagination controls manually"
475
+ msgstr ""
476
+
477
+ msgid "This View uses AJAX pagination to implement a slider."
478
+ msgstr ""
479
+
480
+ msgid "However, pagination controls are still not inserted into the filter HTML section."
481
+ msgstr ""
482
+
483
+ msgid "We've just inserted shortcodes that display the pagination."
484
+ msgstr ""
485
+
486
+ msgid "You will see the following shortcodes inside the filter HTML box below."
487
+ msgstr ""
488
+
489
+ msgid "To style the pagination, add your HTML around the pagination shortcodes."
490
+ msgstr ""
491
+
492
+ msgid "You can always insert these shortcodes manually by clicking on the ‘Pagination’ button below."
493
+ msgstr ""
494
+
495
+ msgid "The layout HTML box lets you output your View results and style them on your page."
496
+ msgstr ""
497
+
498
+ msgid "Click on the Layout Wizard to select the style of your Views loop and the fields you want to display."
499
+ msgstr ""
500
+
501
+ msgid "You can also insert fields manually by positioning the cursor inside between the %s and %s tags, and clicking on the Fields button."
502
+ msgstr ""
503
+
504
+ msgid "The Content Template button will let you add, or even create, a Content template to insert directly into your view."
505
+ msgstr ""
506
+
507
+ msgid "Learn more about layouts and building your View loop"
508
+ msgstr ""
509
+
510
+ msgid "Layout wizard"
511
+ msgstr ""
512
+
513
+ msgid "a guided wizard that lets you create layouts, with different styles and content."
514
+ msgstr ""
515
+
516
+ msgid "Recommended if you are new to Views."
517
+ msgstr ""
518
+
519
+ msgid "once you know how the layout loop works, add any field to it, using any formating style."
520
+ msgstr ""
521
+
522
+ msgid "Good for building your own unique loops."
523
+ msgstr ""
524
+
525
+ msgid "add complete blocks into the View loop using Content Templates."
526
+ msgstr ""
527
+
528
+ msgid "This method makes it easy to create complex layouts with simple editing."
529
+ msgstr ""
530
+
531
+ msgid "Media"
532
+ msgstr ""
533
+
534
+ msgid "add images and other media items to the View."
535
+ msgstr ""
536
+
537
+ msgid "Besides these buttons, you can edit the HTML content yourself by writing your own HTML and CSS."
538
+ msgstr ""
539
+
540
+ msgid "The View will iterate through the the results and display them one by one."
541
+ msgstr ""
542
+
543
+ msgid "Learn more by reading the %sViews Loop documentation%s."
544
+ msgstr ""
545
+
546
+ msgid "Hide these instructions"
547
+ msgstr ""
548
+
549
+ msgid "The Layout Wizard just added shortcodes for the fields that you selected to the HTML box."
550
+ msgstr ""
551
+
552
+ msgid "See how the shortcodes appear inside the loop."
553
+ msgstr ""
554
+
555
+ msgid "You can change the appearance by adding HTML and CSS around these shortcodes."
556
+ msgstr ""
557
+
558
+ msgid "You can add HTML code, fields, media and entire Content Templates to the editor."
559
+ msgstr ""
560
+
561
+ msgid "You just added a shortcode for a Content Template to this View."
562
+ msgstr ""
563
+
564
+ msgid "A Content Template works like a subroutine."
565
+ msgstr ""
566
+
567
+ msgid "You can edit its content in one place and use it in several places in the View."
568
+ msgstr ""
569
+
570
+ msgid "You just connected a Content Template to this View."
571
+ msgstr ""
572
+
573
+ msgid "Edit the new Content Template"
574
+ msgstr ""
575
+
576
+ msgid "This Content Template lets you design slides in this slider. Add any field you need to display and design them using HTML and CSS. To style the slide transition controls, scroll up the the filter section."
577
+ msgstr ""
578
+
579
+ msgid "This Content Template lets you design how each item in this grid will be displayed. A default shortcode that displays the post link has been added. You can edit this and add any field you need to display and design them using HTML and CSS."
580
+ msgstr ""
581
+
582
+ msgid "To change what gets displayed, scroll up the the filter section."
583
+ msgstr ""
584
+
585
+ msgid "You are viewing the read-only version of this View. To edit it, you need to get Views plugin."
586
+ msgstr ""
587
+
588
+ msgid "Get Views"
589
+ msgstr ""
590
+
591
+ msgid "You are viewing the read-only version of this Content Template. To edit it, you need to get Views plugin."
592
+ msgstr ""
593
+
594
+ msgid "This Content Template replaces the content area of the posts that you assign it to."
595
+ msgstr ""
596
+
597
+ msgid "It can be used to tweak the content of a post when it is displayed alone or in an archive page."
598
+ msgstr ""
599
+
600
+ msgid "You can also call this Template using a shortcode [wpv-post-body view_template=\"XX\"] to render specific information about the current post."
601
+ msgstr ""
602
+
603
+ msgid "You can add shortcodes to post fields, and also your own HTML and CSS to style the fields and design the page template."
604
+ msgstr ""
605
+
606
+ msgid "Content Template documentation"
607
+ msgstr ""
608
+
609
+ msgid "TwoYou are viewing the read-only version of this WordPress Archive. To edit it, you need to get Views plugin."
610
+ msgstr ""
611
+
612
+ msgid "This WordPress Archive replaces the natural archive loops created by WordPress."
613
+ msgstr ""
614
+
615
+ msgid "WordPress Archives documentation"
616
+ msgstr ""
617
+
618
+ msgid "OneYou are viewing the read-only version of this WordPress Archive. To edit it, you need to get Views plugin."
619
+ msgstr ""
620
+
621
+ msgid "Views will provide a Layout Wizard to select the style of your Views loop and the fields you want to display."
622
+ msgstr ""
623
+
624
+ msgid "You can also insert fields manually."
625
+ msgstr ""
626
+
627
+ msgid "The full Views plugin will let you add, or even create, a Content template to insert directly into your Layout."
628
+ msgstr ""
629
+
630
+ msgid "Besides these helpers, you can edit the HTML content yourself by writing your own HTML and CSS."
631
+ msgstr ""
632
+
633
+ msgid "Title and description"
634
+ msgstr ""
635
+
636
+ msgid "Each View has a title and an optional description. These are used for you, to identify different Views. The title and the description don't appear anywhere on the site's public pages."
637
+ msgstr ""
638
+
639
+ msgid "Content to load"
640
+ msgstr ""
641
+
642
+ msgid "Choose between posts, taxonomy and users and then select the specific content type to load. For posts, you can select multiple content types."
643
+ msgstr ""
644
+
645
+ msgid "Query options"
646
+ msgstr ""
647
+
648
+ msgid "This section includes additional options for what content to load. You will see different options for posts, taxonomy and users."
649
+ msgstr ""
650
+
651
+ msgid "Ordering"
652
+ msgstr ""
653
+
654
+ msgid "Choose how to order the results that the View gets from the database. You can select the sorting key and direction."
655
+ msgstr ""
656
+
657
+ msgid "Limit and offset"
658
+ msgstr ""
659
+
660
+ msgid "You can limit the number of results returned by the query and set an offset. Please note that this option is not intended for pagination and sliders, but for static limit and offset settings."
661
+ msgstr ""
662
+
663
+ msgid "Query filter"
664
+ msgstr ""
665
+
666
+ msgid "You can filter the View query by status, custom fields, taxonomy, users fields and even content search depending on the content that you are going to load. Click on 'Add another filter' and then select the filter type. A View may have as many filters as you like."
667
+ msgstr ""
668
+
669
+ msgid "Pagination and sliders settings"
670
+ msgstr ""
671
+
672
+ msgid "You can use a View to display paginated results and sliders. Both are built using 'Pagination'. For paginated listings, choose to update the entire page. For sliders, choose to update only the View."
673
+ msgstr ""
674
+
675
+ msgid "Filter HTML/CSS/JS"
676
+ msgstr ""
677
+
678
+ msgid "In this section you can add pagination controls, slider controls and parametric searches. If you enabled pagination, you need to insert the pagination controls here. They are used for both paged results and sliders. For parametric searches, insert 'filter' elements. The output of this section is displayed via the [wpv-filter-meta-html] shortcode in the Combined Output section."
679
+ msgstr ""
680
+
681
+ msgid "Parametric search"
682
+ msgstr ""
683
+
684
+ msgid "In this section you can choose when to refresh the Views results and which options to show in form inputs."
685
+ msgstr ""
686
+
687
+ msgid "View HTML output"
688
+ msgstr ""
689
+
690
+ msgid "This HTML determines what the View outputs for the query results. Use the Layout wizard to create a new layout. Then, edit it by adding fields, HTML, media and anything else in the toolbar. The output of this section is displayed via the [wpv-layout-meta-html] in the Combined Output section."
691
+ msgstr ""
692
+
693
+ msgid "Templates for this View"
694
+ msgstr ""
695
+
696
+ msgid "A View may include templates. These templates make it easy to output complex structures without having to repeat them in the View HTML. Click on the 'Content Template' button in the Layout HTML section to add Content Templates here."
697
+ msgstr ""
698
+
699
+ msgid "Combined Output"
700
+ msgstr ""
701
+
702
+ msgid "This HTML box lets you control how the Filter and Layout sections of this Views are displayed. The [wpv-filter-meta-html] shortcode displays the output of the Filter section. The [wpv-layout-meta-html] shortcode displays the output of the Layout section. You can add your HTML and fields to rearrange and style the output."
703
+ msgstr ""
704
+
705
+ msgid "Loop selection"
706
+ msgstr ""
707
+
708
+ msgid "Choose which listing page to customize. The WordPress archive will display the exact same content as WordPress normally does, but you can design it using the View HTML."
709
+ msgstr ""
710
+
711
+ msgid "Module Manager"
712
+ msgstr ""
713
+
714
+ msgid "With Modules, you can easily reuse your designs in different websites and create your own library of building blocks."
715
+ msgstr ""
716
+
717
+ msgid "Home/Blog"
718
+ msgstr ""
719
+
720
+ msgid "Search results"
721
+ msgstr ""
722
+
723
+ msgid "Author archives"
724
+ msgstr ""
725
+
726
+ msgid "Year archives"
727
+ msgstr ""
728
+
729
+ msgid "Month archives"
730
+ msgstr ""
731
+
732
+ msgid "Day archives"
733
+ msgstr ""
734
+
735
+ msgid "%s using \"%s\""
736
+ msgstr ""
737
+
738
+ msgid "There are no Views being used for Post Type archive loops."
739
+ msgstr ""
740
+
741
+ msgid "Edit"
742
+ msgstr ""
743
+
744
+ msgid "Create a new View for this listing page"
745
+ msgstr ""
746
+
747
+ msgid "There are no Views being used for Taxonomy archive loops."
748
+ msgstr ""
749
+
750
+ msgid "post type <strong>%s</strong>"
751
+ msgstr ""
752
+
753
+ msgid "taxonomy <strong>%s</strong>"
754
+ msgstr ""
755
+
756
+ msgid "This View isn't being used for any archive loops."
757
+ msgstr ""
758
+
759
+ msgid "This View is being used for these archive loops: %s"
760
+ msgstr ""
761
+
762
+ msgid "OK"
763
+ msgstr ""
764
+
765
+ msgid "<span style=\"color:red\">*</span> A different WordPress Archive is already assigned to this item"
766
+ msgstr ""
767
+
768
+ msgid "A WordPress Archive with that name already exists. Please use another name."
769
+ msgstr ""
770
+
771
+ msgid "Loop"
772
+ msgstr ""
773
+
774
+ msgid "Use this View"
775
+ msgstr ""
776
+
777
+ msgid "Use this View for these archive loops:"
778
+ msgstr ""
779
+
780
+ msgid "Post type loops"
781
+ msgstr ""
782
+
783
+ msgid "Taxonomy loops"
784
+ msgstr ""
785
+
786
+ msgid "Add new WordPress Archive"
787
+ msgstr ""
788
+
789
+ msgid "What loop will this Archive be used for?"
790
+ msgstr ""
791
+
792
+ msgid "WordPress Native Archives"
793
+ msgstr ""
794
+
795
+ msgid "Post Type Archives"
796
+ msgstr ""
797
+
798
+ msgid "Taxonomy Archives"
799
+ msgstr ""
800
+
801
+ msgid "Name this WordPress Archive"
802
+ msgstr ""
803
+
804
+ msgid "WordPress Archive name"
805
+ msgstr ""
806
+
807
+ msgid "Add new Archive"
808
+ msgstr ""
809
+
810
+ msgid "Accept"
811
+ msgstr ""
812
+
813
+ msgid "custom field"
814
+ msgstr ""
815
+
816
+ msgid "taxonomy"
817
+ msgstr ""
818
+
819
+ msgid "The url_param is missing from the wpv-control shortcode argument."
820
+ msgstr ""
821
+
822
+ msgid "The \"type\" or \"field\" needs to be set in the wpv-control shortcode argument."
823
+ msgstr ""
824
+
825
+ msgid "Types plugin is required."
826
+ msgstr ""
827
+
828
+ msgid "Empty field values or incorrect field defined. "
829
+ msgstr ""
830
+
831
+ msgid "Select date"
832
+ msgstr ""
833
+
834
+ msgid "You need the Types plugin to render this parametric search control"
835
+ msgstr ""
836
+
837
+ msgid "The url_param argument is missing from the wpv-control-set shortcode."
838
+ msgstr ""
839
+
840
+ msgid "The ancestors argument is missing from the wpv-control-set shortcode."
841
+ msgstr ""
842
+
843
+ msgid "The type argument needs to be set in the wpv-control-item shortcode."
844
+ msgstr ""
845
+
846
+ msgid "The ancestor_type argument is missing from the wpv-control-item shortcode."
847
+ msgstr ""
848
+
849
+ msgid "The post types listed in this View do not have ancestors."
850
+ msgstr ""
851
+
852
+ msgid "The ancestor_type argument refers to a post type that is not included in the ancestors tree."
853
+ msgstr ""
854
+
855
+ msgid "The ancestors argument does not end with a valid parent for the returned post types on this View."
856
+ msgstr ""
857
+
858
+ msgid "There seems to be some kind of infinite loop happening."
859
+ msgstr ""
860
+
861
+ msgid "Reset"
862
+ msgstr ""
863
+
864
+ msgid "This View uses an auxiliar query: it has pagination and limit&offset settings, and WordPress can not perform a single Query to handle both."
865
+ msgstr ""
866
+
867
+ msgid "Export"
868
+ msgstr ""
869
+
870
+ msgid "Import"
871
+ msgstr ""
872
+
873
+ msgid "Could not read the Views import file."
874
+ msgstr ""
875
+
876
+ msgid "Unable to open zip file"
877
+ msgstr ""
878
+
879
+ msgid "The Simple XML library is missing."
880
+ msgstr ""
881
+
882
+ msgid "The XML file (%s) could not be read."
883
+ msgstr ""
884
+
885
+ msgid "The XML could not be read."
886
+ msgstr ""
887
+
888
+ msgid "Failed to update view-template - %s."
889
+ msgstr ""
890
+
891
+ msgid "Failed to update Content Template - %s."
892
+ msgstr ""
893
+
894
+ msgid "Failed to create Content Template - %s."
895
+ msgstr ""
896
+
897
+ msgid "%d Content Templates found in the file. %d have been created and %d have been over written."
898
+ msgstr ""
899
+
900
+ msgid "%d existing Content Templates were deleted."
901
+ msgstr ""
902
+
903
+ msgid "Failed to update view - %s."
904
+ msgstr ""
905
+
906
+ msgid "Failed to create view - %s."
907
+ msgstr ""
908
+
909
+ msgid "%d Views found in the file. %d have been created and %d have been over written."
910
+ msgstr ""
911
+
912
+ msgid "%d existing Views were deleted."
913
+ msgstr ""
914
+
915
+ msgid "This Views have filters by IDs that were not correctly imported because they filter by posts that do not exist. Please review them: "
916
+ msgstr ""
917
+
918
+ msgid "This Views filter by post IDs using a shortcode attribute. You may need to modify the Views shortcodes if post IDs have changed during import: "
919
+ msgstr ""
920
+
921
+ msgid "%s could not be found"
922
+ msgstr ""
923
+
924
+ msgid "Settings updated"
925
+ msgstr ""
926
+
927
+ msgid "WordPress Archives and Content Templates settings updated"
928
+ msgstr ""
929
+
930
+ msgid "Import Views, WordPress Archives and Content Templates for your Theme"
931
+ msgstr ""
932
+
933
+ msgid "Import Views, WordPress Archives and Content Templates"
934
+ msgstr ""
935
+
936
+ msgid "Settings"
937
+ msgstr ""
938
+
939
+ msgid "Bulk overwrite if View or WordPress Archive exists"
940
+ msgstr ""
941
+
942
+ msgid "Delete any existing Views or WordPress Archives that are not in the import"
943
+ msgstr ""
944
+
945
+ msgid "Bulk overwrite if Content Template exists"
946
+ msgstr ""
947
+
948
+ msgid "Delete any existing Content Templates that are not in the import"
949
+ msgstr ""
950
+
951
+ msgid "Overwrite Views settings"
952
+ msgstr ""
953
+
954
+ msgid "Import the Views XML file placed in the Views Embedded folder"
955
+ msgstr ""
956
+
957
+ msgid "Select the Views XML file to upload from your computer"
958
+ msgstr ""
959
+
960
+ msgid "Upload file"
961
+ msgstr ""
962
+
963
+ msgid "Content Templates"
964
+ msgstr ""
965
+
966
+ msgid "Error during View import"
967
+ msgstr ""
968
+
969
+ msgid "Error during Content Template import"
970
+ msgstr ""
971
+
972
+ msgid "Views elements in this Module"
973
+ msgstr ""
974
+
975
+ msgid "Page %s"
976
+ msgstr ""
977
+
978
+ msgid "Current post body"
979
+ msgstr ""
980
+
981
+ msgid "Title"
982
+ msgstr ""
983
+
984
+ msgid "ID"
985
+ msgstr ""
986
+
987
+ msgid "Name"
988
+ msgstr ""
989
+
990
+ msgid "User"
991
+ msgstr ""
992
+
993
+ msgid "Object received from cache. MySQL query was cached in"
994
+ msgstr ""
995
+
996
+ msgid "Enable line breaks"
997
+ msgstr ""
998
+
999
+ msgid "Enable syntax higlighter"
1000
+ msgstr ""
1001
+
1002
+ msgid "Notice: Syntax higlighter can cause performance issues for large blocks of code"
1003
+ msgstr ""
1004
+
1005
+ msgid "Page info"
1006
+ msgstr ""
1007
+
1008
+ msgid "Current page"
1009
+ msgstr ""
1010
+
1011
+ msgid "Total memory used"
1012
+ msgstr ""
1013
+
1014
+ msgid "Render time"
1015
+ msgstr ""
1016
+
1017
+ msgid "Total MySQL queries"
1018
+ msgstr ""
1019
+
1020
+ msgid "CPU usage"
1021
+ msgstr ""
1022
+
1023
+ msgid "Elements info"
1024
+ msgstr ""
1025
+
1026
+ msgid "Post body"
1027
+ msgstr ""
1028
+
1029
+ msgid "WordPress Archive"
1030
+ msgstr ""
1031
+
1032
+ msgid "Kind of element"
1033
+ msgstr ""
1034
+
1035
+ msgid "Memory used"
1036
+ msgstr ""
1037
+
1038
+ msgid "Summary"
1039
+ msgstr ""
1040
+
1041
+ msgid "Additional info"
1042
+ msgstr ""
1043
+
1044
+ msgid "Query args"
1045
+ msgstr ""
1046
+
1047
+ msgid "Loading"
1048
+ msgstr ""
1049
+
1050
+ msgid "Hide"
1051
+ msgstr ""
1052
+
1053
+ msgid "Show"
1054
+ msgstr ""
1055
+
1056
+ msgid "MySQL query"
1057
+ msgstr ""
1058
+
1059
+ msgid "Items found"
1060
+ msgstr ""
1061
+
1062
+ msgid "Query results"
1063
+ msgstr ""
1064
+
1065
+ msgid "Filters"
1066
+ msgstr ""
1067
+
1068
+ msgid "Loop"
1069
+ msgstr ""
1070
+
1071
+ msgid "Template results"
1072
+ msgstr ""
1073
+
1074
+ msgid "Post body data"
1075
+ msgstr ""
1076
+
1077
+ msgid "Received array"
1078
+ msgstr ""
1079
+
1080
+ msgid "Original content"
1081
+ msgstr ""
1082
+
1083
+ msgid "Shortcodes"
1084
+ msgstr ""
1085
+
1086
+ msgid "Attributes"
1087
+ msgstr ""
1088
+
1089
+ msgid "Query"
1090
+ msgstr ""
1091
+
1092
+ msgid "Info"
1093
+ msgstr ""
1094
+
1095
+ msgid "Output"
1096
+ msgstr ""
1097
+
1098
+ msgid "Nested elements"
1099
+ msgstr ""
1100
+
1101
+ msgid "Output (RAW)"
1102
+ msgstr ""
1103
+
1104
+ msgid "Views/Content Templates debug information"
1105
+ msgstr ""
1106
+
1107
+ msgid "You attempted to edit a View that doesn&#8217;t exist. Perhaps it was deleted?"
1108
+ msgstr ""
1109
+
1110
+ msgid "You can�t edit this View because it is in the Trash. Please restore it and try again."
1111
+ msgstr ""
1112
+
1113
+ msgid "Preview View"
1114
+ msgstr ""
1115
+
1116
+ msgid "Learn how to display Views"
1117
+ msgstr ""
1118
+
1119
+ msgid "Preview Content Template"
1120
+ msgstr ""
1121
+
1122
+ msgid "Preview WordPress Archive"
1123
+ msgstr ""
1124
+
1125
+ msgid "Preview Layouts Loop View"
1126
+ msgstr ""
1127
+
1128
+ msgid " (post type archive)"
1129
+ msgstr ""
1130
+
1131
+ msgid " (taxonomy archive)"
1132
+ msgstr ""
1133
+
1134
+ msgid "This View loads <strong>%s</strong>"
1135
+ msgstr ""
1136
+
1137
+ msgid "Results are "
1138
+ msgstr ""
1139
+
1140
+ msgid "Select posts with custom field:"
1141
+ msgstr ""
1142
+
1143
+ msgid "Select posts with taxonomy:"
1144
+ msgstr ""
1145
+
1146
+ msgid "Select users with usermeta field:"
1147
+ msgstr ""
1148
+
1149
+ msgid ""
1150
+ msgstr ""
1151
+
1152
+ msgid "Slug of this View: "
1153
+ msgstr ""
1154
+
1155
+ msgid "The query section determines what content the View loads from the database"
1156
+ msgstr ""
1157
+
1158
+ msgid "The filter section lets you set up pagination and parametric search, which let visitors control the View query"
1159
+ msgstr ""
1160
+
1161
+ msgid "The layout section styles the View output on the page."
1162
+ msgstr ""
1163
+
1164
+ msgid "What to see this in action?"
1165
+ msgstr ""
1166
+
1167
+ msgid "Slug of this Content Template: "
1168
+ msgstr ""
1169
+
1170
+ msgid "Slug of this WordPress Archive: "
1171
+ msgstr ""
1172
+
1173
+ msgid "The loop section determines which listing page to customize"
1174
+ msgstr ""
1175
+
1176
+ msgid "This WordPress Archive is not used on any archive loops"
1177
+ msgstr ""
1178
+
1179
+ msgid "This WordPress Archive is used in the following archive loops: "
1180
+ msgstr ""
1181
+
1182
+ msgid "Content selection"
1183
+ msgstr ""
1184
+
1185
+ msgid "No filters set"
1186
+ msgstr ""
1187
+
1188
+ msgid "Pagination and Slider settings"
1189
+ msgstr ""
1190
+
1191
+ msgid "Filter HTML"
1192
+ msgstr ""
1193
+
1194
+ msgid "Layout HTML"
1195
+ msgstr ""
1196
+
1197
+ msgid "Insert search form from View - %s"
1198
+ msgstr ""
1199
+
1200
+ msgid "No target posts were found that use this View"
1201
+ msgstr ""
1202
+
1203
+ msgid "You first need to insert the View named %s in a post or page to show its results"
1204
+ msgstr ""
1205
+
1206
+ msgid "When the form is submitted, go to the results page:"
1207
+ msgstr ""
1208
+
1209
+ msgid "Insert shortcode"
1210
+ msgstr ""
1211
+
1212
+ msgid "Insert translatable string"
1213
+ msgstr ""
1214
+
1215
+ msgid "Insert search term shortcode"
1216
+ msgstr ""
1217
+
1218
+ msgid "Delete"
1219
+ msgstr ""
1220
+
1221
+ msgid "String to translate"
1222
+ msgstr ""
1223
+
1224
+ msgid "WPML context"
1225
+ msgstr ""
1226
+
1227
+ msgid "URL parameter to watch (optional)"
1228
+ msgstr ""
1229
+
1230
+ msgid "Slug"
1231
+ msgstr ""
1232
+
1233
+ msgid "Title with a link"
1234
+ msgstr ""
1235
+
1236
+ msgid "Body"
1237
+ msgstr ""
1238
+
1239
+ msgid "Excerpt"
1240
+ msgstr ""
1241
+
1242
+ msgid "Author"
1243
+ msgstr ""
1244
+
1245
+ msgid "Date"
1246
+ msgstr ""
1247
+
1248
+ msgid "URL"
1249
+ msgstr ""
1250
+
1251
+ msgid "Featured image"
1252
+ msgstr ""
1253
+
1254
+ msgid "Comments number"
1255
+ msgstr ""
1256
+
1257
+ msgid "Edit Link"
1258
+ msgstr ""
1259
+
1260
+ msgid "Post type"
1261
+ msgstr ""
1262
+
1263
+ msgid "Post status"
1264
+ msgstr ""
1265
+
1266
+ msgid "Post class"
1267
+ msgstr ""
1268
+
1269
+ msgid "Comment title"
1270
+ msgstr ""
1271
+
1272
+ msgid "Comment body"
1273
+ msgstr ""
1274
+
1275
+ msgid "Comment Author"
1276
+ msgstr ""
1277
+
1278
+ msgid "Comment Date"
1279
+ msgstr ""
1280
+
1281
+ msgid "Taxonomy title"
1282
+ msgstr ""
1283
+
1284
+ msgid "Taxonomy title with a link"
1285
+ msgstr ""
1286
+
1287
+ msgid "Taxonomy URL"
1288
+ msgstr ""
1289
+
1290
+ msgid "Taxonomy slug"
1291
+ msgstr ""
1292
+
1293
+ msgid "Taxonomy description"
1294
+ msgstr ""
1295
+
1296
+ msgid "Taxonomy post count"
1297
+ msgstr ""
1298
+
1299
+ msgid "Taxonomy page info"
1300
+ msgstr ""
1301
+
1302
+ msgid "Bloginfo value"
1303
+ msgstr ""
1304
+
1305
+ msgid "Search term"
1306
+ msgstr ""
1307
+
1308
+ msgid "Archive link"
1309
+ msgstr ""
1310
+
1311
+ msgid "Current user info"
1312
+ msgstr ""
1313
+
1314
+ msgid "Show user data"
1315
+ msgstr ""
1316
+
1317
+ msgid "Add to cart button"
1318
+ msgstr ""
1319
+
1320
+ msgid "Add to cart box"
1321
+ msgstr ""
1322
+
1323
+ msgid "Edit "
1324
+ msgstr ""
1325
+
1326
+ msgid "Edit This"
1327
+ msgstr ""
1328
+
1329
+ msgid "No Comments"
1330
+ msgstr ""
1331
+
1332
+ msgid "1 Comment"
1333
+ msgstr ""
1334
+
1335
+ msgid "% Comments"
1336
+ msgstr ""
1337
+
1338
+ msgid "Content template"
1339
+ msgstr ""
1340
+
1341
+ msgid "Archive"
1342
+ msgstr ""
1343
+
1344
+ msgid "Parametric search form"
1345
+ msgstr ""
1346
+
1347
+ msgid "Category"
1348
+ msgstr ""
1349
+
1350
+ msgid "all post types"
1351
+ msgstr ""
1352
+
1353
+ msgid "All post types"
1354
+ msgstr ""
1355
+
1356
+ msgid "%s"
1357
+ msgstr ""
1358
+
1359
+ msgid "terms of the taxonomy %s"
1360
+ msgstr ""
1361
+
1362
+ msgid "This View selects terms of the taxonomy %s"
1363
+ msgstr ""
1364
+
1365
+ msgid "terms of a taxonomy that no longer exists"
1366
+ msgstr ""
1367
+
1368
+ msgid "This View selects terms of a taxonomy that no longer exists"
1369
+ msgstr ""
1370
+
1371
+ msgid "users with any role"
1372
+ msgstr ""
1373
+
1374
+ msgid "users with role %s"
1375
+ msgstr ""
1376
+
1377
+ msgid "This View selects users with any role"
1378
+ msgstr ""
1379
+
1380
+ msgid "This View selects users with role %s"
1381
+ msgstr ""
1382
+
1383
+ msgid "post date"
1384
+ msgstr ""
1385
+
1386
+ msgid "post title"
1387
+ msgstr ""
1388
+
1389
+ msgid "post ID"
1390
+ msgstr ""
1391
+
1392
+ msgid "menu order"
1393
+ msgstr ""
1394
+
1395
+ msgid "random order"
1396
+ msgstr ""
1397
+
1398
+ msgid "Field - %s"
1399
+ msgstr ""
1400
+
1401
+ msgid "descending"
1402
+ msgstr ""
1403
+
1404
+ msgid "ascending"
1405
+ msgstr ""
1406
+
1407
+ msgid "term count"
1408
+ msgstr ""
1409
+
1410
+ msgid "term name"
1411
+ msgstr ""
1412
+
1413
+ msgid "term slug"
1414
+ msgstr ""
1415
+
1416
+ msgid "term group"
1417
+ msgstr ""
1418
+
1419
+ msgid "no specific criteria"
1420
+ msgstr ""
1421
+
1422
+ msgid "user login"
1423
+ msgstr ""
1424
+
1425
+ msgid "user ID"
1426
+ msgstr ""
1427
+
1428
+ msgid "user name"
1429
+ msgstr ""
1430
+
1431
+ msgid "display name"
1432
+ msgstr ""
1433
+
1434
+ msgid "user nicename"
1435
+ msgstr ""
1436
+
1437
+ msgid "user email"
1438
+ msgstr ""
1439
+
1440
+ msgid "user url"
1441
+ msgstr ""
1442
+
1443
+ msgid "user registered date"
1444
+ msgstr ""
1445
+
1446
+ msgid "user post count"
1447
+ msgstr ""
1448
+
1449
+ msgid "ordered by <strong>%s</strong> in <strong>%s</strong> order"
1450
+ msgstr ""
1451
+
1452
+ msgid " ordered by %s, %s"
1453
+ msgstr ""
1454
+
1455
+ msgid "All results loaded"
1456
+ msgstr ""
1457
+
1458
+ msgid "Fade"
1459
+ msgstr ""
1460
+
1461
+ msgid "Slide horizontally"
1462
+ msgstr ""
1463
+
1464
+ msgid "Slide vertically"
1465
+ msgstr ""
1466
+
1467
+ msgid "Slide Left"
1468
+ msgstr ""
1469
+
1470
+ msgid "Slide Right"
1471
+ msgstr ""
1472
+
1473
+ msgid "Slide Up"
1474
+ msgstr ""
1475
+
1476
+ msgid "Slide Down"
1477
+ msgstr ""
1478
+
1479
+ msgid "No pagination"
1480
+ msgstr ""
1481
+
1482
+ msgid "Select posts with <strong>%s</strong> as the <strong>author</strong>."
1483
+ msgstr ""
1484
+
1485
+ msgid "None set"
1486
+ msgstr ""
1487
+
1488
+ msgid "Select posts with the author's <strong>%s</strong> determined by the URL parameter <strong>\"%s\"</strong>"
1489
+ msgstr ""
1490
+
1491
+ msgid " eg. yoursite/page-with-this-view/?<strong>%s</strong>=%s"
1492
+ msgstr ""
1493
+
1494
+ msgid "Select posts which author's <strong>%s</strong> is set by the View shortcode attribute <strong>\"%s\"</strong>"
1495
+ msgstr ""
1496
+
1497
+ msgid " eg. [wpv-view name=\"%s\" <strong>%s</strong>=\"%s\"]"
1498
+ msgstr ""
1499
+
1500
+ msgid " OR"
1501
+ msgstr ""
1502
+
1503
+ msgid " AND"
1504
+ msgstr ""
1505
+
1506
+ msgid " OR "
1507
+ msgstr ""
1508
+
1509
+ msgid " AND "
1510
+ msgstr ""
1511
+
1512
+ msgid "Categories"
1513
+ msgstr ""
1514
+
1515
+ msgid "is <strong>One</strong> of these"
1516
+ msgstr ""
1517
+
1518
+ msgid "is <strong>All</strong> of these"
1519
+ msgstr ""
1520
+
1521
+ msgid "is <strong>Not one</strong> of these"
1522
+ msgstr ""
1523
+
1524
+ msgid "the same as the <strong>current page</strong>"
1525
+ msgstr ""
1526
+
1527
+ msgid "set by the View shortcode attribute "
1528
+ msgstr ""
1529
+
1530
+ msgid "set by the URL parameter "
1531
+ msgstr ""
1532
+
1533
+ msgid "set by the parent view."
1534
+ msgstr ""
1535
+
1536
+ msgid "using the operator"
1537
+ msgstr ""
1538
+
1539
+ msgid "eg. [wpv-view name=\"view-name\" <strong>%s=\"xxxx\"</strong>]"
1540
+ msgstr ""
1541
+
1542
+ msgid "eg. http://www.example.com/page/?<strong>%s=xxxx</strong>"
1543
+ msgstr ""
1544
+
1545
+ msgid "Select posts that are <strong>children</strong> of the <strong>Post with ID set by the shortcode attribute %s</strong>."
1546
+ msgstr ""
1547
+
1548
+ msgid " eg. [wpv-view name=\"view-name\" <strong>%s=\"123\"</strong>]"
1549
+ msgstr ""
1550
+
1551
+ msgid "Select posts that are <strong>children</strong> of the <strong>Post with ID set by the URL parameter %s</strong>."
1552
+ msgstr ""
1553
+
1554
+ msgid " eg. http://www.example.com/my-page/?<strong>%s=123</strong>"
1555
+ msgstr ""
1556
+
1557
+ msgid "Select posts that are children of <strong>%s</strong>."
1558
+ msgstr ""
1559
+
1560
+ msgid "Include only posts "
1561
+ msgstr ""
1562
+
1563
+ msgid "Exclude posts "
1564
+ msgstr ""
1565
+
1566
+ msgid "with the following <strong>IDs</strong>: %s"
1567
+ msgstr ""
1568
+
1569
+ msgid "with IDs determined by the URL parameter <strong>\"%s\"</strong>"
1570
+ msgstr ""
1571
+
1572
+ msgid " eg. yoursite/page-with-this-view/?<strong>%s</strong>=1"
1573
+ msgstr ""
1574
+
1575
+ msgid "which IDs is set by the View shortcode attribute <strong>\"%s\"</strong>"
1576
+ msgstr ""
1577
+
1578
+ msgid " eg. [wpv-view name=\"%s\" <strong>%s</strong>=\"1\"]"
1579
+ msgstr ""
1580
+
1581
+ msgid "parent is <strong>%s</strong>"
1582
+ msgstr ""
1583
+
1584
+ msgid "Select posts whose parent is <strong>%s</strong>."
1585
+ msgstr ""
1586
+
1587
+ msgid "Select taxonomy whose parent is <strong>%s</strong>."
1588
+ msgstr ""
1589
+
1590
+ msgid "Filter by <strong>search</strong> term: <strong>%s</strong>"
1591
+ msgstr ""
1592
+
1593
+ msgid "Filter by this search term: <strong>%s</strong>."
1594
+ msgstr ""
1595
+
1596
+ msgid "Show a <strong>search box</strong> for visitors"
1597
+ msgstr ""
1598
+
1599
+ msgid "Show a <strong>search box</strong> for visitors."
1600
+ msgstr ""
1601
+
1602
+ msgid "Filter by <strong>search box</strong>"
1603
+ msgstr ""
1604
+
1605
+ msgid "The search box will be added <strong>manually</strong>.<br /><code>eg. [wpv-filter-search-box]</code>"
1606
+ msgstr ""
1607
+
1608
+ msgid "Taxonomy is <strong>One</strong> of these"
1609
+ msgstr ""
1610
+
1611
+ msgid "Taxonomy is set by the current page"
1612
+ msgstr ""
1613
+
1614
+ msgid "Select users <strong>(%s)</strong> who have role <strong>%s</strong>"
1615
+ msgstr ""
1616
+
1617
+ msgid "Select all users with role <strong>%s</strong>, except of <strong>(%s)</strong>"
1618
+ msgstr ""
1619
+
1620
+ msgid "Select all users with role <strong>%s</strong>"
1621
+ msgstr ""
1622
+
1623
+ msgid "Select users with the <strong>%s</strong> determined by the URL parameter <strong>\"%s\"</strong> and with role <strong>\"%s\"</strong>"
1624
+ msgstr ""
1625
+
1626
+ msgid "Select all users with role <strong>%s</strong>, except of <strong>%s</strong> determined by the URL parameter <strong>\"%s\"</strong>"
1627
+ msgstr ""
1628
+
1629
+ msgid "Select users with <strong>%s</strong> set by the View shortcode attribute <strong>\"%s\"</strong> and with role <strong>\"%s\"</strong>"
1630
+ msgstr ""
1631
+
1632
+ msgid "Select all users with role <strong>%s</strong>, except of <strong>%s</strong> set by the View shortcode attribute <strong>\"%s\"</strong>"
1633
+ msgstr ""
1634
+
1635
+ msgid "status of "
1636
+ msgstr ""
1637
+
1638
+ msgid "Select posts with status of "
1639
+ msgstr ""
1640
+
1641
+ msgid " or "
1642
+ msgstr ""
1643
+
1644
+ msgid "any status."
1645
+ msgstr ""
1646
+
1647
+ msgid "Do not apply any filter based on status."
1648
+ msgstr ""
1649
+
1650
+ msgid "Select posts with the <strong>author</strong> the same as the <strong>current logged in user</strong>."
1651
+ msgstr ""
1652
+
1653
+ msgid "Select posts with the <strong>author set by the parent View</strong>."
1654
+ msgstr ""
1655
+
1656
+ msgid "Select posts with the <strong>author the same as the current page</strong>."
1657
+ msgstr ""
1658
+
1659
+ msgid "Select posts that are <strong>children</strong> of the <strong>Post where this View is inserted</strong>."
1660
+ msgstr ""
1661
+
1662
+ msgid "Select posts that are a <strong>children</strong> of the <strong>Post set by parent View</strong>."
1663
+ msgstr ""
1664
+
1665
+ msgid "parent is the <strong>current page</strong>"
1666
+ msgstr ""
1667
+
1668
+ msgid "Select posts whose parent is the <strong>current page</strong>."
1669
+ msgstr ""
1670
+
1671
+ msgid "Select taxonomy whose parent is the value set by the <strong>parent view</strong>."
1672
+ msgstr ""
1673
+
1674
+ msgid "Displays a View"
1675
+ msgstr ""
1676
+
1677
+ msgid "WP Views"
1678
+ msgstr ""
1679
+
1680
+ msgid "No Views defined. You can add them <a%s>here</a>."
1681
+ msgstr ""
1682
+
1683
+ msgid "Displays the filter section of a View."
1684
+ msgstr ""
1685
+
1686
+ msgid "WP Views Filter"
1687
+ msgstr ""
1688
+
1689
+ msgid "No Views with frontend forms defined. You can add them <a%s>here</a>."
1690
+ msgstr ""
1691
+
1692
+ msgid "Edit view"
1693
+ msgstr ""
1694
+
1695
+ msgid "Title:"
1696
+ msgstr ""
1697
+
1698
+ msgid "View:"
1699
+ msgstr ""
1700
+
1701
+ msgid "Target page:"
1702
+ msgstr ""
1703
+
1704
+ msgid "You have <strong>Views</strong> import pending. %sClick here to import%s | %sDismiss this message%s"
1705
+ msgstr ""
1706
+
1707
+ msgid "Add New View"
1708
+ msgstr ""
1709
+
1710
+ msgid "Edit View"
1711
+ msgstr ""
1712
+
1713
+ msgid "New View"
1714
+ msgstr ""
1715
+
1716
+ msgid "View Views"
1717
+ msgstr ""
1718
+
1719
+ msgid "Search Views"
1720
+ msgstr ""
1721
+
1722
+ msgid "No views found"
1723
+ msgstr ""
1724
+
1725
+ msgid "No views found in Trash"
1726
+ msgstr ""
1727
+
1728
+ msgid "Embedded View"
1729
+ msgstr ""
1730
+
1731
+ msgid "Embedded Content Template"
1732
+ msgstr ""
1733
+
1734
+ msgid "Embedded WordPress Archive"
1735
+ msgstr ""
1736
+
1737
+ msgid "Import Views for theme"
1738
+ msgstr ""
1739
+
1740
+ msgid "View not found"
1741
+ msgstr ""
1742
+
1743
+ msgid "Insert Views Shortcodes"
1744
+ msgstr ""
1745
+
1746
+ msgid "Thumbnail"
1747
+ msgstr ""
1748
+
1749
+ msgid "Got it! Don't show this message again"
1750
+ msgstr ""
1751
+
1752
+ msgid "Getting started"
1753
+ msgstr ""
1754
+
1755
+ msgid "Views Import"
1756
+ msgstr ""
1757
+
1758
+ msgid "Views import complete"
1759
+ msgstr ""
1760
+
1761
+ msgid "WP Views Embedded was <strong>deactivated</strong>! You are already running the complete WP Views plugin, so this one is not needed anymore."
1762
+ msgstr ""
1763
+
1764
+ msgid "Views are lists and groups of content, like a listing or showcase page. On your theme the following Views are defined:"
1765
+ msgstr ""
1766
+
1767
+ msgid "Content Templates are applied to pages to create different layouts. On your theme the following Content Templates are defined:"
1768
+ msgstr ""
1769
+
1770
+ msgid "If you want to edit these or create your own you can purchase the full version of <strong>Views</strong> from %s"
1771
+ msgstr ""
1772
+
1773
+ msgid "Select one %s"
1774
+ msgstr ""
1775
+
1776
+ msgid "Any %s"
1777
+ msgstr ""
1778
+
1779
+ msgid "Types ancestors tree not valid."
1780
+ msgstr ""
1781
+
1782
+ msgid "Please follow the tip hint below. "
1783
+ msgstr ""
1784
+
1785
+ msgid "The post types selected in this View do not have Types ancestors"
1786
+ msgstr ""
1787
+
1788
+ msgid "Post relationship"
1789
+ msgstr ""
1790
+
1791
+ msgid "The view has been succesfully updated"
1792
+ msgstr ""
1793
+
1794
+ msgid "Please make a valid selection."
1795
+ msgstr ""
1796
+
1797
+ msgid "Something bad happend with shortcode building, check the console"
1798
+ msgstr ""
1799
+
1800
+ msgid "The value for \"Refer to this field as\" is mandatory, please provide one."
1801
+ msgstr ""
1802
+
1803
+ msgid "Please make a valid tree selection."
1804
+ msgstr ""
1805
+
1806
+ msgid "This field can not be left empty"
1807
+ msgstr ""
1808
+
1809
+ msgid "\" is a reserved word for "
1810
+ msgstr ""
1811
+
1812
+ msgid "Change this value to avoid conflicts"
1813
+ msgstr ""
1814
+
1815
+ msgid "Error: AJAX returned "
1816
+ msgstr ""
1817
+
1818
+ msgid "Error: "
1819
+ msgstr ""
1820
+
1821
+ msgid "There are problems inserting your data. Check the console. "
1822
+ msgstr ""
1823
+
1824
+ msgid "Please select at least one post type to fiter by."
1825
+ msgstr ""
1826
+
1827
+ msgid "Something went wrong loading data "
1828
+ msgstr ""
1829
+
1830
+ msgid "Something went wrong while bulding model."
1831
+ msgstr ""
1832
+
1833
+ msgid "the same as set by the URL parameter"
1834
+ msgstr ""
1835
+
1836
+ msgid "Something went wrong in building the filter "
1837
+ msgstr ""
1838
+
1839
+ msgid "Basic filters"
1840
+ msgstr ""
1841
+
1842
+ msgid "Select one tree"
1843
+ msgstr ""
1844
+
1845
+ msgid "Submit button"
1846
+ msgstr ""
1847
+
1848
+ msgid "Insert input"
1849
+ msgstr ""
1850
+
1851
+ msgid "Create a submit button for this parametric search."
1852
+ msgstr ""
1853
+
1854
+ msgid "Clear form"
1855
+ msgstr ""
1856
+
1857
+ msgid "Consider adding a label before inserting the button."
1858
+ msgstr ""
1859
+
1860
+ msgid "Spinner"
1861
+ msgstr ""
1862
+
1863
+ msgid "Place cursor within the [wpv-filter-controls][/wpv-filter-controls] tags."
1864
+ msgstr ""
1865
+
1866
+ msgid "Place cursor within the [wpv-filter-start][wpv-filter-end] tags."
1867
+ msgstr ""
1868
+
1869
+ msgid "Place your cursor inside [wpv-control] tags."
1870
+ msgstr ""
1871
+
1872
+ msgid "You should select a [wpv-control] short tag instead of "
1873
+ msgstr ""
1874
+
1875
+ msgid "Place your cursor over a [wpv-control] or a [wpv-control-set] tag to edit it."
1876
+ msgstr ""
1877
+
1878
+ msgid "To edit this filter, place your cursor over the [wpv-control-set] tag."
1879
+ msgstr ""
1880
+
1881
+ msgid "Warning: the cursor is inside another short code, this may cause problems."
1882
+ msgstr ""
1883
+
1884
+ msgid "Edit filter field"
1885
+ msgstr ""
1886
+
1887
+ msgid "Update input"
1888
+ msgstr ""
1889
+
1890
+ msgid "There are problems inserting the shortcode."
1891
+ msgstr ""
1892
+
1893
+ msgid "Button label:"
1894
+ msgstr ""
1895
+
1896
+ msgid "Button classname:"
1897
+ msgstr ""
1898
+
1899
+ msgid "Expand"
1900
+ msgstr ""
1901
+
1902
+ msgid "Please provide at least one non-empty value, you are free to live some of them empty."
1903
+ msgstr ""
1904
+
1905
+ msgid "You should define a callback for your ajax call to async load data"
1906
+ msgstr ""
1907
+
1908
+ msgid "This View already has a content search filter. If you insert a search control to the HTML, the existing search filter will be removed."
1909
+ msgstr ""
1910
+
1911
+ msgid "Post author"
1912
+ msgstr ""
1913
+
1914
+ msgid "Edit this filter"
1915
+ msgstr ""
1916
+
1917
+ msgid "Delete this filter"
1918
+ msgstr ""
1919
+
1920
+ msgid "Post Author"
1921
+ msgstr ""
1922
+
1923
+ msgid "Updated"
1924
+ msgstr ""
1925
+
1926
+ msgid "Not saved"
1927
+ msgstr ""
1928
+
1929
+ msgid "%sLearn about filtering by Post Author%s"
1930
+ msgstr ""
1931
+
1932
+ msgid "Post author is the same as the logged in user"
1933
+ msgstr ""
1934
+
1935
+ msgid "Post author is "
1936
+ msgstr ""
1937
+
1938
+ msgid "Post author is set by the parent View"
1939
+ msgstr ""
1940
+
1941
+ msgid "Post author is the author of the current page"
1942
+ msgstr ""
1943
+
1944
+ msgid "Post author's "
1945
+ msgstr ""
1946
+
1947
+ msgid " is set by this URL parameter: "
1948
+ msgstr ""
1949
+
1950
+ msgid " is set by this View shortcode attribute: "
1951
+ msgstr ""
1952
+
1953
+ msgid " is not a valid taxonomy for the post types you are trying to display."
1954
+ msgstr ""
1955
+
1956
+ msgid "%sLearn about filtering by taxonomy%s"
1957
+ msgstr ""
1958
+
1959
+ msgid "Delete this filter by %s"
1960
+ msgstr ""
1961
+
1962
+ msgid "Value: "
1963
+ msgstr ""
1964
+
1965
+ msgid "Taxonomy name"
1966
+ msgstr ""
1967
+
1968
+ msgid "Shortcode attribute"
1969
+ msgstr ""
1970
+
1971
+ msgid "URL parameter"
1972
+ msgstr ""
1973
+
1974
+ msgid "Operator"
1975
+ msgstr ""
1976
+
1977
+ msgid "IN"
1978
+ msgstr ""
1979
+
1980
+ msgid "NOT IN"
1981
+ msgstr ""
1982
+
1983
+ msgid "AND"
1984
+ msgstr ""
1985
+
1986
+ msgid "Select posts with taxonomy: "
1987
+ msgstr ""
1988
+
1989
+ msgid "Taxonomy relationship:"
1990
+ msgstr ""
1991
+
1992
+ msgid "Relationship to use when querying with multiple taxonomies:"
1993
+ msgstr ""
1994
+
1995
+ msgid "OR"
1996
+ msgstr ""
1997
+
1998
+ msgid "Taxonomy is:"
1999
+ msgstr ""
2000
+
2001
+ msgid "Any of the following"
2002
+ msgstr ""
2003
+
2004
+ msgid "NOT one of the following"
2005
+ msgstr ""
2006
+
2007
+ msgid "All of the following"
2008
+ msgstr ""
2009
+
2010
+ msgid "Value set by the current page"
2011
+ msgstr ""
2012
+
2013
+ msgid "Value set by View shortcode attribute"
2014
+ msgstr ""
2015
+
2016
+ msgid "Value set by URL parameter"
2017
+ msgstr ""
2018
+
2019
+ msgid "Value set by parent view"
2020
+ msgstr ""
2021
+
2022
+ msgid "Custom field - %s"
2023
+ msgstr ""
2024
+
2025
+ msgid "%sLearn about filtering by custom fields%s"
2026
+ msgstr ""
2027
+
2028
+ msgid "Custom field"
2029
+ msgstr ""
2030
+
2031
+ msgid "Constant"
2032
+ msgstr ""
2033
+
2034
+ msgid "Remove"
2035
+ msgstr ""
2036
+
2037
+ msgid "Add another value"
2038
+ msgstr ""
2039
+
2040
+ msgid "%1$s%2$s, %3$s"
2041
+ msgstr ""
2042
+
2043
+ msgid "Select posts with custom field: "
2044
+ msgstr ""
2045
+
2046
+ msgid "Custom field relationship:"
2047
+ msgstr ""
2048
+
2049
+ msgid "Relationship to use when querying with multiple custom fields:"
2050
+ msgstr ""
2051
+
2052
+ msgid "Comparison function:"
2053
+ msgstr ""
2054
+
2055
+ msgid "Post id"
2056
+ msgstr ""
2057
+
2058
+ msgid "Post Ids"
2059
+ msgstr ""
2060
+
2061
+ msgid "%sLearn about filtering by Post ID%s"
2062
+ msgstr ""
2063
+
2064
+ msgid "The View will filter posts to"
2065
+ msgstr ""
2066
+
2067
+ msgid "include"
2068
+ msgstr ""
2069
+
2070
+ msgid "exclude"
2071
+ msgstr ""
2072
+
2073
+ msgid "Posts with those IDs: "
2074
+ msgstr ""
2075
+
2076
+ msgid "Posts with IDs set by this URL parameter: "
2077
+ msgstr ""
2078
+
2079
+ msgid "Posts with IDs set by the View shortcode attribute: "
2080
+ msgstr ""
2081
+
2082
+ msgid "Post parent"
2083
+ msgstr ""
2084
+
2085
+ msgid "%sLearn about filtering by Post Parent%s"
2086
+ msgstr ""
2087
+
2088
+ msgid "Taxonomy parent"
2089
+ msgstr ""
2090
+
2091
+ msgid "This View has a filter for a taxonomy that no longer exists. Please select one taxonomy and update the Content selection section."
2092
+ msgstr ""
2093
+
2094
+ msgid "This mode is not available. Please select one taxonomy and update the Content selection section."
2095
+ msgstr ""
2096
+
2097
+ msgid "Parent is the current page"
2098
+ msgstr ""
2099
+
2100
+ msgid "Parent is:"
2101
+ msgstr ""
2102
+
2103
+ msgid "Parent is the taxonomy selected by the <strong>parent view</strong>"
2104
+ msgstr ""
2105
+
2106
+ msgid "Post relationship - Post is a child of"
2107
+ msgstr ""
2108
+
2109
+ msgid "Post Relationship - Post is a child of"
2110
+ msgstr ""
2111
+
2112
+ msgid "There is no post type selected in the Content selection setion"
2113
+ msgstr ""
2114
+
2115
+ msgid "Post type <strong>%s</strong> doesn't belong to any other post type"
2116
+ msgstr ""
2117
+
2118
+ msgid "Post type <strong>%s</strong> is a child of <strong>%s</strong> post type"
2119
+ msgstr ""
2120
+
2121
+ msgid " and "
2122
+ msgstr ""
2123
+
2124
+ msgid "Post type <strong>%s</strong> is a child of <strong>%s</strong> post types"
2125
+ msgstr ""
2126
+
2127
+ msgid "Post where this View is inserted"
2128
+ msgstr ""
2129
+
2130
+ msgid "Post set by parent View"
2131
+ msgstr ""
2132
+
2133
+ msgid "Post with ID set by the shortcode attribute"
2134
+ msgstr ""
2135
+
2136
+ msgid "Post with ID set by the URL parameter"
2137
+ msgstr ""
2138
+
2139
+ msgid "Specific:"
2140
+ msgstr ""
2141
+
2142
+ msgid "Querying and Displaying Child Posts"
2143
+ msgstr ""
2144
+
2145
+ msgid "Post search"
2146
+ msgstr ""
2147
+
2148
+ msgid "%sLearn about filtering for a specific text string%s"
2149
+ msgstr ""
2150
+
2151
+ msgid "Taxonomy search"
2152
+ msgstr ""
2153
+
2154
+ msgid "Where to search: "
2155
+ msgstr ""
2156
+
2157
+ msgid "Post content and title"
2158
+ msgstr ""
2159
+
2160
+ msgid "Just post titles"
2161
+ msgstr ""
2162
+
2163
+ msgid "Search for a specific text:"
2164
+ msgstr ""
2165
+
2166
+ msgid "I’ll add the search box to the HTML manually"
2167
+ msgstr ""
2168
+
2169
+ msgid "Post Status"
2170
+ msgstr ""
2171
+
2172
+ msgid "Taxonomy term"
2173
+ msgstr ""
2174
+
2175
+ msgid "Remove this filter"
2176
+ msgstr ""
2177
+
2178
+ msgid "Taxonomy term: "
2179
+ msgstr ""
2180
+
2181
+ msgid "is one of these"
2182
+ msgstr ""
2183
+
2184
+ msgid "set by the current page"
2185
+ msgstr ""
2186
+
2187
+ msgid "User field - %s"
2188
+ msgstr ""
2189
+
2190
+ msgid "%sLearn about filtering by user fields%s"
2191
+ msgstr ""
2192
+
2193
+ msgid "User field"
2194
+ msgstr ""
2195
+
2196
+ msgid "Select users with usermeta field: "
2197
+ msgstr ""
2198
+
2199
+ msgid "Usermeta field relationship:"
2200
+ msgstr ""
2201
+
2202
+ msgid "Relationship to use when querying with multiple user fields:"
2203
+ msgstr ""
2204
+
2205
+ msgid "Specific users"
2206
+ msgstr ""
2207
+
2208
+ msgid "username"
2209
+ msgstr ""
2210
+
2211
+ msgid " and "
2212
+ msgstr ""
2213
+
2214
+ msgid " ordered by "
2215
+ msgstr ""
2216
+
2217
+ msgid ", limit to 1 item"
2218
+ msgstr ""
2219
+
2220
+ msgid ", limit to %d items"
2221
+ msgstr ""
2222
+
2223
+ msgid ", skip first item"
2224
+ msgstr ""
2225
+
2226
+ msgid ", skip %d items"
2227
+ msgstr ""
2228
+
2229
+ msgid "This View displays"
2230
+ msgstr ""
2231
+
2232
+ msgid "Users with this display name "
2233
+ msgstr ""
2234
+
2235
+ msgid "Users with "
2236
+ msgstr ""
2237
+
2238
+ msgid " set by this URL parameter: "
2239
+ msgstr ""
2240
+
2241
+ msgid " set by this View shortcode attribute: "
2242
+ msgstr ""
2243
+
2244
+ msgid "Type for search users"
2245
+ msgstr ""
2246
+
2247
+ msgid "No users matched your criteria"
2248
+ msgstr ""
2249
+
2250
+ msgid "Searching"
2251
+ msgstr ""
2252
+
2253
+ msgid "View updated."
2254
+ msgstr ""
2255
+
2256
+ msgid "Custom field updated."
2257
+ msgstr ""
2258
+
2259
+ msgid "Custom field deleted."
2260
+ msgstr ""
2261
+
2262
+ msgid "View restored to revision from %s"
2263
+ msgstr ""
2264
+
2265
+ msgid "View published."
2266
+ msgstr ""
2267
+
2268
+ msgid "View saved."
2269
+ msgstr ""
2270
+
2271
+ msgid "View submitted."
2272
+ msgstr ""
2273
+
2274
+ msgid "View scheduled for: <strong>%1$s</strong>."
2275
+ msgstr ""
2276
+
2277
+ msgid "M j, Y @ G:i"
2278
+ msgstr ""
2279
+
2280
+ msgid "View draft updated"
2281
+ msgstr ""
2282
+
2283
+ msgid "Content template updated."
2284
+ msgstr ""
2285
+
2286
+ msgid "Content template restored to revision from %s"
2287
+ msgstr ""
2288
+
2289
+ msgid "Content template published."
2290
+ msgstr ""
2291
+
2292
+ msgid "Content template saved."
2293
+ msgstr ""
2294
+
2295
+ msgid "Content template submitted."
2296
+ msgstr ""
2297
+
2298
+ msgid "Content template scheduled for: <strong>%1$s</strong>."
2299
+ msgstr ""
2300
+
2301
+ msgid "Content template draft updated"
2302
+ msgstr ""
2303
+
2304
+ msgid "Previous page"
2305
+ msgstr ""
2306
+
2307
+ msgid "Next page"
2308
+ msgstr ""
2309
+
2310
+ msgid "Unnamed View"
2311
+ msgstr ""
2312
+
2313
+ msgid "A View with that name already exists. Please use another name."
2314
+ msgstr ""
2315
+
2316
+ msgid "slide"
2317
+ msgstr ""
2318
+
2319
+ msgid "grid"
2320
+ msgstr ""
2321
+
2322
+ msgid "The View could not be created."
2323
+ msgstr ""
2324
+
2325
+ msgid "Displaying "
2326
+ msgstr ""
2327
+
2328
+ msgid " of "
2329
+ msgstr ""
2330
+
2331
+ msgid "Items per page"
2332
+ msgstr ""
2333
+
2334
+ msgid "Display all items"
2335
+ msgstr ""
2336
+
2337
+ msgid "Display 20 items per page"
2338
+ msgstr ""
2339
+
2340
+ msgid "<a href='%s' target='_blank'>Go to the Settings page &raquo;</a>"
2341
+ msgstr ""
2342
+
2343
+ msgid "Learn about different layouts"
2344
+ msgstr ""
2345
+
2346
+ msgid "Can't insert content in to shortcode"
2347
+ msgstr ""
2348
+
2349
+ msgid "Error occured"
2350
+ msgstr ""
2351
+
2352
+ msgid "Insert"
2353
+ msgstr ""
2354
+
2355
+ msgid "Next"
2356
+ msgstr ""
2357
+
2358
+ msgid "Insert a layout"
2359
+ msgstr ""
2360
+
2361
+ msgid "Layout style"
2362
+ msgstr ""
2363
+
2364
+ msgid "Choose fields"
2365
+ msgstr ""
2366
+
2367
+ msgid "Insert to the view"
2368
+ msgstr ""
2369
+
2370
+ msgid "Select the style of the layout to insert"
2371
+ msgstr ""
2372
+
2373
+ msgid "Unformatted"
2374
+ msgstr ""
2375
+
2376
+ msgid "Bootstrap grid"
2377
+ msgstr ""
2378
+
2379
+ msgid "You need to set the Bootstrap version used in your theme."
2380
+ msgstr ""
2381
+
2382
+ msgid "Table-based grid"
2383
+ msgstr ""
2384
+
2385
+ msgid "Table"
2386
+ msgstr ""
2387
+
2388
+ msgid "Unordered list"
2389
+ msgstr ""
2390
+
2391
+ msgid "Ordered list"
2392
+ msgstr ""
2393
+
2394
+ msgid "Bootstrap grid options"
2395
+ msgstr ""
2396
+
2397
+ msgid "Number of columns"
2398
+ msgstr ""
2399
+
2400
+ msgid "Add container"
2401
+ msgstr ""
2402
+
2403
+ msgid "Add .row class"
2404
+ msgstr ""
2405
+
2406
+ msgid "Compact HTML structure"
2407
+ msgstr ""
2408
+
2409
+ msgid "Detailed HTML structure"
2410
+ msgstr ""
2411
+
2412
+ msgid "Table-based grid options"
2413
+ msgstr ""
2414
+
2415
+ msgid "Table options"
2416
+ msgstr ""
2417
+
2418
+ msgid "Include field names in table headings"
2419
+ msgstr ""
2420
+
2421
+ msgid "Select the fields to include in the layout"
2422
+ msgstr ""
2423
+
2424
+ msgid "Add field"
2425
+ msgstr ""
2426
+
2427
+ msgid "Where do you want to insert this layout?"
2428
+ msgstr ""
2429
+
2430
+ msgid "In the current cursor position"
2431
+ msgstr ""
2432
+
2433
+ msgid "Replace existing layout"
2434
+ msgstr ""
2435
+
2436
+ msgid "Previous"
2437
+ msgstr ""
2438
+
2439
+ msgid "Next"
2440
+ msgstr ""
2441
+
2442
+ msgid "Insert a filter field"
2443
+ msgstr ""
2444
+
2445
+ msgid "Preview"
2446
+ msgstr ""
2447
+
2448
+ msgid "Select what to filter to see the preview here"
2449
+ msgstr ""
2450
+
2451
+ msgid "Defaults"
2452
+ msgstr ""
2453
+
2454
+ msgid "Select what to filter by :"
2455
+ msgstr ""
2456
+
2457
+ msgid "--- Please select ---"
2458
+ msgstr ""
2459
+
2460
+ msgid "Use this kind of input:"
2461
+ msgstr ""
2462
+
2463
+ msgid "Types ancestors:"
2464
+ msgstr ""
2465
+
2466
+ msgid "Checkbox label:"
2467
+ msgstr ""
2468
+
2469
+ msgid "When the checkbox is not checked:"
2470
+ msgstr ""
2471
+
2472
+ msgid "Return all results"
2473
+ msgstr ""
2474
+
2475
+ msgid "Return only results with this field unchecked"
2476
+ msgstr ""
2477
+
2478
+ msgid "Default label:"
2479
+ msgstr ""
2480
+
2481
+ msgid "Options for this input:"
2482
+ msgstr ""
2483
+
2484
+ msgid "Use existing custom field values"
2485
+ msgstr ""
2486
+
2487
+ msgid "Use manually entered values"
2488
+ msgstr ""
2489
+
2490
+ msgid "Values:"
2491
+ msgstr ""
2492
+
2493
+ msgid "Display values:"
2494
+ msgstr ""
2495
+
2496
+ msgid "Default value:"
2497
+ msgstr ""
2498
+
2499
+ msgid "Leave blank for no default"
2500
+ msgstr ""
2501
+
2502
+ msgid "Format of the options:"
2503
+ msgstr ""
2504
+
2505
+ msgid "You can use placeholders like %%NAME%% or %%COUNT%%"
2506
+ msgstr ""
2507
+
2508
+ msgid "Leave empty to display just the option name"
2509
+ msgstr ""
2510
+
2511
+ msgid "Sort values:"
2512
+ msgstr ""
2513
+
2514
+ msgid "Taxonomy order:"
2515
+ msgstr ""
2516
+
2517
+ msgid "Taxonomy order by:"
2518
+ msgstr ""
2519
+
2520
+ msgid "Hide empty terms:"
2521
+ msgstr ""
2522
+
2523
+ msgid "Do not show taxonomy terms with no posts attached"
2524
+ msgstr ""
2525
+
2526
+ msgid "Advanced:"
2527
+ msgstr ""
2528
+
2529
+ msgid "Refer to this field as:"
2530
+ msgstr ""
2531
+
2532
+ msgid "Compare this values as:"
2533
+ msgstr ""
2534
+
2535
+ msgid "Search results for \"%s\""
2536
+ msgstr ""
2537
+
2538
+ msgid "Search results for \"%s\" in trashed WordPress Archives"
2539
+ msgstr ""
2540
+
2541
+ msgid "Search WordPress Archives"
2542
+ msgstr ""
2543
+
2544
+ msgid "This WordPress Archive isn't being used for any loops."
2545
+ msgstr ""
2546
+
2547
+ msgid "No WordPress Archives in trash matched your criteria."
2548
+ msgstr ""
2549
+
2550
+ msgid "No WordPress Archives in trash."
2551
+ msgstr ""
2552
+
2553
+ msgid "No WordPress Archives matched your criteria."
2554
+ msgstr ""
2555
+
2556
+ msgid "WordPress Archives"
2557
+ msgstr ""
2558
+
2559
+ msgid "WordPress Archive moved to the Trash"
2560
+ msgstr ""
2561
+
2562
+ msgid "Undo"
2563
+ msgstr ""
2564
+
2565
+ msgid "WordPress Archive restored from the Trash"
2566
+ msgstr ""
2567
+
2568
+ msgid "WordPress Archive permanently deleted"
2569
+ msgstr ""
2570
+
2571
+ msgid "All loops have a WordPress Archive assigned"
2572
+ msgstr ""
2573
+
2574
+ msgid "Arrange by"
2575
+ msgstr ""
2576
+
2577
+ msgid "Usage"
2578
+ msgstr ""
2579
+
2580
+ msgid "WordPress Archives let you customize the output of standard Archive pages."
2581
+ msgstr ""
2582
+
2583
+ msgid "Create your first WordPress Archive"
2584
+ msgstr ""
2585
+
2586
+ msgid "Published"
2587
+ msgstr ""
2588
+
2589
+ msgid "Trash"
2590
+ msgstr ""
2591
+
2592
+ msgid "Archive usage"
2593
+ msgstr ""
2594
+
2595
+ msgid "Action"
2596
+ msgstr ""
2597
+
2598
+ msgid "Choose"
2599
+ msgstr ""
2600
+
2601
+ msgid "Change archive usage"
2602
+ msgstr ""
2603
+
2604
+ msgid "Move to trash"
2605
+ msgstr ""
2606
+
2607
+ msgid "Restore from trash"
2608
+ msgstr ""
2609
+
2610
+ msgid "Return"
2611
+ msgstr ""
2612
+
2613
+ msgid "Archive loop"
2614
+ msgstr ""
2615
+
2616
+ msgid "WordPress Archive used"
2617
+ msgstr ""
2618
+
2619
+ msgid "Used for"
2620
+ msgstr ""
2621
+
2622
+ msgid "Create a WordPres Archive for this loop"
2623
+ msgstr ""
2624
+
2625
+ msgid "Change"
2626
+ msgstr ""
2627
+
2628
+ msgid "Search results for \"%s\" in trashed Content Templates"
2629
+ msgstr ""
2630
+
2631
+ msgid "No Content Templates in trash matched your criteria."
2632
+ msgstr ""
2633
+
2634
+ msgid "No Content Templates matched your criteria."
2635
+ msgstr ""
2636
+
2637
+ msgid "No Content Templates in trash."
2638
+ msgstr ""
2639
+
2640
+ msgid "Enter new title"
2641
+ msgstr ""
2642
+
2643
+ msgid "There are %s single posts that are currently using this template."
2644
+ msgstr ""
2645
+
2646
+ msgid "Clear single %s"
2647
+ msgstr ""
2648
+
2649
+ msgid "There is no general Content Template asigned to single %s, but %s individual %s have a Content Template asigned to them."
2650
+ msgstr ""
2651
+
2652
+ msgid "Would you like to clear them?"
2653
+ msgstr ""
2654
+
2655
+ msgid " (single)"
2656
+ msgstr ""
2657
+
2658
+ msgid "Bind %u %s "
2659
+ msgstr ""
2660
+
2661
+ msgid "No Post types/Taxonomies assigned"
2662
+ msgstr ""
2663
+
2664
+ msgid "Content template for "
2665
+ msgstr ""
2666
+
2667
+ msgid "Create a Content Template for single %s"
2668
+ msgstr ""
2669
+
2670
+ msgid "Clear %d %s"
2671
+ msgstr ""
2672
+
2673
+ msgid "Add a new Content Template for this post type"
2674
+ msgstr ""
2675
+
2676
+ msgid "Add a new Content Template for this taxonomy"
2677
+ msgstr ""
2678
+
2679
+ msgid "Content Template moved to the Trash"
2680
+ msgstr ""
2681
+
2682
+ msgid "Content Template restored from the Trash"
2683
+ msgstr ""
2684
+
2685
+ msgid "Content Template permanently deleted"
2686
+ msgstr ""
2687
+
2688
+ msgid "Usage for single page"
2689
+ msgstr ""
2690
+
2691
+ msgid "Usage for custom post archives"
2692
+ msgstr ""
2693
+
2694
+ msgid "Usage for taxonomy archives"
2695
+ msgstr ""
2696
+
2697
+ msgid "Search Views:"
2698
+ msgstr ""
2699
+
2700
+ msgid "Content Templates let you design single pages."
2701
+ msgstr ""
2702
+
2703
+ msgid "Add new Content Template"
2704
+ msgstr ""
2705
+
2706
+ msgid "Used on"
2707
+ msgstr ""
2708
+
2709
+ msgid "Change template usage"
2710
+ msgstr ""
2711
+
2712
+ msgid "Duplicate"
2713
+ msgstr ""
2714
+
2715
+ msgid "Delete Content Template"
2716
+ msgstr ""
2717
+
2718
+ msgid "Are you sure you want to delete it?"
2719
+ msgstr ""
2720
+
2721
+ msgid "Duplicate Content Template"
2722
+ msgstr ""
2723
+
2724
+ msgid "Name this Content Template"
2725
+ msgstr ""
2726
+
2727
+ msgid "Enter name here"
2728
+ msgstr ""
2729
+
2730
+ msgid "Template used"
2731
+ msgstr ""
2732
+
2733
+ msgid "Change Content Template"
2734
+ msgstr ""
2735
+
2736
+ msgid "Content updated"
2737
+ msgstr ""
2738
+
2739
+ msgid "Content not saved"
2740
+ msgstr ""
2741
+
2742
+ msgid "Update"
2743
+ msgstr ""
2744
+
2745
+ msgid "Open CSS editor"
2746
+ msgstr ""
2747
+
2748
+ msgid "Close CSS editor"
2749
+ msgstr ""
2750
+
2751
+ msgid "Open JS editor"
2752
+ msgstr ""
2753
+
2754
+ msgid "Close JS editor"
2755
+ msgstr ""
2756
+
2757
+ msgid "Data updated"
2758
+ msgstr ""
2759
+
2760
+ msgid "Data not saved"
2761
+ msgstr ""
2762
+
2763
+ msgid "Filter by <strong>%s</strong>"
2764
+ msgstr ""
2765
+
2766
+ msgid "Your %s filters are using an internal \"OR\" kind of relationship, and dependant parametric search for that filters needs \"AND\" relationships."
2767
+ msgstr ""
2768
+
2769
+ msgid "Close advanced options"
2770
+ msgstr ""
2771
+
2772
+ msgid "Advanced options"
2773
+ msgstr ""
2774
+
2775
+ msgid "Pagination"
2776
+ msgstr ""
2777
+
2778
+ msgid "Parametric search settings"
2779
+ msgstr ""
2780
+
2781
+ msgid "Would you like to make this parametric search a dependant one?"
2782
+ msgstr ""
2783
+
2784
+ msgid "Insert submit button"
2785
+ msgstr ""
2786
+
2787
+ msgid "Create a reset button for this parametric search."
2788
+ msgstr ""
2789
+
2790
+ msgid "Insert clear form button"
2791
+ msgstr ""
2792
+
2793
+ msgid "Create a spinner container for this parametric search."
2794
+ msgstr ""
2795
+
2796
+ msgid "Container type:"
2797
+ msgstr ""
2798
+
2799
+ msgid "Division"
2800
+ msgstr ""
2801
+
2802
+ msgid "Paragraph"
2803
+ msgstr ""
2804
+
2805
+ msgid "Span"
2806
+ msgstr ""
2807
+
2808
+ msgid "Container classname:"
2809
+ msgstr ""
2810
+
2811
+ msgid "Spinner:"
2812
+ msgstr ""
2813
+
2814
+ msgid "Do not show the spinner"
2815
+ msgstr ""
2816
+
2817
+ msgid "Show the spinner before the text"
2818
+ msgstr ""
2819
+
2820
+ msgid "Show the spinner after the text"
2821
+ msgstr ""
2822
+
2823
+ msgid "Content:"
2824
+ msgstr ""
2825
+
2826
+ msgid "Insert spinner container"
2827
+ msgstr ""
2828
+
2829
+ msgid "Only Views listing posts can have parametric search inputs."
2830
+ msgstr ""
2831
+
2832
+ msgid "This View has some query filters that are missing from the form. Maybe you have removed them:"
2833
+ msgstr ""
2834
+
2835
+ msgid "Can they also be removed from the query filtering?"
2836
+ msgstr ""
2837
+
2838
+ msgid "Yes (recommended)"
2839
+ msgstr ""
2840
+
2841
+ msgid "No"
2842
+ msgstr ""
2843
+
2844
+ msgid "When to update the Views results"
2845
+ msgstr ""
2846
+
2847
+ msgid "Update the View results only when submitting the form"
2848
+ msgstr ""
2849
+
2850
+ msgid "Update the View results every time an input changes"
2851
+ msgstr ""
2852
+
2853
+ msgid "Which options to display in the form inputs"
2854
+ msgstr ""
2855
+
2856
+ msgid "Fix filters relationship"
2857
+ msgstr ""
2858
+
2859
+ msgid "Always show all values for inputs"
2860
+ msgstr ""
2861
+
2862
+ msgid "Show only available options for each input"
2863
+ msgstr ""
2864
+
2865
+ msgid "Choose if you want to hide or disable irrelevant options for inputs:"
2866
+ msgstr ""
2867
+
2868
+ msgid "Input type"
2869
+ msgstr ""
2870
+
2871
+ msgid "Disable / Hide"
2872
+ msgstr ""
2873
+
2874
+ msgid "Select dropdown"
2875
+ msgstr ""
2876
+
2877
+ msgid "Disable"
2878
+ msgstr ""
2879
+
2880
+ msgid "Multi-select"
2881
+ msgstr ""
2882
+
2883
+ msgid "Radio inputs"
2884
+ msgstr ""
2885
+
2886
+ msgid "Checkboxes"
2887
+ msgstr ""
2888
+
2889
+ msgid "Spinners settings"
2890
+ msgstr ""
2891
+
2892
+ msgid "You can display a spinner when the View results update"
2893
+ msgstr ""
2894
+
2895
+ msgid "No spinner graphics"
2896
+ msgstr ""
2897
+
2898
+ msgid "Custom spinner graphics"
2899
+ msgstr ""
2900
+
2901
+ msgid "Upload Image"
2902
+ msgstr ""
2903
+
2904
+ msgid "Built in Views spinner graphics"
2905
+ msgstr ""
2906
+
2907
+ msgid "Javascript settings"
2908
+ msgstr ""
2909
+
2910
+ msgid "You can execute the following javascript callbacks before and after the View results are updated."
2911
+ msgstr ""
2912
+
2913
+ msgid "Javascript function to execute before every AJAX update:"
2914
+ msgstr ""
2915
+
2916
+ msgid "Javascript function to execute after every AJAX update:"
2917
+ msgstr ""
2918
+
2919
+ msgid "Submit button settings"
2920
+ msgstr ""
2921
+
2922
+ msgid "When the parametric search updates the results on the fly, how should the submit button work?"
2923
+ msgstr ""
2924
+
2925
+ msgid "Submit the form without reloading the page"
2926
+ msgstr ""
2927
+
2928
+ msgid "Submit the form and reload the page"
2929
+ msgstr ""
2930
+
2931
+ msgid "Do not show this button"
2932
+ msgstr ""
2933
+
2934
+ msgid "There are no parametric search inputs in this View."
2935
+ msgstr ""
2936
+
2937
+ msgid "Learn more about parametric search"
2938
+ msgstr ""
2939
+
2940
+ msgid "Filter the results"
2941
+ msgstr ""
2942
+
2943
+ msgid "%sLearn about filtering by usermeta fields%s"
2944
+ msgstr ""
2945
+
2946
+ msgid "Add a filter"
2947
+ msgstr ""
2948
+
2949
+ msgid "Add another filter"
2950
+ msgstr ""
2951
+
2952
+ msgid "This field can not be empty"
2953
+ msgstr ""
2954
+
2955
+ msgid "Only lowercase letters, numbers, hyphens and underscores allowed as URL parameters"
2956
+ msgstr ""
2957
+
2958
+ msgid "Only lowercase letters and numbers allowed as shortcode attributes"
2959
+ msgstr ""
2960
+
2961
+ msgid "This is a word reserved by WordPress"
2962
+ msgstr ""
2963
+
2964
+ msgid "This is a word reserved by any of the ToolSet plugins"
2965
+ msgstr ""
2966
+
2967
+ msgid "There is a post type named like that"
2968
+ msgstr ""
2969
+
2970
+ msgid "There is a taxonomy named like that"
2971
+ msgstr ""
2972
+
2973
+ msgid "The posts you want to display are not hierarchical, so this filter will not work"
2974
+ msgstr ""
2975
+
2976
+ msgid "The taxonomy you want to display has changed, so this filter needs some action"
2977
+ msgstr ""
2978
+
2979
+ msgid "or %sEdit the filter and delete specific taxonomy filters%s"
2980
+ msgstr ""
2981
+
2982
+ msgid "or %sEdit the filter and delete specific custom field filters%s"
2983
+ msgstr ""
2984
+
2985
+ msgid "or %sEdit the filter and delete specific usermeta field filters%s"
2986
+ msgstr ""
2987
+
2988
+ msgid "Relationship to use when querying with multiple usermeta fields:"
2989
+ msgstr ""
2990
+
2991
+ msgid "Select what to filter by:"
2992
+ msgstr ""
2993
+
2994
+ msgid "Add filter"
2995
+ msgstr ""
2996
+
2997
+ msgid "Delete taxonomy filters"
2998
+ msgstr ""
2999
+
3000
+ msgid "There are more than one taxonomy filters. What would you like to do?"
3001
+ msgstr ""
3002
+
3003
+ msgid "Delete all taxonomy filters"
3004
+ msgstr ""
3005
+
3006
+ msgid "Delete custom field filters"
3007
+ msgstr ""
3008
+
3009
+ msgid "There are more than one custom field filters. What would you like to do?"
3010
+ msgstr ""
3011
+
3012
+ msgid "Delete all custom field filters"
3013
+ msgstr ""
3014
+
3015
+ msgid "Delete usermeta field filters"
3016
+ msgstr ""
3017
+
3018
+ msgid "There are more than one usermeta field filters. What would you like to do?"
3019
+ msgstr ""
3020
+
3021
+ msgid "Delete all usermeta field filters"
3022
+ msgstr ""
3023
+
3024
+ msgid "Aditional Javascript files"
3025
+ msgstr ""
3026
+
3027
+ msgid "Data saved"
3028
+ msgstr ""
3029
+
3030
+ msgid "Additional Javascript files"
3031
+ msgstr ""
3032
+
3033
+ msgid "Pointer header"
3034
+ msgstr ""
3035
+
3036
+ msgid "Tooltip content. Lorem ipsum dolor et umni der lanos"
3037
+ msgstr ""
3038
+
3039
+ msgid "Additional Javascript files to be loaded with this View (comma separated): "
3040
+ msgstr ""
3041
+
3042
+ msgid "Layout HTML/CSS/JS"
3043
+ msgstr ""
3044
+
3045
+ msgid "Content Template was successfully assigned to view."
3046
+ msgstr ""
3047
+
3048
+ msgid "This Content Template already assigned to this view."
3049
+ msgstr ""
3050
+
3051
+ msgid "Content Template was successfully unassigned from view."
3052
+ msgstr ""
3053
+
3054
+ msgid "Content Template was successfully updated."
3055
+ msgstr ""
3056
+
3057
+ msgid "No Content Templates assigned to this view"
3058
+ msgstr ""
3059
+
3060
+ msgid "There are no Content Templates for this View. You can add a Content Template using the Content Template button in the Layout editor tool bar."
3061
+ msgstr ""
3062
+
3063
+ msgid "A Content Template with that name already exists. Please use another name."
3064
+ msgstr ""
3065
+
3066
+ msgid "Remove this Content Template"
3067
+ msgstr ""
3068
+
3069
+ msgid "Limit and offset options updated"
3070
+ msgstr ""
3071
+
3072
+ msgid "Limit and offset options not saved"
3073
+ msgstr ""
3074
+
3075
+ msgid "Display "
3076
+ msgstr ""
3077
+
3078
+ msgid "No limit"
3079
+ msgstr ""
3080
+
3081
+ msgid "items "
3082
+ msgstr ""
3083
+
3084
+ msgid "Skip first"
3085
+ msgstr ""
3086
+
3087
+ msgid "items"
3088
+ msgstr ""
3089
+
3090
+ msgid "Loops selection"
3091
+ msgstr ""
3092
+
3093
+ msgid "Loop selection updated"
3094
+ msgstr ""
3095
+
3096
+ msgid "Loop selection not saved"
3097
+ msgstr ""
3098
+
3099
+ msgid "ID"
3100
+ msgstr ""
3101
+
3102
+ msgid "Count"
3103
+ msgstr ""
3104
+
3105
+ msgid "Name"
3106
+ msgstr ""
3107
+
3108
+ msgid "Slug"
3109
+ msgstr ""
3110
+
3111
+ msgid "Term_group"
3112
+ msgstr ""
3113
+
3114
+ msgid "None"
3115
+ msgstr ""
3116
+
3117
+ msgid "user login"
3118
+ msgstr ""
3119
+
3120
+ msgid "user id"
3121
+ msgstr ""
3122
+
3123
+ msgid "user name"
3124
+ msgstr ""
3125
+
3126
+ msgid "user display name"
3127
+ msgstr ""
3128
+
3129
+ msgid "user nicename"
3130
+ msgstr ""
3131
+
3132
+ msgid "user email"
3133
+ msgstr ""
3134
+
3135
+ msgid "user url"
3136
+ msgstr ""
3137
+
3138
+ msgid "user registered date"
3139
+ msgstr ""
3140
+
3141
+ msgid "user post count"
3142
+ msgstr ""
3143
+
3144
+ msgid "Sorting options updated"
3145
+ msgstr ""
3146
+
3147
+ msgid "Sorting options not saved"
3148
+ msgstr ""
3149
+
3150
+ msgid "Order by: "
3151
+ msgstr ""
3152
+
3153
+ msgid "Pagination and random ordering do not work together and would produce unexpected results. Please disable pagination or random ordering."
3154
+ msgstr ""
3155
+
3156
+ msgid "post id"
3157
+ msgstr ""
3158
+
3159
+ msgid "last modified"
3160
+ msgstr ""
3161
+
3162
+ msgid "Descending"
3163
+ msgstr ""
3164
+
3165
+ msgid "Ascending"
3166
+ msgstr ""
3167
+
3168
+ msgid "This is a preview"
3169
+ msgstr ""
3170
+
3171
+ msgid "Choose pagination control type"
3172
+ msgstr ""
3173
+
3174
+ msgid "Showing page"
3175
+ msgstr ""
3176
+
3177
+ msgid "Choose page"
3178
+ msgstr ""
3179
+
3180
+ msgid "of"
3181
+ msgstr ""
3182
+
3183
+ msgid "Pagination and Sliders settings"
3184
+ msgstr ""
3185
+
3186
+ msgid "Fade fast"
3187
+ msgstr ""
3188
+
3189
+ msgid "Fade slow"
3190
+ msgstr ""
3191
+
3192
+ msgid "Pagination settings updated"
3193
+ msgstr ""
3194
+
3195
+ msgid "Pagination settings not saved"
3196
+ msgstr ""
3197
+
3198
+ msgid "All query results will display."
3199
+ msgstr ""
3200
+
3201
+ msgid "Pagination enabled with manual transition"
3202
+ msgstr ""
3203
+
3204
+ msgid "The query results will display in pages, which visitors will switch."
3205
+ msgstr ""
3206
+
3207
+ msgid "Pagination enabled with automatic transition"
3208
+ msgstr ""
3209
+
3210
+ msgid "The query results will display in pages, which will switch automatically (good for sliders)."
3211
+ msgstr ""
3212
+
3213
+ msgid "Options for manual pagination"
3214
+ msgstr ""
3215
+
3216
+ msgid "Number of items per page:"
3217
+ msgstr ""
3218
+
3219
+ msgid "Pagination updates the entire page"
3220
+ msgstr ""
3221
+
3222
+ msgid "Pagination updates only the view (use AJAX)"
3223
+ msgstr ""
3224
+
3225
+ msgid "Transition effect:"
3226
+ msgstr ""
3227
+
3228
+ msgid "with duration"
3229
+ msgstr ""
3230
+
3231
+ msgid "miliseconds"
3232
+ msgstr ""
3233
+
3234
+ msgid "Please add a numeric value"
3235
+ msgstr ""
3236
+
3237
+ msgid "Preload images before transition"
3238
+ msgstr ""
3239
+
3240
+ msgid "Options for automatic pagination"
3241
+ msgstr ""
3242
+
3243
+ msgid "Show each page for:"
3244
+ msgstr ""
3245
+
3246
+ msgid "seconds"
3247
+ msgstr ""
3248
+
3249
+ msgid " <- Please add a numeric value"
3250
+ msgstr ""
3251
+
3252
+ msgid "Cache pages"
3253
+ msgstr ""
3254
+
3255
+ msgid "Pre-load the next and previous pages - avoids loading delays when users move between pages"
3256
+ msgstr ""
3257
+
3258
+ msgid "Pages to pre-load: "
3259
+ msgstr ""
3260
+
3261
+ msgid "Spinners"
3262
+ msgstr ""
3263
+
3264
+ msgid "Spinner graphics from Views"
3265
+ msgstr ""
3266
+
3267
+ msgid "My custom spinner graphics"
3268
+ msgstr ""
3269
+
3270
+ msgid "Callback function"
3271
+ msgstr ""
3272
+
3273
+ msgid "Javascript function to execute after the pagination transition has been completed:"
3274
+ msgstr ""
3275
+
3276
+ msgid "Would you like to insert transition controls for the pagination?"
3277
+ msgstr ""
3278
+
3279
+ msgid "Pagination controls"
3280
+ msgstr ""
3281
+
3282
+ msgid "Current page number"
3283
+ msgstr ""
3284
+
3285
+ msgid "Number of pages"
3286
+ msgstr ""
3287
+
3288
+ msgid "Page selector using"
3289
+ msgstr ""
3290
+
3291
+ msgid "dropdown"
3292
+ msgstr ""
3293
+
3294
+ msgid "links"
3295
+ msgstr ""
3296
+
3297
+ msgid "Next and previous page controls"
3298
+ msgstr ""
3299
+
3300
+ msgid "Pagination display"
3301
+ msgstr ""
3302
+
3303
+ msgid "Don't show pagination controls if there is only one page"
3304
+ msgstr ""
3305
+
3306
+ msgid "Insert pagination"
3307
+ msgstr ""
3308
+
3309
+ msgid "What pagination controls would you like to insert?"
3310
+ msgstr ""
3311
+
3312
+ msgid "Query options updated"
3313
+ msgstr ""
3314
+
3315
+ msgid "Query options not saved"
3316
+ msgstr ""
3317
+
3318
+ msgid "Don't include current page in query result"
3319
+ msgstr ""
3320
+
3321
+ msgid "Don't show empty terms"
3322
+ msgstr ""
3323
+
3324
+ msgid "Include terms that have non-empty descendants"
3325
+ msgstr ""
3326
+
3327
+ msgid "Include children in the post count"
3328
+ msgstr ""
3329
+
3330
+ msgid "Don't show current logged user."
3331
+ msgstr ""
3332
+
3333
+ msgid "Content selection updated"
3334
+ msgstr ""
3335
+
3336
+ msgid "Content selection not saved"
3337
+ msgstr ""
3338
+
3339
+ msgid "This View will display:"
3340
+ msgstr ""
3341
+
3342
+ msgid "Post types"
3343
+ msgstr ""
3344
+
3345
+ msgid "Users"
3346
+ msgstr ""
3347
+
3348
+ msgid "Any role"
3349
+ msgstr ""
3350
+
3351
+ msgid "No post type has been selected, so this View will list posts of any type."
3352
+ msgstr ""
3353
+
3354
+ msgid "If this is not what you want to do, please select any post type from the checkboxes above."
3355
+ msgstr ""
3356
+
3357
+ msgid "No taxonomy has been selected, so this View will list nothing. Maybe the selected taxonomy no longer exists?"
3358
+ msgstr ""
3359
+
3360
+ msgid "Please select any of the available taxonomies from the list above."
3361
+ msgstr ""
3362
+
3363
+ msgid "Search results for \"%s\" in trashed Views"
3364
+ msgstr ""
3365
+
3366
+ msgid "Enter title here"
3367
+ msgstr ""
3368
+
3369
+ msgid "Now give this View a name"
3370
+ msgstr ""
3371
+
3372
+ msgid "No Views in trash matched your criteria."
3373
+ msgstr ""
3374
+
3375
+ msgid "No Views in trash."
3376
+ msgstr ""
3377
+
3378
+ msgid "No Views matched your criteria."
3379
+ msgstr ""
3380
+
3381
+ msgid "Add new View"
3382
+ msgstr ""
3383
+
3384
+ msgid "View moved to the Trash"
3385
+ msgstr ""
3386
+
3387
+ msgid "View restored from the Trash"
3388
+ msgstr ""
3389
+
3390
+ msgid "View permanently deleted"
3391
+ msgstr ""
3392
+
3393
+ msgid "Views load content from the database and display on the site."
3394
+ msgstr ""
3395
+
3396
+ msgid "Create your first View"
3397
+ msgstr ""
3398
+
3399
+ msgid "Add a new View"
3400
+ msgstr ""
3401
+
3402
+ msgid "A View loads content from the database and displays with your HTML."
3403
+ msgstr ""
3404
+
3405
+ msgid " What kind of display do you want to create?"
3406
+ msgstr ""
3407
+
3408
+ msgid "Display all results"
3409
+ msgstr ""
3410
+
3411
+ msgid "The View will output all the results returned from the query section."
3412
+ msgstr ""
3413
+
3414
+ msgid "Display the results with pagination"
3415
+ msgstr ""
3416
+
3417
+ msgid "The View will display the query results in pages."
3418
+ msgstr ""
3419
+
3420
+ msgid "Display the results as a slider"
3421
+ msgstr ""
3422
+
3423
+ msgid "The View will display the query results as slides."
3424
+ msgstr ""
3425
+
3426
+ msgid "Display the results as a parametric search"
3427
+ msgstr ""
3428
+
3429
+ msgid "Visitors will be able to search through your content using different search criteria."
3430
+ msgstr ""
3431
+
3432
+ msgid "Full custom display mode"
3433
+ msgstr ""
3434
+
3435
+ msgid "See all the View controls open and set up things manually.."
3436
+ msgstr ""
3437
+
3438
+ msgid "Name this View"
3439
+ msgstr ""
3440
+
3441
+ msgid "Create View"
3442
+ msgstr ""
3443
+
3444
+ msgid "Delete View"
3445
+ msgstr ""
3446
+
3447
+ msgid "Are you sure want delete this View? "
3448
+ msgstr ""
3449
+
3450
+ msgid "Please use the Scan button first to be sure that it is not used anywhere."
3451
+ msgstr ""
3452
+
3453
+ msgid "Duplicate View"
3454
+ msgstr ""
3455
+
3456
+ msgid "Scan"
3457
+ msgstr ""
3458
+
3459
+ msgid "Nothing found"
3460
+ msgstr ""
3461
+
3462
+ msgid "An Unexpected HTTP Error occurred during the API request."
3463
+ msgstr ""
3464
+
3465
+ msgid "An unknown error occurred."
3466
+ msgstr ""
3467
+
3468
+ msgid "No content templates found"
3469
+ msgstr ""
3470
+
3471
+ msgid "No content templates found in Trash"
3472
+ msgstr ""
3473
+
3474
+ msgid "Syntax Highlight On"
3475
+ msgstr ""
3476
+
3477
+ msgid "Syntax Highlight Off"
3478
+ msgstr ""
3479
+
3480
+ msgid "Content Template Settings"
3481
+ msgstr ""
3482
+
3483
+ msgid "Content Template CSS and JS"
3484
+ msgstr ""
3485
+
3486
+ msgid "Edit content template"
3487
+ msgstr ""
3488
+
3489
+ msgid "There are no Content Templates being used for single post types."
3490
+ msgstr ""
3491
+
3492
+ msgid "There are no Content Templates being used for post types in taxonomy archive loops."
3493
+ msgstr ""
3494
+
3495
+ msgid "%d %ss use a different template:"
3496
+ msgstr ""
3497
+
3498
+ msgid "Update all %ss now"
3499
+ msgstr ""
3500
+
3501
+ msgid "<span id=\"%s\">%d</span> %ss have updated to use this template."
3502
+ msgstr ""
3503
+
3504
+ msgid "All %s are using this template"
3505
+ msgstr ""
3506
+
3507
+ msgid "There are no %s"
3508
+ msgstr ""
3509
+
3510
+ msgid "There are no Content Templates being used for Taxonomy archive loops."
3511
+ msgstr ""
3512
+
3513
+ msgid "<strong>This template includes single-ended shortcodes</strong>. Please close all shortcodes to avoid processing errors. %sRead more%s"
3514
+ msgstr ""
3515
+
3516
+ msgid "Click to toggle"
3517
+ msgstr ""
3518
+
3519
+ msgid "All %ss were successfully updated"
3520
+ msgstr ""
3521
+
3522
+ msgid "This Content Template will display in the ‘content’ area of "
3523
+ msgstr ""
3524
+
3525
+ msgid " the content types you assign it to."
3526
+ msgstr ""
3527
+
3528
+ msgid "It starts empty and you should add fields to it. To add fields, click on the V icon below. You can add HTML and CSS to style the fields and design the page template."
3529
+ msgstr ""
3530
+
3531
+ msgid "Add description"
3532
+ msgstr ""
3533
+
3534
+ msgid "Describe this Content Template"
3535
+ msgstr ""
3536
+
3537
+ msgid "Here you can modify specific CSS and javascript to be used with this Content Template."
3538
+ msgstr ""
3539
+
3540
+ msgid "Open CSS editor"
3541
+ msgstr ""
3542
+
3543
+ msgid "CSS"
3544
+ msgstr ""
3545
+
3546
+ msgid "This is used to add custom CSS to a Content Template."
3547
+ msgstr ""
3548
+
3549
+ msgid "Close CSS editor"
3550
+ msgstr ""
3551
+
3552
+ msgid "Open JS editor"
3553
+ msgstr ""
3554
+
3555
+ msgid "JS"
3556
+ msgstr ""
3557
+
3558
+ msgid "This is used to add custom javascript to a Content Template."
3559
+ msgstr ""
3560
+
3561
+ msgid "Close JS editor"
3562
+ msgstr ""
3563
+
3564
+ msgid "Output mode"
3565
+ msgstr ""
3566
+
3567
+ msgid "Auto-insert paragraphs"
3568
+ msgstr ""
3569
+
3570
+ msgid "Manual paragraphs"
3571
+ msgstr ""
3572
+
3573
+ msgid "Automaticaly paragraph (Normal WordPress output) - add paragraphs an breaks and resolve shortcodes"
3574
+ msgstr ""
3575
+
3576
+ msgid "Manual paragraph (Raw output) - only resolve shortcodes without adding line breaks or paragraphs"
3577
+ msgstr ""
3578
+
3579
+ msgid "Note"
3580
+ msgstr ""
3581
+
3582
+ msgid "These settings are synced with the post in the origin language and you can't change them here. They can only be changed on the post in the original language."
3583
+ msgstr ""
3584
+
3585
+ msgid "Use this Content Template for:"
3586
+ msgstr ""
3587
+
3588
+ msgid "Editing instructions"
3589
+ msgstr ""
3590
+
3591
+ msgid "Theme support for Content Templates"
3592
+ msgstr ""
3593
+
3594
+ msgid "Content Templates modify the content when called from"
3595
+ msgstr ""
3596
+
3597
+ msgid "function. Some themes don't use"
3598
+ msgstr ""
3599
+
3600
+ msgid "function but define their own function."
3601
+ msgstr ""
3602
+
3603
+ msgid "If Content Templates don't work with your theme then you can enter the name of the function your theme uses here:"
3604
+ msgstr ""
3605
+
3606
+ msgid "Don't know the name of your theme function?"
3607
+ msgstr ""
3608
+
3609
+ msgid "Enable debugging and go to a page that should display a Content Template and Views will display the call function name."
3610
+ msgstr ""
3611
+
3612
+ msgid "Settings saved"
3613
+ msgstr ""
3614
+
3615
+ msgid "Translating with WPML"
3616
+ msgstr ""
3617
+
3618
+ msgid "Congratulations! You are running Views and WPML with the String Translation module, so you can easily translate everything."
3619
+ msgstr ""
3620
+
3621
+ msgid "To translate static texts, wrap them in <strong>[wpml-string][/wpml-string]</strong> shortcodes."
3622
+ msgstr ""
3623
+
3624
+ msgid "You are running Views and WPML, but missing the String Translation module."
3625
+ msgstr ""
3626
+
3627
+ msgid "The String Translation"
3628
+ msgstr ""
3629
+
3630
+ msgid "allows translating static texts in your Views and Content Templates."
3631
+ msgstr ""
3632
+
3633
+ msgid "How would you like to translate Content Templates?"
3634
+ msgstr ""
3635
+
3636
+ msgid "Use the same Content Templates for all languages"
3637
+ msgstr ""
3638
+
3639
+ msgid "Create different Content Templates for each language"
3640
+ msgstr ""
3641
+
3642
+ msgid "Need help?"
3643
+ msgstr ""
3644
+
3645
+ msgid "Translating Views and Content Templates with WPML"
3646
+ msgstr ""
3647
+
3648
+ msgid "For single:"
3649
+ msgstr ""
3650
+
3651
+ msgid "For archive loop:"
3652
+ msgstr ""
3653
+
3654
+ msgid "Post Types"
3655
+ msgstr ""
3656
+
3657
+ msgid "Use this Content Template (Single)"
3658
+ msgstr ""
3659
+
3660
+ msgid "Use this Content Template (Archive loop)"
3661
+ msgstr ""
3662
+
3663
+ msgid "Use this Content Template"
3664
+ msgstr ""
3665
+
3666
+ msgid "Single pages:"
3667
+ msgstr ""
3668
+
3669
+ msgid "Templates updated"
3670
+ msgstr ""
3671
+
3672
+ msgid "Post archives:"
3673
+ msgstr ""
3674
+
3675
+ msgid "There are no custom post types archives"
3676
+ msgstr ""
3677
+
3678
+ msgid "Taxonomy archives:"
3679
+ msgstr ""
3680
+
3681
+ msgid "<span style=\"color:red\">*</span> A different Content Template is already assigned to this item"
3682
+ msgstr ""
3683
+
3684
+ msgid "You can’t edit this View because it is in the Trash. Please restore it and try again."
3685
+ msgstr ""
3686
+
3687
+ msgid "Screen Options Tab"
3688
+ msgstr ""
3689
+
3690
+ msgid "The parametric search settings section has unsaved changes, so you can not hide it"
3691
+ msgstr ""
3692
+
3693
+ msgid "Pagination requires the Filter HTML section to be visible."
3694
+ msgstr ""
3695
+
3696
+ msgid "This section has unsaved changes, so you can not hide it"
3697
+ msgstr ""
3698
+
3699
+ msgid "Display Query section help"
3700
+ msgstr ""
3701
+
3702
+ msgid "Display Filter section help"
3703
+ msgstr ""
3704
+
3705
+ msgid "Display Layout section help"
3706
+ msgstr ""
3707
+
3708
+ msgid "View purpose"
3709
+ msgstr ""
3710
+
3711
+ msgid "All"
3712
+ msgstr ""
3713
+
3714
+ msgid "Slider"
3715
+ msgstr ""
3716
+
3717
+ msgid "Parametric"
3718
+ msgstr ""
3719
+
3720
+ msgid "Bootstrap Grid"
3721
+ msgstr ""
3722
+
3723
+ msgid "Full"
3724
+ msgstr ""
3725
+
3726
+ msgid "Note that those Screen Options are set per View."
3727
+ msgstr ""
3728
+
3729
+ msgid "Saved"
3730
+ msgstr ""
3731
+
3732
+ msgid "View saved"
3733
+ msgstr ""
3734
+
3735
+ msgid "View not saved"
3736
+ msgstr ""
3737
+
3738
+ msgid "View moved to trash"
3739
+ msgstr ""
3740
+
3741
+ msgid "View not moved to trash"
3742
+ msgstr ""
3743
+
3744
+ msgid "Title and description updated"
3745
+ msgstr ""
3746
+
3747
+ msgid "Title and description not saved"
3748
+ msgstr ""
3749
+
3750
+ msgid "Show on screen"
3751
+ msgstr ""
3752
+
3753
+ msgid "Query section"
3754
+ msgstr ""
3755
+
3756
+ msgid "Filter section"
3757
+ msgstr ""
3758
+
3759
+ msgid "Layout section"
3760
+ msgstr ""
3761
+
3762
+ msgid "Screen Options"
3763
+ msgstr ""
3764
+
3765
+ msgid "Return to the Layout"
3766
+ msgstr ""
3767
+
3768
+ msgid "Done editing this View?"
3769
+ msgstr ""
3770
+
3771
+ msgid "Close this window and return to the Layout"
3772
+ msgstr ""
3773
+
3774
+ msgid "Save all sections at once"
3775
+ msgstr ""
3776
+
3777
+ msgid "Enter title here"
3778
+ msgstr ""
3779
+
3780
+ msgid "Slug of this View"
3781
+ msgstr ""
3782
+
3783
+ msgid "Describe this View"
3784
+ msgstr ""
3785
+
3786
+ msgid "Done setting up this View?"
3787
+ msgstr ""
3788
+
3789
+ msgid "Taxonomy fields"
3790
+ msgstr ""
3791
+
3792
+ msgid "Using Content Template"
3793
+ msgstr ""
3794
+
3795
+ msgid "You can not leave the title empty."
3796
+ msgstr ""
3797
+
3798
+ msgid "You can not leave the slug empty."
3799
+ msgstr ""
3800
+
3801
+ msgid "The slug can only contain lowercase letters, numbers or dashes."
3802
+ msgstr ""
3803
+
3804
+ msgid "A %s with that name already exists. Please use another name."
3805
+ msgstr ""
3806
+
3807
+ msgid "A %s with that slug already exists. Please use another slug."
3808
+ msgstr ""
3809
+
3810
+ msgid "The View could not be created"
3811
+ msgstr ""
3812
+
3813
+ msgid "Slug not set in the AJAX call"
3814
+ msgstr ""
3815
+
3816
+ msgid "Single pages"
3817
+ msgstr ""
3818
+
3819
+ msgid "Post type archives"
3820
+ msgstr ""
3821
+
3822
+ msgid "Taxonomy archives"
3823
+ msgstr ""
3824
+
3825
+ msgid "Content template name"
3826
+ msgstr ""
3827
+
3828
+ msgid "Don’t use any Content Template for this Post Type"
3829
+ msgstr ""
3830
+
3831
+ msgid "Change Post Type"
3832
+ msgstr ""
3833
+
3834
+ msgid "Don’t use any Content Template for this Taxonomy"
3835
+ msgstr ""
3836
+
3837
+ msgid "Change Taxonomy"
3838
+ msgstr ""
3839
+
3840
+ msgid " use this content template. What do you want to do?"
3841
+ msgstr ""
3842
+
3843
+ msgid "Name of WordPress Archive for"
3844
+ msgstr ""
3845
+
3846
+ msgid "Select WordPress Archive For Loop"
3847
+ msgstr ""
3848
+
3849
+ msgid "Archive views"
3850
+ msgstr ""
3851
+
3852
+ msgid "Don't use a WordPress Archive for this loop"
3853
+ msgstr ""
3854
+
3855
+ msgid "What content will this template be for?"
3856
+ msgstr ""
3857
+
3858
+ msgid "Don't assign to any post type"
3859
+ msgstr ""
3860
+
3861
+ msgid "There are no single post types to assign Content Templates to"
3862
+ msgstr ""
3863
+
3864
+ msgid "There are no post type archives to assign Content Templates to"
3865
+ msgstr ""
3866
+
3867
+ msgid "There are no taxonomy archives to assign Content Templates to"
3868
+ msgstr ""
3869
+
3870
+ msgid "Create a template"
3871
+ msgstr ""
3872
+
3873
+ msgid "A Content Template that is already connected to this View"
3874
+ msgstr ""
3875
+
3876
+ msgid "Connect an existing Content template to this View"
3877
+ msgstr ""
3878
+
3879
+ msgid "Create a new Content Template for this View"
3880
+ msgstr ""
3881
+
3882
+ msgid "Insert shortcode to editor"
3883
+ msgstr ""
3884
+
3885
+ msgid "Add template"
3886
+ msgstr ""
3887
+
3888
+ msgid "Remove the Content Template from the view"
3889
+ msgstr ""
3890
+
3891
+ msgid "This will remove the link between your view and the Content Template. The Content Template will not be deleted."
3892
+ msgstr ""
3893
+
3894
+ msgid "Change Types"
3895
+ msgstr ""
3896
+
3897
+ msgid "Content template in use"
3898
+ msgstr ""
3899
+
3900
+ msgid "Choose a different content template for them: "
3901
+ msgstr ""
3902
+
3903
+ msgid "Select Content Template"
3904
+ msgstr ""
3905
+
3906
+ msgid "Don't use any content template for these items"
3907
+ msgstr ""
3908
+
3909
+ msgid "Ordered List"
3910
+ msgstr ""
3911
+
3912
+ msgid "Unordered List"
3913
+ msgstr ""
3914
+
3915
+ msgid "Grid"
3916
+ msgstr ""
3917
+
3918
+ msgid "Single view for "
3919
+ msgstr ""
3920
+
3921
+ msgid "Archive view for "
3922
+ msgstr ""
3923
+
3924
+ msgid "Loop view for "
3925
+ msgstr ""
3926
+
3927
+ msgid "This View displays results for an"
3928
+ msgstr ""
3929
+
3930
+ msgid "existing WordPress query"
3931
+ msgstr ""
3932
+
3933
+ msgid "No filters selected."
3934
+ msgstr ""
3935
+
3936
+ msgid "You attempted to edit a WordPress Archive that doesn&#8217;t exist. Perhaps it was deleted?"
3937
+ msgstr ""
3938
+
3939
+ msgid "You can’t edit this WordPress Archive because it is in the Trash. Please restore it and try again."
3940
+ msgstr ""
3941
+
3942
+ msgid "Edit WordPress Archive"
3943
+ msgstr ""
3944
+
3945
+ msgid "Edit Layouts Loop View"
3946
+ msgstr ""
3947
+
3948
+ msgid "Loop section"
3949
+ msgstr ""
3950
+
3951
+ msgid "Slug of this WordPress Archive"
3952
+ msgstr ""
3953
+
3954
+ msgid "The layout section styles the WordPress Archive output on the page."
3955
+ msgstr ""
3956
+
3957
+ msgid "The layout-style and fields that you selected generate meta HTML. This meta HTML includes shortcodes and HTML, which you can edit, to fully customize the appearance of this View's content output section."
3958
+ msgstr ""
3959
+
3960
+ msgid "Generate the new layout content"
3961
+ msgstr ""
3962
+
3963
+ msgid "dismiss"
3964
+ msgstr ""
3965
+
3966
+ msgid "The view layout settings will be copied from the original"
3967
+ msgstr ""
3968
+
3969
+ msgid "Using Content Template:"
3970
+ msgstr ""
3971
+
3972
+ msgid "Using Content template:"
3973
+ msgstr ""
3974
+
3975
+ msgid "Fields to include:"
3976
+ msgstr ""
3977
+
3978
+ msgid "Click on <strong>Add field</strong> to insert additional fields. Drag them to reorder, or delete fields that you don't need."
3979
+ msgstr ""
3980
+
3981
+ msgid "Click on <strong>Add field</strong> to insert fields to this View."
3982
+ msgstr ""
3983
+
3984
+ msgid "Prefix"
3985
+ msgstr ""
3986
+
3987
+ msgid "Row Title"
3988
+ msgstr ""
3989
+
3990
+ msgid "Suffix"
3991
+ msgstr ""
3992
+
3993
+ msgid "Want to add complex fields?"
3994
+ msgstr ""
3995
+
3996
+ msgid "Learn about using Content Templates to customize fields."
3997
+ msgstr ""
3998
+
3999
+ msgid "Want to display posts that belong to this taxonomy? Learn about %sinserting child Views to Taxonomy Views%s."
4000
+ msgstr ""
4001
+
4002
+ msgid "Are you sure you want to change the layout?"
4003
+ msgstr ""
4004
+
4005
+ msgid "It appears that you made modifications to the layout."
4006
+ msgstr ""
4007
+
4008
+ msgid " - Use to layout child taxonomy terms"
4009
+ msgstr ""
4010
+
4011
+ msgid " - Use to layout posts for the current taxonomy term"
4012
+ msgstr ""
4013
+
4014
+ msgid "This View selects Taxonomy of type %s"
4015
+ msgstr ""
4016
+
4017
+ msgid ", ordered by %s, %s"
4018
+ msgstr ""
4019
+
4020
+ msgid "Views Pagination"
4021
+ msgstr ""
4022
+
4023
+ msgid "Use as spinner image"
4024
+ msgstr ""
4025
+
4026
+ msgid "View/Edit Meta HTML"
4027
+ msgstr ""
4028
+
4029
+ msgid "<strong>Meta HTML</strong> - This is used to layout the posts found. It gets generated from the View Layout settings and can be modified to suit."
4030
+ msgstr ""
4031
+
4032
+ msgid "Changes can't be applied. It appears that you made manual modifications to the Meta HTML."
4033
+ msgstr ""
4034
+
4035
+ msgid "(your edits will be displayed and you can apply them again)"
4036
+ msgstr ""
4037
+
4038
+ msgid "<strong>Your edits are shown below:</strong>"
4039
+ msgstr ""
4040
+
4041
+ msgid "* These updates will take effect when you save the view."
4042
+ msgstr ""
4043
+
4044
+ msgid "Edit CSS"
4045
+ msgstr ""
4046
+
4047
+ msgid "<strong>CSS</strong> - This is used to add custom CSS to a View layout."
4048
+ msgstr ""
4049
+
4050
+ msgid "Edit JS"
4051
+ msgstr ""
4052
+
4053
+ msgid "<strong>JS</strong> - This is used to add custom javascript to a View layout."
4054
+ msgstr ""
4055
+
4056
+ msgid "Manage Media"
4057
+ msgstr ""
4058
+
4059
+ msgid "<strong>Media</strong> - This is used to add images to a View output."
4060
+ msgstr ""
4061
+
4062
+ msgid "Upload images"
4063
+ msgstr ""
4064
+
4065
+ msgid "Add Media"
4066
+ msgstr ""
4067
+
4068
+ msgid "Edit media items"
4069
+ msgstr ""
4070
+
4071
+ msgid "Edit media items"
4072
+ msgstr ""
4073
+
4074
+ msgid "Close Media manager"
4075
+ msgstr ""
4076
+
4077
+ msgid "Layout style:"
4078
+ msgstr ""
4079
+
4080
+ msgid "Layout the items using a HTML table"
4081
+ msgstr ""
4082
+
4083
+ msgid "Number of columns:"
4084
+ msgstr ""
4085
+
4086
+ msgid "Create a table of items with a column for each field"
4087
+ msgstr ""
4088
+
4089
+ msgid "Items are added to an ordered list"
4090
+ msgstr ""
4091
+
4092
+ msgid "Items are added to an unordered list"
4093
+ msgstr ""
4094
+
4095
+ msgid "* Views requires Types 1.0.2 or greater for best results when adding fields."
4096
+ msgstr ""
4097
+
4098
+ msgid "Log into <a href=\"%s\">your account</a> and go to <a href=\"%s\">affiliate settings</a> for details."
4099
+ msgstr ""
4100
+
4101
+ msgid "Views Import / Export"
4102
+ msgstr ""
4103
+
4104
+ msgid "Export Views, WordPress Archives and Content Templates"
4105
+ msgstr ""
4106
+
4107
+ msgid "Download all Views, WordPress Archives and Content Templates"
4108
+ msgstr ""
4109
+
4110
+ msgid "When importing to theme:"
4111
+ msgstr ""
4112
+
4113
+ msgid "ask user for approval"
4114
+ msgstr ""
4115
+
4116
+ msgid "import automatically"
4117
+ msgstr ""
4118
+
4119
+ msgid "Affiliate details for theme designers:"
4120
+ msgstr ""
4121
+
4122
+ msgid "Affiliate ID:"
4123
+ msgstr ""
4124
+
4125
+ msgid "Affiliate Key:"
4126
+ msgstr ""
4127
+
4128
+ msgid "You only need to enter affiliate settings if you are a theme designer and want to receive affiliate commission."
4129
+ msgstr ""
4130
+
4131
+ msgid "Filter"
4132
+ msgstr ""
4133
+
4134
+ msgid "This View displays results for an <strong>existing WordPress query</strong>"
4135
+ msgstr ""
4136
+
4137
+ msgid "How this Content Template is used"
4138
+ msgstr ""
4139
+
4140
+ msgid "Fields used"
4141
+ msgstr ""
4142
+
4143
+ msgid "Import/Export"
4144
+ msgstr ""
4145
+
4146
+ msgid "Help"
4147
+ msgstr ""
4148
+
4149
+ msgid "Use <strong>Content Templates</strong> to design single pages in your site. "
4150
+ msgstr ""
4151
+
4152
+ msgid "This page lists the <strong>Content Templates</strong> that you have created and allows you to create new ones."
4153
+ msgstr ""
4154
+
4155
+ msgid "The ‘arrange by’ line, at the top of the page, lets you list the <strong>Content Templates</strong> by their name or by how they are used in the site."
4156
+ msgstr ""
4157
+
4158
+ msgid "Click on the name of a Content Template to edit it or create new <strong>Content Templates</strong> using the ‘Add’ buttons."
4159
+ msgstr ""
4160
+
4161
+ msgid "Content Templates online help"
4162
+ msgstr ""
4163
+
4164
+ msgid "<strong>Content Templates</strong> let you design single pages in your site."
4165
+ msgstr ""
4166
+
4167
+ msgid "To Create a <strong>Content Template</strong>:"
4168
+ msgstr ""
4169
+
4170
+ msgid "Set the title."
4171
+ msgstr ""
4172
+
4173
+ msgid "Add fields to the body. Use the V icon to insert basic fields, custom fields, taxonomy and Views. If you are using CRED, use the C icon to insert CRED forms."
4174
+ msgstr ""
4175
+
4176
+ msgid "Style the output by adding HTML around shortcodes."
4177
+ msgstr ""
4178
+
4179
+ msgid "Use <strong>Views</strong> to load content from the database and display it anyway you choose."
4180
+ msgstr ""
4181
+
4182
+ msgid "This page lists the <strong>Views</strong> in your site. Under ‘actions’, you will find ‘duplicate’ and ‘delete’ for Views."
4183
+ msgstr ""
4184
+
4185
+ msgid "Click on a <strong>Views</strong> name to edit it or create new Views."
4186
+ msgstr ""
4187
+
4188
+ msgid "Views online help"
4189
+ msgstr ""
4190
+
4191
+ msgid "Use <strong>WordPress Archives</strong> to style and design standard listing and archive pages."
4192
+ msgstr ""
4193
+
4194
+ msgid "This page lists the <strong>WordPress Archives</strong> in your site."
4195
+ msgstr ""
4196
+
4197
+ msgid "The ‘arrange by’ line, at the top of the page, lets you list the <strong>WordPress Archives</strong> by their name or by how they are used in the site."
4198
+ msgstr ""
4199
+
4200
+ msgid "Click on the name of a <strong>WordPress Archives</strong> to edit it or create new WordPress Archives using the ‘Add’ buttons."
4201
+ msgstr ""
4202
+
4203
+ msgid "WordPress Archives online help"
4204
+ msgstr ""
4205
+
4206
+ msgid "Use <strong>Views</strong> to filter and display lists in complex and interesting ways. Read more about Views in our user guide:"
4207
+ msgstr ""
4208
+
4209
+ msgid "This page gives you an overview of the Views you have created."
4210
+ msgstr ""
4211
+
4212
+ msgid "It has the following options:"
4213
+ msgstr ""
4214
+
4215
+ msgid "<strong>Add New</strong>: Add a New View"
4216
+ msgstr ""
4217
+
4218
+ msgid "If you hover over a View's name you also have these options:"
4219
+ msgstr ""
4220
+
4221
+ msgid "<strong>Edit</strong>: Click to edit the View<br />\n"
4222
+ msgstr ""
4223
+
4224
+ msgid "<strong>Quick Edit</strong>: click to get quick editing options for the View, such as title, slug and date"
4225
+ msgstr ""
4226
+
4227
+ msgid "<strong>Trash</strong>: Move the View to Trash"
4228
+ msgstr ""
4229
+
4230
+ msgid "If you need additional help with Content Templates you can visit our <a href='%s' target='_blank'>support forum &raquo;</a>."
4231
+ msgstr ""
4232
+
4233
+ msgid "<strong>WordPress Archives</strong> let you style and design standard listing and archive pages."
4234
+ msgstr ""
4235
+
4236
+ msgid "To create a <strong>WordPress Archive</strong>:"
4237
+ msgstr ""
4238
+
4239
+ msgid "Set the title"
4240
+ msgstr ""
4241
+
4242
+ msgid "Select on which listing pages it displays"
4243
+ msgstr ""
4244
+
4245
+ msgid "Design the output for the View by inserting fields and styling with HTML"
4246
+ msgstr ""
4247
+
4248
+ msgid "<strong>Views</strong> load content from the database and display it anyway you choose."
4249
+ msgstr ""
4250
+
4251
+ msgid "To make it easier to use Views, we’ve created different preset usage modes for <strong>Views</strong>. Each usage mode emphasizes the features that you need and hides the ones that are not needed."
4252
+ msgstr ""
4253
+
4254
+ msgid "You can switch between the different <strong>Views</strong> usage mode by opening the ‘Screen options’ tab."
4255
+ msgstr ""
4256
+
4257
+ msgid "To create a <strong>View</strong>:"
4258
+ msgstr ""
4259
+
4260
+ msgid "Select the content to load"
4261
+ msgstr ""
4262
+
4263
+ msgid "Optionally, apply a filter to the query"
4264
+ msgstr ""
4265
+
4266
+ msgid "If needed, enable pagination and front-end filters"
4267
+ msgstr ""
4268
+
4269
+ msgid "When you are done, remember to add the <strong>View</strong> to your content. You can do that by inserting the <strong>View</strong> as a shortcode to content or displaying it as a widget."
4270
+ msgstr ""
4271
+
4272
+ msgid "This View was not saved correctly. You may need to increase the number of post variables allowed in PHP. <a href=\"%s\">How to increase max_post_vars setting</a>."
4273
+ msgstr ""
4274
+
4275
+ msgid "Views sync"
4276
+ msgstr ""
4277
+
4278
+ msgid "Duplicate view from original"
4279
+ msgstr ""
4280
+
4281
+ msgid "Duplicate view to translations"
4282
+ msgstr ""
4283
+
4284
+ msgid "You can get the details in the <a href=\"%s\" title=\"Documentation on the shortcodes within shortcodes\">documentation page</a>."
4285
+ msgstr ""
4286
+
4287
+ msgid "You can get the details in the <a href=\"%s\" title=\"Documentation on the Views debug tool\">documentation page</a>."
4288
+ msgstr ""
4289
+
4290
+ msgid "You can get the details in the <a href=\"%s\" title=\"Documentation on the Views Maps plugin\">documentation page</a>."
4291
+ msgstr ""
4292
+
4293
+ msgid "Bootstrap version overriden by the Layouts plugin settings to use Bootstrap v.%s"
4294
+ msgstr ""
4295
+
4296
+ msgid "You can get the details in the <a href=\"%s\" title=\"Documentation on the Bootstrap Layouts\">documentation page</a>."
4297
+ msgstr ""
4298
+
4299
+ msgid "You can only use an image file here"
4300
+ msgstr ""
4301
+
4302
+ msgid "You need to place your cursor between the [wpv-filter-start] and the [wpv-filter-end] shortcodes"
4303
+ msgstr ""
4304
+
4305
+ msgid "You need to place your cursor between the [wpv-layout-start] and the [wpv-layout-end] shortcodes"
4306
+ msgstr ""
4307
+
4308
+ msgid "This is an optional placeholder to wrap the pagination shortcodes. The content of this shortcode will only be displayed if there is more than one page of results."
4309
+ msgstr ""
4310
+
4311
+ msgid "Displays the current page number"
4312
+ msgstr ""
4313
+
4314
+ msgid "Displays the maximum number of pages found by the Views Query."
4315
+ msgstr ""
4316
+
4317
+ msgid "Displays a pager with the current page selected. Depending on the value of the <em>style</em> parameter it displays a list of links to the other pages or a drop-down list to select another page."
4318
+ msgstr ""
4319
+
4320
+ msgid "Display a <em>Previous</em> link to move to the previous page."
4321
+ msgstr ""
4322
+
4323
+ msgid "Display a <em>Next</em> link to move to the next page."
4324
+ msgstr ""
4325
+
4326
+ msgid "Views Settings"
4327
+ msgstr ""
4328
+
4329
+ msgid "Third-party shortcode arguments"
4330
+ msgstr ""
4331
+
4332
+ msgid "List of custom and third-party shortcodes you want to be able to use as Views shortcode arguments."
4333
+ msgstr ""
4334
+
4335
+ msgid "For example, to support [wpv-post-title id=\"[my-custom-shortcode]\"] add <strong>my-custom-shortcode</strong> as a third-party shortcode argument below."
4336
+ msgstr ""
4337
+
4338
+ msgid "Shortcode name"
4339
+ msgstr ""
4340
+
4341
+ msgid "Add"
4342
+ msgstr ""
4343
+
4344
+ msgid "Only letters, numbers, underscores and dashes"
4345
+ msgstr ""
4346
+
4347
+ msgid "That shortcode already exists"
4348
+ msgstr ""
4349
+
4350
+ msgid "An error ocurred"
4351
+ msgstr ""
4352
+
4353
+ msgid "Debug mode"
4354
+ msgstr ""
4355
+
4356
+ msgid "Enabling Views debug will open a popup on every page showing a Views element."
4357
+ msgstr ""
4358
+
4359
+ msgid "This popup will show usefull information about the elements being displayed: time needed to render, memory used, shortcodes details..."
4360
+ msgstr ""
4361
+
4362
+ msgid "There are two modes: compact and full. Compact mode will give you an overview of the elements rendered. The full mode will display a complete report with all the object involved on the page."
4363
+ msgstr ""
4364
+
4365
+ msgid "Enable Views debug mode"
4366
+ msgstr ""
4367
+
4368
+ msgid "Compact debug mode"
4369
+ msgstr ""
4370
+
4371
+ msgid "Full debug mode"
4372
+ msgstr ""
4373
+
4374
+ msgid "Did a new window just open?"
4375
+ msgstr ""
4376
+
4377
+ msgid "Yes, it worked"
4378
+ msgstr ""
4379
+
4380
+ msgid "No, nothing opened"
4381
+ msgstr ""
4382
+
4383
+ msgid "Views debugger is ready for use. Thanks for checking it"
4384
+ msgstr ""
4385
+
4386
+ msgid "Seems like your browser is blocking popups. You should allow all popup windows from this site to use the Views debugger."
4387
+ msgstr ""
4388
+
4389
+ msgid "Please refer to the following links for documentation related to the most used browsers:"
4390
+ msgstr ""
4391
+
4392
+ msgid "Views debugger will need to open a popup window. Your browser may block it, so let's check that it's working for you."
4393
+ msgstr ""
4394
+
4395
+ msgid "Test the debugger window"
4396
+ msgstr ""
4397
+
4398
+ msgid "It's OK, skip this test"
4399
+ msgstr ""
4400
+
4401
+ msgid "Test debugger window"
4402
+ msgstr ""
4403
+
4404
+ msgid "It works!"
4405
+ msgstr ""
4406
+
4407
+ msgid "You can close this window and click 'Yes, it worked' in the Views settings page."
4408
+ msgstr ""
4409
+
4410
+ msgid "Map plugin"
4411
+ msgstr ""
4412
+
4413
+ msgid "Enabling Views Maps will add the Google Maps API and the Views Maps plugin to your site."
4414
+ msgstr ""
4415
+
4416
+ msgid "This will let you create maps on your site and use Views to plot WordPress posts on a Google Map."
4417
+ msgstr ""
4418
+
4419
+ msgid "Enable Views Map Plugin"
4420
+ msgstr ""
4421
+
4422
+ msgid "Frontend Edit Links"
4423
+ msgstr ""
4424
+
4425
+ msgid "You can enable/disable the edit links on the frontend for Views, Content Templates and WordPress Archives. Remember that the frontend edit links are only visible to administrators."
4426
+ msgstr ""
4427
+
4428
+ msgid "Enable edit links on the frontend"
4429
+ msgstr ""
4430
+
4431
+ msgid "Bootstrap Layouts"
4432
+ msgstr ""
4433
+
4434
+ msgid "You can set here the Bootstrap version that you want to use, based on the one <strong>provided by your theme</strong>. We will then generate the right markup in the Views Layouts Wizard when using the Bootstrap Grid option."
4435
+ msgstr ""
4436
+
4437
+ msgid "Bootstrap version not set"
4438
+ msgstr ""
4439
+
4440
+ msgid "Bootstrap v. 2.0"
4441
+ msgstr ""
4442
+
4443
+ msgid "Bootstrap v. 3.0"
4444
+ msgstr ""
4445
+
4446
+ msgid "Hidden custom fields"
4447
+ msgstr ""
4448
+
4449
+ msgid "The following private custom fields are showing in the Views GUI:"
4450
+ msgstr ""
4451
+
4452
+ msgid "No private custom fields are showing in the Views GUI."
4453
+ msgstr ""
4454
+
4455
+ msgid "Views Help"
4456
+ msgstr ""
4457
+
4458
+ msgid "Building Websites with Views"
4459
+ msgstr ""
4460
+
4461
+ msgid "Views plugin lets you design single pages, display content from the database and customize standard listing pages."
4462
+ msgstr ""
4463
+
4464
+ msgid "Here are the things that you can create with Views plugin:"
4465
+ msgstr ""
4466
+
4467
+ msgid "A View loads content from the database and displays it anyway you choose. Use Views to create content lists, sliders, parametric searches and more.\n"
4468
+ msgstr ""
4469
+
4470
+ msgid "Create a new View"
4471
+ msgstr ""
4472
+
4473
+ msgid "Content Templates let you design single pages using fields, taxonomy and HTML. With Content Templates, you can design the output for posts, pages and custom post types."
4474
+ msgstr ""
4475
+
4476
+ msgid "Create a new Content Template"
4477
+ msgstr ""
4478
+
4479
+ msgid "WordPress Archives let you customize standard listing pages. You will be able to customize the blog, custom post archives, taxonomy pages and other standard listing pages."
4480
+ msgstr ""
4481
+
4482
+ msgid "Create a new WordPress Archive"
4483
+ msgstr ""
4484
+
4485
+ msgid "Learning Views"
4486
+ msgstr ""
4487
+
4488
+ msgid "Views Training"
4489
+ msgstr ""
4490
+
4491
+ msgid "an interactive course that takes you through the basics and advanced features of Views."
4492
+ msgstr ""
4493
+
4494
+ msgid "Learn by building a real site, using sample data and step-by-step tutorials that we’ve prepared for you."
4495
+ msgstr ""
4496
+
4497
+ msgid "Views Documentation"
4498
+ msgstr ""
4499
+
4500
+ msgid "a complete reference library for everything in Views."
4501
+ msgstr ""
4502
+
4503
+ msgid "Support forum"
4504
+ msgstr ""
4505
+
4506
+ msgid "need any technical help? Our support staff are waiting for you in our forum."
4507
+ msgstr ""
4508
+
4509
+ msgid "Views subscription"
4510
+ msgstr ""
4511
+
4512
+ msgid "wp-types.com subscription email"
4513
+ msgstr ""
4514
+
4515
+ msgid "wp-types.com subscription key"
4516
+ msgstr ""
4517
+
4518
+ msgid "Save subscription details"
4519
+ msgstr ""
4520
+
4521
+ msgid "Saving. Please wait..."
4522
+ msgstr ""
4523
+
4524
+ msgid "Views 1.3.1 is compatible with Types version 1.4.0.2 or greater. Please update Types. | <a href=\"%1$s\">Dismiss</a>"
4525
+ msgstr ""
4526
+
4527
+ msgid "Views 1.3.1 is compatible with CRED version 1.2.3 or greater. Please update CRED. | <a href=\"%1$s\">Dismiss</a>"
4528
+ msgstr ""
embedded/common/localization/locale/views-ar.mo ADDED
Binary file
embedded/common/localization/locale/views-bg_BG.mo ADDED
Binary file
embedded/common/localization/locale/views-de_DE.mo ADDED
Binary file
embedded/common/localization/locale/views-el.mo ADDED
Binary file
embedded/common/localization/locale/views-es_ES.mo ADDED
Binary file
embedded/common/localization/locale/views-fr_FR.mo ADDED
Binary file
embedded/common/localization/locale/views-he_IL.mo ADDED
Binary file
embedded/common/localization/locale/views-it_IT.mo ADDED
Binary file
embedded/common/localization/locale/views-ja.mo ADDED
Binary file
embedded/common/localization/locale/views-ko_KR.mo ADDED
Binary file
embedded/common/localization/locale/views-nl_NL.mo ADDED
Binary file
embedded/common/localization/locale/views-pl_PL.mo ADDED
Binary file
embedded/common/localization/locale/views-pt_BR.mo ADDED
Binary file
embedded/common/localization/locale/views-pt_PT.mo ADDED
Binary file
embedded/common/localization/locale/views-ru_RU.mo ADDED
Binary file
embedded/common/localization/locale/views-sv_SE.mo ADDED
Binary file
embedded/common/localization/locale/views-vi.mo ADDED
Binary file
embedded/common/localization/locale/views-zh_CN.mo ADDED
Binary file
embedded/common/localization/locale/views-zh_TW.mo ADDED
Binary file
embedded/common/localization/wpt-localization.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * wpt-localization.php
5
+ *
6
+ * Common localization for shared code on the Toolset and also common way for adding textdomains
7
+ *
8
+ * @since Jul 18 2014
9
+ */
10
+
11
+ if ( defined( 'WPT_LOCALIZATION' ) ) {
12
+ return;
13
+ }
14
+
15
+ define( 'WPT_LOCALIZATION', true );
16
+ define( 'WPT_LOCALIZATION_ABSPATH', dirname( __FILE__ ) . '/locale' );
17
+
18
+ /*
19
+ * WPToolset_Localization
20
+ *
21
+ * Methods for registering textdomains
22
+ *
23
+ */
24
+
25
+ class WPToolset_Localization {
26
+
27
+ /*
28
+ * @param $textdomain (string) the textdomain to use
29
+ * @param $path (string) the path to the folder containing the mo files
30
+ * @param $mo_file (string) the .mo file name, using %s as a placeholder for the locale - do not add the .mo extension!
31
+ */
32
+
33
+ function __construct( $textdomain = 'wpv-views', $path = WPT_LOCALIZATION_ABSPATH, $mo_name = 'views-%s' ) {
34
+ // Set instance properties
35
+ $this->textdomain = $textdomain;
36
+ $this->path = $path;
37
+ $this->mo_name = $mo_name;
38
+ $this->mo_processed_name = '';
39
+ // Set init action
40
+ add_action( 'init', array( $this, 'load_textdomain' ) );
41
+ }
42
+
43
+ /*
44
+ * load_textdomain
45
+ *
46
+ * Initializes localization given a textdomain, a path and a .mo file name
47
+ *
48
+ * @uses load_textdomain
49
+ *
50
+ * @since July 18, 2014
51
+ */
52
+
53
+ function load_textdomain() {
54
+ $locale = get_locale();
55
+ $this->mo_processed_name = sprintf( $this->mo_name, $locale );
56
+ load_textdomain( $this->textdomain, $this->path . '/' . $this->mo_processed_name . '.mo' );
57
+ }
58
+
59
+ }
60
+
61
+ new WPToolset_Localization();
embedded/common/res/css/toolset-common.css ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ----------------------------------------------------------------------------
2
+ Common styles for all the Toolset family
3
+ ---------------------------------------------------------------------------- */
4
+
5
+ /* ----------------------------------------------------------------------------
6
+ Toolset Primary Button Style - use with .button.button-primary-toolset classnames
7
+ ---------------------------------------------------------------------------- */
8
+
9
+ .wp-core-ui .button-primary-toolset {
10
+ background: #f6921e;
11
+ border-color: #EF6223;
12
+ -webkit-box-shadow: inset 0 1px 0 rgba(239, 239, 239, 0.5), 0 1px 0 rgba(0,0,0,.15);
13
+ box-shadow: inset 0 1px 0 rgba(239, 239, 239, 0.5), 0 1px 0 rgba(0,0,0,.15);
14
+ color: #fff;
15
+ text-decoration: none;
16
+ }
17
+
18
+ .wp-core-ui .button-primary-toolset.hover,
19
+ .wp-core-ui .button-primary-toolset:hover,
20
+ .wp-core-ui .button-primary-toolset.focus,
21
+ .wp-core-ui .button-primary-toolset:focus {
22
+ background: #EF6223;
23
+ border-color: #EF6223;
24
+ -webkit-box-shadow: inset 0 1px 0 rgba(239, 239, 239, 0.5);
25
+ box-shadow: inset 0 1px 0 rgba(239, 239, 239, 0.5);
26
+ color: #fff;
27
+ }
28
+
29
+ .wp-core-ui .button-primary-toolset.focus,
30
+ .wp-core-ui .button-primary-toolset:focus {
31
+ border-color: #EF6223;
32
+ -webkit-box-shadow: inset 0 1px 0 rgba(120,200,230,0.6), 1px 1px 2px rgba(0,0,0,0.4);
33
+ box-shadow: inset 0 1px 0 rgba(120,200,230,0.6), 1px 1px 2px rgba(0,0,0,0.4);
34
+ }
35
+
36
+ .wp-core-ui .button-primary-toolset.active,
37
+ .wp-core-ui .button-primary-toolset.active:hover,
38
+ .wp-core-ui .button-primary-toolset.active:focus,
39
+ .wp-core-ui .button-primary-toolset:active {
40
+ background: #f6921e;
41
+ border-color: #EF6223;
42
+ color: rgba(255,255,255,0.95);
43
+ -webkit-box-shadow: inset 0 1px 0 rgba(0,0,0,0.1);
44
+ box-shadow: inset 0 1px 0 rgba(0,0,0,0.1);
45
+ }
46
+
47
+ .wp-core-ui .button-primary-toolset[disabled],
48
+ .wp-core-ui .button-primary-toolset:disabled,
49
+ .wp-core-ui .button-primary-toolset.disabled {
50
+ color: #94cde7 !important;
51
+ background: #298cba !important;
52
+ border-color: #1b607f !important;
53
+ -webkit-box-shadow: none !important;
54
+ box-shadow: none !important;
55
+ text-shadow: 0 -1px 0 rgba(0,0,0,0.1) !important;
56
+ cursor: default;
57
+ }
58
+
59
+ /* ----------------------------------------------------------------------------
60
+ Generic CSS to be applied anywhere
61
+ ---------------------------------------------------------------------------- */
62
+ .padding-top-30{padding-top:30px;}
embedded/common/res/css/toolset-menu-icon.css ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ a[href="admin.php?page=dd_layouts"] .wp-menu-image img{
2
+ position: relative;
3
+ top: -2px;
4
+ }
5
+
6
+ a[href="admin.php?page=types_access"] .wp-menu-image img{
7
+ position: relative;
8
+ top: -3px;
9
+ }
10
+
11
+ a[href="admin.php?page=wpcf-ctt"] .wp-menu-image img{
12
+ position: relative;
13
+ top: -2px;
14
+ }
15
+
16
+ a[href="admin.php?page=ModuleManager_Modules"] .wp-menu-image img{
17
+ position: relative;
18
+ top: -4px;
19
+ }
20
+
21
+ a[href="admin.php?page=CRED_Forms"] .wp-menu-image img{
22
+ position: relative;
23
+ top: -2px;
24
+ }
25
+
26
+ a[href="admin.php?page=views"] .wp-menu-image img{
27
+ position: relative;
28
+ top: -1px;
29
+ }
embedded/common/res/css/wpv-wp-pointer.css ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ .wpv_wp_pointer_clear_ignores {
2
+ margin-top : 20px;
3
+ font-style : italic;
4
+ }
embedded/common/res/images/question.png ADDED
Binary file
embedded/common/res/js/wpv-wp-pointer.js ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function wpv_wp_pointer_ignore( option, nonce, value, id ) {
2
+
3
+ jQuery.ajaxSetup({async:false});
4
+ jQuery.post(ajaxurl, {
5
+ action: 'wpv_wp_pointer_set_ignore',
6
+ option: option,
7
+ wpv_nonce: nonce,
8
+ value: value
9
+ }, function(data) {
10
+ }
11
+ );
12
+
13
+ if (value == 'ignore') {
14
+ jQuery('#wpv_wp_pointer_clear_ignores_' + id).fadeIn();
15
+ }
16
+ }
17
+
embedded/common/toolset-forms/TODO ADDED
@@ -0,0 +1,2 @@
 
 
1
+ - Enable separately queuing scripts/styles for each field type
2
+ - Enable getting field object using API
embedded/common/toolset-forms/__index.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ error_reporting(E_ALL^E_NOTICE);
3
+ require 'classes/class.form_factory.php';
4
+
5
+
6
+ function pre($val) {
7
+ echo "<pre>";
8
+ print_r($val);
9
+ echo "</pre>";
10
+ }
11
+
12
+
13
+ $frm = new FormFactory();
14
+ $data = array('type'=>'textfield',
15
+ 'title'=>'title',
16
+ 'description'=>'description',
17
+ 'name'=>'ciao' ,
18
+ 'validation' => array()
19
+ );
20
+
21
+ $frm->addFormField('myname','textfield', $data);
22
+
23
+ echo $frm->createForm();
24
+ ?>
embedded/common/toolset-forms/api.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function wptoolset_form( $form_id, $config = array() ){
4
+ global $wptoolset_forms;
5
+ $html = $wptoolset_forms->form( $form_id, $config );
6
+ return apply_filters( 'wptoolset_form', $html, $config );
7
+ }
8
+
9
+ function wptoolset_form_field( $form_id, $config, $value = array() ){
10
+ global $wptoolset_forms;
11
+ $html = $wptoolset_forms->field( $form_id, $config, $value );
12
+ return apply_filters( 'wptoolset_fieldform', $html, $config, $form_id );
13
+ }
14
+
15
+ //function wptoolset_form_field_edit( $form_id, $config ){
16
+ // global $wptoolset_forms;
17
+ // $html = $wptoolset_forms->fieldEdit( $form_id, $config );
18
+ // return apply_filters( 'wptoolset_fieldform_edit', $html, $config, $form_id );
19
+ //}
20
+
21
+ function wptoolset_form_validate_field( $form_id, $config, $value ){
22
+ global $wptoolset_forms;
23
+ return $wptoolset_forms->validate_field( $form_id, $config, $value );
24
+ }
25
+
26
+ function wptoolset_form_conditional_check( $config ){
27
+ global $wptoolset_forms;
28
+ return $wptoolset_forms->checkConditional( $config );
29
+ }
30
+
31
+ function wptoolset_form_add_conditional( $form_id, $config ){
32
+ global $wptoolset_forms;
33
+ return $wptoolset_forms->addConditional( $form_id, $config );
34
+ }
35
+
36
+ function wptoolset_form_filter_types_field( $field, $post_id = null, $_post_wpcf = array() ){
37
+ global $wptoolset_forms;
38
+ return $wptoolset_forms->filterTypesField( $field, $post_id, $_post_wpcf );
39
+ }
40
+
41
+ function wptoolset_form_field_add_filters( $type ){
42
+ global $wptoolset_forms;
43
+ $wptoolset_forms->addFieldFilters( $type );
44
+ }
45
+
46
+ function wptoolset_form_get_conditional_data( $post_id ){
47
+ global $wptoolset_forms;
48
+ return $wptoolset_forms->getConditionalData( $post_id );
49
+ }
50
+
51
+ function wptoolset_strtotime( $date, $format = null ){
52
+ global $wptoolset_forms;
53
+ return $wptoolset_forms->strtotime( $date, $format );
54
+ }
55
+
56
+ function wptoolset_timetodate( $timestamp, $format = null ){
57
+ global $wptoolset_forms;
58
+ return $wptoolset_forms->timetodate( $timestamp, $format );
59
+ }
embedded/common/toolset-forms/bootstrap.php ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ *
5
+ * $HeadURL: http://plugins.svn.wordpress.org/types/tags/1.6/embedded/common/toolset-forms/bootstrap.php $
6
+ * $LastChangedDate: 2014-08-22 01:02:43 +0000 (Fri, 22 Aug 2014) $
7
+ * $LastChangedRevision: 970205 $
8
+ * $LastChangedBy: brucepearson $
9
+ *
10
+ */
11
+
12
+ require_once 'api.php';
13
+
14
+ define( 'WPTOOLSET_FORMS_VERSION', '0.1.1' );
15
+ define( 'WPTOOLSET_FORMS_ABSPATH', dirname( __FILE__ ) );
16
+
17
+ /**
18
+ * check we are as a embedded?
19
+ */
20
+ if ( defined('WPCF_RUNNING_EMBEDDED' ) && WPCF_RUNNING_EMBEDDED ) {
21
+ define( 'WPTOOLSET_FORMS_RELPATH', wpcf_get_file_url( __FILE__, false ) );
22
+ }
23
+ /**
24
+ * setup WPTOOLSET_FORMS_RELPATH for plugin
25
+ */
26
+ if ( !defined( 'WPTOOLSET_FORMS_RELPATH' ) ) {
27
+ define( 'WPTOOLSET_FORMS_RELPATH', plugins_url( '', __FILE__ ) );
28
+ }
29
+ if ( !defined( 'WPTOOLSET_COMMON_PATH' ) ) {
30
+ define( 'WPTOOLSET_COMMON_PATH', plugin_dir_path( __FILE__ ) );
31
+ }
32
+
33
+ class WPToolset_Forms_Bootstrap
34
+ {
35
+
36
+ private $__forms;
37
+
38
+ public final function __construct()
39
+ {
40
+ // Custom conditinal AJAX check
41
+ add_action( 'wp_ajax_wptoolset_custom_conditional',
42
+ array($this, 'ajaxCustomConditional') );
43
+
44
+ // Date conditinal AJAX check
45
+ add_action( 'wp_ajax_wptoolset_conditional',
46
+ array($this, 'ajaxConditional') );
47
+
48
+ // Date extended localization AJAX callback
49
+ add_action( 'wp_ajax_wpt_localize_extended_date', array( $this, 'wpt_localize_extended_date' ) );
50
+ add_action( 'wp_ajax_nopriv_wpt_localize_extended_date', array( $this, 'wpt_localize_extended_date' ) );
51
+
52
+ // File media popup
53
+ if ( (isset( $_GET['context'] ) && $_GET['context'] == 'wpt-fields-media-insert') || (isset( $_SERVER['HTTP_REFERER'] ) && strpos( $_SERVER['HTTP_REFERER'],
54
+ 'context=wpt-fields-media-insert' ) !== false)
55
+ ) {
56
+ require_once WPTOOLSET_FORMS_ABSPATH . '/classes/class.file.php';
57
+ add_action( 'init', array('WPToolset_Field_File', 'mediaPopup') );
58
+ }
59
+ add_filter('sanitize_file_name', array( $this, 'sanitize_file_name' ) );
60
+
61
+ add_filter( 'wptoolset_filter_wptoolset_repdrag_image', array( $this, 'set_default_repdrag_image' ), 10, 1 );
62
+ /**
63
+ * common class for calendar
64
+ */
65
+ require_once WPTOOLSET_FORMS_ABSPATH.'/classes/class.date.scripts.php';
66
+ new WPToolset_Field_Date_Scripts();
67
+ }
68
+
69
+ // returns HTML
70
+ public function field($form_id, $config, $value)
71
+ {
72
+ $form = $this->form( $form_id, array() );
73
+ return $form->metaform( $config, $config['name'], $value );
74
+ }
75
+
76
+ // returns HTML
77
+ // public function fieldEdit($form_id, $config) {
78
+ // $form = $this->form( $form_id, array() );
79
+ // return $form->editform( $config );
80
+ // }
81
+
82
+ public function form( $form_id, $config = array() )
83
+ {
84
+ if ( isset( $this->__forms[$form_id] ) ) {
85
+ return $this->__forms[$form_id];
86
+ }
87
+ require_once WPTOOLSET_FORMS_ABSPATH . '/classes/class.form_factory.php';
88
+ return $this->__forms[$form_id] = new FormFactory( $form_id, $config );
89
+ }
90
+
91
+ public function validate_field($form_id, $config, $value)
92
+ {
93
+ if ( empty( $config['validation'] ) ) {
94
+ return true;
95
+ }
96
+ $form = $this->form( $form_id, array() );
97
+ return $form->validateField( $config, $value );
98
+ }
99
+
100
+ public function ajaxCustomConditional()
101
+ {
102
+ require_once WPTOOLSET_FORMS_ABSPATH . '/classes/class.conditional.php';
103
+ WPToolset_Forms_Conditional::ajaxCustomConditional();
104
+ }
105
+
106
+ public function checkConditional($config)
107
+ {
108
+ if ( empty( $config['conditional'] ) ) {
109
+ return true;
110
+ }
111
+ require_once WPTOOLSET_FORMS_ABSPATH . '/classes/class.conditional.php';
112
+ return WPToolset_Forms_Conditional::evaluate( $config['conditional'] );
113
+ }
114
+
115
+ public function addConditional($form_id, $config)
116
+ {
117
+ $this->form( $form_id )->addConditional( $config );
118
+ }
119
+
120
+ public function ajaxConditional()
121
+ {
122
+ $data = $_POST['conditions'];
123
+ $data['values'] = $_POST['values'];
124
+ echo $this->checkConditional( array('conditional' => $data) );
125
+ die();
126
+ }
127
+
128
+ public function wpt_localize_extended_date()
129
+ {
130
+ $date_format = $_POST['date-format'];
131
+ if ($date_format == '') {
132
+ $date_format = get_option('date_format');
133
+ }
134
+ $date = $_POST['date'];
135
+ $date = adodb_mktime(0, 0, 0, substr($date, 2, 2), substr($date, 0, 2), substr($date, 4, 4));
136
+ $date_format = str_replace('\\\\', '\\', $date_format);
137
+ echo json_encode(array('display' => adodb_date($date_format, $date),'timestamp' => $date));
138
+ die();
139
+ }
140
+
141
+ public function filterTypesField($field, $post_id = null, $_post_wpcf = array())
142
+ {
143
+ require_once WPTOOLSET_FORMS_ABSPATH . '/classes/class.types.php';
144
+ return WPToolset_Types::filterField( $field, $post_id, $_post_wpcf);
145
+ }
146
+
147
+ public function addFieldFilters($type)
148
+ {
149
+ if ( $class = $this->form( 'generic' )->loadFieldClass( $type ) ) {
150
+ call_user_func( array($class, 'addFilters') );
151
+ call_user_func( array($class, 'addActions') );
152
+ }
153
+ }
154
+
155
+ public function getConditionalData($form_id)
156
+ {
157
+ return $this->form( $form_id )->getConditionalClass()->getData();
158
+ }
159
+
160
+ public function strtotime($date, $format = null)
161
+ {
162
+ require_once WPTOOLSET_FORMS_ABSPATH . '/classes/class.date.php';
163
+ return WPToolset_Field_Date::strtotime( $date, $format );
164
+ }
165
+
166
+ public function timetodate($timestamp, $format = null)
167
+ {
168
+ require_once WPTOOLSET_FORMS_ABSPATH . '/classes/class.date.php';
169
+ return WPToolset_Field_Date::timetodate( $timestamp, $format );
170
+ }
171
+
172
+ public function sanitize_file_name( $filename )
173
+ {
174
+ /**
175
+ * replace german special characters
176
+ */
177
+ $de_from = array('ä','ö','ü','ß','Ä','Ö','Ü');
178
+ $de_to = array('ae','oe','ue','ss','Ae','Oe','Ue');
179
+ $filename = str_replace($de_from, $de_to, $filename);
180
+ /**
181
+ * replace polish special characters
182
+ */
183
+ $pl_from = array( 'ą', 'ć', 'ę', 'ł', 'ń', 'ó', 'ś', 'ź', 'ż', 'Ą', 'Ć', 'Ę', 'Ł', 'Ń', 'Ó', 'Ś', 'Ź', 'Ż' );
184
+ $pl_to = array( 'a', 'c', 'e', 'l', 'n', 'o', 's', 'z', 'z', 'A', 'C', 'E', 'L', 'N', 'O', 'S', 'Z', 'Z' );
185
+ $filename = str_replace($pl_from, $pl_to, $filename);
186
+ /**
187
+ * remove special characters
188
+ */
189
+ $filename = preg_replace( '/[^A-Za-z0-9\._]/', '-', $filename);
190
+ $filename = preg_replace( '/[_ ]+/', '-', $filename);
191
+ $filename = preg_replace( '/%20/', '-', $filename);
192
+ return $filename;
193
+ }
194
+
195
+ public function set_default_repdrag_image( $image ) {
196
+ return WPTOOLSET_FORMS_RELPATH . '/images/move.png';
197
+ }
198
+ }
199
+
200
+ $GLOBALS['wptoolset_forms'] = new WPToolset_Forms_Bootstrap();
embedded/common/toolset-forms/classes/abstract.field.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ * Field Abstraction
5
+ * @author onTheGo System
6
+ *
7
+ */
8
+ abstract class FieldAbstract {
9
+ //global name of field
10
+ protected $_nameField;
11
+ //field config
12
+ protected $_data;
13
+ //config for enlimbo
14
+ protected $_metaform;
15
+
16
+ abstract public function init();
17
+ abstract public function set_nameField($nameField);
18
+ abstract public function get_nameField();
19
+ abstract public function set_data($data);
20
+ abstract public function get_data();
21
+ abstract public function set_metaform($metaform);
22
+ abstract public function get_metaform();
23
+
24
+ abstract public function getId();
25
+ abstract public function getName();
26
+ abstract public function getType();
27
+ abstract public function getValue();
28
+ abstract public function getAttr();
29
+ abstract public function getTitle();
30
+ abstract public function getDescription();
31
+ abstract public function getData();
32
+ abstract public function getValidationData();
33
+ abstract public function setValidationData($validation);
34
+ }
embedded/common/toolset-forms/classes/abstract.form.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ abstract class FormAbstract {
4
+ /*
5
+ * Create and return form as string
6
+ */
7
+ abstract public function createForm($nameForm);
8
+ /*
9
+ * Create and display form
10
+ */
11
+ abstract public function displayForm($nameForm);
12
+ /*
13
+ * Check id forms
14
+ */
15
+ abstract public function formNameExists(&$nameForm);
16
+ /*
17
+ * Get Field Object from type
18
+ */
19
+ abstract public function getFieldObject($data, $global_name_field, $value);
20
+ /*
21
+ * Add field to a form
22
+ */
23
+ abstract public function addFormField($data);
24
+ /*
25
+ * Loads field (queue script and styles)
26
+ */
27
+ abstract public function loadField( $data, $global_name_field, $value );
28
+ /*
29
+ * Single field form (not added to form fields)
30
+ */
31
+ abstract public function metaform( $config, $global_name_field, $value );
32
+ /*
33
+ * Single field edit form (not added to form fields)
34
+ */
35
+ // abstract public function editform( $config );
36
+ /*
37
+ * Checks if validation is required and inits it per form
38
+ */
39
+ abstract protected function _checkValidation( $config );
40
+ /*
41
+ * checkConditional
42
+ */
43
+ abstract protected function _checkConditional( $config );
44
+ /*
45
+ * repetitive
46
+ */
47
+ abstract protected function _repetitive();
48
+ }
embedded/common/toolset-forms/classes/class.audio.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once 'class.file.php';
3
+
4
+ /**
5
+ * Description of class
6
+ *
7
+ * @author Srdjan
8
+ *
9
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/common/tags/august-release/toolset-forms/classes/class.audio.php $
10
+ * $LastChangedDate: 2014-07-29 23:56:51 +0800 (Tue, 29 Jul 2014) $
11
+ * $LastChangedRevision: 25431 $
12
+ * $LastChangedBy: marcin $
13
+ *
14
+ */
15
+ class WPToolset_Field_Audio extends WPToolset_Field_File
16
+ {
17
+
18
+ protected $_settings = array('min_wp_version' => '3.6');
19
+
20
+ public function metaform()
21
+ {
22
+ $form = parent::metaform();
23
+ return self::setForm($form);
24
+ }
25
+
26
+ public static function setForm($form)
27
+ {
28
+ if ( !isset( $form[0] ) || !is_array($form[0] ) ) {
29
+ return $form;
30
+ }
31
+ if ( !array_key_exists( '#validate', $form[0] ) ) {
32
+ $form[0]['#validate'] = array();
33
+ }
34
+ if ( !array_key_exists( 'extension', $form[0]['#validate'] ) ) {
35
+ $form[0]['#validate']['extension'] = array(
36
+ 'args' => array(
37
+ 'extension',
38
+ '16svx|2sf|8svx|aac|aif|aifc|aiff|amr|ape|asf|ast|au|aup|band|brstm|bwf|cdda|cust|dsf|dwd|flac|gsf|gsm|gym|it|jam|la|ly|m4a|m4p|mid|minipsf|mng|mod|mp1|mp2|mp3|mp4|mpc|mscz|mt2|mus|niff|nsf|off|ofr|ofs|ots|pac|psf|psf2|psflib|ptb|qsf|ra|raw|rka|rm|rmj|s3m|shn|sib|sid|smp|spc|spx|ssf|swa|tta|txm|usf|vgm|voc|vox|vqf|wav|wma|wv|xm|ym',
39
+ ),
40
+ 'message' => __( 'You can add only audio.', 'wpv-views' ),
41
+ );
42
+ }
43
+ return $form;
44
+ }
45
+ }
embedded/common/toolset-forms/classes/class.button.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once 'class.textfield.php';
3
+
4
+ /**
5
+ * Description of class
6
+ *
7
+ * @author Franko
8
+ */
9
+ class WPToolset_Field_Button extends WPToolset_Field_Textfield
10
+ {
11
+
12
+ public function metaform() {
13
+ $config = $this->_config;
14
+ $metaform = array();
15
+ $metaform[] = array(
16
+ '#type' => 'button',
17
+ '#title' => $this->title,
18
+ '#description' => $this->description,
19
+ '#name' => $this->name,
20
+ '#value' => $this->value,
21
+ '#validate' => $config['validation']
22
+ );
23
+ return $metaform;
24
+ }
25
+ }
embedded/common/toolset-forms/classes/class.checkbox.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ * $HeadURL: http://plugins.svn.wordpress.org/types/tags/1.6/embedded/common/toolset-forms/classes/class.checkbox.php $
5
+ * $LastChangedDate: 2014-08-22 01:02:43 +0000 (Fri, 22 Aug 2014) $
6
+ * $LastChangedRevision: 970205 $
7
+ * $LastChangedBy: brucepearson $
8
+ *
9
+ */
10
+ require_once 'class.field_factory.php';
11
+
12
+ /**
13
+ * Description of class
14
+ *
15
+ * @author Srdjan
16
+ */
17
+ class WPToolset_Field_Checkbox extends FieldFactory
18
+ {
19
+ public function metaform()
20
+ {
21
+ global $post;
22
+ $value = $this->getValue();
23
+ $data = $this->getData();
24
+ $checked = null;
25
+
26
+ /**
27
+ * autocheck for new posts
28
+ */
29
+ if (isset($post) && 'auto-draft' == $post->post_status && array_key_exists( 'checked', $data ) && $data['checked']) {
30
+ $checked = true;
31
+ }
32
+ /**
33
+ * is checked?
34
+ */
35
+ if ( isset($data['options']) && array_key_exists( 'checked', $data['options'] ) ) {
36
+ $checked = $data['options']['checked'];
37
+ }
38
+ if ( array_key_exists('default_value', $data) && $value == $data['default_value'] ) {
39
+ $checked = true;
40
+ }
41
+
42
+ // Comment out broken code. This tries to set the previous state after validation fails
43
+ //if (!$checked&&$this->getValue()==1) {
44
+ // $checked=true;
45
+ //}
46
+
47
+ /**
48
+ * metaform
49
+ */
50
+ $form = array(
51
+ '#type' => 'checkbox',
52
+ '#value' => $value,
53
+ '#default_value' => array_key_exists( 'default_value', $data )? $data['default_value']:null,
54
+ '#name' => $this->getName(),
55
+ '#title' => $this->getTitle(),
56
+ '#validate' => $this->getValidationData(),
57
+ '#after' => '<input type="hidden" name="_wptoolset_checkbox[' . $this->getId() . ']" value="1" />',
58
+ '#checked' => $checked,
59
+ '#repetitive' => $this->isRepetitive(),
60
+ );
61
+ return array($form);
62
+ }
63
+ }
embedded/common/toolset-forms/classes/class.checkboxes.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Description of class
4
+ *
5
+ * @author Srdjan
6
+ *
7
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/common/tags/august-release/toolset-forms/classes/class.checkboxes.php $
8
+ * $LastChangedDate: 2014-08-06 00:42:25 +0800 (Wed, 06 Aug 2014) $
9
+ * $LastChangedRevision: 25659 $
10
+ * $LastChangedBy: juan $
11
+ *
12
+ */
13
+
14
+ require_once 'class.field_factory.php';
15
+
16
+ class WPToolset_Field_Checkboxes extends FieldFactory
17
+ {
18
+ public function metaform()
19
+ {
20
+ global $post;
21
+ $value = $this->getValue();
22
+ $data = $this->getData();
23
+ $name = $this->getName();
24
+ $form = array();
25
+ $_options = array();
26
+ if (isset($data['options'])) {
27
+ foreach ( $data['options'] as $option_key => $option ) {
28
+
29
+ $checked = isset( $option['checked'] ) ? $option['checked'] : !empty( $value[$option_key] );
30
+
31
+ if (isset($post) && 'auto-draft' == $post->post_status && array_key_exists( 'checked', $option ) && $option['checked']) {
32
+ $checked = true;
33
+ }
34
+
35
+ // Comment out broken code. This tries to set the previous state after validation fails
36
+ //$_values=$this->getValue();
37
+ //if (!$checked&&isset($value)&&!empty($value)&&is_array($value)&&in_array($option['value'],$value)) {
38
+ // $checked=true;
39
+ //}
40
+
41
+ $_options[$option_key] = array(
42
+ '#value' => $option['value'],
43
+ '#title' => $option['title'],
44
+ '#type' => 'checkbox',
45
+ '#default_value' => $checked,
46
+ '#name' => $option['name']."[]",
47
+ //'#inline' => true,
48
+ );
49
+
50
+ if ( !is_admin() ) {// TODO maybe add a doing_ajax() check too, what if we want to load a form using AJAX?
51
+ $_options[$option_key]['#before'] = '<li class="wpt-form-item wpt-form-item-checkbox">';
52
+ $_options[$option_key]['#after'] = '</li>';
53
+ $_options[$option_key]['#pattern'] = '<BEFORE><PREFIX><ELEMENT><LABEL><ERROR><SUFFIX><DESCRIPTION><AFTER>';
54
+ }
55
+ }
56
+ }
57
+ $metaform = array(
58
+ '#type' => 'checkboxes',
59
+ '#options' => $_options,
60
+ );
61
+ if ( is_admin() ) {
62
+ $metaform['#title'] = $this->getTitle();
63
+ $metaform['#after'] = '<input type="hidden" name="_wptoolset_checkbox[' . $this->getId() . ']" value="1" />';
64
+ } else {
65
+ $metaform['#before'] = '<ul class="wpt-form-set wpt-form-set-checkboxes wpt-form-set-checkboxes-' . $name . '">';
66
+ $metaform['#after'] = '</ul>';
67
+ }
68
+ return array($metaform);
69
+ }
70
+ }
embedded/common/toolset-forms/classes/class.colorpicker.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/common/tags/august-release/toolset-forms/classes/class.colorpicker.php $
5
+ * $LastChangedDate: 2014-07-12 16:38:18 +0800 (Sat, 12 Jul 2014) $
6
+ * $LastChangedRevision: 24908 $
7
+ * $LastChangedBy: gen $
8
+ *
9
+ */
10
+ require_once 'class.field_factory.php';
11
+
12
+ /**
13
+ * Description of class
14
+ *
15
+ * @author Srdjan
16
+ */
17
+ class WPToolset_Field_Colorpicker extends FieldFactory
18
+ {
19
+ public function init()
20
+ {
21
+
22
+ if ( !is_admin() ) {
23
+ wp_enqueue_style( 'wp-color-picker' );
24
+ wp_enqueue_script(
25
+ 'iris',
26
+ admin_url( 'js/iris.min.js' ),
27
+ array( 'jquery-ui-draggable', 'jquery-ui-slider', 'jquery-touch-punch' ),
28
+ false,
29
+ 1
30
+ );
31
+ wp_enqueue_script(
32
+ 'wp-color-picker',
33
+ admin_url( 'js/color-picker.min.js' ),
34
+ array( 'iris' ),
35
+ false,
36
+ 1
37
+ );
38
+ $colorpicker_l10n = array(
39
+ 'clear' => __( 'Clear' ),
40
+ 'defaultString' => __( 'Default', 'wpv-views' ),
41
+ 'pick' => __( 'Select Color', 'wpv-views' )
42
+ );
43
+ wp_localize_script( 'wp-color-picker', 'wpColorPickerL10n', $colorpicker_l10n );
44
+ }
45
+ wp_register_script(
46
+ 'wptoolset-field-colorpicker',
47
+ WPTOOLSET_FORMS_RELPATH . '/js/colorpicker.js',
48
+ array('iris'),
49
+ WPTOOLSET_FORMS_VERSION,
50
+ true
51
+ );
52
+ wp_enqueue_script( 'wptoolset-field-colorpicker' );
53
+
54
+ }
55
+
56
+ static public function registerScripts()
57
+ {
58
+
59
+ }
60
+
61
+ public function enqueueScripts()
62
+ {
63
+
64
+ }
65
+
66
+ public function metaform()
67
+ {
68
+ $classes = array();
69
+ $classes[] = 'js-wpt-colorpicker';
70
+ $form = array();
71
+ $form['name'] = array(
72
+ '#type' => 'textfield',
73
+ '#title' => $this->getTitle(),
74
+ '#description' => $this->getDescription(),
75
+ '#value' => $this->getValue(),
76
+ '#name' => $this->getName(),
77
+ '#attributes' => array('class' => implode(' ', $classes )),
78
+ '#validate' => $this->getValidationData(),
79
+ '#after' => '',
80
+ '#repetitive' => $this->isRepetitive(),
81
+ );
82
+ return $form;
83
+ }
84
+
85
+ public static function filterValidationValue($value)
86
+ {
87
+ if ( isset( $value['datepicker'] ) ) {
88
+ return $value['datepicker'];
89
+ }
90
+ return $value;
91
+ }
92
+ }
embedded/common/toolset-forms/classes/class.conditional.php ADDED
@@ -0,0 +1,536 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * - Checks conditionals when form is displayed and values changed
4
+ * - Checks simple conditionals using JS
5
+ * - Checks custom conditinals via AJAX/PHP
6
+ * - PHP simple and custom checks available using class methods
7
+ *
8
+ * Simple conditionals
9
+ *
10
+ * Data
11
+ * [id] - Trigger ID to match data-wpt-id
12
+ * [type] - field type (trigger)
13
+ * [operator] - operator
14
+ * [args] - array(value, value2...)
15
+ *
16
+ * Example
17
+ * $config['conditional'] = array(
18
+ * 'relation' => 'OR'|'AND',
19
+ * 'conditions' => array(
20
+ * array(
21
+ * 'id' => 'wpcf-text',
22
+ * 'type' => 'textfield',
23
+ * 'operator' => '==',
24
+ * 'args' => array('show')
25
+ * ),
26
+ * array(
27
+ * 'id' => 'wpcf-date',
28
+ * 'type' => 'date',
29
+ * 'operator' => 'beetween',
30
+ * 'args' => array('21/01/2014', '24/01/2014') // Accepts timestamps or string date
31
+ * )
32
+ * ),
33
+ * );
34
+ *
35
+ * Custom conditionals
36
+ *
37
+ * Variable name should match trigger ID - data-wpt-id
38
+ * Example
39
+ * $config['conditional'] = array(
40
+ * 'custom' => '($wpcf-text = show) OR ($wpcf-date > '21-01-2014')'
41
+ * );
42
+ */
43
+ if ( !defined( 'ICL_COMMON_FUNCTIONS' ) ) {
44
+ require_once WPTOOLSET_COMMON_PATH . '/functions.php';
45
+ }
46
+ if (!function_exists('wpv_filter_parse_date')) {
47
+ require_once WPTOOLSET_COMMON_PATH . '/wpv-filter-date-embedded.php';
48
+ }
49
+
50
+ require_once WPTOOLSET_COMMON_PATH . '/expression-parser/parser.php';
51
+
52
+ /**
53
+ * Class description
54
+ *
55
+ * @todo BUG common function wpv_condition has some flaws
56
+ * (dashed names, mixed checks for string and numeric values causes failure)
57
+ *
58
+ * @author Srdjan
59
+ */
60
+
61
+ class WPToolset_Forms_Conditional
62
+ {
63
+
64
+ private $__formID;
65
+ protected $_collected = array(), $_triggers = array(), $_fields = array(), $_custom_triggers = array(), $_custom_fields = array();
66
+
67
+ /**
68
+ * Register and enqueue scripts and actions.
69
+ *
70
+ * @param type $formID
71
+ */
72
+ public function __construct( $formID ) {
73
+ $this->__formID = trim( $formID, '#' );
74
+ // Register and enqueue
75
+ wp_register_script( 'wptoolset-form-conditional',
76
+ WPTOOLSET_FORMS_RELPATH . '/js/conditional.js', array('jquery', 'jquery-effects-scale'),
77
+ WPTOOLSET_FORMS_VERSION, true );
78
+ wp_enqueue_script( 'wptoolset-form-conditional' );
79
+ $js_data = array(
80
+ 'ajaxurl' => admin_url('admin-ajax.php', null),
81
+ );
82
+ wp_localize_script( 'wptoolset-form-conditional', 'wptConditional', $js_data );
83
+
84
+ wp_register_script( 'wptoolset-parser',
85
+ icl_get_file_relpath(__FILE__) . '/../../expression-parser/js/parser.js', array('jquery'),
86
+ WPTOOLSET_FORMS_VERSION, true );
87
+ wp_enqueue_script( 'wptoolset-parser' );
88
+ $js_data = array(
89
+ 'ajaxurl' => admin_url('admin-ajax.php', null),
90
+ );
91
+ // Render settings
92
+ add_action( 'admin_print_footer_scripts', array($this, 'renderJsonData'), 30 );
93
+ add_action( 'wp_footer', array($this, 'renderJsonData'), 30 );
94
+ // Check conditional and hide field
95
+ add_action('wptoolset_field_class', array($this, 'actionFieldClass') );
96
+ }
97
+
98
+ /**
99
+ * Collects data.
100
+ *
101
+ * Called from form_factory.
102
+ *
103
+ * @param type $config
104
+ */
105
+ public function add( $config ) {
106
+ if ( !empty( $config['conditional'] ) ) {
107
+ $this->_collected[$config['id']] = $config['conditional'];
108
+ return;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Sets JSON data to be used with conditional.js
114
+ */
115
+ protected function _parseData() {
116
+ foreach ( $this->_collected as $id => $config ) {
117
+ if ( !empty( $config['custom'] ) ) {
118
+
119
+ $evaluate = wpv_filter_parse_date($config['custom']);
120
+ $evaluate = self::handle_user_function( $evaluate );
121
+ $fields = self::extractFields( $evaluate );
122
+
123
+ foreach ( $fields as $field ) {
124
+ $this->_custom_fields[$id]['custom'] = $evaluate;
125
+ $this->_custom_fields[$id]['triggers'][] = $field;
126
+ $this->_custom_triggers[$field][] = $id;
127
+ }
128
+ } else {
129
+ if (isset($config)&&isset($config['conditions'])) {
130
+ if (isset($config)&&isset($config['relation']))
131
+ $this->_fields[$id]['relation'] = $config['relation'];
132
+
133
+ foreach ( $config['conditions'] as &$c ) {
134
+ /*
135
+ * $c[id] - field id
136
+ * $c[type] - field type
137
+ * $c[operator] - operator
138
+ * $c[args] - array(value, [value2]...)
139
+ */
140
+ if ( !isset( $this->_triggers[$c['id']] ) )
141
+ $this->_triggers[$c['id']] = array();
142
+ $c['args'] = apply_filters( 'wptoolset_conditional_args_js',
143
+ $c['args'], $c['type'] );
144
+ $this->_fields[$id]['conditions'][] = $c;
145
+ if ( !in_array( $id, $this->_triggers[$c['id']] ) )
146
+ $this->_triggers[$c['id']][] = $id;
147
+ }
148
+ }
149
+ }
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Renders JSON data in footer to be used with conditional.js
155
+ */
156
+ public function renderJsonData() {
157
+ $this->_parseData();
158
+ if ( !empty( $this->_triggers ) ) {
159
+ echo '<script type="text/javascript">wptCondTriggers["#'
160
+ . $this->__formID . '"] = ' . json_encode( $this->_triggers ) . ';</script>';
161
+ }
162
+ if ( !empty( $this->_fields ) ) {
163
+ echo '<script type="text/javascript">wptCondFields["#'
164
+ . $this->__formID . '"] = ' . json_encode( $this->_fields ) . ';</script>';
165
+ }
166
+ if ( !empty( $this->_custom_triggers ) ) {
167
+ echo '<script type="text/javascript">wptCondCustomTriggers["#'
168
+ . $this->__formID . '"] = ' . json_encode( $this->_custom_triggers ) . ';</script>';
169
+ }
170
+ if ( !empty( $this->_custom_fields ) ) {
171
+ echo '<script type="text/javascript">wptCondCustomFields["#'
172
+ . $this->__formID . '"] = ' . json_encode( $this->_custom_fields ) . ';</script>';
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Compares values.
178
+ *
179
+ * @param array $config
180
+ * @param array $values
181
+ * @return type
182
+ */
183
+ public static function evaluate( $config ) {
184
+ // Custom conditional
185
+ if ( !empty( $config['custom'] ) ) {
186
+ return self::evaluateCustom( $config['custom'], $config['values'] );
187
+ }
188
+
189
+ /**
190
+ * check conditions
191
+ */
192
+ if ( !array_key_exists( 'conditions', $config ) ) {
193
+ return false;
194
+ }
195
+
196
+ $passedOne = false;
197
+ $passedAll = true;
198
+ $relation = $config['relation'];
199
+
200
+ foreach ( $config['conditions'] as $c ) {
201
+ // Add filters
202
+ wptoolset_form_field_add_filters( $c['type'] );
203
+ $c['args'] = apply_filters( 'wptoolset_conditional_args_php',
204
+ $c['args'], $c['type'] );
205
+ $value = isset( $config['values'][$c['id']] ) ? $config['values'][$c['id']] : null;
206
+ $value = apply_filters( 'wptoolset_conditional_value_php', $value, $c['type'] );
207
+ $compare = $c['args'][0];
208
+ switch ( $c['operator'] ) {
209
+ case '=':
210
+ case '==':
211
+ $passed = $value == $compare;
212
+ break;
213
+
214
+ case '>':
215
+ $passed = floatval( $value ) > floatval( $compare );
216
+ break;
217
+
218
+ case '>=':
219
+ $passed = floatval( $value ) >= floatval( $compare );
220
+ break;
221
+
222
+ case '<':
223
+ $passed = floatval( $value ) < floatval( $compare );
224
+ break;
225
+
226
+ case '<=':
227
+ $passed = floatval( $value ) <= floatval( $compare );
228
+ break;
229
+
230
+ case '===':
231
+ $passed = $value === $compare;
232
+ break;
233
+
234
+ case '!==':
235
+ $passed = $value !== $compare;
236
+ break;
237
+
238
+ case '<>':
239
+ $passed = $value <> $compare;
240
+ break;
241
+
242
+ case 'between':
243
+ $passed = floatval( $value ) > floatval( $compare ) && floatval( $value ) < floatval( $c['args'][1] );
244
+ break;
245
+
246
+ default:
247
+ $passed = false;
248
+ break;
249
+ }
250
+ if ( !$passed ) {
251
+ $passedAll = false;
252
+ } else {
253
+ $passedOne = true;
254
+ }
255
+ }
256
+ if ( $relation == 'AND' && $passedAll ) {
257
+ return true;
258
+ }
259
+ if ( $relation == 'OR' && $passedOne ) {
260
+ return true;
261
+ }
262
+ return false;
263
+ }
264
+
265
+ /**
266
+ * Evaluates conditions using custom conditional statement.
267
+ *
268
+ * @uses wpv_condition()
269
+ *
270
+ * @param type $post
271
+ * @param type $evaluate
272
+ * @return boolean
273
+ */
274
+ public static function evaluateCustom( $evaluate, $values ) {
275
+
276
+ $evaluate = trim( stripslashes( $evaluate ) );
277
+ // Check dates
278
+ $evaluate = wpv_filter_parse_date( $evaluate );
279
+ $evaluate = self::handle_user_function( $evaluate );
280
+ $fields = self::extractFields( $evaluate );
281
+ $evaluate = self::_update_values_in_expression($evaluate, $fields, $values);
282
+
283
+ $check = false;
284
+ try {
285
+ $parser = new Toolset_Parser($evaluate);
286
+ $parser->parse();
287
+ $check = $parser->evaluate();
288
+ } catch (Exception $e) {
289
+ $check = false;
290
+ }
291
+ return $check;
292
+ }
293
+
294
+ static function sortByLength ($a, $b) {
295
+ return strlen($b) - strlen($a);
296
+ }
297
+
298
+
299
+ private static function _update_values_in_expression($evaluate, $fields, $values) {
300
+
301
+ // use string replace to replace any fields with their values.
302
+
303
+ // Sort by length just in case a field name contians a shorter version of another field name.
304
+ // eg. $my-field and $my-field-2
305
+
306
+ $keys = array_keys($fields);
307
+ usort($keys, 'WPToolset_Forms_Conditional::sortByLength');
308
+
309
+ foreach($keys as $key) {
310
+ $value = isset($values[$fields[$key]]) ? $values[$fields[$key]] : '';
311
+ if ($value == '') {
312
+ $value = "''";
313
+ }
314
+ if (is_numeric($value)) {
315
+ $value = '\'' . $value . '\'';
316
+ }
317
+
318
+ if( 'array' === gettype($value) )
319
+ {
320
+ // workaround for datepicker data to cover all cases
321
+ if( array_key_exists ( 'timestamp' , $value ) )
322
+ {
323
+ if ( is_numeric( $value['timestamp'] ) )
324
+ {
325
+ $value = $value['timestamp'];
326
+ }
327
+ else if ( is_array( $value['timestamp'] ) )
328
+ {
329
+ $value = implode(',', array_values ( $value['timestamp'] ) );
330
+ }
331
+ }
332
+ else if( array_key_exists('datepicker', $value ) )
333
+ {
334
+ if ( is_numeric( $value['datepicker'] ) )
335
+ {
336
+ $value = $value['datepicker'];
337
+ }
338
+ else if ( is_array( $value['datepicker'] ) )
339
+ {
340
+ $value = implode(',', array_values ( $value['datepicker'] ) );
341
+ }
342
+ }
343
+ else{
344
+ $value = implode(',', array_values ( $value ) );
345
+ }
346
+ }
347
+
348
+
349
+ // First replace the $(field_name) format
350
+ $evaluate = str_replace('$(' . $fields[$key] . ')', $value, $evaluate);
351
+ // next replace the $field_name format
352
+ $evaluate = str_replace('$' . $fields[$key], $value, $evaluate);
353
+ }
354
+
355
+ return $evaluate;
356
+ }
357
+
358
+ /**
359
+ * Extracts fields from custom conditional statement.
360
+ *
361
+ * @param type $evaluate
362
+ * @return type
363
+ */
364
+ public static function extractFields( $evaluate ) {
365
+ $evaluate = trim( stripslashes( $evaluate ) );
366
+ // Check dates
367
+ $evaluate = wpv_filter_parse_date( $evaluate );
368
+ $evaluate = self::handle_user_function($evaluate);
369
+
370
+ // Add quotes = > < >= <= === <> !==
371
+ $strings_count = preg_match_all( '/[=|==|===|<=|<==|<===|>=|>==|>===|\!===|\!==|\!=|<>]\s(?!\$)(\w*)[\)|\$|\W]/',
372
+ $evaluate, $matches );
373
+
374
+ if ( !empty( $matches[1] ) ) {
375
+ foreach ( $matches[1] as $temp_match ) {
376
+ $temp_replace = is_numeric( $temp_match ) ? $temp_match : '\'' . $temp_match . '\'';
377
+ $evaluate = str_replace( ' ' . $temp_match . ')',
378
+ ' ' . $temp_replace . ')', $evaluate );
379
+ }
380
+ }
381
+ // if new version $(field-value) use this regex
382
+ if( preg_match('/\$\(([^()]+)\)/', $evaluate) ){
383
+ preg_match_all( '/\$\(([^()]+)\)/', $evaluate, $matches );
384
+ }
385
+ // if old version $field-value use this other
386
+ else{
387
+ preg_match_all( '/\$([^\s]*)/', $evaluate, $matches );
388
+ }
389
+
390
+
391
+ $fields = array();
392
+ if ( !empty( $matches ) ) {
393
+ foreach ( $matches[1] as $field_name ) {
394
+ $fields[trim($field_name, '()')] = trim($field_name,'()');
395
+ }
396
+ }
397
+
398
+ return $fields;
399
+ }
400
+
401
+ public static function handle_user_function( $evaluate )
402
+ {
403
+ $evaluate = stripcslashes( $evaluate );
404
+ $occurrences = preg_match_all('/(\\w+)\(([^\)]*)\)/', $evaluate, $matches);
405
+
406
+ if( $occurrences > 0 )
407
+ {
408
+ for ($i = 0; $i < $occurrences; $i++) {
409
+ $result = false;
410
+ $function = $matches[1][$i];
411
+ $field = isset( $matches[2] ) ? rtrim( $matches[2][$i], ',' ) : '';
412
+
413
+ if( $function === 'USER' )
414
+ {
415
+ $result = WPV_Handle_Users_Functions::get_user_field( $field );
416
+ }
417
+
418
+ if( $result ){
419
+ $evaluate = str_replace( $matches[0][$i], $result, $evaluate );
420
+ }
421
+ }
422
+ }
423
+
424
+ return $evaluate;
425
+ }
426
+
427
+ /**
428
+ * Custom conditional AJAX check (called from bootstrap.php)
429
+ */
430
+ public static function ajaxCustomConditional() {
431
+ $res = array('passed' => array(), 'failed' => array());
432
+ $conditional = stripslashes_deep($_POST['conditions']);
433
+ foreach ($conditional as $k => $c ) {
434
+ $post_values = stripslashes_deep($_POST['values']);
435
+ $values = array();
436
+ foreach ( $post_values as $fid => $value ) {
437
+ if ( isset( $_POST['field_types'][$fid] ) ) {
438
+ $field_type = stripslashes_deep($_POST['field_types'][$fid]);
439
+ wptoolset_form_field_add_filters( $field_type );
440
+ $value = apply_filters( 'wptoolset_conditional_value_php',
441
+ $value, $field_type );
442
+ }
443
+ $values[$fid] = $value;
444
+ }
445
+ if ( $passed = self::evaluateCustom( $c, $values ) ) {
446
+ $res['passed'][] = $k;
447
+ } else {
448
+ $res['failed'][] = $k;
449
+ }
450
+ }
451
+ echo json_encode( $res );
452
+ die();
453
+ }
454
+
455
+ /**
456
+ * Checks conditional and hides field.
457
+ *
458
+ * @param type $config
459
+ */
460
+ public function actionFieldClass( $config ) {
461
+ if (
462
+ !empty( $config['conditional'] )
463
+ && array_key_exists( 'conditions', $config['conditional'] )
464
+ && !self::evaluate( $config['conditional'] )
465
+ ) {
466
+ echo ' wpt-hidden js-wpt-remove-on-submit js-wpt-validation-ignore';
467
+ }
468
+ }
469
+
470
+ /**
471
+ * Returns collected JSON data
472
+ *
473
+ * @return type
474
+ */
475
+ public function getData(){
476
+ $this->_parseData();
477
+ return array(
478
+ 'triggers' => $this->_triggers,
479
+ 'fields' => $this->_fields,
480
+ 'custom_triggers' => $this->_custom_triggers,
481
+ 'custom_fields' => $this->_custom_fields,
482
+ );
483
+ }
484
+
485
+ }
486
+
487
+
488
+
489
+ if( !class_exists('WPV_Handle_Users_Functions') )
490
+ {
491
+ class WPV_Handle_Users_Functions{
492
+
493
+ private static $field;
494
+
495
+ public static function get_user_field( $field )
496
+ {
497
+ if( !$field ) return false;
498
+
499
+ self::$field = str_replace("'", '', $field);
500
+
501
+ $ret = self::get_info( );
502
+
503
+ if( $ret !== false ) return "'".$ret."'";
504
+
505
+ return false;
506
+ }
507
+
508
+ private static function get_info( )
509
+ {
510
+ global $current_user;
511
+
512
+ get_currentuserinfo();
513
+
514
+ switch( self::$field )
515
+ {
516
+ case 'role':
517
+ return isset($current_user->roles[0]) ? $current_user->roles[0] : 'Subscriber';
518
+ break;
519
+ case 'login':
520
+ return $current_user->data->user_login;
521
+ break;
522
+ case 'name':
523
+ return $current_user->data->display_name;
524
+ break;
525
+ case 'id':
526
+ return $current_user->data->ID;
527
+ break;
528
+ default:
529
+ return $current_user->data->ID;
530
+ break;
531
+ }
532
+
533
+ return false;
534
+ }
535
+ }
536
+ }
embedded/common/toolset-forms/classes/class.cred.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Types fields specific
4
+ */
5
+ require_once 'class.types.php';
6
+ require_once 'class.conditional.php';
7
+
8
+ /**
9
+ * Class description
10
+ *
11
+ * @author Srdjan
12
+ */
13
+ class WPToolset_Cred
14
+ {
15
+
16
+ /**
17
+ * Filters validation.
18
+ *
19
+ * Loop over validation settings and create array of validation rules.
20
+ * array( $rule => array( 'args' => array, 'message' => string ), ... )
21
+ *
22
+ * @param array|string $field settings array (as stored in DB) or field ID
23
+ * @return array array( $rule => array( 'args' => array, 'message' => string ), ... )
24
+ */
25
+ public static function filterValidation( $config ){
26
+ /* Placeholder for field value '$value'.
27
+ *
28
+ * Used for validation settings.
29
+ * Field value is not processed here, instead string '$value' is used
30
+ * to be replaced with actual value when needed.
31
+ *
32
+ * For example:
33
+ * validation['rangelength'] = array(
34
+ * 'args' => array( '$value', 5, 12 ),
35
+ * 'message' => 'Value length between %s and %s required'
36
+ * );
37
+ * validation['reqiuired'] = array(
38
+ * 'args' => array( '$value', true ),
39
+ * 'message' => 'This field is required'
40
+ * );
41
+ *
42
+ * Types have default and custom messages defined on it's side.
43
+ */
44
+ $value = '$value';
45
+ $validation = array();
46
+ if ( isset( $config['data']['validate'] ) ) {
47
+ foreach ( $config['data']['validate'] as $rule => $settings ) {
48
+ if ( $settings['active'] ) {
49
+ $validation[$rule] = array(
50
+ 'args' => isset( $settings['args'] ) ? array_unshift( $value,
51
+ $settings['args'] ) : array($value, true),
52
+ 'message' => $settings['message']
53
+ );
54
+ }
55
+ }
56
+ }
57
+ return $validation;
58
+ }
59
+
60
+ /**
61
+ * Filters conditional.
62
+ *
63
+ * We'll just handle this as a custom conditional
64
+ *
65
+ * Custom conditional
66
+ * Main properties:
67
+ * [custom] - custom statement made by user, note that $xxxx should match
68
+ * IDs of fields that passed this filter.
69
+ * [values] - same as for regular conditional
70
+ *
71
+ * [conditional] => Array(
72
+ [custom] => ($wpcf-my-date = DATE(01,02,2014)) OR ($wpcf-my-date > DATE(07,02,2014))
73
+ [values] => Array(
74
+ [wpcf-my-date] => 32508691200
75
+ )
76
+ )
77
+ *
78
+ * @param array|string $field settings array (as stored in DB) or field ID
79
+ * @param int $post_id Post or user ID to fetch meta data to check against
80
+ * @return array
81
+ */
82
+ public static function filterConditional( $if, $post_id ){
83
+
84
+ $data = WPToolset_Types::getCustomConditional($if, '', WPToolset_Types::getConditionalValues($post_id));
85
+ return $data;
86
+ }
87
+
88
+ }
embedded/common/toolset-forms/classes/class.credaudio.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once 'class.credfile.php';
3
+
4
+ /**
5
+ * Description of class
6
+ *
7
+ * @author Srdjan
8
+ *
9
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/common/tags/august-release/toolset-forms/classes/class.credaudio.php $
10
+ * $LastChangedDate: 2014-08-14 21:05:33 +0800 (Thu, 14 Aug 2014) $
11
+ * $LastChangedRevision: 25980 $
12
+ * $LastChangedBy: francesco $
13
+ *
14
+ */
15
+ class WPToolset_Field_Credaudio extends WPToolset_Field_Credfile
16
+ {
17
+ protected $_settings = array('min_wp_version' => '3.6');
18
+
19
+ public function metaform()
20
+ {
21
+ //TODO: check if this getValidationData does not break PHP Validation _cakePHP required file.
22
+ $validation = $this->getValidationData();
23
+ $validation['extension'] = array(
24
+ 'args' => array(
25
+ 'extension',
26
+ '16svx|2sf|8svx|aac|aif|aifc|aiff|amr|ape|asf|ast|au|aup|band|brstm|bwf|cdda|cust|dsf|dwd|flac|gsf|gsm|gym|it|jam|la|ly|m4a|m4p|mid|minipsf|mng|mod|mp1|mp2|mp3|mp4|mpc|mscz|mt2|mus|niff|nsf|off|ofr|ofs|ogg|ots|pac|psf|psf2|psflib|ptb|qsf|ra|raw|rka|rm|rmj|s3m|shn|sib|sid|smp|spc|spx|ssf|swa|tta|txm|usf|vgm|voc|vox|vqf|wav|wma|wv|xm|ym',
27
+ ),
28
+ 'message' => __( 'You can add only audio.', 'wpv-views' ),
29
+ );
30
+ $this->setValidationData($validation);
31
+ return parent::metaform();
32
+ }
33
+ }
embedded/common/toolset-forms/classes/class.credfile.php ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/common/tags/august-release/toolset-forms/classes/class.credfile.php $
5
+ * $LastChangedDate: 2014-08-09 05:11:46 +0800 (Sat, 09 Aug 2014) $
6
+ * $LastChangedRevision: 25806 $
7
+ * $LastChangedBy: francesco $
8
+ *
9
+ */
10
+ require_once 'class.textfield.php';
11
+
12
+ /**
13
+ * Description of class
14
+ *
15
+ * @author Francesco / Srdjan
16
+ */
17
+ class WPToolset_Field_Credfile extends WPToolset_Field_Textfield
18
+ {
19
+
20
+ public function init() {
21
+ wp_register_script( 'wpt-field-credfile',
22
+ WPTOOLSET_FORMS_RELPATH . '/js/credfile.js',
23
+ array('wptoolset-forms'), WPTOOLSET_FORMS_VERSION, true );
24
+ wp_enqueue_script( 'wpt-field-credfile' );
25
+ }
26
+
27
+ public static function registerScripts() {
28
+
29
+ }
30
+
31
+ public static function registerStyles() {
32
+
33
+ }
34
+
35
+ public function enqueueScripts() {
36
+
37
+ }
38
+
39
+ public function enqueueStyles() {
40
+
41
+ }
42
+
43
+ public function metaform() {
44
+ $value = $this->getValue();
45
+ $name = $this->getName();
46
+ if ( isset($this->_data['title']) ){
47
+ $title = $this->_data['title'];
48
+ }else{
49
+ $title = $name;
50
+ }
51
+
52
+ $id = str_replace( array( "[", "]" ), "", $name );
53
+ $delete_input_showhide = '';
54
+ $button_extra_classnames = '';
55
+
56
+ $has_image = false;
57
+ $is_empty = false;
58
+
59
+ if ( empty( $value ) ) {
60
+ $value = ''; // NOTE we need to set it to an empty string because sometimes it is NULL on repeating fields
61
+ $is_empty = true;
62
+ $delete_input_showhide = ' style="display:none"';
63
+ }
64
+
65
+ if ( $name == '_featured_image' ) {
66
+ $title = __( 'Featured Image', 'wpv-views' );
67
+ if ( !$is_empty ) {
68
+ if ( preg_match( '/src="([\w\d\:\/\._-]*)"/', $value, $_v ) ) {
69
+ $value = $_v[1];
70
+ }
71
+ }
72
+ }
73
+
74
+ if ( !$is_empty ) {
75
+ $pathinfo = pathinfo( $value );
76
+ // TODO we should check against the allowed mime types, not file extensions
77
+ if ( isset( $pathinfo['extension'] ) && in_array( strtolower( $pathinfo['extension'] ), array( 'png', 'gif', 'jpg', 'jpeg', 'bmp', 'tif' ) ) ) {
78
+ $has_image = true;
79
+ }
80
+ }
81
+
82
+ if ( array_key_exists( 'use_bootstrap', $this->_data ) && $this->_data['use_bootstrap'] ) {
83
+ $button_extra_classnames = ' btn btn-default btn-sm';
84
+ }
85
+
86
+ $preview_file = '';//WPTOOLSET_FORMS_RELPATH . '/images/icon-attachment32.png';
87
+ $attr_hidden = array(
88
+ 'id' => $id . "_hidden",
89
+ 'class' => 'js-wpv-credfile-hidden',
90
+ 'data-wpt-type' => 'file'
91
+ );
92
+ $attr_file = array(
93
+ 'id' => $id . "_file",
94
+ 'class' => 'js-wpt-credfile-upload-file wpt-credfile-upload-file',
95
+ 'alt' => $value,
96
+ );
97
+
98
+ if ( !$is_empty ) {
99
+ $preview_file = $value;
100
+ // Set attributes
101
+ $attr_file['disabled'] = 'disabled';
102
+ $attr_file['style'] = 'display:none';
103
+ } else {
104
+ $attr_hidden['disabled'] = 'disabled';
105
+ }
106
+
107
+ $form = array();
108
+ $form[] = array(
109
+ '#type' => 'markup',
110
+ '#markup' => '<input type="button" style="display:none" data-action="undo" class="js-wpt-credfile-undo wpt-credfile-undo' . $button_extra_classnames . '" value="' . esc_attr( __( 'Restore original', 'wpv-views' ) ) . '" />',
111
+ );
112
+ $form[] = array(
113
+ '#type' => 'markup',
114
+ '#markup' => '<input type="button"' . $delete_input_showhide . ' data-action="delete" class="js-wpt-credfile-delete wpt-credfile-delete' . $button_extra_classnames . '" value="' . esc_attr( __( 'Delete', 'wpv-views' ) ) . '" />',
115
+ );
116
+ $form[] = array(
117
+ '#type' => 'hidden',
118
+ '#name' => $name,
119
+ '#value' => $value,
120
+ '#attributes' => $attr_hidden,
121
+ );
122
+ $form[] = array(
123
+ '#type' => 'file',
124
+ '#name' => $name,
125
+ '#value' => $value,
126
+ '#title' => $title,
127
+ '#before' => '',
128
+ '#after' => '',
129
+ '#attributes' => $attr_file,
130
+ '#validate' => $this->getValidationData(),
131
+ '#repetitive' => $this->isRepetitive(),
132
+ );
133
+ if ( $has_image ) {
134
+ $form[] = array(
135
+ '#type' => 'markup',
136
+ '#markup' => '<span class="js-wpt-credfile-preview wpt-credfile-preview"><img id="'.$id.'_image" src="' . $preview_file . '" title="' . $preview_file . '" alt="' . $preview_file . '" class="js-wpt-credfile-preview-item wpt-credfile-preview-item" /></span>',
137
+ );
138
+ } else {
139
+ //if ( !$is_empty )
140
+ $form[] = array(
141
+ '#type' => 'markup',
142
+ '#markup' => '<span class="js-wpt-credfile-preview wpt-credfile-preview">' . $preview_file . '</span>',
143
+ );
144
+ }
145
+ return $form;
146
+ }
147
+
148
+ }
embedded/common/toolset-forms/classes/class.credimage.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once 'class.credfile.php';
3
+
4
+ /**
5
+ * Description of class
6
+ *
7
+ * @author Srdjan
8
+ *
9
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/common/tags/august-release/toolset-forms/classes/class.credimage.php $
10
+ * $LastChangedDate: 2014-08-14 21:05:33 +0800 (Thu, 14 Aug 2014) $
11
+ * $LastChangedRevision: 25980 $
12
+ * $LastChangedBy: francesco $
13
+ *
14
+ */
15
+ class WPToolset_Field_Credimage extends WPToolset_Field_Credfile
16
+ {
17
+ public function metaform()
18
+ {
19
+ //TODO: check if this getValidationData does not break PHP Validation _cakePHP required file.
20
+ $validation = $this->getValidationData();
21
+ $validation['extension'] = array(
22
+ 'args' => array(
23
+ 'extension',
24
+ 'jpg|jpeg|gif|png|bmp|webp',
25
+ ),
26
+ 'message' => __( 'You can add only images.', 'wpv-views' ),
27
+ );
28
+ $this->setValidationData($validation);
29
+ return parent::metaform();
30
+ }
31
+ }
embedded/common/toolset-forms/classes/class.credvideo.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once 'class.credfile.php';
3
+
4
+ /**
5
+ * Description of class
6
+ *
7
+ * @author Srdjan
8
+ *
9
+ * $HeadURL: https://www.onthegosystems.com/misc_svn/common/tags/august-release/toolset-forms/classes/class.credvideo.php $
10
+ * $LastChangedDate: 2014-08-14 21:05:33 +0800 (Thu, 14 Aug 2014) $
11
+ * $LastChangedRevision: 25980 $
12
+ * $LastChangedBy: francesco $
13
+ *
14
+ */
15
+ class WPToolset_Field_Credvideo extends WPToolset_Field_Credfile
16
+ {
17
+ protected $_settings = array('min_wp_version' => '3.6');
18
+
19
+ public function metaform()
20
+ {
21
+ //TODO: check if this getValidationData does not break PHP Validation _cakePHP required file.
22
+ $validation = $this->getValidationData();
23
+ $validation['extension'] = array(
24
+ 'args' => array(
25
+ 'extension',
26
+ '3gp|aaf|asf|avchd|avi|cam|dat|dsh|fla|flr|flv|m1v|m2v|m4v|mng|mp4|mxf|nsv|ogg|rm|roq|smi|sol|svi|swf|wmv|wrap|mkv|mov|mpe|mpeg|mpg',
27
+ ),
28
+ 'message' => __( 'You can add only video.', 'wpv-views' ),
29
+ );
30
+ $this->setValidationData($validation);
31
+ return parent::metaform();
32
+ }
33
+ }
embedded/common/toolset-forms/classes/class.custom_conditional.php ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Custom conditinal evaluation class.
4
+ *
5
+ * Uses common functions.
6
+ * Cloned wpv_condition() moved here to release it from post meta.
7
+ * Instead getting post meta, array of values is passed (like get_post_custom())
8
+ * and those values are used for evaluation.
9
+ *
10
+ * Known bugs with wpv_condition()
11
+ * - field names with slash, like '$my-field' fails regex
12
+ * - some mixed statements fail, like '($t = 'show') OR ($t > 10)' cause using
13
+ * string and num comparation
14
+ */
15
+ require_once WPTOOLSET_COMMON_PATH . '/functions.php';
16
+ require_once WPTOOLSET_COMMON_PATH . '/wpv-filter-date-embedded.php';
17
+ require_once WPTOOLSET_COMMON_PATH . '/wplogger.php';
18
+
19
+ /**
20
+ * Description of class
21
+ */
22
+ class WPToolset_Forms_Custom_Conditional
23
+ {
24
+
25
+ private $__evaluate, $__fields, $__values;
26
+
27
+ public function __construct( $evaluate, $fields, $values ){
28
+ $this->__evaluate = $evaluate;
29
+ $this->__fields = $fields;
30
+ $this->__values = $values;
31
+ }
32
+
33
+ public function evaluate(){
34
+ return $this->_wpv_condition( $this->__evaluate, $this->__fields );
35
+ }
36
+
37
+ protected function _getValue( $key ){
38
+ return isset( $this->__values[$key] ) ? $this->__values[$key] : null;
39
+ }
40
+
41
+ /**
42
+ * Condition function to evaluate and display given block based on expressions
43
+ *
44
+ * Supported actions and symbols:
45
+ *
46
+ * Integer and floating-point numbers
47
+ * Math operators: +, -, *, /
48
+ * Comparison operators: &lt;, &gt;, =, &lt;=, &gt;=, !=
49
+ * Boolean operators: AND, OR, NOT
50
+ * Nested expressions - several levels of brackets
51
+ * Variables defined as shortcode parameters starting with a dollar sign
52
+ * empty() function that checks for blank or non-existing fields
53
+ *
54
+ * @global type $wplogger
55
+ * @param type $evaluate
56
+ * @param type $fields
57
+ * @return type
58
+ */
59
+ protected function _wpv_condition( $evaluate, $fields ){
60
+
61
+ global $wplogger;
62
+
63
+ $logging_string = "Original expression: " . $evaluate;
64
+
65
+ add_filter( 'wpv-extra-condition-filters', 'wpv_add_time_functions' );
66
+ $evaluate = apply_filters( 'wpv-extra-condition-filters', $evaluate );
67
+
68
+ // evaluate empty() statements for variables
69
+ // $empties = preg_match_all( "/empty\(\s*\\$(\w+)\s*\)/", $evaluate,
70
+ // $matches );
71
+ $empties = preg_match_all( "/empty\(\s*\\$([\w_-]+)\s*\)/", $evaluate,
72
+ $matches );
73
+
74
+ if ( $empties && $empties > 0 ) {
75
+ for ( $i = 0; $i < $empties; $i++ ) {
76
+ $match_var = $this->_getValue( $fields[$matches[1][$i]] );
77
+ $is_empty = '1=0';
78
+
79
+ // mark as empty only nulls and ""
80
+ // if ( is_null( $match_var ) || strlen( $match_var ) == 0 ) {
81
+ if ( is_null( $match_var ) || ( is_string( $match_var ) && strlen( $match_var ) == 0 ) || ( is_array( $match_var ) && empty( $match_var ) ) ) {
82
+ $is_empty = '1=1';
83
+ }
84
+
85
+ $evaluate = str_replace( $matches[0][$i], $is_empty, $evaluate );
86
+ }
87
+ }
88
+
89
+ // find variables that are to be used as strings.
90
+ // eg '$f1'
91
+ // will replace $f1 with the actual field value
92
+ $strings_count = preg_match_all( '/(\'[\$\w^\']*\')/', $evaluate,
93
+ $matches );
94
+ if ( $strings_count && $strings_count > 0 ) {
95
+ for ( $i = 0; $i < $strings_count; $i++ ) {
96
+ $string = $matches[1][$i];
97
+ // remove single quotes from string literals to get value only
98
+ $string = (strpos( $string, '\'' ) === 0) ? substr( $string, 1,
99
+ strlen( $string ) - 2 ) : $string;
100
+ if ( strpos( $string, '$' ) === 0 ) {
101
+ $variable_name = substr( $string, 1 ); // omit dollar sign
102
+ if ( isset( $fields[$variable_name] ) ) {
103
+ $string = $this->_getValue( $fields[$variable_name] );
104
+ $evaluate = str_replace( $matches[1][$i],
105
+ "'" . $string . "'", $evaluate );
106
+ }
107
+ }
108
+ }
109
+ }
110
+
111
+ // find string variables and evaluate
112
+ // $strings_count = preg_match_all( '/((\$\w+)|(\'[^\']*\'))\s*([\!<>\=]+)\s*((\$\w+)|(\'[^\']*\'))/',
113
+ // $evaluate, $matches );
114
+ $strings_count = preg_match_all( '/((\$[\w_-]+)|([\'\d][^\']*[\'\d]))\s*([\!<>\=]+)\s*((\$[\w_-]+)|([\'\d]*[\'\d]))/',
115
+ $evaluate, $matches );
116
+
117
+ // get all string comparisons - with variables and/or literals
118
+ if ( $strings_count && $strings_count > 0 ) {
119
+ for ( $i = 0; $i < $strings_count; $i++ ) {
120
+
121
+ // get both sides and sign
122
+ $first_string = $matches[1][$i];
123
+ $second_string = $matches[5][$i];
124
+ $math_sign = $matches[4][$i];
125
+
126
+ // remove single quotes from string literals to get value only
127
+ $first_string = (strpos( $first_string, '\'' ) === 0) ? substr( $first_string,
128
+ 1, strlen( $first_string ) - 2 ) : $first_string;
129
+ $second_string = (strpos( $second_string, '\'' ) === 0) ? substr( $second_string,
130
+ 1, strlen( $second_string ) - 2 ) : $second_string;
131
+
132
+ // replace variables with text representation
133
+ if ( strpos( $first_string, '$' ) === 0 ) {
134
+ $variable_name = substr( $first_string, 1 ); // omit dollar sign
135
+ if ( isset( $fields[$variable_name] ) ) {
136
+ $first_string = $this->_getValue( $fields[$variable_name] );
137
+ } else {
138
+ $first_string = '';
139
+ }
140
+ }
141
+ if ( strpos( $second_string, '$' ) === 0 ) {
142
+ $variable_name = substr( $second_string, 1 );
143
+ if ( isset( $fields[$variable_name] ) ) {
144
+ $second_string = $this->_getValue( $fields[$variable_name] );
145
+ } else {
146
+ $second_string = '';
147
+ }
148
+ }
149
+
150
+ // don't do string comparison if variables are numbers
151
+ if ( (is_numeric( $first_string ) && !is_numeric( $second_string ))
152
+ || (!is_numeric( $first_string ) && is_numeric( $second_string )) ) {
153
+ $evaluate = str_replace( $matches[0][$i], '1=0',
154
+ $evaluate );
155
+ } else if ( !(is_numeric( $first_string ) && is_numeric( $second_string )) ) {
156
+ // compare string and return true or false
157
+ $compared_str_result = wpv_compare_strings( $first_string,
158
+ $second_string, $math_sign );
159
+
160
+ if ( $compared_str_result ) {
161
+ $evaluate = str_replace( $matches[0][$i], '1=1',
162
+ $evaluate );
163
+ } else {
164
+ $evaluate = str_replace( $matches[0][$i], '1=0',
165
+ $evaluate );
166
+ }
167
+ } else {
168
+ $evaluate = str_replace( $matches[1][$i], $first_string,
169
+ $evaluate );
170
+ $evaluate = str_replace( $matches[5][$i], $second_string,
171
+ $evaluate );
172
+ }
173
+ }
174
+ }
175
+
176
+ // find remaining strings that maybe numeric values.
177
+ // This handles 1='1'
178
+ $strings_count = preg_match_all( '/(\'[^\']*\')/', $evaluate, $matches );
179
+ if ( $strings_count && $strings_count > 0 ) {
180
+ for ( $i = 0; $i < $strings_count; $i++ ) {
181
+ $string = $matches[1][$i];
182
+ // remove single quotes from string literals to get value only
183
+ $string = (strpos( $string, '\'' ) === 0) ? substr( $string, 1,
184
+ strlen( $string ) - 2 ) : $string;
185
+ if ( is_numeric( $string ) ) {
186
+ $evaluate = str_replace( $matches[1][$i], $string, $evaluate );
187
+ }
188
+ }
189
+ }
190
+
191
+
192
+ // find all variable placeholders in expression
193
+ // $count = preg_match_all( '/\$(\w+)/', $evaluate, $matches );
194
+ $count = preg_match_all( '/\$([\w-_]+)/', $evaluate, $matches );
195
+
196
+ $logging_string .= "; Variable placeholders: " . var_export( $matches[1],
197
+ true );
198
+
199
+ // replace all variables with their values listed as shortcode parameters
200
+ if ( $count && $count > 0 ) {
201
+ // sort array by length desc, fix str_replace incorrect replacement
202
+ $matches[1] = wpv_sort_matches_by_length( $matches[1] );
203
+
204
+ foreach ( $matches[1] as $match ) {
205
+ if ( isset( $fields[$match] ) ) {
206
+ $meta = $this->_getValue( $fields[$match] );
207
+ if ( empty( $meta ) ) {
208
+ $meta = "0";
209
+ }
210
+ } else {
211
+ $meta = "0";
212
+ }
213
+ $evaluate = str_replace( '$' . $match, $meta, $evaluate );
214
+ }
215
+ }
216
+
217
+ $logging_string .= "; End evaluated expression: " . $evaluate;
218
+
219
+ $wplogger->log( $logging_string, WPLOG_DEBUG );
220
+ // evaluate the prepared expression using the custom eval script
221
+ $result = wpv_evaluate_expression( $evaluate );
222
+
223
+ // return true, false or error string to the conditional caller
224
+ return $result;
225
+ }
226
+ }
embedded/common/toolset-forms/classes/class.date.php ADDED
@@ -0,0 +1,406 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once 'class.field_factory.php';
3
+ if (!function_exists('adodb_mktime')) {
4
+ require_once WPTOOLSET_FORMS_ABSPATH . '/lib/adodb-time.inc.php';
5
+ }
6
+
7
+ /**
8
+ * Description of class
9
+ *
10
+ * @author Srdjan
11
+ */
12
+ class WPToolset_Field_Date extends FieldFactory
13
+ {
14
+
15
+ // 15/10/1582 00:00 - 31/12/3000 23:59
16
+ protected static $_mintimestamp = -12219292800, $_maxtimestamp = 32535215940;
17
+
18
+ public function init()
19
+ {
20
+ }
21
+
22
+ public static function registerScripts()
23
+ {
24
+ }
25
+
26
+ public static function registerStyles()
27
+ {
28
+ }
29
+
30
+ public static function addFilters(){
31
+ if ( has_filter( 'wptoolset_validation_value_date',
32
+ array('WPToolset_Field_Date', 'filterValidationValue') ) )
33
+ return;
34
+ // Filter validation
35
+ add_filter( 'wptoolset_validation_value_date',
36
+ array('WPToolset_Field_Date', 'filterValidationValue') );
37
+ add_filter( 'wptoolset_validation_rule_js',
38
+ array('WPToolset_Field_Date', 'filterValidationRuleJs') );
39
+ add_filter( 'wptoolset_validation_args_php',
40
+ array('WPToolset_Field_Date', 'filterValidationArgsPhp'), 10, 2 );
41
+ // Filter conditional
42
+ add_filter( 'wptoolset_conditional_args_php',
43
+ array('WPToolset_Field_Date', 'filterConditionalArgsPhp'), 10, 2 );
44
+ add_filter( 'wptoolset_conditional_value_php',
45
+ array('WPToolset_Field_Date', 'filterConditionalValuePhp'), 10,
46
+ 2 );
47
+ add_filter( 'wptoolset_conditional_args_js',
48
+ array('WPToolset_Field_Date', 'filterConditionalArgsJs'), 10, 2 );
49
+ }
50
+
51
+ public function enqueueScripts()
52
+ {
53
+ }
54
+
55
+ public function enqueueStyles()
56
+ {
57
+ }
58
+
59
+ public function metaform() {
60
+ $time_value = $this->getValue();
61
+ $datepicker = $hour = $minute = null;
62
+ $timestamp = false;
63
+ $readonly = false;
64
+ if ( is_admin() ) {
65
+ // In this case, getValue returns the timestamp stored as postmeta value on the database
66
+ // So we compose $timestamp, $datepicker, $hour and $minute based on that value
67
+ if ( !empty( $time_value ) && $time_value != '0' ) {
68
+ if ( !is_numeric( $time_value ) ) {
69
+ $timestamp = self::strtotime( $time_value );
70
+ } else {
71
+ $timestamp = $time_value;
72
+ }
73
+ if ( $timestamp !== false && self::_isTimestampInRange( $timestamp ) ) {
74
+ $datepicker = self::timetodate( $timestamp );
75
+ $hour = self::timetodate( $timestamp, 'H' );
76
+ $minute = self::timetodate( $timestamp, 'i' );
77
+ }
78
+ }
79
+ } else {
80
+ // We are on a CRED form, on frontend, so getVAlue returns nothing or a string or an array of the kind array( 'datepicker' =>, 'hour' =>, 'minute' => )
81
+ // Note that even if the array is passed, 'hour' and 'minute' will only be passed if there are any
82
+ if ( !empty( $time_value ) ) {
83
+ if ( is_array( $time_value ) ) {
84
+ if ( isset ( $time_value['timestamp'] ) && is_numeric( $time_value['timestamp'] ) && self::_isTimestampInRange( $time_value['timestamp'] ) ) {
85
+ $timestamp = $time_value['timestamp'];
86
+ $datepicker = self::timetodate( $timestamp );
87
+ } else if ( isset( $time_value['datepicker'] ) && $time_value['datepicker'] !== false && is_numeric( $time_value['datepicker'] ) && self::_isTimestampInRange( $time_value['datepicker'] ) ) {
88
+ $timestamp = $time_value['datepicker'];
89
+ $datepicker = self::timetodate( $timestamp );
90
+ }
91
+ if ( isset( $time_value['hour'] ) && is_numeric( $time_value['hour'] ) ) {
92
+ $hour = $time_value['hour'];
93
+ }
94
+ if ( isset( $time_value['minute'] ) && is_numeric( $time_value['minute'] ) ) {
95
+ $minute = $time_value['minute'];
96
+ }
97
+ } else {
98
+ if ( is_numeric( $time_value ) && self::_isTimestampInRange( $time_value ) ) {
99
+ $timestamp = $time_value;
100
+ $datepicker = self::timetodate( $timestamp );
101
+ } else {
102
+ $timestamp = self::strtotime( $time_value );
103
+ $datepicker = $time_value;
104
+ }
105
+ }
106
+ }
107
+ }
108
+ $data = $this->getData();
109
+ if ( !$timestamp ) {
110
+ // If there is no timestamp, we need to make it an empty string
111
+ // A false value would render the hidden field with a value of 1
112
+ $timestamp = '';
113
+ $datepicker = null;
114
+ }
115
+
116
+ $def_class = 'js-wpt-date';
117
+
118
+ $def_class_aux = 'js-wpt-date-auxiliar';
119
+
120
+ if ( isset( $data['attribute'] ) && isset( $data['attribute']['readonly'] ) && $data['attribute']['readonly'] == 'readonly' ) {
121
+ $def_class .= ' js-wpv-date-readonly';
122
+ $def_class_aux .= ' js-wpt-date-readonly';
123
+ $readonly = true;
124
+ }
125
+
126
+ $form = array();
127
+
128
+ $validate = $this->getValidationData();
129
+ $title = $this->getTitle();
130
+
131
+ if ( isset( $validate['required'] ) && !empty( $title ) ) {
132
+ // Asterisk
133
+ $title .= '&#42;';
134
+ }
135
+
136
+ $attr_visible = array('class' => $def_class, 'style' => 'display:inline;width:150px;position:relative;z-index:20;', 'readonly' => 'readonly');
137
+ $attr_hidden = array('class' => $def_class_aux, 'data-ts' => $timestamp, 'data-wpt-type' => 'date' );
138
+
139
+ if ( isset( $data['attribute'] ) && isset( $data['attribute']['placeholder'] ) ) {
140
+ $attr_visible['placeholder'] = $data['attribute']['placeholder'];
141
+ }
142
+
143
+ $form[] = array(
144
+ '#type' => 'textfield',
145
+ '#title' => $title,
146
+ '#description' => $this->getDescription(),
147
+ '#attributes' => $attr_visible,
148
+ '#name' => '',
149
+ '#value' => $datepicker,
150
+ );
151
+ $form[] = array(
152
+ '#type' => 'hidden',
153
+ '#title' => $title,
154
+ '#attributes' => $attr_hidden,
155
+ '#name' => $this->getName() . '[datepicker]',
156
+ '#value' => $timestamp,
157
+ '#validate' => $validate,
158
+ '#repetitive' => $this->isRepetitive(),
159
+ );
160
+
161
+ /*
162
+ // This was the old implementaton
163
+ // We have implemented the above one because we need a hidden field to hold the timestamp
164
+ // And the visible text input field to display the date string to the user
165
+ $form[] = array(
166
+ '#type' => 'textfield',
167
+ '#title' => $this->getTitle(),
168
+ '#attributes' => array('class' => $def_class, 'style' => 'width:150px;'),
169
+ '#name' => $this->getName() . '[datepicker]',
170
+ '#value' => $timestamp,
171
+ '#validate' => $this->getValidationData(),
172
+ '#repetitive' => $this->isRepetitive(),
173
+ );
174
+ */
175
+ if ( !empty( $data['add_time'] ) ) {
176
+ // Shared attributes
177
+ $attributes_hour_minute = array();
178
+ if ( $readonly ) {
179
+ $attributes_hour_minute['disabled'] = 'disabled' ;
180
+ }
181
+ if ( array_key_exists( 'use_bootstrap', $this->_data ) && $this->_data['use_bootstrap'] ) {
182
+ $attributes_hour_minute['style'] = 'display:inline;width:auto;' ;
183
+ }
184
+
185
+ // Hour
186
+ $hours = 24;
187
+ $options = array();
188
+ for ( $index = 0; $index < $hours; $index++ ) {
189
+ $prefix = $index < 10 ? '0' : '';
190
+ $options[$index] = array(
191
+ '#title' => $prefix . strval( $index ),
192
+ '#value' => $index,
193
+ );
194
+ }
195
+ $hour_element = array(
196
+ '#type' => 'select',
197
+ '#title' => __( 'Hour', 'wpv-views' ),
198
+ '#options' => $options,
199
+ '#default_value' => $hour,
200
+ '#name' => $this->getName() . '[hour]',
201
+ '#inline' => true,
202
+ );
203
+ if ( !empty( $attributes_hour_minute ) ) {
204
+ $hour_element['#attributes'] = $attributes_hour_minute;
205
+ }
206
+ $form[] = $hour_element;
207
+ // Minutes
208
+ $minutes = 60;
209
+ $options = array();
210
+ for ( $index = 0; $index < $minutes; $index++ ) {
211
+ $prefix = $index < 10 ? '0' : '';
212
+ $options[$index] = array(
213
+ '#title' => $prefix . strval( $index ),
214
+ '#value' => $index,
215
+ );
216
+ }
217
+ $minute_element = array(
218
+ '#type' => 'select',
219
+ '#title' => __( 'Minute', 'wpv-views' ),
220
+ '#options' => $options,
221
+ '#default_value' => $minute,
222
+ '#name' => $this->getName() . '[minute]',
223
+ '#inline' => true,
224
+ );
225
+ if ( !empty( $attributes_hour_minute ) ) {
226
+ $minute_element['#attributes'] = $attributes_hour_minute;
227
+ }
228
+ $form[] = $minute_element;
229
+ }
230
+
231
+ return $form;
232
+ }
233
+
234
+ public static function getDateFormat()
235
+ {
236
+ return WPToolset_Field_Date_Scripts::getDateFormat();
237
+ }
238
+
239
+ protected function _dateToStrftime( $format ) {
240
+ $format = str_replace( 'd', '%d', $format );
241
+ $format = str_replace( 'D', '%a', $format );
242
+ $format = str_replace( 'j', '%e', $format );
243
+ $format = str_replace( 'l', '%A', $format );
244
+ $format = str_replace( 'N', '%u', $format );
245
+ $format = str_replace( 'w', '%w', $format );
246
+
247
+ $format = str_replace( 'W', '%W', $format );
248
+
249
+ $format = str_replace( 'F', '%B', $format );
250
+ $format = str_replace( 'm', '%m', $format );
251
+ $format = str_replace( 'M', '%b', $format );
252
+ $format = str_replace( 'n', '%m', $format );
253
+
254
+ $format = str_replace( 'o', '%g', $format );
255
+ $format = str_replace( 'Y', '%Y', $format );
256
+ $format = str_replace( 'y', '%y', $format );
257
+
258
+ return $format;
259
+ }
260
+
261
+ public static function filterValidationValue( $value ) {
262
+ if ( isset( $value['datepicker'] ) ) {
263
+ return $value['datepicker'];
264
+ }
265
+ return $value;
266
+ }
267
+
268
+ public static function filterValidationRuleJs( $rule ) {
269
+ if ( $rule == 'date' ) {
270
+ return 'dateADODB_STAMP';
271
+ } else {
272
+ return $rule;
273
+ }
274
+ }
275
+
276
+ public static function filterValidationArgsPhp( $args, $rule ) {
277
+ if ( $rule == 'date' ) {
278
+ return array('$value', self::getDateFormat());
279
+ }
280
+ return $args;
281
+ }
282
+
283
+ public static function filterConditionalArgsJs( $args, $type ) {
284
+ if ( $type == 'date' ) {
285
+ foreach ( $args as &$arg ) {
286
+ if ( !is_numeric( $arg ) ) {
287
+ // Well it should be a numeric timestamp indeed
288
+ $arg = self::strtotime( $arg );
289
+ }
290
+ }
291
+ }
292
+ return $args;
293
+ }
294
+
295
+ public static function filterConditionalArgsPhp( $args, $type ) {
296
+ if ( $type == 'date' ) {
297
+ foreach ( $args as &$arg ) {
298
+ $arg = self::filterConditionalValuePhp( $arg, $type );
299
+ }
300
+ }
301
+ return $args;
302
+ }
303
+
304
+ public static function filterConditionalValuePhp( $value, $type ) {
305
+ if ( $type == 'date' ) {
306
+ if ( !is_numeric( $value ) ) {
307
+ // Well it should be a numeric timestamp indeed
308
+ $value = self::strtotime( $value );
309
+ }
310
+ // Use timestamp with PHP
311
+ // Convert back/forward to have rounded timestamp (no H and i)
312
+ // TODO review this because we should not play with timestamps generated on adodb_xxx functions
313
+ //$value = self::strtotime( self::timetodate( $value ) );
314
+ }
315
+ return $value;
316
+ }
317
+
318
+ // We need to keep this for backwards compatibility
319
+ // Note that this function will only convert dates coming on a string:
320
+ // - in english
321
+ // - inside the valid PHP date range
322
+ // We are only using this when the value being checked is not a timestamp
323
+ // And we have tried to avoid that situation from happening
324
+ // But for old implementation, this happens for date conditions on conditional fields
325
+ public static function strtotime( $value, $format = null )
326
+ {
327
+ if ( is_null( $format ) ) {
328
+ $format = self::getDateFormat();
329
+ }
330
+ /**
331
+ * add exception to handle short year
332
+ */
333
+ if ( 'd/m/y' == $format ) {
334
+ preg_match_all( '/(\d{2})/', $value, $value );
335
+ $value[0][2] += $value[0][2] < 70? 2000:1900;
336
+ $value = implode('-', $value[0] );
337
+ }
338
+ if ( strpos($format, 'd/m/Y') !== false ) {
339
+ // strtotime requires a dash or dot separator to determine dd/mm/yyyy format
340
+ preg_match( '/\d{2}\/\d{2}\/\d{4}/', $value, $matches );
341
+ if ( !empty( $matches ) ) {
342
+ foreach ( $matches as $match ) {
343
+ $value = str_replace( $match,
344
+ str_replace( '/', '-', $match ), $value );
345
+ }
346
+ }
347
+ }
348
+ try {
349
+ $date = new DateTime( $value );
350
+ } catch ( Exception $e ) {
351
+ return false;
352
+ }
353
+ $timestamp = $date->format( "U" );
354
+ return self::_isTimestampInRange( $timestamp ) ? $timestamp : false;
355
+ }
356
+
357
+ // TODO review this because we should not play with timestamps generated on adodb_xxx functions
358
+ public static function timetodate( $timestamp, $format = null )
359
+ {
360
+ return WPToolset_Field_Date_Scripts::timetodate( $timestamp, $format );
361
+ }
362
+
363
+ protected static function _isTimestampInRange( $timestamp )
364
+ {
365
+ return WPToolset_Field_Date_Scripts::_isTimestampInRange($timestamp);
366
+ }
367
+
368
+ /**
369
+ * DEPRECATED
370
+ *
371
+ * This is not used anymore
372
+ */
373
+ public static function timeIsValid( $time ) {
374
+ /*
375
+ * http://php.net/manual/en/function.strtotime.php
376
+ * The valid range of a timestamp is typically
377
+ * from Fri, 13 Dec 1901 20:45:54 UTC
378
+ * to Tue, 19 Jan 2038 03:14:07 UTC.
379
+ * (These are the dates that correspond to the minimum
380
+ * and maximum values for a 32-bit signed integer.)
381
+ * Additionally, not all platforms support negative timestamps,
382
+ * therefore your date range may be limited to no earlier than
383
+ * the Unix epoch.
384
+ * This means that e.g. dates prior to Jan 1, 1970 will not
385
+ * work on Windows, some Linux distributions,
386
+ * and a few other operating systems.
387
+ * PHP 5.1.0 and newer versions overcome this limitation though.
388
+ */
389
+ // MIN 'Jan 1, 1970' - 0 | Fri, 13 Dec 1901 20:45:54 UTC
390
+ $_min_time = self::timeNegativeSupported() ? -2147483646 : 0;
391
+ // MAX 'Tue, 19 Jan 2038 03:14:07 UTC' - 2147483647
392
+ $_max_time = 2147483647;
393
+
394
+ return is_numeric( $time ) && $_min_time <= intval( $time ) && intval( $time ) <= $_max_time;
395
+ }
396
+
397
+ /**
398
+ * DEPRECATED
399
+ *
400
+ * This is not used anymore
401
+ */
402
+ public static function timeNegativeSupported() {
403
+ return strtotime( 'Fri, 13 Dec 1950 20:45:54 UTC' ) === -601010046;
404
+ }
405
+
406
+ }
embedded/common/toolset-forms/classes/class.date.scripts.php ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!function_exists('adodb_mktime')) {
3
+ require_once WPTOOLSET_FORMS_ABSPATH . '/lib/adodb-time.inc.php';
4
+ }
5
+
6
+ class WPToolset_Field_Date_Scripts
7
+ {
8
+
9
+ public static $_supported_date_formats = array(
10
+ 'F j, Y', //December 23, 2011
11
+ 'Y/m/d', // 2011/12/23
12
+ 'm/d/Y', // 12/23/2011
13
+ 'd/m/Y', // 23/22/2011
14
+ 'd/m/y', // 23/22/11
15
+ );
16
+
17
+ public $_supported_date_formats_text = array(
18
+ 'F j, Y' => 'Month dd, yyyy',
19
+ 'Y/m/d' => 'yyyy/mm/dd',
20
+ 'm/d/Y' => 'mm/dd/yyyy',
21
+ 'd/m/Y' => 'dd/mm/yyyy',
22
+ 'd/m/y' => 'dd/mm/yy',
23
+ );
24
+
25
+ // 15/10/1582 00:00 - 31/12/3000 23:59
26
+ protected static $_mintimestamp = -12219292800;
27
+ protected static $_maxtimestamp = 32535215940;
28
+
29
+ public function __construct()
30
+ {
31
+ global $pagenow;
32
+ if (
33
+ //for front-end
34
+ !is_admin() ||
35
+ //for edit group pages
36
+ ( ( isset($_GET['page']) && ($_GET['page'] == 'wpcf-edit-usermeta' || $_GET['page'] == 'wpcf-edit') ) ||
37
+ //for edit pages including profile pages
38
+ ($pagenow == 'profile.php' || $pagenow == 'post-new.php' || $pagenow == 'user-edit.php' || $pagenow == 'user-new.php' || $pagenow == 'post.php' || $pagenow == 'admin-ajax.php') && is_admin() ) ){
39
+ add_action( 'admin_enqueue_scripts', array( $this,'date_enqueue_scripts' ) );
40
+ add_action( 'wp_enqueue_scripts', array( $this, 'date_enqueue_scripts' ) );
41
+ }
42
+ $this->localization_slug = false;
43
+ }
44
+
45
+ public function date_enqueue_scripts()
46
+ {
47
+ /**
48
+ * styles
49
+ */
50
+ wp_register_style(
51
+ 'wptoolset-field-datepicker',
52
+ WPTOOLSET_FORMS_RELPATH . '/css/wpt-jquery-ui/datepicker.css',
53
+ array(),
54
+ WPTOOLSET_FORMS_VERSION
55
+ );
56
+ wp_register_style(
57
+ 'wptoolset-field-date',
58
+ WPTOOLSET_FORMS_RELPATH . '/css/wpt-jquery-ui/jquery-ui-1.9.2.custom.min.css',
59
+ array('wptoolset-field-datepicker'),
60
+ WPTOOLSET_FORMS_VERSION
61
+ );
62
+ /**
63
+ * scripts
64
+ */
65
+ wp_register_script(
66
+ 'wptoolset-field-date',
67
+ WPTOOLSET_FORMS_RELPATH . '/js/date.js',
68
+ array('jquery-ui-datepicker', 'wptoolset-forms'),
69
+ WPTOOLSET_FORMS_VERSION,
70
+ true
71
+ );
72
+ // Localize datepicker
73
+ if ( in_array( self::getDateFormat(), self::$_supported_date_formats ) ) {
74
+ /*
75
+ $locale = str_replace( '_', '-', strtolower( get_locale() ) );
76
+ $file = WPTOOLSET_FORMS_ABSPATH . '/js/i18n/jquery.ui.datepicker-' . $locale . '.js';
77
+ if ( file_exists( $file ) ) {
78
+ wp_register_script(
79
+ 'wptoolset-field-date-localized',
80
+ WPTOOLSET_FORMS_RELPATH . '/js/i18n/jquery.ui.datepicker-' . $locale . '.js',
81
+ array('jquery-ui-datepicker'),
82
+ WPTOOLSET_FORMS_VERSION,
83
+ true
84
+ );
85
+ }
86
+ */
87
+ $lang = get_locale();
88
+ $lang = str_replace('_', '-', $lang);
89
+ // TODO integrate this with WPML lang
90
+ if ( file_exists( WPTOOLSET_FORMS_ABSPATH . '/js/i18n/jquery.ui.datepicker-' . $lang . '.js' ) ) {
91
+ if ( !wp_script_is( 'jquery-ui-datepicker-local-' . $lang, 'registered' ) ) {
92
+ wp_register_script( 'jquery-ui-datepicker-local-' . $lang, WPTOOLSET_FORMS_RELPATH . '/js/i18n/jquery.ui.datepicker-' . $lang . '.js', array('jquery-ui-core', 'jquery', 'jquery-ui-datepicker'), WPTOOLSET_FORMS_VERSION, true );
93
+ $this->localization_slug = $lang;
94
+ }
95
+ } else {
96
+ $lang = substr($lang, 0, 2);
97
+ if ( file_exists( WPTOOLSET_FORMS_ABSPATH . '/js/i18n/jquery.ui.datepicker-' . $lang . '.js' ) ) {
98
+ if ( !wp_script_is( 'jquery-ui-datepicker-local-' . $lang, 'registered' ) ) {
99
+ wp_register_script( 'jquery-ui-datepicker-local-' . $lang, WPTOOLSET_FORMS_RELPATH . '/js/i18n/jquery.ui.datepicker-' . $lang . '.js', array('jquery-ui-core', 'jquery', 'jquery-ui-datepicker'), WPTOOLSET_FORMS_VERSION, true );
100
+ $this->localization_slug = $lang;
101
+ }
102
+ }
103
+ }
104
+ }
105
+ /**
106
+ * styles
107
+ */
108
+ wp_enqueue_style( 'wptoolset-field-date' );
109
+ /**
110
+ * scripts
111
+ */
112
+ wp_enqueue_script( 'wptoolset-field-date' );
113
+ $date_format = self::getDateFormat();
114
+ $js_date_format = $this->_convertPhpToJs( $date_format );
115
+ $calendar_image = WPTOOLSET_FORMS_RELPATH . '/images/calendar.gif';
116
+ $calendar_image = apply_filters( 'wptoolset_filter_wptoolset_calendar_image', $calendar_image );
117
+ $calendar_image_readonly = WPTOOLSET_FORMS_RELPATH . '/images/calendar-readonly.gif';
118
+ $calendar_image_readonly = apply_filters( 'wptoolset_filter_wptoolset_calendar_image_readonly', $calendar_image_readonly );
119
+ $js_data = array(
120
+ 'buttonImage' => $calendar_image,
121
+ 'buttonText' => __( 'Select date', 'wpv-views' ),
122
+ 'dateFormat' => $js_date_format,
123
+ 'dateFormatPhp' => $date_format,
124
+ 'dateFormatNote' => esc_js( sprintf( __( 'Input format: %s', 'wpv-views' ), $date_format ) ),
125
+ 'yearMin' => intval( self::timetodate( self::$_mintimestamp, 'Y' ) ) + 1,
126
+ 'yearMax' => self::timetodate( self::$_maxtimestamp, 'Y' ),
127
+ 'ajaxurl' => admin_url('admin-ajax.php', null),
128
+ 'readonly' => esc_js( __( 'This is a readonly date input', 'wpv-views' ) ),
129
+ 'readonly_image' => $calendar_image_readonly
130
+ );
131
+ wp_localize_script( 'wptoolset-field-date', 'wptDateData', $js_data );
132
+ if ( $this->localization_slug && !wp_script_is( 'jquery-ui-datepicker-local-' . $this->localization_slug ) ) {
133
+ wp_enqueue_script( 'jquery-ui-datepicker-local-' . $this->localization_slug );
134
+ }
135
+ }
136
+
137
+ protected function _convertPhpToJs( $date_format )
138
+ {
139
+ $date_format = str_replace( 'd', 'dd', $date_format );
140
+ $date_format = str_replace( 'j', 'd', $date_format );
141
+ $date_format = str_replace( 'l', 'DD', $date_format );
142
+ $date_format = str_replace( 'm', 'mm', $date_format );
143
+ $date_format = str_replace( 'n', 'm', $date_format );
144
+ $date_format = str_replace( 'F', 'MM', $date_format );
145
+ $date_format = str_replace( 'y', 'y', $date_format );
146
+ $date_format = str_replace( 'Y', 'yy', $date_format );
147
+
148
+ return $date_format;
149
+ }
150
+
151
+ public static function getDateFormat() {
152
+ $date_format = get_option( 'date_format' );
153
+ if ( !in_array( $date_format, self::$_supported_date_formats ) ) {
154
+ $date_format = 'F j, Y';
155
+ }
156
+ return $date_format;
157
+ }
158
+
159
+ public static function timetodate( $timestamp, $format = null )
160
+ {
161
+ if ( is_null( $format ) ) {
162
+ $format = self::getDateFormat();
163
+ }
164
+ return self::_isTimestampInRange( $timestamp ) ? @adodb_date( $format, $timestamp ) : false;
165
+ }
166
+
167
+ public static function _isTimestampInRange( $timestamp )
168
+ {
169
+ return self::$_mintimestamp <= $timestamp && $timestamp <= self::$_maxtimestamp;
170
+ }
171
+ }
172
+
173
+
embedded/common/toolset-forms/classes/class.eforms.php ADDED
@@ -0,0 +1,1279 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* Copyright 2011 enlimbo lancers (email : lancers@enlimbo.net)
3
+
4
+ This program is free software; you can redistribute it and/or
5
+ modify it under the terms of the GNU General Public License
6
+ as published by the Free Software Foundation; either version 2
7
+ of the License, or (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program; if not, write to the Free Software
16
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+ */
18
+
19
+ /**
20
+ * Enlimbo Forms class for form creation
21
+ *
22
+ * @package Enlimbo
23
+ * @subpackage Forms
24
+ * @copyright enlimbo lancers 2012
25
+ * @license GPLv2 or later
26
+ * @version 1.1
27
+ * @link http://enlimbo.net/forms
28
+ * @author srdjan <srdjan@enlimbo.net>
29
+ *
30
+ * $HeadURL: http://plugins.svn.wordpress.org/types/tags/1.6/embedded/common/toolset-forms/classes/class.eforms.php $
31
+ * $LastChangedDate: 2014-08-22 01:02:43 +0000 (Fri, 22 Aug 2014) $
32
+ * $LastChangedRevision: 970205 $
33
+ * $LastChangedBy: brucepearson $
34
+ *
35
+ */
36
+
37
+ /*
38
+ Element attributes
39
+
40
+ General rules when adding attributes to an element using strings in chunks
41
+ * always start the chunk with a space and do not end the chunk with another space
42
+ * mind the closing tags and add a space when needed
43
+ */
44
+ class Enlimbo_Forms
45
+ {
46
+
47
+ /**
48
+ * @var string
49
+ */
50
+ private $_id;
51
+
52
+ /**
53
+ * @var array
54
+ */
55
+ private $_errors = array();
56
+
57
+ /**
58
+ * @var array
59
+ */
60
+ private $_elements = array();
61
+
62
+ /**
63
+ * @var array
64
+ */
65
+ private $_count = array();
66
+
67
+ /**
68
+ * @var string
69
+ */
70
+ public $css_class = 'wpt-form';
71
+
72
+ /**
73
+ * @var string
74
+ */
75
+ private $_validationFunc = '';
76
+
77
+ /**
78
+ * @var array
79
+ */
80
+ public $form_settings = array();
81
+
82
+ public function __construct( $id )
83
+ {
84
+ /**
85
+ * default settings
86
+ */
87
+ $this->form_settings = array(
88
+ 'has_media_button' => true,
89
+ 'use_bootstrap' => false,
90
+ );
91
+ $this->_id = $id;
92
+ if ( !is_admin() ) {// TODO check also doing_ajax as this gives false positives
93
+ $cred_form_id = preg_replace( '/^cred_form_(\d+)_\d+$/', "$1", $this->_id );
94
+ $form_settings = get_post_meta( $cred_form_id, '_cred_form_settings', true );
95
+ if ( isset($form_settings->form) ) {
96
+ $this->form_settings = $form_settings->form;
97
+ }
98
+ unset($form_settings);
99
+ /**
100
+ * check CRED setting for bootstrap: only on frontend
101
+ */
102
+ $cred_cred_settings = get_option( 'cred_cred_settings' );
103
+ if ( is_array($cred_cred_settings) ) {
104
+ $this->form_settings['use_bootstrap'] = array_key_exists( 'use_bootstrap', $cred_cred_settings ) && $cred_cred_settings['use_bootstrap'];;
105
+ }
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Auto handler
111
+ *
112
+ * Renders.
113
+ *
114
+ * @param array $element
115
+ * @return HTML formatted output
116
+ */
117
+ public function autoHandle($id, $form)
118
+ {
119
+ // Auto-add nonce field
120
+ $form['nonce'] = array(
121
+ '#type' => 'hidden',
122
+ '#name' => '_nonce',
123
+ '#value' => md5($id),
124
+ );
125
+
126
+ $this->_id = $id;
127
+ $this->_elements = $form;
128
+
129
+ // get submitted data
130
+ if ($this->isSubmitted()) {
131
+
132
+ // check if errors (validation)
133
+ $this->validate($this->_elements);
134
+
135
+ // callback
136
+ if (empty($this->_errors)) {
137
+
138
+ if (isset($form['#form']['callback'])) {
139
+ if (is_array($form['#form']['callback'])) {
140
+ foreach ($form['#form']['callback'] as $callback) {
141
+ if (is_callable($callback)) {
142
+ call_user_func($callback, $this);
143
+ }
144
+ }
145
+ } else {
146
+ if (is_callable($form['#form']['callback'])) {
147
+ call_user_func($form['#form']['callback'], $this);
148
+ }
149
+ }
150
+ }
151
+ // Maybe triggered by callback function
152
+ if (empty($this->_errors)) {
153
+ // redirect
154
+ if (!isset($form['#form']['redirection'])) {
155
+ header('Location: ' . $_SERVER['REQUEST_URI']);
156
+ } else if ($form['#form']['redirection'] != false) {
157
+ header('Location: ' . $form['#form']['redirection']);
158
+ }
159
+ }
160
+ }
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Checks if form is submitted.
166
+ *
167
+ * @param type $id
168
+ * @return type
169
+ */
170
+ public function isSubmitted($id = '')
171
+ {
172
+ if (empty($id)) {
173
+ $id = $this->_id;
174
+ }
175
+ return (isset($_REQUEST['_nonce'])
176
+ && md5($_REQUEST['_nonce']) == $id);
177
+ }
178
+
179
+ /**
180
+ * Sets validation function.
181
+ *
182
+ * @param type $class
183
+ */
184
+ // public function setValidationFunc($func)
185
+ // {
186
+ // $this->_validationFunc = $func;
187
+ // }
188
+
189
+ /**
190
+ * Loops over elements and validates them.
191
+ *
192
+ * @param type $elements
193
+ */
194
+ public function validate(&$elements)
195
+ {
196
+ foreach ($elements as $key => &$element) {
197
+ if (!isset($element['#type'])
198
+ || !$this->_isValidType($element['#type'])) {
199
+ continue;
200
+ }
201
+ if ($element['#type'] != 'fieldset') {
202
+ if (isset($element['#name'])
203
+ && !in_array($element['#type'], array('submit', 'reset'))) {
204
+ if ($this->isSubmitted()) {
205
+ // Set submitted data
206
+ if (!in_array($element['#type'], array('checkboxes'))
207
+ && empty($element['#forced_value'])) {
208
+ $element['#value'] = $this->getSubmittedData($element);
209
+ } else if (!empty($element['#options'])
210
+ && empty($element['#forced_value'])) {
211
+ foreach ($element['#options'] as $option_key => $option) {
212
+ $option['#type'] = 'checkbox';
213
+ $element['#options'][$option_key]['#value'] = $this->getSubmittedData($option);
214
+ }
215
+ }
216
+ }
217
+ }
218
+ // Validate
219
+ if (isset($element['#validate'])) {
220
+ $this->validateElement($element);
221
+ }
222
+ } else if (isset($element['#type'])
223
+ && $element['#type'] == 'fieldset') {
224
+ $this->validate($element);
225
+ } else if (is_array($element)) {
226
+ $this->validate($element);
227
+ }
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Validates element.
233
+ *
234
+ * @param type $element
235
+ */
236
+ public function validateElement( &$element )
237
+ {
238
+ $value = isset( $element['#value'] ) ? $element['#value'] : null;
239
+ if ( is_null( $value ) && isset( $element['#default_value'] ) ) {
240
+ $value = $element['#default_value'];
241
+ }
242
+ $element = apply_filters( 'wptoolset_form_' . $this->_id . '_validate_field',
243
+ $element, $value );
244
+ if ( isset( $element['error'] ) ) {
245
+ $this->_errors = true;
246
+ $_errors = $element['error']->get_error_data();
247
+ $element['#error'] = $_errors[0];
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Checks if there are errors.
253
+ *
254
+ * @return type
255
+ */
256
+ public function isError()
257
+ {
258
+ return $this->_errors;
259
+ }
260
+
261
+ /**
262
+ * Sets errors to true.
263
+ */
264
+ public function triggerError()
265
+ {
266
+ $this->_errors = true;
267
+ }
268
+
269
+ /**
270
+ * Renders form.
271
+ *
272
+ * @return type
273
+ */
274
+ public function renderForm()
275
+ {
276
+ // loop over elements and render them
277
+ return $this->renderElements($this->_elements);
278
+ }
279
+
280
+ /**
281
+ * Counts element types.
282
+ *
283
+ * @param type $type
284
+ * @return type
285
+ */
286
+ private function _count($type) {
287
+ if (!isset($this->_count[$type])) {
288
+ $this->_count[$type] = 0;
289
+ }
290
+ $this->_count[$type] += 1;
291
+ return $this->_count[$type];
292
+ }
293
+
294
+ /**
295
+ * Check if element is of valid type
296
+ *
297
+ * @param string $type
298
+ * @return boolean
299
+ */
300
+ private function _isValidType($type)
301
+ {
302
+ return in_array($type,
303
+ array('select', 'checkboxes', 'checkbox', 'radios',
304
+ 'radio', 'textfield', 'textarea', 'file', 'submit', 'reset',
305
+ 'hidden', 'fieldset', 'markup', 'button', 'password' ));
306
+ }
307
+
308
+ /**
309
+ * Renders elements.
310
+ *
311
+ * @param type $elements
312
+ * @return type
313
+ */
314
+ public function renderElements($elements)
315
+ {
316
+ $output = '';
317
+ if (!isset($elements)) return $output;
318
+ foreach ($elements as $key => $element) {
319
+ if (!isset($element['#type']) || !$this->_isValidType($element['#type'])) {
320
+ continue;
321
+ }
322
+ if ($element['#type'] != 'fieldset') {
323
+
324
+ /**
325
+ * Temporary fixing validation for checkbox/radios/skype because _cakeValidation is not working for thats
326
+ * https://icanlocalize.basecamphq.com/projects/7393061-toolset/todo_items/186243370/comments
327
+ */
328
+ if (!is_admin()) {
329
+ if ($element['#type']=='radios') {
330
+ if (isset($element['#error'])) {
331
+ if (isset($element['#options'])&&count($element['#options'])>0&&!isset($element['#options'][0]['#error']))
332
+ $element['#options'][0]['#error']=$element['#error'];
333
+ }
334
+ }
335
+ }
336
+ //##################################################################################################
337
+
338
+ $output .= $this->renderElement($element);
339
+ } else if (isset($element['#type']) && $element['#type'] == 'fieldset') {
340
+ $buffer = $this->renderElements($element);
341
+ $output .= $this->fieldset($element, 'wrap', $buffer);
342
+ } else if (is_array($element)) {
343
+ $output .= $this->renderElements($element);
344
+ }
345
+ }
346
+ return $output;
347
+ }
348
+
349
+ /**
350
+ * Renders element.
351
+ *
352
+ * Depending on element type, it calls class methods.
353
+ *
354
+ * @param array $element
355
+ * @return HTML formatted output
356
+ */
357
+ public function renderElement($element)
358
+ {
359
+ $method = $element['#type'];
360
+ if (!isset($element['#name']) && !in_array( $element['#type'], array('markup', 'checkboxes'))) {
361
+ if (!isset($element['#attributes']['name'])) {
362
+ return '#name or #attributes[\'name\'] required!';
363
+ } else {
364
+ $element['#name'] = $element['#attributes']['name'];
365
+ }
366
+ }
367
+ if (is_callable(array($this, $method))) {
368
+ $custom_field_title = '';
369
+ if ( isset($element['#title']) && !empty($element['#title']) ){
370
+ $custom_field_title = $element['#title'];
371
+ }
372
+
373
+ if ( empty($custom_field_title) && isset($element['#name']) && !empty($element['#name']) ){
374
+ $custom_field_title = $element['#name'];
375
+ }
376
+ if (!isset($element['#id'])) {
377
+ if (isset($element['#attributes']['id'])) {
378
+ $element['#id'] = $element['#attributes']['id'];
379
+ } else {
380
+ $_id = isset( $this->_id ) ? $this->_id . '-' : '';
381
+ $element['#id'] = "{$_id}{$element['#type']}-"
382
+ . $this->_count($element['#type']) . '-' . time();
383
+ }
384
+ }
385
+
386
+ if (isset($this->_errors[$element['#id']])) {
387
+ $element['#error'] = $this->_errors[$element['#id']];
388
+ }
389
+ // Add JS validation
390
+ if ( !empty( $element['#validate'] ) ) {
391
+ if ( isset( $element['#validate']['required'] )
392
+ && !empty( $element['#title'] ) ) {
393
+ // Asterisk
394
+ $element['#title'] .= '&#42;';
395
+ }
396
+ $element['#attributes']['data-wpt-validate'] = esc_js( self::json_encode( apply_filters( 'wptoolset_forms_field_js_validation_data_' . $this->_id,
397
+ $element['#validate'] ) ) );
398
+ $element['#attributes']['data-wpt-field-title'] = esc_js( $custom_field_title );
399
+ }
400
+ if ( $element['#type'] == 'radios' && !empty( $element['#options'] ) ) {
401
+ foreach ( $element['#options'] as &$option ) {
402
+ if ( !empty( $option['#validate'] ) ) {
403
+ $option['#attributes']['data-wpt-validate'] = esc_js( self::json_encode( apply_filters( 'wptoolset_forms_field_js_validation_data_' . $this->_id,
404
+ $option['#validate'] ) ) );
405
+ $option['#attributes']['data-wpt-field-title'] = esc_js( $custom_field_title );
406
+ }
407
+ }
408
+ }
409
+ return $this->{$method}($element);
410
+ }
411
+ }
412
+
413
+ /**
414
+ * Sets other element attributes.
415
+ *
416
+ * @param array $element
417
+ * @return string
418
+ */
419
+ private function _setElementAttributes($element)
420
+ {
421
+ $attributes = '';
422
+
423
+ $classes = array();
424
+ $classes[] = $this->css_class . '-' . $element['#type'];
425
+ $classes[] = 'form-' . $element['#type'];
426
+
427
+ if ( $this->form_settings['use_bootstrap'] ) {
428
+ switch( $element['#type'] ) {
429
+ case 'hidden':
430
+ case 'button':
431
+ case 'submit':
432
+ case 'radio':
433
+ case 'checkbox':
434
+ case 'file':
435
+ break;
436
+ default:
437
+ $classes[] = 'form-control';
438
+ }
439
+ } else {
440
+ $classes[] = $element['#type'];
441
+ }
442
+
443
+ if ( isset( $element['#attributes'] )
444
+ && !empty( $element['#attributes'] )
445
+ ) {
446
+ if ( isset( $element['#attributes']['class'] ) ) {
447
+ $element['#attributes']['class'] .= ' ' . implode( ' ', $classes );
448
+ } else {
449
+ $element['#attributes']['class'] = implode( ' ', $classes );
450
+ }
451
+ } else {
452
+ $element['#attributes'] = array(
453
+ 'class' => implode( ' ', $classes )
454
+ );
455
+ }
456
+
457
+ foreach ($element['#attributes'] as $attribute => $value) {
458
+ // Prevent undesired elements
459
+ if (in_array($attribute, array('id', 'name'))) {
460
+ continue;
461
+ }
462
+ // Don't set disabled for checkbox
463
+ if ($attribute == 'disabled' && $element['#type'] == 'checkbox') {
464
+ continue;
465
+ }
466
+ // Set return string
467
+ $attributes .= ' ' . $attribute . '="' . $value . '"';
468
+ }
469
+
470
+ return $attributes;
471
+ }
472
+
473
+ /**
474
+ * Sets render elements.
475
+ *
476
+ * @param array $element
477
+ */
478
+ private function _setRender($element)
479
+ {
480
+ if (!isset($element['#id'])) {
481
+ if (isset($element['#attributes']['id'])) {
482
+ $element['#id'] = $element['#attributes']['id'];
483
+ } else {
484
+ $element['#id'] = 'form-' . mt_rand();
485
+ }
486
+ }
487
+ $element['_attributes_string'] = $this->_setElementAttributes($element);
488
+ $element['_render'] = array();
489
+ $element['_render']['prefix'] = isset($element['#prefix']) ? $element['#prefix'] . "\r\n" : '';
490
+ $element['_render']['suffix'] = isset($element['#suffix']) ? $element['#suffix'] . "\r\n" : '';
491
+ $element['_render']['before'] = isset($element['#before']) ? $element['#before'] . "\r\n" : '';
492
+ $element['_render']['after'] = isset($element['#after']) ? $element['#after'] . "\r\n" : '';
493
+ $element['_render']['title'] = $this->_setElementTitle($element);
494
+ $element['_render']['description'] = isset($element['#description']) ? $this->_setElementDescription($element) : '';
495
+ $element['_render']['error'] = $this->renderError($element) . "\r\n";
496
+ /**
497
+ * label
498
+ */
499
+ $element['_render']['label'] = '';
500
+ if ( isset($element['#title']) ) {
501
+ $classes = array();
502
+ $classes[] = sprintf('%s-label', $this->css_class);
503
+ $classes[] = sprintf('%s-%s-label', $this->css_class, $element['#type']);
504
+ if ( $this->form_settings['use_bootstrap']) {
505
+ switch( $element['#type'] ) {
506
+ case 'checkbox':
507
+ case 'radio':
508
+ $classes[] = 'control-label';
509
+ break;
510
+ }
511
+ }
512
+ $element['_render']['label'] .= sprintf(
513
+ '<label class="%s" for="%s">',
514
+ implode(' ', $classes),
515
+ $element['#id']
516
+ );
517
+ $element['_render']['label'] .= stripslashes($element['#title']);
518
+ $element['_render']['label'] .= '</label>';
519
+ }
520
+
521
+ return $element;
522
+ }
523
+
524
+ /**
525
+ * Applies pattern to output.
526
+ *
527
+ * Pass element property #pattern to get custom renedered element.
528
+ *
529
+ * @param array $pattern
530
+ * Accepts: <prefix><suffix><label><title><desription><error>
531
+ * @param array $element
532
+ */
533
+ private function _pattern($pattern, $element)
534
+ {
535
+ $pattern = strtolower($pattern);
536
+ foreach ($element['_render'] as $key => $value) {
537
+ $pattern = str_replace('<' . strtolower($key) . '>', $value, $pattern);
538
+ }
539
+ return $pattern;
540
+ }
541
+
542
+ /**
543
+ * Wrapps element in <div></div>.
544
+ *
545
+ * @param arrat $element
546
+ * @param string $output
547
+ * @return string
548
+ */
549
+ private function _wrapElement($element, $output)
550
+ {
551
+ if (!empty($element['#inline'])) {
552
+ return $output;
553
+ }
554
+ $classes = array();
555
+ $classes[] = 'form-item';
556
+ $classes[] = 'form-item-' . $element['#type'];
557
+ $classes[] = $this->css_class . '-item';
558
+ $classes[] = $this->css_class . '-item-' . $element['#type'];
559
+ if ( $this->form_settings['use_bootstrap'] ) {
560
+ $classes[] = 'form-group';
561
+ }
562
+ if ( preg_match( '/_hidden$/', $element['#id'] ) && !is_admin() ) {
563
+ $classes[] = 'wpt-form-hide-container';
564
+ }
565
+ if ( is_admin() ) {
566
+ return sprintf(
567
+ '<div id="%s-wrapper" class="%s">%s</div>',
568
+ $element['#id'],
569
+ implode( ' ', $classes ),
570
+ $output
571
+ );
572
+ }
573
+ return $output;
574
+ }
575
+
576
+ /**
577
+ * Returns HTML formatted output for element's title.
578
+ *
579
+ * @param string $element
580
+ * @return string
581
+ */
582
+ private function _setElementTitle($element)
583
+ {
584
+ $output = '';
585
+ if (isset($element['#title'])) {
586
+ $output .= '<div class="title '
587
+ . $this->css_class . '-title '
588
+ . $this->css_class . '-title-' . $element['#type'] . ' '
589
+ . 'title-' . $element['#type'] . '">'
590
+ . stripslashes($element['#title'])
591
+ . "</div>\r\n";
592
+ }
593
+ return $output;
594
+ }
595
+
596
+ /**
597
+ * Returns HTML formatted output for element's description.
598
+ *
599
+ * @param array $element
600
+ * @return string
601
+ */
602
+ private function _setElementDescription($element)
603
+ {
604
+ if ( empty( $element['#description'] ) ) return '';
605
+ $element['#description'] = stripslashes($element['#description']);
606
+ $output = "\r\n"
607
+ . '<div class="description '
608
+ . $this->css_class . '-description '
609
+ . $this->css_class . '-description-' . $element['#type'] . ' '
610
+ . 'description-' . $element['#type'] . '">'
611
+ . $element['#description'] . "</div>\r\n";
612
+ return $output;
613
+ }
614
+
615
+ /**
616
+ * Returns HTML formatted element's error message.
617
+ *
618
+ * Pass #supress_errors in #form element to avoid error rendering.
619
+ *
620
+ * @param array $element
621
+ * @return string
622
+ */
623
+ public function renderError($element)
624
+ {
625
+ if (!isset($element['#error'])) {
626
+ return '';
627
+ }
628
+ $output = '<label class="' . $this->css_class . '-error" for="'
629
+ . $element['#id'] . '" generated="true">'
630
+ . $element['#error'] . '</label>' . "\r\n";
631
+ // $output = '<div class="form-error '
632
+ // . $this->css_class . '-error '
633
+ // . $this->css_class . '-form-error '
634
+ // . $this->css_class . '-' . $element['#type'] . '-error '
635
+ // . $element['#type'] . '-error form-error-label'
636
+ // . '">' . $element['#error'] . '</div>'
637
+ // . "\r\n";
638
+ return $output;
639
+ }
640
+
641
+ /**
642
+ * Returns HTML formatted output for fieldset.
643
+ *
644
+ * @param array $element
645
+ * @param string $action open|close|wrap
646
+ * @param string $wrap_content HTML formatted output of child elements
647
+ * @return string
648
+ */
649
+ public function fieldset($element, $action = 'open', $wrap_content = '')
650
+ {
651
+ $collapsible_open = '<div class="fieldset-wrapper">';
652
+ $collapsible_close = '</div>';
653
+ $legend_class = '';
654
+ if (!isset($element['#id'])) {
655
+ $element['#id'] = 'fieldset-' . $this->_count('fieldset');
656
+ }
657
+ if (!isset($element['_attributes_string'])) {
658
+ $element['_attributes_string'] = $this->_setElementAttributes($element);
659
+ }
660
+ if ((isset($element['#collapsible']) && $element['#collapsible'])
661
+ || (isset($element['#collapsed']) && $element['#collapsed'])) {
662
+ $collapsible_open = '<div class="collapsible fieldset-wrapper">';
663
+ $collapsible_close = '</div>';
664
+ $legend_class = ' class="legend-expanded"';
665
+ }
666
+ if (isset($element['#collapsed']) && $element['#collapsed']) {
667
+ $collapsible_open = str_replace('class="', 'class="collapsed ',
668
+ $collapsible_open);
669
+ $legend_class = ' class="legend-collapsed"';
670
+ }
671
+ $output = '';
672
+ switch ($action) {
673
+ case 'close':
674
+ $output .= $collapsible_close . "</fieldset>\r\n";
675
+ $output .= isset($element['#suffix']) ? $element['#suffix']
676
+ . "\r\n" : '';
677
+ $output .= "\n\r";
678
+ break;
679
+
680
+ case 'open':
681
+ $output .= $collapsible_open;
682
+ $output .= isset($element['#prefix']) ? $element['#prefix']
683
+ . "\r\n" : '';
684
+ $output .= '<fieldset' . $element['_attributes_string']
685
+ . ' id="' . $element['#id'] . '">' . "\r\n";
686
+ $output .= isset($element['#title']) ? '<legend'
687
+ . $legend_class . '>'
688
+ . stripslashes($element['#title'])
689
+ . "</legend>\r\n" : '';
690
+ $output .=
691
+ isset($element['#description']) ? $this->_setElementDescription($element) : '';
692
+ $output .= "\n\r";
693
+ break;
694
+
695
+ case 'wrap':
696
+ if (!empty($wrap_content)) {
697
+ $output .= isset($element['#prefix']) ? $element['#prefix'] : '';
698
+ $output .= '<fieldset' . $element['_attributes_string']
699
+ . ' id="' . $element['#id'] . '">' . "\r\n";
700
+ $output .= '<legend' . $legend_class . '>'
701
+ . stripslashes($element['#title'])
702
+ . "</legend>\r\n"
703
+ . $collapsible_open;
704
+ $output .= isset($element['#description']) ? $this->_setElementDescription($element) : '';
705
+ $output .= $wrap_content . $collapsible_close
706
+ . "</fieldset>\r\n";
707
+ $output .=
708
+ isset($element['#suffix']) ? $element['#suffix'] : '';
709
+ $output .= "\n\r";
710
+ }
711
+ break;
712
+ }
713
+ return $output;
714
+ }
715
+
716
+ /**
717
+ * Returns HTML formatted output for checkbox element.
718
+ *
719
+ * @param array $element
720
+ * @return string
721
+ */
722
+ public function checkbox($element)
723
+ {
724
+ $element['#type'] = 'checkbox';
725
+ $element = $this->_setRender($element);
726
+ $element['_render']['element'] = '<input type="checkbox"';
727
+ foreach( array( 'id', 'name' ) as $key ) {
728
+ $element['_render']['element'] .= sprintf( ' %s="%s"', $key, $element['#'.$key] );
729
+ }
730
+ /**
731
+ * type and data_id
732
+ */
733
+ $element['_render']['element'] .= sprintf( ' data-wpt-type="%s"', __FUNCTION__ );
734
+ $element['_render']['element'] .= $this->_getDataWptId( $element );
735
+
736
+ $element['_render']['element'] .= ' value="';
737
+ /**
738
+ * Specific: if value is empty force 1 to be rendered
739
+ * but if is defined default value, use default
740
+ */
741
+ $value = 1;
742
+ if ( array_key_exists( '#default_value', $element ) ) {
743
+ $value = $element['#default_value'];
744
+ }
745
+ $element['_render']['element'] .= ( empty($element['#value']) && !preg_match( '/^0$/', $element['#value']) )? $value:esc_attr($element['#value']);
746
+ $element['_render']['element'] .= '"' . $element['_attributes_string'];
747
+ if (
748
+ (
749
+ !$this->isSubmitted() && (
750
+ ( !empty($element['#default_value']) && $element['#default_value'] == $element['#value'] )
751
+ || ( isset($element['#checked']) && $element['#checked'] )
752
+ )
753
+ )
754
+ || ($this->isSubmitted() && !empty($element['#value']))
755
+ ) {
756
+ $element['_render']['element'] .= ' checked="checked"';
757
+ }
758
+ if (!empty($element['#attributes']['disabled']) || !empty($element['#disable'])) {
759
+ $element['_render']['element'] .= ' onclick="javascript:return false; if(this.checked == 1){this.checked=1; return true;}else{this.checked=0; return false;}"';
760
+ }
761
+ $element['_render']['element'] .= ' />';
762
+
763
+ $pattern = $this->_getStatndardPatern( $element, '<BEFORE><PREFIX><ELEMENT>&nbsp;<LABEL><ERROR><SUFFIX><DESCRIPTION><AFTER>');
764
+ $output = $this->_pattern($pattern, $element);
765
+ $output = $this->_wrapElement($element, $output);
766
+ return $output . "\r\n";
767
+ }
768
+
769
+ /**
770
+ * Returns HTML formatted output for checkboxes element.
771
+ *
772
+ * Renders more than one checkboxes provided as elements in '#options'
773
+ * array element.
774
+ *
775
+ * @param array $element
776
+ * @return string
777
+ */
778
+ public function checkboxes($element)
779
+ {
780
+ $element['#type'] = 'checkboxes';
781
+ $element = $this->_setRender($element);
782
+ $clone = $element;
783
+ $clone['#type'] = 'checkbox';
784
+ $element['_render']['element'] = '';
785
+ foreach ($element['#options'] as $ID => $value) {
786
+ if (!is_array($value)) {
787
+ $value = array('#title' => $ID, '#value' => $value, '#name' => $element['#name'] . '[]');
788
+ }
789
+ $element['_render']['element'] .= $this->checkbox($value);
790
+ }
791
+ $pattern = $this->_getStatndardPatern( $element, '<BEFORE><PREFIX><TITLE><DESCRIPTION><ELEMENT><SUFFIX><AFTER>' );
792
+ $output = $this->_pattern($pattern, $element);
793
+ $output = $this->_wrapElement($element, $output);
794
+ return $output;
795
+ }
796
+
797
+ /**
798
+ * Returns HTML formatted output for radio element.
799
+ *
800
+ * @param array $element
801
+ * @return string
802
+ */
803
+ public function radio($element)
804
+ {
805
+ $element['#type'] = 'radio';
806
+ $element = $this->_setRender($element);
807
+ $element['_render']['element'] = '<input type="radio" id="'
808
+ . $element['#id'] . '" name="'
809
+ . $element['#name'] . '" value="';
810
+ $element['_render']['element'] .= isset($element['#value']) ? htmlspecialchars($element['#value']) : $this->_count['radio'];
811
+ $element['_render']['element'] .= '"';
812
+ $element['_render']['element'] .= $element['_attributes_string'];
813
+ $element['_render']['element'] .= ( isset($element['#value'])
814
+ && $element['#value'] === $element['#default_value']) ? ' checked="checked"' : '';
815
+ if (isset($element['#disable']) && $element['#disable']) {
816
+ $element['_render']['element'] .= ' disabled="disabled"';
817
+ }
818
+ if ( array_key_exists( '#types-value', $element ) ) {
819
+ $element['_render']['element'] .= sprintf( ' data-types-value="%s"', $element['#types-value'] );
820
+ }
821
+ /**
822
+ * type and data_id
823
+ */
824
+ $element['_render']['element'] .= sprintf( ' data-wpt-type="%s"', __FUNCTION__ );
825
+ $element['_render']['element'] .= $this->_getDataWptId( $element );
826
+
827
+ $element['_render']['element'] .= ' />';
828
+
829
+ $pattern = isset($element['#pattern']) ? $element['#pattern'] : '<BEFORE><PREFIX><ELEMENT>&nbsp;<LABEL><ERROR><SUFFIX><DESCRIPTION><AFTER>';
830
+ $output = $this->_pattern($pattern, $element);
831
+ $output = $this->_wrapElement($element, $output);
832
+ return $output . "\r\n";
833
+ }
834
+
835
+ /**
836
+ * Returns HTML formatted output for radios elements.
837
+ *
838
+ * Radios are provided via #options array.
839
+ * Requires #name value.
840
+ *
841
+ * @param array $element
842
+ * @return string
843
+ */
844
+ public function radios($element)
845
+ {
846
+ if (!isset($element['#name']) || empty($element['#name'])) {
847
+ return FALSE;
848
+ }
849
+ $element['#type'] = 'radios';
850
+ $element = $this->_setRender($element);
851
+ $element['_render']['element'] = '';
852
+ foreach ($element['#options'] as $ID => $value) {
853
+ $this->_count('radio');
854
+ if (!is_array($value)) {
855
+ $value = array('#title' => $ID, '#value' => $value);
856
+ $value['#inline'] = true;
857
+ $value['#after'] = '<br />';
858
+ }
859
+ $value['#name'] = $element['#name'];
860
+ $value['#default_value'] = isset($element['#default_value']) ? $element['#default_value'] : $value['#value'];
861
+ $value['#disable'] = isset($element['#disable']) ? $element['#disable'] : false;
862
+ $element['_render']['element'] .= $this->radio($value);
863
+ }
864
+ if (is_admin()) {
865
+ $pattern = '<BEFORE><PREFIX><TITLE><DESCRIPTION><ELEMENT><SUFFIX><AFTER>';
866
+ } else {
867
+ $pattern = '<BEFORE><PREFIX><DESCRIPTION><ELEMENT><SUFFIX><AFTER>';
868
+ }
869
+
870
+ $pattern = $this->_getStatndardPatern($element, $pattern);
871
+ $output = $this->_pattern($pattern, $element);
872
+ $output = $this->_wrapElement($element, $output);
873
+ return $output;
874
+ }
875
+
876
+ /**
877
+ * Returns HTML formatted output for select element.
878
+ *
879
+ * @param array $element
880
+ * @return string
881
+ */
882
+ public function select($element)
883
+ {
884
+ $element = $this->_setRender($element);
885
+
886
+ $element['_render']['element'] = '';
887
+ $element['_render']['element'] .= '<select id="' . $element['#id'] . '" ';
888
+ $element['_render']['element'] .= $element['_attributes_string'];
889
+ $element['_render']['element'] .= sprintf( ' data-wpt-type="%s"', __FUNCTION__ );
890
+ /**
891
+ * multiple
892
+ */
893
+ if ( array_key_exists( '#multiple', $element ) && $element['#multiple'] ) {
894
+ $element['_render']['element'] .= ' multiple="multiple"';
895
+ $element['_render']['element'] .= ' name="' . $element['#name'] . '[]"';
896
+ } else {
897
+ $element['_render']['element'] .= ' name="' . $element['#name'] . '"';
898
+ }
899
+ $element['_render']['element'] .= ">\r\n";
900
+ $count = 1;
901
+ foreach ($element['#options'] as $id => $value) {
902
+ if (!is_array($value)) {
903
+ $value = array('#title' => $id, '#value' => $value, '#type' => 'option');
904
+ }
905
+ $value['#type'] = 'option';
906
+ if (!isset($value['#value'])) {
907
+ $value['#value'] = $this->_count['select'] . '-' . $count;
908
+ $count += 1;
909
+ }
910
+ $element['_render']['element'] .= '<option value="' . htmlspecialchars($value['#value']) . '"';
911
+ $element['_render']['element'] .= $this->_setElementAttributes($value);
912
+ if ( array_key_exists( '#types-value', $value ) ) {
913
+ $element['_render']['element'] .= sprintf( ' data-types-value="%s"', $value['#types-value'] );
914
+ }
915
+ /**
916
+ * type and data_id
917
+ */
918
+ $element['_render']['element'] .= ' data-wpt-type="option"';
919
+ $element['_render']['element'] .= $this->_getDataWptId( $element );
920
+ /**
921
+ * selected
922
+ */
923
+ if ( array_key_exists( '#multiple', $element ) && $element['#multiple'] ) {
924
+ if ( is_array( $element['#default_value'] ) && in_array( $value['#value'], $element['#default_value'] ) ) {
925
+ $element['_render']['element'] .= ' selected="selected"';
926
+ }
927
+ } elseif ( $element['#default_value'] == $value['#value']) {
928
+ $element['_render']['element'] .= ' selected="selected"';
929
+ }
930
+ $element['_render']['element'] .= '>';
931
+ $element['_render']['element'] .= isset($value['#title']) ? $value['#title'] : $value['#value'];
932
+ $element['_render']['element'] .= "</option>\r\n";
933
+ }
934
+ $element['_render']['element'] .= '</select>';
935
+ $element['_render']['element'] .= PHP_EOL;
936
+
937
+ $pattern = $this->_getStatndardPatern( $element );
938
+ $output = $this->_pattern($pattern, $element);
939
+ $output = $this->_wrapElement($element, $output);
940
+
941
+ return $output;
942
+ }
943
+
944
+ /**
945
+ * Returns HTML formatted output for textfield element.
946
+ *
947
+ * @param array $element
948
+ * @return string
949
+ */
950
+ public function textfield($element)
951
+ {
952
+ $element['#type'] = 'textfield';
953
+ $element = $this->_setRender($element);
954
+
955
+ $element['_render']['element'] = '<input type="text"';
956
+ //$element['_render']['element'] .= sprintf( ' data-wpt-type="%s" ', __FUNCTION__ );
957
+ $element['_render']['element'] .= sprintf( ' id="%s"', $element['#id']);
958
+ $element['_render']['element'] .= sprintf( ' name="%s"', $element['#name']);
959
+ $element['_render']['element'] .= sprintf( ' value="%s"', isset($element['#value']) ? esc_attr($element['#value']) : '' );
960
+ $element['_render']['element'] .= $element['_attributes_string'];
961
+ if (isset($element['#disable']) && $element['#disable']) {
962
+ $element['_render']['element'] .= ' disabled="disabled"';
963
+ }
964
+ /**
965
+ * type and data_id
966
+ */
967
+ $element['_render']['element'] .= sprintf( ' data-wpt-type="%s"', __FUNCTION__ );
968
+ $element['_render']['element'] .= $this->_getDataWptId( $element );
969
+
970
+ $element['_render']['element'] .= ' />';
971
+ $pattern = $this->_getStatndardPatern( $element );
972
+ $output = $this->_pattern($pattern, $element);
973
+ $output = $this->_wrapElement($element, $output);
974
+ return $output . "\r\n";
975
+ }
976
+
977
+ /**
978
+ * Returns HTML formatted output for textfield element.
979
+ *
980
+ * @param array $element
981
+ * @return string
982
+ */
983
+ public function password($element)
984
+ {
985
+ $element['#type'] = 'password';
986
+ $element = $this->_setRender($element);
987
+ $element['_render']['element'] = '<input type="password" id="'
988
+ . $element['#id'] . '" name="' . $element['#name'] . '" value="';
989
+ $element['_render']['element'] .= isset($element['#value']) ? $element['#value'] : '';
990
+ $element['_render']['element'] .= '"' . $element['_attributes_string'];
991
+ if (isset($element['#disable']) && $element['#disable']) {
992
+ $element['_render']['element'] .= ' disabled="disabled"';
993
+ }
994
+ /**
995
+ * type and data_id
996
+ */
997
+ $element['_render']['element'] .= sprintf( ' data-wpt-type="%s"', __FUNCTION__ );
998
+ $element['_render']['element'] .= $this->_getDataWptId( $element );
999
+
1000
+ $element['_render']['element'] .= ' />';
1001
+ $pattern = $this->_getStatndardPatern($element);
1002
+ $output = $this->_pattern($pattern, $element);
1003
+ $output = $this->_wrapElement($element, $output);
1004
+ return $output . "\r\n";
1005
+ }
1006
+
1007
+ /**
1008
+ * Returns HTML formatted output for textarea element.
1009
+ *
1010
+ * @param array $element
1011
+ * @return string
1012
+ */
1013
+ public function textarea($element)
1014
+ {
1015
+ $element['#type'] = 'textarea';
1016
+ if (!isset($element['#attributes']['rows'])) {
1017
+ $element['#attributes']['rows'] = 5;
1018
+ }
1019
+ if (!isset($element['#attributes']['cols'])) {
1020
+ $element['#attributes']['cols'] = 1;
1021
+ }
1022
+ $element = $this->_setRender($element);
1023
+ $element['_render']['element'] = '<textarea id="' . $element['#id']
1024
+ . '" name="' . $element['#name'] . '"'
1025
+ . $element['_attributes_string'];
1026
+ /**
1027
+ * type and data_id
1028
+ */
1029
+ $element['_render']['element'] .= sprintf( ' data-wpt-type="%s"', __FUNCTION__ );
1030
+ $element['_render']['element'] .= $this->_getDataWptId( $element );
1031
+
1032
+ $element['_render']['element'] .= '>';
1033
+
1034
+ $element['_render']['element'] .= isset($element['#value']) ? esc_attr($element['#value']) : '';
1035
+ $element['_render']['element'] .= '</textarea>' . "\r\n";
1036
+ $pattern = $this->_getStatndardPatern( $element );
1037
+ $output = $this->_pattern($pattern, $element);
1038
+ $output = $this->_wrapElement($element, $output);
1039
+ return $output . "\r\n";
1040
+ }
1041
+
1042
+ /**
1043
+ * Returns HTML formatted output for file upload element.
1044
+ *
1045
+ * @param array $element
1046
+ * @return string
1047
+ */
1048
+ public function file($element)
1049
+ {
1050
+ $element['#type'] = 'file';
1051
+ $element = $this->_setRender($element);
1052
+ $element['_render']['element'] = '<input type="file" id="'
1053
+ . $element['#id'] . '" name="' . $element['#name'] . '"'
1054
+ . $element['_attributes_string'];
1055
+ if (isset($element['#disable']) && $element['#disable']) {
1056
+ $element['_render']['element'] .= ' disabled="disabled"';
1057
+ }
1058
+ /**
1059
+ * type and data_id
1060
+ */
1061
+ $element['_render']['element'] .= sprintf( ' data-wpt-type="%s"', __FUNCTION__ );
1062
+ $element['_render']['element'] .= $this->_getDataWptId( $element );
1063
+
1064
+ $element['_render']['element'] .= ' />';
1065
+ $pattern = $this->_getStatndardPatern( $element );
1066
+ $output = $this->_pattern($pattern, $element);
1067
+ $output = $this->_wrapElement($element, $output);
1068
+ return $output;
1069
+ }
1070
+
1071
+ /**
1072
+ * Returns HTML formatted output for markup element.
1073
+ *
1074
+ * @param array $element
1075
+ * @return string
1076
+ */
1077
+ public function markup($element)
1078
+ {
1079
+ return $element['#markup'];
1080
+ }
1081
+
1082
+ /**
1083
+ * Returns HTML formatted output for hidden element.
1084
+ *
1085
+ * @param array $element
1086
+ * @return string
1087
+ */
1088
+ public function hidden($element)
1089
+ {
1090
+ $element['#type'] = 'hidden';
1091
+ $element = $this->_setRender($element);
1092
+ $output = '<input type="hidden" id="' . $element['#id'] . '" name="'
1093
+ . $element['#name'] . '" value="';
1094
+ $output .= isset($element['#value']) ? $element['#value'] : 1;
1095
+ $output .= '"' . $element['_attributes_string'] . $this->_getDataWptId( $element ) . ' />';
1096
+ return $output;
1097
+ }
1098
+
1099
+ /**
1100
+ * Returns HTML formatted output for reset button element.
1101
+ *
1102
+ * @param array $element
1103
+ * @return string
1104
+ */
1105
+ public function reset($element)
1106
+ {
1107
+ return $this->submit($element, 'reset', 'Reset');
1108
+ }
1109
+
1110
+ /**
1111
+ * Returns HTML formatted output for button element.
1112
+ *
1113
+ * @param array $element
1114
+ * @return string
1115
+ */
1116
+ public function button($element)
1117
+ {
1118
+ return $this->submit($element, 'button', 'Button');
1119
+ }
1120
+
1121
+ /**
1122
+ * Returns HTML formatted output for radio element.
1123
+ *
1124
+ * Used by reset and button.
1125
+ *
1126
+ * @param array $element
1127
+ * @param string $type
1128
+ * @param string $title
1129
+ * @return string
1130
+ */
1131
+ public function submit($element, $type = 'submit', $title = 'Submit')
1132
+ {
1133
+ $element['#type'] = $type;
1134
+ $element = $this->_setRender($element);
1135
+ $element['_render']['element'] = '<input type="' . $type . '" id="'
1136
+ . $element['#id'] . '" name="' . $element['#name'] . '" value="';
1137
+ $element['_render']['element'] .= isset($element['#value']) ? $element['#value'] : $title;
1138
+ $element['_render']['element'] .= '"' . $element['_attributes_string']
1139
+ . ' />';
1140
+ $pattern = $this->_getStatndardPatern( $element, '<BEFORE><PREFIX><ELEMENT><SUFFIX><AFTER>' );
1141
+ $output = $this->_pattern($pattern, $element);
1142
+ return $output;
1143
+ }
1144
+
1145
+ /**
1146
+ * Searches and returns submitted data for element.
1147
+ *
1148
+ * @param type $element
1149
+ * @return type mixed
1150
+ */
1151
+ public function getSubmittedData($element)
1152
+ {
1153
+ $name = $element['#name'];
1154
+ if (strpos($name, '[') === false) {
1155
+ if ($element['#type'] == 'file') {
1156
+ return $_FILES[$name]['tmp_name'];
1157
+ }
1158
+ return isset($_REQUEST[$name]) ? $_REQUEST[$name] : in_array($element['#type'],
1159
+ array('textfield', 'textarea')) ? '' : 0;
1160
+ }
1161
+
1162
+ $parts = explode('[', $name);
1163
+ $parts = array_map(create_function('&$a', 'return trim($a, \']\');'),
1164
+ $parts);
1165
+ if (!isset($_REQUEST[$parts[0]])) {
1166
+ return in_array($element['#type'], array('textfield', 'textarea')) ? '' : 0;
1167
+ }
1168
+ $search = $_REQUEST[$parts[0]];
1169
+ for ($index = 0; $index < count($parts); $index++) {
1170
+ $key = $parts[$index];
1171
+ // We're at the end but no data retrieved
1172
+ if (!isset($parts[$index + 1])) {
1173
+ return in_array($element['#type'],
1174
+ array('textfield', 'textarea')) ? '' : 0;
1175
+ }
1176
+ $key_next = $parts[$index + 1];
1177
+ if ($index > 0) {
1178
+ if (!isset($search[$key])) {
1179
+ return in_array($element['#type'],
1180
+ array('textfield', 'textarea')) ? '' : 0;
1181
+ } else {
1182
+ $search = $search[$key];
1183
+ }
1184
+ }
1185
+ if (is_array($search) && array_key_exists($key_next, $search)) {
1186
+ if (!is_array($search[$key_next])) {
1187
+ return $search[$key_next];
1188
+ }
1189
+ }
1190
+ }
1191
+ return 0;
1192
+ }
1193
+
1194
+ private function _getDataWptId($element)
1195
+ {
1196
+ $html = '';
1197
+ if ( array_key_exists( '#id', $element ) ) {
1198
+ if ( is_admin() ) {
1199
+ $html .= sprintf( ' data-wpt-id="%s"', preg_replace( '/\[/', '-', preg_replace( '/\]/', '', $element['#name'] ) ) );
1200
+ } else {
1201
+ $html .= sprintf( ' data-wpt-id="%s_%s"', $this->_id, $element['#id'] );
1202
+ }
1203
+ if ( array_key_exists( '#name', $element ) && $element['#name'] ) {
1204
+ if ( !is_admin() && $this->_isRepetitive($element)) {
1205
+ $html .= sprintf( ' data-wpt-name="%s"', preg_replace( '/\[.+$/', '', $element['#name'] ) );
1206
+ } else {
1207
+ if ( preg_match( '/^wpcf_post_relationship\[\d+\]\[\d+\]\[[^\]]+\]/', $element['#name'] ) ) {
1208
+ $html .= sprintf(
1209
+ ' data-wpt-name="%s"',
1210
+ preg_replace( '/^wpcf_post_relationship\[\d+\]\[(\d+)\]\[wpcf-([^\]]+)\]/', "wpcf[$2-$1]", $element['#name'] ) );
1211
+ } else {
1212
+ $html .= sprintf( ' data-wpt-name="%s"', $element['#name'] );
1213
+ }
1214
+ }
1215
+ }
1216
+ }
1217
+ return $html;
1218
+ }
1219
+
1220
+ private function _getStatndardPatern($element, $default = false )
1221
+ {
1222
+ if ( isset($element['#pattern'] ) ) {
1223
+ return $element['#pattern'];
1224
+ }
1225
+ if ( $default ) {
1226
+ return $default;
1227
+ }
1228
+ if ( is_admin() ) {
1229
+ return '<BEFORE><LABEL><DESCRIPTION><ERROR><PREFIX><ELEMENT><SUFFIX><AFTER>';
1230
+ }
1231
+ return '<BEFORE><DESCRIPTION><ERROR><PREFIX><ELEMENT><SUFFIX><AFTER>';
1232
+ }
1233
+
1234
+ private function _isRepetitive($element)
1235
+ {
1236
+ if ( !is_array($element) ) {
1237
+ return false;
1238
+ }
1239
+ return array_key_exists( '#repetitive', $element ) && $element['#repetitive'];
1240
+ }
1241
+
1242
+ static function json_encode( $array )
1243
+ {
1244
+ // php > 5.3 do not escape utf-8 characters using native constant argument
1245
+ if( defined('JSON_UNESCAPED_UNICODE') )
1246
+ {
1247
+ return json_encode($array, JSON_UNESCAPED_UNICODE );
1248
+ }
1249
+ // fallback for php < 5.3 to support unicode characters in json string
1250
+ else
1251
+ {
1252
+ if (function_exists('mb_decode_numericentity')) {
1253
+ return self::json_encode_unescaped_unicode( $array );
1254
+ } else {
1255
+ return json_encode( $array );
1256
+ }
1257
+ }
1258
+ }
1259
+
1260
+ /**
1261
+ * @param $arr
1262
+ * @return string
1263
+ * courtesy from: http://www.php.net/manual/ru/function.json-encode.php#105789
1264
+ */
1265
+ public static function json_encode_unescaped_unicode($arr)
1266
+ {
1267
+
1268
+ array_walk_recursive($arr, array(__CLASS__, 'json_unescaped_unicode_walk_callback' ));
1269
+
1270
+ return mb_decode_numericentity(json_encode($arr), array (0x80, 0xffff, 0, 0xffff), 'UTF-8');
1271
+ }
1272
+
1273
+ /*
1274
+ * Helper function to json_encode with UTF-8 support for php < 5.3
1275
+ */
1276
+ public static function json_unescaped_unicode_walk_callback (&$item, $key){
1277
+ if (is_string($item)) $item = mb_encode_numericentity($item, array (0x80, 0xffff, 0, 0xffff), 'UTF-8');
1278
+ }
1279
+ }
embedded/common/toolset-forms/classes/class.email.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once 'class.textfield.php';
3
+
4
+ /**
5
+ * Description of class
6
+ *
7
+ * @author Srdjan
8
+ */
9
+ class WPToolset_Field_Email extends WPToolset_Field_Textfield
10
+ {
11
+
12
+ }
embedded/common/toolset-forms/classes/class.embed.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once 'class.textfield.php';
3
+
4
+ /**
5
+ * Description of class
6
+ *
7
+ * @author Srdjan
8
+ */
9
+ class WPToolset_Field_Embed extends WPToolset_Field_Textfield
10
+ {
11
+
12
+ protected $_settings = array('min_wp_version' => '3.6');
13
+
14
+ }
embedded/common/toolset-forms/classes/class.field_factory.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ *
5
+ * $HeadURL: http://plugins.svn.wordpress.org/types/tags/1.6/embedded/common/toolset-forms/classes/class.field_factory.php $
6
+ * $LastChangedDate: 2014-08-22 01:02:43 +0000 (Fri, 22 Aug 2014) $
7
+ * $LastChangedRevision: 970205 $
8
+ * $LastChangedBy: brucepearson $
9
+ *
10
+ */
11
+
12
+ require 'abstract.field.php';
13
+
14
+ abstract class FieldFactory extends FieldAbstract
15
+ {
16
+ protected $_nameField, $_data, $_value, $_use_bootstrap;
17
+
18
+ function __construct($data, $global_name_field, $value)
19
+ {
20
+ $this->_nameField = $global_name_field;
21
+ $this->_data = $data;
22
+ $this->_value = $value;
23
+
24
+ $this->init();
25
+ }
26
+
27
+ public function init()
28
+ {
29
+ $cred_cred_settings = get_option( 'cred_cred_settings' );
30
+ $this->_use_bootstrap = is_array($cred_cred_settings) && array_key_exists( 'use_bootstrap', $cred_cred_settings ) && $cred_cred_settings['use_bootstrap'];
31
+ }
32
+
33
+ public function set_metaform($metaform)
34
+ {
35
+ $this->_metaform = $metaform;
36
+ }
37
+
38
+ public function get_metaform()
39
+ {
40
+ return $this->_metaform;
41
+ }
42
+
43
+ public function get_data()
44
+ {
45
+ return $this->data;
46
+ }
47
+
48
+ public function set_data($data)
49
+ {
50
+ $this->data = $data;
51
+ }
52
+
53
+ public function set_nameField($nameField)
54
+ {
55
+ $this->_nameField = $nameField;
56
+ }
57
+
58
+ public function get_nameField()
59
+ {
60
+ return $this->_nameField;
61
+ }
62
+
63
+ public function getId()
64
+ {
65
+ return $this->_data['id'];
66
+ }
67
+
68
+ public function getType()
69
+ {
70
+ return $this->_data['type'];
71
+ }
72
+
73
+ public function getValue()
74
+ {
75
+ return $this->_value;
76
+ }
77
+
78
+ public function getTitle()
79
+ {
80
+ return $this->_data['title'];
81
+ }
82
+
83
+ public function getDescription()
84
+ {
85
+ return wpautop( $this->_data['description'] );
86
+ }
87
+
88
+ public function getName()
89
+ {
90
+ return $this->_data['name'];
91
+ }
92
+
93
+ public function getData()
94
+ {
95
+ return $this->_data;
96
+ }
97
+
98
+ public function getValidationData()
99
+ {
100
+ return !empty( $this->_data['validation'] ) ? $this->_data['validation'] : array();
101
+ }
102
+
103
+ public function setValidationData($validation)
104
+ {
105
+ $this->_data['validation'] = $validation;
106
+ }
107
+
108
+ public function getSettings()
109
+ {
110
+ return isset( $this->_settings ) ? $this->_settings : array();
111
+ }
112
+
113
+ public function isRepetitive()
114
+ {
115
+ return (bool)$this->_data['repetitive'];
116
+ }
117
+
118
+ public function getAttr() {
119
+ if ( array_key_exists( 'attribute', $this->_data ) ) {
120
+ return $this->_data['attribute'];
121
+ }
122
+ return array();
123
+ }
124
+
125
+ public static function registerScripts() {}
126
+ public static function registerStyles() {}
127
+ public static function addFilters() {}
128
+ public static function addActions() {}
129
+
130
+ public function enqueueScripts() {}
131
+ public function enqueueStyles() {}
132
+ public function metaform() {}
133
+ public function editform() {}
134
+ public function mediaEditor() {}
135
+ }
embedded/common/toolset-forms/classes/class.fieldconfig.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ * $HeadURL: http://plugins.svn.wordpress.org/types/tags/1.6/embedded/common/toolset-forms/classes/class.fieldconfig.php $
5
+ * $LastChangedDate: 2014-08-22 01:02:43 +0000 (Fri, 22 Aug 2014) $
6
+ * $LastChangedRevision: 970205 $
7
+ * $LastChangedBy: brucepearson $
8
+ *
9
+ */
10
+ if (!class_exists("FieldConfig")) {
11
+ /**
12
+ * Description of FieldConfig
13
+ *
14
+ * @author ontheGoSystem
15
+ */
16
+ class FieldConfig {
17
+
18
+ private $id;
19
+ private $name = "cred[post_title]";
20
+ private $value;
21
+ private $type = 'textfield';
22
+ private $title = 'Post title';
23
+ private $repetitive = false;
24
+ private $display = '';
25
+ private $description = '';
26
+ private $config = array();
27
+ private $options = array();
28
+ private $default_value = '';
29
+ private $validation = array();
30
+ private $attr;
31
+
32
+ private $add_time = false;
33
+
34
+ public function __construct() {
35
+ }
36
+
37
+ public function setRepetitive($repetitive) {
38
+ $this->repetitive = $repetitive;
39
+ }
40
+
41
+ public function isRepetitive() {
42
+ return $this->repetitive;
43
+ }
44
+
45
+ public function set_add_time($addtime) {
46
+ $this->add_time = $addtime;
47
+ }
48
+
49
+ public function setAttr($attr) {
50
+ $this->attr = $attr;
51
+ }
52
+
53
+ public function getAttr() {
54
+ return $this->attr;
55
+ }
56
+
57
+ public function setDefaultValue($type,$field_arr)
58
+ {
59
+ switch ($type) {
60
+ case 'date':
61
+ $this->add_time = false;
62
+ if ( isset( $field_arr['data']['date_and_time'] ) && 'and_time' == $field_arr['data']['date_and_time'] ) {
63
+ $this->add_time = true;
64
+ }
65
+ break;
66
+ case 'checkboxes':
67
+ if ( is_array( $field_arr['attr']['default'] ) && count( $field_arr['attr']['default'] ) ) {
68
+ $this->default_value = $field_arr['attr']['default'][0];
69
+ }
70
+ break;
71
+
72
+ case 'select':
73
+ $this->default_value = isset( $field_arr['attr']['actual_value'][0] )? $field_arr['attr']['actual_value'][0] : null;
74
+ break;
75
+
76
+ case 'radios':
77
+ $this->default_value = $field_arr['attr']['default'];
78
+ break;
79
+
80
+ case 'checkbox':
81
+ $this->default_value = isset($field_arr['data']['checked'])?$field_arr['data']['checked']:0;
82
+ break;
83
+
84
+ default:
85
+ $this->default_value = "";
86
+ break;
87
+ }
88
+ }
89
+
90
+ public function setOptions($name,$type,$values,$attrs) {
91
+ $arr = array();
92
+ switch ($type) {
93
+ case 'checkbox':
94
+ $arr=$attrs;
95
+ break;
96
+ case 'checkboxes':
97
+ foreach ($attrs['actual_titles'] as $refvalue=>$title) {
98
+ $value = $attrs['actual_values'][$refvalue];
99
+ $arr[$refvalue] = array('value'=>$refvalue,'title'=>$title,'name'=>$name);
100
+ if ( in_array($refvalue, $attrs['default']) ) {
101
+ $arr[$refvalue]['checked'] = true;
102
+ }
103
+ }
104
+ break;
105
+ case 'select':
106
+ $values = $attrs['options'];
107
+ foreach ($values as $refvalue=>$title) {
108
+ $arr[$refvalue] = array(
109
+ 'value' => $refvalue,
110
+ 'title' => $title,
111
+ 'types-value' => $attrs['actual_options'][$refvalue],
112
+ );
113
+ }
114
+ break;
115
+ case 'radios':
116
+ foreach ($attrs['actual_titles'] as $refvalue=>$title) {
117
+ $arr[$refvalue] = array(
118
+ 'value' => $refvalue,
119
+ 'title' => $title,
120
+ 'checked' => false,
121
+ 'name' => $refvalue,
122
+ 'types-value' => $attrs['actual_values'][$refvalue],
123
+ );
124
+ }
125
+ break;
126
+ default:
127
+ return;
128
+ break;
129
+ }
130
+ $this->options = $arr;
131
+ }
132
+
133
+ public function createConfig() {
134
+ $base_name = "cred";
135
+ $this->config = array(
136
+ 'id' => $this->getId(),
137
+ 'type' => $this->getType(),
138
+ 'title' => $this->getTitle(),
139
+ 'options' => $this->getOptions(),
140
+ 'default_value' => $this->getDefaultValue(),
141
+ 'description' => $this->getDescription(),
142
+ 'repetitive' => $this->isRepetitive(),
143
+ /*'name' => $base_name."[".$this->getType()."]",*/
144
+ 'name' => $this->getName(),
145
+ 'value' => $this->getValue(),
146
+ 'add_time' => $this->getAddTime(),
147
+ 'validation' => array(),
148
+ 'display' => $this->getDisplay(),
149
+ 'attribute' => $this->getAttr()
150
+ );
151
+ return $this->config;
152
+ }
153
+
154
+ public function getAddTime() {
155
+ return $this->add_time;
156
+ }
157
+
158
+ public function getType() {
159
+ return $this->type;
160
+ }
161
+
162
+ public function setType($type) {
163
+ $this->type = $type;
164
+ }
165
+
166
+ public function getOptions() {
167
+ return $this->options;
168
+ }
169
+
170
+ public function getDefaultValue() {
171
+ return $this->default_value;
172
+ }
173
+
174
+ public function getTitle() {
175
+ return $this->title;
176
+ }
177
+
178
+ public function getDisplay()
179
+ {
180
+ return $this->display;
181
+ }
182
+
183
+ public function setTitle($title) {
184
+ $this->title = $title;
185
+ }
186
+
187
+ public function getDescription() {
188
+ return $this->description;
189
+ }
190
+
191
+ public function setDescription($description) {
192
+ $this->description = $description;
193
+ }
194
+
195
+ public function getName() {
196
+ return $this->name;
197
+ }
198
+
199
+ public function setName($name) {
200
+ $this->name = $name;
201
+ }
202
+
203
+ public function getValue() {
204
+ return $this->value;
205
+ }
206
+
207
+ public function setValue($value) {
208
+ $this->value = $value;
209
+ }
210
+
211
+ public function getValidation() {
212
+ return !empty($this->validation) ? $this->validation : array();
213
+ }
214
+
215
+ public function setValidation($validati