EMongoUniqueValidator.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <?php
  2. /**
  3. * EMongoUniqueValidator validates that the attribute value is unique in the corresponding database table.
  4. *
  5. * When using the {@link message} property to define a custom error message, the message
  6. * may contain additional placeholders that will be replaced with the actual content. In addition
  7. * to the "{attribute}" placeholder, recognized by all validators (see {@link CValidator}),
  8. * EMongoUniqueValidator allows for the following placeholders to be specified:
  9. * <ul>
  10. * <li>{value}: replaced with current value of the attribute.</li>
  11. * </ul>
  12. */
  13. class EMongoUniqueValidator extends CValidator
  14. {
  15. /**
  16. * @var boolean whether the comparison is case sensitive. Defaults to true.
  17. * Note, by setting it to false, you are assuming the attribute type is string.
  18. */
  19. public $caseSensitive = true;
  20. /**
  21. * @var boolean whether the attribute value can be null or empty. Defaults to true,
  22. * meaning that if the attribute is empty, it is considered valid.
  23. */
  24. public $allowEmpty = true;
  25. /**
  26. * @var string the ActiveRecord class name that should be used to
  27. * look for the attribute value being validated. Defaults to null, meaning using
  28. * the class of the object currently being validated.
  29. * You may use path alias to reference a class name here.
  30. * @see attributeName
  31. */
  32. public $className;
  33. /**
  34. * @var string the ActiveRecord class attribute name that should be
  35. * used to look for the attribute value being validated. Defaults to null,
  36. * meaning using the name of the attribute being validated.
  37. * @see className
  38. */
  39. public $attributeName;
  40. /**
  41. * @var mixed additional query criteria. Either an array or CDbCriteria.
  42. * This will be combined with the condition that checks if the attribute
  43. * value exists in the corresponding table column.
  44. * This array will be used to instantiate a {@link CDbCriteria} object.
  45. */
  46. public $criteria = array();
  47. /**
  48. * @var string the user-defined error message. The placeholders "{attribute}" and "{value}"
  49. * are recognized, which will be replaced with the actual attribute name and value, respectively.
  50. */
  51. public $message;
  52. /**
  53. * @var boolean whether this validation rule should be skipped if when there is already a validation
  54. * error for the current attribute. Defaults to true.
  55. */
  56. public $skipOnError = true;
  57. /**
  58. * Validates the attribute of the object.
  59. * If there is any error, the error message is added to the object.
  60. * @param CModel $object the object being validated
  61. * @param string $attribute the attribute being validated
  62. */
  63. protected function validateAttribute($object,$attribute)
  64. {
  65. $value = $object->$attribute;
  66. if($this->allowEmpty && $this->isEmpty($value)){
  67. return;
  68. }
  69. $className = $this->className === null ? get_class($object) : Yii::import($this->className);
  70. $attributeName = $this->attributeName === null ? $attribute : $this->attributeName;
  71. // We get a RAW document here to prevent the need to make yet another active record instance
  72. $doc = EMongoDocument::model($className)
  73. ->getCollection()
  74. ->findOne(
  75. array_merge(
  76. $this->criteria,
  77. array($attributeName => $this->caseSensitive ? $value : new MongoRegex('/' . $value . '/i'))
  78. )
  79. );
  80. // If a doc was found first test if the unique attribute is the primaryKey
  81. // If we are uniquely id'ing the pk then check this is a new record and not
  82. // an old one and check to see if the pks are the same
  83. // If the found doc is not evaledd onm pk then make sure the two pks are not the same
  84. if(
  85. $doc &&
  86. (
  87. ($attributeName === $object->primaryKey() && $object->getIsNewRecord() && (string)$doc[$object->primaryKey()] == (string)$object->getPrimaryKey()) ||
  88. ((string)$doc[$object->primaryKey()] != (string)$object->getPrimaryKey())
  89. )
  90. ){
  91. // Then it ain't unique
  92. $message = $this->message !== null ? $this->message : Yii::t('yii', '{attribute} "{value}" has already been taken.');
  93. $this->addError($object, $attribute, $message, array('{value}' => CHtml::encode($value)));
  94. }else{}
  95. }
  96. }