Timetable and Event Schedule by MotoPress - Version 2.4.6

Version Description

Download this release

Release Info

Developer jetmonsters
Plugin Icon 128x128 Timetable and Event Schedule by MotoPress
Version 2.4.6
Comparing to
See all releases

Code changes from version 2.4.5 to 2.4.6

Files changed (56) hide show
  1. admin/help/index.php +84 -84
  2. admin/import/export.php +5 -5
  3. admin/import/footer.php +1 -1
  4. admin/import/greet.php +3 -3
  5. admin/import/header.php +2 -2
  6. admin/import/import.php +6 -6
  7. changelog.txt +185 -185
  8. classes/blocks/class-timetable-block.php +218 -218
  9. classes/class-controller.php +40 -40
  10. classes/class-core.php +801 -801
  11. classes/class-hooks.php +310 -310
  12. classes/class-model.php +41 -41
  13. classes/class-module.php +20 -20
  14. classes/class-offer.php +216 -216
  15. classes/class-permalinks.php +138 -138
  16. classes/class-preprocessor.php +182 -182
  17. classes/class-shortcode.php +400 -400
  18. classes/class-state-factory.php +84 -84
  19. classes/class-view.php +235 -235
  20. classes/class-widgets-manager.php +27 -27
  21. classes/controllers/class-controller-column.php +34 -34
  22. classes/controllers/class-controller-events.php +124 -124
  23. classes/controllers/class-controller-help.php +28 -28
  24. classes/controllers/class-controller-import.php +34 -34
  25. classes/controllers/class-controller-popup.php +38 -38
  26. classes/controllers/class-controller-settings.php +73 -73
  27. classes/libs/class-gump.php +2029 -2029
  28. classes/libs/parsers.php +789 -789
  29. classes/models/class-column.php +220 -220
  30. classes/models/class-events.php +936 -936
  31. classes/models/class-export.php +482 -482
  32. classes/models/class-import.php +968 -968
  33. classes/models/class-settings.php +105 -105
  34. classes/modules/class-menu.php +33 -33
  35. classes/modules/class-post.php +108 -108
  36. classes/modules/class-taxonomy.php +42 -42
  37. classes/widgets/class-mp-timetable-elementor-widget.php +472 -472
  38. classes/widgets/class-mp-timetable-widget.php +142 -142
  39. languages/mp-timetable-fa_IR.po +962 -962
  40. languages/mp-timetable-ru_RU-1350249ca68bb46ac81f10c0007fcc6d.json +161 -161
  41. languages/mp-timetable-ru_RU.po +1109 -1109
  42. languages/mp-timetable.pot +1244 -1244
  43. media/css/jbox/jBox.css +569 -569
  44. media/css/jbox/themes/ModalBorder.css +45 -45
  45. media/css/jbox/themes/NoticeBorder.css +44 -44
  46. media/css/jbox/themes/TooltipBorder.css +32 -32
  47. media/css/jbox/themes/TooltipDark.css +36 -36
  48. media/css/jquery-ui-1.10.0.custom.min.css +4 -4
  49. media/css/jquery.ui.timepicker.css +57 -57
  50. media/css/spectrum.css +507 -507
  51. media/js/blocks/dist/index.js +1 -1
  52. media/js/blocks/src/timetable/edit.js +83 -91
  53. media/js/blocks/src/timetable/index.js +27 -27
  54. media/js/blocks/src/timetable/inspector.js +295 -295
  55. media/js/events/event.js +973 -973
  56. media/js/lib/jBox.js +0 -231
admin/help/index.php CHANGED
@@ -1,84 +1,84 @@
1
- <div class="wrap">
2
-
3
- <h1 class="wp-heading-inline">Help</h1>
4
- <p><?php
5
-
6
- $pluginObject = get_plugin_data( MP_TT_PLUGIN_FILE );
7
- $name = $pluginObject[ 'Name' ];
8
-
9
- echo sprintf(
10
- /* translators: 1: Timetable and Event Schedule 2:: five stars rating */
11
- __( 'If you like %1$s please leave us a %2$s rating.', 'mp-timetable' ),
12
- sprintf( '<strong>%s</strong>', esc_html( $name ) ),
13
- '<a href="https://wordpress.org/support/plugin/mp-timetable/reviews?rate=5#new-post" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
14
- );
15
- ?></p>
16
- <hr/>
17
-
18
- <div class="motopress-offer-primary">
19
- <h2>Quick Start Guide</h2>
20
- <ol>
21
- <li>
22
- <p><strong>Add Columns</strong><br/>
23
- Make sure you created Columns prior to adding Events for the events to be then assigned to the created columns.</p>
24
- </li>
25
- <li>
26
- <p><strong>Add Events</strong><br/>
27
- The events will be displayed in the actual timetable. Event details will be shown on each event’s individual page.</p>
28
- <ol>
29
- <li>
30
- <p><strong>Add Event Category</strong><br/>
31
- Events can be presented under different categories, which can be chosen in the shortcode parameters below.</p>
32
- </li>
33
- </ol>
34
- </li>
35
- <li>
36
- <p><strong>Add Timetable to a Page</strong></p>
37
- <ol>
38
- <li>Find "TimeTable" icon on TinyMCE panel in Classic Editor.</li>
39
- <li>Build Timetable shortcode manually.
40
- <p>Shortcode <code>[mp-timetable ... ]</code> attributes:</p>
41
- <ul>
42
- <li><code>col</code> - comma-separated column IDs.</li>
43
- <li><code>events</code> - comma-separated event IDs.</li>
44
- <li><code>event_categ</code> - comma-separated event category IDs.</li>
45
- <li><code>increment</code> - hour measure; possible values <kbd>1</kbd> - hour (1h), <kbd>0.5</kbd> - half an hour (30min), <kbd>0.25</kbd> - quarter an hour (15min).</li>
46
- <li><code>title</code> - display event title; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
47
- <li><code>time</code> - display event time; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
48
- <li><code>sub-title</code> - display event subtitle; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
49
- <li><code>description</code> - display event description; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
50
- <li><code>user</code> - display event head; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
51
- <li><code>row_height</code> - event block height in pixels; example <kbd>45</kbd></li>
52
- <li><code>font_size</code> - base font size for the table; example <kbd>12px</kbd>, <kbd>2em</kbd>, <kbd>80%</kbd>.</li>
53
- <li><code>view</code> - filter style; possible values <kbd>dropdown_list</kbd> or <kbd>tabs</kbd>.</li>
54
- <li><code>view_sort</code> - order of items in filter; possible values <kbd><i>empty string</i></kbd>, <kbd>menu_order</kbd>, <kbd>post_title</kbd>.</li>
55
- <li><code>label</code> - filter label; default is <kbd>All Events</kbd>.</li>
56
- <li><code>hide_label</code> - display 'All Events' label or not; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
57
- <li><code>hide_hrs</code> - hide first (hours) column; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
58
- <li><code>hide_empty_rows</code> - hide empty rows; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
59
- <li><code>group</code> - merge cells with common events; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
60
- <li><code>disable_event_url</code> - disable event URL; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
61
- <li><code>text_align</code> - horizontal align; possible values <kbd>left</kbd>, <kbd>center</kbd>, <kbd>right</kbd>.</li>
62
- <li><code>text_align_vertical</code> - vertical align ; possible values <kbd>default</kbd>, <kbd>top</kbd>, <kbd>middle</kbd>, <kbd>bottom</kbd>.</li>
63
- <li><code>id</code> - unique ID.</li>
64
- <li><code>custom_class</code> - CSS class.</li>
65
- <li><code>responsive</code> - mobile layout; possible values <kbd>1</kbd> - display as list, <kbd>0</kbd> - display as table.</li>
66
- <li><code>table_layout</code> - column width; possible values <kbd>auto</kbd>, <kbd>fixed</kbd>.</li>
67
- </ul>
68
- </li>
69
- <li>Use "TimeTable" block in the new Block Editor.</li>
70
- </ol>
71
- </li>
72
- </ol>
73
- </div>
74
- <?php
75
-
76
- /*
77
- * Offer free plugins
78
- *
79
- */
80
- require_once Mp_Time_Table::get_plugin_path() . 'classes/class-offer.php';
81
- $plugins_offer = new \mp_timetable\plugin_core\classes\Plugins_Offer();
82
- $plugins_offer->render();
83
- ?>
84
- </div>
1
+ <div class="wrap">
2
+
3
+ <h1 class="wp-heading-inline">Help</h1>
4
+ <p><?php
5
+
6
+ $pluginObject = get_plugin_data( MP_TT_PLUGIN_FILE );
7
+ $name = $pluginObject[ 'Name' ];
8
+
9
+ echo sprintf(
10
+ /* translators: 1: Timetable and Event Schedule 2:: five stars rating */
11
+ __( 'If you like %1$s please leave us a %2$s rating.', 'mp-timetable' ),
12
+ sprintf( '<strong>%s</strong>', esc_html( $name ) ),
13
+ '<a href="https://wordpress.org/support/plugin/mp-timetable/reviews?rate=5#new-post" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
14
+ );
15
+ ?></p>
16
+ <hr/>
17
+
18
+ <div class="motopress-offer-primary">
19
+ <h2>Quick Start Guide</h2>
20
+ <ol>
21
+ <li>
22
+ <p><strong>Add Columns</strong><br/>
23
+ Make sure you created Columns prior to adding Events for the events to be then assigned to the created columns.</p>
24
+ </li>
25
+ <li>
26
+ <p><strong>Add Events</strong><br/>
27
+ The events will be displayed in the actual timetable. Event details will be shown on each event’s individual page.</p>
28
+ <ol>
29
+ <li>
30
+ <p><strong>Add Event Category</strong><br/>
31
+ Events can be presented under different categories, which can be chosen in the shortcode parameters below.</p>
32
+ </li>
33
+ </ol>
34
+ </li>
35
+ <li>
36
+ <p><strong>Add Timetable to a Page</strong></p>
37
+ <ol>
38
+ <li>Find "TimeTable" icon on TinyMCE panel in Classic Editor.</li>
39
+ <li>Build Timetable shortcode manually.
40
+ <p>Shortcode <code>[mp-timetable ... ]</code> attributes:</p>
41
+ <ul>
42
+ <li><code>col</code> - comma-separated column IDs.</li>
43
+ <li><code>events</code> - comma-separated event IDs.</li>
44
+ <li><code>event_categ</code> - comma-separated event category IDs.</li>
45
+ <li><code>increment</code> - hour measure; possible values <kbd>1</kbd> - hour (1h), <kbd>0.5</kbd> - half an hour (30min), <kbd>0.25</kbd> - quarter an hour (15min).</li>
46
+ <li><code>title</code> - display event title; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
47
+ <li><code>time</code> - display event time; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
48
+ <li><code>sub-title</code> - display event subtitle; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
49
+ <li><code>description</code> - display event description; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
50
+ <li><code>user</code> - display event head; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
51
+ <li><code>row_height</code> - event block height in pixels; example <kbd>45</kbd></li>
52
+ <li><code>font_size</code> - base font size for the table; example <kbd>12px</kbd>, <kbd>2em</kbd>, <kbd>80%</kbd>.</li>
53
+ <li><code>view</code> - filter style; possible values <kbd>dropdown_list</kbd> or <kbd>tabs</kbd>.</li>
54
+ <li><code>view_sort</code> - order of items in filter; possible values <kbd><i>empty string</i></kbd>, <kbd>menu_order</kbd>, <kbd>post_title</kbd>.</li>
55
+ <li><code>label</code> - filter label; default is <kbd>All Events</kbd>.</li>
56
+ <li><code>hide_label</code> - display 'All Events' label or not; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
57
+ <li><code>hide_hrs</code> - hide first (hours) column; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
58
+ <li><code>hide_empty_rows</code> - hide empty rows; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
59
+ <li><code>group</code> - merge cells with common events; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
60
+ <li><code>disable_event_url</code> - disable event URL; possible values <kbd>1</kbd> or <kbd>0</kbd>.</li>
61
+ <li><code>text_align</code> - horizontal align; possible values <kbd>left</kbd>, <kbd>center</kbd>, <kbd>right</kbd>.</li>
62
+ <li><code>text_align_vertical</code> - vertical align ; possible values <kbd>default</kbd>, <kbd>top</kbd>, <kbd>middle</kbd>, <kbd>bottom</kbd>.</li>
63
+ <li><code>id</code> - unique ID.</li>
64
+ <li><code>custom_class</code> - CSS class.</li>
65
+ <li><code>responsive</code> - mobile layout; possible values <kbd>1</kbd> - display as list, <kbd>0</kbd> - display as table.</li>
66
+ <li><code>table_layout</code> - column width; possible values <kbd>auto</kbd>, <kbd>fixed</kbd>.</li>
67
+ </ul>
68
+ </li>
69
+ <li>Use "TimeTable" block in the new Block Editor.</li>
70
+ </ol>
71
+ </li>
72
+ </ol>
73
+ </div>
74
+ <?php
75
+
76
+ /*
77
+ * Offer free plugins
78
+ *
79
+ */
80
+ require_once Mp_Time_Table::get_plugin_path() . 'classes/class-offer.php';
81
+ $plugins_offer = new \mp_timetable\plugin_core\classes\Plugins_Offer();
82
+ $plugins_offer->render();
83
+ ?>
84
+ </div>
admin/import/export.php CHANGED
@@ -1,6 +1,6 @@
1
- <h3><?php _e('Export', 'mp-timetable') ?></h3>
2
- <form novalidate="novalidate" method="post" id="mptt_export">
3
- <input type="hidden" name="controller" value="import">
4
- <input type="hidden" name="mptt_action" value="export">
5
- <p class="submit"><input type="submit" value="<?php _e('Export', 'mp-timetable') ?>" class="button button-primary" id="submit" name="submit"></p>
6
  </form>
1
+ <h3><?php _e('Export', 'mp-timetable') ?></h3>
2
+ <form novalidate="novalidate" method="post" id="mptt_export">
3
+ <input type="hidden" name="controller" value="import">
4
+ <input type="hidden" name="mptt_action" value="export">
5
+ <p class="submit"><input type="submit" value="<?php _e('Export', 'mp-timetable') ?>" class="button button-primary" id="submit" name="submit"></p>
6
  </form>
admin/import/footer.php CHANGED
@@ -1 +1 @@
1
- </div>
1
+ </div>
admin/import/greet.php CHANGED
@@ -1,4 +1,4 @@
1
- <div class="narrow">
2
- <p><?php _e('Choose a WXR (.xml) file to upload, then click Upload file and import.', 'mp-timetable') ?></p>
3
- <?php wp_import_upload_form('admin.php?import=mptt-importer&amp;step=1') ?>
4
  </div>
1
+ <div class="narrow">
2
+ <p><?php _e('Choose a WXR (.xml) file to upload, then click Upload file and import.', 'mp-timetable') ?></p>
3
+ <?php wp_import_upload_form('admin.php?import=mptt-importer&amp;step=1') ?>
4
  </div>
admin/import/header.php CHANGED
@@ -1,2 +1,2 @@
1
- <div class="wrap">
2
- <h1 class="wp-heading-inline"><?php _e('Import / Export Timetable Plugin Data', 'mp-timetable') ?></h1>
1
+ <div class="wrap">
2
+ <h1 class="wp-heading-inline"><?php _e('Import / Export Timetable Plugin Data', 'mp-timetable') ?></h1>
admin/import/import.php CHANGED
@@ -1,6 +1,6 @@
1
- <?php
2
-
3
- if ( current_user_can('import') ) { ?>
4
- <h3><?php _e('Import', 'mp-timetable') ?></h3><?php
5
- wp_import_upload_form('admin.php?import=mptt-importer&amp;step=1');
6
- }
1
+ <?php
2
+
3
+ if ( current_user_can('import') ) { ?>
4
+ <h3><?php _e('Import', 'mp-timetable') ?></h3><?php
5
+ wp_import_upload_form('admin.php?import=mptt-importer&amp;step=1');
6
+ }
changelog.txt CHANGED
@@ -1,185 +1,185 @@
1
- = 2.4.2, Aug 20 2021 =
2
- * Security - added nonces to prevent CSRF.
3
-
4
- = 2.4.1, Aug 18 2021 =
5
- * Bug fix: fixed a PHP notice in Widget Areas in WordPress 5.8.
6
-
7
- = 2.4.0, Aug 11 2021 =
8
- * Security - Fixed security issues. Reported by wpscan.com.
9
-
10
- = 2.3.19, Jul 27 2021 =
11
- * Improved compatibility with WordPress 5.8.
12
- * Security - Fixed unescaped meta data. Reported by Trustwave.
13
-
14
- = 2.3.18, Mar 18 2021 =
15
- * Improved compatibility with WordPress 5.7.
16
-
17
- = 2.3.17, Mar 3 2021 =
18
- * Improved compatibility with WordPress multisite.
19
-
20
- = 2.3.17, Feb 18 2021 =
21
- * Bug fix: fixed PHP parse error in PHP 7.2.
22
-
23
- = 2.3.15, Feb 17 2021 =
24
- * Added Timetable Elementor widget.
25
- * Bug fix: fixed an issue with invalid XML file while exporting data.
26
-
27
- = 2.3.14, Feb 4 2021 =
28
- * Improved plugin internalization.
29
-
30
- = 2.3.13, Feb 3 2021 =
31
- * Bug fix: fixed an issue with double slashes in the assets' URLs.
32
- * Improved plugin internalization.
33
-
34
- = 2.3.12, Dec 11 2020 =
35
- * Improved compatibility with WordPress 5.6.
36
-
37
- = 2.3.11, May 18 2020 =
38
- * Added the ability to duplicate events.
39
- * Added the ability to set table layout fixed or auto.
40
- * Bug fix: fixed an issue with an empty categories list in the widget.
41
-
42
- = 2.3.10, Apr 24 2020 =
43
- * Bug fix: fixed an issue when a user with the Editor role could not access the administration area.
44
- * Improved compatibility with PHP 7.4.
45
-
46
- = 2.3.9, Apr 21 2020 =
47
- * Added the ability to sort events in the dropdown list or tabs.
48
- * Improved user capability check.
49
-
50
- = 2.3.8, Apr 1 2020 =
51
- * Bug fix: fixed an issue with the missing Event tags field.
52
- * Bug fix: fixed an issue when a user with the read capability could access a Help menu page.
53
-
54
- = 2.3.7, Mar 10 2020 =
55
- * Bug fix: fixed an issue with the erroneous positioning of events.
56
-
57
- = 2.3.6, Feb 19 2020 =
58
- * Bug fix: fixed an issue with the missing subtitle in mobile view.
59
-
60
- = 2.3.5, Feb 19 2020 =
61
- * Bug fix: fixed an issue with slashes in event description.
62
-
63
- = 2.3.4, Sep 25 2019 =
64
- * Bug fix: fixed an issue with UTC timezone offset.
65
-
66
- = 2.3.3, Sep 20 2019 =
67
- * Bug fix: fixed the issue with events disappearing on hover in Chrome.
68
-
69
- = 2.3.2 =
70
- * Bug fix: fixed an issue in IE browser.
71
-
72
- = 2.3.1 =
73
- * Bug fix: fixed the issue with opening PHP tag.
74
-
75
- = 2.3.0 =
76
- * Added support for WordPress 5.0.
77
-
78
- = 2.2.1 =
79
- * Bug fix: fixed an issue with URL hash (not-set:all).
80
-
81
- = 2.2.0 =
82
- * Added filters for register_post_type and register_taxonomy functions.
83
- * Added permalink configuration option in Settings > Permalinks.
84
-
85
- = 2.1.12 =
86
- * Bug fix: fixed an issue in IE browser.
87
-
88
- = 2.1.11 =
89
- * Added translations into the Persian language.
90
-
91
- = 2.1.10 =
92
- * Improved compatibility with WooCommerce Memberships plugin.
93
- * Better W3C validation.
94
-
95
- = 2.1.9 =
96
- * Bug fix: fixed the issue when event was not visible in the timetable if it starts at 00:00.
97
-
98
- = 2.1.8 =
99
- * Improved compatibility with javascript-disabled browsers.
100
-
101
- = 2.1.7 =
102
- * Bug fix: fixed the issue when events were not filtered by the selected category in a widget.
103
- * Bug fix: fixed the issue when event was not visible in the timetable if it ends the next day.
104
- * Minor bugfixes and improvements.
105
-
106
- = 2.1.6 =
107
- * New dashboard icons.
108
-
109
- = 2.1.5 =
110
- * Bug fix: fixed the issue when table is not visible if events filter is set to 'none'.
111
-
112
- = 2.1.4 =
113
- * Bug fix: fixed internal issue.
114
-
115
- = 2.1.3 =
116
- * Added the ability to merge cells with common events.
117
- * Added the ability to set vertical alignment in the table.
118
- * Added the ability to set custom CSS class for table shortcode.
119
- * Added the ability to hide filter control on the top of the table.
120
- * Bug fix: fixed the issue when table ID didn't output on the site.
121
-
122
- = 2.1.2 =
123
- * Bug fix: fixed the issue when plugin overrides default archive template.
124
- * Bug fix: fixed the issue in upcoming events widget when events were not sorted by days.
125
-
126
- = 2.1.1 =
127
- * Bug fix: fixed the issue with shortcode tempalte.
128
-
129
- = 2.1.0 =
130
- * Added the ability to override templates in a theme.
131
- * Bug fix: fixed the issue on WordPress multisite when Event wasn't saving.
132
- * Bug fix: fixed the issue when timeslots didn't show if Event is in the Draft status.
133
-
134
- = 2.0.4 =
135
- * Bug fix: fixed an issue with post template on search results page.
136
-
137
- = 2.0.3 =
138
- * Bug fix: fixed a link to create new column from event screen.
139
- * Improved usernames in Event Head dropdown.
140
-
141
- = 2.0.2 =
142
- * Minor bugfixes and improvements.
143
-
144
- = 2.0.1 =
145
- * Bug fix: fixed an issue with template override.
146
-
147
- = 2.0.0 =
148
- * We improved compatibility with your theme styles in this update. If you still stick to a previous version, simply change the template mode option in the plugin settings.
149
- * Added the ability to set font size for timetable shortcode so you can make your text bigger or smaller.
150
-
151
- = 1.1.6 =
152
- * Bug fix: fixed an issue with empty rows.
153
-
154
- = 1.1.5 =
155
- * Bug fix: fixed an issue with post view in search results.
156
-
157
- = 1.1.4 =
158
- * Improved compatibility with Polylang plugin.
159
-
160
- = 1.1.3 =
161
- * Fixed an issue with categories filter in widget.
162
-
163
- = 1.1.2 =
164
- * Fixed an issue with posts order.
165
-
166
- = 1.1.0 =
167
- * Improved events sorting.
168
- * Minor bugfixes and improvements.
169
-
170
- = 1.0.7 =
171
- * Improved events and columns sorting by date.
172
- * Comments section added to event.
173
- * Minor bugfixes and improvements.
174
-
175
- = 1.0.6 =
176
- * Fixed an issue in column view.
177
-
178
- = 1.0.5 =
179
- * Improved compatibility with IE10+
180
-
181
- = 1.0.4 =
182
- * Minor bugfixes and improvements.
183
-
184
- = 1.0.3 =
185
- * Minor bugfixes and improvements.
1
+ = 2.4.2, Aug 20 2021 =
2
+ * Security - added nonces to prevent CSRF.
3
+
4
+ = 2.4.1, Aug 18 2021 =
5
+ * Bug fix: fixed a PHP notice in Widget Areas in WordPress 5.8.
6
+
7
+ = 2.4.0, Aug 11 2021 =
8
+ * Security - Fixed security issues. Reported by wpscan.com.
9
+
10
+ = 2.3.19, Jul 27 2021 =
11
+ * Improved compatibility with WordPress 5.8.
12
+ * Security - Fixed unescaped meta data. Reported by Trustwave.
13
+
14
+ = 2.3.18, Mar 18 2021 =
15
+ * Improved compatibility with WordPress 5.7.
16
+
17
+ = 2.3.17, Mar 3 2021 =
18
+ * Improved compatibility with WordPress multisite.
19
+
20
+ = 2.3.17, Feb 18 2021 =
21
+ * Bug fix: fixed PHP parse error in PHP 7.2.
22
+
23
+ = 2.3.15, Feb 17 2021 =
24
+ * Added Timetable Elementor widget.
25
+ * Bug fix: fixed an issue with invalid XML file while exporting data.
26
+
27
+ = 2.3.14, Feb 4 2021 =
28
+ * Improved plugin internalization.
29
+
30
+ = 2.3.13, Feb 3 2021 =
31
+ * Bug fix: fixed an issue with double slashes in the assets' URLs.
32
+ * Improved plugin internalization.
33
+
34
+ = 2.3.12, Dec 11 2020 =
35
+ * Improved compatibility with WordPress 5.6.
36
+
37
+ = 2.3.11, May 18 2020 =
38
+ * Added the ability to duplicate events.
39
+ * Added the ability to set table layout fixed or auto.
40
+ * Bug fix: fixed an issue with an empty categories list in the widget.
41
+
42
+ = 2.3.10, Apr 24 2020 =
43
+ * Bug fix: fixed an issue when a user with the Editor role could not access the administration area.
44
+ * Improved compatibility with PHP 7.4.
45
+
46
+ = 2.3.9, Apr 21 2020 =
47
+ * Added the ability to sort events in the dropdown list or tabs.
48
+ * Improved user capability check.
49
+
50
+ = 2.3.8, Apr 1 2020 =
51
+ * Bug fix: fixed an issue with the missing Event tags field.
52
+ * Bug fix: fixed an issue when a user with the read capability could access a Help menu page.
53
+
54
+ = 2.3.7, Mar 10 2020 =
55
+ * Bug fix: fixed an issue with the erroneous positioning of events.
56
+
57
+ = 2.3.6, Feb 19 2020 =
58
+ * Bug fix: fixed an issue with the missing subtitle in mobile view.
59
+
60
+ = 2.3.5, Feb 19 2020 =
61
+ * Bug fix: fixed an issue with slashes in event description.
62
+
63
+ = 2.3.4, Sep 25 2019 =
64
+ * Bug fix: fixed an issue with UTC timezone offset.
65
+
66
+ = 2.3.3, Sep 20 2019 =
67
+ * Bug fix: fixed the issue with events disappearing on hover in Chrome.
68
+
69
+ = 2.3.2 =
70
+ * Bug fix: fixed an issue in IE browser.
71
+
72
+ = 2.3.1 =
73
+ * Bug fix: fixed the issue with opening PHP tag.
74
+
75
+ = 2.3.0 =
76
+ * Added support for WordPress 5.0.
77
+
78
+ = 2.2.1 =
79
+ * Bug fix: fixed an issue with URL hash (not-set:all).
80
+
81
+ = 2.2.0 =
82
+ * Added filters for register_post_type and register_taxonomy functions.
83
+ * Added permalink configuration option in Settings > Permalinks.
84
+
85
+ = 2.1.12 =
86
+ * Bug fix: fixed an issue in IE browser.
87
+
88
+ = 2.1.11 =
89
+ * Added translations into the Persian language.
90
+
91
+ = 2.1.10 =
92
+ * Improved compatibility with WooCommerce Memberships plugin.
93
+ * Better W3C validation.
94
+
95
+ = 2.1.9 =
96
+ * Bug fix: fixed the issue when event was not visible in the timetable if it starts at 00:00.
97
+
98
+ = 2.1.8 =
99
+ * Improved compatibility with javascript-disabled browsers.
100
+
101
+ = 2.1.7 =
102
+ * Bug fix: fixed the issue when events were not filtered by the selected category in a widget.
103
+ * Bug fix: fixed the issue when event was not visible in the timetable if it ends the next day.
104
+ * Minor bugfixes and improvements.
105
+
106
+ = 2.1.6 =
107
+ * New dashboard icons.
108
+
109
+ = 2.1.5 =
110
+ * Bug fix: fixed the issue when table is not visible if events filter is set to 'none'.
111
+
112
+ = 2.1.4 =
113
+ * Bug fix: fixed internal issue.
114
+
115
+ = 2.1.3 =
116
+ * Added the ability to merge cells with common events.
117
+ * Added the ability to set vertical alignment in the table.
118
+ * Added the ability to set custom CSS class for table shortcode.
119
+ * Added the ability to hide filter control on the top of the table.
120
+ * Bug fix: fixed the issue when table ID didn't output on the site.
121
+
122
+ = 2.1.2 =
123
+ * Bug fix: fixed the issue when plugin overrides default archive template.
124
+ * Bug fix: fixed the issue in upcoming events widget when events were not sorted by days.
125
+
126
+ = 2.1.1 =
127
+ * Bug fix: fixed the issue with shortcode tempalte.
128
+
129
+ = 2.1.0 =
130
+ * Added the ability to override templates in a theme.
131
+ * Bug fix: fixed the issue on WordPress multisite when Event wasn't saving.
132
+ * Bug fix: fixed the issue when timeslots didn't show if Event is in the Draft status.
133
+
134
+ = 2.0.4 =
135
+ * Bug fix: fixed an issue with post template on search results page.
136
+
137
+ = 2.0.3 =
138
+ * Bug fix: fixed a link to create new column from event screen.
139
+ * Improved usernames in Event Head dropdown.
140
+
141
+ = 2.0.2 =
142
+ * Minor bugfixes and improvements.
143
+
144
+ = 2.0.1 =
145
+ * Bug fix: fixed an issue with template override.
146
+
147
+ = 2.0.0 =
148
+ * We improved compatibility with your theme styles in this update. If you still stick to a previous version, simply change the template mode option in the plugin settings.
149
+ * Added the ability to set font size for timetable shortcode so you can make your text bigger or smaller.
150
+
151
+ = 1.1.6 =
152
+ * Bug fix: fixed an issue with empty rows.
153
+
154
+ = 1.1.5 =
155
+ * Bug fix: fixed an issue with post view in search results.
156
+
157
+ = 1.1.4 =
158
+ * Improved compatibility with Polylang plugin.
159
+
160
+ = 1.1.3 =
161
+ * Fixed an issue with categories filter in widget.
162
+
163
+ = 1.1.2 =
164
+ * Fixed an issue with posts order.
165
+
166
+ = 1.1.0 =
167
+ * Improved events sorting.
168
+ * Minor bugfixes and improvements.
169
+
170
+ = 1.0.7 =
171
+ * Improved events and columns sorting by date.
172
+ * Comments section added to event.
173
+ * Minor bugfixes and improvements.
174
+
175
+ = 1.0.6 =
176
+ * Fixed an issue in column view.
177
+
178
+ = 1.0.5 =
179
+ * Improved compatibility with IE10+
180
+
181
+ = 1.0.4 =
182
+ * Minor bugfixes and improvements.
183
+
184
+ = 1.0.3 =
185
+ * Minor bugfixes and improvements.
classes/blocks/class-timetable-block.php CHANGED
@@ -1,219 +1,219 @@
1
- <?php
2
-
3
- namespace mp_timetable\classes\blocks;
4
-
5
- use Mp_Time_Table;
6
- use mp_timetable\plugin_core\classes\Core;
7
- use mp_timetable\plugin_core\classes\Shortcode;
8
-
9
- class Timetable_Block {
10
-
11
- public function __construct() {
12
-
13
- global $pagenow;
14
-
15
- $dependencies = array( 'wp-i18n', 'wp-element', 'wp-blocks', 'wp-components', 'wp-api', 'wp-api-fetch', 'mptt-functions', 'mptt-event-object' );
16
-
17
- if ( $pagenow !== 'widgets.php' ) {
18
- array_push( $dependencies, 'wp-editor' );
19
- } else {
20
- array_push( $dependencies, 'wp-edit-widgets' );
21
- }
22
-
23
- // block-js
24
- wp_register_script(
25
- 'mptt-blocks-js',
26
- Mp_Time_Table::get_plugin_url( 'media/js/blocks/dist/index.js' ),
27
- $dependencies,
28
- Core::get_instance()->get_version()
29
- );
30
-
31
- // style.css
32
- wp_register_style(
33
- 'mptt-blocks',
34
- Mp_Time_Table::get_plugin_url( 'media/css/style.css' ),
35
- array(),
36
- Core::get_instance()->get_version()
37
- );
38
-
39
- // block-editor.css
40
- wp_register_style(
41
- 'mptt-blocks-editor',
42
- Mp_Time_Table::get_plugin_url( 'media/css/block-editor.css' ),
43
- array('mptt-blocks'),
44
- Core::get_instance()->get_version()
45
- );
46
-
47
-
48
- // Internationalization
49
-
50
- /*
51
- * For custom translations
52
- * https://developer.wordpress.org/reference/functions/wp_set_script_translations/
53
- *
54
- * By default, minified files should still be excluded, and if you want to explicitly include them, you can do so by adding --include=*.min.js to the command.
55
- * https://github.com/wp-cli/i18n-command/pull/85
56
- *
57
- */
58
- //wp_set_script_translations( 'mptt-blocks-js', 'mp-timetable', Mp_Time_Table::get_plugin_path() . 'languages' );
59
-
60
-
61
- wp_set_script_translations( 'mptt-blocks-js', 'mp-timetable' );
62
-
63
- register_block_type(
64
- 'mp-timetable/timetable',
65
- array(
66
- 'attributes' => array(
67
- 'align' => array(
68
- 'type' => 'string',
69
- ),
70
- 'col' => array(
71
- 'type' => 'array',
72
- 'items' => [
73
- 'type' => 'integer',
74
- ],
75
- ),
76
- 'events' => array(
77
- 'type' => 'array',
78
- 'items' => [
79
- 'type' => 'integer',
80
- ],
81
- ),
82
- 'event_categ' => array(
83
- 'type' => 'array',
84
- 'items' => [
85
- 'type' => 'integer',
86
- ],
87
- ),
88
- 'increment' => array(
89
- 'type' => 'string',
90
- 'default' => '1',
91
- ),
92
- 'view' => array(
93
- 'type' => 'string',
94
- 'default' => 'dropdown_list',
95
- ),
96
- 'view_sort' => array(
97
- 'type' => 'string',
98
- 'default' => '',
99
- ),
100
- 'label' => array(
101
- 'type' => 'string',
102
- 'default' => __( "All Events", 'mp-timetable' ),
103
- ),
104
- 'hide_label' => array(
105
- 'type' => 'string',
106
- 'default' => '0',
107
- ),
108
- 'hide_hrs' => array(
109
- 'type' => 'string',
110
- 'default' => '0',
111
- ),
112
- 'hide_empty_rows' => array(
113
- 'type' => 'string',
114
- 'default' => '1',
115
- ),
116
- 'title' => array(
117
- 'type' => 'string',
118
- 'default' => '1',
119
- ),
120
- 'time' => array(
121
- 'type' => 'string',
122
- 'default' => '1',
123
- ),
124
- 'sub_title' => array(
125
- 'type' => 'string',
126
- 'default' => '0',
127
- ),
128
- 'description' => array(
129
- 'type' => 'string',
130
- 'default' => '1',
131
- ),
132
- 'user' => array(
133
- 'type' => 'string',
134
- 'default' => '0',
135
- ),
136
- 'group' => array(
137
- 'type' => 'string',
138
- 'default' => '0',
139
- ),
140
- 'disable_event_url' => array(
141
- 'type' => 'string',
142
- 'default' => '0',
143
- ),
144
- 'text_align' => array(
145
- 'type' => 'string',
146
- 'default' => 'center',
147
- ),
148
- 'id' => array(
149
- 'type' => 'string',
150
- ),
151
- 'row_height' => array(
152
- 'type' => 'string',
153
- 'default' => '45',
154
- ),
155
- 'font_size' => array(
156
- 'type' => 'string',
157
- ),
158
- 'responsive' => array(
159
- 'type' => 'string',
160
- 'default' => '1',
161
- ),
162
- 'text_align_vertical' => array(
163
- 'type' => 'string',
164
- 'default' => 'default',
165
- ),
166
- 'custom_class' => array(
167
- 'type' => 'string',
168
- ),
169
- 'table_layout' => array(
170
- 'type' => 'string'
171
- ),
172
- ),
173
- 'render_callback' => [ $this, 'render_timetable' ],
174
- 'editor_style' => 'mptt-blocks-editor',
175
- 'editor_script' => 'mptt-blocks-js',
176
- )
177
- );
178
- }
179
-
180
- private function show_shortcode($attributes) {
181
- foreach ($attributes as $key => $value) {
182
- // [] -> '1,2,3'
183
- if ( is_array($value) ) {
184
- $attributes[$key] = implode( ',', $value );
185
- }
186
- // 'sub_title' -> 'sub-title'
187
- if ($key == 'sub_title') {
188
- $attributes['sub-title'] = $attributes[$key];
189
- unset( $attributes[$key] );
190
- }
191
- }
192
-
193
- echo Shortcode::get_instance()->show_shortcode( $attributes );
194
- }
195
-
196
- public function render_timetable( $attributes ) {
197
-
198
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
199
-
200
- $block_name = 'wp-block-timetable';
201
-
202
- $class = $block_name;
203
- if ( isset( $attributes['align'] ) ) {
204
- $class .= ' align' . $attributes['align'];
205
- }
206
-
207
- ob_start();
208
- ?><div class="<?php echo esc_attr( $class ); ?>"><?php
209
-
210
- $this->show_shortcode($attributes);
211
-
212
- ?></div><?php
213
-
214
- $result = ob_get_clean();
215
-
216
- return $result;
217
- }
218
-
219
  }
1
+ <?php
2
+
3
+ namespace mp_timetable\classes\blocks;
4
+
5
+ use Mp_Time_Table;
6
+ use mp_timetable\plugin_core\classes\Core;
7
+ use mp_timetable\plugin_core\classes\Shortcode;
8
+
9
+ class Timetable_Block {
10
+
11
+ public function __construct() {
12
+
13
+ global $pagenow;
14
+
15
+ $dependencies = array( 'wp-i18n', 'wp-element', 'wp-blocks', 'wp-components', 'wp-api', 'wp-api-fetch', 'mptt-functions', 'mptt-event-object' );
16
+
17
+ if ( $pagenow !== 'widgets.php' ) {
18
+ array_push( $dependencies, 'wp-editor' );
19
+ } else {
20
+ array_push( $dependencies, 'wp-edit-widgets' );
21
+ }
22
+
23
+ // block-js
24
+ wp_register_script(
25
+ 'mptt-blocks-js',
26
+ Mp_Time_Table::get_plugin_url( 'media/js/blocks/dist/index.js' ),
27
+ $dependencies,
28
+ Core::get_instance()->get_version()
29
+ );
30
+
31
+ // style.css
32
+ wp_register_style(
33
+ 'mptt-blocks',
34
+ Mp_Time_Table::get_plugin_url( 'media/css/style.css' ),
35
+ array(),
36
+ Core::get_instance()->get_version()
37
+ );
38
+
39
+ // block-editor.css
40
+ wp_register_style(
41
+ 'mptt-blocks-editor',
42
+ Mp_Time_Table::get_plugin_url( 'media/css/block-editor.css' ),
43
+ array('mptt-blocks'),
44
+ Core::get_instance()->get_version()
45
+ );
46
+
47
+
48
+ // Internationalization
49
+
50
+ /*
51
+ * For custom translations
52
+ * https://developer.wordpress.org/reference/functions/wp_set_script_translations/
53
+ *
54
+ * By default, minified files should still be excluded, and if you want to explicitly include them, you can do so by adding --include=*.min.js to the command.
55
+ * https://github.com/wp-cli/i18n-command/pull/85
56
+ *
57
+ */
58
+ //wp_set_script_translations( 'mptt-blocks-js', 'mp-timetable', Mp_Time_Table::get_plugin_path() . 'languages' );
59
+
60
+
61
+ wp_set_script_translations( 'mptt-blocks-js', 'mp-timetable' );
62
+
63
+ register_block_type(
64
+ 'mp-timetable/timetable',
65
+ array(
66
+ 'attributes' => array(
67
+ 'align' => array(
68
+ 'type' => 'string',
69
+ ),
70
+ 'col' => array(
71
+ 'type' => 'array',
72
+ 'items' => [
73
+ 'type' => 'integer',
74
+ ],
75
+ ),
76
+ 'events' => array(
77
+ 'type' => 'array',
78
+ 'items' => [
79
+ 'type' => 'integer',
80
+ ],
81
+ ),
82
+ 'event_categ' => array(
83
+ 'type' => 'array',
84
+ 'items' => [
85
+ 'type' => 'integer',
86
+ ],
87
+ ),
88
+ 'increment' => array(
89
+ 'type' => 'string',
90
+ 'default' => '1',
91
+ ),
92
+ 'view' => array(
93
+ 'type' => 'string',
94
+ 'default' => 'dropdown_list',
95
+ ),
96
+ 'view_sort' => array(
97
+ 'type' => 'string',
98
+ 'default' => '',
99
+ ),
100
+ 'label' => array(
101
+ 'type' => 'string',
102
+ 'default' => __( "All Events", 'mp-timetable' ),
103
+ ),
104
+ 'hide_label' => array(
105
+ 'type' => 'string',
106
+ 'default' => '0',
107
+ ),
108
+ 'hide_hrs' => array(
109
+ 'type' => 'string',
110
+ 'default' => '0',
111
+ ),
112
+ 'hide_empty_rows' => array(
113
+ 'type' => 'string',
114
+ 'default' => '1',
115
+ ),
116
+ 'title' => array(
117
+ 'type' => 'string',
118
+ 'default' => '1',
119
+ ),
120
+ 'time' => array(
121
+ 'type' => 'string',
122
+ 'default' => '1',
123
+ ),
124
+ 'sub_title' => array(
125
+ 'type' => 'string',
126
+ 'default' => '0',
127
+ ),
128
+ 'description' => array(
129
+ 'type' => 'string',
130
+ 'default' => '1',
131
+ ),
132
+ 'user' => array(
133
+ 'type' => 'string',
134
+ 'default' => '0',
135
+ ),
136
+ 'group' => array(
137
+ 'type' => 'string',
138
+ 'default' => '0',
139
+ ),
140
+ 'disable_event_url' => array(
141
+ 'type' => 'string',
142
+ 'default' => '0',
143
+ ),
144
+ 'text_align' => array(
145
+ 'type' => 'string',
146
+ 'default' => 'center',
147
+ ),
148
+ 'id' => array(
149
+ 'type' => 'string',
150
+ ),
151
+ 'row_height' => array(
152
+ 'type' => 'string',
153
+ 'default' => '45',
154
+ ),
155
+ 'font_size' => array(
156
+ 'type' => 'string',
157
+ ),
158
+ 'responsive' => array(
159
+ 'type' => 'string',
160
+ 'default' => '1',
161
+ ),
162
+ 'text_align_vertical' => array(
163
+ 'type' => 'string',
164
+ 'default' => 'default',
165
+ ),
166
+ 'custom_class' => array(
167
+ 'type' => 'string',
168
+ ),
169
+ 'table_layout' => array(
170
+ 'type' => 'string'
171
+ ),
172
+ ),
173
+ 'render_callback' => [ $this, 'render_timetable' ],
174
+ 'editor_style' => 'mptt-blocks-editor',
175
+ 'editor_script' => 'mptt-blocks-js',
176
+ )
177
+ );
178
+ }
179
+
180
+ private function show_shortcode($attributes) {
181
+ foreach ($attributes as $key => $value) {
182
+ // [] -> '1,2,3'
183
+ if ( is_array($value) ) {
184
+ $attributes[$key] = implode( ',', $value );
185
+ }
186
+ // 'sub_title' -> 'sub-title'
187
+ if ($key == 'sub_title') {
188
+ $attributes['sub-title'] = $attributes[$key];
189
+ unset( $attributes[$key] );
190
+ }
191
+ }
192
+
193
+ echo Shortcode::get_instance()->show_shortcode( $attributes );
194
+ }
195
+
196
+ public function render_timetable( $attributes ) {
197
+
198
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
199
+
200
+ $block_name = 'wp-block-timetable';
201
+
202
+ $class = $block_name;
203
+ if ( isset( $attributes['align'] ) ) {
204
+ $class .= ' align' . $attributes['align'];
205
+ }
206
+
207
+ ob_start();
208
+ ?><div class="<?php echo esc_attr( $class ); ?>"><?php
209
+
210
+ $this->show_shortcode($attributes);
211
+
212
+ ?></div><?php
213
+
214
+ $result = ob_get_clean();
215
+
216
+ return $result;
217
+ }
218
+
219
  }
classes/class-controller.php CHANGED
@@ -1,40 +1,40 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- /**
6
- * Controller class
7
- */
8
- class Controller extends Core {
9
-
10
- protected static $instance;
11
-
12
- public static function get_instance() {
13
- if (null === self::$instance) {
14
- self::$instance = new self();
15
- }
16
- return self::$instance;
17
- }
18
-
19
- /**
20
- * Install controllers
21
- */
22
- public function install() {
23
- // include all core controllers
24
- Core::include_all(\Mp_Time_Table::get_plugin_part_path('classes/controllers'));
25
- }
26
-
27
- /**
28
- * Send json data
29
- *
30
- * @param array $data
31
- */
32
- public function send_json($data) {
33
- if (is_array($data) && isset($data['success']) && !$data['success']) {
34
- wp_send_json_error($data);
35
- } else {
36
- wp_send_json_success($data['data']);
37
- }
38
- }
39
-
40
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ /**
6
+ * Controller class
7
+ */
8
+ class Controller extends Core {
9
+
10
+ protected static $instance;
11
+
12
+ public static function get_instance() {
13
+ if (null === self::$instance) {
14
+ self::$instance = new self();
15
+ }
16
+ return self::$instance;
17
+ }
18
+
19
+ /**
20
+ * Install controllers
21
+ */
22
+ public function install() {
23
+ // include all core controllers
24
+ Core::include_all(\Mp_Time_Table::get_plugin_part_path('classes/controllers'));
25
+ }
26
+
27
+ /**
28
+ * Send json data
29
+ *
30
+ * @param array $data
31
+ */
32
+ public function send_json($data) {
33
+ if (is_array($data) && isset($data['success']) && !$data['success']) {
34
+ wp_send_json_error($data);
35
+ } else {
36
+ wp_send_json_success($data['data']);
37
+ }
38
+ }
39
+
40
+ }
classes/class-core.php CHANGED
@@ -1,802 +1,802 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- use Mp_Time_Table;
6
- use mp_timetable\classes\models\Column;
7
- use mp_timetable\classes\models\Events;
8
-
9
- /**
10
- * Class main state
11
- */
12
- class Core {
13
-
14
- protected static $instance;
15
-
16
- protected $version;
17
-
18
- /**
19
- * Current state
20
- */
21
- private $state;
22
-
23
- /**
24
- * Core constructor.
25
- */
26
- public function __construct() {
27
-
28
- $this->taxonomy_names = array(
29
- 'mp-event_category',
30
- 'mp-event_tag'
31
- );
32
- $this->post_types = array(
33
- 'mp-event',
34
- 'mp-column'
35
- );
36
- }
37
-
38
- /**
39
- * Check for ajax post
40
- * @return bool
41
- */
42
- static function is_ajax() {
43
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
44
- return true;
45
- } else {
46
- return false;
47
- }
48
- }
49
-
50
- /**
51
- * @return array
52
- */
53
- public function get_post_types() {
54
- return $this->post_types;
55
- }
56
-
57
- /**
58
- * @return array
59
- */
60
- public function get_taxonomy_names() {
61
- return $this->taxonomy_names;
62
- }
63
-
64
- /**
65
- * Init current plugin
66
- *
67
- * @param $name
68
- */
69
- public function init_plugin( $name ) {
70
-
71
- load_plugin_textdomain( 'mp-timetable', false, Mp_Time_Table::get_plugin_name() . '/languages/' );
72
-
73
- // include template for function
74
- Core::include_all( Mp_Time_Table::get_plugin_part_path( 'templates-functions' ) );
75
-
76
- // include plugin models files
77
- Model::get_instance()->install();
78
-
79
- // include plugin controllers files
80
- Controller::get_instance()->install();
81
-
82
- // include plugin Preprocessors files
83
- Preprocessor::install();
84
-
85
- // include plugin modules
86
- Module::install();
87
-
88
- // install state
89
- $this->install_state( $name );
90
-
91
- // init all hooks
92
- Hooks::get_instance()->install_hooks();
93
- Hooks::get_instance()->register_template_action();
94
- }
95
-
96
- /**
97
- * Include all files from folder
98
- *
99
- * @param string $folder
100
- * @param boolean $inFolder
101
- */
102
- static function include_all( $folder, $inFolder = true ) {
103
- if ( file_exists( $folder ) ) {
104
- $includeArr = scandir( $folder );
105
- foreach ( $includeArr as $include ) {
106
- if ( ! is_dir( $folder . "/" . $include ) ) {
107
- include_once( $folder . "/" . $include );
108
- } else {
109
- if ( $include != "." && $include != ".." && $inFolder ) {
110
- self::include_all( $folder . "/" . $include );
111
- }
112
- }
113
- }
114
- }
115
- }
116
-
117
- /**
118
- * Install current state
119
- *
120
- * @param $name
121
- */
122
- public function install_state( $name ) {
123
- // include plugin state
124
- Core::get_instance()->set_state( new State_Factory( $name ) );
125
- }
126
-
127
- /**
128
- * @return Core
129
- */
130
- public static function get_instance() {
131
- if ( null === self::$instance ) {
132
- self::$instance = new self();
133
- }
134
-
135
- return self::$instance;
136
- }
137
-
138
- /**
139
- * Include pseudo template
140
- *
141
- * @param $template
142
- *
143
- * @return string
144
- */
145
- public function modify_single_template( $template ) {
146
-
147
- global $post;
148
-
149
- if ( ! empty( $post ) && in_array( $post->post_type, $this->post_types ) ) {
150
- add_action( 'loop_start', array( $this, 'setup_pseudo_template' ) );
151
- }
152
-
153
- return $template;
154
- }
155
-
156
- /**
157
- * Setup pseudo template
158
- *
159
- * @param object $query
160
- */
161
- public function setup_pseudo_template( $query ) {
162
-
163
- global $post;
164
-
165
- if ( $query->is_main_query() ) {
166
- if ( ! empty( $post ) && in_array( $post->post_type, $this->post_types ) ) {
167
- add_filter( 'the_content', array( $this, 'append_post_meta' ) );
168
- }
169
- remove_action( 'loop_start', array( $this, 'setup_pseudo_template' ) );
170
- }
171
- }
172
-
173
- /**
174
- * Append post meta
175
- *
176
- * @param $content
177
- *
178
- * @return string
179
- */
180
- public function append_post_meta( $content ) {
181
- // run only once
182
- remove_filter( 'the_content', array( $this, 'append_post_meta' ) );
183
-
184
- global $post;
185
-
186
- ob_start();
187
- switch ( $post->post_type ) {
188
- case 'mp-event':
189
- Events::get_instance()->render_event_metas();
190
- break;
191
- case 'mp-column':
192
- Column::get_instance()->render_column_metas();
193
- break;
194
- }
195
- $append = ob_get_clean();
196
- $content .= $append;
197
-
198
- return $content;
199
- }
200
-
201
- /**
202
- * Get model instace
203
- *
204
- * @param bool|false $type
205
- *
206
- * @return bool|mixed
207
- */
208
- public function get( $type = false ) {
209
- $state = false;
210
- if ( $type ) {
211
- $state = $this->get_model( $type );
212
- }
213
-
214
- return $state;
215
- }
216
-
217
- /**
218
- * Check and return current state
219
- *
220
- * @param string $type
221
- *
222
- * @return boolean
223
- */
224
- public function get_model( $type = null ) {
225
- return Core::get_instance()->get_state()->get_model( $type );
226
- }
227
-
228
- /**
229
- * Get State
230
- * @return bool
231
- */
232
- public function get_state() {
233
- if ( $this->state ) {
234
- return $this->state;
235
- } else {
236
- return false;
237
- }
238
- }
239
-
240
- /**
241
- * Set state
242
- *
243
- * @param $state
244
- */
245
- public function set_state( $state ) {
246
- $this->state = $state;
247
- }
248
-
249
- /**
250
- * Get version
251
- * @return mixed
252
- */
253
- public function get_version() {
254
- if ( empty( $this->version ) ) {
255
- $this->init_plugin_version();
256
- }
257
-
258
- return $this->version;
259
- }
260
-
261
- /**
262
- * Init plugin version
263
- */
264
- public function init_plugin_version() {
265
-
266
- $filePath = Mp_Time_Table::get_plugin_path() . Mp_Time_Table::get_plugin_name() . '.php';
267
-
268
- if ( ! function_exists( 'get_plugin_data' ) ) {
269
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
270
- }
271
-
272
- $pluginObject = get_plugin_data( $filePath );
273
- $this->version = $pluginObject[ 'Version' ];
274
- }
275
-
276
- /**
277
- * Get controller
278
- *
279
- * @param $type
280
- *
281
- * @return mixed
282
- */
283
- public function get_controller( $type ) {
284
- return Core::get_instance()->get_state()->get_controller( $type );
285
- }
286
-
287
- /**
288
- * Get view
289
- *
290
- * @return View
291
- */
292
- public function get_view() {
293
- return View::get_instance();
294
- }
295
-
296
- /**
297
- * Get preprocessor
298
- *
299
- * @param $type
300
- *
301
- * @return mixed
302
- */
303
- public function get_preprocessor( $type = null ) {
304
- return Core::get_instance()->get_state()->get_preprocessor( $type );
305
- }
306
-
307
- /**
308
- * Route plugin url
309
- */
310
- public function wp_ajax_route_url() {
311
-
312
- $controller = isset( $_REQUEST[ "controller" ] ) ? sanitize_text_field( $_REQUEST[ "controller" ] ) : null;
313
- $action = isset( $_REQUEST[ "mptt_action" ] ) ? sanitize_text_field( $_REQUEST[ "mptt_action" ] ) : null;
314
-
315
- if ( ! empty( $action ) && current_user_can('edit_posts') ) {
316
- // call controller
317
- Preprocessor::get_instance()->call_controller( $action, $controller );
318
-
319
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
320
- wp_die();
321
- } else {
322
- die();
323
- }
324
- }
325
- }
326
-
327
- /**
328
- * Register taxonomies
329
- */
330
- public function register_all_taxonomies() {
331
-
332
- $permalinks = Core::get_instance()->get_permalink_structure();
333
-
334
- do_action( 'mptt_before_register_taxonomies' );
335
-
336
- $event_category_labels = array(
337
- 'name' => __( 'Event categories', 'mp-timetable' ),
338
- 'singular_name' => __( 'Event category', 'mp-timetable' ),
339
- 'add_new' => __( 'Add New Event category', 'mp-timetable' ),
340
- 'add_new_item' => __( 'Add New Event category', 'mp-timetable' ),
341
- 'edit_item' => __( 'Edit Event category', 'mp-timetable' ),
342
- 'new_item' => __( 'New Event category', 'mp-timetable' ),
343
- 'all_items' => __( 'All Event categories', 'mp-timetable' ),
344
- 'view_item' => __( 'View Event category', 'mp-timetable' ),
345
- 'search_items' => __( 'Search Event category', 'mp-timetable' ),
346
- 'not_found' => __( 'No Event categories found', 'mp-timetable' ),
347
- 'not_found_in_trash' => __( 'No Event categories found in Trash', 'mp-timetable' ),
348
- 'menu_name' => __( 'Event categories', 'mp-timetable' )
349
- );
350
-
351
- $event_category_args = array(
352
- 'label' => __( 'Event categories', 'mp-timetable' ),
353
- 'labels' => $event_category_labels,
354
- 'show_in_rest' => true,
355
- 'public' => true,
356
- 'show_in_nav_menus' => true,
357
- 'show_ui' => true,
358
- 'show_in_menu' => false,
359
- 'show_tagcloud' => true,
360
- 'hierarchical' => true,
361
- 'update_count_callback' => '',
362
- 'rewrite' => array(
363
- 'slug' => $permalinks['event_category_base'], //'timetable/category'
364
- 'with_front' => false,
365
- 'hierarchical' => true
366
- ),
367
- 'capabilities' => array(),
368
- 'meta_box_cb' => null,
369
- 'show_admin_column' => false,
370
- '_builtin' => false,
371
- 'show_in_quick_edit' => null,
372
- );
373
-
374
- register_taxonomy(
375
- 'mp-event_category',
376
- apply_filters( 'mptt_taxonomy_objects_event_category', array( 'mp-event' ) ),
377
- apply_filters( 'mptt_taxonomy_args_event_category', $event_category_args)
378
- );
379
-
380
- $event_tag_labels = array(
381
- 'name' => __( 'Event tags', 'mp-timetable' ),
382
- 'singular_name' => __( 'Event tag', 'mp-timetable' ),
383
- 'add_new' => __( 'Add New Event tag', 'mp-timetable' ),
384
- 'add_new_item' => __( 'Add New Event tag', 'mp-timetable' ),
385
- 'edit_item' => __( 'Edit Event tag', 'mp-timetable' ),
386
- 'new_item' => __( 'New Event tag', 'mp-timetable' ),
387
- 'all_items' => __( 'All Event tags', 'mp-timetable' ),
388
- 'view_item' => __( 'View Event tag', 'mp-timetable' ),
389
- 'search_items' => __( 'Search Event tag', 'mp-timetable' ),
390
- 'not_found' => __( 'No Event tags found', 'mp-timetable' ),
391
- 'not_found_in_trash' => __( 'No Event tags found in Trash', 'mp-timetable' ),
392
- 'menu_name' => __( 'Event tags', 'mp-timetable' )
393
- );
394
-
395
- $event_tag_args = array(
396
- 'label' => __( 'Event tags', 'mp-timetable' ),
397
- 'labels' => $event_tag_labels,
398
- 'show_in_rest' => true,
399
- 'public' => true,
400
- 'show_in_nav_menus' => true,
401
- 'show_ui' => true,
402
- 'show_in_menu' => false,
403
- 'show_tagcloud' => true,
404
- 'hierarchical' => false,
405
- 'update_count_callback' => '',
406
- 'rewrite' => array(
407
- 'slug' => $permalinks['event_tag_base'], //'timetable/tag'
408
- 'with_front' => false,
409
- 'hierarchical' => true
410
- ),
411
- 'capabilities' => array(),
412
- 'meta_box_cb' => null,
413
- 'show_admin_column' => false,
414
- '_builtin' => false,
415
- 'show_in_quick_edit' => null,
416
- );
417
-
418
- register_taxonomy(
419
- 'mp-event_tag',
420
- apply_filters( 'mptt_taxonomy_objects_event_tag', array( 'mp-event' ) ),
421
- apply_filters( 'mptt_taxonomy_args_event_tag', $event_tag_args)
422
- );
423
-
424
- do_action( 'mptt_after_register_taxonomies' );
425
- }
426
-
427
- /**
428
- * Register custom post type
429
- */
430
- public function register_all_post_type() {
431
-
432
- $permalinks = Core::get_instance()->get_permalink_structure();
433
-
434
- do_action( 'mptt_before_register_post_types' );
435
-
436
- register_post_type(
437
- 'mp-event',
438
- apply_filters(
439
- 'mptt_register_post_type_event',
440
- array(
441
- 'labels' => array(
442
- 'name' => __( 'Events', 'mp-timetable' ),
443
- 'singular_name' => __( 'Event', 'mp-timetable' ),
444
- 'add_new' => __( 'Add New Event', 'mp-timetable' ),
445
- 'add_new_item' => __( 'Add New Event', 'mp-timetable' ),
446
- 'edit_item' => __( 'Edit Event', 'mp-timetable' ),
447
- 'new_item' => __( 'New Event', 'mp-timetable' ),
448
- 'all_items' => __( 'All Events', 'mp-timetable' ),
449
- 'view_item' => __( 'View Event', 'mp-timetable' ),
450
- 'search_items' => __( 'Search Event', 'mp-timetable' ),
451
- 'not_found' => __( 'No Events found', 'mp-timetable' ),
452
- 'not_found_in_trash' => __( 'No Events found in Trash', 'mp-timetable' ),
453
- 'menu_name' => __( 'Events', 'mp-timetable' )
454
- ),
455
- 'public' => true,
456
- 'show_in_rest' => true,
457
- 'show_ui' => true,
458
- 'show_in_menu' => false,
459
- 'show_in_nav_menus' => true,
460
- 'capability_type' => 'post',
461
- 'menu_position' => 21,
462
- 'hierarchical' => false,
463
- 'has_archive' => true,
464
- 'rewrite' => array(
465
- 'slug' => $permalinks['event_base'], //'timetable/event'
466
- 'with_front' => false,
467
- 'hierarchical' => true
468
- ),
469
- 'supports' => array( 'title', 'editor', 'comments', 'excerpt', 'author', 'thumbnail', 'page-attributes' ),
470
- 'show_in_admin_bar' => true
471
- )
472
- )
473
- );
474
-
475
- register_post_type(
476
- 'mp-column',
477
- apply_filters(
478
- 'mptt_register_post_type_column',
479
- array(
480
- 'labels' => array(
481
- 'name' => __( 'Columns', 'mp-timetable' ),
482
- 'singular_name' => __( 'Column', 'mp-timetable' ),
483
- 'add_new' => __( 'Add New Column', 'mp-timetable' ),
484
- 'add_new_item' => __( 'Add New Column', 'mp-timetable' ),
485
- 'edit_item' => __( 'Edit Column', 'mp-timetable' ),
486
- 'new_item' => __( 'New Column', 'mp-timetable' ),
487
- 'all_items' => __( 'All Columns', 'mp-timetable' ),
488
- 'view_item' => __( 'View Column', 'mp-timetable' ),
489
- 'search_items' => __( 'Search Column', 'mp-timetable' ),
490
- 'not_found' => __( 'No Columns found', 'mp-timetable' ),
491
- 'not_found_in_trash' => __( 'No Columns found in Trash', 'mp-timetable' ),
492
- 'menu_name' => __( 'Columns', 'mp-timetable' )
493
- ),
494
- 'public' => true,
495
- 'show_in_rest' => true,
496
- 'show_ui' => true,
497
- 'show_in_menu' => false,
498
- 'show_in_nav_menus' => true,
499
- 'capability_type' => 'post',
500
- 'menu_position' => 21,
501
- 'hierarchical' => false,
502
- 'has_archive' => true,
503
- 'rewrite' => array(
504
- 'slug' => $permalinks['column_base'], //'timetable/column'
505
- 'with_front' => false,
506
- 'hierarchical' => true
507
- ),
508
- 'supports' => array( 'title', 'editor', 'page-attributes' ),
509
- 'show_in_admin_bar' => true
510
- )
511
- )
512
- );
513
-
514
- do_action( 'mptt_after_register_post_types' );
515
-
516
- }
517
-
518
- /**
519
- * Create Plugin table if not exists
520
- */
521
- public function create_table() {
522
-
523
- global $wpdb;
524
-
525
- $charset_collate = $wpdb->get_charset_collate();
526
-
527
- $table_name = Mp_Time_Table::get_datatable();
528
-
529
- $sql = "CREATE TABLE IF NOT EXISTS $table_name (
530
- `id` int(11) NOT NULL AUTO_INCREMENT,
531
- `column_id` int(11) NOT NULL,
532
- `event_id` int(11) NOT NULL,
533
- `event_start` time NOT NULL,
534
- `event_end` time NOT NULL,
535
- `user_id` int(11) NOT NULL,
536
- `description` text NOT NULL,
537
- PRIMARY KEY (`id`),
538
- UNIQUE KEY `id` (`id`)
539
- ) $charset_collate";
540
-
541
- require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
542
- dbDelta( $sql );
543
- }
544
-
545
- /**
546
- * Hook admin_enqueue_scripts
547
- */
548
- public function admin_enqueue_scripts() {
549
- global $current_screen;
550
- $this->current_screen( $current_screen );
551
- }
552
-
553
- /**
554
- * Load script by current screen
555
- *
556
- * @param \WP_Screen $current_screen
557
- */
558
- public function current_screen( \WP_Screen $current_screen = null ) {
559
- wp_register_script( 'mptt-event-object', Mp_Time_Table::get_plugin_url( 'media/js/events/event' . $this->get_prefix() . '.js' ), array( 'jquery' ), $this->version );
560
- wp_localize_script(
561
- 'mptt-event-object',
562
- 'MPTT',
563
- array(
564
- 'table_class' => apply_filters( 'mptt_shortcode_static_table_class', 'mptt-shortcode-table' ),
565
- 'timeslot_delete_nonce' => wp_create_nonce( 'timeslot_delete_nonce' ),
566
- 'timeslot_update_nonce' => wp_create_nonce( 'timeslot_update_nonce' ),
567
- )
568
- );
569
-
570
- wp_enqueue_script( 'underscore' );
571
-
572
- wp_enqueue_style( 'mptt-admin-style', Mp_Time_Table::get_plugin_url( 'media/css/admin.css' ), array(), $this->version );
573
-
574
- wp_enqueue_script( 'mptt-functions', Mp_Time_Table::get_plugin_url( 'media/js/mptt-functions' . $this->get_prefix() . '.js' ), array(), $this->version );
575
-
576
- if ( ! empty( $_GET[ 'page' ] ) ) {
577
- switch ( sanitize_key( $_GET[ 'page' ] ) ) {
578
- case 'mptt-settings' :
579
- case 'mptt-import' :
580
- case 'mptt-help' :
581
- wp_register_script( 'mptt-option-ajax', Mp_Time_Table::get_plugin_url( 'media/js/mptt-option-ajax' . $this->get_prefix() . '.js' ), array( 'jquery' ), $this->version );
582
- wp_enqueue_script( 'mptt-option-ajax' );
583
- wp_localize_script(
584
- 'mptt-option-ajax',
585
- 'MPTT',
586
- array(
587
- 'ajax_url' => admin_url( 'admin-ajax.php' ),
588
- 'nonce' => wp_create_nonce( 'mptt-install-plugins' ),
589
- 'status_download' => esc_html__( 'Install Plugin', 'mp-timetable' ),
590
- 'status_activated' => esc_html__( 'Activated', 'mp-timetable' ),
591
- 'status_active' => esc_html__( 'Active', 'mp-timetable' ),
592
- 'status_inactive' => esc_html__( 'Inactive', 'mp-timetable' ),
593
- 'status_loading' => esc_html__( 'Loading...', 'mp-timetable' ),
594
- 'status_activate' => esc_html__( 'Activate', 'mp-timetable' ),
595
- )
596
- );
597
- break;
598
- default :
599
- break;
600
- }
601
- }
602
-
603
- if ( ! empty( $current_screen ) ) {
604
- switch ( $current_screen->id ) {
605
- case 'mp-event':
606
- wp_enqueue_script( 'spectrum', Mp_Time_Table::get_plugin_url( 'media/js/lib/spectrum' . $this->get_prefix() . '.js' ), array( 'jquery' ), '1.8.0' );
607
- wp_enqueue_script( 'mptt-event-object' );
608
- wp_enqueue_script( 'jquery-ui-timepicker', Mp_Time_Table::get_plugin_url( 'media/js/lib/jquery.ui.timepicker' . $this->get_prefix() . '.js' ), '0.3.3' );
609
-
610
- wp_enqueue_style( 'jquery-ui-core', Mp_Time_Table::get_plugin_url( 'media/css/jquery-ui-1.10.0.custom.min.css' ), array(), '1.10.0' );
611
- wp_enqueue_style( 'spectrum', Mp_Time_Table::get_plugin_url( 'media/css/spectrum.css' ), array(), '1.8.0' );
612
- wp_enqueue_style( 'jquery-ui-timepicker', Mp_Time_Table::get_plugin_url( 'media/css/jquery.ui.timepicker.css' ), array(), '0.3.3' );
613
- break;
614
-
615
- case 'mp-column':
616
- wp_enqueue_script( 'jquery-ui-datepicker' );
617
- wp_enqueue_script( 'mptt-event-object' );
618
-
619
- wp_enqueue_style( 'jquery-ui-core', Mp_Time_Table::get_plugin_url( 'media/css/jquery-ui-1.10.0.custom.min.css' ), array(), '1.10.0' );
620
- break;
621
-
622
- case 'customize':
623
- case 'widgets':
624
- wp_enqueue_script( 'spectrum', Mp_Time_Table::get_plugin_url( 'media/js/lib/spectrum' . $this->get_prefix() . '.js' ), array( 'jquery' ), '1.8.0' );
625
- wp_enqueue_script( 'mptt-event-object' );
626
-
627
- wp_enqueue_style( 'jquery-ui-core', Mp_Time_Table::get_plugin_url( 'media/css/jquery-ui-1.10.0.custom.min.css' ), array(), '1.10.0' );
628
- wp_enqueue_style( 'spectrum', Mp_Time_Table::get_plugin_url( 'media/css/spectrum.css' ), array(), '1.8.0' );
629
- break;
630
- }
631
-
632
- switch ( $current_screen->base ) {
633
- case 'post':
634
- case 'page':
635
- wp_enqueue_script( 'jquery-ui-tabs' );
636
- wp_enqueue_script( 'jBox', Mp_Time_Table::get_plugin_url( 'media/js/lib/jBox' . $this->get_prefix() . '.js' ), array( 'jquery' ), '0.2.1' );
637
-
638
- wp_enqueue_style( 'jBox', Mp_Time_Table::get_plugin_url( 'media/css/jbox/jBox.css' ), array(), '1.8.0' );
639
- break;
640
-
641
- case 'options-permalink':
642
- if ( apply_filters('mptt_permalinks_enabled', true) ) {
643
- $permalinks = new Permalinks();
644
- }
645
- break;
646
-
647
- default:
648
- break;
649
- }
650
- }
651
- }
652
-
653
- public function wp_ajax_install_plugin_ajax() {
654
-
655
- $action = isset( $_REQUEST[ "action" ] ) ? sanitize_text_field( $_REQUEST[ "action" ] ) : null;
656
-
657
- if ( $action && $action === 'install_plugin_ajax' ) {
658
-
659
- if ( empty( $_POST[ 'status' ] ) ) {
660
- wp_send_json_error();
661
- }
662
-
663
- $status = sanitize_key( $_POST[ 'status' ] );
664
-
665
- require_once Mp_Time_Table::get_plugin_path() . 'classes/class-offer.php';
666
- $plugins_offer = new Plugins_Offer();
667
-
668
- switch ( $status ) {
669
- case 'activate' :
670
- $plugins_offer->activatePluginAjax();
671
- break;
672
- case 'install' :
673
- $plugins_offer->installPluginAjax();
674
- break;
675
- default :
676
- break;
677
- }
678
-
679
- wp_send_json_success();
680
- }
681
- }
682
-
683
- /**
684
- * Get prefix
685
- *
686
- * @return string
687
- */
688
- public function get_prefix() {
689
- global $is_IE;
690
-
691
- $prefix = ! MP_TT_DEBUG ? '.min' : '';
692
-
693
- if ($is_IE){
694
- $prefix = '';
695
- }
696
-
697
- return $prefix;
698
- }
699
-
700
- /**
701
- * Hook wp_enqueue_scripts
702
- */
703
- public function wp_enqueue_scripts() {
704
- if ( ! empty( $_GET[ 'motopress-ce' ] ) ) {
705
- $this->add_plugin_js( 'shortcode' );
706
- }
707
- }
708
-
709
- /**
710
- * Hook elementor_enqueue_scripts
711
- */
712
- public function elementor_enqueue_scripts() {
713
- $this->add_plugin_js( 'elementor-widget' );
714
- }
715
-
716
- /**
717
- * Add plugin js
718
- *
719
- * @param bool $type
720
- */
721
- public function add_plugin_js( $type = false ) {
722
- wp_register_script( 'mptt-event-object', Mp_Time_Table::get_plugin_url( 'media/js/events/event' . $this->get_prefix() . '.js' ), array( 'jquery', 'mptt-functions' ), $this->version );
723
- wp_localize_script(
724
- 'mptt-event-object',
725
- 'MPTT',
726
- array( 'table_class' => apply_filters( 'mptt_shortcode_static_table_class', 'mptt-shortcode-table' ) )
727
- );
728
-
729
- switch ( $type ) {
730
- case 'shortcode':
731
- case 'widget':
732
- wp_enqueue_script( 'underscore' );
733
- wp_enqueue_script( 'mptt-functions', Mp_Time_Table::get_plugin_url( 'media/js/mptt-functions' . $this->get_prefix() . '.js' ), array( 'jquery' ), $this->version );
734
- wp_enqueue_script( 'mptt-event-object' );
735
- break;
736
- case 'elementor-widget':
737
- wp_enqueue_script( 'underscore' );
738
- wp_enqueue_script( 'mptt-functions', Mp_Time_Table::get_plugin_url( 'media/js/mptt-functions' . $this->get_prefix() . '.js' ), array( 'jquery' ), $this->version );
739
- wp_enqueue_script( 'mptt-event-object' );
740
- wp_enqueue_script(
741
- 'mptt-editor-panel-js',
742
- Mp_Time_Table::get_plugin_url( 'media/js/mptt-elementor-editor' . $this->get_prefix() . '.js' ),
743
- array( 'jquery', 'mptt-functions', 'mptt-event-object' ),
744
- $this->version
745
- );
746
- break;
747
- }
748
- }
749
-
750
- /**
751
- * Add plugin css
752
- */
753
- public function add_plugin_css() {
754
- wp_enqueue_style( 'mptt-style', Mp_Time_Table::get_plugin_url( 'media/css/style.css' ), array(), $this->version );
755
- }
756
-
757
- /**
758
- * Fix fatal error for earlier WP versions
759
- *
760
- * @return bool
761
- */
762
- public function is_embed() {
763
- global $wp_version;
764
-
765
- if ( ! function_exists( 'is_embed' ) ) {
766
- return false;
767
- }
768
-
769
- if ( version_compare( $wp_version, '4.4', '<' ) ) {
770
- if ( ! function_exists( 'is_embed' ) ) {
771
- return false;
772
- }
773
- }
774
-
775
- return is_embed();
776
- }
777
-
778
- /**
779
- * Get permalink settings
780
- *
781
- * @return array
782
- */
783
- public function get_permalink_structure() {
784
-
785
- $saved_permalinks = (array) get_option( 'mp_timetable_permalinks', array() );
786
-
787
- $permalinks = wp_parse_args(
788
- array_filter( $saved_permalinks ), array(
789
- 'column_base' => 'timetable/column',
790
- 'event_base' => 'timetable/event',
791
- 'event_category_base' => 'timetable/category',
792
- 'event_tag_base' => 'timetable/tag',
793
- )
794
- );
795
-
796
- if ( $saved_permalinks !== $permalinks ) {
797
- update_option( 'mp_timetable_permalinks', $permalinks );
798
- }
799
-
800
- return $permalinks;
801
- }
802
  }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ use Mp_Time_Table;
6
+ use mp_timetable\classes\models\Column;
7
+ use mp_timetable\classes\models\Events;
8
+
9
+ /**
10
+ * Class main state
11
+ */
12
+ class Core {
13
+
14
+ protected static $instance;
15
+
16
+ protected $version;
17
+
18
+ /**
19
+ * Current state
20
+ */
21
+ private $state;
22
+
23
+ /**
24
+ * Core constructor.
25
+ */
26
+ public function __construct() {
27
+
28
+ $this->taxonomy_names = array(
29
+ 'mp-event_category',
30
+ 'mp-event_tag'
31
+ );
32
+ $this->post_types = array(
33
+ 'mp-event',
34
+ 'mp-column'
35
+ );
36
+ }
37
+
38
+ /**
39
+ * Check for ajax post
40
+ * @return bool
41
+ */
42
+ static function is_ajax() {
43
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
44
+ return true;
45
+ } else {
46
+ return false;
47
+ }
48
+ }
49
+
50
+ /**
51
+ * @return array
52
+ */
53
+ public function get_post_types() {
54
+ return $this->post_types;
55
+ }
56
+
57
+ /**
58
+ * @return array
59
+ */
60
+ public function get_taxonomy_names() {
61
+ return $this->taxonomy_names;
62
+ }
63
+
64
+ /**
65
+ * Init current plugin
66
+ *
67
+ * @param $name
68
+ */
69
+ public function init_plugin( $name ) {
70
+
71
+ load_plugin_textdomain( 'mp-timetable', false, Mp_Time_Table::get_plugin_name() . '/languages/' );
72
+
73
+ // include template for function
74
+ Core::include_all( Mp_Time_Table::get_plugin_part_path( 'templates-functions' ) );
75
+
76
+ // include plugin models files
77
+ Model::get_instance()->install();
78
+
79
+ // include plugin controllers files
80
+ Controller::get_instance()->install();
81
+
82
+ // include plugin Preprocessors files
83
+ Preprocessor::install();
84
+
85
+ // include plugin modules
86
+ Module::install();
87
+
88
+ // install state
89
+ $this->install_state( $name );
90
+
91
+ // init all hooks
92
+ Hooks::get_instance()->install_hooks();
93
+ Hooks::get_instance()->register_template_action();
94
+ }
95
+
96
+ /**
97
+ * Include all files from folder
98
+ *
99
+ * @param string $folder
100
+ * @param boolean $inFolder
101
+ */
102
+ static function include_all( $folder, $inFolder = true ) {
103
+ if ( file_exists( $folder ) ) {
104
+ $includeArr = scandir( $folder );
105
+ foreach ( $includeArr as $include ) {
106
+ if ( ! is_dir( $folder . "/" . $include ) ) {
107
+ include_once( $folder . "/" . $include );
108
+ } else {
109
+ if ( $include != "." && $include != ".." && $inFolder ) {
110
+ self::include_all( $folder . "/" . $include );
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Install current state
119
+ *
120
+ * @param $name
121
+ */
122
+ public function install_state( $name ) {
123
+ // include plugin state
124
+ Core::get_instance()->set_state( new State_Factory( $name ) );
125
+ }
126
+
127
+ /**
128
+ * @return Core
129
+ */
130
+ public static function get_instance() {
131
+ if ( null === self::$instance ) {
132
+ self::$instance = new self();
133
+ }
134
+
135
+ return self::$instance;
136
+ }
137
+
138
+ /**
139
+ * Include pseudo template
140
+ *
141
+ * @param $template
142
+ *
143
+ * @return string
144
+ */
145
+ public function modify_single_template( $template ) {
146
+
147
+ global $post;
148
+
149
+ if ( ! empty( $post ) && in_array( $post->post_type, $this->post_types ) ) {
150
+ add_action( 'loop_start', array( $this, 'setup_pseudo_template' ) );
151
+ }
152
+
153
+ return $template;
154
+ }
155
+
156
+ /**
157
+ * Setup pseudo template
158
+ *
159
+ * @param object $query
160
+ */
161
+ public function setup_pseudo_template( $query ) {
162
+
163
+ global $post;
164
+
165
+ if ( $query->is_main_query() ) {
166
+ if ( ! empty( $post ) && in_array( $post->post_type, $this->post_types ) ) {
167
+ add_filter( 'the_content', array( $this, 'append_post_meta' ) );
168
+ }
169
+ remove_action( 'loop_start', array( $this, 'setup_pseudo_template' ) );
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Append post meta
175
+ *
176
+ * @param $content
177
+ *
178
+ * @return string
179
+ */
180
+ public function append_post_meta( $content ) {
181
+ // run only once
182
+ remove_filter( 'the_content', array( $this, 'append_post_meta' ) );
183
+
184
+ global $post;
185
+
186
+ ob_start();
187
+ switch ( $post->post_type ) {
188
+ case 'mp-event':
189
+ Events::get_instance()->render_event_metas();
190
+ break;
191
+ case 'mp-column':
192
+ Column::get_instance()->render_column_metas();
193
+ break;
194
+ }
195
+ $append = ob_get_clean();
196
+ $content .= $append;
197
+
198
+ return $content;
199
+ }
200
+
201
+ /**
202
+ * Get model instace
203
+ *
204
+ * @param bool|false $type
205
+ *
206
+ * @return bool|mixed
207
+ */
208
+ public function get( $type = false ) {
209
+ $state = false;
210
+ if ( $type ) {
211
+ $state = $this->get_model( $type );
212
+ }
213
+
214
+ return $state;
215
+ }
216
+
217
+ /**
218
+ * Check and return current state
219
+ *
220
+ * @param string $type
221
+ *
222
+ * @return boolean
223
+ */
224
+ public function get_model( $type = null ) {
225
+ return Core::get_instance()->get_state()->get_model( $type );
226
+ }
227
+
228
+ /**
229
+ * Get State
230
+ * @return bool
231
+ */
232
+ public function get_state() {
233
+ if ( $this->state ) {
234
+ return $this->state;
235
+ } else {
236
+ return false;
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Set state
242
+ *
243
+ * @param $state
244
+ */
245
+ public function set_state( $state ) {
246
+ $this->state = $state;
247
+ }
248
+
249
+ /**
250
+ * Get version
251
+ * @return mixed
252
+ */
253
+ public function get_version() {
254
+ if ( empty( $this->version ) ) {
255
+ $this->init_plugin_version();
256
+ }
257
+
258
+ return $this->version;
259
+ }
260
+
261
+ /**
262
+ * Init plugin version
263
+ */
264
+ public function init_plugin_version() {
265
+
266
+ $filePath = Mp_Time_Table::get_plugin_path() . Mp_Time_Table::get_plugin_name() . '.php';
267
+
268
+ if ( ! function_exists( 'get_plugin_data' ) ) {
269
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
270
+ }
271
+
272
+ $pluginObject = get_plugin_data( $filePath );
273
+ $this->version = $pluginObject[ 'Version' ];
274
+ }
275
+
276
+ /**
277
+ * Get controller
278
+ *
279
+ * @param $type
280
+ *
281
+ * @return mixed
282
+ */
283
+ public function get_controller( $type ) {
284
+ return Core::get_instance()->get_state()->get_controller( $type );
285
+ }
286
+
287
+ /**
288
+ * Get view
289
+ *
290
+ * @return View
291
+ */
292
+ public function get_view() {
293
+ return View::get_instance();
294
+ }
295
+
296
+ /**
297
+ * Get preprocessor
298
+ *
299
+ * @param $type
300
+ *
301
+ * @return mixed
302
+ */
303
+ public function get_preprocessor( $type = null ) {
304
+ return Core::get_instance()->get_state()->get_preprocessor( $type );
305
+ }
306
+
307
+ /**
308
+ * Route plugin url
309
+ */
310
+ public function wp_ajax_route_url() {
311
+
312
+ $controller = isset( $_REQUEST[ "controller" ] ) ? sanitize_text_field( $_REQUEST[ "controller" ] ) : null;
313
+ $action = isset( $_REQUEST[ "mptt_action" ] ) ? sanitize_text_field( $_REQUEST[ "mptt_action" ] ) : null;
314
+
315
+ if ( ! empty( $action ) && current_user_can('edit_posts') ) {
316
+ // call controller
317
+ Preprocessor::get_instance()->call_controller( $action, $controller );
318
+
319
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
320
+ wp_die();
321
+ } else {
322
+ die();
323
+ }
324
+ }
325
+ }
326
+
327
+ /**
328
+ * Register taxonomies
329
+ */
330
+ public function register_all_taxonomies() {
331
+
332
+ $permalinks = Core::get_instance()->get_permalink_structure();
333
+
334
+ do_action( 'mptt_before_register_taxonomies' );
335
+
336
+ $event_category_labels = array(
337
+ 'name' => __( 'Event categories', 'mp-timetable' ),
338
+ 'singular_name' => __( 'Event category', 'mp-timetable' ),
339
+ 'add_new' => __( 'Add New Event category', 'mp-timetable' ),
340
+ 'add_new_item' => __( 'Add New Event category', 'mp-timetable' ),
341
+ 'edit_item' => __( 'Edit Event category', 'mp-timetable' ),
342
+ 'new_item' => __( 'New Event category', 'mp-timetable' ),
343
+ 'all_items' => __( 'All Event categories', 'mp-timetable' ),
344
+ 'view_item' => __( 'View Event category', 'mp-timetable' ),
345
+ 'search_items' => __( 'Search Event category', 'mp-timetable' ),
346
+ 'not_found' => __( 'No Event categories found', 'mp-timetable' ),
347
+ 'not_found_in_trash' => __( 'No Event categories found in Trash', 'mp-timetable' ),
348
+ 'menu_name' => __( 'Event categories', 'mp-timetable' )
349
+ );
350
+
351
+ $event_category_args = array(
352
+ 'label' => __( 'Event categories', 'mp-timetable' ),
353
+ 'labels' => $event_category_labels,
354
+ 'show_in_rest' => true,
355
+ 'public' => true,
356
+ 'show_in_nav_menus' => true,
357
+ 'show_ui' => true,
358
+ 'show_in_menu' => false,
359
+ 'show_tagcloud' => true,
360
+ 'hierarchical' => true,
361
+ 'update_count_callback' => '',
362
+ 'rewrite' => array(
363
+ 'slug' => $permalinks['event_category_base'], //'timetable/category'
364
+ 'with_front' => false,
365
+ 'hierarchical' => true
366
+ ),
367
+ 'capabilities' => array(),
368
+ 'meta_box_cb' => null,
369
+ 'show_admin_column' => false,
370
+ '_builtin' => false,
371
+ 'show_in_quick_edit' => null,
372
+ );
373
+
374
+ register_taxonomy(
375
+ 'mp-event_category',
376
+ apply_filters( 'mptt_taxonomy_objects_event_category', array( 'mp-event' ) ),
377
+ apply_filters( 'mptt_taxonomy_args_event_category', $event_category_args)
378
+ );
379
+
380
+ $event_tag_labels = array(
381
+ 'name' => __( 'Event tags', 'mp-timetable' ),
382
+ 'singular_name' => __( 'Event tag', 'mp-timetable' ),
383
+ 'add_new' => __( 'Add New Event tag', 'mp-timetable' ),
384
+ 'add_new_item' => __( 'Add New Event tag', 'mp-timetable' ),
385
+ 'edit_item' => __( 'Edit Event tag', 'mp-timetable' ),
386
+ 'new_item' => __( 'New Event tag', 'mp-timetable' ),
387
+ 'all_items' => __( 'All Event tags', 'mp-timetable' ),
388
+ 'view_item' => __( 'View Event tag', 'mp-timetable' ),
389
+ 'search_items' => __( 'Search Event tag', 'mp-timetable' ),
390
+ 'not_found' => __( 'No Event tags found', 'mp-timetable' ),
391
+ 'not_found_in_trash' => __( 'No Event tags found in Trash', 'mp-timetable' ),
392
+ 'menu_name' => __( 'Event tags', 'mp-timetable' )
393
+ );
394
+
395
+ $event_tag_args = array(
396
+ 'label' => __( 'Event tags', 'mp-timetable' ),
397
+ 'labels' => $event_tag_labels,
398
+ 'show_in_rest' => true,
399
+ 'public' => true,
400
+ 'show_in_nav_menus' => true,
401
+ 'show_ui' => true,
402
+ 'show_in_menu' => false,
403
+ 'show_tagcloud' => true,
404
+ 'hierarchical' => false,
405
+ 'update_count_callback' => '',
406
+ 'rewrite' => array(
407
+ 'slug' => $permalinks['event_tag_base'], //'timetable/tag'
408
+ 'with_front' => false,
409
+ 'hierarchical' => true
410
+ ),
411
+ 'capabilities' => array(),
412
+ 'meta_box_cb' => null,
413
+ 'show_admin_column' => false,
414
+ '_builtin' => false,
415
+ 'show_in_quick_edit' => null,
416
+ );
417
+
418
+ register_taxonomy(
419
+ 'mp-event_tag',
420
+ apply_filters( 'mptt_taxonomy_objects_event_tag', array( 'mp-event' ) ),
421
+ apply_filters( 'mptt_taxonomy_args_event_tag', $event_tag_args)
422
+ );
423
+
424
+ do_action( 'mptt_after_register_taxonomies' );
425
+ }
426
+
427
+ /**
428
+ * Register custom post type
429
+ */
430
+ public function register_all_post_type() {
431
+
432
+ $permalinks = Core::get_instance()->get_permalink_structure();
433
+
434
+ do_action( 'mptt_before_register_post_types' );
435
+
436
+ register_post_type(
437
+ 'mp-event',
438
+ apply_filters(
439
+ 'mptt_register_post_type_event',
440
+ array(
441
+ 'labels' => array(
442
+ 'name' => __( 'Events', 'mp-timetable' ),
443
+ 'singular_name' => __( 'Event', 'mp-timetable' ),
444
+ 'add_new' => __( 'Add New Event', 'mp-timetable' ),
445
+ 'add_new_item' => __( 'Add New Event', 'mp-timetable' ),
446
+ 'edit_item' => __( 'Edit Event', 'mp-timetable' ),
447
+ 'new_item' => __( 'New Event', 'mp-timetable' ),
448
+ 'all_items' => __( 'All Events', 'mp-timetable' ),
449
+ 'view_item' => __( 'View Event', 'mp-timetable' ),
450
+ 'search_items' => __( 'Search Event', 'mp-timetable' ),
451
+ 'not_found' => __( 'No Events found', 'mp-timetable' ),
452
+ 'not_found_in_trash' => __( 'No Events found in Trash', 'mp-timetable' ),
453
+ 'menu_name' => __( 'Events', 'mp-timetable' )
454
+ ),
455
+ 'public' => true,
456
+ 'show_in_rest' => true,
457
+ 'show_ui' => true,
458
+ 'show_in_menu' => false,
459
+ 'show_in_nav_menus' => true,
460
+ 'capability_type' => 'post',
461
+ 'menu_position' => 21,
462
+ 'hierarchical' => false,
463
+ 'has_archive' => true,
464
+ 'rewrite' => array(
465
+ 'slug' => $permalinks['event_base'], //'timetable/event'
466
+ 'with_front' => false,
467
+ 'hierarchical' => true
468
+ ),
469
+ 'supports' => array( 'title', 'editor', 'comments', 'excerpt', 'author', 'thumbnail', 'page-attributes' ),
470
+ 'show_in_admin_bar' => true
471
+ )
472
+ )
473
+ );
474
+
475
+ register_post_type(
476
+ 'mp-column',
477
+ apply_filters(
478
+ 'mptt_register_post_type_column',
479
+ array(
480
+ 'labels' => array(
481
+ 'name' => __( 'Columns', 'mp-timetable' ),
482
+ 'singular_name' => __( 'Column', 'mp-timetable' ),
483
+ 'add_new' => __( 'Add New Column', 'mp-timetable' ),
484
+ 'add_new_item' => __( 'Add New Column', 'mp-timetable' ),
485
+ 'edit_item' => __( 'Edit Column', 'mp-timetable' ),
486
+ 'new_item' => __( 'New Column', 'mp-timetable' ),
487
+ 'all_items' => __( 'All Columns', 'mp-timetable' ),
488
+ 'view_item' => __( 'View Column', 'mp-timetable' ),
489
+ 'search_items' => __( 'Search Column', 'mp-timetable' ),
490
+ 'not_found' => __( 'No Columns found', 'mp-timetable' ),
491
+ 'not_found_in_trash' => __( 'No Columns found in Trash', 'mp-timetable' ),
492
+ 'menu_name' => __( 'Columns', 'mp-timetable' )
493
+ ),
494
+ 'public' => true,
495
+ 'show_in_rest' => true,
496
+ 'show_ui' => true,
497
+ 'show_in_menu' => false,
498
+ 'show_in_nav_menus' => true,
499
+ 'capability_type' => 'post',
500
+ 'menu_position' => 21,
501
+ 'hierarchical' => false,
502
+ 'has_archive' => true,
503
+ 'rewrite' => array(
504
+ 'slug' => $permalinks['column_base'], //'timetable/column'
505
+ 'with_front' => false,
506
+ 'hierarchical' => true
507
+ ),
508
+ 'supports' => array( 'title', 'editor', 'page-attributes' ),
509
+ 'show_in_admin_bar' => true
510
+ )
511
+ )
512
+ );
513
+
514
+ do_action( 'mptt_after_register_post_types' );
515
+
516
+ }
517
+
518
+ /**
519
+ * Create Plugin table if not exists
520
+ */
521
+ public function create_table() {
522
+
523
+ global $wpdb;
524
+
525
+ $charset_collate = $wpdb->get_charset_collate();
526
+
527
+ $table_name = Mp_Time_Table::get_datatable();
528
+
529
+ $sql = "CREATE TABLE IF NOT EXISTS $table_name (
530
+ `id` int(11) NOT NULL AUTO_INCREMENT,
531
+ `column_id` int(11) NOT NULL,
532
+ `event_id` int(11) NOT NULL,
533
+ `event_start` time NOT NULL,
534
+ `event_end` time NOT NULL,
535
+ `user_id` int(11) NOT NULL,
536
+ `description` text NOT NULL,
537
+ PRIMARY KEY (`id`),
538
+ UNIQUE KEY `id` (`id`)
539
+ ) $charset_collate";
540
+
541
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
542
+ dbDelta( $sql );
543
+ }
544
+
545
+ /**
546
+ * Hook admin_enqueue_scripts
547
+ */
548
+ public function admin_enqueue_scripts() {
549
+ global $current_screen;
550
+ $this->current_screen( $current_screen );
551
+ }
552
+
553
+ /**
554
+ * Load script by current screen
555
+ *
556
+ * @param \WP_Screen $current_screen
557
+ */
558
+ public function current_screen( \WP_Screen $current_screen = null ) {
559
+ wp_register_script( 'mptt-event-object', Mp_Time_Table::get_plugin_url( 'media/js/events/event' . $this->get_prefix() . '.js' ), array( 'jquery' ), $this->version );
560
+ wp_localize_script(
561
+ 'mptt-event-object',
562
+ 'MPTT',
563
+ array(
564
+ 'table_class' => apply_filters( 'mptt_shortcode_static_table_class', 'mptt-shortcode-table' ),
565
+ 'timeslot_delete_nonce' => wp_create_nonce( 'timeslot_delete_nonce' ),
566
+ 'timeslot_update_nonce' => wp_create_nonce( 'timeslot_update_nonce' ),
567
+ )
568
+ );
569
+
570
+ wp_enqueue_script( 'underscore' );
571
+
572
+ wp_enqueue_style( 'mptt-admin-style', Mp_Time_Table::get_plugin_url( 'media/css/admin.css' ), array(), $this->version );
573
+
574
+ wp_enqueue_script( 'mptt-functions', Mp_Time_Table::get_plugin_url( 'media/js/mptt-functions' . $this->get_prefix() . '.js' ), array(), $this->version );
575
+
576
+ if ( ! empty( $_GET[ 'page' ] ) ) {
577
+ switch ( sanitize_key( $_GET[ 'page' ] ) ) {
578
+ case 'mptt-settings' :
579
+ case 'mptt-import' :
580
+ case 'mptt-help' :
581
+ wp_register_script( 'mptt-option-ajax', Mp_Time_Table::get_plugin_url( 'media/js/mptt-option-ajax' . $this->get_prefix() . '.js' ), array( 'jquery' ), $this->version );
582
+ wp_enqueue_script( 'mptt-option-ajax' );
583
+ wp_localize_script(
584
+ 'mptt-option-ajax',
585
+ 'MPTT',
586
+ array(
587
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
588
+ 'nonce' => wp_create_nonce( 'mptt-install-plugins' ),
589
+ 'status_download' => esc_html__( 'Install Plugin', 'mp-timetable' ),
590
+ 'status_activated' => esc_html__( 'Activated', 'mp-timetable' ),
591
+ 'status_active' => esc_html__( 'Active', 'mp-timetable' ),
592
+ 'status_inactive' => esc_html__( 'Inactive', 'mp-timetable' ),
593
+ 'status_loading' => esc_html__( 'Loading...', 'mp-timetable' ),
594
+ 'status_activate' => esc_html__( 'Activate', 'mp-timetable' ),
595
+ )
596
+ );
597
+ break;
598
+ default :
599
+ break;
600
+ }
601
+ }
602
+
603
+ if ( ! empty( $current_screen ) ) {
604
+ switch ( $current_screen->id ) {
605
+ case 'mp-event':
606
+ wp_enqueue_script( 'spectrum', Mp_Time_Table::get_plugin_url( 'media/js/lib/spectrum' . $this->get_prefix() . '.js' ), array( 'jquery' ), '1.8.0' );
607
+ wp_enqueue_script( 'mptt-event-object' );
608
+ wp_enqueue_script( 'jquery-ui-timepicker', Mp_Time_Table::get_plugin_url( 'media/js/lib/jquery.ui.timepicker' . $this->get_prefix() . '.js' ), '0.3.3' );
609
+
610
+ wp_enqueue_style( 'jquery-ui-core', Mp_Time_Table::get_plugin_url( 'media/css/jquery-ui-1.10.0.custom.min.css' ), array(), '1.10.0' );
611
+ wp_enqueue_style( 'spectrum', Mp_Time_Table::get_plugin_url( 'media/css/spectrum.css' ), array(), '1.8.0' );
612
+ wp_enqueue_style( 'jquery-ui-timepicker', Mp_Time_Table::get_plugin_url( 'media/css/jquery.ui.timepicker.css' ), array(), '0.3.3' );
613
+ break;
614
+
615
+ case 'mp-column':
616
+ wp_enqueue_script( 'jquery-ui-datepicker' );
617
+ wp_enqueue_script( 'mptt-event-object' );
618
+
619
+ wp_enqueue_style( 'jquery-ui-core', Mp_Time_Table::get_plugin_url( 'media/css/jquery-ui-1.10.0.custom.min.css' ), array(), '1.10.0' );
620
+ break;
621
+
622
+ case 'customize':
623
+ case 'widgets':
624
+ wp_enqueue_script( 'spectrum', Mp_Time_Table::get_plugin_url( 'media/js/lib/spectrum' . $this->get_prefix() . '.js' ), array( 'jquery' ), '1.8.0' );
625
+ wp_enqueue_script( 'mptt-event-object' );
626
+
627
+ wp_enqueue_style( 'jquery-ui-core', Mp_Time_Table::get_plugin_url( 'media/css/jquery-ui-1.10.0.custom.min.css' ), array(), '1.10.0' );
628
+ wp_enqueue_style( 'spectrum', Mp_Time_Table::get_plugin_url( 'media/css/spectrum.css' ), array(), '1.8.0' );
629
+ break;
630
+ }
631
+
632
+ switch ( $current_screen->base ) {
633
+ case 'post':
634
+ case 'page':
635
+ wp_enqueue_script( 'jquery-ui-tabs' );
636
+ wp_enqueue_script( 'jBox', Mp_Time_Table::get_plugin_url( 'media/js/lib/jBox' . $this->get_prefix() . '.js' ), array( 'jquery' ), '0.2.1' );
637
+
638
+ wp_enqueue_style( 'jBox', Mp_Time_Table::get_plugin_url( 'media/css/jbox/jBox.css' ), array(), '1.8.0' );
639
+ break;
640
+
641
+ case 'options-permalink':
642
+ if ( apply_filters('mptt_permalinks_enabled', true) ) {
643
+ $permalinks = new Permalinks();
644
+ }
645
+ break;
646
+
647
+ default:
648
+ break;
649
+ }
650
+ }
651
+ }
652
+
653
+ public function wp_ajax_install_plugin_ajax() {
654
+
655
+ $action = isset( $_REQUEST[ "action" ] ) ? sanitize_text_field( $_REQUEST[ "action" ] ) : null;
656
+
657
+ if ( $action && $action === 'install_plugin_ajax' ) {
658
+
659
+ if ( empty( $_POST[ 'status' ] ) ) {
660
+ wp_send_json_error();
661
+ }
662
+
663
+ $status = sanitize_key( $_POST[ 'status' ] );
664
+
665
+ require_once Mp_Time_Table::get_plugin_path() . 'classes/class-offer.php';
666
+ $plugins_offer = new Plugins_Offer();
667
+
668
+ switch ( $status ) {
669
+ case 'activate' :
670
+ $plugins_offer->activatePluginAjax();
671
+ break;
672
+ case 'install' :
673
+ $plugins_offer->installPluginAjax();
674
+ break;
675
+ default :
676
+ break;
677
+ }
678
+
679
+ wp_send_json_success();
680
+ }
681
+ }
682
+
683
+ /**
684
+ * Get prefix
685
+ *
686
+ * @return string
687
+ */
688
+ public function get_prefix() {
689
+ global $is_IE;
690
+
691
+ $prefix = ! MP_TT_DEBUG ? '.min' : '';
692
+
693
+ if ($is_IE){
694
+ $prefix = '';
695
+ }
696
+
697
+ return $prefix;
698
+ }
699
+
700
+ /**
701
+ * Hook wp_enqueue_scripts
702
+ */
703
+ public function wp_enqueue_scripts() {
704
+ if ( ! empty( $_GET[ 'motopress-ce' ] ) ) {
705
+ $this->add_plugin_js( 'shortcode' );
706
+ }
707
+ }
708
+
709
+ /**
710
+ * Hook elementor_enqueue_scripts
711
+ */
712
+ public function elementor_enqueue_scripts() {
713
+ $this->add_plugin_js( 'elementor-widget' );
714
+ }
715
+
716
+ /**
717
+ * Add plugin js
718
+ *
719
+ * @param bool $type
720
+ */
721
+ public function add_plugin_js( $type = false ) {
722
+ wp_register_script( 'mptt-event-object', Mp_Time_Table::get_plugin_url( 'media/js/events/event' . $this->get_prefix() . '.js' ), array( 'jquery', 'mptt-functions' ), $this->version );
723
+ wp_localize_script(
724
+ 'mptt-event-object',
725
+ 'MPTT',
726
+ array( 'table_class' => apply_filters( 'mptt_shortcode_static_table_class', 'mptt-shortcode-table' ) )
727
+ );
728
+
729
+ switch ( $type ) {
730
+ case 'shortcode':
731
+ case 'widget':
732
+ wp_enqueue_script( 'underscore' );
733
+ wp_enqueue_script( 'mptt-functions', Mp_Time_Table::get_plugin_url( 'media/js/mptt-functions' . $this->get_prefix() . '.js' ), array( 'jquery' ), $this->version );
734
+ wp_enqueue_script( 'mptt-event-object' );
735
+ break;
736
+ case 'elementor-widget':
737
+ wp_enqueue_script( 'underscore' );
738
+ wp_enqueue_script( 'mptt-functions', Mp_Time_Table::get_plugin_url( 'media/js/mptt-functions' . $this->get_prefix() . '.js' ), array( 'jquery' ), $this->version );
739
+ wp_enqueue_script( 'mptt-event-object' );
740
+ wp_enqueue_script(
741
+ 'mptt-editor-panel-js',
742
+ Mp_Time_Table::get_plugin_url( 'media/js/mptt-elementor-editor' . $this->get_prefix() . '.js' ),
743
+ array( 'jquery', 'mptt-functions', 'mptt-event-object' ),
744
+ $this->version
745
+ );
746
+ break;
747
+ }
748
+ }
749
+
750
+ /**
751
+ * Add plugin css
752
+ */
753
+ public function add_plugin_css() {
754
+ wp_enqueue_style( 'mptt-style', Mp_Time_Table::get_plugin_url( 'media/css/style.css' ), array(), $this->version );
755
+ }
756
+
757
+ /**
758
+ * Fix fatal error for earlier WP versions
759
+ *
760
+ * @return bool
761
+ */
762
+ public function is_embed() {
763
+ global $wp_version;
764
+
765
+ if ( ! function_exists( 'is_embed' ) ) {
766
+ return false;
767
+ }
768
+
769
+ if ( version_compare( $wp_version, '4.4', '<' ) ) {
770
+ if ( ! function_exists( 'is_embed' ) ) {
771
+ return false;
772
+ }
773
+ }
774
+
775
+ return is_embed();
776
+ }
777
+
778
+ /**
779
+ * Get permalink settings
780
+ *
781
+ * @return array
782
+ */
783
+ public function get_permalink_structure() {
784
+
785
+ $saved_permalinks = (array) get_option( 'mp_timetable_permalinks', array() );
786
+
787
+ $permalinks = wp_parse_args(
788
+ array_filter( $saved_permalinks ), array(
789
+ 'column_base' => 'timetable/column',
790
+ 'event_base' => 'timetable/event',
791
+ 'event_category_base' => 'timetable/category',
792
+ 'event_tag_base' => 'timetable/tag',
793
+ )
794
+ );
795
+
796
+ if ( $saved_permalinks !== $permalinks ) {
797
+ update_option( 'mp_timetable_permalinks', $permalinks );
798
+ }
799
+
800
+ return $permalinks;
801
+ }
802
  }
classes/class-hooks.php CHANGED
@@ -1,310 +1,310 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- use Mp_Time_Table;
6
- use mp_timetable\classes\models\Import;
7
- use mp_timetable\classes\models\Settings;
8
- use mp_timetable\plugin_core\classes\modules\Post;
9
- use mp_timetable\classes\blocks\Timetable_Block;
10
-
11
- /**
12
- * Class Hooks
13
- * @package mp_timetable\plugin_core\classes
14
- */
15
- class Hooks extends Core {
16
-
17
- protected static $instance;
18
-
19
- /**
20
- * @return Hooks
21
- */
22
- public static function get_instance() {
23
- if ( null === self::$instance ) {
24
- self::$instance = new self();
25
- }
26
-
27
- return self::$instance;
28
- }
29
-
30
- /**
31
- * Install hooks
32
- */
33
- public function install_hooks() {
34
- // Elementor widget register.
35
- add_action( 'elementor/init', array( $this, 'elementor_loaded' ) );
36
-
37
- // register custom post type and taxonomies
38
- add_action( 'init', array( $this, 'init' ) );
39
- add_action( 'wp_enqueue_scripts', array( Core::get_instance(), 'add_plugin_css' ) );
40
- add_action( 'wp_head', array( $this, 'set_html_js_class' ) );
41
-
42
- add_action( 'admin_init', array( $this->get_controller( 'settings' ), 'action_save' ) );
43
- add_action( 'admin_init', array( $this, 'admin_init' ) );
44
- add_action( 'admin_menu', array( $this, 'admin_menu' ) );
45
- add_action( 'manage_posts_custom_column', array( $this->get( 'events' ), 'get_event_taxonomy' ) );
46
- add_action( 'manage_posts_custom_column', array( $this->get( 'column' ), 'get_column_columns' ) );
47
- add_action( 'current_screen', array( Core::get_instance(), 'current_screen' ) );
48
- add_action( 'pre_get_posts', array( $this->get( 'column' ), 'clientarea_default_order' ), 9 );
49
-
50
- //add media in frontend WP
51
- add_action( 'wp_enqueue_scripts', array( Core::get_instance(), 'wp_enqueue_scripts' ) );
52
-
53
- //add media in admin WP
54
- add_action( 'admin_enqueue_scripts', array( Core::get_instance(), 'admin_enqueue_scripts' ) );
55
- add_action( 'widgets_init', array( $this, 'register_widgets' ) );
56
-
57
- // Manage event/column columns
58
- add_filter( 'manage_edit-mp-event_columns', array( $this->get( 'events' ), 'set_event_columns' ) );
59
- add_filter( 'manage_edit-mp-column_columns', array( $this->get( 'column' ), 'set_column_columns' ) );
60
-
61
- // Duplicate Event
62
- add_filter( 'post_row_actions', array( $this->get( 'events' ), 'post_row_actions' ), 999, 2 );
63
- add_action( 'post_action_mptt_duplicate_event', array( $this->get( 'events' ), 'post_action_mptt_duplicate_event' ) );
64
-
65
- // post_class filter
66
- add_filter( 'post_class', 'mptt_post_class', 15, 3 );
67
-
68
- // to display events with other posts on author page
69
- add_filter( 'pre_get_posts', array( Post::get_instance(), 'pre_get_posts' ), 9 );
70
- add_filter( 'plugin_row_meta', array( __CLASS__, 'plugin_row_meta' ), 10, 2 );
71
- }
72
-
73
-
74
- /**
75
- * Register widgets and sidebar
76
- */
77
- public function register_widgets() {
78
- $template = get_option( 'template' );
79
- if ( $template != 'twentyfourteen' && Settings::get_instance()->is_plugin_template_mode() ) {
80
- register_sidebar( array(
81
- 'name' => __( 'Timetable Sidebar', 'mp-timetable' ),
82
- 'id' => "mptt-sidebar",
83
- 'description' => __( 'Timetable', 'mp-timetable' ),
84
- 'class' => 'sidebar-container',
85
- 'before_widget' => '<li id="%1$s" class="widget %2$s">',
86
- 'after_widget' => "</li>\n",
87
- 'before_title' => '<h2 class="widget-title">',
88
- 'after_title' => "</h2>\n"
89
- ) );
90
- }
91
- register_widget( 'timetable\classes\widgets\Timetable_widget' );
92
- }
93
-
94
- /**
95
- * Register template_action
96
- */
97
- public function register_template_action() {
98
- add_action( 'mptt_sidebar', 'mptt_sidebar', 10 );
99
- add_filter( 'mptt_widget_settings', 'mptt_widget_settings', 10, 1 );
100
- add_action( 'mptt-single-mp-column-before-wrapper', 'mptt_theme_wrapper_before' );
101
- add_action( 'mptt-single-mp-column-after-wrapper', 'mptt_theme_wrapper_after' );
102
- add_action( 'mptt-single-mp-event-before-wrapper', 'mptt_theme_wrapper_before' );
103
- add_action( 'mptt-single-mp-event-after-wrapper', 'mptt_theme_wrapper_after' );
104
-
105
- // Event template action
106
- add_action( 'mptt_event_item_content', 'mptt_event_template_content_title', 10 );
107
- add_action( 'mptt_event_item_content', 'mptt_event_template_content_thumbnail', 20 );
108
- add_action( 'mptt_event_item_content', 'mptt_event_template_content_post_content', 30 );
109
- add_action( 'mptt_event_item_content', 'mptt_event_template_content_time_title', 40 );
110
- add_action( 'mptt_event_item_content', 'mptt_event_template_content_time_list', 50 );
111
- add_action( 'mptt_event_item_content', 'mptt_event_template_content_comments', 60 );
112
-
113
- // Column template action
114
- add_action( 'mptt_single_column_template_content', 'mptt_column_template_content_title', 10 );
115
- add_action( 'mptt_single_column_template_content', 'mptt_column_template_content_post_content', 20 );
116
- add_action( 'mptt_single_column_template_content', 'mptt_column_template_content_events_list', 30 );
117
-
118
- //Shortcode template action
119
- add_action( 'mptt_shortcode_template_before_content', 'mptt_shortcode_template_before_content', 10 );
120
- add_action( 'mptt_shortcode_template_content', 'mptt_shortcode_template_content_filter', 10 );
121
- add_action( 'mptt_shortcode_template_content', 'mptt_shortcode_template_content_static_table', 20 );
122
- add_action( 'mptt_shortcode_template_content', 'mptt_shortcode_template_content_responsive_table', 30 );
123
- add_action( 'mptt_shortcode_template_after_content', 'mptt_shortcode_template_after_content', 10 );
124
-
125
- // Widget actions
126
- add_action( 'mptt_widget_template_before_content', 'mptt_widget_template_before_content', 10 );
127
- add_action( 'mptt_widget_template_content', 'mptt_widget_template_content', 10 );
128
- add_action( 'mptt_widget_template_after_content', 'mptt_widget_template_after_content', 10 );
129
- }
130
-
131
- /**
132
- * Elementor Init hook.
133
- */
134
- public function elementor_loaded() {
135
- add_action( 'elementor/frontend/after_enqueue_scripts', [ Core::get_instance(), 'elementor_enqueue_scripts' ] );
136
-
137
- new Widgets_Manager();
138
- }
139
-
140
- /**
141
- * Init hook
142
- */
143
- public function init() {
144
-
145
- // Init sort codes
146
- Shortcode::get_instance()->init();
147
- // Register post type
148
- Core::get_instance()->register_all_post_type();
149
- // Register taxonomy all
150
- Core::get_instance()->register_all_taxonomies();
151
- // route url
152
- Core::get_instance()->wp_ajax_route_url();
153
-
154
- if ( Settings::get_instance()->is_plugin_template_mode() ) {
155
- // plugin mode
156
- add_filter( 'template_include', array( View::get_instance(), 'template_loader' ), 99 );
157
- } else {
158
- //theme mode
159
- add_filter( 'single_template', array( Core::get_instance(), 'modify_single_template' ), 99 );
160
- }
161
-
162
- add_action( 'mp_library', array( Shortcode::get_instance(), 'integration_motopress' ), 20, 1 );
163
-
164
- Core::get_instance()->init_plugin_version();
165
-
166
- add_filter( 'body_class', array( $this, 'browser_body_class' ) );
167
- add_filter( 'the_tags', array( $this->get( 'events' ), 'the_tags' ), 10, 5 );
168
- add_filter( 'the_category', array( $this->get( 'events' ), 'the_category' ), 10, 3 );
169
-
170
- if ( function_exists('register_block_type') ) {
171
- new Timetable_Block();
172
- }
173
- }
174
-
175
- /**
176
- * Hooks for admin panel
177
- */
178
- public function admin_init() {
179
- //add buttons to mce
180
- add_filter( "mce_external_plugins", array( $this, "mce_external_plugins" ) );
181
- add_filter( 'mce_buttons', array( $this, "mce_buttons" ) );
182
-
183
- Core::get_instance()->init_plugin_version();
184
-
185
- add_action( 'before_delete_post', array( Post::get_instance(), 'before_delete_custom_post' ) );
186
- add_action( 'add_meta_boxes', array( Post::get_instance(), 'add_meta_boxes' ) );
187
- add_action( 'save_post', array( Post::get_instance(), 'save_custom_post' ), 40, 2 );
188
- add_action( 'wp_ajax_route_url', array( Core::get_instance(), "wp_ajax_route_url" ) );
189
- add_action( 'wp_ajax_install_plugin_ajax', array( Core::get_instance(), 'wp_ajax_install_plugin_ajax' ) );
190
-
191
- register_importer( 'mptt-importer', 'Timetable', __( 'Import Timetable events, categories, tags and images.', 'mp-timetable' ), array( Import::get_instance(), 'import' ) );
192
- }
193
-
194
- /**
195
- * Registered page in admin wp
196
- */
197
- public function admin_menu() {
198
-
199
- //Timetable
200
- add_menu_page( __( 'Timetable', 'mp-timetable' ), __( 'Timetable', 'mp-timetable' ),
201
- 'edit_posts', 'edit.php?post_type=mp-event', '', 'dashicons-calendar', '59.51' );
202
-
203
- //Events
204
- add_submenu_page( 'edit.php?post_type=mp-event', __( 'Events', 'mp-timetable' ), __( 'Events', 'mp-timetable' ),
205
- 'edit_posts', 'edit.php?post_type=mp-event' );
206
-
207
- //Add Event
208
- add_submenu_page( 'edit.php?post_type=mp-event', __( 'Add Event', 'mp-timetable' ), __( 'Add Event', 'mp-timetable' ),
209
- 'edit_posts', 'post-new.php?post_type=mp-event' );
210
-
211
- //Columns
212
- add_submenu_page( 'edit.php?post_type=mp-event', __( 'Columns', 'mp-timetable' ), __( 'Columns', 'mp-timetable' ),
213
- 'edit_posts', 'edit.php?post_type=mp-column' );
214
-
215
- //Add Column
216
- add_submenu_page( 'edit.php?post_type=mp-event', __( 'Add Column', 'mp-timetable' ), __( 'Add Column', 'mp-timetable' ),
217
- 'edit_posts', 'post-new.php?post_type=mp-column' );
218
-
219
- //Event Categories
220
- add_submenu_page( 'edit.php?post_type=mp-event', __( 'Event Categories', 'mp-timetable' ), __( 'Event Categories', 'mp-timetable' ),
221
- 'manage_categories', 'edit-tags.php?taxonomy=mp-event_category&amp;post_type=mp-event' );
222
-
223
- //Event Tags
224
- add_submenu_page( 'edit.php?post_type=mp-event', __( 'Event Tags', 'mp-timetable' ), __( 'Event Tags', 'mp-timetable' ),
225
- 'manage_categories', 'edit-tags.php?taxonomy=mp-event_tag&amp;post_type=mp-event' );
226
-
227
- //Settings
228
- add_submenu_page( 'edit.php?post_type=mp-event', __( 'Settings', 'mp-timetable' ), __( 'Settings', 'mp-timetable' ),
229
- 'manage_options', 'mptt-settings', array( $this->get_controller( 'settings' ), 'action_content' ) );
230
-
231
- //Export / Import
232
- add_submenu_page( 'edit.php?post_type=mp-event', __( 'Export / Import', 'mp-timetable' ), __( 'Export / Import', 'mp-timetable' ),
233
- 'import', 'mptt-import', array( $this->get_controller( 'import' ), 'action_content' ) );
234
-
235
- //Help
236
- add_submenu_page( 'edit.php?post_type=mp-event', __( 'Help & Shortcode', 'mp-timetable' ), __( 'Help & Shortcode', 'mp-timetable' ),
237
- 'edit_posts', 'mptt-help', array( $this->get_controller( 'help' ), 'action_content' ) );
238
- }
239
-
240
- /**
241
- * Connect js for MCE editor
242
- *
243
- * @param $plugin_array
244
- *
245
- * @return mixed
246
- */
247
- public function mce_external_plugins( $plugin_array ) {
248
- $path = Mp_Time_Table::get_plugin_url( 'media/js/mce-timeTable-buttons' . $this->get_prefix() . '.js' );
249
- $plugin_array[ 'mp_timetable' ] = $path;
250
-
251
- return $plugin_array;
252
- }
253
-
254
- /**
255
- * Add button in MCE editor
256
- *
257
- * @param $buttons
258
- *
259
- * @return mixed
260
- */
261
- public function mce_buttons( $buttons ) {
262
- array_push( $buttons, 'addTimeTableButton' );
263
-
264
- return $buttons;
265
- }
266
-
267
- /**
268
- * Browser body class
269
- *
270
- * @param $classes
271
- *
272
- * @return array
273
- */
274
- public function browser_body_class( $classes ) {
275
- global $is_IE;
276
-
277
- if ( $is_IE ) {
278
- $classes[] = 'mprm_ie_browser';
279
- }
280
-
281
- return $classes;
282
- }
283
-
284
- /**
285
- * Set js
286
- */
287
- public function set_html_js_class() {
288
- echo View::get_instance()->get_template_html('events/no-script');
289
- }
290
-
291
- /**
292
- * Show row meta on the plugin screen.
293
- *
294
- * @return array
295
- */
296
- public static function plugin_row_meta( $links, $file ) {
297
-
298
- if ( MP_TT_PLUGIN_BASENAME === $file ) {
299
- $row_meta = array(
300
- 'help' => '<a href="' . esc_url( admin_url('edit.php?post_type=mp-event&page=mptt-help') ) . '" aria-label="' . esc_attr__( 'Quick Start Guide', 'mp-timetable' ) . '">' .
301
- esc_html__( 'Help', 'mp-timetable' ) . '</a>',
302
- 'review' => '<a href="' . esc_url( 'https://wordpress.org/support/plugin/mp-timetable/reviews?rate=5#new-post' ) . '" aria-label="' . esc_attr__( 'Leave a Review', 'mp-timetable' ) . '" target="_blank">' . esc_html__( 'Leave a Review', 'mp-timetable' ) . ' &#9733;&#9733;&#9733;&#9733;&#9733;</a>',
303
- );
304
-
305
- return array_merge( $links, $row_meta );
306
- }
307
-
308
- return (array) $links;
309
- }
310
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ use Mp_Time_Table;
6
+ use mp_timetable\classes\models\Import;
7
+ use mp_timetable\classes\models\Settings;
8
+ use mp_timetable\plugin_core\classes\modules\Post;
9
+ use mp_timetable\classes\blocks\Timetable_Block;
10
+
11
+ /**
12
+ * Class Hooks
13
+ * @package mp_timetable\plugin_core\classes
14
+ */
15
+ class Hooks extends Core {
16
+
17
+ protected static $instance;
18
+
19
+ /**
20
+ * @return Hooks
21
+ */
22
+ public static function get_instance() {
23
+ if ( null === self::$instance ) {
24
+ self::$instance = new self();
25
+ }
26
+
27
+ return self::$instance;
28
+ }
29
+
30
+ /**
31
+ * Install hooks
32
+ */
33
+ public function install_hooks() {
34
+ // Elementor widget register.
35
+ add_action( 'elementor/init', array( $this, 'elementor_loaded' ) );
36
+
37
+ // register custom post type and taxonomies
38
+ add_action( 'init', array( $this, 'init' ) );
39
+ add_action( 'wp_enqueue_scripts', array( Core::get_instance(), 'add_plugin_css' ) );
40
+ add_action( 'wp_head', array( $this, 'set_html_js_class' ) );
41
+
42
+ add_action( 'admin_init', array( $this->get_controller( 'settings' ), 'action_save' ) );
43
+ add_action( 'admin_init', array( $this, 'admin_init' ) );
44
+ add_action( 'admin_menu', array( $this, 'admin_menu' ) );
45
+ add_action( 'manage_posts_custom_column', array( $this->get( 'events' ), 'get_event_taxonomy' ) );
46
+ add_action( 'manage_posts_custom_column', array( $this->get( 'column' ), 'get_column_columns' ) );
47
+ add_action( 'current_screen', array( Core::get_instance(), 'current_screen' ) );
48
+ add_action( 'pre_get_posts', array( $this->get( 'column' ), 'clientarea_default_order' ), 9 );
49
+
50
+ //add media in frontend WP
51
+ add_action( 'wp_enqueue_scripts', array( Core::get_instance(), 'wp_enqueue_scripts' ) );
52
+
53
+ //add media in admin WP
54
+ add_action( 'admin_enqueue_scripts', array( Core::get_instance(), 'admin_enqueue_scripts' ) );
55
+ add_action( 'widgets_init', array( $this, 'register_widgets' ) );
56
+
57
+ // Manage event/column columns
58
+ add_filter( 'manage_edit-mp-event_columns', array( $this->get( 'events' ), 'set_event_columns' ) );
59
+ add_filter( 'manage_edit-mp-column_columns', array( $this->get( 'column' ), 'set_column_columns' ) );
60
+
61
+ // Duplicate Event
62
+ add_filter( 'post_row_actions', array( $this->get( 'events' ), 'post_row_actions' ), 999, 2 );
63
+ add_action( 'post_action_mptt_duplicate_event', array( $this->get( 'events' ), 'post_action_mptt_duplicate_event' ) );
64
+
65
+ // post_class filter
66
+ add_filter( 'post_class', 'mptt_post_class', 15, 3 );
67
+
68
+ // to display events with other posts on author page
69
+ add_filter( 'pre_get_posts', array( Post::get_instance(), 'pre_get_posts' ), 9 );
70
+ add_filter( 'plugin_row_meta', array( __CLASS__, 'plugin_row_meta' ), 10, 2 );
71
+ }
72
+
73
+
74
+ /**
75
+ * Register widgets and sidebar
76
+ */
77
+ public function register_widgets() {
78
+ $template = get_option( 'template' );
79
+ if ( $template != 'twentyfourteen' && Settings::get_instance()->is_plugin_template_mode() ) {
80
+ register_sidebar( array(
81
+ 'name' => __( 'Timetable Sidebar', 'mp-timetable' ),
82
+ 'id' => "mptt-sidebar",
83
+ 'description' => __( 'Timetable', 'mp-timetable' ),
84
+ 'class' => 'sidebar-container',
85
+ 'before_widget' => '<li id="%1$s" class="widget %2$s">',
86
+ 'after_widget' => "</li>\n",
87
+ 'before_title' => '<h2 class="widget-title">',
88
+ 'after_title' => "</h2>\n"
89
+ ) );
90
+ }
91
+ register_widget( 'timetable\classes\widgets\Timetable_widget' );
92
+ }
93
+
94
+ /**
95
+ * Register template_action
96
+ */
97
+ public function register_template_action() {
98
+ add_action( 'mptt_sidebar', 'mptt_sidebar', 10 );
99
+ add_filter( 'mptt_widget_settings', 'mptt_widget_settings', 10, 1 );
100
+ add_action( 'mptt-single-mp-column-before-wrapper', 'mptt_theme_wrapper_before' );
101
+ add_action( 'mptt-single-mp-column-after-wrapper', 'mptt_theme_wrapper_after' );
102
+ add_action( 'mptt-single-mp-event-before-wrapper', 'mptt_theme_wrapper_before' );
103
+ add_action( 'mptt-single-mp-event-after-wrapper', 'mptt_theme_wrapper_after' );
104
+
105
+ // Event template action
106
+ add_action( 'mptt_event_item_content', 'mptt_event_template_content_title', 10 );
107
+ add_action( 'mptt_event_item_content', 'mptt_event_template_content_thumbnail', 20 );
108
+ add_action( 'mptt_event_item_content', 'mptt_event_template_content_post_content', 30 );
109
+ add_action( 'mptt_event_item_content', 'mptt_event_template_content_time_title', 40 );
110
+ add_action( 'mptt_event_item_content', 'mptt_event_template_content_time_list', 50 );
111
+ add_action( 'mptt_event_item_content', 'mptt_event_template_content_comments', 60 );
112
+
113
+ // Column template action
114
+ add_action( 'mptt_single_column_template_content', 'mptt_column_template_content_title', 10 );
115
+ add_action( 'mptt_single_column_template_content', 'mptt_column_template_content_post_content', 20 );
116
+ add_action( 'mptt_single_column_template_content', 'mptt_column_template_content_events_list', 30 );
117
+
118
+ //Shortcode template action
119
+ add_action( 'mptt_shortcode_template_before_content', 'mptt_shortcode_template_before_content', 10 );
120
+ add_action( 'mptt_shortcode_template_content', 'mptt_shortcode_template_content_filter', 10 );
121
+ add_action( 'mptt_shortcode_template_content', 'mptt_shortcode_template_content_static_table', 20 );
122
+ add_action( 'mptt_shortcode_template_content', 'mptt_shortcode_template_content_responsive_table', 30 );
123
+ add_action( 'mptt_shortcode_template_after_content', 'mptt_shortcode_template_after_content', 10 );
124
+
125
+ // Widget actions
126
+ add_action( 'mptt_widget_template_before_content', 'mptt_widget_template_before_content', 10 );
127
+ add_action( 'mptt_widget_template_content', 'mptt_widget_template_content', 10 );
128
+ add_action( 'mptt_widget_template_after_content', 'mptt_widget_template_after_content', 10 );
129
+ }
130
+
131
+ /**
132
+ * Elementor Init hook.
133
+ */
134
+ public function elementor_loaded() {
135
+ add_action( 'elementor/frontend/after_enqueue_scripts', [ Core::get_instance(), 'elementor_enqueue_scripts' ] );
136
+
137
+ new Widgets_Manager();
138
+ }
139
+
140
+ /**
141
+ * Init hook
142
+ */
143
+ public function init() {
144
+
145
+ // Init sort codes
146
+ Shortcode::get_instance()->init();
147
+ // Register post type
148
+ Core::get_instance()->register_all_post_type();
149
+ // Register taxonomy all
150
+ Core::get_instance()->register_all_taxonomies();
151
+ // route url
152
+ Core::get_instance()->wp_ajax_route_url();
153
+
154
+ if ( Settings::get_instance()->is_plugin_template_mode() ) {
155
+ // plugin mode
156
+ add_filter( 'template_include', array( View::get_instance(), 'template_loader' ), 99 );
157
+ } else {
158
+ //theme mode
159
+ add_filter( 'single_template', array( Core::get_instance(), 'modify_single_template' ), 99 );
160
+ }
161
+
162
+ add_action( 'mp_library', array( Shortcode::get_instance(), 'integration_motopress' ), 20, 1 );
163
+
164
+ Core::get_instance()->init_plugin_version();
165
+
166
+ add_filter( 'body_class', array( $this, 'browser_body_class' ) );
167
+ add_filter( 'the_tags', array( $this->get( 'events' ), 'the_tags' ), 10, 5 );
168
+ add_filter( 'the_category', array( $this->get( 'events' ), 'the_category' ), 10, 3 );
169
+
170
+ if ( function_exists('register_block_type') ) {
171
+ new Timetable_Block();
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Hooks for admin panel
177
+ */
178
+ public function admin_init() {
179
+ //add buttons to mce
180
+ add_filter( "mce_external_plugins", array( $this, "mce_external_plugins" ) );
181
+ add_filter( 'mce_buttons', array( $this, "mce_buttons" ) );
182
+
183
+ Core::get_instance()->init_plugin_version();
184
+
185
+ add_action( 'before_delete_post', array( Post::get_instance(), 'before_delete_custom_post' ) );
186
+ add_action( 'add_meta_boxes', array( Post::get_instance(), 'add_meta_boxes' ) );
187
+ add_action( 'save_post', array( Post::get_instance(), 'save_custom_post' ), 40, 2 );
188
+ add_action( 'wp_ajax_route_url', array( Core::get_instance(), "wp_ajax_route_url" ) );
189
+ add_action( 'wp_ajax_install_plugin_ajax', array( Core::get_instance(), 'wp_ajax_install_plugin_ajax' ) );
190
+
191
+ register_importer( 'mptt-importer', 'Timetable', __( 'Import Timetable events, categories, tags and images.', 'mp-timetable' ), array( Import::get_instance(), 'import' ) );
192
+ }
193
+
194
+ /**
195
+ * Registered page in admin wp
196
+ */
197
+ public function admin_menu() {
198
+
199
+ //Timetable
200
+ add_menu_page( __( 'Timetable', 'mp-timetable' ), __( 'Timetable', 'mp-timetable' ),
201
+ 'edit_posts', 'edit.php?post_type=mp-event', '', 'dashicons-calendar', '59.51' );
202
+
203
+ //Events
204
+ add_submenu_page( 'edit.php?post_type=mp-event', __( 'Events', 'mp-timetable' ), __( 'Events', 'mp-timetable' ),
205
+ 'edit_posts', 'edit.php?post_type=mp-event' );
206
+
207
+ //Add Event
208
+ add_submenu_page( 'edit.php?post_type=mp-event', __( 'Add Event', 'mp-timetable' ), __( 'Add Event', 'mp-timetable' ),
209
+ 'edit_posts', 'post-new.php?post_type=mp-event' );
210
+
211
+ //Columns
212
+ add_submenu_page( 'edit.php?post_type=mp-event', __( 'Columns', 'mp-timetable' ), __( 'Columns', 'mp-timetable' ),
213
+ 'edit_posts', 'edit.php?post_type=mp-column' );
214
+
215
+ //Add Column
216
+ add_submenu_page( 'edit.php?post_type=mp-event', __( 'Add Column', 'mp-timetable' ), __( 'Add Column', 'mp-timetable' ),
217
+ 'edit_posts', 'post-new.php?post_type=mp-column' );
218
+
219
+ //Event Categories
220
+ add_submenu_page( 'edit.php?post_type=mp-event', __( 'Event Categories', 'mp-timetable' ), __( 'Event Categories', 'mp-timetable' ),
221
+ 'manage_categories', 'edit-tags.php?taxonomy=mp-event_category&amp;post_type=mp-event' );
222
+
223
+ //Event Tags
224
+ add_submenu_page( 'edit.php?post_type=mp-event', __( 'Event Tags', 'mp-timetable' ), __( 'Event Tags', 'mp-timetable' ),
225
+ 'manage_categories', 'edit-tags.php?taxonomy=mp-event_tag&amp;post_type=mp-event' );
226
+
227
+ //Settings
228
+ add_submenu_page( 'edit.php?post_type=mp-event', __( 'Settings', 'mp-timetable' ), __( 'Settings', 'mp-timetable' ),
229
+ 'manage_options', 'mptt-settings', array( $this->get_controller( 'settings' ), 'action_content' ) );
230
+
231
+ //Export / Import
232
+ add_submenu_page( 'edit.php?post_type=mp-event', __( 'Export / Import', 'mp-timetable' ), __( 'Export / Import', 'mp-timetable' ),
233
+ 'import', 'mptt-import', array( $this->get_controller( 'import' ), 'action_content' ) );
234
+
235
+ //Help
236
+ add_submenu_page( 'edit.php?post_type=mp-event', __( 'Help & Shortcode', 'mp-timetable' ), __( 'Help & Shortcode', 'mp-timetable' ),
237
+ 'edit_posts', 'mptt-help', array( $this->get_controller( 'help' ), 'action_content' ) );
238
+ }
239
+
240
+ /**
241
+ * Connect js for MCE editor
242
+ *
243
+ * @param $plugin_array
244
+ *
245
+ * @return mixed
246
+ */
247
+ public function mce_external_plugins( $plugin_array ) {
248
+ $path = Mp_Time_Table::get_plugin_url( 'media/js/mce-timeTable-buttons' . $this->get_prefix() . '.js' );
249
+ $plugin_array[ 'mp_timetable' ] = $path;
250
+
251
+ return $plugin_array;
252
+ }
253
+
254
+ /**
255
+ * Add button in MCE editor
256
+ *
257
+ * @param $buttons
258
+ *
259
+ * @return mixed
260
+ */
261
+ public function mce_buttons( $buttons ) {
262
+ array_push( $buttons, 'addTimeTableButton' );
263
+
264
+ return $buttons;
265
+ }
266
+
267
+ /**
268
+ * Browser body class
269
+ *
270
+ * @param $classes
271
+ *
272
+ * @return array
273
+ */
274
+ public function browser_body_class( $classes ) {
275
+ global $is_IE;
276
+
277
+ if ( $is_IE ) {
278
+ $classes[] = 'mprm_ie_browser';
279
+ }
280
+
281
+ return $classes;
282
+ }
283
+
284
+ /**
285
+ * Set js
286
+ */
287
+ public function set_html_js_class() {
288
+ echo View::get_instance()->get_template_html('events/no-script');
289
+ }
290
+
291
+ /**
292
+ * Show row meta on the plugin screen.
293
+ *
294
+ * @return array
295
+ */
296
+ public static function plugin_row_meta( $links, $file ) {
297
+
298
+ if ( MP_TT_PLUGIN_BASENAME === $file ) {
299
+ $row_meta = array(
300
+ 'help' => '<a href="' . esc_url( admin_url('edit.php?post_type=mp-event&page=mptt-help') ) . '" aria-label="' . esc_attr__( 'Quick Start Guide', 'mp-timetable' ) . '">' .
301
+ esc_html__( 'Help', 'mp-timetable' ) . '</a>',
302
+ 'review' => '<a href="' . esc_url( 'https://wordpress.org/support/plugin/mp-timetable/reviews?rate=5#new-post' ) . '" aria-label="' . esc_attr__( 'Leave a Review', 'mp-timetable' ) . '" target="_blank">' . esc_html__( 'Leave a Review', 'mp-timetable' ) . ' &#9733;&#9733;&#9733;&#9733;&#9733;</a>',
303
+ );
304
+
305
+ return array_merge( $links, $row_meta );
306
+ }
307
+
308
+ return (array) $links;
309
+ }
310
+ }
classes/class-model.php CHANGED
@@ -1,41 +1,41 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- /**
6
- * Model class
7
- */
8
- class Model extends Core {
9
-
10
- protected static $instance;
11
-
12
- /**
13
- * @return Model
14
- */
15
- public static function get_instance() {
16
- if (null === self::$instance) {
17
- self::$instance = new self();
18
- }
19
- return self::$instance;
20
- }
21
-
22
- /**
23
- * Install models by type
24
- */
25
- public function install() {
26
- // include all core models
27
- Core::include_all(\Mp_Time_Table::get_plugin_part_path('classes/models'));
28
- }
29
-
30
- /**
31
- * Get return Array
32
- *
33
- * @param array $data
34
- * @param bool|false $success
35
- *
36
- * @return array
37
- */
38
- public function get_arr($data = array(), $success = false) {
39
- return array('success' => $success, 'data' => $data);
40
- }
41
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ /**
6
+ * Model class
7
+ */
8
+ class Model extends Core {
9
+
10
+ protected static $instance;
11
+
12
+ /**
13
+ * @return Model
14
+ */
15
+ public static function get_instance() {
16
+ if (null === self::$instance) {
17
+ self::$instance = new self();
18
+ }
19
+ return self::$instance;
20
+ }
21
+
22
+ /**
23
+ * Install models by type
24
+ */
25
+ public function install() {
26
+ // include all core models
27
+ Core::include_all(\Mp_Time_Table::get_plugin_part_path('classes/models'));
28
+ }
29
+
30
+ /**
31
+ * Get return Array
32
+ *
33
+ * @param array $data
34
+ * @param bool|false $success
35
+ *
36
+ * @return array
37
+ */
38
+ public function get_arr($data = array(), $success = false) {
39
+ return array('success' => $success, 'data' => $data);
40
+ }
41
+ }
classes/class-module.php CHANGED
@@ -1,20 +1,20 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- use Mp_Time_Table;
6
-
7
- /**
8
- * Class Module
9
- * @package mp_timetable\plugin_core\classes
10
- */
11
- class Module extends Core {
12
-
13
- /**
14
- * Install controllers
15
- */
16
- public static function install() {
17
- // include all core controllers
18
- Core::include_all(Mp_Time_Table::get_plugin_part_path('classes/modules'));
19
- }
20
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ use Mp_Time_Table;
6
+
7
+ /**
8
+ * Class Module
9
+ * @package mp_timetable\plugin_core\classes
10
+ */
11
+ class Module extends Core {
12
+
13
+ /**
14
+ * Install controllers
15
+ */
16
+ public static function install() {
17
+ // include all core controllers
18
+ Core::include_all(Mp_Time_Table::get_plugin_part_path('classes/modules'));
19
+ }
20
+ }
classes/class-offer.php CHANGED
@@ -1,216 +1,216 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- class Plugins_Offer {
6
-
7
- public function __construct() { }
8
-
9
- public static function activatePluginAjax() {
10
-
11
- check_ajax_referer( 'mptt-install-plugins', 'nonce' );
12
-
13
- $error = esc_html__( 'Could not activate the plugin.', 'mp-timetable' );
14
-
15
- if ( ! current_user_can( 'activate_plugins' ) ) {
16
-
17
- wp_send_json_error( $error );
18
- }
19
-
20
- if ( isset( $_POST[ 'plugin' ] ) ) {
21
-
22
- $plugin = sanitize_text_field( wp_unslash( $_POST['plugin'] ) );
23
- $activate = activate_plugins( $plugin );
24
-
25
- if ( ! is_wp_error( $activate ) ) {
26
- wp_send_json_success(
27
- [
28
- 'is_activated' => true
29
- ]
30
- );
31
- }
32
- }
33
-
34
- wp_send_json_error( $error );
35
- }
36
-
37
- public static function installPluginAjax() {
38
-
39
- check_ajax_referer( 'mptt-install-plugins', 'nonce' );
40
-
41
- $plugin = sanitize_text_field( wp_unslash( $_POST['plugin'] ) );
42
- $slug = strtok( $plugin, '/' );
43
-
44
- if ( empty( $_POST[ 'plugin' ] ) ) {
45
- wp_send_json_error( esc_html__( 'Could not install the plugin.', 'mp-timetable' ) );
46
- }
47
-
48
- if ( ! current_user_can( 'install_plugins' ) ) {
49
- wp_send_json_error( esc_html__( 'Sorry, you are not allowed to install plugins on this site.', 'mp-timetable' ) );
50
- }
51
-
52
- require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
53
- include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
54
-
55
- $api = plugins_api(
56
- 'plugin_information',
57
- array(
58
- 'slug' => sanitize_key( $slug ),
59
- 'fields' => array(
60
- 'sections' => false,
61
- ),
62
- )
63
- );
64
-
65
- if ( is_wp_error( $api ) ) {
66
-
67
- wp_send_json_error( $api->get_error_message() );
68
- }
69
-
70
- $skin = new \WP_Ajax_Upgrader_Skin();
71
- $upgrader = new \Plugin_Upgrader( $skin );
72
- $result = $upgrader->install( $api->download_link );
73
-
74
- wp_cache_flush();
75
-
76
- if ( is_wp_error( $result ) ) {
77
-
78
- wp_send_json_error( $result->get_error_message() );
79
- } elseif ( is_wp_error( $skin->result ) ) {
80
-
81
- wp_send_json_error( $skin->result->get_error_message() );
82
- } elseif ( $skin->get_errors()->has_errors() ) {
83
-
84
- wp_send_json_error( $skin->get_error_messages() );
85
- } elseif ( is_null( $result ) ) {
86
-
87
- global $wp_filesystem;
88
-
89
- $error = esc_html__( 'Unable to connect to the filesystem. Please confirm your credentials.' );
90
-
91
- if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
92
- $error = esc_html__( $wp_filesystem->errors->get_error_message() );
93
- }
94
-
95
- wp_send_json_error( $error );
96
- }
97
-
98
- $install_status = install_plugin_install_status( $api );
99
-
100
- if ( is_plugin_inactive( $install_status[ 'file' ] ) ) {
101
- wp_send_json_success(
102
- [
103
- 'is_activated' => false
104
- ]
105
- );
106
- }
107
-
108
- wp_send_json_error( esc_html__( 'Could not install the plugin.', 'mp-timetable' ) );
109
- }
110
-
111
- private function getPluginLists() {
112
-
113
- $plugins = array(
114
- 'getwid' => array(
115
- 'slug' => 'getwid',
116
- 'name' => 'Getwid: 40+ Free Gutenberg Blocks',
117
- 'path' => 'getwid/getwid.php',
118
- 'icon' => 'https://ps.w.org/getwid/assets/icon.svg',
119
- 'description' => 'Getwid is a collection of 40+ Gutenberg blocks that greatly extends the library of existing core WordPress blocks and 35+ unique pre-made block templates for the Block Editor.'
120
- ),
121
- 'stratum' => array(
122
- 'slug' => 'stratum',
123
- 'name' => 'Stratum: 20+ Free Elementor Widgets',
124
- 'path' => 'stratum/stratum.php',
125
- 'icon' => 'https://ps.w.org/stratum/assets/icon.svg',
126
- 'description' => 'Stratum is a free collection of 20+ Elementor addons with the aim of enhancing the existing widget functionality of your favorite page builder.'
127
- ),
128
- 'hotel-booking' => array(
129
- 'slug' => 'motopress-hotel-booking-lite',
130
- 'name' => 'Hotel Booking: WordPress Booking Plugin',
131
- 'path' => 'motopress-hotel-booking-lite/motopress-hotel-booking.php',
132
- 'icon' => 'https://ps.w.org/motopress-hotel-booking-lite/assets/icon-128x128.png',
133
- 'description' => 'Hotel Booking plugin by MotoPress is the ultimate WordPress property rental system with a real lodging business in mind.'
134
- )
135
- );
136
-
137
- return $plugins;
138
- }
139
-
140
- private function getPluginInstallationLink( $slug ) {
141
-
142
- $action = 'install-plugin';
143
-
144
- return wp_nonce_url(
145
- add_query_arg(
146
- array(
147
- 'action' => $action,
148
- 'plugin' => $slug
149
- ),
150
- admin_url( 'update.php' )
151
- ),
152
- $action.'_'.$slug
153
- );
154
- }
155
-
156
- // check status
157
- private function getPluginData( $plugin ) {
158
-
159
- if ( array_key_exists( $plugin['path'], get_plugins() ) ) {
160
-
161
- if ( is_plugin_active( $plugin['path'] ) ) {
162
- $plugin['status_text'] = esc_html__( 'Active', 'mp-timetable' );
163
- $plugin['status_class'] = 'active';
164
- $plugin['action_class'] = 'button button-secondary disabled';
165
- $plugin['action_text'] = esc_html__( 'Activated', 'mp-timetable' );
166
- } else {
167
- $plugin['status_text'] = esc_html__( 'Inactive', 'mp-timetable' );
168
- $plugin['status_class'] = 'inactive';
169
- $plugin['action_class'] = 'button button-secondary';
170
- $plugin['action_text'] = esc_html__( 'Activate', 'mp-timetable' );
171
- }
172
- } else {
173
- $plugin['status_text'] = esc_html__( 'Not Installed', 'mp-timetable' );
174
- $plugin['status_class'] = 'not-installed';
175
- $plugin['action_class'] = 'button button-primary';
176
- $plugin['action_text'] = esc_html__( 'Install Plugin', 'mp-timetable' );
177
- }
178
-
179
- return $plugin;
180
- }
181
-
182
- public function render() {
183
- ?>
184
- <div class="motopress-offer-secondary">
185
-
186
- <h2>More free plugins for you</h2>
187
- <?php
188
- foreach ( $this->getPluginLists() as $key => $plugin ) :
189
-
190
- $plugin = $this->getPluginData( $plugin );
191
- ?>
192
- <div class="plugin-container">
193
- <div class="plugin-item">
194
- <div class="details">
195
- <img src="<?php echo esc_url( $plugin['icon'] ); ?>">
196
- <h5 class="plugin-name"><?php echo esc_html( $plugin['name'] ); ?></h5>
197
- <p class="plugin-description"><?php echo esc_html( $plugin['description'] ); ?></p>
198
- </div>
199
- <div class="actions">
200
- <div class="status">
201
- <strong>Status: <span class="status-label <?php echo esc_attr( $plugin['status_class'] ); ?>">
202
- <?php echo esc_html( $plugin['status_text'] ); ?></span></strong>
203
- </div>
204
- <div class="action-button">
205
- <button data-path="<?php echo esc_attr( $plugin[ 'path' ] ); ?>" class="<?php echo esc_attr( $plugin['action_class'] ); ?>">
206
- <?php echo esc_html( $plugin['action_text'] ); ?>
207
- </button>
208
- </div>
209
- </div>
210
- </div>
211
- </div>
212
- <?php endforeach; ?>
213
- </div>
214
- <?php
215
- }
216
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ class Plugins_Offer {
6
+
7
+ public function __construct() { }
8
+
9
+ public static function activatePluginAjax() {
10
+
11
+ check_ajax_referer( 'mptt-install-plugins', 'nonce' );
12
+
13
+ $error = esc_html__( 'Could not activate the plugin.', 'mp-timetable' );
14
+
15
+ if ( ! current_user_can( 'activate_plugins' ) ) {
16
+
17
+ wp_send_json_error( $error );
18
+ }
19
+
20
+ if ( isset( $_POST[ 'plugin' ] ) ) {
21
+
22
+ $plugin = sanitize_text_field( wp_unslash( $_POST['plugin'] ) );
23
+ $activate = activate_plugins( $plugin );
24
+
25
+ if ( ! is_wp_error( $activate ) ) {
26
+ wp_send_json_success(
27
+ [
28
+ 'is_activated' => true
29
+ ]
30
+ );
31
+ }
32
+ }
33
+
34
+ wp_send_json_error( $error );
35
+ }
36
+
37
+ public static function installPluginAjax() {
38
+
39
+ check_ajax_referer( 'mptt-install-plugins', 'nonce' );
40
+
41
+ $plugin = sanitize_text_field( wp_unslash( $_POST['plugin'] ) );
42
+ $slug = strtok( $plugin, '/' );
43
+
44
+ if ( empty( $_POST[ 'plugin' ] ) ) {
45
+ wp_send_json_error( esc_html__( 'Could not install the plugin.', 'mp-timetable' ) );
46
+ }
47
+
48
+ if ( ! current_user_can( 'install_plugins' ) ) {
49
+ wp_send_json_error( esc_html__( 'Sorry, you are not allowed to install plugins on this site.', 'mp-timetable' ) );
50
+ }
51
+
52
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
53
+ include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
54
+
55
+ $api = plugins_api(
56
+ 'plugin_information',
57
+ array(
58
+ 'slug' => sanitize_key( $slug ),
59
+ 'fields' => array(
60
+ 'sections' => false,
61
+ ),
62
+ )
63
+ );
64
+
65
+ if ( is_wp_error( $api ) ) {
66
+
67
+ wp_send_json_error( $api->get_error_message() );
68
+ }
69
+
70
+ $skin = new \WP_Ajax_Upgrader_Skin();
71
+ $upgrader = new \Plugin_Upgrader( $skin );
72
+ $result = $upgrader->install( $api->download_link );
73
+
74
+ wp_cache_flush();
75
+
76
+ if ( is_wp_error( $result ) ) {
77
+
78
+ wp_send_json_error( $result->get_error_message() );
79
+ } elseif ( is_wp_error( $skin->result ) ) {
80
+
81
+ wp_send_json_error( $skin->result->get_error_message() );
82
+ } elseif ( $skin->get_errors()->has_errors() ) {
83
+
84
+ wp_send_json_error( $skin->get_error_messages() );
85
+ } elseif ( is_null( $result ) ) {
86
+
87
+ global $wp_filesystem;
88
+
89
+ $error = esc_html__( 'Unable to connect to the filesystem. Please confirm your credentials.' );
90
+
91
+ if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
92
+ $error = esc_html__( $wp_filesystem->errors->get_error_message() );
93
+ }
94
+
95
+ wp_send_json_error( $error );
96
+ }
97
+
98
+ $install_status = install_plugin_install_status( $api );
99
+
100
+ if ( is_plugin_inactive( $install_status[ 'file' ] ) ) {
101
+ wp_send_json_success(
102
+ [
103
+ 'is_activated' => false
104
+ ]
105
+ );
106
+ }
107
+
108
+ wp_send_json_error( esc_html__( 'Could not install the plugin.', 'mp-timetable' ) );
109
+ }
110
+
111
+ private function getPluginLists() {
112
+
113
+ $plugins = array(
114
+ 'getwid' => array(
115
+ 'slug' => 'getwid',
116
+ 'name' => 'Getwid: 40+ Free Gutenberg Blocks',
117
+ 'path' => 'getwid/getwid.php',
118
+ 'icon' => 'https://ps.w.org/getwid/assets/icon.svg',
119
+ 'description' => 'Getwid is a collection of 40+ Gutenberg blocks that greatly extends the library of existing core WordPress blocks and 35+ unique pre-made block templates for the Block Editor.'
120
+ ),
121
+ 'stratum' => array(
122
+ 'slug' => 'stratum',
123
+ 'name' => 'Stratum: 20+ Free Elementor Widgets',
124
+ 'path' => 'stratum/stratum.php',
125
+ 'icon' => 'https://ps.w.org/stratum/assets/icon.svg',
126
+ 'description' => 'Stratum is a free collection of 20+ Elementor addons with the aim of enhancing the existing widget functionality of your favorite page builder.'
127
+ ),
128
+ 'hotel-booking' => array(
129
+ 'slug' => 'motopress-hotel-booking-lite',
130
+ 'name' => 'Hotel Booking: WordPress Booking Plugin',
131
+ 'path' => 'motopress-hotel-booking-lite/motopress-hotel-booking.php',
132
+ 'icon' => 'https://ps.w.org/motopress-hotel-booking-lite/assets/icon-128x128.png',
133
+ 'description' => 'Hotel Booking plugin by MotoPress is the ultimate WordPress property rental system with a real lodging business in mind.'
134
+ )
135
+ );
136
+
137
+ return $plugins;
138
+ }
139
+
140
+ private function getPluginInstallationLink( $slug ) {
141
+
142
+ $action = 'install-plugin';
143
+
144
+ return wp_nonce_url(
145
+ add_query_arg(
146
+ array(
147
+ 'action' => $action,
148
+ 'plugin' => $slug
149
+ ),
150
+ admin_url( 'update.php' )
151
+ ),
152
+ $action.'_'.$slug
153
+ );
154
+ }
155
+
156
+ // check status
157
+ private function getPluginData( $plugin ) {
158
+
159
+ if ( array_key_exists( $plugin['path'], get_plugins() ) ) {
160
+
161
+ if ( is_plugin_active( $plugin['path'] ) ) {
162
+ $plugin['status_text'] = esc_html__( 'Active', 'mp-timetable' );
163
+ $plugin['status_class'] = 'active';
164
+ $plugin['action_class'] = 'button button-secondary disabled';
165
+ $plugin['action_text'] = esc_html__( 'Activated', 'mp-timetable' );
166
+ } else {
167
+ $plugin['status_text'] = esc_html__( 'Inactive', 'mp-timetable' );
168
+ $plugin['status_class'] = 'inactive';
169
+ $plugin['action_class'] = 'button button-secondary';
170
+ $plugin['action_text'] = esc_html__( 'Activate', 'mp-timetable' );
171
+ }
172
+ } else {
173
+ $plugin['status_text'] = esc_html__( 'Not Installed', 'mp-timetable' );
174
+ $plugin['status_class'] = 'not-installed';
175
+ $plugin['action_class'] = 'button button-primary';
176
+ $plugin['action_text'] = esc_html__( 'Install Plugin', 'mp-timetable' );
177
+ }
178
+
179
+ return $plugin;
180
+ }
181
+
182
+ public function render() {
183
+ ?>
184
+ <div class="motopress-offer-secondary">
185
+
186
+ <h2>More free plugins for you</h2>
187
+ <?php
188
+ foreach ( $this->getPluginLists() as $key => $plugin ) :
189
+
190
+ $plugin = $this->getPluginData( $plugin );
191
+ ?>
192
+ <div class="plugin-container">
193
+ <div class="plugin-item">
194
+ <div class="details">
195
+ <img src="<?php echo esc_url( $plugin['icon'] ); ?>">
196
+ <h5 class="plugin-name"><?php echo esc_html( $plugin['name'] ); ?></h5>
197
+ <p class="plugin-description"><?php echo esc_html( $plugin['description'] ); ?></p>
198
+ </div>
199
+ <div class="actions">
200
+ <div class="status">
201
+ <strong>Status: <span class="status-label <?php echo esc_attr( $plugin['status_class'] ); ?>">
202
+ <?php echo esc_html( $plugin['status_text'] ); ?></span></strong>
203
+ </div>
204
+ <div class="action-button">
205
+ <button data-path="<?php echo esc_attr( $plugin[ 'path' ] ); ?>" class="<?php echo esc_attr( $plugin['action_class'] ); ?>">
206
+ <?php echo esc_html( $plugin['action_text'] ); ?>
207
+ </button>
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </div>
212
+ <?php endforeach; ?>
213
+ </div>
214
+ <?php
215
+ }
216
+ }
classes/class-permalinks.php CHANGED
@@ -1,138 +1,138 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- class Permalinks {
6
-
7
- /**
8
- * Permalink settings.
9
- *
10
- * @var array
11
- */
12
- private $permalinks = array();
13
-
14
- /**
15
- * Hook in tabs.
16
- */
17
- public function __construct() {
18
- $this->settings_init();
19
- $this->settings_save();
20
- }
21
-
22
- /**
23
- * Init our settings.
24
- */
25
- public function settings_init() {
26
- add_settings_section( 'mp-timetable-permalinks', __( 'Timetable Permalinks', 'mp-timetable' ), array( $this, 'settings' ), 'permalink' );
27
-
28
- add_settings_field(
29
- 'timetable_column_slug',
30
- __( 'Column base', 'mp-timetable' ),
31
- array( $this, 'timetable_column_slug_input' ),
32
- 'permalink',
33
- 'mp-timetable-permalinks'
34
- );
35
- add_settings_field(
36
- 'timetable_event_slug',
37
- __( 'Event base', 'mp-timetable' ),
38
- array( $this, 'timetable_event_slug_input' ),
39
- 'permalink',
40
- 'mp-timetable-permalinks'
41
- );
42
- add_settings_field(
43
- 'timetable_event_category_slug',
44
- __( 'Event Category base', 'mp-timetable' ),
45
- array( $this, 'timetable_event_category_slug_input' ),
46
- 'permalink',
47
- 'mp-timetable-permalinks'
48
- );
49
- add_settings_field(
50
- 'timetable_event_tag_slug',
51
- __( 'Event Tag base', 'mp-timetable' ),
52
- array( $this, 'timetable_event_tag_slug_input' ),
53
- 'permalink',
54
- 'mp-timetable-permalinks'
55
- );
56
-
57
- $this->permalinks = Core::get_instance()->get_permalink_structure();
58
- }
59
-
60
- /**
61
- * Show a Column slug input box.
62
- */
63
- public function timetable_column_slug_input() {
64
- ?>
65
- <input name="timetable_column_slug" type="text" class="regular-text" value="<?php echo esc_attr( $this->permalinks['column_base'] ); ?>" placeholder="timetable/column" />
66
- <?php
67
- }
68
-
69
- /**
70
- * Show an Event slug input box.
71
- */
72
- public function timetable_event_slug_input() {
73
- ?>
74
- <input name="timetable_event_slug" type="text" class="regular-text" value="<?php echo esc_attr( $this->permalinks['event_base'] ); ?>" placeholder="timetable/event" />
75
- <?php
76
- }
77
-
78
- /**
79
- * Show an Event Category slug input box.
80
- */
81
- public function timetable_event_category_slug_input() {
82
- ?>
83
- <input name="timetable_event_category_slug" type="text" class="regular-text" value="<?php echo esc_attr( $this->permalinks['event_category_base'] ); ?>" placeholder="timetable/category" />
84
- <?php
85
- }
86
-
87
- /**
88
- * Show an Event Tag slug input box.
89
- */
90
- public function timetable_event_tag_slug_input() {
91
- ?>
92
- <input name="timetable_event_tag_slug" type="text" class="regular-text" value="<?php echo esc_attr( $this->permalinks['event_tag_base'] ); ?>" placeholder="timetable/tag" />
93
- <?php
94
- }
95
-
96
- /**
97
- * Show the settings.
98
- */
99
- public function settings() {
100
- wp_nonce_field( 'timetable-permalinks', 'timetable-permalinks-nonce' );
101
- }
102
-
103
- /**
104
- * Save the settings.
105
- */
106
- public function settings_save() {
107
- if ( ! is_admin() ) {
108
- return;
109
- }
110
-
111
- // We need to save the options ourselves; settings api does not trigger save for the permalinks page.
112
- if ( isset( $_POST['permalink_structure'],
113
- $_POST['timetable-permalinks-nonce'],
114
- $_POST['timetable_column_slug'],
115
- $_POST['timetable_event_slug'],
116
- $_POST['timetable_event_category_slug'],
117
- $_POST['timetable_event_tag_slug']
118
- ) && wp_verify_nonce( sanitize_key( $_POST['timetable-permalinks-nonce'] ), 'timetable-permalinks' )
119
- ) { // WPCS: input var ok, sanitization ok.
120
-
121
- $permalinks = (array) get_option( 'mp_timetable_permalinks', array() );
122
-
123
- $permalinks['column_base'] = $this->sanitize_permalink( wp_unslash( $_POST['timetable_column_slug'] ) ); // WPCS: input var ok, sanitization ok.
124
- $permalinks['event_base'] = $this->sanitize_permalink( wp_unslash( $_POST['timetable_event_slug'] ) ); // WPCS: input var ok, sanitization ok.
125
- $permalinks['event_category_base'] = $this->sanitize_permalink( wp_unslash( $_POST['timetable_event_category_slug'] ) ); // WPCS: input var ok, sanitization ok.
126
- $permalinks['event_tag_base'] = $this->sanitize_permalink( wp_unslash( $_POST['timetable_event_tag_slug'] ) ); // WPCS: input var ok, sanitization ok.
127
-
128
- update_option( 'mp_timetable_permalinks', $permalinks );
129
- }
130
- }
131
-
132
- private function sanitize_permalink( $value ) {
133
-
134
- $value = esc_url_raw( trim( $value ) );
135
- $value = str_replace( 'http://', '', $value );
136
- return untrailingslashit( $value );
137
- }
138
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ class Permalinks {
6
+
7
+ /**
8
+ * Permalink settings.
9
+ *
10
+ * @var array
11
+ */
12
+ private $permalinks = array();
13
+
14
+ /**
15
+ * Hook in tabs.
16
+ */
17
+ public function __construct() {
18
+ $this->settings_init();
19
+ $this->settings_save();
20
+ }
21
+
22
+ /**
23
+ * Init our settings.
24
+ */
25
+ public function settings_init() {
26
+ add_settings_section( 'mp-timetable-permalinks', __( 'Timetable Permalinks', 'mp-timetable' ), array( $this, 'settings' ), 'permalink' );
27
+
28
+ add_settings_field(
29
+ 'timetable_column_slug',
30
+ __( 'Column base', 'mp-timetable' ),
31
+ array( $this, 'timetable_column_slug_input' ),
32
+ 'permalink',
33
+ 'mp-timetable-permalinks'
34
+ );
35
+ add_settings_field(
36
+ 'timetable_event_slug',
37
+ __( 'Event base', 'mp-timetable' ),
38
+ array( $this, 'timetable_event_slug_input' ),
39
+ 'permalink',
40
+ 'mp-timetable-permalinks'
41
+ );
42
+ add_settings_field(
43
+ 'timetable_event_category_slug',
44
+ __( 'Event Category base', 'mp-timetable' ),
45
+ array( $this, 'timetable_event_category_slug_input' ),
46
+ 'permalink',
47
+ 'mp-timetable-permalinks'
48
+ );
49
+ add_settings_field(
50
+ 'timetable_event_tag_slug',
51
+ __( 'Event Tag base', 'mp-timetable' ),
52
+ array( $this, 'timetable_event_tag_slug_input' ),
53
+ 'permalink',
54
+ 'mp-timetable-permalinks'
55
+ );
56
+
57
+ $this->permalinks = Core::get_instance()->get_permalink_structure();
58
+ }
59
+
60
+ /**
61
+ * Show a Column slug input box.
62
+ */
63
+ public function timetable_column_slug_input() {
64
+ ?>
65
+ <input name="timetable_column_slug" type="text" class="regular-text" value="<?php echo esc_attr( $this->permalinks['column_base'] ); ?>" placeholder="timetable/column" />
66
+ <?php
67
+ }
68
+
69
+ /**
70
+ * Show an Event slug input box.
71
+ */
72
+ public function timetable_event_slug_input() {
73
+ ?>
74
+ <input name="timetable_event_slug" type="text" class="regular-text" value="<?php echo esc_attr( $this->permalinks['event_base'] ); ?>" placeholder="timetable/event" />
75
+ <?php
76
+ }
77
+
78
+ /**
79
+ * Show an Event Category slug input box.
80
+ */
81
+ public function timetable_event_category_slug_input() {
82
+ ?>
83
+ <input name="timetable_event_category_slug" type="text" class="regular-text" value="<?php echo esc_attr( $this->permalinks['event_category_base'] ); ?>" placeholder="timetable/category" />
84
+ <?php
85
+ }
86
+
87
+ /**
88
+ * Show an Event Tag slug input box.
89
+ */
90
+ public function timetable_event_tag_slug_input() {
91
+ ?>
92
+ <input name="timetable_event_tag_slug" type="text" class="regular-text" value="<?php echo esc_attr( $this->permalinks['event_tag_base'] ); ?>" placeholder="timetable/tag" />
93
+ <?php
94
+ }
95
+
96
+ /**
97
+ * Show the settings.
98
+ */
99
+ public function settings() {
100
+ wp_nonce_field( 'timetable-permalinks', 'timetable-permalinks-nonce' );
101
+ }
102
+
103
+ /**
104
+ * Save the settings.
105
+ */
106
+ public function settings_save() {
107
+ if ( ! is_admin() ) {
108
+ return;
109
+ }
110
+
111
+ // We need to save the options ourselves; settings api does not trigger save for the permalinks page.
112
+ if ( isset( $_POST['permalink_structure'],
113
+ $_POST['timetable-permalinks-nonce'],
114
+ $_POST['timetable_column_slug'],
115
+ $_POST['timetable_event_slug'],
116
+ $_POST['timetable_event_category_slug'],
117
+ $_POST['timetable_event_tag_slug']
118
+ ) && wp_verify_nonce( sanitize_key( $_POST['timetable-permalinks-nonce'] ), 'timetable-permalinks' )
119
+ ) { // WPCS: input var ok, sanitization ok.
120
+
121
+ $permalinks = (array) get_option( 'mp_timetable_permalinks', array() );
122
+
123
+ $permalinks['column_base'] = $this->sanitize_permalink( wp_unslash( $_POST['timetable_column_slug'] ) ); // WPCS: input var ok, sanitization ok.
124
+ $permalinks['event_base'] = $this->sanitize_permalink( wp_unslash( $_POST['timetable_event_slug'] ) ); // WPCS: input var ok, sanitization ok.
125
+ $permalinks['event_category_base'] = $this->sanitize_permalink( wp_unslash( $_POST['timetable_event_category_slug'] ) ); // WPCS: input var ok, sanitization ok.
126
+ $permalinks['event_tag_base'] = $this->sanitize_permalink( wp_unslash( $_POST['timetable_event_tag_slug'] ) ); // WPCS: input var ok, sanitization ok.
127
+
128
+ update_option( 'mp_timetable_permalinks', $permalinks );
129
+ }
130
+ }
131
+
132
+ private function sanitize_permalink( $value ) {
133
+
134
+ $value = esc_url_raw( trim( $value ) );
135
+ $value = str_replace( 'http://', '', $value );
136
+ return untrailingslashit( $value );
137
+ }
138
+ }
classes/class-preprocessor.php CHANGED
@@ -1,182 +1,182 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- use mp_timetable\classes\libs\GUMP;
6
- use \Mp_Time_Table;
7
-
8
- class Preprocessor extends GUMP {
9
-
10
- protected static $instance;
11
-
12
- public static function get_instance() {
13
- if (null === self::$instance) {
14
- self::$instance = new self();
15
- }
16
- return self::$instance;
17
- }
18
-
19
- /**
20
- * Install Preprocessors
21
- */
22
- static function install() {
23
- Core::include_all( Mp_Time_Table::get_plugin_part_path('classes/preprocessors') );
24
- }
25
-
26
- /**
27
- * Call controller
28
- *
29
- * @param string $action
30
- * @param bool|false $controller
31
- *
32
- * @return mixed
33
- */
34
- public function call_controller($action = 'content', $controller = false) {
35
- if (empty($controller)) {
36
- trigger_error("Wrong controller ");
37
- }
38
- $path = Mp_Time_Table::get_plugin_part_path('classes/controllers/');
39
- // if controller exists
40
- if ('controller' != $controller && !file_exists("{$path}class-controller-{$controller}.php")) {
41
- $ControllerName = 'Controller_' . ucfirst($controller);
42
- if (class_exists($ControllerName)) {
43
- trigger_error("Wrong controller {$path}class-controller-{$controller}.php");
44
- }
45
- }
46
- $action = "action_$action";
47
- $controller = Core::get_instance()->get_state()->get_controller($controller);
48
- // if method exists
49
- if (method_exists($controller, $action)) {
50
- return $controller->$action();
51
- } else {
52
- trigger_error("Wrong {$action} in {$path}class-controller-{$controller}.php");
53
- }
54
- }
55
-
56
- /**
57
- * Progress
58
- *
59
- * @param array $params
60
- * @param $name
61
- * @param $type
62
- *
63
- * @return array
64
- */
65
- protected function progress(array $params, $name, $type) {
66
- $success = $this->run($params);
67
- if ($success !== false) {
68
- return Core::get_instance()->get_model($type)->$name($params);
69
- } else {
70
- $name = "on_error_{$name}";
71
- if (!method_exists($this, $name)) {
72
- $name = 'get_errors_array';
73
- }
74
- return array('success' => $success, 'data' => $this->$name());
75
- }
76
- }
77
-
78
- /**
79
- * Process the validation errors and return an array of errors with field names as keys.
80
- *
81
- * @param $convert_to_string
82
- *
83
- * @return array | null (if empty)
84
- */
85
- public function get_errors_array($convert_to_string = null) {
86
- if (empty($this->errors)) {
87
- return ($convert_to_string) ? null : array();
88
- }
89
-
90
- $resp = array();
91
-
92
- foreach ($this->errors as $e) {
93
- $field = ucwords(str_replace(array('_', '-'), chr(32), $e['field']));
94
- $param = $e['param'];
95
-
96
- // Let's fetch explicit field names if they exist
97
- if (array_key_exists($e['field'], self::$fields)) {
98
- $field = self::$fields[$e['field']];
99
- }
100
-
101
- switch ($e['rule']) {
102
- case 'mismatch' :
103
- $resp[$e['field']] = "There is no validation rule for $field";
104
- break;
105
- case 'validate_required':
106
- $resp[$e['field']] = "Enter $field field";
107
- break;
108
- case 'validate_valid_email':
109
- $resp[$e['field']] = "Enter a valid email address";
110
- break;
111
- case 'validate_max_len':
112
- $resp[$e['field']] = "The $field field needs to be $param or shorter in length";
113
- break;
114
- case 'validate_min_len':
115
- $resp[$e['field']] = "The $field field needs to be $param or longer in length";
116
- break;
117
- case 'validate_exact_len':
118
- $resp[$e['field']] = "The $field field needs to be exactly $param characters in length";
119
- break;
120
- case 'validate_alpha':
121
- $resp[$e['field']] = "The $field field may only contain alpha characters(a-z)";
122
- break;
123
- case 'validate_alpha_numeric':
124
- $resp[$e['field']] = "The $field field may only contain alpha-numeric characters";
125
- break;
126
- case 'validate_alpha_dash':
127
- $resp[$e['field']] = "The $field field may only contain alpha characters &amp; dashes";
128
- break;
129
- case 'validate_numeric':
130
- $resp[$e['field']] = "The $field field may only contain numeric characters";
131
- break;
132
- case 'validate_integer':
133
- $resp[$e['field']] = "The $field field may only contain a numeric value";
134
- break;
135
- case 'validate_boolean':
136
- $resp[$e['field']] = "The $field field may only contain a true or false value";
137
- break;
138
- case 'validate_float':
139
- $resp[$e['field']] = "The $field field may only contain a float value";
140
- break;
141
- case 'validate_valid_url':
142
- $resp[$e['field']] = "The $field field is required to be a valid URL";
143
- break;
144
- case 'validate_url_exists':
145
- $resp[$e['field']] = "The $field URL does not exist";
146
- break;
147
- case 'validate_valid_ip':
148
- $resp[$e['field']] = "The $field field needs to contain a valid IP address";
149
- break;
150
- case 'validate_valid_cc':
151
- $resp[$e['field']] = "The $field field needs to contain a valid credit card number";
152
- break;
153
- case 'validate_valid_name':
154
- $resp[$e['field']] = "The $field field needs to contain a valid human name";
155
- break;
156
- case 'validate_contains':
157
- $resp[$e['field']] = "The $field field needs to contain one of these values: " . implode(', ', $param);
158
- break;
159
- case 'validate_street_address':
160
- $resp[$e['field']] = "The $field field needs to be a valid street address";
161
- break;
162
- case 'validate_date':
163
- $resp[$e['field']] = "The $field field needs to be a valid date";
164
- break;
165
- case 'validate_min_numeric':
166
- $resp[$e['field']] = "The $field field needs to be a numeric value, equal to, or higher than $param";
167
- break;
168
- case 'validate_max_numeric':
169
- $resp[$e['field']] = "The $field field needs to be a numeric value, equal to, or lower than $param";
170
- break;
171
- case 'validate_min_age':
172
- $resp[$e['field']] = "The $field field needs to have an age greater than or equal to $param";
173
- break;
174
- default:
175
- $resp[$e['field']] = "The $field field is invalid";
176
- }
177
- }
178
-
179
- return $resp;
180
- }
181
-
182
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ use mp_timetable\classes\libs\GUMP;
6
+ use \Mp_Time_Table;
7
+
8
+ class Preprocessor extends GUMP {
9
+
10
+ protected static $instance;
11
+
12
+ public static function get_instance() {
13
+ if (null === self::$instance) {
14
+ self::$instance = new self();
15
+ }
16
+ return self::$instance;
17
+ }
18
+
19
+ /**
20
+ * Install Preprocessors
21
+ */
22
+ static function install() {
23
+ Core::include_all( Mp_Time_Table::get_plugin_part_path('classes/preprocessors') );
24
+ }
25
+
26
+ /**
27
+ * Call controller
28
+ *
29
+ * @param string $action
30
+ * @param bool|false $controller
31
+ *
32
+ * @return mixed
33
+ */
34
+ public function call_controller($action = 'content', $controller = false) {
35
+ if (empty($controller)) {
36
+ trigger_error("Wrong controller ");
37
+ }
38
+ $path = Mp_Time_Table::get_plugin_part_path('classes/controllers/');
39
+ // if controller exists
40
+ if ('controller' != $controller && !file_exists("{$path}class-controller-{$controller}.php")) {
41
+ $ControllerName = 'Controller_' . ucfirst($controller);
42
+ if (class_exists($ControllerName)) {
43
+ trigger_error("Wrong controller {$path}class-controller-{$controller}.php");
44
+ }
45
+ }
46
+ $action = "action_$action";
47
+ $controller = Core::get_instance()->get_state()->get_controller($controller);
48
+ // if method exists
49
+ if (method_exists($controller, $action)) {
50
+ return $controller->$action();
51
+ } else {
52
+ trigger_error("Wrong {$action} in {$path}class-controller-{$controller}.php");
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Progress
58
+ *
59
+ * @param array $params
60
+ * @param $name
61
+ * @param $type
62
+ *
63
+ * @return array
64
+ */
65
+ protected function progress(array $params, $name, $type) {
66
+ $success = $this->run($params);
67
+ if ($success !== false) {
68
+ return Core::get_instance()->get_model($type)->$name($params);
69
+ } else {
70
+ $name = "on_error_{$name}";
71
+ if (!method_exists($this, $name)) {
72
+ $name = 'get_errors_array';
73
+ }
74
+ return array('success' => $success, 'data' => $this->$name());
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Process the validation errors and return an array of errors with field names as keys.
80
+ *
81
+ * @param $convert_to_string
82
+ *
83
+ * @return array | null (if empty)
84
+ */
85
+ public function get_errors_array($convert_to_string = null) {
86
+ if (empty($this->errors)) {
87
+ return ($convert_to_string) ? null : array();
88
+ }
89
+
90
+ $resp = array();
91
+
92
+ foreach ($this->errors as $e) {
93
+ $field = ucwords(str_replace(array('_', '-'), chr(32), $e['field']));
94
+ $param = $e['param'];
95
+
96
+ // Let's fetch explicit field names if they exist
97
+ if (array_key_exists($e['field'], self::$fields)) {
98
+ $field = self::$fields[$e['field']];
99
+ }
100
+
101
+ switch ($e['rule']) {
102
+ case 'mismatch' :
103
+ $resp[$e['field']] = "There is no validation rule for $field";
104
+ break;
105
+ case 'validate_required':
106
+ $resp[$e['field']] = "Enter $field field";
107
+ break;
108
+ case 'validate_valid_email':
109
+ $resp[$e['field']] = "Enter a valid email address";
110
+ break;
111
+ case 'validate_max_len':
112
+ $resp[$e['field']] = "The $field field needs to be $param or shorter in length";
113
+ break;
114
+ case 'validate_min_len':
115
+ $resp[$e['field']] = "The $field field needs to be $param or longer in length";
116
+ break;
117
+ case 'validate_exact_len':
118
+ $resp[$e['field']] = "The $field field needs to be exactly $param characters in length";
119
+ break;
120
+ case 'validate_alpha':
121
+ $resp[$e['field']] = "The $field field may only contain alpha characters(a-z)";
122
+ break;
123
+ case 'validate_alpha_numeric':
124
+ $resp[$e['field']] = "The $field field may only contain alpha-numeric characters";
125
+ break;
126
+ case 'validate_alpha_dash':
127
+ $resp[$e['field']] = "The $field field may only contain alpha characters &amp; dashes";
128
+ break;
129
+ case 'validate_numeric':
130
+ $resp[$e['field']] = "The $field field may only contain numeric characters";
131
+ break;
132
+ case 'validate_integer':
133
+ $resp[$e['field']] = "The $field field may only contain a numeric value";
134
+ break;
135
+ case 'validate_boolean':
136
+ $resp[$e['field']] = "The $field field may only contain a true or false value";
137
+ break;
138
+ case 'validate_float':
139
+ $resp[$e['field']] = "The $field field may only contain a float value";
140
+ break;
141
+ case 'validate_valid_url':
142
+ $resp[$e['field']] = "The $field field is required to be a valid URL";
143
+ break;
144
+ case 'validate_url_exists':
145
+ $resp[$e['field']] = "The $field URL does not exist";
146
+ break;
147
+ case 'validate_valid_ip':
148
+ $resp[$e['field']] = "The $field field needs to contain a valid IP address";
149
+ break;
150
+ case 'validate_valid_cc':
151
+ $resp[$e['field']] = "The $field field needs to contain a valid credit card number";
152
+ break;
153
+ case 'validate_valid_name':
154
+ $resp[$e['field']] = "The $field field needs to contain a valid human name";
155
+ break;
156
+ case 'validate_contains':
157
+ $resp[$e['field']] = "The $field field needs to contain one of these values: " . implode(', ', $param);
158
+ break;
159
+ case 'validate_street_address':
160
+ $resp[$e['field']] = "The $field field needs to be a valid street address";
161
+ break;
162
+ case 'validate_date':
163
+ $resp[$e['field']] = "The $field field needs to be a valid date";
164
+ break;
165
+ case 'validate_min_numeric':
166
+ $resp[$e['field']] = "The $field field needs to be a numeric value, equal to, or higher than $param";
167
+ break;
168
+ case 'validate_max_numeric':
169
+ $resp[$e['field']] = "The $field field needs to be a numeric value, equal to, or lower than $param";
170
+ break;
171
+ case 'validate_min_age':
172
+ $resp[$e['field']] = "The $field field needs to have an age greater than or equal to $param";
173
+ break;
174
+ default:
175
+ $resp[$e['field']] = "The $field field is invalid";
176
+ }
177
+ }
178
+
179
+ return $resp;
180
+ }
181
+
182
+ }
classes/class-shortcode.php CHANGED
@@ -1,401 +1,401 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- use mp_timetable\classes\models\Column;
6
- use mp_timetable\classes\models\Events;
7
-
8
- /**
9
- * Class Shortcode
10
- *
11
- * @package mp_timetable\plugin_core\classes
12
- */
13
- class Shortcode extends Core {
14
-
15
- protected static $instance;
16
-
17
- /**
18
- * Shortcode constructor.
19
- */
20
- public function __construct() {
21
- $this->init_plugin_version();
22
- parent::__construct();
23
- }
24
-
25
- /**
26
- * Return instance
27
- *
28
- * @return Shortcode
29
- */
30
- public static function get_instance() {
31
- if ( null === self::$instance ) {
32
- self::$instance = new self();
33
- }
34
-
35
- return self::$instance;
36
- }
37
-
38
- /**
39
- * Init
40
- */
41
- public function init() {
42
- add_shortcode( 'mp-timetable', array( $this, "show_shortcode" ) );
43
- }
44
-
45
- /**
46
- * Show shortcode
47
- *
48
- * @param $params
49
- *
50
- * @return mixed
51
- */
52
- public function show_shortcode( $params ) {
53
- global $mptt_shortcode_data;
54
-
55
- $this->add_plugin_js( 'shortcode' );
56
-
57
- if ( empty( $params ) ) {
58
- $params = array();
59
- }
60
-
61
- $mptt_shortcode_data = array();
62
-
63
- $mptt_shortcode_data[ 'params' ] = $params = shortcode_atts( array(
64
- 'events' => "",
65
- 'event_categ' => "",
66
- 'col' => "",
67
- 'increment' => "1", // 1 | 0.5 | 0.25
68
- 'view' => "dropdown_list", // dropdown_list | tabs
69
- 'view_sort' => "", // '' | menu_order || post_title
70
- 'label' => __( "All Events", 'mp-timetable' ),
71
- 'hide_label' => "0",
72
- 'title' => "0",
73
- 'time' => "0",
74
- 'group' => "0",
75
- 'sub-title' => "0",
76
- 'description' => "0",
77
- 'user' => "0",
78
- 'hide_hrs' => "0",
79
- 'hide_empty_rows' => "1",
80
- 'text_align_vertical' => "default", // default | top | middle | bottom
81
- 'row_height' => "45",
82
- 'font_size' => "",
83
- 'disable_event_url' => "0",
84
- 'text_align' => "center", // left | center | right
85
- 'id' => "",
86
- 'custom_class' => "",
87
- 'responsive' => "1",
88
- 'table_layout' => "" // default | auto | fixed
89
- ), $params );
90
-
91
- $mptt_shortcode_data[ 'events_data' ] = $this->get_shortcode_events( $params );
92
-
93
- if ( ! empty( $mptt_shortcode_data[ 'events_data' ] ) ) {
94
- if ( isset($mptt_shortcode_data[ 'events_data' ][ 'unique_events' ]) ) {
95
- $mptt_shortcode_data[ 'unique_events' ] = $mptt_shortcode_data[ 'events_data' ][ 'unique_events' ];
96
- }
97
- if ( isset( $mptt_shortcode_data[ 'events_data' ][ 'events' ] ) ) {
98
- unset( $mptt_shortcode_data[ 'events_data' ][ 'events' ] );
99
- }
100
- }
101
-
102
- if ( empty( $mptt_shortcode_data[ 'events_data' ][ 'events' ] ) && empty( $mptt_shortcode_data[ 'events_data' ][ 'column' ] ) ) {
103
- return $this->get_view()->get_template_html( 'shortcodes/empty-search-events', array() );
104
- } else {
105
- return $this->get_view()->get_template_html( 'shortcodes/index-timetable', array() );
106
- }
107
- }
108
-
109
- /**
110
- * Get shortcode events
111
- *
112
- * @param $params
113
- *
114
- * @return array
115
- */
116
- public function get_shortcode_events( $params ) {
117
- $columns_ids = $events_categ = $events = array();
118
-
119
- $step = $params[ 'increment' ] === '1' ? 60 : ( 60 * $params[ 'increment' ] );
120
-
121
- $events_data = array( 'events' => array(), 'column' => array() );
122
-
123
- //get event by id
124
- if ( ! empty( $params[ 'events' ] ) && empty( $params[ 'col' ] ) && empty( $params[ 'event_categ' ] ) ) {
125
- $events = $this->get( 'events' )->get_events_data( array( 'column' => 'event_id', 'list' => $params[ 'events' ] ) );
126
- }
127
-
128
- // get event by category
129
- if ( ! empty( $params[ 'event_categ' ] ) ) {
130
- $events_categ = $this->get( 'events' )->get_events_data_by_category( $params[ 'event_categ' ] );
131
- }
132
-
133
- // get event by column
134
- if ( ! empty( $params[ 'col' ] ) && empty( $params[ 'event_categ' ] ) && empty( $params[ 'events' ] ) ) {
135
- $events = $this->get( 'events' )->get_events_data( array( 'column' => 'column_id', 'list' => $params[ 'col' ] ) );
136
- }
137
-
138
- //Columns + events
139
- if ( ! empty( $params[ 'events' ] ) && ! empty( $params[ 'col' ] ) && empty( $params[ 'event_categ' ] ) ) {
140
- $events = $this->get( 'events' )->get_events_data( array( 'column' => array( 'column_id', 'event_id' ), 'list' => array( 'column_id' => $params[ 'col' ], 'event_id' => $params[ 'events' ] ) ) );
141
- }
142
-
143
- //Events + Categories
144
- if ( ! empty( $params[ 'events' ] ) && ! empty( $params[ 'event_categ' ] ) && empty( $params[ 'col' ] ) ) {
145
- $events = $this->get( 'events' )->get_events_data( array( 'column' => 'event_id', 'list' => $params[ 'events' ] ) );
146
- }
147
-
148
- //if all params empty
149
- if ( empty( $params[ 'col' ] ) && empty( $params[ 'event_categ' ] ) && empty( $params[ 'events' ] ) ) {
150
- $events = $this->get( 'events' )->get_events_data( array( 'column' => 'event_id', 'all' => true ) );
151
- $events_categ = $this->get( 'events' )->get_events_data_by_category( '' );
152
- }
153
- // select all event option
154
- if ( ! empty( $params[ 'col' ] ) && ! empty( $params[ 'event_categ' ] ) && ! empty( $params[ 'events' ] ) ) {
155
- $events = $this->get( 'events' )->get_events_data( array( 'column' => 'event_id', 'list' => $params[ 'events' ] ) );
156
- }
157
-
158
- $events_data[ 'events' ] = array_merge( $events_data[ 'events' ], $events_categ, $events );
159
-
160
- //Create column array;
161
- if ( empty( $params[ 'col' ] ) ) {
162
- foreach ( $events_data[ 'events' ] as $event ) {
163
- $columns_ids[] = $event->column_id;
164
- }
165
- $columns_ids = array_unique( $columns_ids );
166
- } else {
167
- $columns_ids = explode( ',', $params[ 'col' ] );
168
- }
169
-
170
- //Sort column by menu order
171
- $events_data[ 'column' ] = $this->get( 'column' )->get_all_column( array( 'post__in' => $columns_ids ) );
172
-
173
- if ( ! empty( $events_data[ 'column' ] ) ) {
174
- foreach ( $events_data[ 'column' ] as $key => $column ) {
175
- $column_events = array();
176
- // add to column events
177
-
178
- foreach ( $events_data[ 'events' ] as $event_key => $event ) {
179
- if ( $column->ID == $event->column_id ) {
180
- $start_index = $this->get_event_index( $params[ 'increment' ], $event->event_start, $step, 'start' );
181
- $end_index = $this->get_event_index( $params[ 'increment' ], $event->event_end, $step, 'end' );
182
- $event->output = false;
183
- $event->start_index = $start_index;
184
- $event->end_index = ( $end_index < $start_index ) ? $this->get_event_index( $params[ 'increment' ], '23:59', $step, 'end' ) : $end_index;
185
- $column_events[ $event->id ] = $event;
186
- $events_data[ 'unique_events' ][ $event->event_id ] = $event;
187
- }
188
- }
189
-
190
- //sort by start date
191
- $column_events = $this->get_model( 'events' )->sort_by_param( $column_events );
192
-
193
- $events_data[ 'column_events' ][ $column->ID ] = $column_events;
194
- }
195
- } else {
196
- $events_data[ 'events' ] = array();
197
- }
198
-
199
- return $events_data;
200
- }
201
-
202
- /**
203
- * @param $increment
204
- * @param $time
205
- * @param $step
206
- * @param $type
207
- *
208
- * @return float|int
209
- */
210
- protected function get_event_index( $increment, $time, $step, $type ) {
211
- if ( $type == 'start' ) {
212
- $index = date( 'G', strtotime( $time ) ) / $increment + floor( date( 'i', strtotime( $time ) ) / $step );
213
- } else {
214
- $index = date( 'G', strtotime( $time ) ) / $increment + ceil( date( 'i', strtotime( $time ) ) / $step );
215
- }
216
-
217
- return $index;
218
- }
219
-
220
- /**
221
- * Get events Id
222
- *
223
- * @param array $data
224
- *
225
- * @return string
226
- */
227
- public function get_event_ids( array $data = array() ) {
228
- $ids_list = array();
229
- if ( empty( $data ) ) {
230
- return '';
231
- } else {
232
- foreach ( $data as $event ) {
233
- $ids_list[] = $event->id;
234
- }
235
-
236
- return implode( ',', $ids_list );
237
- }
238
- }
239
-
240
- /**
241
- * Integration in motopress
242
- *
243
- * @param $motopressCELibrary
244
- */
245
- public function integration_motopress( $motopressCELibrary ) {
246
- $columns = $this->create_list_motopress( Column::get_instance()->get_all_column() );
247
- $events = $this->create_list_motopress( Events::get_instance()->get_all_events() );
248
-
249
- $categories = get_terms( 'mp-event_category', 'orderby=count&hide_empty=0' );
250
- $categories = $this->create_list_motopress( $categories, 'term' );
251
-
252
- $attributes = array(
253
- 'col' => array(
254
- 'type' => 'select-multiple',
255
- 'label' => __( 'Column', 'mp-timetable' ),
256
- 'list' => $columns
257
- ),
258
- 'events' => array(
259
- 'type' => 'select-multiple',
260
- 'label' => __( 'Events', 'mp-timetable' ),
261
- 'list' => $events
262
- ),
263
- 'event_categ' => array(
264
- 'type' => 'select-multiple',
265
- 'label' => __( 'Event categories', 'mp-timetable' ),
266
- 'list' => $categories
267
- ),
268
- 'increment' => array(
269
- 'type' => 'select',
270
- 'label' => __( 'Hour measure', 'mp-timetable' ),
271
- 'list' => array( '1' => __( 'Hour (1h)', 'mp-timetable' ), '0.5' => __( 'Half hour (30min)', 'mp-timetable' ), '0.25' => __( 'Quarter hour (15min)', 'mp-timetable' ) )
272
- ),
273
- 'view' => array(
274
- 'type' => 'select',
275
- 'label' => __( 'Filter style', 'mp-timetable' ),
276
- 'list' => array( 'dropdown_list' => __( 'Dropdown list', 'mp-timetable' ), 'tabs' => __( 'Tabs', 'mp-timetable' ) )
277
- ),
278
- 'view_sort' => array(
279
- 'type' => 'select',
280
- 'label' => __( 'Order of items in filter', 'mp-timetable' ),
281
- 'list' => array( '' => __( 'Default', 'mp-timetable' ), 'menu_order' => __( 'Menu Order', 'mp-timetable' ), 'post_title' => __( 'Title', 'mp-timetable' ) )
282
- ),
283
- 'label' => array(
284
- 'type' => 'text',
285
- 'label' => __( 'Filter label', 'mp-timetable' ),
286
- 'default' => __( 'All Events', 'mp-timetable' )
287
- ),
288
- 'hide_label' => array(
289
- 'type' => 'select',
290
- 'label' => __( "Hide 'All Events' view", 'mp-timetable' ),
291
- 'list' => array( '0' => __( 'No', 'mp-timetable' ), '1' => __( 'Yes', 'mp-timetable' ) )
292
- ),
293
- 'hide_hrs' => array(
294
- 'type' => 'select',
295
- 'label' => __( 'Hide first (hours) column', 'mp-timetable' ),
296
- 'list' => array( '0' => __( 'No', 'mp-timetable' ), '1' => __( 'Yes', 'mp-timetable' ) )
297
- ),
298
- 'hide_empty_rows' => array(
299
- 'type' => 'select',
300
- 'label' => __( 'Hide empty rows', 'mp-timetable' ),
301
- 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
302
- 'default' => 1
303
- ),
304
- 'title' => array(
305
- 'type' => 'radio-buttons',
306
- 'label' => __( 'Title', 'mp-timetable' ),
307
- 'default' => 1,
308
- 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
309
- ),
310
- 'time' => array(
311
- 'type' => 'radio-buttons',
312
- 'label' => __( 'Time', 'mp-timetable' ),
313
- 'default' => 1,
314
- 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
315
- ),
316
- 'sub-title' => array(
317
- 'type' => 'radio-buttons',
318
- 'label' => __( 'Subtitle', 'mp-timetable' ),
319
- 'default' => 1,
320
- 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
321
- ),
322
- 'description' => array(
323
- 'type' => 'radio-buttons',
324
- 'label' => __( 'Description', 'mp-timetable' ),
325
- 'default' => 0,
326
- 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
327
- ),
328
- 'user' => array(
329
- 'type' => 'radio-buttons',
330
- 'label' => __( 'User', 'mp-timetable' ),
331
- 'default' => 0,
332
- 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
333
- ),
334
- 'disable_event_url' => array(
335
- 'type' => 'select',
336
- 'label' => __( 'Disable event URL', 'mp-timetable' ),
337
- 'list' => array( '0' => __( 'No', 'mp-timetable' ), '1' => __( 'Yes', 'mp-timetable' ) )
338
- ),
339
- 'text_align' => array(
340
- 'type' => 'select',
341
- 'label' => __( 'Text align', 'mp-timetable' ),
342
- 'list' => array( 'center' => __( 'center', 'mp-timetable' ), 'left' => __( 'left', 'mp-timetable' ), 'right' => __( 'right', 'mp-timetable' ) )
343
- ),
344
- 'id' => array(
345
- 'type' => 'text',
346
- 'label' => __( 'Id', 'mp-timetable' )
347
- ),
348
- 'row_height' => array(
349
- 'type' => 'text',
350
- 'label' => __( 'Row height (in px)', 'mp-timetable' ),
351
- 'default' => 45
352
- ),
353
- 'font_size' => array(
354
- 'type' => 'text',
355
- 'label' => __( 'Base Font Size', 'mp-timetable' ),
356
- 'default' => ''
357
- ),
358
- 'responsive' => array(
359
- 'type' => 'select',
360
- 'label' => __( 'Responsive', 'mp-timetable' ),
361
- 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
362
- 'default' => 1,
363
- ),
364
- 'table_layout' => array(
365
- 'type' => 'select',
366
- 'label' => __( 'Column width', 'mp-timetable' ),
367
- 'list' => array( '' => __( 'Default', 'mp-timetable' ), 'auto' => __( 'Auto', 'mp-timetable' ), 'fixed' => __( 'Fixed', 'mp-timetable' ) )
368
- ),
369
- );
370
-
371
- $mp_timetable = new \MPCEObject( 'mp-timetable', __( 'Timetable', 'mp-timetable' ), '', $attributes );
372
-
373
- $motopressCELibrary->addObject( $mp_timetable, 'other' );
374
- }
375
-
376
- /**
377
- * @param array $data_array
378
- * @param string $type
379
- *
380
- * @return array
381
- */
382
- public function create_list_motopress( $data_array = array(), $type = 'post' ) {
383
- $list_array = array();
384
- switch ( $type ) {
385
- case "post":
386
- foreach ( $data_array as $item ) {
387
- $list_array[ $item->ID ] = $item->post_title;
388
- }
389
- break;
390
- case "term":
391
- foreach ( $data_array as $item ) {
392
- $list_array[ $item->term_id ] = $item->name;
393
- }
394
- break;
395
- default:
396
- break;
397
- }
398
-
399
- return $list_array;
400
- }
401
  }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ use mp_timetable\classes\models\Column;
6
+ use mp_timetable\classes\models\Events;
7
+
8
+ /**
9
+ * Class Shortcode
10
+ *
11
+ * @package mp_timetable\plugin_core\classes
12
+ */
13
+ class Shortcode extends Core {
14
+
15
+ protected static $instance;
16
+
17
+ /**
18
+ * Shortcode constructor.
19
+ */
20
+ public function __construct() {
21
+ $this->init_plugin_version();
22
+ parent::__construct();
23
+ }
24
+
25
+ /**
26
+ * Return instance
27
+ *
28
+ * @return Shortcode
29
+ */
30
+ public static function get_instance() {
31
+ if ( null === self::$instance ) {
32
+ self::$instance = new self();
33
+ }
34
+
35
+ return self::$instance;
36
+ }
37
+
38
+ /**
39
+ * Init
40
+ */
41
+ public function init() {
42
+ add_shortcode( 'mp-timetable', array( $this, "show_shortcode" ) );
43
+ }
44
+
45
+ /**
46
+ * Show shortcode
47
+ *
48
+ * @param $params
49
+ *
50
+ * @return mixed
51
+ */
52
+ public function show_shortcode( $params ) {
53
+ global $mptt_shortcode_data;
54
+
55
+ $this->add_plugin_js( 'shortcode' );
56
+
57
+ if ( empty( $params ) ) {
58
+ $params = array();
59
+ }
60
+
61
+ $mptt_shortcode_data = array();
62
+
63
+ $mptt_shortcode_data[ 'params' ] = $params = shortcode_atts( array(
64
+ 'events' => "",
65
+ 'event_categ' => "",
66
+ 'col' => "",
67
+ 'increment' => "1", // 1 | 0.5 | 0.25
68
+ 'view' => "dropdown_list", // dropdown_list | tabs
69
+ 'view_sort' => "", // '' | menu_order || post_title
70
+ 'label' => __( "All Events", 'mp-timetable' ),
71
+ 'hide_label' => "0",
72
+ 'title' => "0",
73
+ 'time' => "0",
74
+ 'group' => "0",
75
+ 'sub-title' => "0",
76
+ 'description' => "0",
77
+ 'user' => "0",
78
+ 'hide_hrs' => "0",
79
+ 'hide_empty_rows' => "1",
80
+ 'text_align_vertical' => "default", // default | top | middle | bottom
81
+ 'row_height' => "45",
82
+ 'font_size' => "",
83
+ 'disable_event_url' => "0",
84
+ 'text_align' => "center", // left | center | right
85
+ 'id' => "",
86
+ 'custom_class' => "",
87
+ 'responsive' => "1",
88
+ 'table_layout' => "" // default | auto | fixed
89
+ ), $params );
90
+
91
+ $mptt_shortcode_data[ 'events_data' ] = $this->get_shortcode_events( $params );
92
+
93
+ if ( ! empty( $mptt_shortcode_data[ 'events_data' ] ) ) {
94
+ if ( isset($mptt_shortcode_data[ 'events_data' ][ 'unique_events' ]) ) {
95
+ $mptt_shortcode_data[ 'unique_events' ] = $mptt_shortcode_data[ 'events_data' ][ 'unique_events' ];
96
+ }
97
+ if ( isset( $mptt_shortcode_data[ 'events_data' ][ 'events' ] ) ) {
98
+ unset( $mptt_shortcode_data[ 'events_data' ][ 'events' ] );
99
+ }
100
+ }
101
+
102
+ if ( empty( $mptt_shortcode_data[ 'events_data' ][ 'events' ] ) && empty( $mptt_shortcode_data[ 'events_data' ][ 'column' ] ) ) {
103
+ return $this->get_view()->get_template_html( 'shortcodes/empty-search-events', array() );
104
+ } else {
105
+ return $this->get_view()->get_template_html( 'shortcodes/index-timetable', array() );
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Get shortcode events
111
+ *
112
+ * @param $params
113
+ *
114
+ * @return array
115
+ */
116
+ public function get_shortcode_events( $params ) {
117
+ $columns_ids = $events_categ = $events = array();
118
+
119
+ $step = $params[ 'increment' ] === '1' ? 60 : ( 60 * $params[ 'increment' ] );
120
+
121
+ $events_data = array( 'events' => array(), 'column' => array() );
122
+
123
+ //get event by id
124
+ if ( ! empty( $params[ 'events' ] ) && empty( $params[ 'col' ] ) && empty( $params[ 'event_categ' ] ) ) {
125
+ $events = $this->get( 'events' )->get_events_data( array( 'column' => 'event_id', 'list' => $params[ 'events' ] ) );
126
+ }
127
+
128
+ // get event by category
129
+ if ( ! empty( $params[ 'event_categ' ] ) ) {
130
+ $events_categ = $this->get( 'events' )->get_events_data_by_category( $params[ 'event_categ' ] );
131
+ }
132
+
133
+ // get event by column
134
+ if ( ! empty( $params[ 'col' ] ) && empty( $params[ 'event_categ' ] ) && empty( $params[ 'events' ] ) ) {
135
+ $events = $this->get( 'events' )->get_events_data( array( 'column' => 'column_id', 'list' => $params[ 'col' ] ) );
136
+ }
137
+
138
+ //Columns + events
139
+ if ( ! empty( $params[ 'events' ] ) && ! empty( $params[ 'col' ] ) && empty( $params[ 'event_categ' ] ) ) {
140
+ $events = $this->get( 'events' )->get_events_data( array( 'column' => array( 'column_id', 'event_id' ), 'list' => array( 'column_id' => $params[ 'col' ], 'event_id' => $params[ 'events' ] ) ) );
141
+ }
142
+
143
+ //Events + Categories
144
+ if ( ! empty( $params[ 'events' ] ) && ! empty( $params[ 'event_categ' ] ) && empty( $params[ 'col' ] ) ) {
145
+ $events = $this->get( 'events' )->get_events_data( array( 'column' => 'event_id', 'list' => $params[ 'events' ] ) );
146
+ }
147
+
148
+ //if all params empty
149
+ if ( empty( $params[ 'col' ] ) && empty( $params[ 'event_categ' ] ) && empty( $params[ 'events' ] ) ) {
150
+ $events = $this->get( 'events' )->get_events_data( array( 'column' => 'event_id', 'all' => true ) );
151
+ $events_categ = $this->get( 'events' )->get_events_data_by_category( '' );
152
+ }
153
+ // select all event option
154
+ if ( ! empty( $params[ 'col' ] ) && ! empty( $params[ 'event_categ' ] ) && ! empty( $params[ 'events' ] ) ) {
155
+ $events = $this->get( 'events' )->get_events_data( array( 'column' => 'event_id', 'list' => $params[ 'events' ] ) );
156
+ }
157
+
158
+ $events_data[ 'events' ] = array_merge( $events_data[ 'events' ], $events_categ, $events );
159
+
160
+ //Create column array;
161
+ if ( empty( $params[ 'col' ] ) ) {
162
+ foreach ( $events_data[ 'events' ] as $event ) {
163
+ $columns_ids[] = $event->column_id;
164
+ }
165
+ $columns_ids = array_unique( $columns_ids );
166
+ } else {
167
+ $columns_ids = explode( ',', $params[ 'col' ] );
168
+ }
169
+
170
+ //Sort column by menu order
171
+ $events_data[ 'column' ] = $this->get( 'column' )->get_all_column( array( 'post__in' => $columns_ids ) );
172
+
173
+ if ( ! empty( $events_data[ 'column' ] ) ) {
174
+ foreach ( $events_data[ 'column' ] as $key => $column ) {
175
+ $column_events = array();
176
+ // add to column events
177
+
178
+ foreach ( $events_data[ 'events' ] as $event_key => $event ) {
179
+ if ( $column->ID == $event->column_id ) {
180
+ $start_index = $this->get_event_index( $params[ 'increment' ], $event->event_start, $step, 'start' );
181
+ $end_index = $this->get_event_index( $params[ 'increment' ], $event->event_end, $step, 'end' );
182
+ $event->output = false;
183
+ $event->start_index = $start_index;
184
+ $event->end_index = ( $end_index < $start_index ) ? $this->get_event_index( $params[ 'increment' ], '23:59', $step, 'end' ) : $end_index;
185
+ $column_events[ $event->id ] = $event;
186
+ $events_data[ 'unique_events' ][ $event->event_id ] = $event;
187
+ }
188
+ }
189
+
190
+ //sort by start date
191
+ $column_events = $this->get_model( 'events' )->sort_by_param( $column_events );
192
+
193
+ $events_data[ 'column_events' ][ $column->ID ] = $column_events;
194
+ }
195
+ } else {
196
+ $events_data[ 'events' ] = array();
197
+ }
198
+
199
+ return $events_data;
200
+ }
201
+
202
+ /**
203
+ * @param $increment
204
+ * @param $time
205
+ * @param $step
206
+ * @param $type
207
+ *
208
+ * @return float|int
209
+ */
210
+ protected function get_event_index( $increment, $time, $step, $type ) {
211
+ if ( $type == 'start' ) {
212
+ $index = date( 'G', strtotime( $time ) ) / $increment + floor( date( 'i', strtotime( $time ) ) / $step );
213
+ } else {
214
+ $index = date( 'G', strtotime( $time ) ) / $increment + ceil( date( 'i', strtotime( $time ) ) / $step );
215
+ }
216
+
217
+ return $index;
218
+ }
219
+
220
+ /**
221
+ * Get events Id
222
+ *
223
+ * @param array $data
224
+ *
225
+ * @return string
226
+ */
227
+ public function get_event_ids( array $data = array() ) {
228
+ $ids_list = array();
229
+ if ( empty( $data ) ) {
230
+ return '';
231
+ } else {
232
+ foreach ( $data as $event ) {
233
+ $ids_list[] = $event->id;
234
+ }
235
+
236
+ return implode( ',', $ids_list );
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Integration in motopress
242
+ *
243
+ * @param $motopressCELibrary
244
+ */
245
+ public function integration_motopress( $motopressCELibrary ) {
246
+ $columns = $this->create_list_motopress( Column::get_instance()->get_all_column() );
247
+ $events = $this->create_list_motopress( Events::get_instance()->get_all_events() );
248
+
249
+ $categories = get_terms( 'mp-event_category', 'orderby=count&hide_empty=0' );
250
+ $categories = $this->create_list_motopress( $categories, 'term' );
251
+
252
+ $attributes = array(
253
+ 'col' => array(
254
+ 'type' => 'select-multiple',
255
+ 'label' => __( 'Column', 'mp-timetable' ),
256
+ 'list' => $columns
257
+ ),
258
+ 'events' => array(
259
+ 'type' => 'select-multiple',
260
+ 'label' => __( 'Events', 'mp-timetable' ),
261
+ 'list' => $events
262
+ ),
263
+ 'event_categ' => array(
264
+ 'type' => 'select-multiple',
265
+ 'label' => __( 'Event categories', 'mp-timetable' ),
266
+ 'list' => $categories
267
+ ),
268
+ 'increment' => array(
269
+ 'type' => 'select',
270
+ 'label' => __( 'Hour measure', 'mp-timetable' ),
271
+ 'list' => array( '1' => __( 'Hour (1h)', 'mp-timetable' ), '0.5' => __( 'Half hour (30min)', 'mp-timetable' ), '0.25' => __( 'Quarter hour (15min)', 'mp-timetable' ) )
272
+ ),
273
+ 'view' => array(
274
+ 'type' => 'select',
275
+ 'label' => __( 'Filter style', 'mp-timetable' ),
276
+ 'list' => array( 'dropdown_list' => __( 'Dropdown list', 'mp-timetable' ), 'tabs' => __( 'Tabs', 'mp-timetable' ) )
277
+ ),
278
+ 'view_sort' => array(
279
+ 'type' => 'select',
280
+ 'label' => __( 'Order of items in filter', 'mp-timetable' ),
281
+ 'list' => array( '' => __( 'Default', 'mp-timetable' ), 'menu_order' => __( 'Menu Order', 'mp-timetable' ), 'post_title' => __( 'Title', 'mp-timetable' ) )
282
+ ),
283
+ 'label' => array(
284
+ 'type' => 'text',
285
+ 'label' => __( 'Filter label', 'mp-timetable' ),
286
+ 'default' => __( 'All Events', 'mp-timetable' )
287
+ ),
288
+ 'hide_label' => array(
289
+ 'type' => 'select',
290
+ 'label' => __( "Hide 'All Events' view", 'mp-timetable' ),
291
+ 'list' => array( '0' => __( 'No', 'mp-timetable' ), '1' => __( 'Yes', 'mp-timetable' ) )
292
+ ),
293
+ 'hide_hrs' => array(
294
+ 'type' => 'select',
295
+ 'label' => __( 'Hide first (hours) column', 'mp-timetable' ),
296
+ 'list' => array( '0' => __( 'No', 'mp-timetable' ), '1' => __( 'Yes', 'mp-timetable' ) )
297
+ ),
298
+ 'hide_empty_rows' => array(
299
+ 'type' => 'select',
300
+ 'label' => __( 'Hide empty rows', 'mp-timetable' ),
301
+ 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
302
+ 'default' => 1
303
+ ),
304
+ 'title' => array(
305
+ 'type' => 'radio-buttons',
306
+ 'label' => __( 'Title', 'mp-timetable' ),
307
+ 'default' => 1,
308
+ 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
309
+ ),
310
+ 'time' => array(
311
+ 'type' => 'radio-buttons',
312
+ 'label' => __( 'Time', 'mp-timetable' ),
313
+ 'default' => 1,
314
+ 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
315
+ ),
316
+ 'sub-title' => array(
317
+ 'type' => 'radio-buttons',
318
+ 'label' => __( 'Subtitle', 'mp-timetable' ),
319
+ 'default' => 1,
320
+ 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
321
+ ),
322
+ 'description' => array(
323
+ 'type' => 'radio-buttons',
324
+ 'label' => __( 'Description', 'mp-timetable' ),
325
+ 'default' => 0,
326
+ 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
327
+ ),
328
+ 'user' => array(
329
+ 'type' => 'radio-buttons',
330
+ 'label' => __( 'User', 'mp-timetable' ),
331
+ 'default' => 0,
332
+ 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
333
+ ),
334
+ 'disable_event_url' => array(
335
+ 'type' => 'select',
336
+ 'label' => __( 'Disable event URL', 'mp-timetable' ),
337
+ 'list' => array( '0' => __( 'No', 'mp-timetable' ), '1' => __( 'Yes', 'mp-timetable' ) )
338
+ ),
339
+ 'text_align' => array(
340
+ 'type' => 'select',
341
+ 'label' => __( 'Text align', 'mp-timetable' ),
342
+ 'list' => array( 'center' => __( 'center', 'mp-timetable' ), 'left' => __( 'left', 'mp-timetable' ), 'right' => __( 'right', 'mp-timetable' ) )
343
+ ),
344
+ 'id' => array(
345
+ 'type' => 'text',
346
+ 'label' => __( 'Id', 'mp-timetable' )
347
+ ),
348
+ 'row_height' => array(
349
+ 'type' => 'text',
350
+ 'label' => __( 'Row height (in px)', 'mp-timetable' ),
351
+ 'default' => 45
352
+ ),
353
+ 'font_size' => array(
354
+ 'type' => 'text',
355
+ 'label' => __( 'Base Font Size', 'mp-timetable' ),
356
+ 'default' => ''
357
+ ),
358
+ 'responsive' => array(
359
+ 'type' => 'select',
360
+ 'label' => __( 'Responsive', 'mp-timetable' ),
361
+ 'list' => array( '1' => __( 'Yes', 'mp-timetable' ), '0' => __( 'No', 'mp-timetable' ) ),
362
+ 'default' => 1,
363
+ ),
364
+ 'table_layout' => array(
365
+ 'type' => 'select',
366
+ 'label' => __( 'Column width', 'mp-timetable' ),
367
+ 'list' => array( '' => __( 'Default', 'mp-timetable' ), 'auto' => __( 'Auto', 'mp-timetable' ), 'fixed' => __( 'Fixed', 'mp-timetable' ) )
368
+ ),
369
+ );
370
+
371
+ $mp_timetable = new \MPCEObject( 'mp-timetable', __( 'Timetable', 'mp-timetable' ), '', $attributes );
372
+
373
+ $motopressCELibrary->addObject( $mp_timetable, 'other' );
374
+ }
375
+
376
+ /**
377
+ * @param array $data_array
378
+ * @param string $type
379
+ *
380
+ * @return array
381
+ */
382
+ public function create_list_motopress( $data_array = array(), $type = 'post' ) {
383
+ $list_array = array();
384
+ switch ( $type ) {
385
+ case "post":
386
+ foreach ( $data_array as $item ) {
387
+ $list_array[ $item->ID ] = $item->post_title;
388
+ }
389
+ break;
390
+ case "term":
391
+ foreach ( $data_array as $item ) {
392
+ $list_array[ $item->term_id ] = $item->name;
393
+ }
394
+ break;
395
+ default:
396
+ break;
397
+ }
398
+
399
+ return $list_array;
400
+ }
401
  }
classes/class-state-factory.php CHANGED
@@ -1,84 +1,84 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- /**
6
- * Singleton factory
7
- */
8
- class State_Factory {
9
-
10
- protected static $instance;
11
- protected $namespace;
12
-
13
- /**
14
- * State_Factory constructor.
15
- *
16
- * @param string $namespace
17
- */
18
- public function __construct($namespace = 'plugin_core') {
19
- $this->namespace = $namespace;
20
- }
21
-
22
- /**
23
- * @return State_Factory
24
- */
25
- public static function get_instance() {
26
- if (null === self::$instance) {
27
- self::$instance = new self();
28
- }
29
- return self::$instance;
30
- }
31
-
32
- /**
33
- * Get register instance object
34
- *
35
- * @param null $value
36
- *
37
- * @return bool|\mp_timetable\plugin_core\classes\Model
38
- */
39
- public function get_model($value = null) {
40
- $model = false;
41
- if ('model' == $value) {
42
- $model = Model::get_instance();
43
- } else {
44
- $class = "{$this->namespace}\classes\models\\" . ucfirst($value);
45
- if (class_exists($class)) {
46
- $model = $class::get_instance();
47
- }
48
- }
49
- return $model;
50
- }
51
-
52
- /**
53
- * Get controller instance object
54
- *
55
- * @param null $value
56
- *
57
- * @return bool
58
- */
59
- public function get_controller($value = null) {
60
- $controller = false;
61
- $class = "{$this->namespace}\classes\controllers\Controller_" . ucfirst($value);
62
- if (class_exists($class)) {
63
- $controller = $class::get_instance();
64
- }
65
- return $controller;
66
- }
67
-
68
- /**
69
- * Get Preprocessor instance object
70
- *
71
- * @param null $value
72
- *
73
- * @return bool
74
- */
75
- public function get_preprocessor($value = null) {
76
- $preprocessor = false;
77
- $class = "{$this->namespace}\classes\preprocessors\Preprocessor_" . ucfirst($value);
78
- if (class_exists($class)) {
79
- $preprocessor = $class::get_instance();
80
- }
81
- return $preprocessor;
82
- }
83
-
84
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ /**
6
+ * Singleton factory
7
+ */
8
+ class State_Factory {
9
+
10
+ protected static $instance;
11
+ protected $namespace;
12
+
13
+ /**
14
+ * State_Factory constructor.
15
+ *
16
+ * @param string $namespace
17
+ */
18
+ public function __construct($namespace = 'plugin_core') {
19
+ $this->namespace = $namespace;
20
+ }
21
+
22
+ /**
23
+ * @return State_Factory
24
+ */
25
+ public static function get_instance() {
26
+ if (null === self::$instance) {
27
+ self::$instance = new self();
28
+ }
29
+ return self::$instance;
30
+ }
31
+
32
+ /**
33
+ * Get register instance object
34
+ *
35
+ * @param null $value
36
+ *
37
+ * @return bool|\mp_timetable\plugin_core\classes\Model
38
+ */
39
+ public function get_model($value = null) {
40
+ $model = false;
41
+ if ('model' == $value) {
42
+ $model = Model::get_instance();
43
+ } else {
44
+ $class = "{$this->namespace}\classes\models\\" . ucfirst($value);
45
+ if (class_exists($class)) {
46
+ $model = $class::get_instance();
47
+ }
48
+ }
49
+ return $model;
50
+ }
51
+
52
+ /**
53
+ * Get controller instance object
54
+ *
55
+ * @param null $value
56
+ *
57
+ * @return bool
58
+ */
59
+ public function get_controller($value = null) {
60
+ $controller = false;
61
+ $class = "{$this->namespace}\classes\controllers\Controller_" . ucfirst($value);
62
+ if (class_exists($class)) {
63
+ $controller = $class::get_instance();
64
+ }
65
+ return $controller;
66
+ }
67
+
68
+ /**
69
+ * Get Preprocessor instance object
70
+ *
71
+ * @param null $value
72
+ *
73
+ * @return bool
74
+ */
75
+ public function get_preprocessor($value = null) {
76
+ $preprocessor = false;
77
+ $class = "{$this->namespace}\classes\preprocessors\Preprocessor_" . ucfirst($value);
78
+ if (class_exists($class)) {
79
+ $preprocessor = $class::get_instance();
80
+ }
81
+ return $preprocessor;
82
+ }
83
+
84
+ }
classes/class-view.php CHANGED
@@ -1,235 +1,235 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- use Mp_Time_Table;
6
-
7
- /**
8
- * View class
9
- */
10
- class View {
11
-
12
- protected static $instance;
13
- protected $template_path;
14
- protected $templates_path;
15
- protected $prefix = 'mptt';
16
- private $data;
17
-
18
- /**
19
- * View constructor.
20
- */
21
- public function __construct() {
22
- $this->template_path = Mp_Time_Table::get_template_path();
23
- $this->templates_path = Mp_Time_Table::get_templates_path();
24
- $this->taxonomy_names = Core::get_instance()->get_taxonomy_names();
25
- $this->post_types = Core::get_instance()->get_post_types();
26
- }
27
-
28
- /**
29
- * @return View
30
- */
31
- public static function get_instance() {
32
- if (null === self::$instance) {
33
- self::$instance = new self();
34
- }
35
- return self::$instance;
36
- }
37
-
38
- /**
39
- * Render template
40
- *
41
- * @param null $template
42
- * @param null $data
43
- */
44
- function render_template($template = null, $data = null) {
45
- $this->template = $template;
46
- if (is_array($data)) {
47
- extract($data);
48
- }
49
- $this->data = $data;
50
- include_once $this->templates_path . 'index.php';
51
- }
52
-
53
- /**
54
- * Render html
55
- *
56
- * @param $template
57
- * @param null $data
58
- * @param bool $output
59
- *
60
- * @return string
61
- */
62
- public function render_html($template, $data = null, $output = true) {
63
-
64
- $this->data = $data;
65
- if ( is_array($data) ) {
66
- extract($data, EXTR_SKIP);
67
- }
68
-
69
- $includeFile = $this->templates_path . $template . '.php';
70
-
71
- ob_start();
72
- include($includeFile);
73
- $out = ob_get_clean();
74
-
75
- if ($output) {
76
- echo $out;
77
- } else {
78
- return $out;
79
- }
80
- }
81
-
82
- /**
83
- * Get template part theme/plugin
84
- *
85
- * @param string $name
86
- * @param string $slug
87
- *
88
- * @return void
89
- */
90
- public function get_template_part($slug, $name = '') {
91
- $template = '';
92
-
93
- if ($name) {
94
- $template = locate_template(array("{$slug}-{$name}.php", $this->template_path . "{$slug}-{$name}.php"));
95
- }
96
-
97
- // Get default slug-name.php
98
- if (!$template && $name && file_exists($this->templates_path . "{$slug}-{$name}.php")) {
99
- $template = $this->templates_path . "{$slug}-{$name}.php";
100
- }
101
-
102
- if (!$template) {
103
- $template = locate_template(array("{$slug}.php", $this->template_path . "{$slug}.php"));
104
- }
105
-
106
- // Allow 3rd party plugins to filter template file from their plugin.
107
- $template = apply_filters($this->prefix . '_get_template_part', $template, $slug, $name);
108
-
109
- if ($template) {
110
- load_template($template, false);
111
- }
112
- }
113
-
114
- /**
115
- * @param $template_name
116
- * @param array $args
117
- * @param string $template_path
118
- * @param string $default_path
119
- *
120
- * @return mixed/void
121
- */
122
- public function get_template_html($template_name, $args = array(), $template_path = '', $default_path = '') {
123
- ob_start();
124
- $this->get_template($template_name, $args, $template_path, $default_path);
125
- return ob_get_clean();
126
- }
127
-
128
- /**
129
- * Get template
130
- *
131
- * @param $template_name
132
- * @param array $args
133
- * @param string $template_path
134
- * @param string $default_path
135
- */
136
- public function get_template($template_name, $args = array(), $template_path = '', $default_path = '') {
137
- $template_name = $template_name . '.php';
138
-
139
- if (!empty($args) && is_array($args)) {
140
- extract($args);
141
- }
142
-
143
- $located = $this->locate_template($template_name, $template_path, $default_path);
144
-
145
- if (!file_exists($located)) {
146
- _doing_it_wrong(__FUNCTION__, sprintf('<code>%s</code> does not exist.', $located), '2.1');
147
- return;
148
- }
149
-
150
- // Allow 3rd party plugin filter template file from their plugin.
151
- $located = apply_filters($this->prefix . '_get_template', $located, $template_name, $args, $template_path, $default_path);
152
-
153
- do_action($this->prefix . '_before_template_part', $template_name, $template_path, $located, $args);
154
-
155
- include($located);
156
-
157
- do_action($this->prefix . '_after_template_part', $template_name, $template_path, $located, $args);
158
- }
159
-
160
- /**
161
- * Locate template
162
- *
163
- * @param $template_name
164
- * @param string $template_path
165
- * @param string $default_path
166
- *
167
- * @return mixed|void
168
- */
169
- function locate_template($template_name, $template_path = '', $default_path = '') {
170
- if (!$template_path) {
171
- $template_path = $this->template_path;
172
- }
173
-
174
- if (!$default_path) {
175
- $default_path = $this->templates_path;
176
- }
177
-
178
- // Look within passed path within the theme - this is priority.
179
- $template_args = array(trailingslashit($template_path) . $template_name, $template_name);
180
-
181
- $template = locate_template($template_args);
182
-
183
- // Get default template/
184
- if (!$template) {
185
- $template = $default_path . $template_name;
186
- }
187
-
188
- // Return what we found.
189
- return apply_filters($this->prefix . '_locate_template', $template, $template_name, $template_path);
190
- }
191
-
192
-
193
- /**
194
- * Include template
195
- *
196
- * @param $template
197
- *
198
- * @return string
199
- */
200
- public function template_loader($template) {
201
- global $post, $taxonomy;
202
- $file = '';
203
- $find = array();
204
- if (is_embed()) {
205
- return $template;
206
- }
207
- if (is_single() && in_array($post->post_type, $this->post_types)) {
208
- $file = "single-{$post->post_type}.php";
209
- $find[] = $file;
210
- $find[] = $this->template_path . $file;
211
- } elseif (in_array($taxonomy, $this->taxonomy_names)) {
212
- $term = get_queried_object();
213
- $file = "taxonomy-{$term->taxonomy}.php";
214
- $find[] = 'taxonomy-' . $term->taxonomy . '-' . $term->slug . '.php';
215
- $find[] = $this->template_path . 'taxonomy-' . $term->taxonomy . '-' . $term->slug . '.php';
216
- $find[] = 'taxonomy-' . $term->taxonomy . '.php';
217
- $find[] = $this->template_path . 'taxonomy-' . $term->taxonomy . '.php';
218
- $find[] = $file;
219
- $find[] = $this->template_path . $file;
220
- }
221
- // elseif (is_post_type_archive($this->post_types)) {
222
- // $file = 'archive.php';
223
- // $find[] = $file;
224
- // $find[] = $this->template_path . $file;
225
- // }
226
- if ($file) {
227
- $find_template = locate_template(array_unique($find));
228
- if (!empty($find_template)) {
229
- $template = $find_template;
230
- }
231
- }
232
-
233
- return $template;
234
- }
235
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ use Mp_Time_Table;
6
+
7
+ /**
8
+ * View class
9
+ */
10
+ class View {
11
+
12
+ protected static $instance;
13
+ protected $template_path;
14
+ protected $templates_path;
15
+ protected $prefix = 'mptt';
16
+ private $data;
17
+
18
+ /**
19
+ * View constructor.
20
+ */
21
+ public function __construct() {
22
+ $this->template_path = Mp_Time_Table::get_template_path();
23
+ $this->templates_path = Mp_Time_Table::get_templates_path();
24
+ $this->taxonomy_names = Core::get_instance()->get_taxonomy_names();
25
+ $this->post_types = Core::get_instance()->get_post_types();
26
+ }
27
+
28
+ /**
29
+ * @return View
30
+ */
31
+ public static function get_instance() {
32
+ if (null === self::$instance) {
33
+ self::$instance = new self();
34
+ }
35
+ return self::$instance;
36
+ }
37
+
38
+ /**
39
+ * Render template
40
+ *
41
+ * @param null $template
42
+ * @param null $data
43
+ */
44
+ function render_template($template = null, $data = null) {
45
+ $this->template = $template;
46
+ if (is_array($data)) {
47
+ extract($data);
48
+ }
49
+ $this->data = $data;
50
+ include_once $this->templates_path . 'index.php';
51
+ }
52
+
53
+ /**
54
+ * Render html
55
+ *
56
+ * @param $template
57
+ * @param null $data
58
+ * @param bool $output
59
+ *
60
+ * @return string
61
+ */
62
+ public function render_html($template, $data = null, $output = true) {
63
+
64
+ $this->data = $data;
65
+ if ( is_array($data) ) {
66
+ extract($data, EXTR_SKIP);
67
+ }
68
+
69
+ $includeFile = $this->templates_path . $template . '.php';
70
+
71
+ ob_start();
72
+ include($includeFile);
73
+ $out = ob_get_clean();
74
+
75
+ if ($output) {
76
+ echo $out;
77
+ } else {
78
+ return $out;
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Get template part theme/plugin
84
+ *
85
+ * @param string $name
86
+ * @param string $slug
87
+ *
88
+ * @return void
89
+ */
90
+ public function get_template_part($slug, $name = '') {
91
+ $template = '';
92
+
93
+ if ($name) {
94
+ $template = locate_template(array("{$slug}-{$name}.php", $this->template_path . "{$slug}-{$name}.php"));
95
+ }
96
+
97
+ // Get default slug-name.php
98
+ if (!$template && $name && file_exists($this->templates_path . "{$slug}-{$name}.php")) {
99
+ $template = $this->templates_path . "{$slug}-{$name}.php";
100
+ }
101
+
102
+ if (!$template) {
103
+ $template = locate_template(array("{$slug}.php", $this->template_path . "{$slug}.php"));
104
+ }
105
+
106
+ // Allow 3rd party plugins to filter template file from their plugin.
107
+ $template = apply_filters($this->prefix . '_get_template_part', $template, $slug, $name);
108
+
109
+ if ($template) {
110
+ load_template($template, false);
111
+ }
112
+ }
113
+
114
+ /**
115
+ * @param $template_name
116
+ * @param array $args
117
+ * @param string $template_path
118
+ * @param string $default_path
119
+ *
120
+ * @return mixed/void
121
+ */
122
+ public function get_template_html($template_name, $args = array(), $template_path = '', $default_path = '') {
123
+ ob_start();
124
+ $this->get_template($template_name, $args, $template_path, $default_path);
125
+ return ob_get_clean();
126
+ }
127
+
128
+ /**
129
+ * Get template
130
+ *
131
+ * @param $template_name
132
+ * @param array $args
133
+ * @param string $template_path
134
+ * @param string $default_path
135
+ */
136
+ public function get_template($template_name, $args = array(), $template_path = '', $default_path = '') {
137
+ $template_name = $template_name . '.php';
138
+
139
+ if (!empty($args) && is_array($args)) {
140
+ extract($args);
141
+ }
142
+
143
+ $located = $this->locate_template($template_name, $template_path, $default_path);
144
+
145
+ if (!file_exists($located)) {
146
+ _doing_it_wrong(__FUNCTION__, sprintf('<code>%s</code> does not exist.', $located), '2.1');
147
+ return;
148
+ }
149
+
150
+ // Allow 3rd party plugin filter template file from their plugin.
151
+ $located = apply_filters($this->prefix . '_get_template', $located, $template_name, $args, $template_path, $default_path);
152
+
153
+ do_action($this->prefix . '_before_template_part', $template_name, $template_path, $located, $args);
154
+
155
+ include($located);
156
+
157
+ do_action($this->prefix . '_after_template_part', $template_name, $template_path, $located, $args);
158
+ }
159
+
160
+ /**
161
+ * Locate template
162
+ *
163
+ * @param $template_name
164
+ * @param string $template_path
165
+ * @param string $default_path
166
+ *
167
+ * @return mixed|void
168
+ */
169
+ function locate_template($template_name, $template_path = '', $default_path = '') {
170
+ if (!$template_path) {
171
+ $template_path = $this->template_path;
172
+ }
173
+
174
+ if (!$default_path) {
175
+ $default_path = $this->templates_path;
176
+ }
177
+
178
+ // Look within passed path within the theme - this is priority.
179
+ $template_args = array(trailingslashit($template_path) . $template_name, $template_name);
180
+
181
+ $template = locate_template($template_args);
182
+
183
+ // Get default template/
184
+ if (!$template) {
185
+ $template = $default_path . $template_name;
186
+ }
187
+
188
+ // Return what we found.
189
+ return apply_filters($this->prefix . '_locate_template', $template, $template_name, $template_path);
190
+ }
191
+
192
+
193
+ /**
194
+ * Include template
195
+ *
196
+ * @param $template
197
+ *
198
+ * @return string
199
+ */
200
+ public function template_loader($template) {
201
+ global $post, $taxonomy;
202
+ $file = '';
203
+ $find = array();
204
+ if (is_embed()) {
205
+ return $template;
206
+ }
207
+ if (is_single() && in_array($post->post_type, $this->post_types)) {
208
+ $file = "single-{$post->post_type}.php";
209
+ $find[] = $file;
210
+ $find[] = $this->template_path . $file;
211
+ } elseif (in_array($taxonomy, $this->taxonomy_names)) {
212
+ $term = get_queried_object();
213
+ $file = "taxonomy-{$term->taxonomy}.php";
214
+ $find[] = 'taxonomy-' . $term->taxonomy . '-' . $term->slug . '.php';
215
+ $find[] = $this->template_path . 'taxonomy-' . $term->taxonomy . '-' . $term->slug . '.php';
216
+ $find[] = 'taxonomy-' . $term->taxonomy . '.php';
217
+ $find[] = $this->template_path . 'taxonomy-' . $term->taxonomy . '.php';
218
+ $find[] = $file;
219
+ $find[] = $this->template_path . $file;
220
+ }
221
+ // elseif (is_post_type_archive($this->post_types)) {
222
+ // $file = 'archive.php';
223
+ // $find[] = $file;
224
+ // $find[] = $this->template_path . $file;
225
+ // }
226
+ if ($file) {
227
+ $find_template = locate_template(array_unique($find));
228
+ if (!empty($find_template)) {
229
+ $template = $find_template;
230
+ }
231
+ }
232
+
233
+ return $template;
234
+ }
235
+ }
classes/class-widgets-manager.php CHANGED
@@ -1,28 +1,28 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes;
4
-
5
- use \Elementor\Plugin;
6
-
7
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
8
-
9
- /**
10
- * Elementor register widgets.
11
- */
12
- class Widgets_Manager {
13
-
14
- /**
15
- * WidgetsManager constructor.
16
- */
17
- public function __construct() {
18
- add_action( 'elementor/widgets/widgets_registered', [ $this, 'register_widgets' ], 12 );
19
- }
20
-
21
- public function register_widgets() {
22
- $path = \Mp_Time_Table::get_plugin_path() . 'classes/widgets/class-mp-timetable-elementor-widget.php';
23
-
24
- if ( file_exists( $path ) ) {
25
- require_once( $path );
26
- }
27
- }
28
  }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes;
4
+
5
+ use \Elementor\Plugin;
6
+
7
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
8
+
9
+ /**
10
+ * Elementor register widgets.
11
+ */
12
+ class Widgets_Manager {
13
+
14
+ /**
15
+ * WidgetsManager constructor.
16
+ */
17
+ public function __construct() {
18
+ add_action( 'elementor/widgets/widgets_registered', [ $this, 'register_widgets' ], 12 );
19
+ }
20
+
21
+ public function register_widgets() {
22
+ $path = \Mp_Time_Table::get_plugin_path() . 'classes/widgets/class-mp-timetable-elementor-widget.php';
23
+
24
+ if ( file_exists( $path ) ) {
25
+ require_once( $path );
26
+ }
27
+ }
28
  }
classes/controllers/class-controller-column.php CHANGED
@@ -1,35 +1,35 @@
1
- <?php
2
-
3
- namespace mp_timetable\classes\controllers;
4
-
5
- use mp_timetable\plugin_core\classes\Controller as Controller;
6
-
7
- /**
8
- * Created by PhpStorm.
9
- * User: newmind
10
- * Date: 12/9/2015
11
- * Time: 5:34 PM
12
- */
13
- class Controller_Column extends Controller {
14
-
15
- protected static $instance;
16
- private $data;
17
-
18
- public static function get_instance() {
19
-
20
- if (null === self::$instance) {
21
- self::$instance = new self();
22
- }
23
- return self::$instance;
24
- }
25
-
26
- /**
27
- * @param $post
28
- */
29
- public function action_page_view($post) {
30
-
31
- $events = $this->get('events')->get_event_data(array('field' => 'column_id', 'id' => $post->ID));
32
- return $events;
33
- }
34
-
35
  }
1
+ <?php
2
+
3
+ namespace mp_timetable\classes\controllers;
4
+
5
+ use mp_timetable\plugin_core\classes\Controller as Controller;
6
+
7
+ /**
8
+ * Created by PhpStorm.
9
+ * User: newmind
10
+ * Date: 12/9/2015
11
+ * Time: 5:34 PM
12
+ */
13
+ class Controller_Column extends Controller {
14
+
15
+ protected static $instance;
16
+ private $data;
17
+
18
+ public static function get_instance() {
19
+
20
+ if (null === self::$instance) {
21
+ self::$instance = new self();
22
+ }
23
+ return self::$instance;
24
+ }
25
+
26
+ /**
27
+ * @param $post
28
+ */
29
+ public function action_page_view($post) {
30
+
31
+ $events = $this->get('events')->get_event_data(array('field' => 'column_id', 'id' => $post->ID));
32
+ return $events;
33
+ }
34
+
35
  }
classes/controllers/class-controller-events.php CHANGED
@@ -1,125 +1,125 @@
1
- <?php
2
-
3
- namespace mp_timetable\classes\controllers;
4
-
5
- use mp_timetable\plugin_core\classes\Controller as Controller;
6
-
7
- /**
8
- * Created by PhpStorm.
9
- * User: newmind
10
- * Date: 12/9/2015
11
- * Time: 5:34 PM
12
- */
13
- class Controller_Events extends Controller {
14
-
15
- protected static $instance;
16
- private $data;
17
-
18
- /**
19
- * @return Controller_Events
20
- */
21
- public static function get_instance() {
22
- if (null === self::$instance) {
23
- self::$instance = new self();
24
- }
25
-
26
- return self::$instance;
27
- }
28
-
29
- /**
30
- * Delete event data by ID
31
- */
32
- public function action_delete() {
33
-
34
- check_ajax_referer( 'timeslot_delete_nonce', 'nonce' );
35
-
36
- $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
37
-
38
- $event_id = 0;
39
- $timeslot = $this->get('events')->get_timeslot_by_id( $id );
40
-
41
- if ( $timeslot ) {
42
- $event_id = (int) $timeslot->event_id;
43
- }
44
-
45
- if ( $event_id && current_user_can( 'edit_post', $event_id ) ) {
46
-
47
- $result = $this->get('events')->delete_event( $id );
48
-
49
- if ($result === false) {
50
- wp_send_json_error(array('status' => $result));
51
- } else {
52
- wp_send_json_success(array('status' => $result));
53
- }
54
- } else {
55
- wp_die( sprintf( 'Access denied, %s, %s', __FUNCTION__, basename( __FILE__ ) ) );
56
- }
57
- }
58
-
59
- /**
60
- * Get single event data
61
- */
62
- public function action_get_event_data() {
63
-
64
- if ( current_user_can('edit_posts') ) {
65
-
66
- $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
67
- $result = $this->get('events')->get_event_data(array('field' => 'id', 'id' => $id), 'event_start', false);
68
-
69
- if (!empty($result)) {
70
- wp_send_json_success($result[ 0 ]);
71
- } else {
72
- wp_send_json_error(array('status' => false));
73
- }
74
- } else {
75
- wp_die( sprintf( 'Access denied, %s, %s', __FUNCTION__, basename( __FILE__ ) ) );
76
- }
77
- }
78
-
79
- /**
80
- * Get events by column id
81
- *
82
- * @param $post
83
- *
84
- * @return mixed
85
- */
86
- public function get_all_event_by_post($post) {
87
-
88
- // Show draft timeslots on preview
89
- $show_public_only = ((get_post_status($post->ID) == 'draft') && is_preview()) ? false : true;
90
- $result = $this->get('events')->get_event_data(array('field' => 'event_id', 'id' => $post->ID), 'event_start', $show_public_only);
91
-
92
- return $result;
93
- }
94
-
95
- /**
96
- * Update Single Event data
97
- */
98
- public function action_update_event_data() {
99
-
100
- check_ajax_referer( 'timeslot_update_nonce', 'nonce' );
101
-
102
- $data = $_REQUEST[ 'data' ]; // WPCS: input var ok, CSRF ok, sanitization ok.
103
-
104
- $event_id = 0;
105
- $id = (int) $data[ 'id' ];
106
- $timeslot = $this->get('events')->get_timeslot_by_id( $id );
107
-
108
- if ( $timeslot ) {
109
- $event_id = (int) $timeslot->event_id;
110
- }
111
-
112
- if ( $event_id && current_user_can( 'edit_post', $event_id ) ) {
113
-
114
- $result = $this->get('events')->update_event_data( $data );
115
-
116
- if ($result === false) {
117
- wp_send_json_error(array('status' => false));
118
- } else {
119
- wp_send_json_success(array('data' => $result));
120
- }
121
- } else {
122
- wp_die( sprintf( 'Access denied, %s, %s', __FUNCTION__, basename( __FILE__ ) ) );
123
- }
124
- }
125
  }
1
+ <?php
2
+
3
+ namespace mp_timetable\classes\controllers;
4
+
5
+ use mp_timetable\plugin_core\classes\Controller as Controller;
6
+
7
+ /**
8
+ * Created by PhpStorm.
9
+ * User: newmind
10
+ * Date: 12/9/2015
11
+ * Time: 5:34 PM
12
+ */
13
+ class Controller_Events extends Controller {
14
+
15
+ protected static $instance;
16
+ private $data;
17
+
18
+ /**
19
+ * @return Controller_Events
20
+ */
21
+ public static function get_instance() {
22
+ if (null === self::$instance) {
23
+ self::$instance = new self();
24
+ }
25
+
26
+ return self::$instance;
27
+ }
28
+
29
+ /**
30
+ * Delete event data by ID
31
+ */
32
+ public function action_delete() {
33
+
34
+ check_ajax_referer( 'timeslot_delete_nonce', 'nonce' );
35
+
36
+ $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
37
+
38
+ $event_id = 0;
39
+ $timeslot = $this->get('events')->get_timeslot_by_id( $id );
40
+
41
+ if ( $timeslot ) {
42
+ $event_id = (int) $timeslot->event_id;
43
+ }
44
+
45
+ if ( $event_id && current_user_can( 'edit_post', $event_id ) ) {
46
+
47
+ $result = $this->get('events')->delete_event( $id );
48
+
49
+ if ($result === false) {
50
+ wp_send_json_error(array('status' => $result));
51
+ } else {
52
+ wp_send_json_success(array('status' => $result));
53
+ }
54
+ } else {
55
+ wp_die( sprintf( 'Access denied, %s, %s', __FUNCTION__, basename( __FILE__ ) ) );
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Get single event data
61
+ */
62
+ public function action_get_event_data() {
63
+
64
+ if ( current_user_can('edit_posts') ) {
65
+
66
+ $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
67
+ $result = $this->get('events')->get_event_data(array('field' => 'id', 'id' => $id), 'event_start', false);
68
+
69
+ if (!empty($result)) {
70
+ wp_send_json_success($result[ 0 ]);
71
+ } else {
72
+ wp_send_json_error(array('status' => false));
73
+ }
74
+ } else {
75
+ wp_die( sprintf( 'Access denied, %s, %s', __FUNCTION__, basename( __FILE__ ) ) );
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Get events by column id
81
+ *
82
+ * @param $post
83
+ *
84
+ * @return mixed
85
+ */
86
+ public function get_all_event_by_post($post) {
87
+
88
+ // Show draft timeslots on preview
89
+ $show_public_only = ((get_post_status($post->ID) == 'draft') && is_preview()) ? false : true;
90
+ $result = $this->get('events')->get_event_data(array('field' => 'event_id', 'id' => $post->ID), 'event_start', $show_public_only);
91
+
92
+ return $result;
93
+ }
94
+
95
+ /**
96
+ * Update Single Event data
97
+ */
98
+ public function action_update_event_data() {
99
+
100
+ check_ajax_referer( 'timeslot_update_nonce', 'nonce' );
101
+
102
+ $data = $_REQUEST[ 'data' ]; // WPCS: input var ok, CSRF ok, sanitization ok.
103
+
104
+ $event_id = 0;
105
+ $id = (int) $data[ 'id' ];
106
+ $timeslot = $this->get('events')->get_timeslot_by_id( $id );
107
+
108
+ if ( $timeslot ) {
109
+ $event_id = (int) $timeslot->event_id;
110
+ }
111
+
112
+ if ( $event_id && current_user_can( 'edit_post', $event_id ) ) {
113
+
114
+ $result = $this->get('events')->update_event_data( $data );
115
+
116
+ if ($result === false) {
117
+ wp_send_json_error(array('status' => false));
118
+ } else {
119
+ wp_send_json_success(array('data' => $result));
120
+ }
121
+ } else {
122
+ wp_die( sprintf( 'Access denied, %s, %s', __FUNCTION__, basename( __FILE__ ) ) );
123
+ }
124
+ }
125
  }
classes/controllers/class-controller-help.php CHANGED
@@ -1,29 +1,29 @@
1
- <?php
2
-
3
- namespace mp_timetable\classes\controllers;
4
-
5
- use mp_timetable\plugin_core\classes\Controller as Controller;
6
- use mp_timetable\plugin_core\classes\View;
7
-
8
- /**
9
- * Class Controller_Help
10
- * @package mp_timetable\classes\controllers
11
- */
12
- class Controller_Help extends Controller {
13
-
14
- protected static $instance;
15
-
16
- public static function get_instance() {
17
- if (null === self::$instance) {
18
- self::$instance = new self();
19
- }
20
- return self::$instance;
21
- }
22
-
23
- /**
24
- * Action template
25
- */
26
- public function action_content() {
27
- View::get_instance()->render_html('../admin/help/index');
28
- }
29
  }
1
+ <?php
2
+
3
+ namespace mp_timetable\classes\controllers;
4
+
5
+ use mp_timetable\plugin_core\classes\Controller as Controller;
6
+ use mp_timetable\plugin_core\classes\View;
7
+
8
+ /**
9
+ * Class Controller_Help
10
+ * @package mp_timetable\classes\controllers
11
+ */
12
+ class Controller_Help extends Controller {
13
+
14
+ protected static $instance;
15
+
16
+ public static function get_instance() {
17
+ if (null === self::$instance) {
18
+ self::$instance = new self();
19
+ }
20
+ return self::$instance;
21
+ }
22
+
23
+ /**
24
+ * Action template
25
+ */
26
+ public function action_content() {
27
+ View::get_instance()->render_html('../admin/help/index');
28
+ }
29
  }
classes/controllers/class-controller-import.php CHANGED
@@ -1,35 +1,35 @@
1
- <?php
2
-
3
- namespace mp_timetable\classes\controllers;
4
-
5
- use mp_timetable\classes\models\Export;
6
- use mp_timetable\plugin_core\classes\Controller as Controller;
7
- use mp_timetable\plugin_core\classes\View;
8
-
9
- /**
10
- * Class Controller_Import
11
- * @package mp_timetable\classes\controllers
12
- */
13
- class Controller_Import extends Controller {
14
-
15
- protected static $instance;
16
-
17
- public static function get_instance() {
18
- if (null === self::$instance) {
19
- self::$instance = new self();
20
- }
21
- return self::$instance;
22
- }
23
-
24
- /**
25
- * Action template
26
- */
27
- public function action_content() {
28
- $data = array();
29
- View::get_instance()->render_html('../admin/import/index', $data);
30
- }
31
-
32
- public function action_export() {
33
- Export::get_instance()->export();
34
- }
35
  }
1
+ <?php
2
+
3
+ namespace mp_timetable\classes\controllers;
4
+
5
+ use mp_timetable\classes\models\Export;
6
+ use mp_timetable\plugin_core\classes\Controller as Controller;
7
+ use mp_timetable\plugin_core\classes\View;
8
+
9
+ /**
10
+ * Class Controller_Import
11
+ * @package mp_timetable\classes\controllers
12
+ */
13
+ class Controller_Import extends Controller {
14
+
15
+ protected static $instance;
16
+
17
+ public static function get_instance() {
18
+ if (null === self::$instance) {
19
+ self::$instance = new self();
20
+ }
21
+ return self::$instance;
22
+ }
23
+
24
+ /**
25
+ * Action template
26
+ */
27
+ public function action_content() {
28
+ $data = array();
29
+ View::get_instance()->render_html('../admin/import/index', $data);
30
+ }
31
+
32
+ public function action_export() {
33
+ Export::get_instance()->export();
34
+ }
35
  }
classes/controllers/class-controller-popup.php CHANGED
@@ -1,39 +1,39 @@
1
- <?php
2
-
3
- namespace mp_timetable\classes\controllers;
4
-
5
- use mp_timetable\plugin_core\classes\Controller as Controller;
6
- use mp_timetable\plugin_core\classes\Model as Model;
7
-
8
- /**
9
- * Class Controller_Popup
10
- * @package mp_timetable\classes\controllers
11
- */
12
- class Controller_Popup extends Controller {
13
-
14
- protected static $instance;
15
- private $data;
16
-
17
- public static function get_instance() {
18
- if (null === self::$instance) {
19
- self::$instance = new self();
20
- }
21
- return self::$instance;
22
- }
23
-
24
- /**
25
- * Action template
26
- */
27
- public function action_get_popup_html_content() {
28
-
29
- if ( is_user_logged_in() ) {
30
-
31
- $this->data['column'] = $this->get('column')->get_all_column();
32
- $this->data['events'] = $this->get('events')->get_all_events();
33
- $this->data['category'] = get_terms('mp-event_category', 'orderby=count&hide_empty=0');
34
- $data["html"] = $this->get_view()->render_html("popup/index", $this->data, false);
35
- $this->send_json(Model::get_instance()->get_arr($data, true));
36
- }
37
- }
38
-
39
  }
1
+ <?php
2
+
3
+ namespace mp_timetable\classes\controllers;
4
+
5
+ use mp_timetable\plugin_core\classes\Controller as Controller;
6
+ use mp_timetable\plugin_core\classes\Model as Model;
7
+
8
+ /**
9
+ * Class Controller_Popup
10
+ * @package mp_timetable\classes\controllers
11
+ */
12
+ class Controller_Popup extends Controller {
13
+
14
+ protected static $instance;
15
+ private $data;
16
+
17
+ public static function get_instance() {
18
+ if (null === self::$instance) {
19
+ self::$instance = new self();
20
+ }
21
+ return self::$instance;
22
+ }
23
+
24
+ /**
25
+ * Action template
26
+ */
27
+ public function action_get_popup_html_content() {
28
+
29
+ if ( is_user_logged_in() ) {
30
+
31
+ $this->data['column'] = $this->get('column')->get_all_column();
32
+ $this->data['events'] = $this->get('events')->get_all_events();
33
+ $this->data['category'] = get_terms('mp-event_category', 'orderby=count&hide_empty=0');
34
+ $data["html"] = $this->get_view()->render_html("popup/index", $this->data, false);
35
+ $this->send_json(Model::get_instance()->get_arr($data, true));
36
+ }
37
+ }
38
+
39
  }
classes/controllers/class-controller-settings.php CHANGED
@@ -1,73 +1,73 @@
1
- <?php
2
-
3
- namespace mp_timetable\classes\controllers;
4
-
5
- use mp_timetable\classes\models\Settings;
6
- use mp_timetable\plugin_core\classes\Controller as Controller;
7
- use mp_timetable\plugin_core\classes\View;
8
-
9
- /**
10
- * Class Controller_Settings
11
- * @package mp_timetable\classes\controllers
12
- */
13
- class Controller_Settings extends Controller {
14
-
15
- protected static $instance;
16
-
17
- /**
18
- * @return Controller_Settings
19
- */
20
- public static function get_instance() {
21
- if (null === self::$instance) {
22
- self::$instance = new self();
23
- }
24
- return self::$instance;
25
- }
26
-
27
- /**
28
- * Action template
29
- */
30
- public function action_content() {
31
-
32
- if ( current_user_can('manage_options') ) {
33
-
34
- $data = Settings::get_instance()->get_settings();
35
- $theme_supports = $this->get('Settings')->is_theme_supports();
36
-
37
- View::get_instance()->render_html('../templates/settings/general', array('settings' => $data, 'theme_supports' => $theme_supports));
38
-
39
- } else {
40
- wp_die( sprintf( 'Access denied, %s, %s', __FUNCTION__, basename( __FILE__ ) ) );
41
- }
42
- }
43
-
44
- /**
45
- * Save settings
46
- */
47
- public function action_save() {
48
-
49
- if ( isset( $_POST['mp-timetable-save-settings'] ) &&
50
- wp_verify_nonce( sanitize_key( $_POST['mp-timetable-save-settings'] ), 'mp_timetable_nonce_settings') ) {
51
-
52
- $redirect = Settings::get_instance()->save_settings();
53
-
54
- wp_safe_redirect(
55
- add_query_arg(
56
- array(
57
- 'page' => sanitize_key( $_GET['page'] ),
58
- 'settings-updated' => 'true'
59
- ),
60
- admin_url( 'edit.php?post_type=mp-event')
61
- )
62
- );
63
- exit;
64
- }
65
-
66
- /**
67
- * Show success message
68
- */
69
- if ( isset( $_GET['settings-updated'] ) && ( filter_var( $_GET['settings-updated'], FILTER_VALIDATE_BOOLEAN) == TRUE ) ) {
70
- add_settings_error('mpTimetableSettings', esc_attr('settings_updated'), __('Settings saved.', 'mp-timetable'), 'updated');
71
- }
72
- }
73
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\classes\controllers;
4
+
5
+ use mp_timetable\classes\models\Settings;
6
+ use mp_timetable\plugin_core\classes\Controller as Controller;
7
+ use mp_timetable\plugin_core\classes\View;
8
+
9
+ /**
10
+ * Class Controller_Settings
11
+ * @package mp_timetable\classes\controllers
12
+ */
13
+ class Controller_Settings extends Controller {
14
+
15
+ protected static $instance;
16
+
17
+ /**
18
+ * @return Controller_Settings
19
+ */
20
+ public static function get_instance() {
21
+ if (null === self::$instance) {
22
+ self::$instance = new self();
23
+ }
24
+ return self::$instance;
25
+ }
26
+
27
+ /**
28
+ * Action template
29
+ */
30
+ public function action_content() {
31
+
32
+ if ( current_user_can('manage_options') ) {
33
+
34
+ $data = Settings::get_instance()->get_settings();
35
+ $theme_supports = $this->get('Settings')->is_theme_supports();
36
+
37
+ View::get_instance()->render_html('../templates/settings/general', array('settings' => $data, 'theme_supports' => $theme_supports));
38
+
39
+ } else {
40
+ wp_die( sprintf( 'Access denied, %s, %s', __FUNCTION__, basename( __FILE__ ) ) );
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Save settings
46
+ */
47
+ public function action_save() {
48
+
49
+ if ( isset( $_POST['mp-timetable-save-settings'] ) &&
50
+ wp_verify_nonce( sanitize_key( $_POST['mp-timetable-save-settings'] ), 'mp_timetable_nonce_settings') ) {
51
+
52
+ $redirect = Settings::get_instance()->save_settings();
53
+
54
+ wp_safe_redirect(
55
+ add_query_arg(
56
+ array(
57
+ 'page' => sanitize_key( $_GET['page'] ),
58
+ 'settings-updated' => 'true'
59
+ ),
60
+ admin_url( 'edit.php?post_type=mp-event')
61
+ )
62
+ );
63
+ exit;
64
+ }
65
+
66
+ /**
67
+ * Show success message
68
+ */
69
+ if ( isset( $_GET['settings-updated'] ) && ( filter_var( $_GET['settings-updated'], FILTER_VALIDATE_BOOLEAN) == TRUE ) ) {
70
+ add_settings_error('mpTimetableSettings', esc_attr('settings_updated'), __('Settings saved.', 'mp-timetable'), 'updated');
71
+ }
72
+ }
73
+ }
classes/libs/class-gump.php CHANGED
@@ -1,2029 +1,2029 @@
1
- <?php
2
- namespace mp_timetable\classes\libs;
3
- /**
4
- * GUMP - A fast, extensible PHP input validation class.
5
- *
6
- * @author Sean Nieuwoudt (http://twitter.com/SeanNieuwoudt)
7
- * @copyright Copyright (c) 2015 wixelhq.com
8
- *
9
- * @link http://github.com/Wixel/GUMP
10
- *
11
- * @version 1.0
12
- */
13
- class GUMP {
14
- // Validation rules for execution
15
- protected $validation_rules = array();
16
-
17
- // Filter rules for execution
18
- protected $filter_rules = array();
19
-
20
- // Instance attribute containing errors from last run
21
- protected $errors = array();
22
-
23
- // Contain readable field names that have been set manually
24
- protected static $fields = array();
25
-
26
- // Custom validation methods
27
- protected static $validation_methods = array();
28
-
29
- // Customer filter methods
30
- protected static $filter_methods = array();
31
-
32
- // ** ------------------------- Validation Data ------------------------------- ** //
33
-
34
- public static $basic_tags = '<br><p><a><strong><b><i><em><img><blockquote><code><dd><dl><hr><h1><h2><h3><h4><h5><h6><label><ul><li><span><sub><sup>';
35
-
36
- public static $en_noise_words = "about,after,all,also,an,and,another,any,are,as,at,be,because,been,before,
37
- being,between,both,but,by,came,can,come,could,did,do,each,for,from,get,
38
- got,has,had,he,have,her,here,him,himself,his,how,if,in,into,is,it,its,it's,like,
39
- make,many,me,might,more,most,much,must,my,never,now,of,on,only,or,other,
40
- our,out,over,said,same,see,should,since,some,still,such,take,than,that,
41
- the,their,them,then,there,these,they,this,those,through,to,too,under,up,
42
- very,was,way,we,well,were,what,where,which,while,who,with,would,you,your,a,
43
- b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,$,1,2,3,4,5,6,7,8,9,0,_";
44
-
45
- // field characters below will be replaced with a space.
46
- protected $fieldCharsToRemove = array('_', '-');
47
-
48
- // ** ------------------------- Validation Helpers ---------------------------- ** //
49
-
50
- /**
51
- * Shorthand method for inline validation.
52
- *
53
- * @param array $data The data to be validated
54
- * @param array $validators The GUMP validators
55
- *
56
- * @return mixed True(boolean) or the array of error messages
57
- */
58
- public static function is_valid(array $data, array $validators) {
59
- $gump = new self();
60
-
61
- $gump->validation_rules($validators);
62
-
63
- if ($gump->run($data) === false) {
64
- return $gump->get_readable_errors(false);
65
- } else {
66
- return true;
67
- }
68
- }
69
-
70
- /**
71
- * Shorthand method for running only the data filters.
72
- *
73
- * @param array $data
74
- * @param array $filters
75
- *
76
- * @return mixed
77
- */
78
- public static function filter_input(array $data, array $filters) {
79
- $gump = new self();
80
-
81
- return $gump->filter($data, $filters);
82
- }
83
-
84
- /**
85
- * Magic method to generate the validation error messages.
86
- *
87
- * @return string
88
- */
89
- public function __toString() {
90
- return $this->get_readable_errors(true);
91
- }
92
-
93
- /**
94
- * Perform XSS clean to prevent cross site scripting.
95
- *
96
- * @static
97
- *
98
- * @param array $data
99
- *
100
- * @return array
101
- */
102
- public static function xss_clean(array $data) {
103
- foreach ($data as $k => $v) {
104
- $data[$k] = filter_var($v, FILTER_SANITIZE_STRING);
105
- }
106
-
107
- return $data;
108
- }
109
-
110
- /**
111
- * Adds a custom validation rule using a callback function.
112
- *
113
- * @param string $rule
114
- * @param callable $callback
115
- *
116
- * @return bool
117
- *
118
- * @throws Exception
119
- */
120
- public static function add_validator($rule, $callback) {
121
- $method = 'validate_' . $rule;
122
-
123
- if (method_exists(__CLASS__, $method) || isset(self::$validation_methods[$rule])) {
124
- throw new Exception("Validator rule '$rule' already exists.");
125
- }
126
-
127
- self::$validation_methods[$rule] = $callback;
128
-
129
- return true;
130
- }
131
-
132
- /**
133
- * Adds a custom filter using a callback function.
134
- *
135
- * @param string $rule
136
- * @param callable $callback
137
- *
138
- * @return bool
139
- *
140
- * @throws Exception
141
- */
142
- public static function add_filter($rule, $callback) {
143
- $method = 'filter_' . $rule;
144
-
145
- if (method_exists(__CLASS__, $method) || isset(self::$filter_methods[$rule])) {
146
- throw new Exception("Filter rule '$rule' already exists.");
147
- }
148
-
149
- self::$filter_methods[$rule] = $callback;
150
-
151
- return true;
152
- }
153
-
154
- /**
155
- * Helper method to extract an element from an array safely
156
- *
157
- * @param mixed $key
158
- * @param array $array
159
- * @param mixed $default
160
- *
161
- * @return mixed
162
- */
163
- public static function field($key, array $array, $default = null) {
164
- if (!is_array($array)) {
165
- return null;
166
- }
167
-
168
- if (isset($array[$key])) {
169
- return $array[$key];
170
- } else {
171
- return $default;
172
- }
173
- }
174
-
175
- /**
176
- * Getter/Setter for the validation rules.
177
- *
178
- * @param array $rules
179
- *
180
- * @return array
181
- */
182
- public function validation_rules(array $rules = array()) {
183
- if (empty($rules)) {
184
- return $this->validation_rules;
185
- }
186
-
187
- $this->validation_rules = $rules;
188
- }
189
-
190
- /**
191
- * Getter/Setter for the filter rules.
192
- *
193
- * @param array $rules
194
- *
195
- * @return array
196
- */
197
- public function filter_rules(array $rules = array()) {
198
- if (empty($rules)) {
199
- return $this->filter_rules;
200
- }
201
-
202
- $this->filter_rules = $rules;
203
- }
204
-
205
- /**
206
- * Run the filtering and validation after each other.
207
- *
208
- * @param array $data
209
- * @param bool $check_fields
210
- *
211
- * @return array
212
- *
213
- * @throws Exception
214
- */
215
- public function run(array $data, $check_fields = false) {
216
- $data = $this->filter($data, $this->filter_rules());
217
-
218
- $validated = $this->validate(
219
- $data, $this->validation_rules()
220
- );
221
-
222
- if ($check_fields === true) {
223
- $this->check_fields($data);
224
- }
225
-
226
- if ($validated !== true) {
227
- return false;
228
- }
229
-
230
- return $data;
231
- }
232
-
233
- /**
234
- * Ensure that the field counts match the validation rule counts.
235
- *
236
- * @param array $data
237
- */
238
- private function check_fields(array $data) {
239
- $ruleset = $this->validation_rules();
240
- $mismatch = array_diff_key($data, $ruleset);
241
- $fields = array_keys($mismatch);
242
-
243
- foreach ($fields as $field) {
244
- $this->errors[] = array(
245
- 'field' => $field,
246
- 'value' => $data[$field],
247
- 'rule' => 'mismatch',
248
- 'param' => null,
249
- );
250
- }
251
- }
252
-
253
- /**
254
- * Sanitize the input data.
255
- *
256
- * @param array $input
257
- * @param null $fields
258
- * @param bool $utf8_encode
259
- *
260
- * @return array
261
- */
262
- public function sanitize(array $input, array $fields = array(), $utf8_encode = true) {
263
- $magic_quotes = (bool)get_magic_quotes_gpc();
264
-
265
- if (empty($fields)) {
266
- $fields = array_keys($input);
267
- }
268
-
269
- $return = array();
270
-
271
- foreach ($fields as $field) {
272
- if (!isset($input[$field])) {
273
- continue;
274
- } else {
275
- $value = $input[$field];
276
- if (is_array($value)) {
277
- $value = null;
278
- }
279
- if (is_string($value)) {
280
- if ($magic_quotes === true) {
281
- $value = stripslashes($value);
282
- }
283
-
284
- if (strpos($value, "\r") !== false) {
285
- $value = trim($value);
286
- }
287
-
288
- if (function_exists('iconv') && function_exists('mb_detect_encoding') && $utf8_encode) {
289
- $current_encoding = mb_detect_encoding($value);
290
-
291
- if ($current_encoding != 'UTF-8' && $current_encoding != 'UTF-16') {
292
- $value = iconv($current_encoding, 'UTF-8', $value);
293
- }
294
- }
295
-
296
- $value = filter_var($value, FILTER_SANITIZE_STRING);
297
- }
298
-
299
- $return[$field] = $value;
300
- }
301
- }
302
-
303
- return $return;
304
- }
305
-
306
- /**
307
- * Return the error array from the last validation run.
308
- *
309
- * @return array
310
- */
311
- public function errors() {
312
- return $this->errors;
313
- }
314
-
315
- /**
316
- * Perform data validation against the provided ruleset.
317
- *
318
- * @param mixed $input
319
- * @param array $ruleset
320
- *
321
- * @return mixed
322
- *
323
- * @throws Exception
324
- */
325
- public function validate(array $input, array $ruleset) {
326
- $this->errors = array();
327
-
328
- foreach ($ruleset as $field => $rules) {
329
-
330
- $rules = explode('|', $rules);
331
-
332
- if (in_array('required', $rules) || (isset($input[$field]) && !is_array($input[$field]))) {
333
- foreach ($rules as $rule) {
334
- $method = null;
335
- $param = null;
336
-
337
- // Check if we have rule parameters
338
- if (strstr($rule, ',') !== false) {
339
- $rule = explode(',', $rule);
340
- $method = 'validate_' . $rule[0];
341
- $param = $rule[1];
342
- $rule = $rule[0];
343
- } else {
344
- $method = 'validate_' . $rule;
345
- }
346
-
347
- //self::$validation_methods[$rule] = $callback;
348
-
349
- if (is_callable(array($this, $method))) {
350
- $result = $this->$method(
351
- $field, $input, $param
352
- );
353
-
354
- if (is_array($result)) {
355
- $this->errors[] = $result;
356
- }
357
- } elseif (isset(self::$validation_methods[$rule])) {
358
-
359
- $result = call_user_func(self::$validation_methods[$rule], $field, $input, $param);
360
-
361
- if ($result === false) {
362
- $this->errors[] = array(
363
- 'field' => $field,
364
- 'value' => $input,
365
- 'rule' => self::$validation_methods[$rule],
366
- 'param' => $param,
367
- );
368
- }
369
-
370
- } else {
371
- throw new Exception("Validator method '$method' does not exist.");
372
- }
373
- }
374
- }
375
- }
376
-
377
- return (count($this->errors) > 0) ? $this->errors : true;
378
- }
379
-
380
- /**
381
- * Overloadable method to invoke validation.
382
- *
383
- * @param array $input
384
- * @param $rules
385
- * @param $field
386
- *
387
- * @return bool
388
- */
389
- protected function shouldRunValidation(array $input, $rules, $field) {
390
- return in_array('required', $rules) || (isset($input[$field]) && trim($input[$field]) != '');
391
- }
392
-
393
- /**
394
- * Set a readable name for a specified field names.
395
- *
396
- * @param string $field
397
- * @param string $readable_name
398
- */
399
- public static function set_field_name($field, $readable_name) {
400
- self::$fields[$field] = $readable_name;
401
- }
402
-
403
- /**
404
- * Set readable name for specified fields in an array.
405
- *
406
- * Usage:
407
- *
408
- * GUMP::set_field_names(array(
409
- * "name" => "My Lovely Name",
410
- * "username" => "My Beloved Username",
411
- * ));
412
- *
413
- * @param array $array
414
- */
415
- public static function set_field_names(array $array) {
416
- foreach ($array as $field => $readable_name) {
417
- self::$fields[$field] = $readable_name;
418
- }
419
- }
420
-
421
- /**
422
- * Process the validation errors and return human readable error messages.
423
- *
424
- * @param bool $convert_to_string = false
425
- * @param string $field_class
426
- * @param string $error_class
427
- *
428
- * @return array
429
- * @return string
430
- */
431
- public function get_readable_errors($convert_to_string = false, $field_class = 'gump-field', $error_class = 'gump-error-message') {
432
- if (empty($this->errors)) {
433
- return ($convert_to_string) ? null : array();
434
- }
435
-
436
- $resp = array();
437
-
438
- foreach ($this->errors as $e) {
439
- $field = ucwords(str_replace($this->fieldCharsToRemove, chr(32), $e['field']));
440
- $param = $e['param'];
441
-
442
- // Let's fetch explicit field names if they exist
443
- if (array_key_exists($e['field'], self::$fields)) {
444
- $field = self::$fields[$e['field']];
445
- }
446
-
447
-
448
- switch ($e['rule']) {
449
- case 'mismatch' :
450
- $resp[] = sprintf( 'There is no validation rule for <span class="%1$s">%2$s</span>', $field_class, $field );
451
- break;
452
- case 'validate_required' :
453
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field is required', $field_class, $field );
454
- break;
455
- case 'validate_valid_email':
456
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field is required to be a valid email address', $field_class, $field );
457
- break;
458
- case 'validate_max_len':
459
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be %d or shorter in length', $field_class, $field, $param );
460
- break;
461
- case 'validate_min_len':
462
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be %d or longer in length', $field_class, $field, $param );
463
- break;
464
- case 'validate_exact_len':
465
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be exactly %d characters in length', $field_class, $field, $param );
466
- break;
467
- case 'validate_alpha':
468
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain alpha characters(a-z)', $field_class, $field );
469
- break;
470
- case 'validate_alpha_numeric':
471
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain alpha-numeric characters', $field_class, $field );
472
- break;
473
- case 'validate_alpha_dash':
474
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain alpha characters &amp; dashes', $field_class, $field );
475
- break;
476
- case 'validate_numeric':
477
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain numeric characters', $field_class, $field );
478
- break;
479
- case 'validate_integer':
480
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain a numeric value', $field_class, $field );
481
- break;
482
- case 'validate_boolean':
483
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain a true or false value', $field_class, $field );
484
- break;
485
- case 'validate_float':
486
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain a float value', $field_class, $field );
487
- break;
488
- case 'validate_valid_url':
489
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field is required to be a valid URL', $field_class, $field );
490
- break;
491
- case 'validate_url_exists':
492
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> URL does not exist', $field_class, $field );
493
- break;
494
- case 'validate_valid_ip':
495
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to contain a valid IP address', $field_class, $field );
496
- break;
497
- case 'validate_valid_cc':
498
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to contain a valid credit card number', $field_class, $field );
499
- break;
500
- case 'validate_valid_name':
501
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to contain a valid human name', $field_class, $field );
502
- break;
503
- case 'validate_contains':
504
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to contain one of these values:', $field_class, $field ) . ' ' . implode(', ', $param);
505
- break;
506
- case 'validate_contains_list':
507
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs contain a value from its drop down list', $field_class, $field );
508
- break;
509
- case 'validate_doesnt_contain_list':
510
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field contains a value that is not accepted', $field_class, $field );
511
- break;
512
- case 'validate_street_address':
513
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be a valid street address', $field_class, $field );
514
- break;
515
- case 'validate_date':
516
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be a valid date', $field_class, $field );
517
- break;
518
- case 'validate_min_numeric':
519
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be a numeric value, equal to, or higher than', $field_class, $field ) . $param;
520
- break;
521
- case 'validate_max_numeric':
522
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be a numeric value, equal to, or lower than', $field_class, $field ) . ' ' . $param;
523
- break;
524
- case 'validate_starts':
525
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to start with', $field_class, $field ) . ' ' . $param;
526
- break;
527
- case 'validate_extension':
528
- $resp[] = sprintf( 'The <span class"%1$s">%2$s</span> field can have the following extensions', $field_class, $field ) . ' '. $param;
529
- break;
530
- case 'validate_required_file':
531
- $resp[] = sprintf( 'The <span class"%1$s">%2$s</span> field is required', $field_class, $field ) .' ' . $param;
532
- break;
533
- case 'validate_equalsfield':
534
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field does not equal %d field', $field_class, $field, $param ) ;
535
- break;
536
- case 'validate_min_age':
537
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to have an age greater than or equal to', $field_class, $field ) . ' '. $param;;
538
- break;
539
- default:
540
- $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field is invalid', $field_class, $field );
541
- }
542
- }
543
-
544
- if (!$convert_to_string) {
545
- return $resp;
546
- } else {
547
- $buffer = '';
548
- foreach ($resp as $s) {
549
- $buffer .= "<span class=\"$error_class\">$s</span>";
550
- }
551
-
552
- return $buffer;
553
- }
554
- }
555
-
556
- /**
557
- * Process the validation errors and return an array of errors with field names as keys.
558
- *
559
- * @param $convert_to_string
560
- *
561
- * @return array | null (if empty)
562
- */
563
- public function get_errors_array($convert_to_string = null) {
564
- if (empty($this->errors)) {
565
- return ($convert_to_string) ? null : array();
566
- }
567
-
568
- $resp = array();
569
-
570
- foreach ($this->errors as $e) {
571
- $field = ucwords(str_replace(array('_', '-'), chr(32), $e['field']));
572
- $param = $e['param'];
573
-
574
- // Let's fetch explicit field names if they exist
575
- if (array_key_exists($e['field'], self::$fields)) {
576
- $field = self::$fields[$e['field']];
577
- }
578
-
579
- switch ($e['rule']) {
580
- case 'mismatch' :
581
- $resp[$field] = 'There is no validation rule for' . ' ' . $field;
582
- break;
583
- case 'validate_required':
584
- $resp[$field] = sprintf( 'The %s field is required', $field);
585
- break;
586
- case 'validate_valid_email':
587
- $resp[$field] = sprintf( 'The %s field is required to be a valid email address', $field);
588
- break;
589
- case 'validate_max_len':
590
- $resp[$field] = sprintf( 'The %s field needs to be %d or shorter in length', $field, $param);
591
- break;
592
- case 'validate_min_len':
593
- $resp[$field] = sprintf( 'The %s field needs to be %d or longer in length', $field, $param);
594
- break;
595
- case 'validate_exact_len':
596
- $resp[$field] = sprintf( 'The %s field needs to be exactly %d characters in length', $field, $param);
597
- break;
598
- case 'validate_alpha':
599
- $resp[$field] = sprintf( 'The %s field may only contain alpha characters(a-z)', $field);
600
- break;
601
- case 'validate_alpha_numeric':
602
- $resp[$field] = sprintf( 'The %s field may only contain alpha-numeric characters', $field);
603
- break;
604
- case 'validate_alpha_dash':
605
- $resp[$field] = sprintf( 'The %s field may only contain alpha characters &amp; dashes', $field);
606
- break;
607
- case 'validate_numeric':
608
- $resp[$field] = sprintf( 'The %s field may only contain numeric characters', $field);
609
- break;
610
- case 'validate_integer':
611
- $resp[$field] = sprintf( 'The %s field may only contain a numeric value', $field);
612
- break;
613
- case 'validate_boolean':
614
- $resp[$field] = sprintf( 'The %s field may only contain a true or false value', $field);
615
- break;
616
- case 'validate_float':
617
- $resp[$field] = sprintf( 'The %s field may only contain a float value', $field);
618
- break;
619
- case 'validate_valid_url':
620
- $resp[$field] = sprintf( 'The %s field is required to be a valid URL', $field);
621
- break;
622
- case 'validate_url_exists':
623
- $resp[$field] = sprintf( 'The %s URL does not exist', $field);
624
- break;
625
- case 'validate_valid_ip':
626
- $resp[$field] = sprintf( 'The %s field needs to contain a valid IP address', $field);
627
- break;
628
- case 'validate_valid_cc':
629
- $resp[$field] = sprintf( 'The %s field needs to contain a valid credit card number', $field);
630
- break;
631
- case 'validate_valid_name':
632
- $resp[$field] = sprintf( 'The %s field needs to contain a valid human name', $field);
633
- break;
634
- case 'validate_contains':
635
- $resp[$field] = sprintf( 'The %s field needs to contain one of these values:', $field) . ' ' . implode(', ', $param);
636
- break;
637
- case 'validate_street_address':
638
- $resp[$field] = sprintf( 'The %s field needs to be a valid street address', $field);
639
- break;
640
- case 'validate_date':
641
- $resp[$field] = sprintf( 'The %s field needs to be a valid date', $field);
642
- break;
643
- case 'validate_min_numeric':
644
- $resp[$field] = sprintf( 'The %s field needs to be a numeric value, equal to, or higher than %d', $field, $param);
645
- break;
646
- case 'validate_max_numeric':
647
- $resp[$field] = sprintf( 'The %s field needs to be a numeric value, equal to, or lower than %d', $field, $param);
648
- break;
649
- case 'validate_min_age':
650
- $resp[$field] = sprintf( 'The %s field needs to have an age greater than or equal to %d', $field, $param);
651
- break;
652
- default:
653
- $resp[$field] = sprintf( 'The %s field is invalid', $field );
654
- }
655
- }
656
-
657
- return $resp;
658
- }
659
-
660
-
661
- /**
662
- * Filter the input data according to the specified filter set.
663
- *
664
- * @param mixed $input
665
- * @param array $filterset
666
- *
667
- * @throws Exception
668
- *
669
- * @return mixed
670
- *
671
- * @throws Exception
672
- */
673
- public function filter(array $input, array $filterset) {
674
- foreach ($filterset as $field => $filters) {
675
- if (!array_key_exists($field, $input)) {
676
- continue;
677
- }
678
-
679
- $filters = explode('|', $filters);
680
-
681
- foreach ($filters as $filter) {
682
- $params = null;
683
-
684
- if (strstr($filter, ',') !== false) {
685
- $filter = explode(',', $filter);
686
-
687
- $params = array_slice($filter, 1, count($filter) - 1);
688
-
689
- $filter = $filter[0];
690
- }
691
-
692
- if (is_callable(array($this, 'filter_' . $filter))) {
693
- $method = 'filter_' . $filter;
694
- $input[$field] = $this->$method($input[$field], $params);
695
- } elseif (function_exists($filter)) {
696
- $input[$field] = $filter($input[$field]);
697
- } elseif (isset(self::$filter_methods[$filter])) {
698
- $input[$field] = call_user_func(self::$filter_methods[$filter], $input[$field], $params);
699
- } else {
700
- throw new Exception("Filter method '$filter' does not exist.");
701
- }
702
- }
703
- }
704
-
705
- return $input;
706
- }
707
-
708
- // ** ------------------------- Filters --------------------------------------- ** //
709
-
710
- /**
711
- * Replace noise words in a string (http://tax.cchgroup.com/help/Avoiding_noise_words_in_your_search.htm).
712
- *
713
- * Usage: '<index>' => 'noise_words'
714
- *
715
- * @param string $value
716
- * @param array $params
717
- *
718
- * @return string
719
- */
720
- protected function filter_noise_words($value, $params = null) {
721
- $value = preg_replace('/\s\s+/u', chr(32), $value);
722
-
723
- $value = " $value ";
724
-
725
- $words = explode(',', self::$en_noise_words);
726
-
727
- foreach ($words as $word) {
728
- $word = trim($word);
729
-
730
- $word = " $word "; // Normalize
731
-
732
- if (stripos($value, $word) !== false) {
733
- $value = str_ireplace($word, chr(32), $value);
734
- }
735
- }
736
-
737
- return trim($value);
738
- }
739
-
740
- /**
741
- * Remove all known punctuation from a string.
742
- *
743
- * Usage: '<index>' => 'rmpunctuataion'
744
- *
745
- * @param string $value
746
- * @param array $params
747
- *
748
- * @return string
749
- */
750
- protected function filter_rmpunctuation($value, $params = null) {
751
- return preg_replace("/(?![.=$'€%-])\p{P}/u", '', $value);
752
- }
753
-
754
- /**
755
- * Translate an input string to a desired language [DEPRECIATED].
756
- *
757
- * Any ISO 639-1 2 character language code may be used
758
- *
759
- * See: http://www.science.co.il/language/Codes.asp?s=code2
760
- *
761
- * @param string $value
762
- * @param array $params
763
- *
764
- * @return string
765
- */
766
- /*
767
- protected function filter_translate($value, $params = NULL)
768
- {
769
- $input_lang = 'en';
770
- $output_lang = 'en';
771
-
772
- if(is_null($params))
773
- {
774
- return $value;
775
- }
776
-
777
- switch(count($params))
778
- {
779
- case 1:
780
- $input_lang = $params[0];
781
- break;
782
- case 2:
783
- $input_lang = $params[0];
784
- $output_lang = $params[1];
785
- break;
786
- }
787
-
788
- $text = urlencode($value);
789
-
790
- $translation = file_get_contents(
791
- "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q={$text}&langpair={$input_lang}|{$output_lang}"
792
- );
793
-
794
- $json = json_decode($translation, true);
795
-
796
- if($json['responseStatus'] != 200)
797
- {
798
- return $value;
799
- }
800
- else
801
- {
802
- return $json['responseData']['translatedText'];
803
- }
804
- }
805
- */
806
-
807
- /**
808
- * Sanitize the string by removing any script tags.
809
- *
810
- * Usage: '<index>' => 'sanitize_string'
811
- *
812
- * @param string $value
813
- * @param array $params
814
- *
815
- * @return string
816
- */
817
- protected function filter_sanitize_string($value, $params = null) {
818
- return filter_var($value, FILTER_SANITIZE_STRING);
819
- }
820
-
821
- /**
822
- * Sanitize the string by urlencoding characters.
823
- *
824
- * Usage: '<index>' => 'urlencode'
825
- *
826
- * @param string $value
827
- * @param array $params
828
- *
829
- * @return string
830
- */
831
- protected function filter_urlencode($value, $params = null) {
832
- return filter_var($value, FILTER_SANITIZE_ENCODED);
833
- }
834
-
835
- /**
836
- * Sanitize the string by converting HTML characters to their HTML entities.
837
- *
838
- * Usage: '<index>' => 'htmlencode'
839
- *
840
- * @param string $value
841
- * @param array $params
842
- *
843
- * @return string
844
- */
845
- protected function filter_htmlencode($value, $params = null) {
846
- return filter_var($value, FILTER_SANITIZE_SPECIAL_CHARS);
847
- }
848
-
849
- /**
850
- * Sanitize the string by removing illegal characters from emails.
851
- *
852
- * Usage: '<index>' => 'sanitize_email'
853
- *
854
- * @param string $value
855
- * @param array $params
856
- *
857
- * @return string
858
- */
859
- protected function filter_sanitize_email($value, $params = null) {
860
- return filter_var($value, FILTER_SANITIZE_EMAIL);
861
- }
862
-
863
- /**
864
- * Sanitize the string by removing illegal characters from numbers.
865
- *
866
- * @param string $value
867
- * @param array $params
868
- *
869
- * @return string
870
- */
871
- protected function filter_sanitize_numbers($value, $params = null) {
872
- return filter_var($value, FILTER_SANITIZE_NUMBER_INT);
873
- }
874
-
875
- /**
876
- * Filter out all HTML tags except the defined basic tags.
877
- *
878
- * @param string $value
879
- * @param array $params
880
- *
881
- * @return string
882
- */
883
- protected function filter_basic_tags($value, $params = null) {
884
- return strip_tags($value, self::$basic_tags);
885
- }
886
-
887
- /**
888
- * Convert the provided numeric value to a whole number.
889
- *
890
- * @param string $value
891
- * @param array $params
892
- *
893
- * @return string
894
- */
895
- protected function filter_whole_number($value, $params = null) {
896
- return intval($value);
897
- }
898
-
899
- // ** ------------------------- Validators ------------------------------------ ** //
900
-
901
-
902
- /**
903
- * Verify that a value is contained within the pre-defined value set.
904
- *
905
- * Usage: '<index>' => 'contains,value value value'
906
- *
907
- * @param string $field
908
- * @param array $input
909
- * @param null $param
910
- *
911
- * @return mixed
912
- */
913
- protected function validate_contains($field, $input, $param = null) {
914
- if (!isset($input[$field])) {
915
- return;
916
- }
917
-
918
- $param = trim(strtolower($param));
919
-
920
- $value = trim(strtolower($input[$field]));
921
-
922
- if (preg_match_all('#\'(.+?)\'#', $param, $matches, PREG_PATTERN_ORDER)) {
923
- $param = $matches[1];
924
- } else {
925
- $param = explode(chr(32), $param);
926
- }
927
-
928
- if (in_array($value, $param)) { // valid, return nothing
929
- return;
930
- }
931
-
932
- return array(
933
- 'field' => $field,
934
- 'value' => $value,
935
- 'rule' => __FUNCTION__,
936
- 'param' => $param,
937
- );
938
- }
939
-
940
- /**
941
- * Verify that a value is contained within the pre-defined value set.
942
- * OUTPUT: will NOT show the list of values.
943
- *
944
- * Usage: '<index>' => 'contains_list,value;value;value'
945
- *
946
- * @param string $field
947
- * @param array $input
948
- *
949
- * @return mixed
950
- */
951
- protected function validate_contains_list($field, $input, $param = null) {
952
- $param = trim(strtolower($param));
953
-
954
- $value = trim(strtolower($input[$field]));
955
-
956
- $param = explode(';', $param);
957
-
958
- // consider: in_array(strtolower($value), array_map('strtolower', $param)
959
-
960
- if (in_array($value, $param)) { // valid, return nothing
961
- return;
962
- } else {
963
- return array(
964
- 'field' => $field,
965
- 'value' => $value,
966
- 'rule' => __FUNCTION__,
967
- 'param' => $param,
968
- );
969
- }
970
- }
971
-
972
- /**
973
- * Verify that a value is NOT contained within the pre-defined value set.
974
- * OUTPUT: will NOT show the list of values.
975
- *
976
- * Usage: '<index>' => 'doesnt_contain_list,value;value;value'
977
- *
978
- * @param string $field
979
- * @param array $input
980
- *
981
- * @return mixed
982
- */
983
- protected function validate_doesnt_contain_list($field, $input, $param = null) {
984
- $param = trim(strtolower($param));
985
-
986
- $value = trim(strtolower($input[$field]));
987
-
988
- $param = explode(';', $param);
989
-
990
- if (!in_array($value, $param)) { // valid, return nothing
991
- return;
992
- } else {
993
- return array(
994
- 'field' => $field,
995
- 'value' => $value,
996
- 'rule' => __FUNCTION__,
997
- 'param' => $param,
998
- );
999
- }
1000
- }
1001
-
1002
- /**
1003
- * Check if the specified key is present and not empty.
1004
- *
1005
- * Usage: '<index>' => 'required'
1006
- *
1007
- * @param string $field
1008
- * @param array $input
1009
- * @param null $param
1010
- *
1011
- * @return mixed
1012
- */
1013
- protected function validate_required($field, $input, $param = null) {
1014
- if (isset($input[$field]) && ($input[$field] === false || $input[$field] === 0 || $input[$field] === 0.0 || $input[$field] === '0' || !empty($input[$field]))) {
1015
- return;
1016
- }
1017
-
1018
- return array(
1019
- 'field' => $field,
1020
- 'value' => null,
1021
- 'rule' => __FUNCTION__,
1022
- 'param' => $param,
1023
- );
1024
- }
1025
-
1026
- /**
1027
- * Determine if the provided email is valid.
1028
- *
1029
- * Usage: '<index>' => 'valid_email'
1030
- *
1031
- * @param string $field
1032
- * @param array $input
1033
- * @param null $param
1034
- *
1035
- * @return mixed
1036
- */
1037
- protected function validate_valid_email($field, $input, $param = null) {
1038
- if (!isset($input[$field]) || empty($input[$field])) {
1039
- return;
1040
- }
1041
-
1042
- if (!filter_var($input[$field], FILTER_VALIDATE_EMAIL)) {
1043
- return array(
1044
- 'field' => $field,
1045
- 'value' => $input[$field],
1046
- 'rule' => __FUNCTION__,
1047
- 'param' => $param,
1048
- );
1049
- }
1050
- }
1051
-
1052
- /**
1053
- * Determine if the provided value length is less or equal to a specific value.
1054
- *
1055
- * Usage: '<index>' => 'max_len,240'
1056
- *
1057
- * @param string $field
1058
- * @param array $input
1059
- * @param null $param
1060
- *
1061
- * @return mixed
1062
- */
1063
- protected function validate_max_len($field, $input, $param = null) {
1064
- if (!isset($input[$field])) {
1065
- return;
1066
- }
1067
-
1068
- if (function_exists('mb_strlen')) {
1069
- if (mb_strlen($input[$field]) <= (int)$param) {
1070
- return;
1071
- }
1072
- } else {
1073
- if (strlen($input[$field]) <= (int)$param) {
1074
- return;
1075
- }
1076
- }
1077
-
1078
- return array(
1079
- 'field' => $field,
1080
- 'value' => $input[$field],
1081
- 'rule' => __FUNCTION__,
1082
- 'param' => $param,
1083
- );
1084
- }
1085
-
1086
- /**
1087
- * Determine if the provided value length is more or equal to a specific value.
1088
- *
1089
- * Usage: '<index>' => 'min_len,4'
1090
- *
1091
- * @param string $field
1092
- * @param array $input
1093
- * @param null $param
1094
- *
1095
- * @return mixed
1096
- */
1097
- protected function validate_min_len($field, $input, $param = null) {
1098
- if (!isset($input[$field])) {
1099
- return;
1100
- }
1101
-
1102
- if (function_exists('mb_strlen')) {
1103
- if (mb_strlen($input[$field]) >= (int)$param) {
1104
- return;
1105
- }
1106
- } else {
1107
- if (strlen($input[$field]) >= (int)$param) {
1108
- return;
1109
- }
1110
- }
1111
-
1112
- return array(
1113
- 'field' => $field,
1114
- 'value' => $input[$field],
1115
- 'rule' => __FUNCTION__,
1116
- 'param' => $param,
1117
- );
1118
- }
1119
-
1120
- /**
1121
- * Determine if the provided value length matches a specific value.
1122
- *
1123
- * Usage: '<index>' => 'exact_len,5'
1124
- *
1125
- * @param string $field
1126
- * @param array $input
1127
- * @param null $param
1128
- *
1129
- * @return mixed
1130
- */
1131
- protected function validate_exact_len($field, $input, $param = null) {
1132
- if (!isset($input[$field])) {
1133
- return;
1134
- }
1135
-
1136
- if (function_exists('mb_strlen')) {
1137
- if (mb_strlen($input[$field]) == (int)$param) {
1138
- return;
1139
- }
1140
- } else {
1141
- if (strlen($input[$field]) == (int)$param) {
1142
- return;
1143
- }
1144
- }
1145
-
1146
- return array(
1147
- 'field' => $field,
1148
- 'value' => $input[$field],
1149
- 'rule' => __FUNCTION__,
1150
- 'param' => $param,
1151
- );
1152
- }
1153
-
1154
- /**
1155
- * Determine if the provided value contains only alpha characters.
1156
- *
1157
- * Usage: '<index>' => 'alpha'
1158
- *
1159
- * @param string $field
1160
- * @param array $input
1161
- * @param null $param
1162
- *
1163
- * @return mixed
1164
- */
1165
- protected function validate_alpha($field, $input, $param = null) {
1166
- if (!isset($input[$field]) || empty($input[$field])) {
1167
- return;
1168
- }
1169
-
1170
- if (!preg_match('/^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ])+$/i', $input[$field]) !== false) {
1171
- return array(
1172
- 'field' => $field,
1173
- 'value' => $input[$field],
1174
- 'rule' => __FUNCTION__,
1175
- 'param' => $param,
1176
- );
1177
- }
1178
- }
1179
-
1180
- /**
1181
- * Determine if the provided value contains only alpha-numeric characters.
1182
- *
1183
- * Usage: '<index>' => 'alpha_numeric'
1184
- *
1185
- * @param string $field
1186
- * @param array $input
1187
- * @param null $param
1188
- *
1189
- * @return mixed
1190
- */
1191
- protected function validate_alpha_numeric($field, $input, $param = null) {
1192
- if (!isset($input[$field]) || empty($input[$field])) {
1193
- return;
1194
- }
1195
-
1196
- if (!preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ])+$/i', $input[$field]) !== false) {
1197
- return array(
1198
- 'field' => $field,
1199
- 'value' => $input[$field],
1200
- 'rule' => __FUNCTION__,
1201
- 'param' => $param,
1202
- );
1203
- }
1204
- }
1205
-
1206
- /**
1207
- * Determine if the provided value contains only alpha characters with dashed and underscores.
1208
- *
1209
- * Usage: '<index>' => 'alpha_dash'
1210
- *
1211
- * @param string $field
1212
- * @param array $input
1213
- * @param null $param
1214
- *
1215
- * @return mixed
1216
- */
1217
- protected function validate_alpha_dash($field, $input, $param = null) {
1218
- if (!isset($input[$field]) || empty($input[$field])) {
1219
- return;
1220
- }
1221
-
1222
- if (!preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ_-])+$/i', $input[$field]) !== false) {
1223
- return array(
1224
- 'field' => $field,
1225
- 'value' => $input[$field],
1226
- 'rule' => __FUNCTION__,
1227
- 'param' => $param,
1228
- );
1229
- }
1230
- }
1231
-
1232
- /**
1233
- * Determine if the provided value contains only alpha numeric characters with spaces.
1234
- *
1235
- * Usage: '<index>' => 'alpha_space'
1236
- *
1237
- * @param string $field
1238
- * @param array $input
1239
- * @param null $param
1240
- *
1241
- * @return mixed
1242
- */
1243
- protected function validate_alpha_space($field, $input, $param = null) {
1244
- if (!isset($input[$field]) || empty($input[$field])) {
1245
- return;
1246
- }
1247
-
1248
- if (!preg_match("/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ\s])+$/i", $input[$field]) !== false) {
1249
- return array(
1250
- 'field' => $field,
1251
- 'value' => $input[$field],
1252
- 'rule' => __FUNCTION__,
1253
- 'param' => $param,
1254
- );
1255
- }
1256
- }
1257
-
1258
- /**
1259
- * Determine if the provided value is a valid number or numeric string.
1260
- *
1261
- * Usage: '<index>' => 'numeric'
1262
- *
1263
- * @param string $field
1264
- * @param array $input
1265
- * @param null $param
1266
- *
1267
- * @return mixed
1268
- */
1269
- protected function validate_numeric($field, $input, $param = null) {
1270
- if (!isset($input[$field]) || empty($input[$field])) {
1271
- return;
1272
- }
1273
-
1274
- if (!is_numeric($input[$field])) {
1275
- return array(
1276
- 'field' => $field,
1277
- 'value' => $input[$field],
1278
- 'rule' => __FUNCTION__,
1279
- 'param' => $param,
1280
- );
1281
- }
1282
- }
1283
-
1284
- /**
1285
- * Determine if the provided value is a valid integer.
1286
- *
1287
- * Usage: '<index>' => 'integer'
1288
- *
1289
- * @param string $field
1290
- * @param array $input
1291
- * @param null $param
1292
- *
1293
- * @return mixed
1294
- */
1295
- protected function validate_integer($field, $input, $param = null) {
1296
- if (!isset($input[$field]) || empty($input[$field])) {
1297
- return;
1298
- }
1299
-
1300
- if (filter_var($input[$field], FILTER_VALIDATE_INT) === false) {
1301
- return array(
1302
- 'field' => $field,
1303
- 'value' => $input[$field],
1304
- 'rule' => __FUNCTION__,
1305
- 'param' => $param,
1306
- );
1307
- }
1308
- }
1309
-
1310
- /**
1311
- * Determine if the provided value is a PHP accepted boolean.
1312
- *
1313
- * Usage: '<index>' => 'boolean'
1314
- *
1315
- * @param string $field
1316
- * @param array $input
1317
- * @param null $param
1318
- *
1319
- * @return mixed
1320
- */
1321
- protected function validate_boolean($field, $input, $param = null) {
1322
- if (!isset($input[$field]) || empty($input[$field]) && $input[$field] !== 0) {
1323
- return;
1324
- }
1325
-
1326
- if ($input[$field] === true || $input[$field] === false) {
1327
- return;
1328
- }
1329
-
1330
- return array(
1331
- 'field' => $field,
1332
- 'value' => $input[$field],
1333
- 'rule' => __FUNCTION__,
1334
- 'param' => $param,
1335
- );
1336
- }
1337
-
1338
- /**
1339
- * Determine if the provided value is a valid float.
1340
- *
1341
- * Usage: '<index>' => 'float'
1342
- *
1343
- * @param string $field
1344
- * @param array $input
1345
- * @param null $param
1346
- *
1347
- * @return mixed
1348
- */
1349
- protected function validate_float($field, $input, $param = null) {
1350
- if (!isset($input[$field]) || empty($input[$field])) {
1351
- return;
1352
- }
1353
-
1354
- if (filter_var($input[$field], FILTER_VALIDATE_FLOAT) === false) {
1355
- return array(
1356
- 'field' => $field,
1357
- 'value' => $input[$field],
1358
- 'rule' => __FUNCTION__,
1359
- 'param' => $param,
1360
- );
1361
- }
1362
- }
1363
-
1364
- /**
1365
- * Determine if the provided value is a valid URL.
1366
- *
1367
- * Usage: '<index>' => 'valid_url'
1368
- *
1369
- * @param string $field
1370
- * @param array $input
1371
- * @param null $param
1372
- *
1373
- * @return mixed
1374
- */
1375
- protected function validate_valid_url($field, $input, $param = null) {
1376
- if (!isset($input[$field]) || empty($input[$field])) {
1377
- return;
1378
- }
1379
-
1380
- if (!filter_var($input[$field], FILTER_VALIDATE_URL)) {
1381
- return array(
1382
- 'field' => $field,
1383
- 'value' => $input[$field],
1384
- 'rule' => __FUNCTION__,
1385
- 'param' => $param,
1386
- );
1387
- }
1388
- }
1389
-
1390
- /**
1391
- * Determine if a URL exists & is accessible.
1392
- *
1393
- * Usage: '<index>' => 'url_exists'
1394
- *
1395
- * @param string $field
1396
- * @param array $input
1397
- * @param null $param
1398
- *
1399
- * @return mixed
1400
- */
1401
- protected function validate_url_exists($field, $input, $param = null) {
1402
- if (!isset($input[$field]) || empty($input[$field])) {
1403
- return;
1404
- }
1405
-
1406
- $url = parse_url(strtolower($input[$field]));
1407
-
1408
- if (isset($url['host'])) {
1409
- $url = $url['host'];
1410
- }
1411
-
1412
- if (function_exists('checkdnsrr')) {
1413
- if (checkdnsrr($url) === false) {
1414
- return array(
1415
- 'field' => $field,
1416
- 'value' => $input[$field],
1417
- 'rule' => __FUNCTION__,
1418
- 'param' => $param,
1419
- );
1420
- }
1421
- } else {
1422
- if (gethostbyname($url) == $url) {
1423
- return array(
1424
- 'field' => $field,
1425
- 'value' => $input[$field],
1426
- 'rule' => __FUNCTION__,
1427
- 'param' => $param,
1428
- );
1429
- }
1430
- }
1431
- }
1432
-
1433
- /**
1434
- * Determine if the provided value is a valid IP address.
1435
- *
1436
- * Usage: '<index>' => 'valid_ip'
1437
- *
1438
- * @param string $field
1439
- * @param array $input
1440
- *
1441
- * @return mixed
1442
- */
1443
- protected function validate_valid_ip($field, $input, $param = null) {
1444
- if (!isset($input[$field]) || empty($input[$field])) {
1445
- return;
1446
- }
1447
-
1448
- if (!filter_var($input[$field], FILTER_VALIDATE_IP) !== false) {
1449
- return array(
1450
- 'field' => $field,
1451
- 'value' => $input[$field],
1452
- 'rule' => __FUNCTION__,
1453
- 'param' => $param,
1454
- );
1455
- }
1456
- }
1457
-
1458
- /**
1459
- * Determine if the provided value is a valid IPv4 address.
1460
- *
1461
- * Usage: '<index>' => 'valid_ipv4'
1462
- *
1463
- * @param string $field
1464
- * @param array $input
1465
- *
1466
- * @return mixed
1467
- *
1468
- * @see http://pastebin.com/UvUPPYK0
1469
- */
1470
-
1471
- /*
1472
- * What about private networks? http://en.wikipedia.org/wiki/Private_network
1473
- * What about loop-back address? 127.0.0.1
1474
- */
1475
- protected function validate_valid_ipv4($field, $input, $param = null) {
1476
- if (!isset($input[$field]) || empty($input[$field])) {
1477
- return;
1478
- }
1479
-
1480
- if (!filter_var($input[$field], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
1481
- // removed !== FALSE
1482
-
1483
- return array(
1484
- 'field' => $field,
1485
- 'value' => $input[$field],
1486
- 'rule' => __FUNCTION__,
1487
- 'param' => $param,
1488
- );
1489
- }
1490
- }
1491
-
1492
- /**
1493
- * Determine if the provided value is a valid IPv6 address.
1494
- *
1495
- * Usage: '<index>' => 'valid_ipv6'
1496
- *
1497
- * @param string $field
1498
- * @param array $input
1499
- *
1500
- * @return mixed
1501
- */
1502
- protected function validate_valid_ipv6($field, $input, $param = null) {
1503
- if (!isset($input[$field]) || empty($input[$field])) {
1504
- return;
1505
- }
1506
-
1507
- if (!filter_var($input[$field], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
1508
- return array(
1509
- 'field' => $field,
1510
- 'value' => $input[$field],
1511
- 'rule' => __FUNCTION__,
1512
- 'param' => $param,
1513
- );
1514
- }
1515
- }
1516
-
1517
- /**
1518
- * Determine if the input is a valid credit card number.
1519
- *
1520
- * See: http://stackoverflow.com/questions/174730/what-is-the-best-way-to-validate-a-credit-card-in-php
1521
- * Usage: '<index>' => 'valid_cc'
1522
- *
1523
- * @param string $field
1524
- * @param array $input
1525
- *
1526
- * @return mixed
1527
- */
1528
- protected function validate_valid_cc($field, $input, $param = null) {
1529
- if (!isset($input[$field]) || empty($input[$field])) {
1530
- return;
1531
- }
1532
-
1533
- $number = preg_replace('/\D/', '', $input[$field]);
1534
-
1535
- if (function_exists('mb_strlen')) {
1536
- $number_length = mb_strlen($number);
1537
- } else {
1538
- $number_length = strlen($number);
1539
- }
1540
-
1541
- $parity = $number_length % 2;
1542
-
1543
- $total = 0;
1544
-
1545
- for ($i = 0; $i < $number_length; ++$i) {
1546
- $digit = $number[$i];
1547
-
1548
- if ($i % 2 == $parity) {
1549
- $digit *= 2;
1550
-
1551
- if ($digit > 9) {
1552
- $digit -= 9;
1553
- }
1554
- }
1555
-
1556
- $total += $digit;
1557
- }
1558
-
1559
- if ($total % 10 == 0) {
1560
- return; // Valid
1561
- }
1562
-
1563
- return array(
1564
- 'field' => $field,
1565
- 'value' => $input[$field],
1566
- 'rule' => __FUNCTION__,
1567
- 'param' => $param,
1568
- );
1569
- }
1570
-
1571
- /**
1572
- * Determine if the input is a valid human name [Credits to http://github.com/ben-s].
1573
- *
1574
- * See: https://github.com/Wixel/GUMP/issues/5
1575
- * Usage: '<index>' => 'valid_name'
1576
- *
1577
- * @param string $field
1578
- * @param array $input
1579
- *
1580
- * @return mixed
1581
- */
1582
- protected function validate_valid_name($field, $input, $param = null) {
1583
- if (!isset($input[$field]) || empty($input[$field])) {
1584
- return;
1585
- }
1586
-
1587
- if (!preg_match("/^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïñðòóôõöùúûüýÿ '-])+$/i", $input[$field]) !== false) {
1588
- return array(
1589
- 'field' => $field,
1590
- 'value' => $input[$field],
1591
- 'rule' => __FUNCTION__,
1592
- 'param' => $param,
1593
- );
1594
- }
1595
- }
1596
-
1597
- /**
1598
- * Determine if the provided input is likely to be a street address using weak detection.
1599
- *
1600
- * Usage: '<index>' => 'street_address'
1601
- *
1602
- * @param string $field
1603
- * @param array $input
1604
- *
1605
- * @return mixed
1606
- */
1607
- protected function validate_street_address($field, $input, $param = null) {
1608
- if (!isset($input[$field]) || empty($input[$field])) {
1609
- return;
1610
- }
1611
-
1612
- // Theory: 1 number, 1 or more spaces, 1 or more words
1613
- $hasLetter = preg_match('/[a-zA-Z]/', $input[$field]);
1614
- $hasDigit = preg_match('/\d/', $input[$field]);
1615
- $hasSpace = preg_match('/\s/', $input[$field]);
1616
-
1617
- $passes = $hasLetter && $hasDigit && $hasSpace;
1618
-
1619
- if (!$passes) {
1620
- return array(
1621
- 'field' => $field,
1622
- 'value' => $input[$field],
1623
- 'rule' => __FUNCTION__,
1624
- 'param' => $param,
1625
- );
1626
- }
1627
- }
1628
-
1629
- /**
1630
- * Determine if the provided value is a valid IBAN.
1631
- *
1632
- * Usage: '<index>' => 'iban'
1633
- *
1634
- * @param string $field
1635
- * @param array $input
1636
- *
1637
- * @return mixed
1638
- */
1639
- protected function validate_iban($field, $input, $param = null) {
1640
- if (!isset($input[$field]) || empty($input[$field])) {
1641
- return;
1642
- }
1643
-
1644
- static $character = array(
1645
- 'A' => 10, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16,
1646
- 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22,
1647
- 'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, 'S' => 28,
1648
- 'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34,
1649
- 'Z' => 35, 'B' => 11
1650
- );
1651
-
1652
- if (!preg_match("/\A[A-Z]{2}\d{2} ?[A-Z\d]{4}( ?\d{4}){1,} ?\d{1,4}\z/", $input[$field])) {
1653
- return array(
1654
- 'field' => $field,
1655
- 'value' => $input[$field],
1656
- 'rule' => __FUNCTION__,
1657
- 'param' => $param,
1658
- );
1659
- }
1660
-
1661
- $iban = str_replace(' ', '', $input[$field]);
1662
- $iban = substr($iban, 4) . substr($iban, 0, 4);
1663
- $iban = strtr($iban, $character);
1664
-
1665
- if (bcmod($iban, 97) != 1) {
1666
- return array(
1667
- 'field' => $field,
1668
- 'value' => $input[$field],
1669
- 'rule' => __FUNCTION__,
1670
- 'param' => $param,
1671
- );
1672
- }
1673
- }
1674
-
1675
- /**
1676
- * Determine if the provided input is a valid date (ISO 8601).
1677
- *
1678
- * Usage: '<index>' => 'date'
1679
- *
1680
- * @param string $field
1681
- * @param string $input date ('Y-m-d') or datetime ('Y-m-d H:i:s')
1682
- * @param null $param
1683
- *
1684
- * @return mixed
1685
- */
1686
- protected function validate_date($field, $input, $param = null) {
1687
- if (!isset($input[$field]) || empty($input[$field])) {
1688
- return;
1689
- }
1690
-
1691
- $cdate1 = date('Y-m-d', strtotime($input[$field]));
1692
- $cdate2 = date('Y-m-d H:i:s', strtotime($input[$field]));
1693
-
1694
- if ($cdate1 != $input[$field] && $cdate2 != $input[$field]) {
1695
- return array(
1696
- 'field' => $field,
1697
- 'value' => $input[$field],
1698
- 'rule' => __FUNCTION__,
1699
- 'param' => $param,
1700
- );
1701
- }
1702
- }
1703
-
1704
- /**
1705
- * Determine if the provided input meets age requirement (ISO 8601).
1706
- *
1707
- * Usage: '<index>' => 'min_age,13'
1708
- *
1709
- * @param string $field
1710
- * @param string $input date ('Y-m-d') or datetime ('Y-m-d H:i:s')
1711
- * @param string $param int
1712
- *
1713
- * @return mixed
1714
- */
1715
- protected function validate_min_age($field, $input, $param = null) {
1716
- if (!isset($input[$field]) || empty($input[$field])) {
1717
- return;
1718
- }
1719
-
1720
- $cdate1 = new DateTime(date('Y-m-d', strtotime($input[$field])));
1721
- $today = new DateTime(date('d-m-Y'));
1722
-
1723
- $interval = $cdate1->diff($today);
1724
- $age = $interval->y;
1725
-
1726
- if ($age <= $param) {
1727
- return array(
1728
- 'field' => $field,
1729
- 'value' => $input[$field],
1730
- 'rule' => __FUNCTION__,
1731
- 'param' => $param,
1732
- );
1733
- }
1734
- }
1735
-
1736
- /**
1737
- * Determine if the provided numeric value is lower or equal to a specific value.
1738
- *
1739
- * Usage: '<index>' => 'max_numeric,50'
1740
- *
1741
- * @param string $field
1742
- * @param array $input
1743
- * @param null $param
1744
- *
1745
- * @return mixed
1746
- */
1747
- protected function validate_max_numeric($field, $input, $param = null) {
1748
- if (!isset($input[$field]) || empty($input[$field])) {
1749
- return;
1750
- }
1751
-
1752
- if (is_numeric($input[$field]) && is_numeric($param) && ($input[$field] <= $param)) {
1753
- return;
1754
- }
1755
-
1756
- return array(
1757
- 'field' => $field,
1758
- 'value' => $input[$field],
1759
- 'rule' => __FUNCTION__,
1760
- 'param' => $param,
1761
- );
1762
- }
1763
-
1764
- /**
1765
- * Determine if the provided numeric value is higher or equal to a specific value.
1766
- *
1767
- * Usage: '<index>' => 'min_numeric,1'
1768
- *
1769
- * @param string $field
1770
- * @param array $input
1771
- * @param null $param
1772
- *
1773
- * @return mixed
1774
- */
1775
- protected function validate_min_numeric($field, $input, $param = null) {
1776
- if (!isset($input[$field])) {
1777
- return;
1778
- }
1779
-
1780
- if (is_numeric($input[$field]) && is_numeric($param) && ($input[$field] >= $param)) {
1781
- return;
1782
- }
1783
-
1784
- return array(
1785
- 'field' => $field,
1786
- 'value' => $input[$field],
1787
- 'rule' => __FUNCTION__,
1788
- 'param' => $param,
1789
- );
1790
- }
1791
-
1792
- /**
1793
- * Determine if the provided value starts with param.
1794
- *
1795
- * Usage: '<index>' => 'starts,Z'
1796
- *
1797
- * @param string $field
1798
- * @param array $input
1799
- *
1800
- * @return mixed
1801
- */
1802
- protected function validate_starts($field, $input, $param = null) {
1803
- if (!isset($input[$field]) || empty($input[$field])) {
1804
- return;
1805
- }
1806
-
1807
- if (strpos($input[$field], $param) !== 0) {
1808
- return array(
1809
- 'field' => $field,
1810
- 'value' => $input[$field],
1811
- 'rule' => __FUNCTION__,
1812
- 'param' => $param,
1813
- );
1814
- }
1815
- }
1816
-
1817
- /**
1818
- * checks if a file was uploaded.
1819
- *
1820
- * Usage: '<index>' => 'required_file'
1821
- *
1822
- * @param string $field
1823
- * @param array $input
1824
- *
1825
- * @return mixed
1826
- */
1827
- protected function validate_required_file($field, $input, $param = null) {
1828
- if ($input[$field]['error'] !== 4) {
1829
- return;
1830
- }
1831
-
1832
- return array(
1833
- 'field' => $field,
1834
- 'value' => $input[$field],
1835
- 'rule' => __FUNCTION__,
1836
- 'param' => $param,
1837
- );
1838
- }
1839
-
1840
- /**
1841
- * check the uploaded file for extension
1842
- * for now checks onlt the ext should add mime type check.
1843
- *
1844
- * Usage: '<index>' => 'starts,Z'
1845
- *
1846
- * @param string $field
1847
- * @param array $input
1848
- *
1849
- * @return mixed
1850
- */
1851
- protected function validate_extension($field, $input, $param = null) {
1852
- if ($input[$field]['error'] !== 4) {
1853
- $param = trim(strtolower($param));
1854
- $allowed_extensions = explode(';', $param);
1855
-
1856
- $path_info = pathinfo($input[$field]['name']);
1857
- $extension = $path_info['extension'];
1858
-
1859
- if (in_array($extension, $allowed_extensions)) {
1860
- return;
1861
- }
1862
-
1863
- return array(
1864
- 'field' => $field,
1865
- 'value' => $input[$field],
1866
- 'rule' => __FUNCTION__,
1867
- 'param' => $param,
1868
- );
1869
- }
1870
- }
1871
-
1872
- /**
1873
- * Determine if the provided field value equals current field value.
1874
- *
1875
- * Usage: '<index>' => 'equalsfield,Z'
1876
- *
1877
- * @param string $field
1878
- * @param string $input
1879
- * @param string $param field to compare with
1880
- *
1881
- * @return mixed
1882
- */
1883
- protected function validate_equalsfield($field, $input, $param = null) {
1884
- if (!isset($input[$field]) || empty($input[$field])) {
1885
- return;
1886
- }
1887
-
1888
- if ($input[$field] == $input[$param]) {
1889
- return;
1890
- }
1891
-
1892
- return array(
1893
- 'field' => $field,
1894
- 'value' => $input[$field],
1895
- 'rule' => __FUNCTION__,
1896
- 'param' => $param,
1897
- );
1898
- }
1899
-
1900
- /**
1901
- * Determine if the provided field value is a valid GUID (v4)
1902
- *
1903
- * Usage: '<index>' => 'guidv4'
1904
- *
1905
- * @param string $field
1906
- * @param string $input
1907
- * @param string $param field to compare with
1908
- *
1909
- * @return mixed
1910
- */
1911
- protected function validate_guidv4($field, $input, $param = null) {
1912
- if (!isset($input[$field]) || empty($input[$field])) {
1913
- return;
1914
- }
1915
-
1916
- if (preg_match("/\{?[A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12}\}?$/", $input[$field])) {
1917
- return;
1918
- }
1919
-
1920
- return array(
1921
- 'field' => $field,
1922
- 'value' => $input[$field],
1923
- 'rule' => __FUNCTION__,
1924
- 'param' => $param,
1925
- );
1926
- }
1927
-
1928
- /**
1929
- * Trims whitespace only when the value is a scalar.
1930
- *
1931
- * @param mixed $value
1932
- *
1933
- * @return mixed
1934
- */
1935
- private function trimScalar($value) {
1936
- if (is_scalar($value)) {
1937
- $value = trim($value);
1938
- }
1939
-
1940
- return $value;
1941
- }
1942
-
1943
- /**
1944
- * Determine if the provided value is a valid phone number.
1945
- *
1946
- * Usage: '<index>' => 'phone_number'
1947
- *
1948
- * @param string $field
1949
- * @param array $input
1950
- *
1951
- * @return mixed
1952
- *
1953
- * Examples:
1954
- *
1955
- * 555-555-5555: valid
1956
- * 5555425555: valid
1957
- * 555 555 5555: valid
1958
- * 1(519) 555-4444: valid
1959
- * 1 (519) 555-4422: valid
1960
- * 1-555-555-5555: valid
1961
- * 1-(555)-555-5555: valid
1962
- */
1963
- protected function validate_phone_number($field, $input, $param = null) {
1964
- if (!isset($input[$field]) || empty($input[$field])) {
1965
- return;
1966
- }
1967
-
1968
- $regex = '/^(\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}$/i';
1969
- if (!preg_match($regex, $input[$field])) {
1970
- return array(
1971
- 'field' => $field,
1972
- 'value' => $input[$field],
1973
- 'rule' => __FUNCTION__,
1974
- 'param' => $param,
1975
- );
1976
- }
1977
- }
1978
-
1979
- /**
1980
- * Custom regex validator.
1981
- *
1982
- * Usage: '<index>' => 'regex&&&/regex/'
1983
- *
1984
- * @param string $field
1985
- * @param array $input
1986
- *
1987
- * @return mixed
1988
- */
1989
- protected function validate_regex($field, $input, $param = null) {
1990
- if (!isset($input[$field]) || empty($input[$field])) {
1991
- return;
1992
- }
1993
-
1994
- $regex = $param;
1995
- if (!preg_match($regex, $input[$field])) {
1996
- return array(
1997
- 'field' => $field,
1998
- 'value' => $input[$field],
1999
- 'rule' => __FUNCTION__,
2000
- 'param' => $param,
2001
- );
2002
- }
2003
- }
2004
-
2005
- /**
2006
- * Json validatior.
2007
- *
2008
- * Usage: '<index>' => 'valid_json_string'
2009
- *
2010
- * @param string $field
2011
- * @param array $input
2012
- *
2013
- * @return mixed
2014
- */
2015
- protected function validate_valid_json_string($field, $input, $param = null) {
2016
- if (!isset($input[$field]) || empty($input[$field])) {
2017
- return;
2018
- }
2019
-
2020
- if (!is_string($input[$field]) || !is_object(json_decode($input[$field]))) {
2021
- return array(
2022
- 'field' => $field,
2023
- 'value' => $input[$field],
2024
- 'rule' => __FUNCTION__,
2025
- 'param' => $param,
2026
- );
2027
- }
2028
- }
2029
- } // EOC
1
+ <?php
2
+ namespace mp_timetable\classes\libs;
3
+ /**
4
+ * GUMP - A fast, extensible PHP input validation class.
5
+ *
6
+ * @author Sean Nieuwoudt (http://twitter.com/SeanNieuwoudt)
7
+ * @copyright Copyright (c) 2015 wixelhq.com
8
+ *
9
+ * @link http://github.com/Wixel/GUMP
10
+ *
11
+ * @version 1.0
12
+ */
13
+ class GUMP {
14
+ // Validation rules for execution
15
+ protected $validation_rules = array();
16
+
17
+ // Filter rules for execution
18
+ protected $filter_rules = array();
19
+
20
+ // Instance attribute containing errors from last run
21
+ protected $errors = array();
22
+
23
+ // Contain readable field names that have been set manually
24
+ protected static $fields = array();
25
+
26
+ // Custom validation methods
27
+ protected static $validation_methods = array();
28
+
29
+ // Customer filter methods
30
+ protected static $filter_methods = array();
31
+
32
+ // ** ------------------------- Validation Data ------------------------------- ** //
33
+
34
+ public static $basic_tags = '<br><p><a><strong><b><i><em><img><blockquote><code><dd><dl><hr><h1><h2><h3><h4><h5><h6><label><ul><li><span><sub><sup>';
35
+
36
+ public static $en_noise_words = "about,after,all,also,an,and,another,any,are,as,at,be,because,been,before,
37
+ being,between,both,but,by,came,can,come,could,did,do,each,for,from,get,
38
+ got,has,had,he,have,her,here,him,himself,his,how,if,in,into,is,it,its,it's,like,
39
+ make,many,me,might,more,most,much,must,my,never,now,of,on,only,or,other,
40
+ our,out,over,said,same,see,should,since,some,still,such,take,than,that,
41
+ the,their,them,then,there,these,they,this,those,through,to,too,under,up,
42
+ very,was,way,we,well,were,what,where,which,while,who,with,would,you,your,a,
43
+ b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,$,1,2,3,4,5,6,7,8,9,0,_";
44
+
45
+ // field characters below will be replaced with a space.
46
+ protected $fieldCharsToRemove = array('_', '-');
47
+
48
+ // ** ------------------------- Validation Helpers ---------------------------- ** //
49
+
50
+ /**
51
+ * Shorthand method for inline validation.
52
+ *
53
+ * @param array $data The data to be validated
54
+ * @param array $validators The GUMP validators
55
+ *
56
+ * @return mixed True(boolean) or the array of error messages
57
+ */
58
+ public static function is_valid(array $data, array $validators) {
59
+ $gump = new self();
60
+
61
+ $gump->validation_rules($validators);
62
+
63
+ if ($gump->run($data) === false) {
64
+ return $gump->get_readable_errors(false);
65
+ } else {
66
+ return true;
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Shorthand method for running only the data filters.
72
+ *
73
+ * @param array $data
74
+ * @param array $filters
75
+ *
76
+ * @return mixed
77
+ */
78
+ public static function filter_input(array $data, array $filters) {
79
+ $gump = new self();
80
+
81
+ return $gump->filter($data, $filters);
82
+ }
83
+
84
+ /**
85
+ * Magic method to generate the validation error messages.
86
+ *
87
+ * @return string
88
+ */
89
+ public function __toString() {
90
+ return $this->get_readable_errors(true);
91
+ }
92
+
93
+ /**
94
+ * Perform XSS clean to prevent cross site scripting.
95
+ *
96
+ * @static
97
+ *
98
+ * @param array $data
99
+ *
100
+ * @return array
101
+ */
102
+ public static function xss_clean(array $data) {
103
+ foreach ($data as $k => $v) {
104
+ $data[$k] = filter_var($v, FILTER_SANITIZE_STRING);
105
+ }
106
+
107
+ return $data;
108
+ }
109
+
110
+ /**
111
+ * Adds a custom validation rule using a callback function.
112
+ *
113
+ * @param string $rule
114
+ * @param callable $callback
115
+ *
116
+ * @return bool
117
+ *
118
+ * @throws Exception
119
+ */
120
+ public static function add_validator($rule, $callback) {
121
+ $method = 'validate_' . $rule;
122
+
123
+ if (method_exists(__CLASS__, $method) || isset(self::$validation_methods[$rule])) {
124
+ throw new Exception("Validator rule '$rule' already exists.");
125
+ }
126
+
127
+ self::$validation_methods[$rule] = $callback;
128
+
129
+ return true;
130
+ }
131
+
132
+ /**
133
+ * Adds a custom filter using a callback function.
134
+ *
135
+ * @param string $rule
136
+ * @param callable $callback
137
+ *
138
+ * @return bool
139
+ *
140
+ * @throws Exception
141
+ */
142
+ public static function add_filter($rule, $callback) {
143
+ $method = 'filter_' . $rule;
144
+
145
+ if (method_exists(__CLASS__, $method) || isset(self::$filter_methods[$rule])) {
146
+ throw new Exception("Filter rule '$rule' already exists.");
147
+ }
148
+
149
+ self::$filter_methods[$rule] = $callback;
150
+
151
+ return true;
152
+ }
153
+
154
+ /**
155
+ * Helper method to extract an element from an array safely
156
+ *
157
+ * @param mixed $key
158
+ * @param array $array
159
+ * @param mixed $default
160
+ *
161
+ * @return mixed
162
+ */
163
+ public static function field($key, array $array, $default = null) {
164
+ if (!is_array($array)) {
165
+ return null;
166
+ }
167
+
168
+ if (isset($array[$key])) {
169
+ return $array[$key];
170
+ } else {
171
+ return $default;
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Getter/Setter for the validation rules.
177
+ *
178
+ * @param array $rules
179
+ *
180
+ * @return array
181
+ */
182
+ public function validation_rules(array $rules = array()) {
183
+ if (empty($rules)) {
184
+ return $this->validation_rules;
185
+ }
186
+
187
+ $this->validation_rules = $rules;
188
+ }
189
+
190
+ /**
191
+ * Getter/Setter for the filter rules.
192
+ *
193
+ * @param array $rules
194
+ *
195
+ * @return array
196
+ */
197
+ public function filter_rules(array $rules = array()) {
198
+ if (empty($rules)) {
199
+ return $this->filter_rules;
200
+ }
201
+
202
+ $this->filter_rules = $rules;
203
+ }
204
+
205
+ /**
206
+ * Run the filtering and validation after each other.
207
+ *
208
+ * @param array $data
209
+ * @param bool $check_fields
210
+ *
211
+ * @return array
212
+ *
213
+ * @throws Exception
214
+ */
215
+ public function run(array $data, $check_fields = false) {
216
+ $data = $this->filter($data, $this->filter_rules());
217
+
218
+ $validated = $this->validate(
219
+ $data, $this->validation_rules()
220
+ );
221
+
222
+ if ($check_fields === true) {
223
+ $this->check_fields($data);
224
+ }
225
+
226
+ if ($validated !== true) {
227
+ return false;
228
+ }
229
+
230
+ return $data;
231
+ }
232
+
233
+ /**
234
+ * Ensure that the field counts match the validation rule counts.
235
+ *
236
+ * @param array $data
237
+ */
238
+ private function check_fields(array $data) {
239
+ $ruleset = $this->validation_rules();
240
+ $mismatch = array_diff_key($data, $ruleset);
241
+ $fields = array_keys($mismatch);
242
+
243
+ foreach ($fields as $field) {
244
+ $this->errors[] = array(
245
+ 'field' => $field,
246
+ 'value' => $data[$field],
247
+ 'rule' => 'mismatch',
248
+ 'param' => null,
249
+ );
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Sanitize the input data.
255
+ *
256
+ * @param array $input
257
+ * @param null $fields
258
+ * @param bool $utf8_encode
259
+ *
260
+ * @return array
261
+ */
262
+ public function sanitize(array $input, array $fields = array(), $utf8_encode = true) {
263
+ $magic_quotes = (bool)get_magic_quotes_gpc();
264
+
265
+ if (empty($fields)) {
266
+ $fields = array_keys($input);
267
+ }
268
+
269
+ $return = array();
270
+
271
+ foreach ($fields as $field) {
272
+ if (!isset($input[$field])) {
273
+ continue;
274
+ } else {
275
+ $value = $input[$field];
276
+ if (is_array($value)) {
277
+ $value = null;
278
+ }
279
+ if (is_string($value)) {
280
+ if ($magic_quotes === true) {
281
+ $value = stripslashes($value);
282
+ }
283
+
284
+ if (strpos($value, "\r") !== false) {
285
+ $value = trim($value);
286
+ }
287
+
288
+ if (function_exists('iconv') && function_exists('mb_detect_encoding') && $utf8_encode) {
289
+ $current_encoding = mb_detect_encoding($value);
290
+
291
+ if ($current_encoding != 'UTF-8' && $current_encoding != 'UTF-16') {
292
+ $value = iconv($current_encoding, 'UTF-8', $value);
293
+ }
294
+ }
295
+
296
+ $value = filter_var($value, FILTER_SANITIZE_STRING);
297
+ }
298
+
299
+ $return[$field] = $value;
300
+ }
301
+ }
302
+
303
+ return $return;
304
+ }
305
+
306
+ /**
307
+ * Return the error array from the last validation run.
308
+ *
309
+ * @return array
310
+ */
311
+ public function errors() {
312
+ return $this->errors;
313
+ }
314
+
315
+ /**
316
+ * Perform data validation against the provided ruleset.
317
+ *
318
+ * @param mixed $input
319
+ * @param array $ruleset
320
+ *
321
+ * @return mixed
322
+ *
323
+ * @throws Exception
324
+ */
325
+ public function validate(array $input, array $ruleset) {
326
+ $this->errors = array();
327
+
328
+ foreach ($ruleset as $field => $rules) {
329
+
330
+ $rules = explode('|', $rules);
331
+
332
+ if (in_array('required', $rules) || (isset($input[$field]) && !is_array($input[$field]))) {
333
+ foreach ($rules as $rule) {
334
+ $method = null;
335
+ $param = null;
336
+
337
+ // Check if we have rule parameters
338
+ if (strstr($rule, ',') !== false) {
339
+ $rule = explode(',', $rule);
340
+ $method = 'validate_' . $rule[0];
341
+ $param = $rule[1];
342
+ $rule = $rule[0];
343
+ } else {
344
+ $method = 'validate_' . $rule;
345
+ }
346
+
347
+ //self::$validation_methods[$rule] = $callback;
348
+
349
+ if (is_callable(array($this, $method))) {
350
+ $result = $this->$method(
351
+ $field, $input, $param
352
+ );
353
+
354
+ if (is_array($result)) {
355
+ $this->errors[] = $result;
356
+ }
357
+ } elseif (isset(self::$validation_methods[$rule])) {
358
+
359
+ $result = call_user_func(self::$validation_methods[$rule], $field, $input, $param);
360
+
361
+ if ($result === false) {
362
+ $this->errors[] = array(
363
+ 'field' => $field,
364
+ 'value' => $input,
365
+ 'rule' => self::$validation_methods[$rule],
366
+ 'param' => $param,
367
+ );
368
+ }
369
+
370
+ } else {
371
+ throw new Exception("Validator method '$method' does not exist.");
372
+ }
373
+ }
374
+ }
375
+ }
376
+
377
+ return (count($this->errors) > 0) ? $this->errors : true;
378
+ }
379
+
380
+ /**
381
+ * Overloadable method to invoke validation.
382
+ *
383
+ * @param array $input
384
+ * @param $rules
385
+ * @param $field
386
+ *
387
+ * @return bool
388
+ */
389
+ protected function shouldRunValidation(array $input, $rules, $field) {
390
+ return in_array('required', $rules) || (isset($input[$field]) && trim($input[$field]) != '');
391
+ }
392
+
393
+ /**
394
+ * Set a readable name for a specified field names.
395
+ *
396
+ * @param string $field
397
+ * @param string $readable_name
398
+ */
399
+ public static function set_field_name($field, $readable_name) {
400
+ self::$fields[$field] = $readable_name;
401
+ }
402
+
403
+ /**
404
+ * Set readable name for specified fields in an array.
405
+ *
406
+ * Usage:
407
+ *
408
+ * GUMP::set_field_names(array(
409
+ * "name" => "My Lovely Name",
410
+ * "username" => "My Beloved Username",
411
+ * ));
412
+ *
413
+ * @param array $array
414
+ */
415
+ public static function set_field_names(array $array) {
416
+ foreach ($array as $field => $readable_name) {
417
+ self::$fields[$field] = $readable_name;
418
+ }
419
+ }
420
+
421
+ /**
422
+ * Process the validation errors and return human readable error messages.
423
+ *
424
+ * @param bool $convert_to_string = false
425
+ * @param string $field_class
426
+ * @param string $error_class
427
+ *
428
+ * @return array
429
+ * @return string
430
+ */
431
+ public function get_readable_errors($convert_to_string = false, $field_class = 'gump-field', $error_class = 'gump-error-message') {
432
+ if (empty($this->errors)) {
433
+ return ($convert_to_string) ? null : array();
434
+ }
435
+
436
+ $resp = array();
437
+
438
+ foreach ($this->errors as $e) {
439
+ $field = ucwords(str_replace($this->fieldCharsToRemove, chr(32), $e['field']));
440
+ $param = $e['param'];
441
+
442
+ // Let's fetch explicit field names if they exist
443
+ if (array_key_exists($e['field'], self::$fields)) {
444
+ $field = self::$fields[$e['field']];
445
+ }
446
+
447
+
448
+ switch ($e['rule']) {
449
+ case 'mismatch' :
450
+ $resp[] = sprintf( 'There is no validation rule for <span class="%1$s">%2$s</span>', $field_class, $field );
451
+ break;
452
+ case 'validate_required' :
453
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field is required', $field_class, $field );
454
+ break;
455
+ case 'validate_valid_email':
456
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field is required to be a valid email address', $field_class, $field );
457
+ break;
458
+ case 'validate_max_len':
459
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be %d or shorter in length', $field_class, $field, $param );
460
+ break;
461
+ case 'validate_min_len':
462
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be %d or longer in length', $field_class, $field, $param );
463
+ break;
464
+ case 'validate_exact_len':
465
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be exactly %d characters in length', $field_class, $field, $param );
466
+ break;
467
+ case 'validate_alpha':
468
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain alpha characters(a-z)', $field_class, $field );
469
+ break;
470
+ case 'validate_alpha_numeric':
471
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain alpha-numeric characters', $field_class, $field );
472
+ break;
473
+ case 'validate_alpha_dash':
474
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain alpha characters &amp; dashes', $field_class, $field );
475
+ break;
476
+ case 'validate_numeric':
477
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain numeric characters', $field_class, $field );
478
+ break;
479
+ case 'validate_integer':
480
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain a numeric value', $field_class, $field );
481
+ break;
482
+ case 'validate_boolean':
483
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain a true or false value', $field_class, $field );
484
+ break;
485
+ case 'validate_float':
486
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field may only contain a float value', $field_class, $field );
487
+ break;
488
+ case 'validate_valid_url':
489
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field is required to be a valid URL', $field_class, $field );
490
+ break;
491
+ case 'validate_url_exists':
492
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> URL does not exist', $field_class, $field );
493
+ break;
494
+ case 'validate_valid_ip':
495
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to contain a valid IP address', $field_class, $field );
496
+ break;
497
+ case 'validate_valid_cc':
498
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to contain a valid credit card number', $field_class, $field );
499
+ break;
500
+ case 'validate_valid_name':
501
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to contain a valid human name', $field_class, $field );
502
+ break;
503
+ case 'validate_contains':
504
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to contain one of these values:', $field_class, $field ) . ' ' . implode(', ', $param);
505
+ break;
506
+ case 'validate_contains_list':
507
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs contain a value from its drop down list', $field_class, $field );
508
+ break;
509
+ case 'validate_doesnt_contain_list':
510
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field contains a value that is not accepted', $field_class, $field );
511
+ break;
512
+ case 'validate_street_address':
513
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be a valid street address', $field_class, $field );
514
+ break;
515
+ case 'validate_date':
516
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be a valid date', $field_class, $field );
517
+ break;
518
+ case 'validate_min_numeric':
519
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be a numeric value, equal to, or higher than', $field_class, $field ) . $param;
520
+ break;
521
+ case 'validate_max_numeric':
522
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to be a numeric value, equal to, or lower than', $field_class, $field ) . ' ' . $param;
523
+ break;
524
+ case 'validate_starts':
525
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to start with', $field_class, $field ) . ' ' . $param;
526
+ break;
527
+ case 'validate_extension':
528
+ $resp[] = sprintf( 'The <span class"%1$s">%2$s</span> field can have the following extensions', $field_class, $field ) . ' '. $param;
529
+ break;
530
+ case 'validate_required_file':
531
+ $resp[] = sprintf( 'The <span class"%1$s">%2$s</span> field is required', $field_class, $field ) .' ' . $param;
532
+ break;
533
+ case 'validate_equalsfield':
534
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field does not equal %d field', $field_class, $field, $param ) ;
535
+ break;
536
+ case 'validate_min_age':
537
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field needs to have an age greater than or equal to', $field_class, $field ) . ' '. $param;;
538
+ break;
539
+ default:
540
+ $resp[] = sprintf( 'The <span class="%1$s">%2$s</span> field is invalid', $field_class, $field );
541
+ }
542
+ }
543
+
544
+ if (!$convert_to_string) {
545
+ return $resp;
546
+ } else {
547
+ $buffer = '';
548
+ foreach ($resp as $s) {
549
+ $buffer .= "<span class=\"$error_class\">$s</span>";
550
+ }
551
+
552
+ return $buffer;
553
+ }
554
+ }
555
+
556
+ /**
557
+ * Process the validation errors and return an array of errors with field names as keys.
558
+ *
559
+ * @param $convert_to_string
560
+ *
561
+ * @return array | null (if empty)
562
+ */
563
+ public function get_errors_array($convert_to_string = null) {
564
+ if (empty($this->errors)) {
565
+ return ($convert_to_string) ? null : array();
566
+ }
567
+
568
+ $resp = array();
569
+
570
+ foreach ($this->errors as $e) {
571
+ $field = ucwords(str_replace(array('_', '-'), chr(32), $e['field']));
572
+ $param = $e['param'];
573
+
574
+ // Let's fetch explicit field names if they exist
575
+ if (array_key_exists($e['field'], self::$fields)) {
576
+ $field = self::$fields[$e['field']];
577
+ }
578
+
579
+ switch ($e['rule']) {
580
+ case 'mismatch' :
581
+ $resp[$field] = 'There is no validation rule for' . ' ' . $field;
582
+ break;
583
+ case 'validate_required':
584
+ $resp[$field] = sprintf( 'The %s field is required', $field);
585
+ break;
586
+ case 'validate_valid_email':
587
+ $resp[$field] = sprintf( 'The %s field is required to be a valid email address', $field);
588
+ break;
589
+ case 'validate_max_len':
590
+ $resp[$field] = sprintf( 'The %s field needs to be %d or shorter in length', $field, $param);
591
+ break;
592
+ case 'validate_min_len':
593
+ $resp[$field] = sprintf( 'The %s field needs to be %d or longer in length', $field, $param);
594
+ break;
595
+ case 'validate_exact_len':
596
+ $resp[$field] = sprintf( 'The %s field needs to be exactly %d characters in length', $field, $param);
597
+ break;
598
+ case 'validate_alpha':
599
+ $resp[$field] = sprintf( 'The %s field may only contain alpha characters(a-z)', $field);
600
+ break;
601
+ case 'validate_alpha_numeric':
602
+ $resp[$field] = sprintf( 'The %s field may only contain alpha-numeric characters', $field);
603
+ break;
604
+ case 'validate_alpha_dash':
605
+ $resp[$field] = sprintf( 'The %s field may only contain alpha characters &amp; dashes', $field);
606
+ break;
607
+ case 'validate_numeric':
608
+ $resp[$field] = sprintf( 'The %s field may only contain numeric characters', $field);
609
+ break;
610
+ case 'validate_integer':
611
+ $resp[$field] = sprintf( 'The %s field may only contain a numeric value', $field);
612
+ break;
613
+ case 'validate_boolean':
614
+ $resp[$field] = sprintf( 'The %s field may only contain a true or false value', $field);
615
+ break;
616
+ case 'validate_float':
617
+ $resp[$field] = sprintf( 'The %s field may only contain a float value', $field);
618
+ break;
619
+ case 'validate_valid_url':
620
+ $resp[$field] = sprintf( 'The %s field is required to be a valid URL', $field);
621
+ break;
622
+ case 'validate_url_exists':
623
+ $resp[$field] = sprintf( 'The %s URL does not exist', $field);
624
+ break;
625
+ case 'validate_valid_ip':
626
+ $resp[$field] = sprintf( 'The %s field needs to contain a valid IP address', $field);
627
+ break;
628
+ case 'validate_valid_cc':
629
+ $resp[$field] = sprintf( 'The %s field needs to contain a valid credit card number', $field);
630
+ break;
631
+ case 'validate_valid_name':
632
+ $resp[$field] = sprintf( 'The %s field needs to contain a valid human name', $field);
633
+ break;
634
+ case 'validate_contains':
635
+ $resp[$field] = sprintf( 'The %s field needs to contain one of these values:', $field) . ' ' . implode(', ', $param);
636
+ break;
637
+ case 'validate_street_address':
638
+ $resp[$field] = sprintf( 'The %s field needs to be a valid street address', $field);
639
+ break;
640
+ case 'validate_date':
641
+ $resp[$field] = sprintf( 'The %s field needs to be a valid date', $field);
642
+ break;
643
+ case 'validate_min_numeric':
644
+ $resp[$field] = sprintf( 'The %s field needs to be a numeric value, equal to, or higher than %d', $field, $param);
645
+ break;
646
+ case 'validate_max_numeric':
647
+ $resp[$field] = sprintf( 'The %s field needs to be a numeric value, equal to, or lower than %d', $field, $param);
648
+ break;
649
+ case 'validate_min_age':
650
+ $resp[$field] = sprintf( 'The %s field needs to have an age greater than or equal to %d', $field, $param);
651
+ break;
652
+ default:
653
+ $resp[$field] = sprintf( 'The %s field is invalid', $field );
654
+ }
655
+ }
656
+
657
+ return $resp;
658
+ }
659
+
660
+
661
+ /**
662
+ * Filter the input data according to the specified filter set.
663
+ *
664
+ * @param mixed $input
665
+ * @param array $filterset
666
+ *
667
+ * @throws Exception
668
+ *
669
+ * @return mixed
670
+ *
671
+ * @throws Exception
672
+ */
673
+ public function filter(array $input, array $filterset) {
674
+ foreach ($filterset as $field => $filters) {
675
+ if (!array_key_exists($field, $input)) {
676
+ continue;
677
+ }
678
+
679
+ $filters = explode('|', $filters);
680
+
681
+ foreach ($filters as $filter) {
682
+ $params = null;
683
+
684
+ if (strstr($filter, ',') !== false) {
685
+ $filter = explode(',', $filter);
686
+
687
+ $params = array_slice($filter, 1, count($filter) - 1);
688
+
689
+ $filter = $filter[0];
690
+ }
691
+
692
+ if (is_callable(array($this, 'filter_' . $filter))) {
693
+ $method = 'filter_' . $filter;
694
+ $input[$field] = $this->$method($input[$field], $params);
695
+ } elseif (function_exists($filter)) {
696
+ $input[$field] = $filter($input[$field]);
697
+ } elseif (isset(self::$filter_methods[$filter])) {
698
+ $input[$field] = call_user_func(self::$filter_methods[$filter], $input[$field], $params);
699
+ } else {
700
+ throw new Exception("Filter method '$filter' does not exist.");
701
+ }
702
+ }
703
+ }
704
+
705
+ return $input;
706
+ }
707
+
708
+ // ** ------------------------- Filters --------------------------------------- ** //
709
+
710
+ /**
711
+ * Replace noise words in a string (http://tax.cchgroup.com/help/Avoiding_noise_words_in_your_search.htm).
712
+ *
713
+ * Usage: '<index>' => 'noise_words'
714
+ *
715
+ * @param string $value
716
+ * @param array $params
717
+ *
718
+ * @return string
719
+ */
720
+ protected function filter_noise_words($value, $params = null) {
721
+ $value = preg_replace('/\s\s+/u', chr(32), $value);
722
+
723
+ $value = " $value ";
724
+
725
+ $words = explode(',', self::$en_noise_words);
726
+
727
+ foreach ($words as $word) {
728
+ $word = trim($word);
729
+
730
+ $word = " $word "; // Normalize
731
+
732
+ if (stripos($value, $word) !== false) {
733
+ $value = str_ireplace($word, chr(32), $value);
734
+ }
735
+ }
736
+
737
+ return trim($value);
738
+ }
739
+
740
+ /**
741
+ * Remove all known punctuation from a string.
742
+ *
743
+ * Usage: '<index>' => 'rmpunctuataion'
744
+ *
745
+ * @param string $value
746
+ * @param array $params
747
+ *
748
+ * @return string
749
+ */
750
+ protected function filter_rmpunctuation($value, $params = null) {
751
+ return preg_replace("/(?![.=$'€%-])\p{P}/u", '', $value);
752
+ }
753
+
754
+ /**
755
+ * Translate an input string to a desired language [DEPRECIATED].
756
+ *
757
+ * Any ISO 639-1 2 character language code may be used
758
+ *
759
+ * See: http://www.science.co.il/language/Codes.asp?s=code2
760
+ *
761
+ * @param string $value
762
+ * @param array $params
763
+ *
764
+ * @return string
765
+ */
766
+ /*
767
+ protected function filter_translate($value, $params = NULL)
768
+ {
769
+ $input_lang = 'en';
770
+ $output_lang = 'en';
771
+
772
+ if(is_null($params))
773
+ {
774
+ return $value;
775
+ }
776
+
777
+ switch(count($params))
778
+ {
779
+ case 1:
780
+ $input_lang = $params[0];
781
+ break;
782
+ case 2:
783
+ $input_lang = $params[0];
784
+ $output_lang = $params[1];
785
+ break;
786
+ }
787
+
788
+ $text = urlencode($value);
789
+
790
+ $translation = file_get_contents(
791
+ "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q={$text}&langpair={$input_lang}|{$output_lang}"
792
+ );
793
+
794
+ $json = json_decode($translation, true);
795
+
796
+ if($json['responseStatus'] != 200)
797
+ {
798
+ return $value;
799
+ }
800
+ else
801
+ {
802
+ return $json['responseData']['translatedText'];
803
+ }
804
+ }
805
+ */
806
+
807
+ /**
808
+ * Sanitize the string by removing any script tags.
809
+ *
810
+ * Usage: '<index>' => 'sanitize_string'
811
+ *
812
+ * @param string $value
813
+ * @param array $params
814
+ *
815
+ * @return string
816
+ */
817
+ protected function filter_sanitize_string($value, $params = null) {
818
+ return filter_var($value, FILTER_SANITIZE_STRING);
819
+ }
820
+
821
+ /**
822
+ * Sanitize the string by urlencoding characters.
823
+ *
824
+ * Usage: '<index>' => 'urlencode'
825
+ *
826
+ * @param string $value
827
+ * @param array $params
828
+ *
829
+ * @return string
830
+ */
831
+ protected function filter_urlencode($value, $params = null) {
832
+ return filter_var($value, FILTER_SANITIZE_ENCODED);
833
+ }
834
+
835
+ /**
836
+ * Sanitize the string by converting HTML characters to their HTML entities.
837
+ *
838
+ * Usage: '<index>' => 'htmlencode'
839
+ *
840
+ * @param string $value
841
+ * @param array $params
842
+ *
843
+ * @return string
844
+ */
845
+ protected function filter_htmlencode($value, $params = null) {
846
+ return filter_var($value, FILTER_SANITIZE_SPECIAL_CHARS);
847
+ }
848
+
849
+ /**
850
+ * Sanitize the string by removing illegal characters from emails.
851
+ *
852
+ * Usage: '<index>' => 'sanitize_email'
853
+ *
854
+ * @param string $value
855
+ * @param array $params
856
+ *
857
+ * @return string
858
+ */
859
+ protected function filter_sanitize_email($value, $params = null) {
860
+ return filter_var($value, FILTER_SANITIZE_EMAIL);
861
+ }
862
+
863
+ /**
864
+ * Sanitize the string by removing illegal characters from numbers.
865
+ *
866
+ * @param string $value
867
+ * @param array $params
868
+ *
869
+ * @return string
870
+ */
871
+ protected function filter_sanitize_numbers($value, $params = null) {
872
+ return filter_var($value, FILTER_SANITIZE_NUMBER_INT);
873
+ }
874
+
875
+ /**
876
+ * Filter out all HTML tags except the defined basic tags.
877
+ *
878
+ * @param string $value
879
+ * @param array $params
880
+ *
881
+ * @return string
882
+ */
883
+ protected function filter_basic_tags($value, $params = null) {
884
+ return strip_tags($value, self::$basic_tags);
885
+ }
886
+
887
+ /**
888
+ * Convert the provided numeric value to a whole number.
889
+ *
890
+ * @param string $value
891
+ * @param array $params
892
+ *
893
+ * @return string
894
+ */
895
+ protected function filter_whole_number($value, $params = null) {
896
+ return intval($value);
897
+ }
898
+
899
+ // ** ------------------------- Validators ------------------------------------ ** //
900
+
901
+
902
+ /**
903
+ * Verify that a value is contained within the pre-defined value set.
904
+ *
905
+ * Usage: '<index>' => 'contains,value value value'
906
+ *
907
+ * @param string $field
908
+ * @param array $input
909
+ * @param null $param
910
+ *
911
+ * @return mixed
912
+ */
913
+ protected function validate_contains($field, $input, $param = null) {
914
+ if (!isset($input[$field])) {
915
+ return;
916
+ }
917
+
918
+ $param = trim(strtolower($param));
919
+
920
+ $value = trim(strtolower($input[$field]));
921
+
922
+ if (preg_match_all('#\'(.+?)\'#', $param, $matches, PREG_PATTERN_ORDER)) {
923
+ $param = $matches[1];
924
+ } else {
925
+ $param = explode(chr(32), $param);
926
+ }
927
+
928
+ if (in_array($value, $param)) { // valid, return nothing
929
+ return;
930
+ }
931
+
932
+ return array(
933
+ 'field' => $field,
934
+ 'value' => $value,
935
+ 'rule' => __FUNCTION__,
936
+ 'param' => $param,
937
+ );
938
+ }
939
+
940
+ /**
941
+ * Verify that a value is contained within the pre-defined value set.
942
+ * OUTPUT: will NOT show the list of values.
943
+ *
944
+ * Usage: '<index>' => 'contains_list,value;value;value'
945
+ *
946
+ * @param string $field
947
+ * @param array $input
948
+ *
949
+ * @return mixed
950
+ */
951
+ protected function validate_contains_list($field, $input, $param = null) {
952
+ $param = trim(strtolower($param));
953
+
954
+ $value = trim(strtolower($input[$field]));
955
+
956
+ $param = explode(';', $param);
957
+
958
+ // consider: in_array(strtolower($value), array_map('strtolower', $param)
959
+
960
+ if (in_array($value, $param)) { // valid, return nothing
961
+ return;
962
+ } else {
963
+ return array(
964
+ 'field' => $field,
965
+ 'value' => $value,
966
+ 'rule' => __FUNCTION__,
967
+ 'param' => $param,
968
+ );
969
+ }
970
+ }
971
+
972
+ /**
973
+ * Verify that a value is NOT contained within the pre-defined value set.
974
+ * OUTPUT: will NOT show the list of values.
975
+ *
976
+ * Usage: '<index>' => 'doesnt_contain_list,value;value;value'
977
+ *
978
+ * @param string $field
979
+ * @param array $input
980
+ *
981
+ * @return mixed
982
+ */
983
+ protected function validate_doesnt_contain_list($field, $input, $param = null) {
984
+ $param = trim(strtolower($param));
985
+
986
+ $value = trim(strtolower($input[$field]));
987
+
988
+ $param = explode(';', $param);
989
+
990
+ if (!in_array($value, $param)) { // valid, return nothing
991
+ return;
992
+ } else {
993
+ return array(
994
+ 'field' => $field,
995
+ 'value' => $value,
996
+ 'rule' => __FUNCTION__,
997
+ 'param' => $param,
998
+ );
999
+ }
1000
+ }
1001
+
1002
+ /**
1003
+ * Check if the specified key is present and not empty.
1004
+ *
1005
+ * Usage: '<index>' => 'required'
1006
+ *
1007
+ * @param string $field
1008
+ * @param array $input
1009
+ * @param null $param
1010
+ *
1011
+ * @return mixed
1012
+ */
1013
+ protected function validate_required($field, $input, $param = null) {
1014
+ if (isset($input[$field]) && ($input[$field] === false || $input[$field] === 0 || $input[$field] === 0.0 || $input[$field] === '0' || !empty($input[$field]))) {
1015
+ return;
1016
+ }
1017
+
1018
+ return array(
1019
+ 'field' => $field,
1020
+ 'value' => null,
1021
+ 'rule' => __FUNCTION__,
1022
+ 'param' => $param,
1023
+ );
1024
+ }
1025
+
1026
+ /**
1027
+ * Determine if the provided email is valid.
1028
+ *
1029
+ * Usage: '<index>' => 'valid_email'
1030
+ *
1031
+ * @param string $field
1032
+ * @param array $input
1033
+ * @param null $param
1034
+ *
1035
+ * @return mixed
1036
+ */
1037
+ protected function validate_valid_email($field, $input, $param = null) {
1038
+ if (!isset($input[$field]) || empty($input[$field])) {
1039
+ return;
1040
+ }
1041
+
1042
+ if (!filter_var($input[$field], FILTER_VALIDATE_EMAIL)) {
1043
+ return array(
1044
+ 'field' => $field,
1045
+ 'value' => $input[$field],
1046
+ 'rule' => __FUNCTION__,
1047
+ 'param' => $param,
1048
+ );
1049
+ }
1050
+ }
1051
+
1052
+ /**
1053
+ * Determine if the provided value length is less or equal to a specific value.
1054
+ *
1055
+ * Usage: '<index>' => 'max_len,240'
1056
+ *
1057
+ * @param string $field
1058
+ * @param array $input
1059
+ * @param null $param
1060
+ *
1061
+ * @return mixed
1062
+ */
1063
+ protected function validate_max_len($field, $input, $param = null) {
1064
+ if (!isset($input[$field])) {
1065
+ return;
1066
+ }
1067
+
1068
+ if (function_exists('mb_strlen')) {
1069
+ if (mb_strlen($input[$field]) <= (int)$param) {
1070
+ return;
1071
+ }
1072
+ } else {
1073
+ if (strlen($input[$field]) <= (int)$param) {
1074
+ return;
1075
+ }
1076
+ }
1077
+
1078
+ return array(
1079
+ 'field' => $field,
1080
+ 'value' => $input[$field],
1081
+ 'rule' => __FUNCTION__,
1082
+ 'param' => $param,
1083
+ );
1084
+ }
1085
+
1086
+ /**
1087
+ * Determine if the provided value length is more or equal to a specific value.
1088
+ *
1089
+ * Usage: '<index>' => 'min_len,4'
1090
+ *
1091
+ * @param string $field
1092
+ * @param array $input
1093
+ * @param null $param
1094
+ *
1095
+ * @return mixed
1096
+ */
1097
+ protected function validate_min_len($field, $input, $param = null) {
1098
+ if (!isset($input[$field])) {
1099
+ return;
1100
+ }
1101
+
1102
+ if (function_exists('mb_strlen')) {
1103
+ if (mb_strlen($input[$field]) >= (int)$param) {
1104
+ return;
1105
+ }
1106
+ } else {
1107
+ if (strlen($input[$field]) >= (int)$param) {
1108
+ return;
1109
+ }
1110
+ }
1111
+
1112
+ return array(
1113
+ 'field' => $field,
1114
+ 'value' => $input[$field],
1115
+ 'rule' => __FUNCTION__,
1116
+ 'param' => $param,
1117
+ );
1118
+ }
1119
+
1120
+ /**
1121
+ * Determine if the provided value length matches a specific value.
1122
+ *
1123
+ * Usage: '<index>' => 'exact_len,5'
1124
+ *
1125
+ * @param string $field
1126
+ * @param array $input
1127
+ * @param null $param
1128
+ *
1129
+ * @return mixed
1130
+ */
1131
+ protected function validate_exact_len($field, $input, $param = null) {
1132
+ if (!isset($input[$field])) {
1133
+ return;
1134
+ }
1135
+
1136
+ if (function_exists('mb_strlen')) {
1137
+ if (mb_strlen($input[$field]) == (int)$param) {
1138
+ return;
1139
+ }
1140
+ } else {
1141
+ if (strlen($input[$field]) == (int)$param) {
1142
+ return;
1143
+ }
1144
+ }
1145
+
1146
+ return array(
1147
+ 'field' => $field,
1148
+ 'value' => $input[$field],
1149
+ 'rule' => __FUNCTION__,
1150
+ 'param' => $param,
1151
+ );
1152
+ }
1153
+
1154
+ /**
1155
+ * Determine if the provided value contains only alpha characters.
1156
+ *
1157
+ * Usage: '<index>' => 'alpha'
1158
+ *
1159
+ * @param string $field
1160
+ * @param array $input
1161
+ * @param null $param
1162
+ *
1163
+ * @return mixed
1164
+ */
1165
+ protected function validate_alpha($field, $input, $param = null) {
1166
+ if (!isset($input[$field]) || empty($input[$field])) {
1167
+ return;
1168
+ }
1169
+
1170
+ if (!preg_match('/^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ])+$/i', $input[$field]) !== false) {
1171
+ return array(
1172
+ 'field' => $field,
1173
+ 'value' => $input[$field],
1174
+ 'rule' => __FUNCTION__,
1175
+ 'param' => $param,
1176
+ );
1177
+ }
1178
+ }
1179
+
1180
+ /**
1181
+ * Determine if the provided value contains only alpha-numeric characters.
1182
+ *
1183
+ * Usage: '<index>' => 'alpha_numeric'
1184
+ *
1185
+ * @param string $field
1186
+ * @param array $input
1187
+ * @param null $param
1188
+ *
1189
+ * @return mixed
1190
+ */
1191
+ protected function validate_alpha_numeric($field, $input, $param = null) {
1192
+ if (!isset($input[$field]) || empty($input[$field])) {
1193
+ return;
1194
+ }
1195
+
1196
+ if (!preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ])+$/i', $input[$field]) !== false) {
1197
+ return array(
1198
+ 'field' => $field,
1199
+ 'value' => $input[$field],
1200
+ 'rule' => __FUNCTION__,
1201
+ 'param' => $param,
1202
+ );
1203
+ }
1204
+ }
1205
+
1206
+ /**
1207
+ * Determine if the provided value contains only alpha characters with dashed and underscores.
1208
+ *
1209
+ * Usage: '<index>' => 'alpha_dash'
1210
+ *
1211
+ * @param string $field
1212
+ * @param array $input
1213
+ * @param null $param
1214
+ *
1215
+ * @return mixed
1216
+ */
1217
+ protected function validate_alpha_dash($field, $input, $param = null) {
1218
+ if (!isset($input[$field]) || empty($input[$field])) {
1219
+ return;
1220
+ }
1221
+
1222
+ if (!preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ_-])+$/i', $input[$field]) !== false) {
1223
+ return array(
1224
+ 'field' => $field,
1225
+ 'value' => $input[$field],
1226
+ 'rule' => __FUNCTION__,
1227
+ 'param' => $param,
1228
+ );
1229
+ }
1230
+ }
1231
+
1232
+ /**
1233
+ * Determine if the provided value contains only alpha numeric characters with spaces.
1234
+ *
1235
+ * Usage: '<index>' => 'alpha_space'
1236
+ *
1237
+ * @param string $field
1238
+ * @param array $input
1239
+ * @param null $param
1240
+ *
1241
+ * @return mixed
1242
+ */
1243
+ protected function validate_alpha_space($field, $input, $param = null) {
1244
+ if (!isset($input[$field]) || empty($input[$field])) {
1245
+ return;
1246
+ }
1247
+
1248
+ if (!preg_match("/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ\s])+$/i", $input[$field]) !== false) {
1249
+ return array(
1250
+ 'field' => $field,
1251
+ 'value' => $input[$field],
1252
+ 'rule' => __FUNCTION__,
1253
+ 'param' => $param,
1254
+ );
1255
+ }
1256
+ }
1257
+
1258
+ /**
1259
+ * Determine if the provided value is a valid number or numeric string.
1260
+ *
1261
+ * Usage: '<index>' => 'numeric'
1262
+ *
1263
+ * @param string $field
1264
+ * @param array $input
1265
+ * @param null $param
1266
+ *
1267
+ * @return mixed
1268
+ */
1269
+ protected function validate_numeric($field, $input, $param = null) {
1270
+ if (!isset($input[$field]) || empty($input[$field])) {
1271
+ return;
1272
+ }
1273
+
1274
+ if (!is_numeric($input[$field])) {
1275
+ return array(
1276
+ 'field' => $field,
1277
+ 'value' => $input[$field],
1278
+ 'rule' => __FUNCTION__,
1279
+ 'param' => $param,
1280
+ );
1281
+ }
1282
+ }
1283
+
1284
+ /**
1285
+ * Determine if the provided value is a valid integer.
1286
+ *
1287
+ * Usage: '<index>' => 'integer'
1288
+ *
1289
+ * @param string $field
1290
+ * @param array $input
1291
+ * @param null $param
1292
+ *
1293
+ * @return mixed
1294
+ */
1295
+ protected function validate_integer($field, $input, $param = null) {
1296
+ if (!isset($input[$field]) || empty($input[$field])) {
1297
+ return;
1298
+ }
1299
+
1300
+ if (filter_var($input[$field], FILTER_VALIDATE_INT) === false) {
1301
+ return array(
1302
+ 'field' => $field,
1303
+ 'value' => $input[$field],
1304
+ 'rule' => __FUNCTION__,
1305
+ 'param' => $param,
1306
+ );
1307
+ }
1308
+ }
1309
+
1310
+ /**
1311
+ * Determine if the provided value is a PHP accepted boolean.
1312
+ *
1313
+ * Usage: '<index>' => 'boolean'
1314
+ *
1315
+ * @param string $field
1316
+ * @param array $input
1317
+ * @param null $param
1318
+ *
1319
+ * @return mixed
1320
+ */
1321
+ protected function validate_boolean($field, $input, $param = null) {
1322
+ if (!isset($input[$field]) || empty($input[$field]) && $input[$field] !== 0) {
1323
+ return;
1324
+ }
1325
+
1326
+ if ($input[$field] === true || $input[$field] === false) {
1327
+ return;
1328
+ }
1329
+
1330
+ return array(
1331
+ 'field' => $field,
1332
+ 'value' => $input[$field],
1333
+ 'rule' => __FUNCTION__,
1334
+ 'param' => $param,
1335
+ );
1336
+ }
1337
+
1338
+ /**
1339
+ * Determine if the provided value is a valid float.
1340
+ *
1341
+ * Usage: '<index>' => 'float'
1342
+ *
1343
+ * @param string $field
1344
+ * @param array $input
1345
+ * @param null $param
1346
+ *
1347
+ * @return mixed
1348
+ */
1349
+ protected function validate_float($field, $input, $param = null) {
1350
+ if (!isset($input[$field]) || empty($input[$field])) {
1351
+ return;
1352
+ }
1353
+
1354
+ if (filter_var($input[$field], FILTER_VALIDATE_FLOAT) === false) {
1355
+ return array(
1356
+ 'field' => $field,
1357
+ 'value' => $input[$field],
1358
+ 'rule' => __FUNCTION__,
1359
+ 'param' => $param,
1360
+ );
1361
+ }
1362
+ }
1363
+
1364
+ /**
1365
+ * Determine if the provided value is a valid URL.
1366
+ *
1367
+ * Usage: '<index>' => 'valid_url'
1368
+ *
1369
+ * @param string $field
1370
+ * @param array $input
1371
+ * @param null $param
1372
+ *
1373
+ * @return mixed
1374
+ */
1375
+ protected function validate_valid_url($field, $input, $param = null) {
1376
+ if (!isset($input[$field]) || empty($input[$field])) {
1377
+ return;
1378
+ }
1379
+
1380
+ if (!filter_var($input[$field], FILTER_VALIDATE_URL)) {
1381
+ return array(
1382
+ 'field' => $field,
1383
+ 'value' => $input[$field],
1384
+ 'rule' => __FUNCTION__,
1385
+ 'param' => $param,
1386
+ );
1387
+ }
1388
+ }
1389
+
1390
+ /**
1391
+ * Determine if a URL exists & is accessible.
1392
+ *
1393
+ * Usage: '<index>' => 'url_exists'
1394
+ *
1395
+ * @param string $field
1396
+ * @param array $input
1397
+ * @param null $param
1398
+ *
1399
+ * @return mixed
1400
+ */
1401
+ protected function validate_url_exists($field, $input, $param = null) {
1402
+ if (!isset($input[$field]) || empty($input[$field])) {
1403
+ return;
1404
+ }
1405
+
1406
+ $url = parse_url(strtolower($input[$field]));
1407
+
1408
+ if (isset($url['host'])) {
1409
+ $url = $url['host'];
1410
+ }
1411
+
1412
+ if (function_exists('checkdnsrr')) {
1413
+ if (checkdnsrr($url) === false) {
1414
+ return array(
1415
+ 'field' => $field,
1416
+ 'value' => $input[$field],
1417
+ 'rule' => __FUNCTION__,
1418
+ 'param' => $param,
1419
+ );
1420
+ }
1421
+ } else {
1422
+ if (gethostbyname($url) == $url) {
1423
+ return array(
1424
+ 'field' => $field,
1425
+ 'value' => $input[$field],
1426
+ 'rule' => __FUNCTION__,
1427
+ 'param' => $param,
1428
+ );
1429
+ }
1430
+ }
1431
+ }
1432
+
1433
+ /**
1434
+ * Determine if the provided value is a valid IP address.
1435
+ *
1436
+ * Usage: '<index>' => 'valid_ip'
1437
+ *
1438
+ * @param string $field
1439
+ * @param array $input
1440
+ *
1441
+ * @return mixed
1442
+ */
1443
+ protected function validate_valid_ip($field, $input, $param = null) {
1444
+ if (!isset($input[$field]) || empty($input[$field])) {
1445
+ return;
1446
+ }
1447
+
1448
+ if (!filter_var($input[$field], FILTER_VALIDATE_IP) !== false) {
1449
+ return array(
1450
+ 'field' => $field,
1451
+ 'value' => $input[$field],
1452
+ 'rule' => __FUNCTION__,
1453
+ 'param' => $param,
1454
+ );
1455
+ }
1456
+ }
1457
+
1458
+ /**
1459
+ * Determine if the provided value is a valid IPv4 address.
1460
+ *
1461
+ * Usage: '<index>' => 'valid_ipv4'
1462
+ *
1463
+ * @param string $field
1464
+ * @param array $input
1465
+ *
1466
+ * @return mixed
1467
+ *
1468
+ * @see http://pastebin.com/UvUPPYK0
1469
+ */
1470
+
1471
+ /*
1472
+ * What about private networks? http://en.wikipedia.org/wiki/Private_network
1473
+ * What about loop-back address? 127.0.0.1
1474
+ */
1475
+ protected function validate_valid_ipv4($field, $input, $param = null) {
1476
+ if (!isset($input[$field]) || empty($input[$field])) {
1477
+ return;
1478
+ }
1479
+
1480
+ if (!filter_var($input[$field], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
1481
+ // removed !== FALSE
1482
+
1483
+ return array(
1484
+ 'field' => $field,
1485
+ 'value' => $input[$field],
1486
+ 'rule' => __FUNCTION__,
1487
+ 'param' => $param,
1488
+ );
1489
+ }
1490
+ }
1491
+
1492
+ /**
1493
+ * Determine if the provided value is a valid IPv6 address.
1494
+ *
1495
+ * Usage: '<index>' => 'valid_ipv6'
1496
+ *
1497
+ * @param string $field
1498
+ * @param array $input
1499
+ *
1500
+ * @return mixed
1501
+ */
1502
+ protected function validate_valid_ipv6($field, $input, $param = null) {
1503
+ if (!isset($input[$field]) || empty($input[$field])) {
1504
+ return;
1505
+ }
1506
+
1507
+ if (!filter_var($input[$field], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
1508
+ return array(
1509
+ 'field' => $field,
1510
+ 'value' => $input[$field],
1511
+ 'rule' => __FUNCTION__,
1512
+ 'param' => $param,
1513
+ );
1514
+ }
1515
+ }
1516
+
1517
+ /**
1518
+ * Determine if the input is a valid credit card number.
1519
+ *
1520
+ * See: http://stackoverflow.com/questions/174730/what-is-the-best-way-to-validate-a-credit-card-in-php
1521
+ * Usage: '<index>' => 'valid_cc'
1522
+ *
1523
+ * @param string $field
1524
+ * @param array $input
1525
+ *
1526
+ * @return mixed
1527
+ */
1528
+ protected function validate_valid_cc($field, $input, $param = null) {
1529
+ if (!isset($input[$field]) || empty($input[$field])) {
1530
+ return;
1531
+ }
1532
+
1533
+ $number = preg_replace('/\D/', '', $input[$field]);
1534
+
1535
+ if (function_exists('mb_strlen')) {
1536
+ $number_length = mb_strlen($number);
1537
+ } else {
1538
+ $number_length = strlen($number);
1539
+ }
1540
+
1541
+ $parity = $number_length % 2;
1542
+
1543
+ $total = 0;
1544
+
1545
+ for ($i = 0; $i < $number_length; ++$i) {
1546
+ $digit = $number[$i];
1547
+
1548
+ if ($i % 2 == $parity) {
1549
+ $digit *= 2;
1550
+
1551
+ if ($digit > 9) {
1552
+ $digit -= 9;
1553
+ }
1554
+ }
1555
+
1556
+ $total += $digit;
1557
+ }
1558
+
1559
+ if ($total % 10 == 0) {
1560
+ return; // Valid
1561
+ }
1562
+
1563
+ return array(
1564
+ 'field' => $field,
1565
+ 'value' => $input[$field],
1566
+ 'rule' => __FUNCTION__,
1567
+ 'param' => $param,
1568
+ );
1569
+ }
1570
+
1571
+ /**
1572
+ * Determine if the input is a valid human name [Credits to http://github.com/ben-s].
1573
+ *
1574
+ * See: https://github.com/Wixel/GUMP/issues/5
1575
+ * Usage: '<index>' => 'valid_name'
1576
+ *
1577
+ * @param string $field
1578
+ * @param array $input
1579
+ *
1580
+ * @return mixed
1581
+ */
1582
+ protected function validate_valid_name($field, $input, $param = null) {
1583
+ if (!isset($input[$field]) || empty($input[$field])) {
1584
+ return;
1585
+ }
1586
+
1587
+ if (!preg_match("/^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïñðòóôõöùúûüýÿ '-])+$/i", $input[$field]) !== false) {
1588
+ return array(
1589
+ 'field' => $field,
1590
+ 'value' => $input[$field],
1591
+ 'rule' => __FUNCTION__,
1592
+ 'param' => $param,
1593
+ );
1594
+ }
1595
+ }
1596
+
1597
+ /**
1598
+ * Determine if the provided input is likely to be a street address using weak detection.
1599
+ *
1600
+ * Usage: '<index>' => 'street_address'
1601
+ *
1602
+ * @param string $field
1603
+ * @param array $input
1604
+ *
1605
+ * @return mixed
1606
+ */
1607
+ protected function validate_street_address($field, $input, $param = null) {
1608
+ if (!isset($input[$field]) || empty($input[$field])) {
1609
+ return;
1610
+ }
1611
+
1612
+ // Theory: 1 number, 1 or more spaces, 1 or more words
1613
+ $hasLetter = preg_match('/[a-zA-Z]/', $input[$field]);
1614
+ $hasDigit = preg_match('/\d/', $input[$field]);
1615
+ $hasSpace = preg_match('/\s/', $input[$field]);
1616
+
1617
+ $passes = $hasLetter && $hasDigit && $hasSpace;
1618
+
1619
+ if (!$passes) {
1620
+ return array(
1621
+ 'field' => $field,
1622
+ 'value' => $input[$field],
1623
+ 'rule' => __FUNCTION__,
1624
+ 'param' => $param,
1625
+ );
1626
+ }
1627
+ }
1628
+
1629
+ /**
1630
+ * Determine if the provided value is a valid IBAN.
1631
+ *
1632
+ * Usage: '<index>' => 'iban'
1633
+ *
1634
+ * @param string $field
1635
+ * @param array $input
1636
+ *
1637
+ * @return mixed
1638
+ */
1639
+ protected function validate_iban($field, $input, $param = null) {
1640
+ if (!isset($input[$field]) || empty($input[$field])) {
1641
+ return;
1642
+ }
1643
+
1644
+ static $character = array(
1645
+ 'A' => 10, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16,
1646
+ 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22,
1647
+ 'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, 'S' => 28,
1648
+ 'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34,
1649
+ 'Z' => 35, 'B' => 11
1650
+ );
1651
+
1652
+ if (!preg_match("/\A[A-Z]{2}\d{2} ?[A-Z\d]{4}( ?\d{4}){1,} ?\d{1,4}\z/", $input[$field])) {
1653
+ return array(
1654
+ 'field' => $field,
1655
+ 'value' => $input[$field],
1656
+ 'rule' => __FUNCTION__,
1657
+ 'param' => $param,
1658
+ );
1659
+ }
1660
+
1661
+ $iban = str_replace(' ', '', $input[$field]);
1662
+ $iban = substr($iban, 4) . substr($iban, 0, 4);
1663
+ $iban = strtr($iban, $character);
1664
+
1665
+ if (bcmod($iban, 97) != 1) {
1666
+ return array(
1667
+ 'field' => $field,
1668
+ 'value' => $input[$field],
1669
+ 'rule' => __FUNCTION__,
1670
+ 'param' => $param,
1671
+ );
1672
+ }
1673
+ }
1674
+
1675
+ /**
1676
+ * Determine if the provided input is a valid date (ISO 8601).
1677
+ *
1678
+ * Usage: '<index>' => 'date'
1679
+ *
1680
+ * @param string $field
1681
+ * @param string $input date ('Y-m-d') or datetime ('Y-m-d H:i:s')
1682
+ * @param null $param
1683
+ *
1684
+ * @return mixed
1685
+ */
1686
+ protected function validate_date($field, $input, $param = null) {
1687
+ if (!isset($input[$field]) || empty($input[$field])) {
1688
+ return;
1689
+ }
1690
+
1691
+ $cdate1 = date('Y-m-d', strtotime($input[$field]));
1692
+ $cdate2 = date('Y-m-d H:i:s', strtotime($input[$field]));
1693
+
1694
+ if ($cdate1 != $input[$field] && $cdate2 != $input[$field]) {
1695
+ return array(
1696
+ 'field' => $field,
1697
+ 'value' => $input[$field],
1698
+ 'rule' => __FUNCTION__,
1699
+ 'param' => $param,
1700
+ );
1701
+ }
1702
+ }
1703
+
1704
+ /**
1705
+ * Determine if the provided input meets age requirement (ISO 8601).
1706
+ *
1707
+ * Usage: '<index>' => 'min_age,13'
1708
+ *
1709
+ * @param string $field
1710
+ * @param string $input date ('Y-m-d') or datetime ('Y-m-d H:i:s')
1711
+ * @param string $param int
1712
+ *
1713
+ * @return mixed
1714
+ */
1715
+ protected function validate_min_age($field, $input, $param = null) {
1716
+ if (!isset($input[$field]) || empty($input[$field])) {
1717
+ return;
1718
+ }
1719
+
1720
+ $cdate1 = new DateTime(date('Y-m-d', strtotime($input[$field])));
1721
+ $today = new DateTime(date('d-m-Y'));
1722
+
1723
+ $interval = $cdate1->diff($today);
1724
+ $age = $interval->y;
1725
+
1726
+ if ($age <= $param) {
1727
+ return array(
1728
+ 'field' => $field,
1729
+ 'value' => $input[$field],
1730
+ 'rule' => __FUNCTION__,
1731
+ 'param' => $param,
1732
+ );
1733
+ }
1734
+ }
1735
+
1736
+ /**
1737
+ * Determine if the provided numeric value is lower or equal to a specific value.
1738
+ *
1739
+ * Usage: '<index>' => 'max_numeric,50'
1740
+ *
1741
+ * @param string $field
1742
+ * @param array $input
1743
+ * @param null $param
1744
+ *
1745
+ * @return mixed
1746
+ */
1747
+ protected function validate_max_numeric($field, $input, $param = null) {
1748
+ if (!isset($input[$field]) || empty($input[$field])) {
1749
+ return;
1750
+ }
1751
+
1752
+ if (is_numeric($input[$field]) && is_numeric($param) && ($input[$field] <= $param)) {
1753
+ return;
1754
+ }
1755
+
1756
+ return array(
1757
+ 'field' => $field,
1758
+ 'value' => $input[$field],
1759
+ 'rule' => __FUNCTION__,
1760
+ 'param' => $param,
1761
+ );
1762
+ }
1763
+
1764
+ /**
1765
+ * Determine if the provided numeric value is higher or equal to a specific value.
1766
+ *
1767
+ * Usage: '<index>' => 'min_numeric,1'
1768
+ *
1769
+ * @param string $field
1770
+ * @param array $input
1771
+ * @param null $param
1772
+ *
1773
+ * @return mixed
1774
+ */
1775
+ protected function validate_min_numeric($field, $input, $param = null) {
1776
+ if (!isset($input[$field])) {
1777
+ return;
1778
+ }
1779
+
1780
+ if (is_numeric($input[$field]) && is_numeric($param) && ($input[$field] >= $param)) {
1781
+ return;
1782
+ }
1783
+
1784
+ return array(
1785
+ 'field' => $field,
1786
+ 'value' => $input[$field],
1787
+ 'rule' => __FUNCTION__,
1788
+ 'param' => $param,
1789
+ );
1790
+ }
1791
+
1792
+ /**
1793
+ * Determine if the provided value starts with param.
1794
+ *
1795
+ * Usage: '<index>' => 'starts,Z'
1796
+ *
1797
+ * @param string $field
1798
+ * @param array $input
1799
+ *
1800
+ * @return mixed
1801
+ */
1802
+ protected function validate_starts($field, $input, $param = null) {
1803
+ if (!isset($input[$field]) || empty($input[$field])) {
1804
+ return;
1805
+ }
1806
+
1807
+ if (strpos($input[$field], $param) !== 0) {
1808
+ return array(
1809
+ 'field' => $field,
1810
+ 'value' => $input[$field],
1811
+ 'rule' => __FUNCTION__,
1812
+ 'param' => $param,
1813
+ );
1814
+ }
1815
+ }
1816
+
1817
+ /**
1818
+ * checks if a file was uploaded.
1819
+ *
1820
+ * Usage: '<index>' => 'required_file'
1821
+ *
1822
+ * @param string $field
1823
+ * @param array $input
1824
+ *
1825
+ * @return mixed
1826
+ */
1827
+ protected function validate_required_file($field, $input, $param = null) {
1828
+ if ($input[$field]['error'] !== 4) {
1829
+ return;
1830
+ }
1831
+
1832
+ return array(
1833
+ 'field' => $field,
1834
+ 'value' => $input[$field],
1835
+ 'rule' => __FUNCTION__,
1836
+ 'param' => $param,
1837
+ );
1838
+ }
1839
+
1840
+ /**
1841
+ * check the uploaded file for extension
1842
+ * for now checks onlt the ext should add mime type check.
1843
+ *
1844
+ * Usage: '<index>' => 'starts,Z'
1845
+ *
1846
+ * @param string $field
1847
+ * @param array $input
1848
+ *
1849
+ * @return mixed
1850
+ */
1851
+ protected function validate_extension($field, $input, $param = null) {
1852
+ if ($input[$field]['error'] !== 4) {
1853
+ $param = trim(strtolower($param));
1854
+ $allowed_extensions = explode(';', $param);
1855
+
1856
+ $path_info = pathinfo($input[$field]['name']);
1857
+ $extension = $path_info['extension'];
1858
+
1859
+ if (in_array($extension, $allowed_extensions)) {
1860
+ return;
1861
+ }
1862
+
1863
+ return array(
1864
+ 'field' => $field,
1865
+ 'value' => $input[$field],
1866
+ 'rule' => __FUNCTION__,
1867
+ 'param' => $param,
1868
+ );
1869
+ }
1870
+ }
1871
+
1872
+ /**
1873
+ * Determine if the provided field value equals current field value.
1874
+ *
1875
+ * Usage: '<index>' => 'equalsfield,Z'
1876
+ *
1877
+ * @param string $field
1878
+ * @param string $input
1879
+ * @param string $param field to compare with
1880
+ *
1881
+ * @return mixed
1882
+ */
1883
+ protected function validate_equalsfield($field, $input, $param = null) {
1884
+ if (!isset($input[$field]) || empty($input[$field])) {
1885
+ return;
1886
+ }
1887
+
1888
+ if ($input[$field] == $input[$param]) {
1889
+ return;
1890
+ }
1891
+
1892
+ return array(
1893
+ 'field' => $field,
1894
+ 'value' => $input[$field],
1895
+ 'rule' => __FUNCTION__,
1896
+ 'param' => $param,
1897
+ );
1898
+ }
1899
+
1900
+ /**
1901
+ * Determine if the provided field value is a valid GUID (v4)
1902
+ *
1903
+ * Usage: '<index>' => 'guidv4'
1904
+ *
1905
+ * @param string $field
1906
+ * @param string $input
1907
+ * @param string $param field to compare with
1908
+ *
1909
+ * @return mixed
1910
+ */
1911
+ protected function validate_guidv4($field, $input, $param = null) {
1912
+ if (!isset($input[$field]) || empty($input[$field])) {
1913
+ return;
1914
+ }
1915
+
1916
+ if (preg_match("/\{?[A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12}\}?$/", $input[$field])) {
1917
+ return;
1918
+ }
1919
+
1920
+ return array(
1921
+ 'field' => $field,
1922
+ 'value' => $input[$field],
1923
+ 'rule' => __FUNCTION__,
1924
+ 'param' => $param,
1925
+ );
1926
+ }
1927
+
1928
+ /**
1929
+ * Trims whitespace only when the value is a scalar.
1930
+ *
1931
+ * @param mixed $value
1932
+ *
1933
+ * @return mixed
1934
+ */
1935
+ private function trimScalar($value) {
1936
+ if (is_scalar($value)) {
1937
+ $value = trim($value);
1938
+ }
1939
+
1940
+ return $value;
1941
+ }
1942
+
1943
+ /**
1944
+ * Determine if the provided value is a valid phone number.
1945
+ *
1946
+ * Usage: '<index>' => 'phone_number'
1947
+ *
1948
+ * @param string $field
1949
+ * @param array $input
1950
+ *
1951
+ * @return mixed
1952
+ *
1953
+ * Examples:
1954
+ *
1955
+ * 555-555-5555: valid
1956
+ * 5555425555: valid
1957
+ * 555 555 5555: valid
1958
+ * 1(519) 555-4444: valid
1959
+ * 1 (519) 555-4422: valid
1960
+ * 1-555-555-5555: valid
1961
+ * 1-(555)-555-5555: valid
1962
+ */
1963
+ protected function validate_phone_number($field, $input, $param = null) {
1964
+ if (!isset($input[$field]) || empty($input[$field])) {
1965
+ return;
1966
+ }
1967
+
1968
+ $regex = '/^(\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}$/i';
1969
+ if (!preg_match($regex, $input[$field])) {
1970
+ return array(
1971
+ 'field' => $field,
1972
+ 'value' => $input[$field],
1973
+ 'rule' => __FUNCTION__,
1974
+ 'param' => $param,
1975
+ );
1976
+ }
1977
+ }
1978
+
1979
+ /**
1980
+ * Custom regex validator.
1981
+ *
1982
+ * Usage: '<index>' => 'regex&&&/regex/'
1983
+ *
1984
+ * @param string $field
1985
+ * @param array $input
1986
+ *
1987
+ * @return mixed
1988
+ */
1989
+ protected function validate_regex($field, $input, $param = null) {
1990
+ if (!isset($input[$field]) || empty($input[$field])) {
1991
+ return;
1992
+ }
1993
+
1994
+ $regex = $param;
1995
+ if (!preg_match($regex, $input[$field])) {
1996
+ return array(
1997
+ 'field' => $field,
1998
+ 'value' => $input[$field],
1999
+ 'rule' => __FUNCTION__,
2000
+ 'param' => $param,
2001
+ );
2002
+ }
2003
+ }
2004
+
2005
+ /**
2006
+ * Json validatior.
2007
+ *
2008
+ * Usage: '<index>' => 'valid_json_string'
2009
+ *
2010
+ * @param string $field
2011
+ * @param array $input
2012
+ *
2013
+ * @return mixed
2014
+ */
2015
+ protected function validate_valid_json_string($field, $input, $param = null) {
2016
+ if (!isset($input[$field]) || empty($input[$field])) {
2017
+ return;
2018
+ }
2019
+
2020
+ if (!is_string($input[$field]) || !is_object(json_decode($input[$field]))) {
2021
+ return array(
2022
+ 'field' => $field,
2023
+ 'value' => $input[$field],
2024
+ 'rule' => __FUNCTION__,
2025
+ 'param' => $param,
2026
+ );
2027
+ }
2028
+ }
2029
+ } // EOC
classes/libs/parsers.php CHANGED
@@ -1,789 +1,789 @@
1
- <?php
2
- namespace mp_timetable\classes\libs;
3
- /**
4
- * WordPress eXtended RSS file parser implementations
5
- *
6
- * @package WordPress
7
- * @subpackage Importer
8
- */
9
-
10
- /**
11
- * WordPress Importer class for managing parsing of WXR files.
12
- */
13
- class WXR_Parser {
14
- function parse($file) {
15
-
16
- // Attempt to use proper XML parsers first
17
- if (extension_loaded('simplexml')) {
18
- $parser = new WXR_Parser_SimpleXML;
19
- $result = $parser->parse($file);
20
-
21
- // If SimpleXML succeeds or this is an invalid WXR file then return the results
22
- if (!is_wp_error($result) || 'SimpleXML_parse_error' != $result->get_error_code())
23
- return $result;
24
- } else if (extension_loaded('xml')) {
25
- $parser = new WXR_Parser_XML;
26
- $result = $parser->parse($file);
27
-
28
- // If XMLParser succeeds or this is an invalid WXR file then return the results
29
- if (!is_wp_error($result) || 'XML_parse_error' != $result->get_error_code())
30
- return $result;
31
- }
32
-
33
- // We have a malformed XML file, so display the error and fallthrough to regex
34
- if (isset($result) && defined('IMPORT_DEBUG') && IMPORT_DEBUG) {
35
- echo '<pre>';
36
- if ('SimpleXML_parse_error' == $result->get_error_code()) {
37
- foreach ($result->get_error_data() as $error)
38
- echo esc_html($error->line) . ':' . esc_html($error->column) . ' ' . esc_html($error->message) . "\n";
39
- } else if ('XML_parse_error' == $result->get_error_code()) {
40
- $error = $result->get_error_data();
41
- echo esc_html($error[0]) . ':' . esc_html($error[1]) . ' ' . esc_html($error[2]);
42
- }
43
- echo '</pre>';
44
- echo '<p><strong>' . __('There was an error when reading this WXR file', 'mp-timetable') . '</strong><br />';
45
- echo __('Details are shown above. The importer will now try again with a different parser...', 'mp-timetable') . '</p>';
46
- }
47
-
48
- // use regular expressions if nothing else available or this is bad XML
49
- $parser = new WXR_Parser_Regex;
50
- return $parser->parse($file);
51
- }
52
- }
53
-
54
- /**
55
- * WXR Parser that makes use of the SimpleXML PHP extension.
56
- */
57
- class WXR_Parser_SimpleXML {
58
- function parse($file) {
59
- $authors = $posts = $categories = $tags = $time_slots = $terms = array();
60
-
61
- $internal_errors = libxml_use_internal_errors(true);
62
-
63
- $dom = new \DOMDocument;
64
- $old_value = null;
65
- if (function_exists('libxml_disable_entity_loader')) {
66
- $old_value = libxml_disable_entity_loader(true);
67
- }
68
- $success = $dom->loadXML(file_get_contents($file));
69
- if (!is_null($old_value)) {
70
- libxml_disable_entity_loader($old_value);
71
- }
72
-
73
- if (!$success || isset($dom->doctype)) {
74
- return new \WP_Error('SimpleXML_parse_error', __('There was an error when reading this WXR file', 'mp-timetable'), libxml_get_errors());
75
- }
76
-
77
- $xml = simplexml_import_dom($dom);
78
- unset($dom);
79
-
80
- // halt if loading produces an error
81
- if (!$xml)
82
- return new \WP_Error('SimpleXML_parse_error', __('There was an error when reading this WXR file', 'mp-timetable'), libxml_get_errors());
83
-
84
- $wxr_version = $xml->xpath('/rss/channel/wp:wxr_version');
85
- if (!$wxr_version)
86
- return new \WP_Error('WXR_parse_error', __('This does not appear to be a WXR file, missing/invalid WXR version number', 'mp-timetable'));
87
-
88
- $wxr_version = (string)trim($wxr_version[0]);
89
- // confirm that we are dealing with the correct file format
90
- if (!preg_match('/^\d+\.\d+$/', $wxr_version))
91
- return new \WP_Error('WXR_parse_error', __('This does not appear to be a WXR file, missing/invalid WXR version number', 'mp-timetable'));
92
-
93
- $base_url = $xml->xpath('/rss/channel/wp:base_site_url');
94
- $base_url = (string)trim($base_url[0]);
95
-
96
- $namespaces = $xml->getDocNamespaces();
97
- if (!isset($namespaces['wp']))
98
- $namespaces['wp'] = 'http://wordpress.org/export/1.1/';
99
- if (!isset($namespaces['excerpt']))
100
- $namespaces['excerpt'] = 'http://wordpress.org/export/1.1/excerpt/';
101
-
102
- // grab authors
103
- foreach ($xml->xpath('/rss/channel/wp:author') as $author_arr) {
104
- $a = $author_arr->children($namespaces['wp']);
105
- $login = (string)$a->author_login;
106
- $authors[$login] = array(
107
- 'author_id' => (int)$a->author_id,
108
- 'author_login' => $login,
109
- 'author_email' => (string)$a->author_email,
110
- 'author_display_name' => (string)$a->author_display_name,
111
- 'author_first_name' => (string)$a->author_first_name,
112
- 'author_last_name' => (string)$a->author_last_name
113
- );
114
- }
115
-
116
- // grab cats, tags and terms
117
- foreach ($xml->xpath('/rss/channel/wp:category') as $term_arr) {
118
- $t = $term_arr->children($namespaces['wp']);
119
- $categories[] = array(
120
- 'term_id' => (int)$t->term_id,
121
- 'category_nicename' => (string)$t->category_nicename,
122
- 'category_parent' => (string)$t->category_parent,
123
- 'cat_name' => (string)$t->cat_name,
124
- 'category_description' => (string)$t->category_description
125
- );
126
- }
127
-
128
- foreach ($xml->xpath('/rss/channel/wp:tag') as $term_arr) {
129
- $t = $term_arr->children($namespaces['wp']);
130
- $tags[] = array(
131
- 'term_id' => (int)$t->term_id,
132
- 'tag_slug' => (string)$t->tag_slug,
133
- 'tag_name' => (string)$t->tag_name,
134
- 'tag_description' => (string)$t->tag_description
135
- );
136
- }
137
-
138
- foreach ($xml->xpath('/rss/channel/wp:term') as $term_arr) {
139
- $t = $term_arr->children($namespaces['wp']);
140
- $terms[] = array(
141
- 'term_id' => (int)$t->term_id,
142
- 'term_taxonomy' => (string)$t->term_taxonomy,
143
- 'slug' => (string)$t->term_slug,
144
- 'term_parent' => (string)$t->term_parent,
145
- 'term_name' => (string)$t->term_name,
146
- 'term_description' => (string)$t->term_description
147
- );
148
- }
149
-
150
- // grab posts
151
- foreach ($xml->channel->item as $item) {
152
- $post = array(
153
- 'post_title' => (string)$item->title,
154
- 'guid' => (string)$item->guid,
155
- );
156
-
157
- $dc = $item->children('http://purl.org/dc/elements/1.1/');
158
- $post['post_author'] = (string)$dc->creator;
159
-
160
- $content = $item->children('http://purl.org/rss/1.0/modules/content/');
161
- $excerpt = $item->children($namespaces['excerpt']);
162
- $post['post_content'] = (string)$content->encoded;
163
- $post['post_excerpt'] = (string)$excerpt->encoded;
164
-
165
- $wp = $item->children($namespaces['wp']);
166
- $post['post_id'] = (int)$wp->post_id;
167
- $post['post_date'] = (string)$wp->post_date;
168
- $post['post_date_gmt'] = (string)$wp->post_date_gmt;
169
- $post['comment_status'] = (string)$wp->comment_status;
170
- $post['ping_status'] = (string)$wp->ping_status;
171
- $post['post_name'] = (string)$wp->post_name;
172
- $post['status'] = (string)$wp->status;
173
- $post['post_parent'] = (int)$wp->post_parent;
174
- $post['menu_order'] = (int)$wp->menu_order;
175
- $post['post_type'] = (string)$wp->post_type;
176
- $post['post_password'] = (string)$wp->post_password;
177
- $post['is_sticky'] = (int)$wp->is_sticky;
178
-
179
- if (isset($wp->attachment_url))
180
- $post['attachment_url'] = (string)$wp->attachment_url;
181
-
182
- foreach ($item->category as $c) {
183
- $att = $c->attributes();
184
- if (isset($att['nicename']))
185
- $post['terms'][] = array(
186
- 'name' => (string)$c,
187
- 'slug' => (string)$att['nicename'],
188
- 'domain' => (string)$att['domain']
189
- );
190
- }
191
-
192
- foreach ($wp->postmeta as $meta) {
193
- $post['postmeta'][] = array(
194
- 'key' => (string)$meta->meta_key,
195
- 'value' => (string)$meta->meta_value
196
- );
197
- }
198
-
199
- foreach ($wp->timeslot as $time) {
200
- $post['timeslot'][] = array(
201
- 'column' => (string)$time->column,
202
- 'event' => (string)$time->event,
203
- 'event_start' => (string)$time->event_start,
204
- 'event_end' => (string)$time->event_end,
205
- 'user_id' => (string)$time->user_id,
206
- 'description' => (string)$time->description,
207
- );
208
- }
209
-
210
-
211
- foreach ($wp->comment as $comment) {
212
- $meta = array();
213
- if (isset($comment->commentmeta)) {
214
- foreach ($comment->commentmeta as $m) {
215
- $meta[] = array(
216
- 'key' => (string)$m->meta_key,
217
- 'value' => (string)$m->meta_value
218
- );
219
- }
220
- }
221
-
222
- $post['comments'][] = array(
223
- 'comment_id' => (int)$comment->comment_id,
224
- 'comment_author' => (string)$comment->comment_author,
225
- 'comment_author_email' => (string)$comment->comment_author_email,
226
- 'comment_author_IP' => (string)$comment->comment_author_IP,
227
- 'comment_author_url' => (string)$comment->comment_author_url,
228
- 'comment_date' => (string)$comment->comment_date,
229
- 'comment_date_gmt' => (string)$comment->comment_date_gmt,
230
- 'comment_content' => (string)$comment->comment_content,
231
- 'comment_approved' => (string)$comment->comment_approved,
232
- 'comment_type' => (string)$comment->comment_type,
233
- 'comment_parent' => (string)$comment->comment_parent,
234
- 'comment_user_id' => (int)$comment->comment_user_id,
235
- 'commentmeta' => $meta,
236
- );
237
- }
238
-
239
- $posts[] = $post;
240
- }
241
- // grab time_slots
242
- foreach ($xml->channel->timeslot as $time) {
243
- $time_slots[] = array(
244
- 'column' => (int)$time->column,
245
- 'event' => (int)$time->event,
246
- 'event_start' => (string)$time->event_start,
247
- 'event_end' => (string)$time->event_end,
248
- 'user_id' => (int)$time->user_id,
249
- 'description' => (string)$time->description,
250
- );
251
- }
252
- return array(
253
- 'authors' => $authors,
254
- 'posts' => $posts,
255
- 'categories' => $categories,
256
- 'tags' => $tags,
257
- 'terms' => $terms,
258
- 'time_slots' => $time_slots,
259
- 'base_url' => $base_url,
260
- 'version' => $wxr_version
261
- );
262
- }
263
- }
264
-
265
- /**
266
- * WXR Parser that makes use of the XML Parser PHP extension.
267
- */
268
- class WXR_Parser_XML {
269
- var $wp_tags = array(
270
- 'wp:post_id', 'wp:post_date', 'wp:post_date_gmt', 'wp:comment_status', 'wp:ping_status', 'wp:attachment_url',
271
- 'wp:status', 'wp:post_name', 'wp:post_parent', 'wp:menu_order', 'wp:post_type', 'wp:post_password',
272
- 'wp:is_sticky', 'wp:term_id', 'wp:category_nicename', 'wp:category_parent', 'wp:cat_name', 'wp:category_description',
273
- 'wp:tag_slug', 'wp:tag_name', 'wp:tag_description', 'wp:term_taxonomy', 'wp:term_parent',
274
- 'wp:term_name', 'wp:term_description', 'wp:author_id', 'wp:author_login', 'wp:author_email', 'wp:author_display_name',
275
- 'wp:author_first_name', 'wp:author_last_name',
276
- );
277
- var $wp_sub_tags = array(
278
- 'wp:comment_id', 'wp:comment_author', 'wp:comment_author_email', 'wp:comment_author_url',
279
- 'wp:comment_author_IP', 'wp:comment_date', 'wp:comment_date_gmt', 'wp:comment_content',
280
- 'wp:comment_approved', 'wp:comment_type', 'wp:comment_parent', 'wp:comment_user_id',
281
- );
282
-
283
- function parse($file) {
284
- $this->wxr_version = $this->in_post = $this->cdata = $this->data = $this->sub_data = $this->in_tag = $this->in_sub_tag = false;
285
- $this->authors = $this->posts = $this->term = $this->category = $this->tag = $this->time_slots = array();
286
-
287
- $xml = xml_parser_create('UTF-8');
288
- xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
289
- xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
290
- xml_set_object($xml, $this);
291
- xml_set_character_data_handler($xml, 'cdata');
292
- xml_set_element_handler($xml, 'tag_open', 'tag_close');
293
-
294
- if (!xml_parse($xml, file_get_contents($file), true)) {
295
- $current_line = xml_get_current_line_number($xml);
296
- $current_column = xml_get_current_column_number($xml);
297
- $error_code = xml_get_error_code($xml);
298
- $error_string = xml_error_string($error_code);
299
- return new \WP_Error('XML_parse_error', 'There was an error when reading this WXR file', array($current_line, $current_column, $error_string));
300
- }
301
- xml_parser_free($xml);
302
-
303
- if (!preg_match('/^\d+\.\d+$/', $this->wxr_version))
304
- return new \WP_Error('WXR_parse_error', __('This does not appear to be a WXR file, missing/invalid WXR version number', 'mp-timetable'));
305
-
306
- return array(
307
- 'authors' => $this->authors,
308
- 'posts' => $this->posts,
309
- 'categories' => $this->category,
310
- 'tags' => $this->tag,
311
- 'terms' => $this->term,
312
- 'base_url' => $this->base_url,
313
- 'version' => $this->wxr_version,
314
- 'time_slots' => $this->time_slots
315
- );
316
- }
317
-
318
- function tag_open($parse, $tag, $attr) {
319
- if (in_array($tag, $this->wp_tags)) {
320
- $this->in_tag = substr($tag, 3);
321
- return;
322
- }
323
-
324
- if (in_array($tag, $this->wp_sub_tags)) {
325
- $this->in_sub_tag = substr($tag, 3);
326
- return;
327
- }
328
-
329
- switch ($tag) {
330
- case 'category':
331
- if (isset($attr['domain'], $attr['nicename'])) {
332
- $this->sub_data['domain'] = $attr['domain'];
333
- $this->sub_data['slug'] = $attr['nicename'];
334
- }
335
- break;
336
- case 'item':
337
- $this->in_post = true;
338
- case 'title':
339
- if ($this->in_post) $this->in_tag = 'post_title';
340
- break;
341
- case 'timeslot':
342
- break;
343
- case 'column':
344
- $this->in_tag = 'column';
345
- break;
346
- case 'event':
347
- $this->in_tag = 'event';
348
- break;
349
- case 'event_start':
350
- $this->in_tag = 'event_start';
351
- break;
352
- case 'event_end':
353
- $this->in_tag = 'event_end';
354
- break;
355
- case 'user_id':
356
- $this->in_tag = 'user_id';
357
- break;
358
- case 'description':
359
- $this->in_tag = 'description';
360
- break;
361
- case 'guid':
362
- $this->in_tag = 'guid';
363
- break;
364
- case 'dc:creator':
365
- $this->in_tag = 'post_author';
366
- break;
367
- case 'content:encoded':
368
- $this->in_tag = 'post_content';
369
- break;
370
- case 'excerpt:encoded':
371
- $this->in_tag = 'post_excerpt';
372
- break;
373
- case 'wp:term_slug':
374
- $this->in_tag = 'slug';
375
- break;
376
- case 'wp:meta_key':
377
- $this->in_sub_tag = 'key';
378
- break;
379
- case 'wp:meta_value':
380
- $this->in_sub_tag = 'value';
381
- break;
382
- }
383
- }
384
-
385
- function cdata($parser, $cdata) {
386
- if (!trim($cdata))
387
- return;
388
-
389
- $this->cdata .= trim($cdata);
390
- }
391
-
392
- function tag_close($parser, $tag) {
393
- switch ($tag) {
394
- case 'wp:comment':
395
- unset($this->sub_data['key'], $this->sub_data['value']); // remove meta sub_data
396
- if (!empty($this->sub_data))
397
- $this->data['comments'][] = $this->sub_data;
398
- $this->sub_data = false;
399
- break;
400
- case 'wp:commentmeta':
401
- $this->sub_data['commentmeta'][] = array(
402
- 'key' => $this->sub_data['key'],
403
- 'value' => $this->sub_data['value']
404
- );
405
- break;
406
- case 'category':
407
- if (!empty($this->sub_data)) {
408
- $this->sub_data['name'] = $this->cdata;
409
- $this->data['terms'][] = $this->sub_data;
410
- }
411
- $this->sub_data = false;
412
- break;
413
- case 'wp:postmeta':
414
- if (!empty($this->sub_data))
415
- $this->data['postmeta'][] = $this->sub_data;
416
- $this->sub_data = false;
417
- break;
418
- case 'timeslot':
419
- $this->time_slots[] = $this->data;
420
- $this->data = false;
421
- break;
422
- case 'item':
423
- $this->posts[] = $this->data;
424
- $this->data = false;
425
- break;
426
- case 'wp:category':
427
- case 'wp:tag':
428
- case 'wp:term':
429
- $n = substr($tag, 3);
430
- array_push($this->$n, $this->data);
431
- $this->data = false;
432
- break;
433
- case 'wp:author':
434
- if (!empty($this->data['author_login']))
435
- $this->authors[$this->data['author_login']] = $this->data;
436
- $this->data = false;
437
- break;
438
- case 'wp:base_site_url':
439
- $this->base_url = $this->cdata;
440
- break;
441
- case 'wp:wxr_version':
442
- $this->wxr_version = $this->cdata;
443
- break;
444
-
445
- default:
446
- if ($this->in_sub_tag) {
447
- $this->sub_data[$this->in_sub_tag] = !empty($this->cdata) ? $this->cdata : '';
448
- $this->in_sub_tag = false;
449
- } else if ($this->in_tag) {
450
- $this->data[$this->in_tag] = !empty($this->cdata) ? $this->cdata : '';
451
- $this->in_tag = false;
452
- }
453
- }
454
-
455
- $this->cdata = false;
456
- }
457
- }
458
-
459
- /**
460
- * WXR Parser that uses regular expressions. Fallback for installs without an XML parser.
461
- */
462
- class WXR_Parser_Regex {
463
- var $authors = array();
464
- var $posts = array();
465
- var $categories = array();
466
- var $tags = array();
467
- var $terms = array();
468
- var $time_slots = array();
469
- var $base_url = '';
470
-
471
- function __construct() {
472
- $this->has_gzip = is_callable('gzopen');
473
- }
474
-
475
- function parse($file) {
476
- $wxr_version = $in_post = $in_tag = false;
477
- $post = $tag = '';
478
- $fp = $this->fopen($file, 'r');
479
- if ($fp) {
480
- while (!$this->feof($fp)) {
481
- $importline = rtrim($this->fgets($fp));
482
-
483
- if (!$wxr_version && preg_match('|<wp:wxr_version>(\d+\.\d+)</wp:wxr_version>|', $importline, $version))
484
- $wxr_version = $version[1];
485
-
486
- if (false !== strpos($importline, '<wp:base_site_url>')) {
487
- preg_match('|<wp:base_site_url>(.*?)</wp:base_site_url>|is', $importline, $url);
488
- $this->base_url = $url[1];
489
- continue;
490
- }
491
- if (false !== strpos($importline, '<wp:category>')) {
492
- preg_match('|<wp:category>(.*?)</wp:category>|is', $importline, $category);
493
- $this->categories[] = $this->process_category($category[1]);
494
- continue;
495
- }
496
- if (false !== strpos($importline, '<wp:tag>')) {
497
- preg_match('|<wp:tag>(.*?)</wp:tag>|is', $importline, $tag);
498
- $this->tags[] = $this->process_tag($tag[1]);
499
- continue;
500
- }
501
- if (false !== strpos($importline, '<wp:term>')) {
502
- preg_match('|<wp:term>(.*?)</wp:term>|is', $importline, $term);
503
- if (!empty($term)) {
504
- $this->terms[] = $this->process_term($term[1]);
505
- } else {
506
- $in_tag = true;
507
- }
508
- continue;
509
- }
510
-
511
- if (false !== strpos($importline, '</wp:term>')) {
512
- $tag .= $importline . "\n";
513
- $this->terms[] = $this->process_term($tag);
514
- $tag = '';
515
- $in_tag = false;
516
- continue;
517
- }
518
-
519
- if (false !== strpos($importline, '<timeslot>')) {
520
- preg_match('|<timeslot>(.*?)</timeslot>|is', $importline, $time_slot);
521
- if (!empty($time_slot)) {
522
- $this->time_slots[] = $this->process_time_slot($time_slot[1]);
523
- } else {
524
- $in_tag = true;
525
- }
526
- continue;
527
- }
528
- if (false !== strpos($importline, '</timeslot>')) {
529
- $tag .= $importline . "\n";
530
- $this->time_slots[] = $this->process_time_slot($tag);
531
- $tag = '';
532
- $in_tag = false;
533
- continue;
534
- }
535
-
536
-
537
- if (false !== strpos($importline, '<wp:author>')) {
538
- preg_match('|<wp:author>(.*?)</wp:author>|is', $importline, $author);
539
- $a = $this->process_author($author[1]);
540
- $this->authors[$a['author_login']] = $a;
541
- continue;
542
- }
543
- if (false !== strpos($importline, '<item>')) {
544
- $in_post = true;
545
- continue;
546
- }
547
- if (false !== strpos($importline, '</item>')) {
548
- $in_post = false;
549
- $this->posts[] = $this->process_post($post);
550
- continue;
551
- }
552
- if ($in_post) {
553
- $post .= $importline . "\n";
554
- }
555
-
556
- if ($in_tag) {
557
- $tag .= $importline . "\n";
558
- }
559
- }
560
-
561
- $this->fclose($fp);
562
- }
563
-
564
- if (!$wxr_version)
565
- return new \WP_Error('WXR_parse_error', __('This does not appear to be a WXR file, missing/invalid WXR version number', 'mp-timetable'));
566
-
567
- return array(
568
- 'authors' => $this->authors,
569
- 'posts' => $this->posts,
570
- 'categories' => $this->categories,
571
- 'tags' => $this->tags,
572
- 'terms' => $this->terms,
573
- 'base_url' => $this->base_url,
574
- 'version' => $wxr_version,
575
- 'time_slots' => $this->time_slots
576
- );
577
- }
578
-
579
- function get_tag($string, $tag) {
580
- preg_match("|<$tag.*?>(.*?)</$tag>|is", $string, $return);
581
- if (isset($return[1])) {
582
- if (substr($return[1], 0, 9) == '<![CDATA[') {
583
- if (strpos($return[1], ']]]]><![CDATA[>') !== false) {
584
- preg_match_all('|<!\[CDATA\[(.*?)\]\]>|s', $return[1], $matches);
585
- $return = '';
586
- foreach ($matches[1] as $match)
587
- $return .= $match;
588
- } else {
589
- $return = preg_replace('|^<!\[CDATA\[(.*)\]\]>$|s', '$1', $return[1]);
590
- }
591
- } else {
592
- $return = $return[1];
593
- }
594
- } else {
595
- $return = '';
596
- }
597
- return $return;
598
- }
599
-
600
- function process_category($c) {
601
- return array(
602
- 'term_id' => $this->get_tag($c, 'wp:term_id'),
603
- 'cat_name' => $this->get_tag($c, 'wp:cat_name'),
604
- 'category_nicename' => $this->get_tag($c, 'wp:category_nicename'),
605
- 'category_parent' => $this->get_tag($c, 'wp:category_parent'),
606
- 'category_description' => $this->get_tag($c, 'wp:category_description'),
607
- );
608
- }
609
-
610
- function process_tag($t) {
611
- return array(
612
- 'term_id' => $this->get_tag($t, 'wp:term_id'),
613
- 'tag_name' => $this->get_tag($t, 'wp:tag_name'),
614
- 'tag_slug' => $this->get_tag($t, 'wp:tag_slug'),
615
- 'tag_description' => $this->get_tag($t, 'wp:tag_description'),
616
- );
617
- }
618
-
619
- function process_term($t) {
620
- return array(
621
- 'term_id' => $this->get_tag($t, 'wp:term_id'),
622
- 'term_taxonomy' => $this->get_tag($t, 'wp:term_taxonomy'),
623
- 'slug' => $this->get_tag($t, 'wp:term_slug'),
624
- 'term_parent' => $this->get_tag($t, 'wp:term_parent'),
625
- 'term_name' => $this->get_tag($t, 'wp:term_name'),
626
- 'term_description' => $this->get_tag($t, 'wp:term_description'),
627
- );
628
- }
629
-
630
- function process_time_slot($t) {
631
- return array(
632
- 'column' => $this->get_tag($t, 'column'),
633
- 'event' => $this->get_tag($t, 'event'),
634
- 'event_start' => $this->get_tag($t, 'event_start'),
635
- 'event_end' => $this->get_tag($t, 'event_end'),
636
- 'user_id' => $this->get_tag($t, 'user_id'),
637
- 'description' => $this->get_tag($t, 'description'),
638
- );
639
- }
640
-
641
- function process_author($a) {
642
- return array(
643
- 'author_id' => $this->get_tag($a, 'wp:author_id'),
644
- 'author_login' => $this->get_tag($a, 'wp:author_login'),
645
- 'author_email' => $this->get_tag($a, 'wp:author_email'),
646
- 'author_display_name' => $this->get_tag($a, 'wp:author_display_name'),
647
- 'author_first_name' => $this->get_tag($a, 'wp:author_first_name'),
648
- 'author_last_name' => $this->get_tag($a, 'wp:author_last_name'),
649
- );
650
- }
651
-
652
- function process_post($post) {
653
- $post_id = $this->get_tag($post, 'wp:post_id');
654
- $post_title = $this->get_tag($post, 'title');
655
- $post_date = $this->get_tag($post, 'wp:post_date');
656
- $post_date_gmt = $this->get_tag($post, 'wp:post_date_gmt');
657
- $comment_status = $this->get_tag($post, 'wp:comment_status');
658
- $ping_status = $this->get_tag($post, 'wp:ping_status');
659
- $status = $this->get_tag($post, 'wp:status');
660
- $post_name = $this->get_tag($post, 'wp:post_name');
661
- $post_parent = $this->get_tag($post, 'wp:post_parent');
662
- $menu_order = $this->get_tag($post, 'wp:menu_order');
663
- $post_type = $this->get_tag($post, 'wp:post_type');
664
- $post_password = $this->get_tag($post, 'wp:post_password');
665
- $is_sticky = $this->get_tag($post, 'wp:is_sticky');
666
- $guid = $this->get_tag($post, 'guid');
667
- $post_author = $this->get_tag($post, 'dc:creator');
668
-
669
- $post_excerpt = $this->get_tag($post, 'excerpt:encoded');
670
- $post_excerpt = preg_replace_callback('|<(/?[A-Z]+)|', array(&$this, '_normalize_tag'), $post_excerpt);
671
- $post_excerpt = str_replace('<br>', '<br />', $post_excerpt);
672
- $post_excerpt = str_replace('<hr>', '<hr />', $post_excerpt);
673
-
674
- $post_content = $this->get_tag($post, 'content:encoded');
675
- $post_content = preg_replace_callback('|<(/?[A-Z]+)|', array(&$this, '_normalize_tag'), $post_content);
676
- $post_content = str_replace('<br>', '<br />', $post_content);
677
- $post_content = str_replace('<hr>', '<hr />', $post_content);
678
-
679
- $postdata = compact('post_id', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_excerpt',
680
- 'post_title', 'status', 'post_name', 'comment_status', 'ping_status', 'guid', 'post_parent',
681
- 'menu_order', 'post_type', 'post_password', 'is_sticky'
682
- );
683
-
684
- $attachment_url = $this->get_tag($post, 'wp:attachment_url');
685
- if ($attachment_url)
686
- $postdata['attachment_url'] = $attachment_url;
687
-
688
- preg_match_all('|<category domain="([^"]+?)" nicename="([^"]+?)">(.+?)</category>|is', $post, $terms, PREG_SET_ORDER);
689
- foreach ($terms as $t) {
690
- $post_terms[] = array(
691
- 'slug' => $t[2],
692
- 'domain' => $t[1],
693
- 'name' => str_replace(array('<![CDATA[', ']]>'), '', $t[3]),
694
- );
695
- }
696
- if (!empty($post_terms)) $postdata['terms'] = $post_terms;
697
-
698
- preg_match_all('|<wp:comment>(.+?)</wp:comment>|is', $post, $comments);
699
- $comments = $comments[1];
700
- if ($comments) {
701
- foreach ($comments as $comment) {
702
- preg_match_all('|<wp:commentmeta>(.+?)</wp:commentmeta>|is', $comment, $commentmeta);
703
- $commentmeta = $commentmeta[1];
704
- $c_meta = array();
705
- foreach ($commentmeta as $m) {
706
- $c_meta[] = array(
707
- 'key' => $this->get_tag($m, 'wp:meta_key'),
708
- 'value' => $this->get_tag($m, 'wp:meta_value'),
709
- );
710
- }
711
-
712
- $post_comments[] = array(
713
- 'comment_id' => $this->get_tag($comment, 'wp:comment_id'),
714
- 'comment_author' => $this->get_tag($comment, 'wp:comment_author'),
715
- 'comment_author_email' => $this->get_tag($comment, 'wp:comment_author_email'),
716
- 'comment_author_IP' => $this->get_tag($comment, 'wp:comment_author_IP'),
717
- 'comment_author_url' => $this->get_tag($comment, 'wp:comment_author_url'),
718
- 'comment_date' => $this->get_tag($comment, 'wp:comment_date'),
719
- 'comment_date_gmt' => $this->get_tag($comment, 'wp:comment_date_gmt'),
720
- 'comment_content' => $this->get_tag($comment, 'wp:comment_content'),
721
- 'comment_approved' => $this->get_tag($comment, 'wp:comment_approved'),
722
- 'comment_type' => $this->get_tag($comment, 'wp:comment_type'),
723
- 'comment_parent' => $this->get_tag($comment, 'wp:comment_parent'),
724
- 'comment_user_id' => $this->get_tag($comment, 'wp:comment_user_id'),
725
- 'commentmeta' => $c_meta,
726
- );
727
- }
728
- }
729
- if (!empty($post_comments)) $postdata['comments'] = $post_comments;
730
-
731
- preg_match_all('|<wp:postmeta>(.+?)</wp:postmeta>|is', $post, $postmeta);
732
- $postmeta = $postmeta[1];
733
- if ($postmeta) {
734
- foreach ($postmeta as $p) {
735
- $post_postmeta[] = array(
736
- 'key' => $this->get_tag($p, 'wp:meta_key'),
737
- 'value' => $this->get_tag($p, 'wp:meta_value'),
738
- );
739
- }
740
- }
741
- if (!empty($post_postmeta)) $postdata['postmeta'] = $post_postmeta;
742
-
743
- preg_match_all('|<wp:timeslot>(.+?)</wp:timeslot>|is', $post, $timeslot);
744
- $timeslot = $timeslot[1];
745
- if ($timeslot) {
746
- foreach ($timeslot as $p) {
747
- $post_ptimeslot[] = array(
748
- 'column' => $this->get_tag($p, 'wp:column'),
749
- 'event' => $this->get_tag($p, 'wp:event'),
750
- 'event_start' => $this->get_tag($p, 'wp:event_start'),
751
- 'event_end' => $this->get_tag($p, 'wp:event_end'),
752
- 'user_id' => $this->get_tag($p, 'wp:user_id'),
753
- 'description' => $this->get_tag($p, 'wp:description')
754
- );
755
- }
756
- }
757
- if (!empty($post_timeslot)) $postdata['timeslot'] = $post_timeslot;
758
-
759
- return $postdata;
760
- }
761
-
762
- function _normalize_tag($matches) {
763
- return '<' . strtolower($matches[1]);
764
- }
765
-
766
- function fopen($filename, $mode = 'r') {
767
- if ($this->has_gzip)
768
- return gzopen($filename, $mode);
769
- return fopen($filename, $mode);
770
- }
771
-
772
- function feof($fp) {
773
- if ($this->has_gzip)
774
- return gzeof($fp);
775
- return feof($fp);
776
- }
777
-
778
- function fgets($fp, $len = 8192) {
779
- if ($this->has_gzip)
780
- return gzgets($fp, $len);
781
- return fgets($fp, $len);
782
- }
783
-
784
- function fclose($fp) {
785
- if ($this->has_gzip)
786
- return gzclose($fp);
787
- return fclose($fp);
788
- }
789
- }
1
+ <?php
2
+ namespace mp_timetable\classes\libs;
3
+ /**
4
+ * WordPress eXtended RSS file parser implementations
5
+ *
6
+ * @package WordPress
7
+ * @subpackage Importer
8
+ */
9
+
10
+ /**
11
+ * WordPress Importer class for managing parsing of WXR files.
12
+ */
13
+ class WXR_Parser {
14
+ function parse($file) {
15
+
16
+ // Attempt to use proper XML parsers first
17
+ if (extension_loaded('simplexml')) {
18
+ $parser = new WXR_Parser_SimpleXML;
19
+ $result = $parser->parse($file);
20
+
21
+ // If SimpleXML succeeds or this is an invalid WXR file then return the results
22
+ if (!is_wp_error($result) || 'SimpleXML_parse_error' != $result->get_error_code())
23
+ return $result;
24
+ } else if (extension_loaded('xml')) {
25
+ $parser = new WXR_Parser_XML;
26
+ $result = $parser->parse($file);
27
+
28
+ // If XMLParser succeeds or this is an invalid WXR file then return the results
29
+ if (!is_wp_error($result) || 'XML_parse_error' != $result->get_error_code())
30
+ return $result;
31
+ }
32
+
33
+ // We have a malformed XML file, so display the error and fallthrough to regex
34
+ if (isset($result) && defined('IMPORT_DEBUG') && IMPORT_DEBUG) {
35
+ echo '<pre>';
36
+ if ('SimpleXML_parse_error' == $result->get_error_code()) {
37
+ foreach ($result->get_error_data() as $error)
38
+ echo esc_html($error->line) . ':' . esc_html($error->column) . ' ' . esc_html($error->message) . "\n";
39
+ } else if ('XML_parse_error' == $result->get_error_code()) {
40
+ $error = $result->get_error_data();
41
+ echo esc_html($error[0]) . ':' . esc_html($error[1]) . ' ' . esc_html($error[2]);
42
+ }
43
+ echo '</pre>';
44
+ echo '<p><strong>' . __('There was an error when reading this WXR file', 'mp-timetable') . '</strong><br />';
45
+ echo __('Details are shown above. The importer will now try again with a different parser...', 'mp-timetable') . '</p>';
46
+ }
47
+
48
+ // use regular expressions if nothing else available or this is bad XML
49
+ $parser = new WXR_Parser_Regex;
50
+ return $parser->parse($file);
51
+ }
52
+ }
53
+
54
+ /**
55
+ * WXR Parser that makes use of the SimpleXML PHP extension.
56
+ */
57
+ class WXR_Parser_SimpleXML {
58
+ function parse($file) {
59
+ $authors = $posts = $categories = $tags = $time_slots = $terms = array();
60
+
61
+ $internal_errors = libxml_use_internal_errors(true);
62
+
63
+ $dom = new \DOMDocument;
64
+ $old_value = null;
65
+ if (function_exists('libxml_disable_entity_loader')) {
66
+ $old_value = libxml_disable_entity_loader(true);
67
+ }
68
+ $success = $dom->loadXML(file_get_contents($file));
69
+ if (!is_null($old_value)) {
70
+ libxml_disable_entity_loader($old_value);
71
+ }
72
+
73
+ if (!$success || isset($dom->doctype)) {
74
+ return new \WP_Error('SimpleXML_parse_error', __('There was an error when reading this WXR file', 'mp-timetable'), libxml_get_errors());
75
+ }
76
+
77
+ $xml = simplexml_import_dom($dom);
78
+ unset($dom);
79
+
80
+ // halt if loading produces an error
81
+ if (!$xml)
82
+ return new \WP_Error('SimpleXML_parse_error', __('There was an error when reading this WXR file', 'mp-timetable'), libxml_get_errors());
83
+
84
+ $wxr_version = $xml->xpath('/rss/channel/wp:wxr_version');
85
+ if (!$wxr_version)
86
+ return new \WP_Error('WXR_parse_error', __('This does not appear to be a WXR file, missing/invalid WXR version number', 'mp-timetable'));
87
+
88
+ $wxr_version = (string)trim($wxr_version[0]);
89
+ // confirm that we are dealing with the correct file format
90
+ if (!preg_match('/^\d+\.\d+$/', $wxr_version))
91
+ return new \WP_Error('WXR_parse_error', __('This does not appear to be a WXR file, missing/invalid WXR version number', 'mp-timetable'));
92
+
93
+ $base_url = $xml->xpath('/rss/channel/wp:base_site_url');
94
+ $base_url = (string)trim($base_url[0]);
95
+
96
+ $namespaces = $xml->getDocNamespaces();
97
+ if (!isset($namespaces['wp']))
98
+ $namespaces['wp'] = 'http://wordpress.org/export/1.1/';
99
+ if (!isset($namespaces['excerpt']))
100
+ $namespaces['excerpt'] = 'http://wordpress.org/export/1.1/excerpt/';
101
+
102
+ // grab authors
103
+ foreach ($xml->xpath('/rss/channel/wp:author') as $author_arr) {
104
+ $a = $author_arr->children($namespaces['wp']);
105
+ $login = (string)$a->author_login;
106
+ $authors[$login] = array(
107
+ 'author_id' => (int)$a->author_id,
108
+ 'author_login' => $login,
109
+ 'author_email' => (string)$a->author_email,
110
+ 'author_display_name' => (string)$a->author_display_name,
111
+ 'author_first_name' => (string)$a->author_first_name,
112
+ 'author_last_name' => (string)$a->author_last_name
113
+ );
114
+ }
115
+
116
+ // grab cats, tags and terms
117
+ foreach ($xml->xpath('/rss/channel/wp:category') as $term_arr) {
118
+ $t = $term_arr->children($namespaces['wp']);
119
+ $categories[] = array(
120
+ 'term_id' => (int)$t->term_id,
121
+ 'category_nicename' => (string)$t->category_nicename,
122
+ 'category_parent' => (string)$t->category_parent,
123
+ 'cat_name' => (string)$t->cat_name,
124
+ 'category_description' => (string)$t->category_description
125
+ );
126
+ }
127
+
128
+ foreach ($xml->xpath('/rss/channel/wp:tag') as $term_arr) {
129
+ $t = $term_arr->children($namespaces['wp']);
130
+ $tags[] = array(
131
+ 'term_id' => (int)$t->term_id,
132
+ 'tag_slug' => (string)$t->tag_slug,
133
+ 'tag_name' => (string)$t->tag_name,
134
+ 'tag_description' => (string)$t->tag_description
135
+ );
136
+ }
137
+
138
+ foreach ($xml->xpath('/rss/channel/wp:term') as $term_arr) {
139
+ $t = $term_arr->children($namespaces['wp']);
140
+ $terms[] = array(
141
+ 'term_id' => (int)$t->term_id,
142
+ 'term_taxonomy' => (string)$t->term_taxonomy,
143
+ 'slug' => (string)$t->term_slug,
144
+ 'term_parent' => (string)$t->term_parent,
145
+ 'term_name' => (string)$t->term_name,
146
+ 'term_description' => (string)$t->term_description
147
+ );
148
+ }
149
+
150
+ // grab posts
151
+ foreach ($xml->channel->item as $item) {
152
+ $post = array(
153
+ 'post_title' => (string)$item->title,
154
+ 'guid' => (string)$item->guid,
155
+ );
156
+
157
+ $dc = $item->children('http://purl.org/dc/elements/1.1/');
158
+ $post['post_author'] = (string)$dc->creator;
159
+
160
+ $content = $item->children('http://purl.org/rss/1.0/modules/content/');
161
+ $excerpt = $item->children($namespaces['excerpt']);
162
+ $post['post_content'] = (string)$content->encoded;
163
+ $post['post_excerpt'] = (string)$excerpt->encoded;
164
+
165
+ $wp = $item->children($namespaces['wp']);
166
+ $post['post_id'] = (int)$wp->post_id;
167
+ $post['post_date'] = (string)$wp->post_date;
168
+ $post['post_date_gmt'] = (string)$wp->post_date_gmt;
169
+ $post['comment_status'] = (string)$wp->comment_status;
170
+ $post['ping_status'] = (string)$wp->ping_status;
171
+ $post['post_name'] = (string)$wp->post_name;
172
+ $post['status'] = (string)$wp->status;
173
+ $post['post_parent'] = (int)$wp->post_parent;
174
+ $post['menu_order'] = (int)$wp->menu_order;
175
+ $post['post_type'] = (string)$wp->post_type;
176
+ $post['post_password'] = (string)$wp->post_password;
177
+ $post['is_sticky'] = (int)$wp->is_sticky;
178
+
179
+ if (isset($wp->attachment_url))
180
+ $post['attachment_url'] = (string)$wp->attachment_url;
181
+
182
+ foreach ($item->category as $c) {
183
+ $att = $c->attributes();
184
+ if (isset($att['nicename']))
185
+ $post['terms'][] = array(
186
+ 'name' => (string)$c,
187
+ 'slug' => (string)$att['nicename'],
188
+ 'domain' => (string)$att['domain']
189
+ );
190
+ }
191
+
192
+ foreach ($wp->postmeta as $meta) {
193
+ $post['postmeta'][] = array(
194
+ 'key' => (string)$meta->meta_key,
195
+ 'value' => (string)$meta->meta_value
196
+ );
197
+ }
198
+
199
+ foreach ($wp->timeslot as $time) {
200
+ $post['timeslot'][] = array(
201
+ 'column' => (string)$time->column,
202
+ 'event' => (string)$time->event,
203
+ 'event_start' => (string)$time->event_start,
204
+ 'event_end' => (string)$time->event_end,
205
+ 'user_id' => (string)$time->user_id,
206
+ 'description' => (string)$time->description,
207
+ );
208
+ }
209
+
210
+
211
+ foreach ($wp->comment as $comment) {
212
+ $meta = array();
213
+ if (isset($comment->commentmeta)) {
214
+ foreach ($comment->commentmeta as $m) {
215
+ $meta[] = array(
216
+ 'key' => (string)$m->meta_key,
217
+ 'value' => (string)$m->meta_value
218
+ );
219
+ }
220
+ }
221
+
222
+ $post['comments'][] = array(
223
+ 'comment_id' => (int)$comment->comment_id,
224
+ 'comment_author' => (string)$comment->comment_author,
225
+ 'comment_author_email' => (string)$comment->comment_author_email,
226
+ 'comment_author_IP' => (string)$comment->comment_author_IP,
227
+ 'comment_author_url' => (string)$comment->comment_author_url,
228
+ 'comment_date' => (string)$comment->comment_date,
229
+ 'comment_date_gmt' => (string)$comment->comment_date_gmt,
230
+ 'comment_content' => (string)$comment->comment_content,
231
+ 'comment_approved' => (string)$comment->comment_approved,
232
+ 'comment_type' => (string)$comment->comment_type,
233
+ 'comment_parent' => (string)$comment->comment_parent,
234
+ 'comment_user_id' => (int)$comment->comment_user_id,
235
+ 'commentmeta' => $meta,
236
+ );
237
+ }
238
+
239
+ $posts[] = $post;
240
+ }
241
+ // grab time_slots
242
+ foreach ($xml->channel->timeslot as $time) {
243
+ $time_slots[] = array(
244
+ 'column' => (int)$time->column,
245
+ 'event' => (int)$time->event,
246
+ 'event_start' => (string)$time->event_start,
247
+ 'event_end' => (string)$time->event_end,
248
+ 'user_id' => (int)$time->user_id,
249
+ 'description' => (string)$time->description,
250
+ );
251
+ }
252
+ return array(
253
+ 'authors' => $authors,
254
+ 'posts' => $posts,
255
+ 'categories' => $categories,
256
+ 'tags' => $tags,
257
+ 'terms' => $terms,
258
+ 'time_slots' => $time_slots,
259
+ 'base_url' => $base_url,
260
+ 'version' => $wxr_version
261
+ );
262
+ }
263
+ }
264
+
265
+ /**
266
+ * WXR Parser that makes use of the XML Parser PHP extension.
267
+ */
268
+ class WXR_Parser_XML {
269
+ var $wp_tags = array(
270
+ 'wp:post_id', 'wp:post_date', 'wp:post_date_gmt', 'wp:comment_status', 'wp:ping_status', 'wp:attachment_url',
271
+ 'wp:status', 'wp:post_name', 'wp:post_parent', 'wp:menu_order', 'wp:post_type', 'wp:post_password',
272
+ 'wp:is_sticky', 'wp:term_id', 'wp:category_nicename', 'wp:category_parent', 'wp:cat_name', 'wp:category_description',
273
+ 'wp:tag_slug', 'wp:tag_name', 'wp:tag_description', 'wp:term_taxonomy', 'wp:term_parent',
274
+ 'wp:term_name', 'wp:term_description', 'wp:author_id', 'wp:author_login', 'wp:author_email', 'wp:author_display_name',
275
+ 'wp:author_first_name', 'wp:author_last_name',
276
+ );
277
+ var $wp_sub_tags = array(
278
+ 'wp:comment_id', 'wp:comment_author', 'wp:comment_author_email', 'wp:comment_author_url',
279
+ 'wp:comment_author_IP', 'wp:comment_date', 'wp:comment_date_gmt', 'wp:comment_content',
280
+ 'wp:comment_approved', 'wp:comment_type', 'wp:comment_parent', 'wp:comment_user_id',
281
+ );
282
+
283
+ function parse($file) {
284
+ $this->wxr_version = $this->in_post = $this->cdata = $this->data = $this->sub_data = $this->in_tag = $this->in_sub_tag = false;
285
+ $this->authors = $this->posts = $this->term = $this->category = $this->tag = $this->time_slots = array();
286
+
287
+ $xml = xml_parser_create('UTF-8');
288
+ xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
289
+ xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
290
+ xml_set_object($xml, $this);
291
+ xml_set_character_data_handler($xml, 'cdata');
292
+ xml_set_element_handler($xml, 'tag_open', 'tag_close');
293
+
294
+ if (!xml_parse($xml, file_get_contents($file), true)) {
295
+ $current_line = xml_get_current_line_number($xml);
296
+ $current_column = xml_get_current_column_number($xml);
297
+ $error_code = xml_get_error_code($xml);
298
+ $error_string = xml_error_string($error_code);
299
+ return new \WP_Error('XML_parse_error', 'There was an error when reading this WXR file', array($current_line, $current_column, $error_string));
300
+ }
301
+ xml_parser_free($xml);
302
+
303
+ if (!preg_match('/^\d+\.\d+$/', $this->wxr_version))
304
+ return new \WP_Error('WXR_parse_error', __('This does not appear to be a WXR file, missing/invalid WXR version number', 'mp-timetable'));
305
+
306
+ return array(
307
+ 'authors' => $this->authors,
308
+ 'posts' => $this->posts,
309
+ 'categories' => $this->category,
310
+ 'tags' => $this->tag,
311
+ 'terms' => $this->term,
312
+ 'base_url' => $this->base_url,
313
+ 'version' => $this->wxr_version,
314
+ 'time_slots' => $this->time_slots
315
+ );
316
+ }
317
+
318
+ function tag_open($parse, $tag, $attr) {
319
+ if (in_array($tag, $this->wp_tags)) {
320
+ $this->in_tag = substr($tag, 3);
321
+ return;
322
+ }
323
+
324
+ if (in_array($tag, $this->wp_sub_tags)) {
325
+ $this->in_sub_tag = substr($tag, 3);
326
+ return;
327
+ }
328
+
329
+ switch ($tag) {
330
+ case 'category':
331
+ if (isset($attr['domain'], $attr['nicename'])) {
332
+ $this->sub_data['domain'] = $attr['domain'];
333
+ $this->sub_data['slug'] = $attr['nicename'];
334
+ }
335
+ break;
336
+ case 'item':
337
+ $this->in_post = true;
338
+ case 'title':
339
+ if ($this->in_post) $this->in_tag = 'post_title';
340
+ break;
341
+ case 'timeslot':
342
+ break;
343
+ case 'column':
344
+ $this->in_tag = 'column';
345
+ break;
346
+ case 'event':
347
+ $this->in_tag = 'event';
348
+ break;
349
+ case 'event_start':
350
+ $this->in_tag = 'event_start';
351
+ break;
352
+ case 'event_end':
353
+ $this->in_tag = 'event_end';
354
+ break;
355
+ case 'user_id':
356
+ $this->in_tag = 'user_id';
357
+ break;
358
+ case 'description':
359
+ $this->in_tag = 'description';
360
+ break;
361
+ case 'guid':
362
+ $this->in_tag = 'guid';
363
+ break;
364
+ case 'dc:creator':
365
+ $this->in_tag = 'post_author';
366
+ break;
367
+ case 'content:encoded':
368
+ $this->in_tag = 'post_content';
369
+ break;
370
+ case 'excerpt:encoded':
371
+ $this->in_tag = 'post_excerpt';
372
+ break;
373
+ case 'wp:term_slug':
374
+ $this->in_tag = 'slug';
375
+ break;
376
+ case 'wp:meta_key':
377
+ $this->in_sub_tag = 'key';
378
+ break;
379
+ case 'wp:meta_value':
380
+ $this->in_sub_tag = 'value';
381
+ break;
382
+ }
383
+ }
384
+
385
+ function cdata($parser, $cdata) {
386
+ if (!trim($cdata))
387
+ return;
388
+
389
+ $this->cdata .= trim($cdata);
390
+ }
391
+
392
+ function tag_close($parser, $tag) {
393
+ switch ($tag) {
394
+ case 'wp:comment':
395
+ unset($this->sub_data['key'], $this->sub_data['value']); // remove meta sub_data
396
+ if (!empty($this->sub_data))
397
+ $this->data['comments'][] = $this->sub_data;
398
+ $this->sub_data = false;
399
+ break;
400
+ case 'wp:commentmeta':
401
+ $this->sub_data['commentmeta'][] = array(
402
+ 'key' => $this->sub_data['key'],
403
+ 'value' => $this->sub_data['value']
404
+ );
405
+ break;
406
+ case 'category':
407
+ if (!empty($this->sub_data)) {
408
+ $this->sub_data['name'] = $this->cdata;
409
+ $this->data['terms'][] = $this->sub_data;
410
+ }
411
+ $this->sub_data = false;
412
+ break;
413
+ case 'wp:postmeta':
414
+ if (!empty($this->sub_data))
415
+ $this->data['postmeta'][] = $this->sub_data;
416
+ $this->sub_data = false;
417
+ break;
418
+ case 'timeslot':
419
+ $this->time_slots[] = $this->data;
420
+ $this->data = false;
421
+ break;
422
+ case 'item':
423
+ $this->posts[] = $this->data;
424
+ $this->data = false;
425
+ break;
426
+ case 'wp:category':
427
+ case 'wp:tag':
428
+ case 'wp:term':
429
+ $n = substr($tag, 3);
430
+ array_push($this->$n, $this->data);
431
+ $this->data = false;
432
+ break;
433
+ case 'wp:author':
434
+ if (!empty($this->data['author_login']))
435
+ $this->authors[$this->data['author_login']] = $this->data;
436
+ $this->data = false;
437
+ break;
438
+ case 'wp:base_site_url':
439
+ $this->base_url = $this->cdata;
440
+ break;
441
+ case 'wp:wxr_version':
442
+ $this->wxr_version = $this->cdata;
443
+ break;
444
+
445
+ default:
446
+ if ($this->in_sub_tag) {
447
+ $this->sub_data[$this->in_sub_tag] = !empty($this->cdata) ? $this->cdata : '';
448
+ $this->in_sub_tag = false;
449
+ } else if ($this->in_tag) {
450
+ $this->data[$this->in_tag] = !empty($this->cdata) ? $this->cdata : '';
451
+ $this->in_tag = false;
452
+ }
453
+ }
454
+
455
+ $this->cdata = false;
456
+ }
457
+ }
458
+
459
+ /**
460
+ * WXR Parser that uses regular expressions. Fallback for installs without an XML parser.
461
+ */
462
+ class WXR_Parser_Regex {
463
+ var $authors = array();
464
+ var $posts = array();
465
+ var $categories = array();
466
+ var $tags = array();
467
+ var $terms = array();
468
+ var $time_slots = array();
469
+ var $base_url = '';
470
+
471
+ function __construct() {
472
+ $this->has_gzip = is_callable('gzopen');
473
+ }
474
+
475
+ function parse($file) {
476
+ $wxr_version = $in_post = $in_tag = false;
477
+ $post = $tag = '';
478
+ $fp = $this->fopen($file, 'r');
479
+ if ($fp) {
480
+ while (!$this->feof($fp)) {
481
+ $importline = rtrim($this->fgets($fp));
482
+
483
+ if (!$wxr_version && preg_match('|<wp:wxr_version>(\d+\.\d+)</wp:wxr_version>|', $importline, $version))
484
+ $wxr_version = $version[1];
485
+
486
+ if (false !== strpos($importline, '<wp:base_site_url>')) {
487
+ preg_match('|<wp:base_site_url>(.*?)</wp:base_site_url>|is', $importline, $url);
488
+ $this->base_url = $url[1];
489
+ continue;
490
+ }
491
+ if (false !== strpos($importline, '<wp:category>')) {
492
+ preg_match('|<wp:category>(.*?)</wp:category>|is', $importline, $category);
493
+ $this->categories[] = $this->process_category($category[1]);
494
+ continue;
495
+ }
496
+ if (false !== strpos($importline, '<wp:tag>')) {
497
+ preg_match('|<wp:tag>(.*?)</wp:tag>|is', $importline, $tag);
498
+ $this->tags[] = $this->process_tag($tag[1]);
499
+ continue;
500
+ }
501
+ if (false !== strpos($importline, '<wp:term>')) {
502
+ preg_match('|<wp:term>(.*?)</wp:term>|is', $importline, $term);
503
+ if (!empty($term)) {
504
+ $this->terms[] = $this->process_term($term[1]);
505
+ } else {
506
+ $in_tag = true;
507
+ }
508
+ continue;
509
+ }
510
+
511
+ if (false !== strpos($importline, '</wp:term>')) {
512
+ $tag .= $importline . "\n";
513
+ $this->terms[] = $this->process_term($tag);
514
+ $tag = '';
515
+ $in_tag = false;
516
+ continue;
517
+ }
518
+
519
+ if (false !== strpos($importline, '<timeslot>')) {
520
+ preg_match('|<timeslot>(.*?)</timeslot>|is', $importline, $time_slot);
521
+ if (!empty($time_slot)) {
522
+ $this->time_slots[] = $this->process_time_slot($time_slot[1]);
523
+ } else {
524
+ $in_tag = true;
525
+ }
526
+ continue;
527
+ }
528
+ if (false !== strpos($importline, '</timeslot>')) {
529
+ $tag .= $importline . "\n";
530
+ $this->time_slots[] = $this->process_time_slot($tag);
531
+ $tag = '';
532
+ $in_tag = false;
533
+ continue;
534
+ }
535
+
536
+
537
+ if (false !== strpos($importline, '<wp:author>')) {
538
+ preg_match('|<wp:author>(.*?)</wp:author>|is', $importline, $author);
539
+ $a = $this->process_author($author[1]);
540
+ $this->authors[$a['author_login']] = $a;
541
+ continue;
542
+ }
543
+ if (false !== strpos($importline, '<item>')) {
544
+ $in_post = true;
545
+ continue;
546
+ }
547
+ if (false !== strpos($importline, '</item>')) {
548
+ $in_post = false;
549
+ $this->posts[] = $this->process_post($post);
550
+ continue;
551
+ }
552
+ if ($in_post) {
553
+ $post .= $importline . "\n";
554
+ }
555
+
556
+ if ($in_tag) {
557
+ $tag .= $importline . "\n";
558
+ }
559
+ }
560
+
561
+ $this->fclose($fp);
562
+ }
563
+
564
+ if (!$wxr_version)
565
+ return new \WP_Error('WXR_parse_error', __('This does not appear to be a WXR file, missing/invalid WXR version number', 'mp-timetable'));
566
+
567
+ return array(
568
+ 'authors' => $this->authors,
569
+ 'posts' => $this->posts,
570
+ 'categories' => $this->categories,
571
+ 'tags' => $this->tags,
572
+ 'terms' => $this->terms,
573
+ 'base_url' => $this->base_url,
574
+ 'version' => $wxr_version,
575
+ 'time_slots' => $this->time_slots
576
+ );
577
+ }
578
+
579
+ function get_tag($string, $tag) {
580
+ preg_match("|<$tag.*?>(.*?)</$tag>|is", $string, $return);
581
+ if (isset($return[1])) {
582
+ if (substr($return[1], 0, 9) == '<![CDATA[') {
583
+ if (strpos($return[1], ']]]]><![CDATA[>') !== false) {
584
+ preg_match_all('|<!\[CDATA\[(.*?)\]\]>|s', $return[1], $matches);
585
+ $return = '';
586
+ foreach ($matches[1] as $match)
587
+ $return .= $match;
588
+ } else {
589
+ $return = preg_replace('|^<!\[CDATA\[(.*)\]\]>$|s', '$1', $return[1]);
590
+ }
591
+ } else {
592
+ $return = $return[1];
593
+ }
594
+ } else {
595
+ $return = '';
596
+ }
597
+ return $return;
598
+ }
599
+
600
+ function process_category($c) {
601
+ return array(
602
+ 'term_id' => $this->get_tag($c, 'wp:term_id'),
603
+ 'cat_name' => $this->get_tag($c, 'wp:cat_name'),
604
+ 'category_nicename' => $this->get_tag($c, 'wp:category_nicename'),
605
+ 'category_parent' => $this->get_tag($c, 'wp:category_parent'),
606
+ 'category_description' => $this->get_tag($c, 'wp:category_description'),
607
+ );
608
+ }
609
+
610
+ function process_tag($t) {
611
+ return array(
612
+ 'term_id' => $this->get_tag($t, 'wp:term_id'),
613
+ 'tag_name' => $this->get_tag($t, 'wp:tag_name'),
614
+ 'tag_slug' => $this->get_tag($t, 'wp:tag_slug'),
615
+ 'tag_description' => $this->get_tag($t, 'wp:tag_description'),
616
+ );
617
+ }
618
+
619
+ function process_term($t) {
620
+ return array(
621
+ 'term_id' => $this->get_tag($t, 'wp:term_id'),
622
+ 'term_taxonomy' => $this->get_tag($t, 'wp:term_taxonomy'),
623
+ 'slug' => $this->get_tag($t, 'wp:term_slug'),
624
+ 'term_parent' => $this->get_tag($t, 'wp:term_parent'),
625
+ 'term_name' => $this->get_tag($t, 'wp:term_name'),
626
+ 'term_description' => $this->get_tag($t, 'wp:term_description'),
627
+ );
628
+ }
629
+
630
+ function process_time_slot($t) {
631
+ return array(
632
+ 'column' => $this->get_tag($t, 'column'),
633
+ 'event' => $this->get_tag($t, 'event'),
634
+ 'event_start' => $this->get_tag($t, 'event_start'),
635
+ 'event_end' => $this->get_tag($t, 'event_end'),
636
+ 'user_id' => $this->get_tag($t, 'user_id'),
637
+ 'description' => $this->get_tag($t, 'description'),
638
+ );
639
+ }
640
+
641
+ function process_author($a) {
642
+ return array(
643
+ 'author_id' => $this->get_tag($a, 'wp:author_id'),
644
+ 'author_login' => $this->get_tag($a, 'wp:author_login'),
645
+ 'author_email' => $this->get_tag($a, 'wp:author_email'),
646
+ 'author_display_name' => $this->get_tag($a, 'wp:author_display_name'),
647
+ 'author_first_name' => $this->get_tag($a, 'wp:author_first_name'),
648
+ 'author_last_name' => $this->get_tag($a, 'wp:author_last_name'),
649
+ );
650
+ }
651
+
652
+ function process_post($post) {
653
+ $post_id = $this->get_tag($post, 'wp:post_id');
654
+ $post_title = $this->get_tag($post, 'title');
655
+ $post_date = $this->get_tag($post, 'wp:post_date');
656
+ $post_date_gmt = $this->get_tag($post, 'wp:post_date_gmt');
657
+ $comment_status = $this->get_tag($post, 'wp:comment_status');
658
+ $ping_status = $this->get_tag($post, 'wp:ping_status');
659
+ $status = $this->get_tag($post, 'wp:status');
660
+ $post_name = $this->get_tag($post, 'wp:post_name');
661
+ $post_parent = $this->get_tag($post, 'wp:post_parent');
662
+ $menu_order = $this->get_tag($post, 'wp:menu_order');
663
+ $post_type = $this->get_tag($post, 'wp:post_type');
664
+ $post_password = $this->get_tag($post, 'wp:post_password');
665
+ $is_sticky = $this->get_tag($post, 'wp:is_sticky');
666
+ $guid = $this->get_tag($post, 'guid');
667
+ $post_author = $this->get_tag($post, 'dc:creator');
668
+
669
+ $post_excerpt = $this->get_tag($post, 'excerpt:encoded');
670
+ $post_excerpt = preg_replace_callback('|<(/?[A-Z]+)|', array(&$this, '_normalize_tag'), $post_excerpt);
671
+ $post_excerpt = str_replace('<br>', '<br />', $post_excerpt);
672
+ $post_excerpt = str_replace('<hr>', '<hr />', $post_excerpt);
673
+
674
+ $post_content = $this->get_tag($post, 'content:encoded');
675
+ $post_content = preg_replace_callback('|<(/?[A-Z]+)|', array(&$this, '_normalize_tag'), $post_content);
676
+ $post_content = str_replace('<br>', '<br />', $post_content);
677
+ $post_content = str_replace('<hr>', '<hr />', $post_content);
678
+
679
+ $postdata = compact('post_id', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_excerpt',
680
+ 'post_title', 'status', 'post_name', 'comment_status', 'ping_status', 'guid', 'post_parent',
681
+ 'menu_order', 'post_type', 'post_password', 'is_sticky'
682
+ );
683
+
684
+ $attachment_url = $this->get_tag($post, 'wp:attachment_url');
685
+ if ($attachment_url)
686
+ $postdata['attachment_url'] = $attachment_url;
687
+
688
+ preg_match_all('|<category domain="([^"]+?)" nicename="([^"]+?)">(.+?)</category>|is', $post, $terms, PREG_SET_ORDER);
689
+ foreach ($terms as $t) {
690
+ $post_terms[] = array(
691
+ 'slug' => $t[2],
692
+ 'domain' => $t[1],
693
+ 'name' => str_replace(array('<![CDATA[', ']]>'), '', $t[3]),
694
+ );
695
+ }
696
+ if (!empty($post_terms)) $postdata['terms'] = $post_terms;
697
+
698
+ preg_match_all('|<wp:comment>(.+?)</wp:comment>|is', $post, $comments);
699
+ $comments = $comments[1];
700
+ if ($comments) {
701
+ foreach ($comments as $comment) {
702
+ preg_match_all('|<wp:commentmeta>(.+?)</wp:commentmeta>|is', $comment, $commentmeta);
703
+ $commentmeta = $commentmeta[1];
704
+ $c_meta = array();
705
+ foreach ($commentmeta as $m) {
706
+ $c_meta[] = array(
707
+ 'key' => $this->get_tag($m, 'wp:meta_key'),
708
+ 'value' => $this->get_tag($m, 'wp:meta_value'),
709
+ );
710
+ }
711
+
712
+ $post_comments[] = array(
713
+ 'comment_id' => $this->get_tag($comment, 'wp:comment_id'),
714
+ 'comment_author' => $this->get_tag($comment, 'wp:comment_author'),
715
+ 'comment_author_email' => $this->get_tag($comment, 'wp:comment_author_email'),
716
+ 'comment_author_IP' => $this->get_tag($comment, 'wp:comment_author_IP'),
717
+ 'comment_author_url' => $this->get_tag($comment, 'wp:comment_author_url'),
718
+ 'comment_date' => $this->get_tag($comment, 'wp:comment_date'),
719
+ 'comment_date_gmt' => $this->get_tag($comment, 'wp:comment_date_gmt'),
720
+ 'comment_content' => $this->get_tag($comment, 'wp:comment_content'),
721
+ 'comment_approved' => $this->get_tag($comment, 'wp:comment_approved'),
722
+ 'comment_type' => $this->get_tag($comment, 'wp:comment_type'),
723
+ 'comment_parent' => $this->get_tag($comment, 'wp:comment_parent'),
724
+ 'comment_user_id' => $this->get_tag($comment, 'wp:comment_user_id'),
725
+ 'commentmeta' => $c_meta,
726
+ );
727
+ }
728
+ }
729
+ if (!empty($post_comments)) $postdata['comments'] = $post_comments;
730
+
731
+ preg_match_all('|<wp:postmeta>(.+?)</wp:postmeta>|is', $post, $postmeta);
732
+ $postmeta = $postmeta[1];
733
+ if ($postmeta) {
734
+ foreach ($postmeta as $p) {
735
+ $post_postmeta[] = array(
736
+ 'key' => $this->get_tag($p, 'wp:meta_key'),
737
+ 'value' => $this->get_tag($p, 'wp:meta_value'),
738
+ );
739
+ }
740
+ }
741
+ if (!empty($post_postmeta)) $postdata['postmeta'] = $post_postmeta;
742
+
743
+ preg_match_all('|<wp:timeslot>(.+?)</wp:timeslot>|is', $post, $timeslot);
744
+ $timeslot = $timeslot[1];
745
+ if ($timeslot) {
746
+ foreach ($timeslot as $p) {
747
+ $post_ptimeslot[] = array(
748
+ 'column' => $this->get_tag($p, 'wp:column'),
749
+ 'event' => $this->get_tag($p, 'wp:event'),
750
+ 'event_start' => $this->get_tag($p, 'wp:event_start'),
751
+ 'event_end' => $this->get_tag($p, 'wp:event_end'),
752
+ 'user_id' => $this->get_tag($p, 'wp:user_id'),
753
+ 'description' => $this->get_tag($p, 'wp:description')
754
+ );
755
+ }
756
+ }
757
+ if (!empty($post_timeslot)) $postdata['timeslot'] = $post_timeslot;
758
+
759
+ return $postdata;
760
+ }
761
+
762
+ function _normalize_tag($matches) {
763
+ return '<' . strtolower($matches[1]);
764
+ }
765
+
766
+ function fopen($filename, $mode = 'r') {
767
+ if ($this->has_gzip)
768
+ return gzopen($filename, $mode);
769
+ return fopen($filename, $mode);
770
+ }
771
+
772
+ function feof($fp) {
773
+ if ($this->has_gzip)
774
+ return gzeof($fp);
775
+ return feof($fp);
776
+ }
777
+
778
+ function fgets($fp, $len = 8192) {
779
+ if ($this->has_gzip)
780
+ return gzgets($fp, $len);
781
+ return fgets($fp, $len);
782
+ }
783
+
784
+ function fclose($fp) {
785
+ if ($this->has_gzip)
786
+ return gzclose($fp);
787
+ return fclose($fp);
788
+ }
789
+ }
classes/models/class-column.php CHANGED
@@ -1,221 +1,221 @@
1
- <?php
2
-
3
- namespace mp_timetable\classes\models;
4
-
5
- use mp_timetable\plugin_core\classes\Model as Model;
6
-
7
- /**
8
- * Model Events
9
- */
10
- class Column extends Model {
11
-
12
- protected static $instance;
13
- protected $wpdb;
14
-
15
- /**
16
- * Column constructor.
17
- */
18
- public function __construct() {
19
- parent::__construct();
20
- global $wpdb;
21
- $this->wpdb = $wpdb;
22
- }
23
-
24
- /**
25
- * @return Column
26
- */
27
- public static function get_instance() {
28
- if (null === self::$instance) {
29
- self::$instance = new self();
30
- }
31
- return self::$instance;
32
- }
33
-
34
- /**
35
- * Add column
36
- *
37
- * @param $columns
38
- *
39
- * @return array
40
- */
41
- public function set_column_columns($columns) {
42
- $columns = array_slice($columns, 0, 2, true) + array("mp-column_timeslots_number" => __('Timeslots', 'mp-timetable')) + array_slice($columns, 2, count($columns) - 1, true);
43
-
44
- return $columns;
45
- }
46
-
47
- /**
48
- * Create event category admin link
49
- *
50
- * @param $column
51
- */
52
- public function get_column_columns($column) {
53
-
54
- global $post;
55
-
56
- switch ($column) {
57
- case 'mp-column_timeslots_number':
58
- $metaData = $this->count_events($post);
59
- echo empty($metaData) ? "—" : esc_html( $metaData ); // int
60
- break;
61
- }
62
- }
63
-
64
- /**
65
- * Count events
66
- *
67
- * @param $post
68
- *
69
- * @return int
70
- */
71
- public function count_events($post) {
72
-
73
- $table_name = $this->get('events')->table_name;
74
- $event_ids = $this->wpdb->get_results("SELECT `event_id` FROM {$table_name} WHERE `column_id` = {$post->ID}", ARRAY_A);
75
-
76
- $count = 0;
77
- if ( !empty( $event_ids ) ) {
78
- foreach( $event_ids as $event ) {
79
- $event_id = $event['event_id'];
80
- if ( get_post_type( $event_id ) == 'mp-event' ) {
81
- $count++;
82
- }
83
- }
84
- }
85
-
86
- return intval($count);
87
- }
88
-
89
- /**
90
- * Client area order
91
- *
92
- * @param object $query
93
- *
94
- * @return mixed
95
- */
96
- public function clientarea_default_order($query) {
97
- if (is_admin() || $query->is_main_query()) {
98
- if ($query->get('post_type') === 'mp-column') {
99
- $query->set('orderby', 'menu_order');
100
- $query->set('order', 'ASC');
101
- }
102
- }
103
-
104
- return $query;
105
- }
106
-
107
- /**
108
- * @param array $params
109
- *
110
- * @return array
111
- */
112
- public function get_all_column($params = array()) {
113
- $args = array(
114
- 'post_type' => 'mp-column',
115
- 'post_status' => 'publish',
116
- 'order' => 'ASC',
117
- 'orderby' => 'menu_order date',
118
- 'posts_per_page' => -1,
119
- 'post__in' => ''
120
- );
121
-
122
- $args = array_merge($args, $params);
123
- return get_posts($args);
124
- }
125
-
126
- /**
127
- * Columns by event category
128
- *
129
- * @param $terms
130
- *
131
- * @return array
132
- */
133
- public function get_columns_by_event_category($terms) {
134
- $columns = array();
135
- if (!is_array($terms)) {
136
- $terms = explode(',', $terms);
137
- }
138
- $posts_array = get_posts(
139
- array(
140
- 'fields' => 'ids',
141
- 'posts_per_page' => -1,
142
- 'post_type' => 'mp-event',
143
- 'post_status' => 'publish',
144
- 'tax_query' => array(
145
- array(
146
- 'taxonomy' => 'mp-event_category',
147
- 'field' => 'term_id',
148
- 'terms' => $terms,
149
- )
150
- )
151
- )
152
- );
153
- $ids = implode(',', $posts_array);
154
- $event_data = $this->get('events')->get_events_data(array('column' => 'event_id', 'list' => $ids));
155
- if (!empty($event_data)) {
156
- foreach ($event_data as $event) {
157
- if (in_array($event->event_id, $posts_array)) {
158
- $columns[] = $event->column_id;
159
- }
160
- }
161
- }
162
- return array_unique($columns);
163
- }
164
-
165
- /**
166
- * Render column metabox
167
- *
168
- * @param $post
169
- */
170
- public function render_column_options($post) {
171
- $this->get_view()->render_html("column/metabox-column-options", array('post' => $post), true);
172
- }
173
-
174
- /**
175
- * Render meta data
176
- */
177
- public function render_column_metas() {
178
- $this->append_events();
179
- }
180
-
181
- public function append_events() {
182
- global $post;
183
- $data = $this->get('events')->get_event_data(array('field' => 'column_id', 'id' => $post->ID));
184
- $events = (!empty($data)) ? $data : array();
185
-
186
- $this->get_view()->get_template("theme/column-events", array('events' => $events));
187
- }
188
-
189
- /**
190
- * Save meta data Column post type
191
- *
192
- * @param array $params
193
- */
194
- public function save_column_data(array $params) {
195
-
196
- if ( !empty($params['data']) ) {
197
-
198
- foreach ($params['data'] as $meta_key => $meta) {
199
-
200
- if ( !empty($meta) ) {
201
- update_post_meta($params['post']->ID, $meta_key, sanitize_text_field( $meta ) );
202
- } else {
203
- delete_post_meta($params['post']->ID, $meta_key, $meta);
204
- }
205
- }
206
- }
207
- }
208
-
209
- /**
210
- * Delete time-slots of the Column
211
- *
212
- * @param $post_id
213
- *
214
- * @return false|int
215
- */
216
- public function before_delete_column($post_id) {
217
- $table_name = $this->get('events')->table_name;
218
-
219
- return $this->wpdb->delete($table_name, array('column_id' => $post_id), array('%d'));
220
- }
221
  }
1
+ <?php
2
+
3
+ namespace mp_timetable\classes\models;
4
+
5
+ use mp_timetable\plugin_core\classes\Model as Model;
6
+
7
+ /**
8
+ * Model Events
9
+ */
10
+ class Column extends Model {
11
+
12
+ protected static $instance;
13
+ protected $wpdb;
14
+
15
+ /**
16
+ * Column constructor.
17
+ */
18
+ public function __construct() {
19
+ parent::__construct();
20
+ global $wpdb;
21
+ $this->wpdb = $wpdb;
22
+ }
23
+
24
+ /**
25
+ * @return Column
26
+ */
27
+ public static function get_instance() {
28
+ if (null === self::$instance) {
29
+ self::$instance = new self();
30
+ }
31
+ return self::$instance;
32
+ }
33
+
34
+ /**
35
+ * Add column
36
+ *
37
+ * @param $columns
38
+ *
39
+ * @return array
40
+ */
41
+ public function set_column_columns($columns) {
42
+ $columns = array_slice($columns, 0, 2, true) + array("mp-column_timeslots_number" => __('Timeslots', 'mp-timetable')) + array_slice($columns, 2, count($columns) - 1, true);
43
+
44
+ return $columns;
45
+ }
46
+
47
+ /**
48
+ * Create event category admin link
49
+ *
50
+ * @param $column
51
+ */
52
+ public function get_column_columns($column) {
53
+
54
+ global $post;
55
+
56
+ switch ($column) {
57
+ case 'mp-column_timeslots_number':
58
+ $metaData = $this->count_events($post);
59
+ echo empty($metaData) ? "—" : esc_html( $metaData ); // int
60
+ break;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Count events
66
+ *
67
+ * @param $post
68
+ *
69
+ * @return int
70
+ */
71
+ public function count_events($post) {
72
+
73
+ $table_name = $this->get('events')->table_name;
74
+ $event_ids = $this->wpdb->get_results("SELECT `event_id` FROM {$table_name} WHERE `column_id` = {$post->ID}", ARRAY_A);
75
+
76
+ $count = 0;
77
+ if ( !empty( $event_ids ) ) {
78
+ foreach( $event_ids as $event ) {
79
+ $event_id = $event['event_id'];
80
+ if ( get_post_type( $event_id ) == 'mp-event' ) {
81
+ $count++;
82
+ }
83
+ }
84
+ }
85
+
86
+ return intval($count);
87
+ }
88
+
89
+ /**
90
+ * Client area order
91
+ *
92
+ * @param object $query
93
+ *
94
+ * @return mixed
95
+ */
96
+ public function clientarea_default_order($query) {
97
+ if (is_admin() || $query->is_main_query()) {
98
+ if ($query->get('post_type') === 'mp-column') {
99
+ $query->set('orderby', 'menu_order');
100
+ $query->set('order', 'ASC');
101
+ }
102
+ }
103
+
104
+ return $query;
105
+ }
106
+
107
+ /**
108
+ * @param array $params
109
+ *
110
+ * @return array
111
+ */
112
+ public function get_all_column($params = array()) {
113
+ $args = array(
114
+ 'post_type' => 'mp-column',
115
+ 'post_status' => 'publish',
116
+ 'order' => 'ASC',
117
+ 'orderby' => 'menu_order date',
118
+ 'posts_per_page' => -1,
119
+ 'post__in' => ''
120
+ );
121
+
122
+ $args = array_merge($args, $params);
123
+ return get_posts($args);
124
+ }
125
+
126
+ /**
127
+ * Columns by event category
128
+ *
129
+ * @param $terms
130
+ *
131
+ * @return array
132
+ */
133
+ public function get_columns_by_event_category($terms) {
134
+ $columns = array();
135
+ if (!is_array($terms)) {
136
+ $terms = explode(',', $terms);
137
+ }
138
+ $posts_array = get_posts(
139
+ array(
140
+ 'fields' => 'ids',
141
+ 'posts_per_page' => -1,
142
+ 'post_type' => 'mp-event',
143
+ 'post_status' => 'publish',
144
+ 'tax_query' => array(
145
+ array(
146
+ 'taxonomy' => 'mp-event_category',
147
+ 'field' => 'term_id',
148
+ 'terms' => $terms,
149
+ )
150
+ )
151
+ )
152
+ );
153
+ $ids = implode(',', $posts_array);
154
+ $event_data = $this->get('events')->get_events_data(array('column' => 'event_id', 'list' => $ids));
155
+ if (!empty($event_data)) {
156
+ foreach ($event_data as $event) {
157
+ if (in_array($event->event_id, $posts_array)) {
158
+ $columns[] = $event->column_id;
159
+ }
160
+ }
161
+ }
162
+ return array_unique($columns);
163
+ }
164
+
165
+ /**
166
+ * Render column metabox
167
+ *
168
+ * @param $post
169
+ */
170
+ public function render_column_options($post) {
171
+ $this->get_view()->render_html("column/metabox-column-options", array('post' => $post), true);
172
+ }
173
+
174
+ /**
175
+ * Render meta data
176
+ */
177
+ public function render_column_metas() {
178
+ $this->append_events();
179
+ }
180
+
181
+ public function append_events() {
182
+ global $post;
183
+ $data = $this->get('events')->get_event_data(array('field' => 'column_id', 'id' => $post->ID));
184
+ $events = (!empty($data)) ? $data : array();
185
+
186
+ $this->get_view()->get_template("theme/column-events", array('events' => $events));
187
+ }
188
+
189
+ /**
190
+ * Save meta data Column post type
191
+ *
192
+ * @param array $params
193
+ */
194
+ public function save_column_data(array $params) {
195
+
196
+ if ( !empty($params['data']) ) {
197
+
198
+ foreach ($params['data'] as $meta_key => $meta) {
199
+
200
+ if ( !empty($meta) ) {
201
+ update_post_meta($params['post']->ID, $meta_key, sanitize_text_field( $meta ) );
202
+ } else {
203
+ delete_post_meta($params['post']->ID, $meta_key, $meta);
204
+ }
205
+ }
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Delete time-slots of the Column
211
+ *
212
+ * @param $post_id
213
+ *
214
+ * @return false|int
215
+ */
216
+ public function before_delete_column($post_id) {
217
+ $table_name = $this->get('events')->table_name;
218
+
219
+ return $this->wpdb->delete($table_name, array('column_id' => $post_id), array('%d'));
220
+ }
221
  }
classes/models/class-events.php CHANGED
@@ -1,936 +1,936 @@
1
- <?php
2
-
3
- namespace mp_timetable\classes\models;
4
-
5
- use mp_timetable\plugin_core\classes\Model as Model;
6
- use mp_timetable\plugin_core\classes\modules\Taxonomy;
7
-
8
-
9
- /**
10
- * Model Events
11
- */
12
- class Events extends Model {
13
-
14
- protected static $instance;
15
- protected $wpdb;
16
- protected $table_name;
17
- protected $post_type;
18
-
19
- /**
20
- * Events constructor.
21
- */
22
- function __construct() {
23
- parent::__construct();
24
- global $wpdb;
25
- $this->wpdb = $wpdb;
26
- $this->post_type = 'mp-event';
27
- $this->taxonomy_names = array(
28
- 'tag' => 'mp-event_tag',
29
- 'cat' => 'mp-event_category',
30
- );
31
- $this->table_name = $wpdb->prefix . "mp_timetable_data";
32
- }
33
-
34
- /**
35
- * @return Events
36
- */
37
- public static function get_instance() {
38
- if ( null === self::$instance ) {
39
- self::$instance = new self();
40
- }
41
-
42
- return self::$instance;
43
- }
44
-
45
- /**
46
- * Getter
47
- *
48
- * @param $property
49
- *
50
- * @return mixed
51
- */
52
- function __get( $property ) {
53
- return $this->{$property};
54
- }
55
-
56
- /**
57
- * Setter
58
- *
59
- * @param $property
60
- * @param $value
61
- *
62
- * @return mixed
63
- */
64
- function __set( $property, $value ) {
65
- return $this->{$property} = $value;
66
- }
67
-
68
- /**
69
- * Render event metabox
70
- *
71
- * @param $post
72
- * @param $metabox
73
- */
74
- public function render_event_data( $post, $metabox ) {
75
-
76
- $time_format = get_option( 'time_format' );
77
- if ( $time_format === 'H:i' ) {
78
- $time_format_array = array( 'hours' => '0,23', 'am_pm' => false );
79
- } elseif ( $time_format === 'g:i A' ) {
80
- $time_format_array = array( 'hours' => '1,12', 'am_pm' => true );
81
- } else {
82
- $time_format_array = array( 'hours' => '0,23', 'am_pm' => false );
83
- }
84
-
85
- $data[ 'columns' ] = $this->get( 'column' )->get_all_column();
86
- $event_data = $this->get_event_data( array( 'field' => 'event_id', 'id' => $post->ID ), 'event_start', false );
87
-
88
- $this->get_view()->render_html( "events/metabox-event-data", array( 'event_data' => $event_data, 'args' => $metabox[ 'args' ],
89
- 'columns' => $data[ 'columns' ], 'date' => array( 'time_format' => $time_format_array ) ), true );
90
- }
91
-
92
- /**
93
- *
94
- * Get single event data by id
95
- *
96
- * @param $params
97
- * @param string $order_by
98
- * @param bool $publish
99
- *
100
- * @return array|null|object
101
- */
102
- public function get_event_data( $params, $order_by = 'event_start', $publish = true ) {
103
- $publish_query_part = $publish ? " AND `post_status` = 'publish'" : '';
104
- $table_posts = $this->wpdb->prefix . 'posts';
105
-
106
- $event_data = $this->wpdb->get_results(
107
- "SELECT t.*"
108
- . " FROM $this->table_name t INNER JOIN"
109
- . " ("
110
- . " SELECT * FROM {$table_posts}"
111
- . " WHERE `post_type` = 'mp-column' AND `post_status` = 'publish'"
112
- . " ) p ON t.`column_id` = p.`ID`"
113
- . " INNER JOIN ("
114
- . " SELECT * FROM {$table_posts}"
115
- . " WHERE `post_type` = '{$this->post_type}'{$publish_query_part}"
116
- . " ) e ON t.`event_id` = e.`ID`"
117
- . " WHERE t.`{$params["field"]}` = {$params['id']} "
118
- . " ORDER BY p.`menu_order`, t.`{$order_by}`"
119
- );
120
-
121
- foreach ( $event_data as $key => $event ) {
122
-
123
- $user = false;
124
- $wpUser = get_user_by( 'id', $event_data[ $key ]->user_id );
125
-
126
- if ( ! empty( $wpUser ) ) {
127
- $user = new \stdClass();
128
- $user->ID = $wpUser->ID;
129
- $user->display_name = $wpUser->data->display_name;
130
- }
131
-
132
- $event_data[ $key ]->event_start = date( 'H:i', strtotime( $event_data[ $key ]->event_start ) );
133
- $event_data[ $key ]->event_end = date( 'H:i', strtotime( $event_data[ $key ]->event_end ) );
134
- $event_data[ $key ]->user = $user;
135
- $event_data[ $key ]->post = get_post( $event_data[ $key ]->event_id );
136
- $event_data[ $key ]->description = stripcslashes( $event_data[ $key ]->description );
137
- }
138
-
139
- return $event_data;
140
- }
141
-
142
- /**
143
- * Render meta data
144
- */
145
- public function render_event_metas() {
146
- $this->append_time_slots();
147
- }
148
-
149
- /**
150
- * Render Timeslots by $post
151
- */
152
- public function append_time_slots() {
153
- global $post;
154
-
155
- $show_public_only = ( ( get_post_status( $post->ID ) == 'draft' ) && is_preview() ) ? false : true;
156
-
157
- $data = $this->get_event_data( array( 'field' => 'event_id', 'id' => $post->ID ), 'event_start', $show_public_only );
158
- $event_data = ( ! empty( $data ) ) ? $data : array();
159
- $count = count( $event_data );
160
-
161
- $this->get_view()->get_template( "theme/event-timeslots", array( 'events' => $event_data, 'count' => $count ) );
162
- }
163
-
164
- /**
165
- * Render event options
166
- *
167
- * @param $post
168
- */
169
- public function render_event_options( $post ) {
170
- $this->get_view()->render_html( "events/metabox-event-options", array( 'post' => $post ), true );
171
- }
172
-
173
- /**
174
- * Add column
175
- *
176
- * @param $columns
177
- *
178
- * @return array
179
- */
180
- public function set_event_columns( $columns ) {
181
- $columns = array_slice( $columns, 0, 2, true ) + array( $this->taxonomy_names[ 'tag' ] => __( 'Tags', 'mp-timetable' ) ) + array_slice( $columns, 2, count( $columns ) - 1, true );
182
- $columns = array_slice( $columns, 0, 2, true ) + array( $this->taxonomy_names[ 'cat' ] => __( 'Categories', 'mp-timetable' ) ) + array_slice( $columns, 2, count( $columns ) - 1, true );
183
-
184
- return $columns;
185
- }
186
-
187
- /**
188
- * Create event category admin link
189
- *
190
- * @param $column
191
- */
192
- public function get_event_taxonomy( $column ) {
193
- global $post;
194
- if ( $column === $this->taxonomy_names[ 'cat' ] ) {
195
- echo Taxonomy::get_instance()->get_the_term_filter_list( $post, $this->taxonomy_names[ 'cat' ] );
196
- }
197
- if ( $column === $this->taxonomy_names[ 'tag' ] ) {
198
- echo Taxonomy::get_instance()->get_the_term_filter_list( $post, $this->taxonomy_names[ 'tag' ] );
199
- }
200
- }
201
-
202
- /**
203
- * Output category post
204
- *
205
- * @param string $the_list
206
- * @param string $separator
207
- * @param string $parents
208
- *
209
- * @return mixed
210
- */
211
- public function the_category( $the_list = '', $separator = '', $parents = '' ) {
212
- global $post;
213
-
214
- if ( $post && $post->post_type === $this->post_type && ! is_admin() ) {
215
- $categories = wp_get_post_terms( $post->ID, $this->taxonomy_names[ 'cat' ] );
216
- $the_list .= $this->generate_event_tags( $categories, $separator, $parents );
217
- }
218
-
219
- /**
220
- * Filter the category or list of Timetable categories.
221
- *
222
- * @param array $thelist List of categories for the current post.
223
- * @param string $separator Separator used between the categories.
224
- * @param string $parents How to display the category parents. Accepts 'multiple',
225
- * 'single', or empty.
226
- */
227
- return apply_filters( 'mptt_the_category', $the_list, $separator, $parents );
228
- }
229
-
230
- /**
231
- * Generate HTML of the post tags
232
- *
233
- * @param $categories
234
- * @param $separator
235
- * @param $parents
236
- *
237
- * @return string
238
- */
239
- public function generate_event_tags( $categories, $separator, $parents ) {
240
- global $wp_rewrite;
241
- $the_list = '';
242
- $rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? 'rel="category tag"' : 'rel="category"';
243
-
244
- if ( '' == $separator ) {
245
- $the_list .= '<ul class="post-categories">';
246
- foreach ( $categories as $category ) {
247
- $the_list .= "\n\t<li>";
248
- switch ( strtolower( $parents ) ) {
249
- case 'multiple':
250
- if ( $category->parent ) {
251
- $the_list .= get_category_parents( $category->parent, true, $separator );
252
- }
253
- $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name . '</a></li>';
254
- break;
255
- case 'single':
256
- $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>';
257
- if ( $category->parent ) {
258
- $the_list .= get_category_parents( $category->parent, false, $separator );
259
- }
260
- $the_list .= $category->name . '</a></li>';
261
- break;
262
- case '':
263
- default:
264
- $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name . '</a></li>';
265
- }
266
- }
267
- $the_list .= '</ul>';
268
- } else {
269
- $i = 0;
270
- foreach ( $categories as $category ) {
271
- if ( 0 < $i ) {
272
- $the_list .= $separator;
273
- }
274
- switch ( strtolower( $parents ) ) {
275
- case 'multiple':
276
- if ( $category->parent ) {
277
- $the_list .= get_category_parents( $category->parent, true, $separator );
278
- }
279
- $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name . '</a>';
280
- break;
281
- case 'single':
282
- $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>';
283
- if ( $category->parent ) {
284
- $the_list .= get_category_parents( $category->parent, false, $separator );
285
- }
286
- $the_list .= "$category->name</a>";
287
- break;
288
- case '':
289
- default:
290
- $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name . '</a>';
291
- }
292
- ++ $i;
293
- }
294
- }
295
-
296
- return $the_list;
297
- }
298
-
299
- /**
300
- * Returns a formatted tags.
301
- *
302
- * @param $tags
303
- * @param string $before
304
- * @param string $sep
305
- * @param string $after
306
- * @param int $id
307
- *
308
- * @return mixed
309
- */
310
- public function the_tags( $tags, $before = '', $sep = '', $after = '', $id = 0 ) {
311
- global $post;
312
-
313
- if ( $post && $post->post_type === $this->post_type ) {
314
- $id = ( $id === 0 ) ? $post->id : $id;
315
- $events_tags = get_the_term_list( $id, $this->taxonomy_names[ 'tag' ], $before, $sep, $after );
316
- $tags = apply_filters( 'mptt_the_tags', $events_tags, $tags );
317
- }
318
-
319
- return $tags;
320
- }
321
-
322
- /**
323
- * Save(insert) event data
324
- *
325
- * @param array $params
326
- *
327
- * @return array
328
- */
329
- public function save_event_data( array $params ) {
330
-
331
- $rows_affected = array();
332
-
333
- if ( ! empty( $params[ 'event_data' ] ) ) {
334
- foreach ( $params[ 'event_data' ] as $key => $event ) {
335
- if ( is_array( $event[ 'event_start' ] ) && ! empty( $event[ 'event_start' ] ) ) {
336
-
337
- for ( $i = 0; $i < count( $event[ 'event_start' ] ); $i ++ ) {
338
- $rows_affected[] = $this->wpdb->insert( $this->table_name, array(
339
- 'column_id' => absint( $key ),
340
- 'event_id' => absint( $params[ 'post' ]->ID ),
341
- 'event_start' => date( 'H:i', strtotime( sanitize_text_field( $event[ 'event_start' ][ $i ] ) ) ),
342
- 'event_end' => date( 'H:i', strtotime( sanitize_text_field( $event[ 'event_end' ][ $i ] ) ) ),
343
- 'user_id' => absint( $event[ 'user_id' ][ $i ] ),
344
- 'description' => wp_kses_post( $event[ 'description' ][ $i ] )
345
- )
346
- );
347
- }
348
- }
349
- }
350
- }
351
-
352
- if ( ! empty( $params[ 'event_meta' ] ) ) {
353
- foreach ( $params[ 'event_meta' ] as $meta_key => $meta ) {
354
- switch ( $meta_key ) {
355
- case 'timetable_custom_url':
356
- update_post_meta( $params[ 'post' ]->ID, $meta_key, esc_url_raw( $meta ) );
357
- break;
358
- default:
359
- update_post_meta( $params[ 'post' ]->ID, $meta_key, wp_kses_post( $meta ) );
360
- }
361
- }
362
- }
363
-
364
- return $rows_affected;
365
- }
366
-
367
- /**
368
- * Delete event timeslot
369
- *
370
- * @param $id
371
- *
372
- * @return false|int
373
- */
374
- public function delete_event( $id ) {
375
- return $this->wpdb->delete( $this->table_name, array( 'id' => $id ), array( '%d' ) );
376
- }
377
-
378
- /**
379
- * Delete event data
380
- *
381
- * @param $post_id
382
- *
383
- * @return false|int
384
- */
385
- public function before_delete_event( $post_id ) {
386
- $meta_keys = array( 'event_id', 'event_start', 'event_end', 'user_id', 'description' );
387
-
388
- foreach ( $meta_keys as $meta_key ) {
389
- delete_post_meta( $post_id, $meta_key );
390
- }
391
-
392
- return $this->wpdb->delete( $this->table_name, array( 'event_id' => $post_id ), array( '%d' ) );
393
- }
394
-
395
- /**
396
- * Get widget events
397
- *
398
- * @param $instance
399
- *
400
- * @return array
401
- */
402
- public function get_widget_events( $instance ) {
403
- $events = array();
404
- $current_local_time = current_time( 'timestamp' );
405
-
406
- $weekday = strtolower( date( 'l', $current_local_time ) );
407
- $current_date = date( 'd/m/Y', $current_local_time );
408
-
409
- // 24.09.2019 seconds added
410
- $curent_time = date( 'H:i:s', $current_local_time );
411
-
412
- if ( ! empty( $instance[ 'mp_categories' ] ) ) {
413
- $category_columns_ids = $this->get( 'column' )->get_columns_by_event_category( $instance[ 'mp_categories' ] );
414
- }
415
-
416
- $args = array(
417
- 'post_type' => 'mp-column',
418
- 'post_status' => 'publish',
419
- 'fields' => 'ids',
420
- 'post__in' => ! empty( $category_columns_ids ) ? $category_columns_ids : '',
421
- 'orderby' => 'menu_order',
422
- 'meta_query' => array(
423
- 'relation' => 'OR',
424
- array(
425
- 'key' => 'weekday',
426
- 'value' => $weekday
427
- ),
428
- array(
429
- 'key' => 'option_day',
430
- 'value' => $current_date
431
- )
432
- )
433
- );
434
-
435
- switch ( $instance[ 'view_settings' ] ) {
436
- case'today':
437
- case 'current':
438
- $column_post_ids = get_posts( $args );
439
- if ( ! empty( $column_post_ids ) ) {
440
- $events = $this->get_events_data( array( 'column' => 'column_id', 'list' => $column_post_ids ) );
441
- }
442
- $events = $this->filter_events( array( 'events' => $events, 'view_settings' => $instance[ 'view_settings' ], 'time' => $curent_time, 'mp_categories' => $instance[ 'mp_categories' ] ) );
443
- break;
444
- case 'all':
445
-
446
- if ( ! empty( $instance[ 'next_days' ] ) && $instance[ 'next_days' ] > 0 ) {
447
- $events_array = array();
448
- for ( $i = 0; $i <= $instance[ 'next_days' ]; $i ++ ) {
449
-
450
- // set new day week
451
- $time = strtotime( "+$i days", $current_local_time );
452
- $day = strtolower( date( 'l', $time ) );
453
- $date = date( 'd/m/Y', $time );
454
-
455
- //set week day
456
- $args[ 'meta_query' ][ 0 ][ 'value' ] = $day;
457
- //set new date
458
- $args[ 'meta_query' ][ 1 ][ 'value' ] = $date;
459
-
460
- $column_post_ids = get_posts( $args );
461
-
462
- if ( ! empty( $column_post_ids ) ) {
463
- $events_array[ $i ] = $this->get_events_data( array( 'column' => 'column_id', 'list' => $column_post_ids ) );
464
- } else {
465
- $events_array[ $i ] = array();
466
- }
467
-
468
- // Filter by time and categories for current day
469
- if ( $i === 0 && ! empty( $instance[ 'mp_categories' ] ) && ! empty( $events_array[ $i ] ) ) {
470
- $events_array[ $i ] = $events_array[ $i ] = $this->filter_events( array( 'events' => $events_array[ $i ], 'view_settings' => 'today', 'time' => $curent_time, 'mp_categories' => $instance[ 'mp_categories' ] ) );
471
- } elseif ( ! empty( $instance[ 'mp_categories' ] ) && ! empty( $events_array[ $i ] ) ) {
472
- //Filter by categories for next days
473
- $events_array[ $i ] = $this->filter_events_by_categories( $events_array[ $i ], $instance[ 'mp_categories' ] );
474
- }
475
-
476
- }
477
-
478
- foreach ( $events_array as $day_events ) {
479
- $events = array_merge( $events, $day_events );
480
- }
481
-
482
- }
483
-
484
- break;
485
-
486
- default:
487
- $column_post_ids = get_posts( $args );
488
- if ( ! empty( $column_post_ids ) ) {
489
- $events = $this->get_events_data( array( 'column' => 'column_id', 'list' => $column_post_ids ) );
490
- }
491
- $events = $this->filter_events( array( 'events' => $events, 'view_settings' => 'today', 'time' => $curent_time, 'mp_categories' => $instance[ 'mp_categories' ] ) );
492
-
493
- break;
494
- }
495
- if ( $instance[ 'limit' ] > 0 ) {
496
- $events = array_slice( $events, 0, $instance[ 'limit' ] );
497
- }
498
-
499
- return $events;
500
- }
501
-
502
- /**
503
- * Get event data by post
504
- *
505
- * @param array $params
506
- *
507
- * @return array
508
- */
509
- public function get_events_data( array $params ) {
510
- $events = array();
511
- $sql_request = "SELECT * FROM " . $this->table_name;
512
-
513
- if ( ( ! empty( $params[ 'all' ] ) && $params[ 'all' ] ) || empty( $params[ 'list' ] ) ) {
514
-
515
- } elseif ( ! is_array( $params[ 'column' ] ) ) {
516
-
517
- if ( isset( $params[ 'list' ] ) && is_array( $params[ 'list' ] ) ) {
518
- $params[ 'list' ] = implode( ',', $params[ 'list' ] );
519
- }
520
-
521
- $sql_request .= " WHERE " . $params[ 'column' ] . " IN (" . $params[ 'list' ] . ")";
522
-
523
- } elseif ( is_array( $params[ 'column' ] ) && is_array( $params[ 'list' ] ) ) {
524
-
525
- $sql_request .= " WHERE ";
526
-
527
- $last_key = key( array_slice( $params[ 'column' ], - 1, 1, true ) );
528
-
529
- foreach ( $params[ 'column' ] as $key => $column ) {
530
- if ( isset( $params[ 'list' ][ $column ] ) && is_array( $params[ 'list' ][ $column ] ) ) {
531
- $params[ 'list' ][ $column ] = implode( ',', $params[ 'list' ][ $column ] );
532
- }
533
- $sql_request .= $column . " IN (" . $params[ 'list' ][ $column ] . ")";
534
- $sql_request .= ( $last_key != $key ) ? ' AND ' : '';
535
- }
536
-
537
- }
538
-
539
- $sql_request .= ' ORDER BY `event_start`';
540
-
541
- $events_data = $this->wpdb->get_results( $sql_request );
542
-
543
- if ( is_array( $events_data ) ) {
544
-
545
- foreach ( $events_data as $event ) {
546
- $post = get_post( $event->event_id );
547
-
548
- if ( $post && ( $post->post_type == $this->post_type ) && ( $post->post_status == 'publish' ) ) {
549
- $event->post = $post;
550
- $event->event_start = date( 'H:i', strtotime( $event->event_start ) );
551
- $event->event_end = date( 'H:i', strtotime( $event->event_end ) );
552
- $events[] = $event;
553
- }
554
- }
555
- }
556
-
557
- return $events;
558
- }
559
-
560
- /**
561
- * Filtered events by view settings
562
- *
563
- * @param $params
564
- *
565
- * @return array
566
- */
567
- protected function filter_events( $params ) {
568
-
569
- $events = array();
570
- $events = $this->filter_by_time_period( $params, $events );
571
-
572
- if ( ! empty( $params[ 'mp_categories' ] ) ) {
573
- $events = $this->filter_events_by_categories( $events, $params[ 'mp_categories' ] );
574
- }
575
-
576
- return $events;
577
- }
578
-
579
- /**
580
- * Filter by time period
581
- *
582
- * @param $params
583
- * @param $events
584
- *
585
- * @return array
586
- */
587
- protected function filter_by_time_period( $params, $events ) {
588
- if ( ! empty( $params[ 'events' ] ) ) {
589
-
590
- $time = strtotime( $params[ 'time' ] );
591
-
592
- foreach ( $params[ 'events' ] as $key => $event ) {
593
-
594
- $event_end = strtotime( $event->event_end );
595
- $event_start = strtotime( $event->event_start );
596
-
597
- if ( $params[ 'view_settings' ] === 'today' || $params[ 'view_settings' ] === 'all' ) {
598
- if ( $event_end <= $time ) {
599
- continue;
600
- }
601
- } elseif ( $params[ 'view_settings' ] === 'current' ) {
602
- if ( $event_start >= $time || $event_end <= $time ) {
603
- continue;
604
- }
605
- }
606
- $events[ $key ] = $event;
607
- }
608
- }
609
-
610
- return $events;
611
- }
612
-
613
- /**
614
- * Filter find events by select categories;
615
- *
616
- * @param array $events
617
- * @param array $categories
618
- *
619
- * @return array
620
- */
621
- public function filter_events_by_categories( array $events, array $categories ) {
622
- $temp_events = array();
623
- $taxonomy = $this->taxonomy_names[ 'cat' ];
624
-
625
- foreach ( $events as $event ) {
626
- if ( @has_term( $categories, $taxonomy, $event->post->ID ) ) {
627
- $temp_events[] = $event;
628
- }
629
- }
630
-
631
- return $temp_events;
632
- }
633
-
634
- /**
635
- * Sort by params
636
- *
637
- * @param $events
638
- *
639
- * @return mixed
640
- */
641
-
642
- public function sort_by_param( $events ) {
643
-
644
- usort( $events, function ( $a, $b ) {
645
- if ( strtotime( $a->event_start ) == strtotime( $b->event_start ) ) {
646
- return 0;
647
- }
648
-
649
- return ( strtotime( $a->event_start ) < strtotime( $b->event_start ) ) ? - 1 : 1;
650
- } );
651
-
652
-
653
- return $events;
654
- }
655
-
656
- /**
657
- * @param array /string $event_category
658
- *
659
- * @return array|null|object
660
- */
661
- public function get_events_data_by_category( $event_categories ) {
662
- if ( ! is_array( $event_categories ) ) {
663
- $terms = explode( ',', $event_categories );
664
- } else {
665
- $terms = $event_categories;
666
- }
667
-
668
- $posts_array = get_posts(
669
- array(
670
- 'fields' => 'ids',
671
- 'posts_per_page' => - 1,
672
- 'post_type' => $this->post_type,
673
- 'post_status' => 'publish',
674
- 'tax_query' => array(
675
- array(
676
- 'taxonomy' => 'mp-event_category',
677
- 'field' => 'term_id',
678
- 'terms' => $terms,
679
- )
680
- )
681
- )
682
- );
683
-
684
- $ids = implode( ',', $posts_array );
685
- $event_data = $this->get_events_data( array( 'column' => 'event_id', 'list' => $ids ) );
686
-
687
- return $event_data;
688
- }
689
-
690
- /**
691
- * Update event data
692
- *
693
- * @param $data
694
- *
695
- * @return false|int
696
- */
697
- public function update_event_data( $data ) {
698
-
699
- $id = (int) $data[ 'id' ];
700
-
701
- $result = $this->wpdb->update(
702
- $this->table_name,
703
- array(
704
- 'event_start' => date( 'H:i', strtotime( $data[ 'event_start' ] ) ),
705
- 'event_end' => date( 'H:i', strtotime( $data[ 'event_end' ] ) ),
706
- 'description' => wp_kses_post( $data[ 'description' ] ),
707
- 'column_id' => $data[ 'weekday_ids' ],
708
- 'user_id' => $data[ 'user_id' ],
709
- ),
710
- array( 'id' => $id ),
711
- array(
712
- '%s',
713
- '%s',
714
- '%s',
715
- '%d',
716
- '%d',
717
- ),
718
- array( '%d' )
719
- );
720
-
721
- return $result;
722
- }
723
-
724
- /**
725
- * Get all events
726
- * @return array
727
- */
728
- public function get_all_events() {
729
- $args = array(
730
- 'post_type' => $this->post_type,
731
- 'post_status' => 'publish',
732
- 'order' => 'ASC',
733
- 'orderby' => 'title',
734
- 'posts_per_page' => - 1
735
- );
736
-
737
- return get_posts( $args );
738
- }
739
-
740
- /**
741
- * Choose color widget or event
742
- *
743
- * @param $params
744
- *
745
- * @return string
746
- */
747
-
748
- public function choose_event_color( $params ) {
749
- if ( ! empty( $params[ 'widget_color' ] ) ) {
750
- return $params[ 'widget_color' ];
751
- } elseif ( ! empty( $params[ 'event_color' ] ) ) {
752
- return $params[ 'event_color' ];
753
- } else {
754
- return '';
755
- }
756
- }
757
-
758
- /**
759
- * Filtered events by Event Head
760
- *
761
- * @param $params
762
- *
763
- * @return array
764
- */
765
- protected function filter_events_by_field( $params ) {
766
- $events = array();
767
- if ( ! empty( $params[ 'events' ] ) ) {
768
- foreach ( $params[ 'events' ] as $key => $event ) {
769
- if ( $event->$params[ 'field' ] != $params[ 'value' ] ) {
770
- continue;
771
- }
772
-
773
- $events[ $key ] = $event;
774
- }
775
- }
776
-
777
- return $events;
778
- }
779
-
780
- public function post_row_actions( $actions, $post ) {
781
-
782
- if ( $post->post_type == $this->post_type && current_user_can('edit_posts') ) {
783
-
784
- $action_url = add_query_arg(
785
- array(
786
- 'post' => $post->ID,
787
- 'action' => 'mptt_duplicate_event',
788
- '_wpnonce' => wp_create_nonce( 'mptt_duplicate_event' )
789
- ),
790
- admin_url( 'post.php' )
791
- );
792
-
793
- $actions['duplicate'] = '<a href="' . $action_url . '" aria-label="' .
794
- __('Duplicate', 'mp-timetable') . '" rel="permalink">' . __('Duplicate', 'mp-timetable') . '</a>';
795
- }
796
-
797
- return $actions;
798
- }
799
-
800
- public function post_action_mptt_duplicate_event( $post_id ) {
801
-
802
- global $wpdb;
803
-
804
- $post_type = '';
805
-
806
- if ( $post_id ) {
807
- $post = get_post( $post_id );
808
- }
809
-
810
- if ( $post ) {
811
- $post_type = $post->post_type;
812
- }
813
-
814
- if ( $post_type !== $this->post_type ) {
815
- wp_die( __( 'A post type mismatch has been detected.', 'mp-timetable' ), __( 'Sorry, you are not allowed to edit this item.', 'mp-timetable' ), 400 );
816
- }
817
-
818
- $nonce = sanitize_key( $_REQUEST['_wpnonce'] );
819
-
820
- if ( wp_verify_nonce( $nonce, 'mptt_duplicate_event' ) && current_user_can('edit_posts') ) {
821
-
822
- $current_user = wp_get_current_user();
823
- $new_post_author = $current_user->ID;
824
-
825
- /*
826
- * new post data array
827
- */
828
- $args = array(
829
- 'comment_status' => $post->comment_status,
830
- 'ping_status' => $post->ping_status,
831
- 'post_author' => $new_post_author,
832
- 'post_content' => $post->post_content,
833
- 'post_excerpt' => $post->post_excerpt,
834
- 'post_name' => $post->post_name,
835
- 'post_parent' => $post->post_parent,
836
- 'post_password' => $post->post_password,
837
- 'post_status' => 'draft',
838
- // translators: New post title of the duplicated post
839
- 'post_title' => sprintf( __('%s - Copy', 'mp-timetable'), $post->post_title ),
840
- 'post_type' => $post->post_type,
841
- 'to_ping' => $post->to_ping,
842
- 'menu_order' => $post->menu_order
843
- );
844
-
845
- /*
846
- * insert the post by wp_insert_post() function
847
- */
848
- $new_post_id = wp_insert_post( $args );
849
-
850
- if( is_wp_error($new_post_id) ) {
851
- wp_die( $post_id->get_error_message() );
852
- }
853
-
854
- /*
855
- * get all current post terms and set them to the new post draft
856
- */
857
- $taxonomies = get_object_taxonomies($post->post_type);
858
- foreach ($taxonomies as $taxonomy) {
859
- $post_terms = wp_get_object_terms($post_id, $taxonomy, array('fields' => 'slugs'));
860
- wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false);
861
- }
862
-
863
- /*
864
- * duplicate all post meta
865
- */
866
- $post_meta_keys = \get_post_custom_keys( $post_id );
867
-
868
- if ( ! empty( $post_meta_keys ) ) {
869
-
870
- $meta_excludelist = [
871
- '_edit_lock',
872
- '_edit_last',
873
- '_wp_old_slug'
874
- ];
875
-
876
- $meta_keys = \array_diff( $post_meta_keys, $meta_excludelist );
877
-
878
- foreach ( $meta_keys as $meta_key ) {
879
- $meta_values = \get_post_custom_values( $meta_key, $post_id );
880
-
881
- // Clear existing meta data
882
- \delete_post_meta( $new_post_id, $meta_key );
883
-
884
- foreach ( $meta_values as $meta_value ) {
885
- $meta_value = \maybe_unserialize( $meta_value );
886
- \add_post_meta( $new_post_id, $meta_key, addslashes( $meta_value ) );
887
- }
888
- }
889
-
890
- }
891
-
892
- /*
893
- * duplicate timeslots in custom BD
894
- */
895
- $timeslots = $wpdb->get_results( "SELECT * FROM {$this->table_name} WHERE event_id = " . $post_id, OBJECT );
896
-
897
- if ( !empty($timeslots) ) {
898
-
899
- foreach ( $timeslots as $timeslot ) {
900
- $wpdb->insert(
901
- $this->table_name,
902
- array(
903
- 'column_id' => $timeslot->column_id,
904
- 'event_id' => $new_post_id,
905
- 'event_start' => date( 'H:i', strtotime( $timeslot->event_start ) ),
906
- 'event_end' => date( 'H:i', strtotime( $timeslot->event_end ) ),
907
- 'user_id' => $timeslot->user_id,
908
- 'description' => $timeslot->description
909
- )
910
- );
911
- }
912
- }
913
-
914
- /*
915
- * redirect to the edit post screen for the new draft
916
- */
917
- wp_safe_redirect( get_edit_post_link( $new_post_id, '' ) );
918
- exit();
919
-
920
- } else {
921
- wp_die( __( 'Sorry, you are not allowed to edit this item.' ) );
922
- }
923
- }
924
-
925
- public function get_timeslot_by_id( $id ) {
926
-
927
- global $wpdb;
928
-
929
- $timeslot = $wpdb->get_row(
930
- $wpdb->prepare( "SELECT * FROM {$this->table_name} WHERE id = %d", $id )
931
- );
932
-
933
- return $timeslot;
934
- }
935
-
936
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\classes\models;
4
+
5
+ use mp_timetable\plugin_core\classes\Model as Model;
6
+ use mp_timetable\plugin_core\classes\modules\Taxonomy;
7
+
8
+
9
+ /**
10
+ * Model Events
11
+ */
12
+ class Events extends Model {
13
+
14
+ protected static $instance;
15
+ protected $wpdb;
16
+ protected $table_name;
17
+ protected $post_type;
18
+
19
+ /**
20
+ * Events constructor.
21
+ */
22
+ function __construct() {
23
+ parent::__construct();
24
+ global $wpdb;
25
+ $this->wpdb = $wpdb;
26
+ $this->post_type = 'mp-event';
27
+ $this->taxonomy_names = array(
28
+ 'tag' => 'mp-event_tag',
29
+ 'cat' => 'mp-event_category',
30
+ );
31
+ $this->table_name = $wpdb->prefix . "mp_timetable_data";
32
+ }
33
+
34
+ /**
35
+ * @return Events
36
+ */
37
+ public static function get_instance() {
38
+ if ( null === self::$instance ) {
39
+ self::$instance = new self();
40
+ }
41
+
42
+ return self::$instance;
43
+ }
44
+
45
+ /**
46
+ * Getter
47
+ *
48
+ * @param $property
49
+ *
50
+ * @return mixed
51
+ */
52
+ function __get( $property ) {
53
+ return $this->{$property};
54
+ }
55
+
56
+ /**
57
+ * Setter
58
+ *
59
+ * @param $property
60
+ * @param $value
61
+ *
62
+ * @return mixed
63
+ */
64
+ function __set( $property, $value ) {
65
+ return $this->{$property} = $value;
66
+ }
67
+
68
+ /**
69
+ * Render event metabox
70
+ *
71
+ * @param $post
72
+ * @param $metabox
73
+ */
74
+ public function render_event_data( $post, $metabox ) {
75
+
76
+ $time_format = get_option( 'time_format' );
77
+ if ( $time_format === 'H:i' ) {
78
+ $time_format_array = array( 'hours' => '0,23', 'am_pm' => false );
79
+ } elseif ( $time_format === 'g:i A' ) {
80
+ $time_format_array = array( 'hours' => '1,12', 'am_pm' => true );
81
+ } else {
82
+ $time_format_array = array( 'hours' => '0,23', 'am_pm' => false );
83
+ }
84
+
85
+ $data[ 'columns' ] = $this->get( 'column' )->get_all_column();
86
+ $event_data = $this->get_event_data( array( 'field' => 'event_id', 'id' => $post->ID ), 'event_start', false );
87
+
88
+ $this->get_view()->render_html( "events/metabox-event-data", array( 'event_data' => $event_data, 'args' => $metabox[ 'args' ],
89
+ 'columns' => $data[ 'columns' ], 'date' => array( 'time_format' => $time_format_array ) ), true );
90
+ }
91
+
92
+ /**
93
+ *
94
+ * Get single event data by id
95
+ *
96
+ * @param $params
97
+ * @param string $order_by
98
+ * @param bool $publish
99
+ *
100
+ * @return array|null|object
101
+ */
102
+ public function get_event_data( $params, $order_by = 'event_start', $publish = true ) {
103
+ $publish_query_part = $publish ? " AND `post_status` = 'publish'" : '';
104
+ $table_posts = $this->wpdb->prefix . 'posts';
105
+
106
+ $event_data = $this->wpdb->get_results(
107
+ "SELECT t.*"
108
+ . " FROM $this->table_name t INNER JOIN"
109
+ . " ("
110
+ . " SELECT * FROM {$table_posts}"
111
+ . " WHERE `post_type` = 'mp-column' AND `post_status` = 'publish'"
112
+ . " ) p ON t.`column_id` = p.`ID`"
113
+ . " INNER JOIN ("
114
+ . " SELECT * FROM {$table_posts}"
115
+ . " WHERE `post_type` = '{$this->post_type}'{$publish_query_part}"
116
+ . " ) e ON t.`event_id` = e.`ID`"
117
+ . " WHERE t.`{$params["field"]}` = {$params['id']} "
118
+ . " ORDER BY p.`menu_order`, t.`{$order_by}`"
119
+ );
120
+
121
+ foreach ( $event_data as $key => $event ) {
122
+
123
+ $user = false;
124
+ $wpUser = get_user_by( 'id', $event_data[ $key ]->user_id );
125
+
126
+ if ( ! empty( $wpUser ) ) {
127
+ $user = new \stdClass();
128
+ $user->ID = $wpUser->ID;
129
+ $user->display_name = $wpUser->data->display_name;
130
+ }
131
+
132
+ $event_data[ $key ]->event_start = date( 'H:i', strtotime( $event_data[ $key ]->event_start ) );
133
+ $event_data[ $key ]->event_end = date( 'H:i', strtotime( $event_data[ $key ]->event_end ) );
134
+ $event_data[ $key ]->user = $user;
135
+ $event_data[ $key ]->post = get_post( $event_data[ $key ]->event_id );
136
+ $event_data[ $key ]->description = stripcslashes( $event_data[ $key ]->description );
137
+ }
138
+
139
+ return $event_data;
140
+ }
141
+
142
+ /**
143
+ * Render meta data
144
+ */
145
+ public function render_event_metas() {
146
+ $this->append_time_slots();
147
+ }
148
+
149
+ /**
150
+ * Render Timeslots by $post
151
+ */
152
+ public function append_time_slots() {
153
+ global $post;
154
+
155
+ $show_public_only = ( ( get_post_status( $post->ID ) == 'draft' ) && is_preview() ) ? false : true;
156
+
157
+ $data = $this->get_event_data( array( 'field' => 'event_id', 'id' => $post->ID ), 'event_start', $show_public_only );
158
+ $event_data = ( ! empty( $data ) ) ? $data : array();
159
+ $count = count( $event_data );
160
+
161
+ $this->get_view()->get_template( "theme/event-timeslots", array( 'events' => $event_data, 'count' => $count ) );
162
+ }
163
+
164
+ /**
165
+ * Render event options
166
+ *
167
+ * @param $post
168
+ */
169
+ public function render_event_options( $post ) {
170
+ $this->get_view()->render_html( "events/metabox-event-options", array( 'post' => $post ), true );
171
+ }
172
+
173
+ /**
174
+ * Add column
175
+ *
176
+ * @param $columns
177
+ *
178
+ * @return array
179
+ */
180
+ public function set_event_columns( $columns ) {
181
+ $columns = array_slice( $columns, 0, 2, true ) + array( $this->taxonomy_names[ 'tag' ] => __( 'Tags', 'mp-timetable' ) ) + array_slice( $columns, 2, count( $columns ) - 1, true );
182
+ $columns = array_slice( $columns, 0, 2, true ) + array( $this->taxonomy_names[ 'cat' ] => __( 'Categories', 'mp-timetable' ) ) + array_slice( $columns, 2, count( $columns ) - 1, true );
183
+
184
+ return $columns;
185
+ }
186
+
187
+ /**
188
+ * Create event category admin link
189
+ *
190
+ * @param $column
191
+ */
192
+ public function get_event_taxonomy( $column ) {
193
+ global $post;
194
+ if ( $column === $this->taxonomy_names[ 'cat' ] ) {
195
+ echo Taxonomy::get_instance()->get_the_term_filter_list( $post, $this->taxonomy_names[ 'cat' ] );
196
+ }
197
+ if ( $column === $this->taxonomy_names[ 'tag' ] ) {
198
+ echo Taxonomy::get_instance()->get_the_term_filter_list( $post, $this->taxonomy_names[ 'tag' ] );
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Output category post
204
+ *
205
+ * @param string $the_list
206
+ * @param string $separator
207
+ * @param string $parents
208
+ *
209
+ * @return mixed
210
+ */
211
+ public function the_category( $the_list = '', $separator = '', $parents = '' ) {
212
+ global $post;
213
+
214
+ if ( $post && $post->post_type === $this->post_type && ! is_admin() ) {
215
+ $categories = wp_get_post_terms( $post->ID, $this->taxonomy_names[ 'cat' ] );
216
+ $the_list .= $this->generate_event_tags( $categories, $separator, $parents );
217
+ }
218
+
219
+ /**
220
+ * Filter the category or list of Timetable categories.
221
+ *
222
+ * @param array $thelist List of categories for the current post.
223
+ * @param string $separator Separator used between the categories.
224
+ * @param string $parents How to display the category parents. Accepts 'multiple',
225
+ * 'single', or empty.
226
+ */
227
+ return apply_filters( 'mptt_the_category', $the_list, $separator, $parents );
228
+ }
229
+
230
+ /**
231
+ * Generate HTML of the post tags
232
+ *
233
+ * @param $categories
234
+ * @param $separator
235
+ * @param $parents
236
+ *
237
+ * @return string
238
+ */
239
+ public function generate_event_tags( $categories, $separator, $parents ) {
240
+ global $wp_rewrite;
241
+ $the_list = '';
242
+ $rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? 'rel="category tag"' : 'rel="category"';
243
+
244
+ if ( '' == $separator ) {
245
+ $the_list .= '<ul class="post-categories">';
246
+ foreach ( $categories as $category ) {
247
+ $the_list .= "\n\t<li>";
248
+ switch ( strtolower( $parents ) ) {
249
+ case 'multiple':
250
+ if ( $category->parent ) {
251
+ $the_list .= get_category_parents( $category->parent, true, $separator );
252
+ }
253
+ $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name . '</a></li>';
254
+ break;
255
+ case 'single':
256
+ $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>';
257
+ if ( $category->parent ) {
258
+ $the_list .= get_category_parents( $category->parent, false, $separator );
259
+ }
260
+ $the_list .= $category->name . '</a></li>';
261
+ break;
262
+ case '':
263
+ default:
264
+ $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name . '</a></li>';
265
+ }
266
+ }
267
+ $the_list .= '</ul>';
268
+ } else {
269
+ $i = 0;
270
+ foreach ( $categories as $category ) {
271
+ if ( 0 < $i ) {
272
+ $the_list .= $separator;
273
+ }
274
+ switch ( strtolower( $parents ) ) {
275
+ case 'multiple':
276
+ if ( $category->parent ) {
277
+ $the_list .= get_category_parents( $category->parent, true, $separator );
278
+ }
279
+ $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name . '</a>';
280
+ break;
281
+ case 'single':
282
+ $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>';
283
+ if ( $category->parent ) {
284
+ $the_list .= get_category_parents( $category->parent, false, $separator );
285
+ }
286
+ $the_list .= "$category->name</a>";
287
+ break;
288
+ case '':
289
+ default:
290
+ $the_list .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name . '</a>';
291
+ }
292
+ ++ $i;
293
+ }
294
+ }
295
+
296
+ return $the_list;
297
+ }
298
+
299
+ /**
300
+ * Returns a formatted tags.
301
+ *
302
+ * @param $tags
303
+ * @param string $before
304
+ * @param string $sep
305
+ * @param string $after
306
+ * @param int $id
307
+ *
308
+ * @return mixed
309
+ */
310
+ public function the_tags( $tags, $before = '', $sep = '', $after = '', $id = 0 ) {
311
+ global $post;
312
+
313
+ if ( $post && $post->post_type === $this->post_type ) {
314
+ $id = ( $id === 0 ) ? $post->id : $id;
315
+ $events_tags = get_the_term_list( $id, $this->taxonomy_names[ 'tag' ], $before, $sep, $after );
316
+ $tags = apply_filters( 'mptt_the_tags', $events_tags, $tags );
317
+ }
318
+
319
+ return $tags;
320
+ }
321
+
322
+ /**
323
+ * Save(insert) event data
324
+ *
325
+ * @param array $params
326
+ *
327
+ * @return array
328
+ */
329
+ public function save_event_data( array $params ) {
330
+
331
+ $rows_affected = array();
332
+
333
+ if ( ! empty( $params[ 'event_data' ] ) ) {
334
+ foreach ( $params[ 'event_data' ] as $key => $event ) {
335
+ if ( is_array( $event[ 'event_start' ] ) && ! empty( $event[ 'event_start' ] ) ) {
336
+
337
+ for ( $i = 0; $i < count( $event[ 'event_start' ] ); $i ++ ) {
338
+ $rows_affected[] = $this->wpdb->insert( $this->table_name, array(
339
+ 'column_id' => absint( $key ),
340
+ 'event_id' => absint( $params[ 'post' ]->ID ),
341
+ 'event_start' => date( 'H:i', strtotime( sanitize_text_field( $event[ 'event_start' ][ $i ] ) ) ),
342
+ 'event_end' => date( 'H:i', strtotime( sanitize_text_field( $event[ 'event_end' ][ $i ] ) ) ),
343
+ 'user_id' => absint( $event[ 'user_id' ][ $i ] ),
344
+ 'description' => wp_kses_post( $event[ 'description' ][ $i ] )
345
+ )
346
+ );
347
+ }
348
+ }
349
+ }
350
+ }
351
+
352
+ if ( ! empty( $params[ 'event_meta' ] ) ) {
353
+ foreach ( $params[ 'event_meta' ] as $meta_key => $meta ) {
354
+ switch ( $meta_key ) {
355
+ case 'timetable_custom_url':
356
+ update_post_meta( $params[ 'post' ]->ID, $meta_key, esc_url_raw( $meta ) );
357
+ break;
358
+ default:
359
+ update_post_meta( $params[ 'post' ]->ID, $meta_key, wp_kses_post( $meta ) );
360
+ }
361
+ }
362
+ }
363
+
364
+ return $rows_affected;
365
+ }
366
+
367
+ /**
368
+ * Delete event timeslot
369
+ *
370
+ * @param $id
371
+ *
372
+ * @return false|int
373
+ */
374
+ public function delete_event( $id ) {
375
+ return $this->wpdb->delete( $this->table_name, array( 'id' => $id ), array( '%d' ) );
376
+ }
377
+
378
+ /**
379
+ * Delete event data
380
+ *
381
+ * @param $post_id
382
+ *
383
+ * @return false|int
384
+ */
385
+ public function before_delete_event( $post_id ) {
386
+ $meta_keys = array( 'event_id', 'event_start', 'event_end', 'user_id', 'description' );
387
+
388
+ foreach ( $meta_keys as $meta_key ) {
389
+ delete_post_meta( $post_id, $meta_key );
390
+ }
391
+
392
+ return $this->wpdb->delete( $this->table_name, array( 'event_id' => $post_id ), array( '%d' ) );
393
+ }
394
+
395
+ /**
396
+ * Get widget events
397
+ *
398
+ * @param $instance
399
+ *
400
+ * @return array
401
+ */
402
+ public function get_widget_events( $instance ) {
403
+ $events = array();
404
+ $current_local_time = current_time( 'timestamp' );
405
+
406
+ $weekday = strtolower( date( 'l', $current_local_time ) );
407
+ $current_date = date( 'd/m/Y', $current_local_time );
408
+
409
+ // 24.09.2019 seconds added
410
+ $curent_time = date( 'H:i:s', $current_local_time );
411
+
412
+ if ( ! empty( $instance[ 'mp_categories' ] ) ) {
413
+ $category_columns_ids = $this->get( 'column' )->get_columns_by_event_category( $instance[ 'mp_categories' ] );
414
+ }
415
+
416
+ $args = array(
417
+ 'post_type' => 'mp-column',
418
+ 'post_status' => 'publish',
419
+ 'fields' => 'ids',
420
+ 'post__in' => ! empty( $category_columns_ids ) ? $category_columns_ids : '',
421
+ 'orderby' => 'menu_order',
422
+ 'meta_query' => array(
423
+ 'relation' => 'OR',
424
+ array(
425
+ 'key' => 'weekday',
426
+ 'value' => $weekday
427
+ ),
428
+ array(
429
+ 'key' => 'option_day',
430
+ 'value' => $current_date
431
+ )
432
+ )
433
+ );
434
+
435
+ switch ( $instance[ 'view_settings' ] ) {
436
+ case'today':
437
+ case 'current':
438
+ $column_post_ids = get_posts( $args );
439
+ if ( ! empty( $column_post_ids ) ) {
440
+ $events = $this->get_events_data( array( 'column' => 'column_id', 'list' => $column_post_ids ) );
441
+ }
442
+ $events = $this->filter_events( array( 'events' => $events, 'view_settings' => $instance[ 'view_settings' ], 'time' => $curent_time, 'mp_categories' => $instance[ 'mp_categories' ] ) );
443
+ break;
444
+ case 'all':
445
+
446
+ if ( ! empty( $instance[ 'next_days' ] ) && $instance[ 'next_days' ] > 0 ) {
447
+ $events_array = array();
448
+ for ( $i = 0; $i <= $instance[ 'next_days' ]; $i ++ ) {
449
+
450
+ // set new day week
451
+ $time = strtotime( "+$i days", $current_local_time );
452
+ $day = strtolower( date( 'l', $time ) );
453
+ $date = date( 'd/m/Y', $time );
454
+
455
+ //set week day
456
+ $args[ 'meta_query' ][ 0 ][ 'value' ] = $day;
457
+ //set new date
458
+ $args[ 'meta_query' ][ 1 ][ 'value' ] = $date;
459
+
460
+ $column_post_ids = get_posts( $args );
461
+
462
+ if ( ! empty( $column_post_ids ) ) {
463
+ $events_array[ $i ] = $this->get_events_data( array( 'column' => 'column_id', 'list' => $column_post_ids ) );
464
+ } else {
465
+ $events_array[ $i ] = array();
466
+ }
467
+
468
+ // Filter by time and categories for current day
469
+ if ( $i === 0 && ! empty( $instance[ 'mp_categories' ] ) && ! empty( $events_array[ $i ] ) ) {
470
+ $events_array[ $i ] = $events_array[ $i ] = $this->filter_events( array( 'events' => $events_array[ $i ], 'view_settings' => 'today', 'time' => $curent_time, 'mp_categories' => $instance[ 'mp_categories' ] ) );
471
+ } elseif ( ! empty( $instance[ 'mp_categories' ] ) && ! empty( $events_array[ $i ] ) ) {
472
+ //Filter by categories for next days
473
+ $events_array[ $i ] = $this->filter_events_by_categories( $events_array[ $i ], $instance[ 'mp_categories' ] );
474
+ }
475
+
476
+ }
477
+
478
+ foreach ( $events_array as $day_events ) {
479
+ $events = array_merge( $events, $day_events );
480
+ }
481
+
482
+ }
483
+
484
+ break;
485
+
486
+ default:
487
+ $column_post_ids = get_posts( $args );
488
+ if ( ! empty( $column_post_ids ) ) {
489
+ $events = $this->get_events_data( array( 'column' => 'column_id', 'list' => $column_post_ids ) );
490
+ }
491
+ $events = $this->filter_events( array( 'events' => $events, 'view_settings' => 'today', 'time' => $curent_time, 'mp_categories' => $instance[ 'mp_categories' ] ) );
492
+
493
+ break;
494
+ }
495
+ if ( $instance[ 'limit' ] > 0 ) {
496
+ $events = array_slice( $events, 0, $instance[ 'limit' ] );
497
+ }
498
+
499
+ return $events;
500
+ }
501
+
502
+ /**
503
+ * Get event data by post
504
+ *
505
+ * @param array $params
506
+ *
507
+ * @return array
508
+ */
509
+ public function get_events_data( array $params ) {
510
+ $events = array();
511
+ $sql_request = "SELECT * FROM " . $this->table_name;
512
+
513
+ if ( ( ! empty( $params[ 'all' ] ) && $params[ 'all' ] ) || empty( $params[ 'list' ] ) ) {
514
+
515
+ } elseif ( ! is_array( $params[ 'column' ] ) ) {
516
+
517
+ if ( isset( $params[ 'list' ] ) && is_array( $params[ 'list' ] ) ) {
518
+ $params[ 'list' ] = implode( ',', $params[ 'list' ] );
519
+ }
520
+
521
+ $sql_request .= " WHERE " . $params[ 'column' ] . " IN (" . $params[ 'list' ] . ")";
522
+
523
+ } elseif ( is_array( $params[ 'column' ] ) && is_array( $params[ 'list' ] ) ) {
524
+
525
+ $sql_request .= " WHERE ";
526
+
527
+ $last_key = key( array_slice( $params[ 'column' ], - 1, 1, true ) );
528
+
529
+ foreach ( $params[ 'column' ] as $key => $column ) {
530
+ if ( isset( $params[ 'list' ][ $column ] ) && is_array( $params[ 'list' ][ $column ] ) ) {
531
+ $params[ 'list' ][ $column ] = implode( ',', $params[ 'list' ][ $column ] );
532
+ }
533
+ $sql_request .= $column . " IN (" . $params[ 'list' ][ $column ] . ")";
534
+ $sql_request .= ( $last_key != $key ) ? ' AND ' : '';
535
+ }
536
+
537
+ }
538
+
539
+ $sql_request .= ' ORDER BY `event_start`';
540
+
541
+ $events_data = $this->wpdb->get_results( $sql_request );
542
+
543
+ if ( is_array( $events_data ) ) {
544
+
545
+ foreach ( $events_data as $event ) {
546
+ $post = get_post( $event->event_id );
547
+
548
+ if ( $post && ( $post->post_type == $this->post_type ) && ( $post->post_status == 'publish' ) ) {
549
+ $event->post = $post;
550
+ $event->event_start = date( 'H:i', strtotime( $event->event_start ) );
551
+ $event->event_end = date( 'H:i', strtotime( $event->event_end ) );
552
+ $events[] = $event;
553
+ }
554
+ }
555
+ }
556
+
557
+ return $events;
558
+ }
559
+
560
+ /**
561
+ * Filtered events by view settings
562
+ *
563
+ * @param $params
564
+ *
565
+ * @return array
566
+ */
567
+ protected function filter_events( $params ) {
568
+
569
+ $events = array();
570
+ $events = $this->filter_by_time_period( $params, $events );
571
+
572
+ if ( ! empty( $params[ 'mp_categories' ] ) ) {
573
+ $events = $this->filter_events_by_categories( $events, $params[ 'mp_categories' ] );
574
+ }
575
+
576
+ return $events;
577
+ }
578
+
579
+ /**
580
+ * Filter by time period
581
+ *
582
+ * @param $params
583
+ * @param $events
584
+ *
585
+ * @return array
586
+ */
587
+ protected function filter_by_time_period( $params, $events ) {
588
+ if ( ! empty( $params[ 'events' ] ) ) {
589
+
590
+ $time = strtotime( $params[ 'time' ] );
591
+
592
+ foreach ( $params[ 'events' ] as $key => $event ) {
593
+
594
+ $event_end = strtotime( $event->event_end );
595
+ $event_start = strtotime( $event->event_start );
596
+
597
+ if ( $params[ 'view_settings' ] === 'today' || $params[ 'view_settings' ] === 'all' ) {
598
+ if ( $event_end <= $time ) {
599
+ continue;
600
+ }
601
+ } elseif ( $params[ 'view_settings' ] === 'current' ) {
602
+ if ( $event_start >= $time || $event_end <= $time ) {
603
+ continue;
604
+ }
605
+ }
606
+ $events[ $key ] = $event;
607
+ }
608
+ }
609
+
610
+ return $events;
611
+ }
612
+
613
+ /**
614
+ * Filter find events by select categories;
615
+ *
616
+ * @param array $events
617
+ * @param array $categories
618
+ *
619
+ * @return array
620
+ */
621
+ public function filter_events_by_categories( array $events, array $categories ) {
622
+ $temp_events = array();
623
+ $taxonomy = $this->taxonomy_names[ 'cat' ];
624
+
625
+ foreach ( $events as $event ) {
626
+ if ( @has_term( $categories, $taxonomy, $event->post->ID ) ) {
627
+ $temp_events[] = $event;
628
+ }
629
+ }
630
+
631
+ return $temp_events;
632
+ }
633
+
634
+ /**
635
+ * Sort by params
636
+ *
637
+ * @param $events
638
+ *
639
+ * @return mixed
640
+ */
641
+
642
+ public function sort_by_param( $events ) {
643
+
644
+ usort( $events, function ( $a, $b ) {
645
+ if ( strtotime( $a->event_start ) == strtotime( $b->event_start ) ) {
646
+ return 0;
647
+ }
648
+
649
+ return ( strtotime( $a->event_start ) < strtotime( $b->event_start ) ) ? - 1 : 1;
650
+ } );
651
+
652
+
653
+ return $events;
654
+ }
655
+
656
+ /**
657
+ * @param array /string $event_category
658
+ *
659
+ * @return array|null|object
660
+ */
661
+ public function get_events_data_by_category( $event_categories ) {
662
+ if ( ! is_array( $event_categories ) ) {
663
+ $terms = explode( ',', $event_categories );
664
+ } else {
665
+ $terms = $event_categories;
666
+ }
667
+
668
+ $posts_array = get_posts(
669
+ array(
670
+ 'fields' => 'ids',
671
+ 'posts_per_page' => - 1,
672
+ 'post_type' => $this->post_type,
673
+ 'post_status' => 'publish',
674
+ 'tax_query' => array(
675
+ array(
676
+ 'taxonomy' => 'mp-event_category',
677
+ 'field' => 'term_id',
678
+ 'terms' => $terms,
679
+ )
680
+ )
681
+ )
682
+ );
683
+
684
+ $ids = implode( ',', $posts_array );
685
+ $event_data = $this->get_events_data( array( 'column' => 'event_id', 'list' => $ids ) );
686
+
687
+ return $event_data;
688
+ }
689
+
690
+ /**
691
+ * Update event data
692
+ *
693
+ * @param $data
694
+ *
695
+ * @return false|int
696
+ */
697
+ public function update_event_data( $data ) {
698
+
699
+ $id = (int) $data[ 'id' ];
700
+
701
+ $result = $this->wpdb->update(
702
+ $this->table_name,
703
+ array(
704
+ 'event_start' => date( 'H:i', strtotime( $data[ 'event_start' ] ) ),
705
+ 'event_end' => date( 'H:i', strtotime( $data[ 'event_end' ] ) ),
706
+ 'description' => wp_kses_post( $data[ 'description' ] ),
707
+ 'column_id' => $data[ 'weekday_ids' ],
708
+ 'user_id' => $data[ 'user_id' ],
709
+ ),
710
+ array( 'id' => $id ),
711
+ array(
712
+ '%s',
713
+ '%s',
714
+ '%s',
715
+ '%d',
716
+ '%d',
717
+ ),
718
+ array( '%d' )
719
+ );
720
+
721
+ return $result;
722
+ }
723
+
724
+ /**
725
+ * Get all events
726
+ * @return array
727
+ */
728
+ public function get_all_events() {
729
+ $args = array(
730
+ 'post_type' => $this->post_type,
731
+ 'post_status' => 'publish',
732
+ 'order' => 'ASC',
733
+ 'orderby' => 'title',
734
+ 'posts_per_page' => - 1
735
+ );
736
+
737
+ return get_posts( $args );
738
+ }
739
+
740
+ /**
741
+ * Choose color widget or event
742
+ *
743
+ * @param $params
744
+ *
745
+ * @return string
746
+ */
747
+
748
+ public function choose_event_color( $params ) {
749
+ if ( ! empty( $params[ 'widget_color' ] ) ) {
750
+ return $params[ 'widget_color' ];
751
+ } elseif ( ! empty( $params[ 'event_color' ] ) ) {
752
+ return $params[ 'event_color' ];
753
+ } else {
754
+ return '';
755
+ }
756
+ }
757
+
758
+ /**
759
+ * Filtered events by Event Head
760
+ *
761
+ * @param $params
762
+ *
763
+ * @return array
764
+ */
765
+ protected function filter_events_by_field( $params ) {
766
+ $events = array();
767
+ if ( ! empty( $params[ 'events' ] ) ) {
768
+ foreach ( $params[ 'events' ] as $key => $event ) {
769
+ if ( $event->$params[ 'field' ] != $params[ 'value' ] ) {
770
+ continue;
771
+ }
772
+
773
+ $events[ $key ] = $event;
774
+ }
775
+ }
776
+
777
+ return $events;
778
+ }
779
+
780
+ public function post_row_actions( $actions, $post ) {
781
+
782
+ if ( $post->post_type == $this->post_type && current_user_can('edit_posts') ) {
783
+
784
+ $action_url = add_query_arg(
785
+ array(
786
+ 'post' => $post->ID,
787
+ 'action' => 'mptt_duplicate_event',
788
+ '_wpnonce' => wp_create_nonce( 'mptt_duplicate_event' )
789
+ ),
790
+ admin_url( 'post.php' )
791
+ );
792
+
793
+ $actions['duplicate'] = '<a href="' . $action_url . '" aria-label="' .
794
+ __('Duplicate', 'mp-timetable') . '" rel="permalink">' . __('Duplicate', 'mp-timetable') . '</a>';
795
+ }
796
+
797
+ return $actions;
798
+ }
799
+
800
+ public function post_action_mptt_duplicate_event( $post_id ) {
801
+
802
+ global $wpdb;
803
+
804
+ $post_type = '';
805
+
806
+ if ( $post_id ) {
807
+ $post = get_post( $post_id );
808
+ }
809
+
810
+ if ( $post ) {
811
+ $post_type = $post->post_type;
812
+ }
813
+
814
+ if ( $post_type !== $this->post_type ) {
815
+ wp_die( __( 'A post type mismatch has been detected.', 'mp-timetable' ), __( 'Sorry, you are not allowed to edit this item.', 'mp-timetable' ), 400 );
816
+ }
817
+
818
+ $nonce = sanitize_key( $_REQUEST['_wpnonce'] );
819
+
820
+ if ( wp_verify_nonce( $nonce, 'mptt_duplicate_event' ) && current_user_can('edit_posts') ) {
821
+
822
+ $current_user = wp_get_current_user();
823
+ $new_post_author = $current_user->ID;
824
+
825
+ /*
826
+ * new post data array
827
+ */
828
+ $args = array(
829
+ 'comment_status' => $post->comment_status,
830
+ 'ping_status' => $post->ping_status,
831
+ 'post_author' => $new_post_author,
832
+ 'post_content' => $post->post_content,
833
+ 'post_excerpt' => $post->post_excerpt,
834
+ 'post_name' => $post->post_name,
835
+ 'post_parent' => $post->post_parent,
836
+ 'post_password' => $post->post_password,
837
+ 'post_status' => 'draft',
838
+ // translators: New post title of the duplicated post
839
+ 'post_title' => sprintf( __('%s - Copy', 'mp-timetable'), $post->post_title ),
840
+ 'post_type' => $post->post_type,
841
+ 'to_ping' => $post->to_ping,
842
+ 'menu_order' => $post->menu_order
843
+ );
844
+
845
+ /*
846
+ * insert the post by wp_insert_post() function
847
+ */
848
+ $new_post_id = wp_insert_post( $args );
849
+
850
+ if( is_wp_error($new_post_id) ) {
851
+ wp_die( $post_id->get_error_message() );
852
+ }
853
+
854
+ /*
855
+ * get all current post terms and set them to the new post draft
856
+ */
857
+ $taxonomies = get_object_taxonomies($post->post_type);
858
+ foreach ($taxonomies as $taxonomy) {
859
+ $post_terms = wp_get_object_terms($post_id, $taxonomy, array('fields' => 'slugs'));
860
+ wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false);
861
+ }
862
+
863
+ /*
864
+ * duplicate all post meta
865
+ */
866
+ $post_meta_keys = \get_post_custom_keys( $post_id );
867
+
868
+ if ( ! empty( $post_meta_keys ) ) {
869
+
870
+ $meta_excludelist = [
871
+ '_edit_lock',
872
+ '_edit_last',
873
+ '_wp_old_slug'
874
+ ];
875
+
876
+ $meta_keys = \array_diff( $post_meta_keys, $meta_excludelist );
877
+
878
+ foreach ( $meta_keys as $meta_key ) {
879
+ $meta_values = \get_post_custom_values( $meta_key, $post_id );
880
+
881
+ // Clear existing meta data
882
+ \delete_post_meta( $new_post_id, $meta_key );
883
+
884
+ foreach ( $meta_values as $meta_value ) {
885
+ $meta_value = \maybe_unserialize( $meta_value );
886
+ \add_post_meta( $new_post_id, $meta_key, addslashes( $meta_value ) );
887
+ }
888
+ }
889
+
890
+ }
891
+
892
+ /*
893
+ * duplicate timeslots in custom BD
894
+ */
895
+ $timeslots = $wpdb->get_results( "SELECT * FROM {$this->table_name} WHERE event_id = " . $post_id, OBJECT );
896
+
897
+ if ( !empty($timeslots) ) {
898
+
899
+ foreach ( $timeslots as $timeslot ) {
900
+ $wpdb->insert(
901
+ $this->table_name,
902
+ array(
903
+ 'column_id' => $timeslot->column_id,
904
+ 'event_id' => $new_post_id,
905
+ 'event_start' => date( 'H:i', strtotime( $timeslot->event_start ) ),
906
+ 'event_end' => date( 'H:i', strtotime( $timeslot->event_end ) ),
907
+ 'user_id' => $timeslot->user_id,
908
+ 'description' => $timeslot->description
909
+ )
910
+ );
911
+ }
912
+ }
913
+
914
+ /*
915
+ * redirect to the edit post screen for the new draft
916
+ */
917
+ wp_safe_redirect( get_edit_post_link( $new_post_id, '' ) );
918
+ exit();
919
+
920
+ } else {
921
+ wp_die( __( 'Sorry, you are not allowed to edit this item.' ) );
922
+ }
923
+ }
924
+
925
+ public function get_timeslot_by_id( $id ) {
926
+
927
+ global $wpdb;
928
+
929
+ $timeslot = $wpdb->get_row(
930
+ $wpdb->prepare( "SELECT * FROM {$this->table_name} WHERE id = %d", $id )
931
+ );
932
+
933
+ return $timeslot;
934
+ }
935
+
936
+ }
classes/models/class-export.php CHANGED
@@ -1,483 +1,483 @@
1
- <?php
2
- namespace mp_timetable\classes\models;
3
-
4
- use mp_timetable\classes\libs;
5
- use mp_timetable\plugin_core\classes\Model as Model;
6
-
7
- /**
8
- * Export model
9
- */
10
- class Export extends Model {
11
- protected static $instance;
12
- private $table;
13
-
14
- public static function get_instance() {
15
- if (null === self::$instance) {
16
- self::$instance = new self();
17
- }
18
- return self::$instance;
19
- }
20
-
21
- function __construct() {
22
- $this->table = Events::get_instance()->table_name;
23
- parent::__construct();
24
- }
25
-
26
- /**
27
- * Export file
28
- */
29
- public function export() {
30
-
31
- global $wpdb, $post;
32
-
33
- if ( !defined('ABSPATH') ) exit;
34
-
35
- if ( !current_user_can('export') ) exit;
36
-
37
- if ( !function_exists('export_wp') ) {
38
- include_once(ABSPATH . 'wp-admin/includes/export.php');
39
- }
40
-
41
- $args = array('content' => $this->post_types, 'author' => false, 'category' => false,
42
- 'start_date' => false, 'end_date' => false, 'status' => false);
43
-
44
-
45
- $defaults = array('content' => 'all', 'author' => false, 'category' => false,
46
- 'start_date' => false, 'end_date' => false, 'status' => false,
47
- );
48
- $args = wp_parse_args($args, $defaults);
49
-
50
- /**
51
- * Fires at the beginning of an export, before any headers are sent.
52
- *
53
- * @since 2.3.0
54
- *
55
- * @param array $args An array of export arguments.
56
- */
57
- do_action('export_wp', $args);
58
-
59
- $filename = $this->file_name();
60
-
61
- header('Content-Description: File Transfer');
62
- header('Content-Disposition: attachment; filename=' . $filename);
63
- header('Content-Type: text/xml; charset=' . get_option('blog_charset'), true);
64
-
65
- if ('all' != $args['content'] && post_type_exists($args['content'])) {
66
- $ptype = get_post_type_object($args['content']);
67
- if (!$ptype->can_export)
68
- $args['content'] = 'post';
69
-
70
- $where = $wpdb->prepare("{$wpdb->posts}.post_type = %s", $args['content']);
71
- } else {
72
- $post_types = get_post_types(array('can_export' => true));
73
- $post_types = array_intersect($post_types, $args['content']);
74
- $esses = array_fill(0, count($post_types), '%s');
75
- $where = $wpdb->prepare("{$wpdb->posts}.post_type IN (" . implode(',', $esses) . ')', $post_types);
76
- }
77
-
78
- if ($args['status'] && ('post' == $args['content'] || 'page' == $args['content']))
79
- $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_status = %s", $args['status']);
80
- else
81
- $where .= " AND {$wpdb->posts}.post_status != 'auto-draft'";
82
-
83
- $join = '';
84
- if ($args['category'] && 'post' == $args['content']) {
85
- if ($term = term_exists($args['category'], 'category')) {
86
- $join = "INNER JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)";
87
- $where .= $wpdb->prepare(" AND {$wpdb->term_relationships}.term_taxonomy_id = %d", $term['term_taxonomy_id']);
88
- }
89
- }
90
-
91
- if ('post' == $args['content'] || 'page' == $args['content'] || 'attachment' == $args['content']) {
92
- if ($args['author'])
93
- $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_author = %d", $args['author']);
94
-
95
- if ($args['start_date'])
96
- $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_date >= %s", date('Y-m-d', strtotime($args['start_date'])));
97
-
98
- if ($args['end_date'])
99
- $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_date < %s", date('Y-m-d', strtotime('+1 month', strtotime($args['end_date']))));
100
- }
101
-
102
- // Grab a snapshot of post IDs, just in case it changes during the export.
103
- $post_ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} $join WHERE $where");
104
-
105
- /*
106
- * Get the requested terms ready, empty unless posts filtered by category
107
- * or all content.
108
- */
109
- $thumbnail_ids = array();
110
- foreach ($post_ids as $ID) {
111
- $thumbnail_id = get_post_thumbnail_id($ID);
112
- if (empty($thumbnail_id)) {
113
- continue;
114
- }
115
- $thumbnail_ids[] = $thumbnail_id;
116
- }
117
- if (!empty($thumbnail_ids)) {
118
- $post_ids = array_merge($post_ids, $thumbnail_ids);
119
- }
120
- $cats = $tags = $terms = array();
121
-
122
- if (!empty($this->taxonomy_names)) {
123
- $custom_taxonomies = get_taxonomies(array('_builtin' => false));
124
- $custom_terms = (array)get_terms($this->taxonomy_names, array('get' => 'all'));
125
-
126
- // Put terms in order with no child going before its parent.
127
- while ($t = array_shift($custom_terms)) {
128
- if ($t->parent == 0 || isset($terms[$t->parent]))
129
- $terms[$t->term_id] = $t;
130
- else
131
- $custom_terms[] = $t;
132
- }
133
-
134
- unset($categories, $custom_taxonomies, $custom_terms);
135
- }
136
-
137
- add_filter('mptt_export_skip_postmeta', array($this, 'mptt_filter_postmeta'), 10, 2);
138
-
139
- echo '<?xml version="1.0" encoding="' . get_bloginfo('charset') . "\" ?>\n"; ?>
140
- <?php the_generator('export'); ?>
141
-
142
- <rss version="2.0"
143
- xmlns:excerpt="http://wordpress.org/export/<?php echo WXR_VERSION; ?>/excerpt/"
144
- xmlns:content="http://purl.org/rss/1.0/modules/content/"
145
- xmlns:wfw="http://wellformedweb.org/CommentAPI/"
146
- xmlns:dc="http://purl.org/dc/elements/1.1/"
147
- xmlns:wp="http://wordpress.org/export/<?php echo WXR_VERSION; ?>/">
148
- <channel>
149
- <title><?php bloginfo_rss('name'); ?></title>
150
- <link><?php bloginfo_rss('url'); ?></link>
151
- <description><?php bloginfo_rss('description'); ?></description>
152
- <pubDate><?php echo date('D, d M Y H:i:s +0000'); ?></pubDate>
153
- <language><?php bloginfo_rss('language'); ?></language>
154
- <wp:wxr_version><?php echo WXR_VERSION; ?></wp:wxr_version>
155
- <wp:base_site_url><?php echo $this->mptt_site_url(); ?></wp:base_site_url>
156
- <wp:base_blog_url><?php bloginfo_rss('url'); ?></wp:base_blog_url>
157
-
158
- <?php $this->mptt_authors_list($post_ids); ?>
159
- <?php foreach ($terms as $t) : ?>
160
- <wp:term>
161
- <wp:term_id><?php echo $this->mptt_cdata($t->term_id); ?></wp:term_id>
162
- <wp:term_taxonomy><?php echo $this->mptt_cdata($t->taxonomy); ?></wp:term_taxonomy>
163
- <wp:term_slug><?php echo $this->mptt_cdata($t->slug); ?></wp:term_slug>
164
- <wp:term_parent><?php echo $this->mptt_cdata($t->parent ? $terms[$t->parent]->slug : ''); ?></wp:term_parent><?php $this->mptt_term_name($t); ?><?php $this->mptt_term_description($t); ?> </wp:term>
165
- <?php endforeach; ?>
166
-
167
-
168
- <?php
169
- /** This action is documented in wp-includes/feed-rss2.php */
170
- do_action('rss2_head');
171
- ?>
172
-
173
- <?php if ($post_ids) {
174
- /**
175
- * @global WP_Query $wp_query
176
- */
177
- global $wp_query;
178
-
179
- // Fake being in the loop.
180
- $wp_query->in_the_loop = true;
181
-
182
- // Fetch 20 posts at a time rather than loading the entire table into memory.
183
- while ($next_posts = array_splice($post_ids, 0, 20)) {
184
- $where = 'WHERE ID IN (' . join(',', $next_posts) . ')';
185
- $posts = $wpdb->get_results("SELECT * FROM {$wpdb->posts} $where");
186
-
187
- // Begin Loop.
188
- foreach ($posts as $post) {
189
- setup_postdata($post);
190
- $is_sticky = is_sticky($post->ID) ? 1 : 0; ?>
191
- <item>
192
- <title><?php
193
- /** This filter is documented in wp-includes/feed.php */
194
- echo apply_filters('the_title_rss', $post->post_title); ?></title>
195
- <link><?php the_permalink_rss() ?></link>
196
- <pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_post_time('Y-m-d H:i:s', true), false); ?></pubDate>
197
- <dc:creator><?php echo $this->mptt_cdata(get_the_author_meta('login')); ?></dc:creator>
198
- <guid isPermaLink="false"><?php the_guid(); ?></guid>
199
- <description></description>
200
- <content:encoded><?php
201
- /**
202
- * Filter the post content used for WXR exports.
203
- *
204
- * @since 2.5.0
205
- *
206
- * @param string $post_content Content of the current post.
207
- */
208
- echo $this->mptt_cdata(apply_filters('the_content_export', $post->post_content));
209
- ?></content:encoded>
210
- <excerpt:encoded><?php
211
- /**
212
- * Filter the post excerpt used for WXR exports.
213
- *
214
- * @since 2.6.0
215
- *
216
- * @param string $post_excerpt Excerpt for the current post.
217
- */
218
- echo $this->mptt_cdata(apply_filters('the_excerpt_export', $post->post_excerpt));
219
- ?></excerpt:encoded>
220
- <wp:post_id><?php echo intval($post->ID); ?></wp:post_id>
221
- <wp:post_date><?php echo $this->mptt_cdata($post->post_date); ?></wp:post_date>
222
- <wp:post_date_gmt><?php echo $this->mptt_cdata($post->post_date_gmt); ?></wp:post_date_gmt>
223
- <wp:comment_status><?php echo $this->mptt_cdata($post->comment_status); ?></wp:comment_status>
224
- <wp:ping_status><?php echo $this->mptt_cdata($post->ping_status); ?></wp:ping_status>
225
- <wp:post_name><?php echo $this->mptt_cdata($post->post_name); ?></wp:post_name>
226
- <wp:status><?php echo $this->mptt_cdata($post->post_status); ?></wp:status>
227
- <wp:post_parent><?php echo intval($post->post_parent); ?></wp:post_parent>
228
- <wp:menu_order><?php echo intval($post->menu_order); ?></wp:menu_order>
229
- <wp:post_type><?php echo $this->mptt_cdata($post->post_type); ?></wp:post_type>
230
- <wp:post_password><?php echo $this->mptt_cdata($post->post_password); ?></wp:post_password>
231
- <wp:is_sticky><?php echo intval($is_sticky); ?></wp:is_sticky>
232
- <?php if ($post->post_type == 'attachment') : ?>
233
- <wp:attachment_url><?php echo $this->mptt_cdata(wp_get_attachment_url($post->ID)); ?></wp:attachment_url>
234
- <?php endif; ?>
235
- <?php $this->mptt_post_taxonomy(); ?>
236
-
237
- <?php $postmeta = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE post_id = %d", $post->ID));
238
- foreach ($postmeta as $meta) :
239
- /**
240
- * Filter whether to selectively skip post meta used for WXR exports.
241
- *
242
- * Returning a truthy value to the filter will skip the current meta
243
- * object from being exported.
244
- *
245
- * @since 3.3.0
246
- *
247
- * @param bool $skip Whether to skip the current post meta. Default false.
248
- * @param string $meta_key Current meta key.
249
- * @param object $meta Current meta object.
250
- */
251
- if (apply_filters('mptt_export_skip_postmeta', false, $meta->meta_key, $meta))
252
- continue;
253
- ?>
254
- <wp:postmeta>
255
- <wp:meta_key><?php echo $this->mptt_cdata($meta->meta_key); ?></wp:meta_key>
256
- <wp:meta_value><?php echo $this->mptt_cdata($meta->meta_value); ?></wp:meta_value>
257
- </wp:postmeta>
258
- <?php endforeach; ?>
259
- <?php
260
-
261
- $_comments = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved <> 'spam'", $post->ID));
262
- $comments = array_map('get_comment', $_comments);
263
- foreach ($comments as $c) : ?>
264
- <wp:comment>
265
- <wp:comment_id><?php echo intval($c->comment_ID); ?></wp:comment_id>
266
- <wp:comment_author><?php echo $this->mptt_cdata($c->comment_author); ?></wp:comment_author>
267
- <wp:comment_author_email><?php echo $this->mptt_cdata($c->comment_author_email); ?></wp:comment_author_email>
268
- <wp:comment_author_url><?php echo esc_url_raw($c->comment_author_url); ?></wp:comment_author_url>
269
- <wp:comment_author_IP><?php echo $this->mptt_cdata($c->comment_author_IP); ?></wp:comment_author_IP>
270
- <wp:comment_date><?php echo $this->mptt_cdata($c->comment_date); ?></wp:comment_date>
271
- <wp:comment_date_gmt><?php echo $this->mptt_cdata($c->comment_date_gmt); ?></wp:comment_date_gmt>
272
- <wp:comment_content><?php echo $this->mptt_cdata($c->comment_content) ?></wp:comment_content>
273
- <wp:comment_approved><?php echo $this->mptt_cdata($c->comment_approved); ?></wp:comment_approved>
274
- <wp:comment_type><?php echo $this->mptt_cdata($c->comment_type); ?></wp:comment_type>
275
- <wp:comment_parent><?php echo intval($c->comment_parent); ?></wp:comment_parent>
276
- <wp:comment_user_id><?php echo intval($c->user_id); ?></wp:comment_user_id>
277
- <?php $c_meta = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->commentmeta WHERE comment_id = %d", $c->comment_ID));
278
- foreach ($c_meta as $meta) :
279
- /**
280
- * Filter whether to selectively skip comment meta used for WXR exports.
281
- *
282
- * Returning a truthy value to the filter will skip the current meta
283
- * object from being exported.
284
- *
285
- * @since 4.0.0
286
- *
287
- * @param bool $skip Whether to skip the current comment meta. Default false.
288
- * @param string $meta_key Current meta key.
289
- * @param object $meta Current meta object.
290
- */
291
- if (apply_filters('mptt_export_skip_commentmeta', false, $meta->meta_key, $meta)) {
292
- continue;
293
- }
294
- ?>
295
- <wp:commentmeta>
296
- <wp:meta_key><?php echo $this->mptt_cdata($meta->meta_key); ?></wp:meta_key>
297
- <wp:meta_value><?php echo $this->mptt_cdata($meta->meta_value); ?></wp:meta_value>
298
- </wp:commentmeta>
299
- <?php endforeach; ?>
300
- </wp:comment>
301
- <?php endforeach; ?>
302
- </item>
303
- <?php
304
- }
305
- }
306
-
307
- }
308
- $time_slots = $wpdb->get_results("SELECT * FROM $this->table WHERE 1");
309
- if (!empty($time_slots)) {
310
- foreach ($time_slots as $time_slot) : ?>
311
- <timeslot>
312
- <column><?php echo $this->mptt_cdata($time_slot->column_id); ?></column>
313
- <event><?php echo $this->mptt_cdata($time_slot->event_id); ?></event>
314
- <event_start><?php echo $this->mptt_cdata($time_slot->event_start); ?></event_start>
315
- <event_end><?php echo $this->mptt_cdata($time_slot->event_end); ?></event_end>
316
- <user_id><?php echo $this->mptt_cdata($time_slot->user_id); ?></user_id>
317
- <description><?php echo $this->mptt_cdata($time_slot->description); ?></description>
318
- </timeslot>
319
- <?php endforeach;
320
- }
321
- ?>
322
- </channel>
323
- </rss>
324
- <?php
325
- }
326
-
327
- /**
328
- * Generate file name
329
- * @return mixed|void
330
- */
331
- public function file_name() {
332
- $sitename = sanitize_key(get_bloginfo('name'));
333
- if (!empty($sitename)) {
334
- $sitename .= '_';
335
- }
336
- $date = date('d.m.Y_H.i', time());
337
-
338
- $wp_filename = $sitename . 'timetable_' . $date . '.xml';
339
- /**
340
- * Filter the export filename.
341
- *
342
- * @since 4.4.0
343
- *
344
- * @param string $wp_filename The name of the file for download.
345
- * @param string $sitename The site name.
346
- * @param string $date Today's date, formatted.
347
- */
348
- $filename = apply_filters('export_wp_filename', $wp_filename, $sitename, $date);
349
- return $filename;
350
- }
351
-
352
- /**
353
- * Output list of authors with posts
354
- *
355
- * @since 3.1.0
356
- *
357
- * @global wpdb $wpdb WordPress database abstraction object.
358
- *
359
- * @param array $post_ids Array of post IDs to filter the query by. Optional.
360
- */
361
- public function mptt_authors_list(array $post_ids = null) {
362
- global $wpdb;
363
-
364
- if (!empty($post_ids)) {
365
- $post_ids = array_map('absint', $post_ids);
366
- $and = 'AND ID IN ( ' . implode(', ', $post_ids) . ')';
367
- } else {
368
- $and = '';
369
- }
370
-
371
- $authors = array();
372
- $results = $wpdb->get_results("SELECT DISTINCT post_author FROM $wpdb->posts WHERE post_status != 'auto-draft' $and");
373
- foreach ((array)$results as $result)
374
- $authors[] = get_userdata($result->post_author);
375
-
376
- $authors = array_filter($authors);
377
-
378
- foreach ($authors as $author) {
379
- echo "\t<wp:author>";
380
- echo '<wp:author_id>' . intval($author->ID) . '</wp:author_id>';
381
- echo '<wp:author_login>' . $this->mptt_cdata($author->user_login) . '</wp:author_login>';
382
- echo '<wp:author_email>' . $this->mptt_cdata($author->user_email) . '</wp:author_email>';
383
- echo '<wp:author_display_name>' . $this->mptt_cdata($author->display_name) . '</wp:author_display_name>';
384
- echo '<wp:author_first_name>' . $this->mptt_cdata($author->first_name) . '</wp:author_first_name>';
385
- echo '<wp:author_last_name>' . $this->mptt_cdata($author->last_name) . '</wp:author_last_name>';
386
- echo "</wp:author>\n";
387
- }
388
- }
389
-
390
- /**
391
- * Return the URL of the site
392
- *
393
- * @since 2.5.0
394
- *
395
- * @return string Site URL.
396
- */
397
- public function mptt_site_url() {
398
- // Multisite: the base URL.
399
- if (is_multisite())
400
- return network_home_url();
401
- // WordPress (single site): the blog URL.
402
- else
403
- return get_bloginfo_rss('url');
404
- }
405
-
406
- /**
407
- * Output a term_description XML tag from a given term object
408
- *
409
- * @since 2.9.0
410
- *
411
- * @param object $term Term Object
412
- */
413
- public function mptt_term_description($term) {
414
- if (empty($term->description))
415
- return;
416
-
417
- echo '<wp:term_description>' . $this->mptt_cdata($term->description) . '</wp:term_description>';
418
- }
419
-
420
- /**
421
- * Output a term_name XML tag from a given term object
422
- *
423
- * @since 2.9.0
424
- *
425
- * @param object $term Term Object
426
- */
427
- public function mptt_term_name($term) {
428
- if (empty($term->name))
429
- return;
430
-
431
- echo '<wp:term_name>' . $this->mptt_cdata($term->name) . '</wp:term_name>';
432
- }
433
-
434
- /**
435
- * Wrap given string in XML CDATA tag.
436
- *
437
- * @since 2.1.0
438
- *
439
- * @param string $str String to wrap in XML CDATA tag.
440
- *
441
- * @return string
442
- */
443
- public function mptt_cdata($str) {
444
- if (!seems_utf8($str)) {
445
- $str = utf8_encode($str);
446
- }
447
- // $str = ent2ncr(esc_html($str));
448
- $str = '<![CDATA[' . str_replace(']]>', ']]]]><![CDATA[>', $str) . ']]>';
449
-
450
- return $str;
451
- }
452
-
453
- /**
454
- *
455
- * @param bool $return_me
456
- * @param string $meta_key
457
- *
458
- * @return bool
459
- */
460
- public function mptt_filter_postmeta($return_me, $meta_key) {
461
- if ('_edit_lock' == $meta_key)
462
- $return_me = true;
463
- return $return_me;
464
- }
465
-
466
- /**
467
- * Output list of taxonomy terms, in XML tag format, associated with a post
468
- *
469
- * @since 2.3.0
470
- */
471
- public function mptt_post_taxonomy() {
472
- $post = get_post();
473
-
474
- $taxonomies = get_object_taxonomies($post->post_type);
475
- if (empty($taxonomies))
476
- return;
477
- $terms = wp_get_object_terms($post->ID, $taxonomies);
478
-
479
- foreach ((array)$terms as $term) {
480
- echo "\t\t<category domain=\"{$term->taxonomy}\" nicename=\"{$term->slug}\">" . $this->mptt_cdata($term->name) . "</category>\n";
481
- }
482
- }
483
  }
1
+ <?php
2
+ namespace mp_timetable\classes\models;
3
+
4
+ use mp_timetable\classes\libs;
5
+ use mp_timetable\plugin_core\classes\Model as Model;
6
+
7
+ /**
8
+ * Export model
9
+ */
10
+ class Export extends Model {
11
+ protected static $instance;
12
+ private $table;
13
+
14
+ public static function get_instance() {
15
+ if (null === self::$instance) {
16
+ self::$instance = new self();
17
+ }
18
+ return self::$instance;
19
+ }
20
+
21
+ function __construct() {
22
+ $this->table = Events::get_instance()->table_name;
23
+ parent::__construct();
24
+ }
25
+
26
+ /**
27
+ * Export file
28
+ */
29
+ public function export() {
30
+
31
+ global $wpdb, $post;
32
+
33
+ if ( !defined('ABSPATH') ) exit;
34
+
35
+ if ( !current_user_can('export') ) exit;
36
+
37
+ if ( !function_exists('export_wp') ) {
38
+ include_once(ABSPATH . 'wp-admin/includes/export.php');
39
+ }
40
+
41
+ $args = array('content' => $this->post_types, 'author' => false, 'category' => false,
42
+ 'start_date' => false, 'end_date' => false, 'status' => false);
43
+
44
+
45
+ $defaults = array('content' => 'all', 'author' => false, 'category' => false,
46
+ 'start_date' => false, 'end_date' => false, 'status' => false,
47
+ );
48
+ $args = wp_parse_args($args, $defaults);
49
+
50
+ /**
51
+ * Fires at the beginning of an export, before any headers are sent.
52
+ *
53
+ * @since 2.3.0
54
+ *
55
+ * @param array $args An array of export arguments.
56
+ */
57
+ do_action('export_wp', $args);
58
+
59
+ $filename = $this->file_name();
60
+
61
+ header('Content-Description: File Transfer');
62
+ header('Content-Disposition: attachment; filename=' . $filename);
63
+ header('Content-Type: text/xml; charset=' . get_option('blog_charset'), true);
64
+
65
+ if ('all' != $args['content'] && post_type_exists($args['content'])) {
66
+ $ptype = get_post_type_object($args['content']);
67
+ if (!$ptype->can_export)
68
+ $args['content'] = 'post';
69
+
70
+ $where = $wpdb->prepare("{$wpdb->posts}.post_type = %s", $args['content']);
71
+ } else {
72
+ $post_types = get_post_types(array('can_export' => true));
73
+ $post_types = array_intersect($post_types, $args['content']);
74
+ $esses = array_fill(0, count($post_types), '%s');
75
+ $where = $wpdb->prepare("{$wpdb->posts}.post_type IN (" . implode(',', $esses) . ')', $post_types);
76
+ }
77
+
78
+ if ($args['status'] && ('post' == $args['content'] || 'page' == $args['content']))
79
+ $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_status = %s", $args['status']);
80
+ else
81
+ $where .= " AND {$wpdb->posts}.post_status != 'auto-draft'";
82
+
83
+ $join = '';
84
+ if ($args['category'] && 'post' == $args['content']) {
85
+ if ($term = term_exists($args['category'], 'category')) {
86
+ $join = "INNER JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)";
87
+ $where .= $wpdb->prepare(" AND {$wpdb->term_relationships}.term_taxonomy_id = %d", $term['term_taxonomy_id']);
88
+ }
89
+ }
90
+
91
+ if ('post' == $args['content'] || 'page' == $args['content'] || 'attachment' == $args['content']) {
92
+ if ($args['author'])
93
+ $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_author = %d", $args['author']);
94
+
95
+ if ($args['start_date'])
96
+ $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_date >= %s", date('Y-m-d', strtotime($args['start_date'])));
97
+
98
+ if ($args['end_date'])
99
+ $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_date < %s", date('Y-m-d', strtotime('+1 month', strtotime($args['end_date']))));
100
+ }
101
+
102
+ // Grab a snapshot of post IDs, just in case it changes during the export.
103
+ $post_ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} $join WHERE $where");
104
+
105
+ /*
106
+ * Get the requested terms ready, empty unless posts filtered by category
107
+ * or all content.
108
+ */
109
+ $thumbnail_ids = array();
110
+ foreach ($post_ids as $ID) {
111
+ $thumbnail_id = get_post_thumbnail_id($ID);
112
+ if (empty($thumbnail_id)) {
113
+ continue;
114
+ }
115
+ $thumbnail_ids[] = $thumbnail_id;
116
+ }
117
+ if (!empty($thumbnail_ids)) {
118
+ $post_ids = array_merge($post_ids, $thumbnail_ids);
119
+ }
120
+ $cats = $tags = $terms = array();
121
+
122
+ if (!empty($this->taxonomy_names)) {
123
+ $custom_taxonomies = get_taxonomies(array('_builtin' => false));
124
+ $custom_terms = (array)get_terms($this->taxonomy_names, array('get' => 'all'));
125
+
126
+ // Put terms in order with no child going before its parent.
127
+ while ($t = array_shift($custom_terms)) {
128
+ if ($t->parent == 0 || isset($terms[$t->parent]))
129
+ $terms[$t->term_id] = $t;
130
+ else
131
+ $custom_terms[] = $t;
132
+ }
133
+
134
+ unset($categories, $custom_taxonomies, $custom_terms);
135
+ }
136
+
137
+ add_filter('mptt_export_skip_postmeta', array($this, 'mptt_filter_postmeta'), 10, 2);
138
+
139
+ echo '<?xml version="1.0" encoding="' . get_bloginfo('charset') . "\" ?>\n"; ?>
140
+ <?php the_generator('export'); ?>
141
+
142
+ <rss version="2.0"
143
+ xmlns:excerpt="http://wordpress.org/export/<?php echo WXR_VERSION; ?>/excerpt/"
144
+ xmlns:content="http://purl.org/rss/1.0/modules/content/"
145
+ xmlns:wfw="http://wellformedweb.org/CommentAPI/"
146
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
147
+ xmlns:wp="http://wordpress.org/export/<?php echo WXR_VERSION; ?>/">
148
+ <channel>
149
+ <title><?php bloginfo_rss('name'); ?></title>
150
+ <link><?php bloginfo_rss('url'); ?></link>
151
+ <description><?php bloginfo_rss('description'); ?></description>
152
+ <pubDate><?php echo date('D, d M Y H:i:s +0000'); ?></pubDate>
153
+ <language><?php bloginfo_rss('language'); ?></language>
154
+ <wp:wxr_version><?php echo WXR_VERSION; ?></wp:wxr_version>
155
+ <wp:base_site_url><?php echo $this->mptt_site_url(); ?></wp:base_site_url>
156
+ <wp:base_blog_url><?php bloginfo_rss('url'); ?></wp:base_blog_url>
157
+
158
+ <?php $this->mptt_authors_list($post_ids); ?>
159
+ <?php foreach ($terms as $t) : ?>
160
+ <wp:term>
161
+ <wp:term_id><?php echo $this->mptt_cdata($t->term_id); ?></wp:term_id>
162
+ <wp:term_taxonomy><?php echo $this->mptt_cdata($t->taxonomy); ?></wp:term_taxonomy>
163
+ <wp:term_slug><?php echo $this->mptt_cdata($t->slug); ?></wp:term_slug>
164
+ <wp:term_parent><?php echo $this->mptt_cdata($t->parent ? $terms[$t->parent]->slug : ''); ?></wp:term_parent><?php $this->mptt_term_name($t); ?><?php $this->mptt_term_description($t); ?> </wp:term>
165
+ <?php endforeach; ?>
166
+
167
+
168
+ <?php
169
+ /** This action is documented in wp-includes/feed-rss2.php */
170
+ do_action('rss2_head');
171
+ ?>
172
+
173
+ <?php if ($post_ids) {
174
+ /**
175
+ * @global WP_Query $wp_query
176
+ */
177
+ global $wp_query;
178
+
179
+ // Fake being in the loop.
180
+ $wp_query->in_the_loop = true;
181
+
182
+ // Fetch 20 posts at a time rather than loading the entire table into memory.
183
+ while ($next_posts = array_splice($post_ids, 0, 20)) {
184
+ $where = 'WHERE ID IN (' . join(',', $next_posts) . ')';
185
+ $posts = $wpdb->get_results("SELECT * FROM {$wpdb->posts} $where");
186
+
187
+ // Begin Loop.
188
+ foreach ($posts as $post) {
189
+ setup_postdata($post);
190
+ $is_sticky = is_sticky($post->ID) ? 1 : 0; ?>
191
+ <item>
192
+ <title><?php
193
+ /** This filter is documented in wp-includes/feed.php */
194
+ echo apply_filters('the_title_rss', $post->post_title); ?></title>
195
+ <link><?php the_permalink_rss() ?></link>
196
+ <pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_post_time('Y-m-d H:i:s', true), false); ?></pubDate>
197
+ <dc:creator><?php echo $this->mptt_cdata(get_the_author_meta('login')); ?></dc:creator>
198
+ <guid isPermaLink="false"><?php the_guid(); ?></guid>
199
+ <description></description>
200
+ <content:encoded><?php
201
+ /**
202
+ * Filter the post content used for WXR exports.
203
+ *
204
+ * @since 2.5.0
205
+ *
206
+ * @param string $post_content Content of the current post.
207
+ */
208
+ echo $this->mptt_cdata(apply_filters('the_content_export', $post->post_content));
209
+ ?></content:encoded>
210
+ <excerpt:encoded><?php
211
+ /**
212
+ * Filter the post excerpt used for WXR exports.
213
+ *
214
+ * @since 2.6.0
215
+ *
216
+ * @param string $post_excerpt Excerpt for the current post.
217
+ */
218
+ echo $this->mptt_cdata(apply_filters('the_excerpt_export', $post->post_excerpt));
219
+ ?></excerpt:encoded>
220
+ <wp:post_id><?php echo intval($post->ID); ?></wp:post_id>
221
+ <wp:post_date><?php echo $this->mptt_cdata($post->post_date); ?></wp:post_date>
222
+ <wp:post_date_gmt><?php echo $this->mptt_cdata($post->post_date_gmt); ?></wp:post_date_gmt>
223
+ <wp:comment_status><?php echo $this->mptt_cdata($post->comment_status); ?></wp:comment_status>
224
+ <wp:ping_status><?php echo $this->mptt_cdata($post->ping_status); ?></wp:ping_status>
225
+ <wp:post_name><?php echo $this->mptt_cdata($post->post_name); ?></wp:post_name>
226
+ <wp:status><?php echo $this->mptt_cdata($post->post_status); ?></wp:status>
227
+ <wp:post_parent><?php echo intval($post->post_parent); ?></wp:post_parent>
228
+ <wp:menu_order><?php echo intval($post->menu_order); ?></wp:menu_order>
229
+ <wp:post_type><?php echo $this->mptt_cdata($post->post_type); ?></wp:post_type>
230
+ <wp:post_password><?php echo $this->mptt_cdata($post->post_password); ?></wp:post_password>
231
+ <wp:is_sticky><?php echo intval($is_sticky); ?></wp:is_sticky>
232
+ <?php if ($post->post_type == 'attachment') : ?>
233
+ <wp:attachment_url><?php echo $this->mptt_cdata(wp_get_attachment_url($post->ID)); ?></wp:attachment_url>
234
+ <?php endif; ?>
235
+ <?php $this->mptt_post_taxonomy(); ?>
236
+
237
+ <?php $postmeta = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE post_id = %d", $post->ID));
238
+ foreach ($postmeta as $meta) :
239
+ /**
240
+ * Filter whether to selectively skip post meta used for WXR exports.
241
+ *
242
+ * Returning a truthy value to the filter will skip the current meta
243
+ * object from being exported.
244
+ *
245
+ * @since 3.3.0
246
+ *
247
+ * @param bool $skip Whether to skip the current post meta. Default false.
248
+ * @param string $meta_key Current meta key.
249
+ * @param object $meta Current meta object.
250
+ */
251
+ if (apply_filters('mptt_export_skip_postmeta', false, $meta->meta_key, $meta))
252
+ continue;
253
+ ?>
254
+ <wp:postmeta>
255
+ <wp:meta_key><?php echo $this->mptt_cdata($meta->meta_key); ?></wp:meta_key>
256
+ <wp:meta_value><?php echo $this->mptt_cdata($meta->meta_value); ?></wp:meta_value>
257
+ </wp:postmeta>
258
+ <?php endforeach; ?>
259
+ <?php
260
+
261
+ $_comments = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved <> 'spam'", $post->ID));
262
+ $comments = array_map('get_comment', $_comments);
263
+ foreach ($comments as $c) : ?>
264
+ <wp:comment>
265
+ <wp:comment_id><?php echo intval($c->comment_ID); ?></wp:comment_id>
266
+ <wp:comment_author><?php echo $this->mptt_cdata($c->comment_author); ?></wp:comment_author>
267
+ <wp:comment_author_email><?php echo $this->mptt_cdata($c->comment_author_email); ?></wp:comment_author_email>
268
+ <wp:comment_author_url><?php echo esc_url_raw($c->comment_author_url); ?></wp:comment_author_url>
269
+ <wp:comment_author_IP><?php echo $this->mptt_cdata($c->comment_author_IP); ?></wp:comment_author_IP>
270
+ <wp:comment_date><?php echo $this->mptt_cdata($c->comment_date); ?></wp:comment_date>
271
+ <wp:comment_date_gmt><?php echo $this->mptt_cdata($c->comment_date_gmt); ?></wp:comment_date_gmt>
272
+ <wp:comment_content><?php echo $this->mptt_cdata($c->comment_content) ?></wp:comment_content>
273
+ <wp:comment_approved><?php echo $this->mptt_cdata($c->comment_approved); ?></wp:comment_approved>
274
+ <wp:comment_type><?php echo $this->mptt_cdata($c->comment_type); ?></wp:comment_type>
275
+ <wp:comment_parent><?php echo intval($c->comment_parent); ?></wp:comment_parent>
276
+ <wp:comment_user_id><?php echo intval($c->user_id); ?></wp:comment_user_id>
277
+ <?php $c_meta = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->commentmeta WHERE comment_id = %d", $c->comment_ID));
278
+ foreach ($c_meta as $meta) :
279
+ /**
280
+ * Filter whether to selectively skip comment meta used for WXR exports.
281
+ *
282
+ * Returning a truthy value to the filter will skip the current meta
283
+ * object from being exported.
284
+ *
285
+ * @since 4.0.0
286
+ *
287
+ * @param bool $skip Whether to skip the current comment meta. Default false.
288
+ * @param string $meta_key Current meta key.
289
+ * @param object $meta Current meta object.
290
+ */
291
+ if (apply_filters('mptt_export_skip_commentmeta', false, $meta->meta_key, $meta)) {
292
+ continue;
293
+ }
294
+ ?>
295
+ <wp:commentmeta>
296
+ <wp:meta_key><?php echo $this->mptt_cdata($meta->meta_key); ?></wp:meta_key>
297
+ <wp:meta_value><?php echo $this->mptt_cdata($meta->meta_value); ?></wp:meta_value>
298
+ </wp:commentmeta>
299
+ <?php endforeach; ?>
300
+ </wp:comment>
301
+ <?php endforeach; ?>
302
+ </item>
303
+ <?php
304
+ }
305
+ }
306
+
307
+ }
308
+ $time_slots = $wpdb->get_results("SELECT * FROM $this->table WHERE 1");
309
+ if (!empty($time_slots)) {
310
+ foreach ($time_slots as $time_slot) : ?>
311
+ <timeslot>
312
+ <column><?php echo $this->mptt_cdata($time_slot->column_id); ?></column>
313
+ <event><?php echo $this->mptt_cdata($time_slot->event_id); ?></event>
314
+ <event_start><?php echo $this->mptt_cdata($time_slot->event_start); ?></event_start>
315
+ <event_end><?php echo $this->mptt_cdata($time_slot->event_end); ?></event_end>
316
+ <user_id><?php echo $this->mptt_cdata($time_slot->user_id); ?></user_id>
317
+ <description><?php echo $this->mptt_cdata($time_slot->description); ?></description>
318
+ </timeslot>
319
+ <?php endforeach;
320
+ }
321
+ ?>
322
+ </channel>
323
+ </rss>
324
+ <?php
325
+ }
326
+
327
+ /**
328
+ * Generate file name
329
+ * @return mixed|void
330
+ */
331
+ public function file_name() {
332
+ $sitename = sanitize_key(get_bloginfo('name'));
333
+ if (!empty($sitename)) {
334
+ $sitename .= '_';
335
+ }
336
+ $date = date('d.m.Y_H.i', time());
337
+
338
+ $wp_filename = $sitename . 'timetable_' . $date . '.xml';
339
+ /**
340
+ * Filter the export filename.
341
+ *
342
+ * @since 4.4.0
343
+ *
344
+ * @param string $wp_filename The name of the file for download.
345
+ * @param string $sitename The site name.
346
+ * @param string $date Today's date, formatted.
347
+ */
348
+ $filename = apply_filters('export_wp_filename', $wp_filename, $sitename, $date);
349
+ return $filename;
350
+ }
351
+
352
+ /**
353
+ * Output list of authors with posts
354
+ *
355
+ * @since 3.1.0
356
+ *
357
+ * @global wpdb $wpdb WordPress database abstraction object.
358
+ *
359
+ * @param array $post_ids Array of post IDs to filter the query by. Optional.
360
+ */
361
+ public function mptt_authors_list(array $post_ids = null) {
362
+ global $wpdb;
363
+
364
+ if (!empty($post_ids)) {
365
+ $post_ids = array_map('absint', $post_ids);
366
+ $and = 'AND ID IN ( ' . implode(', ', $post_ids) . ')';
367
+ } else {
368
+ $and = '';
369
+ }
370
+
371
+ $authors = array();
372
+ $results = $wpdb->get_results("SELECT DISTINCT post_author FROM $wpdb->posts WHERE post_status != 'auto-draft' $and");
373
+ foreach ((array)$results as $result)
374
+ $authors[] = get_userdata($result->post_author);
375
+
376
+ $authors = array_filter($authors);
377
+
378
+ foreach ($authors as $author) {
379
+ echo "\t<wp:author>";
380
+ echo '<wp:author_id>' . intval($author->ID) . '</wp:author_id>';
381
+ echo '<wp:author_login>' . $this->mptt_cdata($author->user_login) . '</wp:author_login>';
382
+ echo '<wp:author_email>' . $this->mptt_cdata($author->user_email) . '</wp:author_email>';
383
+ echo '<wp:author_display_name>' . $this->mptt_cdata($author->display_name) . '</wp:author_display_name>';
384
+ echo '<wp:author_first_name>' . $this->mptt_cdata($author->first_name) . '</wp:author_first_name>';
385
+ echo '<wp:author_last_name>' . $this->mptt_cdata($author->last_name) . '</wp:author_last_name>';
386
+ echo "</wp:author>\n";
387
+ }
388
+ }
389
+
390
+ /**
391
+ * Return the URL of the site
392
+ *
393
+ * @since 2.5.0
394
+ *
395
+ * @return string Site URL.
396
+ */
397
+ public function mptt_site_url() {
398
+ // Multisite: the base URL.
399
+ if (is_multisite())
400
+ return network_home_url();
401
+ // WordPress (single site): the blog URL.
402
+ else
403
+ return get_bloginfo_rss('url');
404
+ }
405
+
406
+ /**
407
+ * Output a term_description XML tag from a given term object
408
+ *
409
+ * @since 2.9.0
410
+ *
411
+ * @param object $term Term Object
412
+ */
413
+ public function mptt_term_description($term) {
414
+ if (empty($term->description))
415
+ return;
416
+
417
+ echo '<wp:term_description>' . $this->mptt_cdata($term->description) . '</wp:term_description>';
418
+ }
419
+
420
+ /**
421
+ * Output a term_name XML tag from a given term object
422
+ *
423
+ * @since 2.9.0
424
+ *
425
+ * @param object $term Term Object
426
+ */
427
+ public function mptt_term_name($term) {
428
+ if (empty($term->name))
429
+ return;
430
+
431
+ echo '<wp:term_name>' . $this->mptt_cdata($term->name) . '</wp:term_name>';
432
+ }
433
+
434
+ /**
435
+ * Wrap given string in XML CDATA tag.
436
+ *
437
+ * @since 2.1.0
438
+ *
439
+ * @param string $str String to wrap in XML CDATA tag.
440
+ *
441
+ * @return string
442
+ */
443
+ public function mptt_cdata($str) {
444
+ if (!seems_utf8($str)) {
445
+ $str = utf8_encode($str);
446
+ }
447
+ // $str = ent2ncr(esc_html($str));
448
+ $str = '<![CDATA[' . str_replace(']]>', ']]]]><![CDATA[>', $str) . ']]>';
449
+
450
+ return $str;
451
+ }
452
+
453
+ /**
454
+ *
455
+ * @param bool $return_me
456
+ * @param string $meta_key
457
+ *
458
+ * @return bool
459
+ */
460
+ public function mptt_filter_postmeta($return_me, $meta_key) {
461
+ if ('_edit_lock' == $meta_key)
462
+ $return_me = true;
463
+ return $return_me;
464
+ }
465
+
466
+ /**
467
+ * Output list of taxonomy terms, in XML tag format, associated with a post
468
+ *
469
+ * @since 2.3.0
470
+ */
471
+ public function mptt_post_taxonomy() {
472
+ $post = get_post();
473
+
474
+ $taxonomies = get_object_taxonomies($post->post_type);
475
+ if (empty($taxonomies))
476
+ return;
477
+ $terms = wp_get_object_terms($post->ID, $taxonomies);
478
+
479
+ foreach ((array)$terms as $term) {
480
+ echo "\t\t<category domain=\"{$term->taxonomy}\" nicename=\"{$term->slug}\">" . $this->mptt_cdata($term->name) . "</category>\n";
481
+ }
482
+ }
483
  }
classes/models/class-import.php CHANGED
@@ -1,968 +1,968 @@
1
- <?php
2
- namespace mp_timetable\classes\models;
3
-
4
- use mp_timetable\classes\libs;
5
- use mp_timetable\plugin_core\classes\Model as Model;
6
- use mp_timetable\plugin_core\classes\View as View;
7
-
8
- /**
9
- * Model Events
10
- */
11
- class Import extends Model {
12
-
13
- protected static $instance;
14
- protected $table;
15
- var $max_wxr_version = 1.2; // max. supported WXR version
16
- var $id; // WXR attachment ID
17
- var $file;
18
-
19
- var $import_data;
20
- // information to import from WXR file
21
- var $version;
22
- var $authors = array();
23
- var $posts = array();
24
- var $terms = array();
25
- var $time_slots = array();
26
- var $categories = array();
27
- var $tags = array();
28
- var $base_url = '';
29
-
30
- var $processed_authors = array();
31
- var $author_mapping = array();
32
- var $processed_terms = array();
33
- var $processed_posts = array();
34
- var $post_orphans = array();
35
- var $processed_menu_items = array();
36
- var $menu_item_orphans = array();
37
- var $missing_menu_items = array();
38
-
39
- var $fetch_attachments = false;
40
- var $url_remap = array();
41
- var $featured_images = array();
42
-
43
- public static function get_instance() {
44
- if (null === self::$instance) {
45
- self::$instance = new self();
46
- }
47
- return self::$instance;
48
- }
49
-
50
- function __construct() {
51
- parent::__construct();
52
- $this->table = Events::get_instance()->table_name;
53
- }
54
-
55
- /**
56
- *
57
- * @param bool $return_me
58
- * @param string $meta_key
59
- *
60
- * @return bool
61
- */
62
- public function mptt_filter_postmeta($return_me, $meta_key) {
63
- if ('_edit_lock' == $meta_key)
64
- $return_me = true;
65
- return $return_me;
66
- }
67
-
68
- /**
69
- * Exist time slot
70
- *
71
- * @param array $time_slot
72
- *
73
- * @return bool
74
- */
75
- public function post_time_slot_exist($time_slot = array()) {
76
- global $wpdb;
77
- if (empty($time_slot)) {
78
- return false;
79
- }
80
- $data = $wpdb->get_results('SELECT id FROM ' . $this->table . ' WHERE column_id = "' . $time_slot['column'] . '" AND event_id = "' . $time_slot['event'] . '" AND event_start = "' . $time_slot['event_start'] . '" AND event_end = "' . $time_slot['event_end'] . '"');
81
- return empty($data) ? false : true;
82
- }
83
-
84
- public function header() {
85
- View::get_instance()->render_html('../admin/import/header');
86
- }
87
-
88
- public function footer() {
89
- View::get_instance()->render_html('../admin/import/footer');
90
- }
91
-
92
- public function greet() {
93
- View::get_instance()->render_html('../admin/import/greet');
94
- }
95
-
96
- /**
97
- * Decide whether or not the importer is allowed to create users.
98
- * Default is true, can be filtered via import_allow_create_users
99
- *
100
- * @return bool True if creating users is allowed
101
- */
102
- public function allow_create_users() {
103
- return apply_filters('import_allow_create_users', true);
104
- }
105
-
106
- /**
107
- * Decide whether or not the importer should attempt to download attachment files.
108
- * Default is true, can be filtered via import_allow_fetch_attachments. The choice
109
- * made at the import options screen must also be true, false here hides that checkbox.
110
- *
111
- * @return bool True if downloading attachments is allowed
112
- */
113
- public function allow_fetch_attachments() {
114
- return apply_filters('import_allow_fetch_attachments', true);
115
- }
116
-
117
- public function import_options() {
118
- $j = 0;
119
- ?>
120
- <form action="<?php echo admin_url('admin.php?import=mptt-importer&amp;step=2'); ?>" method="post">
121
- <?php wp_nonce_field('mptt-importer'); ?>
122
- <input type="hidden" name="import_id" value="<?php echo esc_attr( $this->id ); ?>"/>
123
-
124
- <?php if (!empty($this->authors)) : ?>
125
- <h3><?php _e('Assign Authors', 'mp-timetable'); ?></h3>
126
- <p><?php _e('To make it easier for you to edit and save the imported content, you may want to reassign the author of the imported item to an existing user of this site. For example, you may want to import all the entries as <code>admin</code>s entries.', 'mp-timetable'); ?></p>
127
- <?php if ($this->allow_create_users()) : ?>
128
- <p><?php printf(__('If a new user is created by WordPress, a new password will be randomly generated and the new user&#8217;s role will be set as %s. Manually changing the new user&#8217;s details will be necessary.', 'mp-timetable'), esc_html(get_option('default_role'))); ?></p>
129
- <?php endif; ?>
130
- <ol id="authors">
131
- <?php foreach ($this->authors as $author) : ?>
132
- <li><?php $this->author_select($j++, $author); ?></li>
133
- <?php endforeach; ?>
134
- </ol>
135
- <?php endif; ?>
136
-
137
- <?php if ($this->allow_fetch_attachments()) : ?>
138
- <h3><?php _e('Import Attachments', 'mp-timetable'); ?></h3>
139
- <p>
140
- <input type="checkbox" value="1" name="fetch_attachments" id="import-attachments"/>
141
- <label for="import-attachments"><?php _e('Download and import file attachments', 'mp-timetable'); ?></label>
142
- </p>
143
- <?php endif; ?>
144
-
145
- <p class="submit"><input type="submit" class="button" value="<?php esc_attr_e('Submit', 'mp-timetable'); ?>"/></p>
146
- </form>
147
- <?php
148
- }
149
-
150
- /**
151
- * Display import options for an individual author. That is, either create
152
- * a new user based on import info or map to an existing user
153
- *
154
- * @param int $n Index for each author in the form
155
- * @param array $author Author information, e.g. login, display name, email
156
- */
157
- function author_select($n, $author) {
158
- _e('Import author:', 'mp-timetable');
159
- echo ' <strong>' . esc_html( $author['author_display_name'] );
160
- if ($this->version != '1.0') echo ' (' . esc_html($author['author_login']) . ')';
161
- echo '</strong><br />';
162
-
163
- if ($this->version != '1.0')
164
- echo '<div style="margin-left:18px">';
165
-
166
- $create_users = $this->allow_create_users();
167
- if ($create_users) {
168
- if ($this->version != '1.0') {
169
- _e('or create new user with login name:', 'mp-timetable');
170
- $value = '';
171
- } else {
172
- _e('as a new user:', 'mp-timetable');
173
- $value = esc_attr(sanitize_user($author['author_login'], true));
174
- }
175
-
176
- echo ' <input type="text" name="user_new[' . esc_attr( $n ) . ']" value="' . esc_attr( $value ) . '" /><br />';
177
- }
178
-
179
- if (!$create_users && $this->version == '1.0')
180
- _e('assign posts to an existing user:', 'mp-timetable');
181
- else
182
- _e('or assign posts to an existing user:', 'mp-timetable');
183
- wp_dropdown_users(array('name' => "user_map[$n]", 'multi' => true, 'show_option_all' => __('- Select -', 'mp-timetable')));
184
- echo '<input type="hidden" name="imported_authors[' . esc_attr( $n ) . ']" value="' . esc_attr($author['author_login']) . '" />';
185
-
186
- if ($this->version != '1.0')
187
- echo '</div>';
188
- }
189
-
190
- /**
191
- * Import
192
- */
193
- public function import() {
194
- $this->header();
195
- $step = empty($_GET['step']) ? 0 : (int)$_GET['step'];
196
- switch ($step) {
197
- case 0:
198
- $this->greet();
199
- break;
200
- case 1:
201
- check_admin_referer('import-upload');
202
- if ($this->handle_upload()) {
203
- $this->import_options();
204
- }
205
- break;
206
- case 2:
207
- if (!empty($_POST['import_id'])) {
208
- check_admin_referer('mptt-importer');
209
- $this->fetch_attachments = (!empty($_POST['fetch_attachments']) && $this->allow_fetch_attachments());
210
- $this->id = (int)$_POST['import_id'];
211
- $file = get_attached_file($this->id);
212
- } else {
213
- check_admin_referer('import-upload');
214
- $this->handle_upload();
215
- $this->fetch_attachments = $this->allow_fetch_attachments();
216
- $file = $this->file;
217
- }
218
- set_time_limit(0);
219
- add_filter('import_post_meta_key', array($this, 'is_valid_meta_key'));
220
- add_filter('http_request_timeout', array(&$this, 'bump_request_timeout'));
221
-
222
- $this->get_author_mapping();
223
-
224
- $this->process_start($file);
225
- $this->process_end();
226
- break;
227
- }
228
- $this->footer();
229
- }
230
-
231
- /**
232
- * Import start
233
- *
234
- * @param $file
235
- */
236
- public function process_start($file) {
237
- $this->import_data = $this->parse($file);
238
- $this->get_authors_from_import();
239
- $this->version = $this->import_data['version'];
240
- $this->posts = $this->import_data['posts'];
241
- $this->terms = $this->import_data['terms'];
242
- $this->time_slots = $this->import_data['time_slots'];
243
-
244
- wp_suspend_cache_invalidation(true);
245
- $this->process_terms();
246
- $this->process_posts();
247
- $this->process_time_slot();
248
- wp_suspend_cache_invalidation(false);
249
- $this->backfill_parents();
250
- $this->backfill_attachment_urls();
251
- $this->remap_featured_images();
252
- wp_defer_term_counting(true);
253
- wp_defer_comment_counting(true);
254
-
255
- do_action('import_start');
256
- }
257
-
258
- public function process_end() {
259
- wp_import_cleanup($this->id);
260
-
261
- wp_cache_flush();
262
- foreach (get_taxonomies() as $tax) {
263
- delete_option("{$tax}_children");
264
- _get_term_hierarchy($tax);
265
- }
266
- wp_defer_term_counting(false);
267
- wp_defer_comment_counting(false);
268
-
269
- echo '<p>' . __('All done.', 'mp-timetable') . ' <a href="' . admin_url() . '">' . __('Have fun!', 'mp-timetable') . '</a>' . '</p>';
270
- echo '<p>' . __('Remember to update the passwords and roles of imported users.', 'mp-timetable') . '</p>';
271
-
272
- do_action('import_end');
273
- }
274
-
275
- /**
276
- * If fetching attachments is enabled then attempt to create a new attachment
277
- *
278
- * @param array $post Attachment post details from WXR
279
- * @param string $url URL to fetch attachment from
280
- *
281
- * @return int|/WP_Error Post ID on success, WP_Error otherwise
282
- */
283
- public function process_attachment($post, $url) {
284
- if (!$this->fetch_attachments)
285
- return new \WP_Error('attachment_processing_error',
286
- __('Fetching attachments is not enabled', 'mp-timetable'));
287
-
288
- // if the URL is absolute, but does not contain address, then upload it assuming base_site_url
289
- if (preg_match('|^/[\w\W]+$|', $url))
290
- $url = rtrim($this->base_url, '/') . $url;
291
-
292
- $upload = $this->fetch_remote_file($url, $post);
293
- if (is_wp_error($upload))
294
- return $upload;
295
-
296
- if ($info = wp_check_filetype($upload['file']))
297
- $post['post_mime_type'] = $info['type'];
298
- else
299
- return new \WP_Error('attachment_processing_error', __('Invalid file type', 'mp-timetable'));
300
-
301
- $post['guid'] = $upload['url'];
302
-
303
- // as per wp-admin/includes/upload.php
304
- $post_id = wp_insert_attachment($post, $upload['file']);
305
- wp_update_attachment_metadata($post_id, wp_generate_attachment_metadata($post_id, $upload['file']));
306
-
307
- // remap resized image URLs, works by stripping the extension and remapping the URL stub.
308
- if (preg_match('!^image/!', $info['type'])) {
309
- $parts = pathinfo($url);
310
- $name = basename($parts['basename'], ".{$parts['extension']}"); // PATHINFO_FILENAME in PHP 5.2
311
-
312
- $parts_new = pathinfo($upload['url']);
313
- $name_new = basename($parts_new['basename'], ".{$parts_new['extension']}");
314
-
315
- $this->url_remap[$parts['dirname'] . '/' . $name] = $parts_new['dirname'] . '/' . $name_new;
316
- }
317
-
318
- return $post_id;
319
- }
320
-
321
- /**
322
- * Get file by URL and write upload
323
- *
324
- * @param $url
325
- * @param $upload
326
- * @param int $redirection
327
- *
328
- * @return bool
329
- */
330
- private function write_file($url, $upload, $redirection = 5) {
331
- $options = array();
332
- $options['redirection'] = $redirection;
333
-
334
- if (false == $upload['file'])
335
- $options['method'] = 'HEAD';
336
- else
337
- $options['method'] = 'GET';
338
-
339
- $response = wp_safe_remote_request($url, $options);
340
-
341
- if (false == $upload['file']) {
342
- return false;
343
- }
344
- // GET request - write it to the supplied filename
345
- $out_fp = fopen($upload['file'], 'w');
346
- if (!$out_fp) {
347
- return false;
348
- }
349
-
350
- fwrite($out_fp, wp_remote_retrieve_body($response));
351
- fclose($out_fp);
352
- clearstatcache();
353
- return true;
354
- }
355
-
356
- /**
357
- * Attempt to download a remote file attachment
358
- *
359
- * @param string $url URL of item to fetch
360
- * @param array $post Attachment details
361
- *
362
- * @return array|\WP_Error Local file location details on success, WP_Error otherwise
363
- */
364
- public function fetch_remote_file($url, $post) {
365
- // extract the file name and extension from the url
366
- $file_name = basename($url);
367
-
368
- // get placeholder file in the upload dir with a unique, sanitized filename
369
- $upload = wp_upload_bits($file_name, 0, '', $post['upload_date']);
370
- if ($upload['error'])
371
- return new \WP_Error('upload_dir_error', $upload['error']);
372
-
373
- // fetch the remote url and write it to the placeholder file
374
- $response_data = wp_safe_remote_head($url);
375
- $headers = wp_remote_retrieve_headers($response_data);
376
- $headers['response'] = wp_remote_retrieve_response_code($response_data);
377
- if (!$headers) {
378
- @unlink($upload['file']);
379
- return new \WP_Error('import_file_error', __('Remote server did not respond', 'mp-timetable'));
380
- }
381
-
382
- // make sure the fetch was successful
383
- if ($headers['response'] != '200') {
384
- @unlink($upload['file']);
385
- return new \WP_Error('import_file_error', sprintf(__('Remote server returned error response %1$d %2$s', 'mp-timetable'), esc_html($headers['response']), get_status_header_desc($headers['response'])));
386
- }
387
-
388
- $this->write_file($url, $upload);
389
-
390
- $filesize = filesize($upload['file']);
391
-
392
- if (isset($headers['content-length']) && $filesize != $headers['content-length']) {
393
- @unlink($upload['file']);
394
- return new \WP_Error('import_file_error', __('Remote file is incorrect size', 'mp-timetable'));
395
- }
396
-
397
- if (0 == $filesize) {
398
- @unlink($upload['file']);
399
- return new \WP_Error('import_file_error', __('Zero size file downloaded', 'mp-timetable'));
400
- }
401
-
402
- $max_size = (int)$this->max_attachment_size();
403
- if (!empty($max_size) && $filesize > $max_size) {
404
- @unlink($upload['file']);
405
- return new \WP_Error('import_file_error', sprintf(__('Remote file is too large, limit is %s', 'mp-timetable'), size_format($max_size)));
406
- }
407
-
408
- // keep track of the old and new urls so we can substitute them later
409
- $this->url_remap[$url] = $upload['url'];
410
- $this->url_remap[$post['guid']] = $upload['url']; // r13735, really needed?
411
- // keep track of the destination if the remote url is redirected somewhere else
412
- if (isset($headers['x-final-location']) && $headers['x-final-location'] != $url)
413
- $this->url_remap[$headers['x-final-location']] = $upload['url'];
414
-
415
- return $upload;
416
- }
417
-
418
- public function handle_upload() {
419
- $file = wp_import_handle_upload();
420
-
421
- if (isset($file['error'])) {
422
- echo '<p><strong>' . __('Sorry, there has been an error.', 'mp-timetable') . '</strong><br />';
423
- echo esc_html($file['error']) . '</p>';
424
- return false;
425
- } else if (!file_exists($file['file'])) {
426
- echo '<p><strong>' . __('Sorry, there has been an error.', 'mp-timetable') . '</strong><br />';
427
- printf(__('The export file could not be found at <code>%s</code>. It is likely that this was caused by a permissions problem.', 'mp-timetable'), esc_html($file['file']));
428
- echo '</p>';
429
- return false;
430
- }
431
- $this->file = $file['file'];
432
- $this->id = (int)$file['id'];
433
- $this->import_data = $this->parse($file['file']);
434
-
435
- if (is_wp_error($this->import_data)) {
436
- echo '<p><strong>' . __('Sorry, there has been an error.', 'mp-timetable') . '</strong><br />';
437
- echo esc_html($this->import_data->get_error_message()) . '</p>';
438
- return false;
439
- }
440
-
441
- $this->version = $this->import_data['version'];
442
- if ($this->version > $this->max_wxr_version) {
443
- echo '<div class="error"><p><strong>';
444
- printf(__('This WXR file (version %s) may not be supported by this version of the importer. Please consider updating.', 'mp-timetable'), esc_html($this->import_data['version']));
445
- echo '</strong></p></div>';
446
- }
447
- $this->get_authors_from_import();
448
- return true;
449
- }
450
-
451
- /**
452
- * Parse a WXR file
453
- *
454
- * @param string $file Path to WXR file for parsing
455
- *
456
- * @return array Information gathered from the WXR file
457
- */
458
- function parse($file) {
459
- $parser = new libs\WXR_Parser();
460
- return $parser->parse($file);
461
- }
462
-
463
- /**
464
- * Decide if the given meta key maps to information we will want to import
465
- *
466
- * @param string $key The meta key to check
467
- *
468
- * @return string|bool The key if we do want to import, false if not
469
- */
470
- function is_valid_meta_key($key) {
471
- // skip attachment metadata since we'll regenerate it from scratch
472
- // skip _edit_lock as not relevant for import
473
- if (in_array($key, array('_wp_attached_file', '_wp_attachment_metadata', '_edit_lock')))
474
- return false;
475
- return $key;
476
- }
477
-
478
- /**
479
- * Added to http_request_timeout filter to force timeout at 60 seconds during import
480
- * @return int 60
481
- */
482
- function bump_request_timeout() {
483
- return 60;
484
- }
485
-
486
- /**
487
- * Retrieve authors from parsed WXR data
488
- *
489
- * Uses the provided author information from WXR 1.1 files
490
- * or extracts info from each post for WXR 1.0 files
491
- *
492
- */
493
- function get_authors_from_import() {
494
- if (!empty($this->import_data['authors'])) {
495
- $this->authors = $this->import_data['authors'];
496
- // no author information, grab it from the posts
497
- } else {
498
- foreach ($this->import_data['posts'] as $post) {
499
- $login = sanitize_user($post['post_author'], true);
500
- if (empty($login)) {
501
- printf(__('Failed to import author %s. Their posts will be attributed to the current user.', 'mp-timetable'), esc_html($post['post_author']));
502
- echo '<br />';
503
- continue;
504
- }
505
-
506
- if (!isset($this->authors[$login]))
507
- $this->authors[$login] = array(
508
- 'author_login' => $login,
509
- 'author_display_name' => $post['post_author']
510
- );
511
- }
512
- }
513
- }
514
-
515
- /**
516
- * Map old author logins to local user IDs based on decisions made
517
- * in import options form. Can map to an existing user, create a new user
518
- * or falls back to the current user in case of error with either of the previous
519
- */
520
- function get_author_mapping() {
521
- if ( ! isset( $_POST['imported_authors'] ) )
522
- return;
523
-
524
- $create_users = $this->allow_create_users();
525
-
526
- foreach ( (array) $_POST['imported_authors'] as $i => $old_login ) {
527
- // Multisite adds strtolower to sanitize_user. Need to sanitize here to stop breakage in process_posts.
528
- $santized_old_login = sanitize_user( $old_login, true );
529
- $old_id = isset( $this->authors[$old_login]['author_id'] ) ? intval($this->authors[$old_login]['author_id']) : false;
530
-
531
- if ( ! empty( $_POST['user_map'][$i] ) ) {
532
- $user = get_userdata( intval($_POST['user_map'][$i]) );
533
- if ( isset( $user->ID ) ) {
534
- if ( $old_id )
535
- $this->processed_authors[$old_id] = $user->ID;
536
- $this->author_mapping[$santized_old_login] = $user->ID;
537
- }
538
- } else if ( $create_users ) {
539
- if ( ! empty($_POST['user_new'][$i]) ) {
540
- $user_id = wp_create_user( $_POST['user_new'][$i], wp_generate_password() );
541
- } else if ( $this->version != '1.0' ) {
542
- $user_data = array(
543
- 'user_login' => $old_login,
544
- 'user_pass' => wp_generate_password(),
545
- 'user_email' => isset( $this->authors[$old_login]['author_email'] ) ? $this->authors[$old_login]['author_email'] : '',
546
- 'display_name' => $this->authors[$old_login]['author_display_name'],
547
- 'first_name' => isset( $this->authors[$old_login]['author_first_name'] ) ? $this->authors[$old_login]['author_first_name'] : '',
548
- 'last_name' => isset( $this->authors[$old_login]['author_last_name'] ) ? $this->authors[$old_login]['author_last_name'] : '',
549
- );
550
- $user_id = wp_insert_user( $user_data );
551
- }
552
-
553
- if ( ! is_wp_error( $user_id ) ) {
554
- if ( $old_id )
555
- $this->processed_authors[$old_id] = $user_id;
556
- $this->author_mapping[$santized_old_login] = $user_id;
557
- } else {
558
- printf( __( 'Failed to create new user for %s. Their posts will be attributed to the current user.', 'mp-timetable' ), esc_html($this->authors[$old_login]['author_display_name']) );
559
- if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
560
- echo ' ' . $user_id->get_error_message();
561
- echo '<br />';
562
- }
563
- }
564
-
565
- // failsafe: if the user_id was invalid, default to the current user
566
- if ( ! isset( $this->author_mapping[$santized_old_login] ) ) {
567
- if ( $old_id )
568
- $this->processed_authors[$old_id] = (int) get_current_user_id();
569
- $this->author_mapping[$santized_old_login] = (int) get_current_user_id();
570
- }
571
- }
572
- }
573
-
574
- /**
575
- * Create new terms based on import information
576
- *
577
- * Doesn't create a term its slug already exists
578
- */
579
- function process_terms() {
580
- $this->terms = apply_filters('wp_import_terms', $this->terms);
581
-
582
- if (empty($this->terms))
583
- return;
584
-
585
- foreach ($this->terms as $term) {
586
- // if the term already exists in the correct taxonomy leave it alone
587
- $term_id = term_exists($term['slug'], $term['term_taxonomy']);
588
- if ($term_id) {
589
- if (is_array($term_id)) $term_id = $term_id['term_id'];
590
- if (isset($term['term_id']))
591
- $this->processed_terms[intval($term['term_id'])] = (int)$term_id;
592
- continue;
593
- }
594
-
595
- if (empty($term['term_parent'])) {
596
- $parent = 0;
597
- } else {
598
- $parent = term_exists($term['term_parent'], $term['term_taxonomy']);
599
- if (is_array($parent)) $parent = $parent['term_id'];
600
- }
601
- $description = isset($term['term_description']) ? $term['term_description'] : '';
602
- $termarr = array('slug' => $term['slug'], 'description' => $description, 'parent' => intval($parent));
603
-
604
- $id = wp_insert_term($term['term_name'], $term['term_taxonomy'], $termarr);
605
- if (!is_wp_error($id)) {
606
- if (isset($term['term_id']))
607
- $this->processed_terms[intval($term['term_id'])] = $id['term_id'];
608
- } else {
609
- printf(__('Failed to import %s %s', 'mp-timetable'), esc_html($term['term_taxonomy']), esc_html($term['term_name']));
610
- if (defined('IMPORT_DEBUG') && IMPORT_DEBUG)
611
- echo ': ' . $id->get_error_message();
612
- echo '<br />';
613
- continue;
614
- }
615
- }
616
-
617
- unset($this->terms);
618
- }
619
-
620
- public function process_time_slot() {
621
- global $wpdb;
622
- $rows_affected = array();
623
- $time_slots = $this->import_data['time_slots'];
624
- if (!empty($this->import_data['time_slots'])) {
625
- foreach ($time_slots as $time_slot) {
626
- $exist_time_slot = $this->post_time_slot_exist($time_slot);
627
- if (!$exist_time_slot) {
628
- $rows_affected[] = $wpdb->insert($this->table, array(
629
- 'column_id' => $time_slot['column'],
630
- 'event_id' => $time_slot['event'],
631
- 'event_start' => date('H:i:s', strtotime($time_slot['event_start'])),
632
- 'event_end' => date('H:i:s', strtotime($time_slot['event_end'])),
633
- 'user_id' => $time_slot['user_id'],
634
- 'description' => $time_slot['description']
635
- ));
636
- }
637
- }
638
- }
639
- }
640
-
641
- /**
642
- * Create new posts based on import information
643
- *
644
- * Posts marked as having a parent which doesn't exist will become top level items.
645
- * Doesn't create a new post if: the post type doesn't exist, the given post ID
646
- * is already noted as imported or a post with the same title and date already exists.
647
- * Note that new/updated terms, comments and meta are imported for the last of the above.
648
- */
649
- public function process_posts() {
650
- $this->posts = apply_filters('wp_import_posts', $this->posts);
651
-
652
- foreach ($this->posts as $post) {
653
- $post = apply_filters('wp_import_post_data_raw', $post);
654
-
655
- if (!post_type_exists($post['post_type'])) {
656
- printf(__('Failed to import &#8220;%s&#8221;: Invalid post type %s', 'mp-timetable'),
657
- esc_html($post['post_title']), esc_html($post['post_type']));
658
- echo '<br />';
659
- do_action('wp_import_post_exists', $post);
660
- continue;
661
- }
662
-
663
- if (isset($this->processed_posts[$post['post_id']]) && !empty($post['post_id']))
664
- continue;
665
-
666
- if ($post['status'] == 'auto-draft')
667
- continue;
668
-
669
- $post_type_object = get_post_type_object($post['post_type']);
670
-
671
- $post_exists = post_exists($post['post_title'], '', $post['post_date']);
672
- if ($post_exists && get_post_type($post_exists) == $post['post_type']) {
673
- printf(__('%s &#8220;%s&#8221; already exists.', 'mp-timetable'), $post_type_object->labels->singular_name, esc_html($post['post_title']));
674
- echo '<br />';
675
- $comment_post_ID = $post_id = $post_exists;
676
- } else {
677
- $post_parent = (int)$post['post_parent'];
678
- if ($post_parent) {
679
- // if we already know the parent, map it to the new local ID
680
- if (isset($this->processed_posts[$post_parent])) {
681
- $post_parent = $this->processed_posts[$post_parent];
682
- // otherwise record the parent for later
683
- } else {
684
- $this->post_orphans[intval($post['post_id'])] = $post_parent;
685
- $post_parent = 0;
686
- }
687
- }
688
-
689
- // map the post author
690
- $author = sanitize_user($post['post_author'], true);
691
- if (isset($this->author_mapping[$author]))
692
- $author = $this->author_mapping[$author];
693
- else
694
- $author = (int)get_current_user_id();
695
-
696
- $postdata = array(
697
- 'import_id' => $post['post_id'], 'post_author' => $author, 'post_date' => $post['post_date'],
698
- 'post_date_gmt' => $post['post_date_gmt'], 'post_content' => $post['post_content'],
699
- 'post_excerpt' => $post['post_excerpt'], 'post_title' => $post['post_title'],
700
- 'post_status' => $post['status'], 'post_name' => $post['post_name'],
701
- 'comment_status' => $post['comment_status'], 'ping_status' => $post['ping_status'],
702
- 'guid' => $post['guid'], 'post_parent' => $post_parent, 'menu_order' => $post['menu_order'],
703
- 'post_type' => $post['post_type'], 'post_password' => $post['post_password']
704
- );
705
-
706
- $original_post_ID = $post['post_id'];
707
- $postdata = apply_filters('wp_import_post_data_processed', $postdata, $post);
708
-
709
- if ('attachment' == $postdata['post_type']) {
710
- $remote_url = !empty($post['attachment_url']) ? $post['attachment_url'] : $post['guid'];
711
-
712
- // try to use _wp_attached file for upload folder placement to ensure the same location as the export site
713
- // e.g. location is 2003/05/image.jpg but the attachment post_date is 2010/09, see media_handle_upload()
714
- $postdata['upload_date'] = $post['post_date'];
715
- if (isset($post['postmeta'])) {
716
- foreach ($post['postmeta'] as $meta) {
717
- if ($meta['key'] == '_wp_attached_file') {
718
- if (preg_match('%^[0-9]{4}/[0-9]{2}%', $meta['value'], $matches))
719
- $postdata['upload_date'] = $matches[0];
720
- break;
721
- }
722
- }
723
- }
724
-
725
- $comment_post_ID = $post_id = $this->process_attachment($postdata, $remote_url);
726
- } else {
727
- $comment_post_ID = $post_id = wp_insert_post($postdata, true);
728
- do_action('wp_import_insert_post', $post_id, $original_post_ID, $postdata, $post);
729
- }
730
-
731
- if (is_wp_error($post_id)) {
732
- printf(__('Failed to import %s &#8220;%s&#8221;', 'mp-timetable'),
733
- $post_type_object->labels->singular_name, esc_html($post['post_title']));
734
- if (defined('IMPORT_DEBUG') && IMPORT_DEBUG)
735
- echo ': ' . $post_id->get_error_message();
736
- echo '<br />';
737
- continue;
738
- }
739
-
740
- if ($post['is_sticky'] == 1)
741
- stick_post($post_id);
742
- }
743
-
744
- // map pre-import ID to local ID
745
- $this->processed_posts[intval($post['post_id'])] = (int)$post_id;
746
-
747
- if (!isset($post['terms']))
748
- $post['terms'] = array();
749
-
750
- $post['terms'] = apply_filters('wp_import_post_terms', $post['terms'], $post_id, $post);
751
-
752
- // add categories, tags and other terms
753
- if (!empty($post['terms'])) {
754
- $terms_to_set = array();
755
- foreach ($post['terms'] as $term) {
756
- // back compat with WXR 1.0 map 'tag' to 'post_tag'
757
- $taxonomy = ('tag' == $term['domain']) ? 'post_tag' : $term['domain'];
758
- $term_exists = term_exists($term['slug'], $taxonomy);
759
- $term_id = is_array($term_exists) ? $term_exists['term_id'] : $term_exists;
760
- if (!$term_id) {
761
- $t = wp_insert_term($term['name'], $taxonomy, array('slug' => $term['slug']));
762
- if (!is_wp_error($t)) {
763
- $term_id = $t['term_id'];
764
- do_action('wp_import_insert_term', $t, $term, $post_id, $post);
765
- } else {
766
- printf(__('Failed to import %s %s', 'mp-timetable'), esc_html($taxonomy), esc_html($term['name']));
767
- if (defined('IMPORT_DEBUG') && IMPORT_DEBUG)
768
- echo ': ' . $t->get_error_message();
769
- echo '<br />';
770
- do_action('wp_import_insert_term_failed', $t, $term, $post_id, $post);
771
- continue;
772
- }
773
- }
774
- $terms_to_set[$taxonomy][] = intval($term_id);
775
- }
776
-
777
- foreach ($terms_to_set as $tax => $ids) {
778
- $tt_ids = wp_set_post_terms($post_id, $ids, $tax);
779
- do_action('wp_import_set_post_terms', $tt_ids, $ids, $tax, $post_id, $post);
780
- }
781
- unset($post['terms'], $terms_to_set);
782
- }
783
-
784
- if (!isset($post['comments']))
785
- $post['comments'] = array();
786
-
787
- $post['comments'] = apply_filters('wp_import_post_comments', $post['comments'], $post_id, $post);
788
-
789
- // add/update comments
790
- if (!empty($post['comments'])) {
791
- $num_comments = 0;
792
- $inserted_comments = array();
793
- foreach ($post['comments'] as $comment) {
794
- $comment_id = $comment['comment_id'];
795
- $newcomments[$comment_id]['comment_post_ID'] = $comment_post_ID;
796
- $newcomments[$comment_id]['comment_author'] = $comment['comment_author'];
797
- $newcomments[$comment_id]['comment_author_email'] = $comment['comment_author_email'];
798
- $newcomments[$comment_id]['comment_author_IP'] = $comment['comment_author_IP'];
799
- $newcomments[$comment_id]['comment_author_url'] = $comment['comment_author_url'];
800
- $newcomments[$comment_id]['comment_date'] = $comment['comment_date'];
801
- $newcomments[$comment_id]['comment_date_gmt'] = $comment['comment_date_gmt'];
802
- $newcomments[$comment_id]['comment_content'] = $comment['comment_content'];
803
- $newcomments[$comment_id]['comment_approved'] = $comment['comment_approved'];
804
- $newcomments[$comment_id]['comment_type'] = $comment['comment_type'];
805
- $newcomments[$comment_id]['comment_parent'] = $comment['comment_parent'];
806
- $newcomments[$comment_id]['commentmeta'] = isset($comment['commentmeta']) ? $comment['commentmeta'] : array();
807
- if (isset($this->processed_authors[$comment['comment_user_id']]))
808
- $newcomments[$comment_id]['user_id'] = $this->processed_authors[$comment['comment_user_id']];
809
- }
810
- ksort($newcomments);
811
-
812
- foreach ($newcomments as $key => $comment) {
813
- // if this is a new post we can skip the comment_exists() check
814
- if (!$post_exists || !comment_exists($comment['comment_author'], $comment['comment_date'])) {
815
- if (isset($inserted_comments[$comment['comment_parent']]))
816
- $comment['comment_parent'] = $inserted_comments[$comment['comment_parent']];
817
- $comment = wp_filter_comment($comment);
818
- $inserted_comments[$key] = wp_insert_comment($comment);
819
- do_action('wp_import_insert_comment', $inserted_comments[$key], $comment, $comment_post_ID, $post);
820
-
821
- foreach ($comment['commentmeta'] as $meta) {
822
- $value = maybe_unserialize($meta['value']);
823
- add_comment_meta($inserted_comments[$key], $meta['key'], $value);
824
- }
825
-
826
- $num_comments++;
827
- }
828
- }
829
- unset($newcomments, $inserted_comments, $post['comments']);
830
- }
831
-
832
- // change time_slot data if post ID change
833
-
834
- if (!empty($original_post_ID)) {
835
- if ($original_post_ID != $post_id) {
836
- foreach ($this->import_data['time_slots'] as $key => $time_slot) {
837
- if ($post['post_type'] == 'mp-event' && $time_slot['event'] == $original_post_ID) {
838
- $time_slot['event'] = $post_id;
839
- } elseif ($post['post_type'] == 'mp-column' && $time_slot['column'] == $original_post_ID) {
840
- $time_slot['column'] = $post_id;
841
- } else {
842
- continue;
843
- }
844
- $this->import_data['time_slots'][$key] = $time_slot;
845
- }
846
- }
847
- }
848
-
849
-
850
- if (!isset($post['postmeta'])) {
851
- $post['postmeta'] = array();
852
- }
853
- $post['postmeta'] = apply_filters('wp_import_post_meta', $post['postmeta'], $post_id, $post);
854
- // add/update post meta
855
- if (!empty($post['postmeta'])) {
856
- foreach ($post['postmeta'] as $meta) {
857
- $key = apply_filters('import_post_meta_key', $meta['key'], $post_id, $post);
858
- $value = false;
859
-
860
- if ('_edit_last' == $key) {
861
- if (isset($this->processed_authors[intval($meta['value'])]))
862
- $value = $this->processed_authors[intval($meta['value'])];
863
- else
864
- $key = false;
865
- }
866
-
867
- if ($key) {
868
- // export gets meta straight from the DB so could have a serialized string
869
- if (!$value)
870
- $value = maybe_unserialize($meta['value']);
871
-
872
- add_post_meta($post_id, $key, $value);
873
- do_action('import_post_meta', $post_id, $key, $value);
874
-
875
- // if the post has a featured image, take note of this in case of remap
876
- if ('_thumbnail_id' == $key)
877
- $this->featured_images[$post_id] = (int)$value;
878
- }
879
- }
880
- }
881
- }
882
-
883
- unset($this->posts);
884
- }
885
-
886
- /**
887
- * Attempt to associate posts and menu items with previously missing parents
888
- *
889
- * An imported post's parent may not have been imported when it was first created
890
- * so try again. Similarly for child menu items and menu items which were missing
891
- * the object (e.g. post) they represent in the menu
892
- */
893
- function backfill_parents() {
894
- global $wpdb;
895
-
896
- // find parents for post orphans
897
- foreach ($this->post_orphans as $child_id => $parent_id) {
898
- $local_child_id = $local_parent_id = false;
899
- if (isset($this->processed_posts[$child_id]))
900
- $local_child_id = $this->processed_posts[$child_id];
901
- if (isset($this->processed_posts[$parent_id]))
902
- $local_parent_id = $this->processed_posts[$parent_id];
903
-
904
- if ($local_child_id && $local_parent_id)
905
- $wpdb->update($wpdb->posts, array('post_parent' => $local_parent_id), array('ID' => $local_child_id), '%d', '%d');
906
- }
907
-
908
- // all other posts/terms are imported, retry menu items with missing associated object
909
- $missing_menu_items = $this->missing_menu_items;
910
- // foreach ($missing_menu_items as $item)
911
- // $this->process_menu_item($item);
912
-
913
- // find parents for menu item orphans
914
- foreach ($this->menu_item_orphans as $child_id => $parent_id) {
915
- $local_child_id = $local_parent_id = 0;
916
- if (isset($this->processed_menu_items[$child_id]))
917
- $local_child_id = $this->processed_menu_items[$child_id];
918
- if (isset($this->processed_menu_items[$parent_id]))
919
- $local_parent_id = $this->processed_menu_items[$parent_id];
920
-
921
- if ($local_child_id && $local_parent_id)
922
- update_post_meta($local_child_id, '_menu_item_menu_item_parent', (int)$local_parent_id);
923
- }
924
- }
925
-
926
- /**
927
- * Use stored mapping information to update old attachment URLs
928
- */
929
- function backfill_attachment_urls() {
930
- global $wpdb;
931
- $result = array();
932
- // make sure we do the longest urls first, in case one is a substring of another
933
- uksort($this->url_remap, array(&$this, 'cmpr_strlen'));
934
-
935
- foreach ($this->url_remap as $from_url => $to_url) {
936
- // remap urls in post_content
937
- $wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $from_url, $to_url));
938
- // remap enclosure urls
939
- $result = $wpdb->query($wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s) WHERE meta_key='enclosure'", $from_url, $to_url));
940
- }
941
- return $result;
942
- }
943
-
944
- // return the difference in length between two strings
945
- public function cmpr_strlen($a, $b) {
946
- return strlen($b) - strlen($a);
947
- }
948
-
949
- /**
950
- * Update _thumbnail_id meta to new, imported attachment IDs
951
- */
952
- function remap_featured_images() {
953
- // cycle through posts that have a featured image
954
- foreach ($this->featured_images as $post_id => $value) {
955
- if (isset($this->processed_posts[$value])) {
956
- $new_id = $this->processed_posts[$value];
957
- // only update if there's a difference
958
- if ($new_id != $value)
959
- update_post_meta($post_id, '_thumbnail_id', $new_id);
960
- }
961
- }
962
- }
963
-
964
- function max_attachment_size() {
965
- return apply_filters('import_attachment_size_limit', 0);
966
- }
967
- }
968
-
1
+ <?php
2
+ namespace mp_timetable\classes\models;
3
+
4
+ use mp_timetable\classes\libs;
5
+ use mp_timetable\plugin_core\classes\Model as Model;
6
+ use mp_timetable\plugin_core\classes\View as View;
7
+
8
+ /**
9
+ * Model Events
10
+ */
11
+ class Import extends Model {
12
+
13
+ protected static $instance;
14
+ protected $table;
15
+ var $max_wxr_version = 1.2; // max. supported WXR version
16
+ var $id; // WXR attachment ID
17
+ var $file;
18
+
19
+ var $import_data;
20
+ // information to import from WXR file
21
+ var $version;
22
+ var $authors = array();
23
+ var $posts = array();
24
+ var $terms = array();
25
+ var $time_slots = array();
26
+ var $categories = array();
27
+ var $tags = array();
28
+ var $base_url = '';
29
+
30
+ var $processed_authors = array();
31
+ var $author_mapping = array();
32
+ var $processed_terms = array();
33
+ var $processed_posts = array();
34
+ var $post_orphans = array();
35
+ var $processed_menu_items = array();
36
+ var $menu_item_orphans = array();
37
+ var $missing_menu_items = array();
38
+
39
+ var $fetch_attachments = false;
40
+ var $url_remap = array();
41
+ var $featured_images = array();
42
+
43
+ public static function get_instance() {
44
+ if (null === self::$instance) {
45
+ self::$instance = new self();
46
+ }
47
+ return self::$instance;
48
+ }
49
+
50
+ function __construct() {
51
+ parent::__construct();
52
+ $this->table = Events::get_instance()->table_name;
53
+ }
54
+
55
+ /**
56
+ *
57
+ * @param bool $return_me
58
+ * @param string $meta_key
59
+ *
60
+ * @return bool
61
+ */
62
+ public function mptt_filter_postmeta($return_me, $meta_key) {
63
+ if ('_edit_lock' == $meta_key)
64
+ $return_me = true;
65
+ return $return_me;
66
+ }
67
+
68
+ /**
69
+ * Exist time slot
70
+ *
71
+ * @param array $time_slot
72
+ *
73
+ * @return bool
74
+ */
75
+ public function post_time_slot_exist($time_slot = array()) {
76
+ global $wpdb;
77
+ if (empty($time_slot)) {
78
+ return false;
79
+ }
80
+ $data = $wpdb->get_results('SELECT id FROM ' . $this->table . ' WHERE column_id = "' . $time_slot['column'] . '" AND event_id = "' . $time_slot['event'] . '" AND event_start = "' . $time_slot['event_start'] . '" AND event_end = "' . $time_slot['event_end'] . '"');
81
+ return empty($data) ? false : true;
82
+ }
83
+
84
+ public function header() {
85
+ View::get_instance()->render_html('../admin/import/header');
86
+ }
87
+
88
+ public function footer() {
89
+ View::get_instance()->render_html('../admin/import/footer');
90
+ }
91
+
92
+ public function greet() {
93
+ View::get_instance()->render_html('../admin/import/greet');
94
+ }
95
+
96
+ /**
97
+ * Decide whether or not the importer is allowed to create users.
98
+ * Default is true, can be filtered via import_allow_create_users
99
+ *
100
+ * @return bool True if creating users is allowed
101
+ */
102
+ public function allow_create_users() {
103
+ return apply_filters('import_allow_create_users', true);
104
+ }
105
+
106
+ /**
107
+ * Decide whether or not the importer should attempt to download attachment files.
108
+ * Default is true, can be filtered via import_allow_fetch_attachments. The choice
109
+ * made at the import options screen must also be true, false here hides that checkbox.
110
+ *
111
+ * @return bool True if downloading attachments is allowed
112
+ */
113
+ public function allow_fetch_attachments() {
114
+ return apply_filters('import_allow_fetch_attachments', true);
115
+ }
116
+
117
+ public function import_options() {
118
+ $j = 0;
119
+ ?>
120
+ <form action="<?php echo admin_url('admin.php?import=mptt-importer&amp;step=2'); ?>" method="post">
121
+ <?php wp_nonce_field('mptt-importer'); ?>
122
+ <input type="hidden" name="import_id" value="<?php echo esc_attr( $this->id ); ?>"/>
123
+
124
+ <?php if (!empty($this->authors)) : ?>
125
+ <h3><?php _e('Assign Authors', 'mp-timetable'); ?></h3>
126
+ <p><?php _e('To make it easier for you to edit and save the imported content, you may want to reassign the author of the imported item to an existing user of this site. For example, you may want to import all the entries as <code>admin</code>s entries.', 'mp-timetable'); ?></p>
127
+ <?php if ($this->allow_create_users()) : ?>
128
+ <p><?php printf(__('If a new user is created by WordPress, a new password will be randomly generated and the new user&#8217;s role will be set as %s. Manually changing the new user&#8217;s details will be necessary.', 'mp-timetable'), esc_html(get_option('default_role'))); ?></p>
129
+ <?php endif; ?>
130
+ <ol id="authors">
131
+ <?php foreach ($this->authors as $author) : ?>
132
+ <li><?php $this->author_select($j++, $author); ?></li>
133
+ <?php endforeach; ?>
134
+ </ol>
135
+ <?php endif; ?>
136
+
137
+ <?php if ($this->allow_fetch_attachments()) : ?>
138
+ <h3><?php _e('Import Attachments', 'mp-timetable'); ?></h3>
139
+ <p>
140
+ <input type="checkbox" value="1" name="fetch_attachments" id="import-attachments"/>
141
+ <label for="import-attachments"><?php _e('Download and import file attachments', 'mp-timetable'); ?></label>
142
+ </p>
143
+ <?php endif; ?>
144
+
145
+ <p class="submit"><input type="submit" class="button" value="<?php esc_attr_e('Submit', 'mp-timetable'); ?>"/></p>
146
+ </form>
147
+ <?php
148
+ }
149
+
150
+ /**
151
+ * Display import options for an individual author. That is, either create
152
+ * a new user based on import info or map to an existing user
153
+ *
154
+ * @param int $n Index for each author in the form
155
+ * @param array $author Author information, e.g. login, display name, email
156
+ */
157
+ function author_select($n, $author) {
158
+ _e('Import author:', 'mp-timetable');
159
+ echo ' <strong>' . esc_html( $author['author_display_name'] );
160
+ if ($this->version != '1.0') echo ' (' . esc_html($author['author_login']) . ')';
161
+ echo '</strong><br />';
162
+
163
+ if ($this->version != '1.0')
164
+ echo '<div style="margin-left:18px">';
165
+
166
+ $create_users = $this->allow_create_users();
167
+ if ($create_users) {
168
+ if ($this->version != '1.0') {
169
+ _e('or create new user with login name:', 'mp-timetable');
170
+ $value = '';
171
+ } else {
172
+ _e('as a new user:', 'mp-timetable');
173
+ $value = esc_attr(sanitize_user($author['author_login'], true));
174
+ }
175
+
176
+ echo ' <input type="text" name="user_new[' . esc_attr( $n ) . ']" value="' . esc_attr( $value ) . '" /><br />';
177
+ }
178
+
179
+ if (!$create_users && $this->version == '1.0')
180
+ _e('assign posts to an existing user:', 'mp-timetable');
181
+ else
182
+ _e('or assign posts to an existing user:', 'mp-timetable');
183
+ wp_dropdown_users(array('name' => "user_map[$n]", 'multi' => true, 'show_option_all' => __('- Select -', 'mp-timetable')));
184
+ echo '<input type="hidden" name="imported_authors[' . esc_attr( $n ) . ']" value="' . esc_attr($author['author_login']) . '" />';
185
+
186
+ if ($this->version != '1.0')
187
+ echo '</div>';
188
+ }
189
+
190
+ /**
191
+ * Import
192
+ */
193
+ public function import() {
194
+ $this->header();
195
+ $step = empty($_GET['step']) ? 0 : (int)$_GET['step'];
196
+ switch ($step) {
197
+ case 0:
198
+ $this->greet();
199
+ break;
200
+ case 1:
201
+ check_admin_referer('import-upload');
202
+ if ($this->handle_upload()) {
203
+ $this->import_options();
204
+ }
205
+ break;
206
+ case 2:
207
+ if (!empty($_POST['import_id'])) {
208
+ check_admin_referer('mptt-importer');
209
+ $this->fetch_attachments = (!empty($_POST['fetch_attachments']) && $this->allow_fetch_attachments());
210
+ $this->id = (int)$_POST['import_id'];
211
+ $file = get_attached_file($this->id);
212
+ } else {
213
+ check_admin_referer('import-upload');
214
+ $this->handle_upload();
215
+ $this->fetch_attachments = $this->allow_fetch_attachments();
216
+ $file = $this->file;
217
+ }
218
+ set_time_limit(0);
219
+ add_filter('import_post_meta_key', array($this, 'is_valid_meta_key'));
220
+ add_filter('http_request_timeout', array(&$this, 'bump_request_timeout'));
221
+
222
+ $this->get_author_mapping();
223
+
224
+ $this->process_start($file);
225
+ $this->process_end();
226
+ break;
227
+ }
228
+ $this->footer();
229
+ }
230
+
231
+ /**
232
+ * Import start
233
+ *
234
+ * @param $file
235
+ */
236
+ public function process_start($file) {
237
+ $this->import_data = $this->parse($file);
238
+ $this->get_authors_from_import();
239
+ $this->version = $this->import_data['version'];
240
+ $this->posts = $this->import_data['posts'];
241
+ $this->terms = $this->import_data['terms'];
242
+ $this->time_slots = $this->import_data['time_slots'];
243
+
244
+ wp_suspend_cache_invalidation(true);
245
+ $this->process_terms();
246
+ $this->process_posts();
247
+ $this->process_time_slot();
248
+ wp_suspend_cache_invalidation(false);
249
+ $this->backfill_parents();
250
+ $this->backfill_attachment_urls();
251
+ $this->remap_featured_images();
252
+ wp_defer_term_counting(true);
253
+ wp_defer_comment_counting(true);
254
+
255
+ do_action('import_start');
256
+ }
257
+
258
+ public function process_end() {
259
+ wp_import_cleanup($this->id);
260
+
261
+ wp_cache_flush();
262
+ foreach (get_taxonomies() as $tax) {
263
+ delete_option("{$tax}_children");
264
+ _get_term_hierarchy($tax);
265
+ }
266
+ wp_defer_term_counting(false);
267
+ wp_defer_comment_counting(false);
268
+
269
+ echo '<p>' . __('All done.', 'mp-timetable') . ' <a href="' . admin_url() . '">' . __('Have fun!', 'mp-timetable') . '</a>' . '</p>';
270
+ echo '<p>' . __('Remember to update the passwords and roles of imported users.', 'mp-timetable') . '</p>';
271
+
272
+ do_action('import_end');
273
+ }
274
+
275
+ /**
276
+ * If fetching attachments is enabled then attempt to create a new attachment
277
+ *
278
+ * @param array $post Attachment post details from WXR
279
+ * @param string $url URL to fetch attachment from
280
+ *
281
+ * @return int|/WP_Error Post ID on success, WP_Error otherwise
282
+ */
283
+ public function process_attachment($post, $url) {
284
+ if (!$this->fetch_attachments)
285
+ return new \WP_Error('attachment_processing_error',
286
+ __('Fetching attachments is not enabled', 'mp-timetable'));
287
+
288
+ // if the URL is absolute, but does not contain address, then upload it assuming base_site_url
289
+ if (preg_match('|^/[\w\W]+$|', $url))
290
+ $url = rtrim($this->base_url, '/') . $url;
291
+
292
+ $upload = $this->fetch_remote_file($url, $post);
293
+ if (is_wp_error($upload))
294
+ return $upload;
295
+
296
+ if ($info = wp_check_filetype($upload['file']))
297
+ $post['post_mime_type'] = $info['type'];
298
+ else
299
+ return new \WP_Error('attachment_processing_error', __('Invalid file type', 'mp-timetable'));
300
+
301
+ $post['guid'] = $upload['url'];
302
+
303
+ // as per wp-admin/includes/upload.php
304
+ $post_id = wp_insert_attachment($post, $upload['file']);
305
+ wp_update_attachment_metadata($post_id, wp_generate_attachment_metadata($post_id, $upload['file']));
306
+
307
+ // remap resized image URLs, works by stripping the extension and remapping the URL stub.
308
+ if (preg_match('!^image/!', $info['type'])) {
309
+ $parts = pathinfo($url);
310
+ $name = basename($parts['basename'], ".{$parts['extension']}"); // PATHINFO_FILENAME in PHP 5.2
311
+
312
+ $parts_new = pathinfo($upload['url']);
313
+ $name_new = basename($parts_new['basename'], ".{$parts_new['extension']}");
314
+
315
+ $this->url_remap[$parts['dirname'] . '/' . $name] = $parts_new['dirname'] . '/' . $name_new;
316
+ }
317
+
318
+ return $post_id;
319
+ }
320
+
321
+ /**
322
+ * Get file by URL and write upload
323
+ *
324
+ * @param $url
325
+ * @param $upload
326
+ * @param int $redirection
327
+ *
328
+ * @return bool
329
+ */
330
+ private function write_file($url, $upload, $redirection = 5) {
331
+ $options = array();
332
+ $options['redirection'] = $redirection;
333
+
334
+ if (false == $upload['file'])
335
+ $options['method'] = 'HEAD';
336
+ else
337
+ $options['method'] = 'GET';
338
+
339
+ $response = wp_safe_remote_request($url, $options);
340
+
341
+ if (false == $upload['file']) {
342
+ return false;
343
+ }
344
+ // GET request - write it to the supplied filename
345
+ $out_fp = fopen($upload['file'], 'w');
346
+ if (!$out_fp) {
347
+ return false;
348
+ }
349
+
350
+ fwrite($out_fp, wp_remote_retrieve_body($response));
351
+ fclose($out_fp);
352
+ clearstatcache();
353
+ return true;
354
+ }
355
+
356
+ /**
357
+ * Attempt to download a remote file attachment
358
+ *
359
+ * @param string $url URL of item to fetch
360
+ * @param array $post Attachment details
361
+ *
362
+ * @return array|\WP_Error Local file location details on success, WP_Error otherwise
363
+ */
364
+ public function fetch_remote_file($url, $post) {
365
+ // extract the file name and extension from the url
366
+ $file_name = basename($url);
367
+
368
+ // get placeholder file in the upload dir with a unique, sanitized filename
369
+ $upload = wp_upload_bits($file_name, 0, '', $post['upload_date']);
370
+ if ($upload['error'])
371
+ return new \WP_Error('upload_dir_error', $upload['error']);
372
+
373
+ // fetch the remote url and write it to the placeholder file
374
+ $response_data = wp_safe_remote_head($url);
375
+ $headers = wp_remote_retrieve_headers($response_data);
376
+ $headers['response'] = wp_remote_retrieve_response_code($response_data);
377
+ if (!$headers) {
378
+ @unlink($upload['file']);
379
+ return new \WP_Error('import_file_error', __('Remote server did not respond', 'mp-timetable'));
380
+ }
381
+
382
+ // make sure the fetch was successful
383
+ if ($headers['response'] != '200') {
384
+ @unlink($upload['file']);
385
+ return new \WP_Error('import_file_error', sprintf(__('Remote server returned error response %1$d %2$s', 'mp-timetable'), esc_html($headers['response']), get_status_header_desc($headers['response'])));
386
+ }
387
+
388
+ $this->write_file($url, $upload);
389
+
390
+ $filesize = filesize($upload['file']);
391
+
392
+ if (isset($headers['content-length']) && $filesize != $headers['content-length']) {
393
+ @unlink($upload['file']);
394
+ return new \WP_Error('import_file_error', __('Remote file is incorrect size', 'mp-timetable'));
395
+ }
396
+
397
+ if (0 == $filesize) {
398
+ @unlink($upload['file']);
399
+ return new \WP_Error('import_file_error', __('Zero size file downloaded', 'mp-timetable'));
400
+ }
401
+
402
+ $max_size = (int)$this->max_attachment_size();
403
+ if (!empty($max_size) && $filesize > $max_size) {
404
+ @unlink($upload['file']);
405
+ return new \WP_Error('import_file_error', sprintf(__('Remote file is too large, limit is %s', 'mp-timetable'), size_format($max_size)));
406
+ }
407
+
408
+ // keep track of the old and new urls so we can substitute them later
409
+ $this->url_remap[$url] = $upload['url'];
410
+ $this->url_remap[$post['guid']] = $upload['url']; // r13735, really needed?
411
+ // keep track of the destination if the remote url is redirected somewhere else
412
+ if (isset($headers['x-final-location']) && $headers['x-final-location'] != $url)
413
+ $this->url_remap[$headers['x-final-location']] = $upload['url'];
414
+
415
+ return $upload;
416
+ }
417
+
418
+ public function handle_upload() {
419
+ $file = wp_import_handle_upload();
420
+
421
+ if (isset($file['error'])) {
422
+ echo '<p><strong>' . __('Sorry, there has been an error.', 'mp-timetable') . '</strong><br />';
423
+ echo esc_html($file['error']) . '</p>';
424
+ return false;
425
+ } else if (!file_exists($file['file'])) {
426
+ echo '<p><strong>' . __('Sorry, there has been an error.', 'mp-timetable') . '</strong><br />';
427
+ printf(__('The export file could not be found at <code>%s</code>. It is likely that this was caused by a permissions problem.', 'mp-timetable'), esc_html($file['file']));
428
+ echo '</p>';
429
+ return false;
430
+ }
431
+ $this->file = $file['file'];
432
+ $this->id = (int)$file['id'];
433
+ $this->import_data = $this->parse($file['file']);
434
+
435
+ if (is_wp_error($this->import_data)) {
436
+ echo '<p><strong>' . __('Sorry, there has been an error.', 'mp-timetable') . '</strong><br />';
437
+ echo esc_html($this->import_data->get_error_message()) . '</p>';
438
+ return false;
439
+ }
440
+
441
+ $this->version = $this->import_data['version'];
442
+ if ($this->version > $this->max_wxr_version) {
443
+ echo '<div class="error"><p><strong>';
444
+ printf(__('This WXR file (version %s) may not be supported by this version of the importer. Please consider updating.', 'mp-timetable'), esc_html($this->import_data['version']));
445
+ echo '</strong></p></div>';
446
+ }
447
+ $this->get_authors_from_import();
448
+ return true;
449
+ }
450
+
451
+ /**
452
+ * Parse a WXR file
453
+ *
454
+ * @param string $file Path to WXR file for parsing
455
+ *
456
+ * @return array Information gathered from the WXR file
457
+ */
458
+ function parse($file) {
459
+ $parser = new libs\WXR_Parser();
460
+ return $parser->parse($file);
461
+ }
462
+
463
+ /**
464
+ * Decide if the given meta key maps to information we will want to import
465
+ *
466
+ * @param string $key The meta key to check
467
+ *
468
+ * @return string|bool The key if we do want to import, false if not
469
+ */
470
+ function is_valid_meta_key($key) {
471
+ // skip attachment metadata since we'll regenerate it from scratch
472
+ // skip _edit_lock as not relevant for import
473
+ if (in_array($key, array('_wp_attached_file', '_wp_attachment_metadata', '_edit_lock')))
474
+ return false;
475
+ return $key;
476
+ }
477
+
478
+ /**
479
+ * Added to http_request_timeout filter to force timeout at 60 seconds during import
480
+ * @return int 60
481
+ */
482
+ function bump_request_timeout() {
483
+ return 60;
484
+ }
485
+
486
+ /**
487
+ * Retrieve authors from parsed WXR data
488
+ *
489
+ * Uses the provided author information from WXR 1.1 files
490
+ * or extracts info from each post for WXR 1.0 files
491
+ *
492
+ */
493
+ function get_authors_from_import() {
494
+ if (!empty($this->import_data['authors'])) {
495
+ $this->authors = $this->import_data['authors'];
496
+ // no author information, grab it from the posts
497
+ } else {
498
+ foreach ($this->import_data['posts'] as $post) {
499
+ $login = sanitize_user($post['post_author'], true);
500
+ if (empty($login)) {
501
+ printf(__('Failed to import author %s. Their posts will be attributed to the current user.', 'mp-timetable'), esc_html($post['post_author']));
502
+ echo '<br />';
503
+ continue;
504
+ }
505
+
506
+ if (!isset($this->authors[$login]))
507
+ $this->authors[$login] = array(
508
+ 'author_login' => $login,
509
+ 'author_display_name' => $post['post_author']
510
+ );
511
+ }
512
+ }
513
+ }
514
+
515
+ /**
516
+ * Map old author logins to local user IDs based on decisions made
517
+ * in import options form. Can map to an existing user, create a new user
518
+ * or falls back to the current user in case of error with either of the previous
519
+ */
520
+ function get_author_mapping() {
521
+ if ( ! isset( $_POST['imported_authors'] ) )
522
+ return;
523
+
524
+ $create_users = $this->allow_create_users();
525
+
526
+ foreach ( (array) $_POST['imported_authors'] as $i => $old_login ) {
527
+ // Multisite adds strtolower to sanitize_user. Need to sanitize here to stop breakage in process_posts.
528
+ $santized_old_login = sanitize_user( $old_login, true );
529
+ $old_id = isset( $this->authors[$old_login]['author_id'] ) ? intval($this->authors[$old_login]['author_id']) : false;
530
+
531
+ if ( ! empty( $_POST['user_map'][$i] ) ) {
532
+ $user = get_userdata( intval($_POST['user_map'][$i]) );
533
+ if ( isset( $user->ID ) ) {
534
+ if ( $old_id )
535
+ $this->processed_authors[$old_id] = $user->ID;
536
+ $this->author_mapping[$santized_old_login] = $user->ID;
537
+ }
538
+ } else if ( $create_users ) {
539
+ if ( ! empty($_POST['user_new'][$i]) ) {
540
+ $user_id = wp_create_user( $_POST['user_new'][$i], wp_generate_password() );
541
+ } else if ( $this->version != '1.0' ) {
542
+ $user_data = array(
543
+ 'user_login' => $old_login,
544
+ 'user_pass' => wp_generate_password(),
545
+ 'user_email' => isset( $this->authors[$old_login]['author_email'] ) ? $this->authors[$old_login]['author_email'] : '',
546
+ 'display_name' => $this->authors[$old_login]['author_display_name'],
547
+ 'first_name' => isset( $this->authors[$old_login]['author_first_name'] ) ? $this->authors[$old_login]['author_first_name'] : '',
548
+ 'last_name' => isset( $this->authors[$old_login]['author_last_name'] ) ? $this->authors[$old_login]['author_last_name'] : '',
549
+ );
550
+ $user_id = wp_insert_user( $user_data );
551
+ }
552
+
553
+ if ( ! is_wp_error( $user_id ) ) {
554
+ if ( $old_id )
555
+ $this->processed_authors[$old_id] = $user_id;
556
+ $this->author_mapping[$santized_old_login] = $user_id;
557
+ } else {
558
+ printf( __( 'Failed to create new user for %s. Their posts will be attributed to the current user.', 'mp-timetable' ), esc_html($this->authors[$old_login]['author_display_name']) );
559
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
560
+ echo ' ' . $user_id->get_error_message();
561
+ echo '<br />';
562
+ }
563
+ }
564
+
565
+ // failsafe: if the user_id was invalid, default to the current user
566
+ if ( ! isset( $this->author_mapping[$santized_old_login] ) ) {
567
+ if ( $old_id )
568
+ $this->processed_authors[$old_id] = (int) get_current_user_id();
569
+ $this->author_mapping[$santized_old_login] = (int) get_current_user_id();
570
+ }
571
+ }
572
+ }
573
+
574
+ /**
575
+ * Create new terms based on import information
576
+ *
577
+ * Doesn't create a term its slug already exists
578
+ */
579
+ function process_terms() {
580
+ $this->terms = apply_filters('wp_import_terms', $this->terms);
581
+
582
+ if (empty($this->terms))
583
+ return;
584
+
585
+ foreach ($this->terms as $term) {
586
+ // if the term already exists in the correct taxonomy leave it alone
587
+ $term_id = term_exists($term['slug'], $term['term_taxonomy']);
588
+ if ($term_id) {
589
+ if (is_array($term_id)) $term_id = $term_id['term_id'];
590
+ if (isset($term['term_id']))
591
+ $this->processed_terms[intval($term['term_id'])] = (int)$term_id;
592
+ continue;
593
+ }
594
+
595
+ if (empty($term['term_parent'])) {
596
+ $parent = 0;
597
+ } else {
598
+ $parent = term_exists($term['term_parent'], $term['term_taxonomy']);
599
+ if (is_array($parent)) $parent = $parent['term_id'];
600
+ }
601
+ $description = isset($term['term_description']) ? $term['term_description'] : '';
602
+ $termarr = array('slug' => $term['slug'], 'description' => $description, 'parent' => intval($parent));
603
+
604
+ $id = wp_insert_term($term['term_name'], $term['term_taxonomy'], $termarr);
605
+ if (!is_wp_error($id)) {
606
+ if (isset($term['term_id']))
607
+ $this->processed_terms[intval($term['term_id'])] = $id['term_id'];
608
+ } else {
609
+ printf(__('Failed to import %s %s', 'mp-timetable'), esc_html($term['term_taxonomy']), esc_html($term['term_name']));
610
+ if (defined('IMPORT_DEBUG') && IMPORT_DEBUG)
611
+ echo ': ' . $id->get_error_message();
612
+ echo '<br />';
613
+ continue;
614
+ }
615
+ }
616
+
617
+ unset($this->terms);
618
+ }
619
+
620
+ public function process_time_slot() {
621
+ global $wpdb;
622
+ $rows_affected = array();
623
+ $time_slots = $this->import_data['time_slots'];
624
+ if (!empty($this->import_data['time_slots'])) {
625
+ foreach ($time_slots as $time_slot) {
626
+ $exist_time_slot = $this->post_time_slot_exist($time_slot);
627
+ if (!$exist_time_slot) {
628
+ $rows_affected[] = $wpdb->insert($this->table, array(
629
+ 'column_id' => $time_slot['column'],
630
+ 'event_id' => $time_slot['event'],
631
+ 'event_start' => date('H:i:s', strtotime($time_slot['event_start'])),
632
+ 'event_end' => date('H:i:s', strtotime($time_slot['event_end'])),
633
+ 'user_id' => $time_slot['user_id'],
634
+ 'description' => $time_slot['description']
635
+ ));
636
+ }
637
+ }
638
+ }
639
+ }
640
+
641
+ /**
642
+ * Create new posts based on import information
643
+ *
644
+ * Posts marked as having a parent which doesn't exist will become top level items.
645
+ * Doesn't create a new post if: the post type doesn't exist, the given post ID
646
+ * is already noted as imported or a post with the same title and date already exists.
647
+ * Note that new/updated terms, comments and meta are imported for the last of the above.
648
+ */
649
+ public function process_posts() {
650
+ $this->posts = apply_filters('wp_import_posts', $this->posts);
651
+
652
+ foreach ($this->posts as $post) {
653
+ $post = apply_filters('wp_import_post_data_raw', $post);
654
+
655
+ if (!post_type_exists($post['post_type'])) {
656
+ printf(__('Failed to import &#8220;%s&#8221;: Invalid post type %s', 'mp-timetable'),
657
+ esc_html($post['post_title']), esc_html($post['post_type']));
658
+ echo '<br />';
659
+ do_action('wp_import_post_exists', $post);
660
+ continue;
661
+ }
662
+
663
+ if (isset($this->processed_posts[$post['post_id']]) && !empty($post['post_id']))
664
+ continue;
665
+
666
+ if ($post['status'] == 'auto-draft')
667
+ continue;
668
+
669
+ $post_type_object = get_post_type_object($post['post_type']);
670
+
671
+ $post_exists = post_exists($post['post_title'], '', $post['post_date']);
672
+ if ($post_exists && get_post_type($post_exists) == $post['post_type']) {
673
+ printf(__('%s &#8220;%s&#8221; already exists.', 'mp-timetable'), $post_type_object->labels->singular_name, esc_html($post['post_title']));
674
+ echo '<br />';
675
+ $comment_post_ID = $post_id = $post_exists;
676
+ } else {
677
+ $post_parent = (int)$post['post_parent'];
678
+ if ($post_parent) {
679
+ // if we already know the parent, map it to the new local ID
680
+ if (isset($this->processed_posts[$post_parent])) {
681
+ $post_parent = $this->processed_posts[$post_parent];
682
+ // otherwise record the parent for later
683
+ } else {
684
+ $this->post_orphans[intval($post['post_id'])] = $post_parent;
685
+ $post_parent = 0;
686
+ }
687
+ }
688
+
689
+ // map the post author
690
+ $author = sanitize_user($post['post_author'], true);
691
+ if (isset($this->author_mapping[$author]))
692
+ $author = $this->author_mapping[$author];
693
+ else
694
+ $author = (int)get_current_user_id();
695
+
696
+ $postdata = array(
697
+ 'import_id' => $post['post_id'], 'post_author' => $author, 'post_date' => $post['post_date'],
698
+ 'post_date_gmt' => $post['post_date_gmt'], 'post_content' => $post['post_content'],
699
+ 'post_excerpt' => $post['post_excerpt'], 'post_title' => $post['post_title'],
700
+ 'post_status' => $post['status'], 'post_name' => $post['post_name'],
701
+ 'comment_status' => $post['comment_status'], 'ping_status' => $post['ping_status'],
702
+ 'guid' => $post['guid'], 'post_parent' => $post_parent, 'menu_order' => $post['menu_order'],
703
+ 'post_type' => $post['post_type'], 'post_password' => $post['post_password']
704
+ );
705
+
706
+ $original_post_ID = $post['post_id'];
707
+ $postdata = apply_filters('wp_import_post_data_processed', $postdata, $post);
708
+
709
+ if ('attachment' == $postdata['post_type']) {
710
+ $remote_url = !empty($post['attachment_url']) ? $post['attachment_url'] : $post['guid'];
711
+
712
+ // try to use _wp_attached file for upload folder placement to ensure the same location as the export site
713
+ // e.g. location is 2003/05/image.jpg but the attachment post_date is 2010/09, see media_handle_upload()
714
+ $postdata['upload_date'] = $post['post_date'];
715
+ if (isset($post['postmeta'])) {
716
+ foreach ($post['postmeta'] as $meta) {
717
+ if ($meta['key'] == '_wp_attached_file') {
718
+ if (preg_match('%^[0-9]{4}/[0-9]{2}%', $meta['value'], $matches))
719
+ $postdata['upload_date'] = $matches[0];
720
+ break;
721
+ }
722
+ }
723
+ }
724
+
725
+ $comment_post_ID = $post_id = $this->process_attachment($postdata, $remote_url);
726
+ } else {
727
+ $comment_post_ID = $post_id = wp_insert_post($postdata, true);
728
+ do_action('wp_import_insert_post', $post_id, $original_post_ID, $postdata, $post);
729
+ }
730
+
731
+ if (is_wp_error($post_id)) {
732
+ printf(__('Failed to import %s &#8220;%s&#8221;', 'mp-timetable'),
733
+ $post_type_object->labels->singular_name, esc_html($post['post_title']));
734
+ if (defined('IMPORT_DEBUG') && IMPORT_DEBUG)
735
+ echo ': ' . $post_id->get_error_message();
736
+ echo '<br />';
737
+ continue;
738
+ }
739
+
740
+ if ($post['is_sticky'] == 1)
741
+ stick_post($post_id);
742
+ }
743
+
744
+ // map pre-import ID to local ID
745
+ $this->processed_posts[intval($post['post_id'])] = (int)$post_id;
746
+
747
+ if (!isset($post['terms']))
748
+ $post['terms'] = array();
749
+
750
+ $post['terms'] = apply_filters('wp_import_post_terms', $post['terms'], $post_id, $post);
751
+
752
+ // add categories, tags and other terms
753
+ if (!empty($post['terms'])) {
754
+ $terms_to_set = array();
755
+ foreach ($post['terms'] as $term) {
756
+ // back compat with WXR 1.0 map 'tag' to 'post_tag'
757
+ $taxonomy = ('tag' == $term['domain']) ? 'post_tag' : $term['domain'];
758
+ $term_exists = term_exists($term['slug'], $taxonomy);
759
+ $term_id = is_array($term_exists) ? $term_exists['term_id'] : $term_exists;
760
+ if (!$term_id) {
761
+ $t = wp_insert_term($term['name'], $taxonomy, array('slug' => $term['slug']));
762
+ if (!is_wp_error($t)) {
763
+ $term_id = $t['term_id'];
764
+ do_action('wp_import_insert_term', $t, $term, $post_id, $post);
765
+ } else {
766
+ printf(__('Failed to import %s %s', 'mp-timetable'), esc_html($taxonomy), esc_html($term['name']));
767
+ if (defined('IMPORT_DEBUG') && IMPORT_DEBUG)
768
+ echo ': ' . $t->get_error_message();
769
+ echo '<br />';
770
+ do_action('wp_import_insert_term_failed', $t, $term, $post_id, $post);
771
+ continue;
772
+ }
773
+ }
774
+ $terms_to_set[$taxonomy][] = intval($term_id);
775
+ }
776
+
777
+ foreach ($terms_to_set as $tax => $ids) {
778
+ $tt_ids = wp_set_post_terms($post_id, $ids, $tax);
779
+ do_action('wp_import_set_post_terms', $tt_ids, $ids, $tax, $post_id, $post);
780
+ }
781
+ unset($post['terms'], $terms_to_set);
782
+ }
783
+
784
+ if (!isset($post['comments']))
785
+ $post['comments'] = array();
786
+
787
+ $post['comments'] = apply_filters('wp_import_post_comments', $post['comments'], $post_id, $post);
788
+
789
+ // add/update comments
790
+ if (!empty($post['comments'])) {
791
+ $num_comments = 0;
792
+ $inserted_comments = array();
793
+ foreach ($post['comments'] as $comment) {
794
+ $comment_id = $comment['comment_id'];
795
+ $newcomments[$comment_id]['comment_post_ID'] = $comment_post_ID;
796
+ $newcomments[$comment_id]['comment_author'] = $comment['comment_author'];
797
+ $newcomments[$comment_id]['comment_author_email'] = $comment['comment_author_email'];
798
+ $newcomments[$comment_id]['comment_author_IP'] = $comment['comment_author_IP'];
799
+ $newcomments[$comment_id]['comment_author_url'] = $comment['comment_author_url'];
800
+ $newcomments[$comment_id]['comment_date'] = $comment['comment_date'];
801
+ $newcomments[$comment_id]['comment_date_gmt'] = $comment['comment_date_gmt'];
802
+ $newcomments[$comment_id]['comment_content'] = $comment['comment_content'];
803
+ $newcomments[$comment_id]['comment_approved'] = $comment['comment_approved'];
804
+ $newcomments[$comment_id]['comment_type'] = $comment['comment_type'];
805
+ $newcomments[$comment_id]['comment_parent'] = $comment['comment_parent'];
806
+ $newcomments[$comment_id]['commentmeta'] = isset($comment['commentmeta']) ? $comment['commentmeta'] : array();
807
+ if (isset($this->processed_authors[$comment['comment_user_id']]))
808
+ $newcomments[$comment_id]['user_id'] = $this->processed_authors[$comment['comment_user_id']];
809
+ }
810
+ ksort($newcomments);
811
+
812
+ foreach ($newcomments as $key => $comment) {
813
+ // if this is a new post we can skip the comment_exists() check
814
+ if (!$post_exists || !comment_exists($comment['comment_author'], $comment['comment_date'])) {
815
+ if (isset($inserted_comments[$comment['comment_parent']]))
816
+ $comment['comment_parent'] = $inserted_comments[$comment['comment_parent']];
817
+ $comment = wp_filter_comment($comment);
818
+ $inserted_comments[$key] = wp_insert_comment($comment);
819
+ do_action('wp_import_insert_comment', $inserted_comments[$key], $comment, $comment_post_ID, $post);
820
+
821
+ foreach ($comment['commentmeta'] as $meta) {
822
+ $value = maybe_unserialize($meta['value']);
823
+ add_comment_meta($inserted_comments[$key], $meta['key'], $value);
824
+ }
825
+
826
+ $num_comments++;
827
+ }
828
+ }
829
+ unset($newcomments, $inserted_comments, $post['comments']);
830
+ }
831
+
832
+ // change time_slot data if post ID change
833
+
834
+ if (!empty($original_post_ID)) {
835
+ if ($original_post_ID != $post_id) {
836
+ foreach ($this->import_data['time_slots'] as $key => $time_slot) {
837
+ if ($post['post_type'] == 'mp-event' && $time_slot['event'] == $original_post_ID) {
838
+ $time_slot['event'] = $post_id;
839
+ } elseif ($post['post_type'] == 'mp-column' && $time_slot['column'] == $original_post_ID) {
840
+ $time_slot['column'] = $post_id;
841
+ } else {
842
+ continue;
843
+ }
844
+ $this->import_data['time_slots'][$key] = $time_slot;
845
+ }
846
+ }
847
+ }
848
+
849
+
850
+ if (!isset($post['postmeta'])) {
851
+ $post['postmeta'] = array();
852
+ }
853
+ $post['postmeta'] = apply_filters('wp_import_post_meta', $post['postmeta'], $post_id, $post);
854
+ // add/update post meta
855
+ if (!empty($post['postmeta'])) {
856
+ foreach ($post['postmeta'] as $meta) {
857
+ $key = apply_filters('import_post_meta_key', $meta['key'], $post_id, $post);
858
+ $value = false;
859
+
860
+ if ('_edit_last' == $key) {
861
+ if (isset($this->processed_authors[intval($meta['value'])]))
862
+ $value = $this->processed_authors[intval($meta['value'])];
863
+ else
864
+ $key = false;
865
+ }
866
+
867
+ if ($key) {
868
+ // export gets meta straight from the DB so could have a serialized string
869
+ if (!$value)
870
+ $value = maybe_unserialize($meta['value']);
871
+
872
+ add_post_meta($post_id, $key, $value);
873
+ do_action('import_post_meta', $post_id, $key, $value);
874
+
875
+ // if the post has a featured image, take note of this in case of remap
876
+ if ('_thumbnail_id' == $key)
877
+ $this->featured_images[$post_id] = (int)$value;
878
+ }
879
+ }
880
+ }
881
+ }
882
+
883
+ unset($this->posts);
884
+ }
885
+
886
+ /**
887
+ * Attempt to associate posts and menu items with previously missing parents
888
+ *
889
+ * An imported post's parent may not have been imported when it was first created
890
+ * so try again. Similarly for child menu items and menu items which were missing
891
+ * the object (e.g. post) they represent in the menu
892
+ */
893
+ function backfill_parents() {
894
+ global $wpdb;
895
+
896
+ // find parents for post orphans
897
+ foreach ($this->post_orphans as $child_id => $parent_id) {
898
+ $local_child_id = $local_parent_id = false;
899
+ if (isset($this->processed_posts[$child_id]))
900
+ $local_child_id = $this->processed_posts[$child_id];
901
+ if (isset($this->processed_posts[$parent_id]))
902
+ $local_parent_id = $this->processed_posts[$parent_id];
903
+
904
+ if ($local_child_id && $local_parent_id)
905
+ $wpdb->update($wpdb->posts, array('post_parent' => $local_parent_id), array('ID' => $local_child_id), '%d', '%d');
906
+ }
907
+
908
+ // all other posts/terms are imported, retry menu items with missing associated object
909
+ $missing_menu_items = $this->missing_menu_items;
910
+ // foreach ($missing_menu_items as $item)
911
+ // $this->process_menu_item($item);
912
+
913
+ // find parents for menu item orphans
914
+ foreach ($this->menu_item_orphans as $child_id => $parent_id) {
915
+ $local_child_id = $local_parent_id = 0;
916
+ if (isset($this->processed_menu_items[$child_id]))
917
+ $local_child_id = $this->processed_menu_items[$child_id];
918
+ if (isset($this->processed_menu_items[$parent_id]))
919
+ $local_parent_id = $this->processed_menu_items[$parent_id];
920
+
921
+ if ($local_child_id && $local_parent_id)
922
+ update_post_meta($local_child_id, '_menu_item_menu_item_parent', (int)$local_parent_id);
923
+ }
924
+ }
925
+
926
+ /**
927
+ * Use stored mapping information to update old attachment URLs
928
+ */
929
+ function backfill_attachment_urls() {
930
+ global $wpdb;
931
+ $result = array();
932
+ // make sure we do the longest urls first, in case one is a substring of another
933
+ uksort($this->url_remap, array(&$this, 'cmpr_strlen'));
934
+
935
+ foreach ($this->url_remap as $from_url => $to_url) {
936
+ // remap urls in post_content
937
+ $wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $from_url, $to_url));
938
+ // remap enclosure urls
939
+ $result = $wpdb->query($wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s) WHERE meta_key='enclosure'", $from_url, $to_url));
940
+ }
941
+ return $result;
942
+ }
943
+
944
+ // return the difference in length between two strings
945
+ public function cmpr_strlen($a, $b) {
946
+ return strlen($b) - strlen($a);
947
+ }
948
+
949
+ /**
950
+ * Update _thumbnail_id meta to new, imported attachment IDs
951
+ */
952
+ function remap_featured_images() {
953
+ // cycle through posts that have a featured image
954
+ foreach ($this->featured_images as $post_id => $value) {
955
+ if (isset($this->processed_posts[$value])) {
956
+ $new_id = $this->processed_posts[$value];
957
+ // only update if there's a difference
958
+ if ($new_id != $value)
959
+ update_post_meta($post_id, '_thumbnail_id', $new_id);
960
+ }
961
+ }
962
+ }
963
+
964
+ function max_attachment_size() {
965
+ return apply_filters('import_attachment_size_limit', 0);
966
+ }
967
+ }
968
+
classes/models/class-settings.php CHANGED
@@ -1,106 +1,106 @@
1
- <?php
2
-
3
- namespace mp_timetable\classes\models;
4
-
5
- use mp_timetable\plugin_core\classes\Model as Model;
6
-
7
- /**
8
- * Model Events
9
- */
10
- class Settings extends Model {
11
-
12
- protected static $instance;
13
-
14
- /**
15
- * Settings constructor.
16
- */
17
- public function __construct() {
18
- parent::__construct();
19
- }
20
-
21
- /**
22
- * Get instance
23
- *
24
- * @return Settings
25
- */
26
- public static function get_instance() {
27
- if (null === self::$instance) {
28
- self::$instance = new self();
29
- }
30
- return self::$instance;
31
- }
32
-
33
- /**
34
- * Render settings
35
- */
36
- public function render_settings() {
37
- $data = $this->get_settings();
38
-
39
- $this->get_view()->render_html("settings/general", array('settings' => $data), true);
40
- }
41
-
42
- /**
43
- * Get Settings
44
- *
45
- * @return mixed
46
- */
47
- public function get_settings() {
48
-
49
- $mp_timetable_general = array(
50
- 'theme_mode' => 'theme',
51
- );
52
-
53
- $settings = get_option('mp_timetable_general', $mp_timetable_general);
54
-
55
- if ($this->is_theme_supports()) {
56
- $settings['theme_mode'] = 'plugin';
57
- }
58
-
59
- return $settings;
60
- }
61
-
62
- /**
63
- * Theme supports plugin mode.
64
- *
65
- * @return string
66
- */
67
- public function is_theme_supports() {
68
-
69
- return current_theme_supports('mp-timetable');
70
- }
71
-
72
- /**
73
- * Save meta data Column post type
74
- *
75
- */
76
- public function save_settings() {
77
-
78
- if ( current_user_can('manage_options') && !empty( $_POST['theme_mode'] ) ) {
79
-
80
- $options = array();
81
- $options['theme_mode'] = sanitize_key( $_POST['theme_mode'] );
82
-
83
- update_option('mp_timetable_general', $options);
84
- }
85
- }
86
-
87
- /**
88
- * Check whether to use single room template from plugin
89
- *
90
- * @return bool
91
- */
92
- public function is_plugin_template_mode() {
93
- return ($this->get_template_mode() === 'plugin');
94
- }
95
-
96
- /**
97
- * Retrieve template mode. Possible values: plugin, theme.
98
- *
99
- * @return string
100
- */
101
- public function get_template_mode() {
102
- $options = $this->get_settings();
103
-
104
- return isset($options['theme_mode']) ? $options['theme_mode'] : 'theme';
105
- }
106
  }
1
+ <?php
2
+
3
+ namespace mp_timetable\classes\models;
4
+
5
+ use mp_timetable\plugin_core\classes\Model as Model;
6
+
7
+ /**
8
+ * Model Events
9
+ */
10
+ class Settings extends Model {
11
+
12
+ protected static $instance;
13
+
14
+ /**
15
+ * Settings constructor.
16
+ */
17
+ public function __construct() {
18
+ parent::__construct();
19
+ }
20
+
21
+ /**
22
+ * Get instance
23
+ *
24
+ * @return Settings
25
+ */
26
+ public static function get_instance() {
27
+ if (null === self::$instance) {
28
+ self::$instance = new self();
29
+ }
30
+ return self::$instance;
31
+ }
32
+
33
+ /**
34
+ * Render settings
35
+ */
36
+ public function render_settings() {
37
+ $data = $this->get_settings();
38
+
39
+ $this->get_view()->render_html("settings/general", array('settings' => $data), true);
40
+ }
41
+
42
+ /**
43
+ * Get Settings
44
+ *
45
+ * @return mixed
46
+ */
47
+ public function get_settings() {
48
+
49
+ $mp_timetable_general = array(
50
+ 'theme_mode' => 'theme',
51
+ );
52
+
53
+ $settings = get_option('mp_timetable_general', $mp_timetable_general);
54
+
55
+ if ($this->is_theme_supports()) {
56
+ $settings['theme_mode'] = 'plugin';
57
+ }
58
+
59
+ return $settings;
60
+ }
61
+
62
+ /**
63
+ * Theme supports plugin mode.
64
+ *
65
+ * @return string
66
+ */
67
+ public function is_theme_supports() {
68
+
69
+ return current_theme_supports('mp-timetable');
70
+ }
71
+
72
+ /**
73
+ * Save meta data Column post type
74
+ *
75
+ */
76
+ public function save_settings() {
77
+
78
+ if ( current_user_can('manage_options') && !empty( $_POST['theme_mode'] ) ) {
79
+
80
+ $options = array();
81
+ $options['theme_mode'] = sanitize_key( $_POST['theme_mode'] );
82
+
83
+ update_option('mp_timetable_general', $options);
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Check whether to use single room template from plugin
89
+ *
90
+ * @return bool
91
+ */
92
+ public function is_plugin_template_mode() {
93
+ return ($this->get_template_mode() === 'plugin');
94
+ }
95
+
96
+ /**
97
+ * Retrieve template mode. Possible values: plugin, theme.
98
+ *
99
+ * @return string
100
+ */
101
+ public function get_template_mode() {
102
+ $options = $this->get_settings();
103
+
104
+ return isset($options['theme_mode']) ? $options['theme_mode'] : 'theme';
105
+ }
106
  }
classes/modules/class-menu.php CHANGED
@@ -1,33 +1,33 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes\modules;
4
-
5
- class Menu {
6
-
7
- protected static $instance;
8
-
9
- public static function get_instance() {
10
- if (null === self::$instance) {
11
- self::$instance = new self();
12
- }
13
- return self::$instance;
14
- }
15
-
16
- /**
17
- * Add menu page
18
- *
19
- * @param $params
20
- */
21
- public function add_menu_page(array $params) {
22
- add_menu_page($params['page_title'], $params['menu_title'], $params['capability'], $params['menu_slug'], $params['function'], $params['icon_url'], $params['position']);
23
- }
24
-
25
- /**
26
- * Add submenu page
27
- *
28
- * @param $params
29
- */
30
- public function add_submenu_page(array $params) {
31
- add_submenu_page($params['parent_slug'], $params['page_title'], $params['menu_title'], $params['capability'], $params['menu_slug'], $params['function']);
32
- }
33
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes\modules;
4
+
5
+ class Menu {
6
+
7
+ protected static $instance;
8
+
9
+ public static function get_instance() {
10
+ if (null === self::$instance) {
11
+ self::$instance = new self();
12
+ }
13
+ return self::$instance;
14
+ }
15
+
16
+ /**
17
+ * Add menu page
18
+ *
19
+ * @param $params
20
+ */
21
+ public function add_menu_page(array $params) {
22
+ add_menu_page($params['page_title'], $params['menu_title'], $params['capability'], $params['menu_slug'], $params['function'], $params['icon_url'], $params['position']);
23
+ }
24
+
25
+ /**
26
+ * Add submenu page
27
+ *
28
+ * @param $params
29
+ */
30
+ public function add_submenu_page(array $params) {
31
+ add_submenu_page($params['parent_slug'], $params['page_title'], $params['menu_title'], $params['capability'], $params['menu_slug'], $params['function']);
32
+ }
33
+ }
classes/modules/class-post.php CHANGED
@@ -1,108 +1,108 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes\modules;
4
-
5
- use Mp_Time_Table;
6
- use mp_timetable\plugin_core\classes\Module as Module;
7
-
8
- class Post extends Module {
9
-
10
- protected static $instance;
11
-
12
- public static function get_instance() {
13
- if (null === self::$instance) {
14
- self::$instance = new self();
15
- }
16
- return self::$instance;
17
- }
18
-
19
- public function pre_get_posts($query) {
20
- if ($query->is_author() && $query->is_main_query() && !is_admin()) {
21
-
22
- $post_types = $query->get('post_type');
23
- if ( !is_array($post_types) && !empty($post_types) ) {
24
- $post_types = explode(',', $post_types);
25
- }
26
- if ( empty($post_types) )
27
- $post_types = array('post');
28
-
29
- $post_types[] = 'mp-event';
30
- $query->set('post_type', $post_types);
31
- }
32
-
33
- return $query;
34
- }
35
-
36
- /**
37
- * add meta _boxes
38
- */
39
- public function add_meta_boxes() {
40
- add_meta_box('mp-event_data', __('Timeslots', 'mp-timetable'), array($this->get('events'), 'render_event_data'), 'mp-event', 'normal', 'high', array('post_type' => 'mp-event'));
41
- add_meta_box('mp_event_options', __('Settings', 'mp-timetable'), array($this->get('events'), 'render_event_options'), 'mp-event', 'normal', 'high', array('post_type' => 'mp-event'));
42
- add_meta_box('mp-columns', __('Column Type', 'mp-timetable'), array($this->get('column'), 'render_column_options'), 'mp-column', 'normal', 'high', array('post_type' => 'mp-column'));
43
- }
44
-
45
- /**
46
- * Save custom_post
47
- *
48
- * @param $post_id
49
- * @param $post
50
- */
51
- public function save_custom_post($post_id, $post) {
52
-
53
- $request = $_REQUEST; // WPCS: input var ok, CSRF ok, sanitization ok.
54
-
55
- if ( !empty( $request[Mp_Time_Table::get_plugin_name() . '_noncename'] ) ) {
56
-
57
- $post_type = sanitize_text_field( $request['post_type'] );
58
-
59
- if ( !wp_verify_nonce(
60
- sanitize_key( $request[Mp_Time_Table::get_plugin_name() . '_noncename'] ),
61
- Mp_Time_Table::get_plugin_path()
62
- )
63
- ) {
64
- return $post->ID;
65
- }
66
-
67
- // Is the user allowed to edit the post or page?
68
- if (!current_user_can('edit_post', $post->ID)) {
69
- return $post->ID;
70
- }
71
- // verify if this is an auto save routine. If it is our form has not been submitted, so we dont want to do anything
72
- if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
73
- return $post->ID;
74
- }
75
-
76
- //Save post by post_type
77
- switch ($post_type) {
78
- case 'mp-event':
79
- $this->get('events')->save_event_data(array('post' => $post,
80
- 'event_data' => (!empty($request['event_data'])) ? $request['event_data'] : null, // WPCS: input var ok, CSRF ok, sanitization ok.
81
- 'event_meta' => (!empty($request['event_meta'])) ? $request['event_meta'] : null)); // WPCS: input var ok, CSRF ok, sanitization ok.
82
- break;
83
- case 'mp-column':
84
- $this->get('column')->save_column_data(array('post' => $post, 'data' => $request['column']));
85
- break;
86
- default:
87
- break;
88
- }
89
- }
90
- }
91
-
92
- /**
93
- * Before delete custom post
94
- *
95
- * @param $post_id
96
- * @param $post
97
- */
98
- public function before_delete_custom_post($post_id) {
99
- global $post_type;
100
- if ($post_type === 'mp-column') {
101
- $this->get('column')->before_delete_column($post_id);
102
- } elseif ($post_type === 'mp-event') {
103
- $this->get('events')->before_delete_event($post_id);
104
- }
105
-
106
- return;
107
- }
108
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes\modules;
4
+
5
+ use Mp_Time_Table;
6
+ use mp_timetable\plugin_core\classes\Module as Module;
7
+
8
+ class Post extends Module {
9
+
10
+ protected static $instance;
11
+
12
+ public static function get_instance() {
13
+ if (null === self::$instance) {
14
+ self::$instance = new self();
15
+ }
16
+ return self::$instance;
17
+ }
18
+
19
+ public function pre_get_posts($query) {
20
+ if ($query->is_author() && $query->is_main_query() && !is_admin()) {
21
+
22
+ $post_types = $query->get('post_type');
23
+ if ( !is_array($post_types) && !empty($post_types) ) {
24
+ $post_types = explode(',', $post_types);
25
+ }
26
+ if ( empty($post_types) )
27
+ $post_types = array('post');
28
+
29
+ $post_types[] = 'mp-event';
30
+ $query->set('post_type', $post_types);
31
+ }
32
+
33
+ return $query;
34
+ }
35
+
36
+ /**
37
+ * add meta _boxes
38
+ */
39
+ public function add_meta_boxes() {
40
+ add_meta_box('mp-event_data', __('Timeslots', 'mp-timetable'), array($this->get('events'), 'render_event_data'), 'mp-event', 'normal', 'high', array('post_type' => 'mp-event'));
41
+ add_meta_box('mp_event_options', __('Settings', 'mp-timetable'), array($this->get('events'), 'render_event_options'), 'mp-event', 'normal', 'high', array('post_type' => 'mp-event'));
42
+ add_meta_box('mp-columns', __('Column Type', 'mp-timetable'), array($this->get('column'), 'render_column_options'), 'mp-column', 'normal', 'high', array('post_type' => 'mp-column'));
43
+ }
44
+
45
+ /**
46
+ * Save custom_post
47
+ *
48
+ * @param $post_id
49
+ * @param $post
50
+ */
51
+ public function save_custom_post($post_id, $post) {
52
+
53
+ $request = $_REQUEST; // WPCS: input var ok, CSRF ok, sanitization ok.
54
+
55
+ if ( !empty( $request[Mp_Time_Table::get_plugin_name() . '_noncename'] ) ) {
56
+
57
+ $post_type = sanitize_text_field( $request['post_type'] );
58
+
59
+ if ( !wp_verify_nonce(
60
+ sanitize_key( $request[Mp_Time_Table::get_plugin_name() . '_noncename'] ),
61
+ Mp_Time_Table::get_plugin_path()
62
+ )
63
+ ) {
64
+ return $post->ID;
65
+ }
66
+
67
+ // Is the user allowed to edit the post or page?
68
+ if (!current_user_can('edit_post', $post->ID)) {
69
+ return $post->ID;
70
+ }
71
+ // verify if this is an auto save routine. If it is our form has not been submitted, so we dont want to do anything
72
+ if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
73
+ return $post->ID;
74
+ }
75
+
76
+ //Save post by post_type
77
+ switch ($post_type) {
78
+ case 'mp-event':
79
+ $this->get('events')->save_event_data(array('post' => $post,
80
+ 'event_data' => (!empty($request['event_data'])) ? $request['event_data'] : null, // WPCS: input var ok, CSRF ok, sanitization ok.
81
+ 'event_meta' => (!empty($request['event_meta'])) ? $request['event_meta'] : null)); // WPCS: input var ok, CSRF ok, sanitization ok.
82
+ break;
83
+ case 'mp-column':
84
+ $this->get('column')->save_column_data(array('post' => $post, 'data' => $request['column']));
85
+ break;
86
+ default:
87
+ break;
88
+ }
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Before delete custom post
94
+ *
95
+ * @param $post_id
96
+ * @param $post
97
+ */
98
+ public function before_delete_custom_post($post_id) {
99
+ global $post_type;
100
+ if ($post_type === 'mp-column') {
101
+ $this->get('column')->before_delete_column($post_id);
102
+ } elseif ($post_type === 'mp-event') {
103
+ $this->get('events')->before_delete_event($post_id);
104
+ }
105
+
106
+ return;
107
+ }
108
+ }
classes/modules/class-taxonomy.php CHANGED
@@ -1,42 +1,42 @@
1
- <?php
2
-
3
- namespace mp_timetable\plugin_core\classes\modules;
4
-
5
- use mp_timetable\plugin_core\classes\Module;
6
- use mp_timetable\plugin_core\classes\View;
7
-
8
- class Taxonomy extends Module {
9
-
10
- protected static $instance;
11
-
12
- public static function get_instance() {
13
- if (null === self::$instance) {
14
- self::$instance = new self();
15
- }
16
- return self::$instance;
17
- }
18
-
19
-
20
- /**
21
- * Render html for filter taxonomy link
22
- *
23
- * @param $post
24
- * @param $tax_name
25
- *
26
- * @return string
27
- */
28
- public function get_the_term_filter_list($post, $tax_name) {
29
- $taxonomies = wp_get_post_terms($post->ID, $tax_name);
30
- $taxonomies_html = "";
31
- $last_key = key(array_slice($taxonomies, -1, 1, TRUE));
32
-
33
- foreach ($taxonomies as $key => $tax) {
34
- $data["wp"] = $tax;
35
- $data["filter_link"] = admin_url('edit.php?post_type=' . $post->post_type . '&' . $tax->taxonomy . '=' . $tax->slug);
36
- $taxonomies_html .= View::get_instance()->render_html("taxonomies/taxonomy-link", $data, false);
37
- $taxonomies_html .= ($last_key != $key) ? ', ' : '';
38
- }
39
- return (!empty($taxonomies_html)) ? $taxonomies_html : "—";
40
- }
41
-
42
- }
1
+ <?php
2
+
3
+ namespace mp_timetable\plugin_core\classes\modules;
4
+
5
+ use mp_timetable\plugin_core\classes\Module;
6
+ use mp_timetable\plugin_core\classes\View;
7
+
8
+ class Taxonomy extends Module {
9
+
10
+ protected static $instance;
11
+
12
+ public static function get_instance() {
13
+ if (null === self::$instance) {
14
+ self::$instance = new self();
15
+ }
16
+ return self::$instance;
17
+ }
18
+
19
+
20
+ /**
21
+ * Render html for filter taxonomy link
22
+ *
23
+ * @param $post
24
+ * @param $tax_name
25
+ *
26
+ * @return string
27
+ */
28
+ public function get_the_term_filter_list($post, $tax_name) {
29
+ $taxonomies = wp_get_post_terms($post->ID, $tax_name);
30
+ $taxonomies_html = "";
31
+ $last_key = key(array_slice($taxonomies, -1, 1, TRUE));
32
+
33
+ foreach ($taxonomies as $key => $tax) {
34
+ $data["wp"] = $tax;
35
+ $data["filter_link"] = admin_url('edit.php?post_type=' . $post->post_type . '&' . $tax->taxonomy . '=' . $tax->slug);
36
+ $taxonomies_html .= View::get_instance()->render_html("taxonomies/taxonomy-link", $data, false);
37
+ $taxonomies_html .= ($last_key != $key) ? ', ' : '';
38
+ }
39
+ return (!empty($taxonomies_html)) ? $taxonomies_html : "—";
40
+ }
41
+
42
+ }
classes/widgets/class-mp-timetable-elementor-widget.php CHANGED
@@ -1,473 +1,473 @@
1
- <?php
2
-
3
- namespace timetable\classes\widgets;
4
-
5
- use \Elementor\Controls_Manager;
6
- use \Elementor\Plugin;
7
- use \Elementor\Group_Control_Typography;
8
- use \Elementor\Widget_Base;
9
-
10
- use \mp_timetable\plugin_core\classes\Shortcode;
11
-
12
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
-
14
- class Mp_Timetable_Widget extends Widget_Base {
15
-
16
- public function get_name() {
17
- return 'timetable';
18
- }
19
-
20
- public function get_title() {
21
- return __( 'Timetable', 'mp-timetable' );
22
- }
23
-
24
- public function get_icon() {
25
- return 'eicon-table';
26
- }
27
-
28
- public function get_categories() {
29
- return [ 'basic' ];
30
- }
31
-
32
- public function get_posts_type( $post_type ) {
33
- $args = [ 'post_type' => $post_type, 'numberposts' => '-1' ];
34
- $posts = get_posts( $args );
35
- $return = [];
36
-
37
- if ( ! empty( $posts ) ) {
38
- foreach ( $posts as $post ) {
39
- $return[ $post->ID ] = $post->post_title;
40
- }
41
- }
42
-
43
- return $return;
44
- }
45
-
46
- public function get_terms_type( $term_type ) {
47
- $terms = get_terms( $term_type, 'orderby=count&hide_empty=0' );
48
-
49
- $return = [];
50
-
51
- if ( ! empty( $terms ) ) {
52
- foreach ( $terms as $term ) {
53
- $return[ $term->term_id ] = $term->name;
54
- }
55
- }
56
-
57
- return $return;
58
- }
59
-
60
- private static function show_shortcode( $attributes ) {
61
- foreach ( $attributes as $key => $value ) {
62
- // [] -> '1,2,3'
63
- if ( is_array( $value ) ) {
64
- $attributes[ $key ] = implode( ',', $value );
65
- }
66
- // 'sub_title' -> 'sub-title'
67
- if ( $key == 'sub_title' ) {
68
- $attributes[ 'sub-title' ] = $attributes[ $key ];
69
- unset( $attributes[ $key ] );
70
- }
71
- }
72
-
73
- echo Shortcode::get_instance()->show_shortcode( $attributes );
74
- }
75
-
76
- public static function elementor_render_timetable( $attributes ) {
77
-
78
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
79
-
80
- self::show_shortcode( $attributes );
81
- }
82
-
83
- protected function _register_controls() {
84
- $controls = $this;
85
-
86
- $controls->start_controls_section(
87
- 'content_settings',
88
- [
89
- 'label' => __( 'Settings', 'mp-timetable' ),
90
- 'tab' => Controls_Manager::TAB_CONTENT,
91
- ]
92
- );
93
-
94
- $controls->add_control(
95
- 'label',
96
- [
97
- 'label' => esc_html__( 'Filter title to display all events', 'mp-timetable' ),
98
- 'label_block' => true,
99
- 'type' => Controls_Manager::TEXT,
100
- 'default' => esc_html__( 'All Events', 'mp-timetable' ),
101
- ]
102
- );
103
-
104
- $controls->add_control(
105
- 'hide_label',
106
- [
107
- 'label' => esc_html__( 'Hide \'All Events\' option', 'mp-timetable' ),
108
- 'type' => Controls_Manager::SWITCHER,
109
- 'default' => 'no',
110
- ]
111
- );
112
-
113
- $controls->add_control(
114
- 'col',
115
- [
116
- 'label' => esc_html__( 'Columns', 'mp-timetable' ),
117
- 'label_block' => true,
118
- 'type' => Controls_Manager::SELECT2,
119
- 'multiple' => true,
120
- 'options' => $this->get_posts_type( 'mp-column' ),
121
- 'separator' => 'before',
122
- ]
123
- );
124
-
125
- $controls->add_control(
126
- 'events',
127
- [
128
- 'label' => esc_html__( 'Specific events', 'mp-timetable' ),
129
- 'label_block' => true,
130
- 'type' => Controls_Manager::SELECT2,
131
- 'multiple' => true,
132
- 'options' => $this->get_posts_type( 'mp-event' ),
133
- ]
134
- );
135
-
136
- $controls->add_control(
137
- 'event_categ',
138
- [
139
- 'label' => esc_html__( 'Event categories', 'mp-timetable' ),
140
- 'label_block' => true,
141
- 'type' => Controls_Manager::SELECT2,
142
- 'multiple' => true,
143
- 'options' => $this->get_terms_type( 'mp-event_category' ),
144
- 'separator' => 'after',
145
- ]
146
- );
147
-
148
- $controls->add_control(
149
- 'title',
150
- [
151
- 'label' => esc_html__( 'Title', 'mp-timetable' ),
152
- 'type' => Controls_Manager::SWITCHER,
153
- 'label_off' => esc_html__( 'Hide', 'mp-timetable' ),
154
- 'label_on' => esc_html__( 'Show', 'mp-timetable' ),
155
- 'default' => 'yes',
156
- ]
157
- );
158
-
159
- $controls->add_control(
160
- 'time',
161
- [
162
- 'label' => esc_html__( 'Time', 'mp-timetable' ),
163
- 'type' => Controls_Manager::SWITCHER,
164
- 'label_off' => esc_html__( 'Hide', 'mp-timetable' ),
165
- 'label_on' => esc_html__( 'Show', 'mp-timetable' ),
166
- 'default' => 'yes',
167
- ]
168
- );
169
-
170
- $controls->add_control(
171
- 'sub_title',
172
- [
173
- 'label' => esc_html__( 'Subtitle', 'mp-timetable' ),
174
- 'type' => Controls_Manager::SWITCHER,
175
- 'label_off' => esc_html__( 'Hide', 'mp-timetable' ),
176
- 'label_on' => esc_html__( 'Show', 'mp-timetable' ),
177
- 'default' => 'no',
178
- ]
179
- );
180
-
181
- $controls->add_control(
182
- 'description',
183
- [
184
- 'label' => esc_html__( 'Description', 'mp-timetable' ),
185
- 'type' => Controls_Manager::SWITCHER,
186
- 'label_off' => esc_html__( 'Hide', 'mp-timetable' ),
187
- 'label_on' => esc_html__( 'Show', 'mp-timetable' ),
188
- 'default' => 'yes',
189
- ]
190
- );
191
-
192
- $controls->add_control(
193
- 'user',
194
- [
195
- 'label' => esc_html__( 'Event Head', 'mp-timetable' ),
196
- 'type' => Controls_Manager::SWITCHER,
197
- 'label_off' => esc_html__( 'Hide', 'mp-timetable' ),
198
- 'label_on' => esc_html__( 'Show', 'mp-timetable' ),
199
- 'default' => 'no',
200
- ]
201
- );
202
-
203
- $controls->add_control(
204
- 'hide_hrs',
205
- [
206
- 'label' => esc_html__( 'Hide column with hours', 'mp-timetable' ),
207
- 'type' => Controls_Manager::SWITCHER,
208
- 'default' => 'no',
209
- ]
210
- );
211
-
212
- $controls->add_control(
213
- 'hide_empty_rows',
214
- [
215
- 'label' => esc_html__( 'Do not display empty rows', 'mp-timetable' ),
216
- 'type' => Controls_Manager::SWITCHER,
217
- 'default' => 'yes',
218
- ]
219
- );
220
-
221
- $controls->add_control(
222
- 'group',
223
- [
224
- 'label' => esc_html__( 'Merge cells with common events', 'mp-timetable' ),
225
- 'type' => Controls_Manager::SWITCHER,
226
- 'default' => 'no',
227
- ]
228
- );
229
-
230
- $controls->add_control(
231
- 'disable_event_url',
232
- [
233
- 'label' => esc_html__( 'Disable event link', 'mp-timetable' ),
234
- 'type' => Controls_Manager::SWITCHER,
235
- 'default' => 'no',
236
- ]
237
- );
238
-
239
- $controls->add_control(
240
- 'font_size',
241
- [
242
- 'label' => esc_html__( 'Base font size', 'mp-timetable' ),
243
- 'label_block' => true,
244
- 'type' => Controls_Manager::TEXT,
245
- 'description' => __( 'Base font size for the table. Example 12px, 2em, 80%.', 'mp-timetable' ),
246
- 'separator' => 'before',
247
- ]
248
- );
249
-
250
- $controls->add_control(
251
- 'row_height',
252
- [
253
- 'label' => esc_html__( 'Block height in pixels', 'mp-timetable' ),
254
- 'type' => Controls_Manager::NUMBER,
255
- 'default' => 45,
256
- ]
257
- );
258
-
259
- $controls->add_control(
260
- 'increment',
261
- [
262
- 'label' => esc_html__( 'Time frame for event', 'mp-timetable' ),
263
- 'type' => Controls_Manager::SELECT,
264
- 'default' => '1',
265
- 'label_block' => false,
266
- 'options' => [
267
- '1' => esc_html__( 'Hour (1h)', 'mp-timetable' ),
268
- '0.5' => esc_html__( 'Half hour (30min)', 'mp-timetable' ),
269
- '0.25' => esc_html__( 'Quarter hour (15min)', 'mp-timetable' ),
270
- ],
271
- ]
272
- );
273
-
274
- $controls->add_control(
275
- 'view',
276
- [
277
- 'label' => esc_html__( 'Filter events style', 'mp-timetable' ),
278
- 'type' => Controls_Manager::SELECT,
279
- 'default' => 'dropdown_list',
280
- 'label_block' => false,
281
- 'options' => [
282
- 'dropdown_list' => esc_html__( 'Dropdown', 'mp-timetable' ),
283
- 'tabs' => esc_html__( 'Tabs', 'mp-timetable' ),
284
- ],
285
- ]
286
- );
287
-
288
- $controls->add_control(
289
- 'view_sort',
290
- [
291
- 'label' => esc_html__( 'Order of items in filter', 'mp-timetable' ),
292
- 'type' => Controls_Manager::SELECT,
293
- 'default' => '',
294
- 'label_block' => false,
295
- 'options' => [
296
- '' => esc_html__( 'Default', 'mp-timetable' ),
297
- 'menu_order' => esc_html__( 'Menu Order', 'mp-timetable' ),
298
- 'post_title' => esc_html__( 'Title', 'mp-timetable' ),
299
- ],
300
- ]
301
- );
302
-
303
- $controls->add_control(
304
- 'column_width',
305
- [
306
- 'label' => esc_html__( 'Column width', 'mp-timetable' ),
307
- 'type' => Controls_Manager::SELECT,
308
- 'default' => '',
309
- 'label_block' => false,
310
- 'options' => [
311
- '' => esc_html__( 'Default', 'mp-timetable' ),
312
- 'auto' => esc_html__( 'Auto', 'mp-timetable' ),
313
- 'fixed' => esc_html__( 'Fixed', 'mp-timetable' ),
314
- ],
315
- ]
316
- );
317
-
318
- $controls->add_control(
319
- 'responsive',
320
- [
321
- 'label' => esc_html__( 'Mobile behavior', 'mp-timetable' ),
322
- 'type' => Controls_Manager::SELECT,
323
- 'default' => '0',
324
- 'label_block' => false,
325
- 'options' => [
326
- '0' => esc_html__( 'Table', 'mp-timetable' ),
327
- '1' => esc_html__( 'List', 'mp-timetable' ),
328
- ],
329
- 'separator' => 'before',
330
- ]
331
- );
332
-
333
- $controls->add_control(
334
- 'text_align_horizontal',
335
- [
336
- 'label' => esc_html__( 'Horizontal align', 'mp-timetable' ),
337
- 'type' => Controls_Manager::CHOOSE,
338
- 'default' => 'center',
339
- 'toggle' => false,
340
- 'options' => [
341
- 'left' => [
342
- 'title' => esc_html__( 'left', 'mp-timetable' ),
343
- 'icon' => 'fa fa-align-left',
344
- ],
345
- 'center' => [
346
- 'title' => esc_html__( 'center', 'mp-timetable' ),
347
- 'icon' => 'fa fa-align-center',
348
- ],
349
- 'right' => [
350
- 'title' => esc_html__( 'right', 'mp-timetable' ),
351
- 'icon' => 'fa fa-align-right',
352
- ],
353
- ],
354
- 'separator' => 'before',
355
- ]
356
- );
357
-
358
- $controls->add_control(
359
- 'text_align_vertical',
360
- [
361
- 'label' => esc_html__( 'Vertical align', 'mp-timetable' ),
362
- 'type' => Controls_Manager::CHOOSE,
363
- 'default' => 'default',
364
- 'toggle' => false,
365
- 'options' => [
366
- 'default' => [
367
- 'title' => esc_html__( 'default', 'mp-timetable' ),
368
- 'icon' => 'eicon-v-align-stretch',
369
- ],
370
- 'top' => [
371
- 'title' => esc_html__( 'top', 'mp-timetable' ),
372
- 'icon' => 'eicon-v-align-top',
373
- ],
374
- 'middle' => [
375
- 'title' => esc_html__( 'middle', 'mp-timetable' ),
376
- 'icon' => 'eicon-v-align-middle',
377
- ],
378
- 'bottom' => [
379
- 'title' => esc_html__( 'bottom', 'mp-timetable' ),
380
- 'icon' => 'eicon-v-align-bottom',
381
- ],
382
- ],
383
- ]
384
- );
385
-
386
- $controls->add_control(
387
- 'unique_id',
388
- [
389
- 'label' => esc_html__( 'Unique ID', 'mp-timetable' ),
390
- 'label_block' => true,
391
- 'type' => Controls_Manager::TEXT,
392
- 'description' => __( 'If you use more than one table on a page specify the unique ID for a timetable. It is usually all lowercase and contains only letters, numbers, and hyphens.', 'mp-timetable' ),
393
- 'dynamic' => [ 'active' => true ],
394
- 'separator' => 'before',
395
- ]
396
- );
397
-
398
- $controls->add_control(
399
- 'custom_class',
400
- [
401
- 'label' => esc_html__( 'CSS class', 'mp-timetable' ),
402
- 'label_block' => true,
403
- 'type' => Controls_Manager::TEXT,
404
- 'dynamic' => [ 'active' => true ]
405
- ]
406
- );
407
-
408
- $controls->end_controls_section();
409
- }
410
-
411
- protected function render() {
412
- $settings = $this->get_settings();
413
-
414
- $label = $settings[ 'label' ];
415
- $font_size = $settings[ 'font_size' ];
416
- $col = $settings[ 'col' ];
417
- $events = $settings[ 'events' ];
418
- $event_categ = $settings[ 'event_categ' ];
419
- $title = $settings[ 'title' ] === 'yes' ? '1' : '0';
420
- $time = $settings[ 'time' ] === 'yes' ? '1' : '0';
421
- $subtitle = $settings[ 'sub_title' ] === 'yes' ? '1' : '0';
422
- $description = $settings[ 'description' ] === 'yes' ? '1' : '0';
423
- $user = $settings[ 'user' ] === 'yes' ? '1' : '0';
424
- $hide_label = $settings[ 'hide_label' ] === 'yes' ? '1' : '0';
425
- $hide_hrs = $settings[ 'hide_hrs' ] === 'yes' ? '1' : '0';
426
- $hide_empty_rows = $settings[ 'hide_empty_rows' ] === 'yes' ? '1' : '0';
427
- $group = $settings[ 'group' ] === 'yes' ? '1' : '0';
428
- $disable_event_url = $settings[ 'disable_event_url' ] === 'yes' ? '1' : '0';
429
- $row_height = $settings[ 'row_height' ];
430
- $view_sort = $settings[ 'view_sort' ];
431
- $increment = $settings[ 'increment' ];
432
- $view = $settings[ 'view' ];
433
- $text_align_horizontal = $settings[ 'text_align_horizontal' ];
434
- $text_align_vertical = $settings[ 'text_align_vertical' ];
435
- $column_width = $settings[ 'column_width' ];
436
- $responsive = $settings[ 'responsive' ];
437
- $id = $settings[ 'unique_id' ];
438
- $custom_class = $settings[ 'custom_class' ];
439
-
440
- $attributes = array(
441
- 'col' => $col,
442
- 'events' => $events,
443
- 'event_categ' => $event_categ,
444
- 'label' => $label,
445
- 'font_size' => $font_size,
446
- 'time' => $time,
447
- 'custom_class' => $custom_class,
448
- 'id' => $id,
449
- 'table_layout' => $column_width,
450
- 'increment' => $increment,
451
- 'view' => $view,
452
- 'view_sort' => $view_sort,
453
- 'hide_label' => $hide_label,
454
- 'hide_hrs' => $hide_hrs,
455
- 'hide_empty_rows' => $hide_empty_rows,
456
- 'title' => $title,
457
- 'sub_title' => $subtitle,
458
- 'description' => $description,
459
- 'user' => $user,
460
- 'group' => $group,
461
- 'disable_event_url' => $disable_event_url,
462
- 'text_align' => $text_align_horizontal,
463
- 'row_height' => $row_height,
464
- 'responsive' => $responsive,
465
- 'text_align_vertical' => $text_align_vertical,
466
- );
467
-
468
- $this->elementor_render_timetable( $attributes );
469
- }
470
-
471
- }
472
-
473
  Plugin::instance()->widgets_manager->register_widget_type( new Mp_Timetable_Widget() );
1
+ <?php
2
+
3
+ namespace timetable\classes\widgets;
4
+
5
+ use \Elementor\Controls_Manager;
6
+ use \Elementor\Plugin;
7
+ use \Elementor\Group_Control_Typography;
8
+ use \Elementor\Widget_Base;
9
+
10
+ use \mp_timetable\plugin_core\classes\Shortcode;
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
+
14
+ class Mp_Timetable_Widget extends Widget_Base {
15
+
16
+ public function get_name() {
17
+ return 'timetable';
18
+ }
19
+
20
+ public function get_title() {
21
+ return __( 'Timetable', 'mp-timetable' );
22
+ }
23
+
24
+ public function get_icon() {
25
+ return 'eicon-table';
26
+ }
27
+
28
+ public function get_categories() {
29
+ return [ 'basic' ];
30
+ }
31
+
32
+ public function get_posts_type( $post_type ) {
33
+ $args = [ 'post_type' => $post_type, 'numberposts' => '-1' ];
34
+ $posts = get_posts( $args );
35
+ $return = [];
36
+
37
+ if ( ! empty( $posts ) ) {
38
+ foreach ( $posts as $post ) {
39
+ $return[ $post->ID ] = $post->post_title;
40
+ }
41
+ }
42
+
43
+ return $return;
44
+ }
45
+
46
+ public function get_terms_type( $term_type ) {
47
+ $terms = get_terms( $term_type, 'orderby=count&hide_empty=0' );
48
+
49
+ $return = [];
50
+
51
+ if ( ! empty( $terms ) ) {
52
+ foreach ( $terms as $term ) {
53
+ $return[ $term->term_id ] = $term->name;
54
+ }
55
+ }
56
+
57
+ return $return;
58
+ }
59
+
60
+ private static function show_shortcode( $attributes ) {
61
+ foreach ( $attributes as $key => $value ) {
62
+ // [] -> '1,2,3'
63
+ if ( is_array( $value ) ) {
64
+ $attributes[ $key ] = implode( ',', $value );
65
+ }
66
+ // 'sub_title' -> 'sub-title'
67
+ if ( $key == 'sub_title' ) {
68
+ $attributes[ 'sub-title' ] = $attributes[ $key ];
69
+ unset( $attributes[ $key ] );
70
+ }
71
+ }
72
+
73
+ echo Shortcode::get_instance()->show_shortcode( $attributes );
74
+ }
75
+
76
+ public static function elementor_render_timetable( $attributes ) {
77
+
78
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
79
+
80
+ self::show_shortcode( $attributes );
81
+ }
82
+
83
+ protected function _register_controls() {
84
+ $controls = $this;
85
+
86
+ $controls->start_controls_section(
87
+ 'content_settings',
88
+ [
89
+ 'label' => __( 'Settings', 'mp-timetable' ),
90
+ 'tab' => Controls_Manager::TAB_CONTENT,
91
+ ]
92
+ );
93
+
94
+ $controls->add_control(
95
+ 'label',
96
+ [
97
+ 'label' => esc_html__( 'Filter title to display all events', 'mp-timetable' ),
98
+ 'label_block' => true,
99
+ 'type' => Controls_Manager::TEXT,
100
+ 'default' => esc_html__( 'All Events', 'mp-timetable' ),
101
+ ]
102
+ );
103
+
104
+ $controls->add_control(
105
+ 'hide_label',
106
+ [
107
+ 'label' => esc_html__( 'Hide \'All Events\' option', 'mp-timetable' ),
108
+ 'type' => Controls_Manager::SWITCHER,
109
+ 'default' => 'no',
110
+ ]
111
+ );
112
+
113
+ $controls->add_control(
114
+ 'col',
115
+ [
116
+ 'label' => esc_html__( 'Columns', 'mp-timetable' ),
117
+ 'label_block' => true,
118
+ 'type' => Controls_Manager::SELECT2,
119
+ 'multiple' => true,
120
+ 'options' => $this->get_posts_type( 'mp-column' ),
121
+ 'separator' => 'before',
122
+ ]
123
+ );
124
+
125
+ $controls->add_control(
126
+ 'events',
127
+ [
128
+ 'label' => esc_html__( 'Specific events', 'mp-timetable' ),
129
+ 'label_block' => true,
130
+ 'type' => Controls_Manager::SELECT2,
131
+ 'multiple' => true,
132
+ 'options' => $this->get_posts_type( 'mp-event' ),
133
+ ]
134
+ );
135
+
136
+ $controls->add_control(
137
+ 'event_categ',
138
+ [
139
+ 'label' => esc_html__( 'Event categories', 'mp-timetable' ),
140
+ 'label_block' => true,
141
+ 'type' => Controls_Manager::SELECT2,
142
+ 'multiple' => true,
143
+ 'options' => $this->get_terms_type( 'mp-event_category' ),
144
+ 'separator' => 'after',
145
+ ]
146
+ );
147
+
148
+ $controls->add_control(
149
+ 'title',
150
+ [
151
+ 'label' => esc_html__( 'Title', 'mp-timetable' ),
152
+ 'type' => Controls_Manager::SWITCHER,
153
+ 'label_off' => esc_html__( 'Hide', 'mp-timetable' ),
154
+ 'label_on' => esc_html__( 'Show', 'mp-timetable' ),
155
+ 'default' => 'yes',
156
+ ]
157
+ );
158
+
159
+ $controls->add_control(
160
+ 'time',
161
+ [
162
+ 'label' => esc_html__( 'Time', 'mp-timetable' ),
163
+ 'type' => Controls_Manager::SWITCHER,
164
+ 'label_off' => esc_html__( 'Hide', 'mp-timetable' ),
165
+ 'label_on' => esc_html__( 'Show', 'mp-timetable' ),
166
+ 'default' => 'yes',
167
+ ]
168
+ );
169
+
170
+ $controls->add_control(
171
+ 'sub_title',
172
+ [
173
+ 'label' => esc_html__( 'Subtitle', 'mp-timetable' ),
174
+ 'type' => Controls_Manager::SWITCHER,
175
+ 'label_off' => esc_html__( 'Hide', 'mp-timetable' ),
176
+ 'label_on' => esc_html__( 'Show', 'mp-timetable' ),
177
+ 'default' => 'no',
178
+ ]
179
+ );
180
+
181
+ $controls->add_control(
182
+ 'description',
183
+ [
184
+ 'label' => esc_html__( 'Description', 'mp-timetable' ),
185
+ 'type' => Controls_Manager::SWITCHER,
186
+ 'label_off' => esc_html__( 'Hide', 'mp-timetable' ),
187
+ 'label_on' => esc_html__( 'Show', 'mp-timetable' ),
188
+ 'default' => 'yes',
189
+ ]
190
+ );
191
+
192
+ $controls->add_control(
193
+ 'user',
194
+ [
195
+ 'label' => esc_html__( 'Event Head', 'mp-timetable' ),
196
+ 'type' => Controls_Manager::SWITCHER,
197
+ 'label_off' => esc_html__( 'Hide', 'mp-timetable' ),
198
+ 'label_on' => esc_html__( 'Show', 'mp-timetable' ),
199
+ 'default' => 'no',
200
+ ]
201
+ );
202
+
203
+ $controls->add_control(
204
+ 'hide_hrs',
205
+ [
206
+ 'label' => esc_html__( 'Hide column with hours', 'mp-timetable' ),
207
+ 'type' => Controls_Manager::SWITCHER,
208
+ 'default' => 'no',
209
+ ]
210
+ );
211
+
212
+ $controls->add_control(
213
+ 'hide_empty_rows',
214
+ [
215
+ 'label' => esc_html__( 'Do not display empty rows', 'mp-timetable' ),
216
+ 'type' => Controls_Manager::SWITCHER,
217
+ 'default' => 'yes',
218
+ ]
219
+ );
220
+
221
+ $controls->add_control(
222
+ 'group',
223
+ [
224
+ 'label' => esc_html__( 'Merge cells with common events', 'mp-timetable' ),
225
+ 'type' => Controls_Manager::SWITCHER,
226
+ 'default' => 'no',
227
+ ]
228
+ );
229
+
230
+ $controls->add_control(
231
+ 'disable_event_url',
232
+ [
233
+ 'label' => esc_html__( 'Disable event link', 'mp-timetable' ),
234
+ 'type' => Controls_Manager::SWITCHER,
235
+ 'default' => 'no',
236
+ ]
237
+ );
238
+
239
+ $controls->add_control(
240
+ 'font_size',
241
+ [
242
+ 'label' => esc_html__( 'Base font size', 'mp-timetable' ),
243
+ 'label_block' => true,
244
+ 'type' => Controls_Manager::TEXT,
245
+ 'description' => __( 'Base font size for the table. Example 12px, 2em, 80%.', 'mp-timetable' ),
246
+ 'separator' => 'before',
247
+ ]
248
+ );
249
+
250
+ $controls->add_control(
251
+ 'row_height',
252
+ [
253
+ 'label' => esc_html__( 'Block height in pixels', 'mp-timetable' ),
254
+ 'type' => Controls_Manager::NUMBER,
255
+ 'default' => 45,
256
+ ]
257
+ );
258
+
259
+ $controls->add_control(
260
+ 'increment',
261
+ [
262
+ 'label' => esc_html__( 'Time frame for event', 'mp-timetable' ),
263
+ 'type' => Controls_Manager::SELECT,
264
+ 'default' => '1',
265
+ 'label_block' => false,
266
+ 'options' => [
267
+ '1' => esc_html__( 'Hour (1h)', 'mp-timetable' ),
268
+ '0.5' => esc_html__( 'Half hour (30min)', 'mp-timetable' ),
269
+ '0.25' => esc_html__( 'Quarter hour (15min)', 'mp-timetable' ),
270
+ ],
271
+ ]
272
+ );
273
+
274
+ $controls->add_control(
275
+ 'view',
276
+ [
277
+ 'label' => esc_html__( 'Filter events style', 'mp-timetable' ),
278
+ 'type' => Controls_Manager::SELECT,
279
+ 'default' => 'dropdown_list',
280
+ 'label_block' => false,
281
+ 'options' => [
282
+ 'dropdown_list' => esc_html__( 'Dropdown', 'mp-timetable' ),
283
+ 'tabs' => esc_html__( 'Tabs', 'mp-timetable' ),
284
+ ],
285
+ ]
286
+ );
287
+
288
+ $controls->add_control(
289
+ 'view_sort',
290
+ [
291
+ 'label' => esc_html__( 'Order of items in filter', 'mp-timetable' ),
292
+ 'type' => Controls_Manager::SELECT,
293
+ 'default' => '',
294
+ 'label_block' => false,
295
+ 'options' => [
296
+ '' => esc_html__( 'Default', 'mp-timetable' ),
297
+ 'menu_order' => esc_html__( 'Menu Order', 'mp-timetable' ),
298
+ 'post_title' => esc_html__( 'Title', 'mp-timetable' ),
299
+ ],
300
+ ]
301
+ );
302
+
303
+ $controls->add_control(
304
+ 'column_width',
305
+ [
306
+ 'label' => esc_html__( 'Column width', 'mp-timetable' ),
307
+ 'type' => Controls_Manager::SELECT,
308
+ 'default' => '',
309
+ 'label_block' => false,
310
+ 'options' => [
311
+ '' => esc_html__( 'Default', 'mp-timetable' ),
312
+ 'auto' => esc_html__( 'Auto', 'mp-timetable' ),
313
+ 'fixed' => esc_html__( 'Fixed', 'mp-timetable' ),
314
+ ],
315
+ ]
316
+ );
317
+
318
+ $controls->add_control(
319
+ 'responsive',
320
+ [
321
+ 'label' => esc_html__( 'Mobile behavior', 'mp-timetable' ),
322
+ 'type' => Controls_Manager::SELECT,
323
+ 'default' => '0',
324
+ 'label_block' => false,
325
+ 'options' => [
326
+ '0' => esc_html__( 'Table', 'mp-timetable' ),
327
+ '1' => esc_html__( 'List', 'mp-timetable' ),
328
+ ],
329
+ 'separator' => 'before',
330
+ ]
331
+ );
332
+
333
+ $controls->add_control(
334
+ 'text_align_horizontal',
335
+ [
336
+ 'label' => esc_html__( 'Horizontal align', 'mp-timetable' ),
337
+ 'type' => Controls_Manager::CHOOSE,
338
+ 'default' => 'center',
339
+ 'toggle' => false,
340
+ 'options' => [
341
+ 'left' => [
342
+ 'title' => esc_html__( 'left', 'mp-timetable' ),
343
+ 'icon' => 'fa fa-align-left',
344
+ ],
345
+ 'center' => [
346
+ 'title' => esc_html__( 'center', 'mp-timetable' ),
347
+ 'icon' => 'fa fa-align-center',
348
+ ],
349
+ 'right' => [
350
+ 'title' => esc_html__( 'right', 'mp-timetable' ),
351
+ 'icon' => 'fa fa-align-right',
352
+ ],
353
+ ],
354
+ 'separator' => 'before',
355
+ ]
356
+ );
357
+
358
+ $controls->add_control(
359
+ 'text_align_vertical',
360
+ [
361
+ 'label' => esc_html__( 'Vertical align', 'mp-timetable' ),
362
+ 'type' => Controls_Manager::CHOOSE,
363
+ 'default' => 'default',
364
+ 'toggle' => false,
365
+ 'options' => [
366
+ 'default' => [
367
+ 'title' => esc_html__( 'default', 'mp-timetable' ),
368
+ 'icon' => 'eicon-v-align-stretch',
369
+ ],
370
+ 'top' => [
371
+ 'title' => esc_html__( 'top', 'mp-timetable' ),
372
+ 'icon' => 'eicon-v-align-top',
373
+ ],
374
+ 'middle' => [
375
+ 'title' => esc_html__( 'middle', 'mp-timetable' ),
376
+ 'icon' => 'eicon-v-align-middle',
377
+ ],
378
+ 'bottom' => [
379
+ 'title' => esc_html__( 'bottom', 'mp-timetable' ),
380
+ 'icon' => 'eicon-v-align-bottom',
381
+ ],
382
+ ],
383
+ ]
384
+ );
385
+
386
+ $controls->add_control(
387
+ 'unique_id',
388
+ [
389
+ 'label' => esc_html__( 'Unique ID', 'mp-timetable' ),
390
+ 'label_block' => true,
391
+ 'type' => Controls_Manager::TEXT,
392
+ 'description' => __( 'If you use more than one table on a page specify the unique ID for a timetable. It is usually all lowercase and contains only letters, numbers, and hyphens.', 'mp-timetable' ),
393
+ 'dynamic' => [ 'active' => true ],
394
+ 'separator' => 'before',
395
+ ]
396
+ );
397
+
398
+ $controls->add_control(
399
+ 'custom_class',
400
+ [
401
+ 'label' => esc_html__( 'CSS class', 'mp-timetable' ),
402
+ 'label_block' => true,
403
+ 'type' => Controls_Manager::TEXT,
404
+ 'dynamic' => [ 'active' => true ]
405
+ ]
406
+ );
407
+
408
+ $controls->end_controls_section();
409
+ }
410
+
411
+ protected function render() {
412
+ $settings = $this->get_settings();
413
+
414
+ $label = $settings[ 'label' ];
415
+ $font_size = $settings[ 'font_size' ];
416
+ $col = $settings[ 'col' ];
417
+ $events = $settings[ 'events' ];
418
+ $event_categ = $settings[ 'event_categ' ];
419
+ $title = $settings[ 'title' ] === 'yes' ? '1' : '0';
420
+ $time = $settings[ 'time' ] === 'yes' ? '1' : '0';
421
+ $subtitle = $settings[ 'sub_title' ] === 'yes' ? '1' : '0';
422
+ $description = $settings[ 'description' ] === 'yes' ? '1' : '0';
423
+ $user = $settings[ 'user' ] === 'yes' ? '1' : '0';
424
+ $hide_label = $settings[ 'hide_label' ] === 'yes' ? '1' : '0';
425
+ $hide_hrs = $settings[ 'hide_hrs' ] === 'yes' ? '1' : '0';
426
+ $hide_empty_rows = $settings[ 'hide_empty_rows' ] === 'yes' ? '1' : '0';
427
+ $group = $settings[ 'group' ] === 'yes' ? '1' : '0';
428
+ $disable_event_url = $settings[ 'disable_event_url' ] === 'yes' ? '1' : '0';
429
+ $row_height = $settings[ 'row_height' ];
430
+ $view_sort = $settings[ 'view_sort' ];
431
+ $increment = $settings[ 'increment' ];
432
+ $view = $settings[ 'view' ];
433
+ $text_align_horizontal = $settings[ 'text_align_horizontal' ];
434
+ $text_align_vertical = $settings[ 'text_align_vertical' ];
435
+ $column_width = $settings[ 'column_width' ];
436
+ $responsive = $settings[ 'responsive' ];
437
+ $id = $settings[ 'unique_id' ];
438
+ $custom_class = $settings[ 'custom_class' ];
439
+
440
+ $attributes = array(
441
+ 'col' => $col,
442
+ 'events' => $events,
443
+ 'event_categ' => $event_categ,
444
+ 'label' => $label,
445
+ 'font_size' => $font_size,
446
+ 'time' => $time,
447
+ 'custom_class' => $custom_class,
448
+ 'id' => $id,
449
+ 'table_layout' => $column_width,
450
+ 'increment' => $increment,
451
+ 'view' => $view,
452
+ 'view_sort' => $view_sort,
453
+ 'hide_label' => $hide_label,
454
+ 'hide_hrs' => $hide_hrs,
455
+ 'hide_empty_rows' => $hide_empty_rows,
456
+ 'title' => $title,
457
+ 'sub_title' => $subtitle,
458
+ 'description' => $description,
459
+ 'user' => $user,
460
+ 'group' => $group,
461
+ 'disable_event_url' => $disable_event_url,
462
+ 'text_align' => $text_align_horizontal,
463
+ 'row_height' => $row_height,
464
+ 'responsive' => $responsive,
465
+ 'text_align_vertical' => $text_align_vertical,
466
+ );
467
+
468
+ $this->elementor_render_timetable( $attributes );
469
+ }
470
+
471
+ }
472
+
473
  Plugin::instance()->widgets_manager->register_widget_type( new Mp_Timetable_Widget() );
classes/widgets/class-mp-timetable-widget.php CHANGED
@@ -1,142 +1,142 @@
1
- <?php
2
-
3
- namespace timetable\classes\widgets;
4
-
5
- use mp_timetable\classes\models\Column;
6
- use mp_timetable\classes\models\Events;
7
- use mp_timetable\classes\models\Settings;
8
- use mp_timetable\plugin_core\classes\Core;
9
- use mp_timetable\plugin_core\classes\View;
10
-
11
- class Timetable_widget extends \WP_Widget {
12
-
13
- /**
14
- * Widget constructor.
15
- */
16
- public function __construct() {
17
-
18
- $classname = Settings::get_instance()->is_plugin_template_mode() ? 'mptt-container' : 'widget_recent_entries';
19
-
20
- $widget_ops = array(
21
- 'classname' => $classname,
22
- 'description' => __( 'Display upcoming events.', 'mp-timetable' )
23
- );
24
- parent::__construct( 'mp-timetable', __( 'Timetable Events', 'mp-timetable' ), $widget_ops );
25
- add_action( 'save_post', array( &$this, 'flush_widget_cache' ) );
26
- add_action( 'deleted_post', array( &$this, 'flush_widget_cache' ) );
27
- add_action( 'switch_theme', array( &$this, 'flush_widget_cache' ) );
28
- }
29
-
30
- public function form( $instance ) {
31
- $instance = shortcode_atts( array(
32
- 'title' => '',
33
- 'limit' => '3',
34
- 'view_settings' => '',
35
- 'mp_categories' => '',
36
- 'next_days' => '1',
37
- 'time_settings' => '',
38
- 'custom_url' => '',
39
- 'disable_url' => '',
40
- 'background_color' => '',
41
- 'hover_background_color' => '',
42
- 'text_color' => '',
43
- 'hover_text_color' => '',
44
- 'item_border_color' => '',
45
- 'hover_item_border_color' => '',
46
- ), $instance );
47
-
48
- /*$data[ 'columns' ] = Column::get_instance()->get_all_column();
49
- $data[ 'events' ] = Events::get_instance()->get_all_events();
50
- $data[ 'categories' ] = get_terms( 'mp-event_category', 'orderby=count&hide_empty=0' );
51
- $data[ 'localtime' ] = date( get_option( 'time_format' ), current_time( 'timestamp', 0 ) );
52
- $data[ 'utc_time' ] = date( get_option( 'time_format' ), current_time( 'timestamp', 1 ) );
53
-
54
- View::get_instance()->render_html( 'widgets/gallery-list', array( 'widget_object' => $this, 'data' => $data, 'instance' => $instance ), true );*/
55
-
56
- $event_categories = get_terms( 'mp-event_category', 'orderby=title&hide_empty=0' );
57
-
58
- View::get_instance()->render_html('widgets/gallery-list', array(
59
- 'widget_object' => $this,
60
- 'event_categories' => $event_categories,
61
- 'instance' => $instance
62
- ), true);
63
-
64
- }
65
-
66
- /**
67
- * Update widget
68
- *
69
- * @param array $new_instance
70
- * @param array $old_instance
71
- *
72
- * @return array
73
- */
74
- public function update( $new_instance, $old_instance ) {
75
-
76
- $instance = $old_instance;
77
- $instance[ 'title' ] = strip_tags( $new_instance[ 'title' ] );
78
- $instance[ 'limit' ] = strip_tags( $new_instance[ 'limit' ] );
79
- $instance[ 'mp_categories' ] = empty( $new_instance[ 'mp_categories' ] ) ? "" : $new_instance[ 'mp_categories' ];
80
- $instance[ 'view_settings' ] = strip_tags( $new_instance[ 'view_settings' ] );
81
- $instance[ 'next_days' ] = strip_tags( $new_instance[ 'next_days' ] );
82
- $instance[ 'time_settings' ] = empty( $new_instance[ 'time_settings' ] ) ? "" : strip_tags( $new_instance[ 'time_settings' ] );
83
- $instance[ 'custom_url' ] = strip_tags( $new_instance[ 'custom_url' ] );
84
- $instance[ 'disable_url' ] = strip_tags( $new_instance[ 'disable_url' ] );
85
- $instance[ 'background_color' ] = strip_tags( $new_instance[ 'background_color' ] );
86
- $instance[ 'hover_background_color' ] = strip_tags( $new_instance[ 'hover_background_color' ] );
87
- $instance[ 'text_color' ] = strip_tags( $new_instance[ 'text_color' ] );
88
- $instance[ 'hover_text_color' ] = strip_tags( $new_instance[ 'hover_text_color' ] );
89
- $instance[ 'item_border_color' ] = strip_tags( $new_instance[ 'item_border_color' ] );
90
- $instance[ 'hover_item_border_color' ] = strip_tags( $new_instance[ 'hover_item_border_color' ] );
91
-
92
- return $instance;
93
- }
94
-
95
- /**
96
- * Flush widget cache.
97
- *
98
- * @since Twenty Eleven 1.0
99
- */
100
- function flush_widget_cache() {
101
- wp_cache_delete( 'mp-timetable', 'widget' );
102
- }
103
-
104
- /**
105
- * Display widget
106
- *
107
- * @param array $args
108
- * @param array $instance
109
- */
110
- public function widget( $args, $instance ) {
111
- $cache = wp_cache_get( 'mp-timetable', 'widget' );
112
-
113
- if ( ! is_array( $cache ) ) {
114
- $cache = array();
115
- }
116
-
117
- if ( ! isset( $args[ 'widget_id' ] ) ) {
118
- $args[ 'widget_id' ] = null;
119
- }
120
-
121
- if ( isset( $cache[ $args[ 'widget_id' ] ] ) ) {
122
- echo $cache[ $args[ 'widget_id' ] ];
123
-
124
- return;
125
- }
126
-
127
- ob_start();
128
- $data[ 'args' ] = $args;
129
- $data[ 'instance' ] = mptt_widget_settings( $instance );
130
- $data[ 'events' ] = Events::get_instance()->get_widget_events( $data[ 'instance' ] );
131
- if ( Settings::get_instance()->is_plugin_template_mode() ) {
132
- Core::get_instance()->add_plugin_js( 'widget' );
133
- View::get_instance()->get_template( "widgets/widget-view", $data );
134
- } else {
135
- View::get_instance()->get_template( "theme/widget-upcoming-view", $data );
136
- }
137
-
138
- $cache[ $args[ 'widget_id' ] ] = ob_get_flush();
139
- wp_cache_set( 'mp-timetable', $cache, 'widget' );
140
- }
141
- }
142
-
1
+ <?php
2
+
3
+ namespace timetable\classes\widgets;
4
+
5
+ use mp_timetable\classes\models\Column;
6
+ use mp_timetable\classes\models\Events;
7
+ use mp_timetable\classes\models\Settings;
8
+ use mp_timetable\plugin_core\classes\Core;
9
+ use mp_timetable\plugin_core\classes\View;
10
+
11
+ class Timetable_widget extends \WP_Widget {
12
+
13
+ /**
14
+ * Widget constructor.
15
+ */
16
+ public function __construct() {
17
+
18
+ $classname = Settings::get_instance()->is_plugin_template_mode() ? 'mptt-container' : 'widget_recent_entries';
19
+
20
+ $widget_ops = array(
21
+ 'classname' => $classname,
22
+ 'description' => __( 'Display upcoming events.', 'mp-timetable' )
23
+ );
24
+ parent::__construct( 'mp-timetable', __( 'Timetable Events', 'mp-timetable' ), $widget_ops );
25
+ add_action( 'save_post', array( &$this, 'flush_widget_cache' ) );
26
+ add_action( 'deleted_post', array( &$this, 'flush_widget_cache' ) );
27
+ add_action( 'switch_theme', array( &$this, 'flush_widget_cache' ) );
28
+ }
29
+
30
+ public function form( $instance ) {
31
+ $instance = shortcode_atts( array(
32
+ 'title' => '',
33
+ 'limit' => '3',
34
+ 'view_settings' => '',
35
+ 'mp_categories' => '',
36
+ 'next_days' => '1',
37
+ 'time_settings' => '',
38
+ 'custom_url' => '',
39
+ 'disable_url' => '',
40
+ 'background_color' => '',
41
+ 'hover_background_color' => '',
42
+ 'text_color' => '',
43
+ 'hover_text_color' => '',
44
+ 'item_border_color' => '',
45
+ 'hover_item_border_color' => '',
46
+ ), $instance );
47
+
48
+ /*$data[ 'columns' ] = Column::get_instance()->get_all_column();
49
+ $data[ 'events' ] = Events::get_instance()->get_all_events();
50
+ $data[ 'categories' ] = get_terms( 'mp-event_category', 'orderby=count&hide_empty=0' );
51
+ $data[ 'localtime' ] = date( get_option( 'time_format' ), current_time( 'timestamp', 0 ) );
52
+ $data[ 'utc_time' ] = date( get_option( 'time_format' ), current_time( 'timestamp', 1 ) );
53
+
54
+ View::get_instance()->render_html( 'widgets/gallery-list', array( 'widget_object' => $this, 'data' => $data, 'instance' => $instance ), true );*/
55
+
56
+ $event_categories = get_terms( 'mp-event_category', 'orderby=title&hide_empty=0' );
57
+
58
+ View::get_instance()->render_html('widgets/gallery-list', array(
59
+ 'widget_object' => $this,
60
+ 'event_categories' => $event_categories,
61
+ 'instance' => $instance
62
+ ), true);
63
+
64
+ }
65
+
66
+ /**
67
+ * Update widget
68
+ *
69
+ * @param array $new_instance
70
+ * @param array $old_instance
71
+ *
72
+ * @return array
73
+ */
74
+ public function update( $new_instance, $old_instance ) {
75
+
76
+ $instance = $old_instance;
77
+ $instance[ 'title' ] = strip_tags( $new_instance[ 'title' ] );
78
+ $instance[ 'limit' ] = strip_tags( $new_instance[ 'limit' ] );
79
+ $instance[ 'mp_categories' ] = empty( $new_instance[ 'mp_categories' ] ) ? "" : $new_instance[ 'mp_categories' ];
80
+ $instance[ 'view_settings' ] = strip_tags( $new_instance[ 'view_settings' ] );
81
+ $instance[ 'next_days' ] = strip_tags( $new_instance[ 'next_days' ] );
82
+ $instance[ 'time_settings' ] = empty( $new_instance[ 'time_settings' ] ) ? "" : strip_tags( $new_instance[ 'time_settings' ] );
83
+ $instance[ 'custom_url' ] = strip_tags( $new_instance[ 'custom_url' ] );
84
+ $instance[ 'disable_url' ] = strip_tags( $new_instance[ 'disable_url' ] );
85
+ $instance[ 'background_color' ] = strip_tags( $new_instance[ 'background_color' ] );
86
+ $instance[ 'hover_background_color' ] = strip_tags( $new_instance[ 'hover_background_color' ] );
87
+ $instance[ 'text_color' ] = strip_tags( $new_instance[ 'text_color' ] );
88
+ $instance[ 'hover_text_color' ] = strip_tags( $new_instance[ 'hover_text_color' ] );
89
+ $instance[ 'item_border_color' ] = strip_tags( $new_instance[ 'item_border_color' ] );
90
+ $instance[ 'hover_item_border_color' ] = strip_tags( $new_instance[ 'hover_item_border_color' ] );
91
+
92
+ return $instance;
93
+ }
94
+
95
+ /**
96
+ * Flush widget cache.
97
+ *
98
+ * @since Twenty Eleven 1.0
99
+ */
100
+ function flush_widget_cache() {
101
+ wp_cache_delete( 'mp-timetable', 'widget' );
102
+ }
103
+
104
+ /**
105
+ * Display widget
106
+ *
107
+ * @param array $args
108
+ * @param array $instance
109
+ */
110
+ public function widget( $args, $instance ) {
111
+ $cache = wp_cache_get( 'mp-timetable', 'widget' );
112
+
113
+ if ( ! is_array( $cache ) ) {
114
+ $cache = array();
115
+ }
116
+
117
+ if ( ! isset( $args[ 'widget_id' ] ) ) {
118
+ $args[ 'widget_id' ] = null;
119
+ }
120
+
121
+ if ( isset( $cache[ $args[ 'widget_id' ] ] ) ) {
122
+ echo $cache[ $args[ 'widget_id' ] ];
123
+
124
+ return;
125
+ }
126
+
127
+ ob_start();
128
+ $data[ 'args' ] = $args;
129
+ $data[ 'instance' ] = mptt_widget_settings( $instance );
130
+ $data[ 'events' ] = Events::get_instance()->get_widget_events( $data[ 'instance' ] );
131
+ if ( Settings::get_instance()->is_plugin_template_mode() ) {
132
+ Core::get_instance()->add_plugin_js( 'widget' );
133
+ View::get_instance()->get_template( "widgets/widget-view", $data );
134
+ } else {
135
+ View::get_instance()->get_template( "theme/widget-upcoming-view", $data );
136
+ }
137
+
138
+ $cache[ $args[ 'widget_id' ] ] = ob_get_flush();
139
+ wp_cache_set( 'mp-timetable', $cache, 'widget' );
140
+ }
141
+ }
142
+
languages/mp-timetable-fa_IR.po CHANGED
@@ -1,962 +1,962 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: Timetable and Event Schedule Plugin\n"
4
- "POT-Creation-Date: 2018-05-18 09:58+0430\n"
5
- "PO-Revision-Date: \n"
6
- "Last-Translator: \n"
7
- "Language-Team: Alireza Rastegar<alireza.mine@gmail.com>\n"
8
- "Language: fa_IR\n"
9
- "MIME-Version: 1.0\n"
10
- "Content-Type: text/plain; charset=UTF-8\n"
11
- "Content-Transfer-Encoding: 8bit\n"
12
- "Plural-Forms: nplurals=1; plural=0;\n"
13
- "X-Generator: Poedit 2.0.1\n"
14
- "X-Poedit-SourceCharset: UTF-8\n"
15
- "X-Poedit-KeywordsList: esc_attr__;esc_html__;esc_attr_e;__;_e;_n;_x\n"
16
- "X-Poedit-Basepath: ..\n"
17
- "X-Poedit-SearchPath-0: .\n"
18
- "X-Poedit-SearchPathExcluded-0: classes/libs\n"
19
- "X-Poedit-SearchPathExcluded-1: media\n"
20
-
21
- #: admin/import/export.php:1 admin/import/export.php:5
22
- msgid "Export"
23
- msgstr "برونریزی"
24
-
25
- #: admin/import/greet.php:2
26
- msgid "Choose a WXR (.xml) file to upload, then click Upload file and import."
27
- msgstr ""
28
- "یک فایل WXR (.xml) را برای آپلود انتخاب کنید، سپس روی آپلود فایل و وارد کردن "
29
- "کلیک کنید."
30
-
31
- #: admin/import/header.php:2
32
- msgid "Import / Export Timetable Plugin Data"
33
- msgstr "درون ریزی / برون ریزی داده افزونه جدول زمانی"
34
-
35
- #: admin/import/import.php:1
36
- msgid "Import"
37
- msgstr "درون ریزی"
38
-
39
- #: classes/class-core.php:317 classes/class-core.php:329
40
- #: classes/class-core.php:333 classes/class-shortcode.php:261
41
- msgid "Event categories"
42
- msgstr "دسته های رویداد"
43
-
44
- #: classes/class-core.php:318
45
- msgid "Event category"
46
- msgstr "دسته بندی رویداد"
47
-
48
- #: classes/class-core.php:319 classes/class-core.php:320
49
- msgid "Add New Event category"
50
- msgstr "افزودن دسته بندی رویداد"
51
-
52
- #: classes/class-core.php:321
53
- msgid "Edit Event category"
54
- msgstr "ویرایش دسته بندی رویداد"
55
-
56
- #: classes/class-core.php:322
57
- msgid "New Event category"
58
- msgstr "دسته رویداد جدید"
59
-
60
- #: classes/class-core.php:323
61
- msgid "All Event categories"
62
- msgstr "همه دسته های رویداد"
63
-
64
- #: classes/class-core.php:324
65
- msgid "View Event category"
66
- msgstr "نمایش دسته رویداد"
67
-
68
- #: classes/class-core.php:325
69
- msgid "Search Event category"
70
- msgstr "جستجوی دسته رویداد"
71
-
72
- #: classes/class-core.php:326
73
- msgid "No Event categories found"
74
- msgstr "دسته رویدادی پیدا نشد"
75
-
76
- #: classes/class-core.php:327
77
- msgid "No Event categories found in Trash"
78
- msgstr "هیچ دسته رویدادی در «حذف شده ها» یافت نشد"
79
-
80
- #: classes/class-core.php:356 classes/class-core.php:368
81
- #: classes/class-core.php:372
82
- msgid "Event tags"
83
- msgstr "برچسب های رویداد"
84
-
85
- #: classes/class-core.php:357
86
- msgid "Event tag"
87
- msgstr "برچسب رویداد"
88
-
89
- #: classes/class-core.php:358 classes/class-core.php:359
90
- msgid "Add New Event tag"
91
- msgstr "افزودن برچسب جدید رویداد"
92
-
93
- #: classes/class-core.php:360
94
- msgid "Edit Event tag"
95
- msgstr "ویرایش برچسب رویداد"
96
-
97
- #: classes/class-core.php:361
98
- msgid "New Event tag"
99
- msgstr "برچسب جدید رویداد"
100
-
101
- #: classes/class-core.php:362
102
- msgid "All Event tags"
103
- msgstr "همه برچسب های رویداد"
104
-
105
- #: classes/class-core.php:363
106
- msgid "View Event tag"
107
- msgstr "نمایش برچسب رویداد"
108
-
109
- #: classes/class-core.php:364
110
- msgid "Search Event tag"
111
- msgstr "جستجوی برچسب رویداد"
112
-
113
- #: classes/class-core.php:365
114
- msgid "No Event tags found"
115
- msgstr "برچسب رویداد یافت نشد"
116
-
117
- #: classes/class-core.php:366
118
- msgid "No Event tags found in Trash"
119
- msgstr "هیچ برچسب رویدادی در «حذف شده ها» یافت نشد"
120
-
121
- #: classes/class-core.php:404 classes/class-core.php:416
122
- #: classes/class-hooks.php:171 classes/class-shortcode.php:256
123
- msgid "Events"
124
- msgstr "رویدادها"
125
-
126
- #: classes/class-core.php:405
127
- msgid "Event"
128
- msgstr "رویداد"
129
-
130
- #: classes/class-core.php:406 classes/class-core.php:407
131
- msgid "Add New Event"
132
- msgstr "افزودن رویداد جدید"
133
-
134
- #: classes/class-core.php:408
135
- msgid "Edit Event"
136
- msgstr "ویرایش رویداد"
137
-
138
- #: classes/class-core.php:409
139
- msgid "New Event"
140
- msgstr "رویداد جدید"
141
-
142
- #: classes/class-core.php:410 classes/class-shortcode.php:69
143
- #: classes/class-shortcode.php:277
144
- #: templates-functions/action-shortcode-functions.php:39
145
- #: templates-functions/action-shortcode-functions.php:52
146
- #: templates-functions/action-shortcode-functions.php:53
147
- msgid "All Events"
148
- msgstr "همه رویدادها"
149
-
150
- #: classes/class-core.php:411
151
- msgid "View Event"
152
- msgstr "نمایش رویداد"
153
-
154
- #: classes/class-core.php:412
155
- msgid "Search Event"
156
- msgstr "جستجوی رویداد"
157
-
158
- #: classes/class-core.php:413
159
- msgid "No Events found"
160
- msgstr "رویدادی یافت نشد"
161
-
162
- #: classes/class-core.php:414
163
- msgid "No Events found in Trash"
164
- msgstr "هیچ رویدادی در «حذف شده ها» یافت نشد"
165
-
166
- #: classes/class-core.php:438 classes/class-core.php:450
167
- #: classes/class-hooks.php:173
168
- msgid "Columns"
169
- msgstr "ستون ها"
170
-
171
- #: classes/class-core.php:439 classes/class-shortcode.php:251
172
- #: templates/events/event-data.php:4
173
- msgid "Column"
174
- msgstr "ستون"
175
-
176
- #: classes/class-core.php:440 classes/class-core.php:441
177
- msgid "Add New Column"
178
- msgstr "افزودن ستون جدید"
179
-
180
- #: classes/class-core.php:442
181
- msgid "Edit Column"
182
- msgstr "ویرایش ستون"
183
-
184
- #: classes/class-core.php:443
185
- msgid "New Column"
186
- msgstr "ستون جدید"
187
-
188
- #: classes/class-core.php:444
189
- msgid "All Columns"
190
- msgstr "همه ستون ها"
191
-
192
- #: classes/class-core.php:445
193
- msgid "View Column"
194
- msgstr "نمایش ستون"
195
-
196
- #: classes/class-core.php:446
197
- msgid "Search Column"
198
- msgstr "جستجوی ستون"
199
-
200
- #: classes/class-core.php:447
201
- msgid "No Columns found"
202
- msgstr "هیچ ستونی یافت نشد"
203
-
204
- #: classes/class-core.php:448
205
- msgid "No Columns found in Trash"
206
- msgstr "هیچ ستونی در «حذف شده ها» یافت نشد"
207
-
208
- #: classes/class-hooks.php:66
209
- msgid "Timetable Sidebar"
210
- msgstr "ابزارک جدول زمانی"
211
-
212
- #: classes/class-hooks.php:68 classes/class-hooks.php:170
213
- #: classes/class-shortcode.php:356
214
- msgid "Timetable"
215
- msgstr "جدول زمانی"
216
-
217
- #: classes/class-hooks.php:163
218
- msgid "Import Timetable events, categories, tags and images."
219
- msgstr "درون ریزی رویدادهای جدول زمانی، دسته بندی ها، برچسب ها و عکس ها"
220
-
221
- #: classes/class-hooks.php:172
222
- msgid "Add Event"
223
- msgstr "افزودن رویداد"
224
-
225
- #: classes/class-hooks.php:174
226
- msgid "Add Column"
227
- msgstr "افزودن ستون"
228
-
229
- #: classes/class-hooks.php:175
230
- msgid "Event Categories"
231
- msgstr "دسته های رویداد"
232
-
233
- #: classes/class-hooks.php:176
234
- msgid "Event Tags"
235
- msgstr "برچسب های رویداد"
236
-
237
- #: classes/class-hooks.php:177 classes/modules/class-post.php:41
238
- msgid "Settings"
239
- msgstr "تنظیمات"
240
-
241
- #: classes/class-hooks.php:178
242
- msgid "Export / Import"
243
- msgstr "درون ریزی/برون ریزی"
244
-
245
- #: classes/class-shortcode.php:266
246
- msgid "Hour measure"
247
- msgstr "اندازه گیری ساعت"
248
-
249
- #: classes/class-shortcode.php:267 templates/popup/index.php:66
250
- msgid "Hour (1h)"
251
- msgstr "ساعت (1 ساعت)"
252
-
253
- #: classes/class-shortcode.php:267 templates/popup/index.php:67
254
- msgid "Half hour (30min)"
255
- msgstr "نیم ساعت (30 دقیقه)"
256
-
257
- #: classes/class-shortcode.php:267 templates/popup/index.php:68
258
- msgid "Quarter hour (15min)"
259
- msgstr "ربع ساعت (15 دقیقه)"
260
-
261
- #: classes/class-shortcode.php:271
262
- msgid "Filter style"
263
- msgstr "سبک فیلتر"
264
-
265
- #: classes/class-shortcode.php:272
266
- msgid "Dropdown list"
267
- msgstr "لیست بازشو"
268
-
269
- #: classes/class-shortcode.php:272 templates/popup/index.php:77
270
- msgid "Tabs"
271
- msgstr "تب ها"
272
-
273
- #: classes/class-shortcode.php:276
274
- msgid "Filter label"
275
- msgstr "برچسب فیلتر"
276
-
277
- #: classes/class-shortcode.php:281
278
- msgid "Hide 'All Events' view"
279
- msgstr "نمایش ندادن همه رویدادها"
280
-
281
- #: classes/class-shortcode.php:282 classes/class-shortcode.php:287
282
- #: classes/class-shortcode.php:292 classes/class-shortcode.php:299
283
- #: classes/class-shortcode.php:305 classes/class-shortcode.php:311
284
- #: classes/class-shortcode.php:317 classes/class-shortcode.php:323
285
- #: classes/class-shortcode.php:328 classes/class-shortcode.php:352
286
- #: templates/events/metabox-event-options.php:45 templates/popup/index.php:93
287
- #: templates/popup/index.php:102 templates/popup/index.php:112
288
- #: templates/popup/index.php:120 templates/popup/index.php:129
289
- #: templates/widgets/gallery-list.php:60
290
- msgid "No"
291
- msgstr "خیر"
292
-
293
- #: classes/class-shortcode.php:282 classes/class-shortcode.php:287
294
- #: classes/class-shortcode.php:292 classes/class-shortcode.php:299
295
- #: classes/class-shortcode.php:305 classes/class-shortcode.php:311
296
- #: classes/class-shortcode.php:317 classes/class-shortcode.php:323
297
- #: classes/class-shortcode.php:328 classes/class-shortcode.php:352
298
- #: templates/events/metabox-event-options.php:46 templates/popup/index.php:94
299
- #: templates/popup/index.php:103 templates/popup/index.php:111
300
- #: templates/popup/index.php:121 templates/popup/index.php:130
301
- #: templates/widgets/gallery-list.php:62
302
- msgid "Yes"
303
- msgstr "بله"
304
-
305
- #: classes/class-shortcode.php:286
306
- msgid "Hide first (hours) column"
307
- msgstr "پنهان کردن ستون اول (ساعت)"
308
-
309
- #: classes/class-shortcode.php:291
310
- msgid "Hide empty rows"
311
- msgstr "پنهان کردن سطرهای خالی"
312
-
313
- #: classes/class-shortcode.php:297 templates/popup/index.php:40
314
- #: templates/widgets/gallery-list.php:3
315
- msgid "Title"
316
- msgstr "عنوان"
317
-
318
- #: classes/class-shortcode.php:303 templates/popup/index.php:41
319
- msgid "Time"
320
- msgstr "زمان"
321
-
322
- #: classes/class-shortcode.php:309 templates/popup/index.php:42
323
- msgid "Subtitle"
324
- msgstr "عنوان فرعی"
325
-
326
- #: classes/class-shortcode.php:315 templates/events/event-data.php:7
327
- #: templates/popup/index.php:43
328
- msgid "Description"
329
- msgstr "توضیحات"
330
-
331
- #: classes/class-shortcode.php:321
332
- msgid "User"
333
- msgstr "کاربر"
334
-
335
- #: classes/class-shortcode.php:327
336
- msgid "Disable event URL"
337
- msgstr "URL رویداد را غیرفعال کنید"
338
-
339
- #: classes/class-shortcode.php:332
340
- msgid "Text align"
341
- msgstr "چیدمان متن"
342
-
343
- #: classes/class-shortcode.php:333 templates/popup/index.php:137
344
- msgid "center"
345
- msgstr "وسط"
346
-
347
- #: classes/class-shortcode.php:333 templates/popup/index.php:138
348
- msgid "left"
349
- msgstr "چپ"
350
-
351
- #: classes/class-shortcode.php:333 templates/popup/index.php:139
352
- msgid "right"
353
- msgstr "راست"
354
-
355
- #: classes/class-shortcode.php:337
356
- msgid "Id"
357
- msgstr "ID"
358
-
359
- #: classes/class-shortcode.php:341
360
- msgid "Row height (in px)"
361
- msgstr "ارتفاع ردیف (در پیکسل)"
362
-
363
- #: classes/class-shortcode.php:346
364
- msgid "Base Font Size"
365
- msgstr "اندازه فونت پایه"
366
-
367
- #: classes/class-shortcode.php:351
368
- msgid "Responsive"
369
- msgstr "واکنش گرایی"
370
-
371
- #: classes/controllers/class-controller-settings.php:53
372
- msgid "Settings saved."
373
- msgstr "تنظیمات ذخیره شد."
374
-
375
- #: classes/models/class-column.php:42 classes/modules/class-post.php:40
376
- msgid "Timeslots"
377
- msgstr "فاصله زمانی"
378
-
379
- #: classes/models/class-events.php:167
380
- msgid "Tags"
381
- msgstr "تگ ها"
382
-
383
- #: classes/models/class-events.php:168
384
- msgid "Categories"
385
- msgstr "دسته ها"
386
-
387
- #: classes/models/class-import.php:125
388
- msgid "Assign Authors"
389
- msgstr "اختصاص دادن نویسندگان"
390
-
391
- #: classes/models/class-import.php:126
392
- msgid ""
393
- "To make it easier for you to edit and save the imported content, you may "
394
- "want to reassign the author of the imported item to an existing user of this "
395
- "site. For example, you may want to import all the entries as <code>admin</"
396
- "code>s entries."
397
- msgstr ""
398
- "برای اینکه بتوانید محتوای وارد شده را ویرایش و ذخیره کنید، ممکن است بخواهید "
399
- "نویسنده اثر وارد شده را به یک کاربر فعلی این سایت مجددا اختصاص دهید.به عنوان "
400
- "مثال، شما ممکن است بخواهید تمام ورودی ها را به عنوان ورودی <code> مدیر </"
401
- "code> وارد کنید."
402
-
403
- #: classes/models/class-import.php:128
404
- #, php-format
405
- msgid ""
406
- "If a new user is created by WordPress, a new password will be randomly "
407
- "generated and the new user&#8217;s role will be set as %s. Manually changing "
408
- "the new user&#8217;s details will be necessary."
409
- msgstr ""
410
- "اگر یک کاربر جدید توسط وردپرس ایجاد شده باشد، یک رمز عبور جدید به صورت "
411
- "تصادفی ایجاد خواهد شد و نقش کاربر جدید user&#8217;s به عنوان %s تنظیم خواهد "
412
- "شد. تغییر دستی اطلاعات جدید کاربر user&#8217;s ضروری است."
413
-
414
- #: classes/models/class-import.php:138
415
- msgid "Import Attachments"
416
- msgstr "درون ریزی پیوست ها"
417
-
418
- #: classes/models/class-import.php:141
419
- msgid "Download and import file attachments"
420
- msgstr "دریافت و درون ریزی فایل های پیوست"
421
-
422
- #: classes/models/class-import.php:145
423
- msgid "Submit"
424
- msgstr "ارسال"
425
-
426
- #: classes/models/class-import.php:158
427
- msgid "Import author:"
428
- msgstr "درون ریزی نویسنده:"
429
-
430
- #: classes/models/class-import.php:169
431
- msgid "or create new user with login name:"
432
- msgstr "یا ایجاد کاربر جدید با نام کاربری:"
433
-
434
- #: classes/models/class-import.php:172
435
- msgid "as a new user:"
436
- msgstr "به عنوان یک کاربر جدید:"
437
-
438
- #: classes/models/class-import.php:180
439
- msgid "assign posts to an existing user:"
440
- msgstr "اختصاص دادن پست به یک کاربر موجود:"
441
-
442
- #: classes/models/class-import.php:182
443
- msgid "or assign posts to an existing user:"
444
- msgstr "یا اختصاص دادن پست به یک کاربر موجود:"
445
-
446
- #: classes/models/class-import.php:183
447
- #: templates/column/metabox-column-options.php:18
448
- msgid "- Select -"
449
- msgstr "- انتخاب -"
450
-
451
- #: classes/models/class-import.php:269
452
- msgid "All done."
453
- msgstr "همه انجام شد."
454
-
455
- #: classes/models/class-import.php:269
456
- msgid "Have fun!"
457
- msgstr "خوش بگذره!"
458
-
459
- #: classes/models/class-import.php:270
460
- msgid "Remember to update the passwords and roles of imported users."
461
- msgstr ""
462
- "به خاطر داشته باشید که کلمه عبور و نقش کاربران وارد شده را به روز کنید."
463
-
464
- #: classes/models/class-import.php:286
465
- msgid "Fetching attachments is not enabled"
466
- msgstr "پیوست های دریافتی فعال نیستند"
467
-
468
- #: classes/models/class-import.php:299
469
- msgid "Invalid file type"
470
- msgstr "نوع فایل نامعتبر است"
471
-
472
- #: classes/models/class-import.php:379
473
- msgid "Remote server did not respond"
474
- msgstr "سرور از راه دور جواب نمی دهد"
475
-
476
- #: classes/models/class-import.php:385
477
- #, php-format
478
- msgid "Remote server returned error response %1$d %2$s"
479
- msgstr "سرور راه دور پاسخ خطا %1$d %2$s را دریافت کرد"
480
-
481
- #: classes/models/class-import.php:394
482
- msgid "Remote file is incorrect size"
483
- msgstr "سایز فایل ارسالی سرور رته دور نادرست است"
484
-
485
- #: classes/models/class-import.php:399
486
- msgid "Zero size file downloaded"
487
- msgstr "سایز فایل دانلود شده صفر می باشد"
488
-
489
- #: classes/models/class-import.php:405
490
- #, php-format
491
- msgid "Remote file is too large, limit is %s"
492
- msgstr "سایز فایل از راه دور بسیار بزرگ است، سایز به %s محدود شده"
493
-
494
- #: classes/models/class-import.php:422 classes/models/class-import.php:426
495
- #: classes/models/class-import.php:436
496
- msgid "Sorry, there has been an error."
497
- msgstr "با عرض پوزش، یک خطا وجود دارد."
498
-
499
- #: classes/models/class-import.php:427
500
- #, php-format
501
- msgid ""
502
- "The export file could not be found at <code>%s</code>. It is likely that "
503
- "this was caused by a permissions problem."
504
- msgstr ""
505
- "فایل درون ریزی در <code>%s</code> یافت نمی شود. احتمالا این مسئله توسط یک "
506
- "مشکل مجوز ایجاد شده است."
507
-
508
- #: classes/models/class-import.php:444
509
- #, php-format
510
- msgid ""
511
- "This WXR file (version %s) may not be supported by this version of the "
512
- "importer. Please consider updating."
513
- msgstr ""
514
- "این فایل WXR (نسخه %s) ممکن است توسط این نسخه از وارد کننده پشتیبانی نشود. "
515
- "لطفا به روزرسانی کنید."
516
-
517
- #: classes/models/class-import.php:501
518
- #, php-format
519
- msgid ""
520
- "Failed to import author %s. Their posts will be attributed to the current "
521
- "user."
522
- msgstr ""
523
- "وارد کردن نویسنده %s امکان پذیر نبود. پست های آن به کاربر فعلی نسبت داده می "
524
- "شود."
525
-
526
- #: classes/models/class-import.php:558
527
- #, php-format
528
- msgid ""
529
- "Failed to create new user for %s. Their posts will be attributed to the "
530
- "current user."
531
- msgstr ""
532
- "امکان ایجاد کاربر جدید برای %s نبود. پست های آن به کاربر فعلی نسبت داده می "
533
- "شود."
534
-
535
- #: classes/models/class-import.php:609 classes/models/class-import.php:766
536
- #, php-format
537
- msgid "Failed to import %s %s"
538
- msgstr "درون ریزی نا موفق بود %s %s"
539
-
540
- #: classes/models/class-import.php:656
541
- #, php-format
542
- msgid "Failed to import &#8220;%s&#8221;: Invalid post type %s"
543
- msgstr "وارد کردن &#8220;%s&#8221;: ناموفق بود. نوع پست %s نامعتبر است"
544
-
545
- #: classes/models/class-import.php:673
546
- #, php-format
547
- msgid "%s &#8220;%s&#8221; already exists."
548
- msgstr "%s &#8220;%s&#8221; درحال حاضر وجود دارد."
549
-
550
- #: classes/models/class-import.php:732
551
- #, php-format
552
- msgid "Failed to import %s &#8220;%s&#8221;"
553
- msgstr "%s &#8220;%s&#8221; وارد کردن نشد"
554
-
555
- #: classes/modules/class-post.php:42
556
- msgid "Column Type"
557
- msgstr "نوع ستون"
558
-
559
- #: classes/widgets/class-mp-timetable-widget.php:22
560
- msgid "Display upcoming events."
561
- msgstr "نمایش رویدادهای آینده"
562
-
563
- #: classes/widgets/class-mp-timetable-widget.php:24
564
- msgid "Timetable Events"
565
- msgstr "جدول زمانی رویدادها"
566
-
567
- #: templates-functions/actions-mp-event-functions.php:27
568
- #: templates/theme/event-timeslots.php:7
569
- #, php-format
570
- msgid "Event Timeslots (%s)"
571
- msgstr "فاصله زمانی رویداد (%s)"
572
-
573
- #: templates/column/metabox-column-options.php:9
574
- msgid "Simple Column"
575
- msgstr "ستون ساده"
576
-
577
- #: templates/column/metabox-column-options.php:15
578
- msgid "Day"
579
- msgstr "روز"
580
-
581
- #: templates/column/metabox-column-options.php:19
582
- msgid "Sunday"
583
- msgstr "یک شنبه"
584
-
585
- #: templates/column/metabox-column-options.php:20
586
- msgid "Monday"
587
- msgstr "دوشنبه"
588
-
589
- #: templates/column/metabox-column-options.php:21
590
- msgid "Tuesday"
591
- msgstr "سه شنبه"
592
-
593
- #: templates/column/metabox-column-options.php:22
594
- msgid "Wednesday"
595
- msgstr "چهارشنبه"
596
-
597
- #: templates/column/metabox-column-options.php:23
598
- msgid "Thursday"
599
- msgstr "پنج شنبه"
600
-
601
- #: templates/column/metabox-column-options.php:24
602
- msgid "Friday"
603
- msgstr "جمعه"
604
-
605
- #: templates/column/metabox-column-options.php:25
606
- msgid "Saturday"
607
- msgstr "شنبه"
608
-
609
- #: templates/column/metabox-column-options.php:32
610
- msgid "Date"
611
- msgstr "تاریخ"
612
-
613
- #: templates/events/event-data.php:5
614
- msgid "Start"
615
- msgstr "شروع"
616
-
617
- #: templates/events/event-data.php:6
618
- msgid "End"
619
- msgstr "پایان"
620
-
621
- #: templates/events/event-data.php:8
622
- msgid "Head"
623
- msgstr "مسئول"
624
-
625
- #: templates/events/event-data.php:9
626
- msgid "Actions"
627
- msgstr "اقدامات"
628
-
629
- #: templates/events/event-data.php:32
630
- msgid "Edit event in the form below"
631
- msgstr "رویداد را در فرم زیر ویرایش کنید"
632
-
633
- #: templates/events/event-data.php:33
634
- msgid "Delete"
635
- msgstr "حذف"
636
-
637
- #: templates/events/metabox-event-data.php:10
638
- msgid "Column:"
639
- msgstr "ستون:"
640
-
641
- #: templates/events/metabox-event-data.php:18
642
- #, php-format
643
- msgid "Select column or <a target=\"_blank\" href=\"%s\">Add New</a>."
644
- msgstr "انتخاب یک ستون<a target=\"_blank\" href=\"%s\">افزودن ستون جدید</a>."
645
-
646
- #: templates/events/metabox-event-data.php:20
647
- #, php-format
648
- msgid "No columns found. <a href=\"%s\">Create at least one column first.</a>"
649
- msgstr "ستون یافت نشد. <a href=\"%s\">ابتدا حداقل یک ستون ایجاد کنید.</a>"
650
-
651
- #: templates/events/metabox-event-data.php:26
652
- msgid "Start Time:"
653
- msgstr "زمان شروع:"
654
-
655
- #: templates/events/metabox-event-data.php:29
656
- #: templates/events/metabox-event-data.php:36
657
- msgid "hh:mm"
658
- msgstr "hh:mm"
659
-
660
- #: templates/events/metabox-event-data.php:33
661
- msgid "End Time:"
662
- msgstr "زمان اتمام:"
663
-
664
- #: templates/events/metabox-event-data.php:40
665
- msgid "Description:"
666
- msgstr "توضیحات:"
667
-
668
- #: templates/events/metabox-event-data.php:44
669
- msgid "Event Head:"
670
- msgstr "مسئول رویداد:"
671
-
672
- #: templates/events/metabox-event-data.php:52
673
- msgid "none"
674
- msgstr "هیچکدام (خالی)"
675
-
676
- #: templates/events/metabox-event-data.php:75
677
- msgid "Add New"
678
- msgstr "مورد جدیدی اضافه کنید"
679
-
680
- #: templates/events/metabox-event-options.php:4
681
- msgid "Event Subtitle:"
682
- msgstr "عنوان فرعی رویداد:"
683
-
684
- #: templates/events/metabox-event-options.php:8
685
- msgid "Background Color:"
686
- msgstr "رنگ پس زمینه:"
687
-
688
- #: templates/events/metabox-event-options.php:15
689
- msgid "Background Hover Color:"
690
- msgstr "رنگ دور پس زمینه:"
691
-
692
- #: templates/events/metabox-event-options.php:22
693
- msgid "Text Color:"
694
- msgstr "رنگ متن:"
695
-
696
- #: templates/events/metabox-event-options.php:29
697
- msgid "Text Hover Color:"
698
- msgstr "رنگ سایه متن:"
699
-
700
- #: templates/events/metabox-event-options.php:36
701
- msgid "Custom Event URL:"
702
- msgstr "سفارشی کردن URL رویداد:"
703
-
704
- #: templates/events/metabox-event-options.php:42
705
- msgid "Disable link to this event:"
706
- msgstr "غیر فعال کردن لینک به این رویداد:"
707
-
708
- #: templates/popup/index.php:5
709
- msgid "<b>Columns</b> (required)"
710
- msgstr "<b>ستون</b> (ضروری)"
711
-
712
- #: templates/popup/index.php:12 templates/popup/index.php:23
713
- #: templates/popup/index.php:34
714
- msgid "In order to display multiple points hold ctrl/cmd button."
715
- msgstr "برای نمایش چندین نقطه دکمه ctrl / cmd را نگه دارید."
716
-
717
- #: templates/popup/index.php:16
718
- msgid "Specific <b>events</b>"
719
- msgstr "<b>رویدادهای</b> ویژه"
720
-
721
- #: templates/popup/index.php:27
722
- msgid "Event <b>categories</b>"
723
- msgstr "<b>دسته های</b> رویداد"
724
-
725
- #: templates/popup/index.php:38
726
- msgid "Fields to display:"
727
- msgstr "زمینه نمایش:"
728
-
729
- #: templates/popup/index.php:44
730
- msgid "Event Head"
731
- msgstr "مسئول رویداد"
732
-
733
- #: templates/popup/index.php:45
734
- msgid "Check the event parameter(s) to be displayed in the timetable."
735
- msgstr "پارامترهای رویداد را در جدول زمانبندی نمایش دهید."
736
-
737
- #: templates/popup/index.php:49
738
- msgid "Block height in pixels"
739
- msgstr "ارتفاع بلوک به صورت پیکسل"
740
-
741
- #: templates/popup/index.php:52
742
- msgid "Set height of the block"
743
- msgstr "ارتفاع بلوک را تنظیم کنید"
744
-
745
- #: templates/popup/index.php:56
746
- msgid "Base font size"
747
- msgstr "اندازه فونت پایه"
748
-
749
- #: templates/popup/index.php:59
750
- msgid "Base font size for the table. Example 12px, 2em, 80%."
751
- msgstr "اندازه فونت پایه برای جدول. مثال 12px، 2em، 80٪."
752
-
753
- #: templates/popup/index.php:63
754
- msgid "Time frame for event"
755
- msgstr "نحوه نمایش زمان برای رویداد"
756
-
757
- #: templates/popup/index.php:73
758
- msgid "Filter events style"
759
- msgstr "سبک فیلتر رویدادها"
760
-
761
- #: templates/popup/index.php:76
762
- msgid "Dropdown"
763
- msgstr "کشویی"
764
-
765
- #: templates/popup/index.php:78
766
- msgid "None"
767
- msgstr "هیچکدام"
768
-
769
- #: templates/popup/index.php:83
770
- msgid "Filter title to display all events"
771
- msgstr "عنوان فیلتر برای نمایش همه رویدادها"
772
-
773
- #: templates/popup/index.php:89
774
- msgid "Hide 'All Events' option"
775
- msgstr "پنهان کردن گزینه \"همه رویدادها\""
776
-
777
- #: templates/popup/index.php:99
778
- msgid "Hide column with hours"
779
- msgstr "پنهان کردن ستون با ساعت"
780
-
781
- #: templates/popup/index.php:108
782
- msgid "Do not display empty rows"
783
- msgstr "ردیف های خالی را نمایش ندهید"
784
-
785
- #: templates/popup/index.php:117
786
- msgid "Merge cells with common events"
787
- msgstr "ادغام سلول ها با رویدادهای مشترک"
788
-
789
- #: templates/popup/index.php:126 templates/widgets/gallery-list.php:56
790
- msgid "Disable event link"
791
- msgstr "پیوند رویداد را غیرفعال کنید"
792
-
793
- #: templates/popup/index.php:135
794
- msgid "Horizontal align"
795
- msgstr "تراز چیدمان افقی"
796
-
797
- #: templates/popup/index.php:144
798
- msgid "Vertical align"
799
- msgstr "تراز چیدمان عمودی"
800
-
801
- #: templates/popup/index.php:146
802
- msgid "default"
803
- msgstr "پیشفرض"
804
-
805
- #: templates/popup/index.php:147
806
- msgid "top"
807
- msgstr "بالا"
808
-
809
- #: templates/popup/index.php:148
810
- msgid "middle"
811
- msgstr "وسط"
812
-
813
- #: templates/popup/index.php:149
814
- msgid "bottom"
815
- msgstr "پایین"
816
-
817
- #: templates/popup/index.php:154
818
- msgid "Unique ID"
819
- msgstr "شناسه منحصر به فرد"
820
-
821
- #: templates/popup/index.php:157
822
- msgid ""
823
- "If you use more than one table on a page specify the unique ID for a "
824
- "timetable. It is usually all lowercase and contains only letters, numbers, "
825
- "and hyphens."
826
- msgstr ""
827
- "اگر بیش از یک جدول در یک صفحه استفاده کنید، شناسه منحصر به فرد برای یک جدول "
828
- "زمانی را مشخص کنید. شناسه منحصر به فرد به صورت حروف کوچک است و فقط شامل "
829
- "حروف، اعداد و خطوط است."
830
-
831
- #: templates/popup/index.php:161
832
- msgid "CSS class"
833
- msgstr "کلاس CSS"
834
-
835
- #: templates/popup/index.php:167
836
- msgid "Mobile behavior"
837
- msgstr "نحوه نمایش در موبایل"
838
-
839
- #: templates/popup/index.php:170
840
- msgid "List"
841
- msgstr "لیست"
842
-
843
- #: templates/popup/index.php:171
844
- msgid "Table"
845
- msgstr "جدول"
846
-
847
- #: templates/popup/index.php:173
848
- msgid ""
849
- "Tick \"List\" to display events in a list view on mobile devices. Tick "
850
- "\"Table\" to display events in a table."
851
- msgstr ""
852
- "با کلیک بر روی \"لیست\" رویدادها به صورت لیست زیر هم در موبایل به نمایش در "
853
- "می آید. و با انتخاب \"جدول\" رویدادها در یک جدول به نمایش گذاشته می شود.."
854
-
855
- #: templates/popup/index.php:179
856
- msgid "Add Timetable"
857
- msgstr "افزودن جدول زمانی"
858
-
859
- #: templates/settings/general.php:1
860
- msgid "General Settings"
861
- msgstr "تنظیمات عمومی"
862
-
863
- #: templates/settings/general.php:8
864
- msgid "Template Mode"
865
- msgstr "حالت الگو"
866
-
867
- #: templates/settings/general.php:12
868
- msgid "Theme Mode"
869
- msgstr "حالت قالب"
870
-
871
- #: templates/settings/general.php:13
872
- msgid "Developer Mode"
873
- msgstr "حالت توسعه دهنده"
874
-
875
- #: templates/settings/general.php:15
876
- msgid ""
877
- "Choose Theme Mode to display the content with the styles of your theme. "
878
- "Choose Developer Mode to control appearance of the content with custom page "
879
- "templates, actions and filters."
880
- msgstr ""
881
- "اگر میخواهید تا محتوا به سبک قالب فعلی به نمایش گذاشته شود \"حالت قالب\" را "
882
- "انتخاب کنید. اگر حالت توسعه دهنده را انتخاب کنید نحوه نمایش را کاملا می "
883
- "توانید سفارشی کنید."
884
-
885
- #: templates/settings/general.php:15
886
- msgid ""
887
- "This option can't be changed if your theme is initially integrated with the "
888
- "plugin."
889
- msgstr ""
890
- "این گزینه را نمی توان تغییر داد اگر موضوع شما در ابتدا با افزونه ادغام شود."
891
-
892
- #: templates/settings/general.php:20
893
- msgid "Save"
894
- msgstr "ذخیره"
895
-
896
- #: templates/shortcodes/empty-search-events.php:1
897
- #: templates/theme/widget-upcoming-view.php:54
898
- #: templates/widgets/widget-view.php:91
899
- msgid "no events found"
900
- msgstr "رویدادی یافت نشد"
901
-
902
- #: templates/templates-actions/action-sidebar.php:8
903
- #: templates/widgets/gallery-list.php:14
904
- msgid "Today upcoming events"
905
- msgstr "رویدادهای آینده در این روز"
906
-
907
- #: templates/templates-actions/action-sidebar.php:13
908
- #: templates/widgets/gallery-list.php:16
909
- msgid "All upcoming events"
910
- msgstr "همه رویدادهای آینده"
911
-
912
- #: templates/widgets/gallery-list.php:10
913
- msgid "Events to display"
914
- msgstr "رویدادهای برای نمایش"
915
-
916
- #: templates/widgets/gallery-list.php:18
917
- msgid "Ongoing events"
918
- msgstr "رویدادهای پیش رو"
919
-
920
- #: templates/widgets/gallery-list.php:23
921
- msgid "Input number of days"
922
- msgstr "تعداد ورودی ها در روز"
923
-
924
- #: templates/widgets/gallery-list.php:28
925
- msgid "day"
926
- msgstr "روز"
927
-
928
- #: templates/widgets/gallery-list.php:32
929
- msgid "Event categories. Leave blank to display all."
930
- msgstr "دسته های رویداد، برای نمایش همه خالی بگذارید"
931
-
932
- #: templates/widgets/gallery-list.php:49
933
- msgid "Number of events to display"
934
- msgstr "تعداد رویداد قایل نمایش"
935
-
936
- #: templates/widgets/gallery-list.php:67
937
- msgid "Custom link for events"
938
- msgstr "آدرس سفارشی برای رویداد"
939
-
940
- #: templates/widgets/gallery-list.php:75
941
- msgid "Event background color"
942
- msgstr "رنگ پشت زمینه رویداد"
943
-
944
- #: templates/widgets/gallery-list.php:85
945
- msgid "Event background color on hover"
946
- msgstr "رنگ سایه پشت زمینه رویداد"
947
-
948
- #: templates/widgets/gallery-list.php:95
949
- msgid "Event text color"
950
- msgstr "رنگ متن رویداد"
951
-
952
- #: templates/widgets/gallery-list.php:105
953
- msgid "Event text color on hover"
954
- msgstr "رنگ سایه متن رویداد"
955
-
956
- #: templates/widgets/gallery-list.php:115
957
- msgid "Event border color"
958
- msgstr "رنگ کادر دور رویداد"
959
-
960
- #: templates/widgets/gallery-list.php:125
961
- msgid "Event border color on hover"
962
- msgstr "رنگ سایه کادر دور رویداد"
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Timetable and Event Schedule Plugin\n"
4
+ "POT-Creation-Date: 2018-05-18 09:58+0430\n"
5
+ "PO-Revision-Date: \n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: Alireza Rastegar<alireza.mine@gmail.com>\n"
8
+ "Language: fa_IR\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "Plural-Forms: nplurals=1; plural=0;\n"
13
+ "X-Generator: Poedit 2.0.1\n"
14
+ "X-Poedit-SourceCharset: UTF-8\n"
15
+ "X-Poedit-KeywordsList: esc_attr__;esc_html__;esc_attr_e;__;_e;_n;_x\n"
16
+ "X-Poedit-Basepath: ..\n"
17
+ "X-Poedit-SearchPath-0: .\n"
18
+ "X-Poedit-SearchPathExcluded-0: classes/libs\n"
19
+ "X-Poedit-SearchPathExcluded-1: media\n"
20
+
21
+ #: admin/import/export.php:1 admin/import/export.php:5
22
+ msgid "Export"
23
+ msgstr "برونریزی"
24
+
25
+ #: admin/import/greet.php:2
26
+ msgid "Choose a WXR (.xml) file to upload, then click Upload file and import."
27
+ msgstr ""
28
+ "یک فایل WXR (.xml) را برای آپلود انتخاب کنید، سپس روی آپلود فایل و وارد کردن "
29
+ "کلیک کنید."
30
+
31
+ #: admin/import/header.php:2
32
+ msgid "Import / Export Timetable Plugin Data"
33
+ msgstr "درون ریزی / برون ریزی داده افزونه جدول زمانی"
34
+
35
+ #: admin/import/import.php:1
36
+ msgid "Import"
37
+ msgstr "درون ریزی"
38
+
39
+ #: classes/class-core.php:317 classes/class-core.php:329
40
+ #: classes/class-core.php:333 classes/class-shortcode.php:261
41
+ msgid "Event categories"
42
+ msgstr "دسته های رویداد"
43
+
44
+ #: classes/class-core.php:318
45
+ msgid "Event category"
46
+ msgstr "دسته بندی رویداد"
47
+
48
+ #: classes/class-core.php:319 classes/class-core.php:320
49
+ msgid "Add New Event category"
50
+ msgstr "افزودن دسته بندی رویداد"
51
+
52
+ #: classes/class-core.php:321
53
+ msgid "Edit Event category"
54
+ msgstr "ویرایش دسته بندی رویداد"
55
+
56
+ #: classes/class-core.php:322
57
+ msgid "New Event category"
58
+ msgstr "دسته رویداد جدید"
59
+
60
+ #: classes/class-core.php:323
61
+ msgid "All Event categories"
62
+ msgstr "همه دسته های رویداد"
63
+
64
+ #: classes/class-core.php:324
65
+ msgid "View Event category"
66
+ msgstr "نمایش دسته رویداد"
67
+
68
+ #: classes/class-core.php:325
69
+ msgid "Search Event category"
70
+ msgstr "جستجوی دسته رویداد"
71
+
72
+ #: classes/class-core.php:326
73
+ msgid "No Event categories found"
74
+ msgstr "دسته رویدادی پیدا نشد"
75
+
76
+ #: classes/class-core.php:327
77
+ msgid "No Event categories found in Trash"
78
+ msgstr "هیچ دسته رویدادی در «حذف شده ها» یافت نشد"
79
+
80
+ #: classes/class-core.php:356 classes/class-core.php:368
81
+ #: classes/class-core.php:372
82
+ msgid "Event tags"
83
+ msgstr "برچسب های رویداد"
84
+
85
+ #: classes/class-core.php:357
86
+ msgid "Event tag"
87
+ msgstr "برچسب رویداد"
88
+
89
+ #: classes/class-core.php:358 classes/class-core.php:359
90
+ msgid "Add New Event tag"
91
+ msgstr "افزودن برچسب جدید رویداد"
92
+
93
+ #: classes/class-core.php:360
94
+ msgid "Edit Event tag"
95
+ msgstr "ویرایش برچسب رویداد"
96
+
97
+ #: classes/class-core.php:361
98
+ msgid "New Event tag"
99
+ msgstr "برچسب جدید رویداد"
100
+
101
+ #: classes/class-core.php:362
102
+ msgid "All Event tags"
103
+ msgstr "همه برچسب های رویداد"
104
+
105
+ #: classes/class-core.php:363
106
+ msgid "View Event tag"
107
+ msgstr "نمایش برچسب رویداد"
108
+
109
+ #: classes/class-core.php:364
110
+ msgid "Search Event tag"
111
+ msgstr "جستجوی برچسب رویداد"
112
+
113
+ #: classes/class-core.php:365
114
+ msgid "No Event tags found"
115
+ msgstr "برچسب رویداد یافت نشد"
116
+
117
+ #: classes/class-core.php:366
118
+ msgid "No Event tags found in Trash"
119
+ msgstr "هیچ برچسب رویدادی در «حذف شده ها» یافت نشد"
120
+
121
+ #: classes/class-core.php:404 classes/class-core.php:416
122
+ #: classes/class-hooks.php:171 classes/class-shortcode.php:256
123
+ msgid "Events"
124
+ msgstr "رویدادها"
125
+
126
+ #: classes/class-core.php:405
127
+ msgid "Event"
128
+ msgstr "رویداد"
129
+
130
+ #: classes/class-core.php:406 classes/class-core.php:407
131
+ msgid "Add New Event"
132
+ msgstr "افزودن رویداد جدید"
133
+
134
+ #: classes/class-core.php:408
135
+ msgid "Edit Event"
136
+ msgstr "ویرایش رویداد"
137
+
138
+ #: classes/class-core.php:409
139
+ msgid "New Event"
140
+ msgstr "رویداد جدید"
141
+
142
+ #: classes/class-core.php:410 classes/class-shortcode.php:69
143
+ #: classes/class-shortcode.php:277
144
+ #: templates-functions/action-shortcode-functions.php:39
145
+ #: templates-functions/action-shortcode-functions.php:52
146
+ #: templates-functions/action-shortcode-functions.php:53
147
+ msgid "All Events"
148
+ msgstr "همه رویدادها"
149
+
150
+ #: classes/class-core.php:411
151
+ msgid "View Event"
152
+ msgstr "نمایش رویداد"
153
+
154
+ #: classes/class-core.php:412
155
+ msgid "Search Event"
156
+ msgstr "جستجوی رویداد"
157
+
158
+ #: classes/class-core.php:413
159
+ msgid "No Events found"
160
+ msgstr "رویدادی یافت نشد"
161
+
162
+ #: classes/class-core.php:414
163
+ msgid "No Events found in Trash"
164
+ msgstr "هیچ رویدادی در «حذف شده ها» یافت نشد"
165
+
166
+ #: classes/class-core.php:438 classes/class-core.php:450
167
+ #: classes/class-hooks.php:173
168
+ msgid "Columns"
169
+ msgstr "ستون ها"
170
+
171
+ #: classes/class-core.php:439 classes/class-shortcode.php:251
172
+ #: templates/events/event-data.php:4
173
+ msgid "Column"
174
+ msgstr "ستون"
175
+
176
+ #: classes/class-core.php:440 classes/class-core.php:441
177
+ msgid "Add New Column"
178
+ msgstr "افزودن ستون جدید"
179
+
180
+ #: classes/class-core.php:442
181
+ msgid "Edit Column"
182
+ msgstr "ویرایش ستون"
183
+
184
+ #: classes/class-core.php:443
185
+ msgid "New Column"
186
+ msgstr "ستون جدید"
187
+
188
+ #: classes/class-core.php:444
189
+ msgid "All Columns"
190
+ msgstr "همه ستون ها"
191
+
192
+ #: classes/class-core.php:445
193
+ msgid "View Column"
194
+ msgstr "نمایش ستون"
195
+
196
+ #: classes/class-core.php:446
197
+ msgid "Search Column"
198
+ msgstr "جستجوی ستون"
199
+
200
+ #: classes/class-core.php:447
201
+ msgid "No Columns found"
202
+ msgstr "هیچ ستونی یافت نشد"
203
+
204
+ #: classes/class-core.php:448
205
+ msgid "No Columns found in Trash"
206
+ msgstr "هیچ ستونی در «حذف شده ها» یافت نشد"
207
+
208
+ #: classes/class-hooks.php:66
209
+ msgid "Timetable Sidebar"
210
+ msgstr "ابزارک جدول زمانی"
211
+
212
+ #: classes/class-hooks.php:68 classes/class-hooks.php:170
213
+ #: classes/class-shortcode.php:356
214
+ msgid "Timetable"
215
+ msgstr "جدول زمانی"
216
+
217
+ #: classes/class-hooks.php:163
218
+ msgid "Import Timetable events, categories, tags and images."
219
+ msgstr "درون ریزی رویدادهای جدول زمانی، دسته بندی ها، برچسب ها و عکس ها"
220
+
221
+ #: classes/class-hooks.php:172
222
+ msgid "Add Event"
223
+ msgstr "افزودن رویداد"
224
+
225
+ #: classes/class-hooks.php:174
226
+ msgid "Add Column"
227
+ msgstr "افزودن ستون"
228
+
229
+ #: classes/class-hooks.php:175
230
+ msgid "Event Categories"
231
+ msgstr "دسته های رویداد"
232
+
233
+ #: classes/class-hooks.php:176
234
+ msgid "Event Tags"
235
+ msgstr "برچسب های رویداد"
236
+
237
+ #: classes/class-hooks.php:177 classes/modules/class-post.php:41
238
+ msgid "Settings"
239
+ msgstr "تنظیمات"
240
+
241
+ #: classes/class-hooks.php:178
242
+ msgid "Export / Import"
243
+ msgstr "درون ریزی/برون ریزی"
244
+
245
+ #: classes/class-shortcode.php:266
246
+ msgid "Hour measure"
247
+ msgstr "اندازه گیری ساعت"
248
+
249
+ #: classes/class-shortcode.php:267 templates/popup/index.php:66
250
+ msgid "Hour (1h)"
251
+ msgstr "ساعت (1 ساعت)"
252
+
253
+ #: classes/class-shortcode.php:267 templates/popup/index.php:67
254
+ msgid "Half hour (30min)"
255
+ msgstr "نیم ساعت (30 دقیقه)"
256
+
257
+ #: classes/class-shortcode.php:267 templates/popup/index.php:68
258
+ msgid "Quarter hour (15min)"
259
+ msgstr "ربع ساعت (15 دقیقه)"
260
+
261
+ #: classes/class-shortcode.php:271
262
+ msgid "Filter style"
263
+ msgstr "سبک فیلتر"
264
+
265
+ #: classes/class-shortcode.php:272
266
+ msgid "Dropdown list"
267
+ msgstr "لیست بازشو"
268
+
269
+ #: classes/class-shortcode.php:272 templates/popup/index.php:77
270
+ msgid "Tabs"
271
+ msgstr "تب ها"
272
+
273
+ #: classes/class-shortcode.php:276
274
+ msgid "Filter label"
275
+ msgstr "برچسب فیلتر"
276
+
277
+ #: classes/class-shortcode.php:281
278
+ msgid "Hide 'All Events' view"
279
+ msgstr "نمایش ندادن همه رویدادها"
280
+
281
+ #: classes/class-shortcode.php:282 classes/class-shortcode.php:287
282
+ #: classes/class-shortcode.php:292 classes/class-shortcode.php:299
283
+ #: classes/class-shortcode.php:305 classes/class-shortcode.php:311
284
+ #: classes/class-shortcode.php:317 classes/class-shortcode.php:323
285
+ #: classes/class-shortcode.php:328 classes/class-shortcode.php:352
286
+ #: templates/events/metabox-event-options.php:45 templates/popup/index.php:93
287
+ #: templates/popup/index.php:102 templates/popup/index.php:112
288
+ #: templates/popup/index.php:120 templates/popup/index.php:129
289
+ #: templates/widgets/gallery-list.php:60
290
+ msgid "No"
291
+ msgstr "خیر"
292
+
293
+ #: classes/class-shortcode.php:282 classes/class-shortcode.php:287
294
+ #: classes/class-shortcode.php:292 classes/class-shortcode.php:299
295
+ #: classes/class-shortcode.php:305 classes/class-shortcode.php:311
296
+ #: classes/class-shortcode.php:317 classes/class-shortcode.php:323
297
+ #: classes/class-shortcode.php:328 classes/class-shortcode.php:352
298
+ #: templates/events/metabox-event-options.php:46 templates/popup/index.php:94
299
+ #: templates/popup/index.php:103 templates/popup/index.php:111
300
+ #: templates/popup/index.php:121 templates/popup/index.php:130
301
+ #: templates/widgets/gallery-list.php:62
302
+ msgid "Yes"
303
+ msgstr "بله"
304
+
305
+ #: classes/class-shortcode.php:286
306
+ msgid "Hide first (hours) column"
307
+ msgstr "پنهان کردن ستون اول (ساعت)"
308
+
309
+ #: classes/class-shortcode.php:291
310
+ msgid "Hide empty rows"
311
+ msgstr "پنهان کردن سطرهای خالی"
312
+
313
+ #: classes/class-shortcode.php:297 templates/popup/index.php:40
314
+ #: templates/widgets/gallery-list.php:3
315
+ msgid "Title"
316
+ msgstr "عنوان"
317
+
318
+ #: classes/class-shortcode.php:303 templates/popup/index.php:41
319
+ msgid "Time"
320
+ msgstr "زمان"
321
+
322
+ #: classes/class-shortcode.php:309 templates/popup/index.php:42
323
+ msgid "Subtitle"
324
+ msgstr "عنوان فرعی"
325
+
326
+ #: classes/class-shortcode.php:315 templates/events/event-data.php:7
327
+ #: templates/popup/index.php:43
328
+ msgid "Description"
329
+ msgstr "توضیحات"
330
+
331
+ #: classes/class-shortcode.php:321
332
+ msgid "User"
333
+ msgstr "کاربر"
334
+
335
+ #: classes/class-shortcode.php:327
336
+ msgid "Disable event URL"
337
+ msgstr "URL رویداد را غیرفعال کنید"
338
+
339
+ #: classes/class-shortcode.php:332
340
+ msgid "Text align"
341
+ msgstr "چیدمان متن"
342
+
343
+ #: classes/class-shortcode.php:333 templates/popup/index.php:137
344
+ msgid "center"
345
+ msgstr "وسط"
346
+
347
+ #: classes/class-shortcode.php:333 templates/popup/index.php:138
348
+ msgid "left"
349
+ msgstr "چپ"
350
+
351
+ #: classes/class-shortcode.php:333 templates/popup/index.php:139
352
+ msgid "right"
353
+ msgstr "راست"
354
+
355
+ #: classes/class-shortcode.php:337
356
+ msgid "Id"
357
+ msgstr "ID"
358
+
359
+ #: classes/class-shortcode.php:341
360
+ msgid "Row height (in px)"
361
+ msgstr "ارتفاع ردیف (در پیکسل)"
362
+
363
+ #: classes/class-shortcode.php:346
364
+ msgid "Base Font Size"
365
+ msgstr "اندازه فونت پایه"
366
+
367
+ #: classes/class-shortcode.php:351
368
+ msgid "Responsive"
369
+ msgstr "واکنش گرایی"
370
+
371
+ #: classes/controllers/class-controller-settings.php:53
372
+ msgid "Settings saved."
373
+ msgstr "تنظیمات ذخیره شد."
374
+
375
+ #: classes/models/class-column.php:42 classes/modules/class-post.php:40
376
+ msgid "Timeslots"
377
+ msgstr "فاصله زمانی"
378
+
379
+ #: classes/models/class-events.php:167
380
+ msgid "Tags"
381
+ msgstr "تگ ها"
382
+
383
+ #: classes/models/class-events.php:168
384
+ msgid "Categories"
385
+ msgstr "دسته ها"
386
+
387
+ #: classes/models/class-import.php:125
388
+ msgid "Assign Authors"
389
+ msgstr "اختصاص دادن نویسندگان"
390
+
391
+ #: classes/models/class-import.php:126
392
+ msgid ""
393
+ "To make it easier for you to edit and save the imported content, you may "
394
+ "want to reassign the author of the imported item to an existing user of this "
395
+ "site. For example, you may want to import all the entries as <code>admin</"
396
+ "code>s entries."
397
+ msgstr ""
398
+ "برای اینکه بتوانید محتوای وارد شده را ویرایش و ذخیره کنید، ممکن است بخواهید "
399
+ "نویسنده اثر وارد شده را به یک کاربر فعلی این سایت مجددا اختصاص دهید.به عنوان "
400
+ "مثال، شما ممکن است بخواهید تمام ورودی ها را به عنوان ورودی <code> مدیر </"
401
+ "code> وارد کنید."
402
+
403
+ #: classes/models/class-import.php:128
404
+ #, php-format
405
+ msgid ""
406
+ "If a new user is created by WordPress, a new password will be randomly "
407
+ "generated and the new user&#8217;s role will be set as %s. Manually changing "
408
+ "the new user&#8217;s details will be necessary."
409
+ msgstr ""
410
+ "اگر یک کاربر جدید توسط وردپرس ایجاد شده باشد، یک رمز عبور جدید به صورت "
411
+ "تصادفی ایجاد خواهد شد و نقش کاربر جدید user&#8217;s به عنوان %s تنظیم خواهد "
412
+ "شد. تغییر دستی اطلاعات جدید کاربر user&#8217;s ضروری است."
413
+
414
+ #: classes/models/class-import.php:138
415
+ msgid "Import Attachments"
416
+ msgstr "درون ریزی پیوست ها"
417
+
418
+ #: classes/models/class-import.php:141
419
+ msgid "Download and import file attachments"
420
+ msgstr "دریافت و درون ریزی فایل های پیوست"
421
+
422
+ #: classes/models/class-import.php:145
423
+ msgid "Submit"
424
+ msgstr "ارسال"
425
+
426
+ #: classes/models/class-import.php:158
427
+ msgid "Import author:"
428
+ msgstr "درون ریزی نویسنده:"
429
+
430
+ #: classes/models/class-import.php:169
431
+ msgid "or create new user with login name:"
432
+ msgstr "یا ایجاد کاربر جدید با نام کاربری:"
433
+
434
+ #: classes/models/class-import.php:172
435
+ msgid "as a new user:"
436
+ msgstr "به عنوان یک کاربر جدید:"
437
+
438
+ #: classes/models/class-import.php:180
439
+ msgid "assign posts to an existing user:"
440
+ msgstr "اختصاص دادن پست به یک کاربر موجود:"
441
+
442
+ #: classes/models/class-import.php:182
443
+ msgid "or assign posts to an existing user:"
444
+ msgstr "یا اختصاص دادن پست به یک کاربر موجود:"
445
+
446
+ #: classes/models/class-import.php:183
447
+ #: templates/column/metabox-column-options.php:18
448
+ msgid "- Select -"
449
+ msgstr "- انتخاب -"
450
+
451
+ #: classes/models/class-import.php:269
452
+ msgid "All done."
453
+ msgstr "همه انجام شد."
454
+
455
+ #: classes/models/class-import.php:269
456
+ msgid "Have fun!"
457
+ msgstr "خوش بگذره!"
458
+
459
+ #: classes/models/class-import.php:270
460
+ msgid "Remember to update the passwords and roles of imported users."
461
+ msgstr ""
462
+ "به خاطر داشته باشید که کلمه عبور و نقش کاربران وارد شده را به روز کنید."
463
+
464
+ #: classes/models/class-import.php:286
465
+ msgid "Fetching attachments is not enabled"
466
+ msgstr "پیوست های دریافتی فعال نیستند"
467
+
468
+ #: classes/models/class-import.php:299
469
+ msgid "Invalid file type"
470
+ msgstr "نوع فایل نامعتبر است"
471
+
472
+ #: classes/models/class-import.php:379
473
+ msgid "Remote server did not respond"
474
+ msgstr "سرور از راه دور جواب نمی دهد"
475
+
476
+ #: classes/models/class-import.php:385
477
+ #, php-format
478
+ msgid "Remote server returned error response %1$d %2$s"
479
+ msgstr "سرور راه دور پاسخ خطا %1$d %2$s را دریافت کرد"
480
+
481
+ #: classes/models/class-import.php:394
482
+ msgid "Remote file is incorrect size"
483
+ msgstr "سایز فایل ارسالی سرور رته دور نادرست است"
484
+
485
+ #: classes/models/class-import.php:399
486
+ msgid "Zero size file downloaded"
487
+ msgstr "سایز فایل دانلود شده صفر می باشد"
488
+
489
+ #: classes/models/class-import.php:405
490
+ #, php-format
491
+ msgid "Remote file is too large, limit is %s"
492
+ msgstr "سایز فایل از راه دور بسیار بزرگ است، سایز به %s محدود شده"
493
+
494
+ #: classes/models/class-import.php:422 classes/models/class-import.php:426
495
+ #: classes/models/class-import.php:436
496
+ msgid "Sorry, there has been an error."
497
+ msgstr "با عرض پوزش، یک خطا وجود دارد."
498
+
499
+ #: classes/models/class-import.php:427
500
+ #, php-format
501
+ msgid ""
502
+ "The export file could not be found at <code>%s</code>. It is likely that "
503
+ "this was caused by a permissions problem."
504
+ msgstr ""
505
+ "فایل درون ریزی در <code>%s</code> یافت نمی شود. احتمالا این مسئله توسط یک "
506
+ "مشکل مجوز ایجاد شده است."
507
+
508
+ #: classes/models/class-import.php:444
509
+ #, php-format
510
+ msgid ""
511
+ "This WXR file (version %s) may not be supported by this version of the "
512
+ "importer. Please consider updating."
513
+ msgstr ""
514
+ "این فایل WXR (نسخه %s) ممکن است توسط این نسخه از وارد کننده پشتیبانی نشود. "
515
+ "لطفا به روزرسانی کنید."
516
+
517
+ #: classes/models/class-import.php:501
518
+ #, php-format
519
+ msgid ""
520
+ "Failed to import author %s. Their posts will be attributed to the current "
521
+ "user."
522
+ msgstr ""
523
+ "وارد کردن نویسنده %s امکان پذیر نبود. پست های آن به کاربر فعلی نسبت داده می "
524
+ "شود."
525
+
526
+ #: classes/models/class-import.php:558
527
+ #, php-format
528
+ msgid ""
529
+ "Failed to create new user for %s. Their posts will be attributed to the "
530
+ "current user."
531
+ msgstr ""
532
+ "امکان ایجاد کاربر جدید برای %s نبود. پست های آن به کاربر فعلی نسبت داده می "
533
+ "شود."
534
+
535
+ #: classes/models/class-import.php:609 classes/models/class-import.php:766
536
+ #, php-format
537
+ msgid "Failed to import %s %s"
538
+ msgstr "درون ریزی نا موفق بود %s %s"
539
+
540
+ #: classes/models/class-import.php:656
541
+ #, php-format
542
+ msgid "Failed to import &#8220;%s&#8221;: Invalid post type %s"
543
+ msgstr "وارد کردن &#8220;%s&#8221;: ناموفق بود. نوع پست %s نامعتبر است"
544
+
545
+ #: classes/models/class-import.php:673
546
+ #, php-format
547
+ msgid "%s &#8220;%s&#8221; already exists."
548
+ msgstr "%s &#8220;%s&#8221; درحال حاضر وجود دارد."
549
+
550
+ #: classes/models/class-import.php:732
551
+ #, php-format
552
+ msgid "Failed to import %s &#8220;%s&#8221;"
553
+ msgstr "%s &#8220;%s&#8221; وارد کردن نشد"
554
+
555
+ #: classes/modules/class-post.php:42
556
+ msgid "Column Type"
557
+ msgstr "نوع ستون"
558
+
559
+ #: classes/widgets/class-mp-timetable-widget.php:22
560
+ msgid "Display upcoming events."
561
+ msgstr "نمایش رویدادهای آینده"
562
+
563
+ #: classes/widgets/class-mp-timetable-widget.php:24
564
+ msgid "Timetable Events"
565
+ msgstr "جدول زمانی رویدادها"
566
+
567
+ #: templates-functions/actions-mp-event-functions.php:27
568
+ #: templates/theme/event-timeslots.php:7
569
+ #, php-format
570
+ msgid "Event Timeslots (%s)"
571
+ msgstr "فاصله زمانی رویداد (%s)"
572
+
573
+ #: templates/column/metabox-column-options.php:9
574
+ msgid "Simple Column"
575
+ msgstr "ستون ساده"
576
+
577
+ #: templates/column/metabox-column-options.php:15
578
+ msgid "Day"
579
+ msgstr "روز"
580
+
581
+ #: templates/column/metabox-column-options.php:19
582
+ msgid "Sunday"
583
+ msgstr "یک شنبه"
584
+
585
+ #: templates/column/metabox-column-options.php:20
586
+ msgid "Monday"
587
+ msgstr "دوشنبه"
588
+
589
+ #: templates/column/metabox-column-options.php:21
590
+ msgid "Tuesday"
591
+ msgstr "سه شنبه"
592
+
593
+ #: templates/column/metabox-column-options.php:22
594
+ msgid "Wednesday"
595
+ msgstr "چهارشنبه"
596
+
597
+ #: templates/column/metabox-column-options.php:23
598
+ msgid "Thursday"
599
+ msgstr "پنج شنبه"
600
+
601
+ #: templates/column/metabox-column-options.php:24
602
+ msgid "Friday"
603
+ msgstr "جمعه"
604
+
605
+ #: templates/column/metabox-column-options.php:25
606
+ msgid "Saturday"
607
+ msgstr "شنبه"
608
+
609
+ #: templates/column/metabox-column-options.php:32
610
+ msgid "Date"
611
+ msgstr "تاریخ"
612
+
613
+ #: templates/events/event-data.php:5
614
+ msgid "Start"
615
+ msgstr "شروع"
616
+
617
+ #: templates/events/event-data.php:6
618
+ msgid "End"
619
+ msgstr "پایان"
620
+
621
+ #: templates/events/event-data.php:8
622
+ msgid "Head"
623
+ msgstr "مسئول"
624
+
625
+ #: templates/events/event-data.php:9
626
+ msgid "Actions"
627
+ msgstr "اقدامات"
628
+
629
+ #: templates/events/event-data.php:32
630
+ msgid "Edit event in the form below"
631
+ msgstr "رویداد را در فرم زیر ویرایش کنید"
632
+
633
+ #: templates/events/event-data.php:33
634
+ msgid "Delete"
635
+ msgstr "حذف"
636
+
637
+ #: templates/events/metabox-event-data.php:10
638
+ msgid "Column:"
639
+ msgstr "ستون:"
640
+
641
+ #: templates/events/metabox-event-data.php:18
642
+ #, php-format
643
+ msgid "Select column or <a target=\"_blank\" href=\"%s\">Add New</a>."
644
+ msgstr "انتخاب یک ستون<a target=\"_blank\" href=\"%s\">افزودن ستون جدید</a>."
645
+
646
+ #: templates/events/metabox-event-data.php:20
647
+ #, php-format
648
+ msgid "No columns found. <a href=\"%s\">Create at least one column first.</a>"
649
+ msgstr "ستون یافت نشد. <a href=\"%s\">ابتدا حداقل یک ستون ایجاد کنید.</a>"
650
+
651
+ #: templates/events/metabox-event-data.php:26
652
+ msgid "Start Time:"
653
+ msgstr "زمان شروع:"
654
+
655
+ #: templates/events/metabox-event-data.php:29
656
+ #: templates/events/metabox-event-data.php:36
657
+ msgid "hh:mm"
658
+ msgstr "hh:mm"
659
+
660
+ #: templates/events/metabox-event-data.php:33
661
+ msgid "End Time:"
662
+ msgstr "زمان اتمام:"
663
+
664
+ #: templates/events/metabox-event-data.php:40
665
+ msgid "Description:"
666
+ msgstr "توضیحات:"
667
+
668
+ #: templates/events/metabox-event-data.php:44
669
+ msgid "Event Head:"
670
+ msgstr "مسئول رویداد:"
671
+
672
+ #: templates/events/metabox-event-data.php:52
673
+ msgid "none"
674
+ msgstr "هیچکدام (خالی)"
675
+
676
+ #: templates/events/metabox-event-data.php:75
677
+ msgid "Add New"
678
+ msgstr "مورد جدیدی اضافه کنید"
679
+
680
+ #: templates/events/metabox-event-options.php:4
681
+ msgid "Event Subtitle:"
682
+ msgstr "عنوان فرعی رویداد:"
683
+
684
+ #: templates/events/metabox-event-options.php:8
685
+ msgid "Background Color:"
686
+ msgstr "رنگ پس زمینه:"
687
+
688
+ #: templates/events/metabox-event-options.php:15
689
+ msgid "Background Hover Color:"
690
+ msgstr "رنگ دور پس زمینه:"
691
+
692
+ #: templates/events/metabox-event-options.php:22
693
+ msgid "Text Color:"
694
+ msgstr "رنگ متن:"
695
+
696
+ #: templates/events/metabox-event-options.php:29
697
+ msgid "Text Hover Color:"
698
+ msgstr "رنگ سایه متن:"
699
+
700
+ #: templates/events/metabox-event-options.php:36
701
+ msgid "Custom Event URL:"
702
+ msgstr "سفارشی کردن URL رویداد:"
703
+
704
+ #: templates/events/metabox-event-options.php:42
705
+ msgid "Disable link to this event:"
706
+ msgstr "غیر فعال کردن لینک به این رویداد:"
707
+
708
+ #: templates/popup/index.php:5
709
+ msgid "<b>Columns</b> (required)"
710
+ msgstr "<b>ستون</b> (ضروری)"
711
+
712
+ #: templates/popup/index.php:12 templates/popup/index.php:23
713
+ #: templates/popup/index.php:34
714
+ msgid "In order to display multiple points hold ctrl/cmd button."
715
+ msgstr "برای نمایش چندین نقطه دکمه ctrl / cmd را نگه دارید."
716
+
717
+ #: templates/popup/index.php:16
718
+ msgid "Specific <b>events</b>"
719
+ msgstr "<b>رویدادهای</b> ویژه"
720
+
721
+ #: templates/popup/index.php:27
722
+ msgid "Event <b>categories</b>"
723
+ msgstr "<b>دسته های</b> رویداد"
724
+
725
+ #: templates/popup/index.php:38
726
+ msgid "Fields to display:"
727
+ msgstr "زمینه نمایش:"
728
+
729
+ #: templates/popup/index.php:44
730
+ msgid "Event Head"
731
+ msgstr "مسئول رویداد"
732
+
733
+ #: templates/popup/index.php:45
734
+ msgid "Check the event parameter(s) to be displayed in the timetable."
735
+ msgstr "پارامترهای رویداد را در جدول زمانبندی نمایش دهید."
736
+
737
+ #: templates/popup/index.php:49
738
+ msgid "Block height in pixels"
739
+ msgstr "ارتفاع بلوک به صورت پیکسل"
740
+
741
+ #: templates/popup/index.php:52
742
+ msgid "Set height of the block"
743
+ msgstr "ارتفاع بلوک را تنظیم کنید"
744
+
745
+ #: templates/popup/index.php:56
746
+ msgid "Base font size"
747
+ msgstr "اندازه فونت پایه"
748
+
749
+ #: templates/popup/index.php:59
750
+ msgid "Base font size for the table. Example 12px, 2em, 80%."
751
+ msgstr "اندازه فونت پایه برای جدول. مثال 12px، 2em، 80٪."
752
+
753
+ #: templates/popup/index.php:63
754
+ msgid "Time frame for event"
755
+ msgstr "نحوه نمایش زمان برای رویداد"
756
+
757
+ #: templates/popup/index.php:73
758
+ msgid "Filter events style"
759
+ msgstr "سبک فیلتر رویدادها"
760
+
761
+ #: templates/popup/index.php:76
762
+ msgid "Dropdown"
763
+ msgstr "کشویی"
764
+
765
+ #: templates/popup/index.php:78
766
+ msgid "None"
767
+ msgstr "هیچکدام"
768
+
769
+ #: templates/popup/index.php:83
770
+ msgid "Filter title to display all events"
771
+ msgstr "عنوان فیلتر برای نمایش همه رویدادها"
772
+
773
+ #: templates/popup/index.php:89
774
+ msgid "Hide 'All Events' option"
775
+ msgstr "پنهان کردن گزینه \"همه رویدادها\""
776
+
777
+ #: templates/popup/index.php:99
778
+ msgid "Hide column with hours"
779
+ msgstr "پنهان کردن ستون با ساعت"
780
+
781
+ #: templates/popup/index.php:108
782
+ msgid "Do not display empty rows"
783
+ msgstr "ردیف های خالی را نمایش ندهید"
784
+
785
+ #: templates/popup/index.php:117
786
+ msgid "Merge cells with common events"
787
+ msgstr "ادغام سلول ها با رویدادهای مشترک"
788
+
789
+ #: templates/popup/index.php:126 templates/widgets/gallery-list.php:56
790
+ msgid "Disable event link"
791
+ msgstr "پیوند رویداد را غیرفعال کنید"
792
+
793
+ #: templates/popup/index.php:135
794
+ msgid "Horizontal align"
795
+ msgstr "تراز چیدمان افقی"
796
+
797
+ #: templates/popup/index.php:144
798
+ msgid "Vertical align"
799
+ msgstr "تراز چیدمان عمودی"
800
+
801
+ #: templates/popup/index.php:146
802
+ msgid "default"
803
+ msgstr "پیشفرض"
804
+
805
+ #: templates/popup/index.php:147
806
+ msgid "top"
807
+ msgstr "بالا"
808
+
809
+ #: templates/popup/index.php:148
810
+ msgid "middle"
811
+ msgstr "وسط"
812
+
813
+ #: templates/popup/index.php:149
814
+ msgid "bottom"
815
+ msgstr "پایین"
816
+
817
+ #: templates/popup/index.php:154
818
+ msgid "Unique ID"
819
+ msgstr "شناسه منحصر به فرد"
820
+
821
+ #: templates/popup/index.php:157
822
+ msgid ""
823
+ "If you use more than one table on a page specify the unique ID for a "
824
+ "timetable. It is usually all lowercase and contains only letters, numbers, "
825
+ "and hyphens."
826
+ msgstr ""
827
+ "اگر بیش از یک جدول در یک صفحه استفاده کنید، شناسه منحصر به فرد برای یک جدول "
828
+ "زمانی را مشخص کنید. شناسه منحصر به فرد به صورت حروف کوچک است و فقط شامل "
829
+ "حروف، اعداد و خطوط است."
830
+
831
+ #: templates/popup/index.php:161
832
+ msgid "CSS class"
833
+ msgstr "کلاس CSS"
834
+
835
+ #: templates/popup/index.php:167
836
+ msgid "Mobile behavior"
837
+ msgstr "نحوه نمایش در موبایل"
838
+
839
+ #: templates/popup/index.php:170
840
+ msgid "List"
841
+ msgstr "لیست"
842
+
843
+ #: templates/popup/index.php:171
844
+ msgid "Table"
845
+ msgstr "جدول"
846
+
847
+ #: templates/popup/index.php:173
848
+ msgid ""
849
+ "Tick \"List\" to display events in a list view on mobile devices. Tick "
850
+ "\"Table\" to display events in a table."
851
+ msgstr ""
852
+ "با کلیک بر روی \"لیست\" رویدادها به صورت لیست زیر هم در موبایل به نمایش در "
853
+ "می آید. و با انتخاب \"جدول\" رویدادها در یک جدول به نمایش گذاشته می شود.."
854
+
855
+ #: templates/popup/index.php:179
856
+ msgid "Add Timetable"
857
+ msgstr "افزودن جدول زمانی"
858
+
859
+ #: templates/settings/general.php:1
860
+ msgid "General Settings"
861
+ msgstr "تنظیمات عمومی"
862
+
863
+ #: templates/settings/general.php:8
864
+ msgid "Template Mode"
865
+ msgstr "حالت الگو"
866
+
867
+ #: templates/settings/general.php:12
868
+ msgid "Theme Mode"
869
+ msgstr "حالت قالب"
870
+
871
+ #: templates/settings/general.php:13
872
+ msgid "Developer Mode"
873
+ msgstr "حالت توسعه دهنده"
874
+
875
+ #: templates/settings/general.php:15
876
+ msgid ""
877
+ "Choose Theme Mode to display the content with the styles of your theme. "
878
+ "Choose Developer Mode to control appearance of the content with custom page "
879
+ "templates, actions and filters."
880
+ msgstr ""
881
+ "اگر میخواهید تا محتوا به سبک قالب فعلی به نمایش گذاشته شود \"حالت قالب\" را "
882
+ "انتخاب کنید. اگر حالت توسعه دهنده را انتخاب کنید نحوه نمایش را کاملا می "
883
+ "توانید سفارشی کنید."
884
+
885
+ #: templates/settings/general.php:15
886
+ msgid ""
887
+ "This option can't be changed if your theme is initially integrated with the "
888
+ "plugin."
889
+ msgstr ""
890
+ "این گزینه را نمی توان تغییر داد اگر موضوع شما در ابتدا با افزونه ادغام شود."
891
+
892
+ #: templates/settings/general.php:20
893
+ msgid "Save"
894
+ msgstr "ذخیره"
895
+
896
+ #: templates/shortcodes/empty-search-events.php:1
897
+ #: templates/theme/widget-upcoming-view.php:54
898
+ #: templates/widgets/widget-view.php:91
899
+ msgid "no events found"
900
+ msgstr "رویدادی یافت نشد"
901
+
902
+ #: templates/templates-actions/action-sidebar.php:8
903
+ #: templates/widgets/gallery-list.php:14
904
+ msgid "Today upcoming events"
905
+ msgstr "رویدادهای آینده در این روز"
906
+
907
+ #: templates/templates-actions/action-sidebar.php:13
908
+ #: templates/widgets/gallery-list.php:16
909
+ msgid "All upcoming events"
910
+ msgstr "همه رویدادهای آینده"
911
+
912
+ #: templates/widgets/gallery-list.php:10
913
+ msgid "Events to display"
914
+ msgstr "رویدادهای برای نمایش"
915
+
916
+ #: templates/widgets/gallery-list.php:18
917
+ msgid "Ongoing events"
918
+ msgstr "رویدادهای پیش رو"
919
+
920
+ #: templates/widgets/gallery-list.php:23
921
+ msgid "Input number of days"
922
+ msgstr "تعداد ورودی ها در روز"
923
+
924
+ #: templates/widgets/gallery-list.php:28
925
+ msgid "day"
926
+ msgstr "روز"
927
+
928
+ #: templates/widgets/gallery-list.php:32
929
+ msgid "Event categories. Leave blank to display all."
930
+ msgstr "دسته های رویداد، برای نمایش همه خالی بگذارید"
931
+
932
+ #: templates/widgets/gallery-list.php:49
933
+ msgid "Number of events to display"
934
+ msgstr "تعداد رویداد قایل نمایش"
935
+
936
+ #: templates/widgets/gallery-list.php:67
937
+ msgid "Custom link for events"
938
+ msgstr "آدرس سفارشی برای رویداد"
939
+
940
+ #: templates/widgets/gallery-list.php:75
941
+ msgid "Event background color"
942
+ msgstr "رنگ پشت زمینه رویداد"
943
+
944
+ #: templates/widgets/gallery-list.php:85
945
+ msgid "Event background color on hover"
946
+ msgstr "رنگ سایه پشت زمینه رویداد"
947
+
948
+ #: templates/widgets/gallery-list.php:95
949
+ msgid "Event text color"
950
+ msgstr "رنگ متن رویداد"
951
+
952
+ #: templates/widgets/gallery-list.php:105
953
+ msgid "Event text color on hover"
954
+ msgstr "رنگ سایه متن رویداد"
955
+
956
+ #: templates/widgets/gallery-list.php:115
957
+ msgid "Event border color"
958
+ msgstr "رنگ کادر دور رویداد"
959
+
960
+ #: templates/widgets/gallery-list.php:125
961
+ msgid "Event border color on hover"
962
+ msgstr "رنگ سایه کادر دور رویداد"
languages/mp-timetable-ru_RU-1350249ca68bb46ac81f10c0007fcc6d.json CHANGED
@@ -1,162 +1,162 @@
1
- {
2
- "translation-revision-date": "2021-02-03 21:20+0200",
3
- "generator": "WP-CLI\/2.4.0",
4
- "source": "media\/js\/blocks\/dist\/index.js",
5
- "domain": "messages",
6
- "locale_data": {
7
- "messages": {
8
- "": {
9
- "domain": "messages",
10
- "lang": "ru",
11
- "plural-forms": "nplurals=3; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : ((n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) ? 1 : 2);"
12
- },
13
- "Event categories": [
14
- "\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439"
15
- ],
16
- "Columns": [
17
- "\u0421\u0442\u043e\u043b\u0431\u0446\u044b"
18
- ],
19
- "Timetable": [
20
- "\u0420\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435"
21
- ],
22
- "Settings": [
23
- "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438"
24
- ],
25
- "Hour (1h)": [
26
- "\u0427\u0430\u0441 (1 \u0447)"
27
- ],
28
- "Half hour (30min)": [
29
- "\u041f\u043e\u043b\u0447\u0430\u0441\u0430 (30 \u043c\u0438\u043d)"
30
- ],
31
- "Quarter hour (15min)": [
32
- "\u0427\u0435\u0442\u0432\u0435\u0440\u0442\u044c \u0447\u0430\u0441\u0430 (15 \u043c\u0438\u043d)"
33
- ],
34
- "Dropdown list": [
35
- "\u0412\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a"
36
- ],
37
- "Tabs": [
38
- "\u0412\u043a\u043b\u0430\u0434\u043a\u0438"
39
- ],
40
- "Order of items in filter": [
41
- "\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u0444\u0438\u043b\u044c\u0442\u0440\u0435"
42
- ],
43
- "Default": [
44
- "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e"
45
- ],
46
- "Menu Order": [
47
- "\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u043c\u0435\u043d\u044e"
48
- ],
49
- "Title": [
50
- "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a"
51
- ],
52
- "No": [
53
- "\u041d\u0435\u0442"
54
- ],
55
- "Yes": [
56
- "\u0414\u0430"
57
- ],
58
- "Time": [
59
- "\u0412\u0440\u0435\u043c\u044f"
60
- ],
61
- "Subtitle": [
62
- "\u041f\u043e\u0434\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a"
63
- ],
64
- "Description": [
65
- "\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435"
66
- ],
67
- "center": [
68
- "\u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443"
69
- ],
70
- "left": [
71
- "\u0441\u043b\u0435\u0432\u0430"
72
- ],
73
- "right": [
74
- "\u0441\u043f\u0440\u0430\u0432\u0430"
75
- ],
76
- "Column width": [
77
- "\u0428\u0438\u0440\u0438\u043d\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u0430"
78
- ],
79
- "Auto": [
80
- "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438"
81
- ],
82
- "Fixed": [
83
- "\u0424\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435"
84
- ],
85
- "Hold the Ctrl or Command key to select\/deselect multiple options.": [
86
- "\u0423\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0443 Ctrl \u0438\u043b\u0438 Command, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c \/ \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432."
87
- ],
88
- "Specific events": [
89
- "\u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f"
90
- ],
91
- "Event Head": [
92
- "\u0420\u0443\u043a\u043e\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f"
93
- ],
94
- "Block height in pixels": [
95
- "\u0412\u044b\u0441\u043e\u0442\u0430 \u0431\u043b\u043e\u043a\u0430 \u0432 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u0445"
96
- ],
97
- "Base font size": [
98
- "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u0430"
99
- ],
100
- "Base font size for the table. Example 12px, 2em, 80%.": [
101
- "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u0430 \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 12px, 2em, 80%."
102
- ],
103
- "Time frame for event": [
104
- "\u041f\u0435\u0440\u0438\u043e\u0434 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0434\u043b\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f"
105
- ],
106
- "Filter events style": [
107
- "\u0421\u0442\u0438\u043b\u044c \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439"
108
- ],
109
- "Filter title to display all events": [
110
- "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439"
111
- ],
112
- "Hide 'All Events' option": [
113
- "\u0421\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u043e\u043f\u0446\u0438\u044e \"\u0412\u0441\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\""
114
- ],
115
- "Hide column with hours": [
116
- "\u041f\u0440\u044f\u0442\u0430\u0442\u044c \u043a\u043e\u043b\u043e\u043d\u043a\u0443 \u0441 \u0447\u0430\u0441\u0430\u043c\u0438"
117
- ],
118
- "Do not display empty rows": [
119
- "\u041d\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438"
120
- ],
121
- "Merge cells with common events": [
122
- "\u041e\u0431\u044c\u0435\u0434\u0435\u043d\u0438\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0438 \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438"
123
- ],
124
- "Disable event link": [
125
- "\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u044f"
126
- ],
127
- "Horizontal align": [
128
- "\u0413\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435"
129
- ],
130
- "Vertical align": [
131
- "\u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435"
132
- ],
133
- "top": [
134
- "\u0441\u0432\u0435\u0440\u0445\u0443"
135
- ],
136
- "middle": [
137
- "\u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435"
138
- ],
139
- "bottom": [
140
- "\u0441\u043d\u0438\u0437\u0443"
141
- ],
142
- "Unique ID": [
143
- "\u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 ID"
144
- ],
145
- "If you use more than one table on a page specify the unique ID for a timetable. It is usually all lowercase and contains only letters, numbers, and hyphens.": [
146
- "\u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u0431\u043e\u043b\u0435\u0435 \u043e\u0434\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044f. \u041e\u043d, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0443\u043a\u0432\u044b \u0432 \u043d\u0438\u0436\u043d\u0435\u043c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0435, \u0446\u0438\u0444\u0440\u044b \u0438 \u0434\u0435\u0444\u0438\u0441."
147
- ],
148
- "CSS class": [
149
- "CSS \u043a\u043b\u0430\u0441\u0441"
150
- ],
151
- "Mobile behavior": [
152
- "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c"
153
- ],
154
- "List": [
155
- "\u0421\u043f\u0438\u0441\u043e\u043a"
156
- ],
157
- "Table": [
158
- "\u0422\u0430\u0431\u043b\u0438\u0446\u0430"
159
- ]
160
- }
161
- }
162
  }
1
+ {
2
+ "translation-revision-date": "2021-02-03 21:20+0200",
3
+ "generator": "WP-CLI\/2.4.0",
4
+ "source": "media\/js\/blocks\/dist\/index.js",
5
+ "domain": "messages",
6
+ "locale_data": {
7
+ "messages": {
8
+ "": {
9
+ "domain": "messages",
10
+ "lang": "ru",
11
+ "plural-forms": "nplurals=3; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : ((n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) ? 1 : 2);"
12
+ },
13
+ "Event categories": [
14
+ "\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439"
15
+ ],
16
+ "Columns": [
17
+ "\u0421\u0442\u043e\u043b\u0431\u0446\u044b"
18
+ ],
19
+ "Timetable": [
20
+ "\u0420\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435"
21
+ ],
22
+ "Settings": [
23
+ "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438"
24
+ ],
25
+ "Hour (1h)": [
26
+ "\u0427\u0430\u0441 (1 \u0447)"
27
+ ],
28
+ "Half hour (30min)": [
29
+ "\u041f\u043e\u043b\u0447\u0430\u0441\u0430 (30 \u043c\u0438\u043d)"
30
+ ],
31
+ "Quarter hour (15min)": [
32
+ "\u0427\u0435\u0442\u0432\u0435\u0440\u0442\u044c \u0447\u0430\u0441\u0430 (15 \u043c\u0438\u043d)"
33
+ ],
34
+ "Dropdown list": [
35
+ "\u0412\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a"
36
+ ],
37
+ "Tabs": [
38
+ "\u0412\u043a\u043b\u0430\u0434\u043a\u0438"
39
+ ],
40
+ "Order of items in filter": [
41
+ "\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u0444\u0438\u043b\u044c\u0442\u0440\u0435"
42
+ ],
43
+ "Default": [
44
+ "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e"
45
+ ],
46
+ "Menu Order": [
47
+ "\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u043c\u0435\u043d\u044e"
48
+ ],
49
+ "Title": [
50
+ "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a"
51
+ ],
52
+ "No": [
53
+ "\u041d\u0435\u0442"
54
+ ],
55
+ "Yes": [
56
+ "\u0414\u0430"
57
+ ],
58
+ "Time": [
59
+ "\u0412\u0440\u0435\u043c\u044f"
60
+ ],
61
+ "Subtitle": [
62
+ "\u041f\u043e\u0434\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a"
63
+ ],
64
+ "Description": [
65
+ "\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435"
66
+ ],
67
+ "center": [
68
+ "\u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443"
69
+ ],
70
+ "left": [
71
+ "\u0441\u043b\u0435\u0432\u0430"
72
+ ],
73
+ "right": [
74
+ "\u0441\u043f\u0440\u0430\u0432\u0430"
75
+ ],
76
+ "Column width": [
77
+ "\u0428\u0438\u0440\u0438\u043d\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u0430"
78
+ ],
79
+ "Auto": [
80
+ "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438"
81
+ ],
82
+ "Fixed": [
83
+ "\u0424\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435"
84
+ ],
85
+ "Hold the Ctrl or Command key to select\/deselect multiple options.": [
86
+ "\u0423\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0443 Ctrl \u0438\u043b\u0438 Command, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c \/ \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432."
87
+ ],
88
+ "Specific events": [
89
+ "\u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f"
90
+ ],
91
+ "Event Head": [
92
+ "\u0420\u0443\u043a\u043e\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f"
93
+ ],
94
+ "Block height in pixels": [
95
+ "\u0412\u044b\u0441\u043e\u0442\u0430 \u0431\u043b\u043e\u043a\u0430 \u0432 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u0445"
96
+ ],
97
+ "Base font size": [
98
+ "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u0430"
99
+ ],
100
+ "Base font size for the table. Example 12px, 2em, 80%.": [
101
+ "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u0430 \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 12px, 2em, 80%."
102
+ ],
103
+ "Time frame for event": [
104
+ "\u041f\u0435\u0440\u0438\u043e\u0434 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0434\u043b\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f"
105
+ ],
106
+ "Filter events style": [
107
+ "\u0421\u0442\u0438\u043b\u044c \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439"
108
+ ],
109
+ "Filter title to display all events": [
110
+ "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439"
111
+ ],
112
+ "Hide 'All Events' option": [
113
+ "\u0421\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u043e\u043f\u0446\u0438\u044e \"\u0412\u0441\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\""
114
+ ],
115
+ "Hide column with hours": [
116
+ "\u041f\u0440\u044f\u0442\u0430\u0442\u044c \u043a\u043e\u043b\u043e\u043d\u043a\u0443 \u0441 \u0447\u0430\u0441\u0430\u043c\u0438"
117
+ ],
118
+ "Do not display empty rows": [
119
+ "\u041d\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438"
120
+ ],
121
+ "Merge cells with common events": [
122
+ "\u041e\u0431\u044c\u0435\u0434\u0435\u043d\u0438\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0438 \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438"
123
+ ],
124
+ "Disable event link": [
125
+ "\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u044f"
126
+ ],
127
+ "Horizontal align": [
128
+ "\u0413\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435"
129
+ ],
130
+ "Vertical align": [
131
+ "\u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435"
132
+ ],
133
+ "top": [
134
+ "\u0441\u0432\u0435\u0440\u0445\u0443"
135
+ ],
136
+ "middle": [
137
+ "\u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435"
138
+ ],
139
+ "bottom": [
140
+ "\u0441\u043d\u0438\u0437\u0443"
141
+ ],
142
+ "Unique ID": [
143
+ "\u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 ID"
144
+ ],
145
+ "If you use more than one table on a page specify the unique ID for a timetable. It is usually all lowercase and contains only letters, numbers, and hyphens.": [
146
+ "\u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u0431\u043e\u043b\u0435\u0435 \u043e\u0434\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044f. \u041e\u043d, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0443\u043a\u0432\u044b \u0432 \u043d\u0438\u0436\u043d\u0435\u043c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0435, \u0446\u0438\u0444\u0440\u044b \u0438 \u0434\u0435\u0444\u0438\u0441."
147
+ ],
148
+ "CSS class": [
149
+ "CSS \u043a\u043b\u0430\u0441\u0441"
150
+ ],
151
+ "Mobile behavior": [
152
+ "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c"
153
+ ],
154
+ "List": [
155
+ "\u0421\u043f\u0438\u0441\u043e\u043a"
156
+ ],
157
+ "Table": [
158
+ "\u0422\u0430\u0431\u043b\u0438\u0446\u0430"
159
+ ]
160
+ }
161
+ }
162
  }
languages/mp-timetable-ru_RU.po CHANGED
@@ -1,1109 +1,1109 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: Plugins - Timetable and Event Schedule by MotoPress - "
4
- "Development (trunk)\n"
5
- "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/mp-timetable\n"
6
- "POT-Creation-Date: 2021-02-03T19:20:41+00:00\n"
7
- "PO-Revision-Date: 2021-02-03 21:20+0200\n"
8
- "Last-Translator: \n"
9
- "Language-Team: \n"
10
- "Language: ru\n"
11
- "MIME-Version: 1.0\n"
12
- "Content-Type: text/plain; charset=UTF-8\n"
13
- "Content-Transfer-Encoding: 8bit\n"
14
- "Plural-Forms: nplurals=3; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : ((n % "
15
- "10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) ? 1 : 2);\n"
16
- "X-Generator: Poedit 2.2.1\n"
17
-
18
- #. Plugin Name of the plugin
19
- msgid "Timetable and Event Schedule"
20
- msgstr "Timetable and Event Schedule"
21
-
22
- #. Plugin URI of the plugin
23
- msgid "https://motopress.com/products/timetable-event-schedule/"
24
- msgstr "https://motopress.com/products/timetable-event-schedule/"
25
-
26
- #. Description of the plugin
27
- msgid ""
28
- "Smart time-management tool with a clean minimalist design for featuring your "
29
- "timetables and upcoming events."
30
- msgstr ""
31
- "Смарт инструмент для тайм-менеджмента с простым и минималистичным дизайном "
32
- "для отображения расписаний и предстоящих событий."
33
-
34
- #. Author of the plugin
35
- msgid "MotoPress"
36
- msgstr "MotoPress"
37
-
38
- #. Author URI of the plugin
39
- msgid "https://motopress.com"
40
- msgstr "https://motopress.com"
41
-
42
- #. translators: 1: Timetable and Event Schedule 2:: five stars rating
43
- #: admin/help/index.php:10 templates/settings/general.php:41
44
- msgid "If you like %1$s please leave us a %2$s rating."
45
- msgstr "Если вам нравится %1$s, поставьте нам %2$s оценку."
46
-
47
- #: admin/import/export.php:1 admin/import/export.php:5
48
- msgid "Export"
49
- msgstr "Экспортировать"
50
-
51
- #: admin/import/greet.php:2
52
- msgid "Choose a WXR (.xml) file to upload, then click Upload file and import."
53
- msgstr "Выберите WXR файл (с расширением XML), и нажмите кноку Загрузить."
54
-
55
- #: admin/import/header.php:2
56
- msgid "Import / Export Timetable Plugin Data"
57
- msgstr "Импорт / Экспорт данных плагина"
58
-
59
- #: admin/import/import.php:4
60
- msgid "Import"
61
- msgstr "Импортировать"
62
-
63
- #: classes/blocks/class-timetable-block.php:92 classes/class-core.php:443
64
- #: classes/class-shortcode.php:70 classes/class-shortcode.php:286
65
- #: templates-functions/action-shortcode-functions.php:57
66
- #: templates-functions/action-shortcode-functions.php:71
67
- #: templates-functions/action-shortcode-functions.php:72
68
- msgid "All Events"
69
- msgstr "Все события"
70
-
71
- #: classes/class-core.php:332 classes/class-core.php:343
72
- #: classes/class-core.php:347 classes/class-shortcode.php:265
73
- #: templates/popup/index.php:27 media/js/blocks/dist/index.min.js:1
74
- msgid "Event categories"
75
- msgstr "Категории событий"
76
-
77
- #: classes/class-core.php:333
78
- msgid "Event category"
79
- msgstr "Категория события"
80
-
81
- #: classes/class-core.php:334 classes/class-core.php:335
82
- msgid "Add New Event category"
83
- msgstr "Добавить новую категорию события"
84
-
85
- #: classes/class-core.php:336
86
- msgid "Edit Event category"
87
- msgstr "Редактировать категорию события"
88
-
89
- #: classes/class-core.php:337
90
- msgid "New Event category"
91
- msgstr "Новая категория события"
92
-
93
- #: classes/class-core.php:338
94
- msgid "All Event categories"
95
- msgstr "Все категории событий"
96
-
97
- #: classes/class-core.php:339
98
- msgid "View Event category"
99
- msgstr "Просмотр категории события"
100
-
101
- #: classes/class-core.php:340
102
- msgid "Search Event category"
103
- msgstr "Поиск категорий события"
104
-
105
- #: classes/class-core.php:341
106
- msgid "No Event categories found"
107
- msgstr "Категории событий не найдены"
108
-
109
- #: classes/class-core.php:342
110
- msgid "No Event categories found in Trash"
111
- msgstr "Категории событий в корзине не найдены"
112
-
113
- #: classes/class-core.php:376 classes/class-core.php:387
114
- #: classes/class-core.php:391
115
- msgid "Event tags"
116
- msgstr "Ярлыки событий"
117
-
118
- #: classes/class-core.php:377
119
- msgid "Event tag"
120
- msgstr "Ярлык события"
121
-
122
- #: classes/class-core.php:378 classes/class-core.php:379
123
- msgid "Add New Event tag"
124
- msgstr "Добавить новый ярлык события"
125
-
126
- #: classes/class-core.php:380
127
- msgid "Edit Event tag"
128
- msgstr "Редактировать ярлык события"
129
-
130
- #: classes/class-core.php:381
131
- msgid "New Event tag"
132
- msgstr "Новый ярлык события"
133
-
134
- #: classes/class-core.php:382
135
- msgid "All Event tags"
136
- msgstr "Все ярлыки событий"
137
-
138
- #: classes/class-core.php:383
139
- msgid "View Event tag"
140
- msgstr "Просмотр ярлыков события"
141
-
142
- #: classes/class-core.php:384
143
- msgid "Search Event tag"
144
- msgstr "Поиск ярлыка события"
145
-
146
- #: classes/class-core.php:385
147
- msgid "No Event tags found"
148
- msgstr "Ярлыки событий не найдены"
149
-
150
- #: classes/class-core.php:386
151
- msgid "No Event tags found in Trash"
152
- msgstr "Ярлыков событий в корзине не найдено"
153
-
154
- #: classes/class-core.php:437 classes/class-core.php:448
155
- #: classes/class-hooks.php:192 classes/class-shortcode.php:260
156
- msgid "Events"
157
- msgstr "События"
158
-
159
- #: classes/class-core.php:438
160
- msgid "Event"
161
- msgstr "Событие"
162
-
163
- #: classes/class-core.php:439 classes/class-core.php:440
164
- msgid "Add New Event"
165
- msgstr "Добавить новое событе"
166
-
167
- #: classes/class-core.php:441
168
- msgid "Edit Event"
169
- msgstr "Редактировать событие"
170
-
171
- #: classes/class-core.php:442
172
- msgid "New Event"
173
- msgstr "Новое событие"
174
-
175
- #: classes/class-core.php:444
176
- msgid "View Event"
177
- msgstr "Просмотреть событие"
178
-
179
- #: classes/class-core.php:445
180
- msgid "Search Event"
181
- msgstr "Поиск событий"
182
-
183
- #: classes/class-core.php:446
184
- msgid "No Events found"
185
- msgstr "События не найдены"
186
-
187
- #: classes/class-core.php:447
188
- msgid "No Events found in Trash"
189
- msgstr "События не найдены в корзине"
190
-
191
- #: classes/class-core.php:476 classes/class-core.php:487
192
- #: classes/class-hooks.php:200 templates/popup/index.php:5
193
- #: media/js/blocks/dist/index.min.js:1
194
- msgid "Columns"
195
- msgstr "Столбцы"
196
-
197
- #: classes/class-core.php:477 classes/class-shortcode.php:255
198
- #: templates/events/event-data.php:4
199
- msgid "Column"
200
- msgstr "Столбец"
201
-
202
- #: classes/class-core.php:478 classes/class-core.php:479
203
- msgid "Add New Column"
204
- msgstr "Добавить новый столбец"
205
-
206
- #: classes/class-core.php:480
207
- msgid "Edit Column"
208
- msgstr "Редактировать столбец"
209
-
210
- #: classes/class-core.php:481
211
- msgid "New Column"
212
- msgstr "Новый столбец"
213
-
214
- #: classes/class-core.php:482
215
- msgid "All Columns"
216
- msgstr "Все столбцы"
217
-
218
- #: classes/class-core.php:483
219
- msgid "View Column"
220
- msgstr "Просмотр столбцов"
221
-
222
- #: classes/class-core.php:484
223
- msgid "Search Column"
224
- msgstr "Поиск столбцов"
225
-
226
- #: classes/class-core.php:485
227
- msgid "No Columns found"
228
- msgstr "Столбцы не найдены"
229
-
230
- #: classes/class-core.php:486
231
- msgid "No Columns found in Trash"
232
- msgstr "Столбцов в корзине не найдено"
233
-
234
- #: classes/class-hooks.php:78
235
- msgid "Timetable Sidebar"
236
- msgstr "Расписание в боковой панели"
237
-
238
- #: classes/class-hooks.php:80 classes/class-hooks.php:188
239
- #: classes/class-shortcode.php:370 media/js/blocks/dist/index.min.js:1
240
- msgid "Timetable"
241
- msgstr "Расписание"
242
-
243
- #: classes/class-hooks.php:179
244
- msgid "Import Timetable events, categories, tags and images."
245
- msgstr "Импортировать события, категории, ярлыки и изображения."
246
-
247
- #: classes/class-hooks.php:196
248
- msgid "Add Event"
249
- msgstr "Добавить событие"
250
-
251
- #: classes/class-hooks.php:204
252
- msgid "Add Column"
253
- msgstr "Добавить столбец"
254
-
255
- #: classes/class-hooks.php:208
256
- msgid "Event Categories"
257
- msgstr "Категории событий"
258
-
259
- #: classes/class-hooks.php:212
260
- msgid "Event Tags"
261
- msgstr "Ярлыки событий"
262
-
263
- #: classes/class-hooks.php:216 classes/modules/class-post.php:41
264
- #: media/js/blocks/dist/index.min.js:1
265
- msgid "Settings"
266
- msgstr "Настройки"
267
-
268
- #: classes/class-hooks.php:220
269
- msgid "Export / Import"
270
- msgstr "Экспорт / Импорт"
271
-
272
- #: classes/class-hooks.php:224
273
- msgid "Help & Shortcode"
274
- msgstr "Помощь и шорткоды"
275
-
276
- #: classes/class-hooks.php:288
277
- msgid "Quick Start Guide"
278
- msgstr "Краткое руководство пользователя"
279
-
280
- #: classes/class-hooks.php:289
281
- msgid "Help"
282
- msgstr "Помощь"
283
-
284
- #: classes/class-hooks.php:290
285
- msgid "Leave a Review"
286
- msgstr "Оставьте отзыв"
287
-
288
- #: classes/class-permalinks.php:26
289
- msgid "Timetable Permalinks"
290
- msgstr "Ссылки расписания"
291
-
292
- #: classes/class-permalinks.php:30
293
- msgid "Column base"
294
- msgstr "Префикс для столбцов"
295
-
296
- #: classes/class-permalinks.php:37
297
- msgid "Event base"
298
- msgstr "Префикс для событий"
299
-
300
- #: classes/class-permalinks.php:44
301
- msgid "Event Category base"
302
- msgstr "Префикс для рубрик событий"
303
-
304
- #: classes/class-permalinks.php:51
305
- msgid "Event Tag base"
306
- msgstr "Префикс для меток событий"
307
-
308
- #: classes/class-shortcode.php:270
309
- msgid "Hour measure"
310
- msgstr "Мера часа"
311
-
312
- #: classes/class-shortcode.php:271 templates/popup/index.php:71
313
- #: media/js/blocks/dist/index.min.js:1
314
- msgid "Hour (1h)"
315
- msgstr "Час (1 ч)"
316
-
317
- #: classes/class-shortcode.php:271 templates/popup/index.php:72
318
- #: media/js/blocks/dist/index.min.js:1
319
- msgid "Half hour (30min)"
320
- msgstr "Полчаса (30 мин)"
321
-
322
- #: classes/class-shortcode.php:271 templates/popup/index.php:73
323
- #: media/js/blocks/dist/index.min.js:1
324
- msgid "Quarter hour (15min)"
325
- msgstr "Четверть часа (15 мин)"
326
-
327
- #: classes/class-shortcode.php:275
328
- msgid "Filter style"
329
- msgstr "Стиль для фильтра"
330
-
331
- #: classes/class-shortcode.php:276 media/js/blocks/dist/index.min.js:1
332
- msgid "Dropdown list"
333
- msgstr "Выпадающий список"
334
-
335
- #: classes/class-shortcode.php:276 templates/popup/index.php:82
336
- #: media/js/blocks/dist/index.min.js:1
337
- msgid "Tabs"
338
- msgstr "Вкладки"
339
-
340
- #: classes/class-shortcode.php:280 templates/popup/index.php:88
341
- #: media/js/blocks/dist/index.min.js:1
342
- msgid "Order of items in filter"
343
- msgstr "Порядок элементов в фильтре"
344
-
345
- #: classes/class-shortcode.php:281 classes/class-shortcode.php:367
346
- #: templates/popup/index.php:91 templates/popup/index.php:172
347
- #: media/js/blocks/dist/index.min.js:1
348
- msgid "Default"
349
- msgstr "По умолчанию"
350
-
351
- #: classes/class-shortcode.php:281 templates/popup/index.php:92
352
- #: media/js/blocks/dist/index.min.js:1
353
- msgid "Menu Order"
354
- msgstr "Порядок меню"
355
-
356
- #: classes/class-shortcode.php:281 classes/class-shortcode.php:306
357
- #: templates/popup/index.php:40 templates/popup/index.php:93
358
- #: templates/widgets/gallery-list.php:3 media/js/blocks/dist/index.min.js:1
359
- msgid "Title"
360
- msgstr "Заголовок"
361
-
362
- #: classes/class-shortcode.php:285
363
- msgid "Filter label"
364
- msgstr "Метка фильтра"
365
-
366
- #: classes/class-shortcode.php:290
367
- msgid "Hide 'All Events' view"
368
- msgstr "Скрыть вид \"Все события\""
369
-
370
- #: classes/class-shortcode.php:291 classes/class-shortcode.php:296
371
- #: classes/class-shortcode.php:301 classes/class-shortcode.php:308
372
- #: classes/class-shortcode.php:314 classes/class-shortcode.php:320
373
- #: classes/class-shortcode.php:326 classes/class-shortcode.php:332
374
- #: classes/class-shortcode.php:337 classes/class-shortcode.php:361
375
- #: templates/events/metabox-event-options.php:45 templates/popup/index.php:108
376
- #: templates/popup/index.php:117 templates/popup/index.php:127
377
- #: templates/popup/index.php:135 templates/popup/index.php:144
378
- #: templates/widgets/gallery-list.php:63 media/js/blocks/dist/index.min.js:1
379
- msgid "No"
380
- msgstr "Нет"
381
-
382
- #: classes/class-shortcode.php:291 classes/class-shortcode.php:296
383
- #: classes/class-shortcode.php:301 classes/class-shortcode.php:308
384
- #: classes/class-shortcode.php:314 classes/class-shortcode.php:320
385
- #: classes/class-shortcode.php:326 classes/class-shortcode.php:332
386
- #: classes/class-shortcode.php:337 classes/class-shortcode.php:361
387
- #: templates/events/metabox-event-options.php:46 templates/popup/index.php:109
388
- #: templates/popup/index.php:118 templates/popup/index.php:126
389
- #: templates/popup/index.php:136 templates/popup/index.php:145
390
- #: templates/widgets/gallery-list.php:65 media/js/blocks/dist/index.min.js:1
391
- msgid "Yes"
392
- msgstr "Да"
393
-
394
- #: classes/class-shortcode.php:295
395
- msgid "Hide first (hours) column"
396
- msgstr "Скрыть первый (с часами) столбец"
397
-
398
- #: classes/class-shortcode.php:300
399
- msgid "Hide empty rows"
400
- msgstr "Скрыть пустые ряды"
401
-
402
- #: classes/class-shortcode.php:312 templates/popup/index.php:41
403
- #: media/js/blocks/dist/index.min.js:1
404
- msgid "Time"
405
- msgstr "Время"
406
-
407
- #: classes/class-shortcode.php:318 templates/popup/index.php:42
408
- #: media/js/blocks/dist/index.min.js:1
409
- msgid "Subtitle"
410
- msgstr "Подзаголовок"
411
-
412
- #: classes/class-shortcode.php:324 templates/events/event-data.php:7
413
- #: templates/popup/index.php:43 media/js/blocks/dist/index.min.js:1
414
- msgid "Description"
415
- msgstr "Описание"
416
-
417
- #: classes/class-shortcode.php:330
418
- msgid "User"
419
- msgstr "Пользователь"
420
-
421
- #: classes/class-shortcode.php:336
422
- msgid "Disable event URL"
423
- msgstr "Отключить URL события"
424
-
425
- #: classes/class-shortcode.php:341
426
- msgid "Text align"
427
- msgstr "Выравнивание текста"
428
-
429
- #: classes/class-shortcode.php:342 templates/popup/index.php:152
430
- #: media/js/blocks/dist/index.min.js:1
431
- msgid "center"
432
- msgstr "по центру"
433
-
434
- #: classes/class-shortcode.php:342 templates/popup/index.php:153
435
- #: media/js/blocks/dist/index.min.js:1
436
- msgid "left"
437
- msgstr "слева"
438
-
439
- #: classes/class-shortcode.php:342 templates/popup/index.php:154
440
- #: media/js/blocks/dist/index.min.js:1
441
- msgid "right"
442
- msgstr "справа"
443
-
444
- #: classes/class-shortcode.php:346
445
- msgid "Id"
446
- msgstr "Id"
447
-
448
- #: classes/class-shortcode.php:350
449
- msgid "Row height (in px)"
450
- msgstr "Высота ряда (в пикселях)"
451
-
452
- #: classes/class-shortcode.php:355
453
- msgid "Base Font Size"
454
- msgstr "Базовый размер шрифта"
455
-
456
- #: classes/class-shortcode.php:360
457
- msgid "Responsive"
458
- msgstr "Адаптивные"
459
-
460
- #: classes/class-shortcode.php:366 templates/popup/index.php:169
461
- #: media/js/blocks/dist/index.min.js:1
462
- msgid "Column width"
463
- msgstr "Ширина столбца"
464
-
465
- #: classes/class-shortcode.php:367 templates/popup/index.php:173
466
- #: media/js/blocks/dist/index.min.js:1
467
- msgid "Auto"
468
- msgstr "Автоматически"
469
-
470
- #: classes/class-shortcode.php:367 templates/popup/index.php:174
471
- #: media/js/blocks/dist/index.min.js:1
472
- msgid "Fixed"
473
- msgstr "Фиксированное"
474
-
475
- #: classes/controllers/class-controller-settings.php:70
476
- msgid "Settings saved."
477
- msgstr "Настройки сохранены."
478
-
479
- #: classes/libs/parsers.php:44 classes/libs/parsers.php:74
480
- #: classes/libs/parsers.php:82
481
- msgid "There was an error when reading this WXR file"
482
- msgstr "Ошибка при чтении файла WXR"
483
-
484
- #: classes/libs/parsers.php:45
485
- msgid ""
486
- "Details are shown above. The importer will now try again with a different "
487
- "parser..."
488
- msgstr ""
489
- "Подробности ниже. Сейчас плагин повторит попытку импортирования с другим "
490
- "парсером..."
491
-
492
- #: classes/libs/parsers.php:86 classes/libs/parsers.php:91
493
- #: classes/libs/parsers.php:304 classes/libs/parsers.php:565
494
- msgid ""
495
- "This does not appear to be a WXR file, missing/invalid WXR version number"
496
- msgstr "Кажется это файл WXR, пропущенный/неверный номер версии WXR"
497
-
498
- #: classes/models/class-column.php:42 classes/modules/class-post.php:40
499
- msgid "Timeslots"
500
- msgstr "Временные интервалы"
501
-
502
- #: classes/models/class-events.php:171
503
- msgid "Tags"
504
- msgstr "Ключевые слова"
505
-
506
- #: classes/models/class-events.php:172
507
- msgid "Categories"
508
- msgstr "Категории"
509
-
510
- #: classes/models/class-events.php:774
511
- msgid "Duplicate"
512
- msgstr "Дублировать"
513
-
514
- #: classes/models/class-events.php:795
515
- msgid "A post type mismatch has been detected."
516
- msgstr "Обнаружено несоответствие типов постов."
517
-
518
- #: classes/models/class-events.php:795
519
- msgid "Sorry, you are not allowed to edit this item."
520
- msgstr "У вас недостаточно прав для редактирования этого элемента."
521
-
522
- #. translators: New post title of the duplicated post
523
- #: classes/models/class-events.php:819
524
- msgid "%s - Copy"
525
- msgstr "%s - Копия"
526
-
527
- #: classes/models/class-import.php:125
528
- msgid "Assign Authors"
529
- msgstr "Привязка авторов"
530
-
531
- #: classes/models/class-import.php:126
532
- msgid ""
533
- "To make it easier for you to edit and save the imported content, you may "
534
- "want to reassign the author of the imported item to an existing user of this "
535
- "site. For example, you may want to import all the entries as <code>admin</"
536
- "code>s entries."
537
- msgstr ""
538
- "Чтобы сделать проще редактирование и сохранение импортированного материала, "
539
- "вы, возможно, захотите перепривязать автора импортированного элемента к "
540
- "существующему пользователю этого сайта. Например, вы захотите импортировать "
541
- "все записи как записи пользователя <code>admin</code>."
542
-
543
- #: classes/models/class-import.php:128
544
- msgid ""
545
- "If a new user is created by WordPress, a new password will be randomly "
546
- "generated and the new user&#8217;s role will be set as %s. Manually changing "
547
- "the new user&#8217;s details will be necessary."
548
- msgstr ""
549
- "Если новый пользователь создан WordPress, новый пароль будет сгенерирован "
550
- "случайным образом, и роль нового пользователя будет %s. Понадобятся "
551
- "изменения деталей профиля нового пользователя вручную."
552
-
553
- #: classes/models/class-import.php:138
554
- msgid "Import Attachments"
555
- msgstr "Импорт вложений"
556
-
557
- #: classes/models/class-import.php:141
558
- msgid "Download and import file attachments"
559
- msgstr "Скачать и импортировать файлы вложений"
560
-
561
- #: classes/models/class-import.php:145
562
- msgid "Submit"
563
- msgstr "Отправить"
564
-
565
- #: classes/models/class-import.php:158
566
- msgid "Import author:"
567
- msgstr "Импорт автора:"
568
-
569
- #: classes/models/class-import.php:169
570
- msgid "or create new user with login name:"
571
- msgstr "или создать нового пользователя с именем:"
572
-
573
- #: classes/models/class-import.php:172
574
- msgid "as a new user:"
575
- msgstr "как новый пользователь:"
576
-
577
- #: classes/models/class-import.php:180
578
- msgid "assign posts to an existing user:"
579
- msgstr "назначить записи существующему пользователю:"
580
-
581
- #: classes/models/class-import.php:182
582
- msgid "or assign posts to an existing user:"
583
- msgstr "или привязать записи к существующему пользователю:"
584
-
585
- #: classes/models/class-import.php:183
586
- #: templates/column/metabox-column-options.php:23
587
- msgid "- Select -"
588
- msgstr "- Выбрать -"
589
-
590
- #: classes/models/class-import.php:269
591
- msgid "All done."
592
- msgstr "Все готово."
593
-
594
- #: classes/models/class-import.php:269
595
- msgid "Have fun!"
596
- msgstr "Наслаждайтесь!"
597
-
598
- #: classes/models/class-import.php:270
599
- msgid "Remember to update the passwords and roles of imported users."
600
- msgstr "Не забудьте обновить пароли и роли импортированных пользователей."
601
-
602
- #: classes/models/class-import.php:286
603
- msgid "Fetching attachments is not enabled"
604
- msgstr "Импортирование вложений отключено"
605
-
606
- #: classes/models/class-import.php:299
607
- msgid "Invalid file type"
608
- msgstr "Неподходящий тип файла"
609
-
610
- #: classes/models/class-import.php:379
611
- msgid "Remote server did not respond"
612
- msgstr "Удалённый сервер не&nbsp;отвечает"
613
-
614
- #: classes/models/class-import.php:385
615
- msgid "Remote server returned error response %1$d %2$s"
616
- msgstr "Удалённый сервер выдал ошибку %1$d %2$s"
617
-
618
- #: classes/models/class-import.php:394
619
- msgid "Remote file is incorrect size"
620
- msgstr "Удалённый файл неподходящего размера"
621
-
622
- #: classes/models/class-import.php:399
623
- msgid "Zero size file downloaded"
624
- msgstr "Скачан пустой файл"
625
-
626
- #: classes/models/class-import.php:405
627
- msgid "Remote file is too large, limit is %s"
628
- msgstr "Удалённый файл слишком велик. Текущее ограничение: %s"
629
-
630
- #: classes/models/class-import.php:422 classes/models/class-import.php:426
631
- #: classes/models/class-import.php:436
632
- msgid "Sorry, there has been an error."
633
- msgstr "К сожалению, возникла ошибка."
634
-
635
- #: classes/models/class-import.php:427
636
- msgid ""
637
- "The export file could not be found at <code>%s</code>. It is likely that "
638
- "this was caused by a permissions problem."
639
- msgstr ""
640
- "Экспортируемый файл не может быть найден в <code>%s</code>. Похоже, это "
641
- "вызвано ошибкой прав доступа."
642
-
643
- #: classes/models/class-import.php:444
644
- msgid ""
645
- "This WXR file (version %s) may not be supported by this version of the "
646
- "importer. Please consider updating."
647
- msgstr ""
648
- "Данный файл WXR (версии %s) может не поддерживаться настоящей версией "
649
- "плагина. Советуем обновить плагин."
650
-
651
- #: classes/models/class-import.php:501
652
- msgid ""
653
- "Failed to import author %s. Their posts will be attributed to the current "
654
- "user."
655
- msgstr ""
656
- "Не удалось импортировать автора \"%s\". Его статьи будут назначены текущему "
657
- "пользователю."
658
-
659
- #: classes/models/class-import.php:558
660
- msgid ""
661
- "Failed to create new user for %s. Their posts will be attributed to the "
662
- "current user."
663
- msgstr ""
664
- "Не удалось создать нового пользователя для %s. Их записи будут отнесены к "
665
- "текущему пользователю."
666
-
667
- #: classes/models/class-import.php:609 classes/models/class-import.php:766
668
- msgid "Failed to import %s %s"
669
- msgstr "Не удалось импортировать %s %s"
670
-
671
- #: classes/models/class-import.php:656
672
- msgid "Failed to import &#8220;%s&#8221;: Invalid post type %s"
673
- msgstr "Не удалось импортировать &#8220;%s&#8221;: Неверный тип записи %s"
674
-
675
- #: classes/models/class-import.php:673
676
- msgid "%s &#8220;%s&#8221; already exists."
677
- msgstr "%s &#8220;%s&#8221; уже существует."
678
-
679
- #: classes/models/class-import.php:732
680
- msgid "Failed to import %s &#8220;%s&#8221;"
681
- msgstr "Не удалось импортировать %s &#8220;%s&#8221;"
682
-
683
- #: classes/modules/class-post.php:42
684
- msgid "Column Type"
685
- msgstr "Тип столбца"
686
-
687
- #: classes/widgets/class-mp-timetable-widget.php:22
688
- msgid "Display upcoming events."
689
- msgstr "Отобразить предстоящие события."
690
-
691
- #: classes/widgets/class-mp-timetable-widget.php:24
692
- msgid "Timetable Events"
693
- msgstr "События в расписании"
694
-
695
- #: templates-functions/actions-mp-event-functions.php:27
696
- #: templates/theme/event-timeslots.php:7
697
- msgid "Event Timeslots (%s)"
698
- msgstr "Временные интервалы событий (%s)"
699
-
700
- #: templates/column/metabox-column-options.php:11
701
- msgid "Simple Column"
702
- msgstr "Простой столбец"
703
-
704
- #: templates/column/metabox-column-options.php:20
705
- msgid "Day of the week"
706
- msgstr "День недели"
707
-
708
- #: templates/column/metabox-column-options.php:24
709
- msgid "Sunday"
710
- msgstr "Воскресенье"
711
-
712
- #: templates/column/metabox-column-options.php:25
713
- msgid "Monday"
714
- msgstr "Понедельник"
715
-
716
- #: templates/column/metabox-column-options.php:26
717
- msgid "Tuesday"
718
- msgstr "Вторник"
719
-
720
- #: templates/column/metabox-column-options.php:27
721
- msgid "Wednesday"
722
- msgstr "Среда"
723
-
724
- #: templates/column/metabox-column-options.php:28
725
- msgid "Thursday"
726
- msgstr "Четверг"
727
-
728
- #: templates/column/metabox-column-options.php:29
729
- msgid "Friday"
730
- msgstr "Пятница"
731
-
732
- #: templates/column/metabox-column-options.php:30
733
- msgid "Saturday"
734
- msgstr "Суббота"
735
-
736
- #: templates/column/metabox-column-options.php:39
737
- msgid "Date"
738
- msgstr "Дата"
739
-
740
- #: templates/events/event-data.php:5
741
- msgid "Start"
742
- msgstr "Начало"
743
-
744
- #: templates/events/event-data.php:6
745
- msgid "End"
746
- msgstr "Окончание"
747
-
748
- #. translators: Head means the leader of the event.
749
- #: templates/events/event-data.php:10
750
- msgid "Head"
751
- msgstr "Руководитель"
752
-
753
- #: templates/events/event-data.php:12
754
- msgid "Actions"
755
- msgstr "Действия"
756
-
757
- #: templates/events/event-data.php:35
758
- msgid "Edit event in the form below"
759
- msgstr "Отредактируйте событие в форме ниже"
760
-
761
- #: templates/events/event-data.php:36
762
- msgid "Delete"
763
- msgstr "Удалить"
764
-
765
- #: templates/events/metabox-event-data.php:10
766
- msgid "Add New / Edit Timeslot"
767
- msgstr "Добавить новый / Редактировать интервал"
768
-
769
- #: templates/events/metabox-event-data.php:13
770
- msgid "Column:"
771
- msgstr "Столбец:"
772
-
773
- #: templates/events/metabox-event-data.php:21
774
- msgid "Select column or <a target=\"_blank\" href=\"%s\">Add New</a>."
775
- msgstr ""
776
- "Выберите столбец или <a target=\"_blank\" href=\"%s\">Добавьте новый</a>."
777
-
778
- #: templates/events/metabox-event-data.php:23
779
- msgid "No columns found. <a href=\"%s\">Create at least one column first.</a>"
780
- msgstr ""
781
- "Столбцов не найдено. <a href=\"%s\">Создайте как минимум один столбец для "
782
- "начала.</a>"
783
-
784
- #: templates/events/metabox-event-data.php:29
785
- msgid "Start Time:"
786
- msgstr "Время начала:"
787
-
788
- #: templates/events/metabox-event-data.php:32
789
- #: templates/events/metabox-event-data.php:39
790
- msgid "hh:mm"
791
- msgstr "чч:мм"
792
-
793
- #: templates/events/metabox-event-data.php:36
794
- msgid "End Time:"
795
- msgstr "Время окончания:"
796
-
797
- #: templates/events/metabox-event-data.php:43
798
- msgid "Description:"
799
- msgstr "Описание:"
800
-
801
- #. translators: Head means the leader of the event.
802
- #: templates/events/metabox-event-data.php:49
803
- msgid "Event Head:"
804
- msgstr "Руководитель события:"
805
-
806
- #: templates/events/metabox-event-data.php:58
807
- msgid "none"
808
- msgstr "нет"
809
-
810
- #. translators: Button to add a new event.
811
- #: templates/events/metabox-event-data.php:83
812
- msgid "Add New"
813
- msgstr "Добавить новый"
814
-
815
- #: templates/events/metabox-event-options.php:4
816
- msgid "Event Subtitle:"
817
- msgstr "Подзаголовок события:"
818
-
819
- #: templates/events/metabox-event-options.php:8
820
- msgid "Background Color:"
821
- msgstr "Цвет фона:"
822
-
823
- #: templates/events/metabox-event-options.php:15
824
- msgid "Background Hover Color:"
825
- msgstr "Цвет фона при наведении:"
826
-
827
- #: templates/events/metabox-event-options.php:22
828
- msgid "Text Color:"
829
- msgstr "Цвет текста:"
830
-
831
- #: templates/events/metabox-event-options.php:29
832
- msgid "Text Hover Color:"
833
- msgstr "Цвет текста при наведении:"
834
-
835
- #: templates/events/metabox-event-options.php:36
836
- msgid "Custom Event URL:"
837
- msgstr "Специальная ссылка на событие:"
838
-
839
- #: templates/events/metabox-event-options.php:42
840
- msgid "Disable link to this event:"
841
- msgstr "Отключить ссылку на событие:"
842
-
843
- #: templates/popup/index.php:12 templates/popup/index.php:23
844
- #: templates/popup/index.php:34 templates/widgets/gallery-list.php:48
845
- #: media/js/blocks/dist/index.min.js:1
846
- msgid "Hold the Ctrl or Command key to select/deselect multiple options."
847
- msgstr ""
848
- "Удерживайте клавишу Ctrl или Command, чтобы выбрать / отменить выбор "
849
- "нескольких параметров."
850
-
851
- #: templates/popup/index.php:16 media/js/blocks/dist/index.min.js:1
852
- msgid "Specific events"
853
- msgstr "Конкретные события"
854
-
855
- #: templates/popup/index.php:38
856
- msgid "Fields to display:"
857
- msgstr "Поля для отображения:"
858
-
859
- #. translators: Head means the leader of the event.
860
- #: templates/popup/index.php:47 media/js/blocks/dist/index.min.js:1
861
- msgid "Event Head"
862
- msgstr "Руководитель события"
863
-
864
- #: templates/popup/index.php:50
865
- msgid "Check the event parameter(s) to be displayed in the timetable."
866
- msgstr "Отметьте параметры события, которые будут отображаться в расписании."
867
-
868
- #: templates/popup/index.php:54 media/js/blocks/dist/index.min.js:1
869
- msgid "Block height in pixels"
870
- msgstr "Высота блока в пикселях"
871
-
872
- #: templates/popup/index.php:57
873
- msgid "Set height of the block"
874
- msgstr "Установить высоту блока"
875
-
876
- #: templates/popup/index.php:61 media/js/blocks/dist/index.min.js:1
877
- msgid "Base font size"
878
- msgstr "Базовый размер шрифта"
879
-
880
- #: templates/popup/index.php:64 media/js/blocks/dist/index.min.js:1
881
- msgid "Base font size for the table. Example 12px, 2em, 80%."
882
- msgstr "Базовый размер шрифта для таблицы. Например, 12px, 2em, 80%."
883
-
884
- #: templates/popup/index.php:68 media/js/blocks/dist/index.min.js:1
885
- msgid "Time frame for event"
886
- msgstr "Период времени для события"
887
-
888
- #: templates/popup/index.php:78 media/js/blocks/dist/index.min.js:1
889
- msgid "Filter events style"
890
- msgstr "Стиль фильтра событий"
891
-
892
- #: templates/popup/index.php:81
893
- msgid "Dropdown"
894
- msgstr "Выпадающий"
895
-
896
- #: templates/popup/index.php:83
897
- msgid "None"
898
- msgstr "Ничего"
899
-
900
- #: templates/popup/index.php:98 media/js/blocks/dist/index.min.js:1
901
- msgid "Filter title to display all events"
902
- msgstr "Заголовок фильтра для отображения всех событий"
903
-
904
- #: templates/popup/index.php:104 media/js/blocks/dist/index.min.js:1
905
- msgid "Hide 'All Events' option"
906
- msgstr "Спрятать опцию \"Все события\""
907
-
908
- #: templates/popup/index.php:114 media/js/blocks/dist/index.min.js:1
909
- msgid "Hide column with hours"
910
- msgstr "Прятать колонку с часами"
911
-
912
- #: templates/popup/index.php:123 media/js/blocks/dist/index.min.js:1
913
- msgid "Do not display empty rows"
914
- msgstr "Не отображать пустые строки"
915
-
916
- #: templates/popup/index.php:132 media/js/blocks/dist/index.min.js:1
917
- msgid "Merge cells with common events"
918
- msgstr "Обьеденить ячейки с одинаковыми событиями"
919
-
920
- #: templates/popup/index.php:141 templates/widgets/gallery-list.php:59
921
- #: media/js/blocks/dist/index.min.js:1
922
- msgid "Disable event link"
923
- msgstr "Отключить ссылку события"
924
-
925
- #: templates/popup/index.php:150 media/js/blocks/dist/index.min.js:1
926
- msgid "Horizontal align"
927
- msgstr "Горизонтальное выравнивание"
928
-
929
- #: templates/popup/index.php:159 media/js/blocks/dist/index.min.js:1
930
- msgid "Vertical align"
931
- msgstr "Вертикальное выравнивание"
932
-
933
- #: templates/popup/index.php:161
934
- msgid "default"
935
- msgstr "по умолчанию"
936
-
937
- #: templates/popup/index.php:162 media/js/blocks/dist/index.min.js:1
938
- msgid "top"
939
- msgstr "сверху"
940
-
941
- #: templates/popup/index.php:163 media/js/blocks/dist/index.min.js:1
942
- msgid "middle"
943
- msgstr "посередине"
944
-
945
- #: templates/popup/index.php:164 media/js/blocks/dist/index.min.js:1
946
- msgid "bottom"
947
- msgstr "снизу"
948
-
949
- #: templates/popup/index.php:179 media/js/blocks/dist/index.min.js:1
950
- msgid "Unique ID"
951
- msgstr "Уникальный ID"
952
-
953
- #: templates/popup/index.php:182 media/js/blocks/dist/index.min.js:1
954
- msgid ""
955
- "If you use more than one table on a page specify the unique ID for a "
956
- "timetable. It is usually all lowercase and contains only letters, numbers, "
957
- "and hyphens."
958
- msgstr ""
959
- "Если вы используете более одной таблицы на странице, укажите уникальный "
960
- "идентификатор для расписания. Он, как правило, содержит только буквы в "
961
- "нижнем регистре, цифры и дефис."
962
-
963
- #: templates/popup/index.php:186 media/js/blocks/dist/index.min.js:1
964
- msgid "CSS class"
965
- msgstr "CSS класс"
966
-
967
- #: templates/popup/index.php:192 media/js/blocks/dist/index.min.js:1
968
- msgid "Mobile behavior"
969
- msgstr "Отображение на мобильном"
970
-
971
- #: templates/popup/index.php:195 media/js/blocks/dist/index.min.js:1
972
- msgid "List"
973
- msgstr "Список"
974
-
975
- #: templates/popup/index.php:196 media/js/blocks/dist/index.min.js:1
976
- msgid "Table"
977
- msgstr "Таблица"
978
-
979
- #: templates/popup/index.php:198
980
- msgid ""
981
- "Tick \"List\" to display events in a list view on mobile devices. Tick "
982
- "\"Table\" to display events in a table."
983
- msgstr ""
984
- "Выберите \"Список\" для отображения событий в виде списка на мобильных "
985
- "устройствах. Выберите \"Таблица\" для отображения событий в таблице."
986
-
987
- #: templates/popup/index.php:204
988
- msgid "Add Timetable"
989
- msgstr "Добавить расписание"
990
-
991
- #: templates/settings/general.php:2
992
- msgid "General Settings"
993
- msgstr "Основные настройки"
994
-
995
- #: templates/settings/general.php:9
996
- msgid "Template Mode"
997
- msgstr "Режим шаблона"
998
-
999
- #: templates/settings/general.php:13
1000
- msgid "Theme Mode"
1001
- msgstr "Режим темы"
1002
-
1003
- #: templates/settings/general.php:14
1004
- msgid "Developer Mode"
1005
- msgstr "Режим разработчика"
1006
-
1007
- #: templates/settings/general.php:16
1008
- msgid ""
1009
- "Choose Theme Mode to display the content with the styles of your theme. "
1010
- "Choose Developer Mode to control appearance of the content with custom page "
1011
- "templates, actions and filters."
1012
- msgstr ""
1013
- "Выберите режим \"Тема\" для отображения содержимого с помощью стилей вашей "
1014
- "темы. Выберите режим \"Разработчик\", чтобы контролировать внешний вид "
1015
- "содержимого с пользовательских шаблонов страниц, действий и фильтров."
1016
-
1017
- #: templates/settings/general.php:16
1018
- msgid ""
1019
- "This option can't be changed if your theme is initially integrated with the "
1020
- "plugin."
1021
- msgstr ""
1022
- "Эта опция не может быть изменена, если тема изначально интегрирована с "
1023
- "плагином."
1024
-
1025
- #: templates/settings/general.php:23
1026
- msgid "Permalink Settings"
1027
- msgstr "Настройки постоянных ссылок"
1028
-
1029
- #: templates/settings/general.php:24
1030
- msgid ""
1031
- "Configure permalink settings in <a href=\"%s\">Settings > Permalinks</a>"
1032
- msgstr ""
1033
- "Настройте постоянные ссылки в <a href=\"%s\">Настройки > Постоянные ссылки</"
1034
- "a>"
1035
-
1036
- #: templates/settings/general.php:29
1037
- msgid "Save"
1038
- msgstr "Сохранить"
1039
-
1040
- #: templates/shortcodes/empty-search-events.php:1
1041
- #: templates/theme/widget-upcoming-view.php:54
1042
- #: templates/widgets/widget-view.php:91
1043
- msgid "no events found"
1044
- msgstr "событий не найдено"
1045
-
1046
- #: templates/templates-actions/action-sidebar.php:8
1047
- #: templates/widgets/gallery-list.php:14
1048
- msgid "Today upcoming events"
1049
- msgstr "Предстоящие сегодня события"
1050
-
1051
- #: templates/templates-actions/action-sidebar.php:13
1052
- #: templates/widgets/gallery-list.php:16
1053
- msgid "All upcoming events"
1054
- msgstr "Все предстоящие события"
1055
-
1056
- #: templates/widgets/gallery-list.php:10
1057
- msgid "Events to display"
1058
- msgstr "События для отображения"
1059
-
1060
- #: templates/widgets/gallery-list.php:18
1061
- msgid "Ongoing events"
1062
- msgstr "Текущие события"
1063
-
1064
- #: templates/widgets/gallery-list.php:23
1065
- msgid "Input number of days"
1066
- msgstr "Введите количество дней"
1067
-
1068
- #: templates/widgets/gallery-list.php:28
1069
- msgid "day"
1070
- msgid_plural "days"
1071
- msgstr[0] "день"
1072
- msgstr[1] "дня"
1073
- msgstr[2] "дней"
1074
-
1075
- #: templates/widgets/gallery-list.php:32
1076
- msgid "Event categories. Leave blank to display all."
1077
- msgstr "Категории событий. Оставьте пустым для отображения всех."
1078
-
1079
- #: templates/widgets/gallery-list.php:52
1080
- msgid "Number of events to display"
1081
- msgstr "Количество событий для отображения"
1082
-
1083
- #: templates/widgets/gallery-list.php:70
1084
- msgid "Custom link for events"
1085
- msgstr "Специальные ссылки для событий"
1086
-
1087
- #: templates/widgets/gallery-list.php:78
1088
- msgid "Event background color"
1089
- msgstr "Цвет фона событий"
1090
-
1091
- #: templates/widgets/gallery-list.php:88
1092
- msgid "Event background color on hover"
1093
- msgstr "Цвет фона события при наведении"
1094
-
1095
- #: templates/widgets/gallery-list.php:98
1096
- msgid "Event text color"
1097
- msgstr "Цвет текста события"
1098
-
1099
- #: templates/widgets/gallery-list.php:108
1100
- msgid "Event text color on hover"
1101
- msgstr "Цвет текста события при наведении"
1102
-
1103
- #: templates/widgets/gallery-list.php:118
1104
- msgid "Event border color"
1105
- msgstr "Цвет рамки события"
1106
-
1107
- #: templates/widgets/gallery-list.php:128
1108
- msgid "Event border color on hover"
1109
- msgstr "Рамка события при наведении"
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Plugins - Timetable and Event Schedule by MotoPress - "
4
+ "Development (trunk)\n"
5
+ "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/mp-timetable\n"
6
+ "POT-Creation-Date: 2021-02-03T19:20:41+00:00\n"
7
+ "PO-Revision-Date: 2021-02-03 21:20+0200\n"
8
+ "Last-Translator: \n"
9
+ "Language-Team: \n"
10
+ "Language: ru\n"
11
+ "MIME-Version: 1.0\n"
12
+ "Content-Type: text/plain; charset=UTF-8\n"
13
+ "Content-Transfer-Encoding: 8bit\n"
14
+ "Plural-Forms: nplurals=3; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : ((n % "
15
+ "10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) ? 1 : 2);\n"
16
+ "X-Generator: Poedit 2.2.1\n"
17
+
18
+ #. Plugin Name of the plugin
19
+ msgid "Timetable and Event Schedule"
20
+ msgstr "Timetable and Event Schedule"
21
+
22
+ #. Plugin URI of the plugin
23
+ msgid "https://motopress.com/products/timetable-event-schedule/"
24
+ msgstr "https://motopress.com/products/timetable-event-schedule/"
25
+
26
+ #. Description of the plugin
27
+ msgid ""
28
+ "Smart time-management tool with a clean minimalist design for featuring your "
29
+ "timetables and upcoming events."
30
+ msgstr ""
31
+ "Смарт инструмент для тайм-менеджмента с простым и минималистичным дизайном "
32
+ "для отображения расписаний и предстоящих событий."
33
+
34
+ #. Author of the plugin
35
+ msgid "MotoPress"
36
+ msgstr "MotoPress"
37
+
38
+ #. Author URI of the plugin
39
+ msgid "https://motopress.com"
40
+ msgstr "https://motopress.com"
41
+
42
+ #. translators: 1: Timetable and Event Schedule 2:: five stars rating
43
+ #: admin/help/index.php:10 templates/settings/general.php:41
44
+ msgid "If you like %1$s please leave us a %2$s rating."
45
+ msgstr "Если вам нравится %1$s, поставьте нам %2$s оценку."
46
+
47
+ #: admin/import/export.php:1 admin/import/export.php:5
48
+ msgid "Export"
49
+ msgstr "Экспортировать"
50
+
51
+ #: admin/import/greet.php:2
52
+ msgid "Choose a WXR (.xml) file to upload, then click Upload file and import."
53
+ msgstr "Выберите WXR файл (с расширением XML), и нажмите кноку Загрузить."
54
+
55
+ #: admin/import/header.php:2
56
+ msgid "Import / Export Timetable Plugin Data"
57
+ msgstr "Импорт / Экспорт данных плагина"
58
+
59
+ #: admin/import/import.php:4
60
+ msgid "Import"
61
+ msgstr "Импортировать"
62
+
63
+ #: classes/blocks/class-timetable-block.php:92 classes/class-core.php:443
64
+ #: classes/class-shortcode.php:70 classes/class-shortcode.php:286
65
+ #: templates-functions/action-shortcode-functions.php:57
66
+ #: templates-functions/action-shortcode-functions.php:71
67
+ #: templates-functions/action-shortcode-functions.php:72
68
+ msgid "All Events"
69
+ msgstr "Все события"
70
+
71
+ #: classes/class-core.php:332 classes/class-core.php:343
72
+ #: classes/class-core.php:347 classes/class-shortcode.php:265
73
+ #: templates/popup/index.php:27 media/js/blocks/dist/index.min.js:1
74
+ msgid "Event categories"
75
+ msgstr "Категории событий"
76
+
77
+ #: classes/class-core.php:333
78
+ msgid "Event category"
79
+ msgstr "Категория события"
80
+
81
+ #: classes/class-core.php:334 classes/class-core.php:335
82
+ msgid "Add New Event category"
83
+ msgstr "Добавить новую категорию события"
84
+
85
+ #: classes/class-core.php:336
86
+ msgid "Edit Event category"
87
+ msgstr "Редактировать категорию события"
88
+
89
+ #: classes/class-core.php:337
90
+ msgid "New Event category"
91
+ msgstr "Новая категория события"
92
+
93
+ #: classes/class-core.php:338
94
+ msgid "All Event categories"
95
+ msgstr "Все категории событий"
96
+
97
+ #: classes/class-core.php:339
98
+ msgid "View Event category"
99
+ msgstr "Просмотр категории события"
100
+
101
+ #: classes/class-core.php:340
102
+ msgid "Search Event category"
103
+ msgstr "Поиск категорий события"
104
+
105
+ #: classes/class-core.php:341
106
+ msgid "No Event categories found"
107
+ msgstr "Категории событий не найдены"
108
+
109
+ #: classes/class-core.php:342
110
+ msgid "No Event categories found in Trash"
111
+ msgstr "Категории событий в корзине не найдены"
112
+
113
+ #: classes/class-core.php:376 classes/class-core.php:387
114
+ #: classes/class-core.php:391
115
+ msgid "Event tags"
116
+ msgstr "Ярлыки событий"
117
+
118
+ #: classes/class-core.php:377
119
+ msgid "Event tag"
120
+ msgstr "Ярлык события"
121
+
122
+ #: classes/class-core.php:378 classes/class-core.php:379
123
+ msgid "Add New Event tag"
124
+ msgstr "Добавить новый ярлык события"
125
+
126
+ #: classes/class-core.php:380
127
+ msgid "Edit Event tag"
128
+ msgstr "Редактировать ярлык события"
129
+
130
+ #: classes/class-core.php:381
131
+ msgid "New Event tag"
132
+ msgstr "Новый ярлык события"
133
+
134
+ #: classes/class-core.php:382
135
+ msgid "All Event tags"
136
+ msgstr "Все ярлыки событий"
137
+
138
+ #: classes/class-core.php:383
139
+ msgid "View Event tag"
140
+ msgstr "Просмотр ярлыков события"
141
+
142
+ #: classes/class-core.php:384
143
+ msgid "Search Event tag"
144
+ msgstr "Поиск ярлыка события"
145
+
146
+ #: classes/class-core.php:385
147
+ msgid "No Event tags found"
148
+ msgstr "Ярлыки событий не найдены"
149
+
150
+ #: classes/class-core.php:386
151
+ msgid "No Event tags found in Trash"
152
+ msgstr "Ярлыков событий в корзине не найдено"
153
+
154
+ #: classes/class-core.php:437 classes/class-core.php:448
155
+ #: classes/class-hooks.php:192 classes/class-shortcode.php:260
156
+ msgid "Events"
157
+ msgstr "События"
158
+
159
+ #: classes/class-core.php:438
160
+ msgid "Event"
161
+ msgstr "Событие"
162
+
163
+ #: classes/class-core.php:439 classes/class-core.php:440
164
+ msgid "Add New Event"
165
+ msgstr "Добавить новое событе"
166
+
167
+ #: classes/class-core.php:441
168
+ msgid "Edit Event"
169
+ msgstr "Редактировать событие"
170
+
171
+ #: classes/class-core.php:442
172
+ msgid "New Event"
173
+ msgstr "Новое событие"
174
+
175
+ #: classes/class-core.php:444
176
+ msgid "View Event"
177
+ msgstr "Просмотреть событие"
178
+
179
+ #: classes/class-core.php:445
180
+ msgid "Search Event"
181
+ msgstr "Поиск событий"
182
+
183
+ #: classes/class-core.php:446
184
+ msgid "No Events found"
185
+ msgstr "События не найдены"
186
+
187
+ #: classes/class-core.php:447
188
+ msgid "No Events found in Trash"
189
+ msgstr "События не найдены в корзине"
190
+
191
+ #: classes/class-core.php:476 classes/class-core.php:487
192
+ #: classes/class-hooks.php:200 templates/popup/index.php:5
193
+ #: media/js/blocks/dist/index.min.js:1
194
+ msgid "Columns"
195
+ msgstr "Столбцы"
196
+
197
+ #: classes/class-core.php:477 classes/class-shortcode.php:255
198
+ #: templates/events/event-data.php:4
199
+ msgid "Column"
200
+ msgstr "Столбец"
201
+
202
+ #: classes/class-core.php:478 classes/class-core.php:479
203
+ msgid "Add New Column"
204
+ msgstr "Добавить новый столбец"
205
+
206
+ #: classes/class-core.php:480
207
+ msgid "Edit Column"
208
+ msgstr "Редактировать столбец"
209
+
210
+ #: classes/class-core.php:481
211
+ msgid "New Column"
212
+ msgstr "Новый столбец"
213
+
214
+ #: classes/class-core.php:482
215
+ msgid "All Columns"
216
+ msgstr "Все столбцы"
217
+
218
+ #: classes/class-core.php:483
219
+ msgid "View Column"
220
+ msgstr "Просмотр столбцов"
221
+
222
+ #: classes/class-core.php:484
223
+ msgid "Search Column"
224
+ msgstr "Поиск столбцов"
225
+
226
+ #: classes/class-core.php:485
227
+ msgid "No Columns found"
228
+ msgstr "Столбцы не найдены"
229
+
230
+ #: classes/class-core.php:486
231
+ msgid "No Columns found in Trash"
232
+ msgstr "Столбцов в корзине не найдено"
233
+
234
+ #: classes/class-hooks.php:78
235
+ msgid "Timetable Sidebar"
236
+ msgstr "Расписание в боковой панели"
237
+
238
+ #: classes/class-hooks.php:80 classes/class-hooks.php:188
239
+ #: classes/class-shortcode.php:370 media/js/blocks/dist/index.min.js:1
240
+ msgid "Timetable"
241
+ msgstr "Расписание"
242
+
243
+ #: classes/class-hooks.php:179
244
+ msgid "Import Timetable events, categories, tags and images."
245
+ msgstr "Импортировать события, категории, ярлыки и изображения."
246
+
247
+ #: classes/class-hooks.php:196
248
+ msgid "Add Event"
249
+ msgstr "Добавить событие"
250
+
251
+ #: classes/class-hooks.php:204
252
+ msgid "Add Column"
253
+ msgstr "Добавить столбец"
254
+
255
+ #: classes/class-hooks.php:208
256
+ msgid "Event Categories"
257
+ msgstr "Категории событий"
258
+
259
+ #: classes/class-hooks.php:212
260
+ msgid "Event Tags"
261
+ msgstr "Ярлыки событий"
262
+
263
+ #: classes/class-hooks.php:216 classes/modules/class-post.php:41
264
+ #: media/js/blocks/dist/index.min.js:1
265
+ msgid "Settings"
266
+ msgstr "Настройки"
267
+
268
+ #: classes/class-hooks.php:220
269
+ msgid "Export / Import"
270
+ msgstr "Экспорт / Импорт"
271
+
272
+ #: classes/class-hooks.php:224
273
+ msgid "Help & Shortcode"
274
+ msgstr "Помощь и шорткоды"
275
+
276
+ #: classes/class-hooks.php:288
277
+ msgid "Quick Start Guide"
278
+ msgstr "Краткое руководство пользователя"
279
+
280
+ #: classes/class-hooks.php:289
281
+ msgid "Help"
282
+ msgstr "Помощь"
283
+
284
+ #: classes/class-hooks.php:290
285
+ msgid "Leave a Review"
286
+ msgstr "Оставьте отзыв"
287
+
288
+ #: classes/class-permalinks.php:26
289
+ msgid "Timetable Permalinks"
290
+ msgstr "Ссылки расписания"
291
+
292
+ #: classes/class-permalinks.php:30
293
+ msgid "Column base"
294
+ msgstr "Префикс для столбцов"
295
+
296
+ #: classes/class-permalinks.php:37
297
+ msgid "Event base"
298
+ msgstr "Префикс для событий"
299
+
300
+ #: classes/class-permalinks.php:44
301
+ msgid "Event Category base"
302
+ msgstr "Префикс для рубрик событий"
303
+
304
+ #: classes/class-permalinks.php:51
305
+ msgid "Event Tag base"
306
+ msgstr "Префикс для меток событий"
307
+
308
+ #: classes/class-shortcode.php:270
309
+ msgid "Hour measure"
310
+ msgstr "Мера часа"
311
+
312
+ #: classes/class-shortcode.php:271 templates/popup/index.php:71
313
+ #: media/js/blocks/dist/index.min.js:1
314
+ msgid "Hour (1h)"
315
+ msgstr "Час (1 ч)"
316
+
317
+ #: classes/class-shortcode.php:271 templates/popup/index.php:72
318
+ #: media/js/blocks/dist/index.min.js:1
319
+ msgid "Half hour (30min)"
320
+ msgstr "Полчаса (30 мин)"
321
+
322
+ #: classes/class-shortcode.php:271 templates/popup/index.php:73
323
+ #: media/js/blocks/dist/index.min.js:1
324
+ msgid "Quarter hour (15min)"
325
+ msgstr "Четверть часа (15 мин)"
326
+
327
+ #: classes/class-shortcode.php:275
328
+ msgid "Filter style"
329
+ msgstr "Стиль для фильтра"
330
+
331
+ #: classes/class-shortcode.php:276 media/js/blocks/dist/index.min.js:1
332
+ msgid "Dropdown list"
333
+ msgstr "Выпадающий список"
334
+
335
+ #: classes/class-shortcode.php:276 templates/popup/index.php:82
336
+ #: media/js/blocks/dist/index.min.js:1
337
+ msgid "Tabs"
338
+ msgstr "Вкладки"
339
+
340
+ #: classes/class-shortcode.php:280 templates/popup/index.php:88
341
+ #: media/js/blocks/dist/index.min.js:1
342
+ msgid "Order of items in filter"
343
+ msgstr "Порядок элементов в фильтре"
344
+
345
+ #: classes/class-shortcode.php:281 classes/class-shortcode.php:367
346
+ #: templates/popup/index.php:91 templates/popup/index.php:172
347
+ #: media/js/blocks/dist/index.min.js:1
348
+ msgid "Default"
349
+ msgstr "По умолчанию"
350
+
351
+ #: classes/class-shortcode.php:281 templates/popup/index.php:92
352
+ #: media/js/blocks/dist/index.min.js:1
353
+ msgid "Menu Order"
354
+ msgstr "Порядок меню"
355
+
356
+ #: classes/class-shortcode.php:281 classes/class-shortcode.php:306
357
+ #: templates/popup/index.php:40 templates/popup/index.php:93
358
+ #: templates/widgets/gallery-list.php:3 media/js/blocks/dist/index.min.js:1
359
+ msgid "Title"
360
+ msgstr "Заголовок"
361
+
362
+ #: classes/class-shortcode.php:285
363
+ msgid "Filter label"
364
+ msgstr "Метка фильтра"
365
+
366
+ #: classes/class-shortcode.php:290
367
+ msgid "Hide 'All Events' view"
368
+ msgstr "Скрыть вид \"Все события\""
369
+
370
+ #: classes/class-shortcode.php:291 classes/class-shortcode.php:296
371
+ #: classes/class-shortcode.php:301 classes/class-shortcode.php:308
372
+ #: classes/class-shortcode.php:314 classes/class-shortcode.php:320
373
+ #: classes/class-shortcode.php:326 classes/class-shortcode.php:332
374
+ #: classes/class-shortcode.php:337 classes/class-shortcode.php:361
375
+ #: templates/events/metabox-event-options.php:45 templates/popup/index.php:108
376
+ #: templates/popup/index.php:117 templates/popup/index.php:127
377
+ #: templates/popup/index.php:135 templates/popup/index.php:144
378
+ #: templates/widgets/gallery-list.php:63 media/js/blocks/dist/index.min.js:1
379
+ msgid "No"
380
+ msgstr "Нет"
381
+
382
+ #: classes/class-shortcode.php:291 classes/class-shortcode.php:296
383
+ #: classes/class-shortcode.php:301 classes/class-shortcode.php:308
384
+ #: classes/class-shortcode.php:314 classes/class-shortcode.php:320
385
+ #: classes/class-shortcode.php:326 classes/class-shortcode.php:332
386
+ #: classes/class-shortcode.php:337 classes/class-shortcode.php:361
387
+ #: templates/events/metabox-event-options.php:46 templates/popup/index.php:109
388
+ #: templates/popup/index.php:118 templates/popup/index.php:126
389
+ #: templates/popup/index.php:136 templates/popup/index.php:145
390
+ #: templates/widgets/gallery-list.php:65 media/js/blocks/dist/index.min.js:1
391
+ msgid "Yes"
392
+ msgstr "Да"
393
+
394
+ #: classes/class-shortcode.php:295
395
+ msgid "Hide first (hours) column"
396
+ msgstr "Скрыть первый (с часами) столбец"
397
+
398
+ #: classes/class-shortcode.php:300
399
+ msgid "Hide empty rows"
400
+ msgstr "Скрыть пустые ряды"
401
+
402
+ #: classes/class-shortcode.php:312 templates/popup/index.php:41
403
+ #: media/js/blocks/dist/index.min.js:1
404
+ msgid "Time"
405
+ msgstr "Время"
406
+
407
+ #: classes/class-shortcode.php:318 templates/popup/index.php:42
408
+ #: media/js/blocks/dist/index.min.js:1
409
+ msgid "Subtitle"
410
+ msgstr "Подзаголовок"
411
+
412
+ #: classes/class-shortcode.php:324 templates/events/event-data.php:7
413
+ #: templates/popup/index.php:43 media/js/blocks/dist/index.min.js:1
414
+ msgid "Description"
415
+ msgstr "Описание"
416
+
417
+ #: classes/class-shortcode.php:330
418
+ msgid "User"
419
+ msgstr "Пользователь"
420
+
421
+ #: classes/class-shortcode.php:336
422
+ msgid "Disable event URL"
423
+ msgstr "Отключить URL события"
424
+
425
+ #: classes/class-shortcode.php:341
426
+ msgid "Text align"
427
+ msgstr "Выравнивание текста"
428
+
429
+ #: classes/class-shortcode.php:342 templates/popup/index.php:152
430
+ #: media/js/blocks/dist/index.min.js:1
431
+ msgid "center"
432
+ msgstr "по центру"
433
+
434
+ #: classes/class-shortcode.php:342 templates/popup/index.php:153
435
+ #: media/js/blocks/dist/index.min.js:1
436
+ msgid "left"
437
+ msgstr "слева"
438
+
439
+ #: classes/class-shortcode.php:342 templates/popup/index.php:154
440
+ #: media/js/blocks/dist/index.min.js:1
441
+ msgid "right"
442
+ msgstr "справа"
443
+
444
+ #: classes/class-shortcode.php:346
445
+ msgid "Id"
446
+ msgstr "Id"
447
+
448
+ #: classes/class-shortcode.php:350
449
+ msgid "Row height (in px)"
450
+ msgstr "Высота ряда (в пикселях)"
451
+
452
+ #: classes/class-shortcode.php:355
453
+ msgid "Base Font Size"
454
+ msgstr "Базовый размер шрифта"
455
+
456
+ #: classes/class-shortcode.php:360
457
+ msgid "Responsive"
458
+ msgstr "Адаптивные"
459
+
460
+ #: classes/class-shortcode.php:366 templates/popup/index.php:169
461
+ #: media/js/blocks/dist/index.min.js:1
462
+ msgid "Column width"
463
+ msgstr "Ширина столбца"
464
+
465
+ #: classes/class-shortcode.php:367 templates/popup/index.php:173
466
+ #: media/js/blocks/dist/index.min.js:1
467
+ msgid "Auto"
468
+ msgstr "Автоматически"
469
+
470
+ #: classes/class-shortcode.php:367 templates/popup/index.php:174
471
+ #: media/js/blocks/dist/index.min.js:1
472
+ msgid "Fixed"
473
+ msgstr "Фиксированное"
474
+
475
+ #: classes/controllers/class-controller-settings.php:70
476
+ msgid "Settings saved."
477
+ msgstr "Настройки сохранены."
478
+
479
+ #: classes/libs/parsers.php:44 classes/libs/parsers.php:74
480
+ #: classes/libs/parsers.php:82
481
+ msgid "There was an error when reading this WXR file"
482
+ msgstr "Ошибка при чтении файла WXR"
483
+
484
+ #: classes/libs/parsers.php:45
485
+ msgid ""
486
+ "Details are shown above. The importer will now try again with a different "
487
+ "parser..."
488
+ msgstr ""
489
+ "Подробности ниже. Сейчас плагин повторит попытку импортирования с другим "
490
+ "парсером..."
491
+
492
+ #: classes/libs/parsers.php:86 classes/libs/parsers.php:91
493
+ #: classes/libs/parsers.php:304 classes/libs/parsers.php:565
494
+ msgid ""
495
+ "This does not appear to be a WXR file, missing/invalid WXR version number"
496
+ msgstr "Кажется это файл WXR, пропущенный/неверный номер версии WXR"
497
+
498
+ #: classes/models/class-column.php:42 classes/modules/class-post.php:40
499
+ msgid "Timeslots"
500
+ msgstr "Временные интервалы"
501
+
502
+ #: classes/models/class-events.php:171
503
+ msgid "Tags"
504
+ msgstr "Ключевые слова"
505
+
506
+ #: classes/models/class-events.php:172
507
+ msgid "Categories"
508
+ msgstr "Категории"
509
+
510
+ #: classes/models/class-events.php:774
511
+ msgid "Duplicate"
512
+ msgstr "Дублировать"
513
+
514
+ #: classes/models/class-events.php:795
515
+ msgid "A post type mismatch has been detected."
516
+ msgstr "Обнаружено несоответствие типов постов."
517
+
518
+ #: classes/models/class-events.php:795
519
+ msgid "Sorry, you are not allowed to edit this item."
520
+ msgstr "У вас недостаточно прав для редактирования этого элемента."
521
+
522
+ #. translators: New post title of the duplicated post
523
+ #: classes/models/class-events.php:819
524
+ msgid "%s - Copy"
525
+ msgstr "%s - Копия"
526
+
527
+ #: classes/models/class-import.php:125
528
+ msgid "Assign Authors"
529
+ msgstr "Привязка авторов"
530
+
531
+ #: classes/models/class-import.php:126
532
+ msgid ""
533
+ "To make it easier for you to edit and save the imported content, you may "
534
+ "want to reassign the author of the imported item to an existing user of this "
535
+ "site. For example, you may want to import all the entries as <code>admin</"
536
+ "code>s entries."
537
+ msgstr ""
538
+ "Чтобы сделать проще редактирование и сохранение импортированного материала, "
539
+ "вы, возможно, захотите перепривязать автора импортированного элемента к "
540
+ "существующему пользователю этого сайта. Например, вы захотите импортировать "
541
+ "все записи как записи пользователя <code>admin</code>."
542
+
543
+ #: classes/models/class-import.php:128
544
+ msgid ""
545
+ "If a new user is created by WordPress, a new password will be randomly "
546
+ "generated and the new user&#8217;s role will be set as %s. Manually changing "
547
+ "the new user&#8217;s details will be necessary."
548
+ msgstr ""
549
+ "Если новый пользователь создан WordPress, новый пароль будет сгенерирован "
550
+ "случайным образом, и роль нового пользователя будет %s. Понадобятся "
551
+ "изменения деталей профиля нового пользователя вручную."
552
+
553
+ #: classes/models/class-import.php:138
554
+ msgid "Import Attachments"
555
+ msgstr "Импорт вложений"
556
+
557
+ #: classes/models/class-import.php:141
558
+ msgid "Download and import file attachments"
559
+ msgstr "Скачать и импортировать файлы вложений"
560
+
561
+ #: classes/models/class-import.php:145
562
+ msgid "Submit"
563
+ msgstr "Отправить"
564
+
565
+ #: classes/models/class-import.php:158
566
+ msgid "Import author:"
567
+ msgstr "Импорт автора:"
568
+
569
+ #: classes/models/class-import.php:169
570
+ msgid "or create new user with login name:"
571
+ msgstr "или создать нового пользователя с именем:"
572
+
573
+ #: classes/models/class-import.php:172
574
+ msgid "as a new user:"
575
+ msgstr "как новый пользователь:"
576
+
577
+ #: classes/models/class-import.php:180
578
+ msgid "assign posts to an existing user:"
579
+ msgstr "назначить записи существующему пользователю:"
580
+
581
+ #: classes/models/class-import.php:182
582
+ msgid "or assign posts to an existing user:"
583
+ msgstr "или привязать записи к существующему пользователю:"
584
+
585
+ #: classes/models/class-import.php:183
586
+ #: templates/column/metabox-column-options.php:23
587
+ msgid "- Select -"
588
+ msgstr "- Выбрать -"
589
+
590
+ #: classes/models/class-import.php:269
591
+ msgid "All done."
592
+ msgstr "Все готово."
593
+
594
+ #: classes/models/class-import.php:269
595
+ msgid "Have fun!"
596
+ msgstr "Наслаждайтесь!"
597
+
598
+ #: classes/models/class-import.php:270
599
+ msgid "Remember to update the passwords and roles of imported users."
600
+ msgstr "Не забудьте обновить пароли и роли импортированных пользователей."
601
+
602
+ #: classes/models/class-import.php:286
603
+ msgid "Fetching attachments is not enabled"
604
+ msgstr "Импортирование вложений отключено"
605
+
606
+ #: classes/models/class-import.php:299
607
+ msgid "Invalid file type"
608
+ msgstr "Неподходящий тип файла"
609
+
610
+ #: classes/models/class-import.php:379
611
+ msgid "Remote server did not respond"
612
+ msgstr "Удалённый сервер не&nbsp;отвечает"
613
+
614
+ #: classes/models/class-import.php:385
615
+ msgid "Remote server returned error response %1$d %2$s"
616
+ msgstr "Удалённый сервер выдал ошибку %1$d %2$s"
617
+
618
+ #: classes/models/class-import.php:394
619
+ msgid "Remote file is incorrect size"
620
+ msgstr "Удалённый файл неподходящего размера"
621
+
622
+ #: classes/models/class-import.php:399
623
+ msgid "Zero size file downloaded"
624
+ msgstr "Скачан пустой файл"
625
+
626
+ #: classes/models/class-import.php:405
627
+ msgid "Remote file is too large, limit is %s"
628
+ msgstr "Удалённый файл слишком велик. Текущее ограничение: %s"
629
+
630
+ #: classes/models/class-import.php:422 classes/models/class-import.php:426
631
+ #: classes/models/class-import.php:436
632
+ msgid "Sorry, there has been an error."
633
+ msgstr "К сожалению, возникла ошибка."
634
+
635
+ #: classes/models/class-import.php:427
636
+ msgid ""
637
+ "The export file could not be found at <code>%s</code>. It is likely that "
638
+ "this was caused by a permissions problem."
639
+ msgstr ""
640
+ "Экспортируемый файл не может быть найден в <code>%s</code>. Похоже, это "
641
+ "вызвано ошибкой прав доступа."
642
+
643
+ #: classes/models/class-import.php:444
644
+ msgid ""
645
+ "This WXR file (version %s) may not be supported by this version of the "
646
+ "importer. Please consider updating."
647
+ msgstr ""
648
+ "Данный файл WXR (версии %s) может не поддерживаться настоящей версией "
649
+ "плагина. Советуем обновить плагин."
650
+
651
+ #: classes/models/class-import.php:501
652
+ msgid ""
653
+ "Failed to import author %s. Their posts will be attributed to the current "
654
+ "user."
655
+ msgstr ""
656
+ "Не удалось импортировать автора \"%s\". Его статьи будут назначены текущему "
657
+ "пользователю."
658
+
659
+ #: classes/models/class-import.php:558
660
+ msgid ""
661
+ "Failed to create new user for %s. Their posts will be attributed to the "
662
+ "current user."
663
+ msgstr ""
664
+ "Не удалось создать нового пользователя для %s. Их записи будут отнесены к "
665
+ "текущему пользователю."
666
+
667
+ #: classes/models/class-import.php:609 classes/models/class-import.php:766
668
+ msgid "Failed to import %s %s"
669
+ msgstr "Не удалось импортировать %s %s"
670
+
671
+ #: classes/models/class-import.php:656
672
+ msgid "Failed to import &#8220;%s&#8221;: Invalid post type %s"
673
+ msgstr "Не удалось импортировать &#8220;%s&#8221;: Неверный тип записи %s"
674
+
675
+ #: classes/models/class-import.php:673
676
+ msgid "%s &#8220;%s&#8221; already exists."
677
+ msgstr "%s &#8220;%s&#8221; уже существует."
678
+
679
+ #: classes/models/class-import.php:732
680
+ msgid "Failed to import %s &#8220;%s&#8221;"
681
+ msgstr "Не удалось импортировать %s &#8220;%s&#8221;"
682
+
683
+ #: classes/modules/class-post.php:42
684
+ msgid "Column Type"
685
+ msgstr "Тип столбца"
686
+
687
+ #: classes/widgets/class-mp-timetable-widget.php:22
688
+ msgid "Display upcoming events."
689
+ msgstr "Отобразить предстоящие события."
690
+
691
+ #: classes/widgets/class-mp-timetable-widget.php:24
692
+ msgid "Timetable Events"
693
+ msgstr "События в расписании"
694
+
695
+ #: templates-functions/actions-mp-event-functions.php:27
696
+ #: templates/theme/event-timeslots.php:7
697
+ msgid "Event Timeslots (%s)"
698
+ msgstr "Временные интервалы событий (%s)"
699
+
700
+ #: templates/column/metabox-column-options.php:11
701
+ msgid "Simple Column"
702
+ msgstr "Простой столбец"
703
+
704
+ #: templates/column/metabox-column-options.php:20
705
+ msgid "Day of the week"
706
+ msgstr "День недели"
707
+
708
+ #: templates/column/metabox-column-options.php:24
709
+ msgid "Sunday"
710
+ msgstr "Воскресенье"
711
+
712
+ #: templates/column/metabox-column-options.php:25
713
+ msgid "Monday"
714
+ msgstr "Понедельник"
715
+
716
+ #: templates/column/metabox-column-options.php:26
717
+ msgid "Tuesday"
718
+ msgstr "Вторник"
719
+
720
+ #: templates/column/metabox-column-options.php:27
721
+ msgid "Wednesday"
722
+ msgstr "Среда"
723
+
724
+ #: templates/column/metabox-column-options.php:28
725
+ msgid "Thursday"
726
+ msgstr "Четверг"
727
+
728
+ #: templates/column/metabox-column-options.php:29
729
+ msgid "Friday"
730
+ msgstr "Пятница"
731
+
732
+ #: templates/column/metabox-column-options.php:30
733
+ msgid "Saturday"
734
+ msgstr "Суббота"
735
+
736
+ #: templates/column/metabox-column-options.php:39
737
+ msgid "Date"
738
+ msgstr "Дата"
739
+
740
+ #: templates/events/event-data.php:5
741
+ msgid "Start"
742
+ msgstr "Начало"
743
+
744
+ #: templates/events/event-data.php:6
745
+ msgid "End"
746
+ msgstr "Окончание"
747
+
748
+ #. translators: Head means the leader of the event.
749
+ #: templates/events/event-data.php:10
750
+ msgid "Head"
751
+ msgstr "Руководитель"
752
+
753
+ #: templates/events/event-data.php:12
754
+ msgid "Actions"
755
+ msgstr "Действия"
756
+
757
+ #: templates/events/event-data.php:35
758
+ msgid "Edit event in the form below"
759
+ msgstr "Отредактируйте событие в форме ниже"
760
+
761
+ #: templates/events/event-data.php:36
762
+ msgid "Delete"
763
+ msgstr "Удалить"
764
+
765
+ #: templates/events/metabox-event-data.php:10
766
+ msgid "Add New / Edit Timeslot"
767
+ msgstr "Добавить новый / Редактировать интервал"
768
+
769
+ #: templates/events/metabox-event-data.php:13
770
+ msgid "Column:"
771
+ msgstr "Столбец:"
772
+
773
+ #: templates/events/metabox-event-data.php:21
774
+ msgid "Select column or <a target=\"_blank\" href=\"%s\">Add New</a>."
775
+ msgstr ""
776
+ "Выберите столбец или <a target=\"_blank\" href=\"%s\">Добавьте новый</a>."
777
+
778
+ #: templates/events/metabox-event-data.php:23
779
+ msgid "No columns found. <a href=\"%s\">Create at least one column first.</a>"
780
+ msgstr ""
781
+ "Столбцов не найдено. <a href=\"%s\">Создайте как минимум один столбец для "
782
+ "начала.</a>"
783
+
784
+ #: templates/events/metabox-event-data.php:29
785
+ msgid "Start Time:"
786
+ msgstr "Время начала:"
787
+
788
+ #: templates/events/metabox-event-data.php:32
789
+ #: templates/events/metabox-event-data.php:39
790
+ msgid "hh:mm"
791
+ msgstr "чч:мм"
792
+
793
+ #: templates/events/metabox-event-data.php:36
794
+ msgid "End Time:"
795
+ msgstr "Время окончания:"
796
+
797
+ #: templates/events/metabox-event-data.php:43
798
+ msgid "Description:"
799
+ msgstr "Описание:"
800
+
801
+ #. translators: Head means the leader of the event.
802
+ #: templates/events/metabox-event-data.php:49
803
+ msgid "Event Head:"
804
+ msgstr "Руководитель события:"
805
+
806
+ #: templates/events/metabox-event-data.php:58
807
+ msgid "none"
808
+ msgstr "нет"
809
+
810
+ #. translators: Button to add a new event.
811
+ #: templates/events/metabox-event-data.php:83
812
+ msgid "Add New"
813
+ msgstr "Добавить новый"
814
+
815
+ #: templates/events/metabox-event-options.php:4
816
+ msgid "Event Subtitle:"
817
+ msgstr "Подзаголовок события:"
818
+
819
+ #: templates/events/metabox-event-options.php:8
820
+ msgid "Background Color:"
821
+ msgstr "Цвет фона:"
822
+
823
+ #: templates/events/metabox-event-options.php:15
824
+ msgid "Background Hover Color:"
825
+ msgstr "Цвет фона при наведении:"
826
+
827
+ #: templates/events/metabox-event-options.php:22
828
+ msgid "Text Color:"
829
+ msgstr "Цвет текста:"
830
+
831
+ #: templates/events/metabox-event-options.php:29
832
+ msgid "Text Hover Color:"
833
+ msgstr "Цвет текста при наведении:"
834
+
835
+ #: templates/events/metabox-event-options.php:36
836
+ msgid "Custom Event URL:"
837
+ msgstr "Специальная ссылка на событие:"
838
+
839
+ #: templates/events/metabox-event-options.php:42
840
+ msgid "Disable link to this event:"
841
+ msgstr "Отключить ссылку на событие:"
842
+
843
+ #: templates/popup/index.php:12 templates/popup/index.php:23
844
+ #: templates/popup/index.php:34 templates/widgets/gallery-list.php:48
845
+ #: media/js/blocks/dist/index.min.js:1
846
+ msgid "Hold the Ctrl or Command key to select/deselect multiple options."
847
+ msgstr ""
848
+ "Удерживайте клавишу Ctrl или Command, чтобы выбрать / отменить выбор "
849
+ "нескольких параметров."
850
+
851
+ #: templates/popup/index.php:16 media/js/blocks/dist/index.min.js:1
852
+ msgid "Specific events"
853
+ msgstr "Конкретные события"
854
+
855
+ #: templates/popup/index.php:38
856
+ msgid "Fields to display:"
857
+ msgstr "Поля для отображения:"
858
+
859
+ #. translators: Head means the leader of the event.
860
+ #: templates/popup/index.php:47 media/js/blocks/dist/index.min.js:1
861
+ msgid "Event Head"
862
+ msgstr "Руководитель события"
863
+
864
+ #: templates/popup/index.php:50
865
+ msgid "Check the event parameter(s) to be displayed in the timetable."
866
+ msgstr "Отметьте параметры события, которые будут отображаться в расписании."
867
+
868
+ #: templates/popup/index.php:54 media/js/blocks/dist/index.min.js:1
869
+ msgid "Block height in pixels"
870
+ msgstr "Высота блока в пикселях"
871
+
872
+ #: templates/popup/index.php:57
873
+ msgid "Set height of the block"
874
+ msgstr "Установить высоту блока"
875
+
876
+ #: templates/popup/index.php:61 media/js/blocks/dist/index.min.js:1
877
+ msgid "Base font size"
878
+ msgstr "Базовый размер шрифта"
879
+
880
+ #: templates/popup/index.php:64 media/js/blocks/dist/index.min.js:1
881
+ msgid "Base font size for the table. Example 12px, 2em, 80%."
882
+ msgstr "Базовый размер шрифта для таблицы. Например, 12px, 2em, 80%."
883
+
884
+ #: templates/popup/index.php:68 media/js/blocks/dist/index.min.js:1
885
+ msgid "Time frame for event"
886
+ msgstr "Период времени для события"
887
+
888
+ #: templates/popup/index.php:78 media/js/blocks/dist/index.min.js:1
889
+ msgid "Filter events style"
890
+ msgstr "Стиль фильтра событий"
891
+
892
+ #: templates/popup/index.php:81
893
+ msgid "Dropdown"
894
+ msgstr "Выпадающий"
895
+
896
+ #: templates/popup/index.php:83
897
+ msgid "None"
898
+ msgstr "Ничего"
899
+
900
+ #: templates/popup/index.php:98 media/js/blocks/dist/index.min.js:1
901
+ msgid "Filter title to display all events"
902
+ msgstr "Заголовок фильтра для отображения всех событий"
903
+
904
+ #: templates/popup/index.php:104 media/js/blocks/dist/index.min.js:1
905
+ msgid "Hide 'All Events' option"
906
+ msgstr "Спрятать опцию \"Все события\""
907
+
908
+ #: templates/popup/index.php:114 media/js/blocks/dist/index.min.js:1
909
+ msgid "Hide column with hours"
910
+ msgstr "Прятать колонку с часами"
911
+
912
+ #: templates/popup/index.php:123 media/js/blocks/dist/index.min.js:1
913
+ msgid "Do not display empty rows"
914
+ msgstr "Не отображать пустые строки"
915
+
916
+ #: templates/popup/index.php:132 media/js/blocks/dist/index.min.js:1
917
+ msgid "Merge cells with common events"
918
+ msgstr "Обьеденить ячейки с одинаковыми событиями"
919
+
920
+ #: templates/popup/index.php:141 templates/widgets/gallery-list.php:59
921
+ #: media/js/blocks/dist/index.min.js:1
922
+ msgid "Disable event link"
923
+ msgstr "Отключить ссылку события"
924
+
925
+ #: templates/popup/index.php:150 media/js/blocks/dist/index.min.js:1
926
+ msgid "Horizontal align"
927
+ msgstr "Горизонтальное выравнивание"
928
+
929
+ #: templates/popup/index.php:159 media/js/blocks/dist/index.min.js:1
930
+ msgid "Vertical align"
931
+ msgstr "Вертикальное выравнивание"
932
+
933
+ #: templates/popup/index.php:161
934
+ msgid "default"
935
+ msgstr "по умолчанию"
936
+
937
+ #: templates/popup/index.php:162 media/js/blocks/dist/index.min.js:1
938
+ msgid "top"
939
+ msgstr "сверху"
940
+
941
+ #: templates/popup/index.php:163 media/js/blocks/dist/index.min.js:1
942
+ msgid "middle"
943
+ msgstr "посередине"
944
+
945
+ #: templates/popup/index.php:164 media/js/blocks/dist/index.min.js:1
946
+ msgid "bottom"
947
+ msgstr "снизу"
948
+
949
+ #: templates/popup/index.php:179 media/js/blocks/dist/index.min.js:1
950
+ msgid "Unique ID"
951
+ msgstr "Уникальный ID"
952
+
953
+ #: templates/popup/index.php:182 media/js/blocks/dist/index.min.js:1
954
+ msgid ""
955
+ "If you use more than one table on a page specify the unique ID for a "
956
+ "timetable. It is usually all lowercase and contains only letters, numbers, "
957
+ "and hyphens."
958
+ msgstr ""
959
+ "Если вы используете более одной таблицы на странице, укажите уникальный "
960
+ "идентификатор для расписания. Он, как правило, содержит только буквы в "
961
+ "нижнем регистре, цифры и дефис."
962
+
963
+ #: templates/popup/index.php:186 media/js/blocks/dist/index.min.js:1
964
+ msgid "CSS class"
965
+ msgstr "CSS класс"
966
+
967
+ #: templates/popup/index.php:192 media/js/blocks/dist/index.min.js:1
968
+ msgid "Mobile behavior"
969
+ msgstr "Отображение на мобильном"
970
+
971
+ #: templates/popup/index.php:195 media/js/blocks/dist/index.min.js:1
972
+ msgid "List"
973
+ msgstr "Список"
974
+
975
+ #: templates/popup/index.php:196 media/js/blocks/dist/index.min.js:1
976
+ msgid "Table"
977
+ msgstr "Таблица"
978
+
979
+ #: templates/popup/index.php:198
980
+ msgid ""
981
+ "Tick \"List\" to display events in a list view on mobile devices. Tick "
982
+ "\"Table\" to display events in a table."
983
+ msgstr ""
984
+ "Выберите \"Список\" для отображения событий в виде списка на мобильных "
985
+ "устройствах. Выберите \"Таблица\" для отображения событий в таблице."
986
+
987
+ #: templates/popup/index.php:204
988
+ msgid "Add Timetable"
989
+ msgstr "Добавить расписание"
990
+
991
+ #: templates/settings/general.php:2
992
+ msgid "General Settings"
993
+ msgstr "Основные настройки"
994
+
995
+ #: templates/settings/general.php:9
996
+ msgid "Template Mode"
997
+ msgstr "Режим шаблона"
998
+
999
+ #: templates/settings/general.php:13
1000
+ msgid "Theme Mode"
1001
+ msgstr "Режим темы"
1002
+
1003
+ #: templates/settings/general.php:14
1004
+ msgid "Developer Mode"
1005
+ msgstr "Режим разработчика"
1006
+
1007
+ #: templates/settings/general.php:16
1008
+ msgid ""
1009
+ "Choose Theme Mode to display the content with the styles of your theme. "
1010
+ "Choose Developer Mode to control appearance of the content with custom page "
1011
+ "templates, actions and filters."
1012
+ msgstr ""
1013
+ "Выберите режим \"Тема\" для отображения содержимого с помощью стилей вашей "
1014
+ "темы. Выберите режим \"Разработчик\", чтобы контролировать внешний вид "
1015
+ "содержимого с пользовательских шаблонов страниц, действий и фильтров."
1016
+
1017
+ #: templates/settings/general.php:16
1018
+ msgid ""
1019
+ "This option can't be changed if your theme is initially integrated with the "
1020
+ "plugin."
1021
+ msgstr ""
1022
+ "Эта опция не может быть изменена, если тема изначально интегрирована с "
1023
+ "плагином."
1024
+
1025
+ #: templates/settings/general.php:23
1026
+ msgid "Permalink Settings"
1027
+ msgstr "Настройки постоянных ссылок"
1028
+
1029
+ #: templates/settings/general.php:24
1030
+ msgid ""
1031
+ "Configure permalink settings in <a href=\"%s\">Settings > Permalinks</a>"
1032
+ msgstr ""
1033
+ "Настройте постоянные ссылки в <a href=\"%s\">Настройки > Постоянные ссылки</"
1034
+ "a>"
1035
+
1036
+ #: templates/settings/general.php:29
1037
+ msgid "Save"
1038
+ msgstr "Сохранить"
1039
+
1040
+ #: templates/shortcodes/empty-search-events.php:1
1041
+ #: templates/theme/widget-upcoming-view.php:54
1042
+ #: templates/widgets/widget-view.php:91
1043
+ msgid "no events found"
1044
+ msgstr "событий не найдено"
1045
+
1046
+ #: templates/templates-actions/action-sidebar.php:8
1047
+ #: templates/widgets/gallery-list.php:14
1048
+ msgid "Today upcoming events"
1049
+ msgstr "Предстоящие сегодня события"
1050
+
1051
+ #: templates/templates-actions/action-sidebar.php:13
1052
+ #: templates/widgets/gallery-list.php:16
1053
+ msgid "All upcoming events"
1054
+ msgstr "Все предстоящие события"
1055
+
1056
+ #: templates/widgets/gallery-list.php:10
1057
+ msgid "Events to display"
1058
+ msgstr "События для отображения"
1059
+
1060
+ #: templates/widgets/gallery-list.php:18
1061
+ msgid "Ongoing events"
1062
+ msgstr "Текущие события"
1063
+
1064
+ #: templates/widgets/gallery-list.php:23
1065
+ msgid "Input number of days"
1066
+ msgstr "Введите количество дней"
1067
+
1068
+ #: templates/widgets/gallery-list.php:28
1069
+ msgid "day"
1070
+ msgid_plural "days"
1071
+ msgstr[0] "день"
1072
+ msgstr[1] "дня"
1073
+ msgstr[2] "дней"
1074
+
1075
+ #: templates/widgets/gallery-list.php:32
1076
+ msgid "Event categories. Leave blank to display all."
1077
+ msgstr "Категории событий. Оставьте пустым для отображения всех."
1078
+
1079
+ #: templates/widgets/gallery-list.php:52
1080
+ msgid "Number of events to display"
1081
+ msgstr "Количество событий для отображения"
1082
+
1083
+ #: templates/widgets/gallery-list.php:70
1084
+ msgid "Custom link for events"
1085
+ msgstr "Специальные ссылки для событий"
1086
+
1087
+ #: templates/widgets/gallery-list.php:78
1088
+ msgid "Event background color"
1089
+ msgstr "Цвет фона событий"
1090
+
1091
+ #: templates/widgets/gallery-list.php:88
1092
+ msgid "Event background color on hover"
1093
+ msgstr "Цвет фона события при наведении"
1094
+
1095
+ #: templates/widgets/gallery-list.php:98
1096
+ msgid "Event text color"
1097
+ msgstr "Цвет текста события"
1098
+
1099
+ #: templates/widgets/gallery-list.php:108
1100
+ msgid "Event text color on hover"
1101
+ msgstr "Цвет текста события при наведении"
1102
+
1103
+ #: templates/widgets/gallery-list.php:118
1104
+ msgid "Event border color"
1105
+ msgstr "Цвет рамки события"
1106
+
1107
+ #: templates/widgets/gallery-list.php:128
1108
+ msgid "Event border color on hover"
1109
+ msgstr "Рамка события при наведении"
languages/mp-timetable.pot CHANGED
@@ -1,1244 +1,1244 @@
1
- # Copyright (C) 2021 MotoPress
2
- # This file is distributed under the same license as the Timetable and Event Schedule plugin.
3
- msgid ""
4
- msgstr ""
5
- "Project-Id-Version: Timetable and Event Schedule 2.4.1\n"
6
- "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/mp-timetable\n"
7
- "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
8
- "Language-Team: LANGUAGE <LL@li.org>\n"
9
- "MIME-Version: 1.0\n"
10
- "Content-Type: text/plain; charset=UTF-8\n"
11
- "Content-Transfer-Encoding: 8bit\n"
12
- "POT-Creation-Date: 2021-08-19T15:15:13+00:00\n"
13
- "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
- "X-Generator: WP-CLI 2.4.0\n"
15
- "X-Domain: mp-timetable\n"
16
-
17
- #. Plugin Name of the plugin
18
- msgid "Timetable and Event Schedule"
19
- msgstr ""
20
-
21
- #. Plugin URI of the plugin
22
- msgid "https://motopress.com/products/timetable-event-schedule/"
23
- msgstr ""
24
-
25
- #. Description of the plugin
26
- msgid "Smart time-management tool with a clean minimalist design for featuring your timetables and upcoming events."
27
- msgstr ""
28
-
29
- #. Author of the plugin
30
- msgid "MotoPress"
31
- msgstr ""
32
-
33
- #. Author URI of the plugin
34
- msgid "https://motopress.com"
35
- msgstr ""
36
-
37
- #. translators: 1: Timetable and Event Schedule 2:: five stars rating
38
- #: admin/help/index.php:11
39
- #: templates/settings/general.php:41
40
- msgid "If you like %1$s please leave us a %2$s rating."
41
- msgstr ""
42
-
43
- #: admin/import/export.php:1
44
- #: admin/import/export.php:5
45
- msgid "Export"
46
- msgstr ""
47
-
48
- #: admin/import/greet.php:2
49
- msgid "Choose a WXR (.xml) file to upload, then click Upload file and import."
50
- msgstr ""
51
-
52
- #: admin/import/header.php:2
53
- msgid "Import / Export Timetable Plugin Data"
54
- msgstr ""
55
-
56
- #: admin/import/import.php:4
57
- msgid "Import"
58
- msgstr ""
59
-
60
- #: classes/blocks/class-timetable-block.php:102
61
- #: classes/class-core.php:448
62
- #: classes/class-shortcode.php:70
63
- #: classes/class-shortcode.php:286
64
- #: classes/widgets/class-mp-timetable-elementor-widget.php:100
65
- #: templates-functions/action-shortcode-functions.php:60
66
- #: templates-functions/action-shortcode-functions.php:74
67
- #: templates-functions/action-shortcode-functions.php:75
68
- msgid "All Events"
69
- msgstr ""
70
-
71
- #: classes/class-core.php:337
72
- #: classes/class-core.php:348
73
- #: classes/class-core.php:352
74
- #: classes/class-shortcode.php:265
75
- #: classes/widgets/class-mp-timetable-elementor-widget.php:139
76
- #: templates/popup/index.php:27
77
- #: media/js/blocks/dist/index.js:1
78
- msgid "Event categories"
79
- msgstr ""
80
-
81
- #: classes/class-core.php:338
82
- msgid "Event category"
83
- msgstr ""
84
-
85
- #: classes/class-core.php:339
86
- #: classes/class-core.php:340
87
- msgid "Add New Event category"
88
- msgstr ""
89
-
90
- #: classes/class-core.php:341
91
- msgid "Edit Event category"
92
- msgstr ""
93
-
94
- #: classes/class-core.php:342
95
- msgid "New Event category"
96
- msgstr ""
97
-
98
- #: classes/class-core.php:343
99
- msgid "All Event categories"
100
- msgstr ""
101
-
102
- #: classes/class-core.php:344
103
- msgid "View Event category"
104
- msgstr ""
105
-
106
- #: classes/class-core.php:345
107
- msgid "Search Event category"
108
- msgstr ""
109
-
110
- #: classes/class-core.php:346
111
- msgid "No Event categories found"
112
- msgstr ""
113
-
114
- #: classes/class-core.php:347
115
- msgid "No Event categories found in Trash"
116
- msgstr ""
117
-
118
- #: classes/class-core.php:381
119
- #: classes/class-core.php:392
120
- #: classes/class-core.php:396
121
- msgid "Event tags"
122
- msgstr ""
123
-
124
- #: classes/class-core.php:382
125
- msgid "Event tag"
126
- msgstr ""
127
-
128
- #: classes/class-core.php:383
129
- #: classes/class-core.php:384
130
- msgid "Add New Event tag"
131
- msgstr ""
132
-
133
- #: classes/class-core.php:385
134
- msgid "Edit Event tag"
135
- msgstr ""
136
-
137
- #: classes/class-core.php:386
138
- msgid "New Event tag"
139
- msgstr ""
140
-
141
- #: classes/class-core.php:387
142
- msgid "All Event tags"
143
- msgstr ""
144
-
145
- #: classes/class-core.php:388
146
- msgid "View Event tag"
147
- msgstr ""
148
-
149
- #: classes/class-core.php:389
150
- msgid "Search Event tag"
151
- msgstr ""
152
-
153
- #: classes/class-core.php:390
154
- msgid "No Event tags found"
155
- msgstr ""
156
-
157
- #: classes/class-core.php:391
158
- msgid "No Event tags found in Trash"
159
- msgstr ""
160
-
161
- #: classes/class-core.php:442
162
- #: classes/class-core.php:453
163
- #: classes/class-hooks.php:204
164
- #: classes/class-shortcode.php:260
165
- msgid "Events"
166
- msgstr ""
167
-
168
- #: classes/class-core.php:443
169
- msgid "Event"
170
- msgstr ""
171
-
172
- #: classes/class-core.php:444
173
- #: classes/class-core.php:445
174
- msgid "Add New Event"
175
- msgstr ""
176
-
177
- #: classes/class-core.php:446
178
- msgid "Edit Event"
179
- msgstr ""
180
-
181
- #: classes/class-core.php:447
182
- msgid "New Event"
183
- msgstr ""
184
-
185
- #: classes/class-core.php:449
186
- msgid "View Event"
187
- msgstr ""
188
-
189
- #: classes/class-core.php:450
190
- msgid "Search Event"
191
- msgstr ""
192
-
193
- #: classes/class-core.php:451
194
- msgid "No Events found"
195
- msgstr ""
196
-
197
- #: classes/class-core.php:452
198
- msgid "No Events found in Trash"
199
- msgstr ""
200
-
201
- #: classes/class-core.php:481
202
- #: classes/class-core.php:492
203
- #: classes/class-hooks.php:212
204
- #: classes/widgets/class-mp-timetable-elementor-widget.php:116
205
- #: templates/popup/index.php:5
206
- #: media/js/blocks/dist/index.js:1
207
- msgid "Columns"
208
- msgstr ""
209
-
210
- #: classes/class-core.php:482
211
- #: classes/class-shortcode.php:255
212
- #: templates/events/event-data.php:4
213
- msgid "Column"
214
- msgstr ""
215
-
216
- #: classes/class-core.php:483
217
- #: classes/class-core.php:484
218
- msgid "Add New Column"
219
- msgstr ""
220
-
221
- #: classes/class-core.php:485
222
- msgid "Edit Column"
223
- msgstr ""
224
-
225
- #: classes/class-core.php:486
226
- msgid "New Column"
227
- msgstr ""
228
-
229
- #: classes/class-core.php:487
230
- msgid "All Columns"
231
- msgstr ""
232
-
233
- #: classes/class-core.php:488
234
- msgid "View Column"
235
- msgstr ""
236
-
237
- #: classes/class-core.php:489
238
- msgid "Search Column"
239
- msgstr ""
240
-
241
- #: classes/class-core.php:490
242
- msgid "No Columns found"
243
- msgstr ""
244
-
245
- #: classes/class-core.php:491
246
- msgid "No Columns found in Trash"
247
- msgstr ""
248
-
249
- #: classes/class-core.php:590
250
- #: classes/class-offer.php:174
251
- msgid "Install Plugin"
252
- msgstr ""
253
-
254
- #: classes/class-core.php:591
255
- #: classes/class-offer.php:163
256
- msgid "Activated"
257
- msgstr ""
258
-
259
- #: classes/class-core.php:592
260
- #: classes/class-offer.php:160
261
- msgid "Active"
262
- msgstr ""
263
-
264
- #: classes/class-core.php:593
265
- #: classes/class-offer.php:165
266
- msgid "Inactive"
267
- msgstr ""
268
-
269
- #: classes/class-core.php:594
270
- msgid "Loading..."
271
- msgstr ""
272
-
273
- #: classes/class-core.php:595
274
- #: classes/class-offer.php:168
275
- msgid "Activate"
276
- msgstr ""
277
-
278
- #: classes/class-hooks.php:81
279
- msgid "Timetable Sidebar"
280
- msgstr ""
281
-
282
- #: classes/class-hooks.php:83
283
- #: classes/class-hooks.php:200
284
- #: classes/class-shortcode.php:371
285
- #: classes/widgets/class-mp-timetable-elementor-widget.php:21
286
- #: media/js/blocks/dist/index.js:1
287
- msgid "Timetable"
288
- msgstr ""
289
-
290
- #: classes/class-hooks.php:191
291
- msgid "Import Timetable events, categories, tags and images."
292
- msgstr ""
293
-
294
- #: classes/class-hooks.php:208
295
- msgid "Add Event"
296
- msgstr ""
297
-
298
- #: classes/class-hooks.php:216
299
- msgid "Add Column"
300
- msgstr ""
301
-
302
- #: classes/class-hooks.php:220
303
- msgid "Event Categories"
304
- msgstr ""
305
-
306
- #: classes/class-hooks.php:224
307
- msgid "Event Tags"
308
- msgstr ""
309
-
310
- #: classes/class-hooks.php:228
311
- #: classes/modules/class-post.php:41
312
- #: classes/widgets/class-mp-timetable-elementor-widget.php:89
313
- #: media/js/blocks/dist/index.js:1
314
- msgid "Settings"
315
- msgstr ""
316
-
317
- #: classes/class-hooks.php:232
318
- msgid "Export / Import"
319
- msgstr ""
320
-
321
- #: classes/class-hooks.php:236
322
- msgid "Help & Shortcode"
323
- msgstr ""
324
-
325
- #: classes/class-hooks.php:300
326
- msgid "Quick Start Guide"
327
- msgstr ""
328
-
329
- #: classes/class-hooks.php:301
330
- msgid "Help"
331
- msgstr ""
332
-
333
- #: classes/class-hooks.php:302
334
- msgid "Leave a Review"
335
- msgstr ""
336
-
337
- #: classes/class-offer.php:13
338
- msgid "Could not activate the plugin."
339
- msgstr ""
340
-
341
- #: classes/class-offer.php:43
342
- #: classes/class-offer.php:106
343
- msgid "Could not install the plugin."
344
- msgstr ""
345
-
346
- #: classes/class-offer.php:47
347
- msgid "Sorry, you are not allowed to install plugins on this site."
348
- msgstr ""
349
-
350
- #: classes/class-offer.php:171
351
- msgid "Not Installed"
352
- msgstr ""
353
-
354
- #: classes/class-permalinks.php:26
355
- msgid "Timetable Permalinks"
356
- msgstr ""
357
-
358
- #: classes/class-permalinks.php:30
359
- msgid "Column base"
360
- msgstr ""
361
-
362
- #: classes/class-permalinks.php:37
363
- msgid "Event base"
364
- msgstr ""
365
-
366
- #: classes/class-permalinks.php:44
367
- msgid "Event Category base"
368
- msgstr ""
369
-
370
- #: classes/class-permalinks.php:51
371
- msgid "Event Tag base"
372
- msgstr ""
373
-
374
- #: classes/class-shortcode.php:270
375
- msgid "Hour measure"
376
- msgstr ""
377
-
378
- #: classes/class-shortcode.php:271
379
- #: classes/widgets/class-mp-timetable-elementor-widget.php:267
380
- #: templates/popup/index.php:71
381
- #: media/js/blocks/dist/index.js:1
382
- msgid "Hour (1h)"
383
- msgstr ""
384
-
385
- #: classes/class-shortcode.php:271
386
- #: classes/widgets/class-mp-timetable-elementor-widget.php:268
387
- #: templates/popup/index.php:72
388
- #: media/js/blocks/dist/index.js:1
389
- msgid "Half hour (30min)"
390
- msgstr ""
391
-
392
- #: classes/class-shortcode.php:271
393
- #: classes/widgets/class-mp-timetable-elementor-widget.php:269
394
- #: templates/popup/index.php:73
395
- #: media/js/blocks/dist/index.js:1
396
- msgid "Quarter hour (15min)"
397
- msgstr ""
398
-
399
- #: classes/class-shortcode.php:275
400
- msgid "Filter style"
401
- msgstr ""
402
-
403
- #: classes/class-shortcode.php:276
404
- #: media/js/blocks/dist/index.js:1
405
- msgid "Dropdown list"
406
- msgstr ""
407
-
408
- #: classes/class-shortcode.php:276
409
- #: classes/widgets/class-mp-timetable-elementor-widget.php:283
410
- #: templates/popup/index.php:82
411
- #: media/js/blocks/dist/index.js:1
412
- msgid "Tabs"
413
- msgstr ""
414
-
415
- #: classes/class-shortcode.php:280
416
- #: classes/widgets/class-mp-timetable-elementor-widget.php:291
417
- #: templates/popup/index.php:88
418
- #: media/js/blocks/dist/index.js:1
419
- msgid "Order of items in filter"
420
- msgstr ""
421
-
422
- #: classes/class-shortcode.php:281
423
- #: classes/class-shortcode.php:367
424
- #: classes/widgets/class-mp-timetable-elementor-widget.php:296
425
- #: classes/widgets/class-mp-timetable-elementor-widget.php:311
426
- #: templates/popup/index.php:91
427
- #: templates/popup/index.php:172
428
- #: media/js/blocks/dist/index.js:1
429
- msgid "Default"
430
- msgstr ""
431
-
432
- #: classes/class-shortcode.php:281
433
- #: classes/widgets/class-mp-timetable-elementor-widget.php:297
434
- #: templates/popup/index.php:92
435
- #: media/js/blocks/dist/index.js:1
436
- msgid "Menu Order"
437
- msgstr ""
438
-
439
- #: classes/class-shortcode.php:281
440
- #: classes/class-shortcode.php:306
441
- #: classes/widgets/class-mp-timetable-elementor-widget.php:151
442
- #: classes/widgets/class-mp-timetable-elementor-widget.php:298
443
- #: templates/popup/index.php:40
444
- #: templates/popup/index.php:93
445
- #: templates/widgets/gallery-list.php:3
446
- #: media/js/blocks/dist/index.js:1
447
- msgid "Title"
448
- msgstr ""
449
-
450
- #: classes/class-shortcode.php:285
451
- msgid "Filter label"
452
- msgstr ""
453
-
454
- #: classes/class-shortcode.php:290
455
- msgid "Hide 'All Events' view"
456
- msgstr ""
457
-
458
- #: classes/class-shortcode.php:291
459
- #: classes/class-shortcode.php:296
460
- #: classes/class-shortcode.php:301
461
- #: classes/class-shortcode.php:308
462
- #: classes/class-shortcode.php:314
463
- #: classes/class-shortcode.php:320
464
- #: classes/class-shortcode.php:326
465
- #: classes/class-shortcode.php:332
466
- #: classes/class-shortcode.php:337
467
- #: classes/class-shortcode.php:361
468
- #: templates/events/metabox-event-options.php:45
469
- #: templates/popup/index.php:108
470
- #: templates/popup/index.php:117
471
- #: templates/popup/index.php:127
472
- #: templates/popup/index.php:135
473
- #: templates/popup/index.php:144
474
- #: templates/widgets/gallery-list.php:63
475
- #: media/js/blocks/dist/index.js:1
476
- msgid "No"
477
- msgstr ""
478
-
479
- #: classes/class-shortcode.php:291
480
- #: classes/class-shortcode.php:296
481
- #: classes/class-shortcode.php:301
482
- #: classes/class-shortcode.php:308
483
- #: classes/class-shortcode.php:314
484
- #: classes/class-shortcode.php:320
485
- #: classes/class-shortcode.php:326
486
- #: classes/class-shortcode.php:332
487
- #: classes/class-shortcode.php:337
488
- #: classes/class-shortcode.php:361
489
- #: templates/events/metabox-event-options.php:46
490
- #: templates/popup/index.php:109
491
- #: templates/popup/index.php:118
492
- #: templates/popup/index.php:126
493
- #: templates/popup/index.php:136
494
- #: templates/popup/index.php:145
495
- #: templates/widgets/gallery-list.php:65
496
- #: media/js/blocks/dist/index.js:1
497
- msgid "Yes"
498
- msgstr ""
499
-
500
- #: classes/class-shortcode.php:295
501
- msgid "Hide first (hours) column"
502
- msgstr ""
503
-
504
- #: classes/class-shortcode.php:300
505
- msgid "Hide empty rows"
506
- msgstr ""
507
-
508
- #: classes/class-shortcode.php:312
509
- #: classes/widgets/class-mp-timetable-elementor-widget.php:162
510
- #: templates/popup/index.php:41
511
- #: media/js/blocks/dist/index.js:1
512
- msgid "Time"
513
- msgstr ""
514
-
515
- #: classes/class-shortcode.php:318
516
- #: classes/widgets/class-mp-timetable-elementor-widget.php:173
517
- #: templates/popup/index.php:42
518
- #: media/js/blocks/dist/index.js:1
519
- msgid "Subtitle"
520
- msgstr ""
521
-
522
- #: classes/class-shortcode.php:324
523
- #: classes/widgets/class-mp-timetable-elementor-widget.php:184
524
- #: templates/events/event-data.php:7
525
- #: templates/popup/index.php:43
526
- #: media/js/blocks/dist/index.js:1
527
- msgid "Description"
528
- msgstr ""
529
-
530
- #: classes/class-shortcode.php:330
531
- msgid "User"
532
- msgstr ""
533
-
534
- #: classes/class-shortcode.php:336
535
- msgid "Disable event URL"
536
- msgstr ""
537
-
538
- #: classes/class-shortcode.php:341
539
- msgid "Text align"
540
- msgstr ""
541
-
542
- #: classes/class-shortcode.php:342
543
- #: classes/widgets/class-mp-timetable-elementor-widget.php:346
544
- #: templates/popup/index.php:152
545
- #: media/js/blocks/dist/index.js:1
546
- msgid "center"
547
- msgstr ""
548
-
549
- #: classes/class-shortcode.php:342
550
- #: classes/widgets/class-mp-timetable-elementor-widget.php:342
551
- #: templates/popup/index.php:153
552
- #: media/js/blocks/dist/index.js:1
553
- msgid "left"
554
- msgstr ""
555
-
556
- #: classes/class-shortcode.php:342
557
- #: classes/widgets/class-mp-timetable-elementor-widget.php:350
558
- #: templates/popup/index.php:154
559
- #: media/js/blocks/dist/index.js:1
560
- msgid "right"
561
- msgstr ""
562
-
563
- #: classes/class-shortcode.php:346
564
- msgid "Id"
565
- msgstr ""
566
-
567
- #: classes/class-shortcode.php:350
568
- msgid "Row height (in px)"
569
- msgstr ""
570
-
571
- #: classes/class-shortcode.php:355
572
- msgid "Base Font Size"
573
- msgstr ""
574
-
575
- #: classes/class-shortcode.php:360
576
- msgid "Responsive"
577
- msgstr ""
578
-
579
- #: classes/class-shortcode.php:366
580
- #: classes/widgets/class-mp-timetable-elementor-widget.php:306
581
- #: templates/popup/index.php:169
582
- #: media/js/blocks/dist/index.js:1
583
- msgid "Column width"
584
- msgstr ""
585
-
586
- #: classes/class-shortcode.php:367
587
- #: classes/widgets/class-mp-timetable-elementor-widget.php:312
588
- #: templates/popup/index.php:173
589
- #: media/js/blocks/dist/index.js:1
590
- msgid "Auto"
591
- msgstr ""
592
-
593
- #: classes/class-shortcode.php:367
594
- #: classes/widgets/class-mp-timetable-elementor-widget.php:313
595
- #: templates/popup/index.php:174
596
- #: media/js/blocks/dist/index.js:1
597
- msgid "Fixed"
598
- msgstr ""
599
-
600
- #: classes/controllers/class-controller-settings.php:70
601
- msgid "Settings saved."
602
- msgstr ""
603
-
604
- #: classes/libs/parsers.php:44
605
- #: classes/libs/parsers.php:74
606
- #: classes/libs/parsers.php:82
607
- msgid "There was an error when reading this WXR file"
608
- msgstr ""
609
-
610
- #: classes/libs/parsers.php:45
611
- msgid "Details are shown above. The importer will now try again with a different parser..."
612
- msgstr ""
613
-
614
- #: classes/libs/parsers.php:86
615
- #: classes/libs/parsers.php:91
616
- #: classes/libs/parsers.php:304
617
- #: classes/libs/parsers.php:565
618
- msgid "This does not appear to be a WXR file, missing/invalid WXR version number"
619
- msgstr ""
620
-
621
- #: classes/models/class-column.php:42
622
- #: classes/modules/class-post.php:40
623
- msgid "Timeslots"
624
- msgstr ""
625
-
626
- #: classes/models/class-events.php:181
627
- msgid "Tags"
628
- msgstr ""
629
-
630
- #: classes/models/class-events.php:182
631
- msgid "Categories"
632
- msgstr ""
633
-
634
- #: classes/models/class-events.php:793
635
- msgid "Duplicate"
636
- msgstr ""
637
-
638
- #: classes/models/class-events.php:814
639
- msgid "A post type mismatch has been detected."
640
- msgstr ""
641
-
642
- #: classes/models/class-events.php:814
643
- msgid "Sorry, you are not allowed to edit this item."
644
- msgstr ""
645
-
646
- #. translators: New post title of the duplicated post
647
- #: classes/models/class-events.php:838
648
- msgid "%s - Copy"
649
- msgstr ""
650
-
651
- #: classes/models/class-import.php:125
652
- msgid "Assign Authors"
653
- msgstr ""
654
-
655
- #: classes/models/class-import.php:126
656
- msgid "To make it easier for you to edit and save the imported content, you may want to reassign the author of the imported item to an existing user of this site. For example, you may want to import all the entries as <code>admin</code>s entries."
657
- msgstr ""
658
-
659
- #: classes/models/class-import.php:128
660
- msgid "If a new user is created by WordPress, a new password will be randomly generated and the new user&#8217;s role will be set as %s. Manually changing the new user&#8217;s details will be necessary."
661
- msgstr ""
662
-
663
- #: classes/models/class-import.php:138
664
- msgid "Import Attachments"
665
- msgstr ""
666
-
667
- #: classes/models/class-import.php:141
668
- msgid "Download and import file attachments"
669
- msgstr ""
670
-
671
- #: classes/models/class-import.php:145
672
- msgid "Submit"
673
- msgstr ""
674
-
675
- #: classes/models/class-import.php:158
676
- msgid "Import author:"
677
- msgstr ""
678
-
679
- #: classes/models/class-import.php:169
680
- msgid "or create new user with login name:"
681
- msgstr ""
682
-
683
- #: classes/models/class-import.php:172
684
- msgid "as a new user:"
685
- msgstr ""
686
-
687
- #: classes/models/class-import.php:180
688
- msgid "assign posts to an existing user:"
689
- msgstr ""
690
-
691
- #: classes/models/class-import.php:182
692
- msgid "or assign posts to an existing user:"
693
- msgstr ""
694
-
695
- #: classes/models/class-import.php:183
696
- #: templates/column/metabox-column-options.php:23
697
- msgid "- Select -"
698
- msgstr ""
699
-
700
- #: classes/models/class-import.php:269
701
- msgid "All done."
702
- msgstr ""
703
-
704
- #: classes/models/class-import.php:269
705
- msgid "Have fun!"
706
- msgstr ""
707
-
708
- #: classes/models/class-import.php:270
709
- msgid "Remember to update the passwords and roles of imported users."
710
- msgstr ""
711
-
712
- #: classes/models/class-import.php:286
713
- msgid "Fetching attachments is not enabled"
714
- msgstr ""
715
-
716
- #: classes/models/class-import.php:299
717
- msgid "Invalid file type"
718
- msgstr ""
719
-
720
- #: classes/models/class-import.php:379
721
- msgid "Remote server did not respond"
722
- msgstr ""
723
-
724
- #: classes/models/class-import.php:385
725
- msgid "Remote server returned error response %1$d %2$s"
726
- msgstr ""
727
-
728
- #: classes/models/class-import.php:394
729
- msgid "Remote file is incorrect size"
730
- msgstr ""
731
-
732
- #: classes/models/class-import.php:399
733
- msgid "Zero size file downloaded"
734
- msgstr ""
735
-
736
- #: classes/models/class-import.php:405
737
- msgid "Remote file is too large, limit is %s"
738
- msgstr ""
739
-
740
- #: classes/models/class-import.php:422
741
- #: classes/models/class-import.php:426
742
- #: classes/models/class-import.php:436
743
- msgid "Sorry, there has been an error."
744
- msgstr ""
745
-
746
- #: classes/models/class-import.php:427
747
- msgid "The export file could not be found at <code>%s</code>. It is likely that this was caused by a permissions problem."
748
- msgstr ""
749
-
750
- #: classes/models/class-import.php:444
751
- msgid "This WXR file (version %s) may not be supported by this version of the importer. Please consider updating."
752
- msgstr ""
753
-
754
- #: classes/models/class-import.php:501
755
- msgid "Failed to import author %s. Their posts will be attributed to the current user."
756
- msgstr ""
757
-
758
- #: classes/models/class-import.php:558
759
- msgid "Failed to create new user for %s. Their posts will be attributed to the current user."
760
- msgstr ""
761
-
762
- #: classes/models/class-import.php:609
763
- #: classes/models/class-import.php:766
764
- msgid "Failed to import %s %s"
765
- msgstr ""
766
-
767
- #: classes/models/class-import.php:656
768
- msgid "Failed to import &#8220;%s&#8221;: Invalid post type %s"
769
- msgstr ""
770
-
771
- #: classes/models/class-import.php:673
772
- msgid "%s &#8220;%s&#8221; already exists."
773
- msgstr ""
774
-
775
- #: classes/models/class-import.php:732
776
- msgid "Failed to import %s &#8220;%s&#8221;"
777
- msgstr ""
778
-
779
- #: classes/modules/class-post.php:42
780
- msgid "Column Type"
781
- msgstr ""
782
-
783
- #: classes/widgets/class-mp-timetable-elementor-widget.php:97
784
- #: templates/popup/index.php:98
785
- #: media/js/blocks/dist/index.js:1
786
- msgid "Filter title to display all events"
787
- msgstr ""
788
-
789
- #: classes/widgets/class-mp-timetable-elementor-widget.php:107
790
- #: templates/popup/index.php:104
791
- #: media/js/blocks/dist/index.js:1
792
- msgid "Hide 'All Events' option"
793
- msgstr ""
794
-
795
- #: classes/widgets/class-mp-timetable-elementor-widget.php:128
796
- #: templates/popup/index.php:16
797
- #: media/js/blocks/dist/index.js:1
798
- msgid "Specific events"
799
- msgstr ""
800
-
801
- #: classes/widgets/class-mp-timetable-elementor-widget.php:153
802
- #: classes/widgets/class-mp-timetable-elementor-widget.php:164
803
- #: classes/widgets/class-mp-timetable-elementor-widget.php:175
804
- #: classes/widgets/class-mp-timetable-elementor-widget.php:186
805
- #: classes/widgets/class-mp-timetable-elementor-widget.php:197
806
- msgid "Hide"
807
- msgstr ""
808
-
809
- #: classes/widgets/class-mp-timetable-elementor-widget.php:154
810
- #: classes/widgets/class-mp-timetable-elementor-widget.php:165
811
- #: classes/widgets/class-mp-timetable-elementor-widget.php:176
812
- #: classes/widgets/class-mp-timetable-elementor-widget.php:187
813
- #: classes/widgets/class-mp-timetable-elementor-widget.php:198
814
- msgid "Show"
815
- msgstr ""
816
-
817
- #. translators: Head means the leader of the event.
818
- #: classes/widgets/class-mp-timetable-elementor-widget.php:195
819
- #: templates/popup/index.php:47
820
- #: media/js/blocks/dist/index.js:1
821
- msgid "Event Head"
822
- msgstr ""
823
-
824
- #: classes/widgets/class-mp-timetable-elementor-widget.php:206
825
- #: templates/popup/index.php:114
826
- #: media/js/blocks/dist/index.js:1
827
- msgid "Hide column with hours"
828
- msgstr ""
829
-
830
- #: classes/widgets/class-mp-timetable-elementor-widget.php:215
831
- #: templates/popup/index.php:123
832
- #: media/js/blocks/dist/index.js:1
833
- msgid "Do not display empty rows"
834
- msgstr ""
835
-
836
- #: classes/widgets/class-mp-timetable-elementor-widget.php:224
837
- #: templates/popup/index.php:132
838
- #: media/js/blocks/dist/index.js:1
839
- msgid "Merge cells with common events"
840
- msgstr ""
841
-
842
- #: classes/widgets/class-mp-timetable-elementor-widget.php:233
843
- #: templates/popup/index.php:141
844
- #: templates/widgets/gallery-list.php:59
845
- #: media/js/blocks/dist/index.js:1
846
- msgid "Disable event link"
847
- msgstr ""
848
-
849
- #: classes/widgets/class-mp-timetable-elementor-widget.php:242
850
- #: templates/popup/index.php:61
851
- #: media/js/blocks/dist/index.js:1
852
- msgid "Base font size"
853
- msgstr ""
854
-
855
- #: classes/widgets/class-mp-timetable-elementor-widget.php:245
856
- #: templates/popup/index.php:64
857
- #: media/js/blocks/dist/index.js:1
858
- msgid "Base font size for the table. Example 12px, 2em, 80%."
859
- msgstr ""
860
-
861
- #: classes/widgets/class-mp-timetable-elementor-widget.php:253
862
- #: templates/popup/index.php:54
863
- #: media/js/blocks/dist/index.js:1
864
- msgid "Block height in pixels"
865
- msgstr ""
866
-
867
- #: classes/widgets/class-mp-timetable-elementor-widget.php:262
868
- #: templates/popup/index.php:68
869
- #: media/js/blocks/dist/index.js:1
870
- msgid "Time frame for event"
871
- msgstr ""
872
-
873
- #: classes/widgets/class-mp-timetable-elementor-widget.php:277
874
- #: templates/popup/index.php:78
875
- #: media/js/blocks/dist/index.js:1
876
- msgid "Filter events style"
877
- msgstr ""
878
-
879
- #: classes/widgets/class-mp-timetable-elementor-widget.php:282
880
- #: templates/popup/index.php:81
881
- msgid "Dropdown"
882
- msgstr ""
883
-
884
- #: classes/widgets/class-mp-timetable-elementor-widget.php:321
885
- #: templates/popup/index.php:192
886
- #: media/js/blocks/dist/index.js:1
887
- msgid "Mobile behavior"
888
- msgstr ""
889
-
890
- #: classes/widgets/class-mp-timetable-elementor-widget.php:326
891
- #: templates/popup/index.php:196
892
- #: media/js/blocks/dist/index.js:1
893
- msgid "Table"
894
- msgstr ""
895
-
896
- #: classes/widgets/class-mp-timetable-elementor-widget.php:327
897
- #: templates/popup/index.php:195
898
- #: media/js/blocks/dist/index.js:1
899
- msgid "List"
900
- msgstr ""
901
-
902
- #: classes/widgets/class-mp-timetable-elementor-widget.php:336
903
- #: templates/popup/index.php:150
904
- #: media/js/blocks/dist/index.js:1
905
- msgid "Horizontal align"
906
- msgstr ""
907
-
908
- #: classes/widgets/class-mp-timetable-elementor-widget.php:361
909
- #: templates/popup/index.php:159
910
- #: media/js/blocks/dist/index.js:1
911
- msgid "Vertical align"
912
- msgstr ""
913
-
914
- #: classes/widgets/class-mp-timetable-elementor-widget.php:367
915
- #: templates/popup/index.php:161
916
- msgid "default"
917
- msgstr ""
918
-
919
- #: classes/widgets/class-mp-timetable-elementor-widget.php:371
920
- #: templates/popup/index.php:162
921
- #: media/js/blocks/dist/index.js:1
922
- msgid "top"
923
- msgstr ""
924
-
925
- #: classes/widgets/class-mp-timetable-elementor-widget.php:375
926
- #: templates/popup/index.php:163
927
- #: media/js/blocks/dist/index.js:1
928
- msgid "middle"
929
- msgstr ""
930
-
931
- #: classes/widgets/class-mp-timetable-elementor-widget.php:379
932
- #: templates/popup/index.php:164
933
- #: media/js/blocks/dist/index.js:1
934
- msgid "bottom"
935
- msgstr ""
936
-
937
- #: classes/widgets/class-mp-timetable-elementor-widget.php:389
938
- #: templates/popup/index.php:179
939
- #: media/js/blocks/dist/index.js:1
940
- msgid "Unique ID"
941
- msgstr ""
942
-
943
- #: classes/widgets/class-mp-timetable-elementor-widget.php:392
944
- #: templates/popup/index.php:182
945
- #: media/js/blocks/dist/index.js:1
946
- msgid "If you use more than one table on a page specify the unique ID for a timetable. It is usually all lowercase and contains only letters, numbers, and hyphens."
947
- msgstr ""
948
-
949
- #: classes/widgets/class-mp-timetable-elementor-widget.php:401
950
- #: templates/popup/index.php:186
951
- #: media/js/blocks/dist/index.js:1
952
- msgid "CSS class"
953
- msgstr ""
954
-
955
- #: classes/widgets/class-mp-timetable-widget.php:22
956
- msgid "Display upcoming events."
957
- msgstr ""
958
-
959
- #: classes/widgets/class-mp-timetable-widget.php:24
960
- msgid "Timetable Events"
961
- msgstr ""
962
-
963
- #: templates-functions/actions-mp-event-functions.php:27
964
- #: templates/theme/event-timeslots.php:7
965
- msgid "Event Timeslots (%s)"
966
- msgstr ""
967
-
968
- #: templates/column/metabox-column-options.php:11
969
- msgid "Simple Column"
970
- msgstr ""
971
-
972
- #: templates/column/metabox-column-options.php:20
973
- msgid "Day of the week"
974
- msgstr ""
975
-
976
- #: templates/column/metabox-column-options.php:24
977
- msgid "Sunday"
978
- msgstr ""
979
-
980
- #: templates/column/metabox-column-options.php:25
981
- msgid "Monday"
982
- msgstr ""
983
-
984
- #: templates/column/metabox-column-options.php:26
985
- msgid "Tuesday"
986
- msgstr ""
987
-
988
- #: templates/column/metabox-column-options.php:27
989
- msgid "Wednesday"
990
- msgstr ""
991
-
992
- #: templates/column/metabox-column-options.php:28
993
- msgid "Thursday"
994
- msgstr ""
995
-
996
- #: templates/column/metabox-column-options.php:29
997
- msgid "Friday"
998
- msgstr ""
999
-
1000
- #: templates/column/metabox-column-options.php:30
1001
- msgid "Saturday"
1002
- msgstr ""
1003
-
1004
- #: templates/column/metabox-column-options.php:39
1005
- msgid "Date"
1006
- msgstr ""
1007
-
1008
- #: templates/events/event-data.php:5
1009
- msgid "Start"
1010
- msgstr ""
1011
-
1012
- #: templates/events/event-data.php:6
1013
- msgid "End"
1014
- msgstr ""
1015
-
1016
- #. translators: Head means the leader of the event.
1017
- #: templates/events/event-data.php:10
1018
- msgid "Head"
1019
- msgstr ""
1020
-
1021
- #: templates/events/event-data.php:12
1022
- msgid "Actions"
1023
- msgstr ""
1024
-
1025
- #: templates/events/event-data.php:35
1026
- msgid "Edit event in the form below"
1027
- msgstr ""
1028
-
1029
- #: templates/events/event-data.php:36
1030
- msgid "Delete"
1031
- msgstr ""
1032
-
1033
- #: templates/events/metabox-event-data.php:10
1034
- msgid "Add New / Edit Timeslot"
1035
- msgstr ""
1036
-
1037
- #: templates/events/metabox-event-data.php:13
1038
- msgid "Column:"
1039
- msgstr ""
1040
-
1041
- #: templates/events/metabox-event-data.php:21
1042
- msgid "Select column or <a target=\"_blank\" href=\"%s\">Add New</a>."
1043
- msgstr ""
1044
-
1045
- #: templates/events/metabox-event-data.php:23
1046
- msgid "No columns found. <a href=\"%s\">Create at least one column first.</a>"
1047
- msgstr ""
1048
-
1049
- #: templates/events/metabox-event-data.php:29
1050
- msgid "Start Time:"
1051
- msgstr ""
1052
-
1053
- #: templates/events/metabox-event-data.php:32
1054
- #: templates/events/metabox-event-data.php:39
1055
- msgid "hh:mm"
1056
- msgstr ""
1057
-
1058
- #: templates/events/metabox-event-data.php:36
1059
- msgid "End Time:"
1060
- msgstr ""
1061
-
1062
- #: templates/events/metabox-event-data.php:43
1063
- msgid "Description:"
1064
- msgstr ""
1065
-
1066
- #. translators: Head means the leader of the event.
1067
- #: templates/events/metabox-event-data.php:49
1068
- msgid "Event Head:"
1069
- msgstr ""
1070
-
1071
- #: templates/events/metabox-event-data.php:58
1072
- msgid "none"
1073
- msgstr ""
1074
-
1075
- #. translators: Button to add a new event.
1076
- #: templates/events/metabox-event-data.php:83
1077
- msgid "Add New"
1078
- msgstr ""
1079
-
1080
- #: templates/events/metabox-event-options.php:4
1081
- msgid "Event Subtitle:"
1082
- msgstr ""
1083
-
1084
- #: templates/events/metabox-event-options.php:8
1085
- msgid "Background Color:"
1086
- msgstr ""
1087
-
1088
- #: templates/events/metabox-event-options.php:15
1089
- msgid "Background Hover Color:"
1090
- msgstr ""
1091
-
1092
- #: templates/events/metabox-event-options.php:22
1093
- msgid "Text Color:"
1094
- msgstr ""
1095
-
1096
- #: templates/events/metabox-event-options.php:29
1097
- msgid "Text Hover Color:"
1098
- msgstr ""
1099
-
1100
- #: templates/events/metabox-event-options.php:36
1101
- msgid "Custom Event URL:"
1102
- msgstr ""
1103
-
1104
- #: templates/events/metabox-event-options.php:42
1105
- msgid "Disable link to this event:"
1106
- msgstr ""
1107
-
1108
- #: templates/popup/index.php:12
1109
- #: templates/popup/index.php:23
1110
- #: templates/popup/index.php:34
1111
- #: templates/widgets/gallery-list.php:48
1112
- #: media/js/blocks/dist/index.js:1
1113
- msgid "Hold the Ctrl or Command key to select/deselect multiple options."
1114
- msgstr ""
1115
-
1116
- #: templates/popup/index.php:38
1117
- msgid "Fields to display:"
1118
- msgstr ""
1119
-
1120
- #: templates/popup/index.php:50
1121
- msgid "Check the event parameter(s) to be displayed in the timetable."
1122
- msgstr ""
1123
-
1124
- #: templates/popup/index.php:57
1125
- msgid "Set height of the block"
1126
- msgstr ""
1127
-
1128
- #: templates/popup/index.php:83
1129
- msgid "None"
1130
- msgstr ""
1131
-
1132
- #: templates/popup/index.php:198
1133
- msgid "Tick \"List\" to display events in a list view on mobile devices. Tick \"Table\" to display events in a table."
1134
- msgstr ""
1135
-
1136
- #: templates/popup/index.php:204
1137
- msgid "Add Timetable"
1138
- msgstr ""
1139
-
1140
- #: templates/settings/general.php:2
1141
- msgid "General Settings"
1142
- msgstr ""
1143
-
1144
- #: templates/settings/general.php:10
1145
- msgid "Template Mode"
1146
- msgstr ""
1147
-
1148
- #: templates/settings/general.php:14
1149
- msgid "Theme Mode"
1150
- msgstr ""
1151
-
1152
- #: templates/settings/general.php:15
1153
- msgid "Developer Mode"
1154
- msgstr ""
1155
-
1156
- #: templates/settings/general.php:17
1157
- msgid "Choose Theme Mode to display the content with the styles of your theme. Choose Developer Mode to control appearance of the content with custom page templates, actions and filters."
1158
- msgstr ""
1159
-
1160
- #: templates/settings/general.php:17
1161
- msgid "This option can't be changed if your theme is initially integrated with the plugin."
1162
- msgstr ""
1163
-
1164
- #: templates/settings/general.php:24
1165
- msgid "Permalink Settings"
1166
- msgstr ""
1167
-
1168
- #: templates/settings/general.php:25
1169
- msgid "Configure permalink settings in <a href=\"%s\">Settings > Permalinks</a>"
1170
- msgstr ""
1171
-
1172
- #: templates/settings/general.php:30
1173
- msgid "Save"
1174
- msgstr ""
1175
-
1176
- #: templates/shortcodes/empty-search-events.php:1
1177
- #: templates/theme/widget-upcoming-view.php:57
1178
- #: templates/widgets/widget-view.php:97
1179
- msgid "no events found"
1180
- msgstr ""
1181
-
1182
- #: templates/templates-actions/action-sidebar.php:8
1183
- #: templates/widgets/gallery-list.php:14
1184
- msgid "Today upcoming events"
1185
- msgstr ""
1186
-
1187
- #: templates/templates-actions/action-sidebar.php:13
1188
- #: templates/widgets/gallery-list.php:16
1189
- msgid "All upcoming events"
1190
- msgstr ""
1191
-
1192
- #: templates/widgets/gallery-list.php:10
1193
- msgid "Events to display"
1194
- msgstr ""
1195
-
1196
- #: templates/widgets/gallery-list.php:18
1197
- msgid "Ongoing events"
1198
- msgstr ""
1199
-
1200
- #: templates/widgets/gallery-list.php:23
1201
- msgid "Input number of days"
1202
- msgstr ""
1203
-
1204
- #: templates/widgets/gallery-list.php:28
1205
- msgid "day"
1206
- msgid_plural "days"
1207
- msgstr[0] ""
1208
- msgstr[1] ""
1209
-
1210
- #: templates/widgets/gallery-list.php:32
1211
- msgid "Event categories. Leave blank to display all."
1212
- msgstr ""
1213
-
1214
- #: templates/widgets/gallery-list.php:52
1215
- msgid "Number of events to display"
1216
- msgstr ""
1217
-
1218
- #: templates/widgets/gallery-list.php:70
1219
- msgid "Custom link for events"
1220
- msgstr ""
1221
-
1222
- #: templates/widgets/gallery-list.php:78
1223
- msgid "Event background color"
1224
- msgstr ""
1225
-
1226
- #: templates/widgets/gallery-list.php:88
1227
- msgid "Event background color on hover"
1228
- msgstr ""
1229
-
1230
- #: templates/widgets/gallery-list.php:98
1231
- msgid "Event text color"
1232
- msgstr ""
1233
-
1234
- #: templates/widgets/gallery-list.php:108
1235
- msgid "Event text color on hover"
1236
- msgstr ""
1237
-
1238
- #: templates/widgets/gallery-list.php:118
1239
- msgid "Event border color"
1240
- msgstr ""
1241
-
1242
- #: templates/widgets/gallery-list.php:128
1243
- msgid "Event border color on hover"
1244
- msgstr ""
1
+ # Copyright (C) 2021 MotoPress
2
+ # This file is distributed under the same license as the Timetable and Event Schedule plugin.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: Timetable and Event Schedule 2.4.1\n"
6
+ "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/mp-timetable\n"
7
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
8
+ "Language-Team: LANGUAGE <LL@li.org>\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "POT-Creation-Date: 2021-08-19T15:15:13+00:00\n"
13
+ "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
+ "X-Generator: WP-CLI 2.4.0\n"
15
+ "X-Domain: mp-timetable\n"
16
+
17
+ #. Plugin Name of the plugin
18
+ msgid "Timetable and Event Schedule"
19
+ msgstr ""
20
+
21
+ #. Plugin URI of the plugin
22
+ msgid "https://motopress.com/products/timetable-event-schedule/"
23
+ msgstr ""
24
+
25
+ #. Description of the plugin
26
+ msgid "Smart time-management tool with a clean minimalist design for featuring your timetables and upcoming events."
27
+ msgstr ""
28
+
29
+ #. Author of the plugin
30
+ msgid "MotoPress"
31
+ msgstr ""
32
+
33
+ #. Author URI of the plugin
34
+ msgid "https://motopress.com"
35
+ msgstr ""
36
+
37
+ #. translators: 1: Timetable and Event Schedule 2:: five stars rating
38
+ #: admin/help/index.php:11
39
+ #: templates/settings/general.php:41
40
+ msgid "If you like %1$s please leave us a %2$s rating."
41
+ msgstr ""
42
+
43
+ #: admin/import/export.php:1
44
+ #: admin/import/export.php:5
45
+ msgid "Export"
46
+ msgstr ""
47
+
48
+ #: admin/import/greet.php:2
49
+ msgid "Choose a WXR (.xml) file to upload, then click Upload file and import."
50
+ msgstr ""
51
+
52
+ #: admin/import/header.php:2
53
+ msgid "Import / Export Timetable Plugin Data"
54
+ msgstr ""
55
+
56
+ #: admin/import/import.php:4
57
+ msgid "Import"
58
+ msgstr ""
59
+
60
+ #: classes/blocks/class-timetable-block.php:102
61
+ #: classes/class-core.php:448
62
+ #: classes/class-shortcode.php:70
63
+ #: classes/class-shortcode.php:286
64
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:100
65
+ #: templates-functions/action-shortcode-functions.php:60
66
+ #: templates-functions/action-shortcode-functions.php:74
67
+ #: templates-functions/action-shortcode-functions.php:75
68
+ msgid "All Events"
69
+ msgstr ""
70
+
71
+ #: classes/class-core.php:337
72
+ #: classes/class-core.php:348
73
+ #: classes/class-core.php:352
74
+ #: classes/class-shortcode.php:265
75
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:139
76
+ #: templates/popup/index.php:27
77
+ #: media/js/blocks/dist/index.js:1
78
+ msgid "Event categories"
79
+ msgstr ""
80
+
81
+ #: classes/class-core.php:338
82
+ msgid "Event category"
83
+ msgstr ""
84
+
85
+ #: classes/class-core.php:339
86
+ #: classes/class-core.php:340
87
+ msgid "Add New Event category"
88
+ msgstr ""
89
+
90
+ #: classes/class-core.php:341
91
+ msgid "Edit Event category"
92
+ msgstr ""
93
+
94
+ #: classes/class-core.php:342
95
+ msgid "New Event category"
96
+ msgstr ""
97
+
98
+ #: classes/class-core.php:343
99
+ msgid "All Event categories"
100
+ msgstr ""
101
+
102
+ #: classes/class-core.php:344
103
+ msgid "View Event category"
104
+ msgstr ""
105
+
106
+ #: classes/class-core.php:345
107
+ msgid "Search Event category"
108
+ msgstr ""
109
+
110
+ #: classes/class-core.php:346
111
+ msgid "No Event categories found"
112
+ msgstr ""
113
+
114
+ #: classes/class-core.php:347
115
+ msgid "No Event categories found in Trash"
116
+ msgstr ""
117
+
118
+ #: classes/class-core.php:381
119
+ #: classes/class-core.php:392
120
+ #: classes/class-core.php:396
121
+ msgid "Event tags"
122
+ msgstr ""
123
+
124
+ #: classes/class-core.php:382
125
+ msgid "Event tag"
126
+ msgstr ""
127
+
128
+ #: classes/class-core.php:383
129
+ #: classes/class-core.php:384
130
+ msgid "Add New Event tag"
131
+ msgstr ""
132
+
133
+ #: classes/class-core.php:385
134
+ msgid "Edit Event tag"
135
+ msgstr ""
136
+
137
+ #: classes/class-core.php:386
138
+ msgid "New Event tag"
139
+ msgstr ""
140
+
141
+ #: classes/class-core.php:387
142
+ msgid "All Event tags"
143
+ msgstr ""
144
+
145
+ #: classes/class-core.php:388
146
+ msgid "View Event tag"
147
+ msgstr ""
148
+
149
+ #: classes/class-core.php:389
150
+ msgid "Search Event tag"
151
+ msgstr ""
152
+
153
+ #: classes/class-core.php:390
154
+ msgid "No Event tags found"
155
+ msgstr ""
156
+
157
+ #: classes/class-core.php:391
158
+ msgid "No Event tags found in Trash"
159
+ msgstr ""
160
+
161
+ #: classes/class-core.php:442
162
+ #: classes/class-core.php:453
163
+ #: classes/class-hooks.php:204
164
+ #: classes/class-shortcode.php:260
165
+ msgid "Events"
166
+ msgstr ""
167
+
168
+ #: classes/class-core.php:443
169
+ msgid "Event"
170
+ msgstr ""
171
+
172
+ #: classes/class-core.php:444
173
+ #: classes/class-core.php:445
174
+ msgid "Add New Event"
175
+ msgstr ""
176
+
177
+ #: classes/class-core.php:446
178
+ msgid "Edit Event"
179
+ msgstr ""
180
+
181
+ #: classes/class-core.php:447
182
+ msgid "New Event"
183
+ msgstr ""
184
+
185
+ #: classes/class-core.php:449
186
+ msgid "View Event"
187
+ msgstr ""
188
+
189
+ #: classes/class-core.php:450
190
+ msgid "Search Event"
191
+ msgstr ""
192
+
193
+ #: classes/class-core.php:451
194
+ msgid "No Events found"
195
+ msgstr ""
196
+
197
+ #: classes/class-core.php:452
198
+ msgid "No Events found in Trash"
199
+ msgstr ""
200
+
201
+ #: classes/class-core.php:481
202
+ #: classes/class-core.php:492
203
+ #: classes/class-hooks.php:212
204
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:116
205
+ #: templates/popup/index.php:5
206
+ #: media/js/blocks/dist/index.js:1
207
+ msgid "Columns"
208
+ msgstr ""
209
+
210
+ #: classes/class-core.php:482
211
+ #: classes/class-shortcode.php:255
212
+ #: templates/events/event-data.php:4
213
+ msgid "Column"
214
+ msgstr ""
215
+
216
+ #: classes/class-core.php:483
217
+ #: classes/class-core.php:484
218
+ msgid "Add New Column"
219
+ msgstr ""
220
+
221
+ #: classes/class-core.php:485
222
+ msgid "Edit Column"
223
+ msgstr ""
224
+
225
+ #: classes/class-core.php:486
226
+ msgid "New Column"
227
+ msgstr ""
228
+
229
+ #: classes/class-core.php:487
230
+ msgid "All Columns"
231
+ msgstr ""
232
+
233
+ #: classes/class-core.php:488
234
+ msgid "View Column"
235
+ msgstr ""
236
+
237
+ #: classes/class-core.php:489
238
+ msgid "Search Column"
239
+ msgstr ""
240
+
241
+ #: classes/class-core.php:490
242
+ msgid "No Columns found"
243
+ msgstr ""
244
+
245
+ #: classes/class-core.php:491
246
+ msgid "No Columns found in Trash"
247
+ msgstr ""
248
+
249
+ #: classes/class-core.php:590
250
+ #: classes/class-offer.php:174
251
+ msgid "Install Plugin"
252
+ msgstr ""
253
+
254
+ #: classes/class-core.php:591
255
+ #: classes/class-offer.php:163
256
+ msgid "Activated"
257
+ msgstr ""
258
+
259
+ #: classes/class-core.php:592
260
+ #: classes/class-offer.php:160
261
+ msgid "Active"
262
+ msgstr ""
263
+
264
+ #: classes/class-core.php:593
265
+ #: classes/class-offer.php:165
266
+ msgid "Inactive"
267
+ msgstr ""
268
+
269
+ #: classes/class-core.php:594
270
+ msgid "Loading..."
271
+ msgstr ""
272
+
273
+ #: classes/class-core.php:595
274
+ #: classes/class-offer.php:168
275
+ msgid "Activate"
276
+ msgstr ""
277
+
278
+ #: classes/class-hooks.php:81
279
+ msgid "Timetable Sidebar"
280
+ msgstr ""
281
+
282
+ #: classes/class-hooks.php:83
283
+ #: classes/class-hooks.php:200
284
+ #: classes/class-shortcode.php:371
285
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:21
286
+ #: media/js/blocks/dist/index.js:1
287
+ msgid "Timetable"
288
+ msgstr ""
289
+
290
+ #: classes/class-hooks.php:191
291
+ msgid "Import Timetable events, categories, tags and images."
292
+ msgstr ""
293
+
294
+ #: classes/class-hooks.php:208
295
+ msgid "Add Event"
296
+ msgstr ""
297
+
298
+ #: classes/class-hooks.php:216
299
+ msgid "Add Column"
300
+ msgstr ""
301
+
302
+ #: classes/class-hooks.php:220
303
+ msgid "Event Categories"
304
+ msgstr ""
305
+
306
+ #: classes/class-hooks.php:224
307
+ msgid "Event Tags"
308
+ msgstr ""
309
+
310
+ #: classes/class-hooks.php:228
311
+ #: classes/modules/class-post.php:41
312
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:89
313
+ #: media/js/blocks/dist/index.js:1
314
+ msgid "Settings"
315
+ msgstr ""
316
+
317
+ #: classes/class-hooks.php:232
318
+ msgid "Export / Import"
319
+ msgstr ""
320
+
321
+ #: classes/class-hooks.php:236
322
+ msgid "Help & Shortcode"
323
+ msgstr ""
324
+
325
+ #: classes/class-hooks.php:300
326
+ msgid "Quick Start Guide"
327
+ msgstr ""
328
+
329
+ #: classes/class-hooks.php:301
330
+ msgid "Help"
331
+ msgstr ""
332
+
333
+ #: classes/class-hooks.php:302
334
+ msgid "Leave a Review"
335
+ msgstr ""
336
+
337
+ #: classes/class-offer.php:13
338
+ msgid "Could not activate the plugin."
339
+ msgstr ""
340
+
341
+ #: classes/class-offer.php:43
342
+ #: classes/class-offer.php:106
343
+ msgid "Could not install the plugin."
344
+ msgstr ""
345
+
346
+ #: classes/class-offer.php:47
347
+ msgid "Sorry, you are not allowed to install plugins on this site."
348
+ msgstr ""
349
+
350
+ #: classes/class-offer.php:171
351
+ msgid "Not Installed"
352
+ msgstr ""
353
+
354
+ #: classes/class-permalinks.php:26
355
+ msgid "Timetable Permalinks"
356
+ msgstr ""
357
+
358
+ #: classes/class-permalinks.php:30
359
+ msgid "Column base"
360
+ msgstr ""
361
+
362
+ #: classes/class-permalinks.php:37
363
+ msgid "Event base"
364
+ msgstr ""
365
+
366
+ #: classes/class-permalinks.php:44
367
+ msgid "Event Category base"
368
+ msgstr ""
369
+
370
+ #: classes/class-permalinks.php:51
371
+ msgid "Event Tag base"
372
+ msgstr ""
373
+
374
+ #: classes/class-shortcode.php:270
375
+ msgid "Hour measure"
376
+ msgstr ""
377
+
378
+ #: classes/class-shortcode.php:271
379
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:267
380
+ #: templates/popup/index.php:71
381
+ #: media/js/blocks/dist/index.js:1
382
+ msgid "Hour (1h)"
383
+ msgstr ""
384
+
385
+ #: classes/class-shortcode.php:271
386
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:268
387
+ #: templates/popup/index.php:72
388
+ #: media/js/blocks/dist/index.js:1
389
+ msgid "Half hour (30min)"
390
+ msgstr ""
391
+
392
+ #: classes/class-shortcode.php:271
393
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:269
394
+ #: templates/popup/index.php:73
395
+ #: media/js/blocks/dist/index.js:1
396
+ msgid "Quarter hour (15min)"
397
+ msgstr ""
398
+
399
+ #: classes/class-shortcode.php:275
400
+ msgid "Filter style"
401
+ msgstr ""
402
+
403
+ #: classes/class-shortcode.php:276
404
+ #: media/js/blocks/dist/index.js:1
405
+ msgid "Dropdown list"
406
+ msgstr ""
407
+
408
+ #: classes/class-shortcode.php:276
409
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:283
410
+ #: templates/popup/index.php:82
411
+ #: media/js/blocks/dist/index.js:1
412
+ msgid "Tabs"
413
+ msgstr ""
414
+
415
+ #: classes/class-shortcode.php:280
416
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:291
417
+ #: templates/popup/index.php:88
418
+ #: media/js/blocks/dist/index.js:1
419
+ msgid "Order of items in filter"
420
+ msgstr ""
421
+
422
+ #: classes/class-shortcode.php:281
423
+ #: classes/class-shortcode.php:367
424
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:296
425
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:311
426
+ #: templates/popup/index.php:91
427
+ #: templates/popup/index.php:172
428
+ #: media/js/blocks/dist/index.js:1
429
+ msgid "Default"
430
+ msgstr ""
431
+
432
+ #: classes/class-shortcode.php:281
433
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:297
434
+ #: templates/popup/index.php:92
435
+ #: media/js/blocks/dist/index.js:1
436
+ msgid "Menu Order"
437
+ msgstr ""
438
+
439
+ #: classes/class-shortcode.php:281
440
+ #: classes/class-shortcode.php:306
441
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:151
442
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:298
443
+ #: templates/popup/index.php:40
444
+ #: templates/popup/index.php:93
445
+ #: templates/widgets/gallery-list.php:3
446
+ #: media/js/blocks/dist/index.js:1
447
+ msgid "Title"
448
+ msgstr ""
449
+
450
+ #: classes/class-shortcode.php:285
451
+ msgid "Filter label"
452
+ msgstr ""
453
+
454
+ #: classes/class-shortcode.php:290
455
+ msgid "Hide 'All Events' view"
456
+ msgstr ""
457
+
458
+ #: classes/class-shortcode.php:291
459
+ #: classes/class-shortcode.php:296
460
+ #: classes/class-shortcode.php:301
461
+ #: classes/class-shortcode.php:308
462
+ #: classes/class-shortcode.php:314
463
+ #: classes/class-shortcode.php:320
464
+ #: classes/class-shortcode.php:326
465
+ #: classes/class-shortcode.php:332
466
+ #: classes/class-shortcode.php:337
467
+ #: classes/class-shortcode.php:361
468
+ #: templates/events/metabox-event-options.php:45
469
+ #: templates/popup/index.php:108
470
+ #: templates/popup/index.php:117
471
+ #: templates/popup/index.php:127
472
+ #: templates/popup/index.php:135
473
+ #: templates/popup/index.php:144
474
+ #: templates/widgets/gallery-list.php:63
475
+ #: media/js/blocks/dist/index.js:1
476
+ msgid "No"
477
+ msgstr ""
478
+
479
+ #: classes/class-shortcode.php:291
480
+ #: classes/class-shortcode.php:296
481
+ #: classes/class-shortcode.php:301
482
+ #: classes/class-shortcode.php:308
483
+ #: classes/class-shortcode.php:314
484
+ #: classes/class-shortcode.php:320
485
+ #: classes/class-shortcode.php:326
486
+ #: classes/class-shortcode.php:332
487
+ #: classes/class-shortcode.php:337
488
+ #: classes/class-shortcode.php:361
489
+ #: templates/events/metabox-event-options.php:46
490
+ #: templates/popup/index.php:109
491
+ #: templates/popup/index.php:118
492
+ #: templates/popup/index.php:126
493
+ #: templates/popup/index.php:136
494
+ #: templates/popup/index.php:145
495
+ #: templates/widgets/gallery-list.php:65
496
+ #: media/js/blocks/dist/index.js:1
497
+ msgid "Yes"
498
+ msgstr ""
499
+
500
+ #: classes/class-shortcode.php:295
501
+ msgid "Hide first (hours) column"
502
+ msgstr ""
503
+
504
+ #: classes/class-shortcode.php:300
505
+ msgid "Hide empty rows"
506
+ msgstr ""
507
+
508
+ #: classes/class-shortcode.php:312
509
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:162
510
+ #: templates/popup/index.php:41
511
+ #: media/js/blocks/dist/index.js:1
512
+ msgid "Time"
513
+ msgstr ""
514
+
515
+ #: classes/class-shortcode.php:318
516
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:173
517
+ #: templates/popup/index.php:42
518
+ #: media/js/blocks/dist/index.js:1
519
+ msgid "Subtitle"
520
+ msgstr ""
521
+
522
+ #: classes/class-shortcode.php:324
523
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:184
524
+ #: templates/events/event-data.php:7
525
+ #: templates/popup/index.php:43
526
+ #: media/js/blocks/dist/index.js:1
527
+ msgid "Description"
528
+ msgstr ""
529
+
530
+ #: classes/class-shortcode.php:330
531
+ msgid "User"
532
+ msgstr ""
533
+
534
+ #: classes/class-shortcode.php:336
535
+ msgid "Disable event URL"
536
+ msgstr ""
537
+
538
+ #: classes/class-shortcode.php:341
539
+ msgid "Text align"
540
+ msgstr ""
541
+
542
+ #: classes/class-shortcode.php:342
543
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:346
544
+ #: templates/popup/index.php:152
545
+ #: media/js/blocks/dist/index.js:1
546
+ msgid "center"
547
+ msgstr ""
548
+
549
+ #: classes/class-shortcode.php:342
550
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:342
551
+ #: templates/popup/index.php:153
552
+ #: media/js/blocks/dist/index.js:1
553
+ msgid "left"
554
+ msgstr ""
555
+
556
+ #: classes/class-shortcode.php:342
557
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:350
558
+ #: templates/popup/index.php:154
559
+ #: media/js/blocks/dist/index.js:1
560
+ msgid "right"
561
+ msgstr ""
562
+
563
+ #: classes/class-shortcode.php:346
564
+ msgid "Id"
565
+ msgstr ""
566
+
567
+ #: classes/class-shortcode.php:350
568
+ msgid "Row height (in px)"
569
+ msgstr ""
570
+
571
+ #: classes/class-shortcode.php:355
572
+ msgid "Base Font Size"
573
+ msgstr ""
574
+
575
+ #: classes/class-shortcode.php:360
576
+ msgid "Responsive"
577
+ msgstr ""
578
+
579
+ #: classes/class-shortcode.php:366
580
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:306
581
+ #: templates/popup/index.php:169
582
+ #: media/js/blocks/dist/index.js:1
583
+ msgid "Column width"
584
+ msgstr ""
585
+
586
+ #: classes/class-shortcode.php:367
587
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:312
588
+ #: templates/popup/index.php:173
589
+ #: media/js/blocks/dist/index.js:1
590
+ msgid "Auto"
591
+ msgstr ""
592
+
593
+ #: classes/class-shortcode.php:367
594
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:313
595
+ #: templates/popup/index.php:174
596
+ #: media/js/blocks/dist/index.js:1
597
+ msgid "Fixed"
598
+ msgstr ""
599
+
600
+ #: classes/controllers/class-controller-settings.php:70
601
+ msgid "Settings saved."
602
+ msgstr ""
603
+
604
+ #: classes/libs/parsers.php:44
605
+ #: classes/libs/parsers.php:74
606
+ #: classes/libs/parsers.php:82
607
+ msgid "There was an error when reading this WXR file"
608
+ msgstr ""
609
+
610
+ #: classes/libs/parsers.php:45
611
+ msgid "Details are shown above. The importer will now try again with a different parser..."
612
+ msgstr ""
613
+
614
+ #: classes/libs/parsers.php:86
615
+ #: classes/libs/parsers.php:91
616
+ #: classes/libs/parsers.php:304
617
+ #: classes/libs/parsers.php:565
618
+ msgid "This does not appear to be a WXR file, missing/invalid WXR version number"
619
+ msgstr ""
620
+
621
+ #: classes/models/class-column.php:42
622
+ #: classes/modules/class-post.php:40
623
+ msgid "Timeslots"
624
+ msgstr ""
625
+
626
+ #: classes/models/class-events.php:181
627
+ msgid "Tags"
628
+ msgstr ""
629
+
630
+ #: classes/models/class-events.php:182
631
+ msgid "Categories"
632
+ msgstr ""
633
+
634
+ #: classes/models/class-events.php:793
635
+ msgid "Duplicate"
636
+ msgstr ""
637
+
638
+ #: classes/models/class-events.php:814
639
+ msgid "A post type mismatch has been detected."
640
+ msgstr ""
641
+
642
+ #: classes/models/class-events.php:814
643
+ msgid "Sorry, you are not allowed to edit this item."
644
+ msgstr ""
645
+
646
+ #. translators: New post title of the duplicated post
647
+ #: classes/models/class-events.php:838
648
+ msgid "%s - Copy"
649
+ msgstr ""
650
+
651
+ #: classes/models/class-import.php:125
652
+ msgid "Assign Authors"
653
+ msgstr ""
654
+
655
+ #: classes/models/class-import.php:126
656
+ msgid "To make it easier for you to edit and save the imported content, you may want to reassign the author of the imported item to an existing user of this site. For example, you may want to import all the entries as <code>admin</code>s entries."
657
+ msgstr ""
658
+
659
+ #: classes/models/class-import.php:128
660
+ msgid "If a new user is created by WordPress, a new password will be randomly generated and the new user&#8217;s role will be set as %s. Manually changing the new user&#8217;s details will be necessary."
661
+ msgstr ""
662
+
663
+ #: classes/models/class-import.php:138
664
+ msgid "Import Attachments"
665
+ msgstr ""
666
+
667
+ #: classes/models/class-import.php:141
668
+ msgid "Download and import file attachments"
669
+ msgstr ""
670
+
671
+ #: classes/models/class-import.php:145
672
+ msgid "Submit"
673
+ msgstr ""
674
+
675
+ #: classes/models/class-import.php:158
676
+ msgid "Import author:"
677
+ msgstr ""
678
+
679
+ #: classes/models/class-import.php:169
680
+ msgid "or create new user with login name:"
681
+ msgstr ""
682
+
683
+ #: classes/models/class-import.php:172
684
+ msgid "as a new user:"
685
+ msgstr ""
686
+
687
+ #: classes/models/class-import.php:180
688
+ msgid "assign posts to an existing user:"
689
+ msgstr ""
690
+
691
+ #: classes/models/class-import.php:182
692
+ msgid "or assign posts to an existing user:"
693
+ msgstr ""
694
+
695
+ #: classes/models/class-import.php:183
696
+ #: templates/column/metabox-column-options.php:23
697
+ msgid "- Select -"
698
+ msgstr ""
699
+
700
+ #: classes/models/class-import.php:269
701
+ msgid "All done."
702
+ msgstr ""
703
+
704
+ #: classes/models/class-import.php:269
705
+ msgid "Have fun!"
706
+ msgstr ""
707
+
708
+ #: classes/models/class-import.php:270
709
+ msgid "Remember to update the passwords and roles of imported users."
710
+ msgstr ""
711
+
712
+ #: classes/models/class-import.php:286
713
+ msgid "Fetching attachments is not enabled"
714
+ msgstr ""
715
+
716
+ #: classes/models/class-import.php:299
717
+ msgid "Invalid file type"
718
+ msgstr ""
719
+
720
+ #: classes/models/class-import.php:379
721
+ msgid "Remote server did not respond"
722
+ msgstr ""
723
+
724
+ #: classes/models/class-import.php:385
725
+ msgid "Remote server returned error response %1$d %2$s"
726
+ msgstr ""
727
+
728
+ #: classes/models/class-import.php:394
729
+ msgid "Remote file is incorrect size"
730
+ msgstr ""
731
+
732
+ #: classes/models/class-import.php:399
733
+ msgid "Zero size file downloaded"
734
+ msgstr ""
735
+
736
+ #: classes/models/class-import.php:405
737
+ msgid "Remote file is too large, limit is %s"
738
+ msgstr ""
739
+
740
+ #: classes/models/class-import.php:422
741
+ #: classes/models/class-import.php:426
742
+ #: classes/models/class-import.php:436
743
+ msgid "Sorry, there has been an error."
744
+ msgstr ""
745
+
746
+ #: classes/models/class-import.php:427
747
+ msgid "The export file could not be found at <code>%s</code>. It is likely that this was caused by a permissions problem."
748
+ msgstr ""
749
+
750
+ #: classes/models/class-import.php:444
751
+ msgid "This WXR file (version %s) may not be supported by this version of the importer. Please consider updating."
752
+ msgstr ""
753
+
754
+ #: classes/models/class-import.php:501
755
+ msgid "Failed to import author %s. Their posts will be attributed to the current user."
756
+ msgstr ""
757
+
758
+ #: classes/models/class-import.php:558
759
+ msgid "Failed to create new user for %s. Their posts will be attributed to the current user."
760
+ msgstr ""
761
+
762
+ #: classes/models/class-import.php:609
763
+ #: classes/models/class-import.php:766
764
+ msgid "Failed to import %s %s"
765
+ msgstr ""
766
+
767
+ #: classes/models/class-import.php:656
768
+ msgid "Failed to import &#8220;%s&#8221;: Invalid post type %s"
769
+ msgstr ""
770
+
771
+ #: classes/models/class-import.php:673
772
+ msgid "%s &#8220;%s&#8221; already exists."
773
+ msgstr ""
774
+
775
+ #: classes/models/class-import.php:732
776
+ msgid "Failed to import %s &#8220;%s&#8221;"
777
+ msgstr ""
778
+
779
+ #: classes/modules/class-post.php:42
780
+ msgid "Column Type"
781
+ msgstr ""
782
+
783
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:97
784
+ #: templates/popup/index.php:98
785
+ #: media/js/blocks/dist/index.js:1
786
+ msgid "Filter title to display all events"
787
+ msgstr ""
788
+
789
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:107
790
+ #: templates/popup/index.php:104
791
+ #: media/js/blocks/dist/index.js:1
792
+ msgid "Hide 'All Events' option"
793
+ msgstr ""
794
+
795
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:128
796
+ #: templates/popup/index.php:16
797
+ #: media/js/blocks/dist/index.js:1
798
+ msgid "Specific events"
799
+ msgstr ""
800
+
801
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:153
802
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:164
803
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:175
804
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:186
805
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:197
806
+ msgid "Hide"
807
+ msgstr ""
808
+
809
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:154
810
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:165
811
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:176
812
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:187
813
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:198
814
+ msgid "Show"
815
+ msgstr ""
816
+
817
+ #. translators: Head means the leader of the event.
818
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:195
819
+ #: templates/popup/index.php:47
820
+ #: media/js/blocks/dist/index.js:1
821
+ msgid "Event Head"
822
+ msgstr ""
823
+
824
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:206
825
+ #: templates/popup/index.php:114
826
+ #: media/js/blocks/dist/index.js:1
827
+ msgid "Hide column with hours"
828
+ msgstr ""
829
+
830
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:215
831
+ #: templates/popup/index.php:123
832
+ #: media/js/blocks/dist/index.js:1
833
+ msgid "Do not display empty rows"
834
+ msgstr ""
835
+
836
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:224
837
+ #: templates/popup/index.php:132
838
+ #: media/js/blocks/dist/index.js:1
839
+ msgid "Merge cells with common events"
840
+ msgstr ""
841
+
842
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:233
843
+ #: templates/popup/index.php:141
844
+ #: templates/widgets/gallery-list.php:59
845
+ #: media/js/blocks/dist/index.js:1
846
+ msgid "Disable event link"
847
+ msgstr ""
848
+
849
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:242
850
+ #: templates/popup/index.php:61
851
+ #: media/js/blocks/dist/index.js:1
852
+ msgid "Base font size"
853
+ msgstr ""
854
+
855
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:245
856
+ #: templates/popup/index.php:64
857
+ #: media/js/blocks/dist/index.js:1
858
+ msgid "Base font size for the table. Example 12px, 2em, 80%."
859
+ msgstr ""
860
+
861
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:253
862
+ #: templates/popup/index.php:54
863
+ #: media/js/blocks/dist/index.js:1
864
+ msgid "Block height in pixels"
865
+ msgstr ""
866
+
867
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:262
868
+ #: templates/popup/index.php:68
869
+ #: media/js/blocks/dist/index.js:1
870
+ msgid "Time frame for event"
871
+ msgstr ""
872
+
873
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:277
874
+ #: templates/popup/index.php:78
875
+ #: media/js/blocks/dist/index.js:1
876
+ msgid "Filter events style"
877
+ msgstr ""
878
+
879
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:282
880
+ #: templates/popup/index.php:81
881
+ msgid "Dropdown"
882
+ msgstr ""
883
+
884
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:321
885
+ #: templates/popup/index.php:192
886
+ #: media/js/blocks/dist/index.js:1
887
+ msgid "Mobile behavior"
888
+ msgstr ""
889
+
890
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:326
891
+ #: templates/popup/index.php:196
892
+ #: media/js/blocks/dist/index.js:1
893
+ msgid "Table"
894
+ msgstr ""
895
+
896
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:327
897
+ #: templates/popup/index.php:195
898
+ #: media/js/blocks/dist/index.js:1
899
+ msgid "List"
900
+ msgstr ""
901
+
902
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:336
903
+ #: templates/popup/index.php:150
904
+ #: media/js/blocks/dist/index.js:1
905
+ msgid "Horizontal align"
906
+ msgstr ""
907
+
908
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:361
909
+ #: templates/popup/index.php:159
910
+ #: media/js/blocks/dist/index.js:1
911
+ msgid "Vertical align"
912
+ msgstr ""
913
+
914
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:367
915
+ #: templates/popup/index.php:161
916
+ msgid "default"
917
+ msgstr ""
918
+
919
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:371
920
+ #: templates/popup/index.php:162
921
+ #: media/js/blocks/dist/index.js:1
922
+ msgid "top"
923
+ msgstr ""
924
+
925
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:375
926
+ #: templates/popup/index.php:163
927
+ #: media/js/blocks/dist/index.js:1
928
+ msgid "middle"
929
+ msgstr ""
930
+
931
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:379
932
+ #: templates/popup/index.php:164
933
+ #: media/js/blocks/dist/index.js:1
934
+ msgid "bottom"
935
+ msgstr ""
936
+
937
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:389
938
+ #: templates/popup/index.php:179
939
+ #: media/js/blocks/dist/index.js:1
940
+ msgid "Unique ID"
941
+ msgstr ""
942
+
943
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:392
944
+ #: templates/popup/index.php:182
945
+ #: media/js/blocks/dist/index.js:1
946
+ msgid "If you use more than one table on a page specify the unique ID for a timetable. It is usually all lowercase and contains only letters, numbers, and hyphens."
947
+ msgstr ""
948
+
949
+ #: classes/widgets/class-mp-timetable-elementor-widget.php:401
950
+ #: templates/popup/index.php:186
951
+ #: media/js/blocks/dist/index.js:1
952
+ msgid "CSS class"
953
+ msgstr ""
954
+
955
+ #: classes/widgets/class-mp-timetable-widget.php:22
956
+ msgid "Display upcoming events."
957
+ msgstr ""
958
+
959
+ #: classes/widgets/class-mp-timetable-widget.php:24
960
+ msgid "Timetable Events"
961
+ msgstr ""
962
+
963
+ #: templates-functions/actions-mp-event-functions.php:27
964
+ #: templates/theme/event-timeslots.php:7
965
+ msgid "Event Timeslots (%s)"
966
+ msgstr ""
967
+
968
+ #: templates/column/metabox-column-options.php:11
969
+ msgid "Simple Column"
970
+ msgstr ""
971
+
972
+ #: templates/column/metabox-column-options.php:20
973
+ msgid "Day of the week"
974
+ msgstr ""
975
+
976
+ #: templates/column/metabox-column-options.php:24
977
+ msgid "Sunday"
978
+ msgstr ""
979
+
980
+ #: templates/column/metabox-column-options.php:25
981
+ msgid "Monday"
982
+ msgstr ""
983
+
984
+ #: templates/column/metabox-column-options.php:26
985
+ msgid "Tuesday"
986
+ msgstr ""
987
+
988
+ #: templates/column/metabox-column-options.php:27
989
+ msgid "Wednesday"
990
+ msgstr ""
991
+
992
+ #: templates/column/metabox-column-options.php:28
993
+ msgid "Thursday"
994
+ msgstr ""
995
+
996
+ #: templates/column/metabox-column-options.php:29
997
+ msgid "Friday"
998
+ msgstr ""
999
+
1000
+ #: templates/column/metabox-column-options.php:30
1001
+ msgid "Saturday"
1002
+ msgstr ""
1003
+
1004
+ #: templates/column/metabox-column-options.php:39
1005
+ msgid "Date"
1006
+ msgstr ""
1007
+
1008
+ #: templates/events/event-data.php:5
1009
+ msgid "Start"
1010
+ msgstr ""
1011
+
1012
+ #: templates/events/event-data.php:6
1013
+ msgid "End"
1014
+ msgstr ""
1015
+
1016
+ #. translators: Head means the leader of the event.
1017
+ #: templates/events/event-data.php:10
1018
+ msgid "Head"
1019
+ msgstr ""
1020
+
1021
+ #: templates/events/event-data.php:12
1022
+ msgid "Actions"
1023
+ msgstr ""
1024
+
1025
+ #: templates/events/event-data.php:35
1026
+ msgid "Edit event in the form below"
1027
+ msgstr ""
1028
+
1029
+ #: templates/events/event-data.php:36
1030
+ msgid "Delete"
1031
+ msgstr ""
1032
+
1033
+ #: templates/events/metabox-event-data.php:10
1034
+ msgid "Add New / Edit Timeslot"
1035
+ msgstr ""
1036
+
1037
+ #: templates/events/metabox-event-data.php:13
1038
+ msgid "Column:"
1039
+ msgstr ""
1040
+
1041
+ #: templates/events/metabox-event-data.php:21
1042
+ msgid "Select column or <a target=\"_blank\" href=\"%s\">Add New</a>."
1043
+ msgstr ""
1044
+
1045
+ #: templates/events/metabox-event-data.php:23
1046
+ msgid "No columns found. <a href=\"%s\">Create at least one column first.</a>"
1047
+ msgstr ""
1048
+
1049
+ #: templates/events/metabox-event-data.php:29
1050
+ msgid "Start Time:"
1051
+ msgstr ""
1052
+
1053
+ #: templates/events/metabox-event-data.php:32
1054
+ #: templates/events/metabox-event-data.php:39
1055
+ msgid "hh:mm"
1056
+ msgstr ""
1057
+
1058
+ #: templates/events/metabox-event-data.php:36
1059
+ msgid "End Time:"
1060
+ msgstr ""
1061
+
1062
+ #: templates/events/metabox-event-data.php:43
1063
+ msgid "Description:"
1064
+ msgstr ""
1065
+
1066
+ #. translators: Head means the leader of the event.
1067
+ #: templates/events/metabox-event-data.php:49
1068
+ msgid "Event Head:"
1069
+ msgstr ""
1070
+
1071
+ #: templates/events/metabox-event-data.php:58
1072
+ msgid "none"
1073
+ msgstr ""
1074
+
1075
+ #. translators: Button to add a new event.
1076
+ #: templates/events/metabox-event-data.php:83
1077
+ msgid "Add New"
1078
+ msgstr ""
1079
+
1080
+ #: templates/events/metabox-event-options.php:4
1081
+ msgid "Event Subtitle:"
1082
+ msgstr ""
1083
+
1084
+ #: templates/events/metabox-event-options.php:8
1085
+ msgid "Background Color:"
1086
+ msgstr ""
1087
+
1088
+ #: templates/events/metabox-event-options.php:15
1089
+ msgid "Background Hover Color:"
1090
+ msgstr ""
1091
+
1092
+ #: templates/events/metabox-event-options.php:22
1093
+ msgid "Text Color:"
1094
+ msgstr ""
1095
+
1096
+ #: templates/events/metabox-event-options.php:29
1097
+ msgid "Text Hover Color:"
1098
+ msgstr ""
1099
+
1100
+ #: templates/events/metabox-event-options.php:36
1101
+ msgid "Custom Event URL:"
1102
+ msgstr ""
1103
+
1104
+ #: templates/events/metabox-event-options.php:42
1105
+ msgid "Disable link to this event:"
1106
+ msgstr ""
1107
+
1108
+ #: templates/popup/index.php:12
1109
+ #: templates/popup/index.php:23
1110
+ #: templates/popup/index.php:34
1111
+ #: templates/widgets/gallery-list.php:48
1112
+ #: media/js/blocks/dist/index.js:1
1113
+ msgid "Hold the Ctrl or Command key to select/deselect multiple options."
1114
+ msgstr ""
1115
+
1116
+ #: templates/popup/index.php:38
1117
+ msgid "Fields to display:"
1118
+ msgstr ""
1119
+
1120
+ #: templates/popup/index.php:50
1121
+ msgid "Check the event parameter(s) to be displayed in the timetable."
1122
+ msgstr ""
1123
+
1124
+ #: templates/popup/index.php:57
1125
+ msgid "Set height of the block"
1126
+ msgstr ""
1127
+
1128
+ #: templates/popup/index.php:83
1129
+ msgid "None"
1130
+ msgstr ""
1131
+
1132
+ #: templates/popup/index.php:198
1133
+ msgid "Tick \"List\" to display events in a list view on mobile devices. Tick \"Table\" to display events in a table."
1134
+ msgstr ""
1135
+
1136
+ #: templates/popup/index.php:204
1137
+ msgid "Add Timetable"
1138
+ msgstr ""
1139
+
1140
+ #: templates/settings/general.php:2
1141
+ msgid "General Settings"
1142
+ msgstr ""
1143
+
1144
+ #: templates/settings/general.php:10
1145
+ msgid "Template Mode"
1146
+ msgstr ""
1147
+
1148
+ #: templates/settings/general.php:14
1149
+ msgid "Theme Mode"
1150
+ msgstr ""
1151
+
1152
+ #: templates/settings/general.php:15
1153
+ msgid "Developer Mode"
1154
+ msgstr ""
1155
+
1156
+ #: templates/settings/general.php:17
1157
+ msgid "Choose Theme Mode to display the content with the styles of your theme. Choose Developer Mode to control appearance of the content with custom page templates, actions and filters."
1158
+ msgstr ""
1159
+
1160
+ #: templates/settings/general.php:17
1161
+ msgid "This option can't be changed if your theme is initially integrated with the plugin."
1162
+ msgstr ""
1163
+
1164
+ #: templates/settings/general.php:24
1165
+ msgid "Permalink Settings"
1166
+ msgstr ""
1167
+
1168
+ #: templates/settings/general.php:25
1169
+ msgid "Configure permalink settings in <a href=\"%s\">Settings > Permalinks</a>"
1170
+ msgstr ""
1171
+
1172
+ #: templates/settings/general.php:30
1173
+ msgid "Save"
1174
+ msgstr ""
1175
+
1176
+ #: templates/shortcodes/empty-search-events.php:1
1177
+ #: templates/theme/widget-upcoming-view.php:57
1178
+ #: templates/widgets/widget-view.php:97
1179
+ msgid "no events found"
1180
+ msgstr ""
1181
+
1182
+ #: templates/templates-actions/action-sidebar.php:8
1183
+ #: templates/widgets/gallery-list.php:14
1184
+ msgid "Today upcoming events"
1185
+ msgstr ""
1186
+
1187
+ #: templates/templates-actions/action-sidebar.php:13
1188
+ #: templates/widgets/gallery-list.php:16
1189
+ msgid "All upcoming events"
1190
+ msgstr ""
1191
+
1192
+ #: templates/widgets/gallery-list.php:10
1193
+ msgid "Events to display"
1194
+ msgstr ""
1195
+
1196
+ #: templates/widgets/gallery-list.php:18
1197
+ msgid "Ongoing events"
1198
+ msgstr ""
1199
+
1200
+ #: templates/widgets/gallery-list.php:23
1201
+ msgid "Input number of days"
1202
+ msgstr ""
1203
+
1204
+ #: templates/widgets/gallery-list.php:28
1205
+ msgid "day"
1206
+ msgid_plural "days"
1207
+ msgstr[0] ""
1208
+ msgstr[1] ""
1209
+
1210
+ #: templates/widgets/gallery-list.php:32
1211
+ msgid "Event categories. Leave blank to display all."
1212
+ msgstr ""
1213
+
1214
+ #: templates/widgets/gallery-list.php:52
1215
+ msgid "Number of events to display"
1216
+ msgstr ""
1217
+
1218
+ #: templates/widgets/gallery-list.php:70
1219
+ msgid "Custom link for events"
1220
+ msgstr ""
1221
+
1222
+ #: templates/widgets/gallery-list.php:78
1223
+ msgid "Event background color"
1224
+ msgstr ""
1225
+
1226
+ #: templates/widgets/gallery-list.php:88
1227
+ msgid "Event background color on hover"
1228
+ msgstr ""
1229
+
1230
+ #: templates/widgets/gallery-list.php:98
1231
+ msgid "Event text color"
1232
+ msgstr ""
1233
+
1234
+ #: templates/widgets/gallery-list.php:108
1235
+ msgid "Event text color on hover"
1236
+ msgstr ""
1237
+
1238
+ #: templates/widgets/gallery-list.php:118
1239
+ msgid "Event border color"
1240
+ msgstr ""
1241
+
1242
+ #: templates/widgets/gallery-list.php:128
1243
+ msgid "Event border color on hover"
1244
+ msgstr ""
media/css/jbox/jBox.css CHANGED
@@ -1,569 +1,569 @@
1
-
2
- /* Global */
3
-
4
- .jBox-wrapper {
5
- text-align: left;
6
- }
7
-
8
- .jBox-wrapper,
9
- .jBox-wrapper * {
10
- -webkit-box-sizing: border-box;
11
- box-sizing: border-box;
12
- -webkit-font-smoothing: antialiased;
13
- -moz-osx-font-smoothing: grayscale;
14
- }
15
-
16
- .jBox-title,
17
- .jBox-content,
18
- .jBox-container {
19
- position: relative;
20
- word-break: break-word;
21
- }
22
-
23
- .jBox-container {
24
- background: #fff;
25
- }
26
-
27
- .jBox-content {
28
- padding: 8px 10px;
29
- overflow: auto;
30
- -webkit-transition: opacity .15s;
31
- transition: opacity .15s;
32
- }
33
-
34
- /* jBox Tooltip */
35
-
36
- .jBox-Tooltip .jBox-container,
37
- .jBox-Mouse .jBox-container {
38
- border-radius: 3px;
39
- box-shadow: 0 0 5px rgba(0, 0, 0, .3);
40
- }
41
-
42
- .jBox-Tooltip .jBox-title,
43
- .jBox-Mouse .jBox-title {
44
- padding: 8px 10px 0;
45
- font-weight: bold;
46
- }
47
-
48
- .jBox-hasTitle.jBox-Tooltip .jBox-content,
49
- .jBox-hasTitle.jBox-Mouse .jBox-content {
50
- padding-top: 5px;
51
- }
52
-
53
- /* Pointer */
54
-
55
- .jBox-pointer {
56
- position: absolute;
57
- overflow: hidden;
58
- }
59
-
60
- .jBox-pointer-top { top: 0; }
61
- .jBox-pointer-bottom { bottom: 0; }
62
- .jBox-pointer-left { left: 0; }
63
- .jBox-pointer-right { right: 0; }
64
-
65
- .jBox-pointer-top,
66
- .jBox-pointer-bottom {
67
- width: 30px;
68
- height: 12px;
69
- }
70
-
71
- .jBox-pointer-left,
72
- .jBox-pointer-right {
73
- width: 12px;
74
- height: 30px;
75
- }
76
-
77
- .jBox-pointer:after {
78
- content: '';
79
- width: 20px;
80
- height: 20px;
81
- position: absolute;
82
- background: #fff;
83
- -webkit-transform: rotate(45deg);
84
- transform: rotate(45deg);
85
- }
86
-
87
- .jBox-pointer-top:after {
88
- left: 5px;
89
- top: 6px;
90
- box-shadow: -1px -1px 4px rgba(0, 0, 0, .2);
91
- }
92
-
93
- .jBox-pointer-right:after {
94
- top: 5px;
95
- right: 6px;
96
- box-shadow: 1px -1px 4px rgba(0, 0, 0, .2);
97
- }
98
-
99
- .jBox-pointer-bottom:after {
100
- left: 5px;
101
- bottom: 6px;
102
- box-shadow: 1px 1px 4px rgba(0, 0, 0, .2);
103
- }
104
-
105
- .jBox-pointer-left:after {
106
- top: 5px;
107
- left: 6px;
108
- box-shadow: -1px 1px 4px rgba(0, 0, 0, .2);
109
- }
110
-
111
- /* jBox Modal & jBox Confirm */
112
-
113
- .jBox-Modal .jBox-container,
114
- .jBox-Confirm .jBox-container {
115
- border-radius: 3px;
116
- box-shadow: 0 3px 15px rgba(0, 0, 0, .4), 0 0 5px rgba(0, 0, 0, .4);
117
- }
118
-
119
- .jBox-Modal .jBox-title,
120
- .jBox-Confirm .jBox-title {
121
- border-radius: 3px 3px 0 0;
122
- padding: 10px 15px;
123
- background: #f4f5f6;
124
- border-bottom: 1px solid #ddd;
125
- text-shadow: 0 1px 0 #fff;
126
- }
127
-
128
- .jBox-Modal.jBox-closeButton-title .jBox-title,
129
- .jBox-Confirm.jBox-closeButton-title .jBox-title {
130
- padding-right: 55px;
131
- }
132
-
133
- .jBox-Modal.jBox-closeButton-box:before,
134
- .jBox-Confirm.jBox-closeButton-box:before {
135
- box-shadow: 0 3px 15px rgba(0, 0, 0, .4), 0 0 5px rgba(0, 0, 0, .4);
136
- }
137
-
138
- /* jBox Modal */
139
-
140
- .jBox-Modal .jBox-content {
141
- padding: 12px 15px;
142
- }
143
-
144
- /* jBox Confirm */
145
-
146
- .jBox-Confirm .jBox-content {
147
- text-align: center;
148
- padding: 45px 35px;
149
- }
150
-
151
- .jBox-Confirm-footer {
152
- border-top: 1px solid #e2e2e2;
153
- background: #fafafa;
154
- border-radius: 0 0 3px 3px;
155
- text-align: center;
156
- padding: 10px 0;
157
- }
158
-
159
- .jBox-Confirm-button {
160
- display: inline-block;
161
- cursor: pointer;
162
- font-size: 15px;
163
- line-height: 30px;
164
- height: 30px;
165
- border-radius: 3px;
166
- padding: 0 20px;
167
- -webkit-transition: color .2s, background-color .2s;
168
- transition: color .2s, background-color .2s;
169
- }
170
-
171
- .jBox-Confirm-button-cancel {
172
- text-shadow: 0 1px 1px rgba(255, 255, 255, .6);
173
- background: #ddd;
174
- color: #999;
175
- margin-right: 25px;
176
- }
177
-
178
- .jBox-Confirm-button-cancel:hover {
179
- background: #ccc;
180
- color: #666;
181
- }
182
-
183
- .jBox-Confirm-button-submit {
184
- text-shadow: 0 -1px 1px rgba(0, 0, 0, .2);
185
- background: #5fc04c;
186
- color: #fff;
187
- }
188
-
189
- .jBox-Confirm-button-submit:hover {
190
- background: #53a642;
191
- }
192
-
193
- .jBox-Confirm-button-cancel:active,
194
- .jBox-Confirm-button-submit:active {
195
- box-shadow: inset 0 1px 3px rgba(0, 0, 0, .26);
196
- }
197
-
198
- /* jBox Notice */
199
-
200
- .jBox-Notice {
201
- -webkit-transition: margin .2s;
202
- transition: margin .2s;
203
- }
204
-
205
- .jBox-Notice .jBox-container {
206
- border-radius: 3px;
207
- box-shadow: 0 0 3px rgba(0, 0, 0, .2);
208
- color: #fff;
209
- text-shadow: 0 -1px 0 #000;
210
- background: #333;
211
- background-image: linear-gradient(to bottom, #444, #222);
212
- }
213
-
214
- .jBox-Notice .jBox-content {
215
- border-radius: 3px;
216
- padding: 12px 20px;
217
- }
218
-
219
- .jBox-Notice .jBox-title {
220
- padding: 8px 20px 0;
221
- font-weight: bold;
222
- }
223
-
224
- .jBox-hasTitle.jBox-Notice .jBox-content {
225
- padding-top: 5px;
226
- }
227
-
228
- .jBox-Notice-color .jBox-container {
229
- text-shadow: 0 -1px 0 rgba(0, 0, 0, .3);
230
- }
231
-
232
- .jBox-Notice-gray .jBox-container {
233
- color: #666;
234
- text-shadow: 0 1px 0 #fff;
235
- background: #f4f4f4;
236
- background-image: linear-gradient(to bottom, #fafafa, #f0f0f0);
237
- }
238
-
239
- .jBox-Notice-red .jBox-container {
240
- background: #b02222;
241
- background-image: linear-gradient(to bottom, #ee2222, #b02222);
242
- }
243
-
244
- .jBox-Notice-green .jBox-container {
245
- background: #70a800;
246
- background-image: linear-gradient(to bottom, #95cc2a, #70a800);
247
- }
248
-
249
- .jBox-Notice-blue .jBox-container {
250
- background: #2b91d9;
251
- background-image: linear-gradient(to bottom, #5abaff, #2b91d9);
252
- }
253
-
254
- .jBox-Notice-yellow .jBox-container {
255
- color: #744700;
256
- text-shadow: 0 1px 0 rgba(255, 255, 255, .6);
257
- background: #ffb11f;
258
- background-image: linear-gradient(to bottom, #ffd665, #ffb11f);
259
- }
260
-
261
- /* jBox Image */
262
-
263
- .jBox-Image {
264
- background: #fff;
265
- padding: 8px 8px 45px;
266
- border-radius: 5px;
267
- }
268
-
269
- .jBox-Image .jBox-content {
270
- padding: 0;
271
- width: 100%;
272
- height: 100%;
273
- }
274
-
275
- .jBox-image-container {
276
- border-radius: 5px;
277
- background: #fff center center no-repeat;
278
- position: absolute;
279
- width: 100%;
280
- height: 100%;
281
- opacity: 0;
282
- }
283
-
284
- .jBox-image-label {
285
- box-sizing: border-box;
286
- position: absolute;
287
- background: #fff;
288
- top: 100%;
289
- left: 0;
290
- width: 100%;
291
- color: #333;
292
- margin-top: -35px;
293
- padding: 0 90px 5px 10px;
294
- border-radius: 0 0 5px 5px;
295
- -webkit-transition: opacity .3s;
296
- transition: opacity .3s;
297
- opacity: 0;
298
- }
299
-
300
- .jBox-image-label.active {
301
- opacity: 1;
302
- }
303
-
304
- .jBox-image-pointer-next,
305
- .jBox-image-pointer-prev {
306
- position: absolute;
307
- bottom: 0px;
308
- width: 22px;
309
- height: 45px;
310
- background: no-repeat center center url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ijc0LjcgMjI0IDE4LjcgMzIiPg0KPHBhdGggZmlsbD0iIzAwMDAwMCIgZD0iTTkzLDIyNy40TDgwLjQsMjQwTDkzLDI1Mi42YzAuNCwwLjQsMC40LDEuMSwwLDEuNWwtMS42LDEuNmMtMC40LDAuNC0xLDAuNS0xLjUsMEw3NSwyNDAuN2MtMC40LTAuNC0wLjUtMSwwLTEuNWwxNC45LTE0LjljMC40LTAuNCwxLTAuNCwxLjUsMGwxLjYsMS42QzkzLjUsMjI2LjQsOTMuNCwyMjcsOTMsMjI3LjR6Ii8+DQo8L3N2Zz4=);
311
- background-size: 11px auto;
312
- cursor: pointer;
313
- opacity: .6;
314
- -webkit-touch-callout: none;
315
- -webkit-user-select: none;
316
- -moz-user-select: none;
317
- -ms-user-select: none;
318
- user-select: none;
319
- -webkit-transition: opacity .2s;
320
- transition: opacity .2s;
321
- }
322
-
323
- .jBox-image-pointer-next:hover,
324
- .jBox-image-pointer-prev:hover {
325
- opacity: 1;
326
- }
327
-
328
- .jBox-image-pointer-next {
329
- right: 8px;
330
- -webkit-transform: scaleX(-1);
331
- transform: scaleX(-1);
332
- }
333
-
334
- .jBox-image-pointer-prev {
335
- right: 30px;
336
- }
337
-
338
- .jBox-image-open #jBox-overlay {
339
- background-color: rgba(0, 0, 0, .86);
340
- }
341
-
342
- .jBox-Image.jBox-loading .jBox-container:before {
343
- left: auto;
344
- top: auto;
345
- bottom: -33px;
346
- right: 55px;
347
- margin-top: -9px;
348
- margin-left: -9px;
349
- }
350
-
351
- /* Close button */
352
-
353
- .jBox-closeButton {
354
- cursor: pointer;
355
- position: absolute;
356
- }
357
-
358
- .jBox-closeButton svg {
359
- position: absolute;
360
- top: 50%;
361
- right: 50%;
362
- }
363
-
364
- .jBox-closeButton path {
365
- -webkit-transition: fill .2s;
366
- transition: fill .2s;
367
- }
368
-
369
- .jBox-closeButton path {
370
- fill: #aaa;
371
- }
372
-
373
- .jBox-closeButton:hover path {
374
- fill: #888;
375
- }
376
-
377
- .jBox-closeButton:active path {
378
- fill: #666;
379
- }
380
-
381
- /* Close button in overlay */
382
-
383
- #jBox-overlay .jBox-closeButton {
384
- top: 0;
385
- right: 0;
386
- width: 40px;
387
- height: 40px;
388
- }
389
-
390
- #jBox-overlay .jBox-closeButton svg {
391
- width: 20px;
392
- height: 20px;
393
- margin-top: -10px;
394
- margin-right: -10px;
395
- }
396
-
397
- #jBox-overlay .jBox-closeButton path {
398
- fill: #d2d4d6;
399
- }
400
-
401
- #jBox-overlay .jBox-closeButton:hover path {
402
- fill: #fff;
403
- }
404
-
405
- #jBox-overlay .jBox-closeButton:active path {
406
- fill: #b2b4b6;
407
- }
408
-
409
- /* Close button in title */
410
-
411
- .jBox-closeButton-title .jBox-closeButton {
412
- top: 0;
413
- right: 0;
414
- bottom: 0;
415
- width: 40px;
416
- }
417
-
418
- .jBox-closeButton-title .jBox-closeButton svg {
419
- width: 12px;
420
- height: 12px;
421
- margin-top: -6px;
422
- margin-right: -6px;
423
- }
424
-
425
- /* Close button in box */
426
-
427
- .jBox-closeButton-box .jBox-closeButton {
428
- top: -8px;
429
- right: -10px;
430
- width: 24px;
431
- height: 24px;
432
- background: #fff;
433
- border-radius: 50%;
434
- }
435
-
436
- .jBox-closeButton-box .jBox-closeButton svg {
437
- width: 10px;
438
- height: 10px;
439
- margin-top: -5px;
440
- margin-right: -5px;
441
- }
442
-
443
- .jBox-hasTitle.jBox-Modal.jBox-closeButton-box .jBox-closeButton {
444
- background: #f4f5f6;
445
- }
446
-
447
- .jBox-closeButton-box:before {
448
- content: '';
449
- position: absolute;
450
- top: -8px;
451
- right: -10px;
452
- width: 24px;
453
- height: 24px;
454
- border-radius: 50%;
455
- box-shadow: 0 0 5px rgba(0, 0, 0, .3);
456
- }
457
-
458
- .jBox-pointerPosition-top.jBox-closeButton-box:before {
459
- top: 4px;
460
- }
461
-
462
- .jBox-pointerPosition-right.jBox-closeButton-box:before {
463
- right: 2px;
464
- }
465
-
466
- /* Overlay */
467
-
468
- #jBox-overlay {
469
- position: fixed;
470
- top: 0;
471
- left: 0;
472
- width: 100%;
473
- height: 100%;
474
- background: #000;
475
- background-color: rgba(0, 0, 0, .6);
476
- }
477
-
478
- /* Block scrolling */
479
-
480
- body[class^="jBox-blockScroll-"],
481
- body[class*=" jBox-blockScroll-"] {
482
- overflow: hidden;
483
- }
484
-
485
- /* Draggable */
486
-
487
- .jBox-draggable {
488
- cursor: move;
489
- }
490
-
491
- /* Spinner */
492
-
493
- @keyframes jBoxLoading {
494
- to {transform: rotate(360deg);}
495
- }
496
-
497
- @-webkit-keyframes jBoxLoading {
498
- to {-webkit-transform: rotate(360deg);}
499
- }
500
-
501
- .jBox-loading .jBox-content {
502
- min-height: 32px;
503
- min-width: 38px;
504
- opacity: 0;
505
- }
506
-
507
- .jBox-spinner {
508
- position: absolute;
509
- top: 50%;
510
- left: 50%;
511
- width: 20px;
512
- height: 20px;
513
- margin-top: -10px;
514
- margin-left: -10px;
515
- }
516
-
517
- .jBox-spinner:before {
518
- content: 'Loading…';
519
- display: block;
520
- width: 20px;
521
- height: 20px;
522
- text-align: center;
523
- -webkit-box-sizing: border-box;
524
- box-sizing: border-box;
525
- }
526
-
527
- .jBox-spinner:not(:required):before {
528
- content: '';
529
- border-radius: 50%;
530
- border: 2px solid rgba(0, 0, 0, .3);
531
- border-top-color: rgba(0, 0, 0, .6);
532
- animation: jBoxLoading .6s linear infinite;
533
- -webkit-animation: jBoxLoading .6s linear infinite;
534
- }
535
-
536
- /* IE8 fixes */
537
-
538
- .jBox-IE8.jBox-Tooltip .jBox-container,
539
- .jBox-IE8.jBox-Mouse .jBox-container {
540
- border: 1px solid #aaa;
541
- }
542
-
543
- .jBox-IE8 .jBox-pointer:after {
544
- display: none;
545
- }
546
-
547
- .jBox-IE8 .jBox-pointer {
548
- border: 0;
549
- background: no-repeat url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAYAAACN1PRVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPJJREFUeNq01l0OwyAIAGAlvY+n8ZJ6Gk/EqqkNtf7ApCQ+LM34iuCmRUQzihjj6FH+kjWL8N4/Ph9GHpiTnC9SwDbhLGyvspSScc71KkOa/HpuuRhIK+psE2pjONouCQg7kBSEXUgC2tHo52mTTBpnaEATWlaYK6MrhIAaceWpOcsCrYp6FV4H/90zTWjUQ/gSevVQq0ecHqoOxWpYoO7p5O9ku2fnVtp7QAik2rsK3fnpWfjynJWpbw+1BkghurrYDjiCptg/4AxaYhJwBbEwDsiB2NgM5EIirAdKIDFGQSmU1+NaIPjJYt2I25vxT4ABAMhWvtle2YvmAAAAAElFTkSuQmCC);
550
- }
551
-
552
- .jBox-IE8 .jBox-pointer-top { background-position: center top; }
553
- .jBox-IE8 .jBox-pointer-bottom { background-position: center bottom; }
554
- .jBox-IE8 .jBox-pointer-left { background-position: left center; }
555
- .jBox-IE8 .jBox-pointer-right { background-position: right center; }
556
-
557
- .jBox-IE8.jBox-Modal .jBox-container {
558
- border: 3px solid #aaa;
559
- }
560
-
561
- /* No SVG support fixes */
562
-
563
- .jBox-nosvg .jBox-closeButton:before {
564
- font-family: Verdana, sans-serif;
565
- content: 'x';
566
- text-align: center;
567
- font-size: 18px;
568
- color: #888;
569
- }
1
+
2
+ /* Global */
3
+
4
+ .jBox-wrapper {
5
+ text-align: left;
6
+ }
7
+
8
+ .jBox-wrapper,
9
+ .jBox-wrapper * {
10
+ -webkit-box-sizing: border-box;
11
+ box-sizing: border-box;
12
+ -webkit-font-smoothing: antialiased;
13
+ -moz-osx-font-smoothing: grayscale;
14
+ }
15
+
16
+ .jBox-title,
17
+ .jBox-content,
18
+ .jBox-container {
19
+ position: relative;
20
+ word-break: break-word;
21
+ }
22
+
23
+ .jBox-container {
24
+ background: #fff;
25
+ }
26
+
27
+ .jBox-content {
28
+ padding: 8px 10px;
29
+ overflow: auto;
30
+ -webkit-transition: opacity .15s;
31
+ transition: opacity .15s;
32
+ }
33
+
34
+ /* jBox Tooltip */
35
+
36
+ .jBox-Tooltip .jBox-container,
37
+ .jBox-Mouse .jBox-container {
38
+ border-radius: 3px;
39
+ box-shadow: 0 0 5px rgba(0, 0, 0, .3);
40
+ }
41
+
42
+ .jBox-Tooltip .jBox-title,
43
+ .jBox-Mouse .jBox-title {
44
+ padding: 8px 10px 0;
45
+ font-weight: bold;
46
+ }
47
+
48
+ .jBox-hasTitle.jBox-Tooltip .jBox-content,
49
+ .jBox-hasTitle.jBox-Mouse .jBox-content {
50
+ padding-top: 5px;
51
+ }
52
+
53
+ /* Pointer */
54
+
55
+ .jBox-pointer {
56
+ position: absolute;
57
+ overflow: hidden;
58
+ }
59
+
60
+ .jBox-pointer-top { top: 0; }
61
+ .jBox-pointer-bottom { bottom: 0; }
62
+ .jBox-pointer-left { left: 0; }
63
+ .jBox-pointer-right { right: 0; }
64
+
65
+ .jBox-pointer-top,
66
+ .jBox-pointer-bottom {
67
+ width: 30px;
68
+ height: 12px;
69
+ }
70
+
71
+ .jBox-pointer-left,
72
+ .jBox-pointer-right {
73
+ width: 12px;
74
+ height: 30px;
75
+ }
76
+
77
+ .jBox-pointer:after {
78
+ content: '';
79
+ width: 20px;
80
+ height: 20px;
81
+ position: absolute;
82
+ background: #fff;
83
+ -webkit-transform: rotate(45deg);
84
+ transform: rotate(45deg);
85
+ }
86
+
87
+ .jBox-pointer-top:after {
88
+ left: 5px;
89
+ top: 6px;
90
+ box-shadow: -1px -1px 4px rgba(0, 0, 0, .2);
91
+ }
92
+
93
+ .jBox-pointer-right:after {
94
+ top: 5px;
95
+ right: 6px;
96
+ box-shadow: 1px -1px 4px rgba(0, 0, 0, .2);
97
+ }
98
+
99
+ .jBox-pointer-bottom:after {
100
+ left: 5px;
101
+ bottom: 6px;
102
+ box-shadow: 1px 1px 4px rgba(0, 0, 0, .2);
103
+ }
104
+
105
+ .jBox-pointer-left:after {
106
+ top: 5px;
107
+ left: 6px;
108
+ box-shadow: -1px 1px 4px rgba(0, 0, 0, .2);
109
+ }
110
+
111
+ /* jBox Modal & jBox Confirm */
112
+
113
+ .jBox-Modal .jBox-container,
114
+ .jBox-Confirm .jBox-container {
115
+ border-radius: 3px;
116
+ box-shadow: 0 3px 15px rgba(0, 0, 0, .4), 0 0 5px rgba(0, 0, 0, .4);
117
+ }
118
+
119
+ .jBox-Modal .jBox-title,
120
+ .jBox-Confirm .jBox-title {
121
+ border-radius: 3px 3px 0 0;
122
+ padding: 10px 15px;
123
+ background: #f4f5f6;
124
+ border-bottom: 1px solid #ddd;
125
+ text-shadow: 0 1px 0 #fff;
126
+ }
127
+
128
+ .jBox-Modal.jBox-closeButton-title .jBox-title,
129
+ .jBox-Confirm.jBox-closeButton-title .jBox-title {
130
+ padding-right: 55px;
131
+ }
132
+
133
+ .jBox-Modal.jBox-closeButton-box:before,
134
+ .jBox-Confirm.jBox-closeButton-box:before {
135
+ box-shadow: 0 3px 15px rgba(0, 0, 0, .4), 0 0 5px rgba(0, 0, 0, .4);
136
+ }
137
+
138
+ /* jBox Modal */
139
+
140
+ .jBox-Modal .jBox-content {
141
+ padding: 12px 15px;
142
+ }
143
+
144
+ /* jBox Confirm */
145
+
146
+ .jBox-Confirm .jBox-content {
147
+ text-align: center;
148
+ padding: 45px 35px;
149
+ }
150
+
151
+ .jBox-Confirm-footer {
152
+ border-top: 1px solid #e2e2e2;
153
+ background: #fafafa;
154
+ border-radius: 0 0 3px 3px;
155
+ text-align: center;
156
+ padding: 10px 0;
157
+ }
158
+
159
+ .jBox-Confirm-button {
160
+ display: inline-block;
161
+ cursor: pointer;
162
+ font-size: 15px;
163
+ line-height: 30px;
164
+ height: 30px;
165
+ border-radius: 3px;
166
+ padding: 0 20px;
167
+ -webkit-transition: color .2s, background-color .2s;
168
+ transition: color .2s, background-color .2s;
169
+ }
170
+
171
+ .jBox-Confirm-button-cancel {
172
+ text-shadow: 0 1px 1px rgba(255, 255, 255, .6);
173
+ background: #ddd;
174
+ color: #999;
175
+ margin-right: 25px;
176
+ }
177
+
178
+ .jBox-Confirm-button-cancel:hover {
179
+ background: #ccc;
180
+ color: #666;
181
+ }
182
+
183
+ .jBox-Confirm-button-submit {
184
+ text-shadow: 0 -1px 1px rgba(0, 0, 0, .2);
185
+ background: #5fc04c;
186
+ color: #fff;
187
+ }
188
+
189
+ .jBox-Confirm-button-submit:hover {
190
+ background: #53a642;
191
+ }
192
+
193
+ .jBox-Confirm-button-cancel:active,
194
+ .jBox-Confirm-button-submit:active {
195
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, .26);
196
+ }
197
+
198
+ /* jBox Notice */
199
+
200
+ .jBox-Notice {
201
+ -webkit-transition: margin .2s;
202
+ transition: margin .2s;
203
+ }
204
+
205
+ .jBox-Notice .jBox-container {
206
+ border-radius: 3px;
207
+ box-shadow: 0 0 3px rgba(0, 0, 0, .2);
208
+ color: #fff;
209
+ text-shadow: 0 -1px 0 #000;
210
+ background: #333;
211
+ background-image: linear-gradient(to bottom, #444, #222);
212
+ }
213
+
214
+ .jBox-Notice .jBox-content {
215
+ border-radius: 3px;
216
+ padding: 12px 20px;
217
+ }
218
+
219
+ .jBox-Notice .jBox-title {
220
+ padding: 8px 20px 0;
221
+ font-weight: bold;
222
+ }
223
+
224
+ .jBox-hasTitle.jBox-Notice .jBox-content {
225
+ padding-top: 5px;
226
+ }
227
+
228
+ .jBox-Notice-color .jBox-container {
229
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, .3);
230
+ }
231
+
232
+ .jBox-Notice-gray .jBox-container {
233
+ color: #666;
234
+ text-shadow: 0 1px 0 #fff;
235
+ background: #f4f4f4;
236
+ background-image: linear-gradient(to bottom, #fafafa, #f0f0f0);
237
+ }
238
+
239
+ .jBox-Notice-red .jBox-container {
240
+ background: #b02222;
241
+ background-image: linear-gradient(to bottom, #ee2222, #b02222);
242
+ }
243
+
244
+ .jBox-Notice-green .jBox-container {
245
+ background: #70a800;
246
+ background-image: linear-gradient(to bottom, #95cc2a, #70a800);
247
+ }
248
+
249
+ .jBox-Notice-blue .jBox-container {
250
+ background: #2b91d9;
251
+ background-image: linear-gradient(to bottom, #5abaff, #2b91d9);
252
+ }
253
+
254
+ .jBox-Notice-yellow .jBox-container {
255
+ color: #744700;
256
+ text-shadow: 0 1px 0 rgba(255, 255, 255, .6);
257
+ background: #ffb11f;
258
+ background-image: linear-gradient(to bottom, #ffd665, #ffb11f);
259
+ }
260
+
261
+ /* jBox Image */
262
+
263
+ .jBox-Image {
264
+ background: #fff;
265
+ padding: 8px 8px 45px;
266
+ border-radius: 5px;
267
+ }
268
+
269
+ .jBox-Image .jBox-content {
270
+ padding: 0;
271
+ width: 100%;
272
+ height: 100%;
273
+ }
274
+
275
+ .jBox-image-container {
276
+ border-radius: 5px;
277
+ background: #fff center center no-repeat;
278
+ position: absolute;
279
+ width: 100%;
280
+ height: 100%;
281
+ opacity: 0;
282
+ }
283
+
284
+ .jBox-image-label {
285
+ box-sizing: border-box;
286
+ position: absolute;
287
+ background: #fff;
288
+ top: 100%;
289
+ left: 0;
290
+ width: 100%;
291
+ color: #333;
292
+ margin-top: -35px;
293
+ padding: 0 90px 5px 10px;
294
+ border-radius: 0 0 5px 5px;
295
+ -webkit-transition: opacity .3s;
296
+ transition: opacity .3s;
297
+ opacity: 0;
298
+ }
299
+
300
+ .jBox-image-label.active {
301
+ opacity: 1;
302
+ }
303
+
304
+ .jBox-image-pointer-next,
305
+ .jBox-image-pointer-prev {
306
+ position: absolute;
307
+ bottom: 0px;
308
+ width: 22px;
309
+ height: 45px;
310
+ background: no-repeat center center url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ijc0LjcgMjI0IDE4LjcgMzIiPg0KPHBhdGggZmlsbD0iIzAwMDAwMCIgZD0iTTkzLDIyNy40TDgwLjQsMjQwTDkzLDI1Mi42YzAuNCwwLjQsMC40LDEuMSwwLDEuNWwtMS42LDEuNmMtMC40LDAuNC0xLDAuNS0xLjUsMEw3NSwyNDAuN2MtMC40LTAuNC0wLjUtMSwwLTEuNWwxNC45LTE0LjljMC40LTAuNCwxLTAuNCwxLjUsMGwxLjYsMS42QzkzLjUsMjI2LjQsOTMuNCwyMjcsOTMsMjI3LjR6Ii8+DQo8L3N2Zz4=);
311
+ background-size: 11px auto;
312
+ cursor: pointer;
313
+ opacity: .6;
314
+ -webkit-touch-callout: none;
315
+ -webkit-user-select: none;
316
+ -moz-user-select: none;
317
+ -ms-user-select: none;
318
+ user-select: none;
319
+ -webkit-transition: opacity .2s;
320
+ transition: opacity .2s;
321
+ }
322
+
323
+ .jBox-image-pointer-next:hover,
324
+ .jBox-image-pointer-prev:hover {
325
+ opacity: 1;
326
+ }
327
+
328
+ .jBox-image-pointer-next {
329
+ right: 8px;
330
+ -webkit-transform: scaleX(-1);
331
+ transform: scaleX(-1);
332
+ }
333
+
334
+ .jBox-image-pointer-prev {
335
+ right: 30px;
336
+ }
337
+
338
+ .jBox-image-open #jBox-overlay {
339
+ background-color: rgba(0, 0, 0, .86);
340
+ }
341
+
342
+ .jBox-Image.jBox-loading .jBox-container:before {
343
+ left: auto;
344
+ top: auto;
345
+ bottom: -33px;
346
+ right: 55px;
347
+ margin-top: -9px;
348
+ margin-left: -9px;
349
+ }
350
+
351
+ /* Close button */
352
+
353
+ .jBox-closeButton {
354
+ cursor: pointer;
355
+ position: absolute;
356
+ }
357
+
358
+ .jBox-closeButton svg {
359
+ position: absolute;
360
+ top: 50%;
361
+ right: 50%;
362
+ }
363
+
364
+ .jBox-closeButton path {
365
+ -webkit-transition: fill .2s;
366
+ transition: fill .2s;
367
+ }
368
+
369
+ .jBox-closeButton path {
370
+ fill: #aaa;
371
+ }
372
+
373
+ .jBox-closeButton:hover path {
374
+ fill: #888;
375
+ }
376
+
377
+ .jBox-closeButton:active path {
378
+ fill: #666;
379
+ }
380
+
381
+ /* Close button in overlay */
382
+
383
+ #jBox-overlay .jBox-closeButton {
384
+ top: 0;
385
+ right: 0;
386
+ width: 40px;
387
+ height: 40px;
388
+ }
389
+
390
+ #jBox-overlay .jBox-closeButton svg {
391
+ width: 20px;
392
+ height: 20px;
393
+ margin-top: -10px;
394
+ margin-right: -10px;
395
+ }
396
+
397
+ #jBox-overlay .jBox-closeButton path {
398
+ fill: #d2d4d6;
399
+ }
400
+
401
+ #jBox-overlay .jBox-closeButton:hover path {
402
+ fill: #fff;
403
+ }
404
+
405
+ #jBox-overlay .jBox-closeButton:active path {
406
+ fill: #b2b4b6;
407
+ }
408
+
409
+ /* Close button in title */
410
+
411
+ .jBox-closeButton-title .jBox-closeButton {
412
+ top: 0;
413
+ right: 0;
414
+ bottom: 0;
415
+ width: 40px;
416
+ }
417
+
418
+ .jBox-closeButton-title .jBox-closeButton svg {
419
+ width: 12px;
420
+ height: 12px;
421
+ margin-top: -6px;
422
+ margin-right: -6px;
423
+ }
424
+
425
+ /* Close button in box */
426
+
427
+ .jBox-closeButton-box .jBox-closeButton {
428
+ top: -8px;
429
+ right: -10px;
430
+ width: 24px;
431
+ height: 24px;
432
+ background: #fff;
433
+ border-radius: 50%;
434
+ }
435
+
436
+ .jBox-closeButton-box .jBox-closeButton svg {
437
+ width: 10px;
438
+ height: 10px;
439
+ margin-top: -5px;
440
+ margin-right: -5px;
441
+ }
442
+
443
+ .jBox-hasTitle.jBox-Modal.jBox-closeButton-box .jBox-closeButton {
444
+ background: #f4f5f6;
445
+ }
446
+
447
+ .jBox-closeButton-box:before {
448
+ content: '';
449
+ position: absolute;
450
+ top: -8px;
451
+ right: -10px;
452
+ width: 24px;
453
+ height: 24px;
454
+ border-radius: 50%;
455
+ box-shadow: 0 0 5px rgba(0, 0, 0, .3);
456
+ }
457
+
458
+ .jBox-pointerPosition-top.jBox-closeButton-box:before {
459
+ top: 4px;
460
+ }
461
+
462
+ .jBox-pointerPosition-right.jBox-closeButton-box:before {
463
+ right: 2px;
464
+ }
465
+
466
+ /* Overlay */
467
+
468
+ #jBox-overlay {
469
+ position: fixed;
470
+ top: 0;
471
+ left: 0;
472
+ width: 100%;
473
+ height: 100%;
474
+ background: #000;
475
+ background-color: rgba(0, 0, 0, .6);
476
+ }
477
+
478
+ /* Block scrolling */
479
+
480
+ body[class^="jBox-blockScroll-"],
481
+ body[class*=" jBox-blockScroll-"] {
482
+ overflow: hidden;
483
+ }
484
+
485
+ /* Draggable */
486
+
487
+ .jBox-draggable {
488
+ cursor: move;
489
+ }
490
+
491
+ /* Spinner */
492
+
493
+ @keyframes jBoxLoading {
494
+ to {transform: rotate(360deg);}
495
+ }
496
+
497
+ @-webkit-keyframes jBoxLoading {
498
+ to {-webkit-transform: rotate(360deg);}
499
+ }
500
+
501
+ .jBox-loading .jBox-content {
502
+ min-height: 32px;
503
+ min-width: 38px;
504
+ opacity: 0;
505
+ }
506
+
507
+ .jBox-spinner {
508
+ position: absolute;
509
+ top: 50%;
510
+ left: 50%;
511
+ width: 20px;
512
+ height: 20px;
513
+ margin-top: -10px;
514
+ margin-left: -10px;
515
+ }
516
+
517
+ .jBox-spinner:before {
518
+ content: 'Loading…';
519
+ display: block;
520
+ width: 20px;
521
+ height: 20px;
522
+ text-align: center;
523
+ -webkit-box-sizing: border-box;
524
+ box-sizing: border-box;
525
+ }
526
+
527
+ .jBox-spinner:not(:required):before {
528
+ content: '';
529
+ border-radius: 50%;
530
+ border: 2px solid rgba(0, 0, 0, .3);
531
+ border-top-color: rgba(0, 0, 0, .6);
532
+ animation: jBoxLoading .6s linear infinite;
533
+ -webkit-animation: jBoxLoading .6s linear infinite;
534
+ }
535
+
536
+ /* IE8 fixes */
537
+
538
+ .jBox-IE8.jBox-Tooltip .jBox-container,
539
+ .jBox-IE8.jBox-Mouse .jBox-container {
540
+ border: 1px solid #aaa;
541
+ }
542
+
543
+ .jBox-IE8 .jBox-pointer:after {
544
+ display: none;
545
+ }
546
+
547
+ .jBox-IE8 .jBox-pointer {
548
+ border: 0;
549
+ background: no-repeat url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAYAAACN1PRVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPJJREFUeNq01l0OwyAIAGAlvY+n8ZJ6Gk/EqqkNtf7ApCQ+LM34iuCmRUQzihjj6FH+kjWL8N4/Ph9GHpiTnC9SwDbhLGyvspSScc71KkOa/HpuuRhIK+psE2pjONouCQg7kBSEXUgC2tHo52mTTBpnaEATWlaYK6MrhIAaceWpOcsCrYp6FV4H/90zTWjUQ/gSevVQq0ecHqoOxWpYoO7p5O9ku2fnVtp7QAik2rsK3fnpWfjynJWpbw+1BkghurrYDjiCptg/4AxaYhJwBbEwDsiB2NgM5EIirAdKIDFGQSmU1+NaIPjJYt2I25vxT4ABAMhWvtle2YvmAAAAAElFTkSuQmCC);
550
+ }
551
+
552
+ .jBox-IE8 .jBox-pointer-top { background-position: center top; }
553
+ .jBox-IE8 .jBox-pointer-bottom { background-position: center bottom; }
554
+ .jBox-IE8 .jBox-pointer-left { background-position: left center; }
555
+ .jBox-IE8 .jBox-pointer-right { background-position: right center; }
556
+
557
+ .jBox-IE8.jBox-Modal .jBox-container {
558
+ border: 3px solid #aaa;
559
+ }
560
+
561
+ /* No SVG support fixes */
562
+
563
+ .jBox-nosvg .jBox-closeButton:before {
564
+ font-family: Verdana, sans-serif;
565
+ content: 'x';
566
+ text-align: center;
567
+ font-size: 18px;
568
+ color: #888;
569
+ }
media/css/jbox/themes/ModalBorder.css CHANGED
@@ -1,46 +1,46 @@
1
-
2
- /* Wrapper */
3
-
4
- .jBox-ModalBorder {
5
- border-radius: 8px;
6
- background: rgba(0, 0, 0, .4);
7
- padding: 8px;
8
- box-shadow: 0 0 6px rgba(0, 0, 0, .2);
9
- }
10
-
11
- /* Container */
12
-
13
- .jBox-ModalBorder .jBox-container {
14
- border-radius: 5px;
15
- box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
16
- }
17
-
18
- /* Close button */
19
-
20
- .jBox-ModalBorder.jBox-closeButton-box {
21
- border-top-right-radius: 0;
22
- }
23
-
24
- .jBox-ModalBorder.jBox-closeButton-box:before {
25
- display: none;
26
- }
27
-
28
- .jBox-ModalBorder.jBox-hasTitle.jBox-closeButton-box .jBox-closeButton,
29
- .jBox-ModalBorder.jBox-closeButton-box .jBox-closeButton {
30
- background: rgba(0, 0, 0, .4);
31
- border-radius: 0 50% 50% 0;
32
- right: -32px;
33
- top: -8px;
34
- }
35
-
36
- .jBox-ModalBorder.jBox-closeButton-box .jBox-closeButton path {
37
- fill: #d2d4d6;
38
- }
39
-
40
- .jBox-ModalBorder.jBox-closeButton-box .jBox-closeButton:hover path {
41
- fill: #fff;
42
- }
43
-
44
- .jBox-ModalBorder.jBox-closeButton-box .jBox-closeButton:active path {
45
- fill: #b2b4b6;
46
  }
1
+
2
+ /* Wrapper */
3
+
4
+ .jBox-ModalBorder {
5
+ border-radius: 8px;
6
+ background: rgba(0, 0, 0, .4);
7
+ padding: 8px;
8
+ box-shadow: 0 0 6px rgba(0, 0, 0, .2);
9
+ }
10
+
11
+ /* Container */
12
+
13
+ .jBox-ModalBorder .jBox-container {
14
+ border-radius: 5px;
15
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
16
+ }
17
+
18
+ /* Close button */
19
+
20
+ .jBox-ModalBorder.jBox-closeButton-box {
21
+ border-top-right-radius: 0;
22
+ }
23
+
24
+ .jBox-ModalBorder.jBox-closeButton-box:before {
25
+ display: none;
26
+ }
27
+
28
+ .jBox-ModalBorder.jBox-hasTitle.jBox-closeButton-box .jBox-closeButton,
29
+ .jBox-ModalBorder.jBox-closeButton-box .jBox-closeButton {
30
+ background: rgba(0, 0, 0, .4);
31
+ border-radius: 0 50% 50% 0;
32
+ right: -32px;
33
+ top: -8px;
34
+ }
35
+
36
+ .jBox-ModalBorder.jBox-closeButton-box .jBox-closeButton path {
37
+ fill: #d2d4d6;
38
+ }
39
+
40
+ .jBox-ModalBorder.jBox-closeButton-box .jBox-closeButton:hover path {
41
+ fill: #fff;
42
+ }
43
+
44
+ .jBox-ModalBorder.jBox-closeButton-box .jBox-closeButton:active path {
45
+ fill: #b2b4b6;
46
  }
media/css/jbox/themes/NoticeBorder.css CHANGED
@@ -1,45 +1,45 @@
1
-
2
- /* jBox: Notice */
3
-
4
- .jBox-NoticeBorder .jBox-container {
5
- border-radius: 6px;
6
- }
7
-
8
- .jBox-NoticeBorder .jBox-content,
9
- .jBox-NoticeBorder .jBox-title {
10
- padding-left: 26px;
11
- }
12
-
13
- .jBox-NoticeBorder.jBox-Notice-color .jBox-container {
14
- color: #fff;
15
- text-shadow: 0 -1px 0 #000;
16
- background: rgba(0, 0, 0, .92);
17
- }
18
-
19
- .jBox-NoticeBorder.jBox-Notice-color .jBox-container:after {
20
- content: '';
21
- position: absolute;
22
- top: 0;
23
- left: 0;
24
- bottom: 0;
25
- width: 8px;
26
- border-radius: 5px 0 0 5px;
27
- background-image: linear-gradient(45deg, rgba(255, 255, 255, .5) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .5) 50%, rgba(255, 255, 255, .5) 75%, transparent 75%, transparent);
28
- background-size: 18px 18px;
29
- }
30
-
31
- .jBox-NoticeBorder.jBox-Notice-red .jBox-container:after {
32
- background-color: #ee0000;
33
- }
34
-
35
- .jBox-NoticeBorder.jBox-Notice-green .jBox-container:after {
36
- background-color: #95cc2a;
37
- }
38
-
39
- .jBox-NoticeBorder.jBox-Notice-blue .jBox-container:after {
40
- background-color: #4cb4ff;
41
- }
42
-
43
- .jBox-NoticeBorder.jBox-Notice-yellow .jBox-container:after {
44
- background-color: #ffba00;
45
  }
1
+
2
+ /* jBox: Notice */
3
+
4
+ .jBox-NoticeBorder .jBox-container {
5
+ border-radius: 6px;
6
+ }
7
+
8
+ .jBox-NoticeBorder .jBox-content,
9
+ .jBox-NoticeBorder .jBox-title {
10
+ padding-left: 26px;
11
+ }
12
+
13
+ .jBox-NoticeBorder.jBox-Notice-color .jBox-container {
14
+ color: #fff;
15
+ text-shadow: 0 -1px 0 #000;
16
+ background: rgba(0, 0, 0, .92);
17
+ }
18
+
19
+ .jBox-NoticeBorder.jBox-Notice-color .jBox-container:after {
20
+ content: '';
21
+ position: absolute;
22
+ top: 0;
23
+ left: 0;
24
+ bottom: 0;
25
+ width: 8px;
26
+ border-radius: 5px 0 0 5px;
27
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .5) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .5) 50%, rgba(255, 255, 255, .5) 75%, transparent 75%, transparent);
28
+ background-size: 18px 18px;
29
+ }
30
+
31
+ .jBox-NoticeBorder.jBox-Notice-red .jBox-container:after {
32
+ background-color: #ee0000;
33
+ }
34
+
35
+ .jBox-NoticeBorder.jBox-Notice-green .jBox-container:after {
36
+ background-color: #95cc2a;
37
+ }
38
+
39
+ .jBox-NoticeBorder.jBox-Notice-blue .jBox-container:after {
40
+ background-color: #4cb4ff;
41
+ }
42
+
43
+ .jBox-NoticeBorder.jBox-Notice-yellow .jBox-container:after {
44
+ background-color: #ffba00;
45
  }
media/css/jbox/themes/TooltipBorder.css CHANGED
@@ -1,33 +1,33 @@
1
-
2
- /* Container */
3
-
4
- .jBox-TooltipBorder .jBox-container {
5
- border-radius: 5px;
6
- border: 2px solid #52a2cb;
7
- }
8
-
9
- /* Pointer */
10
-
11
- .jBox-TooltipBorder .jBox-pointer:after {
12
- border: 2px solid #52a2cb;
13
- }
14
-
15
- .jBox-TooltipBorder .jBox-pointer-top,
16
- .jBox-TooltipBorder .jBox-pointer-bottom {
17
- width: 34px;
18
- height: 12px;
19
- }
20
-
21
- .jBox-TooltipBorder .jBox-pointer-left,
22
- .jBox-TooltipBorder .jBox-pointer-right {
23
- width: 12px;
24
- height: 34px;
25
- }
26
-
27
- /* Close button */
28
-
29
- .jBox-TooltipBorder.jBox-closeButton-box:before {
30
- width: 28px;
31
- height: 28px;
32
- background: #52a2cb;
33
  }
1
+
2
+ /* Container */
3
+
4
+ .jBox-TooltipBorder .jBox-container {
5
+ border-radius: 5px;
6
+ border: 2px solid #52a2cb;
7
+ }
8
+
9
+ /* Pointer */
10
+
11
+ .jBox-TooltipBorder .jBox-pointer:after {
12
+ border: 2px solid #52a2cb;
13
+ }
14
+
15
+ .jBox-TooltipBorder .jBox-pointer-top,
16
+ .jBox-TooltipBorder .jBox-pointer-bottom {
17
+ width: 34px;
18
+ height: 12px;
19
+ }
20
+
21
+ .jBox-TooltipBorder .jBox-pointer-left,
22
+ .jBox-TooltipBorder .jBox-pointer-right {
23
+ width: 12px;
24
+ height: 34px;
25
+ }
26
+
27
+ /* Close button */
28
+
29
+ .jBox-TooltipBorder.jBox-closeButton-box:before {
30
+ width: 28px;
31
+ height: 28px;
32
+ background: #52a2cb;
33
  }
media/css/jbox/themes/TooltipDark.css CHANGED
@@ -1,37 +1,37 @@
1
-
2
- /* Container */
3
-
4
- .jBox-TooltipDark .jBox-container {
5
- border-radius: 3px;
6
- background: #222;
7
- color: #fff;
8
- box-shadow: 0 0 6px rgba(0, 0, 0, .4);
9
- }
10
-
11
- /* Pointer */
12
-
13
- .jBox-TooltipDark .jBox-pointer:after {
14
- background: #222;
15
- }
16
-
17
- /* Close button */
18
-
19
- .jBox-TooltipDark .jBox-closeButton {
20
- background: #222;
21
- }
22
-
23
- .jBox-TooltipDark.jBox-closeButton-box:before {
24
- box-shadow: 0 0 6px rgba(0, 0, 0, .4);
25
- }
26
-
27
- .jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton path {
28
- fill: #d2d4d6;
29
- }
30
-
31
- .jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:hover path {
32
- fill: #fff;
33
- }
34
-
35
- .jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:active path {
36
- fill: #b2b4b6;
37
  }
1
+
2
+ /* Container */
3
+
4
+ .jBox-TooltipDark .jBox-container {
5
+ border-radius: 3px;
6
+ background: #222;
7
+ color: #fff;
8
+ box-shadow: 0 0 6px rgba(0, 0, 0, .4);
9
+ }
10
+
11
+ /* Pointer */
12
+
13
+ .jBox-TooltipDark .jBox-pointer:after {
14
+ background: #222;
15
+ }
16
+
17
+ /* Close button */
18
+
19
+ .jBox-TooltipDark .jBox-closeButton {
20
+ background: #222;
21
+ }
22
+
23
+ .jBox-TooltipDark.jBox-closeButton-box:before {
24
+ box-shadow: 0 0 6px rgba(0, 0, 0, .4);
25
+ }
26
+
27
+ .jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton path {
28
+ fill: #d2d4d6;
29
+ }
30
+
31
+ .jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:hover path {
32
+ fill: #fff;
33
+ }
34
+
35
+ .jBox-TooltipDark.jBox-closeButton-box .jBox-closeButton:active path {
36
+ fill: #b2b4b6;
37
  }
media/css/jquery-ui-1.10.0.custom.min.css CHANGED
@@ -1,5 +1,5 @@
1
- /*! jQuery UI - v1.10.0 - 2013-01-25
2
- * http://jqueryui.com
3
- * Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
4
- * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
5
  * Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;min-height:0}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:21px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;width:100%}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;min-height:0;font-weight:normal}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("images/animated-overlay.gif");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#1c94c4}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#1c94c4;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #fbcb09;background:#fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#c77405}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#c77405;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #fbd850;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#eb8f00}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#eb8f00;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fed22f;background:#ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px;background-position:16px 16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_ffffff_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_228ef1_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_ffd27a_256x240.png)}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);border-radius:5px}
1
+ /*! jQuery UI - v1.10.0 - 2013-01-25
2
+ * http://jqueryui.com
3
+ * Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
4
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
5
  * Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;min-height:0}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:21px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;width:100%}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;min-height:0;font-weight:normal}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("images/animated-overlay.gif");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#1c94c4}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#1c94c4;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #fbcb09;background:#fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#c77405}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#c77405;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #fbd850;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#eb8f00}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#eb8f00;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fed22f;background:#ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px;background-position:16px 16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_ffffff_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_228ef1_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_ffd27a_256x240.png)}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);border-radius:5px}
media/css/jquery.ui.timepicker.css CHANGED
@@ -1,57 +1,57 @@
1
- /*
2
- * Timepicker stylesheet
3
- * Highly inspired from datepicker
4
- * FG - Nov 2010 - Web3R
5
- *
6
- * version 0.0.3 : Fixed some settings, more dynamic
7
- * version 0.0.4 : Removed width:100% on tables
8
- * version 0.1.1 : set width 0 on tables to fix an ie6 bug
9
- */
10
-
11
- .ui-timepicker-inline { display: inline; }
12
-
13
- #ui-timepicker-div { padding: 0.2em; }
14
- .ui-timepicker-table { display: inline-table; width: 0; }
15
- .ui-timepicker-table table { margin:0.15em 0 0 0; border-collapse: collapse; }
16
-
17
- .ui-timepicker-hours, .ui-timepicker-minutes { padding: 0.2em; }
18
-
19
- .ui-timepicker-table .ui-timepicker-title { line-height: 1.8em; text-align: center; }
20
- .ui-timepicker-table td { padding: 0.1em; width: 2.2em; }
21
- .ui-timepicker-table th.periods { padding: 0.1em; width: 2.2em; }
22
-
23
- /* span for disabled cells */
24
- .ui-timepicker-table td span {
25
- display:block;
26
- padding:0.2em 0.3em 0.2em 0.5em;
27
- width: 1.2em;
28
-
29
- text-align:right;
30
- text-decoration:none;
31
- }
32
- /* anchors for clickable cells */
33
- .ui-timepicker-table td a {
34
- display:block;
35
- padding:0.2em 0.3em 0.2em 0.5em;
36
- width: 1.2em;
37
- cursor: pointer;
38
- text-align:right;
39
- text-decoration:none;
40
- }
41
-
42
-
43
- /* buttons and button pane styling */
44
- .ui-timepicker .ui-timepicker-buttonpane {
45
- background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0;
46
- }
47
- .ui-timepicker .ui-timepicker-buttonpane button { margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
48
- /* The close button */
49
- .ui-timepicker .ui-timepicker-close { float: right }
50
-
51
- /* the now button */
52
- .ui-timepicker .ui-timepicker-now { float: left; }
53
-
54
- /* the deselect button */
55
- .ui-timepicker .ui-timepicker-deselect { float: left; }
56
-
57
-
1
+ /*
2
+ * Timepicker stylesheet
3
+ * Highly inspired from datepicker
4
+ * FG - Nov 2010 - Web3R
5
+ *
6
+ * version 0.0.3 : Fixed some settings, more dynamic
7
+ * version 0.0.4 : Removed width:100% on tables
8
+ * version 0.1.1 : set width 0 on tables to fix an ie6 bug
9
+ */
10
+
11
+ .ui-timepicker-inline { display: inline; }
12
+
13
+ #ui-timepicker-div { padding: 0.2em; }
14
+ .ui-timepicker-table { display: inline-table; width: 0; }
15
+ .ui-timepicker-table table { margin:0.15em 0 0 0; border-collapse: collapse; }
16
+
17
+ .ui-timepicker-hours, .ui-timepicker-minutes { padding: 0.2em; }
18
+
19
+ .ui-timepicker-table .ui-timepicker-title { line-height: 1.8em; text-align: center; }
20
+ .ui-timepicker-table td { padding: 0.1em; width: 2.2em; }
21
+ .ui-timepicker-table th.periods { padding: 0.1em; width: 2.2em; }
22
+
23
+ /* span for disabled cells */
24
+ .ui-timepicker-table td span {
25
+ display:block;
26
+ padding:0.2em 0.3em 0.2em 0.5em;
27
+ width: 1.2em;
28
+
29
+ text-align:right;
30
+ text-decoration:none;
31
+ }
32
+ /* anchors for clickable cells */
33
+ .ui-timepicker-table td a {
34
+ display:block;
35
+ padding:0.2em 0.3em 0.2em 0.5em;
36
+ width: 1.2em;
37
+ cursor: pointer;
38
+ text-align:right;
39
+ text-decoration:none;
40
+ }
41
+
42
+
43
+ /* buttons and button pane styling */
44
+ .ui-timepicker .ui-timepicker-buttonpane {
45
+ background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0;
46
+ }
47
+ .ui-timepicker .ui-timepicker-buttonpane button { margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
48
+ /* The close button */
49
+ .ui-timepicker .ui-timepicker-close { float: right }
50
+
51
+ /* the now button */
52
+ .ui-timepicker .ui-timepicker-now { float: left; }
53
+
54
+ /* the deselect button */
55
+ .ui-timepicker .ui-timepicker-deselect { float: left; }
56
+
57
+
media/css/spectrum.css CHANGED
@@ -1,507 +1,507 @@
1
- /***
2
- Spectrum Colorpicker v1.8.1
3
- https://github.com/bgrins/spectrum
4
- Author: Brian Grinstead
5
- License: MIT
6
- ***/
7
-
8
- .sp-container {
9
- position:absolute;
10
- top:0;
11
- left:0;
12
- display:inline-block;
13
- *display: inline;
14
- *zoom: 1;
15
- /* https://github.com/bgrins/spectrum/issues/40 */
16
- z-index: 9999994;
17
- overflow: hidden;
18
- }
19
- .sp-container.sp-flat {
20
- position: relative;
21
- }
22
-
23
- /* Fix for * { box-sizing: border-box; } */
24
- .sp-container,
25
- .sp-container * {
26
- -webkit-box-sizing: content-box;
27
- -moz-box-sizing: content-box;
28
- box-sizing: content-box;
29
- }
30
-
31
- /* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */
32
- .sp-top {
33
- position:relative;
34
- width: 100%;
35
- display:inline-block;
36
- }
37
- .sp-top-inner {
38
- position:absolute;
39
- top:0;
40
- left:0;
41
- bottom:0;
42
- right:0;
43
- }
44
- .sp-color {
45
- position: absolute;
46
- top:0;
47
- left:0;
48
- bottom:0;
49
- right:20%;
50
- }
51
- .sp-hue {
52
- position: absolute;
53
- top:0;
54
- right:0;
55
- bottom:0;
56
- left:84%;
57
- height: 100%;
58
- }
59
-
60
- .sp-clear-enabled .sp-hue {
61
- top:33px;
62
- height: 77.5%;
63
- }
64
-
65
- .sp-fill {
66
- padding-top: 80%;
67
- }
68
- .sp-sat, .sp-val {
69
- position: absolute;
70
- top:0;
71
- left:0;
72
- right:0;
73
- bottom:0;
74
- }
75
-
76
- .sp-alpha-enabled .sp-top {
77
- margin-bottom: 18px;
78
- }
79
- .sp-alpha-enabled .sp-alpha {
80
- display: block;
81
- }
82
- .sp-alpha-handle {
83
- position:absolute;
84
- top:-4px;
85
- bottom: -4px;
86
- width: 6px;
87
- left: 50%;
88
- cursor: pointer;
89
- border: 1px solid black;
90
- background: white;
91
- opacity: .8;
92
- }
93
- .sp-alpha {
94
- display: none;
95
- position: absolute;
96
- bottom: -14px;
97
- right: 0;
98
- left: 0;
99
- height: 8px;
100
- }
101
- .sp-alpha-inner {
102
- border: solid 1px #333;
103
- }
104
-
105
- .sp-clear {
106
- display: none;
107
- }
108
-
109
- .sp-clear.sp-clear-display {
110
- background-position: center;
111
- }
112
-
113
- .sp-clear-enabled .sp-clear {
114
- display: block;
115
- position:absolute;
116
- top:0px;
117
- right:0;
118
- bottom:0;
119
- left:84%;
120
- height: 28px;
121
- }
122
-
123
- /* Don't allow text selection */
124
- .sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button {
125
- -webkit-user-select:none;
126
- -moz-user-select: -moz-none;
127
- -o-user-select:none;
128
- user-select: none;
129
- }
130
-
131
- .sp-container.sp-input-disabled .sp-input-container {
132
- display: none;
133
- }
134
- .sp-container.sp-buttons-disabled .sp-button-container {
135
- display: none;
136
- }
137
- .sp-container.sp-palette-buttons-disabled .sp-palette-button-container {
138
- display: none;
139
- }
140
- .sp-palette-only .sp-picker-container {
141
- display: none;
142
- }
143
- .sp-palette-disabled .sp-palette-container {
144
- display: none;
145
- }
146
-
147
- .sp-initial-disabled .sp-initial {
148
- display: none;
149
- }
150
-
151
-
152
- /* Gradients for hue, saturation and value instead of images. Not pretty... but it works */
153
- .sp-sat {
154
- background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));
155
- background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));
156
- background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
157
- background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
158
- background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
159
- background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));
160
- -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)";
161
- filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');
162
- }
163
- .sp-val {
164
- background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));
165
- background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0));
166
- background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
167
- background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
168
- background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
169
- background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));
170
- -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)";
171
- filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');
172
- }
173
-
174
- .sp-hue {
175
- background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
176
- background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
177
- background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
178
- background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000));
179
- background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
180
- background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
181
- }
182
-
183
- /* IE filters do not support multiple color stops.
184
- Generate 6 divs, line them up, and do two color gradients for each.
185
- Yes, really.
186
- */
187
- .sp-1 {
188
- height:17%;
189
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');
190
- }
191
- .sp-2 {
192
- height:16%;
193
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');
194
- }
195
- .sp-3 {
196
- height:17%;
197
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');
198
- }
199
- .sp-4 {
200
- height:17%;
201
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');
202
- }
203
- .sp-5 {
204
- height:16%;
205
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');
206
- }
207
- .sp-6 {
208
- height:17%;
209
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');
210
- }
211
-
212
- .sp-hidden {
213
- display: none !important;
214
- }
215
-
216
- /* Clearfix hack */
217
- .sp-cf:before, .sp-cf:after { content: ""; display: table; }
218
- .sp-cf:after { clear: both; }
219
- .sp-cf { *zoom: 1; }
220
-
221
- /* Mobile devices, make hue slider bigger so it is easier to slide */
222
- @media (max-device-width: 480px) {
223
- .sp-color { right: 40%; }
224
- .sp-hue { left: 63%; }
225
- .sp-fill { padding-top: 60%; }
226
- }
227
- .sp-dragger {
228
- border-radius: 5px;
229
- height: 5px;
230
- width: 5px;
231
- border: 1px solid #fff;
232
- background: #000;
233
- cursor: pointer;
234
- position:absolute;
235
- top:0;
236
- left: 0;
237
- }
238
- .sp-slider {
239
- position: absolute;
240
- top:0;
241
- cursor:pointer;
242
- height: 3px;
243
- left: -1px;
244
- right: -1px;
245
- border: 1px solid #000;
246
- background: white;
247
- opacity: .8;
248
- }
249
-
250
- /*
251
- Theme authors:
252
- Here are the basic themeable display options (colors, fonts, global widths).
253
- See http://bgrins.github.io/spectrum/themes/ for instructions.
254
- */
255
-
256
- .sp-container {
257
- border-radius: 0;
258
- background-color: #ECECEC;
259
- border: solid 1px #f0c49B;
260
- padding: 0;
261
- }
262
- .sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear {
263
- font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
264
- -webkit-box-sizing: border-box;
265
- -moz-box-sizing: border-box;
266
- -ms-box-sizing: border-box;
267
- box-sizing: border-box;
268
- }
269
- .sp-top {
270
- margin-bottom: 3px;
271
- }
272
- .sp-color, .sp-hue, .sp-clear {
273
- border: solid 1px #666;
274
- }
275
-
276
- /* Input */
277
- .sp-input-container {
278
- float:right;
279
- width: 100px;
280
- margin-bottom: 4px;
281
- }
282
- .sp-initial-disabled .sp-input-container {
283
- width: 100%;
284
- }
285
- .sp-input {
286
- font-size: 12px !important;
287
- border: 1px inset;
288
- padding: 4px 5px;
289
- margin: 0;
290
- width: 100%;
291
- background:transparent;
292
- border-radius: 3px;
293
- color: #222;
294
- }
295
- .sp-input:focus {
296
- border: 1px solid orange;
297
- }
298
- .sp-input.sp-validation-error {
299
- border: 1px solid red;
300
- background: #fdd;
301
- }
302
- .sp-picker-container , .sp-palette-container {
303
- float:left;
304
- position: relative;
305
- padding: 10px;
306
- padding-bottom: 300px;
307
- margin-bottom: -290px;
308
- }
309
- .sp-picker-container {
310
- width: 172px;
311
- border-left: solid 1px #fff;
312
- }
313
-
314
- /* Palettes */
315
- .sp-palette-container {
316
- border-right: solid 1px #ccc;
317
- }
318
-
319
- .sp-palette-only .sp-palette-container {
320
- border: 0;
321
- }
322
-
323
- .sp-palette .sp-thumb-el {
324
- display: block;
325
- position:relative;
326
- float:left;
327
- width: 24px;
328
- height: 15px;
329
- margin: 3px;
330
- cursor: pointer;
331
- border:solid 2px transparent;
332
- }
333
- .sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {
334
- border-color: orange;
335
- }
336
- .sp-thumb-el {
337
- position:relative;
338
- }
339
-
340
- /* Initial */
341
- .sp-initial {
342
- float: left;
343
- border: solid 1px #333;
344
- }
345
- .sp-initial span {
346
- width: 30px;
347
- height: 25px;
348
- border:none;
349
- display:block;
350
- float:left;
351
- margin:0;
352
- }
353
-
354
- .sp-initial .sp-clear-display {
355
- background-position: center;
356
- }
357
-
358
- /* Buttons */
359
- .sp-palette-button-container,
360
- .sp-button-container {
361
- float: right;
362
- }
363
-
364
- /* Replacer (the little preview div that shows up instead of the <input>) */
365
- .sp-replacer {
366
- margin:0;
367
- overflow:hidden;
368
- cursor:pointer;
369
- padding: 4px;
370
- display:inline-block;
371
- *zoom: 1;
372
- *display: inline;
373
- border: solid 1px #91765d;
374
- background: #eee;
375
- color: #333;
376
- vertical-align: middle;
377
- }
378
- .sp-replacer:hover, .sp-replacer.sp-active {
379
- border-color: #F0C49B;
380
- color: #111;
381
- }
382
- .sp-replacer.sp-disabled {
383
- cursor:default;
384
- border-color: silver;
385
- color: silver;
386
- }
387
- .sp-dd {
388
- padding: 2px 0;
389
- height: 16px;
390
- line-height: 16px;
391
- float:left;
392
- font-size:10px;
393
- }
394
- .sp-preview {
395
- position:relative;
396
- width:25px;
397
- height: 20px;
398
- border: solid 1px #222;
399
- margin-right: 5px;
400
- float:left;
401
- z-index: 0;
402
- }
403
-
404
- .sp-palette {
405
- *width: 220px;
406
- max-width: 220px;
407
- }
408
- .sp-palette .sp-thumb-el {
409
- width:16px;
410
- height: 16px;
411
- margin:2px 1px;
412
- border: solid 1px #d0d0d0;
413
- }
414
-
415
- .sp-container {
416
- padding-bottom:0;
417
- }
418
-
419
-
420
- /* Buttons: http://hellohappy.org/css3-buttons/ */
421
- .sp-container button {
422
- background-color: #eeeeee;
423
- background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);
424
- background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);
425
- background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);
426
- background-image: -o-linear-gradient(top, #eeeeee, #cccccc);
427
- background-image: linear-gradient(to bottom, #eeeeee, #cccccc);
428
- border: 1px solid #ccc;
429
- border-bottom: 1px solid #bbb;
430
- border-radius: 3px;
431
- color: #333;
432
- font-size: 14px;
433
- line-height: 1;
434
- padding: 5px 4px;
435
- text-align: center;
436
- text-shadow: 0 1px 0 #eee;
437
- vertical-align: middle;
438
- }
439
- .sp-container button:hover {
440
- background-color: #dddddd;
441
- background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);
442
- background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);
443
- background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);
444
- background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);
445
- background-image: linear-gradient(to bottom, #dddddd, #bbbbbb);
446
- border: 1px solid #bbb;
447
- border-bottom: 1px solid #999;
448
- cursor: pointer;
449
- text-shadow: 0 1px 0 #ddd;
450
- }
451
- .sp-container button:active {
452
- border: 1px solid #aaa;
453
- border-bottom: 1px solid #888;
454
- -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
455
- -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
456
- -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
457
- -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
458
- box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
459
- }
460
- .sp-cancel {
461
- font-size: 11px;
462
- color: #d93f3f !important;
463
- margin:0;
464
- padding:2px;
465
- margin-right: 5px;
466
- vertical-align: middle;
467
- text-decoration:none;
468
-
469
- }
470
- .sp-cancel:hover {
471
- color: #d93f3f !important;
472
- text-decoration: underline;
473
- }
474
-
475
-
476
- .sp-palette span:hover, .sp-palette span.sp-thumb-active {
477
- border-color: #000;
478
- }
479
-
480
- .sp-preview, .sp-alpha, .sp-thumb-el {
481
- position:relative;
482
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
483
- }
484
- .sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner {
485
- display:block;
486
- position:absolute;
487
- top:0;left:0;bottom:0;right:0;
488
- }
489
-
490
- .sp-palette .sp-thumb-inner {
491
- background-position: 50% 50%;
492
- background-repeat: no-repeat;
493
- }
494
-
495
- .sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner {
496
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);
497
- }
498
-
499
- .sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner {
500
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);
501
- }
502
-
503
- .sp-clear-display {
504
- background-repeat:no-repeat;
505
- background-position: center;
506
- background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==);
507
- }
1
+ /***
2
+ Spectrum Colorpicker v1.8.1
3
+ https://github.com/bgrins/spectrum
4
+ Author: Brian Grinstead
5
+ License: MIT
6
+ ***/
7
+
8
+ .sp-container {
9
+ position:absolute;
10
+ top:0;
11
+ left:0;
12
+ display:inline-block;
13
+ *display: inline;
14
+ *zoom: 1;
15
+ /* https://github.com/bgrins/spectrum/issues/40 */
16
+ z-index: 9999994;
17
+ overflow: hidden;
18
+ }
19
+ .sp-container.sp-flat {
20
+ position: relative;
21
+ }
22
+
23
+ /* Fix for * { box-sizing: border-box; } */
24
+ .sp-container,
25
+ .sp-container * {
26
+ -webkit-box-sizing: content-box;
27
+ -moz-box-sizing: content-box;
28
+ box-sizing: content-box;
29
+ }
30
+
31
+ /* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */
32
+ .sp-top {
33
+ position:relative;
34
+ width: 100%;
35
+ display:inline-block;
36
+ }
37
+ .sp-top-inner {
38
+ position:absolute;
39
+ top:0;
40
+ left:0;
41
+ bottom:0;
42
+ right:0;
43
+ }
44
+ .sp-color {
45
+ position: absolute;
46
+ top:0;
47
+ left:0;
48
+ bottom:0;
49
+ right:20%;
50
+ }
51
+ .sp-hue {
52
+ position: absolute;
53
+ top:0;
54
+ right:0;
55
+ bottom:0;
56
+ left:84%;
57
+ height: 100%;
58
+ }
59
+
60
+ .sp-clear-enabled .sp-hue {
61
+ top:33px;
62
+ height: 77.5%;
63
+ }
64
+
65
+ .sp-fill {
66
+ padding-top: 80%;
67
+ }
68
+ .sp-sat, .sp-val {
69
+ position: absolute;
70
+ top:0;
71
+ left:0;
72
+ right:0;
73
+ bottom:0;
74
+ }
75
+
76
+ .sp-alpha-enabled .sp-top {
77
+ margin-bottom: 18px;
78
+ }
79
+ .sp-alpha-enabled .sp-alpha {
80
+ display: block;
81
+ }
82
+ .sp-alpha-handle {
83
+ position:absolute;
84
+ top:-4px;
85
+ bottom: -4px;
86
+ width: 6px;
87
+ left: 50%;
88
+ cursor: pointer;
89
+ border: 1px solid black;
90
+ background: white;
91
+ opacity: .8;
92
+ }
93
+ .sp-alpha {
94
+ display: none;
95
+ position: absolute;
96
+ bottom: -14px;
97
+ right: 0;
98
+ left: 0;
99
+ height: 8px;
100
+ }
101
+ .sp-alpha-inner {
102
+ border: solid 1px #333;
103
+ }
104
+
105
+ .sp-clear {
106
+ display: none;
107
+ }
108
+
109
+ .sp-clear.sp-clear-display {
110
+ background-position: center;
111
+ }
112
+
113
+ .sp-clear-enabled .sp-clear {
114
+ display: block;
115
+ position:absolute;
116
+ top:0px;
117
+ right:0;
118
+ bottom:0;
119
+ left:84%;
120
+ height: 28px;
121
+ }
122
+
123
+ /* Don't allow text selection */
124
+ .sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button {
125
+ -webkit-user-select:none;
126
+ -moz-user-select: -moz-none;
127
+ -o-user-select:none;
128
+ user-select: none;
129
+ }
130
+
131
+ .sp-container.sp-input-disabled .sp-input-container {
132
+ display: none;
133
+ }
134
+ .sp-container.sp-buttons-disabled .sp-button-container {
135
+ display: none;
136
+ }
137
+ .sp-container.sp-palette-buttons-disabled .sp-palette-button-container {
138
+ display: none;
139
+ }
140
+ .sp-palette-only .sp-picker-container {
141
+ display: none;
142
+ }
143
+ .sp-palette-disabled .sp-palette-container {
144
+ display: none;
145
+ }
146
+
147
+ .sp-initial-disabled .sp-initial {
148
+ display: none;
149
+ }
150
+
151
+
152
+ /* Gradients for hue, saturation and value instead of images. Not pretty... but it works */
153
+ .sp-sat {
154
+ background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));
155
+ background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));
156
+ background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
157
+ background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
158
+ background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
159
+ background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));
160
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)";
161
+ filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');
162
+ }
163
+ .sp-val {
164
+ background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));
165
+ background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0));
166
+ background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
167
+ background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
168
+ background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
169
+ background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));
170
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)";
171
+ filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');
172
+ }
173
+
174
+ .sp-hue {
175
+ background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
176
+ background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
177
+ background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
178
+ background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000));
179
+ background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
180
+ background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
181
+ }
182
+
183
+ /* IE filters do not support multiple color stops.
184
+ Generate 6 divs, line them up, and do two color gradients for each.
185
+ Yes, really.
186
+ */
187
+ .sp-1 {
188
+ height:17%;
189
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');
190
+ }
191
+ .sp-2 {
192
+ height:16%;
193
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');
194
+ }
195
+ .sp-3 {
196
+ height:17%;
197
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');
198
+ }
199
+ .sp-4 {
200
+ height:17%;
201
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');
202
+ }
203
+ .sp-5 {
204
+ height:16%;
205
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');
206
+ }
207
+ .sp-6 {
208
+ height:17%;
209
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');
210
+ }
211
+
212
+ .sp-hidden {
213
+ display: none !important;
214
+ }
215
+
216
+ /* Clearfix hack */
217
+ .sp-cf:before, .sp-cf:after { content: ""; display: table; }
218
+ .sp-cf:after { clear: both; }
219
+ .sp-cf { *zoom: 1; }
220
+
221
+ /* Mobile devices, make hue slider bigger so it is easier to slide */
222
+ @media (max-device-width: 480px) {
223
+ .sp-color { right: 40%; }
224
+ .sp-hue { left: 63%; }
225
+ .sp-fill { padding-top: 60%; }
226
+ }
227
+ .sp-dragger {
228
+ border-radius: 5px;
229
+ height: 5px;
230
+ width: 5px;
231
+ border: 1px solid #fff;
232
+ background: #000;
233
+ cursor: pointer;
234
+ position:absolute;
235
+ top:0;
236
+ left: 0;
237
+ }
238
+ .sp-slider {
239
+ position: absolute;
240
+ top:0;
241
+ cursor:pointer;
242
+ height: 3px;
243
+ left: -1px;
244
+ right: -1px;
245
+ border: 1px solid #000;
246
+ background: white;
247
+ opacity: .8;
248
+ }
249
+
250
+ /*
251
+ Theme authors:
252
+ Here are the basic themeable display options (colors, fonts, global widths).
253
+ See http://bgrins.github.io/spectrum/themes/ for instructions.
254
+ */
255
+
256
+ .sp-container {
257
+ border-radius: 0;
258
+ background-color: #ECECEC;
259
+ border: solid 1px #f0c49B;
260
+ padding: 0;
261
+ }
262
+ .sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear {
263
+ font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
264
+ -webkit-box-sizing: border-box;
265
+ -moz-box-sizing: border-box;
266
+ -ms-box-sizing: border-box;
267
+ box-sizing: border-box;
268
+ }
269
+ .sp-top {
270
+ margin-bottom: 3px;
271
+ }
272
+ .sp-color, .sp-hue, .sp-clear {
273
+ border: solid 1px #666;
274
+ }
275
+
276
+ /* Input */
277
+ .sp-input-container {
278
+ float:right;
279
+ width: 100px;
280
+ margin-bottom: 4px;
281
+ }
282
+ .sp-initial-disabled .sp-input-container {
283
+ width: 100%;
284
+ }
285
+ .sp-input {
286
+ font-size: 12px !important;
287
+ border: 1px inset;
288
+ padding: 4px 5px;
289
+ margin: 0;
290
+ width: 100%;
291
+ background:transparent;
292
+ border-radius: 3px;
293
+ color: #222;
294
+ }
295
+ .sp-input:focus {
296
+ border: 1px solid orange;
297
+ }
298
+ .sp-input.sp-validation-error {
299
+ border: 1px solid red;
300
+ background: #fdd;
301
+ }
302
+ .sp-picker-container , .sp-palette-container {
303
+ float:left;
304
+ position: relative;
305
+ padding: 10px;
306
+ padding-bottom: 300px;
307
+ margin-bottom: -290px;
308
+ }
309
+ .sp-picker-container {
310
+ width: 172px;
311
+ border-left: solid 1px #fff;
312
+ }
313
+
314
+ /* Palettes */
315
+ .sp-palette-container {
316
+ border-right: solid 1px #ccc;
317
+ }
318
+
319
+ .sp-palette-only .sp-palette-container {
320
+ border: 0;
321
+ }
322
+
323
+ .sp-palette .sp-thumb-el {
324
+ display: block;
325
+ position:relative;
326
+ float:left;
327
+ width: 24px;
328
+ height: 15px;
329
+ margin: 3px;
330
+ cursor: pointer;
331
+ border:solid 2px transparent;
332
+ }
333
+ .sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {
334
+ border-color: orange;
335
+ }
336
+ .sp-thumb-el {
337
+ position:relative;
338
+ }
339
+
340
+ /* Initial */
341
+ .sp-initial {
342
+ float: left;
343
+ border: solid 1px #333;
344
+ }
345
+ .sp-initial span {
346
+ width: 30px;
347
+ height: 25px;
348
+ border:none;
349
+ display:block;
350
+ float:left;
351
+ margin:0;
352
+ }
353
+
354
+ .sp-initial .sp-clear-display {
355
+ background-position: center;
356
+ }
357
+
358
+ /* Buttons */
359
+ .sp-palette-button-container,
360
+ .sp-button-container {
361
+ float: right;
362
+ }
363
+
364
+ /* Replacer (the little preview div that shows up instead of the <input>) */
365
+ .sp-replacer {
366
+ margin:0;
367
+ overflow:hidden;
368
+ cursor:pointer;
369
+ padding: 4px;
370
+ display:inline-block;
371
+ *zoom: 1;
372
+ *display: inline;
373
+ border: solid 1px #91765d;
374
+ background: #eee;
375
+ color: #333;
376
+ vertical-align: middle;
377
+ }
378
+ .sp-replacer:hover, .sp-replacer.sp-active {
379
+ border-color: #F0C49B;
380
+ color: #111;
381
+ }
382
+ .sp-replacer.sp-disabled {
383
+ cursor:default;
384
+ border-color: silver;
385
+ color: silver;
386
+ }
387
+ .sp-dd {
388
+ padding: 2px 0;
389
+ height: 16px;
390
+ line-height: 16px;
391
+ float:left;
392
+ font-size:10px;
393
+ }
394
+ .sp-preview {
395
+ position:relative;
396
+ width:25px;
397
+ height: 20px;
398
+ border: solid 1px #222;
399
+ margin-right: 5px;
400
+ float:left;
401
+ z-index: 0;
402
+ }
403
+
404
+ .sp-palette {
405
+ *width: 220px;
406
+ max-width: 220px;
407
+ }
408
+ .sp-palette .sp-thumb-el {
409
+ width:16px;
410
+ height: 16px;
411
+ margin:2px 1px;
412
+ border: solid 1px #d0d0d0;
413
+ }
414
+
415
+ .sp-container {
416
+ padding-bottom:0;
417
+ }
418
+
419
+
420
+ /* Buttons: http://hellohappy.org/css3-buttons/ */
421
+ .sp-container button {
422
+ background-color: #eeeeee;
423
+ background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);
424
+ background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);
425
+ background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);
426
+ background-image: -o-linear-gradient(top, #eeeeee, #cccccc);
427
+ background-image: linear-gradient(to bottom, #eeeeee, #cccccc);
428
+ border: 1px solid #ccc;
429
+ border-bottom: 1px solid #bbb;
430
+ border-radius: 3px;
431
+ color: #333;
432
+ font-size: 14px;
433
+ line-height: 1;
434
+ padding: 5px 4px;
435
+ text-align: center;
436
+ text-shadow: 0 1px 0 #eee;
437
+ vertical-align: middle;
438
+ }
439
+ .sp-container button:hover {
440
+ background-color: #dddddd;
441
+ background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);
442
+ background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);
443
+ background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);
444
+ background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);
445
+ background-image: linear-gradient(to bottom, #dddddd, #bbbbbb);
446
+ border: 1px solid #bbb;
447
+ border-bottom: 1px solid #999;
448
+ cursor: pointer;
449
+ text-shadow: 0 1px 0 #ddd;
450
+ }
451
+ .sp-container button:active {
452
+ border: 1px solid #aaa;
453
+ border-bottom: 1px solid #888;
454
+ -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
455
+ -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
456
+ -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
457
+ -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
458
+ box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
459
+ }
460
+ .sp-cancel {
461
+ font-size: 11px;
462
+ color: #d93f3f !important;
463
+ margin:0;
464
+ padding:2px;
465
+ margin-right: 5px;
466
+ vertical-align: middle;
467
+ text-decoration:none;
468
+
469
+ }
470
+ .sp-cancel:hover {
471
+ color: #d93f3f !important;
472
+ text-decoration: underline;
473
+ }
474
+
475
+
476
+ .sp-palette span:hover, .sp-palette span.sp-thumb-active {
477
+ border-color: #000;
478
+ }
479
+
480
+ .sp-preview, .sp-alpha, .sp-thumb-el {
481
+ position:relative;
482
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
483
+ }
484
+ .sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner {
485
+ display:block;
486
+ position:absolute;
487
+ top:0;left:0;bottom:0;right:0;
488
+ }
489
+
490
+ .sp-palette .sp-thumb-inner {
491
+ background-position: 50% 50%;
492
+ background-repeat: no-repeat;
493
+ }
494
+
495
+ .sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner {
496
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);
497
+ }
498
+
499
+ .sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner {
500
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);
501
+ }
502
+
503
+ .sp-clear-display {
504
+ background-repeat:no-repeat;
505
+ background-position: center;
506
+ background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==);
507
+ }
media/js/blocks/dist/index.js CHANGED
@@ -1 +1 @@
1
- window.wp=window.wp||{},window.wp["./media/js/blocks/dist/index.js"]=function(e){var t={};function n(l){if(t[l])return t[l].exports;var o=t[l]={i:l,l:!1,exports:{}};return e[l].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,l){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:l})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var l=Object.create(null);if(n.r(l),Object.defineProperty(l,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(l,o,function(t){return e[t]}.bind(null,o));return l},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=7)}([function(e,t){e.exports=window.wp.i18n},function(e,t){e.exports=window.lodash},,,,,,function(e,t,n){"use strict";n.r(t);var l=n(1),o=n(0);function a(e){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var n=0;n<t.length;n++){var l=t[n];l.enumerable=l.enumerable||!1,l.configurable=!0,"value"in l&&(l.writable=!0),Object.defineProperty(e,l.key,l)}}function c(e,t){return!t||"object"!==a(t)&&"function"!=typeof t?u(e):t}function u(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function b(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}function p(e){return(p=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function m(e,t){return(m=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var s=wp.element.Component,f=(wp.blockEditor||wp.editor).InspectorControls,_=wp.components,v=_.SelectControl,d=_.CheckboxControl,h=_.PanelBody,y=_.TextControl,O=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&m(e,t)}(O,e);var t,n,a,s,_=(t=O,function(){var e,n=p(t);if(b()){var l=p(this).constructor;e=Reflect.construct(n,arguments,l)}else e=n.apply(this,arguments);return c(this,e)});function O(){var e;return r(this,O),(e=_.apply(this,arguments)).setOptions=e.setOptions.bind(u(e)),e}return n=O,(a=[{key:"setOptions",value:function(e){var t=[];return e&&(t=e.map((function(e){return{value:e.id.toString(),label:Object(l.get)(e,["title","raw"])||Object(l.get)(e,["name"])}}))),t}},{key:"render",value:function(){var e=this.props,t=e.attributes,n=t.col,l=t.events,a=t.event_categ,r=t.increment,i=t.view,c=t.view_sort,u=t.label,b=t.hide_label,p=t.hide_hrs,m=t.hide_empty_rows,s=t.title,_=t.time,O=t.sub_title,j=t.description,g=t.user,w=t.group,C=t.disable_event_url,E=t.text_align,R=t.text_align_vertical,S=t.id,k=t.custom_class,x=t.row_height,T=t.font_size,P=t.responsive,D=t.table_layout,I=e.selectedEvents,N=e.selectedColumns,H=e.selectedEventCategories,z=e.setAttributes;return React.createElement(f,null,React.createElement(h,{title:Object(o.__)("Settings","mp-timetable")},React.createElement(v,{className:"timetable-wp56-fix",multiple:!0,size:"7",label:Object(o.__)("Columns","mp-timetable"),help:Object(o.__)("Hold the Ctrl or Command key to select/deselect multiple options.","mp-timetable"),value:n,onChange:function(e){return z({col:e})},options:this.setOptions(N)}),React.createElement(v,{className:"timetable-wp56-fix",multiple:!0,size:"7",label:Object(o.__)("Specific events","mp-timetable"),help:Object(o.__)("Hold the Ctrl or Command key to select/deselect multiple options.","mp-timetable"),value:l,onChange:function(e){return z({events:e})},options:this.setOptions(I)}),React.createElement(v,{className:"timetable-wp56-fix",multiple:!0,size:"7",label:Object(o.__)("Event categories","mp-timetable"),help:Object(o.__)("Hold the Ctrl or Command key to select/deselect multiple options.","mp-timetable"),value:a,onChange:function(e){return z({event_categ:e})},options:this.setOptions(H)}),React.createElement(d,{label:Object(o.__)("Title","mp-timetable"),checked:"1"==s,onChange:function(e){z({title:e?"1":"0"})}}),React.createElement(d,{label:Object(o.__)("Time","mp-timetable"),checked:"1"==_,onChange:function(e){z({time:e?"1":"0"})}}),React.createElement(d,{label:Object(o.__)("Subtitle","mp-timetable"),checked:"1"==O,onChange:function(e){z({sub_title:e?"1":"0"})}}),React.createElement(d,{label:Object(o.__)("Description","mp-timetable"),checked:"1"==j,onChange:function(e){z({description:e?"1":"0"})}}),React.createElement(d,{label:Object(o.__)("Event Head","mp-timetable"),checked:"1"==g,onChange:function(e){z({user:e?"1":"0"})}}),React.createElement(y,{label:Object(o.__)("Block height in pixels","mp-timetable"),type:"number",value:isNaN(x)?0:parseInt(x),onChange:function(e){z({row_height:e.toString()})},min:1,step:1}),React.createElement(y,{label:Object(o.__)("Base font size","mp-timetable"),help:Object(o.__)("Base font size for the table. Example 12px, 2em, 80%.","mp-timetable"),value:T,onChange:function(e){return z({font_size:e})}}),React.createElement(v,{label:Object(o.__)("Time frame for event","mp-timetable"),value:r,onChange:function(e){return z({increment:e})},options:[{value:"1",label:Object(o.__)("Hour (1h)","mp-timetable")},{value:"0.5",label:Object(o.__)("Half hour (30min)","mp-timetable")},{value:"0.25",label:Object(o.__)("Quarter hour (15min)","mp-timetable")}]}),React.createElement(v,{label:Object(o.__)("Filter events style","mp-timetable"),value:i,onChange:function(e){return z({view:e})},options:[{value:"dropdown_list",label:Object(o.__)("Dropdown list","mp-timetable")},{value:"tabs",label:Object(o.__)("Tabs","mp-timetable")}]}),React.createElement(v,{label:Object(o.__)("Order of items in filter","mp-timetable"),value:c,onChange:function(e){return z({view_sort:e})},options:[{value:"",label:Object(o.__)("Default","mp-timetable")},{value:"menu_order",label:Object(o.__)("Menu Order","mp-timetable")},{value:"post_title",label:Object(o.__)("Title","mp-timetable")}]}),React.createElement(y,{label:Object(o.__)("Filter title to display all events","mp-timetable"),value:u,onChange:function(e){return z({label:e})}}),React.createElement(v,{label:Object(o.__)("Hide 'All Events' option","mp-timetable"),value:b,onChange:function(e){return z({hide_label:e})},options:[{value:"0",label:Object(o.__)("No","mp-timetable")},{value:"1",label:Object(o.__)("Yes","mp-timetable")}]}),React.createElement(v,{label:Object(o.__)("Hide column with hours","mp-timetable"),value:p,onChange:function(e){return z({hide_hrs:e})},options:[{value:"0",label:Object(o.__)("No","mp-timetable")},{value:"1",label:Object(o.__)("Yes","mp-timetable")}]}),React.createElement(v,{label:Object(o.__)("Do not display empty rows","mp-timetable"),value:m,onChange:function(e){return z({hide_empty_rows:e})},options:[{value:"0",label:Object(o.__)("No","mp-timetable")},{value:"1",label:Object(o.__)("Yes","mp-timetable")}]}),React.createElement(v,{label:Object(o.__)("Merge cells with common events","mp-timetable"),value:w,onChange:function(e){return z({group:e})},options:[{value:"0",label:Object(o.__)("No","mp-timetable")},{value:"1",label:Object(o.__)("Yes","mp-timetable")}]}),React.createElement(v,{label:Object(o.__)("Disable event link","mp-timetable"),value:C,onChange:function(e){return z({disable_event_url:e})},options:[{value:"0",label:Object(o.__)("No","mp-timetable")},{value:"1",label:Object(o.__)("Yes","mp-timetable")}]}),React.createElement(v,{label:Object(o.__)("Horizontal align","mp-timetable"),value:E,onChange:function(e){return z({text_align:e})},options:[{value:"center",label:Object(o.__)("center","mp-timetable")},{value:"left",label:Object(o.__)("left","mp-timetable")},{value:"right",label:Object(o.__)("right","mp-timetable")}]}),React.createElement(v,{label:Object(o.__)("Vertical align","mp-timetable"),value:R,onChange:function(e){return z({text_align_vertical:e})},options:[{value:"default",label:Object(o.__)("Default","mp-timetable")},{value:"top",label:Object(o.__)("top","mp-timetable")},{value:"middle",label:Object(o.__)("middle","mp-timetable")},{value:"bottom",label:Object(o.__)("bottom","mp-timetable")}]}),React.createElement(v,{label:Object(o.__)("Column width","mp-timetable"),value:D,onChange:function(e){return z({table_layout:e})},options:[{value:"",label:Object(o.__)("Default","mp-timetable")},{value:"auto",label:Object(o.__)("Auto","mp-timetable")},{value:"fixed",label:Object(o.__)("Fixed","mp-timetable")}]}),React.createElement(y,{label:Object(o.__)("Unique ID","mp-timetable"),help:Object(o.__)("If you use more than one table on a page specify the unique ID for a timetable. It is usually all lowercase and contains only letters, numbers, and hyphens.","mp-timetable"),value:S,onChange:function(e){return z({id:e})}}),React.createElement(y,{label:Object(o.__)("CSS class","mp-timetable"),value:k,onChange:function(e){return z({custom_class:e})}}),React.createElement(v,{label:Object(o.__)("Mobile behavior","mp-timetable"),value:P,onChange:function(e){return z({responsive:e})},options:[{value:"0",label:Object(o.__)("Table","mp-timetable")},{value:"1",label:Object(o.__)("List","mp-timetable")}]})))}}])&&i(n.prototype,a),s&&i(n,s),O}(s);function j(e){return(j="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function g(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function w(e,t){for(var n=0;n<t.length;n++){var l=t[n];l.enumerable=l.enumerable||!1,l.configurable=!0,"value"in l&&(l.writable=!0),Object.defineProperty(e,l.key,l)}}function C(e,t){return!t||"object"!==j(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function E(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}function R(e){return(R=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function S(e,t){return(S=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var k=wp.serverSideRender,x=wp.element,T=x.Component,P=x.Fragment,D=wp.compose.compose,I=wp.components.Disabled,N=wp.data.withSelect,H=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&S(e,t)}(i,e);var t,n,o,a,r=(t=i,function(){var e,n=R(t);if(E()){var l=R(this).constructor;e=Reflect.construct(n,arguments,l)}else e=n.apply(this,arguments);return C(this,e)});function i(){return g(this,i),r.apply(this,arguments)}return n=i,(o=[{key:"initTable",value:function(){var e=this.props.clientId,t=jQuery("#block-".concat(e)),n=setInterval((function(){t.find(".mptt-shortcode-wrapper").length&&!t.find(".mptt-shortcode-wrapper").hasClass("table-init")&&(clearInterval(n),window.mptt.tableInit())}),1)}},{key:"componentDidUpdate",value:function(e,t){Object(l.isEqual)(this.props.attributes,e.attributes)||this.initTable()}},{key:"componentDidMount",value:function(){this.initTable()}},{key:"render",value:function(){var e=this.props.attributes;return e.events,e.event_categ,React.createElement(P,null,React.createElement(O,this.props),React.createElement(I,null,React.createElement(k,{block:"mp-timetable/timetable",attributes:this.props.attributes})))}}])&&w(n.prototype,o),a&&w(n,a),i}(T),z=D([N((function(e,t){var n=e("core"),o=n.getEntityRecords,a=(n.getCategories,o("postType","mp-event",{per_page:-1,orderby:"title",order:"asc"})),r=o("postType","mp-column",{per_page:-1}),i=o("taxonomy","mp-event_category",{per_page:-1});return{selectedEvents:a?a.map((function(e){return Object(l.pick)(e,["id","title"])})):null,selectedColumns:r?r.map((function(e){return Object(l.pick)(e,["id","title"])})):null,selectedEventCategories:i?i.map((function(e){return Object(l.pick)(e,["id","name"])})):null}}))])(H);(0,wp.blocks.registerBlockType)("mp-timetable/timetable",{title:Object(o.__)("Timetable","mp-timetable"),category:"common",icon:"calendar",supports:{align:["wide","full"]},getEditWrapperProps:function(e){var t=e.align;if(["wide","full"].includes(t))return{"data-align":t}},edit:z,save:function(){return null}})}]);
1
+ window.wp=window.wp||{},window.wp["./media/js/blocks/dist/index.js"]=function(e){var t={};function n(l){if(t[l])return t[l].exports;var o=t[l]={i:l,l:!1,exports:{}};return e[l].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,l){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:l})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var l=Object.create(null);if(n.r(l),Object.defineProperty(l,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(l,o,function(t){return e[t]}.bind(null,o));return l},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=7)}([function(e,t){e.exports=window.wp.i18n},function(e,t){e.exports=window.lodash},,,,,,function(e,t,n){"use strict";n.r(t);var l=n(1),o=n(0);function a(e){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var n=0;n<t.length;n++){var l=t[n];l.enumerable=l.enumerable||!1,l.configurable=!0,"value"in l&&(l.writable=!0),Object.defineProperty(e,l.key,l)}}function c(e,t){return!t||"object"!==a(t)&&"function"!=typeof t?u(e):t}function u(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function b(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}function p(e){return(p=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function m(e,t){return(m=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var s=wp.element.Component,f=(wp.blockEditor||wp.editor).InspectorControls,_=wp.components,d=_.SelectControl,v=_.CheckboxControl,h=_.PanelBody,y=_.TextControl,O=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&m(e,t)}(O,e);var t,n,a,s,_=(t=O,function(){var e,n=p(t);if(b()){var l=p(this).constructor;e=Reflect.construct(n,arguments,l)}else e=n.apply(this,arguments);return c(this,e)});function O(){var e;return r(this,O),(e=_.apply(this,arguments)).setOptions=e.setOptions.bind(u(e)),e}return n=O,(a=[{key:"setOptions",value:function(e){var t=[];return e&&(t=e.map((function(e){return{value:e.id.toString(),label:Object(l.get)(e,["title","raw"])||Object(l.get)(e,["name"])}}))),t}},{key:"render",value:function(){var e=this.props,t=e.attributes,n=t.col,l=t.events,a=t.event_categ,r=t.increment,i=t.view,c=t.view_sort,u=t.label,b=t.hide_label,p=t.hide_hrs,m=t.hide_empty_rows,s=t.title,_=t.time,O=t.sub_title,j=t.description,g=t.user,w=t.group,E=t.disable_event_url,C=t.text_align,R=t.text_align_vertical,S=t.id,k=t.custom_class,x=t.row_height,P=t.font_size,T=t.responsive,D=t.table_layout,N=e.selectedEvents,H=e.selectedColumns,I=e.selectedEventCategories,M=e.setAttributes;return React.createElement(f,null,React.createElement(h,{title:Object(o.__)("Settings","mp-timetable")},React.createElement(d,{className:"timetable-wp56-fix",multiple:!0,size:"7",label:Object(o.__)("Columns","mp-timetable"),help:Object(o.__)("Hold the Ctrl or Command key to select/deselect multiple options.","mp-timetable"),value:n,onChange:function(e){return M({col:e})},options:this.setOptions(H)}),React.createElement(d,{className:"timetable-wp56-fix",multiple:!0,size:"7",label:Object(o.__)("Specific events","mp-timetable"),help:Object(o.__)("Hold the Ctrl or Command key to select/deselect multiple options.","mp-timetable"),value:l,onChange:function(e){return M({events:e})},options:this.setOptions(N)}),React.createElement(d,{className:"timetable-wp56-fix",multiple:!0,size:"7",label:Object(o.__)("Event categories","mp-timetable"),help:Object(o.__)("Hold the Ctrl or Command key to select/deselect multiple options.","mp-timetable"),value:a,onChange:function(e){return M({event_categ:e})},options:this.setOptions(I)}),React.createElement(v,{label:Object(o.__)("Title","mp-timetable"),checked:"1"==s,onChange:function(e){M({title:e?"1":"0"})}}),React.createElement(v,{label:Object(o.__)("Time","mp-timetable"),checked:"1"==_,onChange:function(e){M({time:e?"1":"0"})}}),React.createElement(v,{label:Object(o.__)("Subtitle","mp-timetable"),checked:"1"==O,onChange:function(e){M({sub_title:e?"1":"0"})}}),React.createElement(v,{label:Object(o.__)("Description","mp-timetable"),checked:"1"==j,onChange:function(e){M({description:e?"1":"0"})}}),React.createElement(v,{label:Object(o.__)("Event Head","mp-timetable"),checked:"1"==g,onChange:function(e){M({user:e?"1":"0"})}}),React.createElement(y,{label:Object(o.__)("Block height in pixels","mp-timetable"),type:"number",value:isNaN(x)?0:parseInt(x),onChange:function(e){M({row_height:e.toString()})},min:1,step:1}),React.createElement(y,{label:Object(o.__)("Base font size","mp-timetable"),help:Object(o.__)("Base font size for the table. Example 12px, 2em, 80%.","mp-timetable"),value:P,onChange:function(e){return M({font_size:e})}}),React.createElement(d,{label:Object(o.__)("Time frame for event","mp-timetable"),value:r,onChange:function(e){return M({increment:e})},options:[{value:"1",label:Object(o.__)("Hour (1h)","mp-timetable")},{value:"0.5",label:Object(o.__)("Half hour (30min)","mp-timetable")},{value:"0.25",label:Object(o.__)("Quarter hour (15min)","mp-timetable")}]}),React.createElement(d,{label:Object(o.__)("Filter events style","mp-timetable"),value:i,onChange:function(e){return M({view:e})},options:[{value:"dropdown_list",label:Object(o.__)("Dropdown list","mp-timetable")},{value:"tabs",label:Object(o.__)("Tabs","mp-timetable")}]}),React.createElement(d,{label:Object(o.__)("Order of items in filter","mp-timetable"),value:c,onChange:function(e){return M({view_sort:e})},options:[{value:"",label:Object(o.__)("Default","mp-timetable")},{value:"menu_order",label:Object(o.__)("Menu Order","mp-timetable")},{value:"post_title",label:Object(o.__)("Title","mp-timetable")}]}),React.createElement(y,{label:Object(o.__)("Filter title to display all events","mp-timetable"),value:u,onChange:function(e){return M({label:e})}}),React.createElement(d,{label:Object(o.__)("Hide 'All Events' option","mp-timetable"),value:b,onChange:function(e){return M({hide_label:e})},options:[{value:"0",label:Object(o.__)("No","mp-timetable")},{value:"1",label:Object(o.__)("Yes","mp-timetable")}]}),React.createElement(d,{label:Object(o.__)("Hide column with hours","mp-timetable"),value:p,onChange:function(e){return M({hide_hrs:e})},options:[{value:"0",label:Object(o.__)("No","mp-timetable")},{value:"1",label:Object(o.__)("Yes","mp-timetable")}]}),React.createElement(d,{label:Object(o.__)("Do not display empty rows","mp-timetable"),value:m,onChange:function(e){return M({hide_empty_rows:e})},options:[{value:"0",label:Object(o.__)("No","mp-timetable")},{value:"1",label:Object(o.__)("Yes","mp-timetable")}]}),React.createElement(d,{label:Object(o.__)("Merge cells with common events","mp-timetable"),value:w,onChange:function(e){return M({group:e})},options:[{value:"0",label:Object(o.__)("No","mp-timetable")},{value:"1",label:Object(o.__)("Yes","mp-timetable")}]}),React.createElement(d,{label:Object(o.__)("Disable event link","mp-timetable"),value:E,onChange:function(e){return M({disable_event_url:e})},options:[{value:"0",label:Object(o.__)("No","mp-timetable")},{value:"1",label:Object(o.__)("Yes","mp-timetable")}]}),React.createElement(d,{label:Object(o.__)("Horizontal align","mp-timetable"),value:C,onChange:function(e){return M({text_align:e})},options:[{value:"center",label:Object(o.__)("center","mp-timetable")},{value:"left",label:Object(o.__)("left","mp-timetable")},{value:"right",label:Object(o.__)("right","mp-timetable")}]}),React.createElement(d,{label:Object(o.__)("Vertical align","mp-timetable"),value:R,onChange:function(e){return M({text_align_vertical:e})},options:[{value:"default",label:Object(o.__)("Default","mp-timetable")},{value:"top",label:Object(o.__)("top","mp-timetable")},{value:"middle",label:Object(o.__)("middle","mp-timetable")},{value:"bottom",label:Object(o.__)("bottom","mp-timetable")}]}),React.createElement(d,{label:Object(o.__)("Column width","mp-timetable"),value:D,onChange:function(e){return M({table_layout:e})},options:[{value:"",label:Object(o.__)("Default","mp-timetable")},{value:"auto",label:Object(o.__)("Auto","mp-timetable")},{value:"fixed",label:Object(o.__)("Fixed","mp-timetable")}]}),React.createElement(y,{label:Object(o.__)("Unique ID","mp-timetable"),help:Object(o.__)("If you use more than one table on a page specify the unique ID for a timetable. It is usually all lowercase and contains only letters, numbers, and hyphens.","mp-timetable"),value:S,onChange:function(e){return M({id:e})}}),React.createElement(y,{label:Object(o.__)("CSS class","mp-timetable"),value:k,onChange:function(e){return M({custom_class:e})}}),React.createElement(d,{label:Object(o.__)("Mobile behavior","mp-timetable"),value:T,onChange:function(e){return M({responsive:e})},options:[{value:"0",label:Object(o.__)("Table","mp-timetable")},{value:"1",label:Object(o.__)("List","mp-timetable")}]})))}}])&&i(n.prototype,a),s&&i(n,s),O}(s);function j(e){return(j="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function g(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function w(e,t){for(var n=0;n<t.length;n++){var l=t[n];l.enumerable=l.enumerable||!1,l.configurable=!0,"value"in l&&(l.writable=!0),Object.defineProperty(e,l.key,l)}}function E(e,t){return!t||"object"!==j(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function C(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}function R(e){return(R=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function S(e,t){return(S=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var k=wp.serverSideRender,x=wp.element,P=x.Component,T=x.Fragment,D=wp.compose.compose,N=wp.components,H=N.Disabled,I=N.Spinner,M=N.Placeholder,z=wp.data.withSelect,B=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&S(e,t)}(r,e);var t,n,l,o,a=(t=r,function(){var e,n=R(t);if(C()){var l=R(this).constructor;e=Reflect.construct(n,arguments,l)}else e=n.apply(this,arguments);return E(this,e)});function r(){return g(this,r),a.apply(this,arguments)}return n=r,(l=[{key:"componentDidMount",value:function(){var e=document.getElementById("block-".concat(this.props.clientId));new MutationObserver((function(){window.mptt.tableInit()})).observe(e,{childList:!0,subtree:!0})}},{key:"placeholder",value:function(){return React.createElement(M,null,React.createElement(I,null))}},{key:"render",value:function(){return React.createElement(T,null,React.createElement(O,this.props),React.createElement(H,null,React.createElement(k,{block:"mp-timetable/timetable",attributes:this.props.attributes,LoadingResponsePlaceholder:this.placeholder})))}}])&&w(n.prototype,l),o&&w(n,o),r}(P),Y=D([z((function(e,t){var n=e("core"),o=n.getEntityRecords,a=(n.getCategories,o("postType","mp-event",{per_page:-1,orderby:"title",order:"asc"})),r=o("postType","mp-column",{per_page:-1}),i=o("taxonomy","mp-event_category",{per_page:-1});return{selectedEvents:a?a.map((function(e){return Object(l.pick)(e,["id","title"])})):null,selectedColumns:r?r.map((function(e){return Object(l.pick)(e,["id","title"])})):null,selectedEventCategories:i?i.map((function(e){return Object(l.pick)(e,["id","name"])})):null}}))])(B);(0,wp.blocks.registerBlockType)("mp-timetable/timetable",{title:Object(o.__)("Timetable","mp-timetable"),category:"common",icon:"calendar",supports:{align:["wide","full"]},getEditWrapperProps:function(e){var t=e.align;if(["wide","full"].includes(t))return{"data-align":t}},edit:Y,save:function(){return null}})}]);
media/js/blocks/src/timetable/edit.js CHANGED
@@ -1,91 +1,83 @@
1
- import Inspector from './inspector';
2
-
3
- import { pick, isEqual } from "lodash";
4
- import { __ } from 'wp.i18n';
5
-
6
- const { serverSideRender: ServerSideRender } = wp;
7
- const { Component, Fragment } = wp.element;
8
- const { compose } = wp.compose;
9
-
10
- const {
11
- Disabled
12
- } = wp.components;
13
-
14
- const {
15
- withSelect
16
- } = wp.data;
17
-
18
- class Edit extends Component {
19
- constructor() {
20
- super(...arguments);
21
- }
22
-
23
- initTable(){
24
- const { clientId } = this.props;
25
- const $block = jQuery( `#block-${clientId}` );
26
-
27
- //Set timer and check when table is load fully, and then initialize table data, and after stop timer
28
- const waitLoadTable = setInterval( () => {
29
- if ($block.find('.mptt-shortcode-wrapper').length && !$block.find('.mptt-shortcode-wrapper').hasClass('table-init')){
30
- clearInterval(waitLoadTable);
31
- window.mptt.tableInit();
32
- }
33
- }, 1);
34
- }
35
-
36
- componentDidUpdate(prevProps, prevState) {
37
- if (!isEqual(this.props.attributes, prevProps.attributes)) {
38
- this.initTable();
39
- }
40
- }
41
-
42
- componentDidMount() {
43
- this.initTable();
44
- }
45
-
46
- render() {
47
-
48
- const {
49
- attributes: {
50
- events,
51
- event_categ
52
- }
53
- } = this.props;
54
-
55
- return (
56
- <Fragment>
57
- <Inspector {...this.props }/>
58
- <Disabled>
59
- <ServerSideRender
60
- block="mp-timetable/timetable"
61
- attributes={this.props.attributes}
62
- />
63
- </Disabled>
64
- </Fragment>
65
- );
66
- }
67
- }
68
-
69
- export default compose([
70
- withSelect(( select, props ) => {
71
- const { getEntityRecords, getCategories } = select( "core" );
72
-
73
- let events = getEntityRecords( "postType", "mp-event", {per_page: -1, orderby: 'title', order: 'asc'} );
74
- let columns = getEntityRecords( "postType", "mp-column", {per_page: -1} );
75
- let eventCategories = getEntityRecords( "taxonomy", "mp-event_category", {per_page: -1} );
76
-
77
- return {
78
- selectedEvents: events ? events .map((event) => {
79
- return pick( event, [ 'id', 'title' ])
80
- }) : null,
81
-
82
- selectedColumns: columns ? columns.map((column) => {
83
- return pick( column, [ 'id', 'title' ])
84
- }) : null,
85
-
86
- selectedEventCategories: eventCategories ? eventCategories.map((categorie) => {
87
- return pick( categorie, [ 'id', 'name' ])
88
- }) : null
89
- };
90
- }),
91
- ])(Edit);
1
+ import Inspector from './inspector';
2
+
3
+ import { pick } from "lodash";
4
+
5
+ const { serverSideRender: ServerSideRender } = wp;
6
+ const { Component, Fragment } = wp.element;
7
+ const { compose } = wp.compose;
8
+
9
+ const {
10
+ Disabled,
11
+ Spinner,
12
+ Placeholder
13
+ } = wp.components;
14
+
15
+ const {
16
+ withSelect
17
+ } = wp.data;
18
+
19
+ class Edit extends Component {
20
+ constructor() {
21
+ super(...arguments);
22
+ }
23
+
24
+ componentDidMount() {
25
+ const block = document.getElementById( `block-${this.props.clientId}` );
26
+
27
+ const mutationObserver = new MutationObserver( () => {
28
+ window.mptt.tableInit();
29
+ } );
30
+
31
+ mutationObserver.observe( block, {
32
+ childList: true,
33
+ subtree: true
34
+ } );
35
+ }
36
+
37
+ placeholder() {
38
+ return (
39
+ <Placeholder>
40
+ <Spinner />
41
+ </Placeholder>
42
+ );
43
+ }
44
+
45
+ render() {
46
+ return (
47
+ <Fragment>
48
+ <Inspector { ...this.props }/>
49
+ <Disabled>
50
+ <ServerSideRender
51
+ block="mp-timetable/timetable"
52
+ attributes={ this.props.attributes }
53
+ LoadingResponsePlaceholder={ this.placeholder }
54
+ />
55
+ </Disabled>
56
+ </Fragment>
57
+ );
58
+ }
59
+ }
60
+
61
+ export default compose([
62
+ withSelect(( select, props ) => {
63
+ const { getEntityRecords, getCategories } = select( "core" );
64
+
65
+ let events = getEntityRecords( "postType", "mp-event", {per_page: -1, orderby: 'title', order: 'asc'} );
66
+ let columns = getEntityRecords( "postType", "mp-column", {per_page: -1} );
67
+ let eventCategories = getEntityRecords( "taxonomy", "mp-event_category", {per_page: -1} );
68
+
69
+ return {
70
+ selectedEvents: events ? events .map((event) => {
71
+ return pick( event, [ 'id', 'title' ])
72
+ }) : null,
73
+
74
+ selectedColumns: columns ? columns.map((column) => {
75
+ return pick( column, [ 'id', 'title' ])
76
+ }) : null,
77
+
78
+ selectedEventCategories: eventCategories ? eventCategories.map((categorie) => {
79
+ return pick( categorie, [ 'id', 'name' ])
80
+ }) : null
81
+ };
82
+ }),
83
+ ])(Edit);
 
 
 
 
 
 
 
 
media/js/blocks/src/timetable/index.js CHANGED
@@ -1,28 +1,28 @@
1
- import edit from './edit';
2
- import { __ } from 'wp.i18n';
3
-
4
- const {
5
- registerBlockType,
6
- } = wp.blocks;
7
-
8
- export default registerBlockType(
9
- 'mp-timetable/timetable',
10
- {
11
- title: __('Timetable', 'mp-timetable'),
12
- category: 'common',
13
- icon: 'calendar',
14
- supports: {
15
- align: [ 'wide', 'full' ],
16
- },
17
- getEditWrapperProps( attributes ) {
18
- const { align } = attributes;
19
- if ( [ 'wide', 'full' ].includes( align ) ) {
20
- return { 'data-align': align };
21
- }
22
- },
23
- edit,
24
- save: () => {
25
- return null;
26
- },
27
- }
28
  )
1
+ import edit from './edit';
2
+ import { __ } from 'wp.i18n';
3
+
4
+ const {
5
+ registerBlockType,
6
+ } = wp.blocks;
7
+
8
+ export default registerBlockType(
9
+ 'mp-timetable/timetable',
10
+ {
11
+ title: __('Timetable', 'mp-timetable'),
12
+ category: 'common',
13
+ icon: 'calendar',
14
+ supports: {
15
+ align: [ 'wide', 'full' ],
16
+ },
17
+ getEditWrapperProps( attributes ) {
18
+ const { align } = attributes;
19
+ if ( [ 'wide', 'full' ].includes( align ) ) {
20
+ return { 'data-align': align };
21
+ }
22
+ },
23
+ edit,
24
+ save: () => {
25
+ return null;
26
+ },
27
+ }
28
  )
media/js/blocks/src/timetable/inspector.js CHANGED
@@ -1,296 +1,296 @@
1
- import { get } from "lodash";
2
- import { __ } from 'wp.i18n';
3
-
4
- const {Component} = wp.element;
5
-
6
- const {
7
- InspectorControls,
8
- } = wp.blockEditor || wp.editor;
9
-
10
- const {
11
- SelectControl,
12
- CheckboxControl,
13
- PanelBody,
14
- TextControl,
15
-
16
- } = wp.components;
17
-
18
- class Inspector extends Component {
19
- constructor() {
20
- super(...arguments);
21
-
22
- this.setOptions = this.setOptions.bind( this );
23
- }
24
-
25
- setOptions(data) {
26
- let options = [];
27
- if (data) {
28
- options = data.map((event => {
29
- return {
30
- value: event.id.toString(),
31
- label: get( event, [ 'title', 'raw' ] ) || get( event, [ 'name' ] )
32
- }
33
- }));
34
- }
35
- return options;
36
- }
37
-
38
- render() {
39
-
40
- const {
41
- attributes: {
42
- col,
43
- events,
44
- event_categ,
45
-
46
- increment,
47
- view,
48
- view_sort,
49
- label,
50
-
51
- hide_label,
52
- hide_hrs,
53
- hide_empty_rows,
54
-
55
- title,
56
- time,
57
- sub_title,
58
- description,
59
- user,
60
-
61
- group,
62
- disable_event_url,
63
- text_align,
64
- text_align_vertical,
65
- id,
66
- custom_class,
67
-
68
- row_height,
69
- font_size,
70
- responsive,
71
- table_layout,
72
- },
73
-
74
- selectedEvents,
75
- selectedColumns,
76
- selectedEventCategories,
77
-
78
- setAttributes,
79
- } = this.props;
80
-
81
- return (
82
- <InspectorControls>
83
- <PanelBody
84
- title={__('Settings', 'mp-timetable')}
85
- >
86
- <SelectControl
87
- className="timetable-wp56-fix"
88
- multiple
89
- size="7"
90
- label={__('Columns', 'mp-timetable')}
91
- help={__('Hold the Ctrl or Command key to select/deselect multiple options.', 'mp-timetable')}
92
- value={col}
93
- onChange={col => setAttributes({col})}
94
- options={this.setOptions(selectedColumns)}
95
- />
96
- <SelectControl
97
- className="timetable-wp56-fix"
98
- multiple
99
- size="7"
100
- label={__('Specific events', 'mp-timetable')}
101
- help={__('Hold the Ctrl or Command key to select/deselect multiple options.', 'mp-timetable')}
102
- value={events}
103
- onChange={events => setAttributes({events})}
104
- options={this.setOptions(selectedEvents )}
105
- />
106
- <SelectControl
107
- className="timetable-wp56-fix"
108
- multiple
109
- size="7"
110
- label={__('Event categories', 'mp-timetable')}
111
- help={__('Hold the Ctrl or Command key to select/deselect multiple options.', 'mp-timetable')}
112
- value={event_categ}
113
- onChange={event_categ => setAttributes({event_categ})}
114
- options={this.setOptions(selectedEventCategories)}
115
- />
116
- <CheckboxControl
117
- label={__('Title', 'mp-timetable')}
118
- checked={title == '1' ? true : false}
119
- onChange={(title) => {
120
- setAttributes({title: title ? '1' : '0'})
121
- }}
122
- />
123
- <CheckboxControl
124
- label={__('Time', 'mp-timetable')}
125
- checked={time == '1' ? true : false}
126
- onChange={(time) => { setAttributes({time: time ? '1' : '0'}) }}
127
- />
128
- <CheckboxControl
129
- label={__('Subtitle', 'mp-timetable')}
130
- checked={sub_title == '1' ? true : false}
131
- onChange={(sub_title) => { setAttributes({sub_title: sub_title ? '1' : '0'}) }}
132
- />
133
- <CheckboxControl
134
- label={__('Description', 'mp-timetable')}
135
- checked={description == '1' ? true : false}
136
- onChange={(description) => { setAttributes({description: description ? '1' : '0'}) }}
137
- />
138
- <CheckboxControl
139
- label={__('Event Head', 'mp-timetable')}
140
- checked={user == '1' ? true : false}
141
- onChange={(user) => { setAttributes({user: user ? '1' : '0'}) }}
142
- />
143
- <TextControl
144
- label={__('Block height in pixels', 'mp-timetable')}
145
- type={'number'}
146
- value={isNaN(row_height) ? 0 : parseInt(row_height)}
147
- onChange={row_height => {
148
- setAttributes({ row_height: row_height.toString() });
149
- }}
150
- min={1}
151
- step={1}
152
- />
153
- <TextControl
154
- label={__('Base font size', 'mp-timetable')}
155
- help={__('Base font size for the table. Example 12px, 2em, 80%.', 'mp-timetable')}
156
- value={font_size}
157
- onChange={font_size => setAttributes({font_size})}
158
- />
159
- <SelectControl
160
- label={__('Time frame for event', 'mp-timetable')}
161
- value={increment}
162
- onChange={increment => setAttributes({ increment })}
163
- options={[
164
- { value: '1' , label: __( 'Hour (1h)' , 'mp-timetable' ) },
165
- { value: '0.5' , label: __( 'Half hour (30min)' , 'mp-timetable' ) },
166
- { value: '0.25', label: __( 'Quarter hour (15min)' , 'mp-timetable' ) },
167
- ]}
168
- />
169
- <SelectControl
170
- label={__('Filter events style', 'mp-timetable')}
171
- value={view}
172
- onChange={view => setAttributes({ view })}
173
- options={[
174
- { value: 'dropdown_list', label: __( 'Dropdown list', 'mp-timetable' ) },
175
- { value: 'tabs' , label: __( 'Tabs' , 'mp-timetable' ) },
176
- ]}
177
- />
178
- <SelectControl
179
- label={__('Order of items in filter', 'mp-timetable')}
180
- value={view_sort}
181
- onChange={view_sort => setAttributes({ view_sort })}
182
- options={[
183
- { value: '' , label: __( 'Default', 'mp-timetable' ) },
184
- { value: 'menu_order' , label: __( 'Menu Order', 'mp-timetable' ) },
185
- { value: 'post_title' , label: __( 'Title', 'mp-timetable' ) },
186
- ]}
187
- />
188
- <TextControl
189
- label={__('Filter title to display all events', 'mp-timetable')}
190
- value={label}
191
- onChange={label => setAttributes({ label })}
192
- />
193
- <SelectControl
194
- label={__('Hide \'All Events\' option', 'mp-timetable')}
195
- value={hide_label}
196
- onChange={hide_label => setAttributes({ hide_label })}
197
- options={[
198
- { value: '0', label: __( 'No' , 'mp-timetable' ) },
199
- { value: '1', label: __( 'Yes', 'mp-timetable' ) },
200
- ]}
201
- />
202
- <SelectControl
203
- label={__('Hide column with hours', 'mp-timetable')}
204
- value={hide_hrs}
205
- onChange={hide_hrs => setAttributes({ hide_hrs })}
206
- options={[
207
- { value: '0', label: __( 'No' , 'mp-timetable' ) },
208
- { value: '1', label: __( 'Yes', 'mp-timetable' ) },
209
- ]}
210
- />
211
- <SelectControl
212
- label={__('Do not display empty rows', 'mp-timetable')}
213
- value={hide_empty_rows}
214
- onChange={hide_empty_rows => setAttributes({ hide_empty_rows })}
215
- options={[
216
- { value: '0', label: __( 'No' , 'mp-timetable' ) },
217
- { value: '1', label: __( 'Yes', 'mp-timetable' ) },
218
- ]}
219
- />
220
- <SelectControl
221
- label={__('Merge cells with common events', 'mp-timetable')}
222
- value={group}
223
- onChange={group => setAttributes({ group })}
224
- options={[
225
- { value: '0', label: __( 'No' , 'mp-timetable' ) },
226
- { value: '1', label: __( 'Yes', 'mp-timetable' ) },
227
- ]}
228
- />
229
- <SelectControl
230
- label={__('Disable event link', 'mp-timetable')}
231
- value={disable_event_url}
232
- onChange={disable_event_url => setAttributes({ disable_event_url })}
233
- options={[
234
- { value: '0', label: __( 'No' , 'mp-timetable' ) },
235
- { value: '1', label: __( 'Yes', 'mp-timetable' ) },
236
- ]}
237
- />
238
- <SelectControl
239
- label={__('Horizontal align', 'mp-timetable')}
240
- value={text_align}
241
- onChange={text_align => setAttributes({ text_align })}
242
- options={[
243
- { value: 'center', label: __( 'center', 'mp-timetable' ) },
244
- { value: 'left', label: __( 'left' , 'mp-timetable' ) },
245
- { value: 'right', label: __( 'right' , 'mp-timetable' ) },
246
- ]}
247
- />
248
- <SelectControl
249
- label={__('Vertical align', 'mp-timetable')}
250
- value={text_align_vertical}
251
- onChange={text_align_vertical => setAttributes({ text_align_vertical })}
252
- options={[
253
- { value: 'default', label: __( 'Default', 'mp-timetable' ) },
254
- { value: 'top', label: __( 'top' , 'mp-timetable' ) },
255
- { value: 'middle', label: __( 'middle' , 'mp-timetable' ) },
256
- { value: 'bottom', label: __( 'bottom' , 'mp-timetable' ) },
257
- ]}
258
- />
259
- <SelectControl
260
- label={__('Column width', 'mp-timetable')}
261
- value={table_layout}
262
- onChange={table_layout => setAttributes({ table_layout })}
263
- options={[
264
- { value: '', label: __( 'Default', 'mp-timetable' ) },
265
- { value: 'auto', label: __( 'Auto' , 'mp-timetable' ) },
266
- { value: 'fixed', label: __( 'Fixed' , 'mp-timetable' ) },
267
- ]}
268
- />
269
- <TextControl
270
- label={__('Unique ID', 'mp-timetable')}
271
- help={__('If you use more than one table on a page specify the unique ID for a timetable. It is usually all lowercase and contains only letters, numbers, and hyphens.', 'mp-timetable')}
272
- value={id}
273
- onChange={id => setAttributes({id})}
274
- />
275
- <TextControl
276
- label={__('CSS class', 'mp-timetable')}
277
- value={custom_class}
278
- onChange={custom_class => setAttributes({custom_class})}
279
- />
280
- <SelectControl
281
- label={__('Mobile behavior', 'mp-timetable')}
282
- value={responsive}
283
- onChange={responsive => setAttributes({responsive})}
284
- options={[
285
- { value: '0', label: __( 'Table' , 'mp-timetable' ) },
286
- { value: '1', label: __( 'List', 'mp-timetable' ) },
287
- ]}
288
- />
289
-
290
- </PanelBody>
291
- </InspectorControls>
292
- );
293
- }
294
- }
295
-
296
  export default (Inspector);
1
+ import { get } from "lodash";
2
+ import { __ } from 'wp.i18n';
3
+
4
+ const {Component} = wp.element;
5
+
6
+ const {
7
+ InspectorControls,
8
+ } = wp.blockEditor || wp.editor;
9
+
10
+ const {
11
+ SelectControl,
12
+ CheckboxControl,
13
+ PanelBody,
14
+ TextControl,
15
+
16
+ } = wp.components;
17
+
18
+ class Inspector extends Component {
19
+ constructor() {
20
+ super(...arguments);
21
+
22
+ this.setOptions = this.setOptions.bind( this );
23
+ }
24
+
25
+ setOptions(data) {
26
+ let options = [];
27
+ if (data) {
28
+ options = data.map((event => {
29
+ return {
30
+ value: event.id.toString(),
31
+ label: get( event, [ 'title', 'raw' ] ) || get( event, [ 'name' ] )
32
+ }
33
+ }));
34
+ }
35
+ return options;
36
+ }
37
+
38
+ render() {
39
+
40
+ const {
41
+ attributes: {
42
+ col,
43
+ events,
44
+ event_categ,
45
+
46
+ increment,
47
+ view,
48
+ view_sort,
49
+ label,
50
+
51
+ hide_label,
52
+ hide_hrs,
53
+ hide_empty_rows,
54
+
55
+ title,
56
+ time,
57
+ sub_title,
58
+ description,
59
+ user,
60
+
61
+ group,
62
+ disable_event_url,
63
+ text_align,
64
+ text_align_vertical,
65
+ id,
66
+ custom_class,
67
+
68
+ row_height,
69
+ font_size,
70
+ responsive,
71
+ table_layout,
72
+ },
73
+
74
+ selectedEvents,
75
+ selectedColumns,
76
+ selectedEventCategories,
77
+
78
+ setAttributes,
79
+ } = this.props;
80
+
81
+ return (
82
+ <InspectorControls>
83
+ <PanelBody
84
+ title={__('Settings', 'mp-timetable')}
85
+ >
86
+ <SelectControl
87
+ className="timetable-wp56-fix"
88
+ multiple
89
+ size="7"
90
+ label={__('Columns', 'mp-timetable')}
91
+ help={__('Hold the Ctrl or Command key to select/deselect multiple options.', 'mp-timetable')}
92
+ value={col}
93
+ onChange={col => setAttributes({col})}
94
+ options={this.setOptions(selectedColumns)}
95
+ />
96
+ <SelectControl
97
+ className="timetable-wp56-fix"
98
+ multiple
99
+ size="7"
100
+ label={__('Specific events', 'mp-timetable')}
101
+ help={__('Hold the Ctrl or Command key to select/deselect multiple options.', 'mp-timetable')}
102
+ value={events}
103
+ onChange={events => setAttributes({events})}
104
+ options={this.setOptions(selectedEvents )}
105
+ />
106
+ <SelectControl
107
+ className="timetable-wp56-fix"
108
+ multiple
109
+ size="7"
110
+ label={__('Event categories', 'mp-timetable')}
111
+ help={__('Hold the Ctrl or Command key to select/deselect multiple options.', 'mp-timetable')}
112
+ value={event_categ}
113
+ onChange={event_categ => setAttributes({event_categ})}
114
+ options={this.setOptions(selectedEventCategories)}
115
+ />
116
+ <CheckboxControl
117
+ label={__('Title', 'mp-timetable')}
118
+ checked={title == '1' ? true : false}
119
+ onChange={(title) => {
120
+ setAttributes({title: title ? '1' : '0'})
121
+ }}
122
+ />
123
+ <CheckboxControl
124
+ label={__('Time', 'mp-timetable')}
125
+ checked={time == '1' ? true : false}
126
+ onChange={(time) => { setAttributes({time: time ? '1' : '0'}) }}
127
+ />
128
+ <CheckboxControl
129
+ label={__('Subtitle', 'mp-timetable')}
130
+ checked={sub_title == '1' ? true : false}
131
+ onChange={(sub_title) => { setAttributes({sub_title: sub_title ? '1' : '0'}) }}
132
+ />
133
+ <CheckboxControl
134
+ label={__('Description', 'mp-timetable')}
135
+ checked={description == '1' ? true : false}
136
+ onChange={(description) => { setAttributes({description: description ? '1' : '0'}) }}
137
+ />
138
+ <CheckboxControl
139
+ label={__('Event Head', 'mp-timetable')}
140
+ checked={user == '1' ? true : false}
141
+ onChange={(user) => { setAttributes({user: user ? '1' : '0'}) }}
142
+ />
143
+ <TextControl
144
+ label={__('Block height in pixels', 'mp-timetable')}
145
+ type={'number'}
146
+ value={isNaN(row_height) ? 0 : parseInt(row_height)}
147
+ onChange={row_height => {
148
+ setAttributes({ row_height: row_height.toString() });
149
+ }}
150
+ min={1}
151
+ step={1}
152
+ />
153
+ <TextControl
154
+ label={__('Base font size', 'mp-timetable')}
155
+ help={__('Base font size for the table. Example 12px, 2em, 80%.', 'mp-timetable')}
156
+ value={font_size}
157
+ onChange={font_size => setAttributes({font_size})}
158
+ />
159
+ <SelectControl
160
+ label={__('Time frame for event', 'mp-timetable')}
161
+ value={increment}
162
+ onChange={increment => setAttributes({ increment })}
163
+ options={[
164
+ { value: '1' , label: __( 'Hour (1h)' , 'mp-timetable' ) },
165
+ { value: '0.5' , label: __( 'Half hour (30min)' , 'mp-timetable' ) },
166
+ { value: '0.25', label: __( 'Quarter hour (15min)' , 'mp-timetable' ) },
167
+ ]}
168
+ />
169
+ <SelectControl
170
+ label={__('Filter events style', 'mp-timetable')}
171
+ value={view}
172
+ onChange={view => setAttributes({ view })}
173
+ options={[
174
+ { value: 'dropdown_list', label: __( 'Dropdown list', 'mp-timetable' ) },
175
+ { value: 'tabs' , label: __( 'Tabs' , 'mp-timetable' ) },
176
+ ]}
177
+ />
178
+ <SelectControl
179
+ label={__('Order of items in filter', 'mp-timetable')}
180
+ value={view_sort}
181
+ onChange={view_sort => setAttributes({ view_sort })}
182
+ options={[
183
+ { value: '' , label: __( 'Default', 'mp-timetable' ) },
184
+ { value: 'menu_order' , label: __( 'Menu Order', 'mp-timetable' ) },
185
+ { value: 'post_title' , label: __( 'Title', 'mp-timetable' ) },
186
+ ]}
187
+ />
188
+ <TextControl
189
+ label={__('Filter title to display all events', 'mp-timetable')}
190
+ value={label}
191
+ onChange={label => setAttributes({ label })}
192
+ />
193
+ <SelectControl
194
+ label={__('Hide \'All Events\' option', 'mp-timetable')}
195
+ value={hide_label}
196
+ onChange={hide_label => setAttributes({ hide_label })}
197
+ options={[
198
+ { value: '0', label: __( 'No' , 'mp-timetable' ) },
199
+ { value: '1', label: __( 'Yes', 'mp-timetable' ) },
200
+ ]}
201
+ />
202
+ <SelectControl
203
+ label={__('Hide column with hours', 'mp-timetable')}
204
+ value={hide_hrs}
205
+ onChange={hide_hrs => setAttributes({ hide_hrs })}
206
+ options={[
207
+ { value: '0', label: __( 'No' , 'mp-timetable' ) },
208
+ { value: '1', label: __( 'Yes', 'mp-timetable' ) },
209
+ ]}
210
+ />
211
+ <SelectControl
212
+ label={__('Do not display empty rows', 'mp-timetable')}
213
+ value={hide_empty_rows}
214
+ onChange={hide_empty_rows => setAttributes({ hide_empty_rows })}
215
+ options={[
216
+ { value: '0', label: __( 'No' , 'mp-timetable' ) },
217
+ { value: '1', label: __( 'Yes', 'mp-timetable' ) },
218
+ ]}
219
+ />
220
+ <SelectControl
221
+ label={__('Merge cells with common events', 'mp-timetable')}
222
+ value={group}
223
+ onChange={group => setAttributes({ group })}
224
+ options={[
225
+ { value: '0', label: __( 'No' , 'mp-timetable' ) },
226
+ { value: '1', label: __( 'Yes', 'mp-timetable' ) },
227
+ ]}
228
+ />
229
+ <SelectControl
230
+ label={__('Disable event link', 'mp-timetable')}
231
+ value={disable_event_url}
232
+ onChange={disable_event_url => setAttributes({ disable_event_url })}
233
+ options={[
234
+ { value: '0', label: __( 'No' , 'mp-timetable' ) },
235
+ { value: '1', label: __( 'Yes', 'mp-timetable' ) },
236
+ ]}
237
+ />
238
+ <SelectControl
239
+ label={__('Horizontal align', 'mp-timetable')}
240
+ value={text_align}
241
+ onChange={text_align => setAttributes({ text_align })}
242
+ options={[
243
+ { value: 'center', label: __( 'center', 'mp-timetable' ) },
244
+ { value: 'left', label: __( 'left' , 'mp-timetable' ) },
245
+ { value: 'right', label: __( 'right' , 'mp-timetable' ) },
246
+ ]}
247
+ />
248
+ <SelectControl
249
+ label={__('Vertical align', 'mp-timetable')}
250
+ value={text_align_vertical}
251
+ onChange={text_align_vertical => setAttributes({ text_align_vertical })}
252
+ options={[
253
+ { value: 'default', label: __( 'Default', 'mp-timetable' ) },
254
+ { value: 'top', label: __( 'top' , 'mp-timetable' ) },
255
+ { value: 'middle', label: __( 'middle' , 'mp-timetable' ) },
256
+ { value: 'bottom', label: __( 'bottom' , 'mp-timetable' ) },
257
+ ]}
258
+ />
259
+ <SelectControl
260
+ label={__('Column width', 'mp-timetable')}
261
+ value={table_layout}
262
+ onChange={table_layout => setAttributes({ table_layout })}
263
+ options={[
264
+ { value: '', label: __( 'Default', 'mp-timetable' ) },
265
+ { value: 'auto', label: __( 'Auto' , 'mp-timetable' ) },
266
+ { value: 'fixed', label: __( 'Fixed' , 'mp-timetable' ) },
267
+ ]}
268
+ />
269
+ <TextControl
270
+ label={__('Unique ID', 'mp-timetable')}
271
+ help={__('If you use more than one table on a page specify the unique ID for a timetable. It is usually all lowercase and contains only letters, numbers, and hyphens.', 'mp-timetable')}
272
+ value={id}
273
+ onChange={id => setAttributes({id})}
274
+ />
275
+ <TextControl
276
+ label={__('CSS class', 'mp-timetable')}
277
+ value={custom_class}
278
+ onChange={custom_class => setAttributes({custom_class})}
279
+ />
280
+ <SelectControl
281
+ label={__('Mobile behavior', 'mp-timetable')}
282
+ value={responsive}
283
+ onChange={responsive => setAttributes({responsive})}
284
+ options={[
285
+ { value: '0', label: __( 'Table' , 'mp-timetable' ) },
286
+ { value: '1', label: __( 'List', 'mp-timetable' ) },
287
+ ]}
288
+ />
289
+
290
+ </PanelBody>
291
+ </InspectorControls>
292
+ );
293
+ }
294
+ }
295
+
296
  export default (Inspector);
media/js/events/event.js CHANGED
@@ -1,974 +1,974 @@
1
- /*global jQuery:false, console:false, _:false, CommonManager:false,Registry:false, wp:false, MPTT:false*/
2
-
3
- Registry.register("Event",
4
- (function($) {
5
- "use strict";
6
-
7
- var state;
8
-
9
- function createInstance() {
10
-
11
- return {
12
- event_id: '',
13
- eventsData: {},
14
- /**
15
- * Init
16
- */
17
- init: function() {
18
- state.initTimePicker();
19
- state.addEventButton();
20
- state.initDeleteButtons();
21
- state.initEditButtons();
22
- state.initColorPicker();
23
- state.initDatePicker();
24
- state.columnRadioBox();
25
- },
26
- /**
27
- * Init time picker
28
- */
29
- initTimePicker: function() {
30
- var timeFormat = Boolean(parseInt($('#time_format').val()));
31
- $('#event_start').timepicker({
32
- showPeriod: timeFormat, // Define whether or not to show AM/PM with selected time. (default: false)
33
- showPeriodLabels: timeFormat,
34
- defaultTime: '00:00'
35
- });
36
-
37
- $('#event_end').timepicker({
38
- showPeriod: timeFormat, // Define whether or not to show AM/PM with selected time. (default: false)
39
- showPeriodLabels: timeFormat,
40
- defaultTime: '00:00'
41
- });
42
- },
43
- /**
44
- * Init widget slider
45
- * @param selector
46
- * @param autoScroll
47
- */
48
- initSlider: function(selector, autoScroll) {
49
- var play = _.isUndefined(autoScroll) ? false : Boolean(autoScroll);
50
- var id = selector.replace(/^\D+/g, '');
51
- $(selector).carouFredSel({
52
- items: {
53
- visible: 3
54
- },
55
- direction: "up",
56
- scroll: {
57
- items: 1,
58
- easing: "swing",
59
- pauseOnHover: true,
60
- onAfter: function(data) {
61
- data.items.old.each(function() {
62
- $(this).removeClass('visible');
63
- }
64
- );
65
- data.items.visible.each(function() {
66
- $(this).addClass('visible');
67
- }
68
- );
69
- }
70
- },
71
- auto: {
72
- play: play,
73
- timeoutDuration: 3000
74
- },
75
- prev: {
76
- button: "#mp_prev_button" + id
77
- },
78
- next: {
79
- button: "#mp_next_button" + id
80
- }
81
- });
82
-
83
- $(selector).trigger("currentVisible", function(items) {
84
- items.addClass("visible");
85
- });
86
- state.setColorSettings(selector + ' ' + '.mptt-colorized');
87
- },
88
- /**
89
- * init Delete Button
90
- */
91
- initDeleteButton: function() {
92
- var $events = $('#events-list');
93
-
94
- $events.find('li.event').find('i.operation-button.dashicons-no.dashicons').off('click').on('click', function() {
95
- if ($events.find('li.event').length > 1) {
96
- $(this).parents('li.event').remove();
97
- } else {
98
- $events.remove();
99
- }
100
- });
101
- },
102
- /**
103
- * Init color picker
104
- */
105
- initColorPicker: function(parent) {
106
- if (_.isUndefined(parent)) {
107
- parent = '';
108
- }
109
- var selectorColorInput = $(parent + ' input.clr-picker');
110
- var selectorTextInput = $(parent + ' input.regular-text');
111
- selectorColorInput.spectrum("destroy");
112
-
113
- // init color picker
114
- selectorColorInput.spectrum({
115
- preferredFormat: "rgb",
116
- showInput: true,
117
- showAlpha: true,
118
- allowEmpty: true,
119
- palette: [
120
- ["#000", "#444", "#666", "#999", "#ccc", "#eee", "#f3f3f3", "#fff"],
121
- ["#f00", "#f90", "#ff0", "#0f0", "#0ff", "#00f", "#90f", "#f0f"],
122
- ["#f4cccc", "#fce5cd", "#fff2cc", "#d9ead3", "#d0e0e3", "#cfe2f3", "#d9d2e9", "#ead1dc"],
123
- ["#ea9999", "#f9cb9c", "#ffe599", "#b6d7a8", "#a2c4c9", "#9fc5e8", "#b4a7d6", "#d5a6bd"],
124
- ["#e06666", "#f6b26b", "#ffd966", "#93c47d", "#76a5af", "#6fa8dc", "#8e7cc3", "#c27ba0"],
125
- ["#c00", "#e69138", "#f1c232", "#6aa84f", "#45818e", "#3d85c6", "#674ea7", "#a64d79"],
126
- ["#900", "#b45f06", "#bf9000", "#38761d", "#134f5c", "#0b5394", "#351c75", "#741b47"],
127
- ["#600", "#783f04", "#7f6000", "#274e13", "#0c343d", "#073763", "#20124d", "#4c1130"]
128
- ],
129
- showPalette: true,
130
- show: function(color) {
131
- $(this).val(color);
132
- },
133
- hide: function(color) {
134
- var parent = $(this).parents('.select-color');
135
- parent.find('.regular-text').val($(this).val());
136
- },
137
- change: function(color) {
138
- var parent = $(this).parents('.select-color');
139
- parent.find('input:not([type="hidden"])').val($(this).val());
140
- }
141
- });
142
-
143
- //change color preview block
144
- selectorTextInput.off('keyup').on('keyup', function() {
145
- var parentTr = $(this).parents('.select-color');
146
- var spectrumElement = parentTr.find('.clr-picker');
147
- var colorElement = parentTr.find(".regular-text").val();
148
- var preview_inner = parentTr.find(".sp-preview-inner");
149
- preview_inner.css({
150
- 'background-color': colorElement
151
- });
152
- spectrumElement.spectrum("set", colorElement);
153
- });
154
- },
155
- /**
156
- * Add event
157
- */
158
- addEventButton: function() {
159
- $(document).on('click.admin', '#add_mp_event', function() {
160
- if ($(this).hasClass('edit')) {
161
- state.updateEventData();
162
- } else {
163
- state.renderEventItem();
164
- }
165
- });
166
- },
167
- /**
168
- * init event data delete button
169
- */
170
- initDeleteButtons: function() {
171
- $(document).on('click.admin', '#events-list .delete-event-button', function() {
172
- var id = $(this).attr('data-id');
173
- state.deleteEvent(id);
174
- });
175
- },
176
- /**
177
- * init event data edit button
178
- */
179
- initEditButtons: function() {
180
- $(document).on('click.admin', '#events-list .edit-event-button', function() {
181
- var id = $(this).attr('data-id'),
182
- $tr = $(this).parent().parent();
183
- $(this).parent().find('.spinner').addClass('is-active');
184
-
185
- Registry._get("adminFunctions").wpAjax({
186
- controller: "events",
187
- action: "get_event_data",
188
- id: id
189
- },
190
- function(data) {
191
- var $addMpEvent = $('#add_mp_event');
192
- var $events = $('#events-list');
193
- $events.find('.spinner').removeClass('is-active');
194
- $events.find(' tr').removeClass('active');
195
- $tr.addClass('active');
196
-
197
- $('#event_start').val(data.event_start);
198
- $('#event_end').val(data.event_end);
199
- $('#description').val(data.description);
200
- $('#user_id').val(data.user_id);
201
- $('#weekday_id').val(data.column_id);
202
-
203
- $addMpEvent.addClass('edit');
204
- $addMpEvent.val('Update');
205
-
206
- state.event_id = data.id;
207
- },
208
- function(data) {
209
- console.warn(data);
210
- }
211
- );
212
- });
213
- },
214
- /**
215
- * Delete event data by id
216
- *
217
- * @param id
218
- */
219
- deleteEvent: function(id) {
220
- Registry._get("adminFunctions").wpAjax(
221
- {
222
- controller: "events",
223
- action: "delete",
224
- id: id,
225
- nonce: MPTT.timeslot_delete_nonce
226
- },
227
- function(data) {
228
- var $deleteEvent = $('#events-list').find('tr[data-id="' + id + '"]');
229
- if ($deleteEvent.length) {
230
- $deleteEvent.remove();
231
- }
232
- },
233
- function(data) {
234
- console.log(data);
235
- }
236
- );
237
- },
238
- /**
239
- * Update event item
240
- */
241
- updateEventItem: function() {
242
- var item = $('#events-list').find('tr[data-id="' + state.event_id + '"]');
243
- var $userId = $('#user_id');
244
-
245
- item.find('td.event-column').text($('#weekday_id').find('option:selected').text());
246
- item.find('td.event-start').text($('#event_start').val());
247
- item.find('td.event-end').text($('#event_end').val());
248
-
249
- item.find('td.event-user-id').text(( $userId.val() === '-1') ? '' : $userId.find('option:selected').text());
250
- item.find('td.event-description').text($('#description').val());
251
-
252
- state.event_id = null;
253
- $('#add_mp_event').removeClass('edit').val('Add New');
254
- },
255
- /**
256
- * Update Event data
257
- */
258
- updateEventData: function() {
259
- var $addEventTable = $('#add_event_table').find('.spinner');
260
-
261
- $addEventTable.addClass('is-active');
262
-
263
- Registry._get("adminFunctions").wpAjax({
264
- controller: "events",
265
- action: "update_event_data",
266
- nonce: MPTT.timeslot_update_nonce,
267
- data: {
268
- id: Registry._get("Event").event_id,
269
- event_start: $('#event_start').val(),
270
- event_end: $('#event_end').val(),
271
- description: $('#description').val(),
272
- user_id: $('#user_id').val(),
273
- weekday_ids: $('#weekday_id').val()
274
- }
275
- },
276
- function() {
277
- $addEventTable.removeClass('is-active');
278
- state.updateEventItem();
279
- state.clearTable();
280
- },
281
- function(data) {
282
- $addEventTable.removeClass('is-active');
283
- console.log(data);
284
- }
285
- );
286
- },
287
- /**
288
- * Render event item
289
- */
290
- renderEventItem: function() {
291
- var $weekdayId = $('#weekday_id');
292
- var $userId = $('#user_id');
293
- var column_ID = $weekdayId.find('option:selected').val();
294
- var $eventStart = $('#event_start');
295
- var $eventEnd = $('#event_end');
296
- var $description = $('#description');
297
-
298
- var template = {
299
- tag: 'tr',
300
- attrs: {},
301
- content: [
302
- {
303
- tag: 'td',
304
- attrs: {'style': 'display:none;'},
305
- content: [
306
- {
307
- tag: 'input',
308
- attrs: {
309
- 'type': 'hidden',
310
- 'name': 'event_data[' + column_ID + '][weekday_ids][]',
311
- 'value': column_ID
312
- }
313
- },
314
- {
315
- tag: 'input',
316
- attrs: {
317
- 'type': 'hidden',
318
- 'name': 'event_data[' + column_ID + '][event_start][]',
319
- 'value': $eventStart.val()
320
- }
321
- },
322
- {
323
- tag: 'input',
324
- attrs: {
325
- 'type': 'hidden',
326
- 'name': 'event_data[' + column_ID + '][event_end][]',
327
- 'value': $eventEnd.val()
328
- }
329
- },
330
- {
331
- tag: 'input',
332
- attrs: {
333
- 'type': 'hidden',
334
- 'name': 'event_data[' + column_ID + '][description][]',
335
- 'value': $description.val()
336
- }
337
- },
338
- {
339
- tag: 'input',
340
- attrs: {
341
- 'type': 'hidden',
342
- 'name': 'event_data[' + column_ID + '][user_id][]',
343
- 'value': $userId.val()
344
- }
345
- }
346
- ]
347
- },
348
- {
349
- tag: 'td',
350
- attrs: {
351
- 'class': 'event-column'
352
- },
353
- content: [$weekdayId.find('option:selected').text()]
354
- },
355
- {
356
- tag: 'td',
357
- attrs: {
358
- 'class': 'event-start'
359
- },
360
- content: [$eventStart.val()]
361
- },
362
- {
363
- tag: 'td',
364
- attrs: {
365
- 'class': 'event-end'
366
- },
367
- content: [$eventEnd.val()]
368
- },
369
- {
370
- tag: 'td',
371
- attrs: {
372
- 'class': 'event-description'
373
- },
374
- content: [$description.val()]
375
- },
376
- {
377
- tag: 'td',
378
- attrs: {
379
- 'class': 'event-user-id'
380
- },
381
- content: [( $userId.val() === '-1') ? '' : $userId.find('option:selected').text()]
382
- },
383
- {
384
- tag: 'td',
385
- attrs: {},
386
- content: []
387
- }
388
- ]
389
- };
390
-
391
- var htmlObject = Registry._get("adminFunctions").getHtml(template);
392
- $('#events-list').find('tbody').append(htmlObject);
393
- $('.events-list-wrapper').scrollTop(1E10);
394
- state.clearTable();
395
- },
396
- /**
397
- * Set event height
398
- *
399
- * @param element
400
- */
401
- setEventHeight: function(element) {
402
- var parent_height = element.parent().outerHeight(),
403
- body = $('body');
404
-
405
- var elementHeight = element.height();
406
- var min_height = element.data('min-height');
407
- var inner_height = element.find('.mptt-inner-event-content').height();
408
-
409
- element.css('position', '').css('width', '').css('min-height', '');
410
-
411
- if (!body.hasClass('mprm_ie_browser')) {
412
- if (inner_height <= min_height) {
413
- element.css('min-height', min_height);
414
- } else {
415
- element.css('min-height', inner_height);
416
- }
417
- } else {
418
- /** IE block **/
419
- inner_height = element.css('height', '').find('.mptt-inner-event-content').height();
420
- element.height(elementHeight);
421
-
422
- if (inner_height <= min_height) {
423
- element.css('max-height', min_height);
424
- } else {
425
- element.css('height', '');
426
- element.css('max-height', inner_height);
427
- }
428
- }
429
-
430
- if (parent_height < elementHeight) {
431
- element.height(elementHeight);
432
- }
433
- },
434
- /**
435
- * Recalculate Height
436
- * @param tdParent
437
- * @param element
438
- */
439
- recalculate_Height: function(tdParent, element) {
440
- var events = $('.mptt-event-container', tdParent),
441
- eventCount = events.length,
442
- heightItem = 0,
443
- top = 0,
444
- tdHeight = tdParent.height();
445
-
446
- if (!$('body').hasClass('mprm_ie_browser')) {
447
-
448
- heightItem = 100 / ((eventCount > 0) ? eventCount : 1);
449
-
450
- if (!_.isUndefined(element)) {
451
- element.height(heightItem + '%');
452
-
453
- } else {
454
-
455
- $.each(events, function() {
456
- var $event = $(this);
457
- $event.height(heightItem + '%');
458
-
459
- if (_.isEmpty($event.data('min-height'))) {
460
- $event.data('min-height', $event.height());
461
- }
462
-
463
- $event.css('top', top + '%');
464
- $event.removeClass('mptt-hidden');
465
- top += heightItem;
466
- });
467
- }
468
-
469
- } else {
470
-
471
- heightItem = tdHeight / ((eventCount > 0) ? eventCount : 1);
472
-
473
- if (!_.isUndefined(element)) {
474
- element.height(heightItem);
475
- } else {
476
- $.each(events, function() {
477
- var $event = $(this);
478
- $event.height(heightItem);
479
-
480
- if (_.isEmpty($event.data('min-height'))) {
481
- var min_height = $event.height();
482
- if (min_height === 0) {
483
- $event.data('min-height', heightItem);
484
- } else {
485
- $event.data('min-height', min_height);
486
- }
487
- }
488
-
489
- $event.css('top', top + 'px');
490
- $event.removeClass('mptt-hidden');
491
- top += heightItem;
492
- });
493
- }
494
- }
495
- },
496
- /**
497
- * Fill all possible height in ceil
498
- */
499
- setEventsHeight: function() {
500
- var events = $('.mptt-shortcode-wrapper').find('table').find('td.event');
501
- $.each(events, function() {
502
- var td = $(this);
503
- state.recalculate_Height(td);
504
- });
505
- },
506
- /**
507
- * Set user color settings
508
- * @param selector
509
- */
510
- setColorSettings: function(selector) {
511
- if (_.isUndefined(selector)) {
512
- selector = '.mptt-colorized';
513
- }
514
-
515
- var elements = $(selector);
516
- // var height = '';
517
- $.each(elements, function() {
518
- var element = $(this),
519
- bg = element.attr('data-bg_hover_color'),
520
- color = element.attr('data-hover_color'),
521
- tdParent = element.parent();
522
- // parentHeight = tdParent.height(),
523
- // elementHeight = '';
524
-
525
- switch (element.attr('data-type')) {
526
- case "column":
527
- case "event":
528
- element.hover(
529
- function() {
530
- if (!_.isEmpty(bg)) {
531
- element.css('background-color', bg);
532
- }
533
- if (!_.isEmpty(color)) {
534
- element.css('color', color);
535
- }
536
-
537
- state.setEventHeight(element);
538
-
539
- }, function() {
540
- element.css('max-height', '').css('min-height', '');
541
- state.recalculate_Height(tdParent, element);
542
-
543
- element.css('background-color', element.attr('data-bg_color'));
544
- element.css('color', element.attr('data-color'));
545
- }
546
- );
547
- break;
548
- case "widget":
549
- element.hover(
550
- function() {
551
- element.css('background-color', element.attr('data-background-hover-color'));
552
- element.css('color', $(this).attr('data-hover-color'));
553
- element.css('border-left-color', element.attr('data-hover-border-color'));
554
- },
555
- function() {
556
- element.css('background-color', element.attr('data-background-color'));
557
- element.css('color', element.attr('data-color'));
558
- element.css('border-left-color', element.attr('data-border-color'));
559
- }
560
- );
561
- break;
562
- default:
563
- break;
564
- }
565
- });
566
- },
567
- /**
568
- * Clear input data
569
- */
570
- clearTable: function() {
571
- var $weekdayId = $("#weekday_id");
572
- $('#add_event_table input:not(.button),#add_event_table textarea').val('');
573
- $weekdayId.val($weekdayId.find('option:first').attr('value'));
574
- },
575
- /**
576
- * get Row span
577
- *
578
- * @param events
579
- * @returns {number}
580
- */
581
- getRowSpan: function(events, td) {
582
- var arrMax = [];
583
- var arrMin = [];
584
- var columnId = td.attr('data-column-id');
585
-
586
- /*
587
- * Erroneous Positioning of Events
588
- * https://wordpress.org/support/topic/erroneous-positioning-of-events/
589
- */
590
- var nextTr = td.closest('tr').next('tr');
591
- var nextTd = nextTr.find('td[data-column-id="' + columnId + '"]');
592
- var nextTdSet = (nextTr.length > 0) && (nextTd.length > 0) && (nextTd.children().length > 0);
593
-
594
- while ( !nextTdSet ) {
595
- if( nextTr.next('tr').length == 0 ){
596
- nextTdSet = true;
597
- nextTr = false;
598
- break;
599
- }
600
-
601
- nextTr = nextTr.next('tr');
602
- nextTd = nextTr.find('td[data-column-id="' + columnId + '"]');
603
- nextTdSet = nextTd.children().length > 0;
604
- }
605
-
606
- var nextEventIndex = false
607
- if (nextTr) {
608
- nextEventIndex = nextTr.data('index');
609
- }
610
- //console.log(td, nextEventIndex)
611
-
612
- /* End of "Erroneous Positioning of Events" */
613
-
614
- $.each(events, function(index) {
615
- var start = $(this).attr('data-start');
616
- var end = $(this).attr('data-end');
617
-
618
- arrMin[index] = start;
619
- arrMax[index] = end;
620
- });
621
-
622
- var min = Math.min.apply(Math, arrMin);
623
- var max = Math.max.apply(Math, arrMax);
624
-
625
- if ( nextEventIndex && max > nextEventIndex ) {
626
- max = nextEventIndex;
627
- }
628
-
629
- var rowSpan = (max - min);
630
-
631
- return rowSpan < 1 ? 1 : rowSpan;
632
- },
633
- /**
634
- * Responsive filter
635
- *
636
- * @param element
637
- */
638
- responsiveFilter: function(element) {
639
- var eventID = 'all';
640
- var parentShortcode = element.parents('.mptt-shortcode-wrapper');
641
-
642
- if (element.is("select")) {
643
- eventID = element.val();
644
- } else {
645
- eventID = element.attr('href').replace("#", "");
646
- }
647
-
648
- var $listEvent = parentShortcode.find('.mptt-list-event');
649
-
650
- if (eventID !== 'all') {
651
- $listEvent.hide();
652
- parentShortcode.find('.mptt-list-event[data-event-id="' + eventID + '"]').show();
653
- } else {
654
- $listEvent.show();
655
- }
656
-
657
- $.each(parentShortcode.find('.mptt-column'), function() {
658
- $(this).show();
659
- if ($(this).find('.mptt-list-event:visible').length < 1) {
660
- $(this).hide();
661
- }
662
- });
663
-
664
- },
665
- /**
666
- * Filter static version
667
- *
668
- * @param element
669
- */
670
- filterStatic: function(element, event) {
671
-
672
- var parentShortcode = element.parents('.mptt-shortcode-wrapper');
673
- var eventID = '#all';
674
- var id = _.isEmpty(parentShortcode.attr('id')) ? 'not-set' : parentShortcode.attr('id');
675
-
676
- if (element.is("select")) {
677
- eventID = element.val();
678
- } else {
679
- eventID = element.attr('href').replace("#", "");
680
- }
681
-
682
- if (event == false || event.originalEvent === undefined) {
683
- //console.log('skip');
684
- } else {
685
- window.location.hash = id + ':' + eventID;
686
- }
687
-
688
- parentShortcode.find('table').hide();
689
-
690
- parentShortcode.find('table[id="#' + eventID + '"]').fadeIn();
691
-
692
- state.setEventsHeight();
693
- },
694
- /**
695
- * Add class if exists events in <TD>
696
- */
697
- setClassTd: function() {
698
- $.each($('.mptt-event-container'), function() {
699
- $(this).parents('td').addClass('event');
700
- });
701
- },
702
- /**
703
- * Init TimeTable
704
- */
705
- initTableData: function() {
706
- state.setClassTd();
707
- state.setRowSpanTd();
708
- var table_class = '.' + MPTT.table_class;
709
-
710
- if ($(table_class).data('hide_empty_row')) {
711
- state.hideEmptyRows();
712
- }
713
- },
714
- /**
715
- * init Filters
716
- */
717
- filterShortcodeEvents: function() {
718
- var selector = $('.mptt-menu');
719
-
720
- if (selector.length) {
721
-
722
- selector.off('change').on('change', function(event) {
723
- state.filterStatic($(this), event);
724
- state.responsiveFilter($(this));
725
- });
726
-
727
- $('.mptt-navigation-tabs.mptt-menu a').off('click').on('click', function(event) {
728
-
729
- var $currentTab = $(this);
730
- $currentTab.parents('.mptt-navigation-tabs.mptt-menu').find('li').removeClass('active');
731
-
732
- $currentTab.parents('li').addClass('active');
733
- state.filterStatic($currentTab, event);
734
- state.responsiveFilter($currentTab);
735
-
736
- });
737
-
738
- }
739
- },
740
- /**
741
- * Show events in shortcode container by current event
742
- * @param shortcode_wrapper
743
- * @param event
744
- */
745
- showCurrentEvent: function(shortcode_wrapper, event) {
746
- if (shortcode_wrapper.find('.mptt-menu').hasClass('mptt-navigation-tabs')) {
747
- shortcode_wrapper.find('.mptt-navigation-tabs').find('a[href="#' + event + '"]').click();
748
- } else if (shortcode_wrapper.find('.mptt-menu').hasClass('mptt-navigation-select')) {
749
- if (shortcode_wrapper.find('.mptt-navigation-select option[value="' + event + '"]')) {
750
- shortcode_wrapper.find('.mptt-navigation-select').val(event).change();
751
- } else {
752
- shortcode_wrapper.find('table[id="#all"]').fadeIn();
753
- }
754
- } else {
755
- shortcode_wrapper.find('table[id="#all"]').fadeIn();
756
- }
757
- },
758
- /**
759
- * Filter by hash
760
- */
761
- getFilterByHash: function() {
762
- var is_single = 1;
763
- var hash = window.location.hash;
764
-
765
- if (!_.isUndefined(hash)) {
766
- var HashArray = hash.split(':');
767
- var id = HashArray[0];
768
- var event = HashArray[1];
769
- var shortcode_wrapper = $('.mptt-shortcode-wrapper');
770
- event = _.isUndefined(event) ? 'all' : event;
771
-
772
- if (shortcode_wrapper.length === is_single) {
773
- state.showCurrentEvent(shortcode_wrapper, event);
774
- } else {
775
-
776
- $.each(shortcode_wrapper, function(index, object) {
777
- var element = $(object);
778
- var element_id = '#' + element.attr('id');
779
-
780
- if (element_id === id) {
781
- state.showCurrentEvent(element, event);
782
- } else {
783
- state.showCurrentEvent(element, 'all');
784
- }
785
- });
786
-
787
- }
788
- }
789
- state.setEventsHeight();
790
- },
791
- /**
792
- * Clear table after change colSpan
793
- *
794
- * @param columnIndex
795
- * @param toColSpan
796
- * @param $table
797
- * @param row
798
- */
799
- removeCellsAfterChangeColSpan: function(columnIndex, toColSpan, $table, row) {
800
- for (columnIndex; columnIndex < toColSpan; columnIndex++) {
801
- var columnId = $table.find('th[data-index="' + columnIndex + '"]').data('column-id');
802
- row.find('td:not(.event)[data-column-id="' + columnId + '"]').remove();
803
- }
804
- },
805
- /**
806
- * Set rowSpan
807
- * @param td
808
- * @param rowSpan
809
- * @param $table
810
- * @param columnId
811
- * @returns rowSpan
812
- */
813
- removeCellsAfterChangeRowSpan: function(td, rowSpan, $table, columnId) {
814
- var index = td.parents('tr').attr('data-index'),
815
- toRowSpan = rowSpan + parseInt(index) - 1,
816
- colSpan = td.attr('colspan'),
817
- columnIndex = $table.find('th[data-column-id="' + columnId + '"]').data('index'),
818
- toColSpan = parseInt(columnIndex) + parseInt(colSpan);
819
-
820
- for (index; index < toRowSpan; index++) {
821
-
822
- var row = $table.find('tr.mptt-shortcode-row-' + (parseInt(index) + 1));
823
-
824
- if (row.length) {
825
-
826
- if (row.find('td.event[data-column-id="' + columnId + '"]').length) {
827
- rowSpan -= (toRowSpan - index);
828
-
829
- if (rowSpan < 2) {
830
- rowSpan = 1;
831
- break;
832
- }
833
- }
834
-
835
- if (colSpan > 1) {
836
- state.removeCellsAfterChangeColSpan(columnIndex, toColSpan, $table, row);
837
- }
838
-
839
- row.find('td:not(.event)[data-column-id="' + columnId + '"]').remove();
840
- }
841
- }
842
- return rowSpan;
843
- },
844
- /**
845
- * Set rowSpan td
846
- */
847
- setRowSpanTd: function() {
848
- var table_class = '.' + MPTT.table_class;
849
- $.each($(table_class), function() {
850
- var $table = $(this);
851
-
852
- $.each($table.find('td.event'), function() {
853
- var td = $(this),
854
- events = td.find('.mptt-event-container'),
855
- columnId = td.attr('data-column-id'),
856
- rowHeight = td.attr('data-row_height'),
857
- rowSpan = state.getRowSpan(events, td);
858
-
859
- if (!_.isUndefined(rowSpan) && rowSpan > 1) {
860
-
861
- rowSpan = state.removeCellsAfterChangeRowSpan(td, rowSpan, $table, columnId);
862
-
863
- if (!isNaN(rowHeight)) {
864
- td.css('height', rowSpan * rowHeight);
865
- }
866
- }
867
-
868
- td.attr('rowspan', rowSpan);
869
- });
870
- });
871
- },
872
- /**
873
- * Remove empty rows
874
- */
875
- hideEmptyRows: function() {
876
- var table_class = '.' + MPTT.table_class;
877
-
878
- var trs = $(table_class + ' tbody tr'),
879
- col_count = $(table_class).first().find('th').length;
880
-
881
- $.each(trs, function(index, value) {
882
- // if all columns in the row are empty
883
- if ($(value).find('td.event').length === 0 && $(value).find('td').length === col_count) {
884
- $(value).remove();
885
- }
886
- });
887
- },
888
- /**
889
- * Widget settings
890
- */
891
- displaySettings: function() {
892
- var $viewSettings = $('.view_settings');
893
- if ($viewSettings.length) {
894
- $viewSettings.change(function() {
895
- if ($(this).val() === "all") {
896
- var id = $(this).attr('id');
897
- $(this).parents('.mptt-container').find('.next-days').css("display", "block");
898
- }
899
- else {
900
- $(this).parents('.mptt-container').find(".next-days").css("display", "none");
901
- }
902
- });
903
- }
904
- },
905
- /**
906
- * Widget time settings
907
- * @param selector
908
- */
909
- timeMode: function(selector) {
910
- if (selector) {
911
- var selector_id = "." + $(this).attr('id');
912
- $('#' + selector).change(function() {
913
- if ($(this).val() === "server") {
914
- var id = $(this).attr('id');
915
- $(this).parents('.mptt-container').find(selector_id).css("display", "block");
916
- }
917
- else {
918
- $(this).parents('.mptt-container').find(selector_id).css("display", "none");
919
- }
920
- });
921
- }
922
- },
923
- /**
924
- * init DatePicker for column
925
- */
926
- initDatePicker: function() {
927
- var $date_picker = $("#datepicker");
928
-
929
- if ($date_picker.length) {
930
- $date_picker.datepicker({
931
- dateFormat: 'd/m/yy',
932
- setDate: Date.parse($date_picker.val())
933
- });
934
- }
935
- },
936
- /**
937
- * init Column radio box change
938
- */
939
- columnRadioBox: function() {
940
- var $date_picker = $('#datepicker');
941
- var $column_option = $('input.option-input[name="column[column_option]"]');
942
- var $weekday = $('select.mp-weekday');
943
-
944
- if ($column_option.length) {
945
- $column_option.on('change', function() {
946
- switch ($(this).val()) {
947
- case 'simple':
948
- $weekday.prop("disabled", true);
949
- $date_picker.prop("disabled", true);
950
- break;
951
- case 'weekday':
952
- $weekday.prop("disabled", false);
953
- $date_picker.val('').prop("disabled", true);
954
- break;
955
- case 'date':
956
- $weekday.prop("disabled", true);
957
- $date_picker.prop("disabled", false);
958
- break;
959
- }
960
- });
961
- }
962
- }
963
- };
964
- }
965
-
966
- return {
967
- getInstance: function() {
968
- if (!state) {
969
- state = createInstance();
970
- }
971
- return state;
972
- }
973
- };
974
  })(jQuery));
1
+ /*global jQuery:false, console:false, _:false, CommonManager:false,Registry:false, wp:false, MPTT:false*/
2
+
3
+ Registry.register("Event",
4
+ (function($) {
5
+ "use strict";
6
+
7
+ var state;
8
+
9
+ function createInstance() {
10
+
11
+ return {
12
+ event_id: '',
13
+ eventsData: {},
14
+ /**
15
+ * Init
16
+ */
17
+ init: function() {
18
+ state.initTimePicker();
19
+ state.addEventButton();
20
+ state.initDeleteButtons();
21
+ state.initEditButtons();
22
+ state.initColorPicker();
23
+ state.initDatePicker();
24
+ state.columnRadioBox();
25
+ },
26
+ /**
27
+ * Init time picker
28
+ */
29
+ initTimePicker: function() {
30
+ var timeFormat = Boolean(parseInt($('#time_format').val()));
31
+ $('#event_start').timepicker({
32
+ showPeriod: timeFormat, // Define whether or not to show AM/PM with selected time. (default: false)
33
+ showPeriodLabels: timeFormat,
34
+ defaultTime: '00:00'
35
+ });
36
+
37
+ $('#event_end').timepicker({
38
+ showPeriod: timeFormat, // Define whether or not to show AM/PM with selected time. (default: false)
39
+ showPeriodLabels: timeFormat,
40
+ defaultTime: '00:00'
41
+ });
42
+ },
43
+ /**
44
+ * Init widget slider
45
+ * @param selector
46
+ * @param autoScroll
47
+ */
48
+ initSlider: function(selector, autoScroll) {
49
+ var play = _.isUndefined(autoScroll) ? false : Boolean(autoScroll);
50
+ var id = selector.replace(/^\D+/g, '');
51
+ $(selector).carouFredSel({
52
+ items: {
53
+ visible: 3
54
+ },
55
+ direction: "up",
56
+ scroll: {
57
+ items: 1,
58
+ easing: "swing",
59
+ pauseOnHover: true,
60
+ onAfter: function(data) {
61
+ data.items.old.each(function() {
62
+ $(this).removeClass('visible');
63
+ }
64
+ );
65
+ data.items.visible.each(function() {
66
+ $(this).addClass('visible');
67
+ }
68
+ );
69
+ }
70
+ },
71
+ auto: {
72
+ play: play,
73
+ timeoutDuration: 3000
74
+ },
75
+ prev: {
76
+ button: "#mp_prev_button" + id
77
+ },
78
+ next: {
79
+ button: "#mp_next_button" + id
80
+ }
81
+ });
82
+
83
+ $(selector).trigger("currentVisible", function(items) {
84
+ items.addClass("visible");
85
+ });
86
+ state.setColorSettings(selector + ' ' + '.mptt-colorized');
87
+ },
88
+ /**
89
+ * init Delete Button
90
+ */
91
+ initDeleteButton: function() {
92
+ var $events = $('#events-list');
93
+
94
+ $events.find('li.event').find('i.operation-button.dashicons-no.dashicons').off('click').on('click', function() {
95
+ if ($events.find('li.event').length > 1) {
96
+ $(this).parents('li.event').remove();
97
+ } else {
98
+ $events.remove();
99
+ }
100
+ });
101
+ },
102
+ /**
103
+ * Init color picker
104
+ */
105
+ initColorPicker: function(parent) {
106
+ if (_.isUndefined(parent)) {
107
+ parent = '';
108
+ }
109
+ var selectorColorInput = $(parent + ' input.clr-picker');
110
+ var selectorTextInput = $(parent + ' input.regular-text');
111
+ selectorColorInput.spectrum("destroy");
112
+
113
+ // init color picker
114
+ selectorColorInput.spectrum({
115
+ preferredFormat: "rgb",
116
+ showInput: true,
117
+ showAlpha: true,
118
+ allowEmpty: true,
119
+ palette: [
120
+ ["#000", "#444", "#666", "#999", "#ccc", "#eee", "#f3f3f3", "#fff"],
121
+ ["#f00", "#f90", "#ff0", "#0f0", "#0ff", "#00f", "#90f", "#f0f"],
122
+ ["#f4cccc", "#fce5cd", "#fff2cc", "#d9ead3", "#d0e0e3", "#cfe2f3", "#d9d2e9", "#ead1dc"],
123
+ ["#ea9999", "#f9cb9c", "#ffe599", "#b6d7a8", "#a2c4c9", "#9fc5e8", "#b4a7d6", "#d5a6bd"],
124
+ ["#e06666", "#f6b26b", "#ffd966", "#93c47d", "#76a5af", "#6fa8dc", "#8e7cc3", "#c27ba0"],
125
+ ["#c00", "#e69138", "#f1c232", "#6aa84f", "#45818e", "#3d85c6", "#674ea7", "#a64d79"],
126
+ ["#900", "#b45f06", "#bf9000", "#38761d", "#134f5c", "#0b5394", "#351c75", "#741b47"],
127
+ ["#600", "#783f04", "#7f6000", "#274e13", "#0c343d", "#073763", "#20124d", "#4c1130"]
128
+ ],
129
+ showPalette: true,
130
+ show: function(color) {
131
+ $(this).val(color);
132
+ },
133
+ hide: function(color) {
134
+ var parent = $(this).parents('.select-color');
135
+ parent.find('.regular-text').val($(this).val());
136
+ },
137
+ change: function(color) {
138
+ var parent = $(this).parents('.select-color');
139
+ parent.find('input:not([type="hidden"])').val($(this).val());
140
+ }
141
+ });
142
+
143
+ //change color preview block
144
+ selectorTextInput.off('keyup').on('keyup', function() {
145
+ var parentTr = $(this).parents('.select-color');
146
+ var spectrumElement = parentTr.find('.clr-picker');
147
+ var colorElement = parentTr.find(".regular-text").val();
148
+ var preview_inner = parentTr.find(".sp-preview-inner");
149
+ preview_inner.css({
150
+ 'background-color': colorElement
151
+ });
152
+ spectrumElement.spectrum("set", colorElement);
153
+ });
154
+ },
155
+ /**
156
+ * Add event
157
+ */
158
+ addEventButton: function() {
159
+ $(document).on('click.admin', '#add_mp_event', function() {
160
+ if ($(this).hasClass('edit')) {
161
+ state.updateEventData();
162
+ } else {
163
+ state.renderEventItem();
164
+ }
165
+ });
166
+ },
167
+ /**
168
+ * init event data delete button
169
+ */
170
+ initDeleteButtons: function() {
171
+ $(document).on('click.admin', '#events-list .delete-event-button', function() {
172
+ var id = $(this).attr('data-id');
173
+ state.deleteEvent(id);
174
+ });
175
+ },
176
+ /**
177
+ * init event data edit button
178
+ */
179
+ initEditButtons: function() {
180
+ $(document).on('click.admin', '#events-list .edit-event-button', function() {
181
+ var id = $(this).attr('data-id'),
182
+ $tr = $(this).parent().parent();
183
+ $(this).parent().find('.spinner').addClass('is-active');
184
+
185
+ Registry._get("adminFunctions").wpAjax({
186
+ controller: "events",
187
+ action: "get_event_data",
188
+ id: id
189
+ },
190
+ function(data) {
191
+ var $addMpEvent = $('#add_mp_event');
192
+ var $events = $('#events-list');
193
+ $events.find('.spinner').removeClass('is-active');
194
+ $events.find(' tr').removeClass('active');
195
+ $tr.addClass('active');
196
+
197
+ $('#event_start').val(data.event_start);
198
+ $('#event_end').val(data.event_end);
199
+ $('#description').val(data.description);
200
+ $('#user_id').val(data.user_id);
201
+ $('#weekday_id').val(data.column_id);
202
+
203
+ $addMpEvent.addClass('edit');
204
+ $addMpEvent.val('Update');
205
+
206
+ state.event_id = data.id;
207
+ },
208
+ function(data) {
209
+ console.warn(data);
210
+ }
211
+ );
212
+ });
213
+ },
214
+ /**
215
+ * Delete event data by id
216
+ *
217
+ * @param id
218
+ */
219
+ deleteEvent: function(id) {
220
+ Registry._get("adminFunctions").wpAjax(
221
+ {
222
+ controller: "events",
223
+ action: "delete",
224
+ id: id,
225
+ nonce: MPTT.timeslot_delete_nonce
226
+ },
227
+ function(data) {
228
+ var $deleteEvent = $('#events-list').find('tr[data-id="' + id + '"]');
229
+ if ($deleteEvent.length) {
230
+ $deleteEvent.remove();
231
+ }
232
+ },
233
+ function(data) {
234
+ console.log(data);
235
+ }
236
+ );
237
+ },
238
+ /**
239
+ * Update event item
240
+ */
241
+ updateEventItem: function() {
242
+ var item = $('#events-list').find('tr[data-id="' + state.event_id + '"]');
243
+ var $userId = $('#user_id');
244
+
245
+ item.find('td.event-column').text($('#weekday_id').find('option:selected').text());
246
+ item.find('td.event-start').text($('#event_start').val());
247
+ item.find('td.event-end').text($('#event_end').val());
248
+
249
+ item.find('td.event-user-id').text(( $userId.val() === '-1') ? '' : $userId.find('option:selected').text());
250
+ item.find('td.event-description').text($('#description').val());
251
+
252
+ state.event_id = null;
253
+ $('#add_mp_event').removeClass('edit').val('Add New');
254
+ },
255
+ /**
256
+ * Update Event data
257
+ */
258
+ updateEventData: function() {
259
+ var $addEventTable = $('#add_event_table').find('.spinner');
260
+
261
+ $addEventTable.addClass('is-active');
262
+
263
+ Registry._get("adminFunctions").wpAjax({
264
+ controller: "events",
265
+ action: "update_event_data",
266
+ nonce: MPTT.timeslot_update_nonce,
267
+ data: {
268
+ id: Registry._get("Event").event_id,
269
+ event_start: $('#event_start').val(),
270
+ event_end: $('#event_end').val(),
271
+ description: $('#description').val(),
272
+ user_id: $('#user_id').val(),
273
+ weekday_ids: $('#weekday_id').val()
274
+ }
275
+ },
276
+ function() {
277
+ $addEventTable.removeClass('is-active');
278
+ state.updateEventItem();
279
+ state.clearTable();
280
+ },
281
+ function(data) {
282
+ $addEventTable.removeClass('is-active');
283
+ console.log(data);
284
+ }
285
+ );
286
+ },
287
+ /**
288
+ * Render event item
289
+ */
290
+ renderEventItem: function() {
291
+ var $weekdayId = $('#weekday_id');
292
+ var $userId = $('#user_id');
293
+ var column_ID = $weekdayId.find('option:selected').val();
294
+ var $eventStart = $('#event_start');
295
+ var $eventEnd = $('#event_end');
296
+ var $description = $('#description');
297
+
298
+ var template = {
299
+ tag: 'tr',
300
+ attrs: {},
301
+ content: [
302
+ {
303
+ tag: 'td',
304
+ attrs: {'style': 'display:none;'},
305
+ content: [
306
+ {
307
+ tag: 'input',
308
+ attrs: {
309
+ 'type': 'hidden',
310
+ 'name': 'event_data[' + column_ID + '][weekday_ids][]',
311
+ 'value': column_ID
312
+ }
313
+ },
314
+ {
315
+ tag: 'input',
316
+ attrs: {
317
+ 'type': 'hidden',
318
+ 'name': 'event_data[' + column_ID + '][event_start][]',
319
+ 'value': $eventStart.val()
320
+ }
321
+ },
322
+ {
323
+ tag: 'input',
324
+ attrs: {
325
+ 'type': 'hidden',
326
+ 'name': 'event_data[' + column_ID + '][event_end][]',
327
+ 'value': $eventEnd.val()
328
+ }
329
+ },
330
+ {
331
+ tag: 'input',
332
+ attrs: {
333
+ 'type': 'hidden',
334
+ 'name': 'event_data[' + column_ID + '][description][]',
335
+ 'value': $description.val()
336
+ }
337
+ },
338
+ {
339
+ tag: 'input',
340
+ attrs: {
341
+ 'type': 'hidden',
342
+ 'name': 'event_data[' + column_ID + '][user_id][]',
343
+ 'value': $userId.val()
344
+ }
345
+ }
346
+ ]
347
+ },
348
+ {
349
+ tag: 'td',
350
+ attrs: {
351
+ 'class': 'event-column'
352
+ },
353
+ content: [$weekdayId.find('option:selected').text()]
354
+ },
355
+ {
356
+ tag: 'td',
357
+ attrs: {
358
+ 'class': 'event-start'
359
+ },
360
+ content: [$eventStart.val()]
361
+ },
362
+ {
363
+ tag: 'td',
364
+ attrs: {
365
+ 'class': 'event-end'
366
+ },
367
+ content: [$eventEnd.val()]
368
+ },
369
+ {
370
+ tag: 'td',
371
+ attrs: {
372
+ 'class': 'event-description'
373
+ },
374
+ content: [$description.val()]
375
+ },
376
+ {
377
+ tag: 'td',
378
+ attrs: {
379
+ 'class': 'event-user-id'
380
+ },
381
+ content: [( $userId.val() === '-1') ? '' : $userId.find('option:selected').text()]
382
+ },
383
+ {
384
+ tag: 'td',
385
+ attrs: {},
386
+ content: []
387
+ }
388
+ ]
389
+ };
390
+
391
+ var htmlObject = Registry._get("adminFunctions").getHtml(template);
392
+ $('#events-list').find('tbody').append(htmlObject);
393
+ $('.events-list-wrapper').scrollTop(1E10);
394
+ state.clearTable();
395
+ },
396
+ /**
397
+ * Set event height
398
+ *
399
+ * @param element
400
+ */
401
+ setEventHeight: function(element) {
402
+ var parent_height = element.parent().outerHeight(),
403
+ body = $('body');
404
+
405
+ var elementHeight = element.height();
406
+ var min_height = element.data('min-height');
407
+ var inner_height = element.find('.mptt-inner-event-content').height();
408
+
409
+ element.css('position', '').css('width', '').css('min-height', '');
410
+
411
+ if (!body.hasClass('mprm_ie_browser')) {
412
+ if (inner_height <= min_height) {
413
+ element.css('min-height', min_height);
414
+ } else {
415
+ element.css('min-height', inner_height);
416
+ }
417
+ } else {
418
+ /** IE block **/
419
+ inner_height = element.css('height', '').find('.mptt-inner-event-content').height();
420
+ element.height(elementHeight);
421
+
422
+ if (inner_height <= min_height) {
423
+ element.css('max-height', min_height);
424
+ } else {
425
+ element.css('height', '');
426
+ element.css('max-height', inner_height);
427
+ }
428
+ }
429
+
430
+ if (parent_height < elementHeight) {
431
+ element.height(elementHeight);
432
+ }
433
+ },
434
+ /**
435
+ * Recalculate Height
436
+ * @param tdParent
437
+ * @param element
438
+ */
439
+ recalculate_Height: function(tdParent, element) {
440
+ var events = $('.mptt-event-container', tdParent),
441
+ eventCount = events.length,
442
+ heightItem = 0,
443
+ top = 0,
444
+ tdHeight = tdParent.height();
445
+
446
+ if (!$('body').hasClass('mprm_ie_browser')) {
447
+
448
+ heightItem = 100 / ((eventCount > 0) ? eventCount : 1);
449
+
450
+ if (!_.isUndefined(element)) {
451
+ element.height(heightItem + '%');
452
+
453
+ } else {
454
+
455
+ $.each(events, function() {
456
+ var $event = $(this);
457
+ $event.height(heightItem + '%');
458
+
459
+ if (_.isEmpty($event.data('min-height'))) {
460
+ $event.data('min-height', $event.height());
461
+ }
462
+
463
+ $event.css('top', top + '%');
464
+ $event.removeClass('mptt-hidden');
465
+ top += heightItem;
466
+ });
467
+ }
468
+
469
+ } else {
470
+
471
+ heightItem = tdHeight / ((eventCount > 0) ? eventCount : 1);
472
+
473
+ if (!_.isUndefined(element)) {
474
+ element.height(heightItem);
475
+ } else {
476
+ $.each(events, function() {
477
+ var $event = $(this);
478
+ $event.height(heightItem);
479
+
480
+ if (_.isEmpty($event.data('min-height'))) {
481
+ var min_height = $event.height();
482
+ if (min_height === 0) {
483
+ $event.data('min-height', heightItem);
484
+ } else {
485
+ $event.data('min-height', min_height);
486
+ }
487
+ }
488
+
489
+ $event.css('top', top + 'px');
490
+ $event.removeClass('mptt-hidden');
491
+ top += heightItem;
492
+ });
493
+ }
494
+ }
495
+ },
496
+ /**
497
+ * Fill all possible height in ceil
498
+ */
499
+ setEventsHeight: function() {
500
+ var events = $('.mptt-shortcode-wrapper').find('table').find('td.event');
501
+ $.each(events, function() {
502
+ var td = $(this);
503
+ state.recalculate_Height(td);
504
+ });
505
+ },
506
+ /**
507
+ * Set user color settings
508
+ * @param selector
509
+ */
510
+ setColorSettings: function(selector) {
511
+ if (_.isUndefined(selector)) {
512
+ selector = '.mptt-colorized';
513
+ }
514
+
515
+ var elements = $(selector);
516
+ // var height = '';
517
+ $.each(elements, function() {
518
+ var element = $(this),
519
+ bg = element.attr('data-bg_hover_color'),
520
+ color = element.attr('data-hover_color'),
521
+ tdParent = element.parent();
522
+ // parentHeight = tdParent.height(),
523
+ // elementHeight = '';
524
+
525
+ switch (element.attr('data-type')) {
526
+ case "column":
527
+ case "event":
528
+ element.hover(
529
+ function() {
530
+ if (!_.isEmpty(bg)) {
531
+ element.css('background-color', bg);
532
+ }
533
+ if (!_.isEmpty(color)) {
534
+ element.css('color', color);
535
+ }
536
+
537
+ state.setEventHeight(element);
538
+
539
+ }, function() {
540
+ element.css('max-height', '').css('min-height', '');
541
+ state.recalculate_Height(tdParent, element);
542
+
543
+ element.css('background-color', element.attr('data-bg_color'));
544
+ element.css('color', element.attr('data-color'));
545
+ }
546
+ );
547
+ break;
548
+ case "widget":
549
+ element.hover(
550
+ function() {
551
+ element.css('background-color', element.attr('data-background-hover-color'));
552
+ element.css('color', $(this).attr('data-hover-color'));
553
+ element.css('border-left-color', element.attr('data-hover-border-color'));
554
+ },
555
+ function() {
556
+ element.css('background-color', element.attr('data-background-color'));
557
+ element.css('color', element.attr('data-color'));
558
+ element.css('border-left-color', element.attr('data-border-color'));
559
+ }
560
+ );
561
+ break;
562
+ default:
563
+ break;
564
+ }
565
+ });
566
+ },
567
+ /**
568
+ * Clear input data
569
+ */
570
+ clearTable: function() {
571
+ var $weekdayId = $("#weekday_id");
572
+ $('#add_event_table input:not(.button),#add_event_table textarea').val('');
573
+ $weekdayId.val($weekdayId.find('option:first').attr('value'));
574
+ },
575
+ /**
576
+ * get Row span
577
+ *
578
+ * @param events
579
+ * @returns {number}
580
+ */
581
+ getRowSpan: function(events, td) {
582
+ var arrMax = [];
583
+ var arrMin = [];
584
+ var columnId = td.attr('data-column-id');
585
+
586
+ /*
587
+ * Erroneous Positioning of Events
588
+ * https://wordpress.org/support/topic/erroneous-positioning-of-events/
589
+ */
590
+ var nextTr = td.closest('tr').next('tr');
591
+ var nextTd = nextTr.find('td[data-column-id="' + columnId + '"]');
592
+ var nextTdSet = (nextTr.length > 0) && (nextTd.length > 0) && (nextTd.children().length > 0);
593
+
594
+ while ( !nextTdSet ) {
595
+ if( nextTr.next('tr').length == 0 ){
596
+ nextTdSet = true;
597
+ nextTr = false;
598
+ break;
599
+ }
600
+
601
+ nextTr = nextTr.next('tr');
602
+ nextTd = nextTr.find('td[data-column-id="' + columnId + '"]');
603
+ nextTdSet = nextTd.children().length > 0;
604
+ }
605
+
606
+ var nextEventIndex = false
607
+ if (nextTr) {
608
+ nextEventIndex = nextTr.data('index');
609
+ }
610
+ //console.log(td, nextEventIndex)
611
+
612
+ /* End of "Erroneous Positioning of Events" */
613
+
614
+ $.each(events, function(index) {
615
+ var start = $(this).attr('data-start');
616
+ var end = $(this).attr('data-end');
617
+
618
+ arrMin[index] = start;
619
+ arrMax[index] = end;
620
+ });
621
+
622
+ var min = Math.min.apply(Math, arrMin);
623
+ var max = Math.max.apply(Math, arrMax);
624
+
625
+ if ( nextEventIndex && max > nextEventIndex ) {
626
+ max = nextEventIndex;
627
+ }
628
+
629
+ var rowSpan = (max - min);
630
+
631
+ return rowSpan < 1 ? 1 : rowSpan;
632
+ },
633
+ /**
634
+ * Responsive filter
635
+ *
636
+ * @param element
637
+ */
638
+ responsiveFilter: function(element) {
639
+ var eventID = 'all';
640
+ var parentShortcode = element.parents('.mptt-shortcode-wrapper');
641
+
642
+ if (element.is("select")) {
643
+ eventID = element.val();
644
+ } else {
645
+ eventID = element.attr('href').replace("#", "");
646
+ }
647
+
648
+ var $listEvent = parentShortcode.find('.mptt-list-event');
649
+
650
+ if (eventID !== 'all') {
651
+ $listEvent.hide();
652
+ parentShortcode.find('.mptt-list-event[data-event-id="' + eventID + '"]').show();
653
+ } else {
654
+ $listEvent.show();
655
+ }
656
+
657
+ $.each(parentShortcode.find('.mptt-column'), function() {
658
+ $(this).show();
659
+ if ($(this).find('.mptt-list-event:visible').length < 1) {
660
+ $(this).hide();
661
+ }
662
+ });
663
+
664
+ },
665
+ /**
666
+ * Filter static version
667
+ *
668
+ * @param element
669
+ */
670
+ filterStatic: function(element, event) {
671
+
672
+ var parentShortcode = element.parents('.mptt-shortcode-wrapper');
673
+ var eventID = '#all';
674
+ var id = _.isEmpty(parentShortcode.attr('id')) ? 'not-set' : parentShortcode.attr('id');
675
+
676
+ if (element.is("select")) {
677
+ eventID = element.val();
678
+ } else {
679
+ eventID = element.attr('href').replace("#", "");
680
+ }
681
+
682
+ if (event == false || event.originalEvent === undefined) {
683
+ //console.log('skip');
684
+ } else {
685
+ window.location.hash = id + ':' + eventID;
686
+ }
687
+
688
+ parentShortcode.find('table').hide();
689
+
690
+ parentShortcode.find('table[id="#' + eventID + '"]').fadeIn();
691
+
692
+ state.setEventsHeight();
693
+ },
694
+ /**
695
+ * Add class if exists events in <TD>
696
+ */
697
+ setClassTd: function() {
698
+ $.each($('.mptt-event-container'), function() {
699
+ $(this).parents('td').addClass('event');
700
+ });
701
+ },
702
+ /**
703
+ * Init TimeTable
704
+ */
705
+ initTableData: function() {
706
+ state.setClassTd();
707
+ state.setRowSpanTd();
708
+ var table_class = '.' + MPTT.table_class;
709
+
710
+ if ($(table_class).data('hide_empty_row')) {
711
+ state.hideEmptyRows();
712
+ }
713
+ },
714
+ /**
715
+ * init Filters
716
+ */
717
+ filterShortcodeEvents: function() {
718
+ var selector = $('.mptt-menu');
719
+
720
+ if (selector.length) {
721
+
722
+ selector.off('change').on('change', function(event) {
723
+ state.filterStatic($(this), event);
724
+ state.responsiveFilter($(this));
725
+ });
726
+
727
+ $('.mptt-navigation-tabs.mptt-menu a').off('click').on('click', function(event) {
728
+
729
+ var $currentTab = $(this);
730
+ $currentTab.parents('.mptt-navigation-tabs.mptt-menu').find('li').removeClass('active');
731
+
732
+ $currentTab.parents('li').addClass('active');
733
+ state.filterStatic($currentTab, event);
734
+ state.responsiveFilter($currentTab);
735
+
736
+ });
737
+
738
+ }
739
+ },
740
+ /**
741
+ * Show events in shortcode container by current event
742
+ * @param shortcode_wrapper
743
+ * @param event
744
+ */
745
+ showCurrentEvent: function(shortcode_wrapper, event) {
746
+ if (shortcode_wrapper.find('.mptt-menu').hasClass('mptt-navigation-tabs')) {
747
+ shortcode_wrapper.find('.mptt-navigation-tabs').find('a[href="#' + event + '"]').click();
748
+ } else if (shortcode_wrapper.find('.mptt-menu').hasClass('mptt-navigation-select')) {
749
+ if (shortcode_wrapper.find('.mptt-navigation-select option[value="' + event + '"]')) {
750
+ shortcode_wrapper.find('.mptt-navigation-select').val(event).change();
751
+ } else {
752
+ shortcode_wrapper.find('table[id="#all"]').fadeIn();
753
+ }
754
+ } else {
755
+ shortcode_wrapper.find('table[id="#all"]').fadeIn();
756
+ }
757
+ },
758
+ /**
759
+ * Filter by hash
760
+ */
761
+ getFilterByHash: function() {
762
+ var is_single = 1;
763
+ var hash = window.location.hash;
764
+
765
+ if (!_.isUndefined(hash)) {
766
+ var HashArray = hash.split(':');
767
+ var id = HashArray[0];
768
+ var event = HashArray[1];
769
+ var shortcode_wrapper = $('.mptt-shortcode-wrapper');
770
+ event = _.isUndefined(event) ? 'all' : event;
771
+
772
+ if (shortcode_wrapper.length === is_single) {
773
+ state.showCurrentEvent(shortcode_wrapper, event);
774
+ } else {
775
+
776
+ $.each(shortcode_wrapper, function(index, object) {
777
+ var element = $(object);
778
+ var element_id = '#' + element.attr('id');
779
+
780
+ if (element_id === id) {
781
+ state.showCurrentEvent(element, event);
782
+ } else {
783
+ state.showCurrentEvent(element, 'all');
784
+ }
785
+ });
786
+
787
+ }
788
+ }
789
+ state.setEventsHeight();
790
+ },
791
+ /**
792
+ * Clear table after change colSpan
793
+ *
794
+ * @param columnIndex
795
+ * @param toColSpan
796
+ * @param $table
797
+ * @param row
798
+ */
799
+ removeCellsAfterChangeColSpan: function(columnIndex, toColSpan, $table, row) {
800
+ for (columnIndex; columnIndex < toColSpan; columnIndex++) {
801
+ var columnId = $table.find('th[data-index="' + columnIndex + '"]').data('column-id');
802
+ row.find('td:not(.event)[data-column-id="' + columnId + '"]').remove();
803
+ }
804
+ },
805
+ /**
806
+ * Set rowSpan
807
+ * @param td
808
+ * @param rowSpan
809
+ * @param $table
810
+ * @param columnId
811
+ * @returns rowSpan
812
+ */
813
+ removeCellsAfterChangeRowSpan: function(td, rowSpan, $table, columnId) {
814
+ var index = td.parents('tr').attr('data-index'),
815
+ toRowSpan = rowSpan + parseInt(index) - 1,
816
+ colSpan = td.attr('colspan'),
817
+ columnIndex = $table.find('th[data-column-id="' + columnId + '"]').data('index'),
818
+ toColSpan = parseInt(columnIndex) + parseInt(colSpan);
819
+
820
+ for (index; index < toRowSpan; index++) {
821
+
822
+ var row = $table.find('tr.mptt-shortcode-row-' + (parseInt(index) + 1));
823
+
824
+ if (row.length) {
825
+
826
+ if (row.find('td.event[data-column-id="' + columnId + '"]').length) {
827
+ rowSpan -= (toRowSpan - index);
828
+
829
+ if (rowSpan < 2) {
830
+ rowSpan = 1;
831
+ break;
832
+ }
833
+ }
834
+
835
+ if (colSpan > 1) {
836
+ state.removeCellsAfterChangeColSpan(columnIndex, toColSpan, $table, row);
837
+ }
838
+
839
+ row.find('td:not(.event)[data-column-id="' + columnId + '"]').remove();
840
+ }
841
+ }
842
+ return rowSpan;
843
+ },
844
+ /**
845
+ * Set rowSpan td
846
+ */
847
+ setRowSpanTd: function() {
848
+ var table_class = '.' + MPTT.table_class;
849
+ $.each($(table_class), function() {
850
+ var $table = $(this);
851
+
852
+ $.each($table.find('td.event'), function() {
853
+ var td = $(this),
854
+ events = td.find('.mptt-event-container'),
855
+ columnId = td.attr('data-column-id'),
856
+ rowHeight = td.attr('data-row_height'),
857
+ rowSpan = state.getRowSpan(events, td);
858
+
859
+ if (!_.isUndefined(rowSpan) && rowSpan > 1) {
860
+
861
+ rowSpan = state.removeCellsAfterChangeRowSpan(td, rowSpan, $table, columnId);
862
+
863
+ if (!isNaN(rowHeight)) {
864
+ td.css('height', rowSpan * rowHeight);
865
+ }
866
+ }
867
+
868
+ td.attr('rowspan', rowSpan);
869
+ });
870
+ });
871
+ },
872
+ /**
873
+ * Remove empty rows
874
+ */
875
+ hideEmptyRows: function() {
876
+ var table_class = '.' + MPTT.table_class;
877
+
878
+ var trs = $(table_class + ' tbody tr'),
879
+ col_count = $(table_class).first().find('th').length;
880
+
881
+ $.each(trs, function(index, value) {
882
+ // if all columns in the row are empty
883
+ if ($(value).find('td.event').length === 0 && $(value).find('td').length === col_count) {
884
+ $(value).remove();
885
+ }
886
+ });
887
+ },
888
+ /**
889
+ * Widget settings
890
+ */
891
+ displaySettings: function() {
892
+ var $viewSettings = $('.view_settings');
893
+ if ($viewSettings.length) {
894
+ $viewSettings.change(function() {
895
+ if ($(this).val() === "all") {
896
+ var id = $(this).attr('id');
897
+ $(this).parents('.mptt-container').find('.next-days').css("display", "block");
898
+ }
899
+ else {
900
+ $(this).parents('.mptt-container').find(".next-days").css("display", "none");
901
+ }
902
+ });
903
+ }
904
+ },
905
+ /**
906
+ * Widget time settings
907
+ * @param selector
908
+ */
909
+ timeMode: function(selector) {
910
+ if (selector) {
911
+ var selector_id = "." + $(this).attr('id');
912
+ $('#' + selector).change(function() {
913
+ if ($(this).val() === "server") {
914
+ var id = $(this).attr('id');
915
+ $(this).parents('.mptt-container').find(selector_id).css("display", "block");
916
+ }
917
+ else {
918
+ $(this).parents('.mptt-container').find(selector_id).css("display", "none");
919
+ }
920
+ });
921
+ }
922
+ },
923
+ /**
924
+ * init DatePicker for column
925
+ */
926
+ initDatePicker: function() {
927
+ var $date_picker = $("#datepicker");
928
+
929
+ if ($date_picker.length) {
930
+ $date_picker.datepicker({
931
+ dateFormat: 'd/m/yy',
932
+ setDate: Date.parse($date_picker.val())
933
+ });
934
+ }
935
+ },
936
+ /**
937
+ * init Column radio box change
938
+ */
939
+ columnRadioBox: function() {
940
+ var $date_picker = $('#datepicker');
941
+ var $column_option = $('input.option-input[name="column[column_option]"]');
942
+ var $weekday = $('select.mp-weekday');
943
+
944
+ if ($column_option.length) {
945
+ $column_option.on('change', function() {
946
+ switch ($(this).val()) {
947
+ case 'simple':
948
+ $weekday.prop("disabled", true);
949
+ $date_picker.prop("disabled", true);
950
+ break;
951
+ case 'weekday':
952
+ $weekday.prop("disabled", false);
953
+ $date_picker.val('').prop("disabled", true);
954
+ break;
955
+ case 'date':
956
+ $weekday.prop("disabled", true);
957
+ $date_picker.prop("disabled", false);
958
+ break;
959
+ }
960
+ });
961
+ }
962
+ }
963
+ };
964
+ }
965
+
966
+ return {
967
+ getInstance: function() {
968
+ if (!state) {
969
+ state = createInstance();
970
+ }
971
+ return state;
972
+ }
973
+ };
974
  })(jQuery));
media/js/lib/jBox.js CHANGED
@@ -1,1574 +1,1574 @@
1
- /*
2
- ---
3
- description: jBox is a powerful and flexible jQuery plugin, taking care of all your modal windows, tooltips, notices and more.
4
-
5
- authors: Stephan Wagner (http://stephanwagner.me)
6
-
7
- license: MIT (http://www.opensource.org/licenses/mit-license.php)
8
-
9
- requires: jQuery 1.11.0 (http://code.jquery.com/jquery-1.11.0.min.js)
10
- jQuery 2.1.0 (http://code.jquery.com/jquery-2.1.0.min.js)
11
-
12
- documentation: http://stephanwagner.me/jBox/documentation
13
-
14
- demos: http://stephanwagner.me/jBox/demos
15
- ...
16
- */
17
-
18
- function jBox(type, options) {
19
-
20
- this.options = {
21
-
22
- // jBox ID
23
- id: null, // Choose a unique id, otherwise jBox will set one for you (jBoxID1, jBoxID2, ...)
24
-
25
- // Dimensions
26
- width: 'auto', // Width of content area (e.g. 'auto', 100)
27
- height: 'auto', // Height of content area
28
- minWidth: null, // Minimum width
29
- maxHeight: null, // Minimum height
30
- minWidth: null, // Maximum width
31
- maxHeight: null, // Minimum height
32
-
33
- // Attach
34
- attach: null, // Attach jBox to elements (if no target element is provided, jBox will use the attached element as target)
35
- trigger: 'click', // The event to open or close your jBoxes, use 'click' or 'mouseenter'
36
- preventDefault: false, // Prevent default event when opening jBox (e.g. don't follow the href in a link when clicking on it)
37
-
38
- // Content
39
- title: null, // Adds a title to your jBox
40
- content: null, // You can use a string to set text or HTML as content, or an element selector (e.g. jQuery('#jBox-content')) to append one or several elements (elements appended will get style display: 'block', so hide them with CSS style display: 'none' beforehand)
41
- getTitle: null, // Get the title from an attribute when jBox opens
42
- getContent: null, // Get the content from an attribute when jBox opens
43
-
44
- // AJAX request
45
- ajax: { // Setting an url will make an AJAX call when jBox opens
46
- url: null, // URL to send the AJAX request to
47
- data: '', // Data to send with your AJAX call (e.g. 'id=82&limit=10')
48
- // Optional you can add any jQuery AJAX option (http://api.jquery.com/jquery.ajax/)
49
- reload: false, // Resend the ajax call every time jBox opens
50
- getData: 'data-ajax', // The attribute in the source element where the AJAX will look for the data to send with, e.g. data-ajax="id=82&limit=10"
51
- setContent: true, // Automatically set the response as new content when the AJAX call is finished
52
- spinner: true // Hides the current content and adds a spinner while loading, you can pass html content to add your own spinner, e.g. spinner: '<div class="mySpinner"></div>'
53
- },
54
-
55
- // Position
56
- target: null, // The target element where jBox will be opened
57
- position: {
58
- x: 'center', // Horizontal Position (Use a number, 'left', 'right' or 'center')
59
- y: 'center' // Vertical Position (Use a number, 'top', 'bottom' or 'center')
60
- },
61
- outside: null, // Use 'x', 'y', or 'xy' to move your jBox outside of the target element
62
- offset: 0, // Offset to final position, you can set different values for x and y with an object e.g. {x: 15, y: 0}
63
-
64
- attributes: { // Note that attributes can only be 'left' or 'right' when using numbers for position, e.g. {x: 300, y: 20}
65
- x: 'left', // Horizontal position, use 'left' or 'right'
66
- y: 'top' // Vertical position, use 'top' or 'bottom'
67
- },
68
- adjustPosition: false, // Adjusts the position when there is not enough space (use true, 'flip' or 'move')
69
- adjustTracker: false, // By default jBox adjusts the position when opening, to adjust when scrolling or resizing, use 'scroll', 'resize' or 'true' (both events)
70
- adjustDistance: 5, // How far from the window edge we start adjusting, use an object to set different values: {bottom: 5, top: 50, left: 5, right: 20}
71
- fixed: false, // Your jBox will stay on position when scrolling
72
- reposition: false, // Calculates new position when the window-size changes
73
- repositionOnOpen: true, // Calculates new position each time jBox opens (rather than only when it opens the first time)
74
- repositionOnContent: true, // Calculates new position when the content changes with .setContent() or .setTitle()
75
-
76
- // Pointer
77
- pointer: false, // Your pointer will always point towards the target element, so the option outside should be 'x' or 'y'
78
- pointTo: 'target', // Setting something else than 'target' will add a pointer even if there is no target element set or found (Use 'top', 'bottom', 'left' or 'right')
79
-
80
- // Animations
81
- fade: 180, // Fade duration in ms, set to 0 or false to disable
82
- animation: null, // Animation when opening or closing (use 'pulse', 'zoomIn', 'zoomOut', 'move', 'slide', 'flip', 'tada') (CSS inspired from Daniel Edens Animate.css: http://daneden.me/animate)
83
-
84
- // Appearance
85
- theme: 'Default', // Set a jBox theme class
86
- addClass: '', // Adds classes to the wrapper
87
- overlay: false, // Adds an overlay when jBox opens (set color and opacity with CSS)
88
- zIndex: 10000, // Use a high zIndex (your overlay will have the lowest zIndex of all your jBoxes (with overlays) minus one)
89
-
90
- // Delays
91
- delayOpen: 0, // Delay opening in ms (Note that the delay will be ignored if your jBox didn't finish closing)
92
- delayClose: 0, // Delay closing in ms (Note that there is always a closing delay of at least 10ms to ensure jBox won't be closed when opening right away)
93
-
94
- // Closing events
95
- closeOnEsc: false, // Close jBox when pressing [esc] key
96
- closeOnClick: false, // Close jBox with mouseclick, use 'true' (click anywhere), 'box' (click on jBox itself), 'overlay' (click on the overlay), 'body' (click anywhere but jBox)
97
- closeOnMouseleave: false, // Close jBox when the mouse leaves the jBox area or the area of the attached element
98
- closeButton: false, // Adds a close button to your jBox, use 'title', 'overlay', 'box' or true (true will add the button to overlay, title or box, in that order if any of those elements can be found)
99
-
100
- // Other options
101
- constructOnInit: false, // Construct jBox when it's being initialized
102
- blockScroll: false, // When jBox is open, block scrolling
103
- appendTo: jQuery('body'), // Provide an element if you want the jBox to be positioned inside a specific element (only useful for fixed positions or when position values are numbers)
104
- draggable: null, // Make your jBox draggable (use 'true', 'title' or provide an element as handle) (inspired from Chris Coyiers CSS-Tricks http://css-tricks.com/snippets/jquery/draggable-without-jquery-ui/)
105
- dragOver: true, // When you have multiple draggable jBoxes, the one you select will always move over the other ones
106
-
107
- // Events // Note: You can use 'this' in the event functions, it refers to your jBox object (e.g. onInit: function() { this.open(); })
108
- onInit: function() {}, // Triggered when jBox is initialized, just before it's being created
109
- onCreated: function() {}, // Triggered when jBox is created and is availible in DOM
110
- onOpen: function() {}, // Triggered when jBox is opened
111
- onClose: function() {}, // Triggered when jBox is closed
112
- onCloseComplete: function() {}, // Triggered when jBox is completely closed (when fading is finished, useful if you want to destroy the jBox when it is closed)
113
-
114
- // Only for type "Confirm"
115
- confirmButton: 'Submit', // Text for the submit button
116
- cancelButton: 'Cancel', // Text for the cancel button
117
- confirm: null, // Function to execute when clicking the submit button. By default jBox will use firstly the onclick and secondly the href attribute
118
- cancel: null, // Function to execute when clicking the cancel button
119
-
120
- // Only for type "Notice"
121
- autoClose: 7000, // Time when jBox should close automatically
122
- color: null, // Makes your notices colorful, use 'black', 'red', 'green', 'blue', 'yellow'
123
- stack: true, // Set to false to disable notice-stacking
124
- audio: false, // Set the url to an audio file without extention, e.g. '/url/filename'. jBox will look for an .mp3 and an .ogg file
125
- volume: 100, // Percent of volume for audio files
126
-
127
- // Only for type "Image"
128
- src: 'href', // The attribute where jBox gets the image source from, e.g. href="/path_to_image/image.jpg"
129
- gallery: 'data-jbox-image', // The attribute where you define the image gallery, e.g. data-jbox-image="gallery1"
130
- imageLabel: 'title', // The attribute where jBox gets the image label from, e.g. title="My label"
131
- imageFade: 600, // The fade duration for images
132
- imageSize: 'contain' // How to display the images: Use CSS background-position values, e.g. 'cover', 'contain', 'auto', 'initial', '50% 50%'
133
- };
134
-
135
- // Default type options
136
- this.defaultOptions = {
137
- // Default options for tooltips
138
- 'Tooltip': {
139
- getContent: 'title',
140
- trigger: 'mouseenter',
141
- position: {x: 'center', y: 'top'},
142
- outside: 'y',
143
- pointer: true,
144
- adjustPosition: true,
145
- reposition: true
146
- },
147
- // Default options for mouse tooltips
148
- 'Mouse': {
149
- target: 'mouse',
150
- position: {x: 'right', y: 'bottom'},
151
- offset: 15,
152
- trigger: 'mouseenter',
153
- adjustPosition: 'flip'
154
- },
155
- // Default options for modal windows
156
- 'Modal': {
157
- target: jQuery(window),
158
- fixed: true,
159
- blockScroll: true,
160
- closeOnEsc: true,
161
- closeOnClick: 'overlay',
162
- closeButton: true,
163
- overlay: true,
164
- animation: 'zoomOut'
165
- },
166
- // Default options for modal confirm windows
167
- 'Confirm': {
168
- target: jQuery(window),
169
- fixed: true,
170
- attach: jQuery('[data-confirm]'),
171
- getContent: 'data-confirm',
172
- content: 'Do you really want to do this?',
173
- minWidth: 320,
174
- maxWidth: 460,
175
- blockScroll: true,
176
- closeOnEsc: true,
177
- closeOnClick: 'overlay',
178
- closeButton: true,
179
- overlay: true,
180
- animation: 'zoomOut',
181
- preventDefault: true,
182
- _onAttach: function(el) {
183
- // Extract the href or the onclick event if no submit event is passed
184
- if (!this.options.confirm) {
185
- var submit = el.attr('onclick') ? el.attr('onclick') : (el.attr('href') ? (el.attr('target') ? 'window.open("' + el.attr('href') + '", "' + el.attr('target') + '");' : 'window.location.href = "' + el.attr('href') + '";') : '');
186
- el.prop('onclick', null).data('jBox-Confirm-submit', submit);
187
- }
188
- },
189
- _onCreated: function() {
190
- // Add a footer to the jBox container
191
- this.footer = jQuery('<div class="jBox-Confirm-footer"/>');
192
- jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-cancel"/>').html(this.options.cancelButton).click(function() { this.options.cancel && this.options.cancel(); this.close(); }.bind(this)).appendTo(this.footer);
193
- this.submitButton = jQuery('<div class="jBox-Confirm-button jBox-Confirm-button-submit"/>').html(this.options.confirmButton).appendTo(this.footer);
194
- this.footer.appendTo(this.container);
195
- },
196
- _onOpen: function() {
197
- // Set the new action for the submit button
198
- this.submitButton.off('click.jBox-Confirm' + this.id).on('click.jBox-Confirm' + this.id, function() { this.options.confirm ? this.options.confirm() : eval(this.source.data('jBox-Confirm-submit')); this.close(); }.bind(this));
199
- }
200
- },
201
- // Default options for notices
202
- 'Notice': {
203
- target: jQuery(window),
204
- fixed: true,
205
- position: {x: 20, y: 20},
206
- attributes: {x: 'right', y: 'top'},
207
- animation: 'zoomIn',
208
- closeOnClick: 'box',
209
- _onInit: function () {
210
- this.open();
211
- this.options.delayClose = this.options.autoClose;
212
- this.options.delayClose && this.close();
213
- },
214
- _onCreated: function() {
215
- this.options.color && this.wrapper.addClass('jBox-Notice-color jBox-Notice-' + this.options.color);
216
- this.wrapper.data('jBox-Notice-position', this.options.attributes.x + '-' + this.options.attributes.y);
217
- },
218
- _onOpen: function() {
219
- // Loop through notices at same window corner and either move or destroy them
220
- jQuery.each(jQuery('.jBox-Notice'), function(index, el) {
221
- el = jQuery(el);
222
-
223
- if (el.attr('id') == this.id || el.data('jBox-Notice-position') != this.options.attributes.x + '-' + this.options.attributes.y) return;
224
- if (!this.options.stack) {
225
- el.data('jBox').close({ignoreDelay: true});
226
- return;
227
- }
228
- el.css('margin-' + this.options.attributes.y, parseInt(el.css('margin-' + this.options.attributes.y)) + this.wrapper.outerHeight() + 10);
229
- }.bind(this));
230
-
231
- // Play