kenken999 commited on
Commit
1d2619c
2 Parent(s): 6893b3f acd181a
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. php/.gitattributes +38 -0
  2. php/Dockerfile +20 -0
  3. php/README.md +13 -0
  4. php/admin_comments_edit.php +109 -0
  5. php/admin_comments_list.php +165 -0
  6. php/admin_comments_search.php +97 -0
  7. php/autocomplete.php +62 -0
  8. php/autofillfields.php +44 -0
  9. php/buildpdf.php +19 -0
  10. php/buttonhandler.php +903 -18
  11. php/checkduplicates.php +82 -0
  12. php/classes/addpage.php +1887 -0
  13. php/classes/advancedsearchcontrol.php +31 -0
  14. php/classes/base32.php +101 -0
  15. php/classes/button.php +210 -0
  16. php/classes/chartpage.php +376 -0
  17. php/classes/chartpage_master.php +74 -0
  18. php/classes/charts.php +2067 -0
  19. php/classes/cipherer.php +343 -0
  20. php/classes/context.php +625 -0
  21. php/classes/controls/CheckboxField.php +93 -0
  22. php/classes/controls/Control.php +792 -0
  23. php/classes/controls/DatabaseFileField.php +289 -0
  24. php/classes/controls/DateField.php +295 -0
  25. php/classes/controls/DateTimeControl.php +27 -0
  26. php/classes/controls/EditControlsContainer.php +332 -0
  27. php/classes/controls/FileField.php +457 -0
  28. php/classes/controls/FileFieldSingle.php +279 -0
  29. php/classes/controls/FilterBoolean.php +139 -0
  30. php/classes/controls/FilterControl.php +667 -0
  31. php/classes/controls/FilterIntervalDateSlider.php +775 -0
  32. php/classes/controls/FilterIntervalList.php +261 -0
  33. php/classes/controls/FilterIntervalSlider.php +385 -0
  34. php/classes/controls/FilterIntervalTimeSlider.php +135 -0
  35. php/classes/controls/FilterMultiselectLookup.php +89 -0
  36. php/classes/controls/FilterValuesList.php +725 -0
  37. php/classes/controls/HiddenField.php +20 -0
  38. php/classes/controls/LookupField.php +1645 -0
  39. php/classes/controls/LookupTextField.php +98 -0
  40. php/classes/controls/PasswordField.php +34 -0
  41. php/classes/controls/ReadOnlyField.php +49 -0
  42. php/classes/controls/TextAreaField.php +122 -0
  43. php/classes/controls/TextControl.php +45 -0
  44. php/classes/controls/TextField.php +49 -0
  45. php/classes/controls/TimeField.php +98 -0
  46. php/classes/controls/UserControl.php +42 -0
  47. php/classes/controls/ViewAudioFileField.php +94 -0
  48. php/classes/controls/ViewCheckboxField.php +57 -0
  49. php/classes/controls/ViewControl.php +973 -0
  50. php/classes/controls/ViewControlsContainer.php +234 -0
php/.gitattributes CHANGED
@@ -1,3 +1,4 @@
 
1
  *.7z filter=lfs diff=lfs merge=lfs -text
2
  *.arrow filter=lfs diff=lfs merge=lfs -text
3
  *.bin filter=lfs diff=lfs merge=lfs -text
@@ -33,3 +34,40 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <<<<<<< HEAD
2
  *.7z filter=lfs diff=lfs merge=lfs -text
3
  *.arrow filter=lfs diff=lfs merge=lfs -text
4
  *.bin filter=lfs diff=lfs merge=lfs -text
 
34
  *.zip filter=lfs diff=lfs merge=lfs -text
35
  *.zst filter=lfs diff=lfs merge=lfs -text
36
  *tfevents* filter=lfs diff=lfs merge=lfs -text
37
+ =======
38
+ *.7z filter=lfs diff=lfs merge=lfs -text
39
+ *.arrow filter=lfs diff=lfs merge=lfs -text
40
+ *.bin filter=lfs diff=lfs merge=lfs -text
41
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
42
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
43
+ *.ftz filter=lfs diff=lfs merge=lfs -text
44
+ *.gz filter=lfs diff=lfs merge=lfs -text
45
+ *.h5 filter=lfs diff=lfs merge=lfs -text
46
+ *.joblib filter=lfs diff=lfs merge=lfs -text
47
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
48
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
49
+ *.model filter=lfs diff=lfs merge=lfs -text
50
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
51
+ *.npy filter=lfs diff=lfs merge=lfs -text
52
+ *.npz filter=lfs diff=lfs merge=lfs -text
53
+ *.onnx filter=lfs diff=lfs merge=lfs -text
54
+ *.ot filter=lfs diff=lfs merge=lfs -text
55
+ *.parquet filter=lfs diff=lfs merge=lfs -text
56
+ *.pb filter=lfs diff=lfs merge=lfs -text
57
+ *.pickle filter=lfs diff=lfs merge=lfs -text
58
+ *.pkl filter=lfs diff=lfs merge=lfs -text
59
+ *.pt filter=lfs diff=lfs merge=lfs -text
60
+ *.pth filter=lfs diff=lfs merge=lfs -text
61
+ *.rar filter=lfs diff=lfs merge=lfs -text
62
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
63
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
64
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
65
+ *.tar filter=lfs diff=lfs merge=lfs -text
66
+ *.tflite filter=lfs diff=lfs merge=lfs -text
67
+ *.tgz filter=lfs diff=lfs merge=lfs -text
68
+ *.wasm filter=lfs diff=lfs merge=lfs -text
69
+ *.xz filter=lfs diff=lfs merge=lfs -text
70
+ *.zip filter=lfs diff=lfs merge=lfs -text
71
+ *.zst filter=lfs diff=lfs merge=lfs -text
72
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
73
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
php/Dockerfile CHANGED
@@ -1,3 +1,4 @@
 
1
  # Use the official phpMyAdmin image
2
  # Use the official phpMyAdmin image
3
  FROM phpmyadmin/phpmyadmin:latest
@@ -15,3 +16,22 @@ ENV APACHE_PORT=7860
15
  # Add test.php to the phpMyAdmin root directory
16
 
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <<<<<<< HEAD
2
  # Use the official phpMyAdmin image
3
  # Use the official phpMyAdmin image
4
  FROM phpmyadmin/phpmyadmin:latest
 
16
  # Add test.php to the phpMyAdmin root directory
17
 
18
 
19
+ =======
20
+ # Use the official phpMyAdmin image
21
+ # Use the official phpMyAdmin image
22
+ FROM phpmyadmin/phpmyadmin:latest
23
+ RUN chmod -R 777 /var/
24
+ RUN chmod -R 777 /etc/phpmyadmin/
25
+ RUN chmod -R 777 /etc/apache2/
26
+ # Set correct permissions for phpMyAdmin configuration file
27
+ RUN chmod 644 /etc/phpmyadmin/config.inc.php
28
+ COPY test.php /var/www/html/test.php
29
+ # Set environment variables
30
+ ENV PMA_HOST=mysql-7364790-localbugtv.l.aivencloud.com
31
+ ENV PMA_PORT=10490
32
+ ENV MYSQL_ROOT_PASSWORD=root
33
+ ENV APACHE_PORT=7860
34
+ # Add test.php to the phpMyAdmin root directory
35
+
36
+
37
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
php/README.md CHANGED
@@ -1,3 +1,4 @@
 
1
  ---
2
  title: php
3
  emoji: 🚀
@@ -8,3 +9,15 @@ pinned: false
8
  ---
9
 
10
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <<<<<<< HEAD
2
  ---
3
  title: php
4
  emoji: 🚀
 
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
12
+ =======
13
+ ---
14
+ title: php
15
+ emoji: 🚀
16
+ colorFrom: blue
17
+ colorTo: blue
18
+ sdk: docker
19
+ pinned: false
20
+ ---
21
+
22
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
23
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
php/admin_comments_edit.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
 
3
  @ini_set("display_errors","1");
@@ -104,4 +105,112 @@ if( $pageObject->isLockingRequest() )
104
  $pageObject->init();
105
 
106
  $pageObject->process();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
 
4
  @ini_set("display_errors","1");
 
105
  $pageObject->init();
106
 
107
  $pageObject->process();
108
+ =======
109
+ <?php
110
+
111
+ @ini_set("display_errors","1");
112
+ @ini_set("display_startup_errors","1");
113
+
114
+ require_once("include/dbcommon.php");
115
+ require_once("classes/searchclause.php");
116
+ require_once("include/admin_comments_variables.php");
117
+ require_once('include/xtempl.php');
118
+ require_once('classes/editpage.php');
119
+
120
+ add_nocache_headers();
121
+
122
+ if( Security::hasLogin() ) {
123
+ if( !EditPage::processEditPageSecurity( $strTableName ) )
124
+ return;
125
+ }
126
+
127
+ EditPage::handleBrokenRequest();
128
+
129
+ // render all necessary layouts
130
+
131
+
132
+ // parse control parameters
133
+ $pageMode = EditPage::readEditModeFromRequest();
134
+
135
+ $xt = new Xtempl();
136
+
137
+ $id = postvalue_number("id");
138
+ $id = intval($id) == 0 ? 1 : $id;
139
+
140
+
141
+ // $keys could not be set properly if editid params were no passed
142
+ $keys = array();
143
+ $keys["CommentID"] = postvalue("editid1");
144
+
145
+ //array of params for classes
146
+ $params = array();
147
+ $params["id"] = $id;
148
+ $params["xt"] = &$xt;
149
+ $params["keys"] = $keys;
150
+ $params["mode"] = $pageMode;
151
+ $params["pageType"] = PAGE_EDIT;
152
+ $params["pageName"] = postvalue("page");
153
+ $params["tName"] = $strTableName;
154
+ $params["action"] = postvalue("a");
155
+ $params["selectedFields"] = postvalue("fields");
156
+
157
+ ;
158
+ $params["captchaName"] = "captcha_1209xre";
159
+ $params["captchaValue"] = postvalue("value_captcha_1209xre_" . $id);
160
+ $params["selection"] = postvalue("selection");
161
+ $params["rowIds"] = my_json_decode( postvalue("rowIds") );
162
+
163
+ $params["masterTable"] = postvalue("mastertable");
164
+ if( $params["masterTable"] )
165
+ $params["masterKeysReq"] = RunnerPage::readMasterKeysFromRequest();
166
+
167
+ // locking parameters
168
+ $params["lockingAction"] = postvalue("action");
169
+ $params["lockingSid"] = postvalue("sid");
170
+ $params["lockingKeys"] = postvalue("keys");
171
+ $params["lockingStart"] = postvalue("startEdit");
172
+
173
+ if( $pageMode == EDIT_INLINE )
174
+ {
175
+ $params["screenWidth"] = postvalue("screenWidth");
176
+ $params["screenHeight"] = postvalue("screenHeight");
177
+ $params["orientation"] = postvalue("orientation");
178
+ }
179
+
180
+ if( $pageMode == EDIT_DASHBOARD )
181
+ {
182
+ $params["dashElementName"] = postvalue("dashelement");
183
+ $params["dashTName"] = postvalue("table");
184
+ $params["dashPage"] = postvalue("dashPage");
185
+
186
+ if( postvalue("mapRefresh") )
187
+ {
188
+ $params["mapRefresh"] = true;
189
+ $params["vpCoordinates"] = my_json_decode( postvalue("vpCoordinates") );
190
+ }
191
+ }
192
+
193
+ if(( $pageMode == EDIT_POPUP || $pageMode == EDIT_INLINE ) && postvalue("dashTName"))
194
+ {
195
+ $params["dashTName"] = postvalue("dashTName");
196
+ $params["dashElementName"] = postvalue("dashelement");
197
+ $params["dashPage"] = postvalue("dashPage");
198
+ }
199
+
200
+ $params["forSpreadsheetGrid"] = postvalue("spreadsheetGrid");
201
+ $params["hostPageName"] = postvalue("hostPageName");
202
+ $params["listPage"] = postvalue("listPage");
203
+
204
+ $pageObject = EditPage::EditPageFactory($params);
205
+
206
+ if( $pageObject->isLockingRequest() )
207
+ {
208
+ $pageObject->doLockingAction();
209
+ exit();
210
+ }
211
+
212
+ $pageObject->init();
213
+
214
+ $pageObject->process();
215
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
216
  ?>
php/admin_comments_list.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  @ini_set("display_errors","1");
3
  @ini_set("display_startup_errors","1");
@@ -160,4 +161,168 @@ $pageObject->prepareForBuildPage();
160
  // show page depends of mode
161
  $pageObject->showPage();
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  @ini_set("display_errors","1");
4
  @ini_set("display_startup_errors","1");
 
161
  // show page depends of mode
162
  $pageObject->showPage();
163
 
164
+ =======
165
+ <?php
166
+ @ini_set("display_errors","1");
167
+ @ini_set("display_startup_errors","1");
168
+
169
+ $requestTable = "admin_comments";
170
+ $requestPage = "list";
171
+
172
+ require_once("include/dbcommon.php");
173
+ add_nocache_headers();
174
+
175
+ require_once('include/xtempl.php');
176
+
177
+ require_once("classes/searchcontrol.php");
178
+ require_once("classes/searchclause.php");
179
+ require_once("classes/panelsearchcontrol.php");
180
+ require_once("include/admin_comments_variables.php");
181
+ require_once('classes/listpage.php');
182
+ require_once('include/lookuplinks.php');
183
+
184
+ // Check whether the page was called as a part of Lookup wizard - List page with search.
185
+ // Verify the eligibility of such a call.
186
+
187
+ InitLookupLinks();
188
+ if( Security::hasLogin() ) {
189
+ if( !ListPage::processListPageSecurity( $strTableName ) )
190
+ return;
191
+ }
192
+
193
+ if( ListPage::processSaveParams( $strTableName ) )
194
+ return;
195
+
196
+ $options = array();
197
+ //array of params for classes
198
+
199
+ // Include necessary files in accordance with the page displaying mode
200
+ $mode = ListPage::readListModeFromRequest();
201
+ if( $mode == LIST_SIMPLE )
202
+ {
203
+ require_once('classes/listpage_simple.php');
204
+ require_once("classes/searchpanelsimple.php");
205
+ }
206
+ elseif( $mode == LIST_AJAX )
207
+ {
208
+ require_once('classes/listpage_simple.php');
209
+ require_once('classes/listpage_ajax.php');
210
+ require_once("classes/searchpanelsimple.php");
211
+ }
212
+ elseif( $mode == LIST_LOOKUP )
213
+ {
214
+ require_once('classes/listpage_embed.php');
215
+ require_once('classes/listpage_lookup.php');
216
+
217
+ $options["mainTable"] = postvalue("table");
218
+ $options["mainField"] = postvalue("field");
219
+ $options["mainPageType"] = postvalue("pageType");
220
+
221
+ $options["mainRecordData"] = my_json_decode( postvalue('data') );
222
+ $options["mainRecordMasterTable"] = postvalue('mainRecordMasterTable');
223
+
224
+ if( postvalue("parentsExist") )
225
+ $options["parentCtrlsData"] = my_json_decode( postvalue("parentCtrlsData") );
226
+ }
227
+ elseif( $mode == LIST_POPUPDETAILS )
228
+ {
229
+ require_once('classes/listpage_embed.php');
230
+ require_once('classes/listpage_dpinline.php');
231
+ require_once('classes/listpage_dppopup.php');
232
+ }
233
+ elseif( $mode == LIST_DETAILS )
234
+ {
235
+ require_once('classes/listpage_embed.php');
236
+ require_once('classes/listpage_dpinline.php');
237
+ require_once('classes/listpage_dplist.php');
238
+ }
239
+ elseif( $mode == LIST_DASHDETAILS )
240
+ {
241
+ require_once('classes/listpage_embed.php');
242
+ require_once('classes/listpage_dashboard.php');
243
+ require_once('classes/listpage_dpdash.php');
244
+ }
245
+ elseif( $mode == LIST_DASHBOARD )
246
+ {
247
+ require_once('classes/listpage_embed.php');
248
+ require_once('classes/listpage_dashboard.php');
249
+ }
250
+ elseif( $mode == MAP_DASHBOARD )
251
+ {
252
+ require_once('classes/listpage_embed.php');
253
+ require_once('classes/listpage_dashboard.php');
254
+ require_once('classes/map_dashboard.php');
255
+ }
256
+
257
+ $xt = new Xtempl( $mode != LIST_SIMPLE ); //#9607 1. Temporary fix
258
+
259
+ $options["pageName"] = postvalue("page");
260
+ $options["pageType"] = PAGE_LIST;
261
+ $options["id"] = postvalue_number("id") ? postvalue_number("id") : 1;
262
+ $options["flyId"] = (int)postvalue("recordId");
263
+ $options["mode"] = $mode;
264
+ $options["xt"] = &$xt;
265
+ $options["firstTime"] = postvalue("firstTime");
266
+ $options["sortBy"] = postvalue("sortby");
267
+ $options["requestGoto"] = postvalue_number("goto");
268
+
269
+
270
+ $options["masterPageType"] = postvalue("masterpagetype");
271
+ $options["masterPage"] = postvalue("masterpage");
272
+ $options["masterId"] = postvalue("masterid");
273
+
274
+ $options["masterTable"] = postvalue("mastertable");
275
+ if( $options["masterTable"] )
276
+ $options["masterKeysReq"] = RunnerPage::readMasterKeysFromRequest();
277
+
278
+
279
+ if( $mode == LIST_DASHBOARD && postvalue("nodata") && strlen($options["masterTable"]) )
280
+ $options["showNoData"] = true;
281
+
282
+ if( $mode != LIST_LOOKUP )
283
+ {
284
+ $options["dashElementName"] = postvalue("dashelement");
285
+ $options["dashTName"] = postvalue("table");
286
+ $options["dashPage"] = postvalue("dashPage");
287
+ }
288
+
289
+ if( postvalue("mapRefresh") )
290
+ {
291
+ $options["mapRefresh"] = true;
292
+ $options["vpCoordinates"] = my_json_decode( postvalue("vpCoordinates") );
293
+ }
294
+
295
+ if( postvalue("firstTime") )
296
+ $options["firstTime"] = true;
297
+
298
+ // Create $pageObject
299
+ $pageObject = ListPage::createListPage($strTableName, $options);
300
+
301
+ if( $pageObject->processSaveSearch() )
302
+ exit();
303
+
304
+ if( $pageObject->updateRowOrder() )
305
+ exit();
306
+
307
+ if ( $pageObject->processFieldFilter() )
308
+ exit();
309
+
310
+ if( $pageObject->processTotals() )
311
+ exit();
312
+
313
+ if( $mode != LIST_DETAILS && $mode != MAP_DASHBOARD && $mode != LIST_DASHBOARD )
314
+ {
315
+ //maps
316
+ }
317
+
318
+ unset($_SESSION["message_add"]);
319
+ unset($_SESSION["message_edit"]);
320
+
321
+ // prepare code for build page
322
+ $pageObject->prepareForBuildPage();
323
+
324
+ // show page depends of mode
325
+ $pageObject->showPage();
326
+
327
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
328
  ?>
php/admin_comments_search.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  @ini_set("display_errors","1");
3
  @ini_set("display_startup_errors","1");
@@ -92,4 +93,100 @@ if( $pageMode == SEARCH_LOAD_CONTROL )
92
 
93
  $pageObject->init();
94
  $pageObject->process();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  @ini_set("display_errors","1");
4
  @ini_set("display_startup_errors","1");
 
93
 
94
  $pageObject->init();
95
  $pageObject->process();
96
+ =======
97
+ <?php
98
+ @ini_set("display_errors","1");
99
+ @ini_set("display_startup_errors","1");
100
+
101
+ require_once("include/dbcommon.php");
102
+ add_nocache_headers();
103
+
104
+ require_once("classes/searchclause.php");
105
+ require_once("include/admin_comments_variables.php");
106
+ require_once("classes/searchcontrol.php");
107
+ require_once("classes/advancedsearchcontrol.php");
108
+ require_once("classes/panelsearchcontrol.php");
109
+
110
+
111
+ Security::processLogoutRequest();
112
+
113
+ if( !isLogged() )
114
+ {
115
+ Security::saveRedirectURL();
116
+ redirectToLogin();
117
+ }
118
+
119
+ require_once( "include/reportfunctions.php" );
120
+ $cname = postvalue("cname");
121
+ $rname = postvalue("rname");
122
+ if( $rname || $cname ) {
123
+ $rpt_array = wrGetEntityArray(
124
+ $rname ? $rname : $cname,
125
+ $rname ? WR_REPORT : WR_CHART
126
+ );
127
+ $accessGranted = @$rpt_array['status'] != "private" || @$rpt_array['owner'] != Security::getUserName();
128
+ } else {
129
+ $accessGranted = CheckTablePermissions( $strTableName, "S" );
130
+ }
131
+ if(!$accessGranted)
132
+ {
133
+ HeaderRedirect("menu");
134
+ }
135
+
136
+
137
+ require_once('include/xtempl.php');
138
+ require_once('classes/searchpage.php');
139
+ require_once('classes/searchpage_dash.php');
140
+
141
+ $xt = new Xtempl();
142
+ $pageMode = SearchPage::readSearchModeFromRequest();
143
+
144
+ if( $pageMode == SEARCH_LOAD_CONTROL )
145
+ $layoutVersion = postvalue("layoutVersion");
146
+
147
+
148
+ $params = array();
149
+ $params['xt'] = &$xt;
150
+ $params['id'] = postvalue_number("id");
151
+ $params['mode'] = $pageMode;
152
+ $params['tName'] = $strTableName;
153
+ $params["pageName"] = postvalue("page");
154
+ $params['pageType'] = PAGE_SEARCH;
155
+ $params['chartName'] = $cname;
156
+ $params['reportName'] = $rname;
157
+ $params['templatefile'] = $templatefile;
158
+ $params['shortTableName'] = 'admin_comments';
159
+ $params['layoutVersion'] = $layoutVersion;
160
+
161
+ $params['searchControllerId'] = postvalue('searchControllerId') ? postvalue('searchControllerId') : $id;
162
+ $params['ctrlField'] = postvalue('ctrlField');
163
+
164
+ $params['needSettings'] = postvalue('isNeedSettings');
165
+
166
+ if( $pageMode == SEARCH_DASHBOARD )
167
+ {
168
+ $params["dashTName"] = postvalue("table");
169
+ $params["dashElementName"] = postvalue("dashelement");
170
+ $params["dashPage"] = postvalue("dashPage");
171
+ }
172
+
173
+ // e.g. crosstable params
174
+ $params["extraPageParams"] = SearchPage::getExtraPageParams();
175
+
176
+ $params["masterTable"] = postvalue("mastertable");
177
+ if( $params["masterTable"] )
178
+ $params["masterKeysReq"] = RunnerPage::readMasterKeysFromRequest();
179
+
180
+
181
+ $pageObject = new SearchPage($params);
182
+
183
+ if( $pageMode == SEARCH_LOAD_CONTROL )
184
+ {
185
+ $pageObject->displaySearchControl();
186
+ return;
187
+ }
188
+
189
+ $pageObject->init();
190
+ $pageObject->process();
191
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
192
  ?>
php/autocomplete.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  @ini_set("display_errors","1");
3
 
@@ -57,4 +58,65 @@ echo printJSON( $respObj );
57
 
58
  RunnerContext::pop();
59
  exit();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  @ini_set("display_errors","1");
4
 
 
58
 
59
  RunnerContext::pop();
60
  exit();
61
+ =======
62
+ <?php
63
+ @ini_set("display_errors","1");
64
+
65
+ require_once("include/dbcommon.php");
66
+ header("Expires: Thu, 01 Jan 1970 00:00:01 GMT");
67
+
68
+ $shortTableName = postvalue("shortTName");
69
+ $table = GetTableByShort( $shortTableName );
70
+ if( !$table )
71
+ exit(0);
72
+
73
+
74
+ $field = postvalue("field");
75
+
76
+ $pageType = postvalue('pageType');
77
+ $pageName = postvalue('page');
78
+
79
+ if( !Security::userHasFieldPermissions( $table, $field, $pageType, $pageName, true ) )
80
+ return;
81
+
82
+ $cipherer = new RunnerCipherer( $table );
83
+ $pSet = new ProjectSettings( $table, $pageType, $pageName );
84
+
85
+ include_once getabspath("classes/controls/EditControlsContainer.php");
86
+ $editControls = new EditControlsContainer( null, $pSet, $pageType, $cipherer );
87
+ $control = $editControls->getControl( $field );
88
+
89
+
90
+ $contextParams = array();
91
+ $contextParams["data"] = my_json_decode( postvalue('data') );
92
+
93
+ $masterTable = postvalue('masterTable');
94
+ if ( $masterTable != "" && isset($_SESSION[ $masterTable . "_masterRecordData" ] ) || postvalue('masterData') )
95
+ {
96
+ $masterData = $_SESSION[ $masterTable . "_masterRecordData" ];
97
+ if( !is_array($masterData) ) {
98
+ $masterData = array();
99
+ }
100
+ $masterControlsData = my_json_decode( postvalue('masterData') );
101
+ foreach( $masterControlsData as $mField => $mValue )
102
+ {
103
+ $masterData[ $mField ] = $mValue;
104
+ }
105
+
106
+ $contextParams["masterData"] = $masterData;
107
+ }
108
+
109
+ RunnerContext::push( new RunnerContextItem( CONTEXT_ROW, $contextParams ) );
110
+
111
+
112
+ $parentCtrlsData = my_json_decode( postvalue('parentCtrlsData') );
113
+ $isExistParent = postvalue('isExistParent');
114
+ $mode = intval( postvalue('mode') );
115
+
116
+ $respObj = array( 'success' => true, 'data' => $control->getLookupContentToReload( $isExistParent === '1', $mode, $parentCtrlsData ) );
117
+ echo printJSON( $respObj );
118
+
119
+ RunnerContext::pop();
120
+ exit();
121
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
122
  ?>
php/autofillfields.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  @ini_set("display_errors","1");
3
 
@@ -39,4 +40,47 @@ echo printJSON( array( 'success'=> true, 'data' => $control->getAutoFillData( $l
39
 
40
  RunnerContext::pop();
41
  exit();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  @ini_set("display_errors","1");
4
 
 
40
 
41
  RunnerContext::pop();
42
  exit();
43
+ =======
44
+ <?php
45
+ @ini_set("display_errors","1");
46
+
47
+ require_once("include/dbcommon.php");
48
+ header("Expires: Thu, 01 Jan 1970 00:00:01 GMT");
49
+
50
+
51
+ $shortTableName = postvalue("shortTName");
52
+ $table = GetTableByShort( $shortTableName );
53
+ if( !$table )
54
+ exit(0);
55
+
56
+ $mainField = postvalue('mainField');
57
+ $linkFieldVal = postvalue('linkFieldVal');
58
+ $pageName = postvalue('page');
59
+ $pageType = postvalue('pageType');
60
+
61
+ if( !Security::userHasFieldPermissions( $table, $mainField, $pageType, $pageName, true ) )
62
+ return;
63
+
64
+ $cipherer = new RunnerCipherer( $table );
65
+ $pSet = new ProjectSettings( $table, $pageType, $pageName );
66
+
67
+ include_once getabspath("classes/controls/EditControlsContainer.php");
68
+ $editControls = new EditControlsContainer( null, $pSet, $pageType, $cipherer );
69
+ $control = $editControls->getControl( $mainField );
70
+
71
+
72
+ $contextParams = array();
73
+ $contextParams["data"] = my_json_decode( postvalue('data') );
74
+
75
+ $masterTable = postvalue('masterTable');
76
+ if ( $masterTable != "" && isset($_SESSION[ $masterTable . "_masterRecordData" ]) )
77
+ $contextParams["masterData"] = $_SESSION[ $masterTable . "_masterRecordData" ];
78
+
79
+ RunnerContext::push( new RunnerContextItem( CONTEXT_ROW, $contextParams ) );
80
+
81
+ echo printJSON( array( 'success'=> true, 'data' => $control->getAutoFillData( $linkFieldVal ) ) );
82
+
83
+ RunnerContext::pop();
84
+ exit();
85
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
86
  ?>
php/buildpdf.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  @ini_set("display_errors","1");
3
  @ini_set("display_startup_errors","1");
@@ -14,4 +15,22 @@ require_once("include/dbcommon.php");
14
  <?php echo GetBaseScriptsForPage(false); ?>
15
  <script type='text/javascript' src="<?php echo GetRootPathForResources("include/pdfnewwindow.js"); ?>"></script>
16
  </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  </html>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  @ini_set("display_errors","1");
4
  @ini_set("display_startup_errors","1");
 
15
  <?php echo GetBaseScriptsForPage(false); ?>
16
  <script type='text/javascript' src="<?php echo GetRootPathForResources("include/pdfnewwindow.js"); ?>"></script>
17
  </body>
18
+ =======
19
+ <?php
20
+ @ini_set("display_errors","1");
21
+ @ini_set("display_startup_errors","1");
22
+
23
+ require_once("include/dbcommon.php");
24
+ ?>
25
+ <!DOCTYPE html>
26
+ <html lang="en-US">
27
+ <head>
28
+ <title>PDF Building</title>
29
+ </head>
30
+ <body>
31
+ <div class="printpdf"></div>
32
+ <?php echo GetBaseScriptsForPage(false); ?>
33
+ <script type='text/javascript' src="<?php echo GetRootPathForResources("include/pdfnewwindow.js"); ?>"></script>
34
+ </body>
35
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
36
  </html>
php/buttonhandler.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  @ini_set("display_errors","1");
3
  @ini_set("display_startup_errors","1");
@@ -285,19 +286,708 @@ function buttonHandler_Create_chart($params)
285
  }
286
 
287
  RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  /*global $loginKeyFields;
289
  $userdata = Security::currentUserData();
290
- $rs = DB::Query("select count(id) as cnt from chat_history where ownerid='".$userdata[$loginKeyFields[0]]."' and targetid='".$params["id"]."' and isread=0");
291
- $data = $rs->fetchAssoc();
292
- if($data["cnt"]==0){
293
- DB::Exec("insert into chat_history (messages, created, isread, targetid, ownerid) values ('','".date("Y-m-d- h:i:s")."',0,".$params["id"].",'".$userdata[$loginKeyFields[0]]."')");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
  }
295
- $result["id"] = $params["id"];*/;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  RunnerContext::pop();
297
  echo my_json_encode($result);
298
  $button->deleteTempFiles();
299
  }
300
- function buttonHandler_Send($params)
301
  {
302
  global $strTableName;
303
  $result = array();
@@ -346,18 +1036,7 @@ function buttonHandler_Send($params)
346
  }
347
 
348
  RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
349
- /*include_once("chat_functions.php");
350
- global $loginKeyFields;
351
- $mess = $params["msg"];
352
- if(strlen($mess)>4000)
353
- $mess = substr($mess,0,4000);
354
- $userdata = Security::currentUserData();
355
- $t = explode(" ",this_microtime());
356
- $sql = DB::PrepareSQL("insert into chat_history (messages, created, isread, targetid, ownerid, status) values (':1',':2','0','".$_SESSION["targetid"]."','".$userdata[$loginKeyFields[0]]."','')", $mess, date("Y-m-d H:i:s",$t[1]).substr((string)$t[0],1,4));
357
- //echo $sql;
358
- DB::Exec($sql);
359
- $_SESSION["message_id"] = DB::LastId();
360
-
361
  **/;
362
  RunnerContext::pop();
363
  echo my_json_encode($result);
@@ -688,6 +1367,7 @@ function buttonHandler_video_chat($params)
688
  }
689
 
690
  RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
 
691
  include_once("chat_functions.php");
692
  global $loginKeyFields, $cDisplayNameField, $cUserNameField;
693
  $result["message"] = "";
@@ -777,6 +1457,210 @@ if(!($data = $rs->fetchAssoc())){
777
  }
778
  }
779
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
780
  ;
781
  RunnerContext::pop();
782
  echo my_json_encode($result);
@@ -979,4 +1863,5 @@ $result["upper"] = strtoupper( $params["value"] );
979
  echo my_json_encode( $result );
980
  $button->deleteTempFiles();
981
  }
 
982
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  @ini_set("display_errors","1");
4
  @ini_set("display_startup_errors","1");
 
286
  }
287
 
288
  RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
289
+ =======
290
+ <?php
291
+ @ini_set("display_errors","1");
292
+ @ini_set("display_startup_errors","1");
293
+
294
+ require_once("include/dbcommon.php");
295
+ require_once("classes/button.php");
296
+
297
+ // CSRF protection
298
+ if( !isPostRequest() )
299
+ return;
300
+
301
+ $params = (array)my_json_decode(postvalue('params'));
302
+
303
+ if( $params["_base64fields"] ) {
304
+ foreach( $params["_base64fields"] as $f ) {
305
+ $params[$f] = base64_str2bin( $params[$f] );
306
+ }
307
+ }
308
+
309
+ $buttId = $params['buttId'];
310
+ $eventId = postvalue('event');
311
+ $table = $params['table'];
312
+ if( !GetTableURL( $table ) ) {
313
+ exit;
314
+ }
315
+ $page = $params['page'];
316
+ if( !Security::userCanSeePage($table, $page ) ) {
317
+ exit;
318
+ }
319
+
320
+ $pSet = new ProjectSettings( $table, "", $page );
321
+ if( $buttId ) {
322
+ $pageButtons = $pSet->customButtons();
323
+ if( array_search( $buttId , $pageButtons ) === false ) {
324
+ exit;
325
+ }
326
+ }
327
+
328
+ $params["masterTable"] = postValue("masterTable");;
329
+ $params["masterKeys"] = array();
330
+ // RunnerPage::readMasterKeysFromRequest
331
+ $i = 1;
332
+ while( isset( $_REQUEST["masterkey".$i] ) ) {
333
+ $params["masterKeys"][ $i ] = $_REQUEST["masterkey".$i];
334
+ $i++;
335
+ }
336
+
337
+
338
+ if($buttId=='Add_Comment')
339
+ {
340
+ // for login page users table can be turned off
341
+ if( $table != GLOBAL_PAGES )
342
+ {
343
+ require_once("include/". GetTableURL( $table ) ."_variables.php");
344
+ $cipherer = new RunnerCipherer( $table );
345
+ }
346
+ buttonHandler_Add_Comment($params);
347
+ }
348
+ if($buttId=='Create_chart')
349
+ {
350
+ // for login page users table can be turned off
351
+ if( $table != GLOBAL_PAGES )
352
+ {
353
+ require_once("include/". GetTableURL( $table ) ."_variables.php");
354
+ $cipherer = new RunnerCipherer( $table );
355
+ }
356
+ buttonHandler_Create_chart($params);
357
+ }
358
+ if($buttId=='Send')
359
+ {
360
+ // for login page users table can be turned off
361
+ if( $table != GLOBAL_PAGES )
362
+ {
363
+ require_once("include/". GetTableURL( $table ) ."_variables.php");
364
+ $cipherer = new RunnerCipherer( $table );
365
+ }
366
+ buttonHandler_Send($params);
367
+ }
368
+ if($buttId=='New_Button')
369
+ {
370
+ // for login page users table can be turned off
371
+ if( $table != GLOBAL_PAGES )
372
+ {
373
+ require_once("include/". GetTableURL( $table ) ."_variables.php");
374
+ $cipherer = new RunnerCipherer( $table );
375
+ }
376
+ buttonHandler_New_Button($params);
377
+ }
378
+ if($buttId=='select_user_button')
379
+ {
380
+ // for login page users table can be turned off
381
+ if( $table != GLOBAL_PAGES )
382
+ {
383
+ require_once("include/". GetTableURL( $table ) ."_variables.php");
384
+ $cipherer = new RunnerCipherer( $table );
385
+ }
386
+ buttonHandler_select_user_button($params);
387
+ }
388
+ if($buttId=='New_Button1')
389
+ {
390
+ // for login page users table can be turned off
391
+ if( $table != GLOBAL_PAGES )
392
+ {
393
+ require_once("include/". GetTableURL( $table ) ."_variables.php");
394
+ $cipherer = new RunnerCipherer( $table );
395
+ }
396
+ buttonHandler_New_Button1($params);
397
+ }
398
+ if($buttId=='Audio')
399
+ {
400
+ // for login page users table can be turned off
401
+ if( $table != GLOBAL_PAGES )
402
+ {
403
+ require_once("include/". GetTableURL( $table ) ."_variables.php");
404
+ $cipherer = new RunnerCipherer( $table );
405
+ }
406
+ buttonHandler_Audio($params);
407
+ }
408
+ if($buttId=='stopAudio')
409
+ {
410
+ // for login page users table can be turned off
411
+ if( $table != GLOBAL_PAGES )
412
+ {
413
+ require_once("include/". GetTableURL( $table ) ."_variables.php");
414
+ $cipherer = new RunnerCipherer( $table );
415
+ }
416
+ buttonHandler_stopAudio($params);
417
+ }
418
+ if($buttId=='video_chat')
419
+ {
420
+ // for login page users table can be turned off
421
+ if( $table != GLOBAL_PAGES )
422
+ {
423
+ require_once("include/". GetTableURL( $table ) ."_variables.php");
424
+ $cipherer = new RunnerCipherer( $table );
425
+ }
426
+ buttonHandler_video_chat($params);
427
+ }
428
+ if($buttId=='clip')
429
+ {
430
+ // for login page users table can be turned off
431
+ if( $table != GLOBAL_PAGES )
432
+ {
433
+ require_once("include/". GetTableURL( $table ) ."_variables.php");
434
+ $cipherer = new RunnerCipherer( $table );
435
+ }
436
+ buttonHandler_clip($params);
437
+ }
438
+ if($buttId=='audiotest')
439
+ {
440
+ // for login page users table can be turned off
441
+ if( $table != GLOBAL_PAGES )
442
+ {
443
+ require_once("include/". GetTableURL( $table ) ."_variables.php");
444
+ $cipherer = new RunnerCipherer( $table );
445
+ }
446
+ buttonHandler_audiotest($params);
447
+ }
448
+
449
+ if( $eventId == 'select_provider' && "chat_settings" == $table )
450
+ {
451
+ require_once("include/chat_settings_variables.php");
452
+ $cipherer = new RunnerCipherer("chat_settings");
453
+ fieldEventHandler_select_provider( $params );
454
+ }
455
+ if( $eventId == 'check_video' && "chat_settings" == $table )
456
+ {
457
+ require_once("include/chat_settings_variables.php");
458
+ $cipherer = new RunnerCipherer("chat_settings");
459
+ fieldEventHandler_check_video( $params );
460
+ }
461
+ if( $eventId == 'tmp_file_event' && "chat_history" == $table )
462
+ {
463
+ require_once("include/chat_history_variables.php");
464
+ $cipherer = new RunnerCipherer("chat_history");
465
+ fieldEventHandler_tmp_file_event( $params );
466
+ }
467
+
468
+
469
+
470
+
471
+ // create table and non table handlers
472
+ function buttonHandler_Add_Comment($params)
473
+ {
474
+ global $strTableName;
475
+ $result = array();
476
+
477
+ // create new button object for get record data
478
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
479
+ $params["isManyKeys"] = postvalue('isManyKeys');
480
+ $params["location"] = postvalue('location');
481
+
482
+ $button = new Button($params);
483
+ $ajax = $button; // for examle from HELP
484
+ $keys = $button->getKeys();
485
+
486
+ $masterData = false;
487
+ if ( isset($params['masterData']) && count($params['masterData']) > 0 )
488
+ {
489
+ $masterData = $params['masterData'];
490
+ }
491
+ else if ( isset($params["masterTable"]) )
492
+ {
493
+ $masterData = $button->getMasterData($params["masterTable"]);
494
+ }
495
+
496
+ $contextParams = array();
497
+ if ( $params["location"] == PAGE_VIEW )
498
+ {
499
+ $contextParams["data"] = $button->getRecordData();
500
+ $contextParams["masterData"] = $masterData;
501
+ }
502
+ else if ( $params["location"] == PAGE_EDIT )
503
+ {
504
+ $contextParams["data"] = $button->getRecordData();
505
+ $contextParams["newData"] = $params['fieldsData'];
506
+ $contextParams["masterData"] = $masterData;
507
+ }
508
+ else if ( $params["location"] == "grid" )
509
+ {
510
+ $params["location"] = "list";
511
+ $contextParams["data"] = $button->getRecordData();
512
+ $contextParams["newData"] = $params['fieldsData'];
513
+ $contextParams["masterData"] = $masterData;
514
+ }
515
+ else
516
+ {
517
+ $contextParams["masterData"] = $masterData;
518
+ }
519
+
520
+ RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
521
+ // Put your code here.
522
+ $result["txt"] = $params["txt"]." world!";
523
+ ;
524
+ RunnerContext::pop();
525
+ echo my_json_encode($result);
526
+ $button->deleteTempFiles();
527
+ }
528
+ function buttonHandler_Create_chart($params)
529
+ {
530
+ global $strTableName;
531
+ $result = array();
532
+
533
+ // create new button object for get record data
534
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
535
+ $params["isManyKeys"] = postvalue('isManyKeys');
536
+ $params["location"] = postvalue('location');
537
+
538
+ $button = new Button($params);
539
+ $ajax = $button; // for examle from HELP
540
+ $keys = $button->getKeys();
541
+
542
+ $masterData = false;
543
+ if ( isset($params['masterData']) && count($params['masterData']) > 0 )
544
+ {
545
+ $masterData = $params['masterData'];
546
+ }
547
+ else if ( isset($params["masterTable"]) )
548
+ {
549
+ $masterData = $button->getMasterData($params["masterTable"]);
550
+ }
551
+
552
+ $contextParams = array();
553
+ if ( $params["location"] == PAGE_VIEW )
554
+ {
555
+ $contextParams["data"] = $button->getRecordData();
556
+ $contextParams["masterData"] = $masterData;
557
+ }
558
+ else if ( $params["location"] == PAGE_EDIT )
559
+ {
560
+ $contextParams["data"] = $button->getRecordData();
561
+ $contextParams["newData"] = $params['fieldsData'];
562
+ $contextParams["masterData"] = $masterData;
563
+ }
564
+ else if ( $params["location"] == "grid" )
565
+ {
566
+ $params["location"] = "list";
567
+ $contextParams["data"] = $button->getRecordData();
568
+ $contextParams["newData"] = $params['fieldsData'];
569
+ $contextParams["masterData"] = $masterData;
570
+ }
571
+ else
572
+ {
573
+ $contextParams["masterData"] = $masterData;
574
+ }
575
+
576
+ RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
577
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
578
  /*global $loginKeyFields;
579
  $userdata = Security::currentUserData();
580
+ $rs = DB::Query("select count(id) as cnt from chat_history where ownerid='".$userdata[$loginKeyFields[0]]."' and targetid='".$params["id"]."' and isread=0");
581
+ $data = $rs->fetchAssoc();
582
+ if($data["cnt"]==0){
583
+ DB::Exec("insert into chat_history (messages, created, isread, targetid, ownerid) values ('','".date("Y-m-d- h:i:s")."',0,".$params["id"].",'".$userdata[$loginKeyFields[0]]."')");
584
+ }
585
+ <<<<<<< HEAD
586
+ $result["id"] = $params["id"];*/;
587
+ RunnerContext::pop();
588
+ echo my_json_encode($result);
589
+ $button->deleteTempFiles();
590
+ }
591
+ function buttonHandler_Send($params)
592
+ {
593
+ global $strTableName;
594
+ $result = array();
595
+
596
+ // create new button object for get record data
597
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
598
+ $params["isManyKeys"] = postvalue('isManyKeys');
599
+ $params["location"] = postvalue('location');
600
+
601
+ $button = new Button($params);
602
+ $ajax = $button; // for examle from HELP
603
+ $keys = $button->getKeys();
604
+
605
+ $masterData = false;
606
+ if ( isset($params['masterData']) && count($params['masterData']) > 0 )
607
+ {
608
+ $masterData = $params['masterData'];
609
+ }
610
+ else if ( isset($params["masterTable"]) )
611
+ {
612
+ $masterData = $button->getMasterData($params["masterTable"]);
613
+ }
614
+
615
+ $contextParams = array();
616
+ if ( $params["location"] == PAGE_VIEW )
617
+ {
618
+ $contextParams["data"] = $button->getRecordData();
619
+ $contextParams["masterData"] = $masterData;
620
+ }
621
+ else if ( $params["location"] == PAGE_EDIT )
622
+ {
623
+ $contextParams["data"] = $button->getRecordData();
624
+ $contextParams["newData"] = $params['fieldsData'];
625
+ $contextParams["masterData"] = $masterData;
626
+ }
627
+ else if ( $params["location"] == "grid" )
628
+ {
629
+ $params["location"] = "list";
630
+ $contextParams["data"] = $button->getRecordData();
631
+ $contextParams["newData"] = $params['fieldsData'];
632
+ $contextParams["masterData"] = $masterData;
633
+ }
634
+ else
635
+ {
636
+ $contextParams["masterData"] = $masterData;
637
+ }
638
+
639
+ RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
640
+ =======
641
+ $result["id"] = $params["id"];*/;
642
+ RunnerContext::pop();
643
+ echo my_json_encode($result);
644
+ $button->deleteTempFiles();
645
+ }
646
+ function buttonHandler_Send($params)
647
+ {
648
+ global $strTableName;
649
+ $result = array();
650
+
651
+ // create new button object for get record data
652
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
653
+ $params["isManyKeys"] = postvalue('isManyKeys');
654
+ $params["location"] = postvalue('location');
655
+
656
+ $button = new Button($params);
657
+ $ajax = $button; // for examle from HELP
658
+ $keys = $button->getKeys();
659
+
660
+ $masterData = false;
661
+ if ( isset($params['masterData']) && count($params['masterData']) > 0 )
662
+ {
663
+ $masterData = $params['masterData'];
664
+ }
665
+ else if ( isset($params["masterTable"]) )
666
+ {
667
+ $masterData = $button->getMasterData($params["masterTable"]);
668
+ }
669
+
670
+ $contextParams = array();
671
+ if ( $params["location"] == PAGE_VIEW )
672
+ {
673
+ $contextParams["data"] = $button->getRecordData();
674
+ $contextParams["masterData"] = $masterData;
675
+ }
676
+ else if ( $params["location"] == PAGE_EDIT )
677
+ {
678
+ $contextParams["data"] = $button->getRecordData();
679
+ $contextParams["newData"] = $params['fieldsData'];
680
+ $contextParams["masterData"] = $masterData;
681
+ }
682
+ else if ( $params["location"] == "grid" )
683
+ {
684
+ $params["location"] = "list";
685
+ $contextParams["data"] = $button->getRecordData();
686
+ $contextParams["newData"] = $params['fieldsData'];
687
+ $contextParams["masterData"] = $masterData;
688
+ }
689
+ else
690
+ {
691
+ $contextParams["masterData"] = $masterData;
692
+ }
693
+
694
+ RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
695
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
696
+ /*include_once("chat_functions.php");
697
+ global $loginKeyFields;
698
+ $mess = $params["msg"];
699
+ if(strlen($mess)>4000)
700
+ $mess = substr($mess,0,4000);
701
+ $userdata = Security::currentUserData();
702
+ $t = explode(" ",this_microtime());
703
+ $sql = DB::PrepareSQL("insert into chat_history (messages, created, isread, targetid, ownerid, status) values (':1',':2','0','".$_SESSION["targetid"]."','".$userdata[$loginKeyFields[0]]."','')", $mess, date("Y-m-d H:i:s",$t[1]).substr((string)$t[0],1,4));
704
+ //echo $sql;
705
+ DB::Exec($sql);
706
+ $_SESSION["message_id"] = DB::LastId();
707
+
708
+ <<<<<<< HEAD
709
+ **/;
710
+ RunnerContext::pop();
711
+ echo my_json_encode($result);
712
+ $button->deleteTempFiles();
713
  }
714
+ function buttonHandler_New_Button($params)
715
+ {
716
+ global $strTableName;
717
+ $result = array();
718
+
719
+ // create new button object for get record data
720
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
721
+ $params["isManyKeys"] = postvalue('isManyKeys');
722
+ $params["location"] = postvalue('location');
723
+
724
+ $button = new Button($params);
725
+ $ajax = $button; // for examle from HELP
726
+ $keys = $button->getKeys();
727
+
728
+ $masterData = false;
729
+ if ( isset($params['masterData']) && count($params['masterData']) > 0 )
730
+ {
731
+ $masterData = $params['masterData'];
732
+ }
733
+ else if ( isset($params["masterTable"]) )
734
+ {
735
+ $masterData = $button->getMasterData($params["masterTable"]);
736
+ }
737
+
738
+ $contextParams = array();
739
+ if ( $params["location"] == PAGE_VIEW )
740
+ {
741
+ $contextParams["data"] = $button->getRecordData();
742
+ $contextParams["masterData"] = $masterData;
743
+ }
744
+ else if ( $params["location"] == PAGE_EDIT )
745
+ {
746
+ $contextParams["data"] = $button->getRecordData();
747
+ $contextParams["newData"] = $params['fieldsData'];
748
+ $contextParams["masterData"] = $masterData;
749
+ }
750
+ else if ( $params["location"] == "grid" )
751
+ {
752
+ $params["location"] = "list";
753
+ $contextParams["data"] = $button->getRecordData();
754
+ $contextParams["newData"] = $params['fieldsData'];
755
+ $contextParams["masterData"] = $masterData;
756
+ }
757
+ else
758
+ {
759
+ $contextParams["masterData"] = $masterData;
760
+ }
761
+
762
+ RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
763
+ ;
764
+ RunnerContext::pop();
765
+ echo my_json_encode($result);
766
+ $button->deleteTempFiles();
767
+ }
768
+ function buttonHandler_select_user_button($params)
769
+ {
770
+ global $strTableName;
771
+ $result = array();
772
+
773
+ // create new button object for get record data
774
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
775
+ $params["isManyKeys"] = postvalue('isManyKeys');
776
+ $params["location"] = postvalue('location');
777
+
778
+ $button = new Button($params);
779
+ $ajax = $button; // for examle from HELP
780
+ $keys = $button->getKeys();
781
+
782
+ $masterData = false;
783
+ if ( isset($params['masterData']) && count($params['masterData']) > 0 )
784
+ {
785
+ $masterData = $params['masterData'];
786
+ }
787
+ else if ( isset($params["masterTable"]) )
788
+ {
789
+ $masterData = $button->getMasterData($params["masterTable"]);
790
+ }
791
+
792
+ $contextParams = array();
793
+ if ( $params["location"] == PAGE_VIEW )
794
+ {
795
+ $contextParams["data"] = $button->getRecordData();
796
+ $contextParams["masterData"] = $masterData;
797
+ }
798
+ else if ( $params["location"] == PAGE_EDIT )
799
+ {
800
+ $contextParams["data"] = $button->getRecordData();
801
+ $contextParams["newData"] = $params['fieldsData'];
802
+ $contextParams["masterData"] = $masterData;
803
+ }
804
+ else if ( $params["location"] == "grid" )
805
+ {
806
+ $params["location"] = "list";
807
+ $contextParams["data"] = $button->getRecordData();
808
+ $contextParams["newData"] = $params['fieldsData'];
809
+ $contextParams["masterData"] = $masterData;
810
+ }
811
+ else
812
+ {
813
+ $contextParams["masterData"] = $masterData;
814
+ }
815
+
816
+ RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
817
+ ;
818
+ RunnerContext::pop();
819
+ echo my_json_encode($result);
820
+ $button->deleteTempFiles();
821
+ }
822
+ function buttonHandler_New_Button1($params)
823
+ {
824
+ global $strTableName;
825
+ $result = array();
826
+
827
+ // create new button object for get record data
828
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
829
+ $params["isManyKeys"] = postvalue('isManyKeys');
830
+ $params["location"] = postvalue('location');
831
+
832
+ $button = new Button($params);
833
+ $ajax = $button; // for examle from HELP
834
+ $keys = $button->getKeys();
835
+
836
+ $masterData = false;
837
+ if ( isset($params['masterData']) && count($params['masterData']) > 0 )
838
+ {
839
+ $masterData = $params['masterData'];
840
+ }
841
+ else if ( isset($params["masterTable"]) )
842
+ {
843
+ $masterData = $button->getMasterData($params["masterTable"]);
844
+ }
845
+
846
+ $contextParams = array();
847
+ if ( $params["location"] == PAGE_VIEW )
848
+ {
849
+ $contextParams["data"] = $button->getRecordData();
850
+ $contextParams["masterData"] = $masterData;
851
+ }
852
+ else if ( $params["location"] == PAGE_EDIT )
853
+ {
854
+ $contextParams["data"] = $button->getRecordData();
855
+ $contextParams["newData"] = $params['fieldsData'];
856
+ $contextParams["masterData"] = $masterData;
857
+ }
858
+ else if ( $params["location"] == "grid" )
859
+ {
860
+ $params["location"] = "list";
861
+ $contextParams["data"] = $button->getRecordData();
862
+ $contextParams["newData"] = $params['fieldsData'];
863
+ $contextParams["masterData"] = $masterData;
864
+ }
865
+ else
866
+ {
867
+ $contextParams["masterData"] = $masterData;
868
+ }
869
+
870
+ RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
871
+ // Put your code here.
872
+ $result["txt"] = $params["txt"]." world!";
873
+ ;
874
+ RunnerContext::pop();
875
+ echo my_json_encode($result);
876
+ $button->deleteTempFiles();
877
+ }
878
+ function buttonHandler_Audio($params)
879
+ {
880
+ global $strTableName;
881
+ $result = array();
882
+
883
+ // create new button object for get record data
884
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
885
+ $params["isManyKeys"] = postvalue('isManyKeys');
886
+ $params["location"] = postvalue('location');
887
+
888
+ $button = new Button($params);
889
+ $ajax = $button; // for examle from HELP
890
+ $keys = $button->getKeys();
891
+
892
+ $masterData = false;
893
+ if ( isset($params['masterData']) && count($params['masterData']) > 0 )
894
+ {
895
+ $masterData = $params['masterData'];
896
+ }
897
+ else if ( isset($params["masterTable"]) )
898
+ {
899
+ $masterData = $button->getMasterData($params["masterTable"]);
900
+ }
901
+
902
+ $contextParams = array();
903
+ if ( $params["location"] == PAGE_VIEW )
904
+ {
905
+ $contextParams["data"] = $button->getRecordData();
906
+ $contextParams["masterData"] = $masterData;
907
+ }
908
+ else if ( $params["location"] == PAGE_EDIT )
909
+ {
910
+ $contextParams["data"] = $button->getRecordData();
911
+ $contextParams["newData"] = $params['fieldsData'];
912
+ $contextParams["masterData"] = $masterData;
913
+ }
914
+ else if ( $params["location"] == "grid" )
915
+ {
916
+ $params["location"] = "list";
917
+ $contextParams["data"] = $button->getRecordData();
918
+ $contextParams["newData"] = $params['fieldsData'];
919
+ $contextParams["masterData"] = $masterData;
920
+ }
921
+ else
922
+ {
923
+ $contextParams["masterData"] = $masterData;
924
+ }
925
+
926
+ RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
927
+ // Put your code here.
928
+ $result["txt"] = $params["txt"]." world!";
929
+ ;
930
+ RunnerContext::pop();
931
+ echo my_json_encode($result);
932
+ $button->deleteTempFiles();
933
+ }
934
+ function buttonHandler_stopAudio($params)
935
+ {
936
+ global $strTableName;
937
+ $result = array();
938
+
939
+ // create new button object for get record data
940
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
941
+ $params["isManyKeys"] = postvalue('isManyKeys');
942
+ $params["location"] = postvalue('location');
943
+
944
+ $button = new Button($params);
945
+ $ajax = $button; // for examle from HELP
946
+ $keys = $button->getKeys();
947
+
948
+ $masterData = false;
949
+ if ( isset($params['masterData']) && count($params['masterData']) > 0 )
950
+ {
951
+ $masterData = $params['masterData'];
952
+ }
953
+ else if ( isset($params["masterTable"]) )
954
+ {
955
+ $masterData = $button->getMasterData($params["masterTable"]);
956
+ }
957
+
958
+ $contextParams = array();
959
+ if ( $params["location"] == PAGE_VIEW )
960
+ {
961
+ $contextParams["data"] = $button->getRecordData();
962
+ $contextParams["masterData"] = $masterData;
963
+ }
964
+ else if ( $params["location"] == PAGE_EDIT )
965
+ {
966
+ $contextParams["data"] = $button->getRecordData();
967
+ $contextParams["newData"] = $params['fieldsData'];
968
+ $contextParams["masterData"] = $masterData;
969
+ }
970
+ else if ( $params["location"] == "grid" )
971
+ {
972
+ $params["location"] = "list";
973
+ $contextParams["data"] = $button->getRecordData();
974
+ $contextParams["newData"] = $params['fieldsData'];
975
+ $contextParams["masterData"] = $masterData;
976
+ }
977
+ else
978
+ {
979
+ $contextParams["masterData"] = $masterData;
980
+ }
981
+
982
+ RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
983
+ // Put your code here.
984
+ $result["txt"] = $params["txt"]." world!";
985
+ ;
986
  RunnerContext::pop();
987
  echo my_json_encode($result);
988
  $button->deleteTempFiles();
989
  }
990
+ function buttonHandler_video_chat($params)
991
  {
992
  global $strTableName;
993
  $result = array();
 
1036
  }
1037
 
1038
  RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
1039
+ =======
 
 
 
 
 
 
 
 
 
 
 
1040
  **/;
1041
  RunnerContext::pop();
1042
  echo my_json_encode($result);
 
1367
  }
1368
 
1369
  RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
1370
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
1371
  include_once("chat_functions.php");
1372
  global $loginKeyFields, $cDisplayNameField, $cUserNameField;
1373
  $result["message"] = "";
 
1457
  }
1458
  }
1459
 
1460
+ <<<<<<< HEAD
1461
+ ;
1462
+ RunnerContext::pop();
1463
+ echo my_json_encode($result);
1464
+ $button->deleteTempFiles();
1465
+ }
1466
+ function buttonHandler_clip($params)
1467
+ {
1468
+ global $strTableName;
1469
+ $result = array();
1470
+
1471
+ // create new button object for get record data
1472
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
1473
+ $params["isManyKeys"] = postvalue('isManyKeys');
1474
+ $params["location"] = postvalue('location');
1475
+
1476
+ $button = new Button($params);
1477
+ $ajax = $button; // for examle from HELP
1478
+ $keys = $button->getKeys();
1479
+
1480
+ $masterData = false;
1481
+ if ( isset($params['masterData']) && count($params['masterData']) > 0 )
1482
+ {
1483
+ $masterData = $params['masterData'];
1484
+ }
1485
+ else if ( isset($params["masterTable"]) )
1486
+ {
1487
+ $masterData = $button->getMasterData($params["masterTable"]);
1488
+ }
1489
+
1490
+ $contextParams = array();
1491
+ if ( $params["location"] == PAGE_VIEW )
1492
+ {
1493
+ $contextParams["data"] = $button->getRecordData();
1494
+ $contextParams["masterData"] = $masterData;
1495
+ }
1496
+ else if ( $params["location"] == PAGE_EDIT )
1497
+ {
1498
+ $contextParams["data"] = $button->getRecordData();
1499
+ $contextParams["newData"] = $params['fieldsData'];
1500
+ $contextParams["masterData"] = $masterData;
1501
+ }
1502
+ else if ( $params["location"] == "grid" )
1503
+ {
1504
+ $params["location"] = "list";
1505
+ $contextParams["data"] = $button->getRecordData();
1506
+ $contextParams["newData"] = $params['fieldsData'];
1507
+ $contextParams["masterData"] = $masterData;
1508
+ }
1509
+ else
1510
+ {
1511
+ $contextParams["masterData"] = $masterData;
1512
+ }
1513
+
1514
+ RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
1515
+ ;
1516
+ RunnerContext::pop();
1517
+ echo my_json_encode($result);
1518
+ $button->deleteTempFiles();
1519
+ }
1520
+ function buttonHandler_audiotest($params)
1521
+ {
1522
+ global $strTableName;
1523
+ $result = array();
1524
+
1525
+ // create new button object for get record data
1526
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
1527
+ $params["isManyKeys"] = postvalue('isManyKeys');
1528
+ $params["location"] = postvalue('location');
1529
+
1530
+ $button = new Button($params);
1531
+ $ajax = $button; // for examle from HELP
1532
+ $keys = $button->getKeys();
1533
+
1534
+ $masterData = false;
1535
+ if ( isset($params['masterData']) && count($params['masterData']) > 0 )
1536
+ {
1537
+ $masterData = $params['masterData'];
1538
+ }
1539
+ else if ( isset($params["masterTable"]) )
1540
+ {
1541
+ $masterData = $button->getMasterData($params["masterTable"]);
1542
+ }
1543
+
1544
+ $contextParams = array();
1545
+ if ( $params["location"] == PAGE_VIEW )
1546
+ {
1547
+ $contextParams["data"] = $button->getRecordData();
1548
+ $contextParams["masterData"] = $masterData;
1549
+ }
1550
+ else if ( $params["location"] == PAGE_EDIT )
1551
+ {
1552
+ $contextParams["data"] = $button->getRecordData();
1553
+ $contextParams["newData"] = $params['fieldsData'];
1554
+ $contextParams["masterData"] = $masterData;
1555
+ }
1556
+ else if ( $params["location"] == "grid" )
1557
+ {
1558
+ $params["location"] = "list";
1559
+ $contextParams["data"] = $button->getRecordData();
1560
+ $contextParams["newData"] = $params['fieldsData'];
1561
+ $contextParams["masterData"] = $masterData;
1562
+ }
1563
+ else
1564
+ {
1565
+ $contextParams["masterData"] = $masterData;
1566
+ }
1567
+
1568
+ RunnerContext::push( new RunnerContextItem( $params["location"], $contextParams));
1569
+ // Put your code here.
1570
+ $result["txt"] = $params["txt"]." world!";
1571
+ ;
1572
+ RunnerContext::pop();
1573
+ echo my_json_encode($result);
1574
+ $button->deleteTempFiles();
1575
+ }
1576
+
1577
+
1578
+
1579
+ function fieldEventHandler_select_provider( $params )
1580
+ {
1581
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
1582
+ $params["isManyKeys"] = false;
1583
+ $params["location"] = postvalue('pageType');
1584
+
1585
+ $button = new Button($params);
1586
+ $keys = $button->getKeys();
1587
+ $ajax = $button; // for examle from HELP
1588
+ $result = array();
1589
+
1590
+ $pageType = postvalue("pageType");
1591
+ $fieldsData = my_json_decode( postvalue("fieldsData") );
1592
+
1593
+ $contextParams = array(
1594
+ "data" => $fieldsData,
1595
+ "masterData" => $_SESSION[ $masterTable . "_masterRecordData" ]
1596
+ );
1597
+
1598
+ RunnerContext::push( new RunnerContextItem( CONTEXT_ROW, $contextParams ) );
1599
+ ;
1600
+ RunnerContext::pop();
1601
+
1602
+ echo my_json_encode( $result );
1603
+ $button->deleteTempFiles();
1604
+ }
1605
+ function fieldEventHandler_check_video( $params )
1606
+ {
1607
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
1608
+ $params["isManyKeys"] = false;
1609
+ $params["location"] = postvalue('pageType');
1610
+
1611
+ $button = new Button($params);
1612
+ $keys = $button->getKeys();
1613
+ $ajax = $button; // for examle from HELP
1614
+ $result = array();
1615
+
1616
+ $pageType = postvalue("pageType");
1617
+ $fieldsData = my_json_decode( postvalue("fieldsData") );
1618
+
1619
+ $contextParams = array(
1620
+ "data" => $fieldsData,
1621
+ "masterData" => $_SESSION[ $masterTable . "_masterRecordData" ]
1622
+ );
1623
+
1624
+ RunnerContext::push( new RunnerContextItem( CONTEXT_ROW, $contextParams ) );
1625
+
1626
+ // Sample:
1627
+ $result["upper"] = strtoupper( $params["value"] );
1628
+ ;
1629
+ RunnerContext::pop();
1630
+
1631
+ echo my_json_encode( $result );
1632
+ $button->deleteTempFiles();
1633
+ }
1634
+ function fieldEventHandler_tmp_file_event( $params )
1635
+ {
1636
+ $params["keys"] = (array)my_json_decode(postvalue('keys'));
1637
+ $params["isManyKeys"] = false;
1638
+ $params["location"] = postvalue('pageType');
1639
+
1640
+ $button = new Button($params);
1641
+ $keys = $button->getKeys();
1642
+ $ajax = $button; // for examle from HELP
1643
+ $result = array();
1644
+
1645
+ $pageType = postvalue("pageType");
1646
+ $fieldsData = my_json_decode( postvalue("fieldsData") );
1647
+
1648
+ $contextParams = array(
1649
+ "data" => $fieldsData,
1650
+ "masterData" => $_SESSION[ $masterTable . "_masterRecordData" ]
1651
+ );
1652
+
1653
+ RunnerContext::push( new RunnerContextItem( CONTEXT_ROW, $contextParams ) );
1654
+
1655
+ // Sample:
1656
+ $result["upper"] = strtoupper( $params["value"] );
1657
+ ;
1658
+ RunnerContext::pop();
1659
+
1660
+ echo my_json_encode( $result );
1661
+ $button->deleteTempFiles();
1662
+ }
1663
+ =======
1664
  ;
1665
  RunnerContext::pop();
1666
  echo my_json_encode($result);
 
1863
  echo my_json_encode( $result );
1864
  $button->deleteTempFiles();
1865
  }
1866
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
1867
  ?>
php/checkduplicates.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  @ini_set("display_errors","1");
3
  @ini_set("display_startup_errors","1");
@@ -77,4 +78,85 @@ if( $data )
77
  $returnJSON = array( "success" => true, "hasDuplicates" => $hasDuplicates, "error" => "" );
78
  echo printJSON( $returnJSON );
79
  return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  @ini_set("display_errors","1");
4
  @ini_set("display_startup_errors","1");
 
78
  $returnJSON = array( "success" => true, "hasDuplicates" => $hasDuplicates, "error" => "" );
79
  echo printJSON( $returnJSON );
80
  return;
81
+ =======
82
+ <?php
83
+ @ini_set("display_errors","1");
84
+ @ini_set("display_startup_errors","1");
85
+
86
+ require_once("include/dbcommon.php");
87
+ header("Expires: Thu, 01 Jan 1970 00:00:01 GMT");
88
+
89
+ $shortTableName = postvalue("tableName");
90
+ $table = GetTableByShort( $shortTableName );
91
+ if( !$table )
92
+ exit(0);
93
+
94
+ $pageType = postvalue("pageType");
95
+ $pageName = postvalue("page");
96
+ $fieldName = postvalue("fieldName");
97
+ $fieldControlType = postvalue("fieldControlType");
98
+ $value = postvalue("value");
99
+
100
+ if( !Security::userHasFieldPermissions( $table, $fieldName, $pageType, $pageName, true ) )
101
+ return;
102
+
103
+ $pSet = new ProjectSettings( $table, $pageType );
104
+ $denyChecking = $pSet->allowDuplicateValues( $fieldName );
105
+
106
+ $regEmailMode = false;
107
+ $regUsernameMode = false;
108
+ $userNameField = Security::usernameField();
109
+ if( Security::registerPage() && $table == Security::loginDataSource() ) {
110
+ $regEmailMode = $fieldName == Security::emailField();
111
+ $regUsernameMode = $fieldName == $userNameField;
112
+ $denyChecking = $denyChecking && $fieldName != $userNameField && $fieldName != Security::emailField();
113
+ }
114
+
115
+ if( $denyChecking ) {
116
+ $returnJSON = array( "success" => false, "error" => "Duplicated values are allowed" );
117
+ echo printJSON( $returnJSON) ;
118
+ return;
119
+ }
120
+
121
+ // set db connection
122
+ $_connection = $cman->byTable( $table );
123
+ $dataSource = getDataSource( $table, $pSet, $_connection );
124
+ $dc = new DsCommand();
125
+
126
+ $dc->totals = array();
127
+ $dc->totals[] = array(
128
+ "total" => "count",
129
+ "alias" => "count_".$fieldName,
130
+ "field" => $fieldName,
131
+ );
132
+
133
+ $dc->filter = DataCondition::FieldEquals( $fieldName, $value, 0, dsCASE_DEFAULT );
134
+
135
+ // emails should always be compared case-insensitively
136
+ if( $regEmailMode ) {
137
+ $dc->filter = DataCondition::FieldEquals( $fieldName, $value, 0, dsCASE_INSENSITIVE );
138
+ }
139
+ // username on register page
140
+ if( $regUsernameMode ) {
141
+ $where = $_connection->comparisonSQL( $fieldSQL, $value, Security::caseInsensitiveUsername() );
142
+ $dc->filter = DataCondition::FieldEquals( $fieldName, $value, 0,
143
+ Security::caseInsensitiveUsername() ? dsCASE_INSENSITIVE : dsCASE_STRICT );
144
+ }
145
+
146
+ $qResult = $dataSource->getTotals( $dc );
147
+ if( !$qResult ) {
148
+ $returnJSON = array( "success" => false, "error" => "Error: Wrong SQL query" );
149
+ echo printJSON( $returnJSON );
150
+ return;
151
+ }
152
+
153
+ $hasDuplicates = false;
154
+ $data = $qResult->fetchAssoc();
155
+ if( $data )
156
+ $hasDuplicates = $data[ "count_".$fieldName ] ? true : false;
157
+
158
+ $returnJSON = array( "success" => true, "hasDuplicates" => $hasDuplicates, "error" => "" );
159
+ echo printJSON( $returnJSON );
160
+ return;
161
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
162
  ?>
php/classes/addpage.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class AddPage extends RunnerPage
3
  {
@@ -1882,4 +1883,1890 @@ class AddPage extends RunnerPage
1882
  return $this->listPagePSet;
1883
  }
1884
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1885
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class AddPage extends RunnerPage
4
  {
 
1883
  return $this->listPagePSet;
1884
  }
1885
  }
1886
+ =======
1887
+ <?php
1888
+ class AddPage extends RunnerPage
1889
+ {
1890
+ /**
1891
+ * The page's message type
1892
+ * @type Number
1893
+ */
1894
+ public $messageType = MESSAGE_ERROR;
1895
+
1896
+ protected $auditObj = null;
1897
+
1898
+ /**
1899
+ * The page's fields array
1900
+ */
1901
+ protected $addFields = array();
1902
+
1903
+ protected $readAddValues = false;
1904
+
1905
+ /**
1906
+ * The record is being added through the 'List page with search' InlineAdd controls
1907
+ */
1908
+ protected $insertedSuccessfully = false;
1909
+
1910
+ protected $defvalues = array();
1911
+
1912
+ protected $newRecordData = array();
1913
+
1914
+ /**
1915
+ * It could be set up in ADD_MASTER mode only
1916
+ */
1917
+ public $afterAdd_id = '';
1918
+
1919
+ /**
1920
+ * The page's action
1921
+ * @type String
1922
+ */
1923
+ public $action = "";
1924
+
1925
+ /**
1926
+ * It's set up in inline add mode only
1927
+ */
1928
+ public $screenWidth = 0;
1929
+
1930
+ /**
1931
+ * It's set up in inline add mode only
1932
+ */
1933
+ public $screenHeight = 0;
1934
+
1935
+ /**
1936
+ * It's set up in inline add mode only
1937
+ */
1938
+ public $orientation = '';
1939
+
1940
+ /**
1941
+ * It's equal to true when a record is added
1942
+ * through the 'List page with search' InlineAdd controls
1943
+ */
1944
+ public $forListPageLookup = false;
1945
+
1946
+ /**
1947
+ * The short lookup table name
1948
+ * It's set up properly when a record is being added
1949
+ * in a lookup 'Add new' popup
1950
+ * or through the 'List page with search' InlineAdd controls
1951
+ */
1952
+ public $lookupTable = "";
1953
+
1954
+ /**
1955
+ * It's set up properly when a record is being added
1956
+ * in a lookup 'Add new' popup
1957
+ * or through the 'List page with search' InlineAdd controls
1958
+ */
1959
+ public $lookupField = "";
1960
+
1961
+ /**
1962
+ * It's set up properly when a record is being added
1963
+ * in a lookup 'Add new' popup
1964
+ * or through the 'List page with search' InlineAdd controls
1965
+ */
1966
+ public $lookupPageType = "";
1967
+
1968
+ /**
1969
+ * @type Array
1970
+ */
1971
+ public $parentCtrlsData;
1972
+
1973
+
1974
+ /**
1975
+ * @type Number
1976
+ */
1977
+ protected $afterAddAction = null;
1978
+
1979
+ /**
1980
+ *
1981
+ */
1982
+ public $fromDashboard = "";
1983
+
1984
+ public $forSpreadsheetGrid = false;
1985
+ public $hostPageName = "";
1986
+ public $newRowId;
1987
+
1988
+ public $listPage = "";
1989
+
1990
+ protected $sqlValues = array();
1991
+
1992
+ /**
1993
+ * @constructor
1994
+ */
1995
+ function __construct(&$params)
1996
+ {
1997
+ parent::__construct($params);
1998
+
1999
+ $this->addFields = $this->getPageFields();
2000
+ $this->auditObj = GetAuditObject($this->tName);
2001
+
2002
+ $this->headerForms = array( "top" );
2003
+ $this->footerForms = array( "below-grid" );
2004
+
2005
+ if ( $this->isMultistepped() )
2006
+ $this->bodyForms = array( "above-grid", "steps" );
2007
+ else
2008
+ $this->bodyForms = array( "above-grid", "grid" );
2009
+
2010
+ $this->addPageSettings();
2011
+ }
2012
+
2013
+ function setSessionVariables() {
2014
+ parent::setSessionVariables();
2015
+ // don't use mastertable pre-stroed in session
2016
+ if( !postvalue("mastertable")) {
2017
+ $this->masterTable = "";
2018
+ }
2019
+ }
2020
+
2021
+ /**
2022
+ * Add js page settings
2023
+ */
2024
+ protected function addPageSettings()
2025
+ {
2026
+ if( $_SESSION[ $this->sessionPrefix . "_recordAdded" ] )
2027
+ {
2028
+ $this->setProxyValue( $this->shortTableName."_recordAdded", true );
2029
+ unset( $_SESSION[ $this->sessionPrefix . "_recordAdded" ] );
2030
+ }
2031
+ else
2032
+ $this->setProxyValue( $this->shortTableName."_recordAdded", false );
2033
+
2034
+ if( $this->mode != ADD_SIMPLE && $this->mode != ADD_POPUP )
2035
+ return;
2036
+
2037
+ $afterAddAction = $this->getAfterAddAction();
2038
+ $this->jsSettings["tableSettings"][ $this->tName ]["afterAddAction"] = $afterAddAction;
2039
+
2040
+ if ( $afterAddAction == AA_TO_DETAIL_LIST || $afterAddAction == AA_TO_DETAIL_ADD )
2041
+ $this->jsSettings["tableSettings"][ $this->tName ]["afterAddActionDetTable"] = GetTableURL( $this->pSet->getAADetailTable() );
2042
+
2043
+ if( $this->listPage && $afterAddAction == AA_TO_LIST ) {
2044
+ $this->pageData["listPage"] = $this->listPage;
2045
+ }
2046
+ }
2047
+
2048
+ /**
2049
+ * Get the correct after add action
2050
+ * basing on the table settings
2051
+ * @return Number
2052
+ */
2053
+ protected function getAfterAddAction()
2054
+ {
2055
+ if( isset( $this->afterAddAction ) && !is_null( $this->afterAddAction ) )
2056
+ return $this->afterAddAction;
2057
+
2058
+ $action = $this->pSet->getAfterAddAction();
2059
+
2060
+ if( $this->mode == ADD_POPUP && $this->pSet->checkClosePopupAfterAdd()
2061
+ || $action == AA_TO_VIEW && !$this->viewAvailable()
2062
+ || $action == AA_TO_EDIT && !$this->editAvailable() )
2063
+ {
2064
+ $action = AA_TO_LIST;
2065
+ }
2066
+
2067
+ if( $action == AA_TO_DETAIL_LIST || $action == AA_TO_DETAIL_ADD )
2068
+ {
2069
+ $dTName = $this->pSet->getAADetailTable();
2070
+ $dPset = new ProjectSettings( $dTName );
2071
+ $dPermissions = $this->getPermissions( $dTName );
2072
+
2073
+ $listPageAllowed = $dPset->hasListPage() && $dPermissions["search"];
2074
+
2075
+ if( !$dTName || $action == AA_TO_DETAIL_LIST && !$listPageAllowed
2076
+ || $action == AA_TO_DETAIL_ADD && ( !$dPset->hasAddPage() || !$dPermissions["add"] && !$listPageAllowed ) )
2077
+ {
2078
+ $action = AA_TO_LIST;
2079
+ }
2080
+ }
2081
+
2082
+ $this->afterAddAction = $action;
2083
+ return $this->afterAddAction;
2084
+ }
2085
+
2086
+ /**
2087
+ * Assign session prefix
2088
+ */
2089
+ protected function assignSessionPrefix()
2090
+ {
2091
+ if( $this->mode == ADD_DASHBOARD || $this->mode == ADD_MASTER_DASH
2092
+ || ($this->mode == ADD_POPUP || $this->mode == ADD_INLINE || $this->fromDashboard != "" ) && $this->dashTName )
2093
+ {
2094
+ $this->sessionPrefix = $this->dashTName."_".$this->tName;
2095
+ return;
2096
+ }
2097
+
2098
+ parent::assignSessionPrefix();
2099
+
2100
+ if( $this->mode == ADD_ONTHEFLY )
2101
+ $this->sessionPrefix.= "_add";
2102
+ }
2103
+
2104
+ /**
2105
+ * Set template file
2106
+ */
2107
+ public function setTemplateFile()
2108
+ {
2109
+ if( $this->mode == ADD_INLINE )
2110
+ $this->templatefile = GetTemplateName($this->shortTableName, "inline_add");
2111
+
2112
+ parent::setTemplateFile();
2113
+ }
2114
+
2115
+ /**
2116
+ * Get the page's fields list
2117
+ * @return Array
2118
+ */
2119
+ protected function getPageFields()
2120
+ {
2121
+ if( $this->mode == ADD_INLINE )
2122
+ {
2123
+ if( $this->masterTable && !$this->inlineAddAvailable() && $this->masterPageType == PAGE_ADD ) // #12518
2124
+ {
2125
+ return $this->pSet->getInlineAddFields();
2126
+ }
2127
+
2128
+ return $this->pSet->getInlineAddFields();
2129
+ }
2130
+
2131
+ return $this->pSet->getAddFields();
2132
+ }
2133
+
2134
+ /**
2135
+ * Process a broken request
2136
+ */
2137
+ public static function handleBrokenRequest()
2138
+ {
2139
+ if( sizeof($_POST) != 0 || !postvalue('submit') )
2140
+ return;
2141
+
2142
+ if( postvalue("inline") )
2143
+ {
2144
+ $returnJSON = array();
2145
+ $returnJSON['success'] = false;
2146
+ $returnJSON['message'] = "Error occurred";
2147
+ $returnJSON['fatalError'] = true;
2148
+ echo printJSON($returnJSON);
2149
+ exit();
2150
+ }
2151
+
2152
+ if( postvalue("fly") )
2153
+ {
2154
+ echo -1;
2155
+ exit();
2156
+ }
2157
+
2158
+ $_SESSION["message_add"] = "<< "."Error occurred"." >>";
2159
+ }
2160
+
2161
+ /**
2162
+ * Redirect after details saved
2163
+ */
2164
+ public function redirectAfterAdd()
2165
+ {
2166
+ if( $_SESSION['after_add_data'] ) {
2167
+ $aaData =& $_SESSION['after_add_data'];
2168
+ } else {
2169
+ $aaData = array();
2170
+ }
2171
+ if( isset($aaData[ $this->afterAdd_id ]) && $aaData[ $this->afterAdd_id ] )
2172
+ {
2173
+ $data = $aaData[ $this->afterAdd_id ];
2174
+ $this->keys = $data['keys'];
2175
+ $this->newRecordData = $data['avalues'];
2176
+ }
2177
+ if( $this->eventsObject->exists("AfterAdd") && isset($aaData[ $this->afterAdd_id ]) && $aaData[ $this->afterAdd_id ] )
2178
+ {
2179
+ $this->eventsObject->AfterAdd( $data['avalues'], $data['keys'], $data['inlineadd'], $this );
2180
+
2181
+ }
2182
+ unset( $aaData[ $this->afterAdd_id ] );
2183
+
2184
+ foreach( $aaData as $k => $v)
2185
+ {
2186
+ if( !is_array($v) or !array_key_exists('time', $v) )
2187
+ {
2188
+ unset( $aaData[ $k ] );
2189
+ continue;
2190
+ }
2191
+
2192
+ if( $v['time'] < time() - 3600 )
2193
+ unset($aaData[ $k ]);
2194
+ }
2195
+ $this->afterAddActionRedirect();
2196
+ }
2197
+
2198
+ /**
2199
+ * Process the page
2200
+ */
2201
+ public function process()
2202
+ {
2203
+ if( strlen($this->afterAdd_id) )
2204
+ {
2205
+ $this->redirectAfterAdd();
2206
+ return;
2207
+ }
2208
+
2209
+ // Before Process event
2210
+ if( $this->eventsObject->exists("BeforeProcessAdd") )
2211
+ $this->eventsObject->BeforeProcessAdd( $this );
2212
+
2213
+ if( $this->action == "added" )
2214
+ {
2215
+ // insert new record if we have to
2216
+ $this->processDataInput();
2217
+
2218
+ $this->readAddValues = !$this->insertedSuccessfully;
2219
+
2220
+ if( $this->mode != ADD_SIMPLE && $this->mode != ADD_DASHBOARD && $this->mode != ADD_MASTER_DASH )
2221
+ {
2222
+ $this->reportSaveStatus();
2223
+ return;
2224
+ }
2225
+
2226
+ if( $this->insertedSuccessfully )
2227
+ {
2228
+ // VBScript fix! don't &&-join these two conditions
2229
+ if( $this->afterAddActionRedirect() )
2230
+ return;
2231
+ }
2232
+ }
2233
+
2234
+ if( $this->captchaExists() )
2235
+ $this->displayCaptcha();
2236
+
2237
+ $this->prgReadMessage();
2238
+
2239
+ $this->prepareDefvalues();
2240
+
2241
+ if( $this->eventsObject->exists("ProcessValuesAdd") )
2242
+ $this->eventsObject->ProcessValuesAdd( $this->defvalues, $this );
2243
+
2244
+ $this->prepareReadonlyFields();
2245
+ $this->prepareEditControls();
2246
+
2247
+ $this->prepareButtons();
2248
+ $this->prepareSteps();
2249
+ $this->prepareDetailsTables();
2250
+
2251
+ // add button events if exist
2252
+ if( $this->mode == ADD_SIMPLE || $this->mode == ADD_ONTHEFLY )
2253
+ $this->addButtonHandlers();
2254
+
2255
+ $this->addCommonJs();
2256
+
2257
+ $this->doCommonAssignments();
2258
+ $this->prepareBreadcrumbs();
2259
+ $this->prepareCollapseButton();
2260
+
2261
+ $this->displayAddPage();
2262
+ }
2263
+
2264
+ /**
2265
+ * Insert a new record to db
2266
+ */
2267
+ protected function processDataInput()
2268
+ {
2269
+ if( $this->action != "added" )
2270
+ return;
2271
+
2272
+ // CSRF protection
2273
+ if( !isPostRequest() )
2274
+ return;
2275
+
2276
+ $this->buildNewRecordData();
2277
+
2278
+ if( !$this->checkCaptcha() )
2279
+ return;
2280
+
2281
+ if( !$this->recheckUserPermissions() )
2282
+ return;
2283
+
2284
+ if( !$this->callBeforeAddEvent() )
2285
+ return;
2286
+
2287
+ //add or set updated lat-lng values for all map fileds with 'UpdateLatLng' ticked
2288
+ $this->setUpdatedLatLng( $this->newRecordData );
2289
+
2290
+ if( !$this->checkDeniedDuplicatedValues() )
2291
+ return;
2292
+
2293
+ if( $this->callCustomAddEvent() )
2294
+ {
2295
+ $insertResult = $this->dataSource->insertSingle( $this->getInsertDataCommand() );
2296
+ $this->insertedSuccessfully = $insertResult !== false;
2297
+
2298
+ if( !$this->insertedSuccessfully )
2299
+ $this->setDatabaseError( $this->dataSource->lastError() );
2300
+ else
2301
+ {
2302
+ $this->newRecordData = $insertResult;
2303
+ // set up keys
2304
+ foreach( $this->pSet->getTableKeys() as $kf ) {
2305
+ if( isset( $this->newRecordData[ $kf ] ) )
2306
+ $this->keys[ $kf ] = $this->newRecordData[ $kf ];
2307
+ }
2308
+
2309
+ if ( count( $this->pSet->getTableKeys() ) != count( $this->keys ) )
2310
+ $this->keys = array();
2311
+ }
2312
+ }
2313
+
2314
+ if( !$this->insertedSuccessfully )
2315
+ return;
2316
+
2317
+ if( $this->getAfterAddAction() == AA_TO_ADD )
2318
+ $_SESSION[ $this->sessionPrefix . "_recordAdded" ] = true;
2319
+
2320
+ $this->ProcessFiles();
2321
+
2322
+ if( $this->auditObj )
2323
+ $this->auditObj->LogAdd( $this->tName, $this->newRecordData, $this->keys );
2324
+
2325
+ $this->callAfterSuccessfulSave();
2326
+ $this->callAfterAddEvent();
2327
+
2328
+ $this->messageType = MESSAGE_INFO;
2329
+ $this->setSuccessfulUpdateMessage();
2330
+ }
2331
+
2332
+ /**
2333
+ * Fill newRecordData properties
2334
+ */
2335
+ protected function buildNewRecordData()
2336
+ {
2337
+ $avalues = array();
2338
+ $blobfields = array();
2339
+ $afilename_values = array();
2340
+
2341
+ foreach($this->addFields as $f)
2342
+ {
2343
+ $control = $this->getControl( $f, $this->id );
2344
+ $control->readWebValue($avalues, $blobfields, NULL, NULL, $afilename_values);
2345
+ }
2346
+
2347
+ if( Security::advancedSecurityAvailable() ) {
2348
+ $securityType = $this->pSet->getAdvancedSecurityType();
2349
+ if( !$this->isAdminTable() && ($securityType == ADVSECURITY_EDIT_OWN || $securityType == ADVSECURITY_VIEW_OWN) )
2350
+ {
2351
+ $tableOwnerIdField = $this->pSet->getTableOwnerIdField();
2352
+ // insert owner id value if it exists an It hasn't already set by user
2353
+ if( $this->checkIfToAddOwnerIdValue( $tableOwnerIdField, $avalues[ $tableOwnerIdField ] ) )
2354
+ $avalues[ $tableOwnerIdField ] = prepare_for_db( $tableOwnerIdField, $_SESSION["_".$this->tName."_OwnerID"] );
2355
+ }
2356
+ }
2357
+ $masterTables = $this->pSet->getMasterTablesArr( );
2358
+ // insert master key value if exists and if not specified
2359
+ foreach( $masterTables as $mTableData )
2360
+ {
2361
+ if( $this->masterTable == $mTableData["mDataSourceTable"] )
2362
+ {
2363
+ foreach( $mTableData["detailKeys"] as $idx => $dk )
2364
+ {
2365
+ $masterkeyIdx = "masterkey".($idx + 1);
2366
+ if( strlen( postvalue($masterkeyIdx) ) )
2367
+ $_SESSION[ $this->sessionPrefix."_".$masterkeyIdx ] = postvalue($masterkeyIdx);
2368
+
2369
+ if( !isset( $avalues[ $dk ] ) || $avalues[ $dk ] == "" )
2370
+ $avalues[ $dk ] = prepare_for_db( $dk, $_SESSION[ $this->sessionPrefix."_".$masterkeyIdx ] );
2371
+ }
2372
+ }
2373
+ }
2374
+
2375
+ $this->addLookupFilterFieldValue( $avalues, $avalues );
2376
+
2377
+ foreach($afilename_values as $fileFName => $value)
2378
+ {
2379
+ $avalues[ $fileFName ] = $value;
2380
+ }
2381
+
2382
+ // calculate order for the reorderRows feature
2383
+ $listPSet = $this->getListPSet();
2384
+ if( $listPSet->reorderRows() ) {
2385
+ $order = postvalue("order");
2386
+ if( $order ) {
2387
+ $order = $this->getUniqueOrder( $listPSet, $order );
2388
+ } else {
2389
+ $order = $this->getMaxOrderValue( $listPSet ) + 1;
2390
+ }
2391
+ $avalues[ $listPSet->reorderRowsField() ] = $order;
2392
+ }
2393
+
2394
+ $this->newRecordData = $avalues;
2395
+ }
2396
+
2397
+ /**
2398
+ * Add to the values array the data about lookup filter field
2399
+ * if it hasn't been set yet
2400
+ * @param Array recordData
2401
+ * @param &Array values
2402
+ */
2403
+ protected function addLookupFilterFieldValue( $recordData, &$values )
2404
+ {
2405
+ $lookupPSet = getLookupMainTableSettings($this->tName, $this->lookupTable, $this->lookupField);
2406
+ if( !$lookupPSet )
2407
+ return;
2408
+
2409
+ if( $lookupPSet->useCategory( $this->lookupField ) )
2410
+ {
2411
+ foreach( $lookupPSet->getParentFieldsData( $this->lookupField ) as $cData )
2412
+ {
2413
+ if( isset( $this->parentCtrlsData[ $cData['main'] ]) && !isset( $recordData[ $cData['lookup'] ] ) )
2414
+ $values[ $cData['lookup'] ]= $this->parentCtrlsData[ $cData['main'] ];
2415
+ }
2416
+ }
2417
+ }
2418
+
2419
+ /**
2420
+ * Check is captcha exists on current page
2421
+ *
2422
+ * @intellisense
2423
+ */
2424
+ function captchaExists()
2425
+ {
2426
+ if ( $this->mode == ADD_ONTHEFLY || $this->mode == ADD_INLINE )
2427
+ {
2428
+ return false;
2429
+ }
2430
+
2431
+ return $this->pSet->hasCaptcha();
2432
+ }
2433
+
2434
+ /**
2435
+ * Get captcha field name
2436
+ *
2437
+ * @intellisense
2438
+ */
2439
+ function getCaptchaFieldName()
2440
+ {
2441
+ return $this->captchaName;
2442
+ }
2443
+
2444
+ /**
2445
+ * @return Boolean
2446
+ */
2447
+ protected function recheckUserPermissions()
2448
+ {
2449
+ if( CheckTablePermissions($this->tName, "A") )
2450
+ return true;
2451
+
2452
+ return parent::recheckUserPermissions();
2453
+ }
2454
+
2455
+ /**
2456
+ * Execute before Add event
2457
+ * @return Boolean
2458
+ */
2459
+ protected function callBeforeAddEvent()
2460
+ {
2461
+ if( !$this->eventsObject->exists("BeforeAdd") )
2462
+ return true;
2463
+
2464
+ $this->sqlValues = array();
2465
+ $usermessage = "";
2466
+ $ret = $this->eventsObject->BeforeAdd( $this->newRecordData, $this->sqlValues, $usermessage, $this->mode == ADD_INLINE, $this );
2467
+ if( $usermessage != "" )
2468
+ $this->setMessage( $usermessage );
2469
+
2470
+ return $ret;
2471
+ }
2472
+
2473
+ /**
2474
+ * Check if some values are duplicated for the fields not allowing duplicates
2475
+ * @return Boolean
2476
+ */
2477
+ public function checkDeniedDuplicatedValues()
2478
+ {
2479
+ $usermessage = "";
2480
+ $ret = $this->hasDeniedDuplicateValues( $this->newRecordData, $usermessage );
2481
+ if( $ret )
2482
+ $this->setMessage( $usermessage );
2483
+
2484
+ return !$ret;
2485
+ }
2486
+
2487
+ /**
2488
+ * #7374
2489
+ * @return Boolean
2490
+ */
2491
+ protected function callCustomAddEvent()
2492
+ {
2493
+ if( !$this->eventsObject->exists("CustomAdd") )
2494
+ return true;
2495
+
2496
+ $keys = array();
2497
+ $customAddError = "";
2498
+ $ret = $this->eventsObject->CustomAdd( $this->newRecordData, $keys, $customAddError, $this->mode == ADD_INLINE, $this );
2499
+
2500
+ if( strlen( $customAddError ) > 0 )
2501
+ {
2502
+ $this->insertedSuccessfully = false;
2503
+ $this->setMessage( $customAddError );
2504
+ $this->keys = array();
2505
+ return false;
2506
+ }
2507
+
2508
+ // do standard Add processing
2509
+ if( $ret )
2510
+ return true;
2511
+
2512
+ $this->insertedSuccessfully = true;
2513
+
2514
+ // update keys and inserted data
2515
+ $keyFields = $this->pSet->getTableKeys();
2516
+
2517
+ if( !is_array( $keys ) && count( $keyFields ) == 1 )
2518
+ $keys = array( $keyFields[0] => $keys );
2519
+
2520
+ foreach( $keyFields as $kf ) {
2521
+ if( strlen( $keys[ $kf ] ) )
2522
+ $this->keys[ $kf ] = $kf;
2523
+ else if( array_key_exists( $kf, $this->newRecordData ) )
2524
+ $this->keys[ $kf ] = $this->newRecordData[ $kf ];
2525
+ else
2526
+ $this->keys[ $kf ] = $this->dataSource->lastAutoincValue( $kf );
2527
+
2528
+ $this->newRecordData[ $kf ] = $this->keys[ $kf ];
2529
+ }
2530
+
2531
+ return false;
2532
+ }
2533
+
2534
+ /**
2535
+ * Give possibility to all edit controls to clean their data
2536
+ */
2537
+ protected function callAfterSuccessfulSave()
2538
+ {
2539
+ foreach($this->addFields as $f)
2540
+ {
2541
+ $this->getControl( $f, $this->id )->afterSuccessfulSave();
2542
+ }
2543
+ }
2544
+
2545
+ /**
2546
+ * Execute After Add event or prepare all necessary data for its execution after redirect
2547
+ */
2548
+ protected function callAfterAddEvent()
2549
+ {
2550
+ if( !$this->eventsObject->exists("AfterAdd") )
2551
+ return;
2552
+
2553
+ if( $this->mode != ADD_MASTER )
2554
+ {
2555
+ $this->eventsObject->AfterAdd( $this->newRecordData, $this->keys, $this->mode == ADD_INLINE, $this );
2556
+ return;
2557
+ }
2558
+
2559
+ $this->afterAdd_id = generatePassword(20);
2560
+
2561
+ if( !$_SESSION['after_add_data'] ) {
2562
+ $_SESSION['after_add_data'] = array();
2563
+ }
2564
+ $_SESSION['after_add_data'][ $this->afterAdd_id ] = array(
2565
+ 'avalues' => $this->newRecordData,
2566
+ 'keys'=> $this->keys,
2567
+ 'inlineadd' => $this->mode == ADD_INLINE,
2568
+ 'time' => time()
2569
+ );
2570
+ }
2571
+
2572
+ /**
2573
+ * Set a successful update message.
2574
+ * Add the corresponding edit/view links to the info message
2575
+ */
2576
+ protected function setSuccessfulUpdateMessage()
2577
+ {
2578
+ if( $this->isMessageSet() )
2579
+ return;
2580
+
2581
+ if( $this->mode == ADD_INLINE )
2582
+ $infoMessage = ""."Record was added"."";
2583
+ else
2584
+ $infoMessage = "<strong><<< "."Record was added"." >>></strong>";
2585
+
2586
+ if( $this->mode != ADD_SIMPLE && $this->mode != ADD_MASTER || !$this->keys )
2587
+ {
2588
+ $this->setMessage( $infoMessage );
2589
+ return;
2590
+ }
2591
+
2592
+ $k = 0;
2593
+ $keyParams = array();
2594
+ $keysArray = array();
2595
+ foreach( $this->keys as $idx => $val )
2596
+ {
2597
+ $keyParams[] = "editid".( ++$k )."=".runner_htmlspecialchars(rawurlencode(@$val));
2598
+ $keysArray[] = $val;
2599
+ }
2600
+ $keylink = implode("&", $keyParams);
2601
+
2602
+ if ( count($keysArray) > 0 && $this->mode == ADD_SIMPLE )
2603
+ {
2604
+ $_SESSION["successKeys"] = $keysArray;
2605
+ }
2606
+ else
2607
+ {
2608
+ $infoMessage.= "<br>";
2609
+
2610
+ if( $this->editAvailable() )
2611
+ $infoMessage.= "&nbsp;<a href='".GetTableLink( $this->pSet->getShortTableName(), "edit", $keylink )."'>"."Edit"."</a>&nbsp;";
2612
+
2613
+ if( $this->viewAvailable() )
2614
+ $infoMessage.= "&nbsp;<a href='".GetTableLink( $this->pSet->getShortTableName(), "view", $keylink )."'>"."View"."</a>&nbsp;";
2615
+ }
2616
+
2617
+ $this->setMessage( $infoMessage );
2618
+ }
2619
+
2620
+ /**
2621
+ * Print JSON containing a saved record data on ajax-like request
2622
+ */
2623
+ protected function reportSaveStatus()
2624
+ {
2625
+ echo printJSON( $this->getSaveStatusJSON() );
2626
+ exit();
2627
+ }
2628
+
2629
+ /**
2630
+ * Get an array containing the record save status
2631
+ * @return Array
2632
+ */
2633
+ protected function getSaveStatusJSON()
2634
+ {
2635
+ global $globalEvents;
2636
+ $returnJSON = array();
2637
+
2638
+ if( $this->action != "added" || $this->mode == ADD_SIMPLE )
2639
+ return $returnJSON;
2640
+
2641
+ $returnJSON['success'] = $this->insertedSuccessfully;
2642
+ $returnJSON['message'] = $this->message;
2643
+
2644
+ if( !$this->isCaptchaOk )
2645
+ {
2646
+ $returnJSON['wrongCaptchaFieldName'] = $this->getCaptchaFieldName();
2647
+ }
2648
+ elseif( $this->mode == ADD_POPUP || $this->mode == ADD_MASTER || $this->mode == ADD_MASTER_POPUP || $this->mode == ADD_MASTER_DASH )
2649
+ {
2650
+ $sessPrefix = $this->tName . "_" . $this->pageType;
2651
+ if( isset($_SESSION["count_passes_captcha"]) || $_SESSION["count_passes_captcha"] > 0 || $_SESSION["count_passes_captcha"] < 5 )
2652
+ $returnJSON['hideCaptcha'] = true;
2653
+ }
2654
+
2655
+
2656
+ if( !$this->insertedSuccessfully )
2657
+ return $returnJSON;
2658
+
2659
+ $jsKeys = array();
2660
+ $keyFields = $this->pSet->getTableKeys();
2661
+ if ( $this->keys ) {
2662
+ foreach( $keyFields as $idx => $f) {
2663
+ $jsKeys[ $idx ] = $this->keys[ $f ];
2664
+ }
2665
+ }
2666
+
2667
+ if( $this->mode == ADD_ONTHEFLY )
2668
+ {
2669
+ $lokupData = $this->getLookupData();
2670
+ $returnJSON['linkValue'] = $lokupData['linkValue'];
2671
+ $returnJSON['displayValue'] = $lokupData['displayValue'];
2672
+ $returnJSON['vals'] = $lokupData['vals'];
2673
+
2674
+ $returnJSON['keys'] = $jsKeys;
2675
+ $returnJSON['keyFields'] = $keyFields;
2676
+
2677
+ return $returnJSON;
2678
+ }
2679
+
2680
+ // get current values and show edit controls
2681
+ $data = array();
2682
+ $haveData = true;
2683
+
2684
+ if( $this->keys )
2685
+ $data = $this->getRecordData( $this->keys );
2686
+
2687
+ if( !$data )
2688
+ {
2689
+ $data = $this->newRecordData;
2690
+ $haveData = false;
2691
+ }
2692
+
2693
+ $keyParams = array();
2694
+ foreach( $this->pSet->getTableKeys() as $i => $kf ) {
2695
+ $keyParams[] = "key".($i + 1). "=". runner_htmlspecialchars( rawurlencode( @$data[ $kf ] ));
2696
+ }
2697
+ $keylink = "&" . implode("&", $keyParams);
2698
+
2699
+ $showValues = array();
2700
+ $showFields = array();
2701
+ $showRawValues = array();
2702
+
2703
+ $listPSet = $this->getListPSet();
2704
+
2705
+ $listViewControls = new ViewControlsContainer(
2706
+ $listPSet,
2707
+ $this->pageType,
2708
+ $this
2709
+ );
2710
+
2711
+ foreach( $this->pSet->getFieldsList() as $f )
2712
+ {
2713
+ $control = $listViewControls->getControl( $f );
2714
+ $showValues[ $f ] = $control->showDBValue( $data, $keylink, true );
2715
+ $showFields[] = $f;
2716
+
2717
+ if( IsBinaryType( $this->pSet->getFieldType( $f ) ) )
2718
+ $showRawValues[ $f ] = "";
2719
+ else
2720
+ $showRawValues[ $f ] = runner_substr($data[ $f ], 0, 100);
2721
+ }
2722
+
2723
+ // reorderRows stuff
2724
+ if( $listPSet->reorderRows() ) {
2725
+ $returnJSON['order'] = $data[ $listPSet->reorderRowsField() ];
2726
+ }
2727
+
2728
+ $returnJSON['keys'] = $jsKeys;
2729
+ $returnJSON['vals'] = $showValues;
2730
+ $returnJSON['fields'] = $showFields;
2731
+
2732
+ $returnJSON['detKeys'] = $this->getShowDetailKeys( $data );
2733
+
2734
+ $dmapIconsData = $this->getDashMapsIconsData( $data );
2735
+ if( !!$dmapIconsData )
2736
+ $returnJSON['mapIconsData'] = $dmapIconsData;
2737
+
2738
+ $fieldsIconsData = $this->getFieldMapIconsData( $data );
2739
+ if( !!$fieldsIconsData )
2740
+ $returnJSON['fieldsMapIconsData'] = $fieldsIconsData;
2741
+
2742
+ //$isEditable = Security::userCan('E', $this->tName) || Security::userCan('D', $this->tName);
2743
+ $isEditable = true;
2744
+ if( $globalEvents->exists("IsRecordEditable", $this->tName) ) {
2745
+ $isEditable = $globalEvents->IsRecordEditable( $data, $isEditable, $this->tName );
2746
+ }
2747
+
2748
+ if( $this->forSpreadsheetGrid ) {
2749
+ if( $haveData && $isEditable ) {
2750
+ // new added grid row id
2751
+ $newRowId = $this->newRowId ? $this->newRowId : $this->id;
2752
+ $editPage = $this->getRelatedInlineEditPage( $this->hostPageName, $this->keys, $newRowId );
2753
+
2754
+ $returnJSON["editFields"] = $listPSet->getInlineEditFields();
2755
+
2756
+ // use "htmlControls" key no to interfire with dash html data
2757
+ $returnJSON["htmlControls"] = array();
2758
+ foreach( $listPSet->getInlineEditFields() as $fName ) {
2759
+ $controls = $editPage->getContolMapData( $fName, $newRowId, $data, $editPage->editFields );
2760
+ // set edit page controlsMap
2761
+ $editPage->fillControlsMap( $controls );
2762
+
2763
+ if( $editPage->getEditFormat( $fName ) == EDIT_FORMAT_READONLY )
2764
+ $editPage->readOnlyFields[ $fName ] = $this->showDBValue( $fName, $data );
2765
+
2766
+ $returnJSON["htmlControls"][ $fName ] = $editPage->getSpreadsheetControlMarkup( $fName, $newRowId, $data );
2767
+ }
2768
+
2769
+ $returnJSON["pageId"] = $newRowId;
2770
+
2771
+ $editPage->fillSetCntrlMaps();
2772
+ // contols map for spreadsheet inline edit controls
2773
+ $returnJSON["spreadControlsMap"] = $editPage->controlsHTMLMap;
2774
+ } else {
2775
+ $returnJSON['nonEditable'] = true;
2776
+ }
2777
+ }
2778
+
2779
+
2780
+ if( $this->mode == ADD_INLINE || $this->mode == ADD_POPUP || $this->mode == ADD_DASHBOARD ) {
2781
+ $returnJSON['noKeys'] = !$haveData;
2782
+ $returnJSON['keyFields'] = $keyFields;
2783
+ $returnJSON['rawVals'] = $showRawValues;
2784
+ $returnJSON['hrefs'] = $this->buildDetailGridLinks( $returnJSON['detKeys'] );
2785
+ // add link and display value if list page is lookup with search
2786
+ if( $this->forListPageLookup )
2787
+ {
2788
+ $linkAndDispVals = $this->getLookupData();
2789
+ $returnJSON['linkValue'] = $linkAndDispVals['linkValue'];
2790
+ $returnJSON['displayValue'] = $linkAndDispVals['displayValue'];
2791
+ }
2792
+ if( $globalEvents->exists("IsRecordEditable", $this->tName) ) {
2793
+ if( !$isEditable )
2794
+ $returnJSON['nonEditable'] = true;
2795
+ }
2796
+
2797
+ return $returnJSON;
2798
+ }
2799
+
2800
+ if( $this->mode == ADD_MASTER || $this->mode == ADD_MASTER_POPUP || $this->mode == ADD_MASTER_DASH )
2801
+ {
2802
+ $_SESSION["message_add"] = $this->message ? $this->message : "";
2803
+ $returnJSON['afterAddId'] = $this->afterAdd_id;
2804
+ $tData = array();
2805
+ $returnJSON['mKeys'] = $this->getDetailTablesMasterKeys( $tData );
2806
+
2807
+ if( $this->mode == ADD_MASTER_POPUP || $this->mode == ADD_MASTER_DASH )
2808
+ {
2809
+ $returnJSON['noKeys'] = !$haveData;
2810
+ $returnJSON['keyFields'] = $keyFields;
2811
+ $returnJSON['rawVals'] = $showRawValues;
2812
+ $returnJSON['hrefs'] = $this->buildDetailGridLinks( $returnJSON['detKeys'] );
2813
+
2814
+ if( $globalEvents->exists("IsRecordEditable", $this->tName) ) {
2815
+ if( !$isEditable )
2816
+ $returnJSON['nonEditable'] = true;
2817
+ }
2818
+ }
2819
+
2820
+ return $returnJSON;
2821
+ }
2822
+ }
2823
+
2824
+ /**
2825
+ * @param &Array data
2826
+ * @return Array
2827
+ */
2828
+ protected function getShowDetailKeys( &$data )
2829
+ {
2830
+ $showDetailKeys = array();
2831
+ foreach( $this->pSet->getDetailTablesArr() as $dt )
2832
+ {
2833
+ foreach( $dt["masterKeys"] as $idx => $dk)
2834
+ {
2835
+ $showDetailKeys[ $dt['dDataSourceTable'] ][ "masterkey".($idx + 1) ] = $data[ $dk ];
2836
+ }
2837
+ }
2838
+
2839
+ if( $this->getAfterAddAction() == AA_TO_DETAIL_ADD )
2840
+ {
2841
+ $AAdTName = $this->pSet->getAADetailTable();
2842
+ $dTUrl = GetTableUrl( $AAdTName );
2843
+
2844
+ if( !isset( $showDetailKeys[ $dTUrl ] ) )
2845
+ $showDetailKeys[ $dTUrl ] = $showDetailKeys[ $AAdTName ];
2846
+ }
2847
+
2848
+ return $showDetailKeys;
2849
+ }
2850
+
2851
+ /**
2852
+ * @return Array
2853
+ */
2854
+ protected function getDetailTablesMasterKeys( $data )
2855
+ {
2856
+ if( !$this->isShowDetailTables || $this->mobileTemplateMode() )
2857
+ return array();
2858
+
2859
+ $data = $this->newRecordData;
2860
+ if( $this->keys )
2861
+ $data = $this->getRecordData( $this->keys ) ;
2862
+
2863
+ $dpParams = $this->getDetailsParams( $this->id );
2864
+ $mKeysData = array();
2865
+ for( $i = 0; $i < count( $dpParams['ids'] ); $i++ ) {
2866
+ $mKeysData[ $dpParams['strTableNames'][$i] ] = $this->getMasterKeysData( $dpParams['strTableNames'][$i], $data);
2867
+ }
2868
+
2869
+ return $mKeysData;
2870
+ }
2871
+
2872
+ /**
2873
+ * @param String dTableName
2874
+ * @param &Array data
2875
+ */
2876
+ protected function getMasterKeysData( $dTableName, &$data )
2877
+ {
2878
+ $mKeyId = 1;
2879
+ $mKeysData = array();
2880
+
2881
+ $mKeys = $this->pSet->getMasterKeysByDetailTable( $dTableName );
2882
+ foreach($mKeys as $mk)
2883
+ {
2884
+ if( strlen( $data[ $mk ] ) )
2885
+ $mKeysData[ 'masterkey'.$mKeyId++ ] = $data[ $mk ];
2886
+ else
2887
+ $mKeysData[ 'masterkey'.$mKeyId++ ] = '';
2888
+ }
2889
+
2890
+ return $mKeysData;
2891
+ }
2892
+
2893
+ /**
2894
+ * It redirects to a new page
2895
+ * according to the add page settings
2896
+ * @return Boolean
2897
+ */
2898
+ protected function afterAddActionRedirect()
2899
+ {
2900
+ if( $this->mode != ADD_SIMPLE )
2901
+ return false;
2902
+
2903
+ switch( $this->getAfterAddAction() )
2904
+ {
2905
+ case AA_TO_ADD:
2906
+ if ( $this->insertedSuccessfully )
2907
+ return $this->prgRedirect();
2908
+
2909
+ $getParams = array();
2910
+ if( $this->pageName )
2911
+ $getParams[] = "page=".$this->pageName;
2912
+ $getParams[] = $this->getStateUrlParams();
2913
+ HeaderRedirect($this->shortTableName, PAGE_ADD, implode( '&', $getParams ));
2914
+ return true;
2915
+
2916
+ case AA_TO_LIST:
2917
+ if( $this->pSet->hasListPage() ) {
2918
+ HeaderRedirect( $this->shortTableName, PAGE_LIST, "a=return&"
2919
+ .( $this->listPage ? "page=".$this->listPage."&" : "" ).$this->getStateUrlParams() );
2920
+ } else {
2921
+ HeaderRedirect("menu");
2922
+ }
2923
+ return true;
2924
+
2925
+ case AA_TO_VIEW:
2926
+ HeaderRedirect( $this->shortTableName, PAGE_VIEW, implode( '&', array( $this->getKeyParams(), $this->getStateUrlParams() ) ) );
2927
+ return true;
2928
+
2929
+ case AA_TO_EDIT:
2930
+ HeaderRedirect( $this->shortTableName, PAGE_EDIT, implode( '&', array( $this->getKeyParams(), $this->getStateUrlParams() ) ) );
2931
+ return true;
2932
+
2933
+ case AA_TO_DETAIL_LIST:
2934
+ $dTName = $this->pSet->getAADetailTable();
2935
+ HeaderRedirect( GetTableURL( $dTName ), PAGE_LIST, implode("&", $this->getNewRecordMasterKeys( $dTName ) ). "&mastertable=" .$this->tName );
2936
+ return true;
2937
+
2938
+ case AA_TO_DETAIL_ADD:
2939
+ $_SESSION["message_add"] = $this->message ? $this->message : "";
2940
+
2941
+ $dTName = $this->pSet->getAADetailTable();
2942
+ HeaderRedirect( GetTableURL( $dTName ), PAGE_ADD, implode("&", $this->getNewRecordMasterKeys( $dTName ) ). "&mastertable=" .$this->tName );
2943
+ return true;
2944
+
2945
+ default:
2946
+ return false;
2947
+ }
2948
+ }
2949
+
2950
+ function getNewRecordMasterKeys( $dTName )
2951
+ {
2952
+ $data = $this->getNewRecordData();
2953
+
2954
+ $mKeys = array();
2955
+ foreach($this->pSet->getMasterKeysByDetailTable( $dTName ) as $i => $mk)
2956
+ {
2957
+ $mKeys[] = "masterkey". ($i + 1) . "=" .$data[ $mk ];
2958
+ }
2959
+ return $mKeys;
2960
+ }
2961
+
2962
+
2963
+ /**
2964
+ * POST-REDIRECT-GET
2965
+ * Redirect after saving the data to avoid saving again on refresh.
2966
+ */
2967
+ protected function prgRedirect()
2968
+ {
2969
+ if( $this->stopPRG )
2970
+ return false;
2971
+ if( !$this->insertedSuccessfully || $this->mode != ADD_SIMPLE || !no_output_done() )
2972
+ return false;
2973
+ // saving message
2974
+ $_SESSION["message_add"] = $this->message ? $this->message : "";
2975
+ $_SESSION["message_add_type"] = $this->messageType;
2976
+ // redirect
2977
+
2978
+
2979
+ $getParams = array();
2980
+ if( $this->pageName )
2981
+ $getParams[] = "page=".$this->pageName;
2982
+
2983
+ $getParams[] = $this->getStateUrlParams();
2984
+
2985
+ HeaderRedirect( $this->pSet->getShortTableName(), $this->pageType, implode( '&', $getParams ) );
2986
+ // turned on output buffering, so we need to stop script
2987
+ return true;
2988
+ }
2989
+
2990
+ /**
2991
+ * POST-REDIRECT-GET
2992
+ * Read the saved message on the GET step.
2993
+ */
2994
+ protected function prgReadMessage()
2995
+ {
2996
+ // for PRG rule, to avoid POSTDATA resend. Saving mess in session
2997
+ if( $this->mode == ADD_SIMPLE && isset( $_SESSION["message_add"] ) )
2998
+ {
2999
+ $this->message = $_SESSION["message_add"];
3000
+ $this->messageType = $_SESSION["message_add_type"];
3001
+ unset( $_SESSION["message_add"] );
3002
+ }
3003
+ }
3004
+
3005
+ /**
3006
+ * @return Array
3007
+ */
3008
+ public function getCurrentRecord()
3009
+ {
3010
+ $data = array();
3011
+ if ( $this->masterTable && !!$this->masterKeysReq )
3012
+ {
3013
+ foreach ($this->detailKeysByM as $key => $detKey )
3014
+ {
3015
+ $data[$detKey] = $this->masterKeysReq[$key+1];
3016
+ }
3017
+ }
3018
+
3019
+ return $data;
3020
+ }
3021
+
3022
+ protected function replaceFileFieldsValuesWithCopies( &$defvalues ) {
3023
+ foreach( $this->addFields as $f ) {
3024
+ if( $this->pSet->getEditFormat( $f ) == EDIT_FORMAT_FILE ) //#10023
3025
+ $defvalues[ $f ] = $this->getControl( $f, $this->id )->getFieldValueCopy( $defvalues[ $f ] );
3026
+ }
3027
+ }
3028
+
3029
+ protected function getCopyKeys() {
3030
+ $copyKeys = array();
3031
+
3032
+ if( !array_key_exists( "copyid1", $_REQUEST ) && !array_key_exists( "editid1", $_REQUEST ) )
3033
+ return $copyKeys;
3034
+
3035
+ $prefix = array_key_exists( "copyid1", $_REQUEST ) ? "copyid" : "editid";
3036
+ foreach( $this->pSet->getTableKeys() as $idx => $k ) {
3037
+ $copyKeys[ $k ] = postvalue( $prefix . ($idx + 1) );
3038
+ }
3039
+
3040
+ return $copyKeys;
3041
+ }
3042
+
3043
+ /**
3044
+ * Set the defvalues property
3045
+ */
3046
+ protected function prepareDefvalues()
3047
+ {
3048
+ $copyKeys = $this->getCopyKeys();
3049
+
3050
+ if( $copyKeys && $this->mode != ADD_DASHBOARD )
3051
+ {
3052
+ // copy record
3053
+ $dc = $this->getDsCommand( $copyKeys );
3054
+ $prep = $this->dataSource->prepareSQL( $dc );
3055
+ $keyWhere = $prep["where"];
3056
+
3057
+ $fetchedArray = $this->dataSource->getSingle( $dc )->fetchAssoc();
3058
+ $this->defvalues = $this->cipherer->DecryptFetchedArray( $fetchedArray );
3059
+
3060
+ $this->replaceFileFieldsValuesWithCopies( $this->defvalues );
3061
+
3062
+ if( $this->eventsObject->exists("CopyOnLoad") ) {
3063
+ // call CopyOnLoad event
3064
+ $this->eventsObject->CopyOnLoad( $this->defvalues, $keyWhere, $this );
3065
+
3066
+ if( $keyWhere != $prep["where"] ) {
3067
+ $this->dataSource->overrideWhere( $dc, $keyWhere );
3068
+ $fetchedArray = $this->dataSource->getSingle( $dc )->fetchAssoc();
3069
+ $this->defvalues = $this->cipherer->DecryptFetchedArray( $fetchedArray );
3070
+
3071
+ $this->replaceFileFieldsValuesWithCopies( $this->defvalues );
3072
+ }
3073
+ }
3074
+ }
3075
+ else
3076
+ {
3077
+ foreach( $this->addFields as $f )
3078
+ {
3079
+ $defaultValue = GetDefaultValue($f, PAGE_ADD, $this->tName );
3080
+ if( strlen($defaultValue) )
3081
+ $this->defvalues[ $f ] = $defaultValue;
3082
+ }
3083
+ }
3084
+
3085
+ if( Security::advancedSecurityAvailable() ) {
3086
+ $securityType = $this->pSet->getAdvancedSecurityType();
3087
+ if( !$this->isAdminTable() && ($securityType == ADVSECURITY_EDIT_OWN || $securityType == ADVSECURITY_VIEW_OWN) )
3088
+ {
3089
+ $tableOwnerIdField = $this->pSet->getTableOwnerIdField();
3090
+ // insert default owner id value if exists
3091
+ if( $this->checkIfToAddOwnerIdValue( $tableOwnerIdField, '' ) )
3092
+ $this->defvalues[ $tableOwnerIdField ] = prepare_for_db( $tableOwnerIdField, $_SESSION["_".$this->tName."_OwnerID"] );
3093
+ }
3094
+ }
3095
+
3096
+ $masterTables = $this->pSet->getMasterTablesArr();
3097
+ // set default values for the foreign keys
3098
+ foreach( $masterTables as $mTableData )
3099
+ {
3100
+ if( $this->masterTable == $mTableData["mDataSourceTable"] )
3101
+ {
3102
+ foreach( $mTableData["detailKeys"] as $idx => $dk )
3103
+ {
3104
+ $masterkeyIdx = "masterkey".($idx + 1);
3105
+ if( strlen( postvalue($masterkeyIdx) ) )
3106
+ $_SESSION[ $this->sessionPrefix."_".$masterkeyIdx ] = postvalue($masterkeyIdx);
3107
+
3108
+ if( $this->masterPageType != PAGE_ADD )
3109
+ $this->defvalues[ $dk ] = @$_SESSION[ $this->sessionPrefix."_".$masterkeyIdx ];
3110
+ }
3111
+ }
3112
+ }
3113
+
3114
+ $this->addLookupFilterFieldValue( $this->newRecordData, $this->defvalues );
3115
+
3116
+ if( $this->readAddValues )
3117
+ {
3118
+ foreach( $this->addFields as $fName )
3119
+ {
3120
+ $editFormat = $this->pSet->getEditFormat($fName);
3121
+ if( $editFormat != EDIT_FORMAT_DATABASE_FILE && $editFormat != EDIT_FORMAT_DATABASE_IMAGE && $editFormat != EDIT_FORMAT_FILE )
3122
+ $this->defvalues[ $fName ] = @$this->newRecordData[ $fName ];
3123
+ }
3124
+ }
3125
+ }
3126
+
3127
+ /**
3128
+ * Set read-only fields
3129
+ */
3130
+ protected function prepareReadonlyFields()
3131
+ {
3132
+ foreach( $this->addFields as $f )
3133
+ {
3134
+ if( $this->pSet->getEditFormat( $f ) == EDIT_FORMAT_READONLY )
3135
+ $this->readOnlyFields[ $f ] = $this->showDBValue($f, $this->defvalues);
3136
+ }
3137
+ }
3138
+
3139
+ /**
3140
+ * Assign buttons xt variables
3141
+ */
3142
+ protected function prepareButtons()
3143
+ {
3144
+ if( $this->mode == ADD_INLINE )
3145
+ return;
3146
+
3147
+ $this->xt->assign("save_button", true);
3148
+
3149
+ $addStyle = "";
3150
+ if ( $this->isMultistepped() )
3151
+ {
3152
+ $addStyle = " style=\"display: none;\"";
3153
+ }
3154
+
3155
+ // legacy assignment used in the Invoice template
3156
+ $this->xt->assign("savebutton_attrs", "id=\"saveButton".$this->id."\"" . $addStyle );
3157
+
3158
+ if( $this->mode == ADD_DASHBOARD )
3159
+ {
3160
+ $this->xt->assign("reset_button", true);
3161
+ return;
3162
+ }
3163
+
3164
+ if( $this->mode != ADD_ONTHEFLY
3165
+ && $this->mode != ADD_POPUP
3166
+ && $this->mode != ADD_MASTER_DASH )
3167
+ {
3168
+ // add was successful
3169
+ if( isset( $_SESSION["successKeys"] ) )
3170
+ $this->xt->assign("message_back_button", true);
3171
+ if( $this->pSet->hasListPage() )
3172
+ $this->xt->assign("back_button", true);
3173
+ else if( $this->isShowMenu() )
3174
+ $this->xt->assign("backToMenu_button", true);
3175
+ }
3176
+ else
3177
+ $this->xt->assign("cancel_button", true);
3178
+
3179
+ if( $this->mode == ADD_SIMPLE )
3180
+ {
3181
+ // back to list/menu buttons
3182
+ if( $this->pSet->hasListPage() )
3183
+ {
3184
+ $this->xt->assign("backbutton_attrs", "id=\"backButton".$this->id."\"");
3185
+ }
3186
+ else if( $this->isShowMenu() )
3187
+ {
3188
+ $this->xt->assign("backbutton_attrs", "id=\"backToMenuButton".$this->id."\"");
3189
+ }
3190
+ }
3191
+
3192
+ if ( isset($_SESSION["successKeys"]) )
3193
+ {
3194
+ $keysArray = $_SESSION["successKeys"];
3195
+ $dataKeysAttr = 'data-keys="'.runner_htmlspecialchars( my_json_encode($keysArray) ).'"';
3196
+ unset($_SESSION["successKeys"]);
3197
+
3198
+ if( $this->viewAvailable() && $keysArray )
3199
+ {
3200
+ $this->xt->assign("view_page_button", true);
3201
+ $this->xt->assign("view_page_button_attrs", 'id="viewPageButton'.$this->id.'" '.$dataKeysAttr);
3202
+ }
3203
+
3204
+ if( $this->editAvailable() && $keysArray )
3205
+ {
3206
+ $this->xt->assign("edit_page_button", true);
3207
+ $this->xt->assign("edit_page_button_attrs", 'id="editPageButton'.$this->id.'" '.$dataKeysAttr);
3208
+ }
3209
+ }
3210
+ }
3211
+
3212
+ /**
3213
+ * Prepare edit controls
3214
+ */
3215
+ protected function prepareEditControls()
3216
+ {
3217
+ $controlFields = $this->addFields;
3218
+
3219
+ if( $this->mode == ADD_INLINE ) { //#9069
3220
+ $controlFields = $this->removeHiddenColumnsFromInlineFields(
3221
+ $controlFields,
3222
+ $this->screenWidth,
3223
+ $this->screenHeight,
3224
+ $this->orientation
3225
+ );
3226
+ }
3227
+
3228
+ foreach( $controlFields as $fName ) {
3229
+ $isDetKeyField = in_array( $fName, $this->detailKeysByM );
3230
+ if( $isDetKeyField ) {
3231
+ // to the ReadOnly control show the detail key control's value
3232
+ $this->readOnlyFields[ $fName ] = $this->showDBValue( $fName, $this->defvalues );
3233
+ }
3234
+
3235
+ $firstElementId = $this->getControl( $fName, $this->id )->getFirstElementId();
3236
+ if( $firstElementId )
3237
+ $this->xt->assign( "labelfor_" . GoodFieldName( $fName ), $firstElementId );
3238
+
3239
+ $parameters = $this->getEditContolParams( $fName, $this->id, $this->defvalues );
3240
+ $this->xt->assign_function( GoodFieldName( $fName )."_editcontrol", "xt_buildeditcontrol", $parameters );
3241
+
3242
+ $controls = $this->getContolMapData( $fName, $this->id, $this->defvalues, $controlFields );
3243
+ if ( in_array( $fName, $this->errorFields ) )
3244
+ $controls["controls"]["isInvalid"] = true;
3245
+
3246
+ $this->fillControlsMap( $controls );
3247
+ $this->fillControlFlags( $fName );
3248
+
3249
+ // fill special settings for a time picker
3250
+ if( $this->pSet->getEditFormat($fName) == "Time" )
3251
+ $this->fillTimePickSettings( $fName, @$this->defvalues[ $fName ] );
3252
+ }
3253
+ }
3254
+
3255
+ public function getContolMapData( $fName, $recId, &$data, $pageFields ) {
3256
+ $controls = array();
3257
+ $controls["controls"] = array();
3258
+ $controls["controls"]["id"] = $recId;
3259
+ $controls["controls"]["ctrlInd"] = 0;
3260
+ $controls["controls"]["fieldName"] = $fName;
3261
+
3262
+ //if richEditor for field
3263
+ if( $this->pSet->isUseRTE( $fName ) )
3264
+ $controls["controls"]["mode"] = "add";
3265
+ else
3266
+ $controls["controls"]["mode"] = $this->mode == ADD_INLINE ? "inline_add" : "add";
3267
+
3268
+ $isDetKeyField = in_array( $fName, $this->detailKeysByM );
3269
+ if( $isDetKeyField )
3270
+ $controls["controls"]["value"] = $data[ $fName ];
3271
+
3272
+ $preload = $this->fillPreload( $fName, $pageFields, $data );
3273
+ if( $preload !== false ) {
3274
+ $controls["controls"]["preloadData"] = $preload;
3275
+ if( !$data[ $fName ] && $preload["vals"] )
3276
+ $data[ $fName ] = $preload["vals"][0];
3277
+ }
3278
+
3279
+ return $controls;
3280
+ }
3281
+
3282
+ /**
3283
+ *
3284
+ */
3285
+ public function getEditContolParams( $fName, $recId, &$data ) {
3286
+ $parameters = array();
3287
+ $parameters["id"] = $recId;
3288
+ $parameters["ptype"] = PAGE_ADD;
3289
+ $parameters["field"] = $fName;
3290
+ $parameters["value"] = $data[ $fName ];
3291
+ $parameters["pageObj"] = $this;
3292
+
3293
+ if( $this->getEditFormat( $fName ) !== EDIT_FORMAT_READONLY ) {
3294
+ $parameters["validate"] = $this->pSet->getValidation( $fName );
3295
+
3296
+ if( $this->pSet->isUseRTE($fName) )
3297
+ $_SESSION[ $this->sessionPrefix."_".$fName."_rte" ] = $data[ $fName ];
3298
+ }
3299
+
3300
+ //if richEditor for field
3301
+ if( $this->pSet->isUseRTE( $fName ) )
3302
+ $parameters["mode"] = "add";
3303
+ else
3304
+ $parameters["mode"] = $this->mode == ADD_INLINE ? "inline_add" : "add";
3305
+
3306
+ return $parameters;
3307
+ }
3308
+
3309
+ public function getEditFormat( $field, $pSet = null ) {
3310
+ $isDetKeyField = in_array( $field, $this->detailKeysByM );
3311
+ if( $isDetKeyField ) {
3312
+ return EDIT_FORMAT_READONLY;
3313
+ }
3314
+ return parent::getEditFormat( $field, $pSet );
3315
+ }
3316
+
3317
+
3318
+ /**
3319
+ * Set details preview on the add master page
3320
+ */
3321
+ protected function prepareDetailsTables()
3322
+ {
3323
+ if( !$this->isShowDetailTables
3324
+ || $this->mode != ADD_SIMPLE && $this->mode != ADD_POPUP && $this->mode != ADD_DASHBOARD && $this->mode != ADD_MASTER_DASH
3325
+ || $this->mobileTemplateMode() )
3326
+ {
3327
+ return;
3328
+ }
3329
+
3330
+ $dpParams = $this->getDetailsParams( $this->id );
3331
+
3332
+ $this->jsSettings['tableSettings'][ $this->tName ]['isShowDetails'] = !!$dpParams;
3333
+ $this->jsSettings['tableSettings'][ $this->tName ]['dpParams'] = array('tableNames' => $dpParams['strTableNames'], 'ids' => $dpParams['ids']);
3334
+
3335
+ if( !$dpParams['ids'] )
3336
+ return;
3337
+
3338
+ $this->xt->assign("detail_tables", true);
3339
+
3340
+ for($d = 0; $d < count($dpParams['ids']); $d++)
3341
+ {
3342
+ $this->setDetailPreview( "list", $dpParams['strTableNames'][ $d ], $dpParams['ids'][ $d ], $this->defvalues );
3343
+ $this->displayDetailsButtons( $dpParams['type'][ $d ], $dpParams['strTableNames'][ $d ], $dpParams['ids'][ $d ] );
3344
+ }
3345
+ }
3346
+
3347
+ /**
3348
+ *
3349
+ */
3350
+ protected function displayDetailsButtons( $dpType, $dpTableName, $dpId )
3351
+ {
3352
+ if ( !CheckTablePermissions($dpTableName, "S") )
3353
+ return;
3354
+
3355
+ $listPageObject = $this->getDetailsPageObject( $dpTableName, $dpId );
3356
+ $listPageObject->assignButtonsOnMasterEdit( $this->xt );
3357
+ }
3358
+
3359
+ /**
3360
+ * Assign basic page's xt variables
3361
+ */
3362
+ protected function doCommonAssignments()
3363
+ {
3364
+ if ( $this->mode === ADD_SIMPLE )
3365
+ {
3366
+ $this->headerCommonAssign();
3367
+ }
3368
+ else
3369
+ {
3370
+ $this->xt->assign("menu_chiddenattr", "data-hidden" );
3371
+ }
3372
+
3373
+ $this->setLangParams();
3374
+
3375
+ $this->xt->assign("message_block", true);
3376
+
3377
+ if( $this->isMessageSet() )
3378
+ {
3379
+ $this->xt->assign("message", $this->message );
3380
+ $this->xt->assign("message_class", $this->messageType == MESSAGE_ERROR ? "alert alert-danger" : "alert alert-success" );
3381
+ }
3382
+ else
3383
+ {
3384
+ $this->hideElement("message");
3385
+ }
3386
+
3387
+ if( $this->mode != ADD_INLINE )
3388
+ $this->assignAddFieldsBlocksAndLabels();
3389
+
3390
+ if( $this->mode == ADD_SIMPLE )
3391
+ {
3392
+ $this->assignBody();
3393
+ $this->xt->assign("flybody", true);
3394
+ }
3395
+
3396
+ if( $this->mode == ADD_ONTHEFLY
3397
+ /*|| $this->mode == ADD_MASTER*/
3398
+ || $this->mode == ADD_POPUP
3399
+ || $this->mode == ADD_DASHBOARD
3400
+ || $this->mode == ADD_MASTER_DASH )
3401
+ {
3402
+ $this->xt->assign("body", true);
3403
+ $this->xt->assign("footer", false);
3404
+ $this->xt->assign("header", false);
3405
+ $this->xt->assign("flybody", $this->body);
3406
+ }
3407
+ }
3408
+
3409
+ /**
3410
+ * Assign add fields' blocks and labels variables
3411
+ */
3412
+ public function assignAddFieldsBlocksAndLabels()
3413
+ {
3414
+ foreach($this->addFields as $fName)
3415
+ {
3416
+ $gfName = GoodFieldName($fName);
3417
+
3418
+ $this->xt->assign($gfName."_fieldblock", true);
3419
+ $this->xt->assign($gfName."_tabfieldblock", true);
3420
+ }
3421
+ }
3422
+
3423
+ /**
3424
+ * Display the add page basing on its mode
3425
+ */
3426
+ protected function displayAddPage()
3427
+ {
3428
+ $templatefile = $this->templatefile;
3429
+
3430
+ if( $this->eventsObject->exists("BeforeShowAdd") )
3431
+ $this->eventsObject->BeforeShowAdd($this->xt, $templatefile, $this);
3432
+
3433
+ if( $this->mode != ADD_INLINE && $this->mode != ADD_ONTHEFLY )
3434
+ $this->displayMasterTableInfo();
3435
+ // invoked after displayMasterTableInfo to add master viewcontrols maps
3436
+ $this->fillSetCntrlMaps();
3437
+
3438
+ if( $this->mode == ADD_SIMPLE /*|| $this->mode ==ADD_MASTER */)
3439
+ {
3440
+ $this->display( $templatefile );
3441
+ return;
3442
+ }
3443
+
3444
+ if( $this->mode == ADD_ONTHEFLY || $this->mode == ADD_POPUP || $this->mode == ADD_DASHBOARD || $this->mode == ADD_MASTER_DASH )
3445
+ {
3446
+ $this->displayAJAX( $templatefile, $this->flyId + 1 );
3447
+ exit();
3448
+ }
3449
+
3450
+ if( $this->mode == ADD_INLINE )
3451
+ {
3452
+ $returnJSON = array();
3453
+
3454
+ $this->xt->load_template( $templatefile );
3455
+
3456
+ $returnJSON["htmlControls"] = array();
3457
+ foreach( $this->addFields as $fName ) {
3458
+ $returnJSON["htmlControls"][ $fName ] = $this->xt->fetchVar( GoodFieldName($fName)."_editcontrol" );
3459
+ }
3460
+
3461
+ $listPSet = $this->getListPSet();
3462
+ if( $listPSet->reorderRows() ) {
3463
+ // provisional order value, to be adjusted at the time of saving
3464
+ $returnJSON['order'] = $this->getMaxOrderValue( $listPSet ) + 1;
3465
+ }
3466
+
3467
+
3468
+ global $pagesData;
3469
+ $returnJSON["pagesData"] = $pagesData;
3470
+
3471
+ $returnJSON['settings'] = $this->jsSettings;
3472
+ $returnJSON['controlsMap'] = $this->controlsHTMLMap;
3473
+ $returnJSON['viewControlsMap'] = $this->viewControlsHTMLMap;
3474
+
3475
+ $returnJSON["additionalJS"] = $this->grabAllJsFiles();
3476
+ $returnJSON["additionalCSS"] = $this->grabAllCSSFiles();
3477
+
3478
+ echo printJSON($returnJSON);
3479
+ exit();
3480
+ }
3481
+ }
3482
+
3483
+ /**
3484
+ * Get extra JSON params to display the page on AJAX-like request
3485
+ * @return Array
3486
+ */
3487
+ protected function getExtraAjaxPageParams()
3488
+ {
3489
+ return $this->getSaveStatusJSON();
3490
+ }
3491
+
3492
+ /**
3493
+ * Return link and display field values after Add on the fly
3494
+ * @return array or false
3495
+ * "link" => <link field value>
3496
+ * "display" => <display field value>
3497
+ */
3498
+ protected function getNewLookupValues( $lookupPSet )
3499
+ {
3500
+ $linkFieldName = $lookupPSet->getLinkField( $this->lookupField );
3501
+ $dispFieldName = $lookupPSet->getDisplayField( $this->lookupField );
3502
+ if( $this->keys ) {
3503
+ $dc = new DsCommand();
3504
+ $dc->keys = $this->keys;
3505
+
3506
+ if( $lookupPSet->getCustomDisplay( $this->lookupField ) ) {
3507
+ $customField = new DsFieldData( $dispFieldName, generateAlias(), "" );
3508
+ $dispFieldName = $customField->alias;
3509
+ $dc->extraColumns[] = $customField;
3510
+ }
3511
+ $data = $this->cipherer->DecryptFetchedArray( $this->dataSource->getSingle( $dc )->fetchAssoc() );
3512
+ }
3513
+ if( !$data ) {
3514
+ $data = $this->newRecordData;
3515
+ }
3516
+ return array(
3517
+ "link" => $data[ $linkFieldName ],
3518
+ "display" => $data[ $dispFieldName ]
3519
+ );
3520
+ }
3521
+
3522
+ /**
3523
+ * Get lookup data from a record added
3524
+ * in 'add value On the Fly' mode
3525
+ * or in Inline Add mode on List page with search.
3526
+ * @return Array
3527
+ */
3528
+ public function getLookupData() {
3529
+ // get Project Settings object for $this->lookupTable
3530
+ $lookupPSet = getLookupMainTableSettings( $this->tName, $this->lookupTable, $this->lookupField, $this->lookupPageType );
3531
+ if( !$lookupPSet )
3532
+ return array();
3533
+
3534
+ $lvals = $this->getNewLookupValues( $lookupPSet );
3535
+ if( !$lvals )
3536
+ return array();
3537
+
3538
+ $linkField = $lookupPSet->getLinkField( $this->lookupField );
3539
+ $dispfield = $lookupPSet->getDisplayField( $this->lookupField );
3540
+
3541
+ $respData = array(
3542
+ $linkField => $lvals["link"],
3543
+ $dispfield => $lvals["display"]
3544
+ );
3545
+
3546
+ // format DATE or TIME value
3547
+ if( in_array( $lookupPSet->getViewFormat( $this->lookupField ), array(FORMAT_DATE_SHORT, FORMAT_DATE_LONG, FORMAT_DATE_TIME) ) ) {
3548
+ $viewContainer = new ViewControlsContainer( $lookupPSet, PAGE_LIST, null );
3549
+
3550
+ $ctrlData = array();
3551
+ $ctrlData[ $this->lookupField ] = $respData[ $linkField ];
3552
+
3553
+ $respData[ $dispfield ] = $viewContainer->getControl( $this->lookupField )->getTextValue( $ctrlData );
3554
+ }
3555
+
3556
+ return array(
3557
+ 'linkValue' => $respData[ $linkField ],
3558
+ 'displayValue' => $respData[ $dispfield ],
3559
+ 'vals' => $respData
3560
+ );
3561
+ }
3562
+
3563
+ /**
3564
+ * Check if to add session owner id value
3565
+ * @param String ownerField
3566
+ * @param String currentValue
3567
+ * @return Boolean
3568
+ */
3569
+ public function checkIfToAddOwnerIdValue( $ownerField, $currentValue )
3570
+ {
3571
+ return originalTableField( $ownerField, $this->pSet ) // legacy
3572
+ && !$this->isAutoincPrimaryKey( $ownerField )
3573
+ && ( !CheckTablePermissions($this->tName, 'M') || !strlen($currentValue) );
3574
+ }
3575
+
3576
+ /**
3577
+ * Check if field is auto-incremented primary key
3578
+ * @param String field
3579
+ * @return Boolean
3580
+ */
3581
+ protected function isAutoincPrimaryKey( $field )
3582
+ {
3583
+ $keyFields = $this->pSet->getTableKeys();
3584
+ return count($keyFields) == 1 && in_array($field, $keyFields) && $this->pSet->isAutoincField( $field );
3585
+ }
3586
+
3587
+ /**
3588
+ * Check if the page's message is set
3589
+ * @return Boolean
3590
+ */
3591
+ protected function isMessageSet()
3592
+ {
3593
+ return strlen( $this->message ) > 0;
3594
+ }
3595
+
3596
+ /**
3597
+ * Set a database error message
3598
+ * @param String message
3599
+ */
3600
+ public function setDatabaseError( $message )
3601
+ {
3602
+ if( $this->mode != ADD_INLINE )
3603
+ {
3604
+ $this->message = "<strong>&lt;&lt;&lt; "."Record was NOT added"."</strong> &gt;&gt;&gt;<br><br>".$message;
3605
+ }
3606
+ else
3607
+ {
3608
+ $this->message = "Record was NOT added".". ".$message;
3609
+ }
3610
+
3611
+ $this->messageType = MESSAGE_ERROR;
3612
+ }
3613
+
3614
+ /**
3615
+ * @return Array
3616
+ */
3617
+ public function getNewRecordData()
3618
+ {
3619
+ return $this->newRecordData;
3620
+ }
3621
+
3622
+
3623
+ /**
3624
+ * @param String fName
3625
+ * @return Boolean
3626
+ */
3627
+ protected function checkFieldOnPage( $fName )
3628
+ {
3629
+ if( $this->mode == ADD_INLINE )
3630
+ return $this->pSet->appearOnInlineAdd( $fName );
3631
+
3632
+ return $this->pSet->appearOnAddPage( $fName );
3633
+ }
3634
+
3635
+ /**
3636
+ * @param String table
3637
+ */
3638
+ public static function processAddPageSecurity( $table )
3639
+ {
3640
+ // user has necessary permissions
3641
+ if( Security::checkPagePermissions( $table, "A" ) )
3642
+ return true;
3643
+
3644
+ // display entered data. Give the user chance to relogin. Do nothing for now.
3645
+ if( postvalue("a") == "added" )
3646
+ return true;
3647
+
3648
+ // page can not be displayed. Redirect or return error
3649
+
3650
+ // return error if the page is requested by AJAX
3651
+ $pageMode = AddPage::readAddModeFromRequest();
3652
+ if( $pageMode != ADD_SIMPLE )
3653
+ {
3654
+ Security::sendPermissionError();
3655
+ return false;
3656
+ }
3657
+
3658
+ // The user is logged in but lacks necessary permissions
3659
+ // redirect to List page or Menu.
3660
+ if( isLogged() && !Security::isGuest() )
3661
+ {
3662
+ Security::redirectToList( $table );
3663
+ return false;
3664
+ }
3665
+
3666
+ redirectToLogin();
3667
+ return false;
3668
+ }
3669
+
3670
+ public static function readAddModeFromRequest()
3671
+ {
3672
+ $editType = postvalue("editType");
3673
+
3674
+ if( $editType == "inline" )
3675
+ return ADD_INLINE;
3676
+ elseif( $editType == ADD_POPUP )
3677
+ return ADD_POPUP;
3678
+ elseif( $editType == ADD_MASTER )
3679
+ return ADD_MASTER;
3680
+ elseif( $editType == ADD_MASTER_POPUP )
3681
+ return ADD_MASTER_POPUP;
3682
+ elseif( $editType == ADD_MASTER_DASH )
3683
+ return ADD_MASTER_DASH;
3684
+ elseif( $editType == ADD_ONTHEFLY )
3685
+ return ADD_ONTHEFLY;
3686
+ elseif( postvalue("mode") == "dashrecord" )
3687
+ return ADD_DASHBOARD;
3688
+ else
3689
+ return ADD_SIMPLE;
3690
+ }
3691
+
3692
+ function editAvailable() {
3693
+ return !$this->dashElementData && parent::editAvailable();
3694
+ }
3695
+
3696
+ function viewAvailable() {
3697
+ return !$this->dashElementData && parent::viewAvailable();
3698
+ }
3699
+
3700
+ /**
3701
+ * API
3702
+ */
3703
+ public function setMessageType( $type )
3704
+ {
3705
+ $this->messageType = $type;
3706
+ }
3707
+
3708
+ function element2Item( $name ) {
3709
+ if( $name == "message" ) {
3710
+ return array( "add_message" );
3711
+ }
3712
+ return parent::element2Item( $name );
3713
+ }
3714
+
3715
+ protected function checkShowBreadcrumbs()
3716
+ {
3717
+ return $this->mode == ADD_SIMPLE;
3718
+ }
3719
+
3720
+ function createProjectSettings() {
3721
+ $this->pSet = new ProjectSettings($this->tName, $this->pageType, $this->pageName, $this->pageTable );
3722
+
3723
+ if( $this->mode != ADD_INLINE && $this->pSet->getPageType() !== PAGE_ADD )
3724
+ {
3725
+ $this->pSet = new ProjectSettings($this->tName, $this->pageType, null, $this->pageTable );
3726
+ }
3727
+
3728
+ if( $this->mode == ADD_POPUP && $this->action == "added" ) {
3729
+ $this->pSet->setPageType( "list" );
3730
+ }
3731
+ }
3732
+
3733
+
3734
+ public function getInsertDataCommand() {
3735
+ $dc = new DsCommand();
3736
+ $dc->values = &$this->newRecordData;
3737
+
3738
+ $dc->advValues = array();
3739
+ foreach( $this->sqlValues as $field => $sqlValue ) {
3740
+ $dc->advValues[ $field ] = new DsOperand( dsotSQL, $sqlValue );
3741
+ }
3742
+ return $dc;
3743
+ }
3744
+
3745
+ public function getSecurityCondition() {
3746
+ return Security::SelectCondition( "S", $this->pSet );
3747
+ }
3748
+
3749
+ protected function getRecordData( $keys ) {
3750
+ $dc = $this->getDsCommand( $keys );
3751
+
3752
+ $fetchedArray = $this->dataSource->getSingle( $dc )->fetchAssoc();
3753
+ return $this->cipherer->DecryptFetchedArray( $fetchedArray );
3754
+ }
3755
+
3756
+ protected function getDsCommand( $keys ) {
3757
+ $dc = new DsCommand();
3758
+ $dc->keys = $keys;
3759
+ $dc->filter = $this->getSecurityCondition();
3760
+
3761
+ return $dc;
3762
+ }
3763
+
3764
+ protected function getListPSet() {
3765
+ if( !$this->listPagePSet ) {
3766
+ $this->listPagePSet = new ProjectSettings( $this->tName, PAGE_LIST, $this->hostPageName, $this->pageTable );
3767
+ }
3768
+ return $this->listPagePSet;
3769
+ }
3770
+ }
3771
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
3772
  ?>
php/classes/advancedsearchcontrol.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
 
3
  /**
@@ -26,4 +27,34 @@ class AdvancedSearchControl extends SearchControl
26
  return parent::getCtrlSearchTypeOptions($fName, $selOpt, $withNot, false, $both);
27
  }
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
 
4
  /**
 
27
  return parent::getCtrlSearchTypeOptions($fName, $selOpt, $withNot, false, $both);
28
  }
29
  }
30
+ =======
31
+ <?php
32
+
33
+ /**
34
+ * Search control builder class for advanced search
35
+ *
36
+ */
37
+ class AdvancedSearchControl extends SearchControl
38
+ {
39
+ function __construct($id, $tName, &$searchClauseObj, &$pageObj)
40
+ {
41
+ parent::__construct($id, $tName, $searchClauseObj, $pageObj);
42
+ $this->getSrchPanelAttrs['ctrlTypeComboStatus'] = true;
43
+ }
44
+
45
+ function getCtrlSearchTypeOptions($fName, $selOpt, $not, $flexible = false, $both = false)
46
+ {
47
+ if( $this->pageObj->isBootstrap() )
48
+ {
49
+ if( !$flexible && ($selOpt == EMPTY_SEARCH || $selOpt == NOT_EMPTY) )
50
+ return $this->getControl($fName)->buildSearchOptions(array(EMPTY_SEARCH, NOT_EMPTY), $selOpt, $not, true);
51
+
52
+ return $this->getControl($fName)->getSearchOptions($selOpt, $not, true);
53
+ }
54
+
55
+ $withNot = $both ? $not : false;
56
+ return parent::getCtrlSearchTypeOptions($fName, $selOpt, $withNot, false, $both);
57
+ }
58
+ }
59
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
60
  ?>
php/classes/base32.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class RunnerBase32 {
3
  public static function encode( $str ) {
@@ -96,3 +97,103 @@ class RunnerBase32 {
96
  );
97
  }
98
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class RunnerBase32 {
4
  public static function encode( $str ) {
 
97
  );
98
  }
99
  ?>
100
+ =======
101
+ <?php
102
+ class RunnerBase32 {
103
+ public static function encode( $str ) {
104
+ $ret = "";
105
+ $n = 0;
106
+ while( "" !== ( $symbol = self::encodeChunk( $str, $n++ ) ) ) {
107
+ $ret .= $symbol;
108
+ }
109
+ return str_pad( $ret, strlen( $ret ) + strlen( $ret ) % 8 , '=' );
110
+ }
111
+
112
+ public static function decode( $str ) {
113
+ $ret = "";
114
+ $n = 0;
115
+ while( $n < strlen( $str ) && self::decodeChunk( $str[ $n ], $ret, $n ) ) {
116
+ ++$n;
117
+ }
118
+ return $ret;
119
+ }
120
+
121
+ /**
122
+ * decode synbol and write n-th 5-bit block to the string
123
+ */
124
+ protected static function decodeChunk( $encoded, &$str, $n ) {
125
+ if( $encoded == '=' ) {
126
+ // reached the end, stop processing
127
+ return false;
128
+ }
129
+ $fiveBits = array_search( $encoded, self::$table );
130
+ if( $fiveBits < 0 ) {
131
+ // wrong symbol, stop procesing
132
+ return false;
133
+ }
134
+
135
+ $charIdx = (int)floor( $n * 5 / 8 );
136
+ $bitOffset = ($n * 5) % 8;
137
+ if( $charIdx < strlen( $str ) ) {
138
+ $byte = ord( $str[ $charIdx ] );
139
+ } else {
140
+ $byte = 0;
141
+ $str .= ' ';
142
+ }
143
+
144
+ if( $bitOffset <= 3 ) {
145
+ $byte += $fiveBits << ( 3 - $bitOffset );
146
+ $str[ $charIdx ] = chr( $byte );
147
+ } else {
148
+ $byte += $fiveBits >> ( $bitOffset - 3 );
149
+ $str[ $charIdx ] = chr( $byte );
150
+
151
+ // if lowest ( $bitOffset - 3 ) bits are not 0, write them to the next byte
152
+ $mask = (1 << ( $bitOffset - 3 )) - 1;
153
+ $nextByte = ( $fiveBits & $mask ) << ( 8 - ( $bitOffset - 3 ) );
154
+ if( $nextByte !== 0 ) {
155
+ if( $charIdx + 1 >= strlen( $str ) ) {
156
+ $str .= chr( $nextByte );
157
+ }
158
+ }
159
+ }
160
+
161
+ return true;
162
+ }
163
+
164
+ /**
165
+ * read and encode n-th 5-bit block from the string
166
+ */
167
+ protected static function encodeChunk( &$str, $n ) {
168
+ $charIdx = (int)floor( $n * 5 / 8 );
169
+ $bitOffset = ($n * 5) % 8;
170
+ if( $charIdx >= strlen( $str ) ) {
171
+ return "";
172
+ }
173
+ $byte = ord( $str[ $charIdx ] );
174
+ if( $bitOffset <= 3 ) {
175
+ // read highest ($bitOffset + 5) bits and puth them into $fiveBits
176
+ $fiveBits = ( $byte >> ( 3 - $bitOffset ) ) & 31;
177
+ } else {
178
+ // read 8 - $bitoffset bits from the first byte
179
+ $mask = ( 1 << ( 8 - $bitOffset ) ) - 1;
180
+ $fiveBits = ( $byte & $mask ) << ( $bitOffset - 3 );
181
+ if( $charIdx < strlen( $str ) - 1 ) {
182
+ // read next ($bitOffset - 3) bits and put them in the lowest bits of $fiveBits
183
+ $nextByte = ord( $str[ $charIdx + 1 ] );
184
+ $fiveBits += $nextByte >> ( 8 - ($bitOffset - 3) );
185
+ }
186
+ }
187
+ $ret = self::$table[ $fiveBits ];
188
+ return $ret;
189
+ }
190
+ protected static $table = array(
191
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
192
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
193
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
194
+ 'Y', 'Z', '2', '3', '4', '5', '6', '7',
195
+ '='
196
+ );
197
+ }
198
+ ?>
199
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
php/classes/button.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class Button
3
  {
@@ -205,4 +206,213 @@ class Button
205
  return $masterDs->getList( $dc )->fetchAssoc();
206
  }
207
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class Button
4
  {
 
206
  return $masterDs->getList( $dc )->fetchAssoc();
207
  }
208
  }
209
+ =======
210
+ <?php
211
+ class Button
212
+ {
213
+ var $keys = array();
214
+
215
+ var $currentKeys = array();
216
+
217
+ var $selectedKeys = array();
218
+
219
+ var $isManyKeys = false;
220
+
221
+ var $location = "";
222
+
223
+ var $nextInd;
224
+
225
+ var $table;
226
+
227
+ var $page;
228
+
229
+ var $tempFileNames = array();
230
+
231
+ public $masterTable;
232
+ public $masterKeys;
233
+
234
+ function __construct(&$params)
235
+ {
236
+ RunnerApply($this, $params);
237
+
238
+ $this->nextInd = 0;
239
+ $this->modifyKeys();
240
+ $this->separateKeys();
241
+ }
242
+ /**
243
+ * Separate modified post keys to current and selected
244
+ */
245
+ function separateKeys()
246
+ {
247
+ if($this->location == 'grid')
248
+ {
249
+ if($this->isManyKeys)
250
+ {
251
+ $this->currentKeys = $this->keys[0];
252
+ for($i=1; $i<count($this->keys); $i++)
253
+ $this->selectedKeys[$i-1] = $this->keys[$i];
254
+ }
255
+ else
256
+ $this->currentKeys = $this->keys;
257
+ }
258
+ if($this->location == PAGE_LIST) {
259
+ $this->selectedKeys = $this->keys;
260
+ $this->currentKeys = $this->keys;
261
+ }
262
+
263
+ if($this->location == PAGE_EDIT || $this->location == PAGE_VIEW)
264
+ $this->currentKeys = $this->keys;
265
+ }
266
+ /**
267
+ * Modify post keys array to associative
268
+ */
269
+ function modifyKeys()
270
+ {
271
+ $pSet = new ProjectSettings( $this->table, "", $this->page );
272
+
273
+ $keys = array();
274
+
275
+ // if array of keys exists
276
+ if( $this->keys )
277
+ {
278
+ $tKeysNamesArr = $pSet->getTableKeys();
279
+ if($this->isManyKeys)
280
+ {
281
+ foreach ($this->keys as $ind => $value)
282
+ {
283
+ $keys[$ind] = array();
284
+ $recKeyArr = explode('&', $value);
285
+ for($j=0;$j<count($tKeysNamesArr);$j++)
286
+ {
287
+ if (isset($recKeyArr[$j])){
288
+ $keys[$ind][$tKeysNamesArr[$j]] = urldecode($recKeyArr[$j]);
289
+ }
290
+ }
291
+ }
292
+ }
293
+ else
294
+ {
295
+ $keysReady = true;
296
+ foreach( $tKeysNamesArr as $kf ) {
297
+ if( !isset( $this->keys[ $kf ] ) ) {
298
+ $keysReady = false;
299
+ break;
300
+ }
301
+ }
302
+
303
+ if( $keysReady )
304
+ return;
305
+
306
+ for($j=0;$j<count($tKeysNamesArr);$j++)
307
+ {
308
+ $keys[$tKeysNamesArr[$j]] = urldecode(@$this->keys[$j]);
309
+ }
310
+ }
311
+ }
312
+ $this->keys = $keys;
313
+ }
314
+ /**
315
+ * Get keys
316
+ * @return {array}
317
+ */
318
+ function getKeys() {
319
+ return $this->keys;
320
+ }
321
+
322
+ /**
323
+ * Get current record data
324
+ * @return {mixed} array of next record data or false
325
+ */
326
+ function getCurrentRecord() {
327
+ return $this->getRecordData();
328
+ }
329
+
330
+ /**
331
+ * Get next selected record
332
+ * @return {mixed} array of next record data or false
333
+ */
334
+ function getNextSelectedRecord() {
335
+ if( $this->nextInd < count( $this->selectedKeys ) ) {
336
+ $data = $this->getRecordData( $this->selectedKeys[ $this->nextInd ] );
337
+ $this->nextInd += 1;
338
+ return $data;
339
+ }
340
+
341
+ return false;
342
+ }
343
+
344
+ /**
345
+ * Read values from the database by keys
346
+ * @return {mixed} array of current record data or false
347
+ */
348
+ public function getRecordData( $keys = null ) {
349
+ global $cipherer;
350
+
351
+ if( !$keys )
352
+ $keys = $this->currentKeys;
353
+
354
+ $pSet = new ProjectSettings( $this->table, "", $this->page );
355
+
356
+ $dc = new DsCommand();
357
+ $dc->filter = Security::SelectCondition( "S", $pSet );
358
+ $dc->keys = $keys;
359
+
360
+ $dataSource = getDataSource( $this->table, $pSet );
361
+ $fetchedArray = $dataSource->getSingle( $dc )->fetchAssoc();
362
+ $data = $cipherer->DecryptFetchedArray( $fetchedArray );
363
+
364
+ return $data;
365
+ }
366
+
367
+
368
+ function getMasterData( $masterTable )
369
+ {
370
+ if ( isset($_SESSION[ $masterTable . "_masterRecordData" ]) )
371
+ {
372
+ return $_SESSION[ $masterTable . "_masterRecordData" ];
373
+ }
374
+
375
+ return false;
376
+ }
377
+
378
+ function saveTempFile( $contents ) {
379
+ $filename = tempnam("", "");
380
+ runner_save_file($filename, $contents);
381
+ $this->tempFileNames[] = $filename;
382
+ return $filename;
383
+ }
384
+
385
+ function deleteTempFiles() {
386
+ foreach( $this->tempFileNames as $f ) {
387
+ @unlink( $f );
388
+ }
389
+ }
390
+
391
+ public function getMasterRecord() {
392
+ if( !$this->masterTable )
393
+ return null;
394
+
395
+ $pSet = new ProjectSettings( $this->table, "", $this->page );
396
+ $mpSet = new ProjectSettings( $this->masterTable, PAGE_LIST );
397
+ $masterDs = getDataSource( $this->masterTable, $mpSet );
398
+
399
+ $filters = array();
400
+ foreach( $pSet->getMasterTablesArr() as $i => $masterTableInfo ) {
401
+ if( $this->masterTable != $masterTableInfo['mDataSourceTable'] )
402
+ continue;
403
+
404
+ foreach( $masterTableInfo['masterKeys'] as $j => $mKeyField ) {
405
+ $filters[] = DataCondition::FieldEquals( $mKeyField, $this->masterKeys[ $j + 1 ] );
406
+ }
407
+ }
408
+ $filters[] = Security::SelectCondition( "S", $mpSet );
409
+
410
+ $dc = new DsCommand;
411
+ $dc->filter = DataCondition::_And( $filters );
412
+ $dc->reccount = 1;
413
+
414
+ return $masterDs->getList( $dc )->fetchAssoc();
415
+ }
416
+ }
417
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
418
  ?>
php/classes/chartpage.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class ChartPage extends RunnerPage
3
  {
@@ -371,4 +372,379 @@ class ChartPage extends RunnerPage
371
  return CHART_SIMPLE;
372
  }
373
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class ChartPage extends RunnerPage
4
  {
 
372
  return CHART_SIMPLE;
373
  }
374
  }
375
+ =======
376
+ <?php
377
+ class ChartPage extends RunnerPage
378
+ {
379
+ /**
380
+ * show message block
381
+ */
382
+ public $show_message_block = false;
383
+
384
+ /**
385
+ * @constructor
386
+ */
387
+ function __construct(&$params = "")
388
+ {
389
+ parent::__construct($params);
390
+
391
+ $this->bodyForms = array( "grid" );
392
+
393
+ $this->jsSettings['tableSettings'][ $this->tName ]['simpleSearchActive'] = $this->searchClauseObj->simpleSearchActive;
394
+
395
+ if( $this->mode == CHART_DASHBOARD ) {
396
+ $this->pageData['detailsMasterKeys'] = $this->getStartMasterKeys();
397
+ }
398
+ $this->pageData['singleChartPage'] = $this->pSet->getChartCount() == 1;
399
+ }
400
+
401
+ /**
402
+ * Set the page's session prefix
403
+ */
404
+ protected function assignSessionPrefix()
405
+ {
406
+ if( $this->mode == CHART_DASHBOARD )
407
+ $this->sessionPrefix = $this->dashTName."_".$this->tName;
408
+ else
409
+ $this->sessionPrefix = $this->tName;
410
+ }
411
+
412
+ /**
413
+ * Process the page
414
+ */
415
+ public function process()
416
+ {
417
+ if( $this->mode == CHART_DASHDETAILS
418
+ || $this->mode == CHART_DETAILS && ( $this->masterPageType == PAGE_LIST || $this->masterPageType == PAGE_REPORT ))
419
+ $this->updateDetailsTabTitles();
420
+
421
+
422
+ // Before Process event
423
+ if( $this->eventsObject->exists("BeforeProcessChart") )
424
+ $this->eventsObject->BeforeProcessChart( $this );
425
+
426
+
427
+ // build tabs and set current
428
+ $this->processGridTabs();
429
+
430
+ $this->doCommonAssignments();
431
+ $this->addButtonHandlers();
432
+ $this->addCommonJs();
433
+ $this->commonAssign();
434
+
435
+ if( $this->mode != CHART_DASHBOARD ) {
436
+ $this->buildSearchPanel();
437
+ $this->assignSimpleSearch();
438
+ }
439
+
440
+ // to restore correctly within a chart class
441
+ $_SESSION[ $this->sessionPrefix.'_advsearch' ] = serialize( $this->searchClauseObj );
442
+
443
+ // display the 'Back to Master' link and master table info
444
+ $this->displayMasterTableInfo();
445
+
446
+ $this->showPage();
447
+ }
448
+
449
+ function callBeforeQueryEvent( $dc ) {
450
+ if( !$this->eventsObject->exists("BeforeQueryChart") ) {
451
+ return;
452
+ }
453
+ $prep = $this->dataSource->prepareSQL( $dc );
454
+ $where = $prep["where"];
455
+ $order = $prep["order"];
456
+ $sql = $prep["sql"];
457
+ $this->eventsObject->BeforeQueryChart($sql, $where, $order );
458
+
459
+ if( $sql != $prep["sql"] )
460
+ $this->dataSource->overrideSQL( $dc, $sql );
461
+ else {
462
+ if( $where != $prep["where"] )
463
+ $this->dataSource->overrideWhere( $dc, $where );
464
+ if( $order != $prep["order"] )
465
+ $this->dataSource->overrideOrder( $dc, $order );
466
+ }
467
+ }
468
+
469
+
470
+
471
+ function getMasterCondition() {
472
+ if( $this->mode == CHART_DASHBOARD )
473
+ return null;
474
+
475
+ return parent::getMasterCondition();
476
+ }
477
+
478
+ /**
479
+ * Get started master keys
480
+ * @return Array
481
+ */
482
+ public function getStartMasterKeys()
483
+ {
484
+ $detailTablesData = $this->pSet->getDetailTablesArr();
485
+ if( !$detailTablesData ) {
486
+ return array();
487
+ }
488
+
489
+ $dc = $this->getSubsetDataCommand();
490
+ $dc->reccount = 1;
491
+
492
+ $rs = $this->dataSource->getList( $dc );
493
+ if( !$rs ) {
494
+ showError( $this->dataSource->lastError() );
495
+ }
496
+
497
+ $data = $this->cipherer->DecryptFetchedArray( $rs->fetchAssoc() );
498
+
499
+ $masterKeysArr = array();
500
+ foreach ( $detailTablesData as $detailId => $detail ) {
501
+ foreach( $detail['masterKeys'] as $idx => $mk ) {
502
+ $masterKeysArr[ $detail['dDataSourceTable'] ] = array( 'masterkey'.($idx + 1) => $data[$mk] );
503
+ }
504
+ }
505
+
506
+ return $masterKeysArr;
507
+ }
508
+
509
+ /**
510
+ *
511
+ */
512
+ public function doCommonAssignments()
513
+ {
514
+
515
+ //set the Search panel
516
+ $this->xt->assign("searchPanel", true);
517
+
518
+ if( $this->isShowMenu() )
519
+ $this->xt->assign("menu_block", true);
520
+
521
+ $this->setLangParams();
522
+
523
+ $this->xt->assign("chart_block", true);
524
+ $this->xt->assign("asearch_link", true);
525
+ $this->xt->assign("exportpdflink_attrs", "onclick='chart.saveAsPDF();'");
526
+ $this->xt->assign("advsearchlink_attrs", "id=\"advButton".$this->id."\"");
527
+
528
+ if( !GetChartXML( $this->shortTableName ) )
529
+ $this->xt->assign("chart_block", false);
530
+
531
+ $this->xt->assign("message_block", true);
532
+
533
+ if( ($this->mode == CHART_SIMPLE || $this->mode == CHART_DASHBOARD) && $this->pSet->noRecordsOnFirstPage() && !$this->searchClauseObj->isSearchFunctionalityActivated() )
534
+ {
535
+ $this->show_message_block = true;
536
+ $this->hideElement("chart");
537
+ $this->xt->assign("chart_block", false);
538
+
539
+ $this->xt->assign("message", $this->noRecordsMessage());
540
+ $this->xt->assign( "message_class", "alert-warning");
541
+ }
542
+
543
+ if( !$this->show_message_block )
544
+ $this->hideElement("message");
545
+
546
+ if( $this->mobileTemplateMode() )
547
+ $this->xt->assign('tableinfomobile_block', true);
548
+
549
+
550
+ $this->assignChartElement();
551
+
552
+ $this->body['begin'].= GetBaseScriptsForPage( $this->isDisplayLoading );
553
+ if( !$this->isDashboardElement() && !$this->mobileTemplateMode() )
554
+ $this->body['begin'].= "<div id=\"search_suggest\" class=\"search_suggest\"></div>";
555
+
556
+ // assign body end
557
+ $this->body['end'] = XTempl::create_method_assignment( "assignBodyEnd", $this);
558
+
559
+ $this->xt->assignbyref('body', $this->body);
560
+ }
561
+
562
+ /**
563
+ * Set the chart xt variable
564
+ */
565
+ public function assignChartElement()
566
+ {
567
+ }
568
+
569
+ /**
570
+ *
571
+ */
572
+ public function prepareDetailsForEditViewPage()
573
+ {
574
+ $this->addButtonHandlers();
575
+
576
+ $this->xt->assign("body", $this->body);
577
+ $this->xt->assign("chart_block", true);
578
+ $this->xt->assign("message_block", true);
579
+ }
580
+
581
+ protected function getExtraAjaxPageParams()
582
+ {
583
+ $returnJSON = array();
584
+ if( $this->mode == REPORT_DETAILS )
585
+ {
586
+ $returnJSON['headerCont'] = $this->getProceedLink() . $returnJSON['headerCont'];
587
+ }
588
+
589
+ return $returnJSON;
590
+ }
591
+
592
+ public function beforeShowChart()
593
+ {
594
+ if( $this->eventsObject->exists("BeforeShowChart") )
595
+ $this->eventsObject->BeforeShowChart($this->xt, $this->templatefile, $this);
596
+ }
597
+
598
+ public function showPage()
599
+ {
600
+ $this->beforeShowChart();
601
+
602
+ if( $this->mode == CHART_DETAILS || $this->mode == CHART_DASHBOARD || $this->mode == CHART_DASHDETAILS )
603
+ {
604
+ $this->addControlsJSAndCSS();
605
+ $this->fillSetCntrlMaps();
606
+
607
+ $this->xt->assign("header", false);
608
+ $this->xt->assign("footer", false);
609
+
610
+ $this->body["begin"] = "";
611
+ $this->body["end"] = "";
612
+ $this->xt->assign("body", $this->body);
613
+
614
+ $this->displayAJAX($this->templatefile, $this->id + 1);
615
+ exit();
616
+ }
617
+
618
+ if( $this->mode == CHART_POPUPDETAILS ) //currently unused
619
+ {
620
+ $this->xt->assign("header", false);
621
+ $this->xt->assign("footer", false);
622
+ $this->body["begin"] = '';
623
+ $this->body["end"] = '';
624
+
625
+ $this->xt->prepare_template($this->templatefile);
626
+ $respArr = array();
627
+ $respArr['success'] = true;
628
+ $respArr['body'] = $this->xt->fetch_loaded("body");
629
+ $respArr['counter'] = postvalue('counter');
630
+ $this->xt->assign("container_master", false);
631
+
632
+ echo printJSON($respArr);
633
+ exit();
634
+ }
635
+
636
+ $this->display( $this->templatefile );
637
+ }
638
+
639
+ /**
640
+ *
641
+ */
642
+ function processGridTabs()
643
+ {
644
+ $ctChanged = parent::processGridTabs();
645
+ $_SESSION[ $this->sessionPrefix . "_chartTabWhere" ] = $this->getCurrentTabWhere();
646
+
647
+ return $ctChanged;
648
+ }
649
+
650
+ function gridTabsAvailable() {
651
+ return true;
652
+ }
653
+
654
+ function displayTabsInPage()
655
+ {
656
+ return $this->simpleMode()
657
+ || ( $this->mode == CHART_DETAILS && ($this->masterPageType == PAGE_VIEW || $this->masterPageType == PAGE_EDIT))
658
+ || $this->mode == CHART_DASHBOARD && $this->dashElementData["tabLocation"] == "body";
659
+ }
660
+
661
+ protected function getBodyMarkup( $templatefile )
662
+ {
663
+ if( $this->mode == CHART_DASHBOARD && $this->dashElementData["tabLocation"] == "body" )
664
+ return $this->fetchBlocksList( array( "above-grid_block", "grid_tabs", "grid_block" ) );
665
+
666
+ return parent::getBodyMarkup( $templatefile );
667
+ }
668
+
669
+ function element2Item( $name ) {
670
+ if( $name == "message" ) {
671
+ return array( "grid_message" );
672
+ }
673
+ if( $name == "chart" ) {
674
+ return array( "chart" );
675
+ }
676
+ return parent::element2Item( $name );
677
+ }
678
+
679
+ public function prepareDisplayDetails()
680
+ {
681
+ $resizeChart = true;
682
+ if( $this->mode == CHART_SIMPLE ||
683
+ $this->mode == CHART_DASHBOARD ||
684
+ $this->mode == CHART_DETAILS && ( $this->masterPageType == PAGE_VIEW || $this->masterPageType == PAGE_EDIT ) )
685
+ $resizeChart = false;
686
+
687
+ //set params for the 'xt_showchart' method showing the chart
688
+ $chartXtParams = array(
689
+ "id" => $this->id,
690
+ "table" => $this->tName,
691
+ "ctype" => $this->pSet->getChartType(),
692
+ "resize" => $resizeChart,
693
+ "chartName" => $this->shortTableName,
694
+ "chartPreview" => $this->mode !== CHART_SIMPLE && $this->mode != CHART_DASHBOARD
695
+ );
696
+
697
+ if( $this->mode == CHART_DASHBOARD || $this->mode == CHART_DASHDETAILS )
698
+ {
699
+ $chartXtParams["refreshTime"] = $this->dashElementData["reload"];
700
+ }
701
+
702
+ $this->prepareCharts();
703
+ $forms = array( "grid" );
704
+ $bodyContents = $this->fetchForms($forms);
705
+ $this->renderedBody = '<div id="detailPreview'.$this->id.'">'.$bodyContents.'</div>';
706
+ return;
707
+ }
708
+
709
+ public function showGridOnly()
710
+ {
711
+ echo $this->renderedBody;
712
+ }
713
+
714
+ function prepareCharts()
715
+ {
716
+ $chartXtParams = array(
717
+ "id" => $this->id,
718
+ // it shows if chart show details
719
+ "chartPreview" => $this->mode !== CHART_SIMPLE && $this->mode != CHART_DASHBOARD,
720
+ "stateLink" => $this->getStateUrlParams()
721
+ );
722
+
723
+ if( $this->dashTName && $this->mode == CHART_DASHBOARD )
724
+ {
725
+ $chartXtParams["dash"] = true;
726
+ $chartXtParams["dashTName"] = $this->dashTName;
727
+ $chartXtParams["dashElementName"] = $this->dashElementName;
728
+ $chartXtParams["dashPage"] = $this->dashPage;
729
+ }
730
+
731
+ $this->xt->assign_function("chart", "xt_showpdchart", $chartXtParams);
732
+ }
733
+
734
+ public static function readChartModeFromRequest()
735
+ {
736
+ $mode = postvalue("mode");
737
+ if( $mode == "listdetails" )
738
+ return CHART_DETAILS;
739
+ elseif( $mode == "listdetailspopup" )
740
+ return CHART_POPUPDETAILS;
741
+ elseif( $mode == "dashchart" )
742
+ return CHART_DASHBOARD;
743
+ elseif( $mode == "dashdetails" )
744
+ return CHART_DASHDETAILS;
745
+ else
746
+ return CHART_SIMPLE;
747
+ }
748
+ }
749
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
750
  ?>
php/classes/chartpage_master.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  /**
3
  * Class for list page with mode simple
@@ -69,3 +70,76 @@ class ChartPage_Master extends ChartPage
69
  }
70
 
71
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <<<<<<< HEAD
2
  <?php
3
  /**
4
  * Class for list page with mode simple
 
70
  }
71
 
72
  ?>
73
+ =======
74
+ <?php
75
+ /**
76
+ * Class for list page with mode simple
77
+ *
78
+ */
79
+ class ChartPage_Master extends ChartPage
80
+ {
81
+ /**
82
+ * Constructor, set initial params
83
+ *
84
+ * @param array $params
85
+ */
86
+ function __construct(&$params)
87
+ {
88
+ // call parent constructor
89
+ parent::__construct($params);
90
+ }
91
+
92
+ public function getMasterHeading()
93
+ {
94
+ $this->xt->assign( "masterlist_title", true );
95
+ return $this->xt->fetch_loaded( "masterlist_title" );
96
+ }
97
+
98
+ public function preparePage()
99
+ {
100
+ if( !$this->masterRecordData || !$this->masterRecordData )
101
+ return;
102
+
103
+ $this->xt->assign("chart_block", true);
104
+ $this->assignChartElement();
105
+
106
+ $this->xt->assign("pagetitlelabel", $this->getPageTitle( $this->pageType, GoodFieldName($this->tName), $this->masterRecordData ));
107
+
108
+ $tKeys = $this->pSet->getTableKeys();
109
+ $keylink = "";
110
+
111
+
112
+ for($i = 0; $i < count($tKeys); $i ++) {
113
+ $keylink.= "&key".($i + 1)."=".runner_htmlspecialchars(rawurlencode(@$this->masterRecordData[$tKeys[$i]]));
114
+ }
115
+
116
+ $fields = $this->pSet->getMasterListFields();
117
+ $fields = array_merge( $fields, $tKeys);
118
+ foreach( $fields as $f )
119
+ {
120
+ $fieldClassStr = $this->fieldClass($f);
121
+ $this->xt->assign( GoodFieldName( $f ) . "_mastervalue", "<span class='". $fieldClassStr ."'>".$this->showDBValue( $f, $this->masterRecordData, $keylink)."</span>");
122
+ $this->xt->assign( GoodFieldName( $f ) . "_class", $fieldClassStr); // add class for field header as field value
123
+ }
124
+
125
+ if( $this->pageLayout )
126
+ $this->xt->assign("pageattrs", 'class="'.$this->pageLayout->style." page-".$this->pageLayout->name.'"');
127
+
128
+ if( $this->pageLayout )
129
+ $this->xt->assign("pageattrs", 'class="'.$this->pageLayout->style." page-".$this->pageLayout->name.'"');
130
+ }
131
+
132
+ public function showMaster( $params )
133
+ {
134
+ if( !$this->masterRecordData || !$this->masterRecordData )
135
+ return;
136
+
137
+ $this->xt->load_template( $this->templatefile );
138
+
139
+ $this->xt->assign( "masterlist_title", false );
140
+ $this->xt->display_loaded();
141
+ }
142
+ }
143
+
144
+ ?>
145
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
php/classes/charts.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class Chart
3
  {
@@ -2062,4 +2063,2070 @@ class Chart_Ohlc extends Chart
2062
  );
2063
  }
2064
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2065
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class Chart
4
  {
 
2063
  );
2064
  }
2065
  }
2066
+ =======
2067
+ <?php
2068
+ class Chart
2069
+ {
2070
+ protected $header;
2071
+ protected $footer;
2072
+
2073
+ protected $y_axis_label;
2074
+
2075
+ protected $strLabel;
2076
+
2077
+ protected $arrDataLabels = array();
2078
+ protected $arrDataSeries = array();
2079
+
2080
+ protected $chrt_array = array();
2081
+ public $webchart;
2082
+ protected $cname;
2083
+
2084
+ protected $table_type;
2085
+
2086
+ protected $cipherer = null;
2087
+ protected $pSet = null;
2088
+ protected $searchClauseObj = null;
2089
+
2090
+ protected $sessionPrefix = "";
2091
+
2092
+ protected $detailTablesData = array();
2093
+
2094
+ protected $pageId;
2095
+
2096
+ /**
2097
+ * A flag helping to detect if to apply
2098
+ * 'details' functionality to the chart
2099
+ */
2100
+ protected $showDetails = true;
2101
+
2102
+ /**
2103
+ * Flag if the chart in master or details preview mode
2104
+ * @type Boolean
2105
+ */
2106
+ protected $chartPreview = false;
2107
+
2108
+ /**
2109
+ * It indicates if chart is shown on a dashboard
2110
+ */
2111
+ protected $dashChart = false;
2112
+
2113
+ /**
2114
+ * It indicates if first point selected
2115
+ */
2116
+ protected $dashChartFirstPointSelected = false;
2117
+
2118
+ protected $detailMasterKeys = "";
2119
+
2120
+ /**
2121
+ * Dashboard table name
2122
+ * It's set up if chart is shown on a dashboard only
2123
+ */
2124
+ protected $dashTName = "";
2125
+
2126
+ /**
2127
+ * Dashboard element name
2128
+ * It's set up if chart is shown on a dashboard only
2129
+ */
2130
+ protected $dashElementName = "";
2131
+
2132
+ /**
2133
+ * @type Connection
2134
+ */
2135
+ protected $connection;
2136
+
2137
+ /**
2138
+ *
2139
+ */
2140
+ protected $_2d;
2141
+
2142
+ /**
2143
+ *
2144
+ */
2145
+ protected $noRecordsFound = false;
2146
+
2147
+ /**
2148
+ *
2149
+ */
2150
+ protected $singleSeries = false;
2151
+
2152
+ protected $masterKeysReq;
2153
+ protected $masterTable;
2154
+
2155
+ /**
2156
+ * DataSource
2157
+ */
2158
+ protected $dataSource = null;
2159
+ protected $tName = "";
2160
+
2161
+
2162
+ function __construct( &$ch_array, $param )
2163
+ {
2164
+ global $strTableName;
2165
+
2166
+ $this->webchart = $param["webchart"];
2167
+
2168
+ if( $this->webchart )
2169
+ $this->chrt_array = Convert_Old_Chart($ch_array);
2170
+ else
2171
+ $this->chrt_array = $ch_array;
2172
+
2173
+ $this->tName = $this->chrt_array['tables'][0];
2174
+
2175
+ // #10461, $this->setConnection(); needs to be called after value is assigned to $this->webchart
2176
+ $this->setConnection();
2177
+
2178
+ $this->pSet = new ProjectSettings( $this->tName, PAGE_CHART );
2179
+ $this->showDetails = $param['showDetails'];
2180
+ if( $this->showDetails )
2181
+ {
2182
+ $this->detailTablesData = $this->pSet->getDetailTablesArr();
2183
+ for($i = 0; $i < count($this->detailTablesData); $i ++)
2184
+ {
2185
+ $strPerm = GetUserPermissions($this->detailTablesData[$i]['dDataSourceTable']);
2186
+ if ( strpos($strPerm, "S") === false )
2187
+ unset($this->detailTablesData[$i]);
2188
+ }
2189
+ }
2190
+
2191
+ $this->table_type = $this->chrt_array["table_type"];
2192
+ if( !$this->table_type )
2193
+ $this->table_type = "project";
2194
+
2195
+ if( $this->table_type == "project" ) {
2196
+ // project table
2197
+ $this->dataSource = getDataSource( $this->tName, $this->pSet, $this->connection );
2198
+ } else {
2199
+ // db-table-based webchart
2200
+ $this->dataSource = getWebDataSource( $this->chrt_array );
2201
+ }
2202
+
2203
+ $this->pageId = $param["pageId"];
2204
+ $this->chrt_array["appearance"]["autoupdate"] = false;
2205
+
2206
+
2207
+ $this->cname = $param["cname"];
2208
+
2209
+ $this->sessionPrefix = $this->chrt_array['tables'][0];
2210
+
2211
+ $this->masterTable = $param["masterTable"];
2212
+ $this->masterKeysReq = $param["masterKeysReq"];
2213
+
2214
+ // true if chart has master
2215
+ $this->chartPreview = $param["chartPreview"];
2216
+ $this->dashChart = $param["dashChart"];
2217
+
2218
+ if( $this->dashChart )
2219
+ {
2220
+ $this->dashTName = $param["dashTName"];
2221
+ $this->dashElementName = $param["dashElementName"];
2222
+ $this->sessionPrefix = $this->dashTName."_".$this->sessionPrefix;
2223
+ }
2224
+
2225
+ if( !$this->webchart && !$this->chartPreview && isset( $_SESSION[ $this->sessionPrefix.'_advsearch' ] ) )
2226
+ $this->searchClauseObj = SearchClause::UnserializeObject( $_SESSION[ $this->sessionPrefix.'_advsearch' ] );
2227
+
2228
+ if( $this->searchClauseObj )
2229
+ RunnerContext::pushSearchContext( $this->searchClauseObj );
2230
+
2231
+ if( $this->isProjectDB() ) {
2232
+ $this->cipherer = new RunnerCipherer( $this->tName );
2233
+ }
2234
+
2235
+ $this->setBasicChartProp();
2236
+
2237
+ if( tableEventExists("UpdateChartSettings", $strTableName) )
2238
+ {
2239
+ $eventObj = getEventObject( $strTableName );
2240
+ $eventObj->UpdateChartSettings( $this );
2241
+ }
2242
+ }
2243
+
2244
+ /**
2245
+ * @param Array params
2246
+ */
2247
+ protected function setSpecParams( $params )
2248
+ {
2249
+ if( $params['name'] == "" )
2250
+ return;
2251
+
2252
+ if( $this->table_type != "db" )
2253
+ $this->arrDataSeries[] = $params['agr_func'] ? $params['label'] : $params['name'];
2254
+ else {
2255
+ $this->arrDataSeries[] = $params['table']."_".$params['name'];
2256
+ // $this->arrDataSeries[] = $params['name'];
2257
+ }
2258
+ }
2259
+
2260
+ /**
2261
+ * @param Array params
2262
+ * @param String gTableName
2263
+ */
2264
+ protected function setDataLabels( $params, $gTableName )
2265
+ {
2266
+ $chartType = $this->chrt_array["chart_type"]["type"];
2267
+ if( $this->table_type == "project" && !$this->webchart )
2268
+ {
2269
+ if( $chartType != "candlestick" && $chartType != "ohlc" )
2270
+ $this->arrDataLabels[] = GetFieldLabel( $gTableName, GoodFieldName($params['name']) );
2271
+ else
2272
+ $this->arrDataLabels[] = GetFieldLabel( $gTableName, GoodFieldName($params['ohlcOpen']) ) ;
2273
+ }
2274
+ else
2275
+ {
2276
+ if( !$params['label'] )
2277
+ {
2278
+ if( $chartType != "candlestick" && $chartType != "ohlc" )
2279
+ $this->arrDataLabels[] = $params['name'];
2280
+ else
2281
+ $this->arrDataLabels[] = $params['ohlcOpen'];
2282
+ }
2283
+ else
2284
+ $this->arrDataLabels[] = $params['label'];
2285
+ }
2286
+ }
2287
+
2288
+ /**
2289
+ *
2290
+ */
2291
+ protected function setBasicChartProp()
2292
+ {
2293
+ $this->header = $this->chrt_array['appearance']['head'];
2294
+ $this->header = $this->header ? $this->header : '';
2295
+
2296
+ $this->footer = $this->chrt_array['appearance']['foot'];
2297
+ $this->footer = $this->footer ? $this->footer : '';
2298
+
2299
+ for ( $i = 0; $i<count($this->chrt_array['parameters']) - 1; $i++)
2300
+ {
2301
+ $this->setSpecParams( $this->chrt_array['parameters'][$i] );
2302
+ $this->setDataLabels( $this->chrt_array['parameters'][$i], GoodFieldName( $this->chrt_array['tables'][0] ) );
2303
+ }
2304
+
2305
+ if( $this->chrt_array["chart_type"]["type"] != "gauge" )
2306
+ {
2307
+ $chartParams = $this->chrt_array['parameters'];
2308
+ $params = $chartParams[ count($chartParams) - 1 ];
2309
+
2310
+ if( $this->table_type != "db" )
2311
+ $this->strLabel = $params['name'];
2312
+ else {
2313
+ // $this->strLabel = $params['name'];
2314
+ $this->strLabel = $params['agr_func'] ? $params['agr_func']."_".$params['table']."_".$params['name']: $params['table']."_".$params['name'];
2315
+ }
2316
+ }
2317
+
2318
+ if( count( $this->arrDataLabels ) == 1 )
2319
+ $this->y_axis_label = $this->arrDataLabels[0];
2320
+ else
2321
+ $this->y_axis_label = $this->chrt_array['appearance']['y_axis_label'];
2322
+ }
2323
+
2324
+
2325
+ protected function getMasterCondition() {
2326
+ if( $this->dashChart )
2327
+ return null;
2328
+
2329
+ $detailKeysByM = $this->pSet->getDetailKeysByMasterTable( $this->masterTable );
2330
+ if( !$detailKeysByM )
2331
+ return null;
2332
+
2333
+ $conditions = array();
2334
+ for( $i = 0; $i < count( $detailKeysByM ); ++$i ) {
2335
+ $conditions[] = DataCondition::FieldEquals( $detailKeysByM[ $i ], $this->masterKeysReq[ $i + 1 ] );
2336
+ }
2337
+
2338
+ return DataCondition::_And( $conditions );
2339
+ }
2340
+
2341
+ /**
2342
+ * Get datasource command
2343
+ */
2344
+ public function getSubsetDataCommand( $ignoreFilterField = "" ) {
2345
+ $dc = new DsCommand();
2346
+
2347
+ $dc->filter = DataCondition::_And( array(
2348
+ Security::SelectCondition( "S", $this->pSet ),
2349
+ $this->getMasterCondition()
2350
+ ));
2351
+
2352
+ if( !$this->chartPreview && $this->searchClauseObj ) {
2353
+ $search = $this->searchClauseObj->getSearchDataCondition();
2354
+ $filter = $this->searchClauseObj->getFilterCondition( $this->pSet );
2355
+
2356
+ $dc->filter = DataCondition::_And( array( $dc->filter, $search, $filter ) );
2357
+ }
2358
+
2359
+ // where tabs
2360
+ if( $_SESSION[ $this->sessionPrefix . "_chartTabWhere" ] ) {
2361
+ $dc->filter = DataCondition::_And( array(
2362
+ $dc->filter,
2363
+ DataCondition::SQLCondition( $_SESSION[ $this->sessionPrefix . "_chartTabWhere" ] )
2364
+ ));
2365
+ }
2366
+
2367
+ require_once( getabspath('classes/orderclause.php') );
2368
+ $orderObject = new OrderClause( $this->pSet, $this->cipherer, $this->sessionPrefix, $this->connection );
2369
+ $dc->order = $orderObject->getOrderFields();
2370
+
2371
+ if( $this->pSet->getRecordsLimit() )
2372
+ $dc->reccount = $this->pSet->getRecordsLimit();
2373
+
2374
+ if( $this->pSet->groupChart() )
2375
+ $dc->totals = $this->getGroupChartCommandTotals();
2376
+
2377
+ return $dc;
2378
+ }
2379
+
2380
+ /**
2381
+ * Get ds command totals
2382
+ * total fields appear in the same order
2383
+ they do in an original orderby clause
2384
+ * @return array
2385
+ */
2386
+ protected function getGroupChartCommandTotals() {
2387
+ $totals = array();
2388
+ // label field
2389
+ $totals[] = array(
2390
+ "alias" => $this->pSet->chartLabelField(),
2391
+ "field" => $this->pSet->chartLabelField(),
2392
+ "modifier" => $this->pSet->chartLabelInterval()
2393
+ );
2394
+
2395
+ $series = $this->pSet->chartSeries();
2396
+ foreach( $series as $s ) {
2397
+ $totals[] = array(
2398
+ "alias" => $s["field"],
2399
+ "field" => $s["field"],
2400
+ "total" => strtolower( $s["total"] )
2401
+ );
2402
+ }
2403
+
2404
+ $orderInfo = $this->pSet->getOrderIndexes();
2405
+ if( !$orderInfo )
2406
+ return $totals;
2407
+
2408
+ $fields = array();
2409
+ foreach( $orderInfo as $o ) {
2410
+ $fields[] = $this->pSet->GetFieldByIndex( $o[0] );
2411
+ }
2412
+
2413
+ foreach( $totals as $idx => $t ) {
2414
+ if( !in_array( $t["field"], $fields ) )
2415
+ $fields[] = $t["field"];
2416
+
2417
+ foreach( $orderInfo as $o ) {
2418
+ $fieldIdx = $this->pSet->getFieldIndex( $t["field"] );
2419
+ if( $fieldIdx == $o[0] ) {
2420
+ $totals[ $idx ]["direction"] = $o[1];
2421
+ break;
2422
+ }
2423
+ }
2424
+ }
2425
+
2426
+ $_totals = array();
2427
+ foreach( $fields as $field ) {
2428
+ foreach( $totals as $t ) {
2429
+ if( $t["field"] == $field ) {
2430
+ $_totals[] = $t;
2431
+ }
2432
+ }
2433
+ }
2434
+
2435
+ return $_totals;
2436
+ }
2437
+
2438
+ /**
2439
+ * Check for a web chart if it's based on the project table
2440
+ * @return Boolean
2441
+ */
2442
+ protected function isProjectDB()
2443
+ {
2444
+ if( !$this->webchart )
2445
+ return true;
2446
+
2447
+ if("public.kbarticles" == $this->chrt_array['tables'][0])
2448
+ return true;
2449
+ if("public.kbcategories" == $this->chrt_array['tables'][0])
2450
+ return true;
2451
+ if("public.kbcomments" == $this->chrt_array['tables'][0])
2452
+ return true;
2453
+ if("public.kbusers" == $this->chrt_array['tables'][0])
2454
+ return true;
2455
+ if("public.kbarticles" == $this->chrt_array['tables'][0])
2456
+ return true;
2457
+ if("public.faicons" == $this->chrt_array['tables'][0])
2458
+ return true;
2459
+ if("public.kbcomments" == $this->chrt_array['tables'][0])
2460
+ return true;
2461
+ if("public.fasis_chat_history" == $this->chrt_array['tables'][0])
2462
+ return true;
2463
+ if("public.diamondprice" == $this->chrt_array['tables'][0])
2464
+ return true;
2465
+ if("public.products" == $this->chrt_array['tables'][0])
2466
+ return true;
2467
+ if("public.items" == $this->chrt_array['tables'][0])
2468
+ return true;
2469
+ if("public.appointments" == $this->chrt_array['tables'][0])
2470
+ return true;
2471
+ if("public.chat_history" == $this->chrt_array['tables'][0])
2472
+ return true;
2473
+ if("public.chat_users" == $this->chrt_array['tables'][0])
2474
+ return true;
2475
+ if("public.chat_settings" == $this->chrt_array['tables'][0])
2476
+ return true;
2477
+ if("public.chat_files" == $this->chrt_array['tables'][0])
2478
+ return true;
2479
+ if("public.chat_groups" == $this->chrt_array['tables'][0])
2480
+ return true;
2481
+ if("public.chat_peopletype" == $this->chrt_array['tables'][0])
2482
+ return true;
2483
+ if("public.chat_timezone" == $this->chrt_array['tables'][0])
2484
+ return true;
2485
+ if("public.chat_files" == $this->chrt_array['tables'][0])
2486
+ return true;
2487
+ if("public.chat_groups" == $this->chrt_array['tables'][0])
2488
+ return true;
2489
+ if("public.chat_history" == $this->chrt_array['tables'][0])
2490
+ return true;
2491
+ if("public.chat_peopletype" == $this->chrt_array['tables'][0])
2492
+ return true;
2493
+ if("public.chat_settings" == $this->chrt_array['tables'][0])
2494
+ return true;
2495
+ if("public.identity" == $this->chrt_array['tables'][0])
2496
+ return true;
2497
+ if("public.dataset_info" == $this->chrt_array['tables'][0])
2498
+ return true;
2499
+ if("public.KnowledgeBase1ugrights" == $this->chrt_array['tables'][0])
2500
+ return true;
2501
+ if("public.KnowledgeBase1ugmembers" == $this->chrt_array['tables'][0])
2502
+ return true;
2503
+ if("public.kbusers" == $this->chrt_array['tables'][0])
2504
+ return true;
2505
+ if("public.history" == $this->chrt_array['tables'][0])
2506
+ return true;
2507
+ if("public.zendesk__dataszz" == $this->chrt_array['tables'][0])
2508
+ return true;
2509
+ if("public.view_zendesk" == $this->chrt_array['tables'][0])
2510
+ return true;
2511
+ if("public.prompts" == $this->chrt_array['tables'][0])
2512
+ return true;
2513
+ if("public.view_faisis_chat_history" == $this->chrt_array['tables'][0])
2514
+ return true;
2515
+ if("public.server_setting" == $this->chrt_array['tables'][0])
2516
+ return true;
2517
+ return false;
2518
+ }
2519
+
2520
+ /**
2521
+ * Set the 'connection' property #9875
2522
+ */
2523
+ protected function setConnection()
2524
+ {
2525
+ global $cman;
2526
+
2527
+ if($this->isProjectDB())
2528
+ $this->connection = $cman->byTable( $this->tName );
2529
+ else
2530
+ $this->connection = $cman->getDefault();
2531
+ }
2532
+
2533
+ public function setFooter($name)
2534
+ {
2535
+ $this->footer = $name;
2536
+ }
2537
+
2538
+ public function getFooter()
2539
+ {
2540
+ return $this->footer;
2541
+ }
2542
+
2543
+ public function setHeader($name)
2544
+ {
2545
+ $this->header = $name;
2546
+ }
2547
+
2548
+ public function getHeader()
2549
+ {
2550
+ return $this->header;
2551
+ }
2552
+
2553
+ public function setLabelField($name)
2554
+ {
2555
+ $this->strLabel = $name;
2556
+ }
2557
+
2558
+ public function getLabelField()
2559
+ {
2560
+ return $this->strLabel;
2561
+ }
2562
+
2563
+ /**
2564
+ * @return String
2565
+ */
2566
+ protected function getDetailedTooltipMessage()
2567
+ {
2568
+ if( !$this->showDetails || !$this->detailTablesData )
2569
+ return "";
2570
+
2571
+ $showClickHere = true;
2572
+
2573
+ if( $this->dashChart )
2574
+ {
2575
+ $showClickHere = false;
2576
+
2577
+ $pDSet = new ProjectSettings( $this->dashTName );
2578
+ $arrDElem = $pDSet->getDashboardElements();
2579
+ foreach($arrDElem as $elem)
2580
+ {
2581
+ if( $elem["table"] == $this->chrt_array['tables'][0] && !!$elem["details"] )
2582
+ $showClickHere = true;
2583
+ }
2584
+ }
2585
+
2586
+ if( $showClickHere )
2587
+ {
2588
+ $tableCaption = GetTableCaption( $this->detailTablesData[0]['dDataSourceTable'] );
2589
+ $tableCaption = $tableCaption ? $tableCaption : $this->detailTablesData[0]['dDataSourceTable'];
2590
+
2591
+ return "\nClick here to see ".$tableCaption." details";
2592
+ }
2593
+
2594
+ return "";
2595
+ }
2596
+
2597
+ /**
2598
+ * @return String
2599
+ */
2600
+ protected function getNoDataMessage()
2601
+ {
2602
+ if( !$this->noRecordsFound )
2603
+ return "";
2604
+
2605
+ if( !$this->searchClauseObj )
2606
+ return "No data yet.";
2607
+
2608
+ if( $this->searchClauseObj->isSearchFunctionalityActivated() )
2609
+ return "No results found.";
2610
+
2611
+ return "No data yet.";
2612
+ }
2613
+
2614
+ /**
2615
+ *
2616
+ */
2617
+ public function write()
2618
+ {
2619
+ $data = array();
2620
+ $chart = array();
2621
+
2622
+ $this->setTypeSpecChartSettings( $chart );
2623
+ if ( @$this->chrt_array["appearance"]["color71"] != "" || @$this->chrt_array["appearance"]["color91"] != "" )
2624
+ $chart["background"] = array();
2625
+ if ( @$this->chrt_array["appearance"]["color71"] != "" )
2626
+ $chart["background"]["fill"] = "#".$this->chrt_array["appearance"]["color71"];
2627
+
2628
+ if ( @$this->chrt_array["appearance"]["color91"] != "" )
2629
+ $chart["background"]["stroke"] = "#".$this->chrt_array["appearance"]["color91"];
2630
+
2631
+ if( $this->noRecordsFound )
2632
+ {
2633
+ $data["noDataMessage"] = $this->getNoDataMessage();
2634
+ echo my_json_encode( $data );
2635
+ return;
2636
+ }
2637
+
2638
+ // animation
2639
+ if( $this->chrt_array["appearance"]["sanim"] == "true" && $this->chrt_array["appearance"]["autoupdate"] != "true" ) // update?
2640
+ $chart["animation"] = array("enabled" => "true", "duration" => 1000);
2641
+
2642
+ // legend
2643
+ if( $this->chrt_array['appearance']['slegend'] == "true" && !$this->chartPreview )
2644
+ $chart["legend"] = array("enabled" => "true");
2645
+ else
2646
+ $chart["legend"] = array("enabled" => false);
2647
+
2648
+ $chart["credits"] = false;
2649
+ // title/header
2650
+ $chart["title"] = array("enabled" => "true", "text" => $this->header);
2651
+ if ( @$this->chrt_array["appearance"]["color101"] != "" )
2652
+ $chart["title"]["fontColor"] = "#".$this->chrt_array["appearance"]["color101"];
2653
+
2654
+ // assign and display
2655
+ $data["chart"] = $chart;
2656
+ echo my_json_encode( $data );
2657
+ }
2658
+
2659
+ /**
2660
+ * A stub
2661
+ * @param &Array chart
2662
+ */
2663
+ protected function setTypeSpecChartSettings( &$chart )
2664
+ {
2665
+ }
2666
+
2667
+ /**
2668
+ * @return Array
2669
+ */
2670
+ protected function getGrids()
2671
+ {
2672
+ $grids = array();
2673
+
2674
+ if($this->chrt_array["appearance"]["sgrid"] == "true")
2675
+ {
2676
+ $stroke = @$this->chrt_array["appearance"]["color121"] != "" ? "#" . $this->chrt_array["appearance"]["color121"] : "#ddd";
2677
+
2678
+ $grid0 = array(
2679
+ "enabled" => true,
2680
+ "drawLastLine" => false,
2681
+ "stroke" => $stroke,
2682
+ "scale" => 0,
2683
+ "axis" => 0
2684
+ );
2685
+
2686
+ if ( @$this->chrt_array["appearance"]["color81"] != "" )
2687
+ {
2688
+ $dataPlotBackgroundColor = "#" . $this->chrt_array["appearance"]["color81"];
2689
+ $grid0["oddFill"] = $dataPlotBackgroundColor;
2690
+ $grid0["evenFill"] = $dataPlotBackgroundColor;
2691
+ }
2692
+
2693
+ $grids[] = $grid0;
2694
+
2695
+ $grids[] = array(
2696
+ "enabled" => true,
2697
+ "drawLastLine" => false,
2698
+ "stroke" => $stroke,
2699
+ "axis" => 1
2700
+ );
2701
+ }
2702
+
2703
+ return $grids;
2704
+ }
2705
+
2706
+ /**
2707
+ * @param String fieldName
2708
+ * @param Array data
2709
+ * @return String
2710
+ */
2711
+ protected function labelFormat($fieldName, $data, $truncated = true)
2712
+ {
2713
+ if( !$fieldName )
2714
+ return "";
2715
+
2716
+ if( $this->table_type == "db" && !!$this->chrt_array['customLabels'] )
2717
+ $fieldName = $this->chrt_array['customLabels'][ $fieldName ];
2718
+
2719
+ include_once getabspath('classes/controls/ViewControlsContainer.php');
2720
+ $viewControls = new ViewControlsContainer( $this->pSet, PAGE_CHART );
2721
+ if( $this->pSet->groupChart() ) {
2722
+ $interval = $this->pSet->chartLabelInterval();
2723
+ if( $interval ) {
2724
+ $fType = $this->pSet->getFieldType( $fieldName );
2725
+ return RunnerPage::formatGroupValueStatic( $fieldName, $interval, $data[ $fieldName ], $this->pSet, $viewControls, false );
2726
+ }
2727
+ }
2728
+ $value = $viewControls->showDBValue( $fieldName, $data, "", "", false );
2729
+
2730
+ if( $truncated && strlen($value) > 50 )
2731
+ $value = runner_substr($value, 0, 47)."...";
2732
+
2733
+ return $value;
2734
+ }
2735
+
2736
+ protected function beforeQueryEvent( &$dc ) {
2737
+ $eventsObject = getEventObject( $this->pSet->getTableName() );
2738
+
2739
+ // ASP conversion requires these checks be separate
2740
+ if( !$eventsObject )
2741
+ return;
2742
+ if( !$eventsObject->exists("BeforeQueryChart") ) {
2743
+ return;
2744
+ }
2745
+
2746
+ $prep = $this->dataSource->prepareSQL( $dc );
2747
+ $where = $prep["where"];
2748
+ $sql = $prep["sql"];
2749
+ $order = $prep["order"];
2750
+
2751
+ // call Before Query event
2752
+ $eventsObject->BeforeQueryChart( $sql, $where, $order );
2753
+
2754
+ if( $sql != $prep["sql"] )
2755
+ $this->dataSource->overrideSQL( $dc, $sql );
2756
+ else {
2757
+ if( $where != $prep["where"] )
2758
+ $this->dataSource->overrideWhere( $dc, $where );
2759
+ if( $order != $prep["order"] )
2760
+ $this->dataSource->overrideOrder( $dc, $order );
2761
+ }
2762
+ }
2763
+
2764
+ /**
2765
+ * @return Array
2766
+ */
2767
+ public function get_data()
2768
+ {
2769
+ $data = array();
2770
+ $clickdata = array();
2771
+ for ( $i = 0; $i < count($this->arrDataSeries); $i++ )
2772
+ {
2773
+ $data[$i] = array();
2774
+ $clickdata[$i] = array();
2775
+ }
2776
+
2777
+ $dc = $this->getSubsetDataCommand();
2778
+ $this->beforeQueryEvent( $dc );
2779
+
2780
+ if( $this->pSet->groupChart() ) {
2781
+ $rs = $this->dataSource->getTotals( $dc );
2782
+ } else {
2783
+ $rs = $this->dataSource->getList( $dc );
2784
+ }
2785
+ if( !$rs ) {
2786
+ showError( $this->dataSource->lastError() );
2787
+ }
2788
+
2789
+ $row = $rs->fetchAssoc();
2790
+ if( $this->cipherer )
2791
+ $row = $this->cipherer->DecryptFetchedArray( $row );
2792
+
2793
+ if( !$row )
2794
+ $this->noRecordsFound = true;
2795
+
2796
+ while ($row)
2797
+ {
2798
+ for ( $i = 0; $i < count($this->arrDataSeries); $i++ )
2799
+ {
2800
+ $data[$i][] = $this->getPoint($i, $row);
2801
+
2802
+ $strLabelFormat = $this->labelFormat( $this->strLabel, $row );
2803
+ $clickdata[$i][] = $this->getActions( $row , $this->arrDataSeries[$i], $strLabelFormat );
2804
+ }
2805
+
2806
+ $row = $rs->fetchAssoc();
2807
+ if( $this->cipherer )
2808
+ $row = $this->cipherer->DecryptFetchedArray( $row );
2809
+ }
2810
+
2811
+ $series = array();
2812
+ for ( $i = 0; $i < count($this->arrDataSeries); $i++ )
2813
+ {
2814
+ $series[] = $this->getSeriesData( $this->arrDataLabels[$i], $data[$i], $clickdata[$i], $i, count($this->arrDataSeries) > 1 );
2815
+ }
2816
+
2817
+ return $series;
2818
+ }
2819
+
2820
+ /**
2821
+ * @param Number seriesNumber
2822
+ * @param Array row
2823
+ * @return Array
2824
+ */
2825
+ protected function getPoint( $seriesNumber, $row ) {
2826
+ $strLabelFormat = $this->labelFormat( $this->strLabel, $row );
2827
+
2828
+ include_once getabspath('classes/controls/ViewControlsContainer.php');
2829
+ $viewControls = new ViewControlsContainer( $this->pSet, PAGE_CHART );
2830
+
2831
+ if( $this->table_type != "db" || !$this->chrt_array['customLabels'] ) {
2832
+ $strDataSeries = $row[ $this->arrDataSeries[ $seriesNumber ] ];
2833
+ $fieldName = $this->arrDataSeries[ $seriesNumber ];
2834
+ $formattedValue = $viewControls->showDBValue( $fieldName, $row, "", "", false );
2835
+ } else {
2836
+ $strDataSeries = $row[ $this->chrt_array['customLabels'][ $this->arrDataSeries[ $seriesNumber ] ] ];
2837
+ $fieldName = $this->chrt_array['customLabels'][ $this->arrDataSeries[ $seriesNumber ] ];
2838
+ $formattedValue = $viewControls->showDBValue( $fieldName, $row, "", "", false );
2839
+ }
2840
+
2841
+ return array(
2842
+ "x" => $strLabelFormat,
2843
+ "value" => (double)str_replace(",", ".", $strDataSeries),
2844
+ "viewAsValue" => $formattedValue
2845
+ );
2846
+ }
2847
+
2848
+ /**
2849
+ * @param String name
2850
+ * @param Array pointsData
2851
+ * @param Array clickData
2852
+ * @param Number seriesNumber
2853
+ * @param Boolean multiSeries (optional)
2854
+ * @return Array
2855
+ */
2856
+ protected function getSeriesData( $name, $pointsData, $clickData, $seriesNumber, $multiSeries = true )
2857
+ {
2858
+ $data = array(
2859
+ "name" => $name,
2860
+ "data" => $pointsData,
2861
+ "xScale" => "0",
2862
+ "yScale" => "1",
2863
+ "seriesType" => $this->getSeriesType($seriesNumber)
2864
+ );
2865
+
2866
+ $data["labels"] = array(
2867
+ "enabled" => $this->chrt_array["appearance"]["sval"] == "true",
2868
+ "format" => "{%viewAsValue}"
2869
+ );
2870
+
2871
+ if ( @$this->chrt_array["appearance"]["color61"] != "" )
2872
+ $data["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color61"];
2873
+
2874
+ if( $clickData && $this->detailTablesData )
2875
+ $data["clickData"] = $clickData;
2876
+
2877
+ $data["tooltip"] = $this->getSeriesTooltip( $multiSeries );
2878
+
2879
+ return $data;
2880
+ }
2881
+
2882
+ /**
2883
+ * @param Boolean $multiSeries
2884
+ * @return Array
2885
+ */
2886
+ protected function getSeriesTooltip( $multiSeries ) {
2887
+ return array(
2888
+ "enabled" => true,
2889
+ "format" => "{%seriesName}: {%viewAsValue}". $this->getDetailedTooltipMessage(),
2890
+ );
2891
+ }
2892
+
2893
+ /**
2894
+ * @return String
2895
+ */
2896
+ protected function getSeriesType($seriesNumber)
2897
+ {
2898
+ return "column";
2899
+ }
2900
+
2901
+ /**
2902
+ * @deprecated
2903
+ * @param String str
2904
+ * @return String
2905
+ */
2906
+ protected function chart_xmlencode($str)
2907
+ {
2908
+ return str_replace(array("&","<",">","\""),array("&amp;","&lt;","&gt;","&quot;"),$str);
2909
+ }
2910
+
2911
+ /**
2912
+ * Get a 'point click' action data
2913
+ * @param Array data
2914
+ * @param Number seriesId
2915
+ * @param Number pointId
2916
+ * @return Array
2917
+ */
2918
+ protected function getActions( $data, $seriesId, $pointId )
2919
+ {
2920
+ global $strTableName;
2921
+
2922
+ if( !$this->detailTablesData )
2923
+ return null;
2924
+
2925
+ if ( $this->dashChart )
2926
+ {
2927
+ $masterKeysArr = array();
2928
+ foreach ( $this->detailTablesData as $detailId => $detail )
2929
+ {
2930
+ foreach( $detail['masterKeys'] as $idx => $mk )
2931
+ {
2932
+ $masterKeysArr[ $detail['dDataSourceTable'] ] = array( 'masterkey'.($idx + 1) => $data[ $mk ] );
2933
+ }
2934
+ }
2935
+
2936
+ if (!$this->dashChartFirstPointSelected)
2937
+ {
2938
+ $this->dashChartFirstPointSelected = true;
2939
+ $this->detailMasterKeys = my_json_encode( $masterKeysArr );
2940
+ }
2941
+
2942
+ return array( "masterKeys" => $masterKeysArr, "seriesId" => $seriesId, "pointId" => $pointId );
2943
+ }
2944
+
2945
+ // The one detail table is allowed for a chart page only
2946
+ $detailTableData = $this->detailTablesData[0];
2947
+ $masterquery = "mastertable=".rawurlencode( $strTableName );
2948
+ foreach( $detailTableData['masterKeys'] as $idx => $mk )
2949
+ {
2950
+ $masterquery.= "&masterkey".($idx + 1)."=".rawurlencode( $data[ $mk ] );
2951
+ }
2952
+
2953
+ return array( "url" => GetTableLink( $detailTableData['dShortTable'], $detailTableData['dType'], $masterquery ) );
2954
+ }
2955
+
2956
+ protected function getLogarithm()
2957
+ {
2958
+ if( $this->chrt_array["appearance"]["slog"] == "true" )
2959
+ return true;
2960
+ return false;
2961
+ }
2962
+ }
2963
+
2964
+
2965
+ class Chart_Bar extends Chart
2966
+ {
2967
+ protected $stacked;
2968
+ protected $bar;
2969
+
2970
+ function __construct( &$ch_array, $param )
2971
+ {
2972
+ parent::__construct( $ch_array, $param );
2973
+
2974
+ $this->stacked = $param["stacked"];
2975
+ $this->_2d = $param["2d"];
2976
+ $this->bar = $param["bar"];
2977
+ }
2978
+
2979
+ /**
2980
+ * @return String
2981
+ */
2982
+ protected function getSeriesType($seriesNumber)
2983
+ {
2984
+ if($this->bar)
2985
+ return "bar";
2986
+ else
2987
+ return "column";
2988
+ }
2989
+
2990
+ /**
2991
+ * @param &Array chart
2992
+ */
2993
+ protected function setTypeSpecChartSettings( &$chart )
2994
+ {
2995
+ $chart["series"] = $this->get_data();
2996
+
2997
+ $chart["scales"] = $this->getScales();
2998
+ $chart["logarithm"] = parent::getLogarithm();
2999
+
3000
+ if( $this->bar )
3001
+ $chart["type"] = "bar";
3002
+ else
3003
+ $chart["type"] = "column";
3004
+
3005
+ if( !$this->_2d )
3006
+ $chart["type"] .= "-3d";
3007
+
3008
+ $chart["xScale"] = 0;
3009
+ $chart["yScale"] = 1;
3010
+
3011
+ // grid
3012
+ $chart["grids"] = $this->getGrids();
3013
+
3014
+
3015
+ // Y-axis label
3016
+ $chart["yAxes"] = array(
3017
+ array(
3018
+ "enabled" => "true",
3019
+ "title" => $this->y_axis_label
3020
+ ));
3021
+
3022
+ // X-axis label
3023
+ $chart["xAxes"] = array(
3024
+ array(
3025
+ "enabled" => "true",
3026
+ "title" => array( 'text' => $this->footer ),
3027
+ "labels" => array( "enabled" => $this->chrt_array["appearance"]["sname"] == "true" )
3028
+ ));
3029
+
3030
+ if ( @$this->chrt_array["appearance"]["color51"] != "" )
3031
+ $chart["xAxes"][0]["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color51"];
3032
+
3033
+ if ( @$this->chrt_array["appearance"]["color111"] != "" )
3034
+ $chart["xAxes"][0]["title"]["fontColor"] = "#".$this->chrt_array["appearance"]["color111"];
3035
+
3036
+ if ( @$this->chrt_array["appearance"]["color131"] != "" )
3037
+ $chart["xAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color131"];
3038
+
3039
+ if ( @$this->chrt_array["appearance"]["color141"] != "" )
3040
+ $chart["yAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color141"];
3041
+ }
3042
+
3043
+ /**
3044
+ * "scales"
3045
+ * @return Array
3046
+ */
3047
+ protected function getScales()
3048
+ {
3049
+ if($this->stacked || $this->chrt_array["appearance"]["slog"] == "true")
3050
+ {
3051
+ $arr = array();
3052
+ if( $this->stacked )
3053
+ $arr["stackMode"] = "value";
3054
+
3055
+ if( $this->chrt_array["appearance"]["slog"] == "true" )
3056
+ {
3057
+ $arr["logBase"] = 10;
3058
+ $arr["type"] = "log";
3059
+ };
3060
+
3061
+ return array(
3062
+ array("names" => array()),
3063
+ $arr
3064
+ );
3065
+ }
3066
+
3067
+ return array();
3068
+ }
3069
+ }
3070
+
3071
+ class Chart_Line extends Chart
3072
+ {
3073
+ protected $type_line;
3074
+
3075
+
3076
+ function __construct( &$ch_array, $param )
3077
+ {
3078
+ parent::__construct( $ch_array, $param );
3079
+
3080
+ $this->type_line = $param["type_line"];
3081
+ }
3082
+
3083
+ /**
3084
+ * @param &Array chart
3085
+ */
3086
+ protected function setTypeSpecChartSettings( &$chart )
3087
+ {
3088
+ $chart["series"] = $this->get_data();
3089
+ $chart["type"] = "line";
3090
+
3091
+ $chart["xScale"] = 0;
3092
+ $chart["yScale"] = 1;
3093
+ $chart["grids"] = $this->getGrids();
3094
+ $chart["logarithm"] = parent::getLogarithm();
3095
+ $chart["tooltip"] = array("displayMode" => "single");
3096
+
3097
+ $chart["yAxes"] = array(
3098
+ array( "enabled" => "true", "title" => $this->y_axis_label )
3099
+ );
3100
+
3101
+ $chart["xAxes"] = array(
3102
+ array(
3103
+ "enabled" => "true",
3104
+ "title" => array( 'text' => $this->footer ),
3105
+ "labels" => array( "enabled" => $this->chrt_array["appearance"]["sname"] == "true" )
3106
+ ));
3107
+
3108
+ if ( @$this->chrt_array["appearance"]["color51"] != "" )
3109
+ $chart["xAxes"][0]["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color51"];
3110
+
3111
+ if ( @$this->chrt_array["appearance"]["color111"] != "" )
3112
+ $chart["xAxes"][0]["title"]["fontColor"] = "#".$this->chrt_array["appearance"]["color111"];
3113
+
3114
+ if ( @$this->chrt_array["appearance"]["color131"] != "" )
3115
+ $chart["xAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color131"];
3116
+
3117
+ if ( @$this->chrt_array["appearance"]["color141"] != "" )
3118
+ $chart["yAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color141"];
3119
+ }
3120
+
3121
+ /**
3122
+ * @return String
3123
+ */
3124
+ protected function getSeriesType($seriesNumber)
3125
+ {
3126
+ switch( $this->type_line )
3127
+ {
3128
+ case "line":
3129
+ return "line";
3130
+ case "spline":
3131
+ return "spline";
3132
+ case "step_line":
3133
+ return "stepLine";
3134
+ default:
3135
+ return "line";
3136
+ }
3137
+ }
3138
+ }
3139
+
3140
+ class Chart_Area extends Chart
3141
+ {
3142
+ protected $stacked;
3143
+
3144
+
3145
+ function __construct( &$ch_array, $param )
3146
+ {
3147
+ parent::__construct( $ch_array, $param );
3148
+
3149
+ $this->stacked = $param["stacked"];
3150
+ }
3151
+
3152
+ /**
3153
+ * @param &Array chart
3154
+ */
3155
+ protected function setTypeSpecChartSettings( &$chart )
3156
+ {
3157
+ $chart["series"] = $this->get_data();
3158
+
3159
+ if( $this->stacked )
3160
+ $chart["scales"] = $this->getScales();
3161
+ $chart["type"] = "area";
3162
+ $chart["xScale"] = 0;
3163
+ $chart["yScale"] = 1;
3164
+ $chart["logarithm"] = parent::getLogarithm();
3165
+ $chart["grids"] = $this->getGrids();
3166
+
3167
+ $chart["tooltip"] = array("displayMode" => "single");
3168
+
3169
+ $chart["yAxes"] = array(
3170
+ array( "enabled" => "true", "title" => $this->y_axis_label )
3171
+ );
3172
+
3173
+ $chart["xAxes"] = array(
3174
+ array(
3175
+ "enabled" => "true",
3176
+ "title" => array( 'text' => $this->footer ),
3177
+ "labels" => array( "enabled" => $this->chrt_array["appearance"]["sname"] == "true" )
3178
+ ));
3179
+
3180
+ if ( @$this->chrt_array["appearance"]["color51"] != "" )
3181
+ $chart["xAxes"][0]["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color51"];
3182
+
3183
+ if ( @$this->chrt_array["appearance"]["color111"] != "" )
3184
+ $chart["xAxes"][0]["title"]["fontColor"] = "#".$this->chrt_array["appearance"]["color111"];
3185
+
3186
+ if ( @$this->chrt_array["appearance"]["color131"] != "" )
3187
+ $chart["xAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color131"];
3188
+
3189
+ if ( @$this->chrt_array["appearance"]["color141"] != "" )
3190
+ $chart["yAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color141"];
3191
+ }
3192
+
3193
+ /**
3194
+ * @return String
3195
+ */
3196
+ protected function getSeriesType($seriesNumber)
3197
+ {
3198
+ return "area";
3199
+ }
3200
+
3201
+ /**
3202
+ * "scales"
3203
+ * @return Array
3204
+ */
3205
+ protected function getScales()
3206
+ {
3207
+ if( $this->stacked )
3208
+ {
3209
+ $arr = array();
3210
+ $arr["stackMode"] = "value";
3211
+
3212
+ if( $this->chrt_array["appearance"]["sstacked"] == "true" )
3213
+ {
3214
+ $arr["stackMode"] = "percent";
3215
+ $arr["maximumGap"] = "10";
3216
+ $arr["maximum"] = "100";
3217
+ };
3218
+
3219
+ return array(
3220
+ array( "names"=> array() ),
3221
+ $arr
3222
+ );
3223
+ }
3224
+
3225
+ return array();
3226
+ }
3227
+ }
3228
+
3229
+ /**
3230
+ * A single series chart
3231
+ */
3232
+ class Chart_Pie extends Chart
3233
+ {
3234
+ protected $pie;
3235
+
3236
+
3237
+ function __construct( &$ch_array, $param )
3238
+ {
3239
+ parent::__construct( $ch_array, $param );
3240
+
3241
+ $this->pie = $param["pie"];
3242
+ $this->_2d = $param["2d"];
3243
+ $this->singleSeries = true;
3244
+ }
3245
+
3246
+ /**
3247
+ * @param &Array chart
3248
+ */
3249
+ protected function setTypeSpecChartSettings( &$chart )
3250
+ {
3251
+ $series = $this->get_data();
3252
+
3253
+ $chart["data"] = $series[0]["data"];
3254
+ $chart["clickData"] = $series[0]["clickData"];
3255
+ $chart["singleSeries"] = true;
3256
+ $chart["tooltip"] = $series[0]["tooltip"];
3257
+ $chart["logarithm"] = false;
3258
+ if( $this->_2d )
3259
+ $chart["type"] = "pie";
3260
+ else
3261
+ $chart["type"] = "pie-3d";
3262
+
3263
+ if( !$this->pie )
3264
+ $chart["innerRadius"] = "30%";
3265
+
3266
+ if( $this->chrt_array['appearance']['slegend'] == "true" && !$this->chartPreview )
3267
+ {
3268
+ $chart["legend"] = array("enabled" => "true");
3269
+ }
3270
+
3271
+ $chart["labels"] = array( "enabled" => $this->chrt_array["appearance"]["sval"] == "true" || $this->chrt_array["appearance"]["sname"] == "true" );
3272
+
3273
+ if ( @$this->chrt_array["appearance"]["color51"] != "" )
3274
+ {
3275
+ if ( $this->chrt_array["appearance"]["sval"] )
3276
+ {
3277
+ $chart["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color61"];
3278
+ }
3279
+ else if ( $this->chrt_array["appearance"]["sname"] )
3280
+ {
3281
+ $chart["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color51"];
3282
+ }
3283
+ }
3284
+
3285
+ }
3286
+ }
3287
+
3288
+ class Chart_Combined extends Chart
3289
+ {
3290
+ function __construct( &$ch_array, $param )
3291
+ {
3292
+ parent::__construct( $ch_array, $param );
3293
+ }
3294
+
3295
+ /**
3296
+ * @param &Array chart
3297
+ */
3298
+ protected function setTypeSpecChartSettings( &$chart )
3299
+ {
3300
+ $chart["series"] = $this->get_data();
3301
+ $chart["type"] = "column";
3302
+ $chart["logarithm"] = parent::getLogarithm();
3303
+ $chart["xScale"] = 0;
3304
+ $chart["yScale"] = 1;
3305
+ $chart["grids"] = $this->getGrids();
3306
+ $chart["yAxes"] = array(
3307
+ array( "enabled" => "true", "title" => $this->y_axis_label )
3308
+ );
3309
+
3310
+ $chart["xAxes"] = array(
3311
+ array(
3312
+ "enabled" => "true",
3313
+ "title" => array( 'text' => $this->footer ),
3314
+ "labels" => array( "enabled" => $this->chrt_array["appearance"]["sname"] == "true" )
3315
+ ));
3316
+
3317
+ if ( @$this->chrt_array["appearance"]["color51"] != "" )
3318
+ $chart["xAxes"][0]["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color51"];
3319
+
3320
+ if ( @$this->chrt_array["appearance"]["color111"] != "" )
3321
+ $chart["xAxes"][0]["title"]["fontColor"] = "#".$this->chrt_array["appearance"]["color111"];
3322
+
3323
+ if ( @$this->chrt_array["appearance"]["color131"] != "" )
3324
+ $chart["xAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color131"];
3325
+
3326
+ if ( @$this->chrt_array["appearance"]["color141"] != "" )
3327
+ $chart["yAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color141"];
3328
+ }
3329
+
3330
+ /**
3331
+ * @return String
3332
+ */
3333
+ protected function getSeriesType($seriesNumber)
3334
+ {
3335
+ switch ($seriesNumber) {
3336
+ case 0:
3337
+ return "spline";
3338
+ break;
3339
+ case 1:
3340
+ return "splineArea";
3341
+ break;
3342
+ default:
3343
+ return "column";
3344
+ }
3345
+ }
3346
+ protected function getLogarithm()
3347
+ {
3348
+ if( $this->chrt_array["appearance"]["slog"] == "true" )
3349
+ return true;
3350
+ return false;
3351
+ }
3352
+ }
3353
+
3354
+ /**
3355
+ * A single series chart
3356
+ */
3357
+ class Chart_Funnel extends Chart
3358
+ {
3359
+ protected $inver;
3360
+
3361
+
3362
+ function __construct( &$ch_array, $param )
3363
+ {
3364
+ parent::__construct( $ch_array, $param );
3365
+
3366
+ $this->inver = $param["funnel_inv"];
3367
+ $this->singleSeries = true;
3368
+ }
3369
+
3370
+ /**
3371
+ * @param &Array chart
3372
+ */
3373
+ protected function setTypeSpecChartSettings( &$chart )
3374
+ {
3375
+ $series = $this->get_data();
3376
+ $chart["type"] = "pyramid";
3377
+
3378
+ $chart["data"] = $series[0]["data"];
3379
+ $chart["clickData"] = $series[0]["clickData"];
3380
+ $chart["singleSeries"] = true;
3381
+ $chart["tooltip"] = $series[0]["tooltip"];
3382
+ $chart["logarithm"] = false;
3383
+ if( $this->inver )
3384
+ $chart["reversed"] = true;
3385
+
3386
+ $chart["labels"] = array( "enabled" => $this->chrt_array["appearance"]["sname"] == "true" );
3387
+
3388
+ if ( @$this->chrt_array["appearance"]["color51"] != "" )
3389
+ $chart["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color51"];
3390
+ }
3391
+ }
3392
+
3393
+ class Chart_Bubble extends Chart
3394
+ {
3395
+ protected $arrDataSize = array();
3396
+
3397
+
3398
+ function __construct( &$ch_array, $param )
3399
+ {
3400
+ parent::__construct( $ch_array, $param );
3401
+
3402
+ $this->_2d = $param["2d"];
3403
+ }
3404
+
3405
+ /**
3406
+ * @param Array params
3407
+ */
3408
+ protected function setSpecParams( $params )
3409
+ {
3410
+ parent::setSpecParams( $params );
3411
+
3412
+ if( $params['name'] != "" )
3413
+ {
3414
+ if( $this->table_type != "db" )
3415
+ $this->arrDataSize[] = $params['size'];
3416
+ else
3417
+ $this->arrDataSize[] = $params['table']."_".$params['size'];
3418
+ }
3419
+ }
3420
+
3421
+ /**
3422
+ * @param &Array chart
3423
+ */
3424
+ protected function setTypeSpecChartSettings( &$chart )
3425
+ {
3426
+ $chart["series"] = $this->get_data();
3427
+ $chart["type"] = "cartesian";
3428
+ $chart["grids"] = $this->getGrids();
3429
+ $chart["logarithm"] = parent::getLogarithm();
3430
+ $chart["yAxes"] = array(
3431
+ array(
3432
+ "enabled" => true,
3433
+ "title" => $this->y_axis_label,
3434
+ "labels" => array( "enabled" => $this->chrt_array["appearance"]["sval"] == "true" )
3435
+ ));
3436
+
3437
+ if ( @$this->chrt_array["appearance"]["color61"] != "" )
3438
+ $chart["yAxes"][0]["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color61"];
3439
+
3440
+ $chart["xAxes"] = array(
3441
+ array(
3442
+ "enabled" => "true",
3443
+ "title" => array( 'text' => $this->footer ),
3444
+ "labels" => array( "enabled" => $this->chrt_array["appearance"]["sname"] == "true" )
3445
+ ));
3446
+
3447
+ if ( @$this->chrt_array["appearance"]["color51"] != "" )
3448
+ $chart["xAxes"][0]["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color51"];
3449
+
3450
+ if ( @$this->chrt_array["appearance"]["color111"] != "" )
3451
+ $chart["xAxes"][0]["title"]["fontColor"] = "#".$this->chrt_array["appearance"]["color111"];
3452
+
3453
+ if ( @$this->chrt_array["appearance"]["color131"] != "" )
3454
+ $chart["xAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color131"];
3455
+
3456
+ if ( @$this->chrt_array["appearance"]["color141"] != "" )
3457
+ $chart["yAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color141"];
3458
+ }
3459
+
3460
+ /**
3461
+ * @return String
3462
+ */
3463
+ protected function getSeriesType($seriesNumber)
3464
+ {
3465
+ return "bubble";
3466
+ }
3467
+
3468
+ /**
3469
+ * @param Number seriesNumber
3470
+ * @param Array row
3471
+ * @return Array
3472
+ */
3473
+ protected function getPoint( $seriesNumber, $row )
3474
+ {
3475
+ $pointData = parent::getPoint( $seriesNumber, $row );
3476
+ $pointData["size"] = (double)str_replace(",", ".", $row[ $this->arrDataSize[ $seriesNumber ] ]);
3477
+
3478
+ return $pointData;
3479
+ }
3480
+ }
3481
+
3482
+ class Chart_Gauge extends Chart
3483
+ {
3484
+ protected $arrGaugeColor = array();
3485
+ protected $gaugeType = "";
3486
+ protected $layout = "";
3487
+
3488
+ function __construct( &$ch_array, $param )
3489
+ {
3490
+ parent::__construct( $ch_array, $param );
3491
+
3492
+ $this->gaugeType = $param["gaugeType"];
3493
+ $this->layout = $param["layout"];
3494
+ }
3495
+
3496
+ /**
3497
+ * @param Array params
3498
+ */
3499
+ protected function setSpecParams( $params )
3500
+ {
3501
+ parent::setSpecParams( $params );
3502
+
3503
+ if ( $params['name'] != "" )
3504
+ {
3505
+ for ($k = 0; is_array( $params["gaugeColorZone"] ) && $k < count( $params["gaugeColorZone"] ); $k++ )
3506
+ {
3507
+ $beginColor = (float)@$params["gaugeColorZone"][ $k ]["gaugeBeginColor"];
3508
+ $endColor = (float)@$params["gaugeColorZone"][ $k ]["gaugeEndColor"];
3509
+ $gColor = "#".@$params["gaugeColorZone"][ $k ]["gaugeColor"];
3510
+
3511
+ $this->arrGaugeColor[ count($this->arrDataSeries) - 1 ][] = array($beginColor, $endColor, $gColor);
3512
+ }
3513
+ }
3514
+ }
3515
+
3516
+ /**
3517
+ *
3518
+ */
3519
+ public function write()
3520
+ {
3521
+ $data = array();
3522
+
3523
+ for($i = 0; $i < count($this->arrDataSeries); $i++)
3524
+ {
3525
+ $chart = array();
3526
+
3527
+ if( $this->chrt_array["appearance"]["sanim"] == "true" )
3528
+ $chart["animation"] = array("enabled" => "true", "duration" => 1000);
3529
+
3530
+ $this->setGaugeSpecChartSettings( $chart, $i );
3531
+
3532
+ if ( @$this->chrt_array["appearance"]["color71"] != "" || @$this->chrt_array["appearance"]["color91"] != "" )
3533
+ $chart["background"] = array();
3534
+ if ( @$this->chrt_array["appearance"]["color71"] != "" )
3535
+ $chart["background"]["fill"] = "#".$this->chrt_array["appearance"]["color71"];
3536
+
3537
+ if ( @$this->chrt_array["appearance"]["color91"] != "" )
3538
+ $chart["background"]["stroke"] = "#".$this->chrt_array["appearance"]["color91"];
3539
+
3540
+ if( $this->noRecordsFound )
3541
+ {
3542
+ $data["noDataMessage"] = $this->getNoDataMessage();
3543
+ echo my_json_encode( $data );
3544
+ return;
3545
+ }
3546
+
3547
+ $data[] = array( "gauge" => $chart );
3548
+ }
3549
+
3550
+ echo my_json_encode( array( "gauge" => $data, "header" => $this->header, "footer" => $this->footer ) );
3551
+ }
3552
+
3553
+ /**
3554
+ * @param &Array chart
3555
+ * @param Number seriesNumber
3556
+ */
3557
+ protected function setGaugeSpecChartSettings( &$chart, $seriesNumber )
3558
+ {
3559
+ $series = $this->get_data();
3560
+ $chart["data"] = $series[ $seriesNumber ]["data"];
3561
+
3562
+ $chart["type"] = $this->gaugeType;
3563
+ $chart["layout"] = $this->layout;
3564
+ $chart["axes"] = array( $this->getAxesSettings( $seriesNumber ) );
3565
+ $chart["credits"] = false;
3566
+ $chart["chartLabels"] = $this->getCircularGaugeLabel( $seriesNumber, $chart["data"][0] );
3567
+ if( $this->gaugeType == "circular-gauge" )
3568
+ {
3569
+ $chart["needles"] = array( array("enabled" => true) );
3570
+ $chart["ranges"] = $this->getColorRanges( $seriesNumber );
3571
+ }
3572
+ else
3573
+ {
3574
+ $hasColorZones = count( $this->arrGaugeColor ) > 0 && array_key_exists($seriesNumber, $this->arrGaugeColor );
3575
+
3576
+ $chart["pointers"] = array(
3577
+ array(
3578
+ "enabled" => true,
3579
+ "pointerType" => "marker",
3580
+ "type" => $this->layout == "horizontal" ? "triangleUp" : "triangleLeft",
3581
+ "name" => "",
3582
+ "offset" => $hasColorZones ? "20%" : "10%",
3583
+ "dataIndex" => 0,
3584
+ )
3585
+ );
3586
+
3587
+ if( $hasColorZones )
3588
+ {
3589
+ foreach( $this->arrGaugeColor[ $seriesNumber ] as $ind => $val )
3590
+ {
3591
+ $chart["pointers"][] = array(
3592
+ "enabled" => true,
3593
+ "pointerType" => "rangeBar",
3594
+ "name" => "",
3595
+ "offset" => "10%",
3596
+ "dataIndex" => $ind + 1, // 0 is an index of the db point then range bars coords go
3597
+ "color" => $val[2]
3598
+ );
3599
+ }
3600
+ }
3601
+
3602
+ $scalesData = $this->getGaugeScales( $seriesNumber );
3603
+
3604
+ $chart["scale"] = 0;
3605
+ $chart["scales"] = array(
3606
+ array(
3607
+ "maximum" => $scalesData["max"],
3608
+ "minimum" => $scalesData["min"],
3609
+ "ticks" => array( "interval"=> $scalesData["interval"] ),
3610
+ "minorTicks" => array( "interval"=> $scalesData["interval"] / 2 )
3611
+ )
3612
+ );
3613
+ }
3614
+ }
3615
+
3616
+ /**
3617
+ * @param Number seriesNumber
3618
+ * @param Array pointData
3619
+ * @return Array
3620
+ */
3621
+ protected function getCircularGaugeLabel( $seriesNumber, $pointData )
3622
+ {
3623
+ $label = array(
3624
+ "enabled" => true,
3625
+ "vAlign" => "center",
3626
+ "hAlign" => "center",
3627
+ "text" => $this->getChartLabelText( $seriesNumber, $pointData["value"] )
3628
+ );
3629
+
3630
+ if( $this->gaugeType == "circular-gauge" )
3631
+ {
3632
+ $label["offsetY"] = -150; //fix it
3633
+ $label["anchor"] = "center";
3634
+
3635
+ $label["background"] = array(
3636
+ "enabled" => true,
3637
+ "fill" => "#fff",
3638
+ "cornerType" => "round",
3639
+ "corner" => 0
3640
+ );
3641
+
3642
+ $label["padding"] = array(
3643
+ "top" => 15,
3644
+ "right" => 20,
3645
+ "bottom" => 15,
3646
+ "left" => 20
3647
+ );
3648
+ }
3649
+
3650
+ return array( $label );
3651
+ }
3652
+
3653
+ /**
3654
+ * @param Number seriesNumber
3655
+ * @return Array
3656
+ */
3657
+ protected function getColorRanges( $seriesNumber )
3658
+ {
3659
+ $ranges = array();
3660
+ if( count( $this->arrGaugeColor ) > 0 && array_key_exists($seriesNumber, $this->arrGaugeColor ) )
3661
+ {
3662
+ foreach( $this->arrGaugeColor[ $seriesNumber ] as $ind => $val )
3663
+ {
3664
+ $ranges[] = array(
3665
+ "radius" => 70,
3666
+ "from" => $val[0],
3667
+ "to" => $val[1],
3668
+ "fill" => $val[2],
3669
+ "endSize" => "10%",
3670
+ "startSize" => "10%"
3671
+ );
3672
+ }
3673
+ }
3674
+
3675
+ return $ranges;
3676
+ }
3677
+
3678
+ /**
3679
+ * @param Number seriesNumber
3680
+ * @return Array
3681
+ */
3682
+ protected function getAxesSettings( $seriesNumber )
3683
+ {
3684
+ $axes = array();
3685
+
3686
+ if( $this->gaugeType == "circular-gauge" )
3687
+ {
3688
+ $axes["startAngle"] = -150;
3689
+ $axes["sweepAngle"] = 300;
3690
+
3691
+ $scalesData = $this->getGaugeScales( $seriesNumber );
3692
+
3693
+ $axes["scale"] = array(
3694
+ "maximum" => $scalesData["max"],
3695
+ "minimum" => $scalesData["min"],
3696
+ "ticks" => array( "interval"=> $scalesData["interval"] ),
3697
+ "minorTicks" => array( "interval" => $scalesData["interval"] / 2 )
3698
+ );
3699
+
3700
+ $axes["ticks"] = array(
3701
+ "type" => "trapezoid",
3702
+ "interval" => $scalesData["interval"]
3703
+ );
3704
+
3705
+ $axes["minorTicks"] = array(
3706
+ "enabled" => true,
3707
+ "length" => 2
3708
+ );
3709
+
3710
+ if ( @$this->chrt_array["appearance"]["color131"] != "" )
3711
+ $axes["fill"] = "#".$this->chrt_array["appearance"]["color131"];
3712
+ }
3713
+
3714
+ $axes["enabled"] = true;
3715
+ $axes["labels"] = array( "enabled" => $this->chrt_array["appearance"]["sval"] == "true" );
3716
+
3717
+ if ( @$this->chrt_array["appearance"]["color61"] != "" )
3718
+ $axes["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color61"];
3719
+
3720
+ return $axes;
3721
+ }
3722
+
3723
+ /**
3724
+ * @param Number seriesNumber
3725
+ * @return Array
3726
+ */
3727
+ protected function getGaugeScales( $seriesNumber )
3728
+ {
3729
+ $min = $this->chrt_array["parameters"][ $seriesNumber ]["gaugeMinValue"];
3730
+ $max = $this->chrt_array["parameters"][ $seriesNumber ]["gaugeMaxValue"];
3731
+
3732
+ if( !is_numeric( $min ) )
3733
+ $min = 0;
3734
+
3735
+ if( !is_numeric( $max ) )
3736
+ $max = 100;
3737
+
3738
+ $diff = $max - $min;
3739
+ $slog = floor( log10( $diff ) );
3740
+ $interval = pow(10, $slog - 2);
3741
+ $muls = array(1,2,3,5,10);
3742
+
3743
+ while(true)
3744
+ {
3745
+ foreach($muls as $m)
3746
+ {
3747
+ if( $diff / ($interval * $m) <= 10 )
3748
+ {
3749
+ $interval*= $m;
3750
+ break;
3751
+ }
3752
+ }
3753
+ if( $diff / ($interval) <= 10 )
3754
+ break;
3755
+
3756
+ $interval*= 10;
3757
+ }
3758
+
3759
+ return array(
3760
+ "min" => $min,
3761
+ "max" => $max,
3762
+ "interval" => $interval
3763
+ );
3764
+ }
3765
+
3766
+
3767
+ public function getSubsetDataCommand( $ignoreFilterField = "" ) {
3768
+ $dc = parent::getSubsetDataCommand();
3769
+
3770
+ if( $this->table_type == "project" ) {
3771
+ require_once( getabspath('classes/orderclause.php') );
3772
+
3773
+ $orderObject = new OrderClause( $this->pSet, $this->cipherer, $this->sessionPrefix, $this->connection );
3774
+ $order = $orderObject->getOrderFields();
3775
+ $revertedOrder = array();
3776
+
3777
+ foreach( $order as $o ) {
3778
+ $ro = $o;
3779
+ $ro['dir'] = $ro['dir'] == "ASC" ? "DESC" : "ASC";
3780
+
3781
+ $revertedOrder[] = $ro;
3782
+ }
3783
+
3784
+ $dc->order = $revertedOrder;
3785
+ }
3786
+
3787
+ return $dc;
3788
+ }
3789
+
3790
+ /**
3791
+ *
3792
+ */
3793
+ public function get_data()
3794
+ {
3795
+ $data = array();
3796
+
3797
+ $dc = $this->getSubsetDataCommand();
3798
+ $this->beforeQueryEvent( $dc );
3799
+
3800
+ $rs = $this->dataSource->getList( $dc );
3801
+ if( !$rs ) {
3802
+ showError( $this->dataSource->lastError() );
3803
+ }
3804
+
3805
+ $row = $rs->fetchAssoc();
3806
+ if( $this->cipherer )
3807
+ $row = $this->cipherer->DecryptFetchedArray( $row );
3808
+
3809
+ if( !$row )
3810
+ $this->noRecordsFound = true;
3811
+
3812
+ for($i = 0; $i < count($this->arrDataSeries); $i++)
3813
+ {
3814
+ if( $row )
3815
+ {
3816
+ $data[$i] = array();
3817
+ $data[$i][] = $this->getPoint($i, $row);
3818
+ }
3819
+ }
3820
+
3821
+ $series = array();
3822
+ for ( $i = 0; $i < count($this->arrDataSeries); $i++ )
3823
+ {
3824
+ $series[] = $this->getSeriesData( $this->arrDataLabels[$i], $data[$i], $clickdata[$i], $i, count($this->arrDataSeries) > 1 );
3825
+ }
3826
+
3827
+ return $series;
3828
+ }
3829
+
3830
+ /**
3831
+ * @param String name
3832
+ * @param Array pointsData
3833
+ * @param Array clickData
3834
+ * @param Number seriesNumber
3835
+ * @param Boolean multiSeries (optional)
3836
+ * @return Array
3837
+ */
3838
+ protected function getSeriesData( $name, $pointsData, $clickData, $seriesNumber, $multiSeries = true )
3839
+ {
3840
+ if( $this->gaugeType == "linearGauge" && count( $this->arrGaugeColor ) > 0 && array_key_exists( $seriesNumber, $this->arrGaugeColor ) )
3841
+ {
3842
+ foreach( $this->arrGaugeColor[ $seriesNumber ] as $ind => $val )
3843
+ {
3844
+ $pointsData[] = array(
3845
+ "low" => $val[0],
3846
+ "high" => $val[1]
3847
+ );
3848
+ }
3849
+ }
3850
+
3851
+ return array(
3852
+ "data" => $pointsData,
3853
+ "labelText" => $this->getChartLabelText( $seriesNumber, $pointsData[0]["value"] )
3854
+ );
3855
+ }
3856
+
3857
+ /**
3858
+ * @param Number seriesNumber
3859
+ * @param String value
3860
+ * @return String
3861
+ */
3862
+ protected function getChartLabelText( $seriesNumber, $value )
3863
+ {
3864
+ if( $this->table_type == "project" && !$this->webchart )
3865
+ {
3866
+ $fieldName = $this->arrDataSeries[ $seriesNumber ];
3867
+
3868
+ include_once getabspath('classes/controls/ViewControlsContainer.php');
3869
+ $viewControls = new ViewControlsContainer($this->pSet, PAGE_CHART);
3870
+
3871
+ $data = array( $fieldName => $value );
3872
+ $viewValue = $viewControls->showDBValue( $fieldName, $data, "", "", false );
3873
+
3874
+ return $this->arrDataLabels[ $seriesNumber ].": ". $viewValue;
3875
+ }
3876
+
3877
+ return $this->arrDataLabels[ $seriesNumber ].": ". $value;
3878
+ }
3879
+ }
3880
+
3881
+ class Chart_Ohlc extends Chart
3882
+ {
3883
+ protected $ohcl_type;
3884
+
3885
+ protected $arrOHLC_high = array();
3886
+ protected $arrOHLC_low = array();
3887
+ protected $arrOHLC_open = array();
3888
+ protected $arrOHLC_close = array();
3889
+
3890
+ function __construct( &$ch_array, $param )
3891
+ {
3892
+ parent::__construct( $ch_array, $param );
3893
+
3894
+ $this->ohcl_type = $param["ohcl_type"];
3895
+ }
3896
+
3897
+ /**
3898
+ * @param Array params
3899
+ */
3900
+ protected function setSpecParams( $params )
3901
+ {
3902
+ if($this->table_type != "db")
3903
+ {
3904
+ $this->arrOHLC_open[] = $params['ohlcOpen'];
3905
+ $this->arrOHLC_high[] = $params['ohlcHigh'];
3906
+ $this->arrOHLC_low[] = $params['ohlcLow'];
3907
+ $this->arrOHLC_close[] = $params['ohlcClose'];
3908
+ return;
3909
+ }
3910
+
3911
+ if( $params['agr_func'] )
3912
+ {
3913
+ $this->arrOHLC_open[] = $params['agr_func']."_".$params['table']."_".$params['ohlcOpen'];
3914
+ $this->arrOHLC_high[] = $params['agr_func']."_".$params['table']."_".$params['ohlcHigh'];
3915
+ $this->arrOHLC_low[] = $params['agr_func']."_".$params['table']."_".$params['ohlcLow'];
3916
+ $this->arrOHLC_close[] = $params['agr_func']."_".$params['table']."_".$params['ohlcClose'];
3917
+ }
3918
+ else
3919
+ {
3920
+ $this->arrOHLC_open[] = $params['table']."_".$params['ohlcOpen'];
3921
+ $this->arrOHLC_high[] = $params['table']."_".$params['ohlcHigh'];
3922
+ $this->arrOHLC_low[] = $params['table']."_".$params['ohlcLow'];
3923
+ $this->arrOHLC_close[] = $params['table']."_".$params['ohlcClose'];
3924
+ }
3925
+ }
3926
+
3927
+ /**
3928
+ *
3929
+ */
3930
+ public function write()
3931
+ {
3932
+ $data = array();
3933
+ $chart = array();
3934
+
3935
+ $this->setTypeSpecChartSettings( $chart );
3936
+ if ( @$this->chrt_array["appearance"]["color71"] != "" || @$this->chrt_array["appearance"]["color91"] != "" )
3937
+ $chart["background"] = array();
3938
+ if ( @$this->chrt_array["appearance"]["color71"] != "" )
3939
+ $chart["background"]["fill"] = "#".$this->chrt_array["appearance"]["color71"];
3940
+
3941
+ if ( @$this->chrt_array["appearance"]["color91"] != "" )
3942
+ $chart["background"]["stroke"] = "#".$this->chrt_array["appearance"]["color91"];
3943
+
3944
+ $chart["credits"] = false;
3945
+ $chart["title"] = array("enabled" => "true", "text" => $this->header);
3946
+ if ( @$this->chrt_array["appearance"]["color101"] != "" )
3947
+ $chart["title"]["fontColor"] = "#".$this->chrt_array["appearance"]["color101"];
3948
+
3949
+ if( $this->chrt_array['appearance']['slegend'] == "true" && !$this->chartPreview )
3950
+ $chart["legend"] = array("enabled" => "true");
3951
+
3952
+ $data["chart"] = $chart;
3953
+ echo my_json_encode( $data );
3954
+ }
3955
+
3956
+ /**
3957
+ * @param &Array chart
3958
+ */
3959
+ protected function setTypeSpecChartSettings( &$chart )
3960
+ {
3961
+ $chart["series"] = $this->get_data();
3962
+ foreach ($this->chrt_array["parameters"] as $seriesNum => $params) {
3963
+ if ( @$params["ohlcColor"] != "" )
3964
+ {
3965
+ $chart["series"][$seriesNum]["fallingStroke"] = "#".$params["ohlcColor"];
3966
+ $chart["series"][$seriesNum]["fallingFill"] = "#".$params["ohlcColor"];
3967
+ if ( $this->ohcl_type == "ohcl" )
3968
+ {
3969
+ $chart["series"][$seriesNum]["risingStroke"] = "#".$params["ohlcColor"];
3970
+ $chart["series"][$seriesNum]["risingFill"] = "#".$params["ohlcColor"];
3971
+ }
3972
+ }
3973
+ if ( @$params["ohlcCandleColor"] != "" && $this->ohcl_type != "ohcl" )
3974
+ {
3975
+ $chart["series"][$seriesNum]["risingStroke"] = "#".$params["ohlcCandleColor"];
3976
+ $chart["series"][$seriesNum]["risingFill"] = "#".$params["ohlcCandleColor"];
3977
+ }
3978
+ }
3979
+
3980
+ $chart["grids"] = $this->getGrids();
3981
+ $chart["logarithm"] = parent::getLogarithm();
3982
+ $chart["type"] = "financial";
3983
+ $chart["xScale"] = 0;
3984
+ $chart["yScale"] = 1;
3985
+
3986
+ $chart["yAxes"] = array(
3987
+ array(
3988
+ "enabled" => "true",
3989
+ "title" => $this->y_axis_label,
3990
+ "labels" => array("enabled" => $this->chrt_array["appearance"]["sval"] == "true")
3991
+ ));
3992
+
3993
+ if ( @$this->chrt_array["appearance"]["color61"] != "" )
3994
+ $chart["yAxes"][0]["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color61"];
3995
+
3996
+ $chart["xAxes"] = array(
3997
+ array(
3998
+ "enabled" => "true",
3999
+ "title" => array( 'text' => $this->footer ),
4000
+ "labels" => array("enabled" => $this->chrt_array["appearance"]["sname"] == "true" )
4001
+ ));
4002
+
4003
+ if ( @$this->chrt_array["appearance"]["color51"] != "" )
4004
+ $chart["xAxes"][0]["labels"]["fontColor"] = "#".$this->chrt_array["appearance"]["color51"];
4005
+
4006
+ if ( @$this->chrt_array["appearance"]["color111"] != "" )
4007
+ $chart["xAxes"][0]["title"]["fontColor"] = "#".$this->chrt_array["appearance"]["color111"];
4008
+
4009
+ if ( @$this->chrt_array["appearance"]["color131"] != "" )
4010
+ $chart["xAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color131"];
4011
+
4012
+ if ( @$this->chrt_array["appearance"]["color141"] != "" )
4013
+ $chart["yAxes"][0]["stroke"] = "#".$this->chrt_array["appearance"]["color141"];
4014
+
4015
+ if( $this->chrt_array["appearance"]["slog"] == "true" )
4016
+ {
4017
+ $chart["scales"] = array(
4018
+ array( "names" => array() ),
4019
+ array( "logBase" => 10, "type" => "log" )
4020
+ );
4021
+ }
4022
+ }
4023
+
4024
+ /**
4025
+ * @return Array
4026
+ */
4027
+ public function get_data()
4028
+ {
4029
+ $data = array();
4030
+ $clickdata = array();
4031
+
4032
+ for ( $i = 0; $i < count( $this->arrOHLC_open ); $i++ )
4033
+ {
4034
+ $data[$i] = array();
4035
+ $clickdata[$i] = array();
4036
+ }
4037
+
4038
+ $dc = $this->getSubsetDataCommand();
4039
+ $this->beforeQueryEvent( $dc );
4040
+
4041
+ $rs = $this->dataSource->getList( $dc );
4042
+ if( !$rs ) {
4043
+ showError( $this->dataSource->lastError() );
4044
+ }
4045
+
4046
+ $row = $rs->fetchAssoc();
4047
+ if( $this->cipherer )
4048
+ $row = $this->cipherer->DecryptFetchedArray( $row );
4049
+
4050
+ if( !$row )
4051
+ $this->noRecordsFound = true;
4052
+
4053
+ while( $row )
4054
+ {
4055
+ for ( $i = 0; $i < count( $this->arrOHLC_open ); $i++ )
4056
+ {
4057
+ $data[$i][] = $this->getPoint( $i, $row );
4058
+
4059
+ $strLabelFormat = $this->labelFormat( $this->strLabel, $row );
4060
+ $clickdata[$i][] = $this->getActions( $row , $this->arrDataSeries[$i], $strLabelFormat );
4061
+ }
4062
+
4063
+ $row = $rs->fetchAssoc();
4064
+ if( $this->cipherer )
4065
+ $row = $this->cipherer->DecryptFetchedArray( $row );
4066
+ }
4067
+
4068
+ $series = array();
4069
+ for ( $i = 0; $i < count( $this->arrOHLC_open ); $i++ )
4070
+ {
4071
+ $series[] = $this->getSeriesData( $this->arrDataLabels[$i], $data[$i], $clickdata[$i], $i );
4072
+ }
4073
+
4074
+ return $series;
4075
+ }
4076
+
4077
+ /**
4078
+ * @return String
4079
+ */
4080
+ protected function getSeriesType($seriesNumber)
4081
+ {
4082
+ if( $this->ohcl_type == "ohcl" )
4083
+ return "ohlc";
4084
+
4085
+ return "candlestick";
4086
+ }
4087
+
4088
+ /**
4089
+ * @param Boolean $multiSeries
4090
+ * @return Array
4091
+ */
4092
+ protected function getSeriesTooltip( $multiSeries ) {
4093
+ $tooltipSettings = array(
4094
+ "enabled" => true
4095
+ );
4096
+
4097
+ return $tooltipSettings;
4098
+ }
4099
+
4100
+ /**
4101
+ * @param Number seriesNumber
4102
+ * @param Array row
4103
+ * @return Array
4104
+ */
4105
+ protected function getPoint( $seriesNumber, $row )
4106
+ {
4107
+ if( $this->table_type!="db" || !$this->chrt_array['customLabels'] )
4108
+ {
4109
+ $high = $row[ $this->arrOHLC_high[ $seriesNumber ] ];
4110
+ $low = $row[ $this->arrOHLC_low[ $seriesNumber ] ];
4111
+ $open = $row[ $this->arrOHLC_open[ $seriesNumber ] ];
4112
+ $close = $row[ $this->arrOHLC_close[ $seriesNumber ] ];
4113
+ }
4114
+ else
4115
+ {
4116
+ $high = $row[ $this->chrt_array['customLabels'][ $this->arrOHLC_high[ $seriesNumber ] ] ];
4117
+ $low = $row[ $this->chrt_array['customLabels'][ $this->arrOHLC_low[ $seriesNumber ] ] ];
4118
+ $open = $row[ $this->chrt_array['customLabels'][ $this->arrOHLC_open[ $seriesNumber ] ] ];
4119
+ $close = $row[ $this->chrt_array['customLabels'][ $this->arrOHLC_close[ $seriesNumber ] ] ];
4120
+ }
4121
+
4122
+ return array(
4123
+ "x" => $this->labelFormat( $this->strLabel, $row ),
4124
+ "open" => (double)$open,
4125
+ "high" => (double)$high,
4126
+ "low" => (double)$low,
4127
+ "close" => (double)str_replace(",", ".", $close)
4128
+ );
4129
+ }
4130
+ }
4131
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
4132
  ?>
php/classes/cipherer.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class RunnerCipherer
3
  {
@@ -338,4 +339,346 @@ class RunnerCipherer
338
  return new RunnerCipherer( GLOBAL_PAGES, null);
339
  }
340
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class RunnerCipherer
4
  {
 
339
  return new RunnerCipherer( GLOBAL_PAGES, null);
340
  }
341
  }
342
+ =======
343
+ <?php
344
+ class RunnerCipherer
345
+ {
346
+ public $key = '';
347
+ public $alg = '';
348
+ public $mode = '';
349
+
350
+ protected $strTableName = '';
351
+
352
+ /**
353
+ * Instance of RunnerCiphererES class for code-based ciphering
354
+ */
355
+ protected $ESFunctions = null;
356
+
357
+ /**
358
+ * Instance of ProjectSettings class
359
+ */
360
+ protected $pSet = null;
361
+
362
+ /**
363
+ * Array of fields which encrypted status already determined
364
+ */
365
+ protected $encryptedFields = array();
366
+
367
+ /**
368
+ * @type Connection
369
+ */
370
+ protected $connection;
371
+
372
+
373
+ function __construct($strTableName, $pSet = null)
374
+ {
375
+
376
+ $this->strTableName = $strTableName;
377
+
378
+ $this->setConnection();
379
+
380
+ if( $this->connection->dbBased() ) {
381
+ $this->key = $this->connection->_encryptInfo["key"];
382
+ $this->alg = $this->connection->_encryptInfo["alg"];
383
+ $this->mode = $this->connection->_encryptInfo["mode"];
384
+ }
385
+
386
+ if($pSet != null)
387
+ $this->pSet = $pSet;
388
+ else
389
+ $this->pSet = new ProjectSettings($strTableName);
390
+ }
391
+
392
+ /**
393
+ * Set the 'connection' property
394
+ */
395
+ protected function setConnection()
396
+ {
397
+ global $cman;
398
+
399
+ if( $this->strTableName != GLOBAL_PAGES )
400
+ $this->connection = $cman->byTable( $this->strTableName );
401
+ else
402
+ $this->connection = getDefaultConnection();
403
+
404
+ if ( $this->connection->dbType == nDATABASE_MSSQLServer && $this->connection->_encryptInfo["alg"] == ENCRYPTION_ALG_AES && $this->connection->_encryptInfo["mode"] == ENCRYPTION_DB )
405
+ {
406
+ $symmetricSql = mysprintf("OPEN SYMMETRIC KEY [%s] DECRYPTION BY CERTIFICATE [%s];", array($this->connection->_encryptInfo["slqserverkey"], $this->connection->_encryptInfo["slqservercert"]));
407
+ $this->connection->setInitializingSQL($symmetricSql);
408
+ }
409
+ }
410
+
411
+ function isEncryptionByPHPEnabled()
412
+ {
413
+ return $this->connection->isEncryptionByPHPEnabled();
414
+ }
415
+
416
+ /**
417
+ * DecryptFetchedArray
418
+ * Fetching record from sql result, looking through array of fetched values and decrypted all encrypted fields
419
+ * @param {array} fetchedArray
420
+ * @return {array} decrypted array
421
+ */
422
+ public function DecryptFetchedArray( $fetchedArray )
423
+ {
424
+ $result = array();
425
+
426
+ if($fetchedArray)
427
+ {
428
+ if( !$this->pSet->hasEncryptedFields() || !$this->connection->isEncryptionByPHPEnabled() )
429
+ return $fetchedArray;
430
+
431
+ foreach ($fetchedArray as $fieldName => $fieldValue)
432
+ {
433
+ $result[ $fieldName ] = $this->DecryptField($fieldName, $fieldValue);
434
+ }
435
+ }
436
+
437
+ return $result;
438
+ }
439
+
440
+ /**
441
+ * @param String field
442
+ * @param String
443
+ */
444
+ public function isFieldEncrypted($field)
445
+ {
446
+ $table = $this->strTableName;
447
+
448
+ if( array_key_exists($table, $this->encryptedFields) && array_key_exists($field, $this->encryptedFields[ $table ]) )
449
+ return $this->encryptedFields[ $table ][ $field ];
450
+
451
+ if( !array_key_exists($table, $this->encryptedFields) )
452
+ $this->encryptedFields[ $table ] = array();
453
+
454
+ $this->encryptedFields[ $table ][ $field ] = $this->pSet->isFieldEncrypted($field);
455
+ return $this->encryptedFields[ $table ][ $field ];
456
+ }
457
+
458
+ /**
459
+ * @param String field
460
+ * @return Boolean
461
+ */
462
+ public function isFieldPHPEncrypted($field)
463
+ {
464
+ return $this->connection->isEncryptionByPHPEnabled() && $this->isFieldEncrypted($field);
465
+ }
466
+
467
+ /**
468
+ * @param String field
469
+ * @param Mixed value
470
+ * @param String controltype (optional)
471
+ * @param Boolean phpEncryptionOnly (optional)
472
+ */
473
+ public function MakeDBValue($field, $value, $controltype = "", $phpEncryptionOnly = false)
474
+ {
475
+ $ret = prepare_for_db($field, $value, $controltype, "", $this->strTableName);
476
+ if( $ret === false )
477
+ return $ret;
478
+
479
+ $ret = add_db_quotes($field, $this->EncryptField($field, $ret), $this->strTableName );
480
+
481
+ if( $phpEncryptionOnly )
482
+ return $ret;
483
+
484
+ return $this->EncryptValueByDB($field, $ret);
485
+ }
486
+
487
+ /**
488
+ * @param String field
489
+ * @param Mixed value
490
+ */
491
+ public function AddDBQuotes($field, $value)
492
+ {
493
+ return $this->EncryptValueByDB( $field, add_db_quotes($field, $this->EncryptField($field, $value), $this->strTableName) );
494
+ }
495
+
496
+
497
+ /**
498
+ * GetFieldName
499
+ * Add to field name decryption function if field is encrypted by database
500
+ * @param {string} field name
501
+ * @param {string} alias of field name
502
+ * @param {bool} shows if 'as' construction needed
503
+ * @return {string}
504
+ */
505
+ public function GetFieldName($field, $alias = null, $addAs = false)
506
+ {
507
+ if($this->connection->isEncryptionByPHPEnabled() || !$this->isFieldEncrypted($alias != null ? $alias : $field))
508
+ return $field;
509
+
510
+ return $this->GetEncryptedFieldName($field, $alias, $addAs);
511
+ }
512
+
513
+ /**
514
+ * Get an SQL expression retriving the encrypted field's value
515
+ * Please note, when changing this function you should make appropriate changes in wizard method (dynamic permissions --> add new user) #8923
516
+ * @param {string} field
517
+ * @param {string} alias
518
+ * @param {string} addAs
519
+ * @return {string}
520
+ */
521
+ public function GetEncryptedFieldName($field, $alias = null, $addAs = false)
522
+ {
523
+ $result = "";
524
+ if ( $this->connection->_encryptInfo["alg"] == ENCRYPTION_ALG_DES)
525
+ {
526
+ if( $this->connection->dbType == nDATABASE_Oracle )
527
+ $result = "utl_raw.cast_to_varchar2(DBMS_CRYPTO.DECRYPT(utl_raw.cast_to_raw(%s), 4353, utl_raw.cast_to_raw('%s')))";
528
+ elseif( $this->connection->dbType == nDATABASE_MSSQLServer )
529
+ $result = "CAST(DecryptByPassPhrase(N'%s', %s) as nvarchar)";
530
+ elseif( $this->connection->dbType == nDATABASE_MySQL )
531
+ $result = "cast(DES_DECRYPT(unhex(%s), '%s') as char)";
532
+ elseif( $this->connection->dbType == nDATABASE_PostgreSQL )
533
+ $result = "pgp_sym_decrypt(CAST(%s as bytea), '%s')";
534
+ }
535
+ else if ( $this->connection->_encryptInfo["alg"] == ENCRYPTION_ALG_AES)
536
+ {
537
+ if( $this->connection->dbType == nDATABASE_Oracle )
538
+ {
539
+ $result = "utl_raw.cast_to_varchar2(DBMS_CRYPTO.DECRYPT(utl_raw.cast_to_raw(%s), 4358, utl_raw.cast_to_raw('%s')))";
540
+ $this->key = substr($this->key, 0, 16);
541
+ }
542
+ elseif( $this->connection->dbType == nDATABASE_MSSQLServer )
543
+ {
544
+ $result = "CAST(DecryptByKey(%s) as nvarchar(4000))";
545
+ $this->key = $field; // for use in first as parametr in mysprintf func
546
+ }
547
+ elseif( $this->connection->dbType == nDATABASE_MySQL )
548
+ $result = "cast(AES_DECRYPT(unhex(%s), '%s') as char)";
549
+ elseif( $this->connection->dbType == nDATABASE_PostgreSQL )
550
+ $result = "pgp_sym_decrypt(CAST(%s as bytea), '%s', 'cipher-algo=aes128')";
551
+ }
552
+
553
+ if($result == "")
554
+ return $field;
555
+
556
+ if( $this->connection->dbType == nDATABASE_MSSQLServer )
557
+ $result = mysprintf($result, array($this->key, $field));
558
+ else
559
+ $result = mysprintf($result, array($field, $this->key));
560
+
561
+ return $addAs ? $result." as ".$this->connection->addFieldWrappers($alias != null ? $alias : $field) : $result;
562
+ }
563
+
564
+ /**
565
+ * EncryptValueByDB
566
+ * Add to field name encryption function if field is encrypted by database
567
+ * Please note, when changing this function you should make appropriate changes in wizard method (dynamic permissions --> add new user) #8923
568
+ * @param {string} field name
569
+ * @param {mixed} value
570
+ * @return {string}
571
+ */
572
+ public function EncryptValueByDB($field, $value)
573
+ {
574
+ if( !$this->isFieldEncrypted($field) || $this->connection->isEncryptionByPHPEnabled() )
575
+ return $value;
576
+
577
+ $result = "";
578
+
579
+ if ( $this->connection->_encryptInfo["alg"] == ENCRYPTION_ALG_DES)
580
+ {
581
+ if( $this->connection->dbType == nDATABASE_Oracle )
582
+ $result = "utl_raw.cast_to_varchar2(DBMS_CRYPTO.ENCRYPT(utl_raw.cast_to_raw(%s), 4353, utl_raw.cast_to_raw('%s')))";
583
+ elseif( $this->connection->dbType == nDATABASE_MSSQLServer )
584
+ $result = "EncryptByPassPhrase(N'%s', %s)";
585
+ elseif( $this->connection->dbType == nDATABASE_MySQL )
586
+ $result = "hex(DES_ENCRYPT(%s, '%s'))";
587
+ elseif( $this->connection->dbType == nDATABASE_PostgreSQL )
588
+ $result = "pgp_sym_encrypt(%s, '%s')";
589
+ }
590
+ else if ( $this->connection->_encryptInfo["alg"] == ENCRYPTION_ALG_AES)
591
+ {
592
+ if( $this->connection->dbType == nDATABASE_Oracle )
593
+ {
594
+ $result = "utl_raw.cast_to_varchar2(DBMS_CRYPTO.ENCRYPT(utl_raw.cast_to_raw(%s), 4358, utl_raw.cast_to_raw('%s')))";
595
+ $this->key = substr($this->key, 0, 16);
596
+ }
597
+ elseif( $this->connection->dbType == nDATABASE_MSSQLServer )
598
+ {
599
+ $result = "EncryptByKey(Key_GUID('%s'), %s)";
600
+ $this->key = $this->connection->_encryptInfo["slqserverkey"];
601
+ }
602
+ elseif( $this->connection->dbType == nDATABASE_MySQL )
603
+ $result = "hex(AES_ENCRYPT(%s, '%s'))";
604
+ elseif( $this->connection->dbType == nDATABASE_PostgreSQL )
605
+ $result = "pgp_sym_encrypt(%s, '%s', 'cipher-algo=aes128')";
606
+ }
607
+
608
+ if($result != "")
609
+ {
610
+ if( $this->connection->dbType == nDATABASE_MSSQLServer )
611
+ $result = mysprintf($result, array($this->key, $value));
612
+ else
613
+ $result = mysprintf($result, array($value, $this->key));
614
+ }
615
+ else
616
+ $result = $value;
617
+
618
+ return $result;
619
+ }
620
+
621
+ /**
622
+ * EncryptField
623
+ * Determine if field need to be encrypted and encrypt value if it so
624
+ * @param {string} field name
625
+ * @param {string} value
626
+ * @return {string} encrypted or plain value
627
+ */
628
+ public function EncryptField($field, $value)
629
+ {
630
+ if( $this->isFieldEncrypted($field) && $this->connection->isEncryptionByPHPEnabled() )
631
+ {
632
+ if( is_null($this->ESFunctions) )
633
+ $this->ESFunctions = $this->getESFunctions();
634
+
635
+ return $this->ESFunctions->Encrypt($value);
636
+ }
637
+
638
+ return $value;
639
+ }
640
+
641
+ /**
642
+ * DecryptField
643
+ * Determine if field encrypted and decrypt value if it so
644
+ * Please note, when changing this function you should make appropriate changes in wizard method (dynamic permissions --> add new user) #8923
645
+ * @param {string} field name
646
+ * @param {string} value
647
+ * @return {string} decrypted or plain value
648
+ */
649
+ public function DecryptField($field, $value)
650
+ {
651
+ if($this->isFieldEncrypted($field) && $this->connection->isEncryptionByPHPEnabled())
652
+ {
653
+ if(is_null($this->ESFunctions))
654
+ $this->ESFunctions = $this->getESFunctions();
655
+
656
+ return $this->ESFunctions->Decrypt($value);
657
+ }
658
+ return $value;
659
+ }
660
+
661
+ function getESFunctions()
662
+ {
663
+ if ( $this->connection->_encryptInfo["alg"] == ENCRYPTION_ALG_DES )
664
+ return new RunnerCiphererDES($this->key);
665
+ if ( $this->connection->_encryptInfo["alg"] == ENCRYPTION_ALG_AES )
666
+ return new RunnerCiphererAES($this->key);
667
+ if ( $this->connection->_encryptInfo["alg"] == ENCRYPTION_ALG_AES_256 )
668
+ return new RunnerCiphererAES($this->key, true);
669
+ }
670
+
671
+ /**
672
+ * @param Mixed loginSet (optional)
673
+ * @return Mixed
674
+ */
675
+ public static function getForLogin( $loginSet = null )
676
+ {
677
+ if( !!Security::loginTable() ) {
678
+ return new RunnerCipherer( "public.kbusers", $loginSet);
679
+ }
680
+ return new RunnerCipherer( GLOBAL_PAGES, null);
681
+ }
682
+ }
683
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
684
  ?>
php/classes/context.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class RunnerContextItem
3
  {
@@ -620,4 +621,628 @@ class TempContext
620
  }
621
  }
622
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
623
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class RunnerContextItem
4
  {
 
621
  }
622
  }
623
 
624
+ =======
625
+ <?php
626
+ class RunnerContextItem
627
+ {
628
+ /**
629
+ * define('CONTEXT_GLOBAL', 0); // global context
630
+ * define('CONTEXT_PAGE', 1); // page where pageObject is available
631
+ * define('CONTEXT_BUTTON', 2); // button or other AJAX event
632
+ * define('CONTEXT_LOOKUP', 3); // dependent lookup
633
+ * define('CONTEXT_ROW', 4); // processing grid row on multiple-records page (list)
634
+ * define('CONTEXT_COMMAND', 5); // DsCommand context
635
+ * define('CONTEXT_SEARCH', 6); // Search object context
636
+ * define('CONTEXT_MASTER', 7); // Search object context
637
+ */
638
+ public $type;
639
+
640
+ public $pageObj;
641
+ public $data;
642
+ public $oldData;
643
+ public $newData;
644
+ public $detailsKeys;
645
+ public $dc;
646
+ public $searchClause;
647
+ public $masterData;
648
+
649
+ function __construct( $type, $params )
650
+ {
651
+ RunnerApply($this, $params);
652
+ $this->type = $type;
653
+ }
654
+
655
+ public function getType()
656
+ {
657
+ return $this->type;
658
+ }
659
+
660
+ /**
661
+ * @return Array
662
+ */
663
+ public function getValues()
664
+ {
665
+ if( $this->data )
666
+ return $this->data;
667
+
668
+ if( $this->dc ) {
669
+ return $this->dc->values;
670
+ }
671
+
672
+ if( $this->pageObj )
673
+ return $this->pageObj->getCurrentRecord();
674
+
675
+ return array();
676
+ }
677
+
678
+ /**
679
+ * @param String field
680
+ * @return Mixed
681
+ */
682
+ public function getFieldValue( $field )
683
+ {
684
+ $data = $this->getValues();
685
+ return getArrayElementNC( $data, $field );
686
+ }
687
+
688
+ public function getSearchValue( $field ) {
689
+ return $this->searchClause->_getFieldValue( $field, null, false, true );
690
+ }
691
+
692
+ public function getAllSearchValue() {
693
+ return $this->searchClause->getAllFieldsSearchValue();
694
+ }
695
+
696
+ /**
697
+ * @return Array
698
+ */
699
+ public function getOldValues()
700
+ {
701
+ if( $this->oldData )
702
+ return $this->oldData;
703
+
704
+ if( $this->pageObj )
705
+ return $this->pageObj->getOldRecordData();
706
+
707
+ return array();
708
+ }
709
+
710
+ public function getKeyValue( $field ) {
711
+ if( $this->dc ) {
712
+ return $this->dc->keys[ $field ];
713
+ }
714
+ return null;
715
+ }
716
+
717
+ public function getOrderValue( $key ) {
718
+ if( !$this->dc ) {
719
+ return null;
720
+ }
721
+ $idx = 0;
722
+ if( substr( $key, 0, 5) == "field" ) {
723
+ $param = "field";
724
+ $idx = (int)substr( $key, 5);
725
+ } else if( substr( $key, 0, 3 ) == "dir" ) {
726
+ $param = "dir";
727
+ $idx = (int)substr( $key, 3);
728
+ }
729
+ if( !$idx || $idx < 1 ) {
730
+ return null;
731
+ }
732
+ if( count( $this->dc->order ) <= $idx ) {
733
+ return null;
734
+ }
735
+ $order = $this->dc->order[ $idx - 1 ];
736
+ if( $param == "field") {
737
+ return $order["column"];
738
+ }
739
+ if( $param == "dir") {
740
+ return $order["dir"];
741
+ }
742
+ return null;
743
+ }
744
+
745
+
746
+ public function getFilterValue( $field ) {
747
+ if( $this->dc ) {
748
+ return $this->dc->findFieldFilterValue( $field );
749
+ }
750
+ }
751
+
752
+ public function getLimitValue( $key ) {
753
+ if( !$this->dc ) {
754
+ return "";
755
+ }
756
+ if( $key == "record_from" ) {
757
+ return $this->dc->startRecord + 1;
758
+ }
759
+ if( $key == "record_to" ) {
760
+ return $this->dc->startRecord + $this->dc->reccount;
761
+ }
762
+ if( $key == "record_count" ) {
763
+ return $this->dc->reccount;
764
+ }
765
+ if( $key == "record_offset" ) {
766
+ return $this->dc->startRecord;
767
+ }
768
+ }
769
+
770
+
771
+ /**
772
+ * @param String field
773
+ * @return Mixed
774
+ */
775
+ public function getOldFieldValue( $field )
776
+ {
777
+ $oldData = $this->getOldValues();
778
+ return getArrayElementNC( $oldData, $field );
779
+ }
780
+
781
+ /**
782
+ * @param String field
783
+ * @return Mixed
784
+ */
785
+ public function getNewFieldValue( $field )
786
+ {
787
+ if ( $this->newData )
788
+ return getArrayElementNC( $this->newData, $field );
789
+ if( $this->dc ) {
790
+ return getArrayElementNC( $this->dc->values, $field );
791
+ }
792
+
793
+ return $this->getFieldValue( $field );
794
+ }
795
+
796
+
797
+
798
+ /**
799
+ * @return Array
800
+ */
801
+ public function getMasterValues()
802
+ {
803
+ if( $this->masterData )
804
+ return $this->masterData;
805
+
806
+ if( $this->pageObj )
807
+ return $this->pageObj->getMasterRecord();
808
+
809
+ return array();
810
+ }
811
+
812
+ /**
813
+ * @param String field
814
+ * @return Mixed
815
+ */
816
+ public function getMasterFieldValue( $field )
817
+ {
818
+ $masterData = $this->getMasterValues();
819
+ if( !$masterData ) {
820
+ return "";
821
+ }
822
+ return getArrayElementNC( $masterData, $field );
823
+
824
+ }
825
+
826
+ /**
827
+ * @param String key
828
+ * @return String
829
+ */
830
+ public function getUserValue( $key )
831
+ {
832
+ return getArrayElementNC( Security::currentUserData(), $key );
833
+ }
834
+
835
+ /**
836
+ * @param String key
837
+ * @return Mixed
838
+ */
839
+ public function getSessionValue( $key )
840
+ {
841
+ return getSessionElementNC( $key );
842
+ }
843
+
844
+ public function getDetailsKeyValue( $key ) {
845
+ return $this->detailsKeys[ $key ];
846
+ }
847
+
848
+
849
+ /**
850
+ * Returns true if context must serve this scope, and search must stop here.
851
+ * For example, when page context is found, it must serve the 'master' and 'details' scopes even if no master-detail is in effect.
852
+ * @param String - scope like 'keys', 'master', 'details'
853
+ * @return Boolean
854
+ */
855
+ public function hasScope( $scope ) {
856
+ if( $scope == "master" )
857
+ return $this->masterData || $this->type == CONTEXT_PAGE;
858
+
859
+ if( $scope == "session" )
860
+ return true;
861
+
862
+ if( $scope == "user" )
863
+ return true;
864
+
865
+ if( $scope == "old" )
866
+ return $this->oldData || $this->type == CONTEXT_PAGE;
867
+
868
+ if( $scope == "keys" )
869
+ return $this->type == CONTEXT_COMMAND;
870
+
871
+ if( $scope == "order" )
872
+ return $this->type == CONTEXT_COMMAND;
873
+
874
+
875
+ if( $scope == "new" )
876
+ return $this->newData || $this->type == CONTEXT_PAGE || $this->type == CONTEXT_COMMAND;
877
+
878
+ if ( $scope == "global" )
879
+ return true;
880
+
881
+ if( $scope == "details" )
882
+ return $this->type == CONTEXT_PAGE || $this->type == CONTEXT_MASTER;
883
+
884
+ if ( $scope == "values" )
885
+ return !!$this->data || $this->type == CONTEXT_PAGE || $this->type == CONTEXT_COMMAND;
886
+
887
+ if( $scope == "search" )
888
+ return $this->type == CONTEXT_SEARCH;
889
+
890
+ if( $scope == "filter" )
891
+ return $this->type == CONTEXT_COMMAND;
892
+
893
+ if( $scope == "request" )
894
+ return true;
895
+
896
+ if( $scope == "limit" )
897
+ return $this->type == CONTEXT_COMMAND;
898
+
899
+ if( $scope == "all_field_search" )
900
+ return $this->type == CONTEXT_SEARCH;
901
+ }
902
+
903
+ /**
904
+ * @param String key
905
+ * @return Mixed
906
+ */
907
+ public function getContextValue( $scope, $key )
908
+ {
909
+
910
+ if( $scope == "master" )
911
+ return $this->getMasterFieldValue( $key );
912
+
913
+ if( $scope == "session" )
914
+ return $this->getSessionValue( $key );
915
+
916
+ if( $scope == "user" )
917
+ return $this->getUserValue( $key );
918
+
919
+ if( $scope == "old" )
920
+ return $this->getOldFieldValue( $key );
921
+
922
+ if( $scope == "keys" )
923
+ return $this->getKeyValue( $key );
924
+
925
+ if( $scope == "order" )
926
+ return $this->getOrderValue( $key );
927
+
928
+ if( $scope == "new" )
929
+ return $this->getNewFieldValue( $key );
930
+
931
+ if ( $scope == "global" && $key == "language" )
932
+ return mlang_getcurrentlang();
933
+
934
+ if( $scope == "details" ) {
935
+ if( $this->type == CONTEXT_PAGE )
936
+ return $this->pageObj->getDetailsKeyValue( $key );
937
+ if( $this->type == CONTEXT_MASTER )
938
+ return $this->getDetailsKeyValue( $key );
939
+ }
940
+
941
+ if( $scope == "values" )
942
+ return $this->getFieldValue( $key );
943
+
944
+ if( $scope == "search" )
945
+ return $this->getSearchValue( $key );
946
+
947
+ if( $scope == "filter" )
948
+ return $this->getFilterValue( $key );
949
+
950
+ if( $scope == "request" )
951
+ return postvalue( $key );
952
+
953
+ if( $scope == "limit" )
954
+ return $this->getLimitValue( $key );
955
+
956
+ if( $scope == "all_field_search" )
957
+ return $this->getAllSearchValue();
958
+
959
+ return false;
960
+ }
961
+ }
962
+
963
+ /**
964
+ * Singletone. All public functions are static
965
+ */
966
+ class RunnerContext
967
+ {
968
+ protected $stack = array();
969
+
970
+ public function __construct( )
971
+ {
972
+ $context = new RunnerContextItem( CONTEXT_GLOBAL, array() );
973
+ $this->stack[ count($this->stack) ] = $context;
974
+ }
975
+
976
+ public static function push( $context )
977
+ {
978
+ global $contextStack;
979
+ $contextStack->stack[ count($contextStack->stack) ] = $context;
980
+ }
981
+
982
+ public static function current( )
983
+ {
984
+ global $contextStack;
985
+ return $contextStack->stack[ count($contextStack->stack) - 1 ];
986
+ }
987
+
988
+ public static function pop( )
989
+ {
990
+ global $contextStack;
991
+
992
+ // this sometimes happens during the error reporting
993
+ if( !$contextStack->stack )
994
+ return null;
995
+
996
+ $context = $contextStack->stack[ count($contextStack->stack) - 1 ];
997
+ unset( $contextStack->stack[ count($contextStack->stack) - 1 ] );
998
+
999
+ return $context;
1000
+ }
1001
+
1002
+ // Utility functions
1003
+ /**
1004
+ * Shortcut for adding page-based context
1005
+ */
1006
+ public static function pushPageContext( $pageObj ) {
1007
+ RunnerContext::push( new RunnerContextItem( CONTEXT_PAGE, array( "pageObj" => $pageObj ) ) );
1008
+ }
1009
+ /**
1010
+ * Shortcut for adding record-based context
1011
+ */
1012
+ public static function pushRecordContext( $record, $pageObj ) {
1013
+ RunnerContext::push( new RunnerContextItem( CONTEXT_ROW, array( "pageObj" => $pageObj, "data" => $record ) ) ); //?
1014
+ }
1015
+
1016
+ public static function pushDataCommandContext( $dc ) {
1017
+ RunnerContext::push( new RunnerContextItem( CONTEXT_COMMAND, array( "dc" => $dc ) ) );
1018
+ }
1019
+
1020
+ public static function pushSearchContext( $searchClause ) {
1021
+ RunnerContext::push( new RunnerContextItem( CONTEXT_SEARCH, array( "searchClause" => $searchClause ) ) );
1022
+ }
1023
+
1024
+ public static function pushMasterContext( $detailsKeys ) {
1025
+ RunnerContext::push( new RunnerContextItem(
1026
+ CONTEXT_MASTER,
1027
+ array(
1028
+ "detailsKeys" => $detailsKeys,
1029
+ ) ) );
1030
+ }
1031
+
1032
+
1033
+ public static function getMasterValues() {
1034
+ $ctx = RunnerContext::current();
1035
+ return $ctx->getMasterValues();
1036
+ }
1037
+
1038
+ public static function getValues() {
1039
+ $ctx = RunnerContext::current();
1040
+ return $ctx->getValues();
1041
+ }
1042
+
1043
+ /**
1044
+ * @return String
1045
+ */
1046
+ public static function PrepareRest( $str, $urlenc = true ) {
1047
+ $context = RunnerContext::current();
1048
+ $tokens = DB::scanTokenString($str);
1049
+
1050
+ $replacements = array();
1051
+ // build array of replacements in this format:
1052
+ // "offset" => position in the string where replacement should be done
1053
+ // "len" => length of original substring to cut out
1054
+ // "insert" => string to insert in place of cut out
1055
+
1056
+ foreach ($tokens["matches"] as $i => $match) {
1057
+ $offset = $tokens["offsets"][$i];
1058
+ $token = $tokens["tokens"][$i];
1059
+
1060
+ $repl = array(
1061
+ "offset" => $offset,
1062
+ "len" => strlen($match)
1063
+ );
1064
+ $val = "";
1065
+ if (is_numeric($token) && count( $args ) > $token) {
1066
+ $val = $args[(int)$token];
1067
+ } else {
1068
+ $val = RunnerContext::getValue($token);
1069
+ }
1070
+ if( $urlenc )
1071
+ $val = rawurlencode($val);
1072
+ $repl["insert"] = $val;
1073
+
1074
+ $replacements[] = $repl;
1075
+ }
1076
+ // do replacements
1077
+ return RunnerContext::doReplacements( $str, $replacements );
1078
+ }
1079
+
1080
+ /**
1081
+ * locate all <? - ?> snippets in a string
1082
+ * @param String str
1083
+ * @return Array of array(
1084
+ * "offset" => integer - offset of the opening bracket in the original string
1085
+ * "len" => integer - length includes opening and closing brackets: <? - ?>
1086
+ * )
1087
+ */
1088
+ protected static function getOptionalBlocks( $str ) {
1089
+ if( !is_string( $str ) )
1090
+ return array();
1091
+
1092
+ $snippetStack = array();
1093
+ $snippets = array();
1094
+ $pos = strpos( $str, '<?' );
1095
+ if( $pos === false )
1096
+ return array();
1097
+
1098
+ while( true ) {
1099
+ $snippetStack[] = $pos;
1100
+ $newPos = strpos( $str, '<?', $pos + 1 );
1101
+
1102
+ /* locate all ?> before the next <? or end of string*/
1103
+ $tailLen = ( $newPos !== false ? $newPos : strlen( $str ) ) - $pos;
1104
+ $tail = substr( $str, $pos, $tailLen );
1105
+ $endPos = 0;
1106
+ while( ($endPos = strpos( $tail, '?>', $endPos+1 ) ) !== false && count( $snippetStack ) ) {
1107
+ $stackIdx = count( $snippetStack ) - 1;
1108
+ $snippets[] = array( "offset" => $snippetStack[ $stackIdx ], "len" => $endPos + $pos + 2 - $snippetStack[ $stackIdx ] );
1109
+ $snippetStack = array_slice( $snippetStack, 0, $stackIdx );
1110
+ }
1111
+ if( $newPos === false )
1112
+ break;
1113
+ $pos = $newPos;
1114
+ }
1115
+ return $snippets;
1116
+ }
1117
+
1118
+ /**
1119
+ * do actual replacements
1120
+ * @param String $str - source string
1121
+ * @param Array $replacements - Array of Array(
1122
+ * "offset" => Integer, position in the source tring
1123
+ * "len" => Integer, length of the source string portion to be replaced
1124
+ * "insert" => String, value to insert instead of replaced
1125
+ * )
1126
+ */
1127
+ public static function doReplacements( $str, $replacements ) {
1128
+ if( !is_string( $str ) )
1129
+ return $str;
1130
+
1131
+ $snippets = RunnerContext::getOptionalBlocks( $str );
1132
+ /* snippets with 0 non-empty requirements must be deleted from the string */
1133
+ /* mark empty snippets */
1134
+ for( $i=0; $i < count( $snippets ); ++$i ) {
1135
+ $s = &$snippets[$i];
1136
+ $s["empty"] = true;
1137
+ foreach ($replacements as $r) {
1138
+ /* replacement inside snippet */
1139
+ if( $r["offset"] > $s["offset"] && $r["offset"] < $s["offset"] + $s["len"] ) {
1140
+ if( $r["insert"] != "" ) {
1141
+ $s["empty"] = false;
1142
+ break;
1143
+ }
1144
+ }
1145
+ }
1146
+ }
1147
+
1148
+ /* do replacements */
1149
+ $offsetShift = 0;
1150
+ foreach ($replacements as $r) {
1151
+ $str = substr_replace($str, $r["insert"], $r["offset"] + $offsetShift, $r["len"]);
1152
+ $offsetDelta = strlen($r["insert"]) - $r["len"];
1153
+ // update all $snippets
1154
+ RunnerContext::updateOptionalBlockOffset( $snippets, $r["offset"], $offsetDelta );
1155
+ $offsetShift += $offsetDelta;
1156
+ }
1157
+
1158
+ /* process optional blocks - delete or remove brackets */
1159
+ for( $i=0; $i < count( $snippets ); ++$i ) {
1160
+ $s = &$snippets[$i];
1161
+ if( $s["empty"]) {
1162
+ $str = substr_replace($str, "", $s["offset"], $s["len"] );
1163
+ $offsetDelta = -$s["len"];
1164
+ } else {
1165
+ $str = substr_replace($str,
1166
+ substr( $str, $s["offset"] + 2, $s["len"] - 4 ),
1167
+ $s["offset"],
1168
+ $s["len"]
1169
+ );
1170
+ $offsetDelta = -4;
1171
+ }
1172
+ RunnerContext::updateOptionalBlockOffset( $snippets, $s["offset"], $offsetDelta );
1173
+ }
1174
+ return $str;
1175
+ }
1176
+
1177
+ protected static function updateOptionalBlockOffset( &$snippets, $offset, $delta ) {
1178
+ for( $i=0; $i < count( $snippets ); ++$i ) {
1179
+ $s = &$snippets[$i];
1180
+ if( $s["offset"] > $offset ) {
1181
+ $s["offset"] += $delta;
1182
+ } else {
1183
+ if( $s["offset"] + $s["len"] > $offset ) {
1184
+ $s["len"] += $delta;
1185
+ }
1186
+ }
1187
+ }
1188
+ }
1189
+
1190
+
1191
+ public static function getValue( $key ) {
1192
+ $prefix = "";
1193
+ $dotPos = strpos( $key, ".");
1194
+ if( $dotPos !== FALSE )
1195
+ {
1196
+ $scope = strtolower( substr( $key, 0, $dotPos ) );
1197
+ $key = substr( $key, $dotPos + 1 );
1198
+ } else {
1199
+ if( $key === "language" ) {
1200
+ $scope = "global";
1201
+ } else if( $key == "all_field_search") {
1202
+ $scope = $key;
1203
+ } else {
1204
+ $scope = "values";
1205
+ }
1206
+
1207
+ }
1208
+ return RunnerContext::_getValue( $scope, $key );
1209
+ }
1210
+
1211
+
1212
+ /**
1213
+ * Search got requested value in the stack of contexts
1214
+ * @param String - scope like 'keys', 'master', 'details'
1215
+ * @param String - key. 'details.teamId' is translated to context=details, key=teamId
1216
+ * @return String or false if value is not found
1217
+ */
1218
+ protected static function _getValue( $scope, $key )
1219
+ {
1220
+ global $contextStack;
1221
+ $idx = count( $contextStack->stack );
1222
+ while( $idx > 0 ) {
1223
+ $ctx = $contextStack->stack[ --$idx ];
1224
+ if( $ctx->hasScope( $scope ) ) {
1225
+ return $ctx->getContextValue( $scope, $key );
1226
+ }
1227
+ }
1228
+ return false;
1229
+ }
1230
+
1231
+ }
1232
+
1233
+ /**
1234
+ * Push context in constructor and pop in destructor
1235
+ */
1236
+ class TempContext
1237
+ {
1238
+ function __construct( $context ) {
1239
+ RunnerContext::push( $context );
1240
+ }
1241
+
1242
+ function __destruct() {
1243
+ RunnerContext::pop();
1244
+ }
1245
+ }
1246
+
1247
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
1248
  ?>
php/classes/controls/CheckboxField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class CheckboxField extends EditControl
3
  {
@@ -88,4 +89,96 @@ class CheckboxField extends EditControl
88
  return CheckboxField::getFieldCondition( $this->field, $searchFor );
89
  }
90
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class CheckboxField extends EditControl
4
  {
 
89
  return CheckboxField::getFieldCondition( $this->field, $searchFor );
90
  }
91
  }
92
+ =======
93
+ <?php
94
+ class CheckboxField extends EditControl
95
+ {
96
+ function __construct($field, $pageObject, $id, $connection)
97
+ {
98
+ parent::__construct($field, $pageObject, $id, $connection);
99
+ $this->format = EDIT_FORMAT_CHECKBOX;
100
+ }
101
+
102
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
103
+ {
104
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
105
+ if($mode == MODE_ADD || $mode == MODE_INLINE_ADD || $mode == MODE_EDIT || $mode == MODE_INLINE_EDIT)
106
+ {
107
+ $checked = "";
108
+
109
+ if( $this->connection->dbType == nDATABASE_PostgreSQL
110
+ && ($value === "t" || $value != "f" && $value != "" && $value != 0 )
111
+ || $this->connection->dbType != nDATABASE_PostgreSQL && ($value != "" && $value != 0 )) {
112
+
113
+ $checked=" checked";
114
+ }
115
+
116
+ if ( $this->connection->dbType == nDATABASE_PostgreSQL ) {
117
+ $reservedBoolean = 'data-true="t" data-false="f"';
118
+ }
119
+
120
+ echo '<span class="checkbox r-checkbox-control"><label>';
121
+
122
+ echo '<input id="'.$this->ctype.'" type="hidden" name="'.$this->ctype.'" value="checkbox">';
123
+ echo '<input id="'.$this->cfield.'" type="Checkbox" '
124
+ .(($mode == MODE_INLINE_EDIT || $mode == MODE_INLINE_ADD) && $this->is508==true ? 'alt="'.$this->strLabel.'" ' : '')
125
+ .'name="'.$this->cfield.'" '.$checked.' '.$reservedBoolean.'>';
126
+
127
+ echo '</label></span>';
128
+ }
129
+ else
130
+ {
131
+ echo '<input id="'.$this->ctype.'" type="hidden" name="'.$this->ctype.'" value="checkbox">';
132
+ echo '<select id="'.$this->cfield.'" '.(($mode == MODE_INLINE_EDIT || $mode == MODE_INLINE_ADD) && $this->is508==true ? 'alt="'
133
+ .$this->strLabel.'" ' : '').'name="'.$this->cfield.'" class="form-control">';
134
+
135
+ $options = array( "", "on", "off" );
136
+ $possibleOptions = array( "" => array(), "on" => array("on", "1"), "off" => array("off", "0") );
137
+ $labels = array("", "True", "False");
138
+
139
+ foreach( $options as $key => $optValue )
140
+ {
141
+ $selected = in_array( $value, $possibleOptions[ $optValue ] ) ? " selected" : "";
142
+ echo '<option value="' . $optValue . '"' . $selected.'>' . $labels[ $key ] . '</option>';
143
+ }
144
+
145
+ echo "</select>";
146
+ }
147
+ $this->buildControlEnd($validate, $mode);
148
+ }
149
+
150
+ function getFirstElementId()
151
+ {
152
+ return $this->cfield;
153
+ }
154
+
155
+ /**
156
+ * Get 'equal to on/off' condition
157
+ */
158
+ public static function getFieldCondition( $field, $searchFor ) {
159
+ if( $searchFor == "none" || $searchFor != "on" && $searchFor != "off" )
160
+ return null;
161
+
162
+ $offCondition = DataCondition::_Or( array(
163
+ DataCondition::FieldIs( $field, dsopEQUAL, '0', false, 0, null, false ),
164
+ DataCondition::FieldIs( $field, dsopEMPTY, '', false, 0, null, false )
165
+ ));
166
+
167
+ if( $searchFor == "off" )
168
+ return $offCondition;
169
+
170
+ return DataCondition::_Not( $offCondition );
171
+ }
172
+
173
+ /**
174
+ * Returns basic condition
175
+ */
176
+ public function getBasicFieldCondition( $searchFor, $strSearchOption, $searchFor2 = "", $etype = "" ) {
177
+ if( $strSearchOption != EQUALS )
178
+ return null;
179
+
180
+ return CheckboxField::getFieldCondition( $this->field, $searchFor );
181
+ }
182
+ }
183
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
184
  ?>
php/classes/controls/Control.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class EditControl
3
  {
@@ -787,4 +788,795 @@ class EditControl
787
  }
788
 
789
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
790
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class EditControl
4
  {
 
788
  }
789
 
790
  }
791
+ =======
792
+ <?php
793
+ class EditControl
794
+ {
795
+ /**
796
+ * Reference to RunnerPage (or its descendant) instance
797
+ */
798
+ public $pageObject = null;
799
+ /**
800
+ * Reference to EditControlsContainer instance
801
+ */
802
+ public $container = null;
803
+
804
+ public $id = "";
805
+ public $field = "";
806
+ public $goodFieldName = "";
807
+ public $format = "";
808
+ /**
809
+ * Field name prefix
810
+ * @var {string}
811
+ */
812
+ public $cfieldname = "";
813
+ /**
814
+ * Value field name
815
+ * @var {string}
816
+ */
817
+ public $cfield = "";
818
+ /**
819
+ * Type field name
820
+ * @var {string}
821
+ */
822
+ public $ctype = "";
823
+ /**
824
+ * A flag indicating whether the support for section 508 is on
825
+ * @var {bool}
826
+ */
827
+ public $is508 = false;
828
+ public $strLabel = "";
829
+ public $type = "";
830
+ public $inputStyle = "";
831
+ public $iquery = "";
832
+ public $keylink = "";
833
+ public $webValue = null;
834
+ public $webType = null;
835
+
836
+ /**
837
+ * Storage for control settings. It fills in the init() function.
838
+ * @var {array}
839
+ */
840
+ public $settings = array();
841
+
842
+ //Search params
843
+ public $isOracle = false;
844
+ public $ismssql = false;
845
+ public $isdb2 = false;
846
+ public $btexttype = false;
847
+ public $isMysql = false;
848
+ public $like = "like";
849
+
850
+ public $searchOptions = array();
851
+
852
+ public $searchPanelControl = false;
853
+ public $data = array();
854
+
855
+ /**
856
+ * @type Connection
857
+ */
858
+ protected $connection;
859
+
860
+ public $forSpreadsheetGrid;
861
+
862
+
863
+ function __construct($field, $pageObject, $id, $connection)
864
+ {
865
+ $this->field = $field;
866
+ $this->goodFieldName = GoodFieldName($field);
867
+ $this->setID($id);
868
+ $this->connection = $connection;
869
+
870
+ $this->pageObject = $pageObject;
871
+
872
+ $this->is508 = isEnableSection508();
873
+
874
+ $this->strLabel = $pageObject->pSetEdit->label($field);
875
+ $this->type = $pageObject->pSetEdit->getFieldType($this->field);
876
+
877
+ if( $this->connection->dbType == nDATABASE_Oracle )
878
+ $this->isOracle = true;
879
+
880
+ if( $this->connection->dbType == nDATABASE_MSSQLServer )
881
+ $this->ismssql=true;
882
+
883
+ if( $this->connection->dbType == nDATABASE_DB2 )
884
+ $this->isdb2=true;
885
+
886
+ if( $this->connection->dbType == nDATABASE_MySQL )
887
+ $this->isMysql = true;
888
+
889
+ if( $this->connection->dbType == nDATABASE_PostgreSQL )
890
+ $this->like = "ilike";
891
+
892
+ $this->searchOptions[CONTAINS] = "Contains";
893
+ $this->searchOptions[EQUALS] = "Equals";
894
+ $this->searchOptions[STARTS_WITH] = "Starts with";
895
+ $this->searchOptions[MORE_THAN] = "More than";
896
+ $this->searchOptions[LESS_THAN] = "Less than";
897
+ $this->searchOptions[BETWEEN] = "Between";
898
+ $this->searchOptions[EMPTY_SEARCH] = "Empty";
899
+ $this->searchOptions[NOT_CONTAINS] = "Doesn't contain";
900
+ $this->searchOptions[NOT_EQUALS] = "Doesn't equal";
901
+ $this->searchOptions[NOT_STARTS_WITH] = "Doesn't start with";
902
+ $this->searchOptions[NOT_MORE_THAN] = "Is not more than";
903
+ $this->searchOptions[NOT_LESS_THAN] = "Is not less than";
904
+ $this->searchOptions[NOT_BETWEEN] = "Is not between";
905
+ $this->searchOptions[NOT_EMPTY] = "Is not empty";
906
+
907
+ $this->init();
908
+ }
909
+
910
+ function setID($id)
911
+ {
912
+ $this->id = $id;
913
+ $this->cfieldname = $this->goodFieldName."_".$id;
914
+ $this->cfield = "value_".$this->goodFieldName."_".$id;
915
+ $this->ctype = "type_".$this->goodFieldName."_".$id;
916
+ }
917
+
918
+ /**
919
+ * addJSFiles
920
+ * Add control JS files to page object
921
+ */
922
+ function addJSFiles()
923
+ {
924
+ //example
925
+ // $this->pageObject->AddJSFile("include/mupload.js");
926
+ }
927
+
928
+ /**
929
+ * addCSSFiles
930
+ * Add control CSS files to page object
931
+ */
932
+ function addCSSFiles()
933
+ {
934
+ //example
935
+ // $this->pageObject->AddCSSFile("include/mupload.css");
936
+ }
937
+
938
+ function getSetting($key)
939
+ {
940
+ return $this->pageObject->pSetEdit->getFieldData($this->field, $key);
941
+ }
942
+
943
+ function addJSSetting($key, $value)
944
+ {
945
+ $this->pageObject->jsSettings['tableSettings'][ $this->pageObject->tName ]['fieldSettings'][ $this->field ][ $this->container->pageType ][ $key ] = $value;
946
+ }
947
+
948
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
949
+ {
950
+ $this->searchPanelControl = $this->isSearchPanelControl( $mode, $additionalCtrlParams );
951
+ $this->inputStyle = $this->getInputStyle( $mode );
952
+
953
+ if($fieldNum)
954
+ {
955
+ $this->cfield="value".$fieldNum."_".$this->goodFieldName."_".$this->id;
956
+ $this->ctype="type".$fieldNum."_".$this->goodFieldName."_".$this->id;
957
+ }
958
+
959
+ $this->iquery = "field=".rawurlencode($this->field);
960
+
961
+ $arrKeys = $this->pageObject->pSetEdit->getTableKeys();
962
+ for ($j = 0; $j < count($arrKeys); $j++)
963
+ {
964
+ $this->keylink .= "&key".($j+1)."=".rawurlencode( $data[ $arrKeys[$j] ] );
965
+ }
966
+ $this->iquery .= $this->keylink;
967
+
968
+ $isHidden = (isset($additionalCtrlParams['hidden']) && $additionalCtrlParams['hidden']);
969
+
970
+ $additionalClass = "";
971
+ if( $this->pageObject->isBootstrap() )
972
+ {
973
+ if( $this->pageObject->isPD() ) {
974
+ $additionalClass.= "bs-ctrlspan ";
975
+ } else {
976
+ $additionalClass.= "bs-ctrlspan rnr-nowrap ";
977
+ }
978
+ if( $this->format == EDIT_FORMAT_READONLY )
979
+ $additionalClass.= "form-control-static ";
980
+
981
+ if( $validate['basicValidate'] && array_search('IsRequired', $validate['basicValidate']) !== false )
982
+ $additionalClass.= "bs-inlinerequired";
983
+ }
984
+ else
985
+ {
986
+ $additionalClass.= "rnr-nowrap ";
987
+ }
988
+
989
+ echo '<span id="edit'.$this->id.'_'.$this->goodFieldName.'_'.$fieldNum.'" class="'.$additionalClass.'"'.($isHidden ? ' style="display:none"' : '').'>';
990
+ }
991
+
992
+ function getFirstElementId()
993
+ {
994
+ return false;
995
+ }
996
+
997
+ /**
998
+ * Check if the control belongs to the Search Panel
999
+ * @param Number mode
1000
+ * @param Array additionalCtrlParams
1001
+ * @return Boolean
1002
+ */
1003
+ function isSearchPanelControl( $mode, $additionalCtrlParams )
1004
+ {
1005
+ return $mode == MODE_SEARCH && isset( $additionalCtrlParams['searchPanelControl'] ) && $additionalCtrlParams['searchPanelControl'] && !$this->pageObject->mobileTemplateMode();
1006
+ }
1007
+
1008
+ function buildControlEnd($validate, $mode)
1009
+ {
1010
+ if( $this->pageObject->isBootstrap() )
1011
+ echo '</span>';
1012
+ else if( $validate['basicValidate'] && array_search('IsRequired', $validate['basicValidate'])!==false)
1013
+ echo'&nbsp;<font color="red">*</font></span>';
1014
+ else
1015
+ echo '</span>';
1016
+ }
1017
+
1018
+ function getPostValueAndType()
1019
+ {
1020
+ $this->webValue = postvalue("value_".$this->goodFieldName."_".$this->id);
1021
+ $this->webType = postvalue("type_".$this->goodFieldName."_".$this->id);
1022
+ }
1023
+
1024
+ function getWebValue()
1025
+ {
1026
+ return $this->webValue;
1027
+ }
1028
+
1029
+ function readWebValue(&$avalues, &$blobfields, $legacy1, $legacy2, &$filename_values)
1030
+ {
1031
+ $this->getPostValueAndType();
1032
+
1033
+ if (FieldSubmitted($this->goodFieldName."_".$this->id))
1034
+ $this->webValue = prepare_for_db($this->field, $this->webValue, $this->webType);
1035
+ else
1036
+ $this->webValue = false;
1037
+
1038
+ if($this->pageObject->pageType == PAGE_EDIT && $this->pageObject->getEditFormat( $this->field) === EDIT_FORMAT_READONLY )
1039
+ {
1040
+ // ??
1041
+ if( $this->pageObject->pSetEdit->getAutoUpdateValue($this->field) )
1042
+ $this->webValue = $this->pageObject->pSetEdit->getAutoUpdateValue($this->field);
1043
+ else if( !originalTableField( $this->field, $this->pageObject->pSetEdit ) ){
1044
+ $this->webValue = false;
1045
+ }
1046
+ }
1047
+
1048
+ if(!($this->webValue===false))
1049
+ {
1050
+ if( $this->connection->dbType == nDATABASE_Informix )
1051
+ {
1052
+ if(IsTextType($this->pageObject->pSetEdit->getFieldType($this->field)))
1053
+ $blobfields[] = $this->field;
1054
+ }
1055
+ $avalues[ $this->field ] = $this->webValue;
1056
+ }
1057
+ }
1058
+
1059
+ /**
1060
+ * Get the substitute columns list for the SELECT Clause and the FORM clause part
1061
+ * that will be joined to the basic page's FROM clause
1062
+ * @param String searchFor
1063
+ * @param String searchOpt
1064
+ * @param Boolean isSuggest
1065
+ * @return Array
1066
+ */
1067
+ public function getSelectColumnsAndJoinFromPart($searchFor, $searchOpt, $isSuggest)
1068
+ {
1069
+ return array(
1070
+ "selectColumns"=> $this->getFieldSQLDecrypt(),
1071
+ "joinFromPart"=> ""
1072
+ );
1073
+ }
1074
+
1075
+ /**
1076
+ * @param String strSearchOption
1077
+ * @return Boolean
1078
+ */
1079
+ public function checkIfDisplayFieldSearch( $strSearchOption )
1080
+ {
1081
+ return false;
1082
+ }
1083
+
1084
+ /**
1085
+ * Form the control's search options markup basing on user's search options settings
1086
+ * @param Array optionsArray Control specified search options
1087
+ * @param String selOpt The control selected search option
1088
+ * @param Boolean not It indicates if the search option passed should be inverted ($selOpt should be considered as "NOT ".$selOpt)
1089
+ * @param Boolean both It indicates if control needs both positive and negative("NOT ...") search options
1090
+ * @return String
1091
+ */
1092
+ function buildSearchOptions($optionsArray, $selOpt, $not, $both)
1093
+ {
1094
+ $userSearchOptions = $this->pageObject->pSetEdit->getSearchOptionsList( $this->field );
1095
+
1096
+ $currentOption = $not ? 'NOT '.$selOpt : $selOpt;
1097
+ if( $userSearchOptions && isset( $this->searchOptions[ $currentOption ] ) )
1098
+ $userSearchOptions[] = $currentOption;
1099
+
1100
+ if( !!$userSearchOptions )
1101
+ $optionsArray = array_intersect($optionsArray, $userSearchOptions);
1102
+
1103
+ $defaultOption = $this->pageObject->pSetEdit->getDefaultSearchOption( $this->field );
1104
+ if( !$defaultOption )
1105
+ $defaultOption = $optionsArray[0];
1106
+
1107
+ $result = '';
1108
+ foreach($optionsArray as $option)
1109
+ {
1110
+ if( !isset( $this->searchOptions[ $option ] ) || !$both && substr($option, 0, 4) == 'NOT ' )
1111
+ continue;
1112
+
1113
+ $selected = $currentOption == $option ? 'selected' : '';
1114
+ $dataAttr = $defaultOption == $option ? ' data-default-option="true"' : '';
1115
+ $result.= '<option value="'.$option.'" '.$selected.$dataAttr.'>'.$this->searchOptions[ $option ].'</option>';
1116
+ }
1117
+ return $result;
1118
+ }
1119
+
1120
+ /**
1121
+ * Form the control specified search options array and built the control's search options markup
1122
+ * @param String selOpt The search option value
1123
+ * @param Boolean not It indicates if the search option negation is set
1124
+ * @param Boolean both It indicates if the control needs 'NOT'-options
1125
+ * @return String A string containing options markup
1126
+ */
1127
+ function getSearchOptions($selOpt, $not, $both)
1128
+ {
1129
+ return $this->buildSearchOptions(array(EQUALS, NOT_EQUALS), $selOpt, $not, $both);
1130
+ }
1131
+
1132
+ /**
1133
+ * Fill the response array with the suggest values
1134
+ *
1135
+ * @param String value
1136
+ * Note: value is preceeded with "_"
1137
+ * @param String searchFor
1138
+ * @param &Array response
1139
+ * @param &Array row
1140
+ */
1141
+ function suggestValue($value, $searchFor, &$response, &$row)
1142
+ {
1143
+ $suggestStringSize = GetGlobalData("suggestStringSize", 40);
1144
+
1145
+ if( $suggestStringSize <= runner_strlen($searchFor) )
1146
+ {
1147
+ $response[ "_".$searchFor ] = $searchFor;
1148
+ return;
1149
+ }
1150
+
1151
+ $viewFormat = $this->pageObject->pSetEdit->getViewFormat($this->field);
1152
+ if( $viewFormat == FORMAT_NUMBER )
1153
+ {
1154
+ $dotPosition = strpos($value, '.');
1155
+ if($dotPosition !== FALSE)
1156
+ {
1157
+ for($i = strlen($value) - 1; $i > $dotPosition; $i--)
1158
+ {
1159
+ if(substr($value, $i, 1) != '0')
1160
+ {
1161
+ if($i < strlen($value) - 1)
1162
+ $value = substr($value, 0, $i + 1);
1163
+ break;
1164
+ }
1165
+ if($i == $dotPosition + 1 && $dotPosition > 0)
1166
+ {
1167
+ $value = substr($value, 0, $dotPosition);
1168
+ break;
1169
+ }
1170
+ }
1171
+ }
1172
+ }
1173
+
1174
+ $realValue = $value;
1175
+
1176
+ if( $viewFormat == FORMAT_HTML )
1177
+ {
1178
+ // declarate patterns for regex
1179
+ $html_tags = '/<.*?>/i'.($useUTF8 ? 'u':'');
1180
+ $get_text = '/(.*<.*>|^.*?)([.]*'.preg_quote($searchFor, "/").'.*?)(<.*>|$)/i'.($useUTF8 ? 'u':'');
1181
+
1182
+ // decode html entity and delete all html tags from value
1183
+ $value = preg_replace($html_tags, '', runner_html_entity_decode($value));
1184
+
1185
+ // if not searchFor in value return
1186
+ if (stristr($value, $searchFor) === false)
1187
+ return;
1188
+
1189
+ // get realValue (string between html tags)
1190
+ if (preg_match($get_text, $realValue, $match))
1191
+ $realValue = $match[2];
1192
+ else
1193
+ $realValue = $value;
1194
+ }
1195
+
1196
+ // if large string cut value and add dots
1197
+ if( $suggestStringSize < runner_strlen($value) )
1198
+ {
1199
+ $startPos = 0;
1200
+ $valueLength = 0;
1201
+ $suggestValues = $this->cutSuggestString( $value, $searchFor );
1202
+ if( $suggestValues ) {
1203
+ if( $viewFormat == FORMAT_HTML ) {
1204
+ $suggestValues["search"] = $realValue;
1205
+ }
1206
+ $response[ $suggestValues["display"] ] = $suggestValues["search"];
1207
+ }
1208
+ } else {
1209
+ $response[ $value ] = $realValue;
1210
+ }
1211
+ }
1212
+
1213
+ /**
1214
+ * Reduce long field value to leave only the text relevant to search suggest
1215
+ * ( "There was a time when Mary had a little lamb", "Mary" ) => "when Mary had"
1216
+ * @return Array - array of (
1217
+ * "search" => "when Mary had" - value that will be used for searching
1218
+ * "display" => "...when Mary had..." - value to show to the user in the suggest list
1219
+ * )
1220
+ * Returns false if anything went wrong
1221
+ */
1222
+ function cutSuggestString( $_value, $searchFor )
1223
+ {
1224
+ $suggestStringSize = GetGlobalData("suggestStringSize", 40);
1225
+ $caseIns = $this->pageObject->pSetEdit->getNCSearch();
1226
+
1227
+ // split to lines. Line breaks shouldn't appear in the suggested values
1228
+ $lines = explode( "\n", $_value );
1229
+ $value = "";
1230
+ for( $lineIdx = 0; $lineIdx< count( $lines); ++$lineIdx ) {
1231
+ $line = $lines[ $lineIdx ];
1232
+ if( $caseIns )
1233
+ {
1234
+ // case-insensitive search
1235
+ $startPos = stripos($line, $searchFor);
1236
+ if( $startPos )
1237
+ $startPos = runner_strlen( substr($line, 0 , $startPos) ); //UTF-8 support
1238
+ }
1239
+ else
1240
+ {
1241
+ $startPos = runner_strpos($line, $searchFor);
1242
+ }
1243
+ if( $startPos !== false )
1244
+ {
1245
+ $value = $line;
1246
+ break;
1247
+ }
1248
+ }
1249
+ if( $startPos === false ) {
1250
+ return false;
1251
+ }
1252
+
1253
+ // cut a chunk of the $value around the $searchFor.
1254
+ // Paddings are parts of the chunk before and after $searchFor
1255
+ // There are two "gray zones" at the begining and end of the chunk.
1256
+ // If there are stop symbols ( spaces, commas ) in the gray zone, cut it up to them
1257
+ // "tion of the next occu" => "of the next"
1258
+
1259
+ $grayZoneLength = 5;
1260
+
1261
+ $leftPaddingLength = min( $suggestStringSize / 2, $startPos );
1262
+ $leftPadding = runner_substr( $value, $startPos - $leftPaddingLength, $leftPaddingLength );
1263
+ $leftGrayZoneLength = $leftPaddingLength < $suggestStringSize / 2
1264
+ ? 0
1265
+ : $grayZoneLength;
1266
+
1267
+ $rightPaddingLength = min( $suggestStringSize - $leftPaddingLength, runner_strlen( $value ) - $startPos - runner_strlen( $searchFor ) );
1268
+ $rightPadding = runner_substr( $value, $startPos + runner_strlen( $searchFor ), $rightPaddingLength );
1269
+ $rightGrayZoneLength = $rightPaddingLength < $suggestStringSize / 2
1270
+ ? 0
1271
+ : $grayZoneLength;
1272
+
1273
+ $leftGrayZone = runner_substr( $leftPadding, 0, $leftGrayZoneLength );
1274
+ $stopPos = $this->findFirstStop( $leftGrayZone, true );
1275
+ if( $stopPos !== false ) {
1276
+ $leftPadding = runner_substr( $leftPadding, $stopPos );
1277
+ }
1278
+
1279
+ $rightGrayZone = runner_substr( $rightPadding, $rightPaddingLength - $rightGrayZoneLength );
1280
+ $stopPos = $this->findFirstStop( $rightGrayZone );
1281
+ if( $stopPos !== false ) {
1282
+ $rightPadding = runner_substr( $rightPadding, 0, runner_strlen( $rightPadding ) - $rightGrayZoneLength + $stopPos );
1283
+ }
1284
+
1285
+ $leftEllipsis = $lineIdx > 0 || runner_strlen( $leftPadding ) < $startPos
1286
+ ? "... "
1287
+ : "";
1288
+ $rightEllipsis = $lineIdx < count( $lines) - 1 || runner_strlen( $rightPadding ) < runner_strlen( $value ) - $startPos - runner_strlen( $searchFor )
1289
+ ? " ..."
1290
+ : "";
1291
+
1292
+ $searchValue = $leftPadding . runner_substr( $value, $startPos, runner_strlen( $searchFor )) . $rightPadding;
1293
+ return array(
1294
+ "search" => $searchValue,
1295
+ "display" => $leftEllipsis . $searchValue . $rightEllipsis
1296
+ );
1297
+ }
1298
+
1299
+ function findFirstStop( $str, $reverse = false ) {
1300
+ $stopSymbols = " .,;:\"'?!|\\/=(){}[]*-+\n\r";
1301
+ $length = runner_strlen( $str);
1302
+ for( $i = 0; $i < $length; ++$i ) {
1303
+ $idx = $reverse ? $length - $i - 1 : $i;
1304
+ $c = runner_substr( $str, $idx, 1 );
1305
+ if( runner_strpos( $stopSymbols, $c ) !== false )
1306
+ return $idx;
1307
+ }
1308
+ return false;
1309
+ }
1310
+
1311
+ /**
1312
+ * This function ivokes after successful saving of added/edited record
1313
+ */
1314
+ function afterSuccessfulSave()
1315
+ {
1316
+ }
1317
+
1318
+ /**
1319
+ * Control settings filling
1320
+ */
1321
+ function init()
1322
+ {
1323
+ }
1324
+
1325
+ /**
1326
+ * Is the search string valid for LIKE search
1327
+ */
1328
+ function isStringValidForLike($str)
1329
+ {
1330
+ if(!IsCharType($this->type) && hasNonAsciiSymbols($str))
1331
+ return false;
1332
+
1333
+ return true;
1334
+ }
1335
+
1336
+ /**
1337
+ * Get the displayed control elemnt's style attribute string
1338
+ * @return String
1339
+ */
1340
+ function getInputStyle( $mode )
1341
+ {
1342
+ return "";
1343
+ if( $this->pageObject->isBootstrap()
1344
+ && ($this->pageObject->pageType != PAGE_ADD || $this->pageObject->mode != ADD_INLINE)
1345
+ && ($this->pageObject->pageType != PAGE_EDIT || $this->pageObject->mode != EDIT_INLINE) )
1346
+ {
1347
+ return "";
1348
+ }
1349
+
1350
+ $width = $this->searchPanelControl ? 150 : $this->pageObject->pSetEdit->getControlWidth( $this->field );
1351
+ $style = $this->makeWidthStyle( $width );
1352
+
1353
+ return 'style="'.$style.'"';
1354
+ }
1355
+
1356
+ /**
1357
+ * Create a CSS rule specifying the control's width
1358
+ * @param Number widthPx
1359
+ */
1360
+ function makeWidthStyle( $widthPx )
1361
+ {
1362
+ return "";
1363
+ /*
1364
+ if( 0 == $widthPx )
1365
+ return "";
1366
+
1367
+ return "width: ".$widthPx."px;";
1368
+ */
1369
+ }
1370
+
1371
+ public function loadLookupContent( $parentValuesData, $childVal = "", $doCategoryFilter = true, $initialLoad = true )
1372
+ {
1373
+ return ""; // .net compatibility
1374
+ }
1375
+
1376
+ public function getLookupContentToReload( $isExistParent, $mode, $parentCtrlsData )
1377
+ {
1378
+ return ""; // .net compatibility
1379
+ }
1380
+
1381
+ /**
1382
+ * A stub
1383
+ */
1384
+ public function getFieldValueCopy( $value )
1385
+ {
1386
+ return $value;
1387
+ }
1388
+
1389
+ public function getFieldSQLDecrypt()
1390
+ {
1391
+ return RunnerPage::_getFieldSQLDecrypt( $this->field, $this->connection, $this->pageObject->pSetEdit, $this->pageObject->cipherer );
1392
+ }
1393
+
1394
+ /**
1395
+ * @return String
1396
+ */
1397
+ protected function getPlaceholderAttr()
1398
+ {
1399
+ if( !$this->searchPanelControl && $this->container->pageType != PAGE_SEARCH )
1400
+ return ' placeholder="'.runner_htmlspecialchars(GetFieldPlaceHolder( GoodFieldname( $this->pageObject->tName ), GoodFieldname( $this->field ) )).'"';
1401
+
1402
+ return "";
1403
+ }
1404
+
1405
+ /**
1406
+ *
1407
+ */
1408
+ public function getConnection()
1409
+ {
1410
+ return $this->connection();
1411
+ }
1412
+
1413
+ /**
1414
+ * Returns basic condition, where first operand is field itself
1415
+ */
1416
+ public function getBasicFieldCondition( $svalue, $strSearchOption, $svalue2 = "", $etype = "" ) {
1417
+ $searchFor = $this->processControlValue( $svalue, $etype );
1418
+ $searchFor2 = $this->processControlValue( $svalue2, $etype );
1419
+ $caseInsensitive = $this->pageObject->pSetEdit->getNCSearch() ? dsCASE_INSENSITIVE : dsCASE_DEFAULT;
1420
+ if( $strSearchOption == EQUALS ) {
1421
+ return DataCondition::FieldEquals( $this->field, $searchFor, 0, $caseInsensitive );
1422
+ } else if( $strSearchOption == STARTS_WITH ) {
1423
+ return DataCondition::FieldIs( $this->field, dsopSTART, $searchFor, $caseInsensitive );
1424
+ } else if( $strSearchOption == CONTAINS ) {
1425
+ return DataCondition::FieldIs( $this->field, dsopCONTAIN, $searchFor, $caseInsensitive );
1426
+ } else if( $strSearchOption == MORE_THAN ) {
1427
+ return DataCondition::FieldIs( $this->field, dsopMORE, $searchFor, $caseInsensitive );
1428
+ } else if( $strSearchOption == LESS_THAN ) {
1429
+ return DataCondition::FieldIs( $this->field, dsopLESS, $searchFor, $caseInsensitive );
1430
+ } else if( $strSearchOption == BETWEEN && ( $searchFor != "" || $searchFor2 != "") ) {
1431
+ if( $searchFor == "" ) {
1432
+ return $this->getSearchCondition( $svalue2, NOT_MORE_THAN, "", $etype );
1433
+ }
1434
+ if( $searchFor2 == "" ) {
1435
+ return $this->getSearchCondition( $svalue, NOT_LESS_THAN, "", $etype );
1436
+ }
1437
+ return DataCondition::FieldBetween( $this->field, $searchFor, $searchFor2, $caseInsensitive );
1438
+ } else if( $strSearchOption == EMPTY_SEARCH ) {
1439
+ return DataCondition::FieldIs( $this->field, dsopEMPTY, $searchFor );
1440
+ }
1441
+ return null;
1442
+ }
1443
+
1444
+ public function getSearchCondition( $searchFor, $strSearchOption, $searchFor2 = "", $not = false, $etype = "" )
1445
+ {
1446
+ if( substr( $strSearchOption, 0, 4) == "NOT " ) {
1447
+ $strSearchOption = substr( $strSearchOption, 4 );
1448
+ $not = true;
1449
+ }
1450
+ $cond = $this->getBasicFieldCondition( $searchFor, $strSearchOption, $searchFor2, $etype );
1451
+
1452
+ if( $not ) {
1453
+ $cond = DataCondition::_Not( $cond );
1454
+ }
1455
+ return $cond;
1456
+ }
1457
+
1458
+ /**
1459
+ * Reduce value passed from web to standard format using controlType
1460
+ * Currently is used for Date and Time controls only
1461
+ */
1462
+ public function processControlValue( $value, $controlType ) {
1463
+
1464
+ if(substr($controlType, 0, 4) == "date")
1465
+ {
1466
+ $dformat = substr($controlType, 4);
1467
+ if($dformat == EDIT_DATE_SIMPLE || $dformat == EDIT_DATE_SIMPLE_INLINE || $dformat == EDIT_DATE_SIMPLE_DP)
1468
+ {
1469
+ $time = localdatetime2db($value);
1470
+ if($time == "null")
1471
+ return "";
1472
+ return $time;
1473
+ }
1474
+ else if($dformat == EDIT_DATE_DD || $dformat == EDIT_DATE_DD_INLINE || $dformat == EDIT_DATE_DD_DP)
1475
+ {
1476
+ $a = explode("-",$value);
1477
+ if(count($a) < 3)
1478
+ return "";
1479
+ else
1480
+ {
1481
+ $y = $a[0];
1482
+ $m = $a[1];
1483
+ $d = $a[2];
1484
+ }
1485
+ if($y < 100)
1486
+ {
1487
+ if($y < 70)
1488
+ $y += 2000;
1489
+ else
1490
+ $y += 1900;
1491
+ }
1492
+ return mysprintf("%04d-%02d-%02d",array($y,$m,$d));
1493
+ }
1494
+ else
1495
+ return "";
1496
+ }
1497
+ else if($controlType == "time")
1498
+ {
1499
+ if(!strlen($value))
1500
+ return "";
1501
+ $ret = localtime2db($value);
1502
+ if( IsDateFieldType( $this->type ) )
1503
+ $ret = "2000-01-01 ".$ret;
1504
+ return $ret;
1505
+
1506
+ }
1507
+
1508
+ return $value;
1509
+ }
1510
+
1511
+ /**
1512
+ *
1513
+ * @returgn String
1514
+ */
1515
+ public function getControlMarkup( &$params, $data ) {
1516
+ $fieldNum = 0;
1517
+ if( $params["fieldNum"] )
1518
+ $fieldNum = $params["fieldNum"];
1519
+
1520
+ $validate = array();
1521
+ if( $params["validate"] )
1522
+ $validate = $params["validate"];
1523
+
1524
+ $additionalCtrlParams = array();
1525
+ if( $params["additionalCtrlParams"] )
1526
+ $additionalCtrlParams = $params["additionalCtrlParams"];
1527
+
1528
+ ob_start();
1529
+
1530
+ $this->buildControl( $data[ $this->field ], $params["mode"], $fieldNum, $validate, $additionalCtrlParams, $data );
1531
+ $markup = ob_get_contents() ;
1532
+
1533
+ ob_end_clean();
1534
+ return $markup;
1535
+ }
1536
+
1537
+ /**
1538
+ * @return DsCommand - create data command for search suggest
1539
+ */
1540
+ public function getSuggestCommand( $searchFor, $searchOpt, $numberOfSuggests )
1541
+ {
1542
+ $dc = new DsCommand();
1543
+ $dc->filter = DataCondition::_And( array(
1544
+ $this->getSearchCondition( $searchFor, $searchOpt ),
1545
+ Security::SelectCondition( "S", $this->pageObject->pSetEdit )
1546
+ ));
1547
+ $dc->totals[] = array(
1548
+ "field" => $this->field,
1549
+ "total" => "distinct"
1550
+ );
1551
+ $dc->skipAggregated = true;
1552
+ $dc->reccount = $numberOfSuggests;
1553
+ return $dc;
1554
+ }
1555
+
1556
+ /**
1557
+ * Get the field's content
1558
+ * @param &Array data
1559
+ * @param Array
1560
+ * @return String
1561
+ */
1562
+ public function getDisplayValue( &$data )
1563
+ {
1564
+ $fName = $this->field;
1565
+ $htmlType = $this->pageObject->pSetEdit->getHTML5InputType( $fName );
1566
+ $value = $data[ $fName ];
1567
+ if( $this->format !== EDIT_FORMAT_READONLY ) {
1568
+ if( IsFloatType( $this->type ) && !is_null( $value ) ) {
1569
+ if( $htmlType == "number" ) {
1570
+ // no thousand delimiters, only dot as decimal delimiter
1571
+ $value = formatNumberForHTML5( $value );
1572
+ } else {
1573
+ $value = formatNumberForEdit( $value );
1574
+ }
1575
+ }
1576
+ }
1577
+ return $value;
1578
+ }
1579
+
1580
+ }
1581
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
1582
  ?>
php/classes/controls/DatabaseFileField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class DatabaseFileField extends EditControl
3
  {
@@ -284,4 +285,292 @@ class DatabaseFileField extends EditControl
284
  && $this->container->tName === Security::loginTable();
285
  }
286
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class DatabaseFileField extends EditControl
4
  {
 
285
  && $this->container->tName === Security::loginTable();
286
  }
287
  }
288
+ =======
289
+ <?php
290
+ class DatabaseFileField extends EditControl
291
+ {
292
+ function __construct($field, $pageObject, $id, $connection)
293
+ {
294
+ parent::__construct($field, $pageObject, $id, $connection);
295
+ $this->format = $pageObject->pSetEdit->getEditFormat($field);
296
+ }
297
+
298
+ /**
299
+ * addJSFiles
300
+ * Add control JS files to page object
301
+ */
302
+ function addJSFiles()
303
+ {
304
+ }
305
+
306
+ /**
307
+ * addCSSFiles
308
+ * Add control CSS files to page object
309
+ */
310
+ function addCSSFiles()
311
+ {
312
+ }
313
+
314
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
315
+ {
316
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
317
+
318
+ $disp = "";
319
+ $strfilename = "";
320
+
321
+ if($mode == MODE_EDIT || $mode == MODE_INLINE_EDIT)
322
+ {
323
+ $value = $this->connection->stripSlashesBinary( $value );
324
+ $itype = SupposeImageType($value);
325
+
326
+ if($itype)
327
+ {
328
+ if( $this->format == EDIT_FORMAT_DATABASE_IMAGE && !$this->pageObject->pSetEdit->showThumbnail( $this->field ) )
329
+ {
330
+ // show real db image instead of icon
331
+ $src = GetTableLink( "file", "", "filename=file.jpg&table=".rawurlencode( $this->container->tName )
332
+ ."&field=".rawurlencode( $this->field )
333
+ ."&nodisp=1"
334
+ .$this->keylink."&fileHash=".fileAttrHash( $this->keylink, strlen_bin( $value ) ) );
335
+
336
+ $imgWidth = $this->container->pSetEdit->getImageWidth( $this->field );
337
+ $imgHeight = $this->container->pSetEdit->getImageHeight( $this->field );
338
+
339
+ $style = '';
340
+ if( $imgWidth )
341
+ $style.= 'max-width:'.$imgWidth.'px;';
342
+ if( $imgHeight )
343
+ $style.= 'max-height:'.$imgHeight.'px;';
344
+
345
+ $imageId = generatePassword( 10 );
346
+ if( $style != "" ) {
347
+ // don't use id attribute since this it should be possible to override this size in other CSS
348
+ $style = '<style> @media screen and (min-width: 768px) { [data-imageid="'. $imageId . '"] { '
349
+ . $style . '} } </style>';
350
+ }
351
+
352
+ $disp = $style.'<img class="" data-imageid="'.$imageId.'" id="image_'.GoodFieldName( $this->field ).'_'.$this->id.'" name="'.$this->cfield.'"';
353
+ if( $this->is508 )
354
+ $disp.= ' alt="Image from DB"';
355
+ $disp.= ' border=0 src="'.$src.'">';
356
+ }
357
+ else if( $this->pageObject->pSetEdit->showThumbnail($this->field) )
358
+ {
359
+ $disp = "<a target=_blank";
360
+
361
+ $disp.=" href=\"".
362
+ GetTableLink("imager", "",
363
+ "page=".$this->pageObject->pageName.
364
+ "&table=".GetTableURL($this->pageObject->tName).
365
+ "&".$this->iquery.
366
+ "&rndVal=".rand(0,32768))."\" >";
367
+ $disp.= "<img class=\"mupload-preview-img\" id=\"image_".GoodFieldName($this->field)."_".$this->id."\" name=\"".$this->cfield."\" border=0";
368
+ if($this->is508)
369
+ $disp .= " alt=\"Image from DB\"";
370
+
371
+ // show thumbnail or fullsize image
372
+ $displayField = $this->pageObject->pSetEdit->getStrThumbnail($this->field);
373
+ if( !strlen( $data[ $displayField ]) ) {
374
+ $displayField = $this->field;
375
+ }
376
+
377
+ $disp .= " src=\"".
378
+ GetTableLink("imager", "",
379
+ "page=".$this->pageObject->pageName.
380
+ "&table=".GetTableURL($this->pageObject->tName).
381
+ "&field=".rawurlencode( $displayField ).
382
+ $this->keylink.
383
+ "&rndVal=".rand(0,32768))."\">";
384
+ $disp.= "</a>";
385
+ }
386
+ else
387
+ {
388
+ $disp='<img class="mupload-preview-img" id="image_'.GoodFieldName($this->field).'_'.$this->id.'" name="'.$this->cfield.'"';
389
+ if($this->is508)
390
+ $disp.= ' alt="Image from DB"';
391
+ $disp.=' border=0 src="'.
392
+ GetTableLink("imager", "",
393
+ 'table='.GetTableURL($this->pageObject->tName).
394
+ "&page=".$this->pageObject->pageName.
395
+ '&'.$this->iquery."&src=1&rndVal=".rand(0,32768)).'">';
396
+ }
397
+ }
398
+ else
399
+ {
400
+ if(strlen($value))
401
+ {
402
+ $disp = '<img class="mupload-preview-img" id="image_'.GoodFieldName($this->field).'_'.$this->id.'" name="'.$this->cfield.'" border=0 ';
403
+ if($this->is508)
404
+ $disp .= ' alt="file"';
405
+ $disp .= ' src="'.GetRootPathForResources("images/file.gif").'">';
406
+ }
407
+ }
408
+ // filename
409
+ if($this->format == EDIT_FORMAT_DATABASE_FILE && !$itype && strlen($value))
410
+ {
411
+ if(!($filename = @$data[$this->pageObject->pSetEdit->getFilenameField($this->field)]))
412
+ $filename = "file.bin";
413
+
414
+ $disp = '<a href="'.GetTableLink("getfile", "", 'table='.GetTableURL( $this->pageObject->tName ).'&filename='.runner_htmlspecialchars( $filename )
415
+ .'&pagename='.runner_htmlspecialchars( $this->pageObject->pSetEdit->pageName() )
416
+ .'&'.$this->iquery).'".>'.$disp.'</a>';
417
+ }
418
+ // filename edit
419
+ if($this->format == EDIT_FORMAT_DATABASE_FILE && $this->pageObject->pSetEdit->getFilenameField($this->field))
420
+ {
421
+ if(!($filename = @$data[$this->pageObject->pSetEdit->getFilenameField($this->field)]))
422
+ $filename = "";
423
+ if($mode == MODE_INLINE_EDIT)
424
+ {
425
+ $strfilename = '<br><label for="filename_'.$this->cfieldname.'">'."Filename"
426
+ .'</label>&nbsp;&nbsp;<input type="text" '.$this->inputStyle.' id="filename_'.$this->cfieldname
427
+ .'" name="filename_'.$this->cfieldname.'" size="20" maxlength="50" value="'.runner_htmlspecialchars($filename).'">';
428
+ }
429
+ else
430
+ {
431
+ $strfilename = '<br><label for="filename_'.$this->cfieldname.'">'."Filename"
432
+ .'</label>&nbsp;&nbsp;<input type="text" '.$this->inputStyle.' id="filename_'.$this->cfieldname.'" name="filename_'
433
+ .$this->cfieldname.'" size="20" maxlength="50" value="'.runner_htmlspecialchars($filename).'">';
434
+ }
435
+ }
436
+ if(strlen($value)) {
437
+ $strtype = '<br><input id="'.$this->ctype.'_keep" type="Radio" name="'.$this->ctype.'" value="file0" checked class="rnr-uploadtype">'."Keep";
438
+
439
+ if(strlen($value) && !$this->pageObject->pSetEdit->isRequired($this->field))
440
+ {
441
+ $strtype .= '<input id="'.$this->ctype.'_delete" type="Radio" name="'.$this->ctype.'" value="file1" class="rnr-uploadtype">'."Delete";
442
+ }
443
+ $strtype .= '<input id="'.$this->ctype.'_update" type="Radio" name="'.$this->ctype.'" value="file2" class="rnr-uploadtype">'."Update";
444
+ } else {
445
+ $strtype = '<input id="'.$this->ctype.'_update" type="hidden" name="'.$this->ctype.'" value="file2" class="rnr-uploadtype">';
446
+ }
447
+ }
448
+ else
449
+ {
450
+ // if Add mode
451
+ $strtype = '<input id="'.$this->ctype.'" type="hidden" name="'.$this->ctype.'" value="file2">';
452
+ if($this->format == EDIT_FORMAT_DATABASE_FILE && $this->pageObject->pSetEdit->getFilenameField($this->field))
453
+ {
454
+ $strfilename = '<br><label for="filename_'.$this->cfieldname.'">'."Filename"
455
+ .'</label>&nbsp;&nbsp;<input type="text" '.$this->inputStyle.' id="filename_'.$this->cfieldname.'" name="filename_'
456
+ .$this->cfieldname.'" size="20" maxlength="50">';
457
+ }
458
+ }
459
+
460
+ if($mode == MODE_INLINE_EDIT && $this->format == EDIT_FORMAT_DATABASE_FILE)
461
+ $disp = "";
462
+ echo $disp.$strtype;
463
+ if (($mode == MODE_EDIT || $mode==MODE_INLINE_EDIT) && (strlen($value)))
464
+ {
465
+ echo '<br>';
466
+ }
467
+ echo '<input type="File" '.$this->inputStyle.' id="'.$this->cfield.'" '
468
+ .'accept="'.$this->pageObject->pSetEdit->getAcceptFileTypesHtml($this->field).'" '
469
+ .(($mode==MODE_INLINE_EDIT || $mode==MODE_INLINE_ADD) && $this->is508 ? 'alt="'.$this->strLabel.'" ' : '').' name="'
470
+ .$this->cfield.'" >'.$strfilename;
471
+ echo '<input type="Hidden" id="notempty_'.$this->cfieldname.'" value="'.(strlen($value) ? 1 : 0).'">';
472
+ $this->buildControlEnd($validate, $mode);
473
+ }
474
+
475
+ /**
476
+ * Create CSS code for specifying control's width
477
+ */
478
+ function makeWidthStyle($widthPx)
479
+ {
480
+ if(0 == $widthPx)
481
+ return "";
482
+ return "min-width: ".$widthPx."px";
483
+ }
484
+
485
+ function readWebValue(&$avalues, &$blobfields, $legacy1, $legacy2, &$filename_values)
486
+ {
487
+ $filename = "";
488
+ $this->getPostValueAndType();
489
+ if (FieldSubmitted($this->goodFieldName."_".$this->id))
490
+ {
491
+ $fileNameForPrepareFunc = securityCheckFileName(postvalue("filename_".$this->goodFieldName."_".$this->id));
492
+ if( $this->pageObject->pageType != PAGE_EDIT && $this->pageObject->pageType != PAGE_USERINFO )
493
+ {
494
+ $prepearedFile = prepare_file($this->webValue, $this->field, "file2", $fileNameForPrepareFunc, $this->id);
495
+ if($prepearedFile !== false)
496
+ {
497
+ $this->webValue = $prepearedFile["value"];
498
+ $filename = $prepearedFile["filename"];
499
+ }
500
+ else
501
+ $this->webValue = false;
502
+ }
503
+ else
504
+ {
505
+ if(substr($this->webType, 0, 4) == "file")
506
+ {
507
+ $prepearedFile = prepare_file($this->webValue, $this->field, $this->webType, $fileNameForPrepareFunc, $this->id);
508
+ if($prepearedFile !== false)
509
+ {
510
+ $this->webValue = $prepearedFile["value"];
511
+ $filename = $prepearedFile["filename"];
512
+ }
513
+ else
514
+ $this->webValue = false;
515
+ }
516
+ else if(substr($this->webType, 0, 6) == "upload")
517
+ {
518
+ if($this->webType == "upload1")
519
+ {
520
+ // file deletion, read filename from the database
521
+ $oldValues = $this->pageObject->getOldRecordData();
522
+ $fileNameForPrepareFunc = $oldValues[$this->field];
523
+ }
524
+ $this->webValue = prepare_upload($this->field, $this->webType, $fileNameForPrepareFunc, $this->webValue, "", $this->id, $this->pageObject);
525
+ }
526
+ else
527
+ $this->webValue = false;
528
+ }
529
+ }
530
+ else
531
+ $this->webValue = false;
532
+
533
+ if(!($this->webValue === false))
534
+ {
535
+ if($this->webValue)
536
+ {
537
+ if($this->pageObject->pSetEdit->getCreateThumbnail($this->field))
538
+ {
539
+ $ext = CheckImageExtension(GetUploadedFileName("value_".$this->goodFieldName."_".$this->id));
540
+ if( $ext ) {
541
+ $thumb = CreateThumbnail($this->webValue, $this->pageObject->pSetEdit->getThumbnailSize($this->field), $ext);
542
+ $blobfields[] = $this->pageObject->pSetEdit->getStrThumbnail($this->field);
543
+ $avalues[$blobfields[count($blobfields) - 1]] = $thumb;
544
+ }
545
+ }
546
+ // resize on upload
547
+ $resizeImageSize = 0;
548
+ if( $this->pageObject->pSetEdit->getResizeOnUpload($this->field) ) {
549
+ $resizeImageSize = $this->pageObject->pSetEdit->getNewImageSize($this->field);
550
+ } else if( $this->fieldIsUserpic() ) {
551
+ $resizeImageSize = 400;
552
+ }
553
+ if( $resizeImageSize ) {
554
+ $ext = CheckImageExtension( GetUploadedFileName("value_".$this->goodFieldName."_".$this->id) );
555
+ $this->webValue = CreateThumbnail($this->webValue, $resizeImageSize, $ext);
556
+ }
557
+ }
558
+ else if($this->pageObject->pageType == PAGE_EDIT && $this->pageObject->pSetEdit->getCreateThumbnail($this->field))
559
+ {
560
+ $blobfields[] = $this->pageObject->pSetEdit->getStrThumbnail($this->field);
561
+ $avalues[$blobfields[count($blobfields) - 1]] = "";
562
+ }
563
+ $blobfields[] = $this->field;
564
+ $avalues[$this->field] = $this->webValue;
565
+ }
566
+ if($filename && $this->pageObject->pSetEdit->getStrFilename($this->field))
567
+ $filename_values[$this->pageObject->pSetEdit->getStrFilename($this->field)] = $filename;
568
+ }
569
+
570
+ protected function fieldIsUserpic() {
571
+ return $this->field === Security::userpicField()
572
+ && $this->container->tName === Security::loginTable();
573
+ }
574
+ }
575
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
576
  ?>
php/classes/controls/DateField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  require_once getabspath('classes/controls/DateTimeControl.php');
3
  class DateField extends DateTimeControl
@@ -290,4 +291,298 @@ class DateField extends DateTimeControl
290
  return parent::getBasicFieldCondition( $searchFor, $strSearchOption, $searchFor2, $etype );
291
  }
292
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  require_once getabspath('classes/controls/DateTimeControl.php');
4
  class DateField extends DateTimeControl
 
291
  return parent::getBasicFieldCondition( $searchFor, $strSearchOption, $searchFor2, $etype );
292
  }
293
  }
294
+ =======
295
+ <?php
296
+ require_once getabspath('classes/controls/DateTimeControl.php');
297
+ class DateField extends DateTimeControl
298
+ {
299
+ function __construct($field, $pageObject, $id, $connection)
300
+ {
301
+ EditControl::__construct($field, $pageObject, $id, $connection);
302
+ $this->format = EDIT_FORMAT_DATE;
303
+ }
304
+
305
+ function addCSSFiles() {
306
+ $this->pageObject->AddCSSFile("include/bootstrap/css/bootstrap-datetimepicker.min.css");
307
+ }
308
+
309
+ function getProjectSettings()
310
+ {
311
+ if($this->pageObject->pageType == PAGE_LIST)
312
+ return new ProjectSettings($this->pageObject->tName, PAGE_SEARCH);
313
+ else
314
+ return $this->pageObject->pSetEdit;
315
+ }
316
+
317
+ function getDateEditType( $pSet = null )
318
+ {
319
+ if( !$pSet )
320
+ $pSet = $this->getProjectSettings();
321
+
322
+ $dateEditType = $pSet->getDateEditType($this->field);
323
+
324
+ // search panel control
325
+ if( !$this->forSpreadsheetGrid
326
+ && ( ( $this->pageObject->pageType == PAGE_LIST || $this->pageObject->pageType == PAGE_CHART || $this->pageObject->pageType == PAGE_REPORT)
327
+ || $this->pageObject->pageType == PAGE_SEARCH && $this->pageObject->mode == SEARCH_LOAD_CONTROL) )
328
+ {
329
+ if( $dateEditType == EDIT_DATE_DD )
330
+ return EDIT_DATE_SIMPLE;
331
+ if( $dateEditType == EDIT_DATE_DD_DP )
332
+ return EDIT_DATE_SIMPLE_DP;
333
+ if( $dateEditType == EDIT_DATE_DD_INLINE )
334
+ return EDIT_DATE_SIMPLE_INLINE;
335
+ }
336
+
337
+ return $dateEditType;
338
+ }
339
+
340
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
341
+ {
342
+ global $locale_info;
343
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
344
+
345
+ if($fieldNum)
346
+ $this->cfield = "value".$fieldNum."_".GoodFieldName($this->field).'_'.$this->id;
347
+
348
+ $pSet = $this->getProjectSettings();
349
+
350
+ $dateEditType = $this->getDateEditType( $pSet );
351
+
352
+ //if( $this->pageObject->pageType == PAGE_LIST ) //
353
+ echo '<input id="'.$this->ctype.'" type="hidden" name="'.$this->ctype.'" value="date'
354
+ .$dateEditType.'">';
355
+
356
+ $tvalue = $value;
357
+
358
+ $time = db2time($tvalue);
359
+ if( !$time )
360
+ $time = array(0, 0, 0, 0, 0, 0);
361
+
362
+ $classString = ' form-control';
363
+
364
+ $dp = 0;
365
+ $hasImgCal = true;
366
+ $showTime = $pSet->dateEditShowTime($this->field);
367
+ switch( $dateEditType )
368
+ {
369
+ case EDIT_DATE_SIMPLE_INLINE:
370
+ $hasImgCal = false;
371
+ case EDIT_DATE_SIMPLE_DP:
372
+ $ovalue = $value;
373
+
374
+ if($locale_info["LOCALE_IDATE"] == 1)
375
+ $fmt = "dd".$locale_info["LOCALE_SDATE"]."MM".$locale_info["LOCALE_SDATE"]."yyyy";
376
+ else if($locale_info["LOCALE_IDATE"] == 0)
377
+ $fmt = "MM".$locale_info["LOCALE_SDATE"]."dd".$locale_info["LOCALE_SDATE"]."yyyy";
378
+ else
379
+ $fmt = "yyyy".$locale_info["LOCALE_SDATE"]."MM".$locale_info["LOCALE_SDATE"]."dd";
380
+
381
+ if($showTime || $time[3] || $time[4] || $time[5]){
382
+ $timeAttrs = $this->pageObject->pSetEdit->getFormatTimeAttrs($this->field);
383
+ $fmt.= " " . $locale_info["LOCALE_STIMEFORMAT"];
384
+ }
385
+
386
+ if($time[0])
387
+ $ovalue = format_datetime_custom($time, $fmt);
388
+
389
+ $ovalue1 = $time[2]."-".$time[1]."-".$time[0];
390
+ if($showTime || $time[3] || $time[4] || $time[5])
391
+ $ovalue1.= " ".$time[3].":".$time[4].":".$time[5];
392
+
393
+ $ret= '<input '.$this->getPlaceholderAttr().' id="'.$this->cfield.'" '.$this->inputStyle.' class="'.$classString.'" type="Text" name="'.$this->cfield.'" value="'.$ovalue.'">';
394
+ $ret.= '<input id="ts'.$this->cfield.'" type="Hidden" name="ts'.$this->cfield.'" value="'.$ovalue1.'">';
395
+
396
+ $ret .= '<span class="input-group-addon" id="imgCal_'.$this->cfield.'"><span class="glyphicon glyphicon-calendar"></span></span>';
397
+
398
+ if ( isRTL() )
399
+ $ret .= "<span></span>"; // for bootstrap calend icon anomaly
400
+
401
+ $ret = '<div class="input-group date">' . $ret . '</div>';
402
+
403
+ echo $ret;
404
+ break;
405
+
406
+ case EDIT_DATE_DD_INLINE:
407
+ case EDIT_DATE_DD_DP:
408
+ $dp=1;
409
+ case EDIT_DATE_DD:
410
+ $controlWidth = $pSet->getControlWidth($this->field);
411
+ if($controlWidth > 0)
412
+ {
413
+ $controlWidth -= 10;
414
+ $yearWidth = floor($controlWidth * 0.3);
415
+ $yearStyle = 'style="min-width: '.$yearWidth.'px;margin-right:5px;" ';
416
+ $dayWidth = floor($controlWidth * 0.2);
417
+ $dayStyle = 'style="min-width: '.$dayWidth.'px; margin-right:5px;" ';
418
+ $mothWidth = $controlWidth - $yearWidth - $dayWidth;
419
+ $monthStyle = 'style="min-width: '.$mothWidth.'px; margin-right:5px;" ';
420
+ }
421
+ else
422
+ {
423
+ $dayStyle = '';
424
+ $monthStyle = '';
425
+ $yearStyle = '';
426
+ }
427
+ $alt = 'alt="'.$this->strLabel.'" ';
428
+
429
+ // for init normal select width/ After load js, this options will clear
430
+ $initMonthOpt = "<option>&nbsp;</option>";
431
+ if ( $time[1] )
432
+ {
433
+ $months = getMountNames();
434
+ $initMonthOpt = "<option>" . $months[$time[1]] . "</option>";
435
+ }
436
+ $initMonthOpt .= "<option>" . $this->maxLengthMonth() . "</option>";
437
+ $initDayOpt = "<option>" . ($time[2] ? $time[2] : "&nbsp;") ." </option><option>22</option>";
438
+ $initYearOpt = "<option>" . ($time[0] ? $time[0] : "&nbsp;") . "</option><option>2000</option>";
439
+ $retday='<select class="'. $classString.'" id="day'.$this->cfield.'" '.$dayStyle.$alt.'name="day'.$this->cfield.'" >'.$initDayOpt.'</select>';
440
+ $retmonth='<select class="'. $classString.'" id="month'.$this->cfield.'" '.$monthStyle.$alt.'name="month'.$this->cfield.'" >'.$initMonthOpt.'</option></select>';
441
+ $retyear='<select class="'. $classString.'" id="year'.$this->cfield.'" '.$yearStyle.$alt.'name="year'.$this->cfield.'" >'.$initYearOpt.'</select>';
442
+
443
+ $space = ($controlWidth > 0 ? '' : "&nbsp;");
444
+
445
+ if($locale_info["LOCALE_ILONGDATE"] == 1)
446
+ $ret = $retday.$space.$retmonth.$space.$retyear;
447
+ else if($locale_info["LOCALE_ILONGDATE"] == 0)
448
+ $ret = $retmonth.$space.$retday.$space.$retyear;
449
+ else
450
+ $ret = $retyear.$space.$retmonth.$space.$retday;
451
+
452
+ $setHiddenElem = 'class="'. $classString.' hiddenPickerElement"';
453
+
454
+ if($time[0] && $time[1] && $time[2])
455
+ $ret.="<input id=\"".$this->cfield."\" ".$setHiddenElem." name=\"".$this->cfield."\" value=\"".$time[0]."-".$time[1]."-".$time[2]."\">";
456
+ else
457
+ $ret.="<input id=\"".$this->cfield."\" ".$setHiddenElem." name=\"".$this->cfield."\" value=\"\">";
458
+
459
+ // calendar handling for three DD
460
+ if( $dp ) {
461
+ $ret .= '<button class="btn btn-default" id="imgCal_'.$this->cfield.'" aria-hidden=true><span class="glyphicon glyphicon-calendar" ></span></button>';
462
+ }
463
+
464
+ $ret = '<span class="bs-date-control form-inline">' . $ret . '</span>';
465
+ echo $ret;
466
+ break;
467
+
468
+ default: // case EDIT_DATE_SIMPLE:
469
+ $ovalue = $value;
470
+ if($time[0])
471
+ {
472
+ if($showTime || $time[3] || $time[4] || $time[5])
473
+ $ovalue = str_format_datetime($time);
474
+ else
475
+ $ovalue = format_shortdate($time);
476
+ }
477
+ echo '<input '.$this->getPlaceholderAttr().' id="'.$this->cfield.'" type=text class="'.$classString.'" name="'.$this->cfield.'" '.$this->inputStyle.' value="'.runner_htmlspecialchars($ovalue).'">';
478
+ }
479
+ $this->buildControlEnd($validate, $mode);
480
+ }
481
+
482
+ function getFirstElementId()
483
+ {
484
+ global $locale_info;
485
+ $dateEditType = $this->getDateEditType();
486
+
487
+ if ( !$dateEditType )
488
+ {
489
+ return $this->cfield;
490
+ }
491
+
492
+ switch( $dateEditType )
493
+ {
494
+ case EDIT_DATE_DD:
495
+ case EDIT_DATE_DD_INLINE:
496
+ case EDIT_DATE_DD_DP:
497
+ if($locale_info["LOCALE_ILONGDATE"] == 1)
498
+ return "day".$this->cfield;
499
+ else if($locale_info["LOCALE_ILONGDATE"] == 0)
500
+ return "month".$this->cfield;
501
+ else
502
+ return "year".$this->cfield;
503
+ break;
504
+
505
+ default:
506
+ return $this->cfield;
507
+ break;
508
+ }
509
+ }
510
+
511
+ function maxLengthMonth()
512
+ {
513
+ $maxLengthMonth = "";
514
+ $mounts = getMountNames();
515
+ $maxLenght = 0;
516
+ for ( $i =0; $i < count($mounts); $i++ )
517
+ {
518
+ $curMontn = $mounts[$i];
519
+ $curMonthLen = runner_strlen($curMontn);
520
+ if ( $maxLenght < $curMonthLen )
521
+ {
522
+ $maxLenght = $curMonthLen;
523
+ $maxLengthMonth = $curMontn;
524
+ }
525
+ }
526
+
527
+ return $maxLengthMonth;
528
+ }
529
+
530
+ /**
531
+ * Returns basic condition
532
+ */
533
+ public function getBasicFieldCondition( $svalue, $strSearchOption, $svalue2 = "", $etype = "" ) {
534
+ $searchFor = $this->processControlValue( $svalue, $etype );
535
+ $searchFor2 = $this->processControlValue( $svalue2, $etype );
536
+ $etype = "";
537
+ $pSet = $this->getProjectSettings();
538
+ if( !$pSet->dateEditShowTime($this->field) && IsDateTimeFieldType( $pSet->getFieldType($this->field) ) ) {
539
+ // search for date only in a datetime field
540
+
541
+ if( $strSearchOption == EQUALS ) {
542
+ // ( NOT field < date ) AND field < ( date + 1 day )
543
+ $tm = db2time( $searchFor );
544
+ if( !$tm[0] ) {
545
+ return DataCondition::_False();
546
+ }
547
+ $nextDay = adddays( $tm, 1 );
548
+ return DataCondition::_And( array(
549
+ DataCondition::_Not(
550
+ DataCondition::FieldIs( $this->field, dsopLESS, date2db( $tm ) )
551
+ ),
552
+ DataCondition::FieldIs( $this->field, dsopLESS, date2db( $nextDay ) )
553
+ ));
554
+ } else if( $strSearchOption == MORE_THAN ) {
555
+ // NOT ( field < ( date + 1 day ) )
556
+ $tm = db2time( $searchFor );
557
+ if( !$tm[0] ) {
558
+ return DataCondition::_False();
559
+ }
560
+ $nextDay = adddays( $tm, 1 );
561
+ return DataCondition::_Not(
562
+ DataCondition::FieldIs( $this->field, dsopLESS, date2db( $nextDay ) )
563
+ );
564
+
565
+ } else if( $strSearchOption == BETWEEN && $searchFor != "" && $searchFor2 != "" ) {
566
+ // true between only
567
+ // NOT ( field < date ) AND field < (date2+1)
568
+ $tm = db2time( $searchFor );
569
+ $tm2 = db2time( $searchFor2 );
570
+ if( !$tm[0] || !$tm2[0] ) {
571
+ return DataCondition::_False();
572
+ }
573
+ $tm2 = adddays( $tm2, 1 );
574
+ return DataCondition::_And( array(
575
+ DataCondition::_Not(
576
+ DataCondition::FieldIs( $this->field, dsopLESS, date2db( $tm ) )
577
+ ),
578
+ DataCondition::FieldIs( $this->field, dsopLESS, date2db( $tm2 ) )
579
+ ));
580
+
581
+ }
582
+
583
+ }
584
+ return parent::getBasicFieldCondition( $searchFor, $strSearchOption, $searchFor2, $etype );
585
+ }
586
+ }
587
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
588
  ?>
php/classes/controls/DateTimeControl.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class DateTimeControl extends EditControl
3
  {
@@ -22,4 +23,30 @@ class DateTimeControl extends EditControl
22
  return $this->buildSearchOptions($optionsArray, $selOpt, $not, $both);
23
  }
24
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class DateTimeControl extends EditControl
4
  {
 
23
  return $this->buildSearchOptions($optionsArray, $selOpt, $not, $both);
24
  }
25
  }
26
+ =======
27
+ <?php
28
+ class DateTimeControl extends EditControl
29
+ {
30
+ /**
31
+ * Form the control specified search options array and built the control's search options markup
32
+ * @param String selOpt The search option value
33
+ * @param Boolean not It indicates if the search option negation is set
34
+ * @param Boolean both It indicates if the control needs 'NOT'-options
35
+ * @return String A string containing options markup
36
+ */
37
+ function getSearchOptions($selOpt, $not, $both)
38
+ {
39
+ $optionsArray = array(EQUALS, MORE_THAN, LESS_THAN, BETWEEN, EMPTY_SEARCH);
40
+ if($both)
41
+ {
42
+ $optionsArray[] = NOT_EQUALS;
43
+ $optionsArray[] = NOT_MORE_THAN;
44
+ $optionsArray[] = NOT_LESS_THAN;
45
+ $optionsArray[] = NOT_BETWEEN;
46
+ $optionsArray[] = NOT_EMPTY;
47
+ }
48
+ return $this->buildSearchOptions($optionsArray, $selOpt, $not, $both);
49
+ }
50
+ }
51
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
52
  ?>
php/classes/controls/EditControlsContainer.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class EditControlsContainer
3
  {
@@ -327,4 +328,335 @@ class EditControlsContainer
327
  return $this->pSetEdit->getEditFormat( $field );
328
  }
329
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class EditControlsContainer
4
  {
 
328
  return $this->pSetEdit->getEditFormat( $field );
329
  }
330
  }
331
+ =======
332
+ <?php
333
+ class EditControlsContainer
334
+ {
335
+ public $controls = array();
336
+ public $jsSettings = array();
337
+ public $pSetEdit = null;
338
+ public $pageType = "";
339
+ public $cipherer = null;
340
+
341
+ public $tName = "";
342
+
343
+ public $pageObject = null;
344
+
345
+ public $pageLikeInline = false;
346
+
347
+ public $tableBasedSearchPanelAdded = false;
348
+
349
+ public $searchPanelActivated = false;
350
+
351
+ /**
352
+ * Associative array used like a container to exchange some data between controls on one page
353
+ * @var {array}
354
+ */
355
+ public $globalVals = array();
356
+
357
+ /**
358
+ * @type Connection
359
+ */
360
+ protected $connection;
361
+
362
+ public $classNamesForEdit = array();
363
+
364
+ public $classNamesForSearch = array();
365
+
366
+ public function __construct($pageObject, $pSetEdit, $pageType, $cipherer = "")
367
+ {
368
+ if($pageObject != null)
369
+ {
370
+ $this->pageObject = $pageObject;
371
+ $this->tName = $pageObject->tName;
372
+
373
+ $this->pageLikeInline = $pageObject->pageType == PAGE_ADD && $pageObject->mode == ADD_INLINE ||
374
+ $pageObject->pageType == PAGE_EDIT && $pageObject->mode == EDIT_INLINE;
375
+ }
376
+ else
377
+ {
378
+ $this->tName = $pSetEdit->_table;
379
+ $this->cipherer = $cipherer;
380
+ }
381
+
382
+ $this->fillControlClassNames();
383
+
384
+ $this->setEditControlsConnection();
385
+
386
+ $this->pSetEdit = $pSetEdit;
387
+ $this->pageType = $pageType;
388
+ $this->searchPanelActivated = true;
389
+ }
390
+
391
+ /**
392
+ * Set the connection property
393
+ */
394
+ protected function setEditControlsConnection()
395
+ {
396
+ global $cman;
397
+
398
+ if( $this->pageObject != null )
399
+ $this->connection = $this->pageObject->connection;
400
+ else
401
+ $this->connection = $cman->byTable( $this->tName );
402
+ }
403
+
404
+ /**
405
+ * @return Boolean
406
+ */
407
+ public function isSearchPanelActivated()
408
+ {
409
+ if( $this->pageObject != null )
410
+ return $this->pageObject->isSearchPanelActivated();
411
+
412
+ return $this->pageType == PAGE_SEARCH;
413
+ }
414
+
415
+ function addControlsJSAndCSS()
416
+ {
417
+ $allowedPageTypes = array( PAGE_ADD, PAGE_EDIT, PAGE_VIEW, PAGE_LIST,
418
+ PAGE_SEARCH, PAGE_REGISTER, PAGE_LOGIN, PAGE_USERINFO );
419
+
420
+ // showing if there is Search panel on the page
421
+ $searchPanelActivated = $this->isSearchPanelActivated();
422
+
423
+ if( !in_array( $this->pageType, $allowedPageTypes ) && !$searchPanelActivated )
424
+ return;
425
+
426
+ switch( $this->pageType )
427
+ {
428
+ case PAGE_ADD:
429
+ $pageTypeStr = "Add";
430
+ break;
431
+ case PAGE_EDIT:
432
+ $pageTypeStr = "Edit";
433
+ break;
434
+ case PAGE_VIEW:
435
+ case PAGE_LIST:
436
+ $pageTypeStr = "List";
437
+ break;
438
+ default:
439
+ $pageTypeStr = "";
440
+ }
441
+
442
+ if( $pageTypeStr != "" )
443
+ {
444
+ $getEditFieldsFunc = "get".($this->pageLikeInline ? "Inline" : "").$pageTypeStr."Fields";
445
+ if( $this->pageLikeInline )
446
+ $appearOnPageFunc = "appearOnInline".$pageTypeStr;
447
+ else
448
+ $appearOnPageFunc = "appearOn".$pageTypeStr."Page";
449
+ }
450
+
451
+ switch( $this->pageType )
452
+ {
453
+ case PAGE_LOGIN:
454
+ case PAGE_REGISTER:
455
+ case PAGE_USERINFO:
456
+ $fields = $this->pSetEdit->getPageFields();
457
+ break;
458
+ case PAGE_SEARCH:
459
+ $fields = $this->pSetEdit->getAdvSearchFields();
460
+ break;
461
+ default:
462
+ $fields = array();
463
+ if( $getEditFieldsFunc )
464
+ $fields = $this->pSetEdit->$getEditFieldsFunc();
465
+ }
466
+
467
+ // Addign fields that aren't appear at list page, but appear on search panel
468
+ $searchFields = array();
469
+ if( $searchPanelActivated )
470
+ {
471
+ $searchFields = $this->pSetEdit->getPanelSearchFields();
472
+ $searchFields = array_merge($searchFields, $this->pSetEdit->getAllSearchFields());
473
+ $fields = array_merge($searchFields, $fields);
474
+ $fields = array_unique($fields);
475
+ }
476
+
477
+ foreach( $fields as $i => $f )
478
+ {
479
+ $appear = false;
480
+
481
+ if( $this->pageType == PAGE_REGISTER || $this->pageType == PAGE_SEARCH
482
+ || $this->pageType == PAGE_LOGIN || $this->pageType == PAGE_USERINFO
483
+ || in_array($f, $searchFields) )
484
+ {
485
+ $appear = true;
486
+ }
487
+ else if( $appearOnPageFunc )
488
+ $appear = $this->pSetEdit->$appearOnPageFunc($f);
489
+
490
+ if( $appear )
491
+ {
492
+ $editControl = $this->getControl($f);
493
+ $editControl->addJSFiles();
494
+ $editControl->addCSSFiles();
495
+ }
496
+ }
497
+ }
498
+
499
+ /**
500
+ * @param String field
501
+ * @param String id (optional)
502
+ * @param Array extraParmas (optional)
503
+ * @return Control
504
+ */
505
+ function getControl($field, $id = "", $extraParmas = array())
506
+ {
507
+ /*
508
+ if( count($extraParmas) && $extraParmas["makeReadonly"] ) {
509
+ include_once(getabspath("classes/controls/Control.php"));
510
+ $className = $this->classNamesForEdit[ EDIT_FORMAT_READONLY ];
511
+
512
+ $ctrl = createControlClass($className, $field, $this->pageObject != null ? $this->pageObject : $this, $id, $this->connection);
513
+ $ctrl->container = $this;
514
+
515
+ return $ctrl;
516
+ }
517
+ */
518
+
519
+ if( count($extraParmas) && $extraParmas["getConrirmFieldCtrl"] )
520
+ {
521
+ include_once(getabspath("classes/controls/Control.php"));
522
+ $className = $this->classNamesForEdit[ EDIT_FORMAT_PASSWORD ];
523
+
524
+ $ctrl = createControlClass($className, $field, $this->pageObject != null ? $this->pageObject : $this, $id, $this->connection);
525
+ if($extraParmas['isConfirm'])
526
+ $ctrl->field = Security::passwordField();
527
+ $ctrl->container = $this;
528
+
529
+ return $ctrl;
530
+ }
531
+
532
+ // if conrol does not created previously
533
+ if(!array_key_exists($field, $this->controls))
534
+ {
535
+ include_once(getabspath("classes/controls/Control.php"));
536
+
537
+ $userControl = false;
538
+ $editFormat = $this->getEditFormat($field);
539
+
540
+ if( ($this->pageType == PAGE_SEARCH || $this->pageType == PAGE_LIST ) && !$extraParmas["spreadsheet"] )
541
+ {
542
+ // Text field may be Lookup field on some page
543
+ $pageTypebyLookupFormat = $this->pSetEdit->getPageTypeByFieldEditFormat($field, EDIT_FORMAT_LOOKUP_WIZARD);
544
+
545
+ if( $editFormat == EDIT_FORMAT_TEXT_FIELD && $pageTypebyLookupFormat != "" )
546
+ {
547
+ $localPSet = new ProjectSettings($this->pSetEdit->_table, $pageTypebyLookupFormat);
548
+
549
+ if( $localPSet->getLinkField($field) != $localPSet->getDisplayField($field) )
550
+ $className = "LookupTextField";
551
+ else
552
+ $className = $this->classNamesForSearch[ $editFormat ];
553
+ }
554
+ else
555
+ $className = $this->classNamesForSearch[ $editFormat ];
556
+ }
557
+ else
558
+ $className = $this->classNamesForEdit[ $editFormat ];
559
+
560
+ if( $className == $this->classNamesForEdit[ EDIT_FORMAT_FILE ] && $this->pSetEdit->isBasicUploadUsed($field) )
561
+ $className = "FileFieldSingle";
562
+
563
+ if( !$className )
564
+ {
565
+ if($editFormat != "")
566
+ {
567
+ $className = "Edit".$editFormat;
568
+ $userControl = true;
569
+ include_once(getabspath("classes/controls/UserControl.php"));
570
+ if( !is_null($this->pageObject) )
571
+ $this->pageObject->AddJSFile("include/runnerJS/controls/".$className.".js", "include/runnerJS/editControls/Control.js");
572
+ }
573
+ else
574
+ $className = $this->classNamesForEdit[ EDIT_FORMAT_TEXT_FIELD ];
575
+ }
576
+
577
+ $this->controls[ $field ] = createControlClass($className, $field, $this->pageObject != null ? $this->pageObject : $this, $id, $this->connection);
578
+ $this->controls[ $field ]->container = $this;
579
+ $this->controls[ $field ]->forSpreadsheetGrid = $extraParmas["spreadsheet"];
580
+
581
+ if($userControl)
582
+ {
583
+ $this->controls[ $field ]->format = $className;
584
+ $this->controls[ $field ]->initUserControl();
585
+ }
586
+ }
587
+
588
+ if( $id !== "" )
589
+ $this->controls[ $field ]->setID($id);
590
+
591
+ return $this->controls[ $field ];
592
+ }
593
+
594
+ /**
595
+ * @deprecated
596
+ */
597
+ function isSystemControl($className)
598
+ {
599
+ include_once(getabspath("classes/controls/Control.php"));
600
+ if($this->pageType == PAGE_SEARCH || $this->pageType == PAGE_LIST)
601
+ return isset($this->classNamesForSearch[$className]);
602
+ else
603
+ return isset($this->classNamesForEdit[$className]);
604
+ }
605
+
606
+ /**
607
+ * Check if the host page is table based
608
+ * @return Boolean
609
+ */
610
+ function isPageTableBased()
611
+ {
612
+ if($this->pageType == PAGE_MENU || $this->pageType == PAGE_LOGIN || $this->pageType == PAGE_REMIND || $this->pageType == PAGE_CHANGEPASS)
613
+ {
614
+ return false;
615
+ }
616
+ return true;
617
+ }
618
+
619
+ function mobileTemplateMode()
620
+ {
621
+ return false;
622
+ }
623
+
624
+ protected function fillControlClassNames()
625
+ {
626
+ $this->classNamesForEdit[EDIT_FORMAT_TEXT_FIELD] = "TextField";
627
+ $this->classNamesForEdit[EDIT_FORMAT_TIME] = "TimeField";
628
+ $this->classNamesForEdit[EDIT_FORMAT_TEXT_AREA] = "TextAreaField";
629
+ $this->classNamesForEdit[EDIT_FORMAT_PASSWORD] = "PasswordField";
630
+ $this->classNamesForEdit[EDIT_FORMAT_DATE] = "DateField";
631
+ $this->classNamesForEdit[EDIT_FORMAT_CHECKBOX] = "CheckboxField";
632
+ $this->classNamesForEdit[EDIT_FORMAT_DATABASE_IMAGE] = "DatabaseFileField";
633
+ $this->classNamesForEdit[EDIT_FORMAT_DATABASE_FILE] = "DatabaseFileField";
634
+ $this->classNamesForEdit[EDIT_FORMAT_HIDDEN] = "HiddenField";
635
+ $this->classNamesForEdit[EDIT_FORMAT_READONLY] = "ReadOnlyField";
636
+ $this->classNamesForEdit[EDIT_FORMAT_FILE] = "FileField";
637
+ $this->classNamesForEdit[EDIT_FORMAT_LOOKUP_WIZARD] = "LookupField";
638
+
639
+ $this->classNamesForSearch[EDIT_FORMAT_TEXT_FIELD] = "TextField";
640
+ $this->classNamesForSearch[EDIT_FORMAT_TIME] = "TimeField";
641
+ $this->classNamesForSearch[EDIT_FORMAT_TEXT_AREA] = "TextField";
642
+ $this->classNamesForSearch[EDIT_FORMAT_PASSWORD] = "TextField";
643
+ $this->classNamesForSearch[EDIT_FORMAT_DATE] = "DateField";
644
+ $this->classNamesForSearch[EDIT_FORMAT_CHECKBOX] = "CheckboxField";
645
+ $this->classNamesForSearch[EDIT_FORMAT_DATABASE_IMAGE] = "TextField";
646
+ $this->classNamesForSearch[EDIT_FORMAT_DATABASE_FILE] = "TextField";
647
+ $this->classNamesForSearch[EDIT_FORMAT_HIDDEN] = "TextField";
648
+ $this->classNamesForSearch[EDIT_FORMAT_READONLY] = "TextField";
649
+ $this->classNamesForSearch[EDIT_FORMAT_FILE] = "FileField";
650
+ $this->classNamesForSearch[EDIT_FORMAT_LOOKUP_WIZARD] = "LookupField";
651
+
652
+ }
653
+
654
+ protected function getEditFormat( $field ) {
655
+ if( $this->pageObject ) {
656
+ return $this->pageObject->getEditFormat( $field );
657
+ }
658
+ return $this->pSetEdit->getEditFormat( $field );
659
+ }
660
+ }
661
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
662
  ?>
php/classes/controls/FileField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  require_once getabspath('classes/filehandler.php');
3
 
@@ -452,4 +453,460 @@ class FileField extends EditControl
452
 
453
 
454
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
455
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  require_once getabspath('classes/filehandler.php');
4
 
 
453
 
454
 
455
  }
456
+ =======
457
+ <?php
458
+ require_once getabspath('classes/filehandler.php');
459
+
460
+ class FileField extends EditControl
461
+ {
462
+ /**
463
+ * Field random identifier for sessions values
464
+ * @var {string}
465
+ */
466
+ var $formStamp = "";
467
+
468
+ function __construct($field, $pageObject, $id, $connection)
469
+ {
470
+ parent::__construct($field, $pageObject, $id, $connection);
471
+ $this->format = EDIT_FORMAT_FILE;
472
+ }
473
+
474
+ function addJSFiles() {
475
+ if ( $this->format = EDIT_FORMAT_FILE ) {
476
+ $this->pageObject->AddJSFile("include/mupload.js");
477
+ }
478
+ }
479
+
480
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
481
+ {
482
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
483
+
484
+ if( $mode == MODE_SEARCH ) {
485
+ $this->format = "";
486
+
487
+ $classString = "";
488
+ if( $this->pageObject->isBootstrap() )
489
+ $classString = " class=\"form-control\"";
490
+
491
+ echo '<input id="'.$this->cfield.'" '.$classString.$this->inputStyle.' type="text" '
492
+ .('autocomplete="off" ')
493
+ .( $this->is508==true ? 'alt="'.$this->strLabel.'" ' : '')
494
+ .'name="'.$this->cfield.'" '.$this->pageObject->pSetEdit->getEditParams($this->field).' value="'
495
+ .runner_htmlspecialchars($value).'">';
496
+
497
+ $this->buildControlEnd($validate, $mode);
498
+ return;
499
+ }
500
+
501
+ $this->formStamp = generatePassword(15);
502
+
503
+ $filesArray = $this->getFileData( $value );
504
+
505
+ $keylink = "";
506
+ if($this->pageObject->pageType == PAGE_EDIT) {
507
+ if( $this->pageObject->keys )
508
+ {
509
+ $i = 1;
510
+ foreach($this->pageObject->keys as $keyName => $keyValue)
511
+ {
512
+ $keylink .= "&key".$i."=".rawurlencode( $keyValue );
513
+ $i++;
514
+ }
515
+ }
516
+ }
517
+ $fh = new RunnerFileHandler( $this->field, $this->pageObject->pSet, $this->formStamp );
518
+ $userFilesArray = $fh->loadFiles( $filesArray );
519
+
520
+ $jsonValue = my_json_encode($userFilesArray);
521
+ $multiple = "";
522
+ if( $this->pageObject->pSetEdit->getMaxNumberOfFiles($this->field) != 1 )
523
+ $multiple = "multiple ";
524
+ echo '
525
+ <!-- The file upload form used as target for the file upload widget -->
526
+ <form id="fileupload_'.$this->cfieldname.'" action="'.GetTableLink("mfhandler").'" method="POST" enctype="multipart/form-data">
527
+
528
+ <input type="hidden" name="formStamp_'.$this->cfieldname.'" id="formStamp_'.$this->cfieldname.'" value="'.$this->formStamp.'" />
529
+ <input type="hidden" name="_action" value="POST" />
530
+ <input type="hidden" id="value_'.$this->cfieldname.'" name="value_'.$this->cfieldname.'" value="'.runner_htmlspecialchars($jsonValue).'" />
531
+
532
+ <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
533
+ <div class="fileupload-buttonbar">
534
+ <div class="span7">
535
+ <!-- The fileinput-button span is used to style the file input field as button -->
536
+ <SPAN class="btn btn-primary btn-sm fileinput-button filesUpload">
537
+ <!--<A class="rnr-button filesUpload button" href="#" >-->
538
+ <input class="fileinput-button-input" type="file" accept="'.$this->pageObject->pSetEdit->getAcceptFileTypesHtml($this->field).'" name="files[]" value="'
539
+ ."Add files"
540
+ .'" '. $multiple .' />'
541
+ ."Add files"
542
+ .'<!--</A>-->
543
+ </SPAN>'
544
+ .'
545
+
546
+ </div>
547
+ <!-- The global progress information -->
548
+ <div class="fileupload-progress fade">
549
+ <!-- The global progress bar -->
550
+ <div class="progress" role="progressbar" aria-valuemin="0" aria-valuenow="0" aria-valuemax="100">
551
+ <div style="width:0;" class="bar progress-bar progress-bar-info progress-bar-striped active" ></div>
552
+ </div>
553
+ <!-- The extended global progress information -->
554
+ <div class="progress-extended">&nbsp;</div>
555
+ </div>
556
+ </div>
557
+ <!-- The loading indicator is shown during file processing -->
558
+ <div class="fileupload-loading"></div>
559
+ <!-- The table listing the files available for upload/download -->
560
+ <table class="mupload-files"><tbody class="files"></tbody></table>
561
+ </form>
562
+ ';
563
+ if(!isset($this->container->globalVals["muploadTemplateIncluded"]))
564
+ {
565
+ echo '<script type="text/x-tmpl" id="template-download">{% for (var i=0, file; file=o.files[i]; i++) { %}
566
+ <tr class="template-download fade">
567
+ {% if (file.error) { %}
568
+ <td></td>
569
+ <td class="name"><span class="text-muted">{%=file.name%}</span></td>
570
+ <td class="size"><span class="text-muted" dir="LTR">{%=o.formatFileSize(file.size)%}</span></td>
571
+ <td colspan=2 class="error"><span class="text-danger rnr-error">'
572
+ .""
573
+ .' {%=locale.fileupload.errors[file.error] || file.error%}</span></td>
574
+ {% } else { %}
575
+ <td class="preview">{% if (file.thumbnail_url) { %}
576
+ <a href="{%=file.url%}" title="{%=file.name%}" rel="gallery" download="{%=file.name%}"
577
+ {% if (!file.isIco) { %} {% } %}
578
+ ><img class="mupload-preview-img" src="{%=file.thumbnail_url%}&src=1"></a>
579
+ {% } else { %}
580
+ {% if (file.isImg) { %}
581
+ <a href="{%=file.url%}&nodisp=1" title="{%=file.name%}" rel="gallery" download="{%=file.name%}" ><img class="mupload-preview-img" src="{%=file.url%}&src=1"></a>
582
+ {% } %}
583
+ {% } %}</td>
584
+ <td class="name">
585
+ <a href="{%=file.url%}" title="{%=file.name%}" rel="{%=file.thumbnail_url&&\'gallery\'%}" download="{%=file.name%}">{%=file.name%}</a>
586
+ </td>
587
+ <td class="size"><span dir="LTR">{%=o.formatFileSize(file.size)%}</span></td>
588
+ <td></td>
589
+ <td class="delete">
590
+ {% if (!file.error) { %}
591
+ <SPAN class="btn btn-xs btn-default delete" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}" data-name="{%=file.name%}">
592
+ <!--<A href="#" >-->'
593
+ ."Delete"
594
+ .'<!--</A>-->
595
+ </SPAN>
596
+ {% } %}
597
+ </td>
598
+ {% } %}
599
+ </tr>
600
+ {% } %}
601
+ </script>
602
+ <script type="text/x-tmpl" id="template-upload">{% for (var i=0, file; file=o.files[i]; i++) { %}
603
+ <tr class="template-upload fade">
604
+ <td class="preview"><span class="fade"></span></td>
605
+ {% if (file.error) { %}
606
+ <td class="name"><span class="text-muted">{%=file.name%}</span></td>
607
+ <td class="size"><span class="text-muted">{%=o.formatFileSize(file.size)%}</span></td>
608
+ <td class="error" colspan="2"><span class="text-danger rnr-error">'
609
+ .""
610
+ .' {%=locale.fileupload.errors[file.error] || file.error%}</span></td>
611
+ {% } else if (o.files.valid && !i) { %}
612
+ <td class="name"><span>{%=file.name%}</span></td>
613
+ <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
614
+ <td>
615
+ <div class="progress progress-success progress-striped active" role="progressbar" aria-valuemin="0"
616
+ aria-valuemax="100" aria-valuenow="0"><div class="progress-bar bar" style="width:0;"></div></div>
617
+ </td>
618
+ {% } else { %}
619
+ <td></td>
620
+ {% } %}
621
+ <td class="cancel">{% if (!i) { %}
622
+ {% if (!file.error) { %}
623
+ <SPAN class="btn btn-default btn-xs">
624
+ <!--<A href="#" >-->'
625
+ ."Cancel"
626
+ .'<!--</A>-->
627
+ </SPAN>
628
+ {% } %}
629
+ {% } %}</td>
630
+ </tr>
631
+ {% } %}</script>';
632
+ $this->container->globalVals["muploadTemplateIncluded"] = true;
633
+ }
634
+ $this->buildControlEnd($validate, $mode);
635
+ }
636
+
637
+ /**
638
+ * Create CSS code for specifying control's width
639
+ */
640
+ function makeWidthStyle($widthPx)
641
+ {
642
+ if(0 == $widthPx)
643
+ return "";
644
+ return "min-width: ".$widthPx."px";
645
+ }
646
+
647
+ public function readWebValue(&$avalues, &$blobfields, $legacy1, $legacy2, &$filename_values)
648
+ {
649
+ $this->getPostValueAndType();
650
+ $this->formStamp = postvalue("formStamp_".$this->goodFieldName."_".$this->id);
651
+ if (FieldSubmitted($this->goodFieldName."_".$this->id) && $this->formStamp != "")
652
+ {
653
+ $filesArray = my_json_decode($this->webValue);
654
+ if(!is_array($filesArray) || count($filesArray) == 0)
655
+ $this->webValue = "";
656
+ else
657
+ {
658
+ if(count($_SESSION["mupload_".$this->formStamp]) > 0)
659
+ {
660
+ foreach($_SESSION["mupload_".$this->formStamp] as $fileArray)
661
+ $fileArray["deleted"] = true;
662
+ }
663
+ $result = array();
664
+ $uploadDir = $this->pageObject->pSetEdit->getLinkPrefix($this->field);
665
+ $searchStr = "";
666
+ foreach ($filesArray as $file)
667
+ {
668
+ if(isset($_SESSION["mupload_".$this->formStamp][$file["name"]]))
669
+ {
670
+ $sessionFile = $_SESSION["mupload_".$this->formStamp][$file["name"]]["file"];
671
+ $searchStr .= $file["name"].",!";
672
+ $result[] = array("name" => $sessionFile["name"],
673
+ "usrName" => $file["name"], "size" => $sessionFile["size"], "type" => $sessionFile["type"]
674
+ );
675
+ if($this->pageObject->pSetEdit->getCreateThumbnail($this->field)
676
+ && $sessionFile["thumbnail"] != "")
677
+ {
678
+ $lastIndex = count($result) - 1;
679
+ $result[$lastIndex]["thumbnail"] = $sessionFile["thumbnail"];
680
+ $result[$lastIndex]["thumbnail_type"] = $sessionFile["thumbnail_type"];
681
+ $result[$lastIndex]["thumbnail_size"] = $sessionFile["thumbnail_size"];
682
+ }
683
+ $_SESSION["mupload_".$this->formStamp][$file["name"]]["deleted"] = false;
684
+ }
685
+ }
686
+ if(count($result) > 0)
687
+ {
688
+ $result[0]["searchStr"] = $searchStr.":sStrEnd";
689
+ $this->webValue = my_json_encode_unescaped_unicode($result);
690
+ }
691
+ else
692
+ $this->webValue = "";
693
+ }
694
+ }
695
+ else
696
+ $this->webValue = false;
697
+
698
+ if(!($this->webValue===false))
699
+ {
700
+ if( $this->connection->dbType == nDATABASE_Informix )
701
+ {
702
+ if(IsTextType($this->pageObject->pSetEdit->getFieldType($this->field)))
703
+ $blobfields[] = $this->field;
704
+ }
705
+ $avalues[$this->field] = $this->webValue;
706
+ }
707
+ }
708
+
709
+ /**
710
+ * Form the control specified search options array and built the control's search options markup
711
+ * @param String selOpt The search option value
712
+ * @param Boolean not It indicates if the search option negation is set
713
+ * @param Boolean both It indicates if the control needs 'NOT'-options
714
+ * @return String A string containing options markup
715
+ */
716
+ public function getSearchOptions($selOpt, $not, $both)
717
+ {
718
+ $optionsArray = array();
719
+ $isPHPEncripted = $this->pageObject->cipherer->isFieldPHPEncrypted($this->field);
720
+ if(!$isPHPEncripted){
721
+ $optionsArray[] = CONTAINS;
722
+ $optionsArray[] = EQUALS;
723
+ }
724
+ $optionsArray[] = EMPTY_SEARCH;
725
+ if($both)
726
+ {
727
+ if(!$isPHPEncripted){
728
+ $optionsArray[] = NOT_CONTAINS;
729
+ $optionsArray[] = NOT_EQUALS;
730
+ }
731
+ $optionsArray[] = NOT_EMPTY;
732
+ }
733
+ return $this->buildSearchOptions($optionsArray, $selOpt, $not, $both);
734
+ }
735
+
736
+ /**
737
+ * Fill the response array with the suggest values
738
+ *
739
+ * @param String value
740
+ * Note: the real value is preceeded with "_" so It's necessary to remove
741
+ * the first character before json decoding . Also It's important to add "_"
742
+ * to the beggining of the response suggest value because Searchsuggest
743
+ * expects that it starts with this character.
744
+ * @param String searchFor
745
+ * @param &Array response
746
+ * @param &Array row
747
+ */
748
+ public function suggestValue($value, $searchFor, &$response, &$row)
749
+ {
750
+ if(!$value)
751
+ return;
752
+
753
+ //value is preceeded with "_"
754
+ $value = substr($value, 1);
755
+
756
+ $filesArray = my_json_decode($value);
757
+
758
+ if(!is_array($filesArray) || count($filesArray) == 0)
759
+ $response[ "_".$value ] = "_".$value;
760
+ else
761
+ {
762
+ for($i = 0; $i < count($filesArray) && count($response) < 10; $i++)
763
+ {
764
+ if($this->pageObject->pSetEdit->getNCSearch())
765
+ $pos = stripos($filesArray[$i]["usrName"], $searchFor);
766
+ else
767
+ $pos = strpos($filesArray[$i]["usrName"], $searchFor);
768
+
769
+ if($pos !== false)
770
+ $response[ "_".$filesArray[$i]["usrName"] ] = "_".$filesArray[$i]["usrName"];
771
+ }
772
+ }
773
+ }
774
+
775
+ public function afterSuccessfulSave()
776
+ {
777
+ if( !$_SESSION["mupload_".$this->formStamp] ) {
778
+ return;
779
+ }
780
+ $fs = getStorageProvider( $this->pageObject->pSet, $this->field );
781
+ foreach( $_SESSION["mupload_".$this->formStamp] as $fileArray ) {
782
+ if( !$fileArray["deleted"] ) {
783
+ continue;
784
+ }
785
+ $fs->delete( $fileArray["file"]["name"] );
786
+ if( $fileArray["file"]["thumbnail"] ) {
787
+ $fs->delete( $fileArray["file"]["thumbnail"] );
788
+ }
789
+ }
790
+ unset($_SESSION["mupload_".$this->formStamp]);
791
+ }
792
+
793
+ /**
794
+ * @param String fieldValue
795
+ * @return String
796
+ */
797
+ public function getFieldValueCopy( $fieldValue )
798
+ {
799
+ $fs = getStorageProvider( $this->pageObject->pSet, $this->field );
800
+ if( !$fs->fast() ) {
801
+ return "[]";
802
+ }
803
+ $uploadFolder = $this->pageObject->pSetEdit->getUploadFolder( $this->field );
804
+
805
+ $filesData = $this->getFileData( $fieldValue );
806
+ foreach( array_keys( $filesData ) as $idx ) {
807
+ $file =& $filesData[ $idx ];
808
+ $newName = $fs->copyFile( $file["name"], $file["usrName"] );
809
+ if( !$newName ) {
810
+ continue;
811
+ }
812
+ $file["name"] = $newName;
813
+
814
+ if( $this->pageObject->pSetEdit->getCreateThumbnail( $this->field ) && $file["thumbnail"] ) {
815
+ $thumbnailPrefix = $this->pageObject->pSetEdit->getStrThumbnail( $this->field );
816
+ $newThumbnail = $fs->copyFile( $file["thumbnail"], $thumbnailPrefix.$file["usrName"] );
817
+ if( $newThumbnail ) {
818
+ $file["thumbnail"] = $newThumbnail;
819
+ } else {
820
+ unset( $file["thumbnail"] );
821
+ }
822
+ }
823
+ }
824
+
825
+ return my_json_encode( $filesData );
826
+ }
827
+
828
+ /**
829
+ * Returns basic condition
830
+ */
831
+ public function getBasicFieldCondition( $searchFor, $strSearchOption, $searchFor2 = "", $etype = "" ) {
832
+ if( $strSearchOption == EQUALS ) {
833
+ return $this->getFilenameCondition( dsopEQUAL, $searchFor );
834
+ } else if( $strSearchOption == STARTS_WITH ) {
835
+ return $this->getFilenameCondition( dsopSTART, $searchFor );
836
+ } else if( $strSearchOption == CONTAINS ) {
837
+ return $this->getFilenameCondition( dsopCONTAIN, $searchFor );
838
+ } else if( $strSearchOption == EMPTY_SEARCH ) {
839
+ return DataCondition::FieldIs( $this->field, dsopEMPTY, $searchFor );
840
+ }
841
+ return null;
842
+ }
843
+
844
+ /**
845
+ * Get file field search condition
846
+ * @param operation dsopEQUAL | dsopSTART | dsopCONTAIN
847
+ * @param String searchFor
848
+ * @return DsCondition
849
+ */
850
+ protected function getFilenameCondition( $operation, $searchFor ) {
851
+ $caseInsensitive = $this->pageObject->pSetEdit->getNCSearch() ? dsCASE_INSENSITIVE : dsCASE_DEFAULT;
852
+
853
+ $startCondition = DataCondition::FieldIs( $this->field, dsopSTART, "[{", $caseInsensitive );
854
+
855
+ // To extend like condition pattern
856
+ $likeWrapper = null;
857
+ $before = 'searchStr":"';
858
+ $after = ':sStrEnd"';
859
+
860
+ // set up suitable value and like wrapper parts
861
+ // to get proper like pattern for Condition with dsopCONTAIN op
862
+ // b $before, a $after, v $searchFor
863
+ if( $operation == dsopEQUAL ) {
864
+ // %bva% eg '%searchStr":"test.gif,!:sStrEnd"%'
865
+ // ',!' is added to the downloaded file name (ex. "test.gif,!")
866
+ $fileSearchFor = $before. $searchFor.',!' .$after;
867
+ } else if( $operation == dsopSTART ) {
868
+ // %bv%a% eg '%searchStr":"test.gif%:sStrEnd"%'
869
+ $fileSearchFor = $before.$searchFor;
870
+ $likeWrapper = array( 'after' => $after );
871
+ } else /* dsopCONTAIN */ {
872
+ // %b%v%a% eg '%searchStr":"%test.gif%:sStrEnd"%'
873
+ $fileSearchFor = $searchFor;
874
+ $likeWrapper = array( 'before' => $before, 'after' => $after );
875
+ }
876
+
877
+ return new DsCondition(
878
+ array(
879
+ new DsOperand( dsotCONDITION, DataCondition::_And( array(
880
+ $startCondition,
881
+ DataCondition::FieldIs( $this->field, dsopCONTAIN, $fileSearchFor, $caseInsensitive, 0, $likeWrapper )
882
+ ))),
883
+ new DsOperand( dsotCONDITION, DataCondition::_And( array(
884
+ DataCondition::_Not( $startCondition ),
885
+ DataCondition::FieldIs( $this->field, $operation, $searchFor, $caseInsensitive )
886
+ )))
887
+ ),
888
+ dsopOR,
889
+ $caseInsensitive
890
+ );
891
+ }
892
+ /**
893
+ * return parsed file info in unified format
894
+ * @return Array of arrays [
895
+ * "usrName" => user-provided filename
896
+ * "name" => file path if saved in filesystem
897
+ * "type" => (optional) file type in HTTP-ready format.
898
+ * "size" => (optional)size in bytes
899
+ * "thumbnail" => (optional)thumbnail file path
900
+ * "thumbnail_size" => (optional)thumbnail size
901
+ * "thumbnail_type" => (optional)thumbnail file type in HTTP-ready format
902
+ * ]
903
+ */
904
+ protected function getFileData( $value ) {
905
+ return RunnerFileHandler::getFileArray( $value, $this->field, $this->pageObject->pSet );
906
+ }
907
+
908
+
909
+
910
+ }
911
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
912
  ?>
php/classes/controls/FileFieldSingle.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  require_once getabspath('classes/filehandler.php');
3
 
@@ -274,4 +275,282 @@ class FileFieldSingle extends EditControl
274
  }
275
 
276
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  require_once getabspath('classes/filehandler.php');
4
 
 
275
  }
276
 
277
  }
278
+ =======
279
+ <?php
280
+ require_once getabspath('classes/filehandler.php');
281
+
282
+ class FileFieldSingle extends EditControl
283
+ {
284
+ function __construct($field, $pageObject, $id, $connection)
285
+ {
286
+ parent::__construct($field, $pageObject, $id, $connection);
287
+ $this->format = EDIT_FORMAT_FILE;
288
+
289
+ }
290
+
291
+
292
+ /**
293
+ * addJSFiles
294
+ * Add control JS files to page object
295
+ */
296
+ function addJSFiles()
297
+ {
298
+ }
299
+
300
+ /**
301
+ * addCSSFiles
302
+ * Add control CSS files to page object
303
+ */
304
+ function addCSSFiles()
305
+ {
306
+ }
307
+
308
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
309
+ {
310
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
311
+
312
+ if( $mode == MODE_SEARCH )
313
+ {
314
+ $this->format = "";
315
+
316
+ $classString = "";
317
+ if( $this->pageObject->isBootstrap() )
318
+ $classString = " class=\"form-control\"";
319
+
320
+ echo '<input id="'.$this->cfield.'" '.$classString.$this->inputStyle.' type="text" '
321
+ .('autocomplete="off" ')
322
+ .( $this->is508 == true ? 'alt="'.$this->strLabel.'" ' : '' )
323
+ .'name="'.$this->cfield.'" '.$this->pageObject->pSetEdit->getEditParams($this->field).' value="'
324
+ .runner_htmlspecialchars($value).'">';
325
+
326
+ $this->buildControlEnd($validate, $mode);
327
+ return;
328
+ }
329
+
330
+ $keyParams = array();
331
+ foreach( $this->pageObject->pSetEdit->getTableKeys() as $i => $kf ) {
332
+ $keyParams[] = "key".($i + 1). "=".runner_htmlspecialchars(rawurlencode( @$data[ $kf ] ));
333
+ }
334
+ $keyLink = "&" . implode("&", $keyParams);
335
+
336
+
337
+ $disp = "";
338
+ $strfilename = "";
339
+
340
+ $filename_size = $this->pageObject->pSetEdit->isUseTimestamp( $this->field )
341
+ ? 50
342
+ : 30;
343
+
344
+ if( $mode == MODE_EDIT || $mode == MODE_INLINE_EDIT )
345
+ {
346
+ // show current file
347
+ $filesArray = $this->getFileData( $value );
348
+ $fileName = "";
349
+ if( $filesArray ) {
350
+ $fileData = $filesArray[0];
351
+ $fileName = $fileData["usrName"];
352
+
353
+ $viewFormat = $this->pageObject->pSetEdit->getViewFormat( $this->field );
354
+ if( $viewFormat == FORMAT_FILE || $viewFormat == FORMAT_FILE_IMAGE )
355
+ $disp = $this->getFileOrImageMarkup( $fileData, $keyLink ) . "<br />";
356
+ }
357
+
358
+
359
+ // filename edit
360
+ $strfilename = '<input type=hidden name="filenameHidden_'.$this->cfieldname.'" value="'.runner_htmlspecialchars( $fileName ).'"><br>'
361
+ ."Filename"
362
+ .'&nbsp;&nbsp;<input type="text" style="background-color:gainsboro" disabled id="filename_'.$this->cfieldname
363
+ .'" name="filename_'.$this->cfieldname.'" size="'.$filename_size.'" maxlength="100" value="'.runner_htmlspecialchars( $fileName ).'">';
364
+
365
+ $strtype = '<br><input id="'.$this->ctype.'_keep" type="Radio" name="'.$this->ctype
366
+ .'" value="upload0" checked class="rnr-uploadtype">'."Keep";
367
+
368
+ if( (strlen($value) || $mode == MODE_INLINE_EDIT) && !$this->pageObject->pSetEdit->isRequired($this->field) )
369
+ {
370
+ $strtype .= '<input id="'.$this->ctype.'_delete" type="Radio" name="'.$this->ctype
371
+ .'" value="upload1" class="rnr-uploadtype">'."Delete";
372
+ }
373
+ $strtype .= '<input id="'.$this->ctype.'_update" type="Radio" name="'.$this->ctype
374
+ .'" value="upload2" class="rnr-uploadtype">'."Update";
375
+ }
376
+ else
377
+ {
378
+ // if Adding record
379
+ $strtype = '<input id="'.$this->ctype.'" type="hidden" name="'.$this->ctype.'" value="upload2">';
380
+
381
+ $strfilename = '<br>'."Filename"
382
+ .'&nbsp;&nbsp;<input type="text" id="filename_'.$this->cfieldname.'" name="filename_'.$this->cfieldname.'" size="'
383
+ .$filename_size.'" maxlength="100">';
384
+ }
385
+
386
+ echo $disp.$strtype;
387
+
388
+ if( $mode == MODE_EDIT || $mode == MODE_INLINE_EDIT )
389
+ echo '<br>';
390
+
391
+ echo '<input type="File" id="'.$this->cfield.'" '
392
+ .'accept="'.$this->pageObject->pSetEdit->getAcceptFileTypesHtml($this->field).'" '
393
+ .( ($mode == MODE_INLINE_EDIT || $mode == MODE_INLINE_ADD) && $this->is508 == true ? 'alt="'.$this->strLabel.'" ' : '')
394
+ .' name="'.$this->cfield.'" >'.$strfilename;
395
+
396
+ echo '<input type="Hidden" id="notempty_'.$this->cfieldname.'" value="'.(strlen($value)? 1 : 0).'">';
397
+
398
+ $this->buildControlEnd($validate, $mode);
399
+ }
400
+
401
+ /**
402
+ * Get the image or file link markup
403
+ * @param String value
404
+ * @param String fileName
405
+ * @param Boolean newUploaderWasUsed
406
+ * @param Array fileData
407
+ * @return String
408
+ */
409
+ function getFileOrImageMarkup( $fileData, $keylink )
410
+ {
411
+ $fileName = $fileData["usrName"];
412
+ $urls = $this->getFileUrls( $fileData, $keylink );
413
+ if( !$urls["url"] ) {
414
+ return "";
415
+ }
416
+
417
+
418
+ if( !CheckImageExtension( $fileName ) )
419
+ {
420
+ return "<a target=\"_blank\" href=\"". runner_htmlspecialchars( $urls["url"] )."\">"
421
+ .runner_htmlspecialchars( $fileName )."</a>";
422
+ }
423
+
424
+ if( !$urls["thumbnail"] ) {
425
+ $urls["thumbnail"] = $urls["url"];
426
+ }
427
+
428
+ $altAttr = " alt=\"".runner_htmlspecialchars( $fileName )."\"" ;
429
+ return "<a target=\"_blank\" href=\"". runner_htmlspecialchars( $urls["url"] ) . "\" >"
430
+ ."<img class=\"r-editfile-img\" ". $altAttr ." border=0 src=\"". runner_htmlspecialchars( $urls["thumbnail"] ) . "\"></a>";
431
+
432
+ }
433
+
434
+ /**
435
+ *
436
+ */
437
+ function readWebValue(&$avalues, &$blobfields, $legacy1, $legacy2, &$filename_values)
438
+ {
439
+ $this->getPostValueAndType();
440
+
441
+ if( FieldSubmitted( $this->goodFieldName."_".$this->id ) )
442
+ {
443
+ $fileNameForPrepareFunc = securityCheckFileName( postvalue("filename_".$this->goodFieldName."_".$this->id) );
444
+ if( $this->pageObject->pageType != PAGE_EDIT )
445
+ {
446
+ $this->webValue = prepare_upload($this->field, "upload2", $fileNameForPrepareFunc, $fileNameForPrepareFunc, ""
447
+ , $this->id, $this->pageObject);
448
+ }
449
+ else
450
+ {
451
+ if(substr($this->webType, 0, 4) == "file")
452
+ {
453
+ $prepearedFile = prepare_file($this->webValue, $this->field, $this->webType, $fileNameForPrepareFunc, $this->id);
454
+ if($prepearedFile !== false)
455
+ {
456
+ $this->webValue = $prepearedFile["value"];
457
+ $filename = $prepearedFile["filename"];
458
+ }
459
+ else
460
+ $this->webValue = false;
461
+ }
462
+ else if(substr($this->webType, 0, 6) == "upload")
463
+ {
464
+ if($fileNameForPrepareFunc)
465
+ $this->webValue = $fileNameForPrepareFunc;
466
+ if($this->webType == "upload1")
467
+ {
468
+ // file deletion, read filename from the database
469
+ $oldValues = $this->pageObject->getOldRecordData();
470
+ $fileNameForPrepareFunc = $oldValues[$this->field];
471
+ }
472
+ $this->webValue = prepare_upload($this->field, $this->webType, $fileNameForPrepareFunc, $this->webValue, "", $this->id, $this->pageObject);
473
+ }
474
+ }
475
+ }
476
+ else
477
+ $this->webValue = false;
478
+
479
+ if(!($this->webValue === false))
480
+ {
481
+ if( $this->webValue && $this->pageObject->pSetEdit->getCreateThumbnail($this->field) )
482
+ {
483
+ $contents = GetUploadedFileContents("value_".$this->goodFieldName."_".$this->id);
484
+ $ext = CheckImageExtension( GetUploadedFileName("value_".$this->goodFieldName."_".$this->id) );
485
+ if( $ext ) {
486
+ $thumb = CreateThumbnail($contents, $this->pageObject->pSetEdit->getThumbnailSize($this->field), $ext);
487
+ $this->pageObject->filesToSave[] = new SaveFile($thumb, $this->pageObject->pSetEdit->GetStrThumbnail($this->field)
488
+ .$this->webValue, $this->pageObject->pSetEdit->getUploadFolder($this->field), $this->pageObject->pSetEdit->isAbsolute($this->field));
489
+ }
490
+ }
491
+
492
+ $avalues[ $this->field ] = $this->webValue;
493
+ }
494
+ }
495
+
496
+ function makeWidthStyle($widthPx)
497
+ {
498
+ if(0 == $widthPx)
499
+ return "";
500
+ return "min-width: ".$widthPx."px";
501
+ }
502
+
503
+ protected function getFileData( $value ) {
504
+ return RunnerFileHandler::getFileArray( $value, $this->field, $this->pageObject->pSet );
505
+ }
506
+
507
+ /**
508
+ * @return Array
509
+ * "url" => string
510
+ * "thumbnail" => string
511
+ * Each element can be empty if no corresponding file exists
512
+ *
513
+ */
514
+ protected function getFileUrls( $fileData, $keylink ) {
515
+ $pSet = $this->pageObject->pSet;
516
+ $fs = getStorageProvider( $pSet, $this->field );
517
+ $fsInfo = $fs->getFileInfo( $fileData["name"] );
518
+ if( !$fsInfo ) {
519
+ return array();
520
+ }
521
+ $lastModified = time();
522
+ if( $fsInfo["lastModified"]) {
523
+ $lastModified = $fsInfo["lastModified"];
524
+ }
525
+
526
+ $params = array();
527
+ $params["file"] = $fileData["usrName"];
528
+ $params["table"] = $pSet->table();
529
+ $params["field"] = $this->field;
530
+ $params["hash"] = fileAttrHash( $keylink, $file["size"], $lastModified );
531
+
532
+ foreach( $additionalParams as $k => $val ) {
533
+ $params[ $k ] = $val;
534
+ }
535
+ $ret = array();
536
+ $ret["url"] = GetTableLink("file", "", prepareUrlQuery( $params ).$keylink );
537
+
538
+
539
+ if( $fileData["thumbnail"] && $fs->getFileInfo( $fileData["thumbnail"] ) ) {
540
+ $params["thumbnail"] = 1;
541
+ $ret["thumbnail"] = GetTableLink("file", "", prepareUrlQuery( $params ).$keylink );
542
+ }
543
+
544
+ if( !$ret["thumbnail"] && $fsInfo["size"] > 512000 ) {
545
+ $ret["thumbnail"] = "images/icons/jpg.png";
546
+ }
547
+
548
+
549
+ return $ret;
550
+
551
+
552
+ }
553
+
554
+ }
555
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
556
  ?>
php/classes/controls/FilterBoolean.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class FilterBoolean extends FilterControl
3
  {
@@ -134,4 +135,142 @@ class FilterBoolean extends FilterControl
134
  return CheckboxField::getFieldCondition( $fName, $value );
135
  }
136
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class FilterBoolean extends FilterControl
4
  {
 
135
  return CheckboxField::getFieldCondition( $fName, $value );
136
  }
137
  }
138
+ =======
139
+ <?php
140
+ class FilterBoolean extends FilterControl
141
+ {
142
+ public function __construct($fName, $pageObject, $id, $viewControls)
143
+ {
144
+ parent::__construct($fName, $pageObject, $id, $viewControls);
145
+
146
+ $this->separator = "~checked~";
147
+ $this->filterFormat = FF_BOOLEAN;
148
+
149
+ if( $this->totals == FT_NONE || $this->totals == FT_COUNT )
150
+ $this->totalsfName = $this->fName;
151
+ }
152
+
153
+ /**
154
+ * Get the view controls' value
155
+ * @param String value
156
+ * @return String
157
+ */
158
+ protected function getValueToShow( $value ) {
159
+ return $this->getShownValue( $value == "on" );
160
+ }
161
+
162
+ /**
163
+ * Get the filter's label
164
+ * @param Boolean checked
165
+ * @return String
166
+ */
167
+ protected function getShownValue( $checked ) {
168
+ $mData = $this->pSet->getBooleanFilterMessageData( $this->fName, $checked );
169
+ return $this->getLabel( $mData["type"], $mData["text"] );
170
+ }
171
+
172
+ /**
173
+ * Form complex totals by aggregating SQL CASE statements, eg:
174
+ SELECT MAX( case when %field is on% then %total field% else null end ) AS `on_max`,
175
+ COUNT( case when %field is on% then 1 else null end ) AS `on_count`,
176
+ MAX( case when %field is off% then %total field% else null end ) AS `off_max`,
177
+ COUNT( case when %field is off% then 1 else null end ) AS `off_count`
178
+ FROM (...)
179
+ */
180
+ protected function getDataCommand() {
181
+ $dc = new DsCommand;
182
+ $dc->filter = $this->pageObject->getDataSourceFilterCriteria( $this->fName );
183
+
184
+ $total = $this->dataTotalsName();
185
+ if( !$total )
186
+ $total = "count";
187
+
188
+ $values = array("on", "off");
189
+ foreach( $values as $v ) {
190
+ if( $total == "count" ) {
191
+ $caseExpr = DataCondition::CaseConstOrNull(
192
+ FilterBoolean::getFilterCondition( $this->fName, $v, $this->pSet ),
193
+ 1
194
+ );
195
+ } else {
196
+ $caseExpr = DataCondition::CaseFieldOrNull(
197
+ FilterBoolean::getFilterCondition( $this->fName, $v, $this->pSet ),
198
+ $this->totalsfName
199
+ );
200
+ }
201
+ $dc->totals[] = array(
202
+ "total" => $total,
203
+ "alias" => $v."_".$total,
204
+ "caseStatement" => $caseExpr
205
+ /*
206
+ "ifCondition" => FilterBoolean::getFilterCondition( $this->fName, $v, $this->pSet ),
207
+ "thenField" => $this->totalsfName,
208
+ "elseConst" => 'null'
209
+ */
210
+ );
211
+
212
+ if( $total != "count" ) {
213
+ $dc->totals[] = array(
214
+ "total" => "count",
215
+ "alias" => $v."_count",
216
+ "caseStatement" => DataCondition::CaseConstOrNull(
217
+ FilterBoolean::getFilterCondition( $this->fName, $v, $this->pSet ),
218
+ 1
219
+ )
220
+ );
221
+ }
222
+ }
223
+
224
+ return $dc;
225
+ }
226
+
227
+ /**
228
+ * Add new filter blocks fetched from db
229
+ * @param &Array
230
+ */
231
+ protected function addFilterBlocksFromDB( &$filterCtrlBlocks ) {
232
+ //$data = $this->connection->query( $this->strSQL )->fetchAssoc();
233
+
234
+ $qResult = $this->dataSource->getTotals( $this->getDataCommand() );
235
+ $data = $qResult->fetchAssoc();
236
+
237
+ $this->decryptDataRow( $data );
238
+
239
+ if( $data["on_count"] == 0 && $data["off_count"] == 0 ) {
240
+ // no records found, hide filter
241
+ return;
242
+ }
243
+
244
+ $values = array("on", "off");
245
+ foreach( $values as $v ) {
246
+ $ctrlData = array( "value" => $v );
247
+ if( $this->dataTotalsName() )
248
+ $ctrlData["total"] = $data[ $v."_".$this->dataTotalsName() ];
249
+
250
+ $filterControl = $this->buildControl( $ctrlData );
251
+ $filterCtrlBlocks[] = $this->getFilterBlockStructure( $filterControl );
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Get a control's markup
257
+ * @params Array data
258
+ * @param Array parentFiltersData (optional)
259
+ * @return String
260
+ */
261
+ protected function buildControl( $data, $parentFiltersData = array() ) {
262
+ $showValue = $this->getShownValue( $data["value"] == "on" );
263
+ $totalValue = $this->getTotalValueToShow( $data["total"] );
264
+
265
+ return $this->getControlHTML( $data["value"], $showValue, $data["value"], $totalValue, $this->separator );
266
+ }
267
+
268
+ public static function getFilterCondition( $fName, $value, $pSet ) {
269
+ include_once getabspath("classes/controls/Control.php");
270
+ include_once getabspath("classes/controls/CheckboxField.php");
271
+
272
+ return CheckboxField::getFieldCondition( $fName, $value );
273
+ }
274
+ }
275
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
276
  ?>
php/classes/controls/FilterControl.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  /**
3
  * The base class for filter controls
@@ -662,4 +663,670 @@ class FilterControl
662
  }
663
  }
664
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
665
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  /**
4
  * The base class for filter controls
 
663
  }
664
  }
665
 
666
+ =======
667
+ <?php
668
+ /**
669
+ * The base class for filter controls
670
+ */
671
+ class FilterControl
672
+ {
673
+ protected $id;
674
+
675
+ protected $fName;
676
+
677
+ protected $gfName;
678
+
679
+ protected $tName;
680
+
681
+ protected $pSet;
682
+
683
+ protected $totals;
684
+
685
+ protected $useTotals;
686
+
687
+ protected $multiSelect;
688
+
689
+ protected $cipherer;
690
+
691
+ protected $filteredFields;
692
+
693
+ protected $filtered = false;
694
+
695
+ protected $totalsfName;
696
+
697
+ protected $strSQL;
698
+
699
+ /**
700
+ * can be NULL
701
+ */
702
+ protected $viewControl;
703
+
704
+ protected $visible = true;
705
+
706
+ protected $filterFormat;
707
+
708
+ protected $useApllyBtn = false;
709
+
710
+ protected $separator = '~~';
711
+
712
+ /**
713
+ * can be NULL
714
+ */
715
+ protected $totalViewControl;
716
+
717
+ protected $showCollapsed = false;
718
+
719
+ protected $whereComponents;
720
+
721
+ protected $fieldType;
722
+
723
+ protected $valuesObtainedFromDB = array();
724
+
725
+ protected $onDemandHiddenItemClassName = "filter-hidden";
726
+
727
+ /**
728
+ * @type Connection
729
+ */
730
+ protected $connection;
731
+ protected $dataSource;
732
+
733
+ public $dependent = false;
734
+
735
+ public $parentFilterName = "";
736
+
737
+ public $pageObject;
738
+
739
+ protected $parentFiltersNames = array();
740
+
741
+
742
+ public function __construct($fName, $pageObj, $id, $viewControls)
743
+ {
744
+ $this->pageObject = $pageObj;
745
+ $this->id = $id;
746
+ $this->fName = $fName;
747
+ $this->gfName = GoodFieldName($this->fName);
748
+ $this->tName = $pageObj->tName;
749
+ $this->connection = $pageObj->connection;
750
+ $this->dataSource = $pageObj->getDataSource();
751
+
752
+ $this->pSet = $pageObj->pSet;
753
+ $this->cipherer = $pageObj->cipherer;
754
+
755
+ $this->totals = $this->pSet->getFilterFieldTotal($fName);
756
+ $this->totalsfName = $this->pSet->getFilterTotalsField($fName);
757
+ if(!$this->totalsfName || $this->totals == FT_COUNT)
758
+ $this->totalsfName = $this->fName;
759
+
760
+ $this->useTotals = $this->totals != FT_NONE;
761
+
762
+ $this->multiSelect = $this->pSet->getFilterFiledMultiSelect($fName);
763
+
764
+
765
+ $this->filteredFields = $pageObj->searchClauseObj->getFilteredFields();
766
+ $this->fieldType = $this->pSet->getFieldType($this->fName);
767
+
768
+ if( !!$this->filteredFields[ $this->fName ] )
769
+ $this->filtered = true;
770
+
771
+ $this->assignViewControls($viewControls);
772
+
773
+ $this->showCollapsed = $this->pSet->showCollapsed($this->fName);
774
+ }
775
+
776
+ /**
777
+ * Get and assign view controls for the filter's and total fields
778
+ * @param object pageObj
779
+ */
780
+ protected function assignViewControls($viewControls)
781
+ {
782
+ if( !$viewControls ) {
783
+ return;
784
+ }
785
+ $this->viewControl = $viewControls->getControl($this->fName);
786
+ //prevent filter's values from highlighting
787
+ $this->viewControl->searchHighlight = false;
788
+ //prevent filter's values from truncating
789
+ $this->viewControl->isUsedForFilter = true;
790
+
791
+ if($this->totals == FT_MIN || $this->totals == FT_MAX)
792
+ {
793
+ $this->totalViewControl = $viewControls->getControl($this->totalsfName);
794
+ //prevent filter's values from highlighting
795
+ $this->totalViewControl->searchHighlight = false;
796
+ //prevent filter's values from truncating
797
+ $this->totalViewControl->isUsedForFilter = true;
798
+ }
799
+ }
800
+
801
+ /**
802
+ * Add filter control's data to the ControlsMap
803
+ * @param Object pageObj
804
+ */
805
+ public function addFilterControlToControlsMap($pageObj)
806
+ {
807
+ $ctrlsMap = $this->getBaseContolsMapParams();
808
+ $pageObj->controlsMap["filters"]["controls"][] = $ctrlsMap;
809
+ }
810
+
811
+ /**
812
+ * Get filter control's base ControlsMap array
813
+ * @return array
814
+ */
815
+ protected function getBaseContolsMapParams()
816
+ {
817
+ $ctrlsMap = array();
818
+ $ctrlsMap['fieldName'] = $this->fName;
819
+ $ctrlsMap['gfieldName'] = $this->gfName;
820
+ $ctrlsMap['filterFormat'] = $this->filterFormat;
821
+ $ctrlsMap['multiSelect'] = $this->multiSelect;
822
+ $ctrlsMap['filtered'] = $this->filtered;
823
+ $ctrlsMap['separator'] = $this->separator;
824
+ $ctrlsMap['collapsed'] = $this->showCollapsed;
825
+
826
+ if( $this->filtered )
827
+ {
828
+ $ctrlsMap['defaultValuesArray'] = $this->filteredFields[ $this->fName ]["values"];
829
+ $ctrlsMap['defaultShowValues'] = array();
830
+ foreach( $ctrlsMap['defaultValuesArray'] as $dv )
831
+ {
832
+ $ctrlsMap['defaultShowValues'][] = $this->getValueToShow( $dv );
833
+ }
834
+ }
835
+
836
+ return $ctrlsMap;
837
+ }
838
+
839
+
840
+ /**
841
+ * The stub. It's overrided in the children classes
842
+ */
843
+ protected function getValueToShow($value)
844
+ {
845
+ }
846
+
847
+ /**
848
+ * Get the total field value
849
+ * @param String totalValue
850
+ * @return String
851
+ */
852
+ protected function getTotalValueToShow($totalValue)
853
+ {
854
+ if($this->totals == FT_MIN || $this->totals == FT_MAX)
855
+ {
856
+ $totalData = array( $this->totalsfName => $totalValue );
857
+ $totalValue = $this->totalViewControl->showDBValue($totalData, "");
858
+ }
859
+ return $totalValue;
860
+ }
861
+
862
+ /**
863
+ * Get the Filter's control block data.
864
+ * @param Object pageObj
865
+ * @param Array $dFilterBlocks (optional)
866
+ * @return Array
867
+ */
868
+ public function buildFilterCtrlBlockArray( $pageObj, $dFilterBlocks = null )
869
+ {
870
+ $this->addFilterControlToControlsMap($pageObj);
871
+
872
+ $filterCtrlBlocks = array();
873
+
874
+ if($this->multiSelect != FM_ALWAYS && $this->filtered)
875
+ {
876
+ $filterCtrlBlocks = $this->getFilteredFilterBlocks();
877
+
878
+ if($this->multiSelect == FM_NONE)
879
+ return $filterCtrlBlocks;
880
+ }
881
+
882
+ $this->addFilterBlocksFromDB($filterCtrlBlocks);
883
+
884
+ if( $this->multiSelect != FM_NONE && $this->filtered )
885
+ $this->addOutRangeValuesToFilter($filterCtrlBlocks);
886
+
887
+ if( !$filterCtrlBlocks )
888
+ $this->visible = false;
889
+
890
+ $this->extraBlocksProcessing($filterCtrlBlocks);
891
+
892
+ return $filterCtrlBlocks;
893
+ }
894
+
895
+ /**
896
+ * Update filter blocks structures
897
+ * @param &Array
898
+ */
899
+ protected function extraBlocksProcessing( &$filterCtrlBlocks )
900
+ {
901
+ $this->sortFilterBlocks($filterCtrlBlocks);
902
+ }
903
+
904
+ /**
905
+ * The stub. It could be overrided in the children classes
906
+ */
907
+ protected function sortFilterBlocks( &$filterCtrlBlocks )
908
+ {
909
+ }
910
+
911
+ /**
912
+ * A stub
913
+ * @return Boolean
914
+ */
915
+ protected function isTruncated()
916
+ {
917
+ return false;
918
+ }
919
+
920
+ /**
921
+ * Usort callback function comparing filter blocks
922
+ * basing on db numeric values
923
+ */
924
+ static function compareBlocksByNumericValues( $block1, $block2 )
925
+ {
926
+ if( $block1["sortValue"] < $block2["sortValue"] )
927
+ return -1;
928
+
929
+ if( $block1["sortValue"] > $block2["sortValue"] )
930
+ return 1;
931
+
932
+ return 0;
933
+ }
934
+
935
+ /**
936
+ * Usort callback function comparing filter blocks
937
+ * basing on db or formatted values
938
+ */
939
+ static function compareBlocksByStringValues( $block1, $block2 )
940
+ {
941
+ $sortValue1 = (string)$block1["sortValue"];
942
+ $sortValue2 = (string)$block2["sortValue"];
943
+
944
+ $caseCompareResult = strcasecmp($sortValue1, $sortValue2);
945
+ if($caseCompareResult == 0)
946
+ return -strcmp($sortValue1, $sortValue2);
947
+
948
+ return $caseCompareResult;
949
+ }
950
+
951
+ /**
952
+ * Get the multiselect filters' filterblocks for values
953
+ * that are out of range. And add them to the existing filter blocks
954
+ * @param &Array filterCtrlBlocks
955
+ */
956
+ protected function addOutRangeValuesToFilter(&$filterCtrlBlocks)
957
+ {
958
+ $visibilityClass = $this->multiSelect == FM_ON_DEMAND ? $this->onDemandHiddenItemClassName : "";
959
+
960
+ foreach( $this->filteredFields[ $this->fName ]["values"] as $value)
961
+ {
962
+ if(in_array($value, $this->valuesObtainedFromDB))
963
+ continue;
964
+
965
+ $filterControl = $this->buildControl( array($this->fName => $value) );
966
+ $filterCtrlBlocks[] = $this->getFilterBlockStructure($filterControl, $visibilityClass, $value);
967
+ }
968
+ }
969
+
970
+ /**
971
+ * Get the arrray with keys corresponding to filter blocks markup
972
+ * @param String filterControl
973
+ * @param String visibilityClass
974
+ * @param String value The raw Db field's value
975
+ * @param Array parentFiltersData (optional)
976
+ * @return Array
977
+ */
978
+ protected function getFilterBlockStructure( $filterControl, $visibilityClass = "", $value = "", $parentFiltersData = array() )
979
+ {
980
+ return array($this->gfName."_filter" => $filterControl, "visibilityClass_".$this->gfName => $visibilityClass);
981
+ }
982
+
983
+ /**
984
+ * Get the filtered not multiselect filter's control block
985
+ * @return Array
986
+ */
987
+ protected function getFilteredFilterBlocks()
988
+ {
989
+ $filterControl = array();
990
+ foreach($this->filteredFields[ $this->fName ]["values"] as $value)
991
+ {
992
+ $showValue = $this->getControlCaption( $value );
993
+ $delButtonHtml = $this->getDelButtonHtml($this->gfName, $this->id, $value);
994
+ $filterControl = '<span>'.$delButtonHtml.$showValue.'</span>';
995
+ $parentFiltersData = $this->getParentFiltersDataForFilteredBlock($value);
996
+ $classes = 'filter-ready-value'.( $this->multiSelect == FM_ON_DEMAND ? ' ondemand' : '' );
997
+ $filterCtrlBlocks[] = $this->getFilterBlockStructure($filterControl, $classes, $value, $parentFiltersData);
998
+ }
999
+
1000
+ return $filterCtrlBlocks;
1001
+ }
1002
+
1003
+ protected function getControlCaption( $value )
1004
+ {
1005
+ return $this->getValueToShow($value);
1006
+ }
1007
+
1008
+ /**
1009
+ * A stab for not dependent filters
1010
+ * @param String
1011
+ * @return Array
1012
+ */
1013
+ protected function getParentFiltersDataForFilteredBlock($value)
1014
+ {
1015
+ return array();
1016
+ }
1017
+
1018
+ /**
1019
+ * The stub. It's overrided in the children classes
1020
+ */
1021
+ protected function addFilterBlocksFromDB(&$filterBlocks)
1022
+ {
1023
+ }
1024
+
1025
+ /**
1026
+ * Get the markup representing a control on the page
1027
+ * @param String value
1028
+ * @param String showValue
1029
+ * @param String dataValue
1030
+ * @param String totalValue
1031
+ * @param String separator
1032
+ * @param Array parentFiltersData
1033
+ * @return String
1034
+ */
1035
+ protected function getControlHTML($value, $showValue, $dataValue, $totalValue, $separator, $parentFiltersData = null)
1036
+ {
1037
+ $filterControl = '';
1038
+ $encodeDataValue = runner_htmlspecialchars($dataValue);
1039
+ $dataValueAttr = 'data-filtervalue="'.$encodeDataValue.'"';
1040
+
1041
+ $extraDataAttrs = $this->getExtraDataAttrs($parentFiltersData);
1042
+
1043
+ $pageType = 'list';
1044
+ if( isReport( $this->pSet->getEntityType() ) )
1045
+ $pageType = 'report';
1046
+ else if( isChart( $this->pSet->getEntityType() ) )
1047
+ $pageType = 'chart';
1048
+
1049
+ if($this->multiSelect != FM_NONE)
1050
+ {
1051
+ $style = $this->filtered || $this->multiSelect == FM_ALWAYS ? '' : 'style="display: none;"';
1052
+ $checkedAttr = $this->getCheckedAttr( $value, $parentFiltersData );
1053
+
1054
+ $checkBox = '<input type="checkbox" '.$checkedAttr.' name="f[]" value="'.$encodeDataValue.'" '
1055
+ .$extraDataAttrs.' class="multifilter-checkbox filter_'.$this->gfName.'_'.$this->id.'" '.$style.'>';
1056
+ }
1057
+ if($this->multiSelect != FM_ALWAYS)
1058
+ {
1059
+ $href = GetTableLink( GetTableURL($this->tName), $pageType, 'f=('.runner_htmlspecialchars( rawurlencode( $this->fName ) ).
1060
+ $separator.$encodeDataValue.')' );
1061
+ $hrefAttr = 'href="'.$href.'"';
1062
+ $label = $checkBox . ' ' .$showValue;
1063
+ }
1064
+ else
1065
+ {
1066
+ $label = $checkBox . ' <span>'.$showValue.'</span>';
1067
+ }
1068
+
1069
+ if($this->useTotals && $totalValue != "")
1070
+ $label .= ' <span dir="LTR">('.$totalValue.')</span>';
1071
+
1072
+ $labelAttrs = implode( " ", array( $hrefAttr, $dataValueAttr, $extraDataAttrs ) );
1073
+ $label = '<a '.$labelAttrs.' class="'.$this->gfName.'-filter-value">' . $label . "</a>";
1074
+
1075
+ $filterControl.= $label;
1076
+ // $filterControl.= '<span>'.$label.'</span>';
1077
+
1078
+ return $filterControl;
1079
+ }
1080
+
1081
+ /**
1082
+ * A stub for not dependat filters
1083
+ * @param Array parentFiltersData
1084
+ * @return String
1085
+ */
1086
+ protected function getExtraDataAttrs( $parentFiltersData )
1087
+ {
1088
+ return '';
1089
+ }
1090
+
1091
+ /**
1092
+ * Get the cheked attribute string for a multiselect filter control
1093
+ * @return String
1094
+ */
1095
+ protected function getCheckedAttr( $value, $parentFiltersData = null )
1096
+ {
1097
+ if( $this->multiSelect == FM_NONE || $this->filtered && !in_array($value, $this->filteredFields[ $this->fName ]['values']) )
1098
+ return '';
1099
+
1100
+ return 'checked="checked"';
1101
+ }
1102
+
1103
+ /**
1104
+ * Get the filter's buttons parameters such as buttons' labels,
1105
+ * class names and attributes
1106
+ * @param Array dBtnParams (optional)
1107
+ * @return Array
1108
+ */
1109
+ public function getFilterButtonParams( $dBtnParams = null )
1110
+ {
1111
+ return array(
1112
+ 'attrs' => 'id="filter_'.$this->gfName.'_'.$this->id.'"',
1113
+ 'hasMultiselectBtn' => $this->multiSelect == FM_ON_DEMAND,
1114
+ 'hasApplyBtn' => $this->useApllyBtn
1115
+ );
1116
+ }
1117
+
1118
+ /**
1119
+ * Get the filter's state array,
1120
+ * @return Array
1121
+ */
1122
+ public function getFilterState()
1123
+ {
1124
+ return array(
1125
+ "visible" => $this->visible,
1126
+ "filtered" => $this->filtered,
1127
+ "collapsed" => $this->showCollapsed,
1128
+ "truncated" => $this->isTruncated(),
1129
+ "showMoreHidden" => $this->isShowMoreHidden()
1130
+ );
1131
+ }
1132
+
1133
+ /**
1134
+ * Check if the "show more" button must be hidden by class attr
1135
+ * @return Boolean
1136
+ */
1137
+ protected function isShowMoreHidden()
1138
+ {
1139
+ return false;
1140
+ }
1141
+
1142
+ /**
1143
+ * Get the filter's extra controlls parameters
1144
+ * @param Array dBtnParams (dExtraCtrls)
1145
+ * @return Array
1146
+ */
1147
+ public function getFilterExtraControls( $dExtraCtrls = null )
1148
+ {
1149
+ $selectAllAttrs = "";
1150
+ if( !$this->filtered && $this->multiSelect !== FM_NONE)
1151
+ $selectAllAttrs = 'checked="checked"';
1152
+
1153
+ if( $this->multiSelect == FM_ON_DEMAND )
1154
+ $selectAllAttrs.= ' style="display: none;"';
1155
+
1156
+ return array(
1157
+ "showValue" => $this->getShowValue(),
1158
+ "filtered" => $this->filtered,
1159
+ "selectAllAttrs" => $selectAllAttrs,
1160
+ "numberOfExtraItemsToShow" => $this->getNumberOfExtraItemsToShow()
1161
+ );
1162
+ }
1163
+
1164
+ /**
1165
+ * A stub
1166
+ * @return Number
1167
+ */
1168
+ protected function getNumberOfExtraItemsToShow()
1169
+ {
1170
+ return 0;
1171
+ }
1172
+
1173
+ /**
1174
+ * Check if the control should be visible
1175
+ * @return Boolean
1176
+ */
1177
+ public function isVisible()
1178
+ {
1179
+ return $this->visible;
1180
+ }
1181
+
1182
+ /**
1183
+ * Check if the control should be collapsed
1184
+ * @return Boolean
1185
+ */
1186
+ public function isCollapsed()
1187
+ {
1188
+ return $this->showCollapsed;
1189
+ }
1190
+
1191
+ /**
1192
+ * Check if the control is filtered
1193
+ * @return Boolean
1194
+ */
1195
+ public function isFiltered()
1196
+ {
1197
+ return $this->filtered;
1198
+ }
1199
+
1200
+ /**
1201
+ * Get the murkup of the control's delete button
1202
+ * @param String gfName
1203
+ * @param Number id
1204
+ * @param String deleteValue
1205
+ * @return String
1206
+ */
1207
+ protected function getDelButtonHtml($gfName, $id, $deleteValue)
1208
+ {
1209
+ $deleteValue = runner_htmlspecialchars($deleteValue);
1210
+ $html = '<a class="delFilterCtrlButt_'.$gfName.'_'.$id.' delete-button" data-delete="'.$deleteValue.'" data-icon="remove" href="#"></a>';
1211
+ return $html;
1212
+ }
1213
+
1214
+ /**
1215
+ * Decrypt the database row data
1216
+ * @param &Array data
1217
+ */
1218
+ protected function decryptDataRow(&$data)
1219
+ {
1220
+ if( $this->cipherer->isFieldPHPEncrypted($this->fName) )
1221
+ $data[ $this->fName ] = $this->cipherer->DecryptField( $this->fName, $data[ $this->fName ] );
1222
+ }
1223
+
1224
+ /**
1225
+ * Get the lable basing on its type
1226
+ * @param {String} type
1227
+ * @param {String} message
1228
+ * @return {String}
1229
+ */
1230
+ public function getLabel($type, $message)
1231
+ {
1232
+ if( $type === "Text" )
1233
+ return $message;
1234
+
1235
+ return GetCustomLabel($message);
1236
+ }
1237
+
1238
+ /**
1239
+ * The static function creating the Filter control basing on the control's type
1240
+ * @param String fName
1241
+ * @param Object pageObj
1242
+ * @param Number id
1243
+ * @param Object viewControls
1244
+ * @return Object
1245
+ */
1246
+ static function getFilterControl($fName, $pageObj, $id, $viewControls = null )
1247
+ {
1248
+ $filterFields = $pageObj->pSet->getFilterFields();
1249
+ if( array_search( $fName, $filterFields ) === false ) {
1250
+ return null;
1251
+ }
1252
+ $contorlType = $pageObj->pSet->getFilterFieldFormat($fName);
1253
+ switch($contorlType)
1254
+ {
1255
+ case FF_VALUE_LIST:
1256
+ include_once getabspath("classes/controls/FilterValuesList.php");
1257
+ if( $pageObj->pSet->multiSelectLookupEdit($fName) ) {
1258
+ include_once getabspath("classes/controls/FilterMultiselectLookup.php");
1259
+ return new FilterMultiselectLookup($fName, $pageObj, $id, $viewControls);
1260
+ }
1261
+
1262
+ return new FilterValuesList($fName, $pageObj, $id, $viewControls);
1263
+
1264
+ case FF_BOOLEAN:
1265
+ include_once getabspath("classes/controls/Control.php");
1266
+ include_once getabspath("classes/controls/CheckboxField.php");
1267
+ include_once getabspath("classes/controls/FilterBoolean.php");
1268
+ return new FilterBoolean($fName, $pageObj, $id, $viewControls);
1269
+
1270
+ case FF_INTERVAL_LIST:
1271
+ include_once getabspath("classes/controls/FilterIntervalList.php");
1272
+ return new FilterIntervalList($fName, $pageObj, $id, $viewControls);
1273
+
1274
+ case FF_INTERVAL_SLIDER:
1275
+ include_once getabspath("classes/controls/FilterIntervalSlider.php");
1276
+ $fieldType = $pageObj->pSet->getFieldType($fName);
1277
+
1278
+ if( IsDateFieldType($fieldType) )
1279
+ {
1280
+ include_once getabspath("classes/controls/FilterIntervalDateSlider.php");
1281
+ return new FilterIntervalDateSlider($fName, $pageObj, $id, $viewControls);
1282
+ }
1283
+ if( IsTimeType($fieldType) )
1284
+ {
1285
+ include_once getabspath("classes/controls/FilterIntervalDateSlider.php");
1286
+ include_once getabspath("classes/controls/FilterIntervalTimeSlider.php");
1287
+ return new FilterIntervalTimeSlider($fName, $pageObj, $id, $viewControls);
1288
+ }
1289
+ return new FilterIntervalSlider($fName, $pageObj, $id, $viewControls);
1290
+
1291
+ default:
1292
+ include_once getabspath("classes/controls/FilterValuesList.php");
1293
+ return new FilterValuesList($fName, $pageObj, $id, $viewControls);
1294
+ }
1295
+ }
1296
+
1297
+ public function hasDependentFilter() {
1298
+ return false;
1299
+ }
1300
+
1301
+ protected function dataTotalsName() {
1302
+ $totalOption = $this->pSet->getFilterFieldTotal( $this->fName );
1303
+ if( $totalOption == FT_COUNT ) {
1304
+ return 'count';
1305
+ } else if( $totalOption == FT_MIN ) {
1306
+ return 'min';
1307
+ } else if( $totalOption == FT_MAX ) {
1308
+ return 'max';
1309
+ }
1310
+ return '';
1311
+ }
1312
+
1313
+ /**
1314
+ * Returns string to be displayed in the horizontal control
1315
+ */
1316
+ protected function getShowValue() {
1317
+ if( !$this->filtered ) {
1318
+ return "";
1319
+ }
1320
+ $values =& $this->filteredFields[ $this->fName ]["values"];
1321
+ if( !$values ) {
1322
+ return "";
1323
+ }
1324
+ if( count( $values ) > 1 ) {
1325
+ return "(" . count( $values ) . ")";
1326
+ }
1327
+ return $this->getControlCaption( $values[0] );
1328
+ }
1329
+ }
1330
+
1331
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
1332
  ?>
php/classes/controls/FilterIntervalDateSlider.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class FilterIntervalDateSlider extends FilterIntervalSlider
3
  {
@@ -770,4 +771,778 @@ class FilterIntervalDateSlider extends FilterIntervalSlider
770
  $pageObj->controlsMap["filters"]["controls"][] = $ctrlsMap;
771
  }
772
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
773
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class FilterIntervalDateSlider extends FilterIntervalSlider
4
  {
 
771
  $pageObj->controlsMap["filters"]["controls"][] = $ctrlsMap;
772
  }
773
  }
774
+ =======
775
+ <?php
776
+ class FilterIntervalDateSlider extends FilterIntervalSlider
777
+ {
778
+ /**
779
+ * The slider's step type
780
+ */
781
+ protected $stepType;
782
+
783
+ /**
784
+ * The max knob ds date/ date-time formatted value
785
+ * @type String
786
+ */
787
+ protected $maxKnobFormatValue;
788
+
789
+ /**
790
+ * The min knob ds date/ date-time formatted value
791
+ * @type String
792
+ */
793
+ protected $minKnobFormatValue;
794
+
795
+ /**
796
+ * The array representation of the min slider's value
797
+ * or step-rounded slider's value for the sliders with
798
+ * 'minutes' or 'seconds' type
799
+ * @type Array
800
+ */
801
+ protected $minDateArray;
802
+
803
+ /**
804
+ * The array representation of the max slider's value
805
+ * @type Array
806
+ */
807
+ protected $maxDateArray;
808
+
809
+ /**
810
+ * The prop containing (for the 'months' type sliders
811
+ * only) the step-rounded min date's month number
812
+ * @type Number
813
+ */
814
+ protected $adjMinDateMonth;
815
+
816
+ /**
817
+ * The prop containing (for the 'months' type sliders
818
+ * only) the step-rounded max date's month number
819
+ * @type Number
820
+ */
821
+ protected $adjMaxDateMonth;
822
+
823
+ /**
824
+ * The array of month names
825
+ * @type Array
826
+ */
827
+ protected $months = array();
828
+
829
+
830
+ public function __construct($fName, $pageObject, $id, $viewControls)
831
+ {
832
+ parent::__construct($fName, $pageObject, $id, $viewControls);
833
+
834
+ $this->stepType = $this->pSet->getFilterStepType($fName);
835
+
836
+ if($this->stepType == FSST_MONTHS)
837
+ {
838
+ $this->months = array(
839
+ "January",
840
+ "February",
841
+ "March",
842
+ "April",
843
+ "May",
844
+ "June",
845
+ "July",
846
+ "August",
847
+ "September",
848
+ "October",
849
+ "November",
850
+ "December" );
851
+ }
852
+ }
853
+
854
+ /**
855
+ * Assign the control's knobs properties
856
+ */
857
+ protected function assignKnobsValues()
858
+ {
859
+ $filterData = $this->filteredFields[ $this->fName ];
860
+
861
+ $filterValues = array();
862
+ $filterValues[] = $filterData['values'][0];
863
+ $filterValues[] = $filterData['sValues'][0];
864
+
865
+ $value1 = prepare_for_db( $this->fName, $filterValues[0], "" );
866
+
867
+ if( $this->knobsType == FS_MIN_ONLY ) {
868
+ $this->minKnobValue = $value1;
869
+ $this->minKnobFormatValue = $filterValues[0];
870
+ return;
871
+ }
872
+
873
+ if( $this->knobsType == FS_MAX_ONLY ) {
874
+ $this->maxKnobValue = $value1;
875
+ $this->maxKnobFormatValue = $filterValues[0];
876
+ return;
877
+ }
878
+
879
+ $this->minKnobValue = $value1;
880
+ $this->maxKnobValue = prepare_for_db( $this->fName, $filterValues[1], "" );
881
+
882
+ $this->minKnobFormatValue = $filterValues[0];
883
+ $this->maxKnobFormatValue = $filterValues[1];
884
+ }
885
+
886
+ /**
887
+ * Get the array representation of the db-formatted date string:
888
+ * array(year, month, day, hour, minute, second)
889
+ * @param String value
890
+ * @return Array
891
+ */
892
+ protected function getDateTimeArray($value, $forCaption = false)
893
+ {
894
+ return db2time($value);
895
+ }
896
+
897
+ /**
898
+ * Get the html markup for the slider knobs' captions
899
+ * @return String
900
+ */
901
+ protected function getCaptionSpansHTML()
902
+ {
903
+ $inlineStyelPrefix = $inlineStyelPostfix = ' style="display: none;"';
904
+ $inlineStyelMin = $inlineStyelMax = '';
905
+
906
+ if( $this->stepType != FSST_YEARS || $this->stepType != FSST_DAYS )
907
+ {
908
+ $minValueArr = $this->minDateArray;
909
+ if( $this->getValueInSeconds($this->minKnobValue) >= $this->getValueInSeconds($this->minValue) )
910
+ $minValueArr = $this->getDateTimeArray($this->minKnobValue);
911
+
912
+ $maxValueArr = $this->maxDateArray;
913
+ if($this->getValueInSeconds($this->maxKnobValue) <= $this->getValueInSeconds($this->maxValue))
914
+ $maxValueArr = $this->getDateTimeArray($this->maxKnobValue);
915
+
916
+ if( $this->stepType == FSST_MONTHS )
917
+ {
918
+ $month = $minValueArr[1];
919
+ if( !$this->filtered || $this->isMonthNumberToAdjust(true, $minValueArr[0], $minValueArr[1]) )
920
+ $month = $this->getAdjustedMonthNumber($minValueArr[1], true);
921
+
922
+ $prefix = $this->getMonthName($month);
923
+
924
+ if( $minValueArr[0] == $maxValueArr[0] )
925
+ {
926
+ $inlineStyelMin = ' style="display: none;"';
927
+ $inlineStyelPrefix = '';
928
+ }
929
+ }
930
+ else if( $this->stepType == FSST_HOURS || $this->stepType == FSST_MINUTES || $this->stepType == FSST_SECONDS )
931
+ {
932
+ global $locale_info;
933
+ $timeFormatString = $locale_info["LOCALE_STIMEFORMAT"];
934
+ if($this->stepType != FSST_SECONDS)
935
+ $timeFormatString = str_replace( $locale_info["LOCALE_STIME"]."ss", "", $timeFormatString );
936
+
937
+ $postfix = format_datetime_custom($maxValueArr, $timeFormatString);
938
+ if( $minValueArr[0] == $maxValueArr[0] && $minValueArr[1] == $maxValueArr[1] && $minValueArr[2] == $maxValueArr[2] )
939
+ {
940
+ $inlineStyelMax = ' style="display: none;"';
941
+ $inlineStyelPostfix = '';
942
+ }
943
+ }
944
+ }
945
+
946
+ $minSpan = '<span class="slider-min"'.$inlineStyelMin.'>'.$this->getMinSpanValue().'</span>';
947
+ $maxSpan = '<span class="slider-max"'.$inlineStyelMax.'>'.$this->getMaxSpanValue().'</span>';
948
+ $captionSpans = $minSpan."&nbsp;-&nbsp".$maxSpan;
949
+
950
+ $prefixSpan = '<span class="slider-caption-prefix"'.$inlineStyelPrefix.'>'.$prefix.'</span>';
951
+ $postfixSpan = '<span class="slider-caption-postfix"'.$inlineStyelPostfix.'>'.$postfix.'</span>';
952
+
953
+ $captionSpans = $prefixSpan . $captionSpans . $postfixSpan;
954
+
955
+ return $captionSpans;
956
+ }
957
+
958
+ /**
959
+ * Get the value converted into seconds
960
+ * @param String value
961
+ * @return Number
962
+ */
963
+ protected function getValueInSeconds($value)
964
+ {
965
+ return strtotime($value);
966
+ }
967
+
968
+ /**
969
+ * Get the caption fot the min slider's knob
970
+ * @return String
971
+ */
972
+ protected function getMinSpanValue()
973
+ {
974
+ $minSpanValue = $this->minKnobValue;
975
+ //process the case when other where conditions make
976
+ //the real minKnobValue going out of the slider's bounds
977
+ if( $this->getValueInSeconds($minSpanValue) < $this->getValueInSeconds($this->minValue) )
978
+ $minSpanValue = $this->minValue;
979
+
980
+ $minSpanValue = $this->getRoundedDateCaption($minSpanValue, true);
981
+
982
+ return $minSpanValue;
983
+ }
984
+
985
+ /**
986
+ * Get the caption fot the max slider's knob
987
+ * @return String
988
+ */
989
+ protected function getMaxSpanValue()
990
+ {
991
+ $maxSpanValue = $this->maxKnobValue;
992
+ //process the case when other where conditions make
993
+ //the real maxKnobValue going out of the slider's bounds
994
+ if($this->getValueInSeconds($maxSpanValue) > $this->getValueInSeconds($this->maxValue))
995
+ $maxSpanValue = $this->maxValue;
996
+
997
+ $maxSpanValue = $this->getRoundedDateCaption($maxSpanValue, false);
998
+
999
+ return $maxSpanValue;
1000
+ }
1001
+
1002
+ /**
1003
+ * Get the caption for the rounded date corresponding to
1004
+ * the db-formatted date string passed
1005
+ * @param String value
1006
+ * @param Boolean isLower
1007
+ * @return String
1008
+ */
1009
+ protected function getRoundedDateCaption($value, $isLower = false)
1010
+ {
1011
+ //array(year,month,day,hour,minute,second)
1012
+ $dateArray = $this->getDateTimeArray($value, true);
1013
+ switch($this->stepType)
1014
+ {
1015
+ case FSST_SECONDS:
1016
+ return $this->getSecondsCaption($dateArray);
1017
+ case FSST_MINUTES:
1018
+ return $this->getMinutesCaption($dateArray);
1019
+ case FSST_HOURS:
1020
+ return $this->getHoursCaption($dateArray, $isLower);
1021
+ case FSST_DAYS:
1022
+ return format_normalized_shortdate($dateArray);
1023
+ case FSST_MONTHS:
1024
+ return $this->getMonthCaption($dateArray, $isLower);
1025
+ case FSST_YEARS:
1026
+ return $dateArray[0];
1027
+ default:
1028
+ return $value;
1029
+ }
1030
+ }
1031
+
1032
+ /**
1033
+ * Get the full caption value for the slider with the 'seconds' step type
1034
+ * @param Array dateArray
1035
+ * @return String
1036
+ */
1037
+ protected function getSecondsCaption($dateArray)
1038
+ {
1039
+ return str_format_datetime($dateArray);
1040
+ }
1041
+
1042
+ /**
1043
+ * Get the full caption value for the slider with the 'minutes' step type
1044
+ * @param Array dateArray
1045
+ * @return String
1046
+ */
1047
+ protected function getMinutesCaption($dateArray)
1048
+ {
1049
+ global $locale_info;
1050
+ $dateArray[5] = 0;
1051
+
1052
+ $timeFormatString = str_replace( $locale_info["LOCALE_STIME"]."ss", "", $locale_info["LOCALE_STIMEFORMAT"]);
1053
+ return format_datetime_custom($dateArray, normalized_date_format()." ".$timeFormatString);
1054
+ }
1055
+
1056
+ /**
1057
+ * Get the full caption value for the slider with the 'hours' step type
1058
+ * @param Array dateArray
1059
+ * @param Boolean isLower
1060
+ * @return String
1061
+ */
1062
+ protected function getHoursCaption($dateArray, $isLower)
1063
+ {
1064
+ global $locale_info;
1065
+
1066
+ $hours = $this->getAdjustedHoursValue($dateArray[3], $dateArray[4], $isLower);
1067
+ $dateArray[3] = $dateArray[4] = $dateArray[5] = 0;
1068
+ $dateArray = addHours($dateArray, $hours);
1069
+
1070
+ $timeFormatString = str_replace( $locale_info["LOCALE_STIME"]."ss", "", $locale_info["LOCALE_STIMEFORMAT"]);
1071
+
1072
+ return format_datetime_custom($dateArray, normalized_date_format()." ".$timeFormatString);
1073
+ }
1074
+
1075
+ /**
1076
+ * Get the srep-rounded hours value
1077
+ * @param Number hours
1078
+ * @param Number minutes
1079
+ * @param Boolean isLower
1080
+ * @return Number
1081
+ */
1082
+ protected function getAdjustedHoursValue($hours, $minutes, $isLower)
1083
+ {
1084
+ $step = $this->stepValue * 60;
1085
+ $minutes = $hours * 60 + $minutes;
1086
+
1087
+ if($isLower)
1088
+ return floor( $minutes / $step ) * $this->stepValue;
1089
+
1090
+ return ceil( $minutes / $step ) * $this->stepValue;
1091
+ }
1092
+
1093
+ /**
1094
+ * Get the full caption value for the slider with the 'months' step type
1095
+ * @param Array dateArray
1096
+ * @param Boolean isLower
1097
+ * @return String
1098
+ */
1099
+ protected function getMonthCaption($dateArray, $isLower)
1100
+ {
1101
+ $year = $dateArray[0];
1102
+ $month = $dateArray[1];
1103
+
1104
+ if( !$this->filtered || $this->isMonthNumberToAdjust($isLower, $year, $month) )
1105
+ $month = $this->getAdjustedMonthNumber($month, $isLower);
1106
+
1107
+ return $this->getMonthName($month)." ".$year;
1108
+ }
1109
+
1110
+ /**
1111
+ * Check if it's necessary to adjust the month value
1112
+ * It returns true for the limit knobs year, month values
1113
+ * @param Boolean isLower
1114
+ * @param Number year
1115
+ * @param Number month
1116
+ * @return Boolean
1117
+ */
1118
+ protected function isMonthNumberToAdjust( $isLower, $year, $month )
1119
+ {
1120
+ switch( $this->knobsType )
1121
+ {
1122
+ case FS_MIN_ONLY:
1123
+ return !$isLower;
1124
+
1125
+ case FS_MAX_ONLY:
1126
+ return $isLower;
1127
+
1128
+ case FS_BOTH:
1129
+ if( $isLower && $year == $this->minDateArray[0] && abs($month - $this->adjMinDateMonth) < $this->stepValue
1130
+ || !$isLower && $year == $this->maxDateArray[0] && abs($month - $this->adjMaxDateMonth) < $this->stepValue )
1131
+ {
1132
+ return true;
1133
+ }
1134
+ return false;
1135
+
1136
+ default:
1137
+ return false;
1138
+ }
1139
+ }
1140
+
1141
+ /**
1142
+ * Get the month's name by its number
1143
+ * @param Number month
1144
+ * @return String
1145
+ */
1146
+ protected function getMonthName($month)
1147
+ {
1148
+ return $this->months[ $month - 1 ];
1149
+ }
1150
+
1151
+ /**
1152
+ * Get the srep-rounded month value
1153
+ * @param Number month
1154
+ * @param Boolean isLower
1155
+ * @return Number
1156
+ */
1157
+ protected function getAdjustedMonthNumber($month, $isLower)
1158
+ {
1159
+ $step = $this->stepValue;
1160
+ if($step != 1)
1161
+ {
1162
+ if($isLower)
1163
+ $month = floor( ( $month - 1 ) / $step ) * $step + 1;
1164
+ else
1165
+ $month = ceil( $month / $step ) * $step ;
1166
+ }
1167
+ return $month;
1168
+ }
1169
+
1170
+ /**
1171
+ * Get date-time formatted string
1172
+ * @param Array dateArray
1173
+ * @return String
1174
+ */
1175
+ protected function getDateTimeString($dateArray)
1176
+ {
1177
+ global $locale_info;
1178
+ //to avoid locale-specific formatting
1179
+ //$formatString = $locale_info["LOCALE_SSHORTDATE"]." HH:mm:ss";
1180
+ $formatString = "yyyy-MM-dd HH:mm:ss";
1181
+ return format_datetime_custom($dateArray, $formatString);
1182
+ }
1183
+
1184
+ /**
1185
+ * Get the step-rounded date/date-time formatted string
1186
+ * @param String value
1187
+ * @param Boolean isLower
1188
+ * @return String
1189
+ */
1190
+ protected function getRoundedDate($value, $isLower, $isKnob = false)
1191
+ {
1192
+ //array(year,month,day,hour,minute,second)
1193
+ $dateArray = $this->getDateTimeArray($value);
1194
+
1195
+ switch($this->stepType)
1196
+ {
1197
+ case FSST_SECONDS:
1198
+ if($isKnob)
1199
+ return $this->getDateTimeString($dateArray);
1200
+
1201
+ $prepDateArray = $this->minDateArray;
1202
+
1203
+ $diffSec = $this->getDifferenceInSecWithMin($value, $isLower);
1204
+ $prepDateArray = addSeconds($prepDateArray, $diffSec);
1205
+
1206
+ return $this->getDateTimeString($prepDateArray);
1207
+
1208
+ case FSST_MINUTES:
1209
+ if($isKnob)
1210
+ return $this->getDateTimeString($dateArray);
1211
+
1212
+ $prepDateArray = $this->minDateArray;
1213
+
1214
+ $diffSec = $this->getDifferenceInSecWithMin($value, $isLower);
1215
+ $minutes = floor( $diffSec / 60);
1216
+ $prepDateArray = addMinutes($prepDateArray, $minutes);
1217
+
1218
+ return $this->getDateTimeString($prepDateArray);
1219
+
1220
+ case FSST_HOURS:
1221
+ $hours = $this->getAdjustedHoursValue( $dateArray[3], $dateArray[4], $isLower );
1222
+ $dateArray[3] = $dateArray[4] = $dateArray[5] = 0;
1223
+ $dateArray = addHours($dateArray, $hours);
1224
+
1225
+ return $this->getDateTimeString($dateArray);
1226
+
1227
+ case FSST_DAYS:
1228
+ return format_datetime_custom($dateArray, "yyyy-MM-dd");
1229
+
1230
+ case FSST_MONTHS:
1231
+ if($isKnob)
1232
+ return format_datetime_custom($dateArray, "yyyy-MM-dd");
1233
+
1234
+ $dateArray[1] = $this->getAdjustedMonthNumber( $dateArray[1], $isLower );
1235
+ $dateArray[2] = $isLower? 1 : getLastMonthDayNumber( $dateArray[0], $dateArray[1] );
1236
+ $dateArray[3] = $dateArray[4] = $dateArray[5] = 0;
1237
+
1238
+ return format_datetime_custom($dateArray, "yyyy-MM-dd");
1239
+
1240
+ case FSST_YEARS:
1241
+ $dateArray[3] = $dateArray[4] = $dateArray[5] = 0;
1242
+ $dateArray[1] = $isLower ? 1 : 12;
1243
+ $dateArray[2] = $isLower ? 1 : 31;
1244
+
1245
+ return format_datetime_custom($dateArray, "yyyy-MM-dd");
1246
+
1247
+ default:
1248
+ return $value;
1249
+ }
1250
+ }
1251
+
1252
+ /**
1253
+ * Get the seconds between the step-rounded value and the min slider's value
1254
+ * @param String value Db time-formatted string
1255
+ * @param Boolean isLower
1256
+ * @return Number
1257
+ */
1258
+ protected function getDifferenceInSecWithMin($value, $isLower)
1259
+ {
1260
+ $step = $this->getStepValue();
1261
+ $minSec = $this->getValueInSeconds($this->minValue);
1262
+ $valueSec = $this->getValueInSeconds($value);
1263
+
1264
+ $min = floor( $minSec / $step ) * $step;
1265
+ if($isLower)
1266
+ $rvalue = floor( $valueSec / $step) * $step;
1267
+ else
1268
+ $rvalue = ceil( $valueSec / $step ) * $step;
1269
+
1270
+ return $rvalue - $min;
1271
+ }
1272
+
1273
+ /**
1274
+ * Get the slider step value
1275
+ * basing on the step type
1276
+ * @return Number
1277
+ */
1278
+ protected function getStepValue()
1279
+ {
1280
+ switch($this->stepType)
1281
+ {
1282
+ case FSST_MINUTES:
1283
+ return 60 * $this->stepValue;
1284
+
1285
+ case FSST_HOURS:
1286
+ return 3600 * $this->stepValue;
1287
+
1288
+ case FSST_DAYS:
1289
+ return 86400 * $this->stepValue;
1290
+
1291
+ default:
1292
+ return $this->stepValue;
1293
+ }
1294
+ }
1295
+
1296
+ /**
1297
+ * Check if there are database values for the filter's field
1298
+ * that are differs from each other for more than a step value
1299
+ * @param Array data
1300
+ * @return Boolean
1301
+ */
1302
+ protected function fieldHasNoRange($data)
1303
+ {
1304
+ if (is_null( $data['sliderMin'] ) && is_null( $data['sliderMax'] ) || $data['sliderMax'] == $data['sliderMin'])
1305
+ return true;
1306
+
1307
+ $step = $this->getStepValue();
1308
+ if($this->stepType == FSST_MONTHS || $this->stepType == FSST_YEARS)
1309
+ {
1310
+ $dateArrayMin = db2time( $data['sliderMin'] );
1311
+ $dateArrayMax = db2time( $data['sliderMax'] );
1312
+
1313
+ if($this->stepType == FSST_MONTHS && $dateArrayMax[0] == $dateArrayMin[0] && ($dateArrayMax[1] - $dateArrayMin[1]) < $step )
1314
+ return true;
1315
+
1316
+ if($this->stepType == FSST_YEARS && ($dateArrayMax[0] - $dateArrayMin[0]) < $step)
1317
+ return true;
1318
+ }
1319
+ else
1320
+ {
1321
+ if( (strtotime( $data['sliderMax'] ) - strtotime( $data['sliderMin'] )) < $step )
1322
+ return true;
1323
+ }
1324
+ return false;
1325
+ }
1326
+
1327
+ /**
1328
+ * Get the html markup representing the control on the page
1329
+ * @param Array data
1330
+ * @param Array parentFiltersData (optional)
1331
+ * @return String
1332
+ */
1333
+ protected function buildControl( $data, $parentFiltersData = array() )
1334
+ {
1335
+ $this->minValue = $data['sliderMin'];
1336
+ $this->maxValue = $data['sliderMax'];
1337
+
1338
+ $timeZone = date_default_timezone_get();
1339
+ date_default_timezone_set('UTC');
1340
+
1341
+ $this->minDateArray = $this->getDateTimeArray($this->minValue);
1342
+ $this->maxDateArray = $this->getDateTimeArray($this->maxValue);
1343
+ if($this->stepType == FSST_MINUTES)
1344
+ $this->minDateArray = $this->getMinuteAdjustedMinValue();
1345
+ else if($this->stepType == FSST_SECONDS)
1346
+ $this->minDateArray = $this->getSecAdjustedMinValue();
1347
+
1348
+ if($this->stepType == FSST_MONTHS)
1349
+ {
1350
+ $this->adjMinDateMonth = $this->getAdjustedMonthNumber($this->minDateArray[1], true);
1351
+ $this->adjMaxDateMonth = $this->getAdjustedMonthNumber($this->maxDateArray[1], false);
1352
+ }
1353
+
1354
+ //assign the knobs values
1355
+ if( !$this->filtered )
1356
+ {
1357
+ $this->minKnobValue = $data['sliderMin'];
1358
+ $this->maxKnobValue = $data['sliderMax'];
1359
+ }
1360
+ else
1361
+ {
1362
+ if($this->knobsType == FS_MAX_ONLY)
1363
+ $this->minKnobValue = $data['sliderMin'];
1364
+
1365
+ if($this->knobsType == FS_MIN_ONLY)
1366
+ $this->maxKnobValue = $data['sliderMax'];
1367
+ }
1368
+
1369
+ date_default_timezone_set($timeZone);
1370
+ return $this->getSliderHTML();
1371
+ }
1372
+
1373
+ /**
1374
+ * Get the step-rounded min slider value's array representation
1375
+ * for the sliders with 'seconds' step type
1376
+ * @return Array
1377
+ */
1378
+ function getSecAdjustedMinValue()
1379
+ {
1380
+ $prepDateArray = $this->minDateArray;
1381
+ $prepDateArray[5] = 0;
1382
+
1383
+ $step = $this->getStepValue();
1384
+ $minRoundSec = floor( strtotime($this->minValue) / $step ) * $step ;
1385
+ $minUpToSec = floor( strtotime($this->minValue) / 60 ) * 60;
1386
+ $diffSec = $minRoundSec - $minUpToSec;
1387
+
1388
+ $prepDateArray = addSeconds($prepDateArray, $diffSec);
1389
+ return $prepDateArray;
1390
+ }
1391
+
1392
+ /**
1393
+ * Get the step-rounded min slider value's array representation
1394
+ * for the sliders with 'minutes' step type
1395
+ * @return Array
1396
+ */
1397
+ function getMinuteAdjustedMinValue()
1398
+ {
1399
+ $prepDateArray = $this->minDateArray;
1400
+ $prepDateArray[4] = $prepDateArray[5] = 0;
1401
+
1402
+ $step = $this->getStepValue();
1403
+ $minRoundSec = floor( strtotime($this->minValue) / $step ) * $step ;
1404
+ $minUpToHour = floor( strtotime($this->minValue) / 3600 ) * 3600;
1405
+ $diffSec = $minRoundSec - $minUpToHour;
1406
+
1407
+ $minutes = floor( $diffSec / 60);
1408
+ $prepDateArray = addMinutes($prepDateArray, $minutes);
1409
+
1410
+ return $prepDateArray;
1411
+ }
1412
+
1413
+ /**
1414
+ * Get the numeric equevalent for the date equivalent to the db date-formatted string
1415
+ * @param String value Db date-formatted string
1416
+ * @param Boolean isLower
1417
+ * @return Number
1418
+ */
1419
+ protected function round($value, $isLower, $isKnob = false)
1420
+ {
1421
+ switch($this->stepType)
1422
+ {
1423
+ case FSST_SECONDS:
1424
+ case FSST_MINUTES:
1425
+ case FSST_HOURS:
1426
+ return $this->getDifferenceInSecWithMin($value, $isLower);
1427
+
1428
+ case FSST_DAYS:
1429
+ return strtotime($value) - strtotime($this->minValue);
1430
+
1431
+ case FSST_MONTHS:
1432
+ $dateArray = db2time($value);
1433
+ $year = $dateArray[0];
1434
+ $month = $dateArray[1];
1435
+ if(!$isKnob || !$this->filtered)
1436
+ $month = $this->getAdjustedMonthNumber($dateArray[1], $isLower);
1437
+
1438
+ $minYear = $this->minDateArray[0];
1439
+
1440
+ $monthsNumber = ($year - $minYear) * 12 + $month - $this->adjMinDateMonth;
1441
+ if(!$isLower)
1442
+ $monthsNumber = $monthsNumber + 1;
1443
+
1444
+ return $monthsNumber;
1445
+
1446
+ case FSST_YEARS:
1447
+ $step = $this->getStepValue();
1448
+ $dateArray = db2time($value);
1449
+ $year = $dateArray[0];
1450
+
1451
+ $minYear = $this->minDateArray[0];
1452
+
1453
+ if($isLower)
1454
+ return floor( ( $year - $minYear ) / $step ) * $step ;
1455
+
1456
+ return ceil( ( $year - $minYear ) / $step ) * $step ;
1457
+
1458
+ default:
1459
+ return $value;
1460
+ }
1461
+ }
1462
+
1463
+ /**
1464
+ * Get the real slider's date value adjusted accordit to the step type
1465
+ * @param String value
1466
+ * @return String
1467
+ */
1468
+ protected function getAdjustedRealDate($value)
1469
+ {
1470
+ $dateArray = $this->getDateTimeArray($value);
1471
+ if($this->stepType == FSST_MINUTES)
1472
+ $dateArray[5] = 0;
1473
+ return $this->getDateTimeString($dateArray);
1474
+ }
1475
+
1476
+ /**
1477
+ * Get date filter control's base ControlsMap array
1478
+ * @return array
1479
+ */
1480
+ protected function getBaseContolsMapParams()
1481
+ {
1482
+ $ctrlsMap = parent::getBaseContolsMapParams();
1483
+ $timeZone = date_default_timezone_get();
1484
+ date_default_timezone_set('UTC');
1485
+
1486
+ $ctrlsMap['stepType'] = $this->stepType;
1487
+
1488
+ if( $this->stepType == FSST_SECONDS || $this->stepType == FSST_MINUTES ) {
1489
+ $ctrlsMap['realMinValue'] = $this->getAdjustedRealDate( $this->minValue );
1490
+ $ctrlsMap['realMaxValue'] = $this->getAdjustedRealDate( $this->maxValue );
1491
+ }
1492
+
1493
+ //the min, max formated dates
1494
+ $ctrlsMap['minValue'] = $this->getRoundedDate( $this->minValue, true );
1495
+ $ctrlsMap['maxValue'] = $this->getRoundedDate( $this->maxValue, false );
1496
+
1497
+ //the min, max slider values (numbers)
1498
+ $ctrlsMap['roundedMin'] = 0;
1499
+ $ctrlsMap['roundedMax'] = $this->round( $this->maxValue, false );
1500
+
1501
+ $ctrlsMap['roundedMinKnobValue'] = $this->round( $this->minKnobValue, true, true );
1502
+ $ctrlsMap['roundedMaxKnobValue'] = $this->round( $this->maxKnobValue, false, true );
1503
+
1504
+ if( $this->filtered ) {
1505
+ //$ctrlsMap['defaultValuesArray'] = array( $this->minKnobFormatValue, $this->maxKnobFormatValue );
1506
+ $ctrlsMap['minKnobValue'] = $ctrlsMap['minValue'];
1507
+ $ctrlsMap['maxKnobValue'] = $ctrlsMap['maxValue'];
1508
+
1509
+ if( $this->knobsType != FS_MAX_ONLY )
1510
+ $ctrlsMap['minKnobValue'] = $this->getRoundedDate( $this->minKnobFormatValue, true, true );
1511
+
1512
+ if( $this->knobsType != FS_MIN_ONLY )
1513
+ $ctrlsMap['maxKnobValue'] = $this->getRoundedDate( $this->maxKnobFormatValue, false, true );
1514
+ }
1515
+ date_default_timezone_set( $timeZone );
1516
+
1517
+ if( $this->stepType == FSST_SECONDS )
1518
+ $ctrlsMap['showSeconds'] = true;
1519
+
1520
+ if( $this->stepType == FSST_SECONDS || $this->stepType == FSST_MINUTES || $this->stepType == FSST_HOURS ) {
1521
+ global $locale_info;
1522
+ $ctrlsMap['showTime'] = true;
1523
+ $ctrlsMap['timeDelimiter'] = $locale_info["LOCALE_STIME"];
1524
+ $ctrlsMap['timeFormat'] = $locale_info["LOCALE_STIMEFORMAT"];
1525
+ $ctrlsMap['is24hoursFormat'] = $locale_info["LOCALE_ITIME"] == "1";
1526
+ $ctrlsMap['leadingZero'] = $locale_info["LOCALE_ITLZERO"] == "1";
1527
+
1528
+ if( $locale_info["LOCALE_ITIME"] == "0" )
1529
+ $ctrlsMap['designators'] = array( "am" => $locale_info["LOCALE_S1159"], "pm" => $locale_info["LOCALE_S2359"] );
1530
+ }
1531
+
1532
+ return $ctrlsMap;
1533
+ }
1534
+
1535
+ /**
1536
+ * Add filter control's data to the ControlsMap
1537
+ * @param Object pageObj
1538
+ */
1539
+ public function addFilterControlToControlsMap($pageObj)
1540
+ {
1541
+ $ctrlsMap = $this->getBaseContolsMapParams();
1542
+ $ctrlsMap['isFieldDateType'] = true;
1543
+
1544
+ $pageObj->controlsMap["filters"]["controls"][] = $ctrlsMap;
1545
+ }
1546
+ }
1547
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
1548
  ?>
php/classes/controls/FilterIntervalList.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
 
3
  class FilterIntervalList extends FilterControl
@@ -256,4 +257,264 @@ class FilterIntervalList extends FilterControl
256
  return FilterIntervalList::getOrdinaryIntervalCondition( $fName, $intervalData, $pSet );
257
  }
258
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
 
4
  class FilterIntervalList extends FilterControl
 
257
  return FilterIntervalList::getOrdinaryIntervalCondition( $fName, $intervalData, $pSet );
258
  }
259
  }
260
+ =======
261
+ <?php
262
+
263
+ class FilterIntervalList extends FilterControl
264
+ {
265
+ public function __construct( $fName, $pageObject, $id, $viewControls )
266
+ {
267
+ parent::__construct( $fName, $pageObject, $id, $viewControls );
268
+
269
+ $this->separator = "~interval~";
270
+ $this->filterFormat = FF_INTERVAL_LIST;
271
+
272
+ if( $this->totals == FT_NONE || $this->totals == FT_COUNT )
273
+ $this->totalsfName = $this->fName;
274
+
275
+ $this->useApllyBtn = $this->multiSelect == FM_ALWAYS;
276
+ }
277
+
278
+ /**
279
+ * Form complex totals by aggregating SQL CASE statements, eg:
280
+ SELECT MIN( ( CASE WHEN %field is > 0% and %field is <= 10% ) THEN %total_field% ELSE NULL END ) ) AS %field%1_min,
281
+ COUNT( ( CASE WHEN %field is > 0% and %field is <= 10% THEN 1 ELSE NULL END ) ) AS %field%1_count,
282
+ MIN( ( CASE WHEN %field is > 10% and %field is <= 20% THEN %total_field% ELSE NULL END ) ) AS %field%2_min,
283
+ COUNT( ( CASE WHEN %field is > 10% and %field is <= 20% THEN 1 ELSE NULL END ) ) AS %field%2_count,
284
+ ...
285
+ FROM ( ... )
286
+ */
287
+ protected function getDataCommand() {
288
+ $dc = new DsCommand;
289
+ $dc->filter = $this->pageObject->getDataSourceFilterCriteria( $this->fName );
290
+
291
+ $intervalsRowData = $this->pSet->getFilterIntervals($this->fName);
292
+ foreach( $intervalsRowData as $intervalData ) {
293
+ $idx = $intervalData["index"];
294
+
295
+ $total = $this->dataTotalsName();
296
+ if( !$total )
297
+ $total = "count";
298
+
299
+ if( $total == "count" ) {
300
+ $caseExpr = DataCondition::CaseConstOrNull(
301
+ FilterIntervalList::getFilterCondition( $this->fName, $idx, $this->pSet ),
302
+ 1
303
+ );
304
+ } else {
305
+ $caseExpr = DataCondition::CaseFieldOrNull(
306
+ FilterIntervalList::getFilterCondition( $this->fName, $idx, $this->pSet ),
307
+ $this->totalsfName
308
+ );
309
+ }
310
+
311
+ $dc->totals[] = array(
312
+ "total" => $total,
313
+ "alias" => $this->fName.$idx."_".$total,
314
+ "caseStatement" => $caseExpr
315
+ );
316
+
317
+ if( $total != "count" ) {
318
+ $dc->totals[] = array(
319
+ "total" => "count",
320
+ "alias" => $this->fName.$idx."_count",
321
+ "caseStatement" => DataCondition::CaseConstOrNull(
322
+ FilterIntervalList::getFilterCondition( $this->fName, $idx, $this->pSet ),
323
+ 1
324
+ )
325
+ );
326
+ }
327
+ }
328
+
329
+ return $dc;
330
+ }
331
+
332
+
333
+ /**
334
+ * Get label
335
+ * @param String index
336
+ * @return String
337
+ */
338
+ protected function getValueToShow( $value ) {
339
+ return $this->getIntervalLabel( $value );
340
+ }
341
+
342
+ protected function getIntervalLabel( $index ) {
343
+ $iData = $this->pSet->getFilterIntervalDatabyIndex( $this->fName, $index );
344
+ return $this->getLabel( $iData["intervalLabelNameType"], $iData["intervalLabelText"] );
345
+ }
346
+
347
+ /**
348
+ * Get the filter blocks data using the database query
349
+ * and add it the the existing blocks
350
+ * @param &Array
351
+ */
352
+ protected function addFilterBlocksFromDB( &$filterCtrlBlocks )
353
+ {
354
+ $visibilityClass = $this->filtered && $this->multiSelect == FM_ON_DEMAND ? $this->onDemandHiddenItemClassName : "";
355
+
356
+ //query to database
357
+ $qResult = $this->dataSource->getTotals( $this->getDataCommand() );
358
+ $data = $qResult->fetchAssoc();
359
+
360
+ $this->decryptDataRow( $data );
361
+
362
+ $intervalsRowData = $this->pSet->getFilterIntervals( $this->fName );
363
+ foreach( $intervalsRowData as $iData ) {
364
+ if( !$this->pSet->showWithNoRecords( $this->fName ) && $data[ $this->fName.$iData["index"]."_count" ] == 0 )
365
+ continue;
366
+
367
+ $this->valuesObtainedFromDB[] = $iData["index"];
368
+
369
+ $ctrlData = array();
370
+ $ctrlData["index"] = $iData["index"];
371
+
372
+ if( $this->dataTotalsName() )
373
+ $ctrlData["total"] = $data[ $this->fName.$iData["index"]."_".$this->dataTotalsName() ];
374
+
375
+ $filterControl = $this->buildControl( $ctrlData );
376
+ $filterCtrlBlocks[] = $this->getFilterBlockStructure( $filterControl, $visibilityClass, $iData["index"] );
377
+ }
378
+ }
379
+
380
+ /**
381
+ * Get the arrray with keys corresponding to filter blocks markup
382
+ * @param String filterControl
383
+ * @param String visibilityClass
384
+ * @param String value The Interval's index
385
+ * @param Array parentFiltersData (optional)
386
+ * @return Array
387
+ */
388
+ protected function getFilterBlockStructure( $filterControl, $visibilityClass = "", $value = "", $parentFiltersData = array() )
389
+ {
390
+ if( $this->multiSelect != FM_ALWAYS )
391
+ $visibilityClass.= " filter-link";
392
+
393
+ return array(
394
+ $this->gfName."_filter" => $filterControl,
395
+ "visibilityClass_".$this->gfName => $visibilityClass,
396
+ "sortValue" => $value
397
+ );
398
+ }
399
+
400
+ /**
401
+ * Sort filter blocks depending on the field's type and format
402
+ * @param &Array filterCtrlBlocks
403
+ */
404
+ protected function sortFilterBlocks( &$filterCtrlBlocks )
405
+ {
406
+ usort( $filterCtrlBlocks, array("FilterControl", "compareBlocksByNumericValues") );
407
+ }
408
+
409
+ /**
410
+ * Get the multiselect filters' filterblocks for values
411
+ * that are out of range. And add them to the existing filter blocks
412
+ * @param &Array filterCtrlBlocks
413
+ */
414
+ protected function addOutRangeValuesToFilter( &$filterCtrlBlocks )
415
+ {
416
+ $visibilityClass = $this->multiSelect == FM_ON_DEMAND ? $this->onDemandHiddenItemClassName : "";
417
+
418
+ foreach( $this->filteredFields[ $this->fName ]["values"] as $index )
419
+ {
420
+ if( in_array( $index, $this->valuesObtainedFromDB ) )
421
+ continue;
422
+
423
+ $filterControl = $this->buildControl( array( "index" => $index ) );
424
+ $filterCtrlBlocks[] = $this->getFilterBlockStructure( $filterControl, $visibilityClass, $index );
425
+ }
426
+ }
427
+
428
+ /**
429
+ * Get the html markup representing the control on the page
430
+ * @params Array data
431
+ * @param Array parentFiltersData (optional)
432
+ * @return String
433
+ */
434
+ protected function buildControl( $data, $parentFiltersData = array() )
435
+ {
436
+ $showValue = $this->getIntervalLabel( $data["index"] );
437
+ $totalValue = $this->getTotalValueToShow( $data["total"] );
438
+
439
+ return $this->getControlHTML( $data["index"], $showValue, $data["index"], $totalValue, $this->separator );
440
+ }
441
+
442
+
443
+ public static function getOrdinaryIntervalCondition( $fName, $intervalData, $pSet ) {
444
+ $lowerCondition = null;
445
+ $caseInsensitive = $intervalData["caseSensitive"] ? dsCASE_DEFAULT : dsCASE_INSENSITIVE;
446
+
447
+ $lowerLimit = $intervalData[ "lowerLimit" ];
448
+ if( $intervalData[ "lowerUsesExpression" ] )
449
+ $lowerLimit = getIntervalLimitsExpressions( $pSet->getTableName(), $fName, $intervalData["index"], true );
450
+
451
+ if( $intervalData["lowerLimitType"] == FIL_MORE_THAN ) {
452
+ $lowerCondition = DataCondition::FieldIs( $fName, dsopMORE, $lowerLimit, $caseInsensitive );
453
+ } else if( $intervalData["lowerLimitType"] == FIL_MORE_THAN_OR_EQUAL ) {
454
+ $lowerCondition = DataCondition::_Not(
455
+ DataCondition::FieldIs( $fName, dsopLESS, $lowerLimit, $caseInsensitive )
456
+ );
457
+ }
458
+
459
+ $upperCondition = null;
460
+ $upperLimit = $intervalData[ "upperLimit" ];
461
+ if( $intervalData[ "upperUsesExpression" ] )
462
+ $upperLimit = getIntervalLimitsExpressions( $pSet->getTableName(), $fName, $intervalData["index"], false );
463
+
464
+ if( $intervalData["upperLimitType"] == FIL_LESS_THAN ) {
465
+ $upperCondition = DataCondition::FieldIs( $fName, dsopLESS, $upperLimit, $caseInsensitive );
466
+ } else if( $intervalData["upperLimitType"] == FIL_LESS_THAN_OR_EQUAL ) {
467
+ $upperCondition = DataCondition::_Not(
468
+ DataCondition::FieldIs( $fName, dsopMORE, $upperLimit, $caseInsensitive )
469
+ );
470
+ }
471
+
472
+ if( $lowerCondition && $upperCondition ) {
473
+ return DataCondition::_And( array( $lowerCondition, $upperCondition ) );
474
+ }
475
+
476
+ if( $lowerCondition )
477
+ return $lowerCondition;
478
+
479
+ if( $upperCondition )
480
+ return $upperCondition;
481
+
482
+ return null;
483
+ }
484
+
485
+
486
+ public static function getFilterCondition( $fName, $index, $pSet ) {
487
+
488
+ $intervalData = $pSet->getFilterIntervalDatabyIndex( $fName, $index );
489
+ if( !$intervalData )
490
+ return null;
491
+
492
+ if( $intervalData["remainder"] ) {
493
+ $conditions = array();
494
+
495
+ foreach( $pSet->getFilterIntervals( $fName ) as $_intervalData ) {
496
+ if( $_intervalData["index"] == $index )
497
+ continue;
498
+
499
+ if( $_intervalData["noLimits"] )
500
+ return DataCondition::_False();
501
+
502
+ $conditions[] = DataCondition::_Not(
503
+ FilterIntervalList::getOrdinaryIntervalCondition( $fName, $_intervalData, $pSet )
504
+ );
505
+ }
506
+
507
+ return DataCondition::_And( $conditions );
508
+ }
509
+
510
+ if( $intervalData["noLimits"] ) {
511
+ return DataCondition::_Not(
512
+ DataCondition::FieldIs( $fName, dsopEMPTY, $index )
513
+ );
514
+ }
515
+
516
+ return FilterIntervalList::getOrdinaryIntervalCondition( $fName, $intervalData, $pSet );
517
+ }
518
+ }
519
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
520
  ?>
php/classes/controls/FilterIntervalSlider.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class FilterIntervalSlider extends FilterControl
3
  {
@@ -380,4 +381,388 @@ class FilterIntervalSlider extends FilterControl
380
  ));
381
  }
382
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class FilterIntervalSlider extends FilterControl
4
  {
 
381
  ));
382
  }
383
  }
384
+ =======
385
+ <?php
386
+ class FilterIntervalSlider extends FilterControl
387
+ {
388
+ protected $separator;
389
+ protected $knobsType;
390
+ protected $stepValue;
391
+
392
+ protected $minValue;
393
+ protected $maxValue;
394
+ protected $minKnobValue;
395
+ protected $maxKnobValue;
396
+
397
+ protected $showCollapsed = false;
398
+
399
+ public function __construct($fName, $pageObject, $id, $viewControls)
400
+ {
401
+ parent::__construct($fName, $pageObject, $id, $viewControls);
402
+
403
+ $this->filterFormat = FF_INTERVAL_SLIDER;
404
+
405
+ $this->useApllyBtn = $this->pSet->isFilterApplyBtnSet($fName);
406
+ $this->knobsType = $this->pSet->getFilterKnobsType($fName);
407
+
408
+ $this->stepValue = $this->pSet->getFilterStepValue($fName);
409
+
410
+ $this->addJS_CSSfiles($pageObject);
411
+
412
+ if( $this->filtered )
413
+ $this->assignKnobsValues();
414
+
415
+ $this->showCollapsed = $this->pSet->showCollapsed($fName);
416
+
417
+ $this->separator = $this->getSeparator();
418
+ }
419
+
420
+ /**
421
+ * Assign the control's knobs properties
422
+ */
423
+ protected function assignKnobsValues()
424
+ {
425
+ $filterData = $this->filteredFields[ $this->fName ];
426
+
427
+ $filterValues = array();
428
+ $filterValues[] = $filterData['values'][0];
429
+ $filterValues[] = $filterData['sValues'][0];
430
+
431
+
432
+ if($this->knobsType == FS_MIN_ONLY)
433
+ {
434
+ $this->minKnobValue = $filterValues[0];
435
+ return;
436
+ }
437
+
438
+ if($this->knobsType == FS_MAX_ONLY)
439
+ {
440
+ $this->maxKnobValue = $filterValues[0];
441
+ return;
442
+ }
443
+
444
+ $this->minKnobValue = $filterValues[0];
445
+ $this->maxKnobValue = $filterValues[1];
446
+ }
447
+
448
+ /**
449
+ * Get the separator value
450
+ * @return String
451
+ */
452
+ protected function getSeparator()
453
+ {
454
+ if( $this->knobsType == FS_MIN_ONLY )
455
+ return '~moreequal~';
456
+
457
+ if( $this->knobsType == FS_MAX_ONLY )
458
+ return '~lessequal~';
459
+
460
+ return '~slider~';
461
+ }
462
+
463
+ /**
464
+ * Form totals of the following type:
465
+ SELECT MIN(field) AS sliderMin, MAX(field) AS sliderMax
466
+ FROM ( ... ) WHERE <field is not null>
467
+ */
468
+ protected function getDataCommand() {
469
+
470
+ $dc = new DsCommand;
471
+ $dc->filter = $this->pageObject->getDataSourceFilterCriteria( $this->fName );
472
+
473
+ $dc->totals[] = array(
474
+ "field" => $this->fName,
475
+ "alias" => "sliderMin",
476
+ "skipEmpty" => true,
477
+ "total" => "min"
478
+ );
479
+
480
+ $dc->totals[] = array(
481
+ "field" => $this->fName,
482
+ "alias" => "sliderMax",
483
+ "total" => "max"
484
+ );
485
+
486
+ return $dc;
487
+ }
488
+
489
+ /**
490
+ * Get the filter blocks data using the database query
491
+ * and add it the the existing blocks
492
+ * @param &Array
493
+ */
494
+ protected function addFilterBlocksFromDB( &$filterCtrlBlocks )
495
+ {
496
+ //query to database
497
+ $qResult = $this->dataSource->getTotals( $this->getDataCommand() );
498
+ $data = $qResult->fetchAssoc();
499
+
500
+ $this->decryptDataRow( $data );
501
+
502
+ if( $this->fieldHasNoRange( $data ) )
503
+ return $filterCtrlBlocks;
504
+
505
+ $filterControl = $this->buildControl( $data );
506
+ $filterCtrlBlocks[] = $this->getFilterBlockStructure( $filterControl );
507
+ }
508
+
509
+ /**
510
+ * Check if there are database values for the filter's field
511
+ * that are differs from each other for more than a step value
512
+ * @param Array data
513
+ * @return Boolean
514
+ */
515
+ protected function fieldHasNoRange($data)
516
+ {
517
+ if( is_null( $data['sliderMin'] ) && is_null( $data['sliderMax'] ) || $data['sliderMax'] == $data['sliderMin'] )
518
+ return true;
519
+
520
+ return false;
521
+ }
522
+
523
+ /**
524
+ * Get the html markup representing the control on the page
525
+ * @param Array data
526
+ * @param Array parentFiltersData (optional)
527
+ * @return String
528
+ */
529
+ protected function buildControl( $data, $parentFiltersData = array() )
530
+ {
531
+ if( !$this->viewControl )
532
+ return "";
533
+ $this->minValue = $data['sliderMin'];
534
+ $this->maxValue = $data['sliderMax'];
535
+
536
+ if( !$this->filtered )
537
+ {
538
+ $this->minKnobValue = $data['sliderMin'];
539
+ $this->maxKnobValue = $data['sliderMax'];
540
+ }
541
+ else
542
+ {
543
+ if( $this->knobsType == FS_MAX_ONLY )
544
+ $this->minKnobValue = $data['sliderMin'];
545
+
546
+ if( $this->knobsType == FS_MIN_ONLY )
547
+ $this->maxKnobValue = $data['sliderMax'];
548
+ }
549
+
550
+ return $this->getSliderHTML();
551
+ }
552
+
553
+ /**
554
+ * Get the html markup for the slider knobs' captions
555
+ * @return String
556
+ */
557
+ protected function getCaptionSpansHTML()
558
+ {
559
+ $minSpan = '<span class="slider-min">'.$this->getMinSpanValue().'</span>';
560
+ $maxSpan = '<span class="slider-max">'.$this->getMaxSpanValue().'</span>';
561
+ $captionSpans = $minSpan."&nbsp;-&nbsp".$maxSpan;
562
+
563
+ $prefixSpan = '<span class="slider-caption-prefix"></span>';
564
+ $postfixSpan = '<span class="slider-caption-postfix"></span>';
565
+
566
+ $captionSpans = $prefixSpan . $captionSpans . $postfixSpan;
567
+
568
+ return $captionSpans;
569
+ }
570
+
571
+ /**
572
+ * Get the html markup for the slider's control
573
+ * @return String
574
+ */
575
+ protected function getSliderHTML()
576
+ {
577
+ $captionSpans = $this->getCaptionSpansHTML();
578
+
579
+ $filterControl = '<div id="slider_values_'.$this->gfName.'" class="filter-slider-values">'.$captionSpans.'</div>';
580
+ $filterControl.= '<div id="slider_'.$this->gfName.'" class="filter-slider"></div>';
581
+ return $filterControl;
582
+ }
583
+
584
+ /**
585
+ * Get the caption fot the min slider's knob
586
+ * @return String
587
+ */
588
+ protected function getMinSpanValue()
589
+ {
590
+ $minSpanValue = $this->minKnobValue;
591
+ if( $minSpanValue < $this->minValue )
592
+ $minSpanValue = $this->minValue;
593
+
594
+ $viewFormat = $this->viewControl->viewFormat;
595
+ if( $viewFormat == FORMAT_CURRENCY || $viewFormat == FORMAT_NUMBER )
596
+ {
597
+ $data = array($this->fName => $minSpanValue);
598
+ $minSpanValue = $this->viewControl->showDBValue($data, "");
599
+ }
600
+ return $minSpanValue;
601
+ }
602
+
603
+ /**
604
+ * Get the caption fot the max slider's knob
605
+ * @return String
606
+ */
607
+ protected function getMaxSpanValue()
608
+ {
609
+ $maxSpanValue = $this->maxKnobValue;
610
+ if( $maxSpanValue > $this->maxValue )
611
+ $maxSpanValue = $this->maxValue;
612
+
613
+ $viewFormat = $this->viewControl->viewFormat;
614
+ if( $viewFormat == FORMAT_CURRENCY || $viewFormat == FORMAT_NUMBER )
615
+ {
616
+ $data = array($this->fName => $maxSpanValue);
617
+ $maxSpanValue = $this->viewControl->showDBValue($data, "");
618
+ }
619
+ return $maxSpanValue;
620
+ }
621
+
622
+ /**
623
+ * Add filter control's data to the ControlsMap
624
+ * @param Object pageObj
625
+ */
626
+ public function addFilterControlToControlsMap($pageObj)
627
+ {
628
+ if( !$this->viewControl )
629
+ return;
630
+
631
+ $ctrlsMap = $this->getBaseContolsMapParams();
632
+
633
+ $ctrlsMap['minValue'] = $this->minValue;
634
+ $ctrlsMap['maxValue'] = $this->maxValue;
635
+ $ctrlsMap['roundedMin'] = $this->round( $this->minValue, true);
636
+ $ctrlsMap['roundedMax'] = $this->round( $this->maxValue, false );
637
+
638
+ $ctrlsMap['roundedMinKnobValue'] = $this->round( $this->minKnobValue, true );
639
+ $ctrlsMap['roundedMaxKnobValue'] = $this->round( $this->maxKnobValue, false );
640
+
641
+ if( $this->filtered ) {
642
+ $ctrlsMap['minKnobValue'] = $this->minKnobValue;
643
+ $ctrlsMap['maxKnobValue'] = $this->maxKnobValue;
644
+ }
645
+
646
+ $viewFomat = $this->viewControl->viewFormat;
647
+ $ctrlsMap['viewAsNumber'] = $viewFomat == FORMAT_NUMBER;
648
+ $ctrlsMap['viewAsCurrency'] = $viewFomat == FORMAT_CURRENCY;
649
+ $ctrlsMap['formatSettings'] = getFormatSettings( $viewFomat, $this->pSet, $this->fName );
650
+
651
+ $pageObj->controlsMap["filters"]["controls"][] = $ctrlsMap;
652
+ }
653
+
654
+ /**
655
+ * Get filter control's base ControlsMap array
656
+ * @return array
657
+ */
658
+ protected function getBaseContolsMapParams()
659
+ {
660
+ $ctrlsMap = array();
661
+ $ctrlsMap['fieldName'] = $this->fName;
662
+ $ctrlsMap['gfieldName'] = $this->gfName;
663
+ $ctrlsMap['filterFormat'] = $this->filterFormat;
664
+ $ctrlsMap['filtered'] = $this->filtered;
665
+ $ctrlsMap['separator'] = $this->separator;
666
+ $ctrlsMap['knobsType'] = $this->knobsType;
667
+ $ctrlsMap['useApllyBtn'] = $this->useApllyBtn;
668
+ $ctrlsMap['step'] = $this->getStepValue();
669
+ $ctrlsMap['collapsed'] = $this->showCollapsed;
670
+
671
+ return $ctrlsMap;
672
+ }
673
+
674
+ /**
675
+ * Get the slider's step value
676
+ * @return number
677
+ */
678
+ protected function getStepValue()
679
+ {
680
+ return $this->stepValue;
681
+ }
682
+
683
+ /**
684
+ * Get the rounded to the upper or lower limit value
685
+ * basing on the step value
686
+ * @param number value
687
+ * @return number
688
+ */
689
+ protected function round( $value, $min )
690
+ {
691
+ $step = $this->stepValue;
692
+
693
+ if( $min )
694
+ return floor( $value / $step ) * $step;
695
+
696
+ return ceil( $value / $step ) * $step;
697
+ }
698
+
699
+ /**
700
+ * Add extra js and css files
701
+ * @param object pageObject
702
+ */
703
+ protected function addJS_CSSfiles($pageObject)
704
+ {
705
+ }
706
+
707
+ /**
708
+ * Get the Filter's control block data.
709
+ * @param Object pageObj
710
+ * @param Array $dFilterBlocks (optional)
711
+ * @return Array
712
+ */
713
+ public function buildFilterCtrlBlockArray( $pageObj, $dFilterBlocks = null )
714
+ {
715
+ $filterCtrlBlocks = array();
716
+ $this->addFilterBlocksFromDB( $filterCtrlBlocks );
717
+
718
+ if( !$filterCtrlBlocks )
719
+ $this->visible = false;
720
+
721
+ if( $this->visible )
722
+ $this->addFilterControlToControlsMap( $pageObj );
723
+
724
+ return $filterCtrlBlocks;
725
+ }
726
+
727
+ /**
728
+ * secondValue is set up for knobsType FS_BOTH only
729
+ */
730
+ public static function getFilterCondition( $fName, $value, $pSet, $secondValue ) {
731
+
732
+ $knobsType = $pSet->getFilterKnobsType( $fName );
733
+
734
+ if( $knobsType == FS_MAX_ONLY ) {
735
+ return DataCondition::_Not(
736
+ DataCondition::FieldIs( $fName, dsopMORE, $value )
737
+ );
738
+ }
739
+
740
+ $conditionMore = DataCondition::_Not(
741
+ DataCondition::FieldIs( $fName, dsopLESS, $value )
742
+ );
743
+
744
+ if( $knobsType == FS_MIN_ONLY )
745
+ return $conditionMore;
746
+
747
+ if( $pSet->getFilterStepType( $fName ) >= 3 && IsDateFieldType( $pSet->getFieldType( $fName ) ) ) {
748
+ // interval "up to 2010-10-10" should translate into "x < 2010-10-11" and not in "x <= 2010-10-10"
749
+ $tm = db2time( $secondValue );
750
+ if( !$tm[0] ) {
751
+ $conditionLess = null;
752
+ } else {
753
+ $conditionLess = DataCondition::FieldIs( $fName, dsopLESS, date2db( adddays( $tm, 1 ) ) );
754
+ }
755
+ } else {
756
+ $conditionLess = DataCondition::_Not(
757
+ DataCondition::FieldIs( $fName, dsopMORE, $secondValue )
758
+ );
759
+ }
760
+
761
+ return DataCondition::_And( array(
762
+ $conditionLess,
763
+ $conditionMore
764
+ ));
765
+ }
766
+ }
767
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
768
  ?>
php/classes/controls/FilterIntervalTimeSlider.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class FilterIntervalTimeSlider extends FilterIntervalDateSlider
3
  {
@@ -130,4 +131,138 @@ class FilterIntervalTimeSlider extends FilterIntervalDateSlider
130
  $pageObj->controlsMap["filters"]["controls"][] = $ctrlsMap;
131
  }
132
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class FilterIntervalTimeSlider extends FilterIntervalDateSlider
4
  {
 
131
  $pageObj->controlsMap["filters"]["controls"][] = $ctrlsMap;
132
  }
133
  }
134
+ =======
135
+ <?php
136
+ class FilterIntervalTimeSlider extends FilterIntervalDateSlider
137
+ {
138
+ /**
139
+ * The array reprsenting the 1st January of 1970 (00:00:00)
140
+ * @type Array
141
+ */
142
+ protected $baseDateArray = array();
143
+
144
+ public function __construct($fName, $pageObject, $id, $viewControls)
145
+ {
146
+ parent::__construct($fName, $pageObject, $id, $viewControls);
147
+ $this->baseDateArray = array(1970, 1, 1, 0, 0, 0);
148
+ }
149
+
150
+ /**
151
+ * Get the date-time array representation
152
+ * @param String value
153
+ * @param Boolean forCaption
154
+ * @return Array
155
+ */
156
+ protected function getDateTimeArray($value, $forCaption = false)
157
+ {
158
+ if($forCaption)
159
+ {
160
+ $timeArray = parsenumbers($value);
161
+ return array(0, 0, 0, $timeArray[0], $timeArray[1] ,$timeArray[2]);
162
+ }
163
+ $timeInSeonds = $this->getValueInSeconds($value);
164
+ $baseDateArray = $this->baseDateArray;
165
+ return addSeconds($baseDateArray, $timeInSeonds);
166
+ }
167
+
168
+ /**
169
+ * Get the value converted into seconds
170
+ * @param String value
171
+ * @return Number
172
+ */
173
+ protected function getValueInSeconds($value)
174
+ {
175
+ $timeArray = parsenumbers($value);
176
+ return $timeArray[2] + $timeArray[1] * 60 + $timeArray[0] * 3600;
177
+ }
178
+
179
+ /**
180
+ * Get the full caption value for the slider with the 'seconds' step type
181
+ * @param Array dateArray
182
+ * @return String
183
+ */
184
+ protected function getSecondsCaption($dateArray)
185
+ {
186
+ return str_format_time($dateArray);
187
+ }
188
+
189
+ /**
190
+ * Get the full caption value for the slider with the 'minutes' step type
191
+ * @param Array dateArray
192
+ * @return String
193
+ */
194
+ protected function getMinutesCaption($dateArray)
195
+ {
196
+ global $locale_info;
197
+ $dateArray[5] = 0;
198
+
199
+ $timeFormatString = str_replace( $locale_info["LOCALE_STIME"]."ss", "", $locale_info["LOCALE_STIMEFORMAT"]);
200
+ return format_datetime_custom($dateArray, $timeFormatString);
201
+ }
202
+
203
+ /**
204
+ * Get the full caption value for the slider with the 'hours' step type
205
+ * @param Array dateArray
206
+ * @param Boolean isLower
207
+ * @return String
208
+ */
209
+ protected function getHoursCaption($dateArray, $isLower)
210
+ {
211
+ global $locale_info;
212
+
213
+ $hours = $this->getAdjustedHoursValue($dateArray[3], $dateArray[4], $isLower);
214
+ $dateArray[3] = $dateArray[4] = $dateArray[5] = 0;
215
+ $dateArray = addHours($dateArray, $hours);
216
+
217
+ $timeFormatString = str_replace( $locale_info["LOCALE_STIME"]."ss", "", $locale_info["LOCALE_STIMEFORMAT"]);
218
+ return format_datetime_custom($dateArray, $timeFormatString);
219
+ }
220
+
221
+ /**
222
+ * Check if there are database values for the filter's field
223
+ * that are differs from each other for more than a step value
224
+ * @param Array data
225
+ * @return Boolean
226
+ */
227
+ protected function fieldHasNoRange($data)
228
+ {
229
+ if (is_null( $data['sliderMin'] ) && is_null( $data['sliderMax'] ) || $data['sliderMax'] == $data['sliderMin'])
230
+ return true;
231
+
232
+ $step = $this->getStepValue();
233
+ $minSec = $this->getValueInSeconds( $data['sliderMin'] );
234
+ $maxSec = $this->getValueInSeconds( $data['sliderMax'] );
235
+
236
+ if( ($maxSec - $minSec) < $step )
237
+ return true;
238
+
239
+ return false;
240
+ }
241
+
242
+ /**
243
+ * Get the html markup for the slider knobs' captions
244
+ * @return String
245
+ */
246
+ protected function getCaptionSpansHTML()
247
+ {
248
+ $minSpan = '<span class="slider-min">'.$this->getMinSpanValue().'</span>';
249
+ $maxSpan = '<span class="slider-max">'.$this->getMaxSpanValue().'</span>';
250
+ $captionSpans = $minSpan."&nbsp;-&nbsp".$maxSpan;
251
+
252
+ return $captionSpans;
253
+ }
254
+
255
+ /**
256
+ * Add filter control's data to the ControlsMap
257
+ * @param Object pageObj
258
+ */
259
+ public function addFilterControlToControlsMap($pageObj)
260
+ {
261
+ $ctrlsMap = $this->getBaseContolsMapParams();
262
+ $ctrlsMap['isFieldTimeType'] = true;
263
+
264
+ $pageObj->controlsMap["filters"]["controls"][] = $ctrlsMap;
265
+ }
266
+ }
267
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
268
  ?>
php/classes/controls/FilterMultiselectLookup.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class FilterMultiselectLookup extends FilterValuesList {
3
 
@@ -84,4 +85,92 @@ class FilterMultiselectLookup extends FilterValuesList {
84
  return DataCondition::FieldHasList( $fName, dsopALL_IN_LIST, array( $value ) );
85
  }
86
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class FilterMultiselectLookup extends FilterValuesList {
4
 
 
85
  return DataCondition::FieldHasList( $fName, dsopALL_IN_LIST, array( $value ) );
86
  }
87
  }
88
+ =======
89
+ <?php
90
+ class FilterMultiselectLookup extends FilterValuesList {
91
+
92
+ public function __construct( $fName, $pageObject, $id, $viewControls ) {
93
+ parent::__construct( $fName, $pageObject, $id, $viewControls );
94
+
95
+ $this->aliases[ $this->fName ] = $this->fName;
96
+ }
97
+
98
+ protected function getDataCommand() {
99
+ $dc = new DsCommand;
100
+ $dc->filter = $this->pageObject->getDataSourceFilterCriteria( $this->fName );
101
+
102
+ return $dc;
103
+ }
104
+
105
+
106
+ /**
107
+ * Get the filter blocks data using the database query
108
+ * and add it the the existing blocks
109
+ * @param &Array
110
+ */
111
+ protected function addFilterBlocksFromDB( &$filterCtrlBlocks )
112
+ {
113
+ $containsFilteredDependentOnDemandFilter = !$this->dependent && !$this->filtered
114
+ && $this->hasFilteredDependentOnDemandFilter();
115
+
116
+ $visibilityClass = $this->filtered && $this->multiSelect == FM_ON_DEMAND ? $this->onDemandHiddenItemClassName : "";
117
+ $totalOption = $this->pSet->getFilterFieldTotal( $this->fName );
118
+
119
+ //query to database with current where settings
120
+ $qResult = $this->dataSource->getList( $this->getDataCommand() );
121
+
122
+ $metaData = array();
123
+ while( $data = $qResult->fetchAssoc() ) {
124
+ $this->decryptDataRow( $data );
125
+
126
+ $parentFiltersData = array();
127
+ $parentString = "";
128
+ if( $this->dependent ) {
129
+ foreach( $this->parentFiltersNames as $pName ) {
130
+ $parentFiltersData[ $pName ] = $data[ $pName ];
131
+ }
132
+ $parentString = my_json_encode( $parentFiltersData );
133
+ }
134
+
135
+ $values = splitLookupValues( $data[ $this->fName ] );
136
+ foreach( $values as $value ) {
137
+ $hash = md5( $parentString.$value );
138
+ if( !$metaData[ $hash ] ) {
139
+ $total = $data[ $this->totalsfName ];
140
+ if( $totalOption == FT_COUNT )
141
+ $total = 1;
142
+
143
+ $metaData[ $hash ] = array( "rawValue" => $value, "total" => $total, "parent" => $parentFiltersData );
144
+ } else {
145
+ if( $totalOption == FT_COUNT ) {
146
+ $metaData[ $hash ]["total"] = $metaData[ $hash ]["total"] + 1;
147
+ } else if( $totalOption == FT_MIN ) {
148
+ $metaData[ $hash ]["total"] = min( $data[ $this->totalsfName ], $metaData[ $hash ]["total"] );
149
+ } else if( $totalOption == FT_MAX ) {
150
+ $metaData[ $hash ]["total"] = max( $data[ $this->totalsfName ], $metaData[ $hash ]["total"] );
151
+ }
152
+ }
153
+ }
154
+ }
155
+
156
+ foreach( $metaData as $meta ) {
157
+ $data = array();
158
+ $data[ $this->fName ] = $meta["rawValue"];
159
+ $data[ $this->fName."TOTAL" ] = $meta["total"];
160
+
161
+ $this->valuesObtainedFromDB[] = $meta["rawValue"];
162
+
163
+ $filterControl = $this->buildControl( $data, $meta["parent"] );
164
+ if( $containsFilteredDependentOnDemandFilter )
165
+ $filterControl = $this->getDelButtonHtml( $this->gfName, $this->id, $meta["rawValue"] ).$filterControl;
166
+
167
+ $filterCtrlBlocks[] = $this->getFilterBlockStructure( $filterControl, $visibilityClass, $meta["rawValue"], $meta["parent"] );
168
+ }
169
+ }
170
+
171
+ public static function getFilterCondition( $fName, $value, $pSet ) {
172
+ return DataCondition::FieldHasList( $fName, dsopALL_IN_LIST, array( $value ) );
173
+ }
174
+ }
175
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
176
  ?>
php/classes/controls/FilterValuesList.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class FilterValuesList extends FilterControl
3
  {
@@ -720,4 +721,728 @@ class FilterValuesList extends FilterControl
720
  return DataCondition::FieldEquals( $fName, $value, $pSet->getFilterByInterval($fName) );
721
  }
722
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
723
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class FilterValuesList extends FilterControl
4
  {
 
721
  return DataCondition::FieldEquals( $fName, $value, $pSet->getFilterByInterval($fName) );
722
  }
723
  }
724
+ =======
725
+ <?php
726
+ class FilterValuesList extends FilterControl
727
+ {
728
+ protected $useFormatedValueInSorting;
729
+
730
+ protected $isDescendingSortOrder;
731
+
732
+ protected $sortingType;
733
+
734
+ protected $parentFiltersNames = array();
735
+
736
+ protected $dependentFilterNames = array();
737
+
738
+ protected $dependentFilterName;
739
+
740
+ protected $hasDependent = false;
741
+
742
+ protected $filteredFieldParentFiltersKeysToIgnore = null;
743
+
744
+ protected $hideShowMore = false;
745
+
746
+ /**
747
+ * The number of items that should be show
748
+ * according to the 'Show firt N item' setting
749
+ * @type Number
750
+ */
751
+ protected $numberOfVisibleItems = 0;
752
+
753
+ /**
754
+ * The flag indicating if to show 'Show N more' button
755
+ * @param Boolean
756
+ */
757
+ protected $truncated = false;
758
+
759
+ protected $numberOfExtraItemsToShow = 0;
760
+
761
+ protected $hiddenExtraItemClassName = "filter-item-hidden";
762
+
763
+ // SQL aliases for current and parent fields
764
+ protected $aliases = array();
765
+
766
+
767
+ public function __construct($fName, $pageObject, $id, $viewControls)
768
+ {
769
+ parent::__construct($fName, $pageObject, $id, $viewControls);
770
+
771
+ $this->filterFormat = FF_VALUE_LIST;
772
+ $this->separator = "~equals~";
773
+
774
+ $this->useApllyBtn = $this->multiSelect == FM_ALWAYS;
775
+
776
+ $this->numberOfVisibleItems = $this->pSet->getNumberOfVisibleFilterItems($fName);
777
+
778
+ $this->parentFilterName = $this->pSet->getParentFilterName($fName);
779
+ $this->dependent = !!$this->parentFilterName;
780
+
781
+ $this->assignDependentFiltersData();
782
+ $this->hasDependent = !!$this->dependentFilterName;
783
+
784
+
785
+ $this->assignParentFiltersData();
786
+
787
+ $this->setSortingParams();
788
+ }
789
+
790
+ /**
791
+ * Assign 'parentFiltersNames' properties to
792
+ * the corresponding data if the current filter is dependent
793
+ */
794
+ protected function assignParentFiltersData()
795
+ {
796
+ if( !$this->dependent )
797
+ return;
798
+
799
+ $this->parentFiltersNames = FilterValuesList::getParentFilterFields( $this->fName, $this->pSet );
800
+
801
+ }
802
+
803
+ public static function getParentFilterFields( $field, $pSet ) {
804
+ $parents = array();
805
+ FilterValuesList::findParentFilters( $field, $parents, $pSet );
806
+ return array_keys( $parents );
807
+ }
808
+
809
+ /**
810
+ * Assign the 'dependentFilterNames' property to
811
+ * the corresponding data if the current filter has any dependent filter
812
+ */
813
+ protected function assignDependentFiltersData()
814
+ {
815
+ $dependents = array();
816
+ $this->findDependentFilters( $this->fName, $this->pSet->getFilterFields(), $dependents );
817
+ $this->dependentFilterNames = array_keys( $dependents );
818
+ }
819
+
820
+ public function hasDependentFilter() {
821
+ return !!$this->dependentFilterName;
822
+ }
823
+
824
+ protected function findDependentFilters( $field, &$filterFields, &$dependents ) {
825
+ foreach( $filterFields as $f ) {
826
+ if( !isset( $dependents[$f] ) && $this->pSet->getParentFilterName( $f ) === $field ) {
827
+ $dependents[ $f ] = true;
828
+ if( $field == $this->fName )
829
+ $this->dependentFilterName = $f;
830
+ FilterValuesList::findDependentFilters( $f, $filterFields, $dependents );
831
+ break;
832
+ }
833
+ }
834
+ }
835
+ protected static function findParentFilters( $field, &$parents, $pSet ) {
836
+ $f = $pSet->getParentFilterName( $field );
837
+ if( !$f )
838
+ return;
839
+ if( !isset( $parents[$f] ) ) {
840
+ $parents[$f] = true;
841
+ FilterValuesList::findParentFilters( $f, $parents, $pSet );
842
+ }
843
+ }
844
+
845
+ protected function getDataCommand()
846
+ {
847
+ $dc = new DsCommand;
848
+ $dc->filter = $this->pageObject->getDataSourceFilterCriteria( $this->fName );
849
+
850
+ $alias = generateAlias();
851
+ $this->aliases[ $this->fName ] = $alias;
852
+ $dc->totals[] = array(
853
+ "field" => $this->fName,
854
+ "alias" => $alias,
855
+ "modifier" => $this->pSet->getFilterByInterval($this->fName),
856
+ "skipEmpty" => true
857
+ );
858
+
859
+ $totalsType = $this->dataTotalsName();
860
+ if( $totalsType ) {
861
+ $dc->totals[] = array(
862
+ "field" => $this->totalsfName,
863
+ "alias" => $this->fName."TOTAL",
864
+ "total" => $totalsType );
865
+ }
866
+
867
+ // calculate add master filter fields
868
+ if( $this->dependent )
869
+ {
870
+ foreach( $this->parentFiltersNames as $p ) {
871
+ $pAlias = generateAlias();
872
+ $this->aliases[ $p ] = $pAlias;
873
+ $dc->totals[] = array(
874
+ "field" => $p,
875
+ "alias" => $pAlias,
876
+ "modifier" => $this->pSet->getFilterByInterval( $p ),
877
+ "skipEmpty" => true
878
+ );
879
+ }
880
+ }
881
+
882
+ $sortingType = $this->pSet->getFilterSortValueType($this->fName);
883
+
884
+ if( $sortingType != SORT_BY_DISP_VALUE )
885
+ {
886
+ $direction = $this->pSet->isFilterSortOrderDescending($this->fName)
887
+ ? "DESC"
888
+ : "ASC";
889
+
890
+ if( $sortingType == SORT_BY_GR_VALUE && $totalsType ) {
891
+ $dc->totals[ 1 ][ "direction" ] = $direction;
892
+ } else {
893
+ $dc->totals[ 0 ][ "direction" ] = $direction;
894
+ }
895
+ }
896
+ return $dc;
897
+ }
898
+
899
+ /**
900
+ * @deprecated
901
+ */
902
+ protected function getFilterSQLExpr( $expr ) {
903
+ return FilterValuesList::_getFilterSQLExpr( $this->fName, $expr, $this->pSet, $this->connection );
904
+ }
905
+
906
+ /**
907
+ * @deprecated
908
+ * @return String
909
+ */
910
+ protected static function _getFilterSQLExpr( $fName, $expr, $pSet, $connection )
911
+ {
912
+ $filterInterval = $pSet->getFilterByInterval($fName);
913
+ if( !$filterInterval )
914
+ return $expr;
915
+
916
+ $ftype = $pSet->getFieldType( $fName );
917
+
918
+ if( IsNumberType($ftype) )
919
+ {
920
+ return $connection->intervalExpressionNumber( $expr, $filterInterval );
921
+ }
922
+
923
+ if( IsCharType( $ftype ) )
924
+ {
925
+ return $connection->intervalExpressionString( $expr, $filterInterval );
926
+ }
927
+
928
+ if( IsDateFieldType( $ftype ) )
929
+ {
930
+ return $connection->intervalExpressionDate( $expr, $filterInterval );
931
+ }
932
+
933
+ return $expr;
934
+ }
935
+
936
+ /**
937
+ * Set the sorting params
938
+ */
939
+ protected function setSortingParams()
940
+ {
941
+ $this->sortingType = $this->pSet->getFilterSortValueType($this->fName);
942
+ $this->isDescendingSortOrder = $this->pSet->isFilterSortOrderDescending($this->fName);
943
+ $this->useFormatedValueInSorting = $this->sortingType == SORT_BY_DISP_VALUE
944
+ || IsCharType($this->fieldType) || $this->pSet->getEditFormat($this->fName) == EDIT_FORMAT_LOOKUP_WIZARD;
945
+ }
946
+
947
+ /**
948
+ * Get the view controls' value
949
+ *
950
+ * @param String values
951
+ * @return String
952
+ */
953
+ protected function getValueToShow($value)
954
+ {
955
+ if( !$this->viewControl ) {
956
+ return "";
957
+ }
958
+ $data = array($this->fName => $value);
959
+ $showValue = $this->viewControl->showDBValue($data, "");
960
+
961
+ return $showValue;
962
+ }
963
+
964
+
965
+
966
+ /**
967
+ * Get the filter blocks data using the database query
968
+ * and add it the the existing blocks
969
+ * @param &Array
970
+ */
971
+ protected function addFilterBlocksFromDB( &$filterCtrlBlocks )
972
+ {
973
+ $containsFilteredDependentOnDemandFilter = !$this->dependent && !$this->filtered && $this->hasFilteredDependentOnDemandFilter();
974
+ $visibilityClass = $this->filtered && $this->multiSelect == FM_ON_DEMAND ? $this->onDemandHiddenItemClassName : "";
975
+
976
+ //query to database with current where settings
977
+ $qResult = $this->dataSource->getTotals( $this->getDataCommand() );
978
+ $alias = $this->aliases[ $this->fName ];
979
+ while( $data = $qResult->fetchAssoc() )
980
+ {
981
+ $this->decryptDataRow($data);
982
+
983
+ $rawValue = $data[ $alias ];
984
+
985
+ $parentFiltersData = array();
986
+ if( $this->dependent )
987
+ {
988
+ foreach($this->parentFiltersNames as $pName)
989
+ {
990
+ $parentFiltersData[ $pName ] = $data[ $this->aliases[ $pName ] ];
991
+ }
992
+ }
993
+
994
+ $this->valuesObtainedFromDB[] = $rawValue;
995
+
996
+ $filterControl = $this->buildControl( $data, $parentFiltersData );
997
+ if( $containsFilteredDependentOnDemandFilter )
998
+ $filterControl = $this->getDelButtonHtml( $this->gfName, $this->id, $rawValue ).$filterControl;
999
+
1000
+ $filterCtrlBlocks[] = $this->getFilterBlockStructure($filterControl, $visibilityClass, $rawValue, $parentFiltersData);
1001
+ }
1002
+ }
1003
+
1004
+ /**
1005
+ * Check if the current filter has any dependent filtered 'on demand' filter
1006
+ * @return Boolean
1007
+ */
1008
+ protected function hasFilteredDependentOnDemandFilter()
1009
+ {
1010
+ if( !$this->hasDependent )
1011
+ return false;
1012
+
1013
+ foreach( $this->dependentFilterNames as $dName )
1014
+ {
1015
+ if( !!$this->filteredFields[ $dName ] && $this->pSet->getFilterFiledMultiSelect($dName) == FM_ON_DEMAND )
1016
+ return true;
1017
+ }
1018
+
1019
+ return false;
1020
+ }
1021
+
1022
+ /**
1023
+ * Get the parent filters data
1024
+ * @param String value
1025
+ * @return Array
1026
+ */
1027
+ protected function getParentFiltersDataForFilteredBlock( $value )
1028
+ {
1029
+ $parentFiltersData = array();
1030
+
1031
+ if( !$this->filtered || !$this->dependent )
1032
+ return $parentFiltersData;
1033
+
1034
+ $parentValuesData = $this->filteredFields[ $this->fName ]["parentValues"];
1035
+ if( count($parentValuesData) <= 1 )
1036
+ {
1037
+ foreach($this->parentFiltersNames as $pName)
1038
+ {
1039
+ //parent filter is single selected
1040
+ $pValue = $this->filteredFields[ $pName ]["values"][0];
1041
+ //parent filter is not presented in filter params string
1042
+ if( !isset($this->filteredFields[ $pName ]) && count( $parentValuesData[0] ) )
1043
+ $pValue = $parentValuesData[0][0];
1044
+
1045
+ $parentFiltersData[ $pName ] = $pValue;
1046
+ }
1047
+ return $parentFiltersData;
1048
+ }
1049
+
1050
+ if( !$this->filteredFieldParentFiltersKeysToIgnore )
1051
+ $this->filteredFieldParentFiltersKeysToIgnore = array();
1052
+
1053
+ foreach( $parentValuesData as $key => $parentValues )
1054
+ {
1055
+ if( $value != $this->filteredFields[ $this->fName ]['values'][ $key ] || in_array($key, $this->filteredFieldParentFiltersKeysToIgnore) )
1056
+ continue;
1057
+
1058
+ $this->filteredFieldParentFiltersKeysToIgnore[] = $key;
1059
+
1060
+ foreach($this->parentFiltersNames as $pKey => $pName)
1061
+ {
1062
+ $pValue = $parentValues[$pKey];
1063
+ $parentFiltersData[ $pName ] = $pValue;
1064
+ }
1065
+
1066
+ return $parentFiltersData;
1067
+ }
1068
+
1069
+ return $parentFiltersData;
1070
+ }
1071
+
1072
+ /**
1073
+ * Get the arrray with keys corresponding to filter blocks markup
1074
+ * @param String filterControl
1075
+ * @param String visibilityClass
1076
+ * @param String value The raw Db field's value
1077
+ * @param Array parentFiltersData (optional)
1078
+ * @return Array
1079
+ */
1080
+ protected function getFilterBlockStructure( $filterControl, $visibilityClass = "", $value = "", $parentFiltersData = array() )
1081
+ {
1082
+ if( !$this->viewControl )
1083
+ return array();
1084
+ $sortValue = $value;
1085
+ if( $this->useFormatedValueInSorting )
1086
+ {
1087
+ $valueData = array($this->fName => $sortValue);
1088
+ $sortValue = $this->viewControl->showDBValue($valueData, "");
1089
+ }
1090
+
1091
+ if( $this->multiSelect != FM_ALWAYS )
1092
+ $visibilityClass.= " filter-link";
1093
+
1094
+ return array(
1095
+ $this->gfName."_filter" => $filterControl,
1096
+ "visibilityClass_".$this->gfName => $visibilityClass,
1097
+ "sortValue" => $sortValue,
1098
+ "dbValue" => $value,
1099
+ "mainValues" => $parentFiltersData
1100
+ );
1101
+ }
1102
+
1103
+ /**
1104
+ * Get the html markup representing the control on the page
1105
+ * @param Array data
1106
+ * @param Array parentFiltersData (optional)
1107
+ * @return String
1108
+ */
1109
+ protected function buildControl( $data, $parentFiltersData = array() )
1110
+ {
1111
+ $filterInterval = $this->pSet->getFilterByInterval($this->fName);
1112
+ $value = $data[ $this->aliases[ $this->fName ] ];
1113
+
1114
+ // pass to attributes
1115
+ $dataValue = $value;
1116
+ $showValue = $this->getControlCaption( $value );
1117
+
1118
+ $totalValue = $this->getTotalValueToShow( $data[ $this->fName."TOTAL" ] );
1119
+
1120
+ return $this->getControlHTML( $value, $showValue, $dataValue, $totalValue, $this->separator, $parentFiltersData );
1121
+ }
1122
+
1123
+ /**
1124
+ * @param Array data
1125
+ * @return String
1126
+ */
1127
+ protected function getControlCaption( $value )
1128
+ {
1129
+ $intervalType = $this->pSet->getFilterByInterval($this->fName);
1130
+ if( !$intervalType )
1131
+ return $this->getValueToShow( $value );
1132
+
1133
+ return $this->pageObject->formatGroupValue( $this->fName, $intervalType, $value );
1134
+ }
1135
+
1136
+ /**
1137
+ * Check if to show the 'Show N more' button
1138
+ * for a not dependent filter
1139
+ * @return Boolean
1140
+ */
1141
+ protected function isTruncated()
1142
+ {
1143
+ return !$this->dependent && $this->truncated;
1144
+ }
1145
+
1146
+ /**
1147
+ * Get the extra data attributes for the control's HTML elements
1148
+ * @param Array parentFiltersData
1149
+ * @return String
1150
+ */
1151
+ protected function getExtraDataAttrs( $parentFiltersData )
1152
+ {
1153
+ if( !$this->dependent || is_null($parentFiltersData) )
1154
+ return '';
1155
+
1156
+ return ' data-parent-filters-values="'.runner_htmlspecialchars( my_json_encode( $parentFiltersData ) ).'" ';
1157
+ }
1158
+
1159
+ /**
1160
+ * Get the cheked attribute string for a multiselect filter control
1161
+ * @param String value
1162
+ * @param String parentFiltersData
1163
+ * @return String
1164
+ */
1165
+ protected function getCheckedAttr( $value, $parentFiltersData = null )
1166
+ {
1167
+ $filteredValues = $this->filteredFields[ $this->fName ]['values'];
1168
+
1169
+ if( $this->multiSelect == FM_NONE || $this->filtered && !in_array($value, $filteredValues) )
1170
+ return '';
1171
+
1172
+ if( $this->filtered && $this->dependent && $this->multiSelect == FM_ON_DEMAND && count($filteredValues) == 1 )
1173
+ return 'checked="checked"';
1174
+
1175
+ if( !$this->filtered || !$this->dependent || is_null($parentFiltersData) )
1176
+ return 'checked="checked"';
1177
+
1178
+ foreach( $this->filteredFields[ $this->fName ]["parentValues"] as $key => $parentValues )
1179
+ {
1180
+ if( $value == $this->filteredFields[ $this->fName ]['values'][$key] && $this->isParentsValuesDataTheSame($parentFiltersData, $parentValues) )
1181
+ return 'checked="checked"';
1182
+ }
1183
+ return '';
1184
+ }
1185
+
1186
+ /**
1187
+ * Check if two data structures passed are similar
1188
+ * @param Array parentFiltersData
1189
+ * @param Array parentValues
1190
+ * @return Boolean
1191
+ */
1192
+ protected function isParentsValuesDataTheSame($parentFiltersData, $parentValues)
1193
+ {
1194
+ foreach($this->parentFiltersNames as $pKey => $pName)
1195
+ {
1196
+ if( $parentFiltersData[$pName] != $parentValues[$pKey] )
1197
+ return false;
1198
+ }
1199
+ return true;
1200
+ }
1201
+
1202
+ /**
1203
+ * Get filter control's base ControlsMap array
1204
+ * @return array
1205
+ */
1206
+ protected function getBaseContolsMapParams()
1207
+ {
1208
+ $ctrlsMap = parent::getBaseContolsMapParams();
1209
+
1210
+ if( $this->dependent )
1211
+ {
1212
+ $ctrlsMap['dependent'] = true;
1213
+ $ctrlsMap['parentFilterNames'] = $this->parentFiltersNames;
1214
+ $ctrlsMap['goodParentName'] = GoodFieldName( $this->parentFilterName );
1215
+ $ctrlsMap['goodOutermostParentName'] = GoodFieldName( $this->parentFiltersNames[ count($this->parentFiltersNames) - 1 ] );
1216
+ }
1217
+
1218
+ if( $this->hasDependent )
1219
+ {
1220
+ $ctrlsMap['hasDependent'] = true;
1221
+ $ctrlsMap['dependentFilterNames'] = $this->dependentFilterNames;
1222
+ }
1223
+
1224
+ return $ctrlsMap;
1225
+ }
1226
+
1227
+ /**
1228
+ * Get the murkup of the control's delete button
1229
+ * @param String gfName
1230
+ * @param Number id
1231
+ * @param String deleteValue
1232
+ * @return String
1233
+ */
1234
+ protected function getDelButtonHtml($gfName, $id, $deleteValue)
1235
+ {
1236
+ if( $this->multiSelect == FM_ALWAYS || $this->dependent )
1237
+ return '';
1238
+
1239
+ return parent::getDelButtonHtml($gfName, $id, $deleteValue);
1240
+ }
1241
+
1242
+ /**
1243
+ * A stub
1244
+ * @return Number
1245
+ */
1246
+ protected function getNumberOfExtraItemsToShow()
1247
+ {
1248
+ return $this->numberOfExtraItemsToShow;
1249
+ }
1250
+
1251
+ /**
1252
+ * Update filter blocks structures
1253
+ * @param &Array
1254
+ */
1255
+ protected function extraBlocksProcessing( &$filterCtrlBlocks )
1256
+ {
1257
+ parent::extraBlocksProcessing($filterCtrlBlocks);
1258
+
1259
+ if( !$this->numberOfVisibleItems || $this->dependent )
1260
+ return;
1261
+
1262
+ $visbleItemsCounter = $hiddenItemsCounter = 0;
1263
+ foreach($filterCtrlBlocks as $index => $block)
1264
+ {
1265
+ $visible = ( strpos( $block[ "visibilityClass_".$this->gfName ], $this->onDemandHiddenItemClassName ) === FALSE );
1266
+ if( $visible )
1267
+ $visbleItemsCounter = $visbleItemsCounter + 1;
1268
+ else
1269
+ $hiddenItemsCounter = $hiddenItemsCounter + 1;
1270
+
1271
+ if( $visible && $visbleItemsCounter > $this->numberOfVisibleItems || !$visible && $hiddenItemsCounter > $this->numberOfVisibleItems )
1272
+ $filterCtrlBlocks[ $index ][ "visibilityClass_".$this->gfName ].= " ".$this->hiddenExtraItemClassName;
1273
+ }
1274
+
1275
+ if( $this->filtered && $this->multiSelect == FM_ON_DEMAND )
1276
+ {
1277
+ if( count($this->filteredFields[ $this->fName ]["values"]) < $this->numberOfVisibleItems && $hiddenItemsCounter > $this->numberOfVisibleItems )
1278
+ {
1279
+ $this->truncated = true;
1280
+ $this->hideShowMore = true;
1281
+ $this->numberOfExtraItemsToShow = $hiddenItemsCounter - $this->numberOfVisibleItems;
1282
+ }
1283
+ }
1284
+ elseif( $visbleItemsCounter > $this->numberOfVisibleItems )
1285
+ {
1286
+ $this->truncated = true;
1287
+ $this->numberOfExtraItemsToShow = $visbleItemsCounter - $this->numberOfVisibleItems;
1288
+ }
1289
+ }
1290
+
1291
+ /**
1292
+ * Check if the "show more" button must be hidden by class attr
1293
+ * @return Boolean
1294
+ */
1295
+ protected function isShowMoreHidden()
1296
+ {
1297
+ return $this->hideShowMore;
1298
+ }
1299
+
1300
+ /**
1301
+ * Sort filter blocks depending on the field's type and format
1302
+ * @param &Array filterCtrlBlocks
1303
+ */
1304
+ protected function sortFilterBlocks(&$filterCtrlBlocks)
1305
+ {
1306
+ if( $this->sortingType != SORT_BY_DISP_VALUE )
1307
+ return;
1308
+
1309
+ // always sort as strings. Lookups must be sorted as strings no matter field type
1310
+ $compareFunction = "compareBlocksByStringValues";
1311
+
1312
+ usort( $filterCtrlBlocks, array("FilterControl", $compareFunction) );
1313
+
1314
+ if( $this->isDescendingSortOrder )
1315
+ $filterCtrlBlocks = array_reverse( $filterCtrlBlocks );
1316
+ }
1317
+
1318
+ /**
1319
+ * Get the Filter's control block data.
1320
+ * @param Object pageObj
1321
+ * @param Array $dFilterBlocks (optional)
1322
+ * @return Array
1323
+ */
1324
+ public function buildFilterCtrlBlockArray( $pageObj, $dFilterBlocks = null )
1325
+ {
1326
+ $filterBlocks = parent::buildFilterCtrlBlockArray( $pageObj );
1327
+
1328
+ if( !$this->hasDependent || is_null($dFilterBlocks) )
1329
+ return $filterBlocks;
1330
+
1331
+ return $this->getCtrlBlocksMergeWithDependentFilterBlocks( $filterBlocks, $dFilterBlocks );
1332
+ }
1333
+
1334
+ /**
1335
+ * Get the main filter's and dependent blocks merged
1336
+ * @param Array mFilterBlocks
1337
+ * @param Array dFilterBlocks
1338
+ * @return Array
1339
+ */
1340
+ protected function getCtrlBlocksMergeWithDependentFilterBlocks( $mFilterBlocks, $dFilterBlocks )
1341
+ {
1342
+ $dgName = GoodFieldName( $this->dependentFilterName );
1343
+ $dBlockName = "filterCtrlBlock_".$dgName;
1344
+ $showMoreBlockName = "filter_button_showmore_".$dgName;
1345
+
1346
+ //Get 'Show first ...' settings
1347
+ $numberOfdItemsToShow = $this->pSet->getNumberOfVisibleFilterItems( $this->dependentFilterName );
1348
+
1349
+ foreach($mFilterBlocks as $key => $block)
1350
+ {
1351
+ $mMainValues = $block["mainValues"];
1352
+ $visibleItemsCounter = 0;
1353
+ $invisibleItemsCounter = 0;
1354
+
1355
+ foreach($dFilterBlocks as $dBlock)
1356
+ {
1357
+ $dMainValues = $dBlock["mainValues"];
1358
+ if( $dMainValues[ $this->fName ] != $block["dbValue"] )
1359
+ continue;
1360
+
1361
+ $addDependentBlock = true;
1362
+
1363
+ foreach($mMainValues as $fName=>$value)
1364
+ {
1365
+ if( $mMainValues[ $fName ] != $dMainValues[ $fName ] )
1366
+ {
1367
+ $addDependentBlock = false;
1368
+ break;
1369
+ }
1370
+ }
1371
+
1372
+ if( $addDependentBlock )
1373
+ {
1374
+ if( $numberOfdItemsToShow )
1375
+ {
1376
+ $visible = $dBlock["visibilityClass_".$dgName] != $this->onDemandHiddenItemClassName;
1377
+ if( $visible )
1378
+ $visibleItemsCounter = $visibleItemsCounter + 1;
1379
+ else
1380
+ $invisibleItemsCounter = $invisibleItemsCounter + 1;
1381
+
1382
+ if( $visible && $visibleItemsCounter > $numberOfdItemsToShow || !$visible && $invisibleItemsCounter > $numberOfdItemsToShow )
1383
+ $dBlock["visibilityClass_".$dgName] = $this->hiddenExtraItemClassName;
1384
+ }
1385
+
1386
+ $mFilterBlocks[ $key ][ $dBlockName ]["data"][] = $dBlock;
1387
+ }
1388
+
1389
+
1390
+ $mFilterBlocks[ $key ]["show_n_more_".$dgName] = str_replace( "%n%", $visibleItemsCounter - $numberOfdItemsToShow, "Show %n% more" );
1391
+ $mFilterBlocks[ $key ][ $showMoreBlockName ] = $numberOfdItemsToShow && $numberOfdItemsToShow < $visibleItemsCounter;
1392
+ }
1393
+ }
1394
+
1395
+ return $mFilterBlocks;
1396
+ }
1397
+
1398
+ /**
1399
+ * Get the filter's buttons parameters such as buttons' labels,
1400
+ * class names and attributes
1401
+ * @param Array dBtnParams (optional)
1402
+ * @return Array
1403
+ */
1404
+ public function getFilterButtonParams( $dBtnParams = null )
1405
+ {
1406
+ $mBtnParams = parent::getFilterButtonParams();
1407
+
1408
+ if( $this->hasDependent && !is_null($dBtnParams) )
1409
+ {
1410
+ $mBtnParams['hasMultiselectBtn'] = $mBtnParams['hasMultiselectBtn'] || $dBtnParams['hasMultiselectBtn'];
1411
+ $mBtnParams['hasApplyBtn'] = $mBtnParams['hasApplyBtn'] || $dBtnParams['hasApplyBtn'];
1412
+ }
1413
+
1414
+ return $mBtnParams;
1415
+ }
1416
+
1417
+ /**
1418
+ * Get the filter's extra controlls parameters
1419
+ * @param Array dBtnParams (dExtraCtrls)
1420
+ * @return Array
1421
+ */
1422
+ public function getFilterExtraControls( $dExtraCtrls = null )
1423
+ {
1424
+ $mExtraCtrls = parent::getFilterExtraControls();
1425
+
1426
+ if( !$this->hasDependent || is_null($dExtraCtrls) )
1427
+ return $mExtraCtrls;
1428
+
1429
+ if( !$mExtraCtrls['selectAllAttrs'] || $this->multiSelect == FM_ON_DEMAND && $dExtraCtrls['selectAllAttrs'] )
1430
+ $mExtraCtrls['selectAllAttrs'] = $dExtraCtrls['selectAllAttrs'];
1431
+
1432
+ if( !$mExtraCtrls['filtered'] )
1433
+ $mExtraCtrls['filtered'] = $dExtraCtrls['filtered'];
1434
+
1435
+ return $mExtraCtrls;
1436
+ }
1437
+
1438
+ public static function getFilterCondition( $fName, $value, $pSet ) {
1439
+ if( $pSet->multiSelectLookupEdit( $fName ) ) {
1440
+ include_once getabspath("classes/controls/FilterMultiselectLookup.php");
1441
+ return FilterMultiselectLookup::getFilterCondition( $fName, $value, $pSet );
1442
+ }
1443
+
1444
+ return DataCondition::FieldEquals( $fName, $value, $pSet->getFilterByInterval($fName) );
1445
+ }
1446
+ }
1447
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
1448
  ?>
php/classes/controls/HiddenField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  require_once getabspath('classes/controls/TextControl.php');
3
  class HiddenField extends TextControl
@@ -15,4 +16,23 @@ class HiddenField extends TextControl
15
  $this->buildControlEnd($validate, $mode);
16
  }
17
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  require_once getabspath('classes/controls/TextControl.php');
4
  class HiddenField extends TextControl
 
16
  $this->buildControlEnd($validate, $mode);
17
  }
18
  }
19
+ =======
20
+ <?php
21
+ require_once getabspath('classes/controls/TextControl.php');
22
+ class HiddenField extends TextControl
23
+ {
24
+ function __construct($field, $pageObject, $id, $connection)
25
+ {
26
+ EditControl::__construct($field, $pageObject, $id, $connection);
27
+ $this->format = EDIT_FORMAT_HIDDEN;
28
+ }
29
+
30
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
31
+ {
32
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
33
+ echo '<input id="'.$this->cfield.'" type="Hidden" name="'.$this->cfield.'" value="'.runner_htmlspecialchars($value).'">';
34
+ $this->buildControlEnd($validate, $mode);
35
+ }
36
+ }
37
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
38
  ?>
php/classes/controls/LookupField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class LookupField extends EditControl
3
  {
@@ -1640,4 +1641,1648 @@ class LookupField extends EditControl
1640
  return runner_htmlspecialchars( $displayValue );
1641
  }
1642
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1643
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class LookupField extends EditControl
4
  {
 
1641
  return runner_htmlspecialchars( $displayValue );
1642
  }
1643
  }
1644
+ =======
1645
+ <?php
1646
+ class LookupField extends EditControl
1647
+ {
1648
+ /**
1649
+ * Name of table which is lookup source
1650
+ * @var unknown_type
1651
+ */
1652
+ public $lookupTable = "";
1653
+ /**
1654
+ * Type of lookup source (db table, project table, etc.)
1655
+ * @var int
1656
+ */
1657
+ public $lookupType = 0;
1658
+ /**
1659
+ * Type of lookup control (Dropdown, List page with search, etc.)
1660
+ * @var int
1661
+ */
1662
+ public $LCType = 0;
1663
+
1664
+ /**
1665
+ * RunnerCipherer entity for lookup table
1666
+ * @var RunnerCipherer
1667
+ */
1668
+ public $ciphererLookup = null;
1669
+
1670
+ public $displayFieldName = "";
1671
+ public $linkFieldName = "";
1672
+ public $linkAndDisplaySame = false;
1673
+
1674
+ /*
1675
+ public $linkFieldIndex = 0;
1676
+ public $displayFieldIndex = 0;
1677
+ */
1678
+
1679
+ public $lookupSize = 1;
1680
+ public $multiple = "";
1681
+ public $postfix = "";
1682
+ public $alt = "";
1683
+
1684
+ public $clookupfield = "";
1685
+
1686
+ public $bUseCategory = false;
1687
+ public $horizontalLookup = false;
1688
+ public $addNewItem = false;
1689
+
1690
+ public $isLinkFieldEncrypted = false;
1691
+ public $isDisplayFieldEncrypted = false;
1692
+
1693
+ public $lookupPageType = "";
1694
+
1695
+ public $lookupPSet = null;
1696
+
1697
+ public $multiselect = false;
1698
+ public $lwLinkField = "";
1699
+ public $lwDisplayFieldWrapped = "";
1700
+ public $customDisplay = "";
1701
+ public $tName = "";
1702
+ private $displayFieldAlias = "";
1703
+
1704
+ /**
1705
+ * Generated lookup table aliases' array
1706
+ */
1707
+ protected $lookupTableAliases = array();
1708
+ /**
1709
+ * Generated link field aliases' array
1710
+ */
1711
+ protected $linkFieldAliases = array();
1712
+ /**
1713
+ * AbnGenerated displayed field aliases' array
1714
+ */
1715
+ protected $displayFieldAliases = array();
1716
+ /**
1717
+ * A flag indicating that search by displayed field is allowed
1718
+ * @type Boolean
1719
+ */
1720
+ protected $searchByDisplayedFieldIsAllowed = null;
1721
+
1722
+ protected $lookupDataSource;
1723
+
1724
+ function __construct($field, $pageObject, $id, $connection)
1725
+ {
1726
+ parent::__construct($field, $pageObject, $id, $connection);
1727
+
1728
+ $this->tName = $this->pageObject->tName;
1729
+ if($this->pageObject->tableBasedSearchPanelAdded)
1730
+ $this->tName = $this->pageObject->searchTableName;
1731
+
1732
+ $this->format = EDIT_FORMAT_TEXT_FIELD;
1733
+
1734
+ if($pageObject->pageType == PAGE_LIST || !$pageObject->isPageTableBased())
1735
+ $this->lookupPageType = PAGE_SEARCH;
1736
+ else
1737
+ $this->lookupPageType = $pageObject->pageType;
1738
+
1739
+ $this->lookupTable = $this->pageObject->pSetEdit->getLookupTable($this->field);
1740
+ $this->lookupType = $this->pageObject->pSetEdit->getLookupType($this->field);
1741
+ $this->lookupDataSource = getLookupDataSource( $this->field, $this->pageObject->pSetEdit );
1742
+
1743
+ if($this->lookupType == LT_QUERY) {
1744
+ $this->lookupPSet = new ProjectSettings($this->lookupTable);
1745
+ }
1746
+
1747
+ $this->displayFieldName = $this->pageObject->pSetEdit->getDisplayField($this->field);
1748
+ $this->linkFieldName = $this->pageObject->pSetEdit->getLinkField($this->field);
1749
+ $this->linkAndDisplaySame = $this->displayFieldName == $this->linkFieldName;
1750
+
1751
+ if($this->lookupType == LT_QUERY)
1752
+ $this->ciphererLookup = new RunnerCipherer($this->lookupTable);
1753
+
1754
+ $this->LCType = $this->pageObject->pSetEdit->lookupControlType($this->field);
1755
+
1756
+ $this->multiselect = $this->pageObject->pSetEdit->multiSelect($this->field);
1757
+ $this->customDisplay = $this->pageObject->pSetEdit->getCustomDisplay($this->field);
1758
+
1759
+
1760
+ // The number of rows in a multiline lookup
1761
+ $this->lookupSize = $this->pageObject->pSetEdit->selectSize($this->field);
1762
+ $this->bUseCategory = $this->pageObject->pSetEdit->useCategory($this->field);
1763
+ }
1764
+
1765
+
1766
+ /**
1767
+ * Create a CSS rule specifying the control's width
1768
+ * @param Number widthPx
1769
+ * @return String
1770
+ */
1771
+ function makeWidthStyle($widthPx)
1772
+ {
1773
+ if( $this->LCType !== LCT_DROPDOWN )
1774
+ return parent::makeWidthStyle( $widthPx );
1775
+
1776
+ if( 0 == $widthPx )
1777
+ return "";
1778
+
1779
+ return "width: ".( $widthPx + 7 )."px";
1780
+ }
1781
+
1782
+ /**
1783
+ * Add control JS files to page object
1784
+ */
1785
+ function addJSFiles()
1786
+ {
1787
+ if( $this->multiselect && ( $this->LCType == LCT_DROPDOWN && $this->lookupSize == 1 || $this->LCType == LCT_AJAX || $this->LCType == LCT_LIST ) )
1788
+ $this->pageObject->AddJSFile("include/chosen/chosen.jquery.js");
1789
+ }
1790
+
1791
+ /**
1792
+ * Add control CSS files to page object
1793
+ */
1794
+ function addCSSFiles()
1795
+ {
1796
+ if( $this->multiselect && ( $this->LCType == LCT_DROPDOWN && $this->lookupSize == 1 || $this->LCType == LCT_AJAX || $this->LCType == LCT_LIST ) )
1797
+ {
1798
+ $this->pageObject->AddCSSFile("include/chosen/bootstrap-chosen.css");
1799
+ }
1800
+ }
1801
+
1802
+ /**
1803
+ * This function need to bypass buildControl function of this class. It calls from LookupTextField class only.
1804
+ */
1805
+ function parentBuildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
1806
+ {
1807
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
1808
+ }
1809
+
1810
+ /**
1811
+ * Get the control's settings and build its HTML markup
1812
+ */
1813
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
1814
+ {
1815
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
1816
+
1817
+
1818
+ $this->alt = ($mode == MODE_INLINE_EDIT || $mode == MODE_INLINE_ADD) && $this->is508 ? ' alt="'.runner_htmlspecialchars($this->strLabel).'" ' : "";
1819
+
1820
+ $suffix = "_".GoodFieldName($this->field)."_".$this->id;
1821
+ $this->clookupfield = "display_value".($fieldNum ? $fieldNum : '').$suffix;
1822
+
1823
+ $this->cfield = "value".$suffix;
1824
+ $this->ctype = "type".$suffix;
1825
+ if($fieldNum)
1826
+ {
1827
+ $this->cfield = "value".$fieldNum.$suffix;
1828
+ $this->ctype = "type".$fieldNum.$suffix;
1829
+ }
1830
+
1831
+ if( $this->ciphererLookup )
1832
+ $this->isLinkFieldEncrypted = $this->ciphererLookup->isFieldPHPEncrypted( $this->linkFieldName );
1833
+
1834
+ $this->horizontalLookup = $this->pageObject->pSetEdit->isHorizontalLookup($this->field);
1835
+
1836
+ $this->addMainFieldsSettings();
1837
+
1838
+ // alter "add on the fly" settings
1839
+ $this->addNewItem = $this->isAllowToAdd( $mode );
1840
+
1841
+ // prepare multi-select attributes
1842
+ $this->multiple = $this->multiselect ? " multiple" : "";
1843
+ $this->postfix = $this->multiselect ? "[]" : "";
1844
+ if( $this->multiselect )
1845
+ $avalue = splitLookupValues($value);
1846
+ else
1847
+ $avalue = array((string)$value);
1848
+
1849
+ $searchOption = $additionalCtrlParams["option"];
1850
+
1851
+ // build the control
1852
+ if( $this->lookupType == LT_LISTOFVALUES )
1853
+ {
1854
+ $this->buildListOfValues($avalue, $value, $mode, $searchOption);
1855
+ }
1856
+ else
1857
+ {
1858
+ if( !$this->lookupDataSource ) {
1859
+ return;
1860
+ }
1861
+ // build a table-based lookup
1862
+ if( $this->ciphererLookup )
1863
+ $this->isDisplayFieldEncrypted = $this->ciphererLookup->isFieldPHPEncrypted( $this->displayFieldName );
1864
+
1865
+ if( $this->LCType == LCT_AJAX || $this->LCType == LCT_LIST )
1866
+ {
1867
+ $this->buildAJAXLookup($avalue, $value, $mode, $searchOption);
1868
+ }
1869
+ else
1870
+ {
1871
+ $this->buildClassicLookup($avalue, $value, $mode, $searchOption);
1872
+ }
1873
+ }
1874
+
1875
+ $this->buildControlEnd($validate, $mode);
1876
+ }
1877
+
1878
+ /**
1879
+ * // alter "add on the fly" settings
1880
+ * @param String mode
1881
+ * @return Boolean
1882
+ */
1883
+ protected function isAllowToAdd( $mode )
1884
+ {
1885
+ $addNewItem = false;
1886
+ $strPerm = GetUserPermissions($this->lookupTable);
1887
+ if( strpos($strPerm,"A") !== false && $this->LCType != LCT_LIST && $mode != MODE_SEARCH )
1888
+ {
1889
+ $addNewItem = $this->pageObject->pSetEdit->isAllowToAdd($this->field);
1890
+ $advancedadd = !$this->pageObject->pSetEdit->isSimpleAdd($this->field);
1891
+ if(!$advancedadd || $this->pageObject->pageType == PAGE_REGISTER)
1892
+ $addNewItem = false;
1893
+ }
1894
+
1895
+ return $addNewItem;
1896
+ }
1897
+
1898
+ /**
1899
+ *
1900
+ */
1901
+ protected function addMainFieldsSettings()
1902
+ {
1903
+ if( $this->pageObject->pSetEdit->isLookupWhereCode( $this->field ) )
1904
+ return;
1905
+
1906
+ $mainMasterFields = array();
1907
+ $mainFields = array();
1908
+
1909
+ $where = $this->pageObject->pSetEdit->getLookupWhere( $this->field );
1910
+ foreach( DB::readSQLTokens( $where ) as $token )
1911
+ {
1912
+ $prefix = "";
1913
+ $field = $token;
1914
+ $dotPos = strpos( $token, ".");
1915
+
1916
+ if( $dotPos !== FALSE )
1917
+ {
1918
+ $prefix = strtolower( substr( $token, 0, $dotPos ) );
1919
+ $field = substr( $token, $dotPos + 1 );
1920
+ }
1921
+
1922
+ if( $prefix == "master" )
1923
+ $mainMasterFields[] = $field;
1924
+ else if( !$prefix )
1925
+ $mainFields[] = $field;
1926
+ }
1927
+
1928
+ $this->addJSSetting( "mainFields", $mainFields );
1929
+ $this->addJSSetting( "mainMasterFields", $mainMasterFields );
1930
+ }
1931
+
1932
+ /**
1933
+ * Get indexes of link and display fields
1934
+ */
1935
+ /*
1936
+ public function fillLookupFieldsIndexes()
1937
+ {
1938
+ $lookupIndexes = GetLookupFieldsIndexes($this->pageObject->pSetEdit, $this->field);
1939
+ $this->linkFieldIndex = $lookupIndexes["linkFieldIndex"];
1940
+ $this->displayFieldIndex = $lookupIndexes["displayFieldIndex"];
1941
+ }
1942
+ */
1943
+
1944
+ /**
1945
+ * Build HTML markup fo the 'List of values' lookup field
1946
+ */
1947
+ public function buildListOfValues($avalue, $value, $mode, $searchOption)
1948
+ {
1949
+ // read lookup values
1950
+ $arr = $this->pageObject->pSetEdit->getLookupValues($this->field);
1951
+ $display_values = $arr;
1952
+
1953
+ if (in_array( $this->pageObject->pSetEdit->getViewFormat($this->field), array(FORMAT_DATE_SHORT, FORMAT_DATE_LONG, FORMAT_DATE_TIME)))
1954
+ {
1955
+ $container = new ViewControlsContainer($this->pageObject->pSetEdit, PAGE_LIST, null);
1956
+ foreach ( $arr as $key => $opt )
1957
+ {
1958
+ $data = array();
1959
+ $data[$this->field] = $opt;
1960
+ $display_values[$key] = $container->getControl($this->field)->getTextValue($data);
1961
+ }
1962
+ }
1963
+
1964
+ $dropDownHasSimpleBox = $this->LCType == LCT_DROPDOWN && !$this->multiselect && $mode == MODE_SEARCH;
1965
+ $optionContains = $dropDownHasSimpleBox && $this->isSearchOpitonForSimpleBox( $searchOption );
1966
+
1967
+ // print Type control to allow selecting nothing
1968
+ if( $this->multiselect )
1969
+ echo '<input id="'.$this->ctype.'" type="hidden" name="'.$this->ctype.'" value="multiselect">';
1970
+
1971
+ switch($this->LCType)
1972
+ {
1973
+ case LCT_DROPDOWN:
1974
+ $dataAttr = $selectClass = '';
1975
+ if( $dropDownHasSimpleBox )
1976
+ {
1977
+ $dataAttr = ' data-usesuggests="true"';
1978
+ $selectClass = $optionContains ? ' class="rnr-hiddenControlSubelem" ' : '';
1979
+ $simpleBoxClass = $optionContains ? '' : ' class="rnr-hiddenControlSubelem" ';
1980
+ $simpleBoxStyle = $this->getWidthStyleForAdditionalControl();
1981
+ echo '<input id="'.$this->cfield.'_simpleSearchBox" type="text" value="'.runner_htmlspecialchars($value).'" autocomplete="off"'.$simpleBoxClass.' '.$simpleBoxStyle.'>';
1982
+ }
1983
+
1984
+ echo '<select id="'.$this->cfield.'" size="'.$this->lookupSize.'" '.$dataAttr.$selectClass.' name="'.$this->cfield.$this->postfix.'" '
1985
+ .$this->multiple.' '.$this->inputStyle.'>';
1986
+ if( !$this->multiselect )
1987
+ echo '<option value="">'."Please select".'</option>';
1988
+ else if($mode == MODE_SEARCH)
1989
+ echo '<option value=""> </option>';
1990
+
1991
+ foreach($arr as $key => $opt)
1992
+ {
1993
+ $res = array_search((string)$opt, $avalue);
1994
+ if( $res !== FALSE )
1995
+ echo '<option value="'.runner_htmlspecialchars($opt).'" selected>'.runner_htmlspecialchars($display_values[$key]).'</option>';
1996
+ else
1997
+ echo '<option value="'.runner_htmlspecialchars($opt).'">'.runner_htmlspecialchars($display_values[$key]).'</option>';
1998
+ }
1999
+ echo "</select>";
2000
+ break;
2001
+
2002
+ case LCT_CBLIST:
2003
+ echo '<div data-lookup-options class="'. ( $this->horizontalLookup ? 'rnr-horizontal-lookup' : 'rnr-vertical-lookup' ).'">';
2004
+ $spacer = '<br/>';
2005
+ if($this->horizontalLookup)
2006
+ $spacer = '&nbsp;&nbsp;';
2007
+ $i = 0;
2008
+ foreach($arr as $key => $opt)
2009
+ {
2010
+ echo '<span class="checkbox"><label>';
2011
+ echo '<input id="'.$this->cfield.'_'.$i.'" class="rnr-checkbox" type="checkbox" '.$this->alt.' name="'.$this->cfield.$this->postfix.'" value="'
2012
+ .runner_htmlspecialchars($opt).'"';
2013
+ $res = array_search((string)$opt, $avalue);
2014
+ if( $res !== FALSE )
2015
+ echo ' checked="checked" ';
2016
+ echo '/>';
2017
+
2018
+ echo '&nbsp;<span class="rnr-checkbox-label" id="data_'.$this->cfield.'_'.$i.'">'.runner_htmlspecialchars($display_values[$key]).'</span>'.$spacer;
2019
+ echo '</label></span>';
2020
+ $i++;
2021
+ }
2022
+ echo '</div>';
2023
+ break;
2024
+
2025
+ case LCT_RADIO:
2026
+ // $spacer = $this->horizontalLookup ? "&nbsp;&nbsp;" : "<br/>";
2027
+ echo '<div data-lookup-options class="'. ( $this->horizontalLookup ? 'rnr-horizontal-lookup' : 'rnr-vertical-lookup' ).'">';
2028
+ echo '<input id="'.$this->cfield.'" type="hidden" name="'.$this->cfield.'" value="'.runner_htmlspecialchars($value).'">';
2029
+ $i = 0;
2030
+ foreach($arr as $key => $opt)
2031
+ {
2032
+ $checked = "";
2033
+ if($opt == $value)
2034
+ $checked = ' checked="checked" ';
2035
+ echo '<span class="radio"><label>';
2036
+ echo '<input type="Radio" class="rnr-radio-button" id="radio_'.$this->cfieldname.'_'.$i.'" '
2037
+ .$this->alt.' name="radio_'.$this->cfieldname.'" '.$checked.' value="'.runner_htmlspecialchars($opt).'">'
2038
+ .' <span id="label_radio_'.$this->cfieldname.'_'.$i.'" class="rnr-radio-label">'
2039
+ .runner_htmlspecialchars($display_values[$key]).'</span >';
2040
+ echo '</label></span>';
2041
+ $i++;
2042
+ }
2043
+ echo '</div>';
2044
+ break;
2045
+ }
2046
+ }
2047
+
2048
+ /**
2049
+ * Build the markup for the 'Edit box with AJAX popup' or 'List page with search' lookup field
2050
+ * @param Array avalue An array of the control values
2051
+ * @param String value A control's value string representation
2052
+ * @param String mode The control's mode (MODE_INLINE_EDIT, MODE_INLINE_ADD)
2053
+ * @param String searchOption The control's search option
2054
+ */
2055
+ public function buildAJAXLookup($avalue, $value, $mode, $searchOption)
2056
+ {
2057
+ if( $this->multiselect )
2058
+ {
2059
+ $this->buildMultiselectAJAXLookup($avalue, $value, $mode, $searchOption);
2060
+ return;
2061
+ }
2062
+
2063
+
2064
+ $listSearchHasSimpleBox = $mode == MODE_SEARCH && $this->isAdditionalControlRequired();
2065
+ $optionContains = $this->isSearchOpitonForSimpleBox( $searchOption );
2066
+ $listOptionContains = $listSearchHasSimpleBox && $optionContains;
2067
+ $dataAttr = '';
2068
+
2069
+
2070
+ if( $this->LCType == LCT_LIST )
2071
+ {
2072
+ $dataAttr = $listSearchHasSimpleBox ? ' data-usesuggests="true"' : '';
2073
+ }
2074
+ else if( $this->LCType == LCT_AJAX && $optionContains )
2075
+ {
2076
+ $dataAttr = ' data-simple-search-mode="true" ';
2077
+ }
2078
+
2079
+ if($this->bUseCategory)
2080
+ {
2081
+ $valueAttr = '';
2082
+ if( $this->LCType == LCT_AJAX && $optionContains || $this->LCType == LCT_LIST && $listOptionContains )
2083
+ $valueAttr = ' value="'.runner_htmlspecialchars($value).'"';
2084
+
2085
+ // dependent ajax-lookup control
2086
+ $inputParams = '" '.$this->getPlaceholderAttr().' autocomplete="off" id="'.$this->clookupfield.'" '.$valueAttr.' name="'.$this->clookupfield.'" '.$this->inputStyle;
2087
+ $inputParams.= $this->LCType == LCT_LIST && !$listOptionContains ? 'readonly': '';
2088
+ echo '<input type="text" '.$inputParams.'>';
2089
+
2090
+ echo '<input type="hidden" id="'.$this->cfield.'" '.$valueAttr.' name="'.$this->cfield.'"'.$dataAttr.'>';
2091
+
2092
+ echo $this->getLookupLinks( $listOptionContains );
2093
+ return;
2094
+ }
2095
+
2096
+ // get the initial value
2097
+ $lookup_value = "";
2098
+ $lookupDc = $this->getLookupDataCommand( array(), $value, false, true );
2099
+
2100
+ $qResult = $this->lookupDataSource->getList( $lookupDc );
2101
+ if( !$qResult ) {
2102
+ showError( $this->lookupDataSource->lastError() );
2103
+ }
2104
+
2105
+ if( $data = $qResult->fetchAssoc() )
2106
+ {
2107
+ if($this->isDisplayFieldEncrypted)
2108
+ $lookup_value = $this->ciphererLookup->DecryptField( $this->displayFieldName , $data[ $this->displayFieldAlias ]);
2109
+ else
2110
+ $lookup_value = $data[ $this->displayFieldAlias ];
2111
+ }
2112
+ elseif( $this->pageObject->pSetEdit->isLookupWhereSet( $this->field ) )
2113
+ {
2114
+ // try w/o WHERE expression
2115
+ $lookupDc = $this->getLookupDataCommand( array(), $value, false, true, false );
2116
+ $qResult = $this->lookupDataSource->getList( $lookupDc );
2117
+ if( !$qResult ) {
2118
+ showError( $this->lookupDataSource->lastError() );
2119
+ }
2120
+ if( $data = $qResult->fetchAssoc() )
2121
+ {
2122
+ if($this->isDisplayFieldEncrypted)
2123
+ $lookup_value = $this->ciphererLookup->DecryptField( $this->displayFieldName , $data[ $this->displayFieldAlias ]);
2124
+ else
2125
+ $lookup_value = $data[ $this->displayFieldAlias ];
2126
+ }
2127
+ }
2128
+
2129
+ // build the regular ajax-lookup control
2130
+ if( $this->LCType == LCT_AJAX && !strlen($lookup_value) && ($this->pageObject->pSetEdit->isfreeInput($this->field) || $this->lookupPageType == PAGE_SEARCH)
2131
+ || $this->LCType == LCT_LIST && $listOptionContains )
2132
+ {
2133
+ $lookup_value = $value;
2134
+ }
2135
+
2136
+ if ( in_array( $this->pageObject->pSetEdit->getViewFormat($this->field), array(FORMAT_DATE_SHORT, FORMAT_DATE_LONG, FORMAT_DATE_TIME) ) )
2137
+ {
2138
+ $container = new ViewControlsContainer($this->pageObject->pSetEdit, PAGE_LIST, null);
2139
+
2140
+ $ctrlData = array();
2141
+ $ctrlData[ $this->field ] = $lookup_value;
2142
+ $lookup_value = $container->getControl( $this->field )->getTextValue( $ctrlData );
2143
+ }
2144
+
2145
+ $inputParams = 'autocomplete="off" '.$this->getPlaceholderAttr().' id="'.$this->clookupfield.'" name="'.$this->clookupfield.'" '.$this->inputStyle.$this->alt;
2146
+ $inputParams.= ' value="'.runner_htmlspecialchars($lookup_value).'"';;
2147
+
2148
+ if( $this->LCType == LCT_LIST && !$listOptionContains )
2149
+ $inputParams.= ' readonly ';
2150
+
2151
+ if( $this->LCType == LCT_LIST && !$this->pageObject->pSetEdit->isRequired($this->field))
2152
+ $inputParams.= ' class="clearable" ';
2153
+
2154
+ $inputTag = '<input type="text" '.$inputParams.'>';
2155
+ if ( $this->LCType == LCT_LIST )
2156
+ {
2157
+ echo '<span class="bs-list-lookup">'.$inputTag.'</span>';
2158
+ }
2159
+ else
2160
+ {
2161
+ echo $inputTag;
2162
+ }
2163
+
2164
+ echo '<input type="hidden" id="'.$this->cfield.'" name="'.$this->cfield.'" value="'.runner_htmlspecialchars($value).'"'.$dataAttr.'>';
2165
+
2166
+ echo $this->getLookupLinks( $listOptionContains );
2167
+ }
2168
+
2169
+ /**
2170
+ * Build a multiselect control html markup to apply JS 'chosen' plugin
2171
+ * @param Array avalue An array of the control values
2172
+ * @param String value A control's value string representation
2173
+ * @param String mode The control's mode (MODE_INLINE_EDIT, MODE_INLINE_ADD)
2174
+ * @param String searchOption The control's search option
2175
+ */
2176
+ protected function buildMultiselectAJAXLookup($avalue, $value, $mode, $searchOption)
2177
+ {
2178
+ echo '<select '.$this->getPlaceholderAttr().' '.$this->multiple.' id="'.$this->cfield.'" name="'.$this->cfield.$this->postfix.'" '.$this->inputStyle.$this->alt.'>';
2179
+
2180
+ if( !$this->bUseCategory && strlen($value) )
2181
+ $this->buildMultiselectAJAXLookupRows($avalue, $value, $mode, $searchOption);
2182
+
2183
+ echo '</select>';
2184
+
2185
+ echo $this->getLookupLinks();
2186
+ }
2187
+
2188
+ /**
2189
+ * Build the control's 'option' elements. If the link and displayed fields are not the same
2190
+ * a db query is used to retrieve displayed values corresponding to the link values ($avalue)
2191
+ * @param Array avalue An array of the control values
2192
+ * @param String value A control's value string representation
2193
+ * @param String mode The control's mode (MODE_INLINE_EDIT, MODE_INLINE_ADD)
2194
+ * @param String searchOption The control's search option
2195
+ */
2196
+ protected function buildMultiselectAJAXLookupRows($avalue, $value, $mode, $searchOption)
2197
+ {
2198
+ //$this->fillLookupFieldsIndexes();
2199
+
2200
+ if( $this->linkAndDisplaySame || $this->lookupPageType == PAGE_SEARCH )
2201
+ {
2202
+ $this->displayFieldAlias = $this->displayFieldName;
2203
+ foreach($avalue as $mKey => $mValue)
2204
+ {
2205
+ $data = array();
2206
+ $data[ $this->linkFieldName ] = $mValue;
2207
+ $data[ $this->displayFieldAlias ] = $mValue;
2208
+
2209
+ $this->buildLookupRow( $mode, $data, ' selected', $mKey );
2210
+ }
2211
+ return;
2212
+ }
2213
+
2214
+ $lookupDc = $this->getLookupDataCommand( array(), $value, false, true );
2215
+ $qResult = $this->lookupDataSource->getList( $lookupDc );
2216
+ if( !$qResult ) {
2217
+ showError( $this->lookupDataSource->lastError() );
2218
+ }
2219
+
2220
+ $options = 0;
2221
+ while( $data = $qResult->fetchAssoc() )
2222
+ {
2223
+ $this->decryptDataRow( $data );
2224
+ if( array_search( $data[ $this->linkFieldName ], $avalue ) !== FALSE )
2225
+ {
2226
+ $this->buildLookupRow( $mode, $data, ' selected', $options );
2227
+ $options++;
2228
+ }
2229
+ }
2230
+
2231
+ // try the same query w/o WHERE clause if options were not found
2232
+ if( $options == 0 && strlen($value) && $mode == MODE_EDIT && $this->pageObject->pSetEdit->isLookupWhereSet( $this->field ) )
2233
+ {
2234
+ //one record mode true
2235
+ $lookupDc = $this->getLookupDataCommand( array(), $value, false, true, false, true );
2236
+ $qResult = $this->lookupDataSource->getList( $lookupDc );
2237
+
2238
+ if( $data = $qResult->fetchAssoc() )
2239
+ {
2240
+ $this->decryptDataRow( $data );
2241
+ $this->buildLookupRow( $mode, $data, ' selected', $options );
2242
+ }
2243
+ }
2244
+ }
2245
+
2246
+ /**
2247
+ * Build HTML markup for the 'dropdown box', 'checkbox list' or 'radio button' lookup field
2248
+ * @param Array avalue
2249
+ * @param String value
2250
+ * @param String mode
2251
+ * @param String searchOption
2252
+ */
2253
+ public function buildClassicLookup($avalue, $value, $mode, $searchOption)
2254
+ {
2255
+ $dropDownHasSimpleBox = $this->LCType == LCT_DROPDOWN && $mode == MODE_SEARCH && $this->isAdditionalControlRequired();
2256
+ $optionContains = $dropDownHasSimpleBox && $this->isSearchOpitonForSimpleBox( $searchOption );
2257
+
2258
+ if( $this->multiselect ) // print Type control to allow selecting nothing
2259
+ echo '<input id="'.$this->ctype.'" type="hidden" name="'.$this->ctype.'" value="multiselect">';
2260
+
2261
+ if($this->bUseCategory)
2262
+ {
2263
+ // dependent classic lookup
2264
+ switch ($this->LCType)
2265
+ {
2266
+ case LCT_CBLIST:
2267
+ echo '<div data-lookup-options>';
2268
+ echo '<input id="'.$this->cfield.'" type="checkbox" name="'.$this->cfield.'" style="display:none;">';
2269
+ echo '</div>';
2270
+ break;
2271
+
2272
+ case LCT_RADIO:
2273
+ echo '<input id="'.$this->cfield.'" type="hidden" name="'.$this->cfield.'" value="'.runner_htmlspecialchars($value).'">';
2274
+ echo '<div data-lookup-options>';
2275
+ echo '</div>';
2276
+ break;
2277
+
2278
+ case LCT_DROPDOWN:
2279
+ $dataAttr = '';
2280
+ $selectClass = 'form-control';
2281
+ $simpleBoxClass = 'form-control';
2282
+ if( $dropDownHasSimpleBox )
2283
+ {
2284
+ $dataAttr = ' data-usesuggests="true"';
2285
+ $selectClass .= $optionContains ? ' rnr-hiddenControlSubelem' : '';
2286
+ $simpleBoxClass .= $optionContains ? '' : ' rnr-hiddenControlSubelem';
2287
+ $simpleBoxStyle = '';
2288
+ echo '<input id="'.$this->cfield.'_simpleSearchBox" type="text" value="'.runner_htmlspecialchars($value).'" autocomplete="off" class="'.$simpleBoxClass.'" '.$simpleBoxStyle.'>';
2289
+ }
2290
+
2291
+ echo '<select size="'.$this->lookupSize.'" id="'.$this->cfield.'" name="'.$this->cfield.$this->postfix.'" class="'.$selectClass.'" '.$dataAttr.
2292
+ $this->multiple.' '.$this->inputStyle.'>';
2293
+ echo '<option value="">'."Please select".'</option>';
2294
+ echo '</select>';
2295
+ break;
2296
+ }
2297
+
2298
+ echo $this->getLookupLinks();
2299
+ return;
2300
+ }
2301
+
2302
+ $lookupDc = $this->getLookupDataCommand( array(), "", false );
2303
+ $qResult = $this->lookupDataSource->getList( $lookupDc );
2304
+ if( !$qResult ) {
2305
+ showError( $this->lookupDataSource->lastError() );
2306
+ }
2307
+
2308
+ // simple classic lookup
2309
+ if($this->LCType == LCT_DROPDOWN)
2310
+ {
2311
+ $dataAttr = '';
2312
+ $selectClass = 'form-control';
2313
+ $simpleBoxClass = 'form-control';
2314
+
2315
+ if( $dropDownHasSimpleBox )
2316
+ {
2317
+ $dataAttr = ' data-usesuggests="true"';
2318
+ $selectClass .= $optionContains ? ' rnr-hiddenControlSubelem' : '';
2319
+ $simpleBoxClass .= $optionContains ? '' : ' rnr-hiddenControlSubelem';
2320
+ $simpleBoxStyle = '';
2321
+ echo '<input id="'.$this->cfield.'_simpleSearchBox" type="text" value="'.runner_htmlspecialchars($value).'" autocomplete="off" class="'.$simpleBoxClass.'" '.$simpleBoxStyle.'>';
2322
+ }
2323
+
2324
+ echo '<select size="'.$this->lookupSize.'" id="'.$this->cfield.'" '
2325
+ .$this->alt.' name="'.$this->cfield.$this->postfix.'"'.$dataAttr.' class="'.$selectClass.'" '.$this->multiple.' '.$this->inputStyle.'>';
2326
+ if( !$this->multiselect )
2327
+ echo '<option value="">'."Please select".'</option>';
2328
+ else if($mode == MODE_SEARCH)
2329
+ echo '<option value=""> </option>';
2330
+ }
2331
+ else
2332
+ {
2333
+ if($this->LCType == LCT_RADIO)
2334
+ echo '<input id="'.$this->cfield.'" type="hidden" name="'.$this->cfield.'" value="'.runner_htmlspecialchars($value).'">';
2335
+
2336
+ echo '<div data-lookup-options class="'. ( $this->horizontalLookup ? 'rnr-horizontal-lookup' : 'rnr-vertical-lookup' ).'">';
2337
+ }
2338
+
2339
+ // print lookup data
2340
+ $found = false;
2341
+ $i = 0;
2342
+ $isLookupUnique = $this->lookupType == LT_QUERY && $this->pageObject->pSetEdit->isLookupUnique($this->field);
2343
+ $uniqueArray = array();
2344
+ while( $data = $qResult->fetchAssoc() )
2345
+ {
2346
+ $this->decryptDataRow( $data );
2347
+ $linkValue = $data[ $this->linkFieldName ];
2348
+ if($isLookupUnique)
2349
+ {
2350
+ if( in_array( $linkValue, $uniqueArray) )
2351
+ continue;
2352
+ $uniqueArray[] = $linkValue;
2353
+ }
2354
+
2355
+ $res = array_search( (string) $linkValue, $avalue );
2356
+ $checked = "";
2357
+ if( $res !== FALSE )
2358
+ {
2359
+ $found = true;
2360
+ $checked = $this->LCType == LCT_CBLIST || $this->LCType == LCT_RADIO ? ' checked="checked"' : ' selected';
2361
+ }
2362
+ $this->buildLookupRow($mode, $data, $checked, $i);
2363
+ $i++;
2364
+ }
2365
+
2366
+ // try the same query w/o WHERE clause if current value not found
2367
+ if(!$found && strlen($value) && $mode == MODE_EDIT && $this->pageObject->pSetEdit->isLookupWhereSet( $this->field ) )
2368
+ {
2369
+ $lookupDc = $this->getLookupDataCommand( array(), $value, false, true, false, true );
2370
+ $qResult = $this->lookupDataSource->getList( $lookupDc );
2371
+ if( !$qResult ) {
2372
+ showError( $this->lookupDataSource->lastError() );
2373
+ }
2374
+ if( $data = $qResult->fetchAssoc() )
2375
+ {
2376
+ $this->decryptDataRow($data);
2377
+ $checked = $this->LCType == LCT_CBLIST || $this->LCType == LCT_RADIO ? ' checked="checked"' : ' selected';
2378
+ $this->buildLookupRow($mode, $data, $checked, $i);
2379
+ }
2380
+ }
2381
+
2382
+ // print footer
2383
+ $footer = $this->LCType == LCT_DROPDOWN ? '</select>' : '</div>';
2384
+ echo $footer;
2385
+
2386
+ echo $this->getLookupLinks();
2387
+ }
2388
+
2389
+ /**
2390
+ * @param &Array data
2391
+ */
2392
+ public function decryptDataRow(&$data)
2393
+ {
2394
+ if($this->isLinkFieldEncrypted)
2395
+ $data[$this->linkFieldName] = $this->ciphererLookup->DecryptField( $this->linkFieldName, $data[$this->linkFieldName] );
2396
+ if($this->isDisplayFieldEncrypted)
2397
+ $data[$this->displayFieldAlias] = $this->ciphererLookup->DecryptField( $this->displayFieldName, $data[$this->displayFieldAlias] );
2398
+ }
2399
+
2400
+ /**
2401
+ * Build HTML markup for a lookup item
2402
+ * @param String mode
2403
+ * @param Array data
2404
+ * @param String checked
2405
+ * @param Number i
2406
+ * @return String
2407
+ */
2408
+ public function buildLookupRow($mode, $data, $checked, $i)
2409
+ {
2410
+ $display_value = $data[ $this->displayFieldAlias ];
2411
+ $link_value = $data[ $this->linkFieldName ];
2412
+
2413
+ if( in_array( $this->pageObject->pSetEdit->getViewFormat($this->field), array(FORMAT_DATE_SHORT, FORMAT_DATE_LONG, FORMAT_DATE_TIME) ) )
2414
+ {
2415
+ $container = new ViewControlsContainer($this->pageObject->pSetEdit, PAGE_LIST, null);
2416
+
2417
+ $ctrlData = array();
2418
+
2419
+ $ctrlData[ $this->field ] = $link_value;
2420
+
2421
+ $display_value = $container->getControl( $this->field )->getTextValue( $ctrlData );
2422
+ }
2423
+
2424
+ $render_value = $this->getLookupTextValue( $display_value );
2425
+
2426
+ switch($this->LCType)
2427
+ {
2428
+ case LCT_DROPDOWN:
2429
+ case LCT_LIST:
2430
+ case LCT_AJAX:
2431
+ echo '<option value="'.runner_htmlspecialchars($data[ $this->linkFieldName ]).'"'.$checked.'>'
2432
+ .$render_value.'</option>';
2433
+ break;
2434
+
2435
+ case LCT_CBLIST:
2436
+ echo '<span class="checkbox"><label>'
2437
+ .'<input id="'.$this->cfield.'_'.$i.'" class="rnr-checkbox" type="checkbox" '.$this->alt.' name="'.$this->cfield.$this->postfix
2438
+ .'" value="'.runner_htmlspecialchars( $link_value ).'"'.$checked.'/>&nbsp;'
2439
+ .'<span class="rnr-checkbox-label" id="data_'.$this->cfield.'_'.$i.'">'
2440
+ .$render_value
2441
+ .'</span>'
2442
+ .'</label></span>';
2443
+ break;
2444
+
2445
+ case LCT_RADIO:
2446
+ echo '<span class="radio"><label>'
2447
+ .'<input type="Radio" class="rnr-radio-button" id="radio_'.$this->cfieldname.'_'.$i.'" '
2448
+ .$this->alt.' name="radio_'.$this->cfieldname.'" '.$checked.' value="'.runner_htmlspecialchars( $link_value ).'">'
2449
+ .' <span id="label_radio_'.$this->cfieldname.'_'.$i.'" class="rnr-radio-label">'
2450
+ .$render_value
2451
+ .'</span>'
2452
+ .'</label></span>';
2453
+ break;
2454
+ }
2455
+ }
2456
+
2457
+ function getFirstElementId()
2458
+ {
2459
+ switch($this->LCType)
2460
+ {
2461
+ case LCT_AJAX:
2462
+ return "display_value_" . $this->goodFieldName . "_" . $this->id;
2463
+ break;
2464
+ default:
2465
+ return $this->cfield;
2466
+ break;
2467
+ }
2468
+ }
2469
+
2470
+ /**
2471
+ * Check if a simple search box should be displayed
2472
+ * for a particular search options
2473
+ * @param String searchOption
2474
+ * @return Boolean
2475
+ */
2476
+ public function isSearchOpitonForSimpleBox( $searchOption )
2477
+ {
2478
+ if( $searchOption == 'Contains' || $searchOption == 'Starts with' )
2479
+ return true;
2480
+
2481
+ if( $searchOption != '' )
2482
+ return false;
2483
+
2484
+ $userSearchOptions = $this->pageObject->pSetEdit->getSearchOptionsList( $this->field );
2485
+ return !($userSearchOptions) || in_array('Contains', $userSearchOptions) || in_array('Starts with', $userSearchOptions);
2486
+ }
2487
+
2488
+ /**
2489
+ * Check if an additional simple search box control should be added to
2490
+ * the ordinary control's markup
2491
+ * @return Boolean
2492
+ */
2493
+ protected function isAdditionalControlRequired()
2494
+ {
2495
+ if( $this->multiselect )
2496
+ return false;
2497
+
2498
+ $hostPageType = $this->pageObject->pSetEdit->getTableType();
2499
+ if( $hostPageType == "report" || $hostPageType == "chart" )
2500
+ return false;
2501
+
2502
+ $userSearchOptions = $this->pageObject->pSetEdit->getSearchOptionsList( $this->field );
2503
+ if( !!$userSearchOptions && !in_array('Contains', $userSearchOptions) && !in_array('Starts with', $userSearchOptions) )
2504
+ return false;
2505
+
2506
+ if( $this->lookupType == LT_LISTOFVALUES || $this->linkAndDisplaySame )
2507
+ return true;
2508
+
2509
+ // #9875 connection and lookupConnection props must be the same
2510
+ if( $this->connection->connId != $this->lookupDataSource->getConnectionId() )
2511
+ return false;
2512
+
2513
+ if( !$this->connection->checkIfJoinSubqueriesOptimized() && $this->LCType == LCT_LIST )
2514
+ return false;
2515
+
2516
+ return $this->isLookupSQLquerySimple() && $this->isMainTableSQLquerySimple();
2517
+ }
2518
+
2519
+ /**
2520
+ * Get the additional control element's style attribute string
2521
+ * @return String
2522
+ */
2523
+ protected function getWidthStyleForAdditionalControl()
2524
+ {
2525
+ $width = $this->searchPanelControl ? 150 : $this->pageObject->pSetEdit->getControlWidth( $this->field );
2526
+ //$style = parent::makeWidthStyle( $width );
2527
+
2528
+ return 'style="'.$style.'"';
2529
+ }
2530
+
2531
+ /**
2532
+ * Check if the lookup table doesn't have encription and its SQL query doesn't have HAVING,
2533
+ * ORDER BY clauses and FROM clause with subqueries. #8564
2534
+ * @return Boolean
2535
+ */
2536
+ protected function isLookupSQLquerySimple()
2537
+ {
2538
+ $lookupConnection = $this->lookupDataSource->getConnection();
2539
+ if( $lookupConnection->dbType == nDATABASE_DB2 || $lookupConnection->dbType == nDATABASE_Informix || $lookupConnection->dbType == nDATABASE_SQLite3 )
2540
+ return false;
2541
+
2542
+ if( $this->lookupType == LT_LOOKUPTABLE || $this->lookupType == LT_LISTOFVALUES )
2543
+ return true;
2544
+
2545
+ // encription is turned on
2546
+ if( $this->lookupPSet->hasEncryptedFields() )
2547
+ return false;
2548
+
2549
+ $lookupSqlQuery = $this->lookupPSet->getSQLQuery();
2550
+
2551
+ if( !$lookupSqlQuery ) {
2552
+ return false;
2553
+ }
2554
+
2555
+ if( $lookupSqlQuery->HasGroupBy() || $lookupSqlQuery->HavingToSql() != "" || $lookupSqlQuery->HasSubQueryInFromClause() )
2556
+ return false;
2557
+
2558
+ if( $lookupConnection->dbType != nDATABASE_MySQL )
2559
+ {
2560
+ $linkFieldType = $this->lookupPSet->getFieldType( $this->linkFieldName );
2561
+ if( !(IsNumberType($this->type) && IsNumberType($linkFieldType) || IsCharType($this->type) && IsCharType($linkFieldType) || IsDateFieldType($this->type) && IsDateFieldType($linkFieldType)) )
2562
+ return false;
2563
+ }
2564
+ return true;
2565
+ }
2566
+
2567
+ /**
2568
+ * Check if the main table doesn't have encryption and its SQL query doesn't have HAVING,
2569
+ * ORDER BY clauses and FROM clause with sub-queries. #8564
2570
+ * @return Boolean
2571
+ */
2572
+ protected function isMainTableSQLquerySimple()
2573
+ {
2574
+ if( $this->connection->dbType != nDATABASE_MySQL
2575
+ && $this->connection->dbType != nDATABASE_MSSQLServer
2576
+ && $this->connection->dbType != nDATABASE_Oracle
2577
+ && $this->connection->dbType != nDATABASE_PostgreSQL )
2578
+ return false;
2579
+
2580
+ // encription is turned on
2581
+ if( $this->pageObject->pSetEdit->hasEncryptedFields() )
2582
+ return false;
2583
+
2584
+ $sqlQuery = $this->pageObject->pSetEdit->getSQLQueryByField( $this->field );
2585
+
2586
+ if( !$sqlQuery ) {
2587
+ return false;
2588
+ }
2589
+
2590
+ if( $sqlQuery->HasGroupBy() || $sqlQuery->HavingToSql() != "" || $sqlQuery->HasSubQueryInFromClause() )
2591
+ return false;
2592
+
2593
+ return true;
2594
+ }
2595
+
2596
+ /**
2597
+ * Check if searching by displayed field is allowed
2598
+ * @return Boolean
2599
+ */
2600
+ protected function isSearchByDispalyedFieldAllowed()
2601
+ {
2602
+ if ( !is_null( $this->searchByDisplayedFieldIsAllowed ) )
2603
+ return $this->searchByDisplayedFieldIsAllowed;
2604
+
2605
+ // #9875 connection and lookupConnection props must be the same
2606
+ if( !$this->lookupDataSource ) {
2607
+ $this->searchByDisplayedFieldIsAllowed = false;
2608
+ return $this->searchByDisplayedFieldIsAllowed;
2609
+ }
2610
+ if( $this->connection->connId != $this->lookupDataSource->getConnectionId() )
2611
+ {
2612
+ $this->searchByDisplayedFieldIsAllowed = false;
2613
+ return $this->searchByDisplayedFieldIsAllowed;
2614
+ }
2615
+
2616
+ if( !$this->connection->checkIfJoinSubqueriesOptimized() && ( $this->LCType == LCT_LIST || $this->LCType == LCT_AJAX ) )
2617
+ {
2618
+ $this->searchByDisplayedFieldIsAllowed = false;
2619
+ return $this->searchByDisplayedFieldIsAllowed;
2620
+ }
2621
+
2622
+ $hostPageType = $this->pageObject->pSetEdit->getTableType();
2623
+
2624
+ $this->searchByDisplayedFieldIsAllowed = $hostPageType != "report" && $hostPageType != "chart" && !$this->linkAndDisplaySame
2625
+ && !$this->multiselect && ( $this->LCType == LCT_LIST || $this->LCType == LCT_DROPDOWN || $this->LCType == LCT_AJAX )
2626
+ && $this->lookupType != LT_LISTOFVALUES && $this->isLookupSQLquerySimple() && $this->isMainTableSQLquerySimple();
2627
+
2628
+ return $this->searchByDisplayedFieldIsAllowed;
2629
+ }
2630
+
2631
+
2632
+ /**
2633
+ * @param String strSearchOption
2634
+ * @return Boolean
2635
+ */
2636
+ public function checkIfDisplayFieldSearch( $strSearchOption )
2637
+ {
2638
+ return $this->isSearchByDispalyedFieldAllowed() && ( $strSearchOption === "Starts with" || $strSearchOption === "Contains" );
2639
+ }
2640
+
2641
+ /**
2642
+ * Get the substitute columns list for the SELECT Clause and the FORM clause part
2643
+ * that will be joined to the basic page's FROM clause
2644
+ * @param String searchFor
2645
+ * @param String searchOpt
2646
+ * @param Boolean isSuggest
2647
+ * @return Array
2648
+ */
2649
+ public function getSelectColumnsAndJoinFromPart($searchFor, $searchOpt, $isSuggest)
2650
+ {
2651
+ if( !$isSuggest || !$this->isSearchByDispalyedFieldAllowed() )
2652
+ return parent::getSelectColumnsAndJoinFromPart($searchFor, $searchOpt, $isSuggest);
2653
+
2654
+ $this->initializeLookupTableAliases();
2655
+
2656
+ return array(
2657
+ "selectColumns"=> $this->getSelectColumns( $isSuggest ),
2658
+ "joinFromPart"=> $this->getFromClauseJoinPart( $searchFor, $searchOpt, $isSuggest)
2659
+ );
2660
+ }
2661
+
2662
+ /**
2663
+ * Form the control specified search options array and built the control's search options markup
2664
+ * @param String selOpt The search option value
2665
+ * @param Boolean not It indicates if the search option negation is set
2666
+ * @param Boolean both It indicates if the control needs 'NOT'-options
2667
+ * @return String A string containing options markup
2668
+ */
2669
+ function getSearchOptions($selOpt, $not, $both)
2670
+ {
2671
+ $optionsArray = array();
2672
+ if ($this->multiselect)
2673
+ $optionsArray[] = CONTAINS;
2674
+ else
2675
+ {
2676
+ if($this->lookupType == LT_QUERY)
2677
+ $this->ciphererLookup = new RunnerCipherer($this->lookupTable);
2678
+
2679
+ if( $this->ciphererLookup )
2680
+ $this->isDisplayFieldEncrypted = $this->ciphererLookup->isFieldPHPEncrypted( $this->displayFieldName );
2681
+
2682
+ if($this->LCType == LCT_AJAX && !$this->isDisplayFieldEncrypted)
2683
+ {
2684
+ if( $this->isSearchByDispalyedFieldAllowed() || $this->linkAndDisplaySame )
2685
+ {
2686
+ $optionsArray[] = CONTAINS;
2687
+ $optionsArray[] = STARTS_WITH;
2688
+ }
2689
+ $optionsArray[] = MORE_THAN;
2690
+ $optionsArray[] = LESS_THAN;
2691
+ $optionsArray[] = BETWEEN;
2692
+ }
2693
+
2694
+ if( ($this->LCType == LCT_LIST || $this->LCType == LCT_DROPDOWN) && $this->isAdditionalControlRequired() )
2695
+ {
2696
+ $optionsArray[] = CONTAINS;
2697
+ $optionsArray[] = STARTS_WITH;
2698
+ }
2699
+ }
2700
+ $optionsArray[] = EQUALS;
2701
+ $optionsArray[] = EMPTY_SEARCH;
2702
+
2703
+ if($both)
2704
+ {
2705
+ if ($this->multiselect)
2706
+ $optionsArray[] = NOT_CONTAINS;
2707
+ else
2708
+ {
2709
+ if($this->LCType == LCT_AJAX && !$this->isDisplayFieldEncrypted)
2710
+ {
2711
+ if( $this->isSearchByDispalyedFieldAllowed() || $this->linkAndDisplaySame )
2712
+ {
2713
+ $optionsArray[] = NOT_CONTAINS;
2714
+ $optionsArray[] = NOT_STARTS_WITH;
2715
+ }
2716
+ $optionsArray[] = NOT_MORE_THAN;
2717
+ $optionsArray[] = NOT_LESS_THAN;
2718
+ $optionsArray[] = NOT_BETWEEN;
2719
+ }
2720
+ if( ($this->LCType == LCT_LIST || $this->LCType == LCT_DROPDOWN) && $this->isAdditionalControlRequired() )
2721
+ {
2722
+ $optionsArray[] = NOT_CONTAINS;
2723
+ $optionsArray[] = NOT_STARTS_WITH;
2724
+ }
2725
+ }
2726
+
2727
+ $optionsArray[] = NOT_EQUALS;
2728
+ $optionsArray[] = NOT_EMPTY;
2729
+ }
2730
+
2731
+ return $this->buildSearchOptions($optionsArray, $selOpt, $not, $both);
2732
+ }
2733
+
2734
+ /**
2735
+ * Fill the response array with the suggest values
2736
+ *
2737
+ *
2738
+ * @param String value
2739
+ * Note: value is preceeded with "_"
2740
+ * @param String searchFor
2741
+ * @param &Array response
2742
+ * @param &Array row
2743
+ */
2744
+ function suggestValue($value, $searchFor, &$response, &$row)
2745
+ {
2746
+ parent::suggestValue($value, $searchFor, $response, $row);
2747
+ return;
2748
+
2749
+ // ??????
2750
+ if( !GetGlobalData("handleSearchSuggestInLookup", true) || $this->lookupType == LT_LISTOFVALUES || $this->isSearchByDispalyedFieldAllowed() )
2751
+ {
2752
+ parent::suggestValue($value, $searchFor, $response, $row);
2753
+ return;
2754
+ }
2755
+
2756
+ $lookupDc = $this->getLookupDataCommand( array(), substr($value, 1), false, true, true, true );
2757
+ $qResult = $this->lookupDataSource->getList( $lookupDc );
2758
+
2759
+ if( $data = $qResult->fetchAssoc() )
2760
+ {
2761
+ // "_" is added to convert number type to string
2762
+ if( $this->isDisplayFieldEncrypted )
2763
+ {
2764
+ $lookup_value = "_" . $this->ciphererLookup->DecryptField( $this->displayFieldName , $data[ $this->displayFieldAlias ] );
2765
+ }
2766
+ else
2767
+ $lookup_value = "_" . $data[ $this->displayFieldAlias ];
2768
+
2769
+ parent::suggestValue($lookup_value, $searchFor, $response, $row);
2770
+ }
2771
+ }
2772
+
2773
+ /**
2774
+ * @param Array parentValuesData
2775
+ * @return Boolean
2776
+ */
2777
+ protected function needCategoryFiltering( $parentValuesData )
2778
+ {
2779
+ foreach( $this->pageObject->pSetEdit->getParentFieldsData( $this->field ) as $cData )
2780
+ {
2781
+ $strCategoryControl = $cData['main'];
2782
+
2783
+ if( !isset( $parentValuesData[ $cData['main'] ] ) )
2784
+ continue ;
2785
+
2786
+ $parentValue = $parentValuesData[ $cData['main'] ];
2787
+ $parentVals = $this->pageObject->pSetEdit->multiSelect($strCategoryControl) ? splitLookupValues( $parentValue ) : array( $parentValue );
2788
+
2789
+ foreach( $parentVals as $parentVal )
2790
+ {
2791
+ if( strlen( trim( $parentVal ) ) )
2792
+ return true;
2793
+ }
2794
+ }
2795
+
2796
+ return false;
2797
+ }
2798
+
2799
+ /**
2800
+ * Get for the dependent lookup an array containing the link field values with even indices
2801
+ * and the corresponding displayed values with odd indices
2802
+ *
2803
+ * @intellisense
2804
+ * @param Array parentValuesData
2805
+ * @param String childVal
2806
+ * @param Boolean doCategoryFilter
2807
+ * @param Boolean initialLoad
2808
+ * @return Array
2809
+ */
2810
+ public function loadLookupContent( $parentValuesData, $childVal = "", $doCategoryFilter = true, $initialLoad = true )
2811
+ {
2812
+ if( $this->bUseCategory && $doCategoryFilter )
2813
+ {
2814
+ if( !$this->needCategoryFiltering( $parentValuesData ) )
2815
+ return array();
2816
+ }
2817
+
2818
+ $lookupDc = $this->getLookupDataCommand( $parentValuesData, $childVal, $doCategoryFilter, $this->LCType == LCT_AJAX && $initialLoad );
2819
+ return $this->getLookupContentData( $lookupDc, $childVal != "" );
2820
+ }
2821
+
2822
+ /**
2823
+ * @param DsCommand lookupDc
2824
+ * @param Boolean selectValue
2825
+ * @return Array
2826
+ */
2827
+ protected function getLookupContentData( $lookupDc, $selectValue )
2828
+ {
2829
+ $response = array();
2830
+ $qResult = $this->lookupDataSource->getList( $lookupDc );
2831
+ if( !$qResult ) {
2832
+ showError( $this->lookupDataSource->lastError() );
2833
+ }
2834
+
2835
+ if( $this->LCType !== LCT_AJAX || $this->multiselect )
2836
+ {
2837
+ $isUnique = $this->pageObject->pSetEdit->isLookupUnique( $this->field );
2838
+ $uniqueArray = array();
2839
+ while( $data = $qResult->fetchAssoc() )
2840
+ {
2841
+ $dispValue = $data[ $this->displayFieldAlias ];
2842
+ if( $isUnique )
2843
+ {
2844
+ if( in_array( $dispValue, $uniqueArray) )
2845
+ continue;
2846
+
2847
+ $uniqueArray[] = $dispValue;
2848
+ }
2849
+ $response[] = $data[ $this->linkFieldName ];
2850
+ $response[] = $this->getLookupTextValue( $dispValue );
2851
+ }
2852
+ }
2853
+ else
2854
+ {
2855
+ $data = $qResult->fetchAssoc();
2856
+ // assign value if it is asked for, or if there is only oine record in recordset
2857
+
2858
+ if( $data && ( $selectValue || !$qResult->fetchAssoc() ) )
2859
+ {
2860
+ $response[] = $data[ $this->linkFieldName ];
2861
+ $response[] = $this->getLookupTextValue( $data[ $this->displayFieldAlias ] );
2862
+ }
2863
+ }
2864
+
2865
+ return $response;
2866
+ }
2867
+
2868
+ /**
2869
+ * @param Boolean isExistParent
2870
+ * @param Number mode
2871
+ * @param Array parentCtrlsData
2872
+ * @return Mixed
2873
+ */
2874
+ public function getLookupContentToReload( $isExistParent, $mode, $parentCtrlsData )
2875
+ {
2876
+ // there are parent lookups on the page
2877
+ if( $isExistParent )
2878
+ {
2879
+ $hasEmptyParent = false;
2880
+ foreach($parentCtrlsData as $value)
2881
+ {
2882
+ if( $value === '' )
2883
+ {
2884
+ $hasEmptyParent = true;
2885
+ break;
2886
+ }
2887
+ }
2888
+
2889
+ if( !$hasEmptyParent )
2890
+ {
2891
+ // there are parent lookups on the page none of them is empty
2892
+ return $this->loadLookupContent( $parentCtrlsData, '', true, false );
2893
+ }
2894
+
2895
+ if( $mode == MODE_SEARCH || $mode == MODE_EDIT || $mode == MODE_INLINE_EDIT || $mode == MODE_INLINE_ADD || $mode == MODE_ADD )
2896
+ return '';
2897
+
2898
+ // which mode is this?
2899
+ return $this->loadLookupContent( $parentCtrlsData, '', true, false );
2900
+ }
2901
+ // there are not parent lookups on the page
2902
+ else
2903
+ {
2904
+ if( $mode == MODE_SEARCH || $mode == MODE_INLINE_ADD || $mode == MODE_ADD || $mode == MODE_EDIT || $mode == MODE_INLINE_EDIT )
2905
+ return $this->loadLookupContent( array(), '', false, false );
2906
+
2907
+ return $this->loadLookupContent( array(), '', true, false );
2908
+ }
2909
+
2910
+ return '';
2911
+ }
2912
+
2913
+ /**
2914
+ * @param String linkFieldVal
2915
+ * @return Array
2916
+ */
2917
+ public function getAutoFillData( $linkFieldVal )
2918
+ {
2919
+ $data = array();
2920
+
2921
+ $lookupDc = $this->getLookupDataCommand( array(), $linkFieldVal, false, true, true );
2922
+ $rs = $this->lookupDataSource->getList( $lookupDc );
2923
+ if( !$rs ) {
2924
+ showError( $this->lookupDataSource->lastError() );
2925
+ }
2926
+ $row = $rs->fetchAssoc();
2927
+
2928
+ $autoCompleteFields = $this->pageObject->pSetEdit->getAutoCompleteFields( $this->field );
2929
+ if( $this->lookupType == LT_QUERY )
2930
+ {
2931
+ $data = $this->ciphererLookup->DecryptFetchedArray( $row );
2932
+ }
2933
+ else
2934
+ {
2935
+ foreach( $autoCompleteFields as $aData )
2936
+ {
2937
+ $data[ $aData["lookupF"] ] = $row[ $aData["lookupF"] ];
2938
+ }
2939
+ }
2940
+
2941
+ $ret = array();
2942
+ $masterData = array();
2943
+ foreach( $autoCompleteFields as $aData ) {
2944
+ $masterData[ $aData["masterF"] ] = $data[ $aData["lookupF"] ];
2945
+
2946
+ $fieldData = array();
2947
+ $val = $data[ $aData["lookupF"] ];
2948
+ $ctrl = $this->pageObject->getControl( $aData["masterF"] );
2949
+ $dispValue = $ctrl->getDisplayValue( $masterData );
2950
+ if( $ctrl->format == EDIT_FORMAT_READONLY ) {
2951
+ $fieldData["value"] = $val;
2952
+ $fieldData["dispValue"] = $dispValue;
2953
+ } else {
2954
+ $fieldData["value"] = $dispValue;
2955
+ }
2956
+
2957
+ $ret[ $aData["lookupF"] ] = $fieldData;
2958
+ }
2959
+
2960
+ if( !$ret )
2961
+ $ret[ $this->field ] = '';
2962
+
2963
+ return $ret;
2964
+ }
2965
+
2966
+
2967
+ function getInputStyle( $mode )
2968
+ {
2969
+ return "class='form-control'";
2970
+ }
2971
+
2972
+ /**
2973
+ * Select & Add new links block
2974
+ * @param Boolean hiddenSelect
2975
+ * @return String
2976
+ */
2977
+ protected function getLookupLinks( $hiddenSelect = false )
2978
+ {
2979
+ $links = array();
2980
+
2981
+ if( $this->LCType == LCT_LIST )
2982
+ {
2983
+ $visibility = $hiddenSelect ? ' style="visibility: hidden;"' : '';
2984
+ $openId = "open_lookup_".GoodFieldName( $this->field )."_".$this->id;
2985
+ $links[] = '<a href="#" id="'.$openId.'" '.$visibility.'>'."Select".'</a>';
2986
+
2987
+ if( $this->multiselect ) {
2988
+ $clearId = "clearLookup_".GoodFieldName( $this->field )."_".$this->id;
2989
+ $links[] = '<a href="#" id="'.$clearId.'" style="visibility: hidden;">'."Clear".'</a>';
2990
+ }
2991
+ }
2992
+
2993
+ if( $this->addNewItem )
2994
+ $links[] = '<a href="#" id="addnew_'.$this->cfield.'">'."Add new".'</a>';
2995
+
2996
+
2997
+ if( !count($links) )
2998
+ return "";
2999
+
3000
+ return '<div class="bs-lookup-links">'.implode("", $links).'</div>';
3001
+ }
3002
+
3003
+ public function getBasicFieldCondition( $searchFor, $strSearchOption, $searchFor2 = "", $etype = "" ) {
3004
+ if( $strSearchOption == EMPTY_SEARCH ) {
3005
+ return parent::getBasicFieldCondition( $searchFor, $strSearchOption, $searchFor2 );
3006
+ }
3007
+ if( !$this->multiselect )
3008
+ return $this->singleValueCondition( $searchFor, $strSearchOption, $searchFor2 );
3009
+ else
3010
+ return $this->multiValueCondition( $searchFor, $strSearchOption, $searchFor2 );
3011
+
3012
+ }
3013
+ public function multiValueCondition( $searchFor, $strSearchOption, $searchFor2 = "" ) {
3014
+ $values = splitLookupValues( $searchFor );
3015
+ // single-select on Add/Edit, butmuti on search
3016
+ if( !$this->pageObject->pSetEdit->multiSelectLookupEdit( $this->field ) ) {
3017
+ $conditions = array();
3018
+ foreach( $values as $v ) {
3019
+ $conditions[] = $this->singleValueCondition( $v, $strSearchOption, $searchFor2 );
3020
+ }
3021
+ return DataCondition::_Or( $conditions );
3022
+ }
3023
+ // true muti-select control
3024
+ // takes only Equals and Contains
3025
+ if( $strSearchOption == EQUALS ) {
3026
+ // all of searched values must be present in the field
3027
+ return DataCondition::FieldHasList( $this->field, dsopALL_IN_LIST, $values );
3028
+ }
3029
+ if( $strSearchOption == CONTAINS ) {
3030
+ // at least one of searched values must be present in the field
3031
+ return DataCondition::FieldHasList( $this->field, dsopSOME_IN_LIST, $values );
3032
+ }
3033
+ return null;
3034
+ }
3035
+
3036
+
3037
+ public function singleValueCondition( $searchFor, $strSearchOption, $searchFor2 = "" ) {
3038
+ $cond = parent::getBasicFieldCondition( $searchFor, $strSearchOption, $searchFor2 );
3039
+
3040
+ if( $this->displayFieldSearch( $strSearchOption ) ) {
3041
+ $cond->operands[0]->joinData = $this->createJoinData();
3042
+ }
3043
+ return $cond;
3044
+ }
3045
+
3046
+ /**
3047
+ * Returns true when searching by display field makes sense.
3048
+ * It only takes in account field Edit settings.
3049
+ * Database and other limitations are handled by the datasource
3050
+ * @return Boolean
3051
+ */
3052
+ protected function displayFieldSearch( $searchOption )
3053
+ {
3054
+ if( $searchOption !== CONTAINS && $searchOption !== STARTS_WITH ) {
3055
+ // basic search, no display field substitution
3056
+ return false;
3057
+ }
3058
+ if( $this->linkAndDisplaySame || $this->lookupType == LT_LISTOFVALUES ) {
3059
+ // no lookup display field
3060
+ return false;
3061
+ }
3062
+
3063
+ if( $this->multiselect && $this->pageObject->pSetEdit->multiSelectLookupEdit( $this->field )) {
3064
+ // multiselect everywhere
3065
+ return false;
3066
+ }
3067
+ return true;
3068
+
3069
+ }
3070
+
3071
+ /**
3072
+ * @return DsJoinData
3073
+ */
3074
+ protected function createJoinData() {
3075
+ $jd = new DsJoinData;
3076
+ $jd->dataSource = $this->lookupDataSource;
3077
+ $jd->linkField = $this->linkFieldName;
3078
+ if( $this->customDisplay )
3079
+ $jd->displayExpression = $this->displayFieldName;
3080
+ else
3081
+ $jd->displayField = $this->displayFieldName;
3082
+
3083
+ // we assume here that 'AJAX' and 'List page' lookups are choosen when the lookup table is rather long
3084
+ $jd->longList = ( $this->LCType == LCT_AJAX || $this->LCType == LCT_LIST );
3085
+ $jd->displayAlias = generateAlias();
3086
+ return $jd;
3087
+ }
3088
+
3089
+ /**
3090
+ * Returns command for the list of lookup values
3091
+ * @param Array parentValuesData
3092
+ * @param String value - field value.
3093
+ * @param Boolean doCategoryFilter - dependent dropdowns
3094
+ * @param Boolean doValueFilter - select only one value
3095
+ * @param Boolean doWhereFilter - add custom WHERE filter
3096
+ * @param Boolean oneRecordMode
3097
+ *
3098
+ * @return DsCommand
3099
+ */
3100
+
3101
+ protected function getLookupDataCommand(
3102
+ $parentValuesData,
3103
+ $value = "",
3104
+ $doCategoryFilter = true,
3105
+ $doValueFilter = false,
3106
+ $doWhereFilter = true,
3107
+ $oneRecordMode = false )
3108
+ {
3109
+ $pSet = $this->pageObject->pSetEdit;
3110
+
3111
+ $ret = LookupField::makeLookupDataCommand(
3112
+ $this->field,
3113
+ $pSet,
3114
+ $parentValuesData,
3115
+ $value,
3116
+ $doCategoryFilter,
3117
+ $doValueFilter,
3118
+ $doWhereFilter,
3119
+ $oneRecordMode
3120
+ );
3121
+ $this->displayFieldAlias = $ret["displayField"];
3122
+ return $ret["dc"];
3123
+
3124
+
3125
+ }
3126
+
3127
+ /**
3128
+ * @param String field name
3129
+ * @param ProjectSettings
3130
+ * @param Array parentValuesData
3131
+ * @param String value - field value.
3132
+ * @param Boolean doCategoryFilter - dependent dropdowns
3133
+ * @param Boolean doValueFilter - select only one value
3134
+ * @param Boolean doWhereFilter - add custom WHERE filter
3135
+ * @param Boolean oneRecordMode
3136
+ * @return array
3137
+ * "ds" => DsCommand
3138
+ * "displayField" => display field alias in the command result
3139
+ */
3140
+ public static function makeLookupDataCommand( $field, $pSet, $parentValuesData, $value, $doCategoryFilter, $doValueFilter, $doWhereFilter, $oneRecordMode )
3141
+ {
3142
+
3143
+ $dc = new DsCommand();
3144
+
3145
+ // order
3146
+ $orderField = $pSet->getLookupOrderBy( $field );
3147
+ if( $orderField ) {
3148
+ $dir = $pSet->isLookupDesc( $field ) ? 'DESC' : 'ASC';
3149
+ $dc->order[] = array( "column" => $orderField, "dir" => $dir );
3150
+ } else {
3151
+ $lookupType = $pSet->getLookupType( $field );
3152
+ if( $lookupType == LT_QUERY ) {
3153
+ require_once( getabspath('classes/orderclause.php') );
3154
+ $lookupTable = $pSet->getLookupTable( $field );
3155
+ $dc->order = OrderClause::originalOrderFields( new ProjectSettings( $lookupTable ) );
3156
+ }
3157
+ }
3158
+
3159
+ // custom display field
3160
+ $displayField = $pSet->getDisplayField( $field );
3161
+ if( $pSet->getCustomDisplay( $field ) ) {
3162
+ $displayFieldAlias = generateAlias();
3163
+ $dc->extraColumns[] = new DsFieldData( $displayField, $displayFieldAlias, "" );
3164
+ } else {
3165
+ $displayFieldAlias = $displayField;
3166
+ }
3167
+
3168
+ // filters
3169
+ $filters = array();
3170
+
3171
+ // select only current value
3172
+ if( $doValueFilter ) {
3173
+ if( $value === "" || $value === null ) {
3174
+ // add/search page or empty value
3175
+ $filters[] = DataCondition::_False();
3176
+ } else {
3177
+ $linkField = $pSet->getLinkField( $field );
3178
+ $multiselect = $pSet->multiSelect( $field );
3179
+ if( !$multiselect ) {
3180
+ $filters[] = DataCondition::FieldEquals( $linkField , $value );
3181
+ } else {
3182
+ $values = splitLookupValues( $value );
3183
+ $valueConditions = array();
3184
+ foreach( $values as $v ) {
3185
+ $valueConditions[] = DataCondition::FieldEquals( $linkField , $v );
3186
+ }
3187
+ $filters[] = DataCondition::_Or( $valueConditions );
3188
+ }
3189
+ }
3190
+ }
3191
+
3192
+ // user-provided WHERE expression
3193
+ if( $doWhereFilter )
3194
+ {
3195
+ $filters[] = DataCondition::SQLCondition( prepareLookupWhere( $field, $pSet ) );
3196
+ }
3197
+
3198
+ // security filter
3199
+ // only check row-level permissions
3200
+ if( $pSet->getLookupType( $field ) == LT_QUERY ) {
3201
+ $filters[] = Security::SelectCondition( "S", new ProjectSettings( $pSet->getLookupTable($field) ), true );
3202
+ }
3203
+
3204
+ // category filter
3205
+ $parents = $pSet->getParentFieldsData( $field );
3206
+ if( $doCategoryFilter && $parentValuesData && $parents )
3207
+ {
3208
+ $parentFilters = array();
3209
+ foreach( $parents as $cdata ) {
3210
+ $mainControlName = $cdata['main'];
3211
+ $filterFieldName = $cdata['lookup'];
3212
+ $mainControlVal = $parentValuesData[ $mainControlName ];
3213
+
3214
+ if( $pSet->multiSelect( $mainControlName ) || strlen( $mainControlVal ) )
3215
+ $filters[] = LookupField::categoryCondition( $pSet, $mainControlName, $filterFieldName, $mainControlVal );
3216
+ }
3217
+ }
3218
+
3219
+ if( $pSet->isLookupUnique($field) ) {
3220
+ $dc->totals[] = array( "field" => $pSet->getLinkField($field), "total" => "distinct" );
3221
+ $dc->totals[] = array( "field" => $displayFieldAlias, "total" => "distinct" );
3222
+ }
3223
+
3224
+ $dc->filter = DataCondition::_And( $filters );
3225
+
3226
+ if( $oneRecordMode )
3227
+ $dc->reccount = 1;
3228
+ return array(
3229
+ "dc" => $dc,
3230
+ "displayField" => $displayFieldAlias
3231
+ );
3232
+ }
3233
+
3234
+
3235
+ /**
3236
+ *
3237
+ */
3238
+ public static function categoryCondition( $pSet, $parentControlName, $filterFieldName, $parentControlValue ) {
3239
+ // single-select
3240
+ if( !$pSet->multiSelect( $parentControlName ) ) {
3241
+ return DataCondition::FieldEquals( $filterFieldName, $parentControlValue );
3242
+ }
3243
+
3244
+ // multiselect parent
3245
+ $values = splitLookupValues( $parentControlValue );
3246
+
3247
+ $conditions = array();
3248
+ foreach( $values as $value )
3249
+ {
3250
+ $conditions[] = DataCondition::FieldEquals( $filterFieldName, $value );
3251
+ }
3252
+
3253
+ return DataCondition::_Or( $conditions );
3254
+ }
3255
+
3256
+ public function getSuggestCommand( $searchFor, $searchOpt, $numberOfSuggests )
3257
+ {
3258
+ $dc = parent::getSuggestCommand( $searchFor, $searchOpt, $numberOfSuggests );
3259
+
3260
+ // add extra field and replace totals
3261
+ if( $this->displayFieldSearch( $searchOpt ) ) {
3262
+
3263
+ $displayAlias = generateAlias();
3264
+ $dc->extraColumns[] = new DsFieldData( "", $displayAlias, $this->field, 0, $this->createJoinData() );
3265
+
3266
+ $dc->totals = array(
3267
+ array(
3268
+ "field" => $displayAlias,
3269
+ "total" => "distinct"
3270
+ )
3271
+ );
3272
+ }
3273
+
3274
+ return $dc;
3275
+ }
3276
+
3277
+ protected function getLookupTextValue( $displayValue ) {
3278
+ if( $this->pageObject->pSetEdit->getViewFormat( $this->field ) == FORMAT_HTML ) {
3279
+ if ( $this->LCType == LCT_CBLIST || $this->LCType == LCT_RADIO ) {
3280
+ return $displayValue;
3281
+ }
3282
+ }
3283
+
3284
+ return runner_htmlspecialchars( $displayValue );
3285
+ }
3286
+ }
3287
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
3288
  ?>
php/classes/controls/LookupTextField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  require_once getabspath('classes/controls/LookupField.php');
3
  class LookupTextField extends LookupField
@@ -93,4 +94,101 @@ class LookupTextField extends LookupField
93
  return $this->buildSearchOptions($optionsArray, $selOpt, $not, $both);
94
  }
95
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  require_once getabspath('classes/controls/LookupField.php');
4
  class LookupTextField extends LookupField
 
94
  return $this->buildSearchOptions($optionsArray, $selOpt, $not, $both);
95
  }
96
  }
97
+ =======
98
+ <?php
99
+ require_once getabspath('classes/controls/LookupField.php');
100
+ class LookupTextField extends LookupField
101
+ {
102
+ var $localPSet;
103
+ var $linkAndDisplaySame = false;
104
+ var $ciphererLink = null;
105
+ var $ciphererDisplay = null;
106
+ function __construct($field, $pageObject, $id, $connection)
107
+ {
108
+ EditControl::__construct($field, $pageObject, $id, $connection);
109
+ $this->format = EDIT_FORMAT_LOOKUP_WIZARD;
110
+
111
+ $this->lookupPageType = $this->pageObject->pSetEdit->getPageTypeByFieldEditFormat($this->field, EDIT_FORMAT_LOOKUP_WIZARD);
112
+
113
+ $this->localPSet = new ProjectSettings($this->pageObject->tName, $this->lookupPageType);
114
+
115
+ $this->lookupDataSource = getLookupDataSource( $this->field, $this->localPSet );
116
+
117
+
118
+ $this->lookupTable = $this->localPSet->getLookupTable($this->field);
119
+ $this->lookupType = $this->localPSet->getLookupType($this->field);
120
+ if($this->lookupType == LT_QUERY)
121
+ $this->lookupPSet = new ProjectSettings($this->lookupTable);
122
+ $this->displayFieldName = $this->localPSet->getDisplayField($this->field);
123
+ $this->linkFieldName = $this->localPSet->getLinkField($this->field);
124
+ $this->linkAndDisplaySame = $this->displayFieldName == $this->linkFieldName;
125
+
126
+ $this->ciphererLink = new RunnerCipherer($this->pageObject->tName);
127
+ if($this->lookupType == LT_QUERY)
128
+ $this->ciphererDisplay = new RunnerCipherer($this->lookupTable);
129
+ else
130
+ $this->ciphererDisplay = $this->ciphererLink;
131
+
132
+ $this->LCType = $this->localPSet->lookupControlType($this->field);
133
+ if( $this->pageObject->mobileTemplateMode() && $this->LCType == LCT_AJAX )
134
+ $this->LCType = LCT_DROPDOWN;
135
+
136
+ $this->multiselect = $this->localPSet->multiSelect($this->field);
137
+ $this->lwLinkField = $connection->addFieldWrappers($this->localPSet->getLinkField($this->field));
138
+ $this->lwDisplayFieldWrapped = RunnerPage::sqlFormattedDisplayField($this->field, $connection, $this->localPSet);
139
+ $this->customDisplay = $this->localPSet->getCustomDisplay($this->field);
140
+ }
141
+
142
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
143
+ {
144
+ parent::parentBuildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
145
+ echo '<input id="'.$this->cfield.'" '.$this->inputStyle.' type="text" '
146
+ .($mode == MODE_SEARCH ? 'autocomplete="off" ' : '')
147
+ .(($mode==MODE_INLINE_EDIT || $mode==MODE_INLINE_ADD) && $this->is508==true ? 'alt="'.$this->strLabel.'" ' : '')
148
+ .'name="'.$this->cfield.'" '.$this->pageObject->pSetEdit->getEditParams($this->field).' value="'
149
+ .runner_htmlspecialchars($value).'">';
150
+ $this->buildControlEnd($validate, $mode);
151
+ }
152
+
153
+
154
+ /**
155
+ * Form the control specified search options array and built the control's search options markup
156
+ * @param String selOpt The search option value
157
+ * @param Boolean not It indicates if the search option negation is set
158
+ * @param Boolean both It indicates if the control needs 'NOT'-options
159
+ * @return String A string containing options markup
160
+ */
161
+ function getSearchOptions($selOpt, $not, $both)
162
+ {
163
+ $optionsArray = array();
164
+ $isPHPEncripted = $this->pageObject->cipherer->isFieldPHPEncrypted($this->field);
165
+ if(!$isPHPEncripted){
166
+ $optionsArray[] = CONTAINS;
167
+ }
168
+ $optionsArray[] = EQUALS;
169
+ if(!$isPHPEncripted){
170
+ $optionsArray[] = STARTS_WITH;
171
+ $optionsArray[] = MORE_THAN;
172
+ $optionsArray[] = LESS_THAN;
173
+ $optionsArray[] = BETWEEN;
174
+ }
175
+ $optionsArray[] = EMPTY_SEARCH;
176
+ if($both)
177
+ {
178
+ if(!$isPHPEncripted){
179
+ $optionsArray[] = NOT_CONTAINS;
180
+ }
181
+ $optionsArray[] = NOT_EQUALS;
182
+ if(!$isPHPEncripted){
183
+ $optionsArray[] = NOT_STARTS_WITH;
184
+ $optionsArray[] = NOT_MORE_THAN;
185
+ $optionsArray[] = NOT_LESS_THAN;
186
+ $optionsArray[] = NOT_BETWEEN;
187
+ }
188
+ $optionsArray[] = NOT_EMPTY;
189
+ }
190
+ return $this->buildSearchOptions($optionsArray, $selOpt, $not, $both);
191
+ }
192
+ }
193
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
194
  ?>
php/classes/controls/PasswordField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  require_once getabspath('classes/controls/TextControl.php');
3
  class PasswordField extends TextControl
@@ -29,4 +30,37 @@ class PasswordField extends TextControl
29
  return $this->cfield;
30
  }
31
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  require_once getabspath('classes/controls/TextControl.php');
4
  class PasswordField extends TextControl
 
30
  return $this->cfield;
31
  }
32
  }
33
+ =======
34
+ <?php
35
+ require_once getabspath('classes/controls/TextControl.php');
36
+ class PasswordField extends TextControl
37
+ {
38
+ function __construct($field, $pageObject, $id, $connection)
39
+ {
40
+ EditControl::__construct($field, $pageObject, $id, $connection);
41
+ $this->format = EDIT_FORMAT_PASSWORD;
42
+ }
43
+
44
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
45
+ {
46
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
47
+
48
+ $classString = " class=\"form-control\"";
49
+
50
+ $autocompleteAttr = $this->container->pageType == 'register'
51
+ ? 'autocomplete="new-password"'
52
+ : '';
53
+ echo '<input '.$this->inputStyle.' '.$autocompleteAttr.' '.$this->getPlaceholderAttr().' id="'.$this->cfield.'" '.$classString.' type="Password" '
54
+ .(($mode==MODE_INLINE_EDIT || $mode==MODE_INLINE_ADD) && $this->is508==true ? 'alt="'.$this->strLabel.'" ' : '').'name="'
55
+ .$this->cfield.'" '.$this->pageObject->pSetEdit->getEditParams($this->field).' value="'.runner_htmlspecialchars($value).'">';
56
+
57
+ $this->buildControlEnd($validate, $mode);
58
+ }
59
+
60
+ function getFirstElementId()
61
+ {
62
+ return $this->cfield;
63
+ }
64
+ }
65
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
66
  ?>
php/classes/controls/ReadOnlyField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  require_once getabspath('classes/controls/TextControl.php');
3
  require_once getabspath("classes/controls/ViewControlsContainer.php");
@@ -44,4 +45,52 @@ class ReadOnlyField extends TextControl
44
  return $control->showDbValue( $data, "", false );
45
  }
46
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  require_once getabspath('classes/controls/TextControl.php');
4
  require_once getabspath("classes/controls/ViewControlsContainer.php");
 
45
  return $control->showDbValue( $data, "", false );
46
  }
47
  }
48
+ =======
49
+ <?php
50
+ require_once getabspath('classes/controls/TextControl.php');
51
+ require_once getabspath("classes/controls/ViewControlsContainer.php");
52
+ class ReadOnlyField extends TextControl
53
+ {
54
+ function __construct($field, $pageObject, $id, $connection)
55
+ {
56
+ EditControl::__construct($field, $pageObject, $id, $connection);
57
+ $this->format = EDIT_FORMAT_READONLY;
58
+ }
59
+
60
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
61
+ {
62
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
63
+
64
+ if( $mode == MODE_EDIT || $mode == MODE_ADD || $mode == MODE_INLINE_EDIT || $mode == MODE_INLINE_ADD ) {
65
+ echo '<span class="r-readonly-control" id="readonly_'.$this->cfield.'" '.$this->inputStyle.'>'
66
+ .$this->pageObject->readOnlyFields[ $this->field ].'</span>';
67
+ }
68
+
69
+ $attr = "";
70
+ if( $this->pageObject->pSetEdit->getViewFormat( $this->field ) == FORMAT_CHECKBOX ) {
71
+ $attr = "data-control-type='checkbox'";
72
+ if ( $this->connection->dbType == nDATABASE_PostgreSQL ) {
73
+ $attr.=' data-true="t" data-false="f"';
74
+ }
75
+ }
76
+
77
+ echo '<input id="'.$this->cfield.'" type="Hidden" name="'.$this->cfield.'" value="'.runner_htmlspecialchars($value).'" '.$attr.'>';
78
+ $this->buildControlEnd( $validate, $mode );
79
+ }
80
+
81
+ /**
82
+ * Get the field's content
83
+ * @param &Array data
84
+ * @return String
85
+ */
86
+ public function getDisplayValue( &$data )
87
+ {
88
+ // $this->pageObject is not always a RunnerPage object, sometimes it is EditControlsContainer
89
+ $container = new ViewControlsContainer( $this->container->pSetEdit, $this->pageObject->pageType, null );
90
+ $control = $container->getControl( $this->field );
91
+
92
+ return $control->showDbValue( $data, "", false );
93
+ }
94
+ }
95
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
96
  ?>
php/classes/controls/TextAreaField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  require_once getabspath('classes/controls/TextControl.php');
3
  class TextAreaField extends TextControl
@@ -117,4 +118,125 @@ class TextAreaField extends TextControl
117
  .'</div>';
118
  }
119
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  require_once getabspath('classes/controls/TextControl.php');
4
  class TextAreaField extends TextControl
 
118
  .'</div>';
119
  }
120
  }
121
+ =======
122
+ <?php
123
+ require_once getabspath('classes/controls/TextControl.php');
124
+ class TextAreaField extends TextControl
125
+ {
126
+ function __construct($field, $pageObject, $id, $connection)
127
+ {
128
+ EditControl::__construct($field, $pageObject, $id, $connection);
129
+ $this->format = EDIT_FORMAT_TEXT_AREA;
130
+ }
131
+
132
+ function buildControl( $value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data ) {
133
+ parent::buildControl( $value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data );
134
+
135
+ if( $this->pageObject->pSetEdit->isUseRTE( $this->field ) ) {
136
+ $value = $this->RTESafe( $value );
137
+
138
+ switch( $this->pageObject->pSetEdit->getRTEType( $this->field ) ) {
139
+ case "RTE":
140
+ $this->buildTinyMCE( $value );
141
+ break;
142
+ case "RTECK_NEW":
143
+ case "RTECK":
144
+ $this->CreateCKeditor( $value );
145
+ break;
146
+ case "RTEINNOVA":
147
+ $this->buildInnova( $value );
148
+ break;
149
+ }
150
+ } else {
151
+ $nHeight = $this->pageObject->pSetEdit->getNRows( $this->field );
152
+ $attrs = $this->getPlaceholderAttr();
153
+ echo '<textarea id="'.$this->cfield.'" alt="'.$this->strLabel.'" name="'.$this->cfield.'" style="height:'.$nHeight.'px;" '
154
+ .$attrs.' class="form-control">'
155
+ .runner_htmlspecialchars( $value )
156
+ .'</textarea>';
157
+ }
158
+
159
+ $this->buildControlEnd($validate, $mode);
160
+ }
161
+
162
+ function getFirstElementId()
163
+ {
164
+ return $this->cfield;
165
+ }
166
+
167
+ /**
168
+ * returns safe code for preloading in the RTE
169
+ * @intellisense
170
+ * @param String text
171
+ * @return String
172
+ */
173
+ protected function RTESafe($text)
174
+ {
175
+ $tmpString = trim($text);
176
+ if(!$tmpString)
177
+ return "";
178
+
179
+ // convert all types of single quotes
180
+ $tmpString = str_replace("'", "&#39;", $tmpString);
181
+
182
+ // replace carriage returns & line feeds
183
+ $tmpString = str_replace( chr(10), " ", $tmpString );
184
+ $tmpString = str_replace( chr(13), " ", $tmpString );
185
+
186
+ return $tmpString;
187
+ }
188
+
189
+ /**
190
+ * @intellisense
191
+ */
192
+ protected function CreateCKeditor($value)
193
+ {
194
+ echo '<div id="disabledCKE_'.$this->cfield.'">'
195
+ .'<textarea id="'.$this->cfield.'" name="'.$this->cfield.'" rows="8" cols="60">'
196
+ .runner_htmlspecialchars($value)
197
+ .'</textarea>'
198
+ .'</div>';
199
+ }
200
+
201
+ /**
202
+ * addJSFiles
203
+ * Add control JS files to page object
204
+ */
205
+ function addJSFiles() {
206
+ if ( $this->pageObject->pSetEdit->getRTEType( $this->field ) == "RTE" ) {
207
+ $this->pageObject->AddJSFile("plugins/tinymce/tinymce.min.js");
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Build a stub markup for Innova editor
213
+ * @param String value
214
+ */
215
+ protected function buildInnova( $value ) {
216
+ $nHeight = $this->pageObject->pSetEdit->getNRows( $this->field );
217
+ if( $nHeight< 300 )
218
+ $nHeight = 300;
219
+
220
+ $assetManagerUrl = projectURL() .'plugins/innovaeditor/assetmanager/'. GetTableLink("assetmanager");
221
+
222
+ echo '<div id="disabledInnova_'.$this->cfield.'" style="width:100%; height:'. $nHeight .'px;" data-am="'.$assetManagerUrl.'">'
223
+ .'<textarea alt="'.$this->strLabel.'" id="'.$this->cfield.'" name="'.$this->cfield.'">'
224
+ .runner_htmlspecialchars( $value )
225
+ .'</textarea>'
226
+ .'<div id="'.$this->cfield.'innova" name="'.$this->cfield.'" style="width:100%; height:'. $nHeight .'px;">'
227
+ .'</div>'
228
+ .'</div>';
229
+ }
230
+
231
+ protected function buildTinyMCE( $value ) {
232
+ $nHeight = $this->pageObject->pSetEdit->getNRows( $this->field ) + 100;
233
+
234
+ echo '<div id="disabledTinyMCE_'.$this->cfield.'">'
235
+ .'<textarea id="'.$this->cfield.'" name="'.$this->cfield.'" alt="'.$this->strLabel.'" style="width:100%; height:'. $nHeight .'px;">'
236
+ .runner_htmlspecialchars( $value )
237
+ .'</textarea>'
238
+ .'</div>';
239
+ }
240
+ }
241
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
242
  ?>
php/classes/controls/TextControl.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class TextControl extends EditControl
3
  {
@@ -40,4 +41,48 @@ class TextControl extends EditControl
40
  return $this->buildSearchOptions($optionsArray, $selOpt, $not, $both);
41
  }
42
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class TextControl extends EditControl
4
  {
 
41
  return $this->buildSearchOptions($optionsArray, $selOpt, $not, $both);
42
  }
43
  }
44
+ =======
45
+ <?php
46
+ class TextControl extends EditControl
47
+ {
48
+ /**
49
+ * Form the control specified search options array and built the control's search options markup
50
+ * @param String selOpt The search option value
51
+ * @param Boolean not It indicates if the search option negation is set
52
+ * @param Boolean both It indicates if the control needs 'NOT'-options
53
+ * @return String A string containing options markup
54
+ */
55
+ function getSearchOptions($selOpt, $not, $both)
56
+ {
57
+ $optionsArray = array();
58
+ $isPHPEncripted = $this->pageObject->cipherer->isFieldPHPEncrypted($this->field);
59
+ if(!$isPHPEncripted){
60
+ $optionsArray[] = CONTAINS;
61
+ }
62
+ $optionsArray[] = EQUALS;
63
+ if(!$isPHPEncripted){
64
+ $optionsArray[] = STARTS_WITH;
65
+ $optionsArray[] = MORE_THAN;
66
+ $optionsArray[] = LESS_THAN;
67
+ $optionsArray[] = BETWEEN;
68
+ }
69
+ $optionsArray[] = EMPTY_SEARCH;
70
+ if($both)
71
+ {
72
+ if(!$isPHPEncripted){
73
+ $optionsArray[] = NOT_CONTAINS;
74
+ }
75
+ $optionsArray[] = NOT_EQUALS;
76
+ if(!$isPHPEncripted){
77
+ $optionsArray[] = NOT_STARTS_WITH;
78
+ $optionsArray[] = NOT_MORE_THAN;
79
+ $optionsArray[] = NOT_LESS_THAN;
80
+ $optionsArray[] = NOT_BETWEEN;
81
+ }
82
+ $optionsArray[] = NOT_EMPTY;
83
+ }
84
+ return $this->buildSearchOptions($optionsArray, $selOpt, $not, $both);
85
+ }
86
+ }
87
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
88
  ?>
php/classes/controls/TextField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  require_once getabspath('classes/controls/TextControl.php');
3
  class TextField extends TextControl
@@ -44,4 +45,52 @@ class TextField extends TextControl
44
  return $this->cfield;
45
  }
46
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  require_once getabspath('classes/controls/TextControl.php');
4
  class TextField extends TextControl
 
45
  return $this->cfield;
46
  }
47
  }
48
+ =======
49
+ <?php
50
+ require_once getabspath('classes/controls/TextControl.php');
51
+ class TextField extends TextControl
52
+ {
53
+ function __construct($field, $pageObject, $id, $connection)
54
+ {
55
+ EditControl::__construct($field, $pageObject, $id, $connection);
56
+ $this->format = EDIT_FORMAT_TEXT_FIELD;
57
+ }
58
+
59
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
60
+ {
61
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
62
+
63
+ $inputType = $this->pageObject->pSetEdit->getHTML5InputType( $this->field );
64
+ $altAttr = ( $mode == MODE_INLINE_EDIT || $mode == MODE_INLINE_ADD ) && $this->is508 == true ? ' alt="'.$this->strLabel.'" ' : '';
65
+
66
+ $classString = "";
67
+ if( $this->pageObject->isBootstrap() )
68
+ $classString = " class=\"form-control\"";
69
+
70
+ $autocompleteAttr = '';
71
+ if( $mode == MODE_SEARCH ) {
72
+ $autocompleteAttr = 'autocomplete="off"';
73
+ }
74
+
75
+ if( $this->pageObject->pageType == 'register' && $this->field == Security::usernameField() ) {
76
+ $autocompleteAttr = 'autocomplete="username"';
77
+ }
78
+
79
+
80
+ echo '<input id="'.$this->cfield.'" '. $classString . $this->inputStyle.' type="'.$inputType.'" '
81
+ .$autocompleteAttr . ' '
82
+ .$altAttr
83
+ .'name="'.$this->cfield.'" '.$this->pageObject->pSetEdit->getEditParams( $this->field )
84
+ . $this->getPlaceholderAttr()
85
+ .' value="'.runner_htmlspecialchars($value).'">';
86
+
87
+ $this->buildControlEnd($validate, $mode);
88
+ }
89
+
90
+ function getFirstElementId()
91
+ {
92
+ return $this->cfield;
93
+ }
94
+ }
95
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
96
  ?>
php/classes/controls/TimeField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  require_once getabspath('classes/controls/DateTimeControl.php');
3
  class TimeField extends DateTimeControl
@@ -93,4 +94,101 @@ class TimeField extends DateTimeControl
93
  $this->pageObject->AddCSSFile("include/bootstrap/css/bootstrap-datetimepicker.min.css");
94
  }
95
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  require_once getabspath('classes/controls/DateTimeControl.php');
4
  class TimeField extends DateTimeControl
 
94
  $this->pageObject->AddCSSFile("include/bootstrap/css/bootstrap-datetimepicker.min.css");
95
  }
96
  }
97
+ =======
98
+ <?php
99
+ require_once getabspath('classes/controls/DateTimeControl.php');
100
+ class TimeField extends DateTimeControl
101
+ {
102
+ protected $timeAttrs;
103
+
104
+ function __construct($field, $pageObject, $id, $connection)
105
+ {
106
+ EditControl::__construct($field, $pageObject, $id, $connection);
107
+
108
+ $this->format = EDIT_FORMAT_TIME;
109
+ $this->timeAttrs = $this->pageObject->pSetEdit->getFormatTimeAttrs( $this->field );
110
+ }
111
+
112
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
113
+ {
114
+ if( $this->container->pageType == PAGE_LIST )
115
+ $value = prepare_for_db($this->field, $value, "time");
116
+
117
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
118
+
119
+ echo '<input id="'.$this->ctype.'" '.$this->inputStyle.' type="hidden" name="'.$this->ctype.'" value="time">';
120
+
121
+
122
+ if( count( $this->timeAttrs ) )
123
+ {
124
+ $type = $this->pageObject->mobileTemplateMode() ? "time" : "text";
125
+
126
+ $classString = 'class="form-control"';
127
+
128
+ $resultHtml = '<input '.$this->getPlaceholderAttr().' type="'.$type.'" '.$this->inputStyle.' name="'.$this->cfield.'" ' . $classString
129
+ .(($mode==MODE_INLINE_EDIT || $mode==MODE_INLINE_ADD) && $this->is508 == true ? 'alt="'.$this->strLabel.'" ' : '')
130
+ .'id="'.$this->cfield.'" '.$this->pageObject->pSetEdit->getEditParams($this->field);
131
+
132
+ if( $this->timeAttrs["useTimePicker"] && !$this->pageObject->mobileTemplateMode() )
133
+ {
134
+ $convention = $this->timeAttrs["hours"];
135
+ $loc = getLacaleAmPmForTimePicker($convention, true);
136
+ $tpVal = getValForTimePicker($this->type, $value, $loc['locale']);
137
+
138
+ $resultHtml .= ' value="'.runner_htmlspecialchars($tpVal['val']).'">';
139
+
140
+ $resultHtml .= '<span class="input-group-addon" id="trigger-test-' . $this->cfield
141
+ .'"><span class="glyphicon glyphicon-time"></span></span>';
142
+ }
143
+ else
144
+ $resultHtml .=' value="'.runner_htmlspecialchars( $this->getOutputValue( $value ) ).'">';
145
+
146
+
147
+ if ( isRTL() )
148
+ $resultHtml .= "<span></span>"; // for bootstrap calend icon anomaly
149
+
150
+ $resultHtml = '<div class="input-group" '.$this->inputStyle.' >' . $resultHtml . '</div>';
151
+ echo $resultHtml;
152
+ }
153
+
154
+ $this->buildControlEnd($validate, $mode);
155
+ }
156
+
157
+ /**
158
+ * @param Mixed fieldValue
159
+ * @return String
160
+ */
161
+ protected function getOutputValue( $fieldValue )
162
+ {
163
+ if ( IsDateFieldType( $this->type ) )
164
+ return str_format_time( db2time( $fieldValue ) );
165
+
166
+ $numbers = parsenumbers( $fieldValue );
167
+ if( !$numbers )
168
+ return "";
169
+
170
+ while( count( $numbers ) < 3 )
171
+ {
172
+ $numbers[] = 0;
173
+ }
174
+
175
+ if( count( $numbers ) == 6 )
176
+ return str_format_time( array(0, 0, 0, $numbers[3], $numbers[4], $numbers[5]) );
177
+
178
+ if( !$this->pageObject->mobileTemplateMode() )
179
+ return str_format_time( array(0, 0, 0, $numbers[0], $numbers[1], $numbers[2]) );
180
+
181
+ return format_datetime_custom( array(0, 0, 0, $numbers[0], $numbers[1], $numbers[2]), "HH:mm:ss" );
182
+ }
183
+
184
+ function getFirstElementId()
185
+ {
186
+ return $this->cfield;
187
+ }
188
+
189
+ function addCSSFiles() {
190
+ $this->pageObject->AddCSSFile("include/bootstrap/css/bootstrap-datetimepicker.min.css");
191
+ }
192
+ }
193
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
194
  ?>
php/classes/controls/UserControl.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class UserControl extends EditControl
3
  {
@@ -37,4 +38,45 @@ class UserControl extends EditControl
37
  {
38
  }
39
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class UserControl extends EditControl
4
  {
 
38
  {
39
  }
40
  }
41
+ =======
42
+ <?php
43
+ class UserControl extends EditControl
44
+ {
45
+ function buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
46
+ {
47
+ parent::buildControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
48
+ $this->buildUserControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data);
49
+ $this->buildControlEnd($validate, $mode);
50
+ }
51
+
52
+ public function buildUserControl($value, $mode, $fieldNum, $validate, $additionalCtrlParams, $data)
53
+ {
54
+ }
55
+
56
+ public function initUserControl()
57
+ {
58
+ }
59
+
60
+ function getUserSearchOptions()
61
+ {
62
+ return array();
63
+ }
64
+
65
+ /**
66
+ * Form the control specified search options array and built the control's search options markup
67
+ * @param String selOpt The search option value
68
+ * @param Boolean not It indicates if the search option negation is set
69
+ * @param Boolean both It indicates if the control needs 'NOT'-options
70
+ * @return String A string containing options markup
71
+ */
72
+ function getSearchOptions($selOpt, $not, $both)
73
+ {
74
+ return $this->buildSearchOptions($this->getUserSearchOptions(), $selOpt, $not, $both);
75
+ }
76
+
77
+ function init()
78
+ {
79
+ }
80
+ }
81
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
82
  ?>
php/classes/controls/ViewAudioFileField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  include_once getabspath("classes/controls/ViewFileField.php");
3
  class ViewAudioFileField extends ViewFileField
@@ -89,4 +90,97 @@ class ViewAudioFileField extends ViewFileField
89
  }
90
 
91
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  include_once getabspath("classes/controls/ViewFileField.php");
4
  class ViewAudioFileField extends ViewFileField
 
90
  }
91
 
92
  }
93
+ =======
94
+ <?php
95
+ include_once getabspath("classes/controls/ViewFileField.php");
96
+ class ViewAudioFileField extends ViewFileField
97
+ {
98
+ public function showDBValue( &$data, $keylink, $html = true )
99
+ {
100
+ $pageType = $this->container->pageType;
101
+ // print or export
102
+ if( !$html || $pageType == PAGE_EXPORT || $pageType == PAGE_PRINT || $this->container->forExport != '' ) {
103
+ $ret = $this->getTextValue( $data );
104
+ return $html
105
+ ? runner_htmlspecialchars( $ret )
106
+ : $ret;
107
+ }
108
+
109
+ $fileUrls = $this->getFileURLs( $data, $keylink );
110
+
111
+ $controls = array();
112
+ foreach( $fileUrls as $u ) {
113
+ $controls[] = ViewAudioFileField::makeAudioControl( $u );
114
+ }
115
+ return implode( "", $controls );
116
+ }
117
+
118
+ /**
119
+ * @param Array urlData - element of array returned by getFileURLs
120
+ * @return String (HTML)
121
+ */
122
+ public static function makeAudioControl( $urlData ) {
123
+
124
+ $htmlTitle = runner_htmlspecialchars( $urlData["title"] );
125
+ $htmlAltTitle = runner_htmlspecialchars( $urlData["altTitle"] );
126
+ $htmlUrl = runner_htmlspecialchars( $urlData["url"] );
127
+
128
+ return '<figure>'
129
+ .'<figcaption>' . $htmlTitle . '<figcaption>'
130
+ .'<audio controls preload="none" src="' . $htmlUrl . '">'
131
+ .'<a title="' . $htmlAltTitle . '" href="' . $htmlUrl . '">' . $htmlAltTitle . '</a>'
132
+ .'</audio></figure>';
133
+ }
134
+
135
+
136
+ /**
137
+ * @return Array of array(
138
+ * "url" => link to the file
139
+ * "title" => audio label
140
+ * )
141
+ */
142
+ protected function getFileURLs( &$data, $keylink )
143
+ {
144
+ $pSet = $this->pSettings();
145
+ $fileData = $this->getFilesData( $data[ $this->field ] );
146
+ $fieldIsUrl = $pSet->isVideoUrlField( $this->field );
147
+
148
+ $ret = array();
149
+ foreach( $fileData as $file ) {
150
+ if( !$file["name"] ) {
151
+ continue;
152
+ }
153
+ if( !$fieldIsUrl ) {
154
+ if( !$this->fastFileExists( $file["name"] ) ) {
155
+ continue;
156
+ }
157
+ }
158
+ if( $fieldIsUrl ) {
159
+ $url = $file["name"];
160
+ } else {
161
+ $url = projectURL() . $this->getFileUrl( $file, $keylink, false );
162
+ }
163
+ $titleField = $pSet->getAudioTitleField( $this->field );
164
+ if ( $titleField ) {
165
+ $title = $data[ $titleField ];
166
+ $altTitle = $title;
167
+ } else {
168
+ $altTitle = $file["usrName"];
169
+ $title = "";
170
+ }
171
+ $ret[] = array(
172
+ "url" => $url,
173
+ "title" => $title,
174
+ "altTitle" => $altTitle
175
+ );
176
+ }
177
+ return $ret;
178
+ }
179
+
180
+ protected function isUrl() {
181
+ return $this->pSettings()->isVideoUrlField( $this->field );
182
+ }
183
+
184
+ }
185
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
186
  ?>
php/classes/controls/ViewCheckboxField.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class ViewCheckboxField extends ViewControl
3
  {
@@ -52,4 +53,60 @@ class ViewCheckboxField extends ViewControl
52
  return nl2br( $data[ $this->field ] );
53
  }
54
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class ViewCheckboxField extends ViewControl
4
  {
 
53
  return nl2br( $data[ $this->field ] );
54
  }
55
  }
56
+ =======
57
+ <?php
58
+ class ViewCheckboxField extends ViewControl
59
+ {
60
+
61
+ public function getTrueCondition($data)
62
+ {
63
+ if( $this->getHostPageDbType() == nDATABASE_PostgreSQL )
64
+ return $data[$this->field] === "t" || $data[$this->field] !== "f" && $data[$this->field] != 0 && $data[$this->field] != "";
65
+ else
66
+ return $data[$this->field] != 0 && $data[$this->field] != "";
67
+ }
68
+
69
+ public function getPdfValue(&$data, $keylink = "")
70
+ {
71
+ $boolVal = $this->getTrueCondition($data) ? "true" : "false";
72
+ return "{text: '', checkbox: " . $boolVal . "}";
73
+ }
74
+
75
+ public function showDBValue(&$data, $keylink, $html = true )
76
+ {
77
+ $result = "<img src=\"";
78
+ $imgSrc = "images/check_";
79
+
80
+ $imgSrc.= $this->getTrueCondition($data) ? "yes" : "no";
81
+
82
+ $result.= GetRootPathForResources($imgSrc.".gif")."\" border=0";
83
+ if(isEnableSection508())
84
+ $result .= " alt=\" \"";
85
+ $result .= ">";
86
+
87
+ return $result;
88
+ }
89
+
90
+ /**
91
+ * Get the host page's db connection's type
92
+ * @return Number
93
+ */
94
+ protected function getHostPageDbType()
95
+ {
96
+ global $cman;
97
+ return $cman->byTable( $this->container->tName )->dbType;
98
+ }
99
+
100
+ /**
101
+ * Get the field's content that will be exported
102
+ * @prarm &Array data
103
+ * @prarm String keylink
104
+ * @return String
105
+ */
106
+ public function getExportValue(&$data, $keylink = "", $html = false )
107
+ {
108
+ return nl2br( $data[ $this->field ] );
109
+ }
110
+ }
111
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
112
  ?>
php/classes/controls/ViewControl.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class ViewControl
3
  {
@@ -968,4 +969,976 @@ class ViewControlTypes
968
  $this->viewTypes[FORMAT_HTML] = "ViewHTMLField";
969
  }
970
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
971
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class ViewControl
4
  {
 
969
  $this->viewTypes[FORMAT_HTML] = "ViewHTMLField";
970
  }
971
  }
972
+ =======
973
+ <?php
974
+ class ViewControl
975
+ {
976
+ public $field = "";
977
+ public $displayField = null;
978
+ /**
979
+ * Reference to ViewControlsContainer instance
980
+ */
981
+ public $container = null;
982
+ /**
983
+ * Reference to RunnerPage (or its descendant) instance if its exist
984
+ */
985
+ public $pageObject = null;
986
+ /**
987
+ * A flag indicating whether the support for section 508 is on
988
+ * @var {bool}
989
+ */
990
+ public $is508 = false;
991
+ public $fieldType = null;
992
+ public $viewFormat = FORMAT_NONE;
993
+ public $editFormat = EDIT_FORMAT_NONE;
994
+ public $localControlsContainer = null;
995
+ public $linkAndDisplaySame = null;
996
+
997
+ /**
998
+ * The search clause object obtained from the page's object
999
+ */
1000
+ public $searchClauseObj = null;
1001
+
1002
+ /**
1003
+ * Storage for control settings. It fills in the init() function.
1004
+ * @var {array}
1005
+ */
1006
+ public $settings = array();
1007
+
1008
+ /**
1009
+ * Array of view controls map
1010
+ *
1011
+ * @var array
1012
+ */
1013
+ public $viewControlsMap = array();
1014
+
1015
+ /**
1016
+ * Set to true, if it is custom user control
1017
+ * @var boolean
1018
+ */
1019
+ protected $userControl = false;
1020
+
1021
+ /**
1022
+ * A flag indicating whether to higlight search results ot not
1023
+ * @var boolean
1024
+ */
1025
+ public $searchHighlight = false;
1026
+
1027
+ /**
1028
+ * A flag indicating whether the view control is used for a filter or not
1029
+ * @var boolean
1030
+ */
1031
+ public $isUsedForFilter = false;
1032
+
1033
+ /**
1034
+ * A flag indicating if the field is table based multiselect
1035
+ * lookup with the same link and displayed fields
1036
+ * and needs comma/quotes processing
1037
+ */
1038
+ protected $needLookupValueProcessing = true;
1039
+
1040
+ /**
1041
+ * A flag indicating if the field is lookup
1042
+ */
1043
+ protected $isFieldLookup = false;
1044
+
1045
+ protected $useUTF8 = false;
1046
+
1047
+ /**
1048
+ * addJSFiles
1049
+ * Add control JS files to page object
1050
+ */
1051
+ public function addJSFiles()
1052
+ {
1053
+ //example
1054
+ // $this->AddJSFile("include/mupload.js");
1055
+ }
1056
+
1057
+ /**
1058
+ * addCSSFiles
1059
+ * Add control CSS files to page object
1060
+ */
1061
+ public function addCSSFiles()
1062
+ {
1063
+ //example
1064
+ // $this->AddCSSFile("include/mupload.css");
1065
+ }
1066
+
1067
+ /**
1068
+ * The container's AddCSSFile method wrapper
1069
+ * @param {String}
1070
+ */
1071
+ public function AddCSSFile($fileName)
1072
+ {
1073
+ $this->getContainer()->AddCSSFile($fileName);
1074
+ }
1075
+
1076
+ /**
1077
+ * The container's AddJSFile method wrapper
1078
+ * @param {String}
1079
+ */
1080
+ public function AddJSFile($fileName, $req1="", $req2="", $req3="")
1081
+ {
1082
+ $this->getContainer()->AddJSFile($fileName, $req1, $req2, $req3);
1083
+ }
1084
+
1085
+ public function pSettings() {
1086
+ return $this->getContainer()->pSet;
1087
+ }
1088
+
1089
+ public function getContainer()
1090
+ {
1091
+ if(!is_null($this->pageObject))
1092
+ return $this->pageObject;
1093
+ else
1094
+ return $this->container;
1095
+ }
1096
+
1097
+ public function __construct($field, $container, $pageObject = null)
1098
+ {
1099
+ $this->useUTF8 = "utf-8" == "utf-8";
1100
+ $this->field = $field;
1101
+ $this->container = $container;
1102
+ $this->pageObject = $pageObject;
1103
+ $this->is508 = isEnableSection508();
1104
+
1105
+ $this->fieldType = $container->pSet->getFieldType($this->field);
1106
+ $this->viewFormat = $container->pSet->getViewFormat($this->field);
1107
+ $this->editFormat = $container->pSet->getEditFormat($this->field);
1108
+
1109
+ if( $this->pageObject ) {
1110
+ $this->searchClauseObj = $this->pageObject->searchClauseObj;
1111
+ if ( $this->searchClauseObj )
1112
+ $this->searchHighlight = $container->searchHighlight && $this->searchClauseObj->searchStarted();
1113
+ }
1114
+ }
1115
+
1116
+ /**
1117
+ * Get the field's content that will be exported
1118
+ * @prarm &Array data
1119
+ * @prarm String keylink
1120
+ * @return String
1121
+ */
1122
+ public function getExportValue(&$data, $keylink = "", $html = false )
1123
+ {
1124
+ return $this->showDBValue($data, $keylink, $html );
1125
+ }
1126
+
1127
+
1128
+ public function getPdfValue(&$data, $keylink = "")
1129
+ {
1130
+ return "'" . jsreplace( $this->showDBValue($data, $keylink, false) ) . "'";
1131
+ }
1132
+
1133
+ /**
1134
+ * Get the field's content
1135
+ * @param &Array data
1136
+ * @param String keylink
1137
+ * @return String
1138
+ */
1139
+ public function showDBValue(&$data, $keylink, $html = true )
1140
+ {
1141
+ $value = $data[$this->field];
1142
+
1143
+ if(IsBinaryType($this->fieldType))
1144
+ {
1145
+ $value = "LONG BINARY DATA - CANNOT BE DISPLAYED";
1146
+ $this->searchHighlight = false;
1147
+ }
1148
+
1149
+ if($value === false)
1150
+ $value = "";
1151
+
1152
+
1153
+ if($this->editFormat == EDIT_FORMAT_CHECKBOX && $this->viewFormat == FORMAT_NONE)
1154
+ {
1155
+ if($value && $value!=0)
1156
+ $value = "Yes";
1157
+ else
1158
+ $value = "No";
1159
+
1160
+ $this->searchHighlight = false;
1161
+ }
1162
+
1163
+ if($this->container->forExport == "excel" || $this->container->forExport == "csv")
1164
+ {
1165
+ return $value;
1166
+ }
1167
+
1168
+ $processedText = $this->processText($value, $keylink, $html);
1169
+ if( $html )
1170
+ return nl2br( $processedText );
1171
+ return $processedText;
1172
+ }
1173
+
1174
+ /**
1175
+ * @param &Array data
1176
+ * @return String
1177
+ */
1178
+ public function getTextValue(&$data)
1179
+ {
1180
+ return $data[ $this->field ];
1181
+ }
1182
+
1183
+ /**
1184
+ * Format the text trunceting it or highlighting the search word within this text.
1185
+ * @param String value The field's content
1186
+ * @param String keylink
1187
+ * @return String
1188
+ */
1189
+ public function processText($value, $keylink, $html = true )
1190
+ {
1191
+ $isMobileLookup = false;
1192
+ $inlineOrFlyMode = false;
1193
+ $pageType = $this->container->pageType;
1194
+ if( !is_null($this->pageObject) )
1195
+ {
1196
+ $mode = $this->pageObject->mode;
1197
+ $isMobileLookup = ($mode == LIST_LOOKUP) && $this->pageObject->mobileTemplateMode();
1198
+ $inlineOrFlyMode = $pageType == PAGE_EDIT && ($mode == EDIT_INLINE || $mode == EDIT_POPUP) || $pageType == PAGE_ADD && ($mode == ADD_INLINE || $mode == ADD_POPUP);
1199
+ }
1200
+ $isDetailPreview = $this->container->isDetailsPreview;
1201
+
1202
+ if( $pageType == PAGE_ADD || $pageType == PAGE_EDIT )
1203
+ $pageType = PAGE_VIEW;
1204
+
1205
+ $isPagePrint = ($pageType == PAGE_RPRINT && $this->container->forExport) || $pageType == PAGE_PRINT || $pageType == PAGE_RPRINT;
1206
+
1207
+ if( $this->editFormat == EDIT_FORMAT_LOOKUP_WIZARD )
1208
+ {
1209
+ $this->isFieldLookup = true;
1210
+ $this->needLookupValueProcessing = $this->checkIfLookupValueIsToProcess();
1211
+ $value = $this->processMultiselectLWValue($value);
1212
+ }
1213
+
1214
+ $cNumberOfChars = $this->container->pSet->getNumberOfChars($this->field);
1215
+ $needShortening = $this->textNeedsTruncating($value, $cNumberOfChars);
1216
+
1217
+ $isReportPage = $pageType == PAGE_REPORT || $pageType == PAGE_MASTER_INFO_REPORT;
1218
+ $isListPage = $pageType == PAGE_LIST || $pageType == PAGE_MASTER_INFO_LIST;
1219
+
1220
+ if( $html && $needShortening && ( $isListPage || $isReportPage || $inlineOrFlyMode ) && !$isMobileLookup && !$isDetailPreview && $keylink != "" )
1221
+ return $this->getShorteningTextAndMoreLink($value, $cNumberOfChars, $keylink, $mode);
1222
+
1223
+ if( $needShortening && ($isPagePrint || $isMobileLookup || $isDetailPreview) )
1224
+ return $this->getShorteningText($value, $cNumberOfChars, $html);
1225
+
1226
+ return $this->getText($value, $html );
1227
+ }
1228
+
1229
+
1230
+ /**
1231
+ * Check if the text needs truncating
1232
+ * @param String value The field's content
1233
+ * @param Number cNumberOfChars The number of chars from the 'value' string that will be visible after truncation
1234
+ * @return Boolean
1235
+ */
1236
+ protected function textNeedsTruncating($value, $cNumberOfChars)
1237
+ {
1238
+ return !$this->isUsedForFilter && !$this->container->fullText && $cNumberOfChars > 0 && runner_strlen($value) > $cNumberOfChars;
1239
+ }
1240
+
1241
+ /**
1242
+ * The object's wrapper for GetShorteningForLargeText function
1243
+ * @param String value The field's content
1244
+ * @param Number cNumberOfChars The number of chars up to truncation
1245
+ * @return String
1246
+ */
1247
+ protected function getShorteningText($value, $cNumberOfChars, $html = true )
1248
+ {
1249
+ $tail = "...";
1250
+ if( $html ) {
1251
+ $tail = "&nbsp;...";
1252
+ }
1253
+ return GetShorteningForLargeText($value, $cNumberOfChars, $html ).$tail;
1254
+ }
1255
+
1256
+ /**
1257
+ * Get the More link following the truncated and highlighted field's content
1258
+ * @param String value The field's content
1259
+ * @param Number cNumberOfChars The number of chars from the 'value' string that will be visible after truncation
1260
+ * @param String keylink
1261
+ * @param Boolean isLookup An indicator showing if this is a lookup list page control
1262
+ * @return String
1263
+ */
1264
+ protected function getShorteningTextAndMoreLink($value, $cNumberOfChars, $keylink, $mode)
1265
+ {
1266
+ $truncatedValue = GetShorteningForLargeText($value, $cNumberOfChars);
1267
+ if( $this->searchHighlight )
1268
+ $truncatedValue = $this->highlightTruncatedBeforeMore($value, $truncatedValue, $cNumberOfChars, $cNumberOfChars);
1269
+
1270
+ $tName = $this->getContainer()->tName;
1271
+ $params = array();
1272
+ $params[] = 'pagetype='.$this->container->pSet->_viewPage;
1273
+ $params[] = 'table='.GetTableURL($tName);
1274
+ $params[] = 'field='.rawurlencode($this->field);
1275
+ /* $keylink starts with & */
1276
+ $params[] = substr( $keylink, 1 );
1277
+ $params[] = 'page='.$this->container->pSet->pageName();
1278
+
1279
+ if ( $mode == LIST_DASHBOARD )
1280
+ $params[] = 'mode='.$mode;
1281
+
1282
+ if ( $mode == LIST_LOOKUP )
1283
+ {
1284
+ $params[] = 'maintable='.$this->pageObject->mainTable;
1285
+ $params[] = 'mainfield='.$this->pageObject->mainField;
1286
+ }
1287
+
1288
+ $label = $this->container->pSet->label( $this->field );
1289
+ $dataField = 'data-fieldlabel="'.runner_htmlspecialchars( $label ).'"';
1290
+
1291
+ return $truncatedValue.' <a href="javascript:void(0);" data-gridlink data-query="'.GetTableLink('fulltext', '', implode('&',$params)).'" '.$dataField.'>'
1292
+ ."More".'&nbsp;...</a>';
1293
+ }
1294
+
1295
+ /**
1296
+ * Get the encoded and highlighted text
1297
+ * @param String value
1298
+ * @return String
1299
+ */
1300
+ protected function getText($value, $html = true )
1301
+ {
1302
+ if( !$html ) {
1303
+ return $value;
1304
+ }
1305
+ $value = runner_htmlspecialchars($value);
1306
+ if( $this->searchHighlight )
1307
+ $value = $this->highlightSearchWord($value, true, "");
1308
+
1309
+ return $value;
1310
+ }
1311
+
1312
+ /**
1313
+ * Check if the fiedl is the project or database table's
1314
+ * multiselect lookup wizard with the same link and display field
1315
+ */
1316
+ protected function checkIfLookupValueIsToProcess()
1317
+ {
1318
+ $pSet = $this->container->pSet;
1319
+
1320
+ if( ($pSet->getLookupType($this->field) == LT_LOOKUPTABLE || $pSet->getLookupType($this->field) == LT_QUERY) &&
1321
+ $pSet->getLinkField($this->field) == $pSet->getDisplayField($this->field) && $pSet->multiSelect($this->field) )
1322
+ {
1323
+ return true;
1324
+ }
1325
+
1326
+ return false;
1327
+ }
1328
+
1329
+ /**
1330
+ * Remove excessive quotes for the multiselect lookup wizard field with
1331
+ * the same display and link field
1332
+ * @param string value
1333
+ * @return string
1334
+ */
1335
+ protected function processMultiselectLWValue($value)
1336
+ {
1337
+ if( !$this->needLookupValueProcessing )
1338
+ return $value;
1339
+
1340
+ return implode(",", splitLookupValues($value));
1341
+ }
1342
+
1343
+ /**
1344
+ * Highlight the search word within the $value string
1345
+ * @param String value The field's content
1346
+ * @param Boolean encoded An indicator showing if the field's content is htmlspecialchars encoded
1347
+ * @param String dbValue The database field's value
1348
+ * @return string
1349
+ */
1350
+ public function highlightSearchWord($value, $encoded, $dbValue = "")
1351
+ {
1352
+ if( $dbValue == "" )
1353
+ {
1354
+ $dbValue = $value;
1355
+ }
1356
+
1357
+ $lookupParams = $this->getLookupParams();
1358
+ $highlightData = $this->searchClauseObj->getSearchHighlightingData($this->field, $dbValue, $encoded, $lookupParams);
1359
+ if( !$highlightData )
1360
+ {
1361
+ return $value;
1362
+ }
1363
+ return $this->getValueHighlighted($value, $highlightData);
1364
+ }
1365
+
1366
+ /**
1367
+ * Highlight a search word for number-like fields
1368
+ * @param String value
1369
+ * @param Boolean encoded
1370
+ * @param String dbValue
1371
+ * @return string
1372
+ */
1373
+ public function highlightSearchWordForNumber( $value, $encoded, $dbValue )
1374
+ {
1375
+ $lookupParams = $this->getLookupParams();
1376
+ $highlightData = $this->searchClauseObj->getSearchHighlightingData( $this->field, $dbValue, $encoded, $lookupParams, true );
1377
+ if( $highlightData )
1378
+ return $this->getValueHighlighted( $value, $highlightData );
1379
+
1380
+ return $value;
1381
+ }
1382
+
1383
+ /**
1384
+ * Form the the string with the search word highlighted
1385
+ * @param String value The field's content
1386
+ * @param Array highlightData
1387
+ * @return string
1388
+ */
1389
+ public function getValueHighlighted($value, $highlightData)
1390
+ {
1391
+ $searchOpt = $highlightData['searchOpt'];
1392
+ $searchWordsPattern = $this->getSearchWordPattern($highlightData['searchWords'], false);
1393
+
1394
+ switch($searchOpt)
1395
+ {
1396
+ case 'Equals':
1397
+ return $this->addHighlightingSpan($value);
1398
+
1399
+ case 'Starts with':
1400
+ return preg_replace('/(^'.$searchWordsPattern.')/i', $this->addHighlightingSpan('$1'), $value);
1401
+
1402
+ case 'Contains':
1403
+ $pattern = '/('.$searchWordsPattern.')/i';
1404
+
1405
+ if( !$this->haveTheSameSpChReference($pattern, $value) )
1406
+ return preg_replace($pattern, $this->addHighlightingSpan('$1'), $value);
1407
+
1408
+ return $this->highlightValueWithSpecialChars($value, $pattern);
1409
+
1410
+ default:
1411
+ return $value;
1412
+ }
1413
+ }
1414
+
1415
+ /**
1416
+ * search highliting for view as number, percent
1417
+ * @param String value The field's content
1418
+ * @param Array highlightData
1419
+ * @return string
1420
+ */
1421
+ public function getNumberValueHighlighted( $value, $highlightData ) {
1422
+ $searchWordArr = array();
1423
+ $decimalPlaces = $this->container->pSet->isDecimalDigits( $this->field );
1424
+ $quantifier = $decimalPlaces <= 1 ? '?' : '{1,'.$decimalPlaces.'}';
1425
+
1426
+ foreach( $highlightData['searchWords'] as $searchWord ) {
1427
+ $currSearchWord = $searchWord;
1428
+ if( !preg_match( '/^[\d]+$/', $searchWord ) ) {
1429
+ $currSearchWord = $this->formatSearchWord( $searchWord );
1430
+ $currSearchWord = preg_replace( '/0'.$quantifier.'$/', '', $currSearchWord );
1431
+ $currSearchWord = preg_replace( '/\.$/', '', $currSearchWord );
1432
+ }
1433
+
1434
+ $searchWordArray = str_split( $currSearchWord );
1435
+ // chain of numbers an possible separators
1436
+ $searchWordArr[] = implode('[^\d]?', $searchWordArray );
1437
+ }
1438
+
1439
+ $searchWord = implode( '|', $searchWordArr );
1440
+ $searchOpt = $highlightData['searchOpt'];
1441
+
1442
+ switch( $searchOpt ) {
1443
+ case 'Equals':
1444
+ return $this->addHighlightingSpan( $value );
1445
+
1446
+ case 'Starts with':
1447
+ return preg_replace('/^('.$searchWord.')/', $this->addHighlightingSpan('$1'), $value);
1448
+
1449
+ case 'Contains':
1450
+ return preg_replace('/('.$searchWord.')/', $this->addHighlightingSpan('$1'), $value);
1451
+
1452
+ default:
1453
+ return $value;
1454
+ }
1455
+ }
1456
+
1457
+ /**
1458
+ * @param String searchWord
1459
+ * return String
1460
+ */
1461
+ protected function formatSearchWord( $searchWord ) {
1462
+ return $searchWord;
1463
+ }
1464
+
1465
+ /**
1466
+ * Check if the pattern string is contained in any special chars codes
1467
+ * occuring in the value string.
1468
+ * @param string pattern
1469
+ * @param string value
1470
+ * @return array
1471
+ */
1472
+ protected function haveTheSameSpChReference($pattern, $value)
1473
+ {
1474
+ $scContainedPattern = $this->getSpecialCharsContainingPattern($pattern);
1475
+ $scFromValue = $this->getSpecialCharsFromString($value);
1476
+ foreach($scContainedPattern as $sc)
1477
+ {
1478
+ if( array_search($sc, $scFromValue) !== FALSE )
1479
+ return true;
1480
+ }
1481
+ return false;
1482
+ }
1483
+
1484
+ /**
1485
+ * Get the array of special chars contained the pattern
1486
+ * @param string pattern
1487
+ * @return array
1488
+ */
1489
+ protected function getSpecialCharsContainingPattern($pattern)
1490
+ {
1491
+ $chars = array('&amp;', '&quot;', '&lt;', '&gt;');
1492
+ $csArray = array();
1493
+ foreach($chars as $char)
1494
+ {
1495
+ if( preg_match($pattern, $char, $matches) )
1496
+ {
1497
+ if( $matches[0] != $char )
1498
+ $csArray[] = $char;
1499
+ }
1500
+ }
1501
+ return $csArray;
1502
+ }
1503
+
1504
+ /**
1505
+ * Get the array of special chars extracted from the string passed
1506
+ * @param string str
1507
+ * @return array
1508
+ */
1509
+ protected function getSpecialCharsFromString($str)
1510
+ {
1511
+ $chars = array('&amp;', '&quot;', '&lt;', '&gt;');
1512
+ $csArray = array();
1513
+ foreach($chars as $char)
1514
+ {
1515
+ if( strpos($str, $char) !== FALSE )
1516
+ $csArray[] = $char;
1517
+ }
1518
+
1519
+ return $csArray;
1520
+ }
1521
+
1522
+ /**
1523
+ * Split the string into array that contains all the string's not overlaping
1524
+ * fragments that are delimeter-substrings and all non-delimeter parts
1525
+ * adjacent with delimiter-substrings. These fragments are indexed in the
1526
+ * same order as they occur in the string.
1527
+ * @param String pattern The regular expression setting delimeter strings
1528
+ * @param String str The string that is split based on its delimiter-substrings occurrences
1529
+ * @return Array
1530
+ */
1531
+ protected function getSplitStringWithCapturedDelimiters($pattern, $str)
1532
+ {
1533
+ $resArray = array();
1534
+
1535
+ if( !strlen($str) )
1536
+ return $resArray ;
1537
+
1538
+ if( !preg_match_all($pattern, $str, $matches) )
1539
+ {
1540
+ $resArray[] = $str;
1541
+ return $resArray;
1542
+ }
1543
+
1544
+ $delimiters = $matches[0];
1545
+ $strArray = preg_split($pattern, $str);
1546
+ foreach($strArray as $key=>$item)
1547
+ {
1548
+ $resArray[] = $item;
1549
+ if( isset( $delimiters[$key] ) )
1550
+ $resArray[] = $delimiters[$key];
1551
+ }
1552
+
1553
+ return $resArray;
1554
+ }
1555
+
1556
+ /**
1557
+ * Highlight the value escaping the special chars codes
1558
+ * @param string pattern
1559
+ * @param string value
1560
+ * @return string
1561
+ */
1562
+ protected function highlightValueWithSpecialChars($value, $pattern)
1563
+ {
1564
+ $chars = array('&amp;', '&quot;', '&lt;', '&gt;');
1565
+ foreach($chars as $char)
1566
+ {
1567
+ $valueArr = $this->getSplitStringWithCapturedDelimiters('/'.$char.'/', $value);
1568
+ if( count($valueArr) == 1 || !preg_match($pattern, $char, $matches) )
1569
+ continue;
1570
+
1571
+ $valueArr2 = array();
1572
+
1573
+ foreach($valueArr as $key=>$part)
1574
+ {
1575
+ if( $part != $char )
1576
+ $valueArr2[] = preg_replace($pattern, $this->addHighlightingSpan('$1'), $part);
1577
+ else
1578
+ $valueArr2[] = $char;
1579
+ }
1580
+
1581
+ $value = implode("",$valueArr2);
1582
+ }
1583
+ return $value;
1584
+ }
1585
+
1586
+ /**
1587
+ * Check if the item string has HTML entities
1588
+ * @param String item
1589
+ * @return Boolean
1590
+ */
1591
+ protected function hasHTMLEntities($item)
1592
+ {
1593
+ if( preg_match_all("/&[^&;]{3,7};/", $item, $matches) )
1594
+ {
1595
+ foreach($matches[0] as $entity)
1596
+ {
1597
+ $data = getHTMLEntityData($entity);
1598
+ if( $data['isHTMLEntity'] )
1599
+ return true;
1600
+ }
1601
+ }
1602
+ return false;
1603
+ }
1604
+
1605
+ /**
1606
+ * Highlight item string basing on the pattern value
1607
+ * skipping the HTML entities
1608
+ * @param String item
1609
+ * @param String pattern
1610
+ * @return String
1611
+ */
1612
+ protected function highlightValueWithHTMLEntities($item, $pattern)
1613
+ {
1614
+ $valueArr = $this->getSplitStringWithCapturedDelimiters("/&[^&;]{3,7};/", $item);
1615
+ $valueArr2 = array();
1616
+ foreach($valueArr as $subitem)
1617
+ {
1618
+ $data = getHTMLEntityData($subitem);
1619
+ if( $data['isHTMLEntity'] )
1620
+ $valueArr2[] = $subitem;
1621
+ else
1622
+ $valueArr2[] = preg_replace($pattern, $this->addHighlightingSpan('$1'), $subitem);
1623
+ }
1624
+ return implode("",$valueArr2);
1625
+ }
1626
+
1627
+ /**
1628
+ * Get the lookup params and settings to pass it
1629
+ * to the searchClause object's getSearchHighlightingData method
1630
+ * @return Array
1631
+ */
1632
+ protected function getLookupParams()
1633
+ {
1634
+ $lookupParams = array();
1635
+
1636
+ if( $this->isFieldLookup )
1637
+ {
1638
+ $pSet = $this->container->pSet;
1639
+ $lookupParams["multiselect"] = $pSet->multiSelect($this->field);
1640
+ $lookupParams["needLookupProcessing"] = $this->needLookupValueProcessing;
1641
+ //linkFieldValue and originLinkValue params are set for looku fields with distinct Link and Displayed fields only
1642
+ $lookupParams["linkFieldValue"] = $this->container->linkFieldValues[$this->field];
1643
+ //originLinkValue param is set for multiselet lookups only
1644
+ $lookupParams["originLinkValue"] = $this->container->originlinkValues[$this->field];
1645
+ }
1646
+ return $lookupParams;
1647
+ }
1648
+
1649
+ /**
1650
+ * Get the first search word from the text truncating field's value
1651
+ * @param Array searchWords
1652
+ * @param String value The raw field's value
1653
+ * @return String
1654
+ */
1655
+ protected function getFirstSearchWordInLargeText($searchWords, $value)
1656
+ {
1657
+ $searchWordsPattern = $this->getSearchWordPattern($searchWords, false);
1658
+
1659
+ if( preg_match('/'.$searchWordsPattern.'/i', $value, $matches) )
1660
+ return $matches[0];
1661
+
1662
+ return $searchWords[0];
1663
+ }
1664
+
1665
+ /**
1666
+ * Format the string before the "More ..." link and highlight a search word depending on the search option's value.
1667
+ * @param String value The raw field's content
1668
+ * @param String truncatedValue The truncated, htmlspecialchars encoded field's content
1669
+ * @param Number cNumberOfChars
1670
+ * @prarm Number contenLength The length of the truncated value
1671
+ * @return string
1672
+ */
1673
+ protected function highlightTruncatedBeforeMore($value, $truncatedValue, $cNumberOfChars, $contenLength)
1674
+ {
1675
+ $lookupParams = $this->getLookupParams();
1676
+ $highlightData = $this->searchClauseObj->getSearchHighlightingData($this->field, $value, false, $lookupParams);
1677
+ if(!$highlightData)
1678
+ {
1679
+ return $truncatedValue;
1680
+ }
1681
+
1682
+ $searchWord = $this->getFirstSearchWordInLargeText($highlightData['searchWords'], $value);
1683
+ $searchWordEncoded = runner_htmlspecialchars($searchWord);
1684
+ $highlighting = $this->addHighlightingSpan($searchWordEncoded);
1685
+ $searchOpt = $highlightData['searchOpt'];
1686
+
1687
+ switch ($searchOpt)
1688
+ {
1689
+ case 'Equals':
1690
+ return $this->addHighlightingSpan($truncatedValue);
1691
+
1692
+ case 'Starts with':
1693
+ if( strlen($searchWordEncoded) > strlen($truncatedValue) )
1694
+ return $this->addHighlightingSpan($truncatedValue);
1695
+
1696
+ return preg_replace('/^'.preg_quote($searchWordEncoded,"/").'/i', $highlighting, $truncatedValue);
1697
+
1698
+ case 'Contains':
1699
+ $regExpModifier = $this->useUTF8 ? 'u' : '';
1700
+
1701
+ $firstPos = $this->getFistOccurencePosition($value, $searchWord, $searchWordEncoded);
1702
+ $lastPos = $this->getLastOccurencePosition($value, $searchWord, $searchWordEncoded);
1703
+ $searchWordEncodedLen = runner_strlen($searchWordEncoded);
1704
+ $truncLen = runner_strlen($truncatedValue);
1705
+
1706
+ $pattern = '/('.$this->getSearchWordPattern($highlightData['searchWords'], true).')/i';
1707
+
1708
+ if( $lastPos + $searchWordEncodedLen <= $truncLen || $firstPos + $searchWordEncodedLen <= $truncLen )
1709
+ {
1710
+ if( !$this->haveTheSameSpChReference($pattern, $truncatedValue) )
1711
+ return preg_replace($pattern.$regExpModifier, $this->addHighlightingSpan('$1'), $truncatedValue);
1712
+
1713
+ return $this->highlightValueWithSpecialChars($truncatedValue, $pattern.$regExpModifier);
1714
+ }
1715
+
1716
+ if( $firstPos > $truncLen )
1717
+ {
1718
+ $newNumberOfChars = ceil($cNumberOfChars / 2);
1719
+ $qNumberOfChars = ceil($cNumberOfChars / 4);
1720
+ $firstPosDecoded = runner_strpos($value, $searchWord);
1721
+
1722
+ $truncSubsr = runner_substr($value, 0, $cNumberOfChars);
1723
+ $valueSubstr = runner_substr($value, $firstPosDecoded - $qNumberOfChars, $qNumberOfChars + runner_strlen($searchWord));
1724
+ $truncSubsr = runner_substr($truncSubsr, 0, $newNumberOfChars);
1725
+ $valueSubstr = runner_htmlspecialchars($valueSubstr);
1726
+
1727
+ $pattern = '/('.preg_quote($searchWordEncoded,"/").')/i';
1728
+
1729
+ if( !$this->haveTheSameSpChReference($pattern, $valueSubstr) )
1730
+ $valueSubstr = preg_replace($pattern.$regExpModifier, $highlighting, $valueSubstr);
1731
+ else
1732
+ $valueSubstr = $this->highlightValueWithSpecialChars($valueSubstr, $pattern.$regExpModifier);
1733
+
1734
+ return runner_htmlspecialchars($truncSubsr)."&nbsp;&lt;...&gt;&nbsp;".$valueSubstr;;
1735
+ }
1736
+
1737
+ return runner_substr($truncatedValue, 0, $firstPos).$highlighting;
1738
+
1739
+ default:
1740
+ return $truncatedValue;
1741
+ }
1742
+ }
1743
+
1744
+ /**
1745
+ * Get the first searchWord occurence in the encoded value string
1746
+ * @param String value
1747
+ * @param String searchWord
1748
+ * @param String searchWordEncoded
1749
+ * @return Number
1750
+ */
1751
+ protected function getFistOccurencePosition($value, $searchWord, $searchWordEncoded)
1752
+ {
1753
+ $planeFirstPos = strpos($value, $searchWord);
1754
+ $planeSubstr = substr($value, 0, $planeFirstPos);
1755
+ $encodedPlaneSubstr = runner_htmlspecialchars($planeSubstr);
1756
+
1757
+ return runner_strpos( runner_htmlspecialchars($value), $searchWordEncoded, runner_strlen($encodedPlaneSubstr) );
1758
+ }
1759
+
1760
+ /**
1761
+ * Get the last searchWord occurence in the encoded value string
1762
+ * @param String value
1763
+ * @param String searchWord
1764
+ * @param String searchWordEncoded
1765
+ * @return Number
1766
+ */
1767
+ protected function getLastOccurencePosition($value, $searchWord, $searchWordEncoded)
1768
+ {
1769
+ $planeLastPos = strrpos($value, $searchWord);
1770
+ $planeSubstr = substr($value, 0, $planeLastPos);
1771
+ $encodedPlaneSubstr = runner_htmlspecialchars($planeSubstr);
1772
+
1773
+ return runner_strrpos(runner_htmlspecialchars($value), $searchWordEncoded, runner_strlen($encodedPlaneSubstr));
1774
+ }
1775
+
1776
+ /**
1777
+ * Get common search words pattern
1778
+ * @param Array searchWords
1779
+ * @param Boolean encoded
1780
+ * @return String
1781
+ */
1782
+ protected function getSearchWordPattern($searchWords, $encoded = false)
1783
+ {
1784
+ $searchWordsPatterns = array();
1785
+ foreach($searchWords as $searchWord)
1786
+ {
1787
+ $wordPattern = preg_quote($searchWord, "/");
1788
+ if( $encoded )
1789
+ $wordPattern = runner_htmlspecialchars($wordPattern);
1790
+
1791
+ $searchWordsPatterns[] = $wordPattern;
1792
+ }
1793
+ return implode('|', $searchWordsPatterns);
1794
+ }
1795
+
1796
+ /**
1797
+ * Wrap the string value with a span element
1798
+ * @param String str
1799
+ * @return String
1800
+ */
1801
+ public function addHighlightingSpan($str)
1802
+ {
1803
+ return '<span class="r-search-highlight">'.$str.'</span>';
1804
+ }
1805
+
1806
+ public function & getJSControl()
1807
+ {
1808
+ if(!isset($this->getContainer()->viewControlsMap["controls"]))
1809
+ $this->getContainer()->viewControlsMap["controls"] = array();
1810
+
1811
+ for($i = 0; $i < count($this->getContainer()->viewControlsMap["controls"]); $i++)
1812
+ {
1813
+ if($this->getContainer()->viewControlsMap["controls"][$i]["fieldName"] == $this->field)
1814
+ return $this->getContainer()->viewControlsMap["controls"][$i];
1815
+ }
1816
+
1817
+ $controlData = array("fieldName" => $this->field, "viewFormat" => $this->viewFormat);
1818
+ $this->getContainer()->viewControlsMap["controls"][] = $controlData ;
1819
+ return $controlData;
1820
+ }
1821
+
1822
+ /**
1823
+ * addJSControlSetting
1824
+ * Add setting for JS control to controls map
1825
+ * @param {string} setting name
1826
+ * @param {object} setting value
1827
+ */
1828
+ public function addJSControlSetting($name, $value)
1829
+ {
1830
+ $JScontrol =& $this->getJSControl();
1831
+ $JScontrol[$name] = $value;
1832
+ }
1833
+
1834
+ /**
1835
+ * Check for need to load the javascript files
1836
+ * @return boolean
1837
+ */
1838
+ public function neededLoadJSFiles()
1839
+ {
1840
+ switch ($this->getContainer()->pageType)
1841
+ {
1842
+ case PAGE_PRINT:
1843
+ return false;
1844
+ default:
1845
+ return true;
1846
+ }
1847
+ }
1848
+
1849
+ /**
1850
+ * Returns true if it is user control
1851
+ * @return boolean
1852
+ */
1853
+ public function isUserControl()
1854
+ {
1855
+ return $this->userControl && $this->userControl === true;
1856
+ }
1857
+
1858
+ /**
1859
+ * Returns css code for thumbnail size optionally wrapped into style="" attribute
1860
+ */
1861
+ protected function getThumbnailSizeStyle($returnStyleAttr = true)
1862
+ {
1863
+ $width = $this->container->pSet->getThumbnailSize($this->field);
1864
+ if(!$width)
1865
+ return "";
1866
+ $style = 'max-width:'.$width.'px; max-height:'.$width.'px;';
1867
+ if( $returnStyleAttr )
1868
+ return ' style="'.$style.'"';
1869
+ return $style;
1870
+ }
1871
+
1872
+ /**
1873
+ * Returns css code for image size optionally wrapped into style="" attribute
1874
+ */
1875
+ protected function getImageSizeStyle($returnStyleAttr = true)
1876
+ {
1877
+ $imgWidth = $this->container->pSet->getImageWidth($this->field);
1878
+ $imgHeight = $this->container->pSet->getImageHeight($this->field);
1879
+ if(!$imgWidth && !$imgHeight)
1880
+ return "";
1881
+ $style = '';
1882
+ if( $imgWidth )
1883
+ $style .= 'max-width:'.$imgWidth.'px;';
1884
+ if( $imgHeight )
1885
+ $style .= 'max-height:'.$imgHeight.'px;';
1886
+ if( $returnStyleAttr )
1887
+ return ' style="'.$style.'"';
1888
+ return $style;
1889
+ }
1890
+
1891
+ /**
1892
+ * User API function
1893
+ * @param Array data
1894
+ * @param String field
1895
+ * @param String table The datasource table name
1896
+ */
1897
+ public static function Format($data, $field, $table )
1898
+ {
1899
+ global $strTableName;
1900
+ if(!$table)
1901
+ $table = $strTableName;
1902
+ $pSet = new ProjectSettings( $table );
1903
+
1904
+ include_once getabspath("classes/controls/ViewControlsContainer.php");
1905
+ $viewControls = new ViewControlsContainer( $pSet, PAGE_VIEW );
1906
+
1907
+ return $viewControls->getControl( $field )->getTextValue( $data );
1908
+ }
1909
+ }
1910
+
1911
+ class ViewControlTypes
1912
+ {
1913
+ public $viewTypes = array();
1914
+
1915
+ function __construct()
1916
+ {
1917
+ $this->viewTypes[FORMAT_NONE] = "";
1918
+ $this->viewTypes[FORMAT_DATE_SHORT] = "ViewShortDateField";
1919
+ $this->viewTypes[FORMAT_DATE_LONG] = "ViewLongDateField";
1920
+ $this->viewTypes[FORMAT_DATE_TIME] = "ViewDatetimeField";
1921
+ $this->viewTypes[FORMAT_TIME] = "ViewTimeField";
1922
+ $this->viewTypes[FORMAT_CURRENCY] = "ViewCurrencyField";
1923
+ $this->viewTypes[FORMAT_PERCENT] = "ViewPercentField";
1924
+ $this->viewTypes[FORMAT_HYPERLINK] = "ViewHyperlinkField";
1925
+ $this->viewTypes[FORMAT_EMAILHYPERLINK] = "ViewEmailHyperlinkField";
1926
+ $this->viewTypes[FORMAT_DATABASE_IMAGE] = "ViewDatabaseImageField";
1927
+ $this->viewTypes[FORMAT_DATABASE_FILE] = "ViewDatabaseFileField";
1928
+ $this->viewTypes[FORMAT_FILE] = "ViewFileDownloadField";
1929
+ $this->viewTypes[FORMAT_FILE_IMAGE] = "ViewImageDownloadField";
1930
+ $this->viewTypes[FORMAT_PHONE_NUMBER] = "ViewPhoneNumberField";
1931
+ $this->viewTypes[FORMAT_NUMBER] = "ViewNumberField";
1932
+ $this->viewTypes[FORMAT_CHECKBOX] = "ViewCheckboxField";
1933
+ $this->viewTypes[FORMAT_MAP] = "ViewMapField";
1934
+ $this->viewTypes[FORMAT_AUDIO] = "ViewAudioFileField";
1935
+ $this->viewTypes[FORMAT_DATABASE_AUDIO] = "ViewDatabaseAudioField";
1936
+ $this->viewTypes[FORMAT_VIDEO] = "ViewVideoFileField";
1937
+ $this->viewTypes[FORMAT_DATABASE_VIDEO] = "ViewDatabaseVideoField";
1938
+ $this->viewTypes[FORMAT_CUSTOM] = "ViewCustomField";
1939
+ $this->viewTypes[FORMAT_LOOKUP_WIZARD] = "ViewLookupWizardField";
1940
+ $this->viewTypes[FORMAT_HTML] = "ViewHTMLField";
1941
+ }
1942
+ }
1943
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
1944
  ?>
php/classes/controls/ViewControlsContainer.php CHANGED
@@ -1,3 +1,4 @@
 
1
  <?php
2
  class ViewControlsContainer
3
  {
@@ -229,4 +230,237 @@ class ViewControlsContainer
229
  return false;
230
  }
231
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  ?>
 
1
+ <<<<<<< HEAD
2
  <?php
3
  class ViewControlsContainer
4
  {
 
230
  return false;
231
  }
232
  }
233
+ =======
234
+ <?php
235
+ class ViewControlsContainer
236
+ {
237
+ public $viewControls = array();
238
+ public $pSet = null;
239
+ public $pageType = "";
240
+ public $isDetailsPreview = false;
241
+
242
+ /**
243
+ * Reference to RunnerPage (or its descendant) instance
244
+ */
245
+ public $pageObject = null;
246
+ public $forExport = "";
247
+ /**
248
+ * A flag indicating whether this container is an internal object of ViewControl (for LookupWizard fields only)
249
+ * @var {bool}
250
+ */
251
+ public $isLocal = false;
252
+
253
+ public $recId = 0;
254
+
255
+ public $id = 0;
256
+
257
+ /**
258
+ * This flag is set true for the "More" link lookup only (before the "More" popup is showing)
259
+ * @var boolean
260
+ */
261
+ var $fullText = false;
262
+
263
+ /**
264
+ * The list of including js files
265
+ */
266
+ var $includes_js = array();
267
+ /**
268
+ * The list of including js files
269
+ */
270
+ var $includes_jsreq = array();
271
+ /**
272
+ * The list of including css files
273
+ */
274
+ var $includes_css = array();
275
+
276
+ var $viewControlsMap = array();
277
+
278
+ /**
279
+ * Array of link fields values for lookup fields with distict link and displayed values
280
+ */
281
+ var $linkFieldValues = array();
282
+
283
+ var $originlinkValues = array();
284
+
285
+ var $tName = "";
286
+
287
+ var $searchHighlight = false;
288
+
289
+ public function __construct($pSet, $pageType, $pageObject = null)
290
+ {
291
+ $this->pSet = $pSet;
292
+ $this->pageType = $pageType;
293
+ $this->pageObject = $pageObject;
294
+ $this->tName = $pSet->getTableName();
295
+ if($pageObject)
296
+ $this->pSet->setPageMode($pageObject->mode);
297
+
298
+ $this->searchHighlight= $this->highlightSearchResults();
299
+ }
300
+
301
+ /**
302
+ * Check if search results need to be highlighted through the page's view controls
303
+ * @return Boolean
304
+ */
305
+ protected function highlightSearchResults()
306
+ {
307
+ $curPageObject = $this->pageObject;
308
+
309
+ if( is_null($curPageObject) || !$this->pSet->highlightSearchResults() || $this->pageType != PAGE_LIST)
310
+ return false;
311
+
312
+ if( $curPageObject->mode != LIST_SIMPLE && $curPageObject->mode != LIST_AJAX && $curPageObject->mode != LIST_LOOKUP && $curPageObject->mode != LIST_DASHBOARD)
313
+ return false;
314
+
315
+ return true;
316
+ }
317
+
318
+ function setForExportVar($forExport)
319
+ {
320
+ $this->forExport = $forExport;
321
+ }
322
+
323
+ /**
324
+ * Add js files for page
325
+ */
326
+ function AddJSFile($file,$req1="",$req2="",$req3="")
327
+ {
328
+ $rootPath = GetRootPathForResources($file);
329
+ $this->includes_js[] = $rootPath;
330
+ if($req1!="")
331
+ {
332
+ $this->includes_jsreq[$rootPath] = array(GetRootPathForResources($req1));
333
+ }
334
+ if($req2!="")
335
+ {
336
+ $this->includes_jsreq[$rootPath][] = GetRootPathForResources($req2);
337
+ }
338
+ if($req3!="")
339
+ {
340
+ $this->includes_jsreq[$rootPath][] = GetRootPathForResources($req3);
341
+ }
342
+ }
343
+
344
+ /**
345
+ * Add css files for page
346
+ */
347
+ function AddCSSFile($file)
348
+ {
349
+ $this->includes_css[] = $file;
350
+ }
351
+
352
+ function addControlsJSAndCSS()
353
+ {
354
+ $fields = $this->pSet->getPageFields();
355
+ for($i = 0; $i < count($fields); $i++)
356
+ {
357
+ $control = $this->getControl($fields[$i]);
358
+
359
+ // admin pages
360
+ if( !$control ) {
361
+ continue;
362
+ }
363
+
364
+ if ($control->neededLoadJSFiles())
365
+ $control->addJSFiles();
366
+
367
+ $control->addCSSFiles();
368
+ }
369
+ }
370
+
371
+ /**
372
+ * Create new control (if needed) for view field, and return it
373
+ * @param {string} field name
374
+ * @param {string} predefined view format
375
+ */
376
+ public function getControl($field, $format = null)
377
+ {
378
+ // if conrol does not created previously
379
+ if(!array_key_exists($field, $this->viewControls))
380
+ {
381
+ include_once(getabspath("classes/controls/ViewControl.php"));
382
+ $vcTypes = new ViewControlTypes();
383
+ $editFormat = $this->pSet->getEditFormat($field);
384
+ if(is_null($format)){
385
+ $localPSet = $this->pSet;
386
+ $lookupPageType = "";
387
+ if(!$this->isLocal)
388
+ {
389
+ $lookupPageType = $this->pSet->getPageTypeByFieldEditFormat($field, EDIT_FORMAT_LOOKUP_WIZARD);
390
+ if($lookupPageType != "")
391
+ $localPSet = new ProjectSettings($this->pSet->_table, $lookupPageType);
392
+ }
393
+ if(!$this->isLocal
394
+ && ($editFormat == EDIT_FORMAT_LOOKUP_WIZARD || $lookupPageType != "")
395
+ && ($localPSet->getLookupType($field) == LT_LOOKUPTABLE || $localPSet->getLookupType($field) == LT_QUERY)
396
+ && $localPSet->getLinkField($field) != $localPSet->getDisplayField($field))
397
+ {
398
+ $viewFormat = FORMAT_LOOKUP_WIZARD;
399
+ }else
400
+ $viewFormat = $this->pSet->getViewFormat($field);
401
+ }else
402
+ $viewFormat = $format;
403
+
404
+ $className = $vcTypes->viewTypes[$viewFormat];
405
+ if($className == "" && $viewFormat != "")
406
+ {
407
+ $className = "View".$viewFormat;
408
+ $userControl = true;
409
+ include_once(getabspath("classes/controls/ViewUserControl.php"));
410
+ }
411
+
412
+ if($className != "")
413
+ {
414
+ $this->viewControls[$field] = createViewControlClass($className, $field, $this, $this->pageObject);
415
+ }
416
+ else
417
+ $this->viewControls[$field] = new ViewControl($field, $this, $this->pageObject);
418
+
419
+ if($userControl)
420
+ {
421
+ $this->viewControls[$field]->viewFormat = $className;
422
+ $this->viewControls[$field]->init();
423
+ $this->viewControls[$field]->initUserControl();
424
+ }
425
+ }
426
+ return $this->viewControls[$field];
427
+ }
428
+
429
+ /**
430
+ * showDBValue
431
+ * Wrapper for ViewControl creation and showDBValue call on it
432
+ * @param {string} field name
433
+ * @param {array} associative array with record data
434
+ * @param {string} string with record keys and values
435
+ */
436
+ function showDBValue($field, &$data, $keylink = "", $value = "", $html = true)
437
+ {
438
+ $control = $this->getControl($field);
439
+ if($value != ""){
440
+ $control->displayField = $value;
441
+ }
442
+
443
+ return $control->showDBValue( $data, $keylink, $html );
444
+ }
445
+
446
+ /**
447
+ * Check availability user control in ViewControlsContaier
448
+ * @return boolean
449
+ */
450
+ public function hasUserControls()
451
+ {
452
+ $arFields = $this->pSet->getPrinterFields();
453
+ foreach ($arFields as $arField)
454
+ {
455
+ if ($this->getControl($arField)->isUserControl())
456
+ return true;
457
+ }
458
+ return false;
459
+ }
460
+ function mobileTemplateMode()
461
+ {
462
+ return false;
463
+ }
464
+ }
465
+ >>>>>>> acd181a7002882ac681210d3324239e51441c5bd
466
  ?>