Skip to content

Commit

Permalink
Php5.5 (#1)
Browse files Browse the repository at this point in the history
* support php5.5

* remove mkdocs from travis file

* add markdown linting

* use mt_rand

* handle sequential arrays

* update README with flags

* handle testing functions in php5.5

* de-dupe sequential code

* slightly less code
  • Loading branch information
Harry Bragg authored Sep 11, 2018
1 parent cf27e85 commit f247888
Show file tree
Hide file tree
Showing 19 changed files with 414 additions and 88 deletions.
17 changes: 1 addition & 16 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ cache:
- $HOME/.composer/cache/files

php:
- 5.5
- 5.6
- 7.0
- 7.1
Expand Down Expand Up @@ -36,26 +37,10 @@ after_script:
stages:
- test
- lint
- name: deploy
if: branch = master
jobs:
include:
- stage: lint
name: "Markdown"
before_script: sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
script: make lint-md
after_script: skip
- stage: deploy
name: "Deploy to GitHub Pages"
before_script: sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
script: make docs-build
after_script: skip
deploy:
provider: pages
local-dir: site
skip-cleanup: true
keep-history: true
verbose: true
github-token: $GITHUB_TOKEN
on:
branch: master
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ lint-php: ## Run phpcs against the code.
${DOCKER_RUN} vendor/bin/phpcs -p --warning-severity=0 src/ tests/

lint-md: ## Run markdownlist against the documentation
${DOCKER} run --rm -v $$(pwd):/data:cached gouvinb/docker-markdownlint -v *.md docs/*.md docs/*/*.md
${DOCKER} run --rm -v $$(pwd):/data:cached gouvinb/docker-markdownlint -v *.md

lint-fix: ## Run phpcsf and fix possible lint errors.
${DOCKER_RUN} vendor/bin/phpcbf -p src/ tests/
Expand All @@ -64,6 +64,7 @@ test-matrix-lowest: ## Test all version, with the lowest version
${MAKE} build-update

test-matrix: ## Run the unit tests against multiple targets.
${MAKE} PHP_VER="5.5" IMAGE="php:5.5-alpine" build-update test
${MAKE} PHP_VER="5.6" build-update test
${MAKE} PHP_VER="7.0" build-update test
${MAKE} PHP_VER="7.1" build-update test
Expand Down
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# array-merger
# Array Merger

[![Latest Version on Packagist](https://img.shields.io/packagist/v/graze/array-merger.svg?style=flat-square)](https://packagist.org/packages/graze/array-merger)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
Expand All @@ -11,7 +11,7 @@ Array Merge allows you to recursively merge arrays and choose how the values sho

![Merge](https://media.giphy.com/media/cnEXDpXvkZ7lm/giphy.gif)

## Why?
## Why

The php function: [`array_merge_recursive`](http://php.net/manual/en/function.array-merge-recursive.php)
does indeed merge arrays, but it converts values with duplicate keys to arrays rather than overwriting the value in
Expand Down Expand Up @@ -91,10 +91,10 @@ RecursiveArrayMerger::lastNonNull(

```php
$merger = new Graze\ArrayMerger\RecursiveArrayMerger(new LastNonNullValue());
var_dump($merger->merge(
$merger->merge(
['a' => 'first', 'b' => ['c' => 'cake', 'd' => 'fish']],
['a' => 'second', 'b' => ['d' => null]]
));
);

// ['a' => 'second', 'b' => ['c' => 'cake', 'd' => 'first']]
```
Expand All @@ -110,6 +110,19 @@ RecursiveArrayMerger::mergeUsing(
// ['a' => 4, 'b' => ['c' => 2, 'd' => 3]]
```

### Sequential Arrays

If instead of overwriting sequential arrays you can append them using a flag

```php
$merger = new Graze\ArrayMerger\RecursiveArrayMerger(new LastValue(), RecursiveArrayMerger::FLAG_APPEND_VALUE_ARRAY);
$merger->merge(
['a' => 'first', 'b' => ['a','c','d']],
['a' => 'second', 'b' => ['e']]
);
// ['a' => 'second', 'b' => ['a','c','d','e']]
```

## Testing

```shell
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
}
],
"require": {
"php": "^5.6 | ^7.0"
"php": "^5.5 | ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.21 | ^6 | ^7",
"phpunit/phpunit": "^4.8.36 | ^5.7.21 | ^6 | ^7",
"squizlabs/php_codesniffer": "^3.0",
"graze/standards": "^2.0"
},
Expand Down
4 changes: 2 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 26 additions & 9 deletions src/ArrayMerger.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Graze\ArrayMerger;

use Graze\ArrayMerger\ValueMerger\ArrayMergerInterface;
use Graze\ArrayMerger\ValueMerger\LastValue;

/**
Expand All @@ -13,52 +12,70 @@
class ArrayMerger implements ArrayMergerInterface
{
use StaticMethodsTrait;
use SequentialTrait;

/** @var callable */
protected $valueMerger;
/** @var int */
private $flags;

/**
* @param callable $valueMerger
* @param int $flags
*/
public function __construct(callable $valueMerger = null)
public function __construct(callable $valueMerger = null, $flags = 0)
{
$this->valueMerger = $valueMerger ?: new LastValue();
$this->flags = $flags;
}

/**
* Merge using the supplied Value Merge
*
* @param callable $valueMerger
* @param array $array1
* @param array ...$arrays
* @param array $arrays
*
* @return array
*/
public static function mergeUsing(callable $valueMerger, array $array1, array ...$arrays)
public static function mergeUsing(callable $valueMerger, array $array1, array $arrays)
{
$merger = new static($valueMerger);
return $merger->merge($array1, ...$arrays);
return call_user_func_array([$merger, 'merge'], array_merge([$array1], array_slice(func_get_args(), 2)));
}

/**
* Merge the values from all the array supplied, the first array is treated as the base array to merge into
*
* @param array $array1
* @param array ...$arrays List of arrays to merge
* @param array $array1
* @param array|null $arrays
*
* @return array
*/
public function merge(array $array1, array ...$arrays)
public function merge(array $array1, array $arrays = null)
{
$arrays = array_slice(func_get_args(), 1);
if (count($arrays) === 0) {
return $array1;
}

// if all arrays are sequential and flag is set, append them all
if ($this->flags & static::FLAG_APPEND_VALUE_ARRAY == static::FLAG_APPEND_VALUE_ARRAY
&& $this->areSequential(array_merge([$array1], $arrays))) {
return call_user_func_array('array_merge', array_merge([$array1], $arrays));
}

$merged = $array1;

foreach ($arrays as $toMerge) {
foreach ($toMerge as $key => &$value) {
if (array_key_exists($key, $merged)) {
$merged[$key] = call_user_func($this->valueMerger, $merged[$key], $value);
if ($this->flags & static::FLAG_APPEND_VALUE_ARRAY == static::FLAG_APPEND_VALUE_ARRAY
&& $this->areSequential([$value, $merged[$key]])) {
$merged[$key] = array_merge($merged[$key], $value);
} else {
$merged[$key] = call_user_func($this->valueMerger, $merged[$key], $value);
}
} else {
$merged[$key] = $value;
}
Expand Down
21 changes: 18 additions & 3 deletions src/ArrayMergerInterface.php
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
<?php

namespace Graze\ArrayMerger\ValueMerger;
namespace Graze\ArrayMerger;

interface ArrayMergerInterface
{
/**
* If 2 elements are both value arrays ['a','b','c'], etc.
* This will append the second array onto the first.
*
* Example:
*
* ```php
* merge(['a' => ['a','b','c']],['b' => ['d','e','f']]);
* // ['a' => ['a','b','c','d','e','f']]
* ```
*
* If it is off, the first value will be replaced by the second
*/
const FLAG_APPEND_VALUE_ARRAY = 1;

/**
* Merge the values from the subsequent set of arrays into the first array
*
* @param array $array1
* @param array ...$arrays
* @param array $arrays multiple arrays to merge into array1
*
* @return array
*/
public function merge(array $array1, array ...$arrays);
public function merge(array $array1, array $arrays = null);
}
28 changes: 20 additions & 8 deletions src/RecursiveArrayMerger.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Graze\ArrayMerger;

use Graze\ArrayMerger\ValueMerger\ArrayMergerInterface;
use Graze\ArrayMerger\ValueMerger\LastValue;

/**
Expand All @@ -19,46 +18,59 @@
class RecursiveArrayMerger implements ArrayMergerInterface
{
use StaticMethodsTrait;
use SequentialTrait;

/** @var callable */
protected $valueMerger;
/** @var int */
private $flags;

/**
* @param callable $valueMerger
* @param int $flags one of ArrayMergerInterface::FLAG_*
*/
public function __construct(callable $valueMerger = null)
public function __construct(callable $valueMerger = null, $flags = 0)
{
$this->valueMerger = $valueMerger ?: new LastValue();
$this->flags = $flags;
}

/**
* Merge using the supplied Value Merge
*
* @param callable $valueMerger
* @param array $array1
* @param array ...$arrays
* @param array $arrays
*
* @return array
*/
public static function mergeUsing(callable $valueMerger, array $array1, array ...$arrays)
public static function mergeUsing(callable $valueMerger, array $array1, array $arrays)
{
$merger = new static($valueMerger);
return $merger->merge($array1, ...$arrays);
return call_user_func_array([$merger, 'merge'], array_merge([$array1], array_slice(func_get_args(), 2)));
}

/**
* Merge the values from all the array supplied, the first array is treated as the base array to merge into
*
* @param array $array1
* @param array ...$arrays List of arrays to merge
* @param array $array1
* @param array|null $arrays
*
* @return array
*/
public function merge(array $array1, array ...$arrays)
public function merge(array $array1, array $arrays = null)
{
$arrays = array_slice(func_get_args(), 1);
if (count($arrays) === 0) {
return $array1;
}

// if all arrays are sequential and flag is set, append them all
if ($this->flags & static::FLAG_APPEND_VALUE_ARRAY == static::FLAG_APPEND_VALUE_ARRAY
&& $this->areSequential(array_merge([$array1], $arrays))) {
return call_user_func_array('array_merge', array_merge([$array1], $arrays));
}

$merged = $array1;

foreach ($arrays as $toMerge) {
Expand Down
37 changes: 37 additions & 0 deletions src/SequentialTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Graze\ArrayMerger;

trait SequentialTrait
{
/**
* Check if the provided array is sequential or not
*
* @param array $array
*
* @return bool
*/
protected function isSequential(array $array)
{
if (!empty($array) && !array_key_exists(0, $array)) {
return false;
}
return array_values($array) === $array;
}

/**
* @param array $arrays Collection of arrays to check
*
* @return bool True if all the arrays are sequential
*/
protected function areSequential(array $arrays)
{
foreach ($arrays as $array) {
if (!is_array($array) || !$this->isSequential($array)) {
return false;
}
}

return true;
}
}
Loading

0 comments on commit f247888

Please sign in to comment.