├── .gitignore ├── .scrutinizer.yml ├── .travis.yml ├── AutoTreeTrait.php ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── phpunit.xml.dist └── tests ├── .gitignore ├── AlMpTest.php ├── AlNiTest.php ├── AlNsTest.php ├── ArrayDataSet.php ├── AutoTreeTraitTestCase.php ├── BaseTestCase.php ├── README.md ├── bootstrap.php ├── data ├── config.php ├── data-ni.php └── data.php ├── migrations └── TestMigration.php └── models ├── NodeAlMp.php ├── NodeAlNi.php ├── NodeAlNs.php └── NodeQuery.php /.gitignore: -------------------------------------------------------------------------------- 1 | # phpstorm project files 2 | .idea 3 | 4 | # windows thumbnail cache 5 | Thumbs.db 6 | 7 | # composer vendor dir 8 | /vendor 9 | 10 | # composer itself is not needed 11 | composer.phar 12 | 13 | # Mac DS_Store Files 14 | .DS_Store 15 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | tools: 2 | external_code_coverage: 3 | timeout: 2100 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.4 5 | - 5.5 6 | - 5.6 7 | - 7.0 8 | - 7.1 9 | - 7.2 10 | - hhvm 11 | 12 | sudo: false 13 | 14 | install: 15 | - composer self-update 16 | - composer update --prefer-dist --no-interaction 17 | 18 | before_script: 19 | - mysql --version 20 | - psql --version 21 | - mysql -e 'create database test;' 22 | - psql -U postgres -c 'CREATE DATABASE test;'; 23 | - | 24 | if [ $TRAVIS_PHP_VERSION = '7.1' ]; then 25 | PHPUNIT_FLAGS="--coverage-clover=coverage.clover" 26 | fi 27 | 28 | script: 29 | - vendor/bin/phpunit $PHPUNIT_FLAGS 30 | 31 | after_script: 32 | - | 33 | if [ $TRAVIS_PHP_VERSION = '7.1' ]; then 34 | wget https://scrutinizer-ci.com/ocular.phar 35 | php ocular.phar code-coverage:upload --format=php-clover coverage.clover 36 | fi 37 | -------------------------------------------------------------------------------- /AutoTreeTrait.php: -------------------------------------------------------------------------------- 1 | 'al', 24 | 'paulzi\adjacencylist\AdjacencyListBehavior' => 'al', 25 | 'paulzi\nestedSets\NestedSetsBehavior' => 'ns', 26 | 'paulzi\nestedsets\NestedSetsBehavior' => 'ns', 27 | 'paulzi\nestedIntervals\NestedIntervalsBehavior' => 'ni', 28 | 'paulzi\nestedintervals\NestedIntervalsBehavior' => 'ni', 29 | 'paulzi\materializedPath\MaterializedPathBehavior' => 'mp', 30 | 'paulzi\materializedpath\MaterializedPathBehavior' => 'mp', 31 | ]; 32 | } 33 | 34 | /** 35 | * 36 | */ 37 | private function autoTreeInit() 38 | { 39 | /** @var \yii\base\Component|self $this */ 40 | $aliases = $this->autoTreeAliases(); 41 | foreach ($this->getBehaviors() as $behavior) { 42 | $className = $behavior::className(); 43 | if (isset($aliases[$className]) && !isset($this->_autoTreeMap[$aliases[$className]])) { 44 | $this->_autoTreeMap[$aliases[$className]] = $behavior; 45 | } 46 | } 47 | } 48 | 49 | /** 50 | * @param string $method 51 | * @param array $list 52 | * @param array $arguments 53 | * @param bool $firstOnly 54 | * @return mixed 55 | */ 56 | private function autoTreeCall($method, $list, $arguments = [], $firstOnly = true) 57 | { 58 | if ($this->_autoTreeMap === null) { 59 | $this->autoTreeInit(); 60 | } 61 | 62 | $result = null; 63 | $founded = false; 64 | foreach ($list as $alias) { 65 | if (isset($this->_autoTreeMap[$alias])) { 66 | $behavior = $this->_autoTreeMap[$alias]; 67 | if (method_exists($behavior, $method)) { 68 | if ($this->_autoTreeReturnBehavior) { 69 | return $behavior; 70 | } 71 | $founded = true; 72 | $result = call_user_func_array([$behavior, $method], $arguments); 73 | if ($firstOnly) { 74 | return $result; 75 | } 76 | } 77 | } 78 | } 79 | 80 | if (!$founded) { 81 | throw new InvalidCallException("Method '{$method}' not founded"); 82 | } 83 | 84 | return $result; 85 | } 86 | 87 | /** 88 | * @inheritdoc 89 | */ 90 | public function __get($name) 91 | { 92 | /** @var \yii\db\BaseActiveRecord|self $this */ 93 | // replace getParents() by getParentsOrdered() if behavior not support ordered query 94 | if ($name === 'parents') { 95 | $this->_autoTreeReturnBehavior = true; 96 | $behavior = $this->getParents(); 97 | $this->_autoTreeReturnBehavior = false; 98 | if (method_exists($behavior, 'getParentsOrdered')) { 99 | $this->populateRelation($name, $behavior->getParentsOrdered()); 100 | } 101 | } 102 | if ($name === 'descendants') { 103 | $this->_autoTreeReturnBehavior = true; 104 | $behavior = $this->getDescendants(); 105 | $this->_autoTreeReturnBehavior = false; 106 | if (method_exists($behavior, 'getDescendantsOrdered')) { 107 | $this->populateRelation($name, $behavior->getDescendantsOrdered()); 108 | } 109 | } 110 | return parent::__get($name); 111 | } 112 | 113 | /** 114 | * @param int|null $depth 115 | * @return \yii\db\ActiveQuery 116 | */ 117 | public function getParents($depth = null) 118 | { 119 | return $this->autoTreeCall('getParents', ['mp', 'ns', 'ni', 'al'], [$depth]); 120 | } 121 | 122 | /** 123 | * @return \yii\db\ActiveQuery 124 | */ 125 | public function getParent() 126 | { 127 | return $this->autoTreeCall('getParent', ['al', 'mp', 'ns', 'ni']); 128 | } 129 | 130 | /** 131 | * @return \yii\db\ActiveQuery 132 | */ 133 | public function getRoot() 134 | { 135 | return $this->autoTreeCall('getRoot', ['mp', 'ns', 'ni', 'al']); 136 | } 137 | 138 | /** 139 | * @param int|null $depth 140 | * @param bool $andSelf 141 | * @return \yii\db\ActiveQuery 142 | */ 143 | public function getDescendants($depth = null, $andSelf = false) 144 | { 145 | return $this->autoTreeCall('getDescendants', ['ns', 'ni', 'mp', 'al'], [$depth, $andSelf]); 146 | } 147 | 148 | /** 149 | * @return \yii\db\ActiveQuery 150 | */ 151 | public function getChildren() 152 | { 153 | return $this->autoTreeCall('getChildren', ['al', 'ns', 'ni', 'mp']); 154 | } 155 | 156 | /** 157 | * @param int|null $depth 158 | * @return \yii\db\ActiveQuery 159 | */ 160 | public function getLeaves($depth = null) 161 | { 162 | return $this->autoTreeCall('getLeaves', ['ns', 'al', 'mp', 'ni'], [$depth]); 163 | } 164 | 165 | /** 166 | * @return \yii\db\ActiveQuery 167 | * @throws \yii\base\NotSupportedException 168 | */ 169 | public function getPrev() 170 | { 171 | return $this->autoTreeCall('getPrev', ['ns', 'mp', 'ni', 'al']); 172 | } 173 | 174 | /** 175 | * @return \yii\db\ActiveQuery 176 | * @throws \yii\base\NotSupportedException 177 | */ 178 | public function getNext() 179 | { 180 | return $this->autoTreeCall('getNext', ['ns', 'mp', 'ni', 'al']); 181 | } 182 | 183 | /** 184 | * Populate children relations for self and all descendants 185 | * @param int $depth = null 186 | * @param string|array $with = null 187 | * @return self 188 | */ 189 | public function populateTree($depth = null, $with = null) 190 | { 191 | return $this->autoTreeCall('populateTree', ['ns', 'ni', 'mp', 'al'], [$depth, $with]); 192 | } 193 | 194 | /** 195 | * @return bool 196 | */ 197 | public function isRoot() 198 | { 199 | return $this->autoTreeCall('isRoot', ['al', 'ns', 'ni', 'mp']); 200 | } 201 | 202 | /** 203 | * @param \yii\db\BaseActiveRecord $node 204 | * @return bool 205 | */ 206 | public function isChildOf($node) 207 | { 208 | return $this->autoTreeCall('isChildOf', ['ns', 'ni', 'mp', 'al'], [$node]); 209 | } 210 | 211 | /** 212 | * @return bool 213 | */ 214 | public function isLeaf() 215 | { 216 | return $this->autoTreeCall('isLeaf', ['ns', 'al', 'ni', 'mp']); 217 | } 218 | 219 | /** 220 | * @return $this 221 | */ 222 | public function makeRoot() 223 | { 224 | return $this->autoTreeCall('makeRoot', ['al', 'ns', 'ni', 'mp'], [], false); 225 | } 226 | 227 | /** 228 | * @param \yii\db\BaseActiveRecord $node 229 | * @return $this 230 | */ 231 | public function prependTo($node) 232 | { 233 | return $this->autoTreeCall('prependTo', ['al', 'ns', 'ni', 'mp'], [$node], false); 234 | } 235 | 236 | /** 237 | * @param \yii\db\BaseActiveRecord $node 238 | * @return $this 239 | */ 240 | public function appendTo($node) 241 | { 242 | return $this->autoTreeCall('appendTo', ['al', 'ns', 'ni', 'mp'], [$node], false); 243 | } 244 | 245 | /** 246 | * @param \yii\db\BaseActiveRecord $node 247 | * @return $this 248 | */ 249 | public function insertBefore($node) 250 | { 251 | return $this->autoTreeCall('insertBefore', ['al', 'ns', 'ni', 'mp'], [$node], false); 252 | } 253 | 254 | /** 255 | * @param \yii\db\BaseActiveRecord $node 256 | * @return $this 257 | */ 258 | public function insertAfter($node) 259 | { 260 | return $this->autoTreeCall('insertAfter', ['al', 'ns', 'ni', 'mp'], [$node], false); 261 | } 262 | 263 | /** 264 | * @return bool|int 265 | * @throws \Exception 266 | * @throws \yii\db\Exception 267 | */ 268 | public function deleteWithChildren() 269 | { 270 | /** @var \yii\db\BaseActiveRecord|self $this */ 271 | $this->autoTreeCall('preDeleteWithChildren', ['ns', 'ni', 'mp', 'al'], [], false); 272 | return $this->autoTreeCall('deleteWithChildren', ['ns', 'ni', 'mp', 'al']); 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 PaulZi (pavel.zimakoff@gmail.com) 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yii2 Auto Tree Trait 2 | 3 | Allow apply multiple tree behavior for ActiveRecord in Yii2. 4 | 5 | For selecting methods used by the most rapid behavior. For modifying methods - call all attached behaviors. 6 | 7 | If you are using the adjacency list for a get list of the parents or the descendants as relation will be used getParentsOrdered() or getDescendantsOrdered(). 8 | 9 | [![Packagist Version](https://img.shields.io/packagist/v/paulzi/yii2-auto-tree.svg)](https://packagist.org/packages/paulzi/yii2-auto-tree) 10 | [![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/paulzi/yii2-auto-tree/master.svg)](https://scrutinizer-ci.com/g/paulzi/yii2-auto-tree/?branch=master) 11 | [![Build Status](https://img.shields.io/travis/paulzi/yii2-auto-tree/master.svg)](https://travis-ci.org/paulzi/yii2-auto-tree) 12 | [![Total Downloads](https://img.shields.io/packagist/dt/paulzi/yii2-auto-tree.svg)](https://packagist.org/packages/paulzi/yii2-auto-tree) 13 | 14 | ## Install 15 | 16 | Install via Composer: 17 | 18 | ```bash 19 | composer require paulzi/yii2-auto-tree 20 | ``` 21 | 22 | or add 23 | 24 | ```bash 25 | "paulzi/yii2-auto-tree" : "^1.1" 26 | ``` 27 | 28 | to the `require` section of your `composer.json` file. 29 | 30 | ## Configuring 31 | 32 | Install and configure one or more behaviors: 33 | 34 | - [Adjacency List](https://github.com/paulzi/yii2-adjacency-list) 35 | - [Nested Sets](https://github.com/paulzi/yii2-nested-sets) 36 | - [Nested Intervals](https://github.com/paulzi/yii2-nested-intervals) 37 | - [Materialized Path](https://github.com/paulzi/yii2-materialized-path) 38 | 39 | And use AutoTreeTrait in model. 40 | 41 | ```php 42 | use paulzi\adjacencylist\AdjacencyListBehavior; 43 | use paulzi\nestedsets\NestedSetsBehavior; 44 | use paulzi\autotree\AutoTreeTrait; 45 | 46 | class Sample extends \yii\db\ActiveRecord 47 | { 48 | use AutoTreeTrait; 49 | 50 | public function behaviors() { 51 | return [ 52 | ['class' => AdjacencyListBehavior::className()], 53 | ['class' => NestedSetsBehavior::className()], 54 | ]; 55 | } 56 | } 57 | ``` 58 | 59 | ## Extending 60 | 61 | If you want to change the order call behavior, override the appropriate methods: 62 | 63 | ```php 64 | use paulzi\autotree\AutoTreeTrait; 65 | 66 | class Sample extends \yii\db\ActiveRecord 67 | { 68 | use AutoTreeTrait; 69 | 70 | /** 71 | * @param int|null $depth 72 | * @return \yii\db\ActiveQuery 73 | */ 74 | public function getParents($depth = null) 75 | { 76 | return $this->autoTreeCall('getParents', ['al', 'mp', 'ns', 'ni'], [$depth]); 77 | } 78 | } 79 | ``` 80 | 81 | If you want to change the list of classes of behaviors: 82 | 83 | ```php 84 | use paulzi\autotree\AutoTreeTrait; 85 | 86 | class Sample extends \yii\db\ActiveRecord 87 | { 88 | use AutoTreeTrait; 89 | 90 | /** 91 | * @return array 92 | */ 93 | private static function autoTreeAliases() 94 | { 95 | return [ 96 | 'example\adjacencylist\AdjacencyListBehavior' => 'al', 97 | 'example\nestedsets\NestedSetsBehavior' => 'ns', 98 | 'example\nestedintervals\NestedIntervalsBehavior' => 'ni', 99 | 'example\materializedpath\MaterializedPathBehavior' => 'mp', 100 | ]; 101 | } 102 | } 103 | ``` 104 | 105 | ## Behaviors speed comparison 106 | ``` 107 | Name DB Queries DB Time Time Mem 108 | 109 | Test 1. Insert. Filling (3 level by 12 child) 110 | Adjacency List 5811 1,567 ms 9,591 ms 71.3 MB 111 | Nested Sets 7697 6,672 ms 25,019 ms 105.9 MB 112 | Nested Intervals amount=24 5813 1,765 ms 10,442 ms 78.7 MB 113 | Nested Intervals amount=12 noPrepend noIns. 5813 1,750 ms 10,223 ms 78.7 MB 114 | Materialized Path (identity pr. key mode) 7696 3,169 ms 13,726 ms 92.5 MB 115 | Materialized Path (attribute mode) 5811 1,690 ms 9,504 ms 71.6 MB 116 | 117 | Test 2. Insert. Filling (6 level by 3 child) 118 | Adjacency List 3642 982 ms 5,812 ms 44.5 MB 119 | Nested Sets 4736 5,447 ms 17,859 ms 65.0 MB 120 | Nested Intervals amount=10 3644 1,275 ms 5,976 ms 48.9 MB 121 | Nested Intervals amount=3 noPrepend noIns. 3644 1,271 ms 5,993 ms 48.9 MB 122 | Materialized Path (identity pr. key mode) 4735 1,316 ms 6,920 ms 57.3 MB 123 | Materialized Path (attribute mode) 3642 1,129 ms 5,507 ms 44.6 MB 124 | 125 | Test 3. Insert in begin <4% (20 in 19657 nodes) 126 | Adjacency List 100 36 ms 190 ms 4.6 MB 127 | PaulZi 100 15,768 ms 16,712 ms 4.7 MB 128 | Nested Intervals 82 21 ms 150 ms 4.7 MB 129 | Materialized Path (identity pr. key mode) 120 98 ms 355 ms 4.8 MB 130 | Materialized Path (attribute mode) 100 74 ms 334 ms 4.6 MB 131 | 132 | Test 4. Insert in middle >46% <50% (20 in 19657 nodes) 133 | Adjacency List 100 24 ms 150 ms 4.6 MB 134 | Nested Sets 100 8,212 ms 8,799 ms 4.7 MB 135 | Nested Intervals 82 269 ms 593 ms 4.7 MB 136 | Materialized Path (identity pr. key mode) 120 35 ms 196 ms 4.9 MB 137 | Materialized Path (attribute mode) 100 287 ms 494 ms 4.6 MB 138 | 139 | Test 5. Insert in end >96% (20 in 19657 nodes) 140 | Adjacency List 100 31 ms 214 ms 4.5 MB 141 | Nested Sets 100 487 ms 899 ms 4.7 MB 142 | Nested Intervals 83 46 ms 187 ms 4.7 MB 143 | Materialized Path (identity pr. key mode) 120 34 ms 229 ms 4.8 MB 144 | Materialized Path (attribute mode) 100 470 ms 718 ms 4.6 MB 145 | 146 | Test 6. Delete from begin <4% (20 in 19657 nodes) 147 | Adjacency List parentJoin=0 childrenJoin=0 60 169 ms 257 ms 3.8 MB 148 | Adjacency List parentJoin=3 childrenJoin=3 60 87 ms 162 ms 3.8 MB 149 | Nested Sets 100 16,480 ms 16,902 ms 4.7 MB 150 | Nested Intervals 60 164 ms 250 ms 4.2 MB 151 | Materialized Path (identity pr. key mode) 60 87 ms 201 ms 4.0 MB 152 | Materialized Path (attribute mode) 60 122 ms 219 ms 4.0 MB 153 | 154 | Test 7. Insert. Random append (5 levels, 1000 nodes) 155 | Adjacency List 4001 1,062 ms 5,976 ms 46.1 MB 156 | Nested Sets 5003 5,428 ms 17,334 ms 64.8 MB 157 | Nested Intervals amount=10 8497 23,301 ms 41,060 ms 120.7 MB 158 | Nested Intervals x64 amount=10 7092 11,330 ms 23,618 ms 97.5 MB 159 | Nested Intervals amount=200,25 noPrep noIns 4009 1,431 ms 6,490 ms 50.2 MB 160 | Nested Intervals x64 a=250,30 noPrep noIns 4003 1,421 ms 6,615 ms 50.0 MB 161 | Materialized Path (identity pr. key mode) 5003 1,621 ms 8,184 ms 57.8 MB 162 | Materialized Path (attribute mode) 4002 1,269 ms 6,169 ms 46.2 MB 163 | 164 | Test 8. Insert. Random operation (5 levels, 1000 nodes) 165 | Adjacency List 4383 1,330 ms 6,147 ms 53.0 MB 166 | Nested Sets 5003 9,577 ms 24,334 ms 64.8 MB 167 | Nested Intervals amount=10 7733 8,123 ms 24,031 ms 107.2 MB 168 | Nested Intervals x64 default amount=10 5663 3,761 ms 14,084 ms 75.6 MB 169 | Nested Intervals amount=200,25 4175 1,548 ms 7,223 ms 52.8 MB 170 | Nested Intervals x64 a=250,30 reserve=2 4003 1,541 ms 6,753 ms 50.0 MB 171 | Materialized Path (identity pr. key mode) 5392 3,211 ms 11,771 ms 65.0 MB 172 | Materialized Path (attribute mode) 4377 2,902 ms 10,132 ms 53.2 MB 173 | 174 | Test 9. Move random in begin <4% (20 in 19657 nodes) 175 | Adjacency List 112 39 ms 261 ms 4.5 MB 176 | Nested Sets 140 218 ms 566 ms 5.5 MB 177 | Nested Intervals 160 180 ms 573 ms 6.0 MB 178 | Materialized Path (identity pr. key mode) 128 38 ms 307 ms 4.9 MB 179 | Materialized Path (attribute mode) 128 159 ms 495 ms 4.9 MB 180 | 181 | Test 10. Move random from end to begin <4% >96% (20 of 19657 nodes) 182 | Nested Sets 140 16,991 ms 17,845 ms 5.5 MB 183 | Nested Intervals 160 16,972 ms 17,854 ms 6.0 MB 184 | Materialized Path (identity pr. key mode) 132 49 ms 319 ms 4.9 MB 185 | Materialized Path (attribute mode) 132 205 ms 502 ms 4.9 MB 186 | Adjacency List 112 33 ms 217 ms 4.5 MB 187 | 188 | Test 11. Select all nodes (19657 nodes) 189 | Adjacency List 1 33 ms 890 ms 179.1 MB 190 | Nested Sets 1 40 ms 1,208 ms 215.2 MB 191 | Nested Intervals 1 42 ms 1,247 ms 225.3 MB 192 | Materialized Path (identity pr. key mode) 1 46 ms 1,240 ms 209.0 MB 193 | Materialized Path (attribute mode) 1 44 ms 1,106 ms 209.0 MB 194 | 195 | Test 12. Select children and descendants (for 819 nodes in middle of 19657 nodes) 196 | Adjacency List parentJoin=0 childrenJoin=0 2562 720 ms 1,969 ms 36.9 MB 197 | Adjacency List parentJoin=3 childrenJoin=3 2461 704 ms 1,966 ms 35.3 MB 198 | Nested Sets 1641 522 ms 1,585 ms 25.0 MB 199 | Nested Intervals 1641 579 ms 1,657 ms 25.0 MB 200 | Materialized Path (identity pr. key mode) 1641 569 ms 1,626 ms 23.4 MB 201 | Materialized Path (attribute mode) 1641 793 ms 6,552 ms 44.7 MB 202 | 203 | Test 13. Select parents (for 819 nodes in middle of 19657 nodes) 204 | Adjacency List parentJoin=0 childrenJoin=0 3180 948 ms 2,304 ms 51.2 MB 205 | Adjacency List parentJoin=3 childrenJoin=3 1641 486 ms 1,495 ms 30.8 MB 206 | Nested Sets 821 3,238 ms 3,979 ms 20.7 MB 207 | Nested Intervals 821 3,292 ms 4,147 ms 22.0 MB 208 | Materialized Path (identity pr. key mode) 821 292 ms 902 ms 21.2 MB 209 | Materialized Path (attribute mode) 821 582 ms 4,574 ms 24.7 MB 210 | 211 | Test 14. Select next/prev (for 819 nodes in middle of 19657 nodes) 212 | Adjacency List parentJoin=0 childrenJoin=0 1641 535 ms 1,442 ms 23.7 MB 213 | Adjacency List parentJoin=3 childrenJoin=3 1641 508 ms 1,421 ms 23.6 MB 214 | Nested Sets 1641 513 ms 1,428 ms 24.5 MB 215 | Nested Intervals 1641 19,681 ms 21,326 ms 27.5 MB 216 | Materialized Path (identity pr. key mode) 1641 730 ms 1,695 ms 24.3 MB 217 | Materialized Path (attribute mode) 1641 1,892 ms 2,964 ms 24.3 MB 218 | 219 | Test 15. Select leaves (for 819 nodes in middle of 19657 nodes) 220 | Adjacency List parentJoin=0 childrenJoin=0 1833 568 ms 1,743 ms 32.6 MB 221 | Adjacency List parentJoin=3 childrenJoin=3 1732 556 ms 1,891 ms 31.3 MB 222 | Nested Sets 821 305 ms 908 ms 18.4 MB 223 | Nested Intervals 821 10,450 ms 11,166 ms 18.8 MB 224 | Materialized Path (identity pr. key mode) 821 7,968 ms 8,434 ms 18.5 MB 225 | Materialized Path (attribute mode) 821 14,349 ms 19,105 ms 21.3 MB 226 | ``` -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "paulzi/yii2-auto-tree", 3 | "description": "Allow apply multiple tree behavior for ActiveRecord in Yii2", 4 | "keywords": ["yii2", "auto tree", "adjacency list", "nested sets", "nested intervals", "materialized path"], 5 | "type": "yii2-extension", 6 | "license": "MIT", 7 | "support": { 8 | "issues": "https://github.com/paulzi/yii2-auto-tree/issues?state=open", 9 | "source": "https://github.com/paulzi/yii2-auto-tree" 10 | }, 11 | "authors": [ 12 | { 13 | "name": "PaulZi", 14 | "email": "pavel.zimakoff@gmail.com" 15 | } 16 | ], 17 | "repositories": [ 18 | { 19 | "type": "composer", 20 | "url": "https://asset-packagist.org" 21 | } 22 | ], 23 | "minimum-stability": "stable", 24 | "require": { 25 | "php": ">=5.4.0", 26 | "yiisoft/yii2": "~2.0.0" 27 | }, 28 | "require-dev": { 29 | "paulzi/yii2-adjacency-list": "^2.0.3", 30 | "paulzi/yii2-nested-sets": "^1.0.4", 31 | "paulzi/yii2-nested-intervals": "^1.0.5", 32 | "paulzi/yii2-materialized-path": "^2.0.6", 33 | "phpunit/phpunit": "~4.0", 34 | "phpunit/dbunit": "~1.0" 35 | }, 36 | "autoload": { 37 | "psr-4": { 38 | "paulzi\\autotree\\": "" 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "cf2f1500a4429ed3ee346d88dd0361be", 8 | "content-hash": "e46c01d12b85d958824c471632571f5a", 9 | "packages": [ 10 | { 11 | "name": "bower-asset/jquery", 12 | "version": "2.2.4", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/jquery/jquery-dist.git", 16 | "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/c0185ab7c75aab88762c5aae780b9d83b80eda72", 21 | "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72", 22 | "shasum": "" 23 | }, 24 | "type": "bower-asset-library", 25 | "extra": { 26 | "bower-asset-main": "dist/jquery.js", 27 | "bower-asset-ignore": [ 28 | "package.json" 29 | ] 30 | }, 31 | "license": [ 32 | "MIT" 33 | ], 34 | "keywords": [ 35 | "browser", 36 | "javascript", 37 | "jquery", 38 | "library" 39 | ] 40 | }, 41 | { 42 | "name": "bower-asset/jquery.inputmask", 43 | "version": "3.2.7", 44 | "source": { 45 | "type": "git", 46 | "url": "https://github.com/RobinHerbots/jquery.inputmask.git", 47 | "reference": "5a72c563b502b8e05958a524cdfffafe9987be38" 48 | }, 49 | "dist": { 50 | "type": "zip", 51 | "url": "https://api.github.com/repos/RobinHerbots/jquery.inputmask/zipball/5a72c563b502b8e05958a524cdfffafe9987be38", 52 | "reference": "5a72c563b502b8e05958a524cdfffafe9987be38", 53 | "shasum": "" 54 | }, 55 | "require": { 56 | "bower-asset/jquery": ">=1.7" 57 | }, 58 | "type": "bower-asset-library", 59 | "extra": { 60 | "bower-asset-main": [ 61 | "./dist/inputmask/inputmask.js" 62 | ], 63 | "bower-asset-ignore": [ 64 | "**/*", 65 | "!dist/*", 66 | "!dist/inputmask/*", 67 | "!dist/min/*", 68 | "!dist/min/inputmask/*", 69 | "!extra/bindings/*", 70 | "!extra/dependencyLibs/*", 71 | "!extra/phone-codes/*" 72 | ] 73 | }, 74 | "license": [ 75 | "http://opensource.org/licenses/mit-license.php" 76 | ], 77 | "description": "jquery.inputmask is a jquery plugin which create an input mask.", 78 | "keywords": [ 79 | "form", 80 | "input", 81 | "inputmask", 82 | "jquery", 83 | "mask", 84 | "plugins" 85 | ] 86 | }, 87 | { 88 | "name": "bower-asset/punycode", 89 | "version": "v1.3.2", 90 | "source": { 91 | "type": "git", 92 | "url": "https://github.com/bestiejs/punycode.js.git", 93 | "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3" 94 | }, 95 | "dist": { 96 | "type": "zip", 97 | "url": "https://api.github.com/repos/bestiejs/punycode.js/zipball/38c8d3131a82567bfef18da09f7f4db68c84f8a3", 98 | "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3", 99 | "shasum": "" 100 | }, 101 | "type": "bower-asset-library", 102 | "extra": { 103 | "bower-asset-main": "punycode.js", 104 | "bower-asset-ignore": [ 105 | "coverage", 106 | "tests", 107 | ".*", 108 | "component.json", 109 | "Gruntfile.js", 110 | "node_modules", 111 | "package.json" 112 | ] 113 | } 114 | }, 115 | { 116 | "name": "bower-asset/yii2-pjax", 117 | "version": "v2.0.6", 118 | "source": { 119 | "type": "git", 120 | "url": "https://github.com/yiisoft/jquery-pjax.git", 121 | "reference": "60728da6ade5879e807a49ce59ef9a72039b8978" 122 | }, 123 | "dist": { 124 | "type": "zip", 125 | "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/60728da6ade5879e807a49ce59ef9a72039b8978", 126 | "reference": "60728da6ade5879e807a49ce59ef9a72039b8978", 127 | "shasum": "" 128 | }, 129 | "require": { 130 | "bower-asset/jquery": ">=1.8" 131 | }, 132 | "type": "bower-asset-library", 133 | "extra": { 134 | "bower-asset-main": "./jquery.pjax.js", 135 | "bower-asset-ignore": [ 136 | ".travis.yml", 137 | "Gemfile", 138 | "Gemfile.lock", 139 | "CONTRIBUTING.md", 140 | "vendor/", 141 | "script/", 142 | "test/" 143 | ] 144 | }, 145 | "license": [ 146 | "MIT" 147 | ] 148 | }, 149 | { 150 | "name": "cebe/markdown", 151 | "version": "1.1.0", 152 | "source": { 153 | "type": "git", 154 | "url": "https://github.com/cebe/markdown.git", 155 | "reference": "54a2c49de31cc44e864ebf0500a35ef21d0010b2" 156 | }, 157 | "dist": { 158 | "type": "zip", 159 | "url": "https://api.github.com/repos/cebe/markdown/zipball/54a2c49de31cc44e864ebf0500a35ef21d0010b2", 160 | "reference": "54a2c49de31cc44e864ebf0500a35ef21d0010b2", 161 | "shasum": "" 162 | }, 163 | "require": { 164 | "lib-pcre": "*", 165 | "php": ">=5.4.0" 166 | }, 167 | "require-dev": { 168 | "cebe/indent": "*", 169 | "facebook/xhprof": "*@dev", 170 | "phpunit/phpunit": "4.1.*" 171 | }, 172 | "bin": [ 173 | "bin/markdown" 174 | ], 175 | "type": "library", 176 | "extra": { 177 | "branch-alias": { 178 | "dev-master": "1.1.x-dev" 179 | } 180 | }, 181 | "autoload": { 182 | "psr-4": { 183 | "cebe\\markdown\\": "" 184 | } 185 | }, 186 | "notification-url": "https://packagist.org/downloads/", 187 | "license": [ 188 | "MIT" 189 | ], 190 | "authors": [ 191 | { 192 | "name": "Carsten Brandt", 193 | "email": "mail@cebe.cc", 194 | "homepage": "http://cebe.cc/", 195 | "role": "Creator" 196 | } 197 | ], 198 | "description": "A super fast, highly extensible markdown parser for PHP", 199 | "homepage": "https://github.com/cebe/markdown#readme", 200 | "keywords": [ 201 | "extensible", 202 | "fast", 203 | "gfm", 204 | "markdown", 205 | "markdown-extra" 206 | ], 207 | "time": "2015-03-06 05:28:07" 208 | }, 209 | { 210 | "name": "ezyang/htmlpurifier", 211 | "version": "v4.8.0", 212 | "source": { 213 | "type": "git", 214 | "url": "https://github.com/ezyang/htmlpurifier.git", 215 | "reference": "d0c392f77d2f2a3dcf7fcb79e2a1e2b8804e75b2" 216 | }, 217 | "dist": { 218 | "type": "zip", 219 | "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d0c392f77d2f2a3dcf7fcb79e2a1e2b8804e75b2", 220 | "reference": "d0c392f77d2f2a3dcf7fcb79e2a1e2b8804e75b2", 221 | "shasum": "" 222 | }, 223 | "require": { 224 | "php": ">=5.2" 225 | }, 226 | "type": "library", 227 | "autoload": { 228 | "psr-0": { 229 | "HTMLPurifier": "library/" 230 | }, 231 | "files": [ 232 | "library/HTMLPurifier.composer.php" 233 | ] 234 | }, 235 | "notification-url": "https://packagist.org/downloads/", 236 | "license": [ 237 | "LGPL" 238 | ], 239 | "authors": [ 240 | { 241 | "name": "Edward Z. Yang", 242 | "email": "admin@htmlpurifier.org", 243 | "homepage": "http://ezyang.com" 244 | } 245 | ], 246 | "description": "Standards compliant HTML filter written in PHP", 247 | "homepage": "http://htmlpurifier.org/", 248 | "keywords": [ 249 | "html" 250 | ], 251 | "time": "2016-07-16 12:58:58" 252 | }, 253 | { 254 | "name": "yiisoft/yii2", 255 | "version": "2.0.9", 256 | "source": { 257 | "type": "git", 258 | "url": "https://github.com/yiisoft/yii2-framework.git", 259 | "reference": "2b75151ea60e1fd820046416eee2e89c3dda1133" 260 | }, 261 | "dist": { 262 | "type": "zip", 263 | "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/2b75151ea60e1fd820046416eee2e89c3dda1133", 264 | "reference": "2b75151ea60e1fd820046416eee2e89c3dda1133", 265 | "shasum": "" 266 | }, 267 | "require": { 268 | "bower-asset/jquery": "2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", 269 | "bower-asset/jquery.inputmask": "~3.2.2", 270 | "bower-asset/punycode": "1.3.*", 271 | "bower-asset/yii2-pjax": "~2.0.1", 272 | "cebe/markdown": "~1.0.0 | ~1.1.0", 273 | "ext-ctype": "*", 274 | "ext-mbstring": "*", 275 | "ezyang/htmlpurifier": "~4.6", 276 | "lib-pcre": "*", 277 | "php": ">=5.4.0", 278 | "yiisoft/yii2-composer": "~2.0.4" 279 | }, 280 | "bin": [ 281 | "yii" 282 | ], 283 | "type": "library", 284 | "extra": { 285 | "branch-alias": { 286 | "dev-master": "2.0.x-dev" 287 | } 288 | }, 289 | "autoload": { 290 | "psr-4": { 291 | "yii\\": "" 292 | } 293 | }, 294 | "notification-url": "https://packagist.org/downloads/", 295 | "license": [ 296 | "BSD-3-Clause" 297 | ], 298 | "authors": [ 299 | { 300 | "name": "Qiang Xue", 301 | "email": "qiang.xue@gmail.com", 302 | "homepage": "http://www.yiiframework.com/", 303 | "role": "Founder and project lead" 304 | }, 305 | { 306 | "name": "Alexander Makarov", 307 | "email": "sam@rmcreative.ru", 308 | "homepage": "http://rmcreative.ru/", 309 | "role": "Core framework development" 310 | }, 311 | { 312 | "name": "Maurizio Domba", 313 | "homepage": "http://mdomba.info/", 314 | "role": "Core framework development" 315 | }, 316 | { 317 | "name": "Carsten Brandt", 318 | "email": "mail@cebe.cc", 319 | "homepage": "http://cebe.cc/", 320 | "role": "Core framework development" 321 | }, 322 | { 323 | "name": "Timur Ruziev", 324 | "email": "resurtm@gmail.com", 325 | "homepage": "http://resurtm.com/", 326 | "role": "Core framework development" 327 | }, 328 | { 329 | "name": "Paul Klimov", 330 | "email": "klimov.paul@gmail.com", 331 | "role": "Core framework development" 332 | }, 333 | { 334 | "name": "Dmitry Naumenko", 335 | "email": "d.naumenko.a@gmail.com", 336 | "role": "Core framework development" 337 | } 338 | ], 339 | "description": "Yii PHP Framework Version 2", 340 | "homepage": "http://www.yiiframework.com/", 341 | "keywords": [ 342 | "framework", 343 | "yii2" 344 | ], 345 | "time": "2016-07-11 13:36:42" 346 | }, 347 | { 348 | "name": "yiisoft/yii2-composer", 349 | "version": "2.0.4", 350 | "source": { 351 | "type": "git", 352 | "url": "https://github.com/yiisoft/yii2-composer.git", 353 | "reference": "7452fd908a5023b8bb5ea1b123a174ca080de464" 354 | }, 355 | "dist": { 356 | "type": "zip", 357 | "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/7452fd908a5023b8bb5ea1b123a174ca080de464", 358 | "reference": "7452fd908a5023b8bb5ea1b123a174ca080de464", 359 | "shasum": "" 360 | }, 361 | "require": { 362 | "composer-plugin-api": "^1.0" 363 | }, 364 | "type": "composer-plugin", 365 | "extra": { 366 | "class": "yii\\composer\\Plugin", 367 | "branch-alias": { 368 | "dev-master": "2.0.x-dev" 369 | } 370 | }, 371 | "autoload": { 372 | "psr-4": { 373 | "yii\\composer\\": "" 374 | } 375 | }, 376 | "notification-url": "https://packagist.org/downloads/", 377 | "license": [ 378 | "BSD-3-Clause" 379 | ], 380 | "authors": [ 381 | { 382 | "name": "Qiang Xue", 383 | "email": "qiang.xue@gmail.com" 384 | } 385 | ], 386 | "description": "The composer plugin for Yii extension installer", 387 | "keywords": [ 388 | "composer", 389 | "extension installer", 390 | "yii2" 391 | ], 392 | "time": "2016-02-06 00:49:24" 393 | } 394 | ], 395 | "packages-dev": [ 396 | { 397 | "name": "doctrine/instantiator", 398 | "version": "1.0.5", 399 | "source": { 400 | "type": "git", 401 | "url": "https://github.com/doctrine/instantiator.git", 402 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 403 | }, 404 | "dist": { 405 | "type": "zip", 406 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 407 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 408 | "shasum": "" 409 | }, 410 | "require": { 411 | "php": ">=5.3,<8.0-DEV" 412 | }, 413 | "require-dev": { 414 | "athletic/athletic": "~0.1.8", 415 | "ext-pdo": "*", 416 | "ext-phar": "*", 417 | "phpunit/phpunit": "~4.0", 418 | "squizlabs/php_codesniffer": "~2.0" 419 | }, 420 | "type": "library", 421 | "extra": { 422 | "branch-alias": { 423 | "dev-master": "1.0.x-dev" 424 | } 425 | }, 426 | "autoload": { 427 | "psr-4": { 428 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 429 | } 430 | }, 431 | "notification-url": "https://packagist.org/downloads/", 432 | "license": [ 433 | "MIT" 434 | ], 435 | "authors": [ 436 | { 437 | "name": "Marco Pivetta", 438 | "email": "ocramius@gmail.com", 439 | "homepage": "http://ocramius.github.com/" 440 | } 441 | ], 442 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 443 | "homepage": "https://github.com/doctrine/instantiator", 444 | "keywords": [ 445 | "constructor", 446 | "instantiate" 447 | ], 448 | "time": "2015-06-14 21:17:01" 449 | }, 450 | { 451 | "name": "paulzi/yii2-adjacency-list", 452 | "version": "v2.0.3", 453 | "source": { 454 | "type": "git", 455 | "url": "https://github.com/paulzi/yii2-adjacency-list.git", 456 | "reference": "65da6ae0bc32211d7dbbf6df4f62526104116e4d" 457 | }, 458 | "dist": { 459 | "type": "zip", 460 | "url": "https://api.github.com/repos/paulzi/yii2-adjacency-list/zipball/65da6ae0bc32211d7dbbf6df4f62526104116e4d", 461 | "reference": "65da6ae0bc32211d7dbbf6df4f62526104116e4d", 462 | "shasum": "" 463 | }, 464 | "require": { 465 | "paulzi/yii2-sortable": "~1.0", 466 | "php": ">=5.4.0", 467 | "yiisoft/yii2": "~2.0.0" 468 | }, 469 | "require-dev": { 470 | "phpunit/dbunit": "~1.0", 471 | "phpunit/phpunit": "~4.0" 472 | }, 473 | "type": "yii2-extension", 474 | "autoload": { 475 | "psr-4": { 476 | "paulzi\\adjacencyList\\": "" 477 | } 478 | }, 479 | "notification-url": "https://packagist.org/downloads/", 480 | "license": [ 481 | "MIT" 482 | ], 483 | "authors": [ 484 | { 485 | "name": "PaulZi", 486 | "email": "pavel.zimakoff@gmail.com" 487 | } 488 | ], 489 | "description": "Adjacency List Behavior for Yii2", 490 | "keywords": [ 491 | "adjacency list", 492 | "yii2" 493 | ], 494 | "time": "2016-07-21 13:50:43" 495 | }, 496 | { 497 | "name": "paulzi/yii2-materialized-path", 498 | "version": "v2.0.6", 499 | "source": { 500 | "type": "git", 501 | "url": "https://github.com/paulzi/yii2-materialized-path.git", 502 | "reference": "37135467e45209f3775fff0312f042a617da413c" 503 | }, 504 | "dist": { 505 | "type": "zip", 506 | "url": "https://api.github.com/repos/paulzi/yii2-materialized-path/zipball/37135467e45209f3775fff0312f042a617da413c", 507 | "reference": "37135467e45209f3775fff0312f042a617da413c", 508 | "shasum": "" 509 | }, 510 | "require": { 511 | "paulzi/yii2-sortable": "~1.0", 512 | "php": ">=5.4.0", 513 | "yiisoft/yii2": "~2.0.0" 514 | }, 515 | "require-dev": { 516 | "phpunit/dbunit": "~1.0", 517 | "phpunit/phpunit": "~4.0" 518 | }, 519 | "type": "yii2-extension", 520 | "autoload": { 521 | "psr-4": { 522 | "paulzi\\materializedPath\\": "" 523 | } 524 | }, 525 | "notification-url": "https://packagist.org/downloads/", 526 | "license": [ 527 | "MIT" 528 | ], 529 | "authors": [ 530 | { 531 | "name": "PaulZi", 532 | "email": "pavel.zimakoff@gmail.com" 533 | } 534 | ], 535 | "description": "Materialized Path Behavior for Yii2", 536 | "keywords": [ 537 | "materialized path", 538 | "yii2" 539 | ], 540 | "time": "2016-07-21 13:56:39" 541 | }, 542 | { 543 | "name": "paulzi/yii2-nested-intervals", 544 | "version": "v1.0.5", 545 | "source": { 546 | "type": "git", 547 | "url": "https://github.com/paulzi/yii2-nested-intervals.git", 548 | "reference": "5a2aa28bc14b33f01c9fcbce85be20b5e49d0336" 549 | }, 550 | "dist": { 551 | "type": "zip", 552 | "url": "https://api.github.com/repos/paulzi/yii2-nested-intervals/zipball/5a2aa28bc14b33f01c9fcbce85be20b5e49d0336", 553 | "reference": "5a2aa28bc14b33f01c9fcbce85be20b5e49d0336", 554 | "shasum": "" 555 | }, 556 | "require": { 557 | "php": ">=5.4.0", 558 | "yiisoft/yii2": "~2.0.0" 559 | }, 560 | "require-dev": { 561 | "phpunit/dbunit": "~1.0", 562 | "phpunit/phpunit": "~4.0" 563 | }, 564 | "type": "yii2-extension", 565 | "autoload": { 566 | "psr-4": { 567 | "paulzi\\nestedintervals\\": "" 568 | } 569 | }, 570 | "notification-url": "https://packagist.org/downloads/", 571 | "license": [ 572 | "MIT" 573 | ], 574 | "authors": [ 575 | { 576 | "name": "PaulZi", 577 | "email": "pavel.zimakoff@gmail.com" 578 | } 579 | ], 580 | "description": "Nested Intervals Behavior for Yii2", 581 | "keywords": [ 582 | "nested intervals", 583 | "nested sets", 584 | "yii2" 585 | ], 586 | "time": "2016-07-21 14:01:31" 587 | }, 588 | { 589 | "name": "paulzi/yii2-nested-sets", 590 | "version": "v1.0.4", 591 | "source": { 592 | "type": "git", 593 | "url": "https://github.com/paulzi/yii2-nested-sets.git", 594 | "reference": "d8350ad4b1a9fb38f990f5c30cf8f46fa9721e3c" 595 | }, 596 | "dist": { 597 | "type": "zip", 598 | "url": "https://api.github.com/repos/paulzi/yii2-nested-sets/zipball/d8350ad4b1a9fb38f990f5c30cf8f46fa9721e3c", 599 | "reference": "d8350ad4b1a9fb38f990f5c30cf8f46fa9721e3c", 600 | "shasum": "" 601 | }, 602 | "require": { 603 | "php": ">=5.4.0", 604 | "yiisoft/yii2": "~2.0.0" 605 | }, 606 | "require-dev": { 607 | "phpunit/dbunit": "~1.0", 608 | "phpunit/phpunit": "~4.0" 609 | }, 610 | "type": "yii2-extension", 611 | "autoload": { 612 | "psr-4": { 613 | "paulzi\\nestedsets\\": "" 614 | } 615 | }, 616 | "notification-url": "https://packagist.org/downloads/", 617 | "license": [ 618 | "MIT" 619 | ], 620 | "authors": [ 621 | { 622 | "name": "Alexander Kochetov", 623 | "email": "creocoder@gmail.com" 624 | }, 625 | { 626 | "name": "PaulZi", 627 | "email": "pavel.zimakoff@gmail.com" 628 | } 629 | ], 630 | "description": "Nested Sets Behavior for Yii2", 631 | "keywords": [ 632 | "nested sets", 633 | "yii2" 634 | ], 635 | "time": "2016-07-21 13:59:00" 636 | }, 637 | { 638 | "name": "paulzi/yii2-sortable", 639 | "version": "v1.0.0", 640 | "source": { 641 | "type": "git", 642 | "url": "https://github.com/paulzi/yii2-sortable.git", 643 | "reference": "7d42496f009ef935e25e6146e34d7d588f62610f" 644 | }, 645 | "dist": { 646 | "type": "zip", 647 | "url": "https://api.github.com/repos/paulzi/yii2-sortable/zipball/7d42496f009ef935e25e6146e34d7d588f62610f", 648 | "reference": "7d42496f009ef935e25e6146e34d7d588f62610f", 649 | "shasum": "" 650 | }, 651 | "require": { 652 | "php": ">=5.4.0", 653 | "yiisoft/yii2": "~2.0.0" 654 | }, 655 | "require-dev": { 656 | "phpunit/dbunit": "~1.0", 657 | "phpunit/phpunit": "~4.0" 658 | }, 659 | "type": "yii2-extension", 660 | "autoload": { 661 | "psr-4": { 662 | "paulzi\\sortable\\": "" 663 | } 664 | }, 665 | "notification-url": "https://packagist.org/downloads/", 666 | "license": [ 667 | "MIT" 668 | ], 669 | "authors": [ 670 | { 671 | "name": "PaulZi", 672 | "email": "pavel.zimakoff@gmail.com" 673 | } 674 | ], 675 | "description": "Sortable Behavior for Yii2", 676 | "keywords": [ 677 | "sortable", 678 | "yii2" 679 | ], 680 | "time": "2015-12-11 16:04:55" 681 | }, 682 | { 683 | "name": "phpdocumentor/reflection-common", 684 | "version": "1.0", 685 | "source": { 686 | "type": "git", 687 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 688 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" 689 | }, 690 | "dist": { 691 | "type": "zip", 692 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 693 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 694 | "shasum": "" 695 | }, 696 | "require": { 697 | "php": ">=5.5" 698 | }, 699 | "require-dev": { 700 | "phpunit/phpunit": "^4.6" 701 | }, 702 | "type": "library", 703 | "extra": { 704 | "branch-alias": { 705 | "dev-master": "1.0.x-dev" 706 | } 707 | }, 708 | "autoload": { 709 | "psr-4": { 710 | "phpDocumentor\\Reflection\\": [ 711 | "src" 712 | ] 713 | } 714 | }, 715 | "notification-url": "https://packagist.org/downloads/", 716 | "license": [ 717 | "MIT" 718 | ], 719 | "authors": [ 720 | { 721 | "name": "Jaap van Otterdijk", 722 | "email": "opensource@ijaap.nl" 723 | } 724 | ], 725 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 726 | "homepage": "http://www.phpdoc.org", 727 | "keywords": [ 728 | "FQSEN", 729 | "phpDocumentor", 730 | "phpdoc", 731 | "reflection", 732 | "static analysis" 733 | ], 734 | "time": "2015-12-27 11:43:31" 735 | }, 736 | { 737 | "name": "phpdocumentor/reflection-docblock", 738 | "version": "3.1.0", 739 | "source": { 740 | "type": "git", 741 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 742 | "reference": "9270140b940ff02e58ec577c237274e92cd40cdd" 743 | }, 744 | "dist": { 745 | "type": "zip", 746 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9270140b940ff02e58ec577c237274e92cd40cdd", 747 | "reference": "9270140b940ff02e58ec577c237274e92cd40cdd", 748 | "shasum": "" 749 | }, 750 | "require": { 751 | "php": ">=5.5", 752 | "phpdocumentor/reflection-common": "^1.0@dev", 753 | "phpdocumentor/type-resolver": "^0.2.0", 754 | "webmozart/assert": "^1.0" 755 | }, 756 | "require-dev": { 757 | "mockery/mockery": "^0.9.4", 758 | "phpunit/phpunit": "^4.4" 759 | }, 760 | "type": "library", 761 | "autoload": { 762 | "psr-4": { 763 | "phpDocumentor\\Reflection\\": [ 764 | "src/" 765 | ] 766 | } 767 | }, 768 | "notification-url": "https://packagist.org/downloads/", 769 | "license": [ 770 | "MIT" 771 | ], 772 | "authors": [ 773 | { 774 | "name": "Mike van Riel", 775 | "email": "me@mikevanriel.com" 776 | } 777 | ], 778 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 779 | "time": "2016-06-10 09:48:41" 780 | }, 781 | { 782 | "name": "phpdocumentor/type-resolver", 783 | "version": "0.2", 784 | "source": { 785 | "type": "git", 786 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 787 | "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" 788 | }, 789 | "dist": { 790 | "type": "zip", 791 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", 792 | "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", 793 | "shasum": "" 794 | }, 795 | "require": { 796 | "php": ">=5.5", 797 | "phpdocumentor/reflection-common": "^1.0" 798 | }, 799 | "require-dev": { 800 | "mockery/mockery": "^0.9.4", 801 | "phpunit/phpunit": "^5.2||^4.8.24" 802 | }, 803 | "type": "library", 804 | "extra": { 805 | "branch-alias": { 806 | "dev-master": "1.0.x-dev" 807 | } 808 | }, 809 | "autoload": { 810 | "psr-4": { 811 | "phpDocumentor\\Reflection\\": [ 812 | "src/" 813 | ] 814 | } 815 | }, 816 | "notification-url": "https://packagist.org/downloads/", 817 | "license": [ 818 | "MIT" 819 | ], 820 | "authors": [ 821 | { 822 | "name": "Mike van Riel", 823 | "email": "me@mikevanriel.com" 824 | } 825 | ], 826 | "time": "2016-06-10 07:14:17" 827 | }, 828 | { 829 | "name": "phpspec/prophecy", 830 | "version": "v1.6.1", 831 | "source": { 832 | "type": "git", 833 | "url": "https://github.com/phpspec/prophecy.git", 834 | "reference": "58a8137754bc24b25740d4281399a4a3596058e0" 835 | }, 836 | "dist": { 837 | "type": "zip", 838 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", 839 | "reference": "58a8137754bc24b25740d4281399a4a3596058e0", 840 | "shasum": "" 841 | }, 842 | "require": { 843 | "doctrine/instantiator": "^1.0.2", 844 | "php": "^5.3|^7.0", 845 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", 846 | "sebastian/comparator": "^1.1", 847 | "sebastian/recursion-context": "^1.0" 848 | }, 849 | "require-dev": { 850 | "phpspec/phpspec": "^2.0" 851 | }, 852 | "type": "library", 853 | "extra": { 854 | "branch-alias": { 855 | "dev-master": "1.6.x-dev" 856 | } 857 | }, 858 | "autoload": { 859 | "psr-0": { 860 | "Prophecy\\": "src/" 861 | } 862 | }, 863 | "notification-url": "https://packagist.org/downloads/", 864 | "license": [ 865 | "MIT" 866 | ], 867 | "authors": [ 868 | { 869 | "name": "Konstantin Kudryashov", 870 | "email": "ever.zet@gmail.com", 871 | "homepage": "http://everzet.com" 872 | }, 873 | { 874 | "name": "Marcello Duarte", 875 | "email": "marcello.duarte@gmail.com" 876 | } 877 | ], 878 | "description": "Highly opinionated mocking framework for PHP 5.3+", 879 | "homepage": "https://github.com/phpspec/prophecy", 880 | "keywords": [ 881 | "Double", 882 | "Dummy", 883 | "fake", 884 | "mock", 885 | "spy", 886 | "stub" 887 | ], 888 | "time": "2016-06-07 08:13:47" 889 | }, 890 | { 891 | "name": "phpunit/dbunit", 892 | "version": "1.4.1", 893 | "source": { 894 | "type": "git", 895 | "url": "https://github.com/sebastianbergmann/dbunit.git", 896 | "reference": "9aaee6447663ff1b0cd50c23637e04af74c5e2ae" 897 | }, 898 | "dist": { 899 | "type": "zip", 900 | "url": "https://api.github.com/repos/sebastianbergmann/dbunit/zipball/9aaee6447663ff1b0cd50c23637e04af74c5e2ae", 901 | "reference": "9aaee6447663ff1b0cd50c23637e04af74c5e2ae", 902 | "shasum": "" 903 | }, 904 | "require": { 905 | "ext-pdo": "*", 906 | "ext-simplexml": "*", 907 | "php": ">=5.3.3", 908 | "phpunit/phpunit": "~4|~5", 909 | "symfony/yaml": "~2.1|~3.0" 910 | }, 911 | "bin": [ 912 | "composer/bin/dbunit" 913 | ], 914 | "type": "library", 915 | "extra": { 916 | "branch-alias": { 917 | "dev-master": "1.3.x-dev" 918 | } 919 | }, 920 | "autoload": { 921 | "classmap": [ 922 | "PHPUnit/" 923 | ] 924 | }, 925 | "notification-url": "https://packagist.org/downloads/", 926 | "include-path": [ 927 | "", 928 | "../../symfony/yaml/" 929 | ], 930 | "license": [ 931 | "BSD-3-Clause" 932 | ], 933 | "authors": [ 934 | { 935 | "name": "Sebastian Bergmann", 936 | "email": "sb@sebastian-bergmann.de", 937 | "role": "lead" 938 | } 939 | ], 940 | "description": "DbUnit port for PHP/PHPUnit to support database interaction testing.", 941 | "homepage": "https://github.com/sebastianbergmann/dbunit/", 942 | "keywords": [ 943 | "database", 944 | "testing", 945 | "xunit" 946 | ], 947 | "time": "2015-08-07 04:57:38" 948 | }, 949 | { 950 | "name": "phpunit/php-code-coverage", 951 | "version": "2.2.4", 952 | "source": { 953 | "type": "git", 954 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 955 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" 956 | }, 957 | "dist": { 958 | "type": "zip", 959 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", 960 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", 961 | "shasum": "" 962 | }, 963 | "require": { 964 | "php": ">=5.3.3", 965 | "phpunit/php-file-iterator": "~1.3", 966 | "phpunit/php-text-template": "~1.2", 967 | "phpunit/php-token-stream": "~1.3", 968 | "sebastian/environment": "^1.3.2", 969 | "sebastian/version": "~1.0" 970 | }, 971 | "require-dev": { 972 | "ext-xdebug": ">=2.1.4", 973 | "phpunit/phpunit": "~4" 974 | }, 975 | "suggest": { 976 | "ext-dom": "*", 977 | "ext-xdebug": ">=2.2.1", 978 | "ext-xmlwriter": "*" 979 | }, 980 | "type": "library", 981 | "extra": { 982 | "branch-alias": { 983 | "dev-master": "2.2.x-dev" 984 | } 985 | }, 986 | "autoload": { 987 | "classmap": [ 988 | "src/" 989 | ] 990 | }, 991 | "notification-url": "https://packagist.org/downloads/", 992 | "license": [ 993 | "BSD-3-Clause" 994 | ], 995 | "authors": [ 996 | { 997 | "name": "Sebastian Bergmann", 998 | "email": "sb@sebastian-bergmann.de", 999 | "role": "lead" 1000 | } 1001 | ], 1002 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 1003 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 1004 | "keywords": [ 1005 | "coverage", 1006 | "testing", 1007 | "xunit" 1008 | ], 1009 | "time": "2015-10-06 15:47:00" 1010 | }, 1011 | { 1012 | "name": "phpunit/php-file-iterator", 1013 | "version": "1.4.1", 1014 | "source": { 1015 | "type": "git", 1016 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 1017 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" 1018 | }, 1019 | "dist": { 1020 | "type": "zip", 1021 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 1022 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 1023 | "shasum": "" 1024 | }, 1025 | "require": { 1026 | "php": ">=5.3.3" 1027 | }, 1028 | "type": "library", 1029 | "extra": { 1030 | "branch-alias": { 1031 | "dev-master": "1.4.x-dev" 1032 | } 1033 | }, 1034 | "autoload": { 1035 | "classmap": [ 1036 | "src/" 1037 | ] 1038 | }, 1039 | "notification-url": "https://packagist.org/downloads/", 1040 | "license": [ 1041 | "BSD-3-Clause" 1042 | ], 1043 | "authors": [ 1044 | { 1045 | "name": "Sebastian Bergmann", 1046 | "email": "sb@sebastian-bergmann.de", 1047 | "role": "lead" 1048 | } 1049 | ], 1050 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1051 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1052 | "keywords": [ 1053 | "filesystem", 1054 | "iterator" 1055 | ], 1056 | "time": "2015-06-21 13:08:43" 1057 | }, 1058 | { 1059 | "name": "phpunit/php-text-template", 1060 | "version": "1.2.1", 1061 | "source": { 1062 | "type": "git", 1063 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1064 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 1065 | }, 1066 | "dist": { 1067 | "type": "zip", 1068 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1069 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1070 | "shasum": "" 1071 | }, 1072 | "require": { 1073 | "php": ">=5.3.3" 1074 | }, 1075 | "type": "library", 1076 | "autoload": { 1077 | "classmap": [ 1078 | "src/" 1079 | ] 1080 | }, 1081 | "notification-url": "https://packagist.org/downloads/", 1082 | "license": [ 1083 | "BSD-3-Clause" 1084 | ], 1085 | "authors": [ 1086 | { 1087 | "name": "Sebastian Bergmann", 1088 | "email": "sebastian@phpunit.de", 1089 | "role": "lead" 1090 | } 1091 | ], 1092 | "description": "Simple template engine.", 1093 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1094 | "keywords": [ 1095 | "template" 1096 | ], 1097 | "time": "2015-06-21 13:50:34" 1098 | }, 1099 | { 1100 | "name": "phpunit/php-timer", 1101 | "version": "1.0.8", 1102 | "source": { 1103 | "type": "git", 1104 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1105 | "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" 1106 | }, 1107 | "dist": { 1108 | "type": "zip", 1109 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", 1110 | "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", 1111 | "shasum": "" 1112 | }, 1113 | "require": { 1114 | "php": ">=5.3.3" 1115 | }, 1116 | "require-dev": { 1117 | "phpunit/phpunit": "~4|~5" 1118 | }, 1119 | "type": "library", 1120 | "autoload": { 1121 | "classmap": [ 1122 | "src/" 1123 | ] 1124 | }, 1125 | "notification-url": "https://packagist.org/downloads/", 1126 | "license": [ 1127 | "BSD-3-Clause" 1128 | ], 1129 | "authors": [ 1130 | { 1131 | "name": "Sebastian Bergmann", 1132 | "email": "sb@sebastian-bergmann.de", 1133 | "role": "lead" 1134 | } 1135 | ], 1136 | "description": "Utility class for timing", 1137 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1138 | "keywords": [ 1139 | "timer" 1140 | ], 1141 | "time": "2016-05-12 18:03:57" 1142 | }, 1143 | { 1144 | "name": "phpunit/php-token-stream", 1145 | "version": "1.4.8", 1146 | "source": { 1147 | "type": "git", 1148 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 1149 | "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" 1150 | }, 1151 | "dist": { 1152 | "type": "zip", 1153 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", 1154 | "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", 1155 | "shasum": "" 1156 | }, 1157 | "require": { 1158 | "ext-tokenizer": "*", 1159 | "php": ">=5.3.3" 1160 | }, 1161 | "require-dev": { 1162 | "phpunit/phpunit": "~4.2" 1163 | }, 1164 | "type": "library", 1165 | "extra": { 1166 | "branch-alias": { 1167 | "dev-master": "1.4-dev" 1168 | } 1169 | }, 1170 | "autoload": { 1171 | "classmap": [ 1172 | "src/" 1173 | ] 1174 | }, 1175 | "notification-url": "https://packagist.org/downloads/", 1176 | "license": [ 1177 | "BSD-3-Clause" 1178 | ], 1179 | "authors": [ 1180 | { 1181 | "name": "Sebastian Bergmann", 1182 | "email": "sebastian@phpunit.de" 1183 | } 1184 | ], 1185 | "description": "Wrapper around PHP's tokenizer extension.", 1186 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 1187 | "keywords": [ 1188 | "tokenizer" 1189 | ], 1190 | "time": "2015-09-15 10:49:45" 1191 | }, 1192 | { 1193 | "name": "phpunit/phpunit", 1194 | "version": "4.8.27", 1195 | "source": { 1196 | "type": "git", 1197 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1198 | "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90" 1199 | }, 1200 | "dist": { 1201 | "type": "zip", 1202 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c062dddcb68e44b563f66ee319ddae2b5a322a90", 1203 | "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90", 1204 | "shasum": "" 1205 | }, 1206 | "require": { 1207 | "ext-dom": "*", 1208 | "ext-json": "*", 1209 | "ext-pcre": "*", 1210 | "ext-reflection": "*", 1211 | "ext-spl": "*", 1212 | "php": ">=5.3.3", 1213 | "phpspec/prophecy": "^1.3.1", 1214 | "phpunit/php-code-coverage": "~2.1", 1215 | "phpunit/php-file-iterator": "~1.4", 1216 | "phpunit/php-text-template": "~1.2", 1217 | "phpunit/php-timer": "^1.0.6", 1218 | "phpunit/phpunit-mock-objects": "~2.3", 1219 | "sebastian/comparator": "~1.1", 1220 | "sebastian/diff": "~1.2", 1221 | "sebastian/environment": "~1.3", 1222 | "sebastian/exporter": "~1.2", 1223 | "sebastian/global-state": "~1.0", 1224 | "sebastian/version": "~1.0", 1225 | "symfony/yaml": "~2.1|~3.0" 1226 | }, 1227 | "suggest": { 1228 | "phpunit/php-invoker": "~1.1" 1229 | }, 1230 | "bin": [ 1231 | "phpunit" 1232 | ], 1233 | "type": "library", 1234 | "extra": { 1235 | "branch-alias": { 1236 | "dev-master": "4.8.x-dev" 1237 | } 1238 | }, 1239 | "autoload": { 1240 | "classmap": [ 1241 | "src/" 1242 | ] 1243 | }, 1244 | "notification-url": "https://packagist.org/downloads/", 1245 | "license": [ 1246 | "BSD-3-Clause" 1247 | ], 1248 | "authors": [ 1249 | { 1250 | "name": "Sebastian Bergmann", 1251 | "email": "sebastian@phpunit.de", 1252 | "role": "lead" 1253 | } 1254 | ], 1255 | "description": "The PHP Unit Testing framework.", 1256 | "homepage": "https://phpunit.de/", 1257 | "keywords": [ 1258 | "phpunit", 1259 | "testing", 1260 | "xunit" 1261 | ], 1262 | "time": "2016-07-21 06:48:14" 1263 | }, 1264 | { 1265 | "name": "phpunit/phpunit-mock-objects", 1266 | "version": "2.3.8", 1267 | "source": { 1268 | "type": "git", 1269 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 1270 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" 1271 | }, 1272 | "dist": { 1273 | "type": "zip", 1274 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", 1275 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", 1276 | "shasum": "" 1277 | }, 1278 | "require": { 1279 | "doctrine/instantiator": "^1.0.2", 1280 | "php": ">=5.3.3", 1281 | "phpunit/php-text-template": "~1.2", 1282 | "sebastian/exporter": "~1.2" 1283 | }, 1284 | "require-dev": { 1285 | "phpunit/phpunit": "~4.4" 1286 | }, 1287 | "suggest": { 1288 | "ext-soap": "*" 1289 | }, 1290 | "type": "library", 1291 | "extra": { 1292 | "branch-alias": { 1293 | "dev-master": "2.3.x-dev" 1294 | } 1295 | }, 1296 | "autoload": { 1297 | "classmap": [ 1298 | "src/" 1299 | ] 1300 | }, 1301 | "notification-url": "https://packagist.org/downloads/", 1302 | "license": [ 1303 | "BSD-3-Clause" 1304 | ], 1305 | "authors": [ 1306 | { 1307 | "name": "Sebastian Bergmann", 1308 | "email": "sb@sebastian-bergmann.de", 1309 | "role": "lead" 1310 | } 1311 | ], 1312 | "description": "Mock Object library for PHPUnit", 1313 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 1314 | "keywords": [ 1315 | "mock", 1316 | "xunit" 1317 | ], 1318 | "time": "2015-10-02 06:51:40" 1319 | }, 1320 | { 1321 | "name": "sebastian/comparator", 1322 | "version": "1.2.0", 1323 | "source": { 1324 | "type": "git", 1325 | "url": "https://github.com/sebastianbergmann/comparator.git", 1326 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" 1327 | }, 1328 | "dist": { 1329 | "type": "zip", 1330 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", 1331 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", 1332 | "shasum": "" 1333 | }, 1334 | "require": { 1335 | "php": ">=5.3.3", 1336 | "sebastian/diff": "~1.2", 1337 | "sebastian/exporter": "~1.2" 1338 | }, 1339 | "require-dev": { 1340 | "phpunit/phpunit": "~4.4" 1341 | }, 1342 | "type": "library", 1343 | "extra": { 1344 | "branch-alias": { 1345 | "dev-master": "1.2.x-dev" 1346 | } 1347 | }, 1348 | "autoload": { 1349 | "classmap": [ 1350 | "src/" 1351 | ] 1352 | }, 1353 | "notification-url": "https://packagist.org/downloads/", 1354 | "license": [ 1355 | "BSD-3-Clause" 1356 | ], 1357 | "authors": [ 1358 | { 1359 | "name": "Jeff Welch", 1360 | "email": "whatthejeff@gmail.com" 1361 | }, 1362 | { 1363 | "name": "Volker Dusch", 1364 | "email": "github@wallbash.com" 1365 | }, 1366 | { 1367 | "name": "Bernhard Schussek", 1368 | "email": "bschussek@2bepublished.at" 1369 | }, 1370 | { 1371 | "name": "Sebastian Bergmann", 1372 | "email": "sebastian@phpunit.de" 1373 | } 1374 | ], 1375 | "description": "Provides the functionality to compare PHP values for equality", 1376 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 1377 | "keywords": [ 1378 | "comparator", 1379 | "compare", 1380 | "equality" 1381 | ], 1382 | "time": "2015-07-26 15:48:44" 1383 | }, 1384 | { 1385 | "name": "sebastian/diff", 1386 | "version": "1.4.1", 1387 | "source": { 1388 | "type": "git", 1389 | "url": "https://github.com/sebastianbergmann/diff.git", 1390 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" 1391 | }, 1392 | "dist": { 1393 | "type": "zip", 1394 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", 1395 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", 1396 | "shasum": "" 1397 | }, 1398 | "require": { 1399 | "php": ">=5.3.3" 1400 | }, 1401 | "require-dev": { 1402 | "phpunit/phpunit": "~4.8" 1403 | }, 1404 | "type": "library", 1405 | "extra": { 1406 | "branch-alias": { 1407 | "dev-master": "1.4-dev" 1408 | } 1409 | }, 1410 | "autoload": { 1411 | "classmap": [ 1412 | "src/" 1413 | ] 1414 | }, 1415 | "notification-url": "https://packagist.org/downloads/", 1416 | "license": [ 1417 | "BSD-3-Clause" 1418 | ], 1419 | "authors": [ 1420 | { 1421 | "name": "Kore Nordmann", 1422 | "email": "mail@kore-nordmann.de" 1423 | }, 1424 | { 1425 | "name": "Sebastian Bergmann", 1426 | "email": "sebastian@phpunit.de" 1427 | } 1428 | ], 1429 | "description": "Diff implementation", 1430 | "homepage": "https://github.com/sebastianbergmann/diff", 1431 | "keywords": [ 1432 | "diff" 1433 | ], 1434 | "time": "2015-12-08 07:14:41" 1435 | }, 1436 | { 1437 | "name": "sebastian/environment", 1438 | "version": "1.3.7", 1439 | "source": { 1440 | "type": "git", 1441 | "url": "https://github.com/sebastianbergmann/environment.git", 1442 | "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" 1443 | }, 1444 | "dist": { 1445 | "type": "zip", 1446 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", 1447 | "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", 1448 | "shasum": "" 1449 | }, 1450 | "require": { 1451 | "php": ">=5.3.3" 1452 | }, 1453 | "require-dev": { 1454 | "phpunit/phpunit": "~4.4" 1455 | }, 1456 | "type": "library", 1457 | "extra": { 1458 | "branch-alias": { 1459 | "dev-master": "1.3.x-dev" 1460 | } 1461 | }, 1462 | "autoload": { 1463 | "classmap": [ 1464 | "src/" 1465 | ] 1466 | }, 1467 | "notification-url": "https://packagist.org/downloads/", 1468 | "license": [ 1469 | "BSD-3-Clause" 1470 | ], 1471 | "authors": [ 1472 | { 1473 | "name": "Sebastian Bergmann", 1474 | "email": "sebastian@phpunit.de" 1475 | } 1476 | ], 1477 | "description": "Provides functionality to handle HHVM/PHP environments", 1478 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1479 | "keywords": [ 1480 | "Xdebug", 1481 | "environment", 1482 | "hhvm" 1483 | ], 1484 | "time": "2016-05-17 03:18:57" 1485 | }, 1486 | { 1487 | "name": "sebastian/exporter", 1488 | "version": "1.2.2", 1489 | "source": { 1490 | "type": "git", 1491 | "url": "https://github.com/sebastianbergmann/exporter.git", 1492 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" 1493 | }, 1494 | "dist": { 1495 | "type": "zip", 1496 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", 1497 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", 1498 | "shasum": "" 1499 | }, 1500 | "require": { 1501 | "php": ">=5.3.3", 1502 | "sebastian/recursion-context": "~1.0" 1503 | }, 1504 | "require-dev": { 1505 | "ext-mbstring": "*", 1506 | "phpunit/phpunit": "~4.4" 1507 | }, 1508 | "type": "library", 1509 | "extra": { 1510 | "branch-alias": { 1511 | "dev-master": "1.3.x-dev" 1512 | } 1513 | }, 1514 | "autoload": { 1515 | "classmap": [ 1516 | "src/" 1517 | ] 1518 | }, 1519 | "notification-url": "https://packagist.org/downloads/", 1520 | "license": [ 1521 | "BSD-3-Clause" 1522 | ], 1523 | "authors": [ 1524 | { 1525 | "name": "Jeff Welch", 1526 | "email": "whatthejeff@gmail.com" 1527 | }, 1528 | { 1529 | "name": "Volker Dusch", 1530 | "email": "github@wallbash.com" 1531 | }, 1532 | { 1533 | "name": "Bernhard Schussek", 1534 | "email": "bschussek@2bepublished.at" 1535 | }, 1536 | { 1537 | "name": "Sebastian Bergmann", 1538 | "email": "sebastian@phpunit.de" 1539 | }, 1540 | { 1541 | "name": "Adam Harvey", 1542 | "email": "aharvey@php.net" 1543 | } 1544 | ], 1545 | "description": "Provides the functionality to export PHP variables for visualization", 1546 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1547 | "keywords": [ 1548 | "export", 1549 | "exporter" 1550 | ], 1551 | "time": "2016-06-17 09:04:28" 1552 | }, 1553 | { 1554 | "name": "sebastian/global-state", 1555 | "version": "1.1.1", 1556 | "source": { 1557 | "type": "git", 1558 | "url": "https://github.com/sebastianbergmann/global-state.git", 1559 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 1560 | }, 1561 | "dist": { 1562 | "type": "zip", 1563 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1564 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1565 | "shasum": "" 1566 | }, 1567 | "require": { 1568 | "php": ">=5.3.3" 1569 | }, 1570 | "require-dev": { 1571 | "phpunit/phpunit": "~4.2" 1572 | }, 1573 | "suggest": { 1574 | "ext-uopz": "*" 1575 | }, 1576 | "type": "library", 1577 | "extra": { 1578 | "branch-alias": { 1579 | "dev-master": "1.0-dev" 1580 | } 1581 | }, 1582 | "autoload": { 1583 | "classmap": [ 1584 | "src/" 1585 | ] 1586 | }, 1587 | "notification-url": "https://packagist.org/downloads/", 1588 | "license": [ 1589 | "BSD-3-Clause" 1590 | ], 1591 | "authors": [ 1592 | { 1593 | "name": "Sebastian Bergmann", 1594 | "email": "sebastian@phpunit.de" 1595 | } 1596 | ], 1597 | "description": "Snapshotting of global state", 1598 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1599 | "keywords": [ 1600 | "global state" 1601 | ], 1602 | "time": "2015-10-12 03:26:01" 1603 | }, 1604 | { 1605 | "name": "sebastian/recursion-context", 1606 | "version": "1.0.2", 1607 | "source": { 1608 | "type": "git", 1609 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1610 | "reference": "913401df809e99e4f47b27cdd781f4a258d58791" 1611 | }, 1612 | "dist": { 1613 | "type": "zip", 1614 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", 1615 | "reference": "913401df809e99e4f47b27cdd781f4a258d58791", 1616 | "shasum": "" 1617 | }, 1618 | "require": { 1619 | "php": ">=5.3.3" 1620 | }, 1621 | "require-dev": { 1622 | "phpunit/phpunit": "~4.4" 1623 | }, 1624 | "type": "library", 1625 | "extra": { 1626 | "branch-alias": { 1627 | "dev-master": "1.0.x-dev" 1628 | } 1629 | }, 1630 | "autoload": { 1631 | "classmap": [ 1632 | "src/" 1633 | ] 1634 | }, 1635 | "notification-url": "https://packagist.org/downloads/", 1636 | "license": [ 1637 | "BSD-3-Clause" 1638 | ], 1639 | "authors": [ 1640 | { 1641 | "name": "Jeff Welch", 1642 | "email": "whatthejeff@gmail.com" 1643 | }, 1644 | { 1645 | "name": "Sebastian Bergmann", 1646 | "email": "sebastian@phpunit.de" 1647 | }, 1648 | { 1649 | "name": "Adam Harvey", 1650 | "email": "aharvey@php.net" 1651 | } 1652 | ], 1653 | "description": "Provides functionality to recursively process PHP variables", 1654 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1655 | "time": "2015-11-11 19:50:13" 1656 | }, 1657 | { 1658 | "name": "sebastian/version", 1659 | "version": "1.0.6", 1660 | "source": { 1661 | "type": "git", 1662 | "url": "https://github.com/sebastianbergmann/version.git", 1663 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" 1664 | }, 1665 | "dist": { 1666 | "type": "zip", 1667 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1668 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1669 | "shasum": "" 1670 | }, 1671 | "type": "library", 1672 | "autoload": { 1673 | "classmap": [ 1674 | "src/" 1675 | ] 1676 | }, 1677 | "notification-url": "https://packagist.org/downloads/", 1678 | "license": [ 1679 | "BSD-3-Clause" 1680 | ], 1681 | "authors": [ 1682 | { 1683 | "name": "Sebastian Bergmann", 1684 | "email": "sebastian@phpunit.de", 1685 | "role": "lead" 1686 | } 1687 | ], 1688 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1689 | "homepage": "https://github.com/sebastianbergmann/version", 1690 | "time": "2015-06-21 13:59:46" 1691 | }, 1692 | { 1693 | "name": "symfony/yaml", 1694 | "version": "v3.1.2", 1695 | "source": { 1696 | "type": "git", 1697 | "url": "https://github.com/symfony/yaml.git", 1698 | "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de" 1699 | }, 1700 | "dist": { 1701 | "type": "zip", 1702 | "url": "https://api.github.com/repos/symfony/yaml/zipball/2884c26ce4c1d61aebf423a8b912950fe7c764de", 1703 | "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de", 1704 | "shasum": "" 1705 | }, 1706 | "require": { 1707 | "php": ">=5.5.9" 1708 | }, 1709 | "type": "library", 1710 | "extra": { 1711 | "branch-alias": { 1712 | "dev-master": "3.1-dev" 1713 | } 1714 | }, 1715 | "autoload": { 1716 | "psr-4": { 1717 | "Symfony\\Component\\Yaml\\": "" 1718 | }, 1719 | "exclude-from-classmap": [ 1720 | "/Tests/" 1721 | ] 1722 | }, 1723 | "notification-url": "https://packagist.org/downloads/", 1724 | "license": [ 1725 | "MIT" 1726 | ], 1727 | "authors": [ 1728 | { 1729 | "name": "Fabien Potencier", 1730 | "email": "fabien@symfony.com" 1731 | }, 1732 | { 1733 | "name": "Symfony Community", 1734 | "homepage": "https://symfony.com/contributors" 1735 | } 1736 | ], 1737 | "description": "Symfony Yaml Component", 1738 | "homepage": "https://symfony.com", 1739 | "time": "2016-06-29 05:41:56" 1740 | }, 1741 | { 1742 | "name": "webmozart/assert", 1743 | "version": "1.0.2", 1744 | "source": { 1745 | "type": "git", 1746 | "url": "https://github.com/webmozart/assert.git", 1747 | "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde" 1748 | }, 1749 | "dist": { 1750 | "type": "zip", 1751 | "url": "https://api.github.com/repos/webmozart/assert/zipball/30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", 1752 | "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", 1753 | "shasum": "" 1754 | }, 1755 | "require": { 1756 | "php": ">=5.3.3" 1757 | }, 1758 | "require-dev": { 1759 | "phpunit/phpunit": "^4.6" 1760 | }, 1761 | "type": "library", 1762 | "extra": { 1763 | "branch-alias": { 1764 | "dev-master": "1.0-dev" 1765 | } 1766 | }, 1767 | "autoload": { 1768 | "psr-4": { 1769 | "Webmozart\\Assert\\": "src/" 1770 | } 1771 | }, 1772 | "notification-url": "https://packagist.org/downloads/", 1773 | "license": [ 1774 | "MIT" 1775 | ], 1776 | "authors": [ 1777 | { 1778 | "name": "Bernhard Schussek", 1779 | "email": "bschussek@gmail.com" 1780 | } 1781 | ], 1782 | "description": "Assertions to validate method input/output with nice error messages.", 1783 | "keywords": [ 1784 | "assert", 1785 | "check", 1786 | "validate" 1787 | ], 1788 | "time": "2015-08-24 13:29:44" 1789 | } 1790 | ], 1791 | "aliases": [], 1792 | "minimum-stability": "stable", 1793 | "stability-flags": [], 1794 | "prefer-stable": false, 1795 | "prefer-lowest": false, 1796 | "platform": { 1797 | "php": ">=5.4.0" 1798 | }, 1799 | "platform-dev": [] 1800 | } 1801 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | ./tests 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | /data/config.local.php -------------------------------------------------------------------------------- /tests/AlMpTest.php: -------------------------------------------------------------------------------- 1 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | namespace paulzi\autotree\tests; 9 | 10 | use paulzi\autotree\tests\models\NodeAlMp; 11 | use Yii; 12 | 13 | /** 14 | * @author PaulZi 15 | * @group AlMp 16 | */ 17 | class AlMpTest extends AutoTreeTraitTestCase 18 | { 19 | public function getModelClass() 20 | { 21 | return NodeAlMp::className(); 22 | } 23 | 24 | public function testMakeRootInsert() 25 | { 26 | $node = new NodeAlMp(['slug' => 'r']); 27 | $this->assertTrue($node->makeRoot()->save()); 28 | 29 | $node->refresh(); 30 | $this->assertEquals(null, $node->parent_id); 31 | $this->assertEquals(0, $node->sort); 32 | $this->assertEquals(0, $node->depth); 33 | } 34 | 35 | public function testMakeRootUpdate() 36 | { 37 | $node = NodeAlMp::findOne(9); 38 | $this->assertTrue($node->makeRoot()->save()); 39 | 40 | $node->refresh(); 41 | $this->assertEquals(null, $node->parent_id); 42 | $this->assertEquals(0, $node->sort); 43 | $this->assertEquals(0, $node->depth); 44 | } 45 | 46 | public function testPrependTo() 47 | { 48 | $node = new NodeAlMp(['slug' => 'new']); 49 | $this->assertTrue($node->prependTo(NodeAlMp::findOne(1))->save()); 50 | 51 | $node->refresh(); 52 | $this->assertEquals(1, $node->parent_id); 53 | $this->assertEquals(-101, $node->sort); 54 | $this->assertEquals(1, $node->depth); 55 | } 56 | 57 | public function testPrependToAnotherTree() 58 | { 59 | $node = NodeAlMp::findOne(30); 60 | $this->assertTrue($node->prependTo(NodeAlMp::findOne(4))->save()); 61 | 62 | $node->refresh(); 63 | $this->assertEquals(4, $node->parent_id); 64 | $this->assertEquals(-100, $node->sort); 65 | $this->assertEquals(2, $node->depth); 66 | } 67 | 68 | public function testAppendTo() 69 | { 70 | $node = NodeAlMp::findOne(10); 71 | $this->assertTrue($node->appendTo(NodeAlMp::findOne(18))->save()); 72 | 73 | $node->refresh(); 74 | $this->assertEquals(18, $node->parent_id); 75 | $this->assertEquals(0, $node->sort); 76 | $this->assertEquals(4, $node->depth); 77 | } 78 | 79 | public function testInsertBefore() 80 | { 81 | $node = new NodeAlMp(['slug' => 'new']); 82 | $this->assertTrue($node->insertBefore(NodeAlMp::findOne(22))->save()); 83 | 84 | $node->refresh(); 85 | $this->assertEquals(9, $node->parent_id); 86 | $this->assertEquals(3, $node->sort); 87 | $this->assertEquals(3, $node->depth); 88 | } 89 | 90 | public function testInsertAfter() 91 | { 92 | $node = NodeAlMp::findOne(32); 93 | $this->assertTrue($node->insertAfter(NodeAlMp::findOne(30))->save()); 94 | 95 | $node->refresh(); 96 | $this->assertEquals(26, $node->parent_id); 97 | $this->assertEquals(3, $node->sort); 98 | $this->assertEquals(1, $node->depth); 99 | } 100 | 101 | public function testInsertAfterAnotherTree() 102 | { 103 | $node = NodeAlMp::findOne(26); 104 | $this->assertTrue($node->insertAfter(NodeAlMp::findOne(21))->save()); 105 | 106 | $node->refresh(); 107 | $this->assertEquals(9, $node->parent_id); 108 | $this->assertEquals(3, $node->sort); 109 | $this->assertEquals(3, $node->depth); 110 | } 111 | 112 | public function testDelete() 113 | { 114 | $this->assertEquals(1, NodeAlMp::findOne(30)->delete()); 115 | $this->assertEquals(null, NodeAlMp::findOne(30)); 116 | } 117 | 118 | public function testDeleteWithChildren() 119 | { 120 | $this->assertEquals(10, NodeAlMp::findOne(4)->deleteWithChildren()); 121 | $this->assertEquals(null, NodeAlMp::findOne(24)); 122 | $this->assertEquals(15, NodeAlMp::findOne(1)->deleteWithChildren()); 123 | } 124 | } -------------------------------------------------------------------------------- /tests/AlNiTest.php: -------------------------------------------------------------------------------- 1 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | namespace paulzi\autotree\tests; 9 | 10 | use paulzi\autotree\tests\models\NodeAlNi; 11 | use Yii; 12 | 13 | /** 14 | * @author PaulZi 15 | * @group AlNi 16 | */ 17 | class AlNiTest extends AutoTreeTraitTestCase 18 | { 19 | /** 20 | * @inheritdoc 21 | */ 22 | public function getDataSet() 23 | { 24 | return new \PHPUnit_Extensions_Database_DataSet_ArrayDataSet(require(__DIR__ . '/data/data-ni.php')); 25 | } 26 | 27 | public function getModelClass() 28 | { 29 | return NodeAlNi::className(); 30 | } 31 | 32 | public function testMakeRootInsert() 33 | { 34 | $node = new NodeAlNi(['slug' => 'r']); 35 | $this->assertTrue($node->makeRoot()->save()); 36 | 37 | $node->refresh(); 38 | $this->assertEquals(null, $node->parent_id); 39 | $this->assertEquals(0, $node->lft); 40 | $this->assertEquals(2147483647, $node->rgt); 41 | $this->assertEquals(0, $node->depth); 42 | } 43 | 44 | public function testMakeRootUpdate() 45 | { 46 | $node = NodeAlNi::findOne(9); 47 | $this->assertTrue($node->makeRoot()->save()); 48 | 49 | $node->refresh(); 50 | $this->assertEquals(null, $node->parent_id); 51 | $this->assertEquals(0, $node->lft); 52 | $this->assertEquals(2147483647, $node->rgt); 53 | $this->assertEquals(0, $node->depth); 54 | } 55 | 56 | public function testPrependTo() 57 | { 58 | $node = new NodeAlNi(['slug' => 'new']); 59 | $this->assertTrue($node->prependTo(NodeAlNi::findOne(1))->save()); 60 | 61 | $node->refresh(); 62 | $this->assertEquals(1, $node->parent_id); 63 | $this->assertEquals(1, $node->lft); 64 | $this->assertEquals(2, $node->rgt); 65 | $this->assertEquals(1, $node->depth); 66 | } 67 | 68 | public function testPrependToAnotherTree() 69 | { 70 | $node = NodeAlNi::findOne(30); 71 | $this->assertTrue($node->prependTo(NodeAlNi::findOne(4))->save()); 72 | 73 | $node->refresh(); 74 | $this->assertEquals(4, $node->parent_id); 75 | $this->assertEquals(1091940810, $node->lft); 76 | $this->assertEquals(1419523107, $node->rgt); 77 | $this->assertEquals(2, $node->depth); 78 | } 79 | 80 | public function testAppendTo() 81 | { 82 | $node = NodeAlNi::findOne(10); 83 | $this->assertTrue($node->appendTo(NodeAlNi::findOne(18))->save()); 84 | 85 | $node->refresh(); 86 | $this->assertEquals(18, $node->parent_id); 87 | $this->assertEquals(1000013, $node->lft); 88 | $this->assertEquals(1000024, $node->rgt); 89 | $this->assertEquals(4, $node->depth); 90 | } 91 | 92 | public function testInsertBefore() 93 | { 94 | $node = new NodeAlNi(['slug' => 'new']); 95 | $this->assertTrue($node->insertBefore(NodeAlNi::findOne(22))->save()); 96 | 97 | $node->refresh(); 98 | $this->assertEquals(9, $node->parent_id); 99 | $this->assertEquals(300000005, $node->lft); 100 | $this->assertEquals(300000006, $node->rgt); 101 | $this->assertEquals(3, $node->depth); 102 | } 103 | 104 | public function testInsertAfter() 105 | { 106 | $node = NodeAlNi::findOne(32); 107 | $this->assertTrue($node->insertAfter(NodeAlNi::findOne(30))->save()); 108 | 109 | $node->refresh(); 110 | $this->assertEquals(26, $node->parent_id); 111 | $this->assertEquals(2147483644, $node->lft); 112 | $this->assertEquals(2147483646, $node->rgt); 113 | $this->assertEquals(1, $node->depth); 114 | } 115 | 116 | public function testInsertAfterAnotherTree() 117 | { 118 | $node = NodeAlNi::findOne(26); 119 | $this->assertTrue($node->insertAfter(NodeAlNi::findOne(21))->save()); 120 | 121 | $node->refresh(); 122 | $this->assertEquals(9, $node->parent_id); 123 | $this->assertEquals(1031907726, $node->lft); 124 | $this->assertEquals(1784921473, $node->rgt); 125 | $this->assertEquals(3, $node->depth); 126 | } 127 | 128 | public function testDelete() 129 | { 130 | $this->assertEquals(1, NodeAlNi::findOne(30)->delete()); 131 | $this->assertEquals(null, NodeAlNi::findOne(30)); 132 | } 133 | 134 | public function testDeleteWithChildren() 135 | { 136 | $this->assertEquals(10, NodeAlNi::findOne(4)->deleteWithChildren()); 137 | $this->assertEquals(null, NodeAlNi::findOne(24)); 138 | $this->assertEquals(15, NodeAlNi::findOne(1)->deleteWithChildren()); 139 | } 140 | } -------------------------------------------------------------------------------- /tests/AlNsTest.php: -------------------------------------------------------------------------------- 1 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | namespace paulzi\autotree\tests; 9 | 10 | use paulzi\autotree\tests\models\NodeAlNs; 11 | use Yii; 12 | 13 | /** 14 | * @author PaulZi 15 | * @group AlNs 16 | */ 17 | class AlNsTest extends AutoTreeTraitTestCase 18 | { 19 | public function getModelClass() 20 | { 21 | return NodeAlNs::className(); 22 | } 23 | 24 | public function testMakeRootInsert() 25 | { 26 | $node = new NodeAlNs(['slug' => 'r']); 27 | $this->assertTrue($node->makeRoot()->save()); 28 | 29 | $node->refresh(); 30 | $this->assertEquals(null, $node->parent_id); 31 | $this->assertEquals(1, $node->lft); 32 | $this->assertEquals(2, $node->rgt); 33 | $this->assertEquals(0, $node->depth); 34 | } 35 | 36 | public function testMakeRootUpdate() 37 | { 38 | $node = NodeAlNs::findOne(9); 39 | $this->assertTrue($node->makeRoot()->save()); 40 | 41 | $node->refresh(); 42 | $this->assertEquals(null, $node->parent_id); 43 | $this->assertEquals(1, $node->lft); 44 | $this->assertEquals(8, $node->rgt); 45 | $this->assertEquals(0, $node->depth); 46 | } 47 | 48 | public function testPrependTo() 49 | { 50 | $node = new NodeAlNs(['slug' => 'new']); 51 | $this->assertTrue($node->prependTo(NodeAlNs::findOne(1))->save()); 52 | 53 | $node->refresh(); 54 | $this->assertEquals(1, $node->parent_id); 55 | $this->assertEquals(2, $node->lft); 56 | $this->assertEquals(3, $node->rgt); 57 | $this->assertEquals(1, $node->depth); 58 | } 59 | 60 | public function testPrependToAnotherTree() 61 | { 62 | $node = NodeAlNs::findOne(30); 63 | $this->assertTrue($node->prependTo(NodeAlNs::findOne(4))->save()); 64 | 65 | $node->refresh(); 66 | $this->assertEquals(4, $node->parent_id); 67 | $this->assertEquals(31, $node->lft); 68 | $this->assertEquals(40, $node->rgt); 69 | $this->assertEquals(2, $node->depth); 70 | } 71 | 72 | public function testAppendTo() 73 | { 74 | $node = NodeAlNs::findOne(10); 75 | $this->assertTrue($node->appendTo(NodeAlNs::findOne(18))->save()); 76 | 77 | $node->refresh(); 78 | $this->assertEquals(18, $node->parent_id); 79 | $this->assertEquals(23, $node->lft); 80 | $this->assertEquals(30, $node->rgt); 81 | $this->assertEquals(4, $node->depth); 82 | } 83 | 84 | public function testInsertBefore() 85 | { 86 | $node = new NodeAlNs(['slug' => 'new']); 87 | $this->assertTrue($node->insertBefore(NodeAlNs::findOne(22))->save()); 88 | 89 | $node->refresh(); 90 | $this->assertEquals(9, $node->parent_id); 91 | $this->assertEquals(38, $node->lft); 92 | $this->assertEquals(39, $node->rgt); 93 | $this->assertEquals(3, $node->depth); 94 | } 95 | 96 | public function testInsertAfter() 97 | { 98 | $node = NodeAlNs::findOne(32); 99 | $this->assertTrue($node->insertAfter(NodeAlNs::findOne(30))->save()); 100 | 101 | $node->refresh(); 102 | $this->assertEquals(26, $node->parent_id); 103 | $this->assertEquals(26, $node->lft); 104 | $this->assertEquals(27, $node->rgt); 105 | $this->assertEquals(1, $node->depth); 106 | } 107 | 108 | public function testInsertAfterAnotherTree() 109 | { 110 | $node = NodeAlNs::findOne(26); 111 | $this->assertTrue($node->insertAfter(NodeAlNs::findOne(21))->save()); 112 | 113 | $node->refresh(); 114 | $this->assertEquals(9, $node->parent_id); 115 | $this->assertEquals(38, $node->lft); 116 | $this->assertEquals(65, $node->rgt); 117 | $this->assertEquals(3, $node->depth); 118 | } 119 | 120 | public function testDelete() 121 | { 122 | $this->assertEquals(1, NodeAlNs::findOne(30)->delete()); 123 | $this->assertEquals(null, NodeAlNs::findOne(30)); 124 | } 125 | 126 | public function testDeleteWithChildren() 127 | { 128 | $this->assertEquals(10, NodeAlNs::findOne(4)->deleteWithChildren()); 129 | $this->assertEquals(null, NodeAlNs::findOne(24)); 130 | $this->assertEquals(15, NodeAlNs::findOne(1)->deleteWithChildren()); 131 | } 132 | } -------------------------------------------------------------------------------- /tests/ArrayDataSet.php: -------------------------------------------------------------------------------- 1 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | namespace paulzi\autotree\tests; 9 | 10 | /** 11 | * @author PaulZi 12 | */ 13 | class ArrayDataSet extends \PHPUnit_Extensions_Database_DataSet_ArrayDataSet 14 | { 15 | public function __construct(array $data) 16 | { 17 | foreach ($data as $tableName => $rows) { 18 | $columns = array(); 19 | if (isset($rows['columns'])) { 20 | $columns = $rows['columns']; 21 | unset($rows['columns']); 22 | } elseif (isset($rows[0])) { 23 | $columns = array_keys($rows[0]); 24 | } 25 | 26 | $metaData = new \PHPUnit_Extensions_Database_DataSet_DefaultTableMetaData($tableName, $columns); 27 | $table = new \PHPUnit_Extensions_Database_DataSet_DefaultTable($metaData); 28 | 29 | foreach ($rows AS $row) { 30 | $table->addRow($row); 31 | } 32 | $this->tables[$tableName] = $table; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /tests/AutoTreeTraitTestCase.php: -------------------------------------------------------------------------------- 1 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | namespace paulzi\autotree\tests; 9 | 10 | use Yii; 11 | 12 | /** 13 | * @author PaulZi 14 | */ 15 | class AutoTreeTraitTestCase extends BaseTestCase 16 | { 17 | /** 18 | * @return \yii\db\BaseActiveRecord 19 | */ 20 | public function getModelClass() 21 | { 22 | return null; 23 | } 24 | 25 | public function testGetParents() 26 | { 27 | $modelClass = $this->getModelClass(); 28 | 29 | $data = [1, 4, 9]; 30 | $this->assertEquals($data, array_map(function ($value) { return $value->id; }, $modelClass::findOne(21)->parents)); 31 | 32 | $data = []; 33 | $this->assertEquals($data, array_map(function ($value) { return $value->id; }, $modelClass::findOne(1)->parents)); 34 | 35 | $data = [2, 7]; 36 | $this->assertEquals($data, array_map(function ($value) { return $value->id; }, $modelClass::findOne(17)->getParents(2)->all())); 37 | 38 | $data = [26, 30]; 39 | $this->assertEquals($data, array_map(function ($value) { return $value->id; }, $modelClass::findOne(38)->parents)); 40 | } 41 | 42 | public function testGetParent() 43 | { 44 | $modelClass = $this->getModelClass(); 45 | $this->assertEquals(5, $modelClass::findOne(12)->parent->id); 46 | $this->assertEquals(26, $modelClass::findOne(29)->getParent()->one()->getAttribute('id')); 47 | $this->assertEquals(null, $modelClass::findOne(1)->parent); 48 | } 49 | 50 | public function testGetRoot() 51 | { 52 | $modelClass = $this->getModelClass(); 53 | $this->assertEquals(26, $modelClass::findOne(28)->root->id); 54 | $this->assertEquals(26, $modelClass::findOne(26)->getRoot()->one()->getAttribute('id')); 55 | } 56 | 57 | public function testGetDescendants() 58 | { 59 | $modelClass = $this->getModelClass(); 60 | 61 | $data = [8, 9, 10, 20, 21, 22, 23, 24, 25]; 62 | $data2 = array_map(function ($value) { return $value->id; }, $modelClass::findOne(4)->descendants); 63 | sort($data2); 64 | $this->assertEquals($data, $data2); 65 | 66 | $data = [2, 5, 6, 7]; 67 | $data2 = array_map(function ($value) { return $value->id; }, $modelClass::findOne(2)->getDescendants(1, true)->all()); 68 | sort($data2); 69 | $this->assertEquals($data, $data2); 70 | 71 | $data = []; 72 | $this->assertEquals($data, array_map(function ($value) { return $value->id; }, $modelClass::findOne(8)->descendants)); 73 | } 74 | 75 | public function testGetChildren() 76 | { 77 | $modelClass = $this->getModelClass(); 78 | 79 | $data = [8, 9, 10]; 80 | $this->assertEquals($data, array_map(function ($value) { return $value->id; }, $modelClass::findOne(4)->children)); 81 | 82 | $data = []; 83 | $this->assertEquals($data, array_map(function ($value) { return $value->id; }, $modelClass::findOne(28)->getChildren()->all())); 84 | } 85 | 86 | public function testGetLeaves() 87 | { 88 | $modelClass = $this->getModelClass(); 89 | 90 | $data = [8, 20, 21, 22, 23, 24, 25]; 91 | $this->assertEquals($data, array_map(function ($value) { return $value->id; }, $modelClass::findOne(4)->leaves)); 92 | 93 | $data = [3, 8]; 94 | $this->assertEquals($data, array_map(function ($value) { return $value->id; }, $modelClass::findOne(1)->getLeaves(2)->all())); 95 | } 96 | 97 | public function testGetPrev() 98 | { 99 | $modelClass = $this->getModelClass(); 100 | $this->assertEquals(11, $modelClass::findOne(12)->prev->id); 101 | $this->assertEquals(null, $modelClass::findOne(20)->getPrev()->one()); 102 | } 103 | 104 | public function testGetNext() 105 | { 106 | $modelClass = $this->getModelClass(); 107 | $this->assertEquals(13, $modelClass::findOne(12)->next->id); 108 | $this->assertEquals(null, $modelClass::findOne(19)->getNext()->one()); 109 | } 110 | 111 | public function testIsRoot() 112 | { 113 | $modelClass = $this->getModelClass(); 114 | $this->assertTrue($modelClass::findOne(1)->isRoot()); 115 | $this->assertTrue($modelClass::findOne(26)->isRoot()); 116 | $this->assertFalse($modelClass::findOne(3)->isRoot()); 117 | $this->assertFalse($modelClass::findOne(37)->isRoot()); 118 | } 119 | 120 | public function testIsChildOf() 121 | { 122 | $modelClass = $this->getModelClass(); 123 | $this->assertTrue($modelClass::findOne(10)->isChildOf($modelClass::findOne(1))); 124 | $this->assertTrue($modelClass::findOne(9)->isChildOf($modelClass::findOne(4))); 125 | $this->assertFalse($modelClass::findOne(12)->isChildOf($modelClass::findOne(15))); 126 | $this->assertFalse($modelClass::findOne(21)->isChildOf($modelClass::findOne(22))); 127 | $this->assertFalse($modelClass::findOne(8)->isChildOf($modelClass::findOne(8))); 128 | $this->assertFalse($modelClass::findOne(6)->isChildOf($modelClass::findOne(27))); 129 | } 130 | 131 | public function testIsLeaf() 132 | { 133 | $modelClass = $this->getModelClass(); 134 | $this->assertTrue($modelClass::findOne(3)->isLeaf()); 135 | $this->assertFalse($modelClass::findOne(4)->isLeaf()); 136 | } 137 | } -------------------------------------------------------------------------------- /tests/BaseTestCase.php: -------------------------------------------------------------------------------- 1 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | namespace paulzi\autotree\tests; 9 | 10 | use paulzi\autotree\tests\migrations\TestMigration; 11 | use Yii; 12 | use yii\db\Connection; 13 | 14 | /** 15 | * @author PaulZi 16 | */ 17 | class BaseTestCase extends \PHPUnit_Extensions_Database_TestCase 18 | { 19 | protected static $driverName = 'sqlite'; 20 | 21 | 22 | /** 23 | * @inheritdoc 24 | */ 25 | public function getConnection() 26 | { 27 | return $this->createDefaultDBConnection(Yii::$app->getDb()->pdo); 28 | } 29 | 30 | /** 31 | * @inheritdoc 32 | */ 33 | public function getDataSet() 34 | { 35 | return new \PHPUnit_Extensions_Database_DataSet_ArrayDataSet(require(__DIR__ . '/data/data.php')); 36 | } 37 | 38 | /** 39 | * @inheritdoc 40 | */ 41 | protected function setUp() 42 | { 43 | if (Yii::$app->get('db', false) === null) { 44 | $this->markTestSkipped(); 45 | } else { 46 | (new TestMigration())->up(); 47 | parent::setUp(); 48 | } 49 | } 50 | 51 | /** 52 | * @inheritdoc 53 | */ 54 | public static function setUpBeforeClass() 55 | { 56 | $config = require(__DIR__ . '/data/config.php'); 57 | $config = $config[static::$driverName]; 58 | $config['class'] = Connection::className(); 59 | try { 60 | Yii::$app->set('db', $config); 61 | Yii::$app->getDb()->open(); 62 | } catch (\Exception $e) { 63 | Yii::$app->clear('db'); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # Yii2 Auto Tree Trait unit tests 2 | 3 | ## How to run the test 4 | 5 | Make sure you have PHPUnit installed and that you installed all composer dependencies (run `composer update` in the repo base directory). 6 | 7 | Run PHPUnit in the yii repo base directory. 8 | 9 | ``` 10 | phpunit 11 | ``` 12 | 13 | You can run tests for specific groups only: 14 | 15 | ``` 16 | phpunit --group=AiNs 17 | ``` 18 | 19 | You can get a list of available groups via `phpunit --list-groups`. 20 | 21 | ## test configurations 22 | 23 | PHPUnit configuration is in `phpunit.xml.dist` in repository root folder. 24 | You can create your own phpunit.xml to override dist config. 25 | 26 | Database and other backend system configuration can be found in `tests/data/config.php` 27 | adjust them to your needs to allow testing databases and caching in your environment. 28 | You can override configuration values by creating a `config.local.php` file 29 | and manipulate the `$config` variable. 30 | For example to change MySQL username and password your `config.local.php` should 31 | contain the following: 32 | 33 | ```php 34 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | defined('YII_DEBUG') or define('YII_DEBUG', true); 9 | defined('YII_ENV') or define('YII_ENV', 'test'); 10 | 11 | require(__DIR__ . '/../vendor/autoload.php'); 12 | require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php'); 13 | 14 | Yii::setAlias('@tests', __DIR__); 15 | 16 | new \yii\console\Application([ 17 | 'id' => 'unit', 18 | 'basePath' => __DIR__, 19 | ]); -------------------------------------------------------------------------------- /tests/data/config.php: -------------------------------------------------------------------------------- 1 | [ 4 | 'dsn' => 'sqlite::memory:', 5 | ], 6 | 'mysql' => [ 7 | 'dsn' => 'mysql:host=localhost;dbname=test', 8 | 'username' => 'root', 9 | 'password' => '', 10 | 'charset' => 'utf8', 11 | ], 12 | 'mssql' => [ 13 | 'dsn' => 'sqlsrv:Server=localhost;Database=test', 14 | 'username' => '', 15 | 'password' => '', 16 | ], 17 | 'pgsql' => [ 18 | 'dsn' => 'pgsql:host=localhost;dbname=test;port=5432;', 19 | 'username' => 'postgres', 20 | 'password' => 'postgres', 21 | ], 22 | ]; 23 | 24 | if (is_file(__DIR__ . '/config.local.php')) { 25 | include(__DIR__ . '/config.local.php'); 26 | } 27 | 28 | return $config; -------------------------------------------------------------------------------- /tests/data/data-ni.php: -------------------------------------------------------------------------------- 1 | array( 4 | array('id' => '1','parent_id' => null,'sort' => '0', 'tree' => '1','lft' => '0','rgt' => '2147483647','depth' => '0','path' => '1','slug' => 'r1'), 5 | array('id' => '2','parent_id' => '1','sort' => '-1','tree' => '1','lft' => '1','rgt' => '1000021','depth' => '1','path' => '1/2','slug' => 'n1'), 6 | array('id' => '3','parent_id' => '1','sort' => '0','tree' => '1','lft' => '10000000','rgt' => '20000000','depth' => '1','path' => '1/3','slug' => 'n2'), 7 | array('id' => '4','parent_id' => '1','sort' => '1','tree' => '1','lft' => '100000000','rgt' => '1987654321','depth' => '1','path' => '1/4','slug' => 'n3'), 8 | array('id' => '5','parent_id' => '2','sort' => '0','tree' => '1','lft' => '2','rgt' => '30002','depth' => '2','path' => '1/2/5','slug' => 'n11'), 9 | array('id' => '6','parent_id' => '2','sort' => '100','tree' => '1','lft' => '30003','rgt' => '1000000','depth' => '2','path' => '1/2/6','slug' => 'n12'), 10 | array('id' => '7','parent_id' => '2','sort' => '200','tree' => '1','lft' => '1000001','rgt' => '1000020','depth' => '2','path' => '1/2/7','slug' => 'n13'), 11 | array('id' => '8','parent_id' => '4','sort' => '0','tree' => '1','lft' => '200000000','rgt' => '200000002','depth' => '2','path' => '1/4/8','slug' => 'n31'), 12 | array('id' => '9','parent_id' => '4','sort' => '1','tree' => '1','lft' => '300000000','rgt' => '300000007','depth' => '2','path' => '1/4/9','slug' => 'n32'), 13 | array('id' => '10','parent_id' => '4','sort' => '100','tree' => '1','lft' => '1234567890','rgt' => '1234567901','depth' => '2','path' => '1/4/10','slug' => 'n33'), 14 | array('id' => '11','parent_id' => '5','sort' => '0','tree' => '1','lft' => '3','rgt' => '4','depth' => '3','path' => '1/2/5/11','slug' => 'n111'), 15 | array('id' => '12','parent_id' => '5','sort' => '99','tree' => '1','lft' => '10000','rgt' => '20000','depth' => '3','path' => '1/2/5/12','slug' => 'n112'), 16 | array('id' => '13','parent_id' => '5','sort' => '100','tree' => '1','lft' => '20001','rgt' => '30000','depth' => '3','path' => '1/2/5/13','slug' => 'n113'), 17 | array('id' => '14','parent_id' => '6','sort' => '-100','tree' => '1','lft' => '444444','rgt' => '444544','depth' => '3','path' => '1/2/6/14','slug' => 'n121'), 18 | array('id' => '15','parent_id' => '6','sort' => '-99','tree' => '1','lft' => '666666','rgt' => '777777','depth' => '3','path' => '1/2/6/15','slug' => 'n122'), 19 | array('id' => '16','parent_id' => '6','sort' => '-98','tree' => '1','lft' => '888888','rgt' => '888898','depth' => '3','path' => '1/2/6/16','slug' => 'n123'), 20 | array('id' => '17','parent_id' => '7','sort' => '-100','tree' => '1','lft' => '1000004','rgt' => '1000007','depth' => '3','path' => '1/2/7/17','slug' => 'n131'), 21 | array('id' => '18','parent_id' => '7','sort' => '0','tree' => '1','lft' => '1000010','rgt' => '1000013','depth' => '3','path' => '1/2/7/18','slug' => 'n132'), 22 | array('id' => '19','parent_id' => '7','sort' => '100','tree' => '1','lft' => '1000016','rgt' => '1000019','depth' => '3','path' => '1/2/7/19','slug' => 'n133'), 23 | array('id' => '20','parent_id' => '9','sort' => '0','tree' => '1','lft' => '300000001','rgt' => '300000002','depth' => '3','path' => '1/4/9/20','slug' => 'n321'), 24 | array('id' => '21','parent_id' => '9','sort' => '2','tree' => '1','lft' => '300000003','rgt' => '300000004','depth' => '3','path' => '1/4/9/21','slug' => 'n322'), 25 | array('id' => '22','parent_id' => '9','sort' => '4','tree' => '1','lft' => '300000005','rgt' => '300000006','depth' => '3','path' => '1/4/9/22','slug' => 'n323'), 26 | array('id' => '23','parent_id' => '10','sort' => '0','tree' => '1','lft' => '1234567892','rgt' => '1234567893','depth' => '3','path' => '1/4/10/23','slug' => 'n331'), 27 | array('id' => '24','parent_id' => '10','sort' => '100','tree' => '1','lft' => '1234567895','rgt' => '1234567896','depth' => '3','path' => '1/4/10/24','slug' => 'n332'), 28 | array('id' => '25','parent_id' => '10','sort' => '200','tree' => '1','lft' => '1234567898','rgt' => '1234567899','depth' => '3','path' => '1/4/10/25','slug' => 'n333'), 29 | 30 | array('id' => '26','parent_id' => null,'sort' => '0','tree' => '26','lft' => '0','rgt' => '2147483647','depth' => '0','path' => '26','slug' => 'r2'), 31 | array('id' => '27','parent_id' => '26','sort' => '-1','tree' => '26','lft' => '10000','rgt' => '10018','depth' => '1','path' => '26/27','slug' => 'n1'), 32 | array('id' => '28','parent_id' => '26','sort' => '0','tree' => '26','lft' => '2323287','rgt' => '2323288','depth' => '1','path' => '26/28','slug' => 'n2'), 33 | array('id' => '29','parent_id' => '26','sort' => '1','tree' => '26','lft' => '72938298','rgt' => '72938302','depth' => '1','path' => '26/29','slug' => 'n3'), 34 | array('id' => '30','parent_id' => '26','sort' => '2','tree' => '26','lft' => '2039849384','rgt' => '2147483646','depth' => '1','path' => '26/30','slug' => 'n4'), 35 | array('id' => '31','parent_id' => '27','sort' => '0','tree' => '26','lft' => '10002','rgt' => '10004','depth' => '2','path' => '26/27/31','slug' => 'n11'), 36 | array('id' => '32','parent_id' => '27','sort' => '1','tree' => '26','lft' => '10006','rgt' => '10008','depth' => '2','path' => '26/27/32','slug' => 'n12'), 37 | array('id' => '33','parent_id' => '27','sort' => '2','tree' => '26','lft' => '10010','rgt' => '10012','depth' => '2','path' => '26/27/33','slug' => 'n13'), 38 | array('id' => '34','parent_id' => '27','sort' => '4','tree' => '26','lft' => '10014','rgt' => '10016','depth' => '2','path' => '26/27/34','slug' => 'n14'), 39 | array('id' => '35','parent_id' => '29','sort' => '0','tree' => '26','lft' => '72938299','rgt' => '72938301','depth' => '2','path' => '26/29/35','slug' => 'n31'), 40 | array('id' => '36','parent_id' => '30','sort' => '0','tree' => '26','lft' => '2147483637','rgt' => '2147483638','depth' => '2','path' => '26/30/36','slug' => 'n41'), 41 | array('id' => '37','parent_id' => '30','sort' => '100','tree' => '26','lft' => '2147483639','rgt' => '2147483640','depth' => '2','path' => '26/30/36','slug' => 'n42'), 42 | array('id' => '38','parent_id' => '30','sort' => '200','tree' => '26','lft' => '2147483642','rgt' => '2147483643','depth' => '2','path' => '26/30/36','slug' => 'n43'), 43 | array('id' => '39','parent_id' => '30','sort' => '300','tree' => '26','lft' => '2147483644','rgt' => '2147483645','depth' => '2','path' => '26/30/36','slug' => 'n44'), 44 | ), 45 | ); -------------------------------------------------------------------------------- /tests/data/data.php: -------------------------------------------------------------------------------- 1 | array( 4 | array('id' => '1','parent_id' => null,'sort' => '0', 'tree' => '1','lft' => '1','rgt' => '50','depth' => '0','path' => '1','slug' => 'r1'), 5 | array('id' => '2','parent_id' => '1','sort' => '-1','tree' => '1','lft' => '2','rgt' => '27','depth' => '1','path' => '1/2','slug' => 'n1'), 6 | array('id' => '3','parent_id' => '1','sort' => '0','tree' => '1','lft' => '28','rgt' => '29','depth' => '1','path' => '1/3','slug' => 'n2'), 7 | array('id' => '4','parent_id' => '1','sort' => '1','tree' => '1','lft' => '30','rgt' => '49','depth' => '1','path' => '1/4','slug' => 'n3'), 8 | array('id' => '5','parent_id' => '2','sort' => '0','tree' => '1','lft' => '3','rgt' => '10','depth' => '2','path' => '1/2/5','slug' => 'n11'), 9 | array('id' => '6','parent_id' => '2','sort' => '100','tree' => '1','lft' => '11','rgt' => '18','depth' => '2','path' => '1/2/6','slug' => 'n12'), 10 | array('id' => '7','parent_id' => '2','sort' => '200','tree' => '1','lft' => '19','rgt' => '26','depth' => '2','path' => '1/2/7','slug' => 'n13'), 11 | array('id' => '8','parent_id' => '4','sort' => '0','tree' => '1','lft' => '31','rgt' => '32','depth' => '2','path' => '1/4/8','slug' => 'n31'), 12 | array('id' => '9','parent_id' => '4','sort' => '1','tree' => '1','lft' => '33','rgt' => '40','depth' => '2','path' => '1/4/9','slug' => 'n32'), 13 | array('id' => '10','parent_id' => '4','sort' => '100','tree' => '1','lft' => '41','rgt' => '48','depth' => '2','path' => '1/4/10','slug' => 'n33'), 14 | array('id' => '11','parent_id' => '5','sort' => '0','tree' => '1','lft' => '4','rgt' => '5','depth' => '3','path' => '1/2/5/11','slug' => 'n111'), 15 | array('id' => '12','parent_id' => '5','sort' => '99','tree' => '1','lft' => '6','rgt' => '7','depth' => '3','path' => '1/2/5/12','slug' => 'n112'), 16 | array('id' => '13','parent_id' => '5','sort' => '100','tree' => '1','lft' => '8','rgt' => '9','depth' => '3','path' => '1/2/5/13','slug' => 'n113'), 17 | array('id' => '14','parent_id' => '6','sort' => '-100','tree' => '1','lft' => '12','rgt' => '13','depth' => '3','path' => '1/2/6/14','slug' => 'n121'), 18 | array('id' => '15','parent_id' => '6','sort' => '-99','tree' => '1','lft' => '14','rgt' => '15','depth' => '3','path' => '1/2/6/15','slug' => 'n122'), 19 | array('id' => '16','parent_id' => '6','sort' => '-98','tree' => '1','lft' => '16','rgt' => '17','depth' => '3','path' => '1/2/6/16','slug' => 'n123'), 20 | array('id' => '17','parent_id' => '7','sort' => '-100','tree' => '1','lft' => '20','rgt' => '21','depth' => '3','path' => '1/2/7/17','slug' => 'n131'), 21 | array('id' => '18','parent_id' => '7','sort' => '0','tree' => '1','lft' => '22','rgt' => '23','depth' => '3','path' => '1/2/7/18','slug' => 'n132'), 22 | array('id' => '19','parent_id' => '7','sort' => '100','tree' => '1','lft' => '24','rgt' => '25','depth' => '3','path' => '1/2/7/19','slug' => 'n133'), 23 | array('id' => '20','parent_id' => '9','sort' => '0','tree' => '1','lft' => '34','rgt' => '35','depth' => '3','path' => '1/4/9/20','slug' => 'n321'), 24 | array('id' => '21','parent_id' => '9','sort' => '2','tree' => '1','lft' => '36','rgt' => '37','depth' => '3','path' => '1/4/9/21','slug' => 'n322'), 25 | array('id' => '22','parent_id' => '9','sort' => '4','tree' => '1','lft' => '38','rgt' => '39','depth' => '3','path' => '1/4/9/22','slug' => 'n323'), 26 | array('id' => '23','parent_id' => '10','sort' => '0','tree' => '1','lft' => '42','rgt' => '43','depth' => '3','path' => '1/4/10/23','slug' => 'n331'), 27 | array('id' => '24','parent_id' => '10','sort' => '100','tree' => '1','lft' => '44','rgt' => '45','depth' => '3','path' => '1/4/10/24','slug' => 'n332'), 28 | array('id' => '25','parent_id' => '10','sort' => '200','tree' => '1','lft' => '46','rgt' => '47','depth' => '3','path' => '1/4/10/25','slug' => 'n333'), 29 | 30 | array('id' => '26','parent_id' => null,'sort' => '0','tree' => '26','lft' => '1','rgt' => '28','depth' => '0','path' => '26','slug' => 'r2'), 31 | array('id' => '27','parent_id' => '26','sort' => '-1','tree' => '26','lft' => '2','rgt' => '11','depth' => '1','path' => '26/27','slug' => 'n1'), 32 | array('id' => '28','parent_id' => '26','sort' => '0','tree' => '26','lft' => '12','rgt' => '13','depth' => '1','path' => '26/28','slug' => 'n2'), 33 | array('id' => '29','parent_id' => '26','sort' => '1','tree' => '26','lft' => '14','rgt' => '17','depth' => '1','path' => '26/29','slug' => 'n3'), 34 | array('id' => '30','parent_id' => '26','sort' => '2','tree' => '26','lft' => '18','rgt' => '27','depth' => '1','path' => '26/30','slug' => 'n4'), 35 | array('id' => '31','parent_id' => '27','sort' => '0','tree' => '26','lft' => '3','rgt' => '4','depth' => '2','path' => '26/27/31','slug' => 'n11'), 36 | array('id' => '32','parent_id' => '27','sort' => '1','tree' => '26','lft' => '5','rgt' => '6','depth' => '2','path' => '26/27/32','slug' => 'n12'), 37 | array('id' => '33','parent_id' => '27','sort' => '2','tree' => '26','lft' => '7','rgt' => '8','depth' => '2','path' => '26/27/33','slug' => 'n13'), 38 | array('id' => '34','parent_id' => '27','sort' => '4','tree' => '26','lft' => '9','rgt' => '10','depth' => '2','path' => '26/27/34','slug' => 'n14'), 39 | array('id' => '35','parent_id' => '29','sort' => '0','tree' => '26','lft' => '15','rgt' => '16','depth' => '2','path' => '26/29/35','slug' => 'n31'), 40 | array('id' => '36','parent_id' => '30','sort' => '0','tree' => '26','lft' => '19','rgt' => '20','depth' => '2','path' => '26/30/36','slug' => 'n41'), 41 | array('id' => '37','parent_id' => '30','sort' => '100','tree' => '26','lft' => '21','rgt' => '22','depth' => '2','path' => '26/30/36','slug' => 'n42'), 42 | array('id' => '38','parent_id' => '30','sort' => '200','tree' => '26','lft' => '23','rgt' => '24','depth' => '2','path' => '26/30/36','slug' => 'n43'), 43 | array('id' => '39','parent_id' => '30','sort' => '300','tree' => '26','lft' => '25','rgt' => '26','depth' => '2','path' => '26/30/36','slug' => 'n44'), 44 | ), 45 | ); -------------------------------------------------------------------------------- /tests/migrations/TestMigration.php: -------------------------------------------------------------------------------- 1 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | namespace paulzi\autotree\tests\migrations; 9 | 10 | use yii\db\Schema; 11 | use yii\db\Migration; 12 | 13 | /** 14 | * @author PaulZi 15 | */ 16 | class TestMigration extends Migration 17 | { 18 | public function up() 19 | { 20 | ob_start(); 21 | $tableOptions = null; 22 | if ($this->db->driverName === 'mysql') { 23 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 24 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; 25 | } 26 | 27 | if ($this->db->getTableSchema('{{%tree}}', true) !== null) { 28 | $this->dropTable('{{%tree}}'); 29 | } 30 | $this->createTable('{{%tree}}', [ 31 | 'id' => Schema::TYPE_PK, 32 | 'parent_id' => Schema::TYPE_INTEGER . ' NULL', 33 | 'sort' => Schema::TYPE_INTEGER . ' NULL', 34 | 'tree' => Schema::TYPE_INTEGER . ' NULL', 35 | 'lft' => Schema::TYPE_INTEGER . ' NULL', 36 | 'rgt' => Schema::TYPE_INTEGER . ' NULL', 37 | 'depth' => Schema::TYPE_INTEGER . ' NULL', 38 | 'path' => Schema::TYPE_STRING . ' NULL', 39 | 'slug' => Schema::TYPE_STRING . ' NOT NULL', 40 | ], $tableOptions); 41 | $this->createIndex('parent_sort', '{{%tree}}', ['parent_id', 'sort']); 42 | $this->createIndex('lft', '{{%tree}}', ['tree', 'lft', 'rgt']); 43 | $this->createIndex('rgt', '{{%tree}}', ['tree', 'rgt']); 44 | $this->createIndex('path', '{{%tree}}', ['tree', 'path']); 45 | 46 | // update cache (sqlite bug) 47 | $this->db->getSchema()->getTableSchema('{{%tree}}', true); 48 | ob_end_clean(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/models/NodeAlMp.php: -------------------------------------------------------------------------------- 1 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | namespace paulzi\autotree\tests\models; 9 | 10 | use paulzi\adjacencyList\AdjacencyListBehavior; 11 | use paulzi\materializedPath\MaterializedPathBehavior; 12 | use paulzi\autotree\AutoTreeTrait; 13 | 14 | /** 15 | * @author PaulZi 16 | * 17 | * @property integer $id 18 | * @property integer $parent_id 19 | * @property integer $sort 20 | * @property integer $tree 21 | * @property integer $lft 22 | * @property integer $rgt 23 | * @property integer $depth 24 | * @property string $path 25 | * @property string $slug 26 | * 27 | * @property NodeAlMp[] $parents 28 | * @property NodeAlMp $parent 29 | * @property NodeAlMp $root 30 | * @property NodeAlMp[] $descendants 31 | * @property NodeAlMp[] $children 32 | * @property NodeAlMp[] $leaves 33 | * @property NodeAlMp $prev 34 | * @property NodeAlMp $next 35 | * 36 | * @method static NodeAlMp|null findOne() findOne($condition) 37 | * 38 | * @mixin AdjacencyListBehavior 39 | * @mixin MaterializedPathBehavior 40 | */ 41 | class NodeAlMp extends \yii\db\ActiveRecord 42 | { 43 | use AutoTreeTrait; 44 | 45 | /** 46 | * @inheritdoc 47 | */ 48 | public static function tableName() 49 | { 50 | return '{{%tree}}'; 51 | } 52 | /** 53 | * @inheritdoc 54 | */ 55 | public function behaviors() 56 | { 57 | return [ 58 | [ 59 | 'class' => AdjacencyListBehavior::className(), 60 | 'sortable' => false, 61 | ], 62 | [ 63 | 'class' => MaterializedPathBehavior::className(), 64 | ], 65 | ]; 66 | } 67 | 68 | /** 69 | * @inheritdoc 70 | */ 71 | public function transactions() 72 | { 73 | return [ 74 | self::SCENARIO_DEFAULT => self::OP_ALL, 75 | ]; 76 | } 77 | 78 | /** 79 | * @return NodeQuery 80 | */ 81 | public static function find() 82 | { 83 | return new NodeQuery(get_called_class()); 84 | } 85 | } -------------------------------------------------------------------------------- /tests/models/NodeAlNi.php: -------------------------------------------------------------------------------- 1 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | namespace paulzi\autotree\tests\models; 9 | 10 | use paulzi\adjacencyList\AdjacencyListBehavior; 11 | use paulzi\nestedintervals\NestedIntervalsBehavior; 12 | use paulzi\autotree\AutoTreeTrait; 13 | 14 | /** 15 | * @author PaulZi 16 | * 17 | * @property integer $id 18 | * @property integer $parent_id 19 | * @property integer $sort 20 | * @property integer $tree 21 | * @property integer $lft 22 | * @property integer $rgt 23 | * @property integer $depth 24 | * @property string $path 25 | * @property string $slug 26 | * 27 | * @property NodeAlNi[] $parents 28 | * @property NodeAlNi $parent 29 | * @property NodeAlNi $root 30 | * @property NodeAlNi[] $descendants 31 | * @property NodeAlNi[] $children 32 | * @property NodeAlNi[] $leaves 33 | * @property NodeAlNi $prev 34 | * @property NodeAlNi $next 35 | * 36 | * @method static NodeAlNi|null findOne() findOne($condition) 37 | * 38 | * @mixin AdjacencyListBehavior 39 | * @mixin NestedIntervalsBehavior 40 | */ 41 | class NodeAlNi extends \yii\db\ActiveRecord 42 | { 43 | use AutoTreeTrait; 44 | 45 | /** 46 | * @inheritdoc 47 | */ 48 | public static function tableName() 49 | { 50 | return '{{%tree}}'; 51 | } 52 | /** 53 | * @inheritdoc 54 | */ 55 | public function behaviors() 56 | { 57 | return [ 58 | [ 59 | 'class' => AdjacencyListBehavior::className(), 60 | 'sortable' => false, 61 | ], 62 | [ 63 | 'class' => NestedIntervalsBehavior::className(), 64 | 'treeAttribute' => 'tree', 65 | ], 66 | ]; 67 | } 68 | 69 | /** 70 | * @inheritdoc 71 | */ 72 | public function transactions() 73 | { 74 | return [ 75 | self::SCENARIO_DEFAULT => self::OP_ALL, 76 | ]; 77 | } 78 | 79 | /** 80 | * @return NodeQuery 81 | */ 82 | public static function find() 83 | { 84 | return new NodeQuery(get_called_class()); 85 | } 86 | } -------------------------------------------------------------------------------- /tests/models/NodeAlNs.php: -------------------------------------------------------------------------------- 1 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | namespace paulzi\autotree\tests\models; 9 | 10 | use paulzi\adjacencyList\AdjacencyListBehavior; 11 | use paulzi\nestedsets\NestedSetsBehavior; 12 | use paulzi\autotree\AutoTreeTrait; 13 | 14 | /** 15 | * @author PaulZi 16 | * 17 | * @property integer $id 18 | * @property integer $parent_id 19 | * @property integer $sort 20 | * @property integer $tree 21 | * @property integer $lft 22 | * @property integer $rgt 23 | * @property integer $depth 24 | * @property string $path 25 | * @property string $slug 26 | * 27 | * @property NodeAlNs[] $parents 28 | * @property NodeAlNs $parent 29 | * @property NodeAlNs $root 30 | * @property NodeAlNs[] $descendants 31 | * @property NodeAlNs[] $children 32 | * @property NodeAlNs[] $leaves 33 | * @property NodeAlNs $prev 34 | * @property NodeAlNs $next 35 | * 36 | * @method static NodeAlNs|null findOne() findOne($condition) 37 | * 38 | * @mixin AdjacencyListBehavior 39 | * @mixin NestedSetsBehavior 40 | */ 41 | class NodeAlNs extends \yii\db\ActiveRecord 42 | { 43 | use AutoTreeTrait; 44 | 45 | /** 46 | * @inheritdoc 47 | */ 48 | public static function tableName() 49 | { 50 | return '{{%tree}}'; 51 | } 52 | /** 53 | * @inheritdoc 54 | */ 55 | public function behaviors() 56 | { 57 | return [ 58 | [ 59 | 'class' => AdjacencyListBehavior::className(), 60 | 'sortable' => false, 61 | ], 62 | [ 63 | 'class' => NestedSetsBehavior::className(), 64 | 'treeAttribute' => 'tree', 65 | ], 66 | ]; 67 | } 68 | 69 | /** 70 | * @inheritdoc 71 | */ 72 | public function transactions() 73 | { 74 | return [ 75 | self::SCENARIO_DEFAULT => self::OP_ALL, 76 | ]; 77 | } 78 | 79 | /** 80 | * @return NodeQuery 81 | */ 82 | public static function find() 83 | { 84 | return new NodeQuery(get_called_class()); 85 | } 86 | } -------------------------------------------------------------------------------- /tests/models/NodeQuery.php: -------------------------------------------------------------------------------- 1 | 5 | * @license MIT (https://github.com/paulzi/yii2-auto-tree/blob/master/LICENSE) 6 | */ 7 | 8 | namespace paulzi\autotree\tests\models; 9 | 10 | use paulzi\adjacencyList\AdjacencyListQueryTrait; 11 | 12 | /** 13 | * @author PaulZi 14 | */ 15 | class NodeQuery extends \yii\db\ActiveQuery 16 | { 17 | use AdjacencyListQueryTrait; 18 | } --------------------------------------------------------------------------------