PageRenderTime 51ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Adapto/EntityValidator.php

http://github.com/egeniq/adapto
PHP | 258 lines | 142 code | 31 blank | 85 comment | 40 complexity | 6a05cb5167808da481b74ecb4e5a1ec1 MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of the Adapto Toolkit.
  4. * Detailed copyright and licensing information can be found
  5. * in the doc/COPYRIGHT and doc/LICENSE files which should be
  6. * included in the distribution.
  7. *
  8. * @package adapto
  9. *
  10. * @copyright (c)2000-2004 Ibuildings.nl BV
  11. * @license http://www.achievo.org/atk/licensing ATK Open Source License
  12. *
  13. */
  14. /**
  15. * Validator for records, based on entity definition.
  16. *
  17. * The class takes an entity, and based on the attribute definitions,
  18. * validation can be performed on records.
  19. *
  20. * @author Kees van Dieren <kees@ibuildings.nl>
  21. * @package adapto
  22. *
  23. */
  24. class Adapto_EntityValidator
  25. {
  26. /**
  27. * @var atkEntity The entity which needs to get validated
  28. * @access private
  29. */
  30. public $m_entityObj = null; // defaulted to public
  31. /**
  32. * @var array the record of the entity which will get validated
  33. * @access private
  34. */
  35. public $m_record = array(); // defaulted to public
  36. /**
  37. * @var String the mode in which the validate will get runned
  38. * @access private
  39. */
  40. public $m_mode = ""; // defaulted to public
  41. /**
  42. * constructor
  43. *
  44. */
  45. public function __construct()
  46. {
  47. }
  48. /**
  49. * set the list of fields which will get ignored
  50. * @param array $fieldArr List of fields to ignore during validation
  51. */
  52. function setIgnoreList($fieldArr)
  53. {
  54. $this->m_ignoreList = $fieldArr;
  55. }
  56. /**
  57. * set the mode in which to validate
  58. * @param String $mode The mode ("edit"/"add")
  59. */
  60. function setMode($mode)
  61. {
  62. $this->m_mode = $mode;
  63. }
  64. /**
  65. * Set the Entity which should be validated
  66. *
  67. * @param atkEntity $entityObj The entity for validation
  68. */
  69. function setEntity(&$entityObj)
  70. {
  71. $this->m_entityObj = &$entityObj;
  72. }
  73. /**
  74. * set the record which should get validated.
  75. * @param array $record The record to validate. The record is passed by
  76. * reference, because errors that are found are
  77. * stored in the record.
  78. */
  79. function setRecord(&$record)
  80. {
  81. $this->m_record = &$record;
  82. }
  83. /**
  84. * Validate a record
  85. *
  86. * @param string $mode Override the mode
  87. * @param array $ignoreList Override the ignoreList
  88. */
  89. function validate($mode="", $ignoreList=array())
  90. {
  91. // check overrides
  92. if(count($ignoreList))
  93. $this->setIgnoreList($ignoreList);
  94. if($mode != "")
  95. $this->setMode($mode);
  96. Adapto_Util_Debugger::debug("validate() with mode ".$this->m_mode." for entity ".$this->m_entityObj->atkEntityType());
  97. // set the record
  98. $record = &$this->m_record;
  99. // Check flags and values
  100. $db = &$this->m_entityObj->getDb();
  101. foreach ($this->m_entityObj->m_attribIndexList as $attribdata)
  102. {
  103. $attribname = $attribdata['name'];
  104. if (!Adapto_in_array($attribname, $this->m_ignoreList))
  105. {
  106. $p_attrib = &$this->m_entityObj->m_attribList[$attribname];
  107. $this->validateAttributeValue($p_attrib, $record);
  108. if ($p_attrib->hasFlag(AF_PRIMARY) && !$p_attrib->hasFlag(AF_AUTO_INCREMENT))
  109. {
  110. $atkorgkey = $record["atkprimkey"];
  111. if(($atkorgkey == '' // no orgkey, so adding this record
  112. || $atkorgkey != $this->m_entityObj->primaryKey($record)) // key has changed, so check is necessary
  113. && $this->m_entityObj->countDb($this->m_entityObj->primaryKey($record))>0
  114. )
  115. {
  116. atkTriggerError($record, $p_attrib, 'error_primarykey_exists');
  117. }
  118. }
  119. // if no root elements may be added to the tree, then every record needs to have a parent!
  120. if ($p_attrib->hasFlag(AF_PARENT) && $this->m_entityObj->hasFlag(EF_TREE_NO_ROOT_ADD) && $this->m_entityObj->m_action == "save")
  121. $p_attrib->m_flags |= AF_OBLIGATORY;
  122. // validate obligatory fields (but not the auto_increment ones, because they don't have a value yet)
  123. if ($p_attrib->hasFlag(AF_OBLIGATORY) && !$p_attrib->hasFlag(AF_AUTO_INCREMENT) && $p_attrib->isEmpty($record))
  124. {
  125. atkTriggerError($record, $p_attrib, 'error_obligatoryfield');
  126. }
  127. // if flag is primary
  128. else if ($p_attrib->hasFlag(AF_UNIQUE) && !$p_attrib->hasFlag(AF_PRIMARY) && !$p_attrib->isEmpty($record)
  129. && $this->m_entityObj->countDb($this->m_entityObj->getTable().".{$attribname}='".$db->escapeSQL($p_attrib->value2db($record))."'".($this->m_mode != 'add' ? " AND NOT (".$this->m_entityObj->primaryKey($record).")" : ""))>0
  130. )
  131. {
  132. atkTriggerError($record, $p_attrib, 'error_uniquefield');
  133. }
  134. }
  135. }
  136. if(isset($record['atkerror'])&&count($record['atkerror']) > 0)
  137. {
  138. for ($i = 0, $_i = count($record["atkerror"]); $i < $_i; $i++)
  139. $record["atkerror"][$i]["entity"] = $this->m_entityObj->m_type;
  140. }
  141. $this->validateUniqueFieldSets($record);
  142. if (isset($record['atkerror']))
  143. {
  144. for ($i = 0, $_i = count($record["atkerror"]); $i < $_i; $i++)
  145. $record["atkerror"][$i]["entity"] = $this->m_entityObj->m_type;
  146. return false;
  147. }
  148. return true;
  149. }
  150. /**
  151. * Validate attribute value.
  152. *
  153. * @param atkAttribute $p_attrib pointer to the attribute
  154. * @param array $record record
  155. */
  156. function validateAttributeValue(&$p_attrib, &$record)
  157. {
  158. if (!$p_attrib->isEmpty($record))
  159. {
  160. $funcname = $p_attrib->m_name."_validate";
  161. if (method_exists($this->m_entityObj, $funcname))
  162. {
  163. $this->m_entityObj->$funcname($record, $this->m_mode);
  164. }
  165. else
  166. {
  167. $p_attrib->validate($record, $this->m_mode);
  168. }
  169. }
  170. }
  171. /**
  172. * Check unique field combinations.
  173. * The function is called by the validate() method automatically. It is
  174. * not necessary to call this manually in a validation process.
  175. * Errors that are found are stored in the $record parameter
  176. *
  177. * @param array $record The record to validate
  178. */
  179. function validateUniqueFieldSets(&$record)
  180. {
  181. $db = &$this->m_entityObj->getDb();
  182. foreach($this->m_entityObj->m_uniqueFieldSets as $uniqueFieldSet)
  183. {
  184. $query = &$db->createQuery();
  185. $query->addField('*');
  186. $query->addTable($this->m_entityObj->m_table);
  187. $attribs = array();
  188. foreach($uniqueFieldSet as $field)
  189. {
  190. $attrib = &$this->m_entityObj->m_attribList[$field];
  191. if ($attrib)
  192. {
  193. $attribs[] = &$attrib;
  194. if (is_a($attrib, 'atkmanytoonerelation') && count($attrib->m_refKey) > 1)
  195. {
  196. $attrib->createDestination();
  197. foreach ($attrib->m_refKey as $refkey)
  198. {
  199. $query->addCondition($query->quoteField($refkey)." = '".$db->escapeSQL($record[$attrib->fieldName()][$refkey])."'");
  200. }
  201. }
  202. else if (!$attrib->isNotNullInDb() && $attrib->isEmpty($record))
  203. {
  204. $query->addCondition($query->quoteField($field)." IS NULL");
  205. }
  206. else
  207. {
  208. $query->addCondition($query->quoteField($field)." = '".$attrib->value2db($record)."'");
  209. }
  210. }
  211. else
  212. throw new Adapto_Exception("Field $field is mentioned in uniquefieldset but does not exist in ".$this->m_entityObj->atkentitytype());
  213. }
  214. if ($this->m_mode != 'add')
  215. {
  216. $query->addCondition("NOT (".$this->m_entityObj->primaryKey($record).")");
  217. }
  218. if (count($db->getRows($query->buildSelect()))> 0)
  219. {
  220. atkTriggerError($record, $attribs, 'error_uniquefieldset');
  221. }
  222. }
  223. }
  224. }
  225. ?>