public function validate(Jam_Validated $model, $attribute, $value) { if ($this->regex !== NULL and !preg_match($this->regex, $value)) { $model->errors()->add($attribute, 'format_regex', array(':regex' => $this->regex)); } if ($this->filter !== NULL and !(filter_var($value, $this->filter, $this->flag) !== FALSE)) { $model->errors()->add($attribute, 'format_filter', array(':filter' => $this->filter)); } if ($this->ip === TRUE and !Valid::ip($value)) { $model->errors()->add($attribute, 'format_ip'); } if ($this->url === TRUE and !Valid::url($value)) { $model->errors()->add($attribute, 'format_url'); } if ($this->email === TRUE and !Valid::email($value)) { $model->errors()->add($attribute, 'format_email'); } if ($this->credit_card === TRUE and !Valid::credit_card($value)) { $model->errors()->add($attribute, 'format_credit_card'); } }
/** * Validates a credit card number, with a Luhn check if possible. * * @param integer $number credit card number * @param string|array $type card type, or an array of card types * @return boolean * @uses Valid::luhn */ public static function credit_card($number, $type = NULL) { // Remove all non-digit characters from the number if (($number = preg_replace('/\\D+/', '', $number)) === '') { return FALSE; } if ($type == NULL) { // Use the default type $type = 'default'; } elseif (is_array($type)) { foreach ($type as $t) { // Test each type for validity if (Valid::credit_card($number, $t)) { return TRUE; } } return FALSE; } $cards = Kohana::config('credit_cards'); // Check card type $type = strtolower($type); if (!isset($cards[$type])) { return FALSE; } // Check card number length $length = strlen($number); // Validate the card length by the card type if (!in_array($length, preg_split('/\\D+/', $cards[$type]['length']))) { return FALSE; } // Check card number prefix if (!preg_match('/^' . $cards[$type]['prefix'] . '/', $number)) { return FALSE; } // No Luhn check required if ($cards[$type]['luhn'] == FALSE) { return TRUE; } return Valid::luhn($number); }
/** * Tests Valid::credit_card() * * @test * @covers Valid::credit_card * @dataProvider provider_credit_card() * @param string $number Credit card number * @param string $type Credit card type * @param boolean $expected */ public function test_credit_card($number, $type, $expected) { $this->assertSame($expected, Valid::credit_card($number, $type)); }
/** * Validates a credit card number using the Luhn (mod10) formula. * @see http://en.wikipedia.org/wiki/Luhn_algorithm * * @param integer credit card number * @param string|array card type, or an array of card types * @return boolean */ public static function credit_card($number, $type = NULL) { // Remove all non-digit characters from the number if (($number = preg_replace('/\\D+/', '', $number)) === '') { return FALSE; } if ($type == NULL) { // Use the default type $type = 'default'; } elseif (is_array($type)) { foreach ($type as $t) { // Test each type for validity if (Valid::credit_card($number, $t)) { return TRUE; } } return FALSE; } $cards = Valid::cards_config(); // Check card type $type = strtolower($type); if (!isset($cards[$type])) { return FALSE; } // Check card number length $length = strlen($number); // Validate the card length by the card type if (!in_array($length, preg_split('/\\D+/', $cards[$type]['length']))) { return FALSE; } // Check card number prefix if (!preg_match('/^' . $cards[$type]['prefix'] . '/', $number)) { return FALSE; } // No Luhn check required if ($cards[$type]['luhn'] == FALSE) { return TRUE; } // Checksum of the card number $checksum = 0; for ($i = $length - 1; $i >= 0; $i -= 2) { // Add up every 2nd digit, starting from the right $checksum += substr($number, $i, 1); } for ($i = $length - 2; $i >= 0; $i -= 2) { // Add up every 2nd digit doubled, starting from the right $double = substr($number, $i, 1) * 2; // Subtract 9 from the double where value is greater than 10 $checksum += $double >= 10 ? $double - 9 : $double; } // If the checksum is a multiple of 10, the number is valid return $checksum % 10 === 0; }
/** * Validates a credit card number, with a Luhn check if possible. * * @param integer $number credit card number * @param string|array $type card type, or an array of card types * @return boolean * @uses Valid::luhn */ public static function credit_card($number, $type = NULL) { // Remove all non-digit characters from the number if (($number = preg_replace('/\\D+/', '', $number)) === '') { return FALSE; } if ($type == NULL) { // Use the default type $type = 'default'; } elseif (is_array($type)) { foreach ($type as $t) { // Test each type for validity if (Valid::credit_card($number, $t)) { return TRUE; } } return FALSE; } $cards = array('default' => array('length' => '13,14,15,16,17,18,19', 'prefix' => '', 'luhn' => TRUE), 'american express' => array('length' => '15', 'prefix' => '3[47]', 'luhn' => TRUE), 'diners club' => array('length' => '14,16', 'prefix' => '36|55|30[0-5]', 'luhn' => TRUE), 'discover' => array('length' => '16', 'prefix' => '6(?:5|011)', 'luhn' => TRUE), 'jcb' => array('length' => '15,16', 'prefix' => '3|1800|2131', 'luhn' => TRUE), 'maestro' => array('length' => '16,18', 'prefix' => '50(?:20|38)|6(?:304|759)', 'luhn' => TRUE), 'mastercard' => array('length' => '16', 'prefix' => '5[1-5]', 'luhn' => TRUE), 'visa' => array('length' => '13,16', 'prefix' => '4', 'luhn' => TRUE)); // Check card type $type = strtolower($type); if (!isset($cards[$type])) { return FALSE; } // Check card number length $length = strlen($number); // Validate the card length by the card type if (!in_array($length, preg_split('/\\D+/', $cards[$type]['length']))) { return FALSE; } // Check card number prefix if (!preg_match('/^' . $cards[$type]['prefix'] . '/', $number)) { return FALSE; } // No Luhn check required if ($cards[$type]['luhn'] == FALSE) { return TRUE; } return Valid::luhn($number); }