├── .gitignore ├── .travis.yml ├── LICENSE ├── composer.json ├── phpunit.xml ├── readme.md ├── src └── Gestalt │ ├── Configuration.php │ ├── Loaders │ ├── DirectoryLoader.php │ ├── IniDirectoryLoader.php │ ├── JsonDirectoryLoader.php │ ├── LoaderInterface.php │ ├── PhpDirectoryLoader.php │ └── YamlDirectoryLoader.php │ └── Util │ ├── Observable.php │ └── ObserverInterface.php └── tests ├── ConfigurationTest.php ├── IniDirectoryLoaderTest.php ├── JsonDirectoryLoader.php ├── ObservableTest.php ├── PhpDirectoryLoaderTest.php ├── TestCase.php ├── YamlDirectoryLoaderTest.php └── config ├── bar.php ├── foo.php ├── foobar.ini ├── foobar.json └── foobar.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.lock 3 | VagrantFile 4 | .vagrant/ 5 | *.sublime-* 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.6 5 | - 7.0 6 | - hhvm 7 | 8 | sudo: required 9 | 10 | before_install: 11 | - if [[ $TRAVIS_PHP_VERSION == "5.6" ]]; then printf "\n" | pecl install yaml; fi 12 | - if [[ $TRAVIS_PHP_VERSION == "7.0" ]]; then printf "\n" | pecl install yaml-2.0.0; fi 13 | - if [[ $TRAVIS_PHP_VERSION == "hhvm" ]]; then echo "hhvm.enable_zend_compat = true" >> /etc/hhvm/php.ini; fi 14 | 15 | install: 16 | - travis_retry composer install --no-interaction --prefer-source 17 | 18 | script: vendor/bin/phpunit 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Sam Rapaport 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "samrap/gestalt", 3 | "description": "Gestalt is a simple, elegant PHP package for managing your framework's configuration values.", 4 | "keywords": ["boilerplate", "configuration", "wrapper", "php"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Sam Rapaport", 9 | "email": "rapaport.sam7@gmail.com" 10 | } 11 | ], 12 | "autoload": { 13 | "psr-4": { 14 | "Gestalt\\": "src/Gestalt" 15 | } 16 | }, 17 | "autoload-dev": { 18 | "classmap": [ 19 | "tests/TestCase.php" 20 | ] 21 | }, 22 | "require": { 23 | "php": ">=5.6" 24 | }, 25 | "require-dev": { 26 | "phpunit/phpunit": "^5.5", 27 | "mockery/mockery": "^0.9.5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Gestalt 2 | 3 | [![StyleCI](https://styleci.io/repos/67276253/shield?style=flat)](https://styleci.io/repos/67276253) 4 | [![Build Status](https://travis-ci.org/samrap/gestalt.svg?branch=master)](https://travis-ci.org/samrap/gestalt) 5 | [![Latest Stable Version](https://poser.pugx.org/samrap/gestalt/v/stable)](https://packagist.org/packages/samrap/gestalt) 6 | [![Total Downloads](https://poser.pugx.org/samrap/gestalt/downloads)](https://packagist.org/packages/samrap/gestalt) 7 | [![Latest Unstable Version](https://poser.pugx.org/samrap/gestalt/v/unstable)](https://packagist.org/packages/samrap/gestalt) 8 | 9 | > **ge·stalt (n):** _Something that is made of many parts and yet is somehow more than or different from the combination of its parts; broadly : the general quality or character of something._ 10 | 11 | Gestalt is a simple and elegant PHP package for managing your framework's configuration values. It is lightweight, flexible, framework agnostic, and has no dependencies other than PHP itself. 12 | 13 | ### Features 14 | - **Lightweight:** Gestalt is built to be lightweight. No dependencies, no bloat, just an object-oriented wrapper around your framework's configuration. 15 | - **Powerful:** Who said lightweight means powerless? Gestalt has a small footprint but packs a mean punch. Just take a look at its [Custom Loaders](https://github.com/samrap/gestalt-docs/blob/master/loaders.md) and [Observers](https://github.com/samrap/gestalt-docs/blob/master/observers.md) and you'll see for yourself. 16 | - **Flexible:** Developers like to do things _our_ way. Gestalt gives you the flexibility to integrate seamlessly with your application. 17 | - **Expressive syntax**: With its clean, collection-like syntax, code artisans will feel right at home. Messy developers will like it too! 18 | 19 | ### Examples 20 | 21 | The following are just a few of the features Gestalt has to offer. [Visit the docs](https://github.com/samrap/gestalt-docs) for more on installation, usage, and features. 22 | 23 | **Basic Usage** ([Learn More](https://github.com/samrap/gestalt-docs/blob/master/introduction.md)) 24 | 25 | ```php 26 | $config = new Configuration([ 27 | 'app' => [ 28 | 'debug' => true, 29 | 'version' => '1.0', 30 | ], 31 | ]); 32 | 33 | // Get values using dot notation or ArrayAccess. 34 | $config->get('app.debug'); 35 | $config['app']; 36 | 37 | // Add values using dot notation or ArrayAccess. 38 | $config->add('app.locale', 'en'); 39 | $config['mail'] = ['driver' => 'MailMonkey']; 40 | ``` 41 | 42 | **Custom Loading** ([Learn More](https://github.com/samrap/gestalt-docs/blob/master/loaders.md)) 43 | 44 | ```php 45 | $config = Configuration::load(new JsonFileLoader); 46 | 47 | $config->get('app.debug'); 48 | ``` 49 | 50 | **Observers** ([Learn More](https://github.com/samrap/gestalt-docs/blob/master/observers.md)) 51 | 52 | ```php 53 | $config = new Configuration($values); 54 | 55 | $config->attach(new StatefulObserver); 56 | 57 | // Notifies the StatefulObserver that the 58 | // Configuration has been updated. 59 | $config->set('app.debug', false); 60 | ``` 61 | 62 | Interested? [Check out the docs](https://github.com/samrap/gestalt-docs) to see all of the features in action! 63 | -------------------------------------------------------------------------------- /src/Gestalt/Configuration.php: -------------------------------------------------------------------------------- 1 | items = $this->getItemsAsArray($items); 35 | 36 | $this->original = $this->items; 37 | } 38 | 39 | /** 40 | * Create a new Configuration with the given loader. 41 | * 42 | * @param \Gestalt\Loaders\LoaderInterface|\Closure $loader 43 | * @return \Gestalt\Collection 44 | */ 45 | public static function load($loader) 46 | { 47 | if ($loader instanceof Closure) { 48 | return new static($loader()); 49 | } elseif ($loader instanceof LoaderInterface) { 50 | return new static($loader->load()); 51 | } 52 | } 53 | 54 | /** 55 | * Create a Configuration instance from a LoaderInterface's `load` method. 56 | * 57 | * @deprecated 1.0.0 Replaced with more flexible `load` method. 58 | * @param \Gestalt\Loaders\LoaderInterface $loader 59 | * @return \Gestalt\Configuration 60 | */ 61 | public static function fromLoader(LoaderInterface $loader) 62 | { 63 | // We will create a new instance using `self`, as we do not want child 64 | // classes creating new instances of themselves if this is called. 65 | return new self($loader->load()); 66 | } 67 | 68 | /** 69 | * Convert the given items into an array. 70 | * 71 | * @param mixed $items 72 | * @return array 73 | */ 74 | protected function getItemsAsArray($items) 75 | { 76 | if (is_array($items)) { 77 | return $items; 78 | } elseif ($items instanceof self) { 79 | return $items->all(); 80 | } elseif ($items instanceof Traversable) { 81 | return iterator_to_array($items); 82 | } 83 | 84 | return (array) $items; 85 | } 86 | 87 | /** 88 | * Get all of the configuration items. 89 | * 90 | * @return array 91 | */ 92 | public function all() 93 | { 94 | return $this->items; 95 | } 96 | 97 | /** 98 | * Get a configuration item. 99 | * 100 | * @param string $key 101 | * @param mixed $default 102 | * @return mixed 103 | */ 104 | public function get($key, $default = null) 105 | { 106 | if ($this->exists($key)) { 107 | return $this->items[$key]; 108 | } 109 | 110 | $result = $this->items; 111 | 112 | foreach (explode('.', $key) as $piece) { 113 | if (is_array($result) && array_key_exists($piece, $result)) { 114 | $result = $result[$piece]; 115 | } else { 116 | return $default; 117 | } 118 | } 119 | 120 | return $result; 121 | } 122 | 123 | /** 124 | * Determine if the specified item exists in the configuration. 125 | * 126 | * @param string $key 127 | * @return bool 128 | */ 129 | public function exists($key) 130 | { 131 | return array_key_exists($key, $this->items); 132 | } 133 | 134 | /** 135 | * Add an item to the configuration if it does not already exist. 136 | * 137 | * @param string $key 138 | * @param mixed $value 139 | * @return void 140 | */ 141 | public function add($key, $value) 142 | { 143 | $keys = explode('.', $key); 144 | $section = &$this->items; 145 | 146 | while (count($keys) > 1) { 147 | $key = array_shift($keys); 148 | 149 | if (! isset($section[$key])) { 150 | // If the key does not exist, we will set it to an empty array 151 | // and move into the next dimension. 152 | $section[$key] = []; 153 | } elseif (! is_array($section[$key])) { 154 | // If the item at this dimension is not an array, then we would 155 | // be overriding it if we continued any further. As the great 156 | // master programmer Yoda once said, exit we must. 157 | return; 158 | } 159 | 160 | $section = &$section[$key]; 161 | } 162 | 163 | $key = array_shift($keys); 164 | 165 | if (! array_key_exists($key, $section)) { 166 | $section[$key] = $value; 167 | 168 | $this->notify(); 169 | } 170 | } 171 | 172 | /** 173 | * Add or modify an item in the configuration. 174 | * 175 | * @param string $key 176 | * @param mixed $value 177 | * @return void 178 | */ 179 | public function set($key, $value) 180 | { 181 | $keys = explode('.', $key); 182 | $section = &$this->items; 183 | 184 | while (count($keys) > 1) { 185 | $key = array_shift($keys); 186 | 187 | if (! isset($section[$key]) || ! is_array($section[$key])) { 188 | // If the key does not exist, we will set it to an empty array 189 | // and move into the next dimension. 190 | $section[$key] = []; 191 | } 192 | 193 | $section = &$section[$key]; 194 | } 195 | 196 | $section[array_shift($keys)] = $value; 197 | 198 | $this->notify(); 199 | } 200 | 201 | /** 202 | * Remove an item from the configuration. 203 | * 204 | * @param string $key 205 | * @return void 206 | */ 207 | public function remove($key) 208 | { 209 | $keys = explode('.', $key); 210 | $section = &$this->items; 211 | 212 | while (count($keys) > 1) { 213 | $key = array_shift($keys); 214 | 215 | if (! isset($section[$key])) { 216 | return; 217 | } 218 | 219 | $section = &$section[$key]; 220 | } 221 | 222 | unset($section[array_shift($keys)]); 223 | 224 | $this->notify(); 225 | } 226 | 227 | /** 228 | * Reset the configuration items to the original values. 229 | * 230 | * @return \Gestalt\Collection 231 | */ 232 | public function reset() 233 | { 234 | $this->items = $this->original; 235 | 236 | return $this; 237 | } 238 | 239 | /** 240 | * Modify a chunk of the Configuration within the specified prefix. 241 | * 242 | * @param string $prefix 243 | * @param \Closure $callback 244 | * @return void 245 | */ 246 | public function prefix($prefix, $callback) 247 | { 248 | $partial = new self($this->get($prefix)); 249 | 250 | // We will pass the newly created "partial" Configuration object to the 251 | // callback so that it can be used within the given prefix. 252 | $callback($partial); 253 | 254 | // We want to make sure that any changes made to the prefixed object are 255 | // reflected in this object, so we will swap it with the partial. 256 | $this->set($prefix, $partial->all()); 257 | 258 | unset($partial); 259 | } 260 | 261 | /** 262 | * Add or modify an item in the configuration. 263 | * 264 | * @param string $offset 265 | * @param mixed $value 266 | * @return void 267 | */ 268 | public function offsetSet($offset, $value) 269 | { 270 | $this->set($offset, $value); 271 | } 272 | 273 | /** 274 | * Determine if the configuration item exists at the given offset. 275 | * 276 | * @param string $offset 277 | * @return bool 278 | */ 279 | public function offsetExists($offset) 280 | { 281 | return $this->exists($offset); 282 | } 283 | 284 | /** 285 | * Remove an item from the configuration. 286 | * 287 | * @param string $offset 288 | * @return void 289 | */ 290 | public function offsetUnset($offset) 291 | { 292 | $this->remove($offset); 293 | } 294 | 295 | /** 296 | * Get a configuration item. 297 | * 298 | * @param string $key 299 | * @return mixed 300 | */ 301 | public function offsetGet($offset) 302 | { 303 | return $this->get($offset); 304 | } 305 | } 306 | -------------------------------------------------------------------------------- /src/Gestalt/Loaders/DirectoryLoader.php: -------------------------------------------------------------------------------- 1 | directory = $directory; 31 | } 32 | 33 | /** 34 | * Define the method of translating the current file into a configuration. 35 | * 36 | * @param string $filePath 37 | * @return mixed 38 | */ 39 | abstract public function translateFile($filePath); 40 | 41 | /** 42 | * Load the configuration items and return them as an array. 43 | * 44 | * @return array 45 | */ 46 | public function load() 47 | { 48 | $items = []; 49 | $directory = new DirectoryIterator(realpath($this->directory)); 50 | 51 | foreach ($directory as $file) { 52 | if ($file->isFile() && $file->getExtension() == $this->extension) { 53 | $filename = $file->getFilename(); 54 | $config = substr($filename, 0, strrpos($filename, '.')); 55 | 56 | $items[$config] = $this->translateFile($file->getPathname()); 57 | } 58 | } 59 | 60 | return $items; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Gestalt/Loaders/IniDirectoryLoader.php: -------------------------------------------------------------------------------- 1 | observers[] = $observer; 23 | } 24 | 25 | /** 26 | * Notify the observers. 27 | * 28 | * @return void 29 | */ 30 | public function notify() 31 | { 32 | foreach ($this->observers as $observer) { 33 | $observer->update($this); 34 | } 35 | } 36 | 37 | /** 38 | * Detach an observer from the list of observers. 39 | * 40 | * @param \Gestalt\Util\ObserverInterface $observer 41 | * @return void 42 | */ 43 | public function detach(ObserverInterface $observer) 44 | { 45 | if (($key = array_search($observer, $this->observers, true)) !== false) { 46 | unset($this->observers[$key]); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Gestalt/Util/ObserverInterface.php: -------------------------------------------------------------------------------- 1 | true]); 10 | 11 | $this->assertTrue($c->get('debug')); 12 | } 13 | 14 | public function test_get_method_gets_item_with_dot_notation() 15 | { 16 | $c = new Configuration($this->getConfigurationItems()); 17 | 18 | $this->assertTrue($c->get('app.debug')); 19 | $this->assertEquals('1.0', $c->get('app.version')); 20 | $this->assertEquals('gestalt', $c->get('database.drivers.mysql.database')); 21 | } 22 | 23 | public function test_get_method_returns_default_value_if_item_isnt_present() 24 | { 25 | $c = new Configuration; 26 | 27 | $this->assertEquals(123, $c->get('foo', 123)); 28 | } 29 | 30 | public function test_all_method_gets_all_items() 31 | { 32 | $c = new Configuration($this->getConfigurationItems()); 33 | 34 | $this->assertEquals($this->getConfigurationItems(), $c->all()); 35 | } 36 | 37 | public function test_exists_method_verifies_existance() 38 | { 39 | $c = new Configuration($this->getConfigurationItems()); 40 | 41 | $this->assertTrue($c->exists('app')); 42 | } 43 | 44 | public function test_add_method_adds_new_item() 45 | { 46 | $c = new Configuration($this->getConfigurationItems()); 47 | $c->add('baz', 'bin'); 48 | 49 | $this->assertEquals('bin', $c->get('baz')); 50 | } 51 | 52 | public function test_add_method_adds_new_item_with_dot_notation() 53 | { 54 | $c = new Configuration($this->getConfigurationItems()); 55 | 56 | $c->add('app.foo', 123); 57 | $c->add('mail.driver', 'MailMonkey'); 58 | 59 | $this->assertEquals(123, $c->get('app.foo')); 60 | $this->assertEquals('MailMonkey', $c->get('mail.driver')); 61 | } 62 | 63 | public function test_add_method_ignores_existing_items() 64 | { 65 | $c = new Configuration(['foo' => 'bar']); 66 | $c->add('foo', 'bin'); 67 | $c->add('foo.bin', 123); 68 | 69 | $this->assertEquals('bar', $c->get('foo')); 70 | $this->assertNull($c->get('foo.bin')); 71 | } 72 | 73 | public function test_set_method_sets_item() 74 | { 75 | $c = new Configuration($this->getConfigurationItems()); 76 | 77 | // The set method should allow overriding. 78 | $c->set('app', null); 79 | // The set method should also allow basic add functionality. 80 | $c->set('baz', 'bin'); 81 | 82 | $this->assertNull($c->get('app')); 83 | $this->assertEquals('bin', $c->get('baz')); 84 | } 85 | 86 | public function test_set_method_sets_new_item_with_dot_notation() 87 | { 88 | $c = new Configuration($this->getConfigurationItems()); 89 | 90 | $c->set('app.foo', 123); 91 | $c->set('app.debug', false); 92 | $c->set('mail.driver', 'MailMonkey'); 93 | 94 | $this->assertArrayHasKey('version', $c->get('app')); 95 | $this->assertEquals('123', $c->get('app.foo')); 96 | $this->assertFalse($c->get('app.debug')); 97 | $this->assertEquals('MailMonkey', $c->get('mail.driver')); 98 | } 99 | 100 | public function test_remove_method_removes_item() 101 | { 102 | $c = new Configuration($this->getConfigurationItems()); 103 | $c->remove('app'); 104 | 105 | $this->assertNull($c->get('app')); 106 | } 107 | 108 | public function test_remote_method_removes_item_with_dot_notation() 109 | { 110 | $c = new Configuration($this->getConfigurationItems()); 111 | $c->remove('app.version'); 112 | 113 | $this->assertNull($c->get('app.version')); 114 | } 115 | 116 | public function test_load_method_loads_configuration() 117 | { 118 | $loader = Mockery::mock('\Gestalt\Loaders\LoaderInterface'); 119 | $loader->shouldReceive('load')->andReturn($this->getConfigurationItems()); 120 | $c = Configuration::fromLoader($loader); 121 | 122 | $this->assertEquals('1.0', $c->get('app.version')); 123 | } 124 | 125 | public function test_for_ArrayAccess_implementation() 126 | { 127 | $c = new Configuration($this->getConfigurationItems()); 128 | 129 | $this->assertArrayHasKey('debug', $c['app']); 130 | $this->assertTrue($c['app.debug']); 131 | 132 | $c['app.debug'] = false; 133 | $this->assertEquals(false, $c['app.debug']); 134 | 135 | unset($c['app.debug']); 136 | $this->assertNull($c['app.debug']); 137 | } 138 | 139 | public function test_instantiation_from_different_types() 140 | { 141 | $items = ['foo' => 'bar']; 142 | $a = new Configuration($items); 143 | $b = new Configuration(new Configuration($items)); 144 | $c = new Configuration(new ArrayIterator($items)); 145 | 146 | $this->assertInternalType('array', $a->all()); 147 | $this->assertInternalType('array', $b->all()); 148 | $this->assertInternalType('array', $c->all()); 149 | $this->assertEquals('bar', $a->get('foo')); 150 | $this->assertEquals('bar', $b->get('foo')); 151 | $this->assertEquals('bar', $c->get('foo')); 152 | } 153 | 154 | public function test_reset_method_resets_changes() 155 | { 156 | $items = $this->getConfigurationItems(); 157 | $a = new Configuration($items); 158 | 159 | $a->set('app', null); 160 | $this->assertNull($a->get('app')); 161 | 162 | $a->reset(); 163 | $this->assertEquals($items, $a->all()); 164 | } 165 | 166 | public function test_configuration_is_observable() 167 | { 168 | $this->assertInstanceOf( 169 | 'Gestalt\Util\Observable', 170 | new Configuration($this->getConfigurationItems()) 171 | ); 172 | } 173 | 174 | public function test_configuration_notifies_observers_on_add() 175 | { 176 | $c = new Configuration($this->getConfigurationItems()); 177 | 178 | $c->attach($this->getObserver()); 179 | $c->attach($this->getObserver()); 180 | 181 | // If the mocked observers aren't notified, an error will be thrown. 182 | $c->add('foo', 123); 183 | } 184 | 185 | public function test_configuration_notifies_observers_on_set() 186 | { 187 | $c = new Configuration($this->getConfigurationItems()); 188 | 189 | $c->attach($this->getObserver()); 190 | $c->attach($this->getObserver()); 191 | 192 | // If the mocked observers aren't notified, an error will be thrown. 193 | $c->set('foo', 123); 194 | } 195 | 196 | public function test_configuration_notifies_observers_on_remove() 197 | { 198 | $c = new Configuration($this->getConfigurationItems()); 199 | 200 | $c->attach($this->getObserver()); 201 | $c->attach($this->getObserver()); 202 | 203 | // If the mocked observers aren't notified, an error will be thrown. 204 | $c->remove('app.version'); 205 | } 206 | 207 | public function test_configuration_does_not_notify_observers_on_reset() 208 | { 209 | $c = new Configuration($this->getConfigurationItems()); 210 | 211 | $c->attach($this->getObserver(1)); 212 | $c->set('foo', 123); 213 | 214 | // Since we told the mocked observer it should only be updated once, 215 | // if the reset method notifies observers, we will get an error. 216 | $c->reset(); 217 | } 218 | 219 | public function test_create_method_creates_configuration_from_closure_loader() 220 | { 221 | $values = $this->getConfigurationItems(); 222 | $c = Configuration::load(function () use ($values) { 223 | return $values; 224 | }); 225 | 226 | $this->assertEquals('1.0', $c->get('app.version')); 227 | } 228 | 229 | public function test_create_method_creates_configuration_from_class_loader() 230 | { 231 | $loader = Mockery::mock('\Gestalt\Loaders\LoaderInterface'); 232 | $loader->shouldReceive('load')->andReturn($this->getConfigurationItems()); 233 | $c = Configuration::load($loader); 234 | 235 | $this->assertEquals('1.0', $c->get('app.version')); 236 | } 237 | 238 | public function test_prefix_method_gets_prefixed_configuration() 239 | { 240 | $testval = null; 241 | 242 | $c = new Configuration($this->getConfigurationItems()); 243 | $c->prefix('database.drivers.mysql', function ($partial) use (&$testval) { 244 | $testval = $partial->get('database'); 245 | }); 246 | 247 | $this->assertEquals($c->get('database.drivers.mysql.database'), $testval); 248 | } 249 | 250 | public function test_prefix_method_modifies_prefixed_configuration() 251 | { 252 | $c = new Configuration($this->getConfigurationItems()); 253 | $c->prefix('database.drivers.mysql', function ($partial) { 254 | $partial->set('username', 'bonnie'); 255 | $partial->set('password', 'martini'); 256 | $partial->add('salt', 'pepper'); 257 | }); 258 | 259 | $this->assertEquals([ 260 | 'database' => 'gestalt', 261 | 'username' => 'bonnie', 262 | 'password' => 'martini', 263 | 'salt' => 'pepper', 264 | ], $c->get('database.drivers.mysql')); 265 | 266 | $this->assertTrue($c->get('app.debug')); 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /tests/IniDirectoryLoaderTest.php: -------------------------------------------------------------------------------- 1 | load(); 11 | 12 | $this->assertArrayHasKey('foobar', $loaded); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/JsonDirectoryLoader.php: -------------------------------------------------------------------------------- 1 | load(); 11 | 12 | $this->assertArrayHasKey('baz', $loaded['foobar']); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/ObservableTest.php: -------------------------------------------------------------------------------- 1 | observable = new Observable; 20 | } 21 | 22 | public function test_observable_attaches_observer() 23 | { 24 | $this->observable->attach($this->getObserver()); 25 | $this->observable->notify(); 26 | } 27 | 28 | public function test_observable_detaches_observer() 29 | { 30 | // Add an observer that expects to only be updated once. This will throw 31 | // an error if it is updated multiple times. 32 | $observer = $this->getObserver(1); 33 | 34 | $this->observable->attach($observer); 35 | $this->observable->notify(); 36 | $this->observable->detach($observer); 37 | $this->observable->notify(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/PhpDirectoryLoaderTest.php: -------------------------------------------------------------------------------- 1 | load(); 11 | 12 | $this->assertArrayHasKey('foo', $loaded); 13 | $this->assertArrayHasKey('bar', $loaded); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'version' => '1.0', 15 | 'debug' => true, 16 | 'locale' => 'en', 17 | ], 18 | 'database' => [ 19 | 'default' => 'mysql', 20 | 'drivers' => [ 21 | 'mysql' => [ 22 | 'database' => 'gestalt', 23 | 'username' => 'sam', 24 | 'password' => 'angostura', 25 | ], 26 | 'sqlite' => [ 27 | 'database' => 'gestalt', 28 | ], 29 | ], 30 | ], 31 | ]; 32 | 33 | /** 34 | * Get the test configuration items. 35 | * 36 | * @return array 37 | */ 38 | protected function getConfigurationItems() 39 | { 40 | return $this->configurationItems; 41 | } 42 | 43 | /** 44 | * Get a mocked \Gestalt\Util\ObserverInterface implementation. 45 | * 46 | * @param int $maxUpdates 47 | * @param int $minUpdates 48 | * @return \Mockery 49 | */ 50 | protected function getObserver($maxUpdates = 0, $minUpdates = 1) 51 | { 52 | $observer = Mockery::mock('Gestalt\Util\ObserverInterface'); 53 | 54 | if ($maxUpdates > 0) { 55 | $observer->shouldReceive('update') 56 | ->atLeast() 57 | ->times($minUpdates) 58 | ->atMost($maxUpdates) 59 | ->times($maxUpdates); 60 | } else { 61 | $observer->shouldReceive('update')->atLeast()->times($minUpdates); 62 | } 63 | 64 | return $observer; 65 | } 66 | 67 | /** 68 | * Return test suite to its original state. 69 | * 70 | * @return void 71 | */ 72 | public function tearDown() 73 | { 74 | Mockery::close(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests/YamlDirectoryLoaderTest.php: -------------------------------------------------------------------------------- 1 | load(); 11 | 12 | $this->assertArrayHasKey('foobar', $loaded); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/config/bar.php: -------------------------------------------------------------------------------- 1 | 456]; 6 | -------------------------------------------------------------------------------- /tests/config/foo.php: -------------------------------------------------------------------------------- 1 | 123]; 6 | -------------------------------------------------------------------------------- /tests/config/foobar.ini: -------------------------------------------------------------------------------- 1 | [foo] 2 | bar=foobar 3 | 4 | [bar] 5 | foo=barfoo 6 | -------------------------------------------------------------------------------- /tests/config/foobar.json: -------------------------------------------------------------------------------- 1 | { 2 | "baz": true 3 | } 4 | -------------------------------------------------------------------------------- /tests/config/foobar.yaml: -------------------------------------------------------------------------------- 1 | foobar: true 2 | --------------------------------------------------------------------------------