Browse Source

Merge branch 'master' into 2.4

Conflicts:
	lib/Cake/Console/Shell.php
mark_story 13 years ago
parent
commit
041c2d289f

+ 73 - 0
CONTRIBUTING.md

@@ -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

+ 1 - 0
lib/Cake/Console/Shell.php

@@ -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');
 

+ 0 - 1
lib/Cake/Console/Templates/default/actions/controller_actions.ctp

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

+ 4 - 6
lib/Cake/Core/App.php

@@ -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();
 	}
 

+ 8 - 2
lib/Cake/Model/Datasource/Database/Sqlserver.php

@@ -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']);
 			}
 

+ 1 - 1
lib/Cake/Network/Email/CakeEmail.php

@@ -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) {

+ 18 - 2
lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php

@@ -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']);
 	}
 
 /**

+ 7 - 7
lib/Cake/Test/Case/TestSuite/CakeTestFixtureTest.php

@@ -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
 			),
 		);

+ 0 - 38
lib/Cake/Test/Case/TestSuite/CakeTestSuiteDispatcherTest.php

@@ -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");
-  }
-
-}

+ 4 - 0
lib/Cake/Test/Case/Utility/ValidationTest.php

@@ -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'));
 

+ 35 - 0
lib/Cake/Test/Case/Utility/XmlTest.php

@@ -541,6 +541,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
  *
  * @return void

+ 27 - 0
lib/Cake/Test/Case/View/Helper/FormHelperTest.php

@@ -2277,6 +2277,33 @@ class FormHelperTest extends CakeTestCase {
 	}
 
 /**
+ * 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
  *
  * @return void

+ 6 - 3
lib/Cake/TestSuite/CakeTestSuiteDispatcher.php

@@ -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');
 	}
 
 /**

+ 4 - 2
lib/Cake/Utility/Validation.php

@@ -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);
 	}
 

+ 2 - 3
lib/Cake/Utility/Xml.php

@@ -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);

+ 5 - 4
lib/Cake/View/Helper/FormHelper.php

@@ -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;

+ 2 - 3
lib/Cake/View/View.php

@@ -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]));
 			}
 		}
 	}