Account Suspended
Account Suspended
This Account has been suspended.
Contact your hosting provider for more information.
 All Data Structures Functions Variables Pages
SearchDataProviderMetadataAdapter.php
1 <?php
2  /*********************************************************************************
3  * Zurmo is a customer relationship management program developed by
4  * Zurmo, Inc. Copyright (C) 2017 Zurmo Inc.
5  *
6  * Zurmo is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License version 3 as published by the
8  * Free Software Foundation with the addition of the following permission added
9  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10  * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
11  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12  *
13  * Zurmo is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Affero General Public License along with
19  * this program; if not, see http://www.gnu.org/licenses or write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301 USA.
22  *
23  * You can contact Zurmo, Inc. with a mailing address at 27 North Wacker Drive
24  * Suite 370 Chicago, IL 60606. or at email address contact@zurmo.com.
25  *
26  * The interactive user interfaces in original and modified versions
27  * of this program must display Appropriate Legal Notices, as required under
28  * Section 5 of the GNU Affero General Public License version 3.
29  *
30  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31  * these Appropriate Legal Notices must retain the display of the Zurmo
32  * logo and Zurmo copyright notice. If the display of the logo is not reasonably
33  * feasible for technical reasons, the Appropriate Legal Notices must display the words
34  * "Copyright Zurmo Inc. 2017. All rights reserved".
35  ********************************************************************************/
36 
42  {
43  protected $appendStructureAsAnd;
44 
48  public function __construct($model, $userId, $metadata)
49  {
50  assert('$model instanceof RedBeanModel || $model instanceof SearchForm');
51  parent::__construct($model, $userId, $metadata);
52  }
53 
60  public function getAdaptedMetadata($appendStructureAsAnd = true, $clauseCount = 1)
61  {
62  assert('is_bool($appendStructureAsAnd)');
63  assert('is_int($clauseCount)');
64  $this->appendStructureAsAnd = $appendStructureAsAnd;
65  $adaptedMetadata = array('clauses' => array(), 'structure' => '');
66  $structure = '';
67  foreach ($this->metadata as $attributeName => $value)
68  {
69  //If attribute is a pseudo attribute on the SearchForm
70  if ($this->model instanceof SearchForm && $this->model->isAttributeOnForm($attributeName))
71  {
72  $this->populateAdaptedMetadataFromSearchFormAttributes( $this->model,
73  $attributeName,
74  $value,
75  $adaptedMetadata['clauses'],
76  $clauseCount,
77  $structure);
78  }
79  else
80  {
81  $this->populateClausesAndStructureForAttribute( $this->model,
82  $attributeName,
83  $value,
84  $adaptedMetadata['clauses'],
85  $clauseCount,
86  $structure);
87  }
88  }
89  if (!$appendStructureAsAnd)
90  {
91  $structure = '(' . $structure . ')';
92  }
93  $adaptedMetadata['structure'] = $structure;
94  return $adaptedMetadata;
95  }
96 
97  protected function populateClausesAndStructureForAttributeWithRelatedModelData( $model,
98  $relatedMetaData,
99  $adaptedMetadataClauseBasePart,
100  & $adaptedMetadataClauses,
101  & $clauseCount,
102  & $structure,
103  $depth,
104  $operatorType = null)
105  {
106  assert('$model instanceof RedBeanModel || $model instanceof SearchForm');
107  assert('is_array($relatedMetaData)');
108  assert('is_int($depth)');
109  $startingOperatorType = $operatorType;
110  foreach ($relatedMetaData as $attributeName => $value)
111  {
112  //If attribute is a pseudo attribute on the SearchForm
113  if ($model instanceof SearchForm && $model->isAttributeOnForm($attributeName))
114  {
115  $this->populateAdaptedMetadataFromSearchFormAttributes( $model,
116  $attributeName,
117  $value,
118  $adaptedMetadataClauses,
119  $clauseCount,
120  $structure,
121  $adaptedMetadataClauseBasePart,
122  $depth);
123  }
124  else
125  {
126  $this->populateClausesAndStructureForAttribute($model,
127  $attributeName,
128  $value,
129  $adaptedMetadataClauses,
130  $clauseCount,
131  $structure,
132  $adaptedMetadataClauseBasePart,
133  $operatorType,
134  $depth);
135  }
136  }
137  }
138 
139  protected function populateClausesAndStructureForAttribute( $model,
140  $attributeName,
141  $value,
142  & $adaptedMetadataClauses,
143  & $clauseCount,
144  & $structure,
145  $adaptedMetadataClauseBasePart = array(),
146  $operatorType = null,
147  $depth = 0)
148  {
149  assert('$model instanceof SearchForm || $model instanceof RedBeanModel');
150  assert('is_string($attributeName)');
151  assert('is_array($adaptedMetadataClauses) || $adaptedMetadataClauses == null');
152  assert('is_int($clauseCount)');
153  assert('$structure == null || is_string($structure)');
154  assert('is_int($depth)');
155  $basePartAtRequiredDepth = static::
156  getAdaptedMetadataClauseBasePartAtRequiredDepth($adaptedMetadataClauseBasePart, $depth);
157  //non-relation attribute that has single data value
158  if (!is_array($value))
159  {
160  if ($value !== null)
161  {
162  $currentClauseCount = $clauseCount;
163  $secondAdaptedMetadataClause = null;
164  $this->resolveOperatorAndCastsAndAppendClauseAsAndToStructureString( $model,
165  $attributeName,
166  $operatorType,
167  $value,
168  $basePartAtRequiredDepth,
169  $secondAdaptedMetadataClause,
170  $structure,
171  $clauseCount);
172  $adaptedMetadataClauses[$currentClauseCount] = static::getAppendedAdaptedMetadataClauseBasePart(
173  $adaptedMetadataClauseBasePart,
174  $basePartAtRequiredDepth,
175  $depth);
176  if ($secondAdaptedMetadataClause != null)
177  {
178  $adaptedMetadataClauses[$currentClauseCount + 1] = static::getAppendedAdaptedMetadataClauseBasePart(
179  $adaptedMetadataClauseBasePart,
180  $secondAdaptedMetadataClause,
181  $depth);
182  }
183  }
184  }
185  //non-relation attribute that has array of data
186  elseif (!$model::isRelation($attributeName))
187  {
188  if (isset($value['value']) && $value['value'] != '')
189  {
190  $currentClauseCount = $clauseCount;
191  $secondAdaptedMetadataClause = null;
192  $this->resolveOperatorAndCastsAndAppendClauseAsAndToStructureString( $model,
193  $attributeName,
194  $operatorType,
195  $value['value'],
196  $basePartAtRequiredDepth,
197  $secondAdaptedMetadataClause,
198  $structure,
199  $clauseCount);
200  $adaptedMetadataClauses[$currentClauseCount] = static::getAppendedAdaptedMetadataClauseBasePart(
201  $adaptedMetadataClauseBasePart,
202  $basePartAtRequiredDepth,
203  $depth);
204  if ($secondAdaptedMetadataClause != null)
205  {
206  $adaptedMetadataClauses[$currentClauseCount + 1] = static::getAppendedAdaptedMetadataClauseBasePart(
207  $adaptedMetadataClauseBasePart,
208  $secondAdaptedMetadataClause,
209  $depth);
210  }
211  }
212  }
213  //relation attribute that is relatedData
214  elseif (isset($value['relatedData']) && $value['relatedData'] == true)
215  {
216  $partToAppend = array('attributeName' => $attributeName,
217  'relatedModelData' => array());
218  $appendedClauseToPassRecursively = static::getAppendedAdaptedMetadataClauseBasePart(
219  $adaptedMetadataClauseBasePart,
220  $partToAppend,
221  $depth);
222  unset($value['relatedData']);
223 
224  $finalModel = static::resolveAsRedBeanModel($model->$attributeName);
225  if ($finalModel::getModuleClassName() != null)
226  {
227  $moduleClassName = $finalModel::getModuleClassName();
228  if ($moduleClassName::getGlobalSearchFormClassName() != null)
229  {
230  $searchFormClassName = $moduleClassName::getGlobalSearchFormClassName();
231  $finalModel = new $searchFormClassName($finalModel);
232  }
233  }
234  $this->populateClausesAndStructureForAttributeWithRelatedModelData(
235  $finalModel,
236  $value,
237  $appendedClauseToPassRecursively,
238  $adaptedMetadataClauses,
239  $clauseCount,
240  $structure,
241  ($depth + 1),
242  $operatorType);
243  }
244  //relation attribute that has array of data
245  else
246  {
247  foreach ($value as $relatedAttributeName => $relatedValue)
248  {
249  $currentClauseCount = $clauseCount;
250  if (static::resolveRelatedValueWhenArray( $model->$attributeName,
251  $relatedAttributeName,
252  $relatedValue,
253  $operatorType))
254  {
255  if ($relatedValue !== null)
256  {
257  if ($model::isRelation($attributeName))
258  {
259  $secondAdaptedMetadataClause = null;
260  $this->resolveOperatorAndCastsAndAppendClauseAsAndToStructureString(
261  $model->$attributeName,
262  $relatedAttributeName,
263  $operatorType,
264  $relatedValue,
265  $basePartAtRequiredDepth,
266  $secondAdaptedMetadataClause,
267  $structure,
268  $clauseCount,
269  $attributeName);
270  $adaptedMetadataClauses[$currentClauseCount] = static::getAppendedAdaptedMetadataClauseBasePart(
271  $adaptedMetadataClauseBasePart,
272  $basePartAtRequiredDepth,
273  $depth);
274  if ($secondAdaptedMetadataClause != null)
275  {
276  $adaptedMetadataClauses[$currentClauseCount + 1] = static::getAppendedAdaptedMetadataClauseBasePart(
277  $adaptedMetadataClauseBasePart,
278  $secondAdaptedMetadataClause,
279  $depth);
280  }
281  }
282  else
283  {
284  throw new NotSupportedException();
285  }
286  }
287  }
288  }
289  }
290  }
291 
292  protected static function resolveRelatedValueWhenArray($model,
293  $relatedAttributeName,
294  & $relatedValue,
295  & $operatorType)
296  {
297  if (is_array($relatedValue))
298  {
299  if (isset($relatedValue['value']) && $relatedValue['value'] != '')
300  {
301  $relatedValue = $relatedValue['value'];
302  }
303  elseif (isset($relatedValue['value']) && empty($relatedValue['value']) &&
304  ModelAttributeToMixedTypeUtil::getType($model, $relatedAttributeName) == 'CheckBox')
305  {
306  //Boolean field with an empty value means there is no clause to include
307  return false;
308  }
309  //Run this before the next set of elseifs to make this scenario is properly checked
310  elseif ($model instanceof MultipleValuesCustomField && count($relatedValue) > 0)
311  {
312  if (count($relatedValue) == 1 && $relatedValue[0] == null)
313  {
314  return false;
315  }
316  }
317  elseif ($model instanceof MultipleValuesCustomField && count($relatedValue) == 0)
318  {
319  return false;
320  }
321  elseif (($model instanceof RedBeanManyToManyRelatedModels ||
322  $model instanceof RedBeanOneToManyRelatedModels ) &&
323  is_array($relatedValue) && count($relatedValue) > 0)
324  {
325  //Continue on using relatedValue as is.
326  }
327  elseif ($model->$relatedAttributeName instanceof RedBeanModels &&
328  is_array($relatedValue) && count($relatedValue) > 0)
329  {
330  //Continue on using relatedValue as is.
331  }
332  elseif ($model instanceof CustomField && count($relatedValue) > 0)
333  {
334  //Handle scenario where the UI posts or sends a get string with an empty value from
335  //a multi-select field.
336  if (count($relatedValue) == 1 && $relatedValue[0] == null)
337  {
338  return false;
339  }
340  //Continue on using relatedValue as is.
341  if ($operatorType == null)
342  {
343  $operatorType = 'oneOf';
344  }
345  }
346  }
347  return true;
348  }
349 
350  public static function resolveAsRedBeanModel($model)
351  {
352  if ($model instanceof RedBeanOneToManyRelatedModels || $model instanceof RedBeanManyToManyRelatedModels)
353  {
354  $relationModelClassName = $model->getModelClassName();
355  return new $relationModelClassName(false);
356  }
357  else
358  {
359  return $model;
360  }
361  }
362 
363  protected function resolveOperatorAndCastsAndAppendClauseAsAndToStructureString( $model,
364  $attributeName,
365  $operatorType,
366  $value,
367  & $adaptedMetadataClause,
368  & $secondAdaptedMetadataClause,
369  & $structure,
370  & $clauseCount,
371  $previousAttributeName = null)
372  {
373  assert('$previousAttributeName == null || is_string($previousAttributeName)');
374  $modelForTypeOperations = static::resolveAsRedBeanModel($model);
375  $mixedType = null;
376  if ($operatorType == null)
377  {
378  $operatorType = ModelAttributeToOperatorTypeUtil::getOperatorType($modelForTypeOperations, $attributeName);
379  }
380  if (is_array($value) && $model instanceof CustomField)
381  {
382  //do nothing, the cast is fine as is. Maybe eventually remove this setting of cast.
383  }
384  else
385  {
386  $value = ModelAttributeToCastTypeUtil::resolveValueForCast($modelForTypeOperations, $attributeName, $value);
387  }
388  if ($model instanceof RedBeanModel)
389  {
390  $mixedType = ModelAttributeToMixedTypeUtil::getType($model, $attributeName);
391  static::resolveBooleanFalseValueAndOperatorTypeForAdaptedMetadataClause($mixedType,
392  $value,
393  $operatorType);
394  }
395  elseif ($model instanceof SearchForm)
396  {
397  $mixedType = ModelAttributeToMixedTypeUtil::getType($model->getModel(), $attributeName);
398  static::resolveBooleanFalseValueAndOperatorTypeForAdaptedMetadataClause($mixedType,
399  $value,
400  $operatorType);
401  }
402  if (static::isBooleanNullOrEmptyOperation($mixedType, $operatorType, $value))
403  {
404  $secondAdaptedMetadataClause = $adaptedMetadataClause;
405  }
406  if ($previousAttributeName == null)
407  {
408  $adaptedMetadataClause['attributeName'] = $attributeName;
409  if (static::isBooleanNullOrEmptyOperation($mixedType, $operatorType, $value))
410  {
411  $secondAdaptedMetadataClause['attributeName'] = $attributeName;
412  }
413  }
414  else
415  {
416  $adaptedMetadataClause['attributeName'] = $previousAttributeName;
417  $adaptedMetadataClause['relatedAttributeName'] = $attributeName;
418  if (static::isBooleanNullOrEmptyOperation($mixedType, $operatorType, $value))
419  {
420  $secondAdaptedMetadataClause['attributeName'] = $previousAttributeName;
421  $secondAdaptedMetadataClause['relatedAttributeName'] = $attributeName;
422  }
423  }
424  $adaptedMetadataClause['operatorType'] = $operatorType;
425  $adaptedMetadataClause['value'] = $value;
426  if (static::isBooleanNullOrEmptyOperation($mixedType, $operatorType, $value))
427  {
428  $secondAdaptedMetadataClause['operatorType'] = OperatorRules::TYPE_IS_NULL;
429  $secondAdaptedMetadataClause['value'] = null;
430  $partialStructure = null;
431  $this->resolveAppendClauseAsAndToStructureString($partialStructure, $clauseCount);
432  static::appendClauseAsOrToStructureString($partialStructure, $clauseCount);
433  $partialStructure = '(' . $partialStructure . ')';
434  if ($this->appendStructureAsAnd)
435  {
436  if ($structure != null)
437  {
438  $structure .= ' and ' . $partialStructure;
439  }
440  else
441  {
442  $structure .= $partialStructure;
443  }
444  }
445  else
446  {
447  if ($structure != null)
448  {
449  $structure .= ' or ' . $partialStructure;
450  }
451  else
452  {
453  $structure .= $partialStructure;
454  }
455  }
456  $clauseCount++;
457  }
458  else
459  {
460  $this->resolveAppendClauseAsAndToStructureString($structure, $clauseCount);
461  }
462  }
463 
464  protected function resolveAppendClauseAsAndToStructureString(& $structure, & $clauseCount)
465  {
466  if ($this->appendStructureAsAnd)
467  {
468  static::appendClauseAsAndToStructureString($structure, $clauseCount);
469  }
470  else
471  {
472  static::appendClauseAsOrToStructureString($structure, $clauseCount);
473  }
474  $clauseCount++;
475  }
476 
482  $attributeNames,
483  $value,
484  & $adaptedMetadataClauseBasePart,
485  & $clauseCount,
486  & $structure,
487  $operatorType = null)
488  {
489  assert('is_array($attributeNames) && count($attributeNames) == 2');
490  assert('is_array($adaptedMetadataClauseBasePart)');
491  assert('is_int($clauseCount)');
492  assert('$structure == null || is_string($structure)');
493  if ($value !== null)
494  {
495  if ($operatorType == null)
496  {
497  $operatorType = ModelAttributeToOperatorTypeUtil::getOperatorType($model, $attributeNames[0]);
498  $operatorTypeCompare = ModelAttributeToOperatorTypeUtil::getOperatorType($model, $attributeNames[1]);
499  if ($operatorType != $operatorTypeCompare)
500  {
501  throw New NotSupportedException();
502  }
503  }
504  $value = ModelAttributeToCastTypeUtil::resolveValueForCast($model, $attributeNames[0], $value);
505  $adaptedMetadataClauseBasePart = array(
506  'concatedAttributeNames' => $attributeNames,
507  'operatorType' => $operatorType,
508  'value' => $value,
509  );
510  if ($this->appendStructureAsAnd)
511  {
512  static::appendClauseAsAndToStructureString($structure, $clauseCount);
513  }
514  else
515  {
516  static::appendClauseAsOrToStructureString($structure, $clauseCount);
517  }
518  $clauseCount++;
519  }
520  }
521 
522  protected function populateAdaptedMetadataFromSearchFormAttributes( $model,
523  $attributeName,
524  $value,
525  &$adaptedMetadataClauses,
526  &$clauseCount,
527  &$structure,
528  $adaptedMetadataClauseBasePart = array(),
529  $depth = 0)
530  {
531  assert('$model instanceof SearchForm || $model instanceof RedBeanModel');
532  assert('is_string($attributeName)');
533  assert('is_array($adaptedMetadataClauses) || $adaptedMetadataClauses == null');
534  assert('is_int($clauseCount)');
535  assert('$structure == null || is_string($structure)');
536  $tempStructure = null;
537  $metadataFromSearchFormAttributes = SearchFormAttributesToSearchDataProviderMetadataUtil::getMetadata(
538  $model, $attributeName, $value);
539  foreach ($metadataFromSearchFormAttributes as $searchFormClause)
540  {
541  if (isset($searchFormClause['concatedAttributeNames']))
542  {
543  assert('is_array($searchFormClause["concatedAttributeNames"][0]) &&
544  count($searchFormClause["concatedAttributeNames"][0]) == 2');
545  assert('!isset($searchFormClause["concatedAttributeNames"]["operatorType"])');
546  assert('!isset($searchFormClause["concatedAttributeNames"]["appendStructureAsAnd"])');
547  $oldAppendStructureAsAndValue = $this->appendStructureAsAnd;
548  $this->appendStructureAsAnd = false;
549  $basePartAtRequiredDepth = static::
550  getAdaptedMetadataClauseBasePartAtRequiredDepth(
551  $adaptedMetadataClauseBasePart, $depth);
552  $currentClauseCount = $clauseCount;
553  if ($searchFormClause['concatedAttributeNames']['value'] != null)
554  {
556  $searchFormClause['concatedAttributeNames'][0],
557  $searchFormClause['concatedAttributeNames']['value'],
558  $basePartAtRequiredDepth,
559  $clauseCount,
560  $tempStructure,
561  false);
562  $adaptedMetadataClauses[$currentClauseCount] = static::getAppendedAdaptedMetadataClauseBasePart(
563  $adaptedMetadataClauseBasePart,
564  $basePartAtRequiredDepth,
565  $depth);
566  }
567  $this->appendStructureAsAnd = $oldAppendStructureAsAndValue;
568  }
569  else
570  {
571  foreach ($searchFormClause as $searchFormAttributeName => $searchFormStructure)
572  {
573  if (isset($searchFormStructure['operatorType']))
574  {
575  $operatorType = $searchFormStructure['operatorType'];
576  }
577  else
578  {
579  $operatorType = null;
580  }
581  //setting a temp value is not ideal. But it avoids passing the parameter.
582  $oldAppendStructureAsAndValue = $this->appendStructureAsAnd;
583  if (isset($searchFormStructure['appendStructureAsAnd']))
584  {
585  $this->appendStructureAsAnd = $searchFormStructure['appendStructureAsAnd'];
586  }
587  else
588  {
589  $this->appendStructureAsAnd = false;
590  }
591  $this->populateClausesAndStructureForAttribute( $model,
592  $searchFormAttributeName,
593  $searchFormStructure['value'],
594  $adaptedMetadataClauses,
595  $clauseCount,
596  $tempStructure,
597  $adaptedMetadataClauseBasePart,
598  $operatorType,
599  $depth);
600  $this->appendStructureAsAnd = $oldAppendStructureAsAndValue;
601  }
602  }
603  }
604  if ($tempStructure != null)
605  {
606  $tempStructure = '(' . $tempStructure . ')';
607  if ($this->appendStructureAsAnd)
608  {
609  static::appendClauseAsAndToStructureString($structure, $tempStructure);
610  }
611  else
612  {
613  static::appendClauseAsOrToStructureString($structure, $tempStructure);
614  }
615  }
616  }
617 
618  protected static function appendClauseAsAndToStructureString(& $structure, $clause)
619  {
620  assert('$structure == null || is_string($structure)');
621  assert('$clause != null || (is_string($clause) || is_int(clause))');
622  if (!empty($structure))
623  {
624  $structure .= ' and ' . $clause;
625  }
626  else
627  {
628  $structure .= $clause;
629  }
630  }
631 
632  protected static function appendClauseAsOrToStructureString(& $structure, $clause)
633  {
634  assert('$structure == null || is_string($structure)');
635  assert('$clause != null || (is_string($clause) || is_int(clause))');
636  if (!empty($structure))
637  {
638  $structure .= ' or ' . $clause;
639  }
640  else
641  {
642  $structure .= $clause;
643  }
644  }
645 
646  protected static function resolveBooleanFalseValueAndOperatorTypeForAdaptedMetadataClause($type, & $value,
647  & $operatorType)
648  {
649  assert('is_string($type)');
650  assert('is_string($operatorType)');
651  if ($type == 'CheckBox' && ($value == '0' || !$value))
652  {
653  $value = '0';
654  }
655  }
656 
665  protected function isBooleanNullOrEmptyOperation($mixedType, $operatorType, $value)
666  {
667  assert('is_string($mixedType) || $mixedType == null');
668  assert('is_string($operatorType)');
669  if ($mixedType == 'CheckBox' && $operatorType == OperatorRules::TYPE_EQUALS && ($value == '0' || !$value))
670  {
671  return true;
672  }
673  return false;
674  }
675 
676  protected static function getAdaptedMetadataClauseBasePartAtRequiredDepth($adaptedMetadataClauseBasePart, $depth)
677  {
678  assert('is_array($adaptedMetadataClauseBasePart)');
679  assert('is_int($depth)');
680  if ($depth == 0)
681  {
682  return $adaptedMetadataClauseBasePart;
683  }
684  $finalPart = $adaptedMetadataClauseBasePart;
685  for ($i = 0; $i < $depth; $i++)
686  {
687  $finalPart = $finalPart['relatedModelData'];
688  }
689  return $finalPart;
690  }
691 
692  protected static function getAppendedAdaptedMetadataClauseBasePart($adaptedMetadataClauseBasePart, $partToAppend, $depth)
693  {
694  assert('is_array($adaptedMetadataClauseBasePart)');
695  assert('is_array($partToAppend)');
696  assert('is_int($depth)');
697  if ($depth == 0)
698  {
699  return $partToAppend;
700  }
701  $finalPart = & $adaptedMetadataClauseBasePart;
702  for ($i = 0; $i < $depth; $i++)
703  {
704  $finalPart = & $finalPart['relatedModelData'];
705  }
706  $finalPart = $partToAppend;
707  return $adaptedMetadataClauseBasePart;
708  }
709  }
710 ?>
populateClausesAndStructureForConcatedAttributes($model, $attributeNames, $value, &$adaptedMetadataClauseBasePart, &$clauseCount, &$structure, $operatorType=null)
static resolveValueForCast($model, $attributeName, $value)
getAdaptedMetadata($appendStructureAsAnd=true, $clauseCount=1)
isBooleanNullOrEmptyOperation($mixedType, $operatorType, $value)
isAttributeOnForm($attributeName)
Definition: SearchForm.php:183
static getType($model, $attributeName)
Generated on Mon Jul 6 2020 07:10:29
Account Suspended
Account Suspended
This Account has been suspended.
Contact your hosting provider for more information.