/**
  * Returns the rules array used by CModel.
  *
  * @param \CModel $model
  *
  * @return array
  */
 public static function getRules(\CModel $model)
 {
     $rules = array();
     $uniqueAttributes = array();
     $uniqueRequiredAttributes = array();
     $requiredAttributes = array();
     $emailAttributes = array();
     $urlAttributes = array();
     $urlFormatAttributes = array();
     $uriAttributes = array();
     $strictLengthAttributes = array();
     $minLengthAttributes = array();
     $maxLengthAttributes = array();
     $attributes = $model->getAttributeConfigs();
     foreach ($attributes as $name => $config) {
         switch ($config['type']) {
             case AttributeType::DateTime:
                 $rules[] = array($name, 'Craft\\DateTimeValidator');
                 break;
             case AttributeType::Email:
                 $emailAttributes[] = $name;
                 break;
             case AttributeType::Enum:
                 $rules[] = array($name, 'in', 'range' => ArrayHelper::stringToArray($config['values']));
                 break;
             case AttributeType::Handle:
                 $rules[] = array($name, 'Craft\\HandleValidator', 'reservedWords' => ArrayHelper::stringToArray($config['reservedWords']));
                 break;
             case AttributeType::Locale:
                 $rules[] = array($name, 'Craft\\LocaleValidator');
                 break;
             case AttributeType::Number:
                 $rule = array($name, 'numerical');
                 if ($config['min'] !== null) {
                     $rule['min'] = $config['min'];
                 }
                 if ($config['max'] !== null) {
                     $rule['max'] = $config['max'];
                 }
                 if (!$config['decimals']) {
                     $rule['integerOnly'] = true;
                 }
                 $rules[] = $rule;
                 break;
             case AttributeType::Url:
                 $urlAttributes[] = $name;
                 break;
             case AttributeType::UrlFormat:
                 $urlFormatAttributes[] = $name;
                 break;
             case AttributeType::Uri:
                 $uriAttributes[] = $name;
                 break;
         }
         // Uniques
         if (!empty($config['unique'])) {
             if (empty($config['required']) && (isset($config['null']) && $config['null'] === false)) {
                 $uniqueRequiredAttributes[] = $name;
             } else {
                 $uniqueAttributes[] = $name;
             }
         }
         // Required
         if ($config['type'] != AttributeType::Bool && !empty($config['required'])) {
             $requiredAttributes[] = $name;
         }
         // Lengths
         if ($config['type'] != AttributeType::Number && $config['type'] != AttributeType::Mixed) {
             if (isset($config['length']) && is_numeric($config['length'])) {
                 $strictLengthAttributes[(string) $config['length']][] = $name;
             } else {
                 // Only worry about min- and max-lengths if a strict length isn't set
                 if (isset($config['minLength']) && is_numeric($config['minLength'])) {
                     $minLengthAttributes[(string) $config['minLength']][] = $name;
                 }
                 if (isset($config['maxLength']) && is_numeric($config['maxLength'])) {
                     $maxLengthAttributes[(string) $config['maxLength']][] = $name;
                 }
             }
         }
         // Compare with other attributes
         if (isset($config['compare'])) {
             $comparisons = ArrayHelper::stringToArray($config['compare']);
             foreach ($comparisons as $comparison) {
                 if (preg_match('/^(==|=|!=|>=|>|<=|<)\\s*\\b(.*)$/', $comparison, $match)) {
                     $rules[] = array($name, 'compare', 'compareAttribute' => $match[2], 'operator' => $match[1], 'allowEmpty' => true);
                 }
             }
         }
         // Regex pattern matching
         if (!empty($config['matchPattern'])) {
             $rules[] = array($name, 'match', 'pattern' => $config['matchPattern']);
         }
     }
     // If this is a BaseRecord instance, catch any unique/required indexes. We don't validate required BELONGS_TO
     // relations because they might not get set until after validation.
     if ($model instanceof BaseRecord) {
         foreach ($model->defineIndexes() as $config) {
             $unique = !empty($config['unique']);
             $required = !empty($config['required']);
             if ($unique || $required) {
                 $columns = ArrayHelper::stringToArray($config['columns']);
                 if ($unique) {
                     if (count($columns) == 1) {
                         if (empty($attributes[$columns[0]]['required']) && (isset($attributes[$columns[0]]['null']) && $attributes[$columns[0]]['null'] === false)) {
                             $uniqueRequiredAttributes[] = $columns[0];
                         } else {
                             $uniqueAttributes[] = $columns[0];
                         }
                     } else {
                         $initialColumn = array_shift($columns);
                         $rules[] = array($initialColumn, 'Craft\\CompositeUniqueValidator', 'with' => implode(',', $columns));
                     }
                 }
                 if ($required) {
                     $requiredAttributes = array_merge($requiredAttributes, $columns);
                 }
             }
         }
     }
     if ($uniqueAttributes) {
         $rules[] = array(implode(',', $uniqueAttributes), 'unique');
     }
     if ($uniqueRequiredAttributes) {
         $rules[] = array(implode(',', $uniqueRequiredAttributes), 'unique', 'allowEmpty' => false);
     }
     if ($requiredAttributes) {
         $rules[] = array(implode(',', $requiredAttributes), 'required');
     }
     if ($emailAttributes) {
         $rules[] = array(implode(',', $emailAttributes), 'email');
     }
     if ($urlAttributes) {
         $rules[] = array(implode(',', $urlAttributes), 'Craft\\UrlValidator', 'defaultScheme' => 'http');
     }
     if ($urlFormatAttributes) {
         $rules[] = array(implode(',', $urlFormatAttributes), 'Craft\\UrlFormatValidator');
     }
     if ($uriAttributes) {
         $rules[] = array(implode(',', $uriAttributes), 'Craft\\UriValidator');
     }
     if ($strictLengthAttributes) {
         foreach ($strictLengthAttributes as $strictLength => $attributeNames) {
             $rules[] = array(implode(',', $attributeNames), 'length', 'is' => (int) $strictLength);
         }
     }
     if ($minLengthAttributes) {
         foreach ($minLengthAttributes as $minLength => $attributeNames) {
             $rules[] = array(implode(',', $attributeNames), 'length', 'min' => (int) $minLength);
         }
     }
     if ($maxLengthAttributes) {
         foreach ($maxLengthAttributes as $maxLength => $attributeNames) {
             $rules[] = array(implode(',', $attributeNames), 'length', 'max' => (int) $maxLength);
         }
     }
     $rules[] = array(implode(',', array_keys($attributes)), 'safe', 'on' => 'search');
     return $rules;
 }