diff --git a/lib/Cake/Cache/Engine/FileEngine.php b/lib/Cake/Cache/Engine/FileEngine.php index c8eafbd0b..f81889dcb 100644 --- a/lib/Cake/Cache/Engine/FileEngine.php +++ b/lib/Cake/Cache/Engine/FileEngine.php @@ -240,7 +240,9 @@ class FileEngine extends CacheEngine { } $path = $this->_File->getRealPath(); $this->_File = null; - unlink($path); + if (file_exists($path)) { + unlink($path); + } } $dir->close(); return true; diff --git a/lib/Cake/Console/Command/BakeShell.php b/lib/Cake/Console/Command/BakeShell.php index 4b8fd6fe8..5d039de83 100644 --- a/lib/Cake/Console/Command/BakeShell.php +++ b/lib/Cake/Console/Command/BakeShell.php @@ -65,6 +65,8 @@ class BakeShell extends Shell { * @return mixed */ public function main() { + Configure::write('Cache.disable', 1); + if (!is_dir($this->DbConfig->path)) { $path = $this->Project->execute(); if (!empty($path)) { diff --git a/lib/Cake/Console/Command/Task/BakeTask.php b/lib/Cake/Console/Command/Task/BakeTask.php index 14fa8ae7f..4f75272ec 100644 --- a/lib/Cake/Console/Command/Task/BakeTask.php +++ b/lib/Cake/Console/Command/Task/BakeTask.php @@ -43,6 +43,17 @@ class BakeTask extends Shell { */ public $interactive = false; +/** + * Disable caching for baking. + * This forces the most current database schema to be used. + * + * @return void + */ + function startup() { + Configure::write('Cache.disable', 1); + parent::startup(); + } + /** * Gets the path for output. Checks the plugin property * and returns the correct path. diff --git a/lib/Cake/Console/Command/Task/FixtureTask.php b/lib/Cake/Console/Command/Task/FixtureTask.php index 47f8b51c1..f271801f8 100644 --- a/lib/Cake/Console/Command/Task/FixtureTask.php +++ b/lib/Cake/Console/Command/Task/FixtureTask.php @@ -316,35 +316,30 @@ class FixtureTask extends BakeTask { $insert = substr($insert, 0, (int)$fieldInfo['length'] - 2); } } - $insert = "'$insert'"; break; case 'timestamp': - $ts = time(); - $insert = "'$ts'"; + $insert = time(); break; case 'datetime': - $ts = date('Y-m-d H:i:s'); - $insert = "'$ts'"; + $insert = date('Y-m-d H:i:s'); break; case 'date': - $ts = date('Y-m-d'); - $insert = "'$ts'"; + $insert = date('Y-m-d'); break; case 'time': - $ts = date('H:i:s'); - $insert = "'$ts'"; + $insert = date('H:i:s'); break; case 'boolean': $insert = 1; break; case 'text': - $insert = "'Lorem ipsum dolor sit amet, aliquet feugiat."; + $insert = "Lorem ipsum dolor sit amet, aliquet feugiat."; $insert .= " Convallis morbi fringilla gravida,"; $insert .= " phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin"; $insert .= " venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla"; $insert .= " vestibulum massa neque ut et, id hendrerit sit,"; $insert .= " feugiat in taciti enim proin nibh, tempor dignissim, rhoncus"; - $insert .= " duis vestibulum nunc mattis convallis.'"; + $insert .= " duis vestibulum nunc mattis convallis."; break; } $record[$field] = $insert; @@ -365,7 +360,8 @@ class FixtureTask extends BakeTask { foreach ($records as $record) { $values = array(); foreach ($record as $field => $value) { - $values[] = "\t\t\t'$field' => $value"; + $val = var_export($value, true); + $values[] = "\t\t\t'$field' => $val"; } $out .= "\t\tarray(\n"; $out .= implode(",\n", $values); @@ -408,7 +404,7 @@ class FixtureTask extends BakeTask { foreach ($records as $record) { $row = array(); foreach ($record[$modelObject->alias] as $field => $value) { - $row[$field] = $db->value($value, $schema[$field]['type']); + $row[$field] = $value; } $out[] = $row; } diff --git a/lib/Cake/Core/App.php b/lib/Cake/Core/App.php index 1e92aa76c..d36ff7966 100644 --- a/lib/Cake/Core/App.php +++ b/lib/Cake/Core/App.php @@ -427,6 +427,9 @@ class App { * * `App::objects('MyPlugin.Model');` returns `array('MyPluginPost', 'MyPluginComment');` * + * When scanning directories, files and directories beginning with `.` will be excluded as these + * are commonly used by version control systems. + * * @param string $type Type of object, i.e. 'Model', 'Controller', 'View/Helper', 'file', 'class' or 'plugin' * @param mixed $path Optional Scan only the path given. If null, paths for the chosen type will be used. * @param boolean $cache Set to false to rescan objects of the chosen type. Defaults to true. @@ -476,12 +479,13 @@ class App { if ($dir != APP && is_dir($dir)) { $files = new RegexIterator(new DirectoryIterator($dir), $extension); foreach ($files as $file) { - if (!$file->isDot()) { + $fileName = basename($file); + if (!$file->isDot() && $fileName[0] !== '.') { $isDir = $file->isDir() ; if ($isDir && $includeDirectories) { - $objects[] = basename($file); + $objects[] = $fileName; } elseif (!$includeDirectories && !$isDir) { - $objects[] = substr(basename($file), 0, -4); + $objects[] = substr($fileName, 0, -4); } } } diff --git a/lib/Cake/I18n/L10n.php b/lib/Cake/I18n/L10n.php index ba803ab2d..9c973b0a7 100644 --- a/lib/Cake/I18n/L10n.php +++ b/lib/Cake/I18n/L10n.php @@ -93,6 +93,7 @@ class L10n { /* Arabic */ 'ara' => 'ar', /* Armenian - Armenia */ 'hye' => 'hy', /* Basque */ 'baq' => 'eu', + /* Tibetan */ 'bod' => 'bo', /* Bosnian */ 'bos' => 'bs', /* Bulgarian */ 'bul' => 'bg', /* Byelorussian */ 'bel' => 'be', @@ -194,6 +195,9 @@ class L10n { 'ar-ye' => array('language' => 'Arabic (Yemen)', 'locale' => 'ar_ye', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'be' => array('language' => 'Byelorussian', 'locale' => 'bel', 'localeFallback' => 'bel', 'charset' => 'utf-8', 'direction' => 'ltr'), 'bg' => array('language' => 'Bulgarian', 'locale' => 'bul', 'localeFallback' => 'bul', 'charset' => 'utf-8', 'direction' => 'ltr'), + 'bo' => array('language' => 'Tibetan', 'locale' => 'bod', 'localeFallback' => 'bod', 'charset' => 'utf-8', 'direction' => 'ltr'), + 'bo-cn' => array('language' => 'Tibetan (China)', 'locale' => 'bo_cn', 'localeFallback' => 'bod', 'charset' => 'utf-8', 'direction' => 'ltr'), + 'bo-in' => array('language' => 'Tibetan (India)', 'locale' => 'bo_in', 'localeFallback' => 'bod', 'charset' => 'utf-8', 'direction' => 'ltr'), 'bs' => array('language' => 'Bosnian', 'locale' => 'bos', 'localeFallback' => 'bos', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ca' => array('language' => 'Catalan', 'locale' => 'cat', 'localeFallback' => 'cat', 'charset' => 'utf-8', 'direction' => 'ltr'), 'cs' => array('language' => 'Czech', 'locale' => 'cze', 'localeFallback' => 'cze', 'charset' => 'utf-8', 'direction' => 'ltr'), diff --git a/lib/Cake/Network/CakeRequest.php b/lib/Cake/Network/CakeRequest.php index afad26b57..213d84bef 100644 --- a/lib/Cake/Network/CakeRequest.php +++ b/lib/Cake/Network/CakeRequest.php @@ -605,23 +605,35 @@ class CakeRequest implements ArrayAccess { * * `$this->request->accepts('json');` * + * This method will order the returned content types by the preference values indicated + * by the client. + * * @param string $type The content type to check for. Leave null to get all types a client accepts. * @return mixed Either an array of all the types the client accepts or a boolean if they accept the * provided type. */ public function accepts($type = null) { - $acceptTypes = explode(',', $this->header('accept')); - $acceptTypes = array_map('trim', $acceptTypes); - foreach ($acceptTypes as $i => $accepted) { - if (strpos($accepted, ';') !== false) { - list($accepted) = explode(';', $accepted); - $acceptTypes[$i] = $accepted; + $accept = array(); + $header = explode(',', $this->header('accept')); + foreach (array_filter(array_reverse($header)) as $value) { + $prefPos = strpos($value, ';'); + if ($prefPos !== false) { + $prefValue = (float) substr($value, strpos($value, '=') + 1); + $value = trim(substr($value, 0, $prefPos)); + } else { + $prefValue = 1.0; + $value = trim($value); + } + if ($prefValue) { + $accept[$value] = $prefValue; } } + arsort($accept); + $accept = array_keys($accept); if ($type === null) { - return $acceptTypes; + return $accept; } - return in_array($type, $acceptTypes); + return in_array($type, $accept); } /** diff --git a/lib/Cake/Test/Case/AllComponentsTest.php b/lib/Cake/Test/Case/AllComponentsTest.php index f93628417..3b6f5ce03 100644 --- a/lib/Cake/Test/Case/AllComponentsTest.php +++ b/lib/Cake/Test/Case/AllComponentsTest.php @@ -36,8 +36,7 @@ class AllComponentsTest extends PHPUnit_Framework_TestSuite { $suite->addTestFile(CORE_TEST_CASES . DS . 'Controller' . DS . 'ComponentTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Controller' . DS . 'ComponentCollectionTest.php'); - $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Controller' . DS . 'Component'); - $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Controller' . DS . 'Component' . DS . 'Auth'); + $suite->addTestDirectoryRecursive(CORE_TEST_CASES . DS . 'Controller' . DS . 'Component'); return $suite; } } diff --git a/lib/Cake/Test/Case/Console/Command/Task/FixtureTaskTest.php b/lib/Cake/Test/Case/Console/Command/Task/FixtureTaskTest.php index 2eee7d612..c60278e13 100644 --- a/lib/Cake/Test/Case/Console/Command/Task/FixtureTaskTest.php +++ b/lib/Cake/Test/Case/Console/Command/Task/FixtureTaskTest.php @@ -164,6 +164,31 @@ class FixtureTaskTest extends CakeTestCase { $this->assertPattern("/'connection' => 'test'/", $result); } +/** + * Ensure that fixture data doesn't get overly escaped. + * + * @return void + */ + function testImportRecordsNoEscaping() { + $Article = ClassRegistry::init('Article'); + $Article->updateAll(array('body' => "'Body \"value\"'")); + + $this->Task->interactive = true; + $this->Task->expects($this->at(0)) + ->method('in') + ->will($this->returnValue('WHERE 1=1 LIMIT 10')); + + $this->Task->connection = 'test'; + $this->Task->path = '/my/path/'; + $result = $this->Task->bake('Article', false, array( + 'fromTable' => true, + 'schema' => 'Article', + 'records' => false + )); + + $this->assertRegExp("/'body' => 'Body \"value\"'/", $result, 'Data has bad escaping'); + } + /** * test that execute passes runs bake depending with named model. * diff --git a/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php b/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php index efe979545..2d2817e0b 100644 --- a/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php @@ -157,7 +157,7 @@ class RequestHandlerComponentTest extends CakeTestCase { */ public function testInitializeCallback() { $this->assertNull($this->RequestHandler->ext); - $this->Controller->request->params['url']['ext'] = 'rss'; + $this->Controller->request->params['ext'] = 'rss'; $this->RequestHandler->initialize($this->Controller); $this->assertEqual($this->RequestHandler->ext, 'rss'); } @@ -222,7 +222,7 @@ class RequestHandlerComponentTest extends CakeTestCase { */ public function testAutoResponseType() { $this->Controller->ext = '.thtml'; - $this->Controller->request->params['url']['ext'] = 'rss'; + $this->Controller->request->params['ext'] = 'rss'; $this->RequestHandler->initialize($this->Controller); $this->RequestHandler->startup($this->Controller); $this->assertEqual($this->Controller->ext, '.ctp'); @@ -240,7 +240,7 @@ class RequestHandlerComponentTest extends CakeTestCase { $this->assertEquals($this->Controller->layout, $this->RequestHandler->ajaxLayout); $this->_init(); - $this->Controller->request->params['url']['ext'] = 'js'; + $this->Controller->request->params['ext'] = 'js'; $this->RequestHandler->initialize($this->Controller); $this->RequestHandler->startup($this->Controller); $this->assertNotEqual($this->Controller->layout, 'ajax'); diff --git a/lib/Cake/Test/Case/Core/AppTest.php b/lib/Cake/Test/Case/Core/AppTest.php index 9f51fd1a1..945a76062 100644 --- a/lib/Cake/Test/Case/Core/AppTest.php +++ b/lib/Cake/Test/Case/Core/AppTest.php @@ -305,6 +305,21 @@ class AppTest extends CakeTestCase { App::build(); } +/** + * Make sure that .svn and friends are excluded from App::objects('plugin') + */ + public function testListObjectsIgnoreDotDirectories() { + $path = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS; + App::build(array( + 'plugins' => array($path) + ), true); + mkdir($path . '.svn'); + $result = App::objects('plugin', null, false); + rmdir($path . '.svn'); + + $this->assertNotContains('.svn', $result); + } + /** * Tests listing objects within a plugin * diff --git a/lib/Cake/Test/Case/Network/CakeRequestTest.php b/lib/Cake/Test/Case/Network/CakeRequestTest.php index 16211dee0..f89ef7625 100644 --- a/lib/Cake/Test/Case/Network/CakeRequestTest.php +++ b/lib/Cake/Test/Case/Network/CakeRequestTest.php @@ -785,7 +785,7 @@ class CakeRequestTestCase extends CakeTestCase { $result = $request->accepts(); $expected = array( - 'text/xml', 'application/xml', 'application/xhtml+xml', 'text/html', 'text/plain', 'image/png' + 'text/xml', 'application/xhtml+xml', 'text/html', 'image/png', 'text/plain', 'application/xml' ); $this->assertEquals($expected, $result, 'Content types differ.'); @@ -813,6 +813,19 @@ class CakeRequestTestCase extends CakeTestCase { $this->assertTrue($request->accepts('text/html')); } +/** + * Content types from accepts() should respect the client's q preference values. + * + * @return void + */ + public function testAcceptWithQvalueSorting() { + $_SERVER['HTTP_ACCEPT'] = 'text/html;q=0.8,application/json;q=0.7,application/xml;q=1.0'; + $request = new CakeRequest('/', false); + $result = $request->accepts(); + $expected = array('application/xml', 'text/html', 'application/json'); + $this->assertEquals($expected, $result); + } + /** * testBaseUrlAndWebrootWithModRewrite method * diff --git a/lib/Cake/Test/Case/Utility/InflectorTest.php b/lib/Cake/Test/Case/Utility/InflectorTest.php index 486db3edc..db14a0c27 100644 --- a/lib/Cake/Test/Case/Utility/InflectorTest.php +++ b/lib/Cake/Test/Case/Utility/InflectorTest.php @@ -106,6 +106,8 @@ class InflectorTest extends CakeTestCase { $this->assertEqual(Inflector::singularize('bases'), 'basis'); $this->assertEqual(Inflector::singularize('analyses'), 'analysis'); $this->assertEqual(Inflector::singularize('curves'), 'curve'); + $this->assertEqual(Inflector::singularize('cafes'), 'cafe'); + $this->assertEqual(Inflector::singularize('roofs'), 'roof'); $this->assertEqual(Inflector::singularize(''), ''); } @@ -153,6 +155,8 @@ class InflectorTest extends CakeTestCase { $this->assertEqual(Inflector::pluralize('tax'), 'taxes'); $this->assertEqual(Inflector::pluralize('wave'), 'waves'); $this->assertEqual(Inflector::pluralize('bureau'), 'bureaus'); + $this->assertEqual(Inflector::pluralize('cafe'), 'cafes'); + $this->assertEqual(Inflector::pluralize('roof'), 'roofs'); $this->assertEqual(Inflector::pluralize(''), ''); } diff --git a/lib/Cake/Test/Case/Utility/ValidationTest.php b/lib/Cake/Test/Case/Utility/ValidationTest.php index cf466155a..bd2d5dbbd 100644 --- a/lib/Cake/Test/Case/Utility/ValidationTest.php +++ b/lib/Cake/Test/Case/Utility/ValidationTest.php @@ -1366,6 +1366,7 @@ class ValidationTest extends CakeTestCase { $this->assertTrue(Validation::date('Dec 27 2006', array('Mdy'))); $this->assertFalse(Validation::date('27 Dec 2006', array('Mdy'))); $this->assertFalse(Validation::date('2006 December 27', array('Mdy'))); + $this->assertTrue(Validation::date('Sep 12, 2011', array('Mdy'))); } /** diff --git a/lib/Cake/TestSuite/CakeTestSuite.php b/lib/Cake/TestSuite/CakeTestSuite.php index 1b121b65c..ea8656155 100644 --- a/lib/Cake/TestSuite/CakeTestSuite.php +++ b/lib/Cake/TestSuite/CakeTestSuite.php @@ -18,6 +18,8 @@ */ PHP_CodeCoverage_Filter::getInstance()->addFileToBlacklist(__FILE__, 'DEFAULT'); +App::uses('Folder', 'Utility'); + class CakeTestSuite extends PHPUnit_Framework_TestSuite { /** @@ -27,13 +29,10 @@ class CakeTestSuite extends PHPUnit_Framework_TestSuite { * @return void */ public function addTestDirectory($directory = '.') { - $files = new DirectoryIterator($directory); + $folder = new Folder($directory); + list($dirs, $files) = $folder->read(true, false, true); foreach ($files as $file) { - if (!$file->isFile()) { - continue; - } - $file = $file->getRealPath(); $this->addTestFile($file); } } @@ -45,15 +44,12 @@ class CakeTestSuite extends PHPUnit_Framework_TestSuite { * @return void */ public function addTestDirectoryRecursive($directory = '.') { - $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)); + $folder = new Folder($directory); + $files = $folder->tree(null, false, 'files'); foreach ($files as $file) { - if (!$file->isFile()) { - continue; - } - $file = $file->getRealPath(); $this->addTestFile($file); } } -} \ No newline at end of file +} diff --git a/lib/Cake/Utility/Folder.php b/lib/Cake/Utility/Folder.php index 44af50df2..671ff1e2b 100644 --- a/lib/Cake/Utility/Folder.php +++ b/lib/Cake/Utility/Folder.php @@ -145,29 +145,33 @@ class Folder { } $skipHidden = isset($exceptions['.']) || $exceptions === true; - if (false === ($dir = @opendir($this->path))) { + try { + $iterator = new DirectoryIterator($this->path); + } catch (UnexpectedValueException $e) { return array($dirs, $files); } - while (false !== ($item = readdir($dir))) { - if ($item === '.' || $item === '..' || ($skipHidden && $item[0] === '.') || isset($exceptions[$item])) { + foreach ($iterator as $item) { + if ($item->isDot()) { continue; } - - $path = Folder::addPathElement($this->path, $item); - if (is_dir($path)) { - $dirs[] = $fullPath ? $path : $item; + $name = $item->getFileName(); + if ($skipHidden && $name[0] === '.' || isset($exceptions[$name])) { + continue; + } + if ($fullPath) { + $name = $item->getPathName(); + } + if ($item->isDir()) { + $dirs[] = $name; } else { - $files[] = $fullPath ? $path : $item; + $files[] = $name; } } - if ($sort || $this->sort) { sort($dirs); sort($files); } - - closedir($dir); return array($dirs, $files); } @@ -380,37 +384,48 @@ class Folder { * @param string $type either file or dir. null returns both files and directories * @return mixed array of nested directories and files in each directory */ - public function tree($path, $exceptions = true, $type = null) { - $original = $this->path; - $path = rtrim($path, DS); - if (!$this->cd($path)) { + public function tree($path = null, $exceptions = true, $type = null) { + if ($path == null) { + $path = $this->path; + } + $files = array(); + $directories = array($path); + $skipHidden = false; + + if ($exceptions === false) { + $skipHidden = true; + } + if (is_array($exceptions)) { + $exceptions = array_flip($exceptions); + } + + try { + $directory = new RecursiveDirectoryIterator($path); + $iterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); + } catch (UnexpectedValueException $e) { if ($type === null) { return array(array(), array()); } return array(); } - $this->_files = array(); - $this->_directories = array($this->realpath($path)); - $directories = array(); - - if ($exceptions === false) { - $exceptions = true; + foreach ($iterator as $item) { + $name = $item->getFileName(); + if ($skipHidden && $name[0] === '.' || isset($exceptions[$name])) { + continue; + } + if ($item->isFile()) { + $files[] = $item->getPathName(); + } else if ($item->isDir()) { + $directories[] = $item->getPathName(); + } } - while (!empty($this->_directories)) { - $dir = array_pop($this->_directories); - $this->_tree($dir, $exceptions); - $directories[] = $dir; - } - if ($type === null) { - return array($directories, $this->_files); + return array($directories, $files); } if ($type === 'dir') { return $directories; } - $this->cd($original); - - return $this->_files; + return $files; } /** diff --git a/lib/Cake/Utility/Inflector.php b/lib/Cake/Utility/Inflector.php index f18874f6c..736ac9dd1 100644 --- a/lib/Cake/Utility/Inflector.php +++ b/lib/Cake/Utility/Inflector.php @@ -67,6 +67,7 @@ class Inflector { 'atlas' => 'atlases', 'beef' => 'beefs', 'brother' => 'brothers', + 'cafe' => 'cafes', 'child' => 'children', 'corpus' => 'corpuses', 'cow' => 'cows', diff --git a/lib/Cake/Utility/Validation.php b/lib/Cake/Utility/Validation.php index 2187c054e..13fe05ca9 100644 --- a/lib/Cake/Utility/Validation.php +++ b/lib/Cake/Utility/Validation.php @@ -300,7 +300,7 @@ class Validation { $regex['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})$%'; $regex['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]))))$%'; $regex['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})$/'; - $regex['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}))$/'; + $regex['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)?|(Sep)(tember)?|(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}))$/'; $regex['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})$%'; $regex['my'] = '%^(((0[123456789]|10|11|12)([- /.])(([1][9][0-9][0-9])|([2][0-9][0-9][0-9]))))$%';