Skip to content

Commit

Permalink
Merge pull request #33 from chrismichaels84/develop
Browse files Browse the repository at this point in the history
Merge Develop into Master for v0.8.6
  • Loading branch information
Michael Wilson committed Nov 3, 2015
2 parents 535bd5f + 1da03d7 commit 86a551f
Show file tree
Hide file tree
Showing 46 changed files with 1,711 additions and 273 deletions.
2 changes: 1 addition & 1 deletion .gitignore
@@ -1,7 +1,7 @@
build
composer.lock
vendor

# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
# composer.lock
.idea/
2 changes: 2 additions & 0 deletions .travis.yml
Expand Up @@ -16,6 +16,8 @@ matrix:
before_script:
- travis_retry composer self-update
- travis_retry composer install --no-interaction --prefer-source --dev
- composer require bocharsky-bw/arrayzy:dev-master
- composer require symfony/yaml:~2.7

script:
- mkdir -p build/logs
Expand Down
30 changes: 21 additions & 9 deletions CHANGELOG.md
@@ -1,10 +1,22 @@
# Changelog
All Notable changes to `Manager` will be documented in this file

# Future
- Initialize `CollectsItemsTrait` and `Collection` class

#v0.8.5 - NEXT
# v0.8.6 - 11-3-2015
- Updates `ManagesItemsInterface`
- Updates Readme documentation

- Adds `push()` to `ManagesItemsTrait` to push values onto a nested array (#27)
- Adds ability to load configuration from files using various decoders
- Adds `FileBag`, `FileLoader`, various decoders, and `LoadsFilesTrait` with tests
- Adds `isArrayable()` helper method to `ManagesItemsTrait`
- Adds method in `ManagesItemsTrait` to prepare data before its returned to user
- Adds basic collection functionality
- Returns instance of `MutableArray` collection if requested
- Introduced CollectionTrait with tests

- Bug: `getIfExists()` now returns `null` if item has been initializes with null(#17)

# v0.8.5 - 9-17-2015
- Adds `IocContainerTrait` for basic DI functionality
- initDI() and share()
- produce from classname, object, factory, or instance of manager
Expand All @@ -13,33 +25,33 @@ All Notable changes to `Manager` will be documented in this file
- Adds `DependsOnManagesItemsTrait` to ensure that other traits require Manages Items.
- Adds `hydrateFrom()` and `appendFrom()` for non-native object formats

#v0.8.4 - 2015-7-14
# v0.8.4 - 2015-7-14
- Better documentation (README.md)
- Add protected items functionality
- Split Arrayable stuff in Manager to ArrayableTrait Issue #11 with tests
- Bug: reversed nestable items so you can get a single item without calling it as method
- Added: CRUD through nested items magic methods (ChainsNestedItemsTrait) Issue #3

#v0.8.3 - 2015-6-24
# v0.8.3 - 2015-6-24
- Move constructor out of `ManagesItemsTrait`
- Added `getIfHas()` which returns the item or a `NoItemFoundMessage`
- Refactor internal to use `getIfHas()` for performance
- Allows for configurable $items property

# V0.8.2 - 2015-6-3
# v0.8.2 - 2015-6-3
- Allow any value in manager initialization, will be cast to array
- Throw exception if nesting under an existing value that is not an array
- Added CustomizedManager test suite and tests for the above
- ManagesItemsTrait::__toJson() accepts options
- alias all() to getAll()

# V0.8.1 - 2015-5-12
# v0.8.1 - 2015-5-12
- Use initManager() to initialize Manager when extending the base class or using traits

# v0.8 - 2015-4-19
This was the first public release version

### Added
### Introduced
- add(), get(), exists(), remove(), getAll(), set(), clear(), reset(), toJson(), isEmpty()
- initialize with items
- full dot-notation and nesting
Expand Down
74 changes: 61 additions & 13 deletions README.md
Expand Up @@ -32,21 +32,18 @@ They are not documented here, but see other readmes for:
* Configuring dependencies for dependencies,
* Fallbacks, preparing objects, and more.
* Use Manager as a configuration bank, complete with defaults.
* Load configuration files (php, yaml, json, xml, and custom)
* Collections for extra array-helper methods (based on [Arrayzy](https://github.com/bocharsky-bw/Arrayzy))

## Install
Via Composer
``` bash
$ composer require michaels/data-manager
```

## Upgrading
Note that between 0.8.2 and 0.8.3, the `__constuct()` method was removed from `ManagesItemsTrait`. If you are using that trait directly, you should implement your own.

See `Michaels\Manager\Manager` for an example.

## Getting Started
Manager does exactly what you would expect: it *manages* complex items such as config data, arrays, and closures.
The best way to get started is simply instantiate `Michaels\Manager\Mangaer`
The best way to get started is simply instantiate `Michaels\Manager\Manager`

```php
$manager = new Michaels\Manager\Manager([
Expand Down Expand Up @@ -78,8 +75,6 @@ $manager->toJson(); // returns json of all items
echo $manager; // returns json string of all items
$manager->reset($array); // rebuild with new items
$manager->clear(); // empty the manager
$manager->hydrateFrom('json', $data); // imports from serialized data into new data set - currently only JSON
$manager->appendFrom('json', $data); // same as hydrate, but adds data to current data set

/* You can also use $manager as an array or in loops */
$manager['some']['starting']['data']; // 'here (optional)'
Expand All @@ -89,6 +84,11 @@ foreach ($manager as $item => $value) {
// do whatever your heart desires
}

/* You may also push elements onto an array */
$manager->set('a.b', []);
$manager->push('a.b', 'c', 'd', 'e');
$manager->get('a.b'); // ['c', 'd', 'e']

/* Finally, you may manage values using magic methods */
$manager->some()->starting()->data; // 'here (optional)'
$manager->some()->item = 'item'; // sets some.item = 'item'
Expand Down Expand Up @@ -156,15 +156,28 @@ There are 3 Traits that make up Manager:
2. `ArrayableTrait` makes the class usable as an array (`$manager['some']['data']`) or in loops and such
3. `ChainsNestedItemsTrait` allows you to use fluent properties to manage data (`$manager->one()->two()->three = 'three`)

And 3 extra Traits to give additional functionality:
1. `CollectionTrait` returns collections with all sorts of [array helpers](https://github.com/bocharsky-bw/Arrayzy)
2. `ManagesIocTrait` turns Manager into a simple, but complete IoC or Dependency Injection manager
3. `LoadsFilesTrait` allows Manager to load data from config files.

Each of these traits is documented below. To include the functionality simply `use` the trait.
it is possible to use ALL traits together in one class, though I don't know why you would need to.

*NOTE THAT* all traits depend on ManagesItemsTrait. If you try to use ChainsNestedItemsTrait or ArrayableTrait without ManagesItemsTrait, you will get all sorts of errors.

```php
/* An example for UberManager */
class MyContainer {
use Michaels\Manager\Traits\ManagesItemsTrait; // for all the basic functionality
use Michaels\Manager\Traits\ChainsNestedItemsTrait; // to access nested items via magic methods
use Michaels\Manager\Traits\ArrayableTrait; // So you can use $myConainer like an array

// Your stuff here. And you may override anything you like
use Michaels\Manager\Traits\ManagesItemsTrait;
use Michaels\Manager\Traits\ChainsNestedItemsTrait;
use Michaels\Manager\Traits\ArrayableTrait;
use Michaels\Manager\Traits\CollectionTrait;
use Michaels\Manager\Traits\LoadsFilesTrait;
use Michaels\Manager\Traits\ManagesIocTrait;

// Your stuff here. And you may override anything you like.
// Remember to add a constructor if you want :)
}
```

Expand Down Expand Up @@ -196,6 +209,34 @@ public function __construct($items = [])
```

You may also use the **tests** under `tests/traits` to test your integrated functionality. You may have to grab these through cloning the repo. composer usually won't include tests in your `require`
## Additional Features

### Collections
Right now, you may choose to return a `MutableArray` which comes with a lot of helpers.
Simply include `Michaels\Manager\Traits\CollectionTrait` into your class. By default, `get()` and `getAll()` will return collections.
These collections behave *identically* to arrays, but come with extra methods. See [Arrayzy](https://github.com/bocharsky-bw/Arrayzy) for a full api.

It is possible to chain things for brevity:
```php
$value = $manager->get('one.two.three')->walk(function(){});
```
In this case, `walk()` is part of the collection and will apply the callback to each value, then return the updated contents.

You may also disable this by `$manager->useCollections = false`

### Loading Files
Manager also gives you the ability to load file data into the Manager. A good use case for this is loading configuration data out of different configuration files.

1. Use `$manager->loadFiles($files)` to load a group of files. The `$files` argument can be either a `\FileBag` object or an array of `\SplFileInfo` objects. Most likely you would use an array, like the return result of [Symfony's Finder Component](https://github.com/symfony/Finder), which can locate files in a directory tree and return them as `\SplFileInfo` objects.
2. If you have created your own type of config file, you can also create a decoder for those types of files. All you need to do is follow the `\DecoderInterface` interface and return a php array of data through the `decode()` method. Then, once you have a decoder, you can add the decoder to the file loader with `$manager->addDecoder($decoder);` Once the decoder is added, you can then load your custom config files to the Manager, as in the previous step.

NOTE: Currently Manager supports Yaml, Json and PHP file formats out of the box. To use the Yaml decoder, you must require the Symfony Yaml Component in your composer.json file.

#### Adding a Decoder
If you have special files not covered by the default decoders available in Manager, you can also create your own and add it to the Manager prior to decoding the files with the `$manager->loadFiles()` method. For an example custom decoder, have a look at the `\CustomXmlDecoder` class in the `/Decoders` directory. Once you've created your custom decoder, you can add it with the `$manager->addDecoder()` method. Again, you must add the decoder prior to loading any file data.

### Managing Dependencies
Please see [ioc.md](ioc.md) for details.

## Some Advanced Features
By default, Manager stores all the items in an `$items` property.
Expand All @@ -217,6 +258,13 @@ $manager->add("one.two", "two-value"); // exception

If you try to alter a protected item, a `ModifyingProtectedItemException` will be thrown.

See /exceptions for more

## Upgrading
Note that between 0.8.2 and 0.8.3, the `__constuct()` method was removed from `ManagesItemsTrait`. If you are using that trait directly, you should implement your own.

See `Michaels\Manager\Manager` for an example.

## Interoperability
Data Manager is [PSR compliant](http://www.php-fig.org/) and [Container Interoperability](https://github.com/container-interop/container-interop) compliant. Any oversights, please let me know.

Expand Down
6 changes: 5 additions & 1 deletion composer.json
Expand Up @@ -24,9 +24,13 @@
"container-interop/container-interop": "1.1.0"
},
"require-dev": {
"phpunit/phpunit" : "4.*",
"phpunit/phpunit": "4.*",
"satooshi/php-coveralls": "dev-master"
},
"suggest": {
"symfony/yaml": "If you are using the YAML decoder. ~2.7",
"bocharsky-bw/arrayzy": "If you are using the Collections feature, you will need to 'dev-master' until 0.3 is released."
},
"autoload": {
"psr-4": {
"Michaels\\Manager\\": "src"
Expand Down
74 changes: 74 additions & 0 deletions src/Bags/FileBag.php
@@ -0,0 +1,74 @@
<?php
namespace Michaels\Manager\Bags;

use Michaels\Manager\Exceptions\BadFileInfoObjectException;

/**
* Class FileBag - a collection object needed to create SplFileInfo objects from file references, in order to inject
* into the FileLoader. This collection class can only store SplFileInfo objects. Anything else will cause exceptions.
*
* @package Michaels\Manager\Bags
*/
class FileBag
{
/**
* @var array An array of SplFileInfo objects
*/
protected $fileObjects = [];

/**
* Constructs a new FileBag
* @param $arrayOfSplFileInfoObjects
*/
public function __construct(array $arrayOfSplFileInfoObjects = [])
{
$this->initialize($arrayOfSplFileInfoObjects);
}

/**
* Return an array of SplFileInfo objects
* @return array
*/
public function getAllFileInfoObjects()
{
return $this->fileObjects;
}

/**
* Reset the FileBag back to an empty array.
* @return array - an empty array
*/
public function emptyBag()
{
$this->fileObjects = [];
return $this->fileObjects;
}

/**
* Set up the bag with a proper array of SplFileInfo objects
* @param array $splFileInfoObjects
* @internal param $arrayOfSplFileInfoObjects
*/
protected function initialize(array $splFileInfoObjects = [])
{
if (!empty($splFileInfoObjects)) {
foreach ($splFileInfoObjects as $object) {
if ($this->isSplFileInfoObject($object)) {
array_push($this->fileObjects, $object);
} else {
throw new BadFileInfoObjectException('The input array does not hold proper SplFileInfo objects.');
}
}
}
}

/**
* Check for an \SplFileInfo object
* @param $object
* @return bool
*/
protected function isSplFileInfoObject($object)
{
return ($object instanceof \SplFileInfo);
}
}
27 changes: 27 additions & 0 deletions src/Contracts/DecoderInterface.php
@@ -0,0 +1,27 @@
<?php
namespace Michaels\Manager\Contracts;

/**
* Contract for Decoders
* @package Michaels\Manager
*/

interface DecoderInterface
{
/**
* This is the method, which does the decoding work.
*
* @param $data
* @return array
*/
public function decode($data);

/**
* The data returned is the actual file extensions supported for the files to decode.
* For instance, if you want to decode Yaml files with the extensions ".yml" and ".yaml",
* then you want to set the return array to ['yaml', 'yml'].
*
* @return array
*/
public function getMimeType();
}
28 changes: 28 additions & 0 deletions src/Contracts/LoadsFilesInterface.php
@@ -0,0 +1,28 @@
<?php
namespace Michaels\Manager\Contracts;

/**
* API Methods for loading file data into the manager
*
* See src/Traits/LoadsFilesTrait.php for implementation example
*/

interface LoadsFilesInterface
{
/**
* This method adds load file functionality.
*
* @param array $files an array of SplFileInfo Objects
* @param $append boolean
* @return array
*/
public function loadFiles(array $files, $append = false);

/**
* Allows for the addition of a custom decoder to load custom files..
*
* @param DecoderInterface $decoder
* @return mixed
*/
public function addDecoder(DecoderInterface $decoder);
}

0 comments on commit 86a551f

Please sign in to comment.