Merge branch 'master' into 2.4

Conflicts:
	lib/Cake/Console/Shell.php
This commit is contained in:
mark_story 2013-03-26 20:31:54 -04:00
commit 041c2d289f
17 changed files with 197 additions and 72 deletions

73
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,73 @@
# How to contribute
CakePHP loves to welcome your contributions. There are several ways to help out:
* Create a ticket in Lighthouse, if you have found a bug
* Write testcases for open bug tickets
* Write patches for open bug/feature tickets, preferably with testcases included
* Contribute to the [documentation](https://github.com/cakephp/docs)
There are a few guidelines that we need contributors to follow so that we have a
chance of keeping on top of things.
## Getting Started
* Make sure you have a [GitHub account](https://github.com/signup/free)
* Submit a ticket for your issue, assuming one does not already exist.
* Clearly describe the issue including steps to reproduce when it is a bug.
* Make sure you fill in the earliest version that you know has the issue.
* Fork the repository on GitHub.
## Making Changes
* Create a topic branch from where you want to base your work.
* This is usually the master branch
* Only target release branches if you are certain your fix must be on that
branch
* To quickly create a topic branch based on master; `git branch
master/my_contribution master` then checkout the new branch with `git
checkout master/my_contribution`. Better avoid working directly on the
`master` branch, to avoid conflicts if you pull in updates from origin.
* Make commits of logical units.
* Check for unnecessary whitespace with `git diff --check` before committing.
* Use descriptive commit messages and reference the #ticket number
* Core testcases should continue to pass. You can run tests locally or enable
[travis-ci](https://travis-ci.org/) for your fork, so all tests and codesniffs
will be executed.
* Your work should apply the CakePHP coding standards.
## Which branch to base the work
* Bugfix branches will be based on master.
* New features that are backwards compatible will be based on next minor release
branch.
* New features or other non-BC changes will go in the next major release branch.
## Submitting Changes
* Push your changes to a topic branch in your fork of the repository.
* Submit a pull request to the repository in the cakephp organization, with the
correct target branch.
## Testcases and codesniffer
CakePHP tests requires [PHPUnit](http://www.phpunit.de/manual/current/en/installation.html)
3.5 or higher. To run the testcases locally use the following command:
./lib/Cake/Console/cake test core AllTests --stderr
To run the sniffs for CakePHP coding standards
phpcs -p --extensions=php --standard=CakePHP ./lib/Cake
Check the [cakephp-codesniffer](https://github.com/cakephp/cakephp-codesniffer)
repository to setup the CakePHP standard. The README contains installation info
for the sniff and phpcs.
# Additional Resources
* [CakePHP coding standards](http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html)
* [Bug tracker](https://cakephp.lighthouseapp.com/projects/42648-cakephp)
* [General GitHub documentation](http://help.github.com/)
* [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
* #cakephp IRC channel on freenode.org

View file

@ -22,6 +22,7 @@ App::uses('ConsoleOutput', 'Console');
App::uses('ConsoleInput', 'Console');
App::uses('ConsoleInputSubcommand', 'Console');
App::uses('ConsoleOptionParser', 'Console');
App::uses('ClassRegistry', 'Utility');
App::uses('File', 'Utility');
App::uses('ClassRegistry', 'Utility');

View file

@ -133,7 +133,6 @@
* <?php echo $admin ?>delete method
*
* @throws NotFoundException
* @throws MethodNotAllowedException
* @param string $id
* @return void
*/

View file

@ -425,6 +425,10 @@ class App {
* @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::objects
*/
public static function objects($type, $path = null, $cache = true) {
if (empty(self::$_objects) && $cache === true) {
self::$_objects = (array)Cache::read('object_map', '_cake_core_');
}
$extension = '/\.php$/';
$includeDirectories = false;
$name = $type;
@ -451,10 +455,6 @@ class App {
$name = $type . str_replace(DS, '', $path);
}
if (empty(self::$_objects) && $cache === true) {
self::$_objects = Cache::read('object_map', '_cake_core_');
}
$cacheLocation = empty($plugin) ? 'app' : $plugin;
if ($cache !== true || !isset(self::$_objects[$cacheLocation][$name])) {
@ -768,7 +768,6 @@ class App {
*/
public static function init() {
self::$_map += (array)Cache::read('file_map', '_cake_core_');
self::$_objects += (array)Cache::read('object_map', '_cake_core_');
register_shutdown_function(array('App', 'shutdown'));
}
@ -896,7 +895,6 @@ class App {
if (self::$_objectCacheChange) {
Cache::write('object_map', self::$_objects, '_cake_core_');
}
self::_checkFatalError();
}

View file

@ -221,14 +221,20 @@ class Sqlserver extends DboSource {
$fields[$field] = array(
'type' => $this->column($column),
'null' => ($column->Null === 'YES' ? true : false),
'default' => preg_replace("/^[(]{1,2}'?([^')]*)?'?[)]{1,2}$/", "$1", $column->Default),
'default' => $column->Default,
'length' => $this->length($column),
'key' => ($column->Key == '1') ? 'primary' : false
);
if ($fields[$field]['default'] === 'null') {
$fields[$field]['default'] = null;
} else {
}
if ($fields[$field]['default'] !== null) {
$fields[$field]['default'] = preg_replace(
"/^[(]{1,2}'?([^')]*)?'?[)]{1,2}$/",
"$1",
$fields[$field]['default']
);
$this->value($fields[$field]['default'], $fields[$field]['type']);
}

View file

@ -1434,7 +1434,7 @@ class CakeEmail {
/**
* Render the body of the email.
*
* @param string $content Content to render
* @param array $content Content to render
* @return array Email body ready to be sent
*/
protected function _render($content) {

View file

@ -448,7 +448,16 @@ class SqlserverTest extends CakeTestCase {
'Length' => 72,
'Null' => 'NO',
'Size' => ''
)
),
(object)array(
'Default' => null,
'Field' => 'parent_id',
'Key' => '0',
'Type' => 'bigint',
'Length' => 8,
'Null' => 'YES',
'Size' => '0',
),
));
$this->db->executeResultsStack = array($SqlserverTableDescription);
$dummyModel = $this->model;
@ -478,9 +487,16 @@ class SqlserverTest extends CakeTestCase {
'default' => '',
'length' => 36,
'key' => 'primary'
)
),
'parent_id' => array(
'type' => 'biginteger',
'null' => true,
'default' => null,
'length' => 8,
),
);
$this->assertEquals($expected, $result);
$this->assertSame($expected['parent_id'], $result['parent_id']);
}
/**

View file

@ -437,7 +437,7 @@ class CakeTestFixtureTest extends CakeTestCase {
$this->insertMulti['fields'] = $fields;
$this->insertMulti['values'] = $values;
$this->insertMulti['fields_values'] = array();
foreach($values as $record) {
foreach ($values as $record) {
$this->insertMulti['fields_values'][] = array_combine($fields, $record);
}
return true;
@ -467,18 +467,18 @@ class CakeTestFixtureTest extends CakeTestCase {
$this->assertEquals($expected, $this->insertMulti['values']);
$expected = array(
array(
'name' => 'Mark Doe',
'email' => 'mark.doe@email.com',
'name' => 'Mark Doe',
'email' => 'mark.doe@email.com',
'age' => null
),
array(
'name' => 'John Doe',
'email' => 'john.doe@email.com',
'name' => 'John Doe',
'email' => 'john.doe@email.com',
'age' => 20
),
array(
'name' => 'Jane Doe',
'email' => 'jane.doe@email.com',
'name' => 'Jane Doe',
'email' => 'jane.doe@email.com',
'age' => 30
),
);

View file

@ -1,38 +0,0 @@
<?php
class CakeTestSuiteDispatcherTest extends CakeTestCase {
public function setUp() {
$this->vendors = App::path('vendors');
$this->includePath = ini_get('include_path');
}
public function tearDown() {
App::build(array('Vendor' => $this->vendors), App::RESET);
ini_set('include_path', $this->includePath);
}
protected function clearPaths() {
App::build(array('Vendor' => array('junk')), App::RESET);
ini_set('include_path', 'junk');
}
public function testLoadTestFramework() {
$dispatcher = new CakeTestSuiteDispatcher();
$this->assertTrue($dispatcher->loadTestFramework());
$this->clearPaths();
$exception = null;
try {
$dispatcher->loadTestFramework();
} catch (Exception $ex) {
$exception = $ex;
}
$this->assertEquals(get_class($exception), "PHPUnit_Framework_Error_Warning");
}
}

View file

@ -2165,6 +2165,10 @@ class ValidationTest extends CakeTestCase {
$this->assertFalse(Validation::postal('BAA 0ABC', null, 'ca'));
$this->assertFalse(Validation::postal('B2A AABC', null, 'ca'));
$this->assertFalse(Validation::postal('B2A 2AB', null, 'ca'));
$this->assertFalse(Validation::postal('K1A 1D1', null, 'ca'));
$this->assertFalse(Validation::postal('K1O 1Q1', null, 'ca'));
$this->assertFalse(Validation::postal('A1A 1U1', null, 'ca'));
$this->assertFalse(Validation::postal('A1F 1B1', null, 'ca'));
$this->assertTrue(Validation::postal('X0A 0A2', null, 'ca'));
$this->assertTrue(Validation::postal('G4V 4C3', null, 'ca'));

View file

@ -540,6 +540,41 @@ XML;
}
}
/**
* Test that there are not unterminated errors when building xml
*
* @return void
*/
public function testFromArrayUnterminatedError() {
$data = array(
'product_ID' => 'GENERT-DL',
'deeplink' => 'http://example.com/deep',
'image_URL' => 'http://example.com/image',
'thumbnail_image_URL' => 'http://example.com/thumb',
'brand' => 'Malte Lange & Co',
'availability' => 'in stock',
'authors' => array(
'author' => array('Malte Lange & Co')
)
);
$xml = Xml::fromArray(array('products' => $data), 'tags');
$expected = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<products>
<product_ID>GENERT-DL</product_ID>
<deeplink>http://example.com/deep</deeplink>
<image_URL>http://example.com/image</image_URL>
<thumbnail_image_URL>http://example.com/thumb</thumbnail_image_URL>
<brand>Malte Lange &amp; Co</brand>
<availability>in stock</availability>
<authors>
<author>Malte Lange &amp; Co</author>
</authors>
</products>
XML;
$this->assertXmlStringEqualsXmlString($expected, $xml->asXML());
}
/**
* testToArray method
*

View file

@ -2276,6 +2276,33 @@ class FormHelperTest extends CakeTestCase {
$this->assertContains('<option value="00" selected="selected">00</option>', $result);
}
/**
* Test interval & timeFormat = 12
*
* @return void
*/
public function testInputTimeWithIntervalAnd12HourFormat() {
$result = $this->Form->input('Model.start_time', array(
'type' => 'time',
'timeFormat' => 12,
'interval' => 5,
'selected' => array('hour' => '4', 'min' => '30', 'meridian' => 'pm')
));
$this->assertContains('<option value="04" selected="selected">4</option>', $result);
$this->assertContains('<option value="30" selected="selected">30</option>', $result);
$this->assertContains('<option value="pm" selected="selected">pm</option>', $result);
$result = $this->Form->input('Model.start_time', array(
'type' => 'time',
'timeFormat' => '12',
'interval' => 5,
'selected' => '2013-04-19 16:30:00'
));
$this->assertContains('<option value="04" selected="selected">4</option>', $result);
$this->assertContains('<option value="30" selected="selected">30</option>', $result);
$this->assertContains('<option value="pm" selected="selected">pm</option>', $result);
}
/**
* test form->input() with datetime, date and time types
*

View file

@ -137,15 +137,18 @@ class CakeTestSuiteDispatcher {
* @return boolean true if found, false otherwise
*/
public function loadTestFramework() {
if (class_exists('PHPUnit_Framework_TestCase')) {
return true;
}
foreach (App::path('vendors') as $vendor) {
$vendor = rtrim($vendor, DS);
$vendor = rtrim($vendor, DS);
if (is_dir($vendor . DS . 'PHPUnit')) {
ini_set('include_path', $vendor . PATH_SEPARATOR . ini_get('include_path'));
break;
}
}
return (include('PHPUnit' . DS . 'Autoload.php')) !== false;
include 'PHPUnit' . DS . 'Autoload.php';
return class_exists('PHPUnit_Framework_TestCase');
}
/**

View file

@ -652,7 +652,9 @@ class Validation {
$regex = '/\\A\\b[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}\\b\\z/i';
break;
case 'ca':
$regex = '/\\A\\b[ABCEGHJKLMNPRSTVXY][0-9][A-Z] [0-9][A-Z][0-9]\\b\\z/i';
$district = '[ABCEGHJKLMNPRSTVYX]';
$letters = '[ABCEGHJKLMNPRSTVWXYZ]';
$regex = "/\\A\\b{$district}[0-9]{$letters} [0-9]{$letters}[0-9]\\b\\z/i";
break;
case 'it':
case 'de':
@ -784,7 +786,7 @@ class Validation {
* @return boolean Success
*/
public static function uuid($check) {
$regex = '/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i';
$regex = '/^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[1-5][a-fA-F0-9]{3}-[89aAbB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$/';
return self::_check($check, $regex);
}

View file

@ -305,10 +305,9 @@ class Xml {
$childValue = (string)$value;
}
$child = $dom->createElement($key);
if ($childValue) {
$child = $dom->createElement($key, $childValue);
} else {
$child = $dom->createElement($key);
$child->appendChild($dom->createTextNode($childValue));
}
if ($childNS) {
$child->setAttribute('xmlns', $childNS);

View file

@ -2387,7 +2387,8 @@ class FormHelper extends AppHelper {
}
$change = (round($min * (1 / $interval)) * $interval) - $min;
$current->modify($change > 0 ? "+$change minutes" : "$change minutes");
$newTime = explode(' ', $current->format('Y m d H i a'));
$format = ($timeFormat === '12') ? 'Y m d h i a' : 'Y m d H i a';
$newTime = explode(' ', $current->format($format));
list($year, $month, $day, $hour, $min, $meridian) = $newTime;
}
@ -2507,14 +2508,14 @@ class FormHelper extends AppHelper {
if (!empty($timeFormat)) {
$time = explode(':', $days[1]);
if ($time[0] >= '12' && $timeFormat === '12') {
if ($time[0] >= 12 && $timeFormat == 12) {
$meridian = 'pm';
} elseif ($time[0] === '00' && $timeFormat === '12') {
} elseif ($time[0] === '00' && $timeFormat == 12) {
$time[0] = 12;
} elseif ($time[0] >= 12) {
$meridian = 'pm';
}
if ($time[0] == 0 && $timeFormat === '12') {
if ($time[0] == 0 && $timeFormat == 12) {
$time[0] = 12;
}
$hour = $min = null;

View file

@ -560,14 +560,13 @@ class View extends Object {
//@codingStandardsIgnoreStart
@unlink($filename);
//@codingStandardsIgnoreEnd
unset ($out);
unset($out);
return false;
} else {
if ($this->layout === 'xml') {
header('Content-type: text/xml');
}
$commentLength = strlen('<!--cachetime:' . $match['1'] . '-->');
return substr($out, $commentLength);
return substr($out, strlen($match[0]));
}
}
}