Skip to content
Permalink
Browse files

Merge branch 'master' into 3.next

  • Loading branch information...
markstory committed Apr 25, 2016
2 parents 87ba9c7 + c263b38 commit 4697b8e303f29f89971a681a1030da8ed127a4bc

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -86,12 +86,14 @@ public function reject(callable $c)
*/
public function every(callable $c)
{
$return = false;
foreach ($this->unwrap() as $key => $value) {
$return = true;
if (!$c($value, $key)) {
return false;
}
}
return true;
return $return;
}
/**
@@ -361,8 +361,10 @@ public function addOption($name, array $options = [])
$option = new ConsoleInputOption($options);
}
$this->_options[$name] = $option;
asort($this->_options);
if ($option->short() !== null) {
$this->_shortOptions[$option->short()] = $name;
asort($this->_shortOptions);
}
return $this;
}
@@ -495,6 +497,7 @@ public function addSubcommand($name, array $options = [])
$command = new ConsoleInputSubcommand($options);
}
$this->_subcommands[$name] = $command;
asort($this->_subcommands);
return $this;
}
@@ -1685,8 +1685,14 @@ public function traverseExpressions(callable $callback)
*
* If type is expressed as "atype[]" (note braces) then it will cause the
* placeholder to be re-written dynamically so if the value is an array, it
* will create as many placeholders as values are in it. For example "string[]"
* will create several placeholders of type string.
* will create as many placeholders as values are in it. For example:
*
* ```
* $query->bind(':id', [1, 2, 3], 'int[]');
* ```
*
* Will create 3 int placeholders. When using named placeholders, this method
* requires that the placeholders include `:` e.g. `:value`.
*
* @param string|int $param placeholder to be replaced with quoted version
* of $value
@@ -20,6 +20,8 @@
/**
* Describes the methods that any class representing a data storage should
* comply with.
*
* @property mixed $id Alias for commonly used primary key.
*/
interface EntityInterface extends ArrayAccess, JsonSerializable
{
@@ -380,19 +380,14 @@ public function body($parser = null)
/**
* Get the response body as JSON decoded data.
*
* @return null|array
* @return mixed
*/
protected function _getJson()
{
if (!empty($this->_json)) {
return $this->_json;
}
$data = json_decode($this->_body, true);
if ($data) {
$this->_json = $data;
return $this->_json;
}
return null;
return $this->_json = json_decode($this->_body, true);
}
/**
@@ -7,14 +7,17 @@ The CakePHP ORM provides a powerful and flexible way to work with relational
databases. Using a datamapper pattern the ORM allows you to manipulate data as
entities allowing you to create expressive domain layers in your applications.

## Connecting to the Database
## Database engines supported

The CakePHP ORM is compatible with:

* MySQL 5.1+
* Postgres 8+
* SQLite3
* SQLServer 2008+
* Oracle (through a [community plugin](https://github.com/CakeDC/cakephp-oracle-driver))

## Connecting to the Database

The first thing you need to do when using this library is register a connection
object. Before performing any operations with the connection, you need to
@@ -1618,6 +1618,45 @@ protected function _update($entity, $data)
return $success;
}
/**
* Persists multiple entities of a table.
*
* The records will be saved in a transaction which will be rolled back if
* any one of the records fails to save due to failed validation or database
* error.
*
* @param array|\Cake\ORM\ResultSet $entities Entities to save.
* @param array|\ArrayAccess $options Options used when calling Table::save() for each entity.
* @return bool|array|\Cake\ORM\ResultSet False on failure, entities list on succcess.
*/
public function saveMany($entities, $options = [])
{
$isNew = [];
$return = $this->connection()->transactional(
function () use ($entities, $options, &$isNew) {
foreach ($entities as $key => $entity) {
$isNew[$key] = $entity->isNew();
if ($this->save($entity, $options) === false) {
return false;
}
}
}
);
if ($return === false) {
foreach ($entities as $key => $entity) {
if (isset($isNew[$key]) && $isNew[$key]) {
$entity->unsetProperty($this->primaryKey());
$entity->isNew(true);
}
}
return false;
}
return $entities;
}
/**
* {@inheritDoc}
*
@@ -4,9 +4,9 @@
"license": "MIT",
"authors": [
{
"name": "CakePHP Community",
"homepage": "http://cakephp.org"
}
"name": "CakePHP Community",
"homepage": "http://cakephp.org"
}
],
"autoload": {
"psr-4": {
@@ -16,8 +16,8 @@
"require": {
"cakephp/collection": "~3.0",
"cakephp/core": "~3.0",
"cakephp/datasource": "~3.0",
"cakephp/database": "~3.0",
"cakephp/datasource": "^3.1.2",
"cakephp/database": "^3.1.4",
"cakephp/event": "~3.0",
"cakephp/utility": "~3.0",
"cakephp/validation": "~3.0"
@@ -104,7 +104,16 @@ public static function randomBytes($length)
return random_bytes($length);
}
if (function_exists('openssl_random_pseudo_bytes')) {
return openssl_random_pseudo_bytes($length);
$bytes = openssl_random_pseudo_bytes($length, $strongSource);
if (!$strongSource) {
trigger_error(
'openssl was unable to use a strong source of entropy. ' .
'Consider updating your system libraries, or ensuring ' .
'you have more available entropy.',
E_USER_WARNING
);
}
return $bytes;
}
trigger_error(
'You do not have a safe source of random data available. ' .
@@ -570,13 +570,12 @@ public static function truncate($text, $length = 100, array $options = [])
$default['ellipsis'] = "\xe2\x80\xa6";
}
$options += $default;
extract($options);
if ($html) {
if ($options['html']) {
if (mb_strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
return $text;
}
$totalLength = mb_strlen(strip_tags($ellipsis));
$totalLength = mb_strlen(strip_tags($options['ellipsis']));
$openTags = [];
$truncate = '';
@@ -609,49 +608,70 @@ public static function truncate($text, $length = 100, array $options = [])
}
}
$truncate .= mb_substr($tag[3], 0, $left + $entitiesLength);
if (!$options['exact']) {
$words = explode(' ', $tag[3]);
// Keep at least one word.
if (count($words) === 1) {
$truncate .= mb_substr($tag[3], 0, $left + $entitiesLength);
} else {
$wordLength = 0;
$addWords = [];
// Append words until the length is crossed.
foreach ($words as $word) {
// Add words until we have enough letters.
if ($wordLength < $left + $entitiesLength) {
$addWords[] = $word;
}
// Include inter-word space.
$wordLength += mb_strlen($word) + 1;
}
$truncate .= implode(' ', $addWords);
// If the string is longer than requested, find the last space and cut there.
$lastSpace = mb_strrpos($truncate, ' ');
if (mb_strlen($truncate) > $totalLength && $lastSpace !== false) {
$remainder = mb_substr($truncate, $lastSpace);
$truncate = mb_substr($truncate, 0, $lastSpace);
// Re-add close tags that were cut off.
preg_match_all('/<\/([a-z]+)>/', $remainder, $droppedTags, PREG_SET_ORDER);
if ($droppedTags) {
foreach ($droppedTags as $closingTag) {
if (!in_array($closingTag[1], $openTags)) {
array_unshift($openTags, $closingTag[1]);
}
}
}
}
}
} else {
$truncate .= mb_substr($tag[3], 0, $left + $entitiesLength);
}
break;
}
$truncate .= $tag[3];
$totalLength += $contentLength;
if ($totalLength >= $length) {
break;
}
}
} else {
if (mb_strlen($text) <= $length) {
return $text;
$truncate .= $options['ellipsis'];
foreach ($openTags as $tag) {
$truncate .= '</' . $tag . '>';
}
$truncate = mb_substr($text, 0, $length - mb_strlen($ellipsis));
return $truncate;
}
if (!$exact) {
if (mb_strlen($text) <= $length) {
return $text;
}
$truncate = mb_substr($text, 0, $length - mb_strlen($options['ellipsis']));
if (!$options['exact']) {
$spacepos = mb_strrpos($truncate, ' ');
if ($html) {
$truncateCheck = mb_substr($truncate, 0, $spacepos);
$lastOpenTag = mb_strrpos($truncateCheck, '<');
$lastCloseTag = mb_strrpos($truncateCheck, '>');
if ($lastOpenTag > $lastCloseTag) {
preg_match_all('/<[\w]+[^>]*>/s', $truncate, $lastTagMatches);
$lastTag = array_pop($lastTagMatches[0]);
$spacepos = mb_strrpos($truncate, $lastTag) + mb_strlen($lastTag);
}
$bits = mb_substr($truncate, $spacepos);
preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
if (!empty($droppedTags)) {
if (!empty($openTags)) {
foreach ($droppedTags as $closingTag) {
if (!in_array($closingTag[1], $openTags)) {
array_unshift($openTags, $closingTag[1]);
}
}
} else {
foreach ($droppedTags as $closingTag) {
$openTags[] = $closingTag[1];
}
}
}
}
$truncate = mb_substr($truncate, 0, $spacepos);
// If truncate still empty, then we don't need to count ellipsis in the cut.
@@ -660,14 +680,7 @@ public static function truncate($text, $length = 100, array $options = [])
}
}
$truncate .= $ellipsis;
if ($html) {
foreach ($openTags as $tag) {
$truncate .= '</' . $tag . '>';
}
}
$truncate .= $options['ellipsis'];
return $truncate;
}
@@ -148,7 +148,7 @@ public function __construct(View $View, array $config = [])
* Adds a link to the breadcrumbs array.
*
* @param string $name Text for link
* @param string|null $link URL for link (if empty it won't be a link)
* @param string|array|null $link URL for link (if empty it won't be a link)
* @param string|array $options Link attributes e.g. ['id' => 'selected']
* @return $this
* @see \Cake\View\Helper\HtmlHelper::link() for details on $options that can be used.
@@ -192,6 +192,13 @@ public function testEveryReturnFalse()
->will($this->returnValue(false));
$callable->expects($this->exactly(2))->method('__invoke');
$this->assertFalse($collection->every($callable));
$items = [];
$collection = new Collection($items);
$callable = $this->getMock('stdClass', ['__invoke']);
$callable->expects($this->never())
->method('__invoke');
$this->assertFalse($collection->every($callable));
}
/**
@@ -591,12 +591,12 @@ public function testHelpSubcommandHelp()
$result = $parser->help('method');
$expected = <<<TEXT
<info>Usage:</info>
cake mycommand method [-h] [--connection]
cake mycommand method [--connection] [-h]
<info>Options:</info>
--help, -h Display this help.
--connection Db connection.
--help, -h Display this help.
TEXT;
$this->assertTextEquals($expected, $result, 'Help is not correct.');
Oops, something went wrong.

0 comments on commit 4697b8e

Please sign in to comment.
You can’t perform that action at this time.