General data checking is done by using Validator statically. Rules can be specified as a parameter to the rule() method or accessed directly via the is[RuleName]() method name convention: {{{ use lithium\util\Validator; The following are equivalent: Validator::rule('email', 'foo@example.com'); // true Validator::isEmail('foo-at-example.com'); // false }}} Data can also be validated against multiple rules, each having their own associated error message. The rule structure is array-based and hierarchical based on rule names and messages. Responses match the keys present in the $data parameter of check() up with an array of rules which they violate. {{{ embed:lithium\tests\cases\util\ValidatorTest::testCheckMultipleHasFirstError(1-15) }}} See the check() method for more information an multi-value datasets. Custom validation rules can also be added to Validator at runtime. These can either take the form of regular expression strings or functions supplied to the add() method. ### Rules The Validator class includes a series of commonly-used rules by default, any of which may be used in calls to rule() or check(), or called directly as a method. Additionally, many rules have a variety of different _formats_ in which they may be specified. The following is the list of the built-in rules, but keep in mind that none of them are hard-coded. Any rule may be overridden by adding a new rule of the same name using the add() method. - notEmpty: Checks that a string contains at least one non-whitespace character. - alphaNumeric: Checks that a string contains only integer or letters. - lengthBetween: Checks that a string length is within a specified range. Spaces are included in the character count. The available options are 'min' and 'max', which designate the minimum and maximum length of the string. - blank: Checks that a field is left blank **OR** only whitespace characters are present in its value. Whitespace characters include spaces, tabs, carriage returns and newlines. - creditCard: Checks that a value is a valid credit card number. This rule is divided into a series of formats: 'amex', 'bankcard', 'diners', 'disc', 'electron', 'enroute', 'jcb', 'maestro', 'mc', 'solo', 'switch', 'visa', 'voyager', 'fast'. If no format value is specified, the value defaults to 'any', which will validate the value if _any_ of the available formats match. You can also use the 'fast' format, which does a high-speed, low-fidelity check to ensure that the value looks like a real credit card number. This rule includes one option, 'deep', which (if set to true) validates the value using the Luhn algorithm if the format validation is successful. See the luhn validator below for more details. - date: Checks that a value is a valid date that complies with one or more formats. Also validates leap years. Possible formats are 'dmy' (27-12-2010 or 27-12-10 separators can be a space, period, dash, forward slash), 'mdy' (12-27-2010 or 12-27-10 separators can be a space, period, dash, forward slash), 'ymd' (2010-12-27 or 10-12-27 separators can be a space, period, dash, forward slash), 'dMy' (27 December 2010 or 27 Dec 2010), 'Mdy' (December 27, 2010 or Dec 27, 2010 comma is optional), 'My' (December 2010 or Dec 2010) or 'my' (12/2010 separators can be a space, period, dash, forward slash). - time: Checks that a value is a valid time. Validates time as 24hr (HH:MM) or am/pm ([ H]H:MM[a|p]m). Does not allow / validate seconds. - boolean: Checks that the value is or looks like a boolean value. The following types of values are interpreted as boolean and will pass the check. - boolean (true, false, 'true', 'false') - boolean number (1, 0, '1', '0') - boolean text string ('on', 'off', 'yes', 'no') - decimal: Checks that a value is a valid decimal. Takes one option, 'precision', which is an optional integer value defining the level of precision the decimal number must match. - email: Checks that a value is (probably) a valid email address. The subject of validating an actual email address is complicated and problematic. A regular expression that correctly validates addresses against RFC 5322 would be several pages long, with the drawback of being unable to keep up as new top-level domains are added. Instead, this validator uses PHP's internal input filtering API to check the format, and provides an option, 'deep' ( _boolean_) which, if set to true, will validate that the email address' domain contains a valid MX record. Keep in mind, this is just one of the many ways to validate an email address in the overall context of an application. For other ideas or examples, ask Sean. - ip: Validates a string as a valid IPv4 or IPv6 address. - money: Checks that a value is a valid monetary amount. This rule has two formats, 'right' and 'left', which indicates which side the monetary symbol (i.e. $) appears on. - numeric: Checks that a value is numeric. - phone: Check that a value is a valid phone number, non-locale-specific phone number. - postalCode: Checks that a given value is a valid US postal code. - inRange: Checks that a numeric value is within a specified range. This value has two options, 'upper' and 'lower', which specify the boundary of the value. - url: Checks that a value is a valid URL according to RFC 2395. Uses PHP's filter API, and accepts any options accepted for the validation URL filter. - luhn: Checks that a value is a valid credit card number according to the Luhn algorithm. (See also: the creditCard validator). - inList: Checks that a value is in a pre-defined list of values. This validator accepts one option, 'list', which is an array containing acceptable values. - regex: Checks that a value appears to be a valid regular expression, possibly containing PCRE-compatible options flags. - uuid: Checks that a value is a valid UUID. ### UTF-8 encoded input strings All rules operating on strings have been created with the possibility of UTF-8 encoded input in mind. A default PHP binary and an enabled Lithium g11n bootstrap will make these rules work correctly in any case. Should you ever experience odd behavior following paragraph with implementation details might help you to track to the cause. The rules alphaNumeric and money rely on additional functionality of PCRE to validate UTF-8 encoded strings. As no PCRE feature detection is done, having this feature enabled in PCRE isn't optional. Please ensure you've got PCRE compiled with UTF-8 support.
Наследование: extends lithium\core\StaticObject
Пример #1
0
 public static function __init(array $options = array())
 {
     parent::__init($options);
     $self = static::_instance();
     $self->_finders['count'] = function ($self, $params, $chain) use(&$query, &$classes) {
         $db = Connections::get($self::meta('connection'));
         $records = $db->read('SELECT count(*) as count FROM posts', array('return' => 'array'));
         return $records[0]['count'];
     };
     Post::applyFilter('save', function ($self, $params, $chain) {
         $post = $params['record'];
         if (!$post->id) {
             $post->created = date('Y-m-d H:i:s');
         } else {
             $post->modified = date('Y-m-d H:i:s');
         }
         $params['record'] = $post;
         return $chain->next($self, $params, $chain);
     });
     Validator::add('isUniqueTitle', function ($value, $format, $options) {
         $conditions = array('title' => $value);
         // If editing the post, skip the current psot
         if (isset($options['values']['id'])) {
             $conditions[] = 'id != ' . $options['values']['id'];
         }
         // Lookup for posts with same title
         return !Post::find('first', array('conditions' => $conditions));
     });
 }
Пример #2
0
 public static function init()
 {
     $class = __CLASS__;
     Validator::add('modelIsSet', function ($value, $format, $options) use($class) {
         if (isset($options['model']) && ($options['model'] = $class)) {
             return true;
         }
         return false;
     });
 }
Пример #3
0
 public function testMultipleLocales()
 {
     $data = '/phone en_US/';
     Catalog::write('runtime', 'validation.phone', 'en_US', $data);
     $data = '/phone en_GB/';
     Catalog::write('runtime', 'validation.phone', 'en_GB', $data);
     Validator::add('phone', array('en_US' => Catalog::read('runtime', 'validation.phone', 'en_US'), 'en_GB' => Catalog::read('runtime', 'validation.phone', 'en_GB')));
     $result = Validator::isPhone('phone en_US', 'en_US');
     $this->assertTrue($result);
     $result = Validator::isPhone('phone en_GB', 'en_GB');
     $this->assertTrue($result);
 }
Пример #4
0
 /**
  * Options variations:
  *   1. +pattern -mx (default)
  *   2. +pattern +mx
  *   3. -pattern -mx
  *   4. -pattern +mx
  *
  * `$emails[0]` with any `$options` or without options should be `true`
  * `$emails[1]` with any `$options` or without options should be `false`
  * `$emails[2]` with `$options[1]` should be `true`
  * `$emails[2]` with `$options[1]` should be `true`
  *
  * `$options[1]` works same as Lithium's default email validator implementation
  */
 public function testEmail()
 {
     $emails = array('*****@*****.**', 'invalid.djordjekovacevic.com', 'looks.valid@djordjekovacevic.c');
     $options = array(array('mx' => true), array('pattern' => false), array('pattern' => false, 'mx' => true));
     $this->assertTrue(Validator::rule('email', $emails[0]));
     $this->assertTrue(Validator::rule('email', $emails[0], 'any', $options[0]));
     $this->assertTrue(Validator::rule('email', $emails[0], 'any', $options[1]));
     $this->assertTrue(Validator::rule('email', $emails[0], 'any', $options[2]));
     $this->assertFalse(Validator::rule('email', $emails[1]));
     $this->assertFalse(Validator::rule('email', $emails[1], 'any', $options[0]));
     $this->assertFalse(Validator::rule('email', $emails[1], 'any', $options[1]));
     $this->assertFalse(Validator::rule('email', $emails[1], 'any', $options[2]));
     $this->assertFalse(Validator::rule('email', $emails[2], 'any'));
     $this->assertTrue(Validator::rule('email', $emails[2], 'any', $options[1]));
 }
Пример #5
0
 public function testConditionalInRange()
 {
     $values = array('height' => 195, 'gender' => 'M');
     $rules = array('height' => array(array('conditionalInRange', 'message' => 'Incorrect value for given condition!', 'upper' => 201, 'lower' => 184, 'conditions' => array(array('gender', '===', 'M'))), array('conditionalInRange', 'message' => 'Incorrect value for given condition!', 'upper' => 186, 'lower' => 167, 'conditions' => array(array('gender', '===', 'W')))));
     $validate = Validator::check($values, $rules);
     $this->assertTrue(empty($validate));
     $values['gender'] = 'W';
     $validate = Validator::check($values, $rules);
     $this->assertTrue(!empty($validate));
     $values['height'] = 171;
     $validate = Validator::check($values, $rules);
     $this->assertTrue(empty($validate));
     $values['height'] = 165;
     $validate = Validator::check($values, $rules);
     $this->assertTrue(!empty($validate));
 }
 public static function __init(array $options = array())
 {
     parent::__init($options);
     $self = static::_instance();
     Comment::applyFilter('save', function ($self, $params, $chain) {
         $comment = $params['record'];
         if (!$comment->id) {
             $comment->created = date('Y-m-d h:i:s');
         } else {
             $comment->modified = date('Y-m-d h:i:s');
         }
         $params['record'] = $comment;
         return $chain->next($self, $params, $chain);
     });
     Validator::add('validName', '/^[A-Za-z0-9\'\\s]+$/');
 }
Пример #7
0
 public static function validate($object, $object_hash = array())
 {
     $errors = null;
     if (!in_array(spl_object_hash($object), $object_hash)) {
         $object_hash[] = spl_object_hash($object);
     }
     $reflection = new \ReflectionClass($object);
     $classname = $reflection->getName();
     $validations = $object->validations;
     if (!empty($validations)) {
         $unique = $equalWith = array();
         foreach ($validations as $field => $rules) {
             foreach ($rules as $key => $value) {
                 if ($value[0] == "unique") {
                     $unique[] = array($field, "message" => $value['message']);
                     if (count($validations[$field]) == 1) {
                         unset($validations[$field]);
                     } else {
                         unset($validations[$field][$key]);
                     }
                 } else {
                     if ($value[0] == "equalWith") {
                         $equalWith[] = array($field, "message" => $value['message'], "with" => $value['with']);
                         if (count($validations[$field]) == 1) {
                             unset($validations[$field]);
                         } else {
                             unset($validations[$field][$key]);
                         }
                     }
                 }
             }
         }
         $errors = Validator::check(static::convertToArray($object), $validations);
         /** Unique checking */
         foreach ($unique as $key => $value) {
             $result = $classname::getRepository()->findOneBy(array($value[0] => $object->{$value}[0]));
             if (!empty($result)) {
                 $errors[$value[0]][] = $value["message"];
             }
         }
         /** EqualWith checking */
         foreach ($equalWith as $key => $value) {
             if ($object->{$value}[0] != $object->{$value}['with']) {
                 $errors[$value[0]][] = $value["message"];
             }
         }
         $reflection = new \ReflectionClass($object);
         $properties = $reflection->getProperties(\ReflectionProperty::IS_PROTECTED);
         try {
             foreach ($properties as $property) {
                 $property->setAccessible(true);
                 if (ModelAnnotation::match($property, array('ManyToMany', 'OneToMany'))) {
                     $relation = $property->getValue($object);
                     foreach ($relation as $item) {
                         if (!in_array(spl_object_hash($item), $object_hash)) {
                             if (!ModelValidator::isValid($item, $object_hash)) {
                                 $errors[$property->getName()][] = $item->getErrors();
                             }
                         }
                     }
                 } elseif (ModelAnnotation::match($property, array('ManyToOne', 'OneToOne'))) {
                     if ($item = $property->getValue($object)) {
                         if (!in_array(spl_object_hash($item), $object_hash)) {
                             if (!ModelValidator::isValid($item, $object_hash)) {
                                 $errors[$property->getName()][] = $item->getErrors();
                             }
                         }
                     }
                 }
             }
         } catch (\ReflectionException $e) {
             die($e->getTrace() . "-" . $e->getMessage());
             continue;
         }
     }
     ModelValidator::$_errors[spl_object_hash($object)] = $errors;
     return $errors;
 }
Пример #8
0
Validator::add(array('sha1' => '/^[A-Fa-f0-9]{40}$/', 'slug' => '/^[a-z0-9\\_\\-\\.]*$/', 'loose_slug' => '/^[a-zA-Z0-9\\_\\-\\.]*$/', 'strict_slug' => '/^[a-z][a-z0-9\\_\\-]*$/', 'isUnique' => function ($value, $format, $options) {
    $conditions = array($options['field'] => $value);
    foreach ((array) $options['model']::meta('key') as $field) {
        if (!empty($options['values'][$field])) {
            $conditions[$field] = array('!=' => $options['values'][$field]);
        }
    }
    $fields = $options['field'];
    $result = $options['model']::find('first', compact('fields', 'conditions'));
    return (bool) empty($result);
}, 'status' => function ($value, $format, $options) {
    return (bool) $options['model']::status($value);
}, 'type' => function ($value, $format, $options) {
    return (bool) $options['model']::types($value);
}, 'md5' => function ($value, $format, $options) {
    return (bool) (strlen($value) === 32 && ctype_xdigit($value));
}, 'attachmentType' => function ($value, $type, $data) {
    if (!isset($data['attachment'])) {
        return true;
    }
    $mime = $data['attachment']['type'];
    $mimeTypes = Mime::types();
    foreach ($data['types'] as $each) {
        if (isset($mimeTypes[$each]) && in_array($mime, $mimeTypes[$each])) {
            return true;
        }
    }
    return false;
}, 'attachmentSize' => function ($value, $type, $data) {
    if (!isset($data['attachment'])) {
        return true;
    }
    $size = $data['attachment']['size'];
    if (is_string($data['size'])) {
        if (preg_match('/([0-9\\.]+) ?([a-z]*)/i', $data['size'], $matches)) {
            $number = $matches[1];
            $suffix = $matches[2];
            $suffixes = array("" => 0, "Bytes" => 0, "KB" => 1, "MB" => 2, "GB" => 3, "TB" => 4, "PB" => 5);
            if (isset($suffixes[$suffix])) {
                $data['size'] = round($number * pow(1024, $suffixes[$suffix]));
            }
        }
    }
    return $data['size'] >= $size;
}));
Пример #9
0
 protected static function _normalizeResource($resource)
 {
     if (is_callable($resource)) {
         return $resource;
     }
     if (is_array($resource)) {
         if ($resource === array('*')) {
             return true;
         }
         return $resource;
     }
     if (!is_string($resource)) {
         throw new Exception('Unsupported resource definition: ' . var_export($resource, true));
     }
     if (preg_match('/^([a-z0-9_\\*\\\\]+)::([a-z0-9_\\*]+)$/i', $resource, $matches)) {
         return array('controller' => $matches[1], 'action' => $matches[2]);
     }
     if (Validator::isRegex($resource)) {
         return function ($params) use($resource) {
             return (bool) preg_match($resource, $params['request']->url);
         };
     }
     if ($resource === '*') {
         return true;
     }
     return function ($params) use($resource) {
         return $resource === $params['request']->url;
     };
 }
Пример #10
0
 *		'width' => 45,
 *		'height' => 45,
 *		'message'   => 'The image dimensions must be 45 x 45'
 *         ]
 *     ]
 * ];
 * }}}
 *
 * If the field is set to `null`, this means the user intends to delete it so it would return `true`.
 */
Validator::add('dimensions', function ($value, $rule, $options) {
    $status = [];
    $field = $options['field'];
    if ($options['required'] && empty($_FILES[$field]['tmp_name'])) {
        return false;
    }
    if ($options['skipEmpty'] && empty($_FILES[$field]['tmp_name'])) {
        return true;
    }
    if (!isset($_FILES[$options['field']]['error']) && null === $_FILES[$options['field']]) {
        return true;
    }
    list($width, $height, $type, $attr) = getimagesize($_FILES[$field]['tmp_name']);
    if (isset($options['width']) && $width !== $options['width']) {
        $status[] = false;
    }
    if (isset($options['height']) && $height !== $options['height']) {
        $status[] = false;
    }
    return !in_array(false, $status, true);
});
Пример #11
0
 /**
  * Detects properties of the request and returns a boolean response.
  *
  * @see lithium\action\Request::detect()
  * @todo Remove $content and refer to Media class instead
  * @param string $flag
  * @return boolean
  */
 public function is($flag)
 {
     $flag = strtolower($flag);
     if (!empty($this->_detectors[$flag])) {
         $detector = $this->_detectors[$flag];
         if (is_array($detector)) {
             list($key, $check) = $detector + array('', '');
             if (is_array($check)) {
                 $check = '/' . join('|', $check) . '/i';
             }
             if (Validator::isRegex($check)) {
                 return (bool) preg_match($check, $this->env($key));
             }
             return $this->env($key) == $check;
         }
         if (is_callable($detector)) {
             return $detector($this);
         }
         return (bool) $this->env($detector);
     }
     return false;
 }
Пример #12
0
/**
 * Integration with `View`. Embeds message translation aliases into the `View`
 * class (or other content handler, if specified) when content is rendered. This
 * enables translation functions, i.e. `<?=$t("Translated content"); ?>`.
 */
Media::applyFilter('_handle', function ($self, $params, $chain) {
    $params['handler'] += array('outputFilters' => array());
    $params['handler']['outputFilters'] += Message::aliases();
    return $chain->next($self, $params, $chain);
});
/**
 * Integration with `Validator`. You can load locale dependent rules into the `Validator`
 * by specifying them manually or retrieving them with the `Catalog` class.
 */
foreach (array('phone', 'postalCode', 'ssn') as $name) {
    Validator::add($name, Catalog::read(true, "validation.{$name}", 'en_US'));
}
/**
 * Intercepts dispatching processes in order to set the effective locale by using
 * the locale of the request or if that is not available retrieving a locale preferred
 * by the client.
 */
ActionDispatcher::applyFilter('_callable', function ($self, $params, $chain) {
    $request = $params['request'];
    $controller = $chain->next($self, $params, $chain);
    if (!$request->locale) {
        $request->params['locale'] = Locale::preferred($request);
    }
    Environment::set(Environment::get(), array('locale' => $request->locale));
    return $controller;
});
Пример #13
0
 /**
  * Convert an exception object to an exception result array for test reporting.
  *
  * @param array $exception The exception data to report on. Statistics are gathered and
  *               added to the reporting stack contained in `Unit::$_results`.
  * @param string $lineFlag
  * @return void
  * @todo Refactor so that reporters handle trace formatting.
  */
 protected function _reportException($exception, $lineFlag = null)
 {
     $message = $exception['message'];
     $isExpected = ($exp = end($this->_expected)) && ($exp === true || $exp === $message || Validator::isRegex($exp) && preg_match($exp, $message));
     if ($isExpected) {
         return array_pop($this->_expected);
     }
     $initFrame = current($exception['trace']) + array('class' => '-', 'function' => '-');
     foreach ($exception['trace'] as $frame) {
         if (isset($scopedFrame)) {
             break;
         }
         if (!class_exists('lithium\\analysis\\Inspector')) {
             continue;
         }
         if (isset($frame['class']) && in_array($frame['class'], Inspector::parents($this))) {
             $scopedFrame = $frame;
         }
     }
     if (class_exists('lithium\\analysis\\Debugger')) {
         $exception['trace'] = Debugger::trace(array('trace' => $exception['trace'], 'format' => '{:functionRef}, line {:line}', 'includeScope' => false, 'scope' => array_filter(array('functionRef' => __NAMESPACE__ . '\\{closure}', 'line' => $lineFlag))));
     }
     $this->_result('exception', $exception + array('class' => $initFrame['class'], 'method' => $initFrame['function']));
 }
Пример #14
0
 public function testValidationWithContextData()
 {
     Validator::add('someModelRule', function ($value, $format, $options) {
         return $value == 'Title' && $options['values']['body'] == 'Body';
     });
     $result = Validator::check(array('title' => 'Title', 'body' => 'Body'), array('title' => array('someModelRule')));
     $this->assertIdentical(array(), $result);
     $result = Validator::check(array('title' => 'Title', 'body' => 'Not Body'), array('title' => array('someModelRule')));
     $this->assertIdentical(array('title' => array(0)), $result);
 }
Пример #15
0
 Validator::add('unique', function ($value, $format, $options) {
     $options += array('conditions' => array(), 'getEntityManager' => 'getEntityManager', 'connection' => isset($options['model']::$connectionName) ? $options['model']::$connectionName : 'default', 'checkPrimaryKey' => true);
     $entityManager = null;
     if (!empty($options['getEntityManager']) && method_exists($options['model'], $options['getEntityManager']) && is_callable($options['model'] . '::' . $options['getEntityManager'])) {
         $entityManager = call_user_func($options['model'] . '::' . $options['getEntityManager']);
     } elseif (!empty($options['connection'])) {
         $entityManager = lithium\data\Connections::get($options['connection'])->getEntityManager();
     }
     if (!$entityManager) {
         throw new \lithium\core\ConfigException('Could not get the entity manager');
     }
     $conditions = array($options['field'] => $value) + $options['conditions'];
     $query = $entityManager->createQueryBuilder();
     $expressions = array();
     $p = 1;
     foreach ($conditions as $field => $value) {
         $expressions[] = $query->expr()->eq('m.' . $field, '?' . $p);
         $query->setParameter($p, $value);
         $p++;
     }
     if ($options['checkPrimaryKey'] && !empty($options['values'])) {
         $metaData = $entityManager->getClassMetadata($options['model']);
         foreach ($metaData->identifier as $field) {
             if (isset($options['values'][$field])) {
                 $expressions[] = $query->expr()->neq('m.' . $field, '?' . $p);
                 $query->setParameter($p, $options['values'][$field]);
                 $p++;
             }
         }
     }
     $query->add('select', 'count(m.' . $options['field'] . ') total')->add('from', $options['model'] . ' m')->add('where', call_user_func_array(array($query->expr(), 'andx'), $expressions));
     $result = $query->getQuery()->getSingleResult();
     return empty($result['total']);
 });
Пример #16
0
});
Uploads::applyFilter('save', function ($self, $params, $chain) {
    if ($params['data']) {
        $params['entity']->set($params['data']);
        $params['data'] = array();
    }
    if (!$params['entity']->id) {
        $params['entity']->created = date('Y-m-d H:i:s');
    }
    return $chain->next($self, $params, $chain);
});
use lithium\util\Validator;
Validator::add('usernameTaken', function ($value) {
    $success = false;
    if (strlen($value) != 0) {
        $success = count(Users::findByUsername($value)) == 0 ? false : true;
    }
    return !$success;
});
use lithium\core\Libraries;
Libraries::add('upload', array('path' => LITHIUM_APP_PATH . '/libraries/_source/upload/'));
Libraries::add('captcha', array('path' => LITHIUM_APP_PATH . '/libraries/_source/captcha/', 'webroot' => LITHIUM_APP_PATH . '/libraries/_source/captcha/', "bootstrap" => "securimage.php"));
define('_INSTALL', file_exists($_SERVER['DOCUMENT_ROOT'] . "/install") ? '1' : '0');
function getBaseUrl()
{
    $protocol = isset($_SERVER["HTTPS"]) && $_SERVER['HTTPS'] != "off" ? "https" : "http";
    return $protocol . "://" . $_SERVER['HTTP_HOST'];
}
use lithium\core\Environment;
Environment::is(function ($request) {
    return in_array($request->env('SERVER_ADDR'), array('::1', '127.0.0.1')) ? 'development' : 'production';
Пример #17
0
 /**
  * Initializes the list of default validation rules.
  *
  * @return void
  */
 public static function __init()
 {
     $alnum = '[A-Fa-f0-9]';
     $class = get_called_class();
     static::$_methodFilters[$class] = array();
     static::$_rules = array('alphaNumeric' => '/^[\\p{Ll}\\p{Lm}\\p{Lo}\\p{Lt}\\p{Lu}\\p{Nd}]+$/mu', 'blank' => '/[^\\s]/', 'creditCard' => array('amex' => '/^3[4|7]\\d{13}$/', 'bankcard' => '/^56(10\\d\\d|022[1-5])\\d{10}$/', 'diners' => '/^(?:3(0[0-5]|[68]\\d)\\d{11})|(?:5[1-5]\\d{14})$/', 'disc' => '/^(?:6011|650\\d)\\d{12}$/', 'electron' => '/^(?:417500|4917\\d{2}|4913\\d{2})\\d{10}$/', 'enroute' => '/^2(?:014|149)\\d{11}$/', 'jcb' => '/^(3\\d{4}|2100|1800)\\d{11}$/', 'maestro' => '/^(?:5020|6\\d{3})\\d{12}$/', 'mc' => '/^5[1-5]\\d{14}$/', 'solo' => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/', 'switch' => '/^(?:49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})' . '\\d{10}(\\d{2,3})?)|(?:564182\\d{10}(\\d{2,3})?)|(6(3(33[0-4]' . '[0-9])|759[0-9]{2})\\d{10}(\\d{2,3})?)$/', 'visa' => '/^4\\d{12}(\\d{3})?$/', 'voyager' => '/^8699[0-9]{11}$/', 'fast' => '/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|3' . '(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$/'), 'date' => array('dmy' => '%^(?:(?:31(\\/|-|\\.|\\x20)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)' . '(\\/|-|\\.|\\x20)(?:0?[1,3-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?' . '\\d{2})$|^(?:29(\\/|-|\\.|\\x20)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?' . '(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])' . '00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/|-|\\.|\\x20)(?:(?:0?[1-9])|' . '(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%', 'mdy' => '%^(?:(?:(?:0?[13578]|1[02])(\\/|-|\\.|\\x20)31)\\1|(?:(?:0?[13-9]|' . '1[0-2])(\\/|-|\\.|\\x20)(?:29|30)\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d' . '{2})$|^(?:0?2(\\/|-|\\.|\\x20)29\\3(?:(?:(?:1[6-9]|[2-9]\\d)?' . '(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])' . '00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\\/|-|\\.|\\x20)(?:0?[1-9]|1' . '\\d|2[0-8])\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%', 'ymd' => '%^(?:(?:(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579]' . '[26])|(?:(?:16|[2468][048]|[3579][26])00)))(\\/|-|\\.|\\x20)' . '(?:0?2\\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\\d)?\\d{2})(\\/|-|\\.|' . '\\x20)(?:(?:(?:0?[13578]|1[02])\\2(?:31))|(?:(?:0?[1,3-9]|1[0-2])' . '\\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\\2(?:0?[1-9]|1\\d|2[0-8]' . '))))$%', 'dMy' => '/^((31(?!\\ (Feb(ruary)?|Apr(il)?|June?|(Sep(?=\\b|t)t?|Nov)' . '(ember)?)))|((30|29)(?!\\ Feb(ruary)?))|(29(?=\\ Feb(ruary)?\\ ' . '(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468]' . '[048]|[3579][26])00)))))|(0?[1-9])|1\\d|2[0-8])\\ (Jan(uary)?|' . 'Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|' . 'Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)\\ ((1[6-9]|[2-9]' . '\\d)\\d{2})$/', 'Mdy' => '/^(?:(((Jan(uary)?|Ma(r(ch)?|y)|Jul(y)?|Aug(ust)?|Oct(ober)?' . '|Dec(ember)?)\\ 31)|((Jan(uary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)' . '|(ne?))|Aug(ust)?|Oct(ober)?|(Sept|Nov|Dec)(ember)?)\\ (0?[1-9]' . '|([12]\\d)|30))|(Feb(ruary)?\\ (0?[1-9]|1\\d|2[0-8]|(29(?=,?\\ ' . '((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468]' . '[048]|[3579][26])00)))))))\\,?\\ ((1[6-9]|[2-9]\\d)\\d{2}))$/', 'My' => '%^(Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|' . 'Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)[ /]((1[6-9]' . '|[2-9]\\d)\\d{2})$%', 'my' => '%^(((0[123456789]|10|11|12)([- /.])(([1][9][0-9][0-9])|([2][0-9]' . '[0-9][0-9]))))$%'), 'hostname' => '(?:[a-z0-9][-a-z0-9]*\\.)*(?:[a-z0-9][-a-z0-9]{0,62})\\.' . '(?:(?:[a-z]{2}\\.)?[a-z]{2,4}|museum|travel)', 'ip' => '(?:(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])\\.){3}' . '(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])', 'money' => array('right' => '/^(?!0,?\\d)(?:\\d{1,3}(?:([, .])\\d{3})?(?:\\1\\d{3})*|(?:\\d+))' . '((?!\\1)[,.]\\d{2})?(?<!\\x{00a2})\\p{Sc}?$/u', 'left' => '/^(?!\\x{00a2})\\p{Sc}?(?!0,?\\d)(?:\\d{1,3}(?:([, .])\\d{3})?' . '(?:\\1\\d{3})*|(?:\\d+))((?!\\1)[,.]\\d{2})?$/u'), 'notEmpty' => '/[^\\s]+/m', 'phone' => '/^\\+?[0-9\\(\\)\\-]{10,20}$/', 'postalCode' => '/(^|\\A\\b)[A-Z0-9\\s\\-]{5,}($|\\b\\z)/i', 'regex' => '/^\\/(.+)\\/[gimsxu]*$/', 'time' => '%^((0?[1-9]|1[012])(:[0-5]\\d){0,2}([AP]M|[ap]m))$|^([01]\\d|2[0-3])' . '(:[0-5]\\d){0,2}$%', 'boolean' => function ($value) {
         return in_array($value, array(0, 1, '0', '1', true, false), true);
     }, 'decimal' => function ($value, $format = null, $options = array()) {
         $defaults = array('precision' => null);
         $options += $defaults;
         $precision = '+(?:[eE][-+]?[0-9]+)?';
         $precision = $options['precision'] ? '{' . $options['precision'] . '}' : $precision;
         return (bool) preg_match("/^[-+]?[0-9]*\\.{1}[0-9]{$precision}\$/", (string) $value);
     }, 'inList' => function ($value, $format, $options) {
         $options += array('list' => array());
         return in_array($value, $options['list']);
     }, 'lengthBetween' => function ($value, $format, $options) {
         $length = strlen($value);
         $options += array('min' => 1, 'max' => 255);
         return $length >= $options['min'] && $length <= $options['max'];
     }, 'luhn' => function ($value) {
         if (empty($value) || !is_string($value)) {
             return false;
         }
         $sum = 0;
         $length = strlen($value);
         for ($position = 1 - $length % 2; $position < $length; $position += 2) {
             $sum += $value[$position];
         }
         for ($position = $length % 2; $position < $length; $position += 2) {
             $number = $value[$position] * 2;
             $sum += $number < 10 ? $number : $number - 9;
         }
         return $sum % 10 == 0;
     }, 'numeric' => function ($value) {
         return is_numeric($value);
     }, 'inRange' => function ($value, $format, $options) {
         $defaults = array('upper' => null, 'lower' => null);
         $options += $defaults;
         if (!is_numeric($value)) {
             return false;
         }
         switch (true) {
             case !is_null($options['upper']) && !is_null($options['lower']):
                 return $value > $options['lower'] && $value < $options['upper'];
             case !is_null($options['upper']):
                 return $value < $options['upper'];
             case !is_null($options['lower']):
                 return $value > $options['lower'];
         }
         return is_finite($value);
     }, 'uuid' => "/{$alnum}{8}-{$alnum}{4}-{$alnum}{4}-{$alnum}{4}-{$alnum}{12}/");
     static::$_rules['email'] = '/^[a-z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&\'*+\\/=?^_`';
     static::$_rules['email'] .= '{|}~-]+)*@' . static::$_rules['hostname'] . '$/i';
     $urlChars = '([' . preg_quote('!"$&\'()*+,-.@_:;=') . '\\/0-9a-z]|(%[0-9a-f]{2}))';
     $url = '/^(?:(?:https?|ftps?|file|news|gopher):\\/\\/)__strict__';
     $url .= '(?:' . static::$_rules['ip'] . '|' . static::$_rules['hostname'] . ')';
     $url .= '(?::[1-9][0-9]{0,3})?(?:\\/?|\\/' . $urlChars . '*)?(?:\\?' . $urlChars . '*)?';
     $url .= '(?:#' . $urlChars . '*)?$/i';
     static::$_rules['url'] = array('strict' => str_replace('__strict__', '', $url), 'loose' => str_replace('__strict__', '?', $url));
     $emptyCheck = function ($self, $params, $chain) {
         extract($params);
         return empty($value) && $value != '0' ? false : $chain->next($self, $params, $chain);
     };
     static::$_methodFilters[$class]['alphaNumeric'] = array($emptyCheck);
     static::$_methodFilters[$class]['notEmpty'] = array($emptyCheck);
     static::$_methodFilters[$class]['creditCard'] = array(function ($self, $params, $chain) {
         extract($params);
         $options += array('deep' => false);
         if (strlen($value = str_replace(array('-', ' '), '', $value)) < 13) {
             return false;
         }
         if (!$chain->next($self, compact('value') + $params, $chain)) {
             return false;
         }
         return $options['deep'] ? Validator::isLuhn($value) : true;
     });
     $host = static::$_rules['hostname'];
     static::$_methodFilters[$class]['email'] = array(function ($self, $params, $chain) use($host) {
         extract($params);
         $defaults = array('deep' => false);
         $options += $defaults;
         if (!$chain->next($self, $params, $chain)) {
             return false;
         }
         if (!$options['deep']) {
             return true;
         }
         if (preg_match('/@(' . $host . ')$/i', $value, $regs)) {
             if (getmxrr($regs[1], $mxhosts)) {
                 return is_array($mxhosts);
             }
         }
         return false;
     });
 }
Пример #18
0
 /**
  * Normalizes `Exception` objects and PHP error data into a single array format, and checks
  * each error against the list of expected errors (set using `expectException()`).  If a match
  * is found, the expectation is removed from the stack and the error is ignored.  If no match
  * is found, then the error data is logged to the test results.
  *
  * @param mixed $exception An `Exception` object instance, or an array containing the following
  *              keys: `'message'`, `'file'`, `'line'`, `'trace'` (in `debug_backtrace()`
  *              format) and optionally `'code'` (error code number) and `'context'` (an array
  *              of variables relevant to the scope of where the error occurred).
  * @param integer $lineFlag A flag used for determining the relevant scope of the call stack.
  *                Set to the line number where test methods are called.
  * @return void
  * @see lithium\test\Unit::expectException()
  * @see lithium\test\Unit::_reportException()
  */
 protected function _handleException($exception, $lineFlag = null)
 {
     if (is_object($exception)) {
         $data = array();
         foreach (array('message', 'file', 'line', 'trace') as $key) {
             $method = 'get' . ucfirst($key);
             $data[$key] = $exception->{$method}();
         }
         $ref = $exception->getTrace();
         $ref = $ref[0] + array('class' => null);
         if ($ref['class'] == __CLASS__ && $ref['function'] == 'skipIf') {
             return $this->_result('skip', $data);
         }
         $exception = $data;
     }
     $message = $exception['message'];
     $isExpected = ($exp = end($this->_expected)) && ($exp === true || $exp == $message || Validator::isRegex($exp) && preg_match($exp, $message));
     if ($isExpected) {
         return array_pop($this->_expected);
     }
     $this->_reportException($exception, $lineFlag);
 }
Пример #19
0
 *  `'mx'` boolean that enable validator to check if MX DNS record exists and
 *  `'pattern'` mixed `false` to use `filter_var()` function (default in lithium)
 * or regex to check against. By default this filter check against custom regex
 * that doesn't match all [RFC 5322](http://tools.ietf.org/html/rfc5322) valid
 * emails, but will match against most correct emails, and doesn't check domain
 * against MX DNS record. With combinations of this options you can achieve
 * enough validations, including lithium's default (`'mx' => false, 'pattern' => false`).
 */
$overriddenValidators['email'] = function ($value, $format, $options) {
    $defaults = array('mx' => false, 'pattern' => '/^[a-z0-9][a-z0-9_.-]*@[a-z0-9.-]{3,}\\.[a-z]{2,4}$/i');
    $options += $defaults;
    $valid = true;
    switch ($options['pattern']) {
        case false:
            $valid = filter_var($value, FILTER_VALIDATE_EMAIL);
            break;
        default:
            $valid = preg_match($options['pattern'], $value);
            break;
    }
    if ($valid && $options['mx'] && function_exists('checkdnsrr')) {
        $emailParts = explode('@', $value);
        $valid = checkdnsrr(end($emailParts), 'MX');
    }
    return $valid;
};
/**
 * Initialize overridden validators
 */
Validator::add($overriddenValidators);
Пример #20
0
 /**
  * Tests validating nested fields using dot-separated paths.
  */
 public function testNestedFields()
 {
     $rules = array('id' => array('numeric', 'message' => 'Bad ID'), 'profile.name' => "Can't be empty", 'profile.email' => array('email', 'message' => 'Must be a valid email'));
     $data = array('id' => 1, 'profile' => array('email' => 'foo'));
     $result = Validator::check($data, $rules);
     $expected = array('profile.name' => array("Can't be empty"), 'profile.email' => array('Must be a valid email'));
     $this->assertEqual($expected, $result);
     $data = array('id' => '.', 'profile' => array('email' => '*****@*****.**', 'name' => 'Bob'));
     $result = Validator::check($data, $rules);
     $this->assertEqual(array('id' => array('Bad ID')), $result);
 }
Пример #21
0
 protected function _assignAccessors($entity)
 {
     $fields = static::_formattedFields($this->_config['fields']);
     $queried = $entity->export()['data'];
     if (0 === count(array_intersect_key($queried, $fields))) {
         return $entity;
     }
     foreach ($fields as $field => $name) {
         if (isset($_FILES[$field]['name'])) {
             // Attempted file upload
             $file = $_FILES[$field]['name'];
             if (Validator::rule('isUploadedFile', $file, 'any', ['field' => $field])) {
                 // Valid file upload
                 $entity->{$field} = new UploadableStorage($field, $name, $entity);
             }
         } else {
             // Read
             $entity->{$field} = new UploadableStorage($field, $name, $entity);
         }
     }
     return $entity;
 }
Пример #22
0
<?php

use lithium\util\Validator;
Validator::add('uniqueName', function ($value, $format, $options) {
    $model = "\\" . $options['model'];
    //return !(boolean) $model::first(array('conditions' => array('name' => $options['values']['name'])));
    return true;
});
Пример #23
0
 public function testRespondsToMagic()
 {
     $this->assertTrue(Validator::respondsTo('isAlphaNumeric'));
     $this->assertTrue(Validator::respondsTo('isCreditCard'));
     $this->assertFalse(Validator::respondsTo('isFoobar'));
 }
 public function testNlNl()
 {
     Validator::add(Catalog::read('validation', 'nl_NL'));
     $this->assertTrue(Validator::isSsn('123456789'));
     $this->assertFalse(Validator::isSsn('12345678'));
 }
Пример #25
0
 * Integration with `View`. Embeds message translation aliases into the `View`
 * class (or other content handler, if specified) when content is rendered. This
 * enables translation functions, i.e. `<?=$t("Translated content"); ?>`.
 */
Media::applyFilter('_handle', function ($self, $params, $chain) {
    $params['handler'] += array('outputFilters' => array());
    $params['handler']['outputFilters'] += Message::aliases();
    return $chain->next($self, $params, $chain);
});
/**
 * Integration with `Validator`. You can load locale dependent rules into the `Validator`
 * by specifying them manually or retrieving them with the `Catalog` class.
 */
Validator::add('phone', Catalog::read('validation.phone', 'en_US'));
Validator::add('postalCode', Catalog::read('validation.postalCode', 'en_US'));
Validator::add('ssn', Catalog::read('validation.ssn', 'en_US'));
/**
 * Intercepts dispatching processes in order to set the effective locale by using
 * the locale of the request or if that is not available retrieving a locale preferred
 * by the client.
 */
ActionDispatcher::applyFilter('_callable', function ($self, $params, $chain) {
    $request = $params['request'];
    $controller = $chain->next($self, $params, $chain);
    if (!$request->locale) {
        $request->params['locale'] = Locale::preferred($request);
    }
    Environment::set(Environment::get(), array('locale' => $request->locale));
    return $controller;
});
ConsoleDispatcher::applyFilter('_callable', function ($self, $params, $chain) {
Пример #26
0
 public static function __init()
 {
     /*
      * Some special validation rules
      */
     Validator::add('uniqueEmail', function ($value) {
         $current_user = Auth::check('li3b_user');
         if (!empty($current_user)) {
             $user = User::find('first', array('fields' => array('_id'), 'conditions' => array('email' => $value, '_id' => array('$ne' => new MongoId($current_user['_id'])))));
         } else {
             $user = User::find('first', array('fields' => array('_id'), 'conditions' => array('email' => $value)));
         }
         if (!empty($user)) {
             return false;
         }
         return true;
     });
     Validator::add('notEmptyHash', function ($value) {
         if ($value == Password::hash('')) {
             return false;
         }
         return true;
     });
     Validator::add('moreThanFive', function ($value) {
         if (strlen($value) < 5) {
             return false;
         }
         return true;
     });
     Validator::add('notTooLarge', function ($value) {
         if ($value == 'TOO_LARGE.jpg') {
             return false;
         }
         return true;
     });
     Validator::add('invalidFileType', function ($value) {
         if ($value == 'INVALID_FILE_TYPE.jpg') {
             return false;
         }
         return true;
     });
     parent::__init();
     /*
      * If told to ues a specific connection, do so.
      * Otherwise, use the default li3b_users connection.
      * Note: This model requires MongoDB.
      * Also note: This must be called AFTER parent::__init()
      *
      * This is useful if the main application also uses MongoDB
      * and wishes everything to use the same database...Be it
      * local or on something like MongoLab or wherever.
      *
      * In fact, when gluing together libraries, one may choose
      * all libraries that use the same database and kinda go
      * with each other. That way it'll end up looking like a single
      * cohesive application from the database's point of view.
      * Of course the it's difficult to avoid conflicts in the MongoDB
      * collection names. In this case, this model is prefixing the
      * library name to the collection in order to ensure there are
      * no conflicts.
      */
     $libConfig = Libraries::get('li3b_users');
     $connection = isset($libConfig['useConnection']) ? $libConfig['useConnection'] : 'li3b_users';
     static::meta('connection', $connection);
 }
Пример #27
0
 /**
  * Provides a simple syntax for making assertions about the properties of a request.
  * By default, the `Request` object is configured with several different types of assertions,
  * which are individually known as _detectors_. Detectors are invoked by calling the `is()` and
  * passing the name of the detector flag, i.e. `$request->is('<name>')`, which returns `true` or
  * `false`, depending on whether or not the the properties (usually headers or data) contained
  * in the request match the detector. The default detectors include the following:
  *
  * - `'mobile'`: Uses a regular expression to match common mobile browser user agents.
  * - `'ajax'`: Checks to see if the `X-Requested-With` header is present, and matches the value
  *    `'XMLHttpRequest'`.
  * - `'flash'`: Checks to see if the user agent is `'Shockwave Flash'`.
  * - `'ssl'`: Verifies that the request is SSL-secured.
  * - `'get'` / `'post'` / `'put'` / `'delete'` / `'head'` / `'options'`: Checks that the HTTP
  *   request method matches the one specified.
  *
  * In addition to the above, this method also accepts media type names (see `Media::type()`) to
  * make assertions against the format of the request body (for POST or PUT requests), i.e.
  * `$request->is('json')`. This will return `true` if the client has made a POST request with
  * JSON data.
  *
  * For information about adding custom detectors or overriding the ones in the core, see the
  * `detect()` method.
  *
  * While these detectors are useful in controllers or other similar contexts, they're also
  * useful when performing _content negotiation_, which is the process of modifying the response
  * format to suit the client (see the `'conditions'` field of the `$options` parameter in
  * `Media::type()`).
  *
  * @see lithium\action\Request::detect()
  * @see lithium\net\http\Media::type()
  * @param string $flag The name of the flag to check, which should be the name of a valid
  *               detector (that is either built-in or defined with `detect()`).
  * @return boolean Returns `true` if the detector check succeeds (see the details for the
  *         built-in detectors above, or `detect()`), otherwise `false`.
  */
 public function is($flag)
 {
     $media = $this->_classes['media'];
     if (!isset($this->_detectors[$flag])) {
         if (!in_array($flag, $media::types())) {
             return false;
         }
         return $this->type() == $flag;
     }
     $detector = $this->_detectors[$flag];
     if (!is_array($detector) && is_callable($detector)) {
         return $detector($this);
     }
     if (!is_array($detector)) {
         return (bool) $this->env($detector);
     }
     list($key, $check) = $detector + array('', '');
     if (is_array($check)) {
         $check = '/' . join('|', $check) . '/i';
     }
     if (Validator::isRegex($check)) {
         return (bool) preg_match($check, $this->env($key));
     }
     return $this->env($key) == $check;
 }
Пример #28
0
<?php

namespace app\models;

use lithium\util\Validator;
use lithium\util\String;
class Documents extends \lithium\data\Model
{
    protected $_meta = array('connection' => 'default_kyc');
    public $validates = array('email' => array(array('uniqueEmail', 'message' => 'This Email is already used'), array('notEmpty', 'message' => 'Please enter your email address'), array('email', 'message' => 'Not a valid email address')));
}
Validator::add('uniqueEmail', function ($value, $rule, $options) {
    $conflicts = Users::count(array('email' => $value));
    if ($conflicts) {
        return false;
    }
    return true;
});
Пример #29
0
 /**
  * Initializes the list of default validation rules.
  *
  * @return void
  */
 public static function __init()
 {
     $alnum = '[A-Fa-f0-9]';
     $class = get_called_class();
     static::$_methodFilters[$class] = array();
     static::$_rules = array('alphaNumeric' => '/^[\\p{Ll}\\p{Lm}\\p{Lo}\\p{Lt}\\p{Lu}\\p{Nd}]+$/mu', 'blank' => '/[^\\s]/', 'creditCard' => array('amex' => '/^3[4|7]\\d{13}$/', 'bankcard' => '/^56(10\\d\\d|022[1-5])\\d{10}$/', 'diners' => '/^(?:3(0[0-5]|[68]\\d)\\d{11})|(?:5[1-5]\\d{14})$/', 'disc' => '/^(?:6011|650\\d)\\d{12}$/', 'electron' => '/^(?:417500|4917\\d{2}|4913\\d{2})\\d{10}$/', 'enroute' => '/^2(?:014|149)\\d{11}$/', 'jcb' => '/^(3\\d{4}|2100|1800)\\d{11}$/', 'maestro' => '/^(?:5020|6\\d{3})\\d{12}$/', 'mc' => '/^5[1-5]\\d{14}$/', 'solo' => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/', 'switch' => '/^(?:49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})' . '\\d{10}(\\d{2,3})?)|(?:564182\\d{10}(\\d{2,3})?)|(6(3(33[0-4]' . '[0-9])|759[0-9]{2})\\d{10}(\\d{2,3})?)$/', 'visa' => '/^4\\d{12}(\\d{3})?$/', 'voyager' => '/^8699[0-9]{11}$/', 'fast' => '/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|3' . '(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$/'), 'date' => array('dmy' => '%^(?:(?:31(\\/|-|\\.|\\x20)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)' . '(\\/|-|\\.|\\x20)(?:0?[1,3-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?' . '\\d{2})$|^(?:29(\\/|-|\\.|\\x20)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?' . '(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])' . '00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/|-|\\.|\\x20)(?:(?:0?[1-9])|' . '(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%', 'mdy' => '%^(?:(?:(?:0?[13578]|1[02])(\\/|-|\\.|\\x20)31)\\1|(?:(?:0?[13-9]|' . '1[0-2])(\\/|-|\\.|\\x20)(?:29|30)\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d' . '{2})$|^(?:0?2(\\/|-|\\.|\\x20)29\\3(?:(?:(?:1[6-9]|[2-9]\\d)?' . '(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])' . '00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\\/|-|\\.|\\x20)(?:0?[1-9]|1' . '\\d|2[0-8])\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%', 'ymd' => '%^(?:(?:(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579]' . '[26])|(?:(?:16|[2468][048]|[3579][26])00)))(\\/|-|\\.|\\x20)' . '(?:0?2\\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\\d)?\\d{2})(\\/|-|\\.|' . '\\x20)(?:(?:(?:0?[13578]|1[02])\\2(?:31))|(?:(?:0?[1,3-9]|1[0-2])' . '\\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\\2(?:0?[1-9]|1\\d|2[0-8]' . '))))$%', 'dMy' => '/^((31(?!\\ (Feb(ruary)?|Apr(il)?|June?|(Sep(?=\\b|t)t?|Nov)' . '(ember)?)))|((30|29)(?!\\ Feb(ruary)?))|(29(?=\\ Feb(ruary)?\\ ' . '(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468]' . '[048]|[3579][26])00)))))|(0?[1-9])|1\\d|2[0-8])\\ (Jan(uary)?|' . 'Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|' . 'Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)\\ ((1[6-9]|[2-9]' . '\\d)\\d{2})$/', 'Mdy' => '/^(?:(((Jan(uary)?|Ma(r(ch)?|y)|Jul(y)?|Aug(ust)?|Oct(ober)?' . '|Dec(ember)?)\\ 31)|((Jan(uary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)' . '|(ne?))|Aug(ust)?|Oct(ober)?|(Sept|Nov|Dec)(ember)?)\\ (0?[1-9]' . '|([12]\\d)|30))|(Feb(ruary)?\\ (0?[1-9]|1\\d|2[0-8]|(29(?=,?\\ ' . '((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468]' . '[048]|[3579][26])00)))))))\\,?\\ ((1[6-9]|[2-9]\\d)\\d{2}))$/', 'My' => '%^(Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|' . 'Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)[ /]((1[6-9]' . '|[2-9]\\d)\\d{2})$%', 'my' => '%^(((0[123456789]|10|11|12)([- /.])(([1][9][0-9][0-9])|([2][0-9]' . '[0-9][0-9]))))$%'), 'ip' => function ($value, $format = null, array $options = array()) {
         $options += array('flags' => array());
         return (bool) filter_var($value, FILTER_VALIDATE_IP, $options);
     }, 'money' => array('right' => '/^(?!0,?\\d)(?:\\d{1,3}(?:([, .])\\d{3})?(?:\\1\\d{3})*|(?:\\d+))' . '((?!\\1)[,.]\\d{2})?(?<!\\x{00a2})\\p{Sc}?$/u', 'left' => '/^(?!\\x{00a2})\\p{Sc}?(?!0,?\\d)(?:\\d{1,3}(?:([, .])\\d{3})?' . '(?:\\1\\d{3})*|(?:\\d+))((?!\\1)[,.]\\d{2})?$/u'), 'notEmpty' => '/[^\\s]+/m', 'phone' => '/^\\+?[0-9\\(\\)\\-]{10,20}$/', 'postalCode' => '/(^|\\A\\b)[A-Z0-9\\s\\-]{5,}($|\\b\\z)/i', 'regex' => '/^(?:([^[:alpha:]\\\\{<\\[\\(])(.+)(?:\\1))|(?:{(.+)})|(?:<(.+)>)|' . '(?:\\[(.+)\\])|(?:\\((.+)\\))[gimsxu]*$/', 'time' => '%^((0?[1-9]|1[012])(:[0-5]\\d){0,2}([AP]M|[ap]m))$|^([01]\\d|2[0-3])' . '(:[0-5]\\d){0,2}$%', 'boolean' => function ($value) {
         $bool = is_bool($value);
         $filter = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
         return $bool || $filter !== null || empty($value);
     }, 'decimal' => function ($value, $format = null, array $options = array()) {
         if (isset($options['precision'])) {
             $precision = strlen($value) - strrpos($value, '.') - 1;
             if ($precision !== (int) $options['precision']) {
                 return false;
             }
         }
         return filter_var($value, FILTER_VALIDATE_FLOAT, FILTER_NULL_ON_FAILURE) !== null;
     }, 'inList' => function ($value, $format, $options) {
         $options += array('list' => array());
         return in_array($value, $options['list']);
     }, 'lengthBetween' => function ($value, $format, $options) {
         $length = strlen($value);
         $options += array('min' => 1, 'max' => 255);
         return $length >= $options['min'] && $length <= $options['max'];
     }, 'luhn' => function ($value) {
         if (empty($value) || !is_string($value)) {
             return false;
         }
         $sum = 0;
         $length = strlen($value);
         for ($position = 1 - $length % 2; $position < $length; $position += 2) {
             $sum += $value[$position];
         }
         for ($position = $length % 2; $position < $length; $position += 2) {
             $number = $value[$position] * 2;
             $sum += $number < 10 ? $number : $number - 9;
         }
         return $sum % 10 == 0;
     }, 'numeric' => function ($value) {
         return is_numeric($value);
     }, 'inRange' => function ($value, $format, $options) {
         $defaults = array('upper' => null, 'lower' => null);
         $options += $defaults;
         if (!is_numeric($value)) {
             return false;
         }
         switch (true) {
             case !is_null($options['upper']) && !is_null($options['lower']):
                 return $value > $options['lower'] && $value < $options['upper'];
             case !is_null($options['upper']):
                 return $value < $options['upper'];
             case !is_null($options['lower']):
                 return $value > $options['lower'];
         }
         return is_finite($value);
     }, 'uuid' => "/^{$alnum}{8}-{$alnum}{4}-{$alnum}{4}-{$alnum}{4}-{$alnum}{12}\$/", 'email' => function ($value) {
         return filter_var($value, FILTER_VALIDATE_EMAIL);
     }, 'url' => function ($value, $format = null, array $options = array()) {
         $options += array('flags' => array());
         return (bool) filter_var($value, FILTER_VALIDATE_URL, $options);
     });
     $isEmpty = function ($self, $params, $chain) {
         extract($params);
         return empty($value) && $value != '0' ? false : $chain->next($self, $params, $chain);
     };
     static::$_methodFilters[$class]['alphaNumeric'] = array($isEmpty);
     static::$_methodFilters[$class]['notEmpty'] = array($isEmpty);
     static::$_methodFilters[$class]['creditCard'] = array(function ($self, $params, $chain) {
         extract($params);
         $options += array('deep' => false);
         if (strlen($value = str_replace(array('-', ' '), '', $value)) < 13) {
             return false;
         }
         if (!$chain->next($self, compact('value') + $params, $chain)) {
             return false;
         }
         return $options['deep'] ? Validator::isLuhn($value) : true;
     });
     static::$_methodFilters[$class]['email'] = array(function ($self, $params, $chain) {
         extract($params);
         $defaults = array('deep' => false);
         $options += $defaults;
         if (!$chain->next($self, $params, $chain)) {
             return false;
         }
         if (!$options['deep']) {
             return true;
         }
         list($prefix, $host) = explode('@', $params['value']);
         if (getmxrr($host, $mxhosts)) {
             return is_array($mxhosts);
         }
         return false;
     });
 }
Пример #30
0
 * locale dependent rules into the by specifying them manually or retrieving
 * them with the `Catalog` class.
 *
 * Enables support for multibyte strings through the `Multibyte` class by
 * overwriting rules (currently just `lengthBetween`).
 *
 * @see lithium\g11n\Catalog
 * @see lithium\g11n\Multibyte
 * @see lithium\util\Validator
 */
foreach (array('phone', 'postalCode', 'ssn') as $name) {
    Validator::add($name, Catalog::read(true, "validation.{$name}", 'en_US'));
}
Validator::add('lengthBetween', function ($value, $format, $options) {
    $length = Multibyte::strlen($value);
    $options += array('min' => 1, 'max' => 255);
    return $length >= $options['min'] && $length <= $options['max'];
});
/**
 * In-View Translation
 *
 * Integration with `View`. Embeds message translation aliases into the `View`
 * class (or other content handler, if specified) when content is rendered. This
 * enables translation functions, i.e. `<?=$t("Translated content"); ?>`.
 *
 * @see lithium\g11n\Message::aliases()
 * @see lithium\net\http\Media
 */
Media::applyFilter('_handle', function ($self, $params, $chain) {
    $params['handler'] += array('outputFilters' => array());
    $params['handler']['outputFilters'] += Message::aliases();