ESubdocumentValidator.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. <?php
  2. /**
  3. * ESubdocumentValidator
  4. *
  5. * Warning: This class, if abused, can cause heavy repitition within your application.
  6. * With great power comes great responsibility.
  7. */
  8. class ESubdocumentValidator extends CValidator
  9. {
  10. public $class;
  11. public $type;
  12. public $rules;
  13. public $scenario;
  14. public $preserveKeys = true;
  15. public $strict = true;
  16. public function validateAttribute($object, $attribute)
  17. {
  18. if(!$this->type){
  19. throw new EMongoException(Yii::t('yii', 'You must supply a subdocument type of either "many" or "one" in order to validate subdocuments'));
  20. }
  21. if(!$this->class && !$this->rules){
  22. throw new EMongoException(Yii::t('yii', 'You must supply either some rules to validate by or a class name to use'));
  23. }
  24. // Lets judge what class we are using
  25. // If we are using a pre-defined class then lets just get on with it otherwise
  26. // lets instantiate a EMongoModel and fill its rules with what we want
  27. if($this->class){
  28. $c = new $this->class;
  29. }else{
  30. $c = new EMongoModel();
  31. foreach($this->rules as $rule){
  32. if(isset($rule[0], $rule[1])){ // attributes, validator name
  33. $c->validatorList->add(CValidator::createValidator($rule[1],$this,$rule[0],array_slice($rule,2)));
  34. }else{
  35. throw new CException(
  36. Yii::t(
  37. 'yii',
  38. '{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.',
  39. array('{class}' => get_class($this))
  40. )
  41. );
  42. }
  43. }
  44. }
  45. if(is_object($this->scenario) && ($this->scenario instanceof Closure)){
  46. $c->scenario = $this->scenario($object);
  47. }else{
  48. $c->scenario = $this->scenario;
  49. }
  50. if($this->type == 'many'){
  51. if(is_array($object->$attribute)){
  52. $fieldErrors = array();
  53. $fieldValue = array();
  54. $newFieldValue = array();
  55. foreach($object->$attribute as $index => $row){
  56. $c->clean();
  57. if($this->preserveKeys){
  58. $val = $fieldValue[$index] = $row instanceof $c ? $row->getRawDocument() : $row;
  59. }else{
  60. $val = $fieldValue[] = $row instanceof $c ? $row->getRawDocument() : $row;
  61. }
  62. $c->setAttributes($val);
  63. if(!$c->validate()){
  64. if($this->preserveKeys){
  65. $fieldErrors[$index] = $c->getErrors();
  66. }else{
  67. $fieldErrors[] = $c->getErrors();
  68. }
  69. }
  70. // Lets get the field value again to apply filters etc
  71. if($this->strict){
  72. if($this->preserveKeys){
  73. $newFieldValue[$index] = $c->getRawDocument();
  74. }else{
  75. $newFieldValue[] = $c->getRawDocument();
  76. }
  77. }
  78. }
  79. if(!$this->strict){
  80. $newFieldValue = $fieldValue;
  81. }
  82. if($this->message !== null){
  83. $this->addError($object, $attribute, $this->message);
  84. }elseif(sizeof($fieldErrors) > 0){
  85. $this->setAttributeErrors($object, $attribute, $fieldErrors);
  86. }
  87. // Strip the models etc from the field value
  88. $object->$attribute = $newFieldValue;
  89. }
  90. }else{
  91. $c->clean();
  92. $fieldValue = $object->$attribute instanceof $c ? $object->$attribute->getRawDocument() : $object->$attribute;
  93. $c->setAttributes($fieldValue);
  94. if(!$c->validate()){
  95. if($this->message !== null){
  96. $this->addError($object,$attribute,$this->message);
  97. }elseif(sizeof($c->getErrors()) > 0){
  98. $this->setAttributeErrors($object, $attribute, $c->getErrors());
  99. }
  100. }
  101. // Lets get the field value again to apply filters etc
  102. if($this->strict){
  103. $fieldValue = $c->getRawDocument();
  104. }
  105. // Strip the models etc from the field value
  106. $object->$attribute = $fieldValue;
  107. }
  108. }
  109. /**
  110. * Sets the errors for a certain attribute
  111. * @param CModel $object the data object being validated
  112. * @param string $attribute the attribute being validated
  113. * @param array $messages the error messages for that attribute
  114. */
  115. protected function setAttributeErrors($object, $attribute, $messages)
  116. {
  117. $object->setAttributeErrors($attribute, $messages);
  118. }
  119. }