├── .gitignore ├── INSTALL ├── LICENSE ├── Makefile ├── README.md ├── composer.json ├── package.ini ├── package.xml ├── src └── Respect │ └── Conversion │ ├── Converter.php │ ├── Operators │ ├── Chart │ │ └── RowSeries │ │ │ └── Line.php │ ├── Collection │ │ ├── First │ │ │ ├── Append.php │ │ │ ├── Callback.php │ │ │ ├── Delete.php │ │ │ ├── Extract.php │ │ │ ├── Name.php │ │ │ ├── Prepend.php │ │ │ └── Up.php │ │ ├── Item │ │ │ ├── Append.php │ │ │ ├── Callback.php │ │ │ ├── Delete.php │ │ │ ├── Extract.php │ │ │ ├── Name.php │ │ │ ├── Prepend.php │ │ │ └── Up.php │ │ └── Last │ │ │ ├── Append.php │ │ │ ├── Callback.php │ │ │ ├── Delete.php │ │ │ ├── Extract.php │ │ │ ├── Name.php │ │ │ ├── Prepend.php │ │ │ └── Up.php │ ├── Common │ │ └── Common │ │ │ ├── AbstractCallback.php │ │ │ ├── AbstractOperator.php │ │ │ ├── Multi.php │ │ │ └── Sequence.php │ ├── Table │ │ ├── Col │ │ │ ├── Dehydrate.php │ │ │ ├── Delete.php │ │ │ ├── Duplicate.php │ │ │ ├── Hydrate.php │ │ │ ├── Name.php │ │ │ └── Up.php │ │ ├── Multi │ │ │ ├── Append.php │ │ │ ├── Callback.php │ │ │ ├── Delete.php │ │ │ ├── Name.php │ │ │ └── Prepend.php │ │ ├── Td │ │ │ ├── Append.php │ │ │ ├── Callback.php │ │ │ ├── Delete.php │ │ │ ├── Name.php │ │ │ └── Prepend.php │ │ └── Tr │ │ │ ├── Callback.php │ │ │ ├── Delete.php │ │ │ ├── Name.php │ │ │ └── Up.php │ └── Tree │ │ ├── Branch │ │ └── Callback.php │ │ └── Leaf │ │ └── Callback.php │ ├── Selectors │ ├── Chart │ │ ├── RowSeries.php │ │ ├── RowSeriesBindInterface.php │ │ └── RowSeriesSelectInterface.php │ ├── Collection │ │ ├── First.php │ │ ├── FirstBindInterface.php │ │ ├── FirstSelectInterface.php │ │ ├── Item.php │ │ ├── ItemBindInterface.php │ │ ├── ItemSelectInterface.php │ │ ├── Last.php │ │ ├── LastBindInterface.php │ │ └── LastSelectInterface.php │ ├── Common │ │ ├── AbstractSelector.php │ │ ├── Multi.php │ │ ├── MultiBindInterface.php │ │ └── MultiSelectInterface.php │ ├── Table │ │ ├── AbstractTrColInteraction.php │ │ ├── Col.php │ │ ├── ColBindInterface.php │ │ ├── ColSelectInterface.php │ │ ├── Td.php │ │ ├── TdBindInterface.php │ │ ├── TdSelectInterface.php │ │ ├── Tr.php │ │ ├── TrBindInterface.php │ │ └── TrSelectInterface.php │ ├── Tree │ │ ├── Branch.php │ │ ├── BranchBindInterface.php │ │ ├── BranchSelectInterface.php │ │ ├── Leaf.php │ │ ├── LeafBindInterface.php │ │ └── LeafSelectInterface.php │ └── Xml │ │ ├── XpathBindInterface.php │ │ └── XpathSelectInterface.php │ └── Types │ ├── AbstractType.php │ ├── Chart.php │ ├── Collection.php │ ├── Table.php │ ├── TextTable.php │ ├── Tree.php │ └── Xml.php └── tests ├── bootstrap.php ├── phpunit.xml └── src └── Respect └── Conversion └── ConverterTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | .buildpath 3 | .project 4 | .DS_Store 5 | .tm_properties 6 | .settings/ 7 | .foundation-tmp 8 | .foundation 9 | phar 10 | *.phar 11 | tests/reports 12 | pirum 13 | nbproject 14 | *.7z 15 | *.jar 16 | *.rar 17 | *.zip 18 | *.gz 19 | *.bzip 20 | *.xz 21 | *.lock 22 | *.lzma 23 | *.iso 24 | *.tar 25 | *.dmg 26 | *.xpi 27 | *.gem 28 | *.egg 29 | *.deb 30 | *.rpm 31 | *.tgz 32 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | To install Respect/Conversion, you can add it as a composer dependency or by downloading the composer.phar executable. 2 | 3 | $ curl -s http://getcomposer.org/installer | php 4 | 5 | and run install 6 | 7 | $ php composer.phar install 8 | 9 | For more details, see http://getcomposer.org. 10 | 11 | We also have a PEAR channel if you prefer. 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2013, Alexandre Gomes Gaigalas. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of Alexandre Gomes Gaigalas nor the names of its 15 | contributors may be used to endorse or promote products derived from this 16 | software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | Copyright (c) 2005-2011, Zend Technologies USA, Inc. 30 | All rights reserved. 31 | 32 | Redistribution and use in source and binary forms, with or without modification, 33 | are permitted provided that the following conditions are met: 34 | 35 | * Redistributions of source code must retain the above copyright notice, 36 | this list of conditions and the following disclaimer. 37 | 38 | * Redistributions in binary form must reproduce the above copyright notice, 39 | this list of conditions and the following disclaimer in the documentation 40 | and/or other materials provided with the distribution. 41 | 42 | * Neither the name of Zend Technologies USA, Inc. nor the names of its 43 | contributors may be used to endorse or promote products derived from this 44 | software without specific prior written permission. 45 | 46 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 47 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 48 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 49 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 50 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 51 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 52 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 53 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 55 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION = 0.1.11 2 | CONFIG_TOOL = php .foundation/repo/bin/project-config.php 3 | GENERATE_TOOL = php .foundation/repo/bin/project-generate.php 4 | 5 | .title: 6 | @echo "Respect/Foundation - $(VERSION)\n" 7 | 8 | .check-foundation: .title 9 | @test -d .foundation || make -f Makefile foundation 10 | 11 | # Help is not the default target cause its mainly used as the main 12 | # build command. We're reserving it. 13 | default: .title 14 | @echo "See 'make help' for instructions." 15 | 16 | help: .title 17 | @echo " help: Shows this message" 18 | @echo " foundation: Installs and updates Foundation" 19 | @echo " project-info: Shows project configuration" 20 | @echo " test: Run project tests" 21 | @echo " coverage: Run project tests and reports coverage status" 22 | @echo " cs-fixer: Run php coding standard fixer (PHP CS Fixer)" 23 | @echo " clean: Removes code coverage reports" 24 | @echo " patch: Increases the patch version of the project (X.X.++)" 25 | @echo " minor: Increases the minor version of the project (X.++.0)" 26 | @echo " major: Increases the major version of the project (++.0.0)" 27 | @echo " alpha: Changes the stability of the current version to alpha" 28 | @echo " beta: Changes the stability of the current version to beta" 29 | @echo " stable: Changes the stability of the current version to stable" 30 | @echo " tag: Makes a git tag of the current project version/stability" 31 | @echo " package-ini: Creates the basic package.ini file" 32 | @echo " package-xml: Propagates changes from package.ini to package.xml" 33 | @echo " composer-json: Propagates changes from package.ini to composer.json" 34 | @echo " package: Generates package.ini, package.xml and composer.json files" 35 | @echo " pear: Generates a PEAR package" 36 | @echo " install: Install this project and its dependencies in the local PEAR" 37 | @echo " get-composer: Downlod composer.phar packager." 38 | @echo "composer-validate: Validate composer.json for syntax and other problems" 39 | @echo " composer-install: Install this project with composer which will create vendor folder" 40 | @echo " composer-update: Update an exiting composer instalation and refresh repositories" 41 | @echo " pear-push: Pushes the latest PEAR package. Custom pear_repo='' and \n\ 42 | pear_package='' available." 43 | @echo " release: Runs tests, coverage reports, tag the build and pushes\n\ 44 | to package repositories" 45 | @echo "" 46 | 47 | # Foundation puts its files into .foundation inside your project folder. 48 | # You can delete .foundation anytime and then run make foundation again if you need 49 | foundation: .title 50 | @echo "Updating Makefile" 51 | curl -LO git.io/Makefile 52 | @echo "Creating .foundation folder" 53 | -rm -Rf .foundation 54 | -mkdir .foundation 55 | git clone --depth 1 git://github.com/Respect/Foundation.git .foundation/repo 56 | @echo "Downloading Onion" 57 | -curl -L https://github.com/c9s/Onion/raw/master/onion > .foundation/onion;chmod +x .foundation/onion 58 | @echo "Done." 59 | 60 | # Target for Respect/Foundation development and internal use only. This target will not appear on the menus. 61 | foundation-develop: .title 62 | @echo "Updating Makefile" 63 | curl -LO https://raw.github.com/Respect/Foundation/develop/Makefile 64 | @echo "Creating .foundation folder" 65 | -rm -Rf .foundation 66 | -mkdir .foundation 67 | git clone --depth 1 git://github.com/Respect/Foundation.git .foundation/repo 68 | cd .foundation/repo/ && git fetch && git checkout develop && cd - 69 | @echo "Downloading Onion" 70 | -curl -L https://github.com/c9s/Onion/raw/master/onion > .foundation/onion;chmod +x .foundation/onion 71 | @echo "Done." 72 | 73 | project-info: .check-foundation 74 | @echo "\nProject Information\n" 75 | @echo " php-version:" `$(CONFIG_TOOL) php-version` 76 | @echo " project-repository:" `$(CONFIG_TOOL) project-repository` 77 | @echo " library-folder:" `$(CONFIG_TOOL) library-folder ` 78 | @echo " test-folder:" `$(CONFIG_TOOL) test-folder ` 79 | @echo " config-folder:" `$(CONFIG_TOOL) config-folder ` 80 | @echo " public-folder:" `$(CONFIG_TOOL) public-folder ` 81 | @echo " executables-folder:" `$(CONFIG_TOOL) executables-folder ` 82 | @echo " vendor-name:" `$(CONFIG_TOOL) vendor-name ` 83 | @echo " package-name:" `$(CONFIG_TOOL) package-name ` 84 | @echo " project-name:" `$(CONFIG_TOOL) project-name ` 85 | @echo " one-line-summary:" `$(CONFIG_TOOL) one-line-summary ` 86 | @echo " package-description:" `$(CONFIG_TOOL) package-description ` 87 | @echo " package-version:" `$(CONFIG_TOOL) package-version ` 88 | @echo " package-stability:" `$(CONFIG_TOOL) package-stability ` 89 | @echo "\r project-authors: "`$(CONFIG_TOOL) package-authors ` \ 90 | | tr ',' '\n' \ 91 | | awk -F' <' '{ printf " %-10-s \t<%15-s \n",$$1,$$2 }' 92 | @echo "\r project-contributors: "`$(CONFIG_TOOL) package-contributors ` \ 93 | | tr ',' '\n' \ 94 | | awk -F' <' '{ printf " %-10-s \t<%15-s \n",$$1,$$2 }' 95 | 96 | @echo " package-date-time:" `$(CONFIG_TOOL) package-date-time ` 97 | @echo " pear-channel:" `$(CONFIG_TOOL) pear-channel ` 98 | @echo " pear-repository:" `$(CONFIG_TOOL) pear-repository ` 99 | @echo " phar-repository:" `$(CONFIG_TOOL) phar-repository ` 100 | @echo " pear-dependencies:" `$(CONFIG_TOOL) pear-dependencies ` 101 | @echo " extension-dependencies:" `$(CONFIG_TOOL) extension-dependencies ` 102 | @echo " readme-file:" `$(CONFIG_TOOL) readme-file ` 103 | @echo " project-license:" `$(CONFIG_TOOL) project-license ` 104 | @echo " project-homepage:" `$(CONFIG_TOOL) project-homepage ` 105 | @echo "" 106 | 107 | # Two-step generation including a tmp file to avoid streaming problems 108 | package-ini: .check-foundation 109 | @$(GENERATE_TOOL) package-ini > package.ini.tmp && mv -f package.ini.tmp package.ini 110 | 111 | # Generates a package.xml from the package.ini 112 | package-xml: .check-foundation 113 | @.foundation/onion build 114 | 115 | composer-json: .check-foundation 116 | @$(GENERATE_TOOL) composer-json > composer.json.tmp && mv -f composer.json.tmp composer.json 117 | 118 | # Generates all package files 119 | package: .check-foundation package-ini package-xml composer-json 120 | 121 | # Phony target so the test folder don't conflict 122 | .PHONY: test 123 | test: .check-foundation 124 | @cd `$(CONFIG_TOOL) test-folder`;phpunit --testdox . 125 | 126 | coverage: .check-foundation 127 | @cd `$(CONFIG_TOOL) test-folder`;phpunit --coverage-html=reports/coverage --coverage-text . 128 | @echo "Done. Reports also available on `$(CONFIG_TOOL) test-folder`/reports/coverage/index.html" 129 | 130 | cs-fixer: .check-foundation 131 | @cd `$(CONFIG_TOOL) library-folder`;php-cs-fixer -v fix --level=all --fixers=indentation,linefeed,trailing_spaces,unused_use,return,php_closing_tag,short_tag,visibility,braces,extra_empty_lines,phpdoc_params,eof_ending,include,controls_spaces,elseif . 132 | @echo "Library folder done. `$(CONFIG_TOOL) library-folder`" 133 | @cd `$(CONFIG_TOOL) test-folder`;php-cs-fixer -v fix --level=all --fixers=indentation,linefeed,trailing_spaces,unused_use,return,php_closing_tag,short_tag,visibility,braces,extra_empty_lines,phpdoc_params,eof_ending,include,controls_spaces,elseif . 134 | @echo "Test folder done. `$(CONFIG_TOOL) test-folder` " 135 | @echo "Done. You may verify the changes and commit if you are happy." 136 | 137 | # Any cleaning mechanism should be here 138 | clean: .check-foundation 139 | @rm -Rf `$(CONFIG_TOOL) test-folder`/reports 140 | 141 | # Targets below use the same rationale. They change the package.ini file, so you'll need a 142 | # package-sync after them 143 | patch: .check-foundation 144 | @$(GENERATE_TOOL) package-ini patch > package.ini.tmp && mv -f package.ini.tmp package.ini 145 | 146 | minor: .check-foundation 147 | @$(GENERATE_TOOL) package-ini minor > package.ini.tmp && mv -f package.ini.tmp package.ini 148 | 149 | major: .check-foundation 150 | @$(GENERATE_TOOL) package-ini major > package.ini.tmp && mv -f package.ini.tmp package.ini 151 | 152 | alpha: .check-foundation 153 | @$(GENERATE_TOOL) package-ini alpha > package.ini.tmp && mv -f package.ini.tmp package.ini 154 | 155 | beta: .check-foundation 156 | @$(GENERATE_TOOL) package-ini beta > package.ini.tmp && mv -f package.ini.tmp package.ini 157 | 158 | stable: .check-foundation 159 | @$(GENERATE_TOOL) package-ini stable > package.ini.tmp && mv -f package.ini.tmp package.ini 160 | 161 | tag: .check-foundation 162 | -git tag `$(CONFIG_TOOL) package-version ` -m 'Tagging.' 163 | 164 | # Runs on the current package.xml file 165 | pear: 166 | @pear package 167 | 168 | # On root PEAR installarions, this need to run as sudo 169 | install: .check-foundation 170 | @echo "You may need to run this as sudo." 171 | @echo "Discovering channel" 172 | -@pear channel-discover `$(CONFIG_TOOL) pear-channel` 173 | @pear install package.xml 174 | 175 | get-composer: .check-foundation 176 | @echo "Attempting to download composer packager." 177 | curl -s http://getcomposer.org/installer | php 178 | 179 | composer-validate: .check-foundation 180 | @echo "Running composer validate, be brave." 181 | php composer.phar validate -v 182 | 183 | composer-install: .check-foundation 184 | @echo "Running composer install, this will create a vendor folder and congigure autoloader." 185 | php composer.phar install -v 186 | 187 | composer-update: .check-foundation 188 | @echo "Running composer update, which updates your existing installarion." 189 | php composer.phar update -v 190 | 191 | # Install pirum, clones the PEAR Repository, make changes there and push them. 192 | pear-push: .check-foundation 193 | @echo "Installing Pirum" 194 | @sudo pear install --soft --force pear.pirum-project.org/Pirum 195 | @echo "Cloning channel from git" `$(CONFIG_TOOL) pear-repository` 196 | -rm -Rf .foundation/pirum 197 | git clone --depth 1 `$(CONFIG_TOOL) pear-repository`.git .foundation/pirum 198 | pirum add .foundation/pirum `$(CONFIG_TOOL) package-name`-`$(CONFIG_TOOL) package-version`.tgz;pirum build .foundation/pirum; 199 | cd .foundation/pirum;git add .;git commit -m "Added " `$(CONFIG_TOOL) package-version`;git push 200 | 201 | packagecommit: 202 | @git add package.ini package.xml composer.json 203 | @git commit -m "Updated package files" 204 | 205 | # Uses other targets to complete the build 206 | release: test package packagecommit pear pear-push tag 207 | @echo "Release done. Pushing to GitHub" 208 | @git push 209 | @git push --tags 210 | @echo "Done. " `$(CONFIG_TOOL) package-name`-`$(CONFIG_TOOL) package-version` 211 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Respect\Conversion 2 | ================== 3 | 4 | The most awesome conversion engine ever written for PHP. 5 | 6 | Featuring: 7 | 8 | * Built-in support for many data formats: tree, collection, table, chart, image, xml, etc. 9 | * Fluent interface like `Converter::table()->col(2)->remove();` and `Converter::chart()->rowSeries("Income")->line("red")` 10 | * Seamless convertion between formats: tree to collection, table to tree, collection to chart, collection to xml, chart to image, etc... 11 | 12 | Disclaimer: Not all features described here are implemented, some of them are incomplete and 13 | unfinished. They're all marked as TODO when appropriate. Coding standards are also sloppy, we're going to fix that. 14 | 15 | Please get in touch if you want to help or if you have any feedback. 16 | 17 | Installation 18 | ------------ 19 | 20 | For now, clone our repo and set up a PSR-0 autoloader for the source folder. Composer 21 | and PEAR packages are on their way! 22 | 23 | Configuration 24 | ------------- 25 | 26 | Just import our namespace: 27 | 28 | item(2) //Selector 40 | ->delete() //Operator 41 | ->transform($data); //The conversion method 42 | 43 | print_r($result); //array('foo', 'bar') //The result 44 | 45 | The type dimensions tell selectors and operators how to behave. The `delete()` 46 | operator for instance needs to know if it is acting on a table row, or a 47 | collection item, or a XML tag. 48 | 49 | Selectors tell operators in which part of the data input they're gonna operate. 50 | In the sample above, we're going to operate on the third item of a collection. 51 | 52 | Operators, finally, act on a selected part of the input data and transform it. 53 | 54 | Let's see a better sample: 55 | 56 | $data = array( 57 | array('id' => 0, 'first_name' => 'Foo', 'last_name' => 'Bar'), 58 | array('id' => 1, 'first_name' => 'Lorem', 'last_name' => 'Ipsum'), 59 | array('id' => 2, 'first_name' => 'John', 'last_name' => 'Doe'), 60 | ); 61 | $result = Converter::table() //Operating in the table dimension 62 | ->col("id") //Select the column "id" 63 | ->delete() //And delete it. 64 | ->td(array(null, "first_name")) //Select the cells from the column "first_name" 65 | ->append(" ") //And append a " " (blank space) 66 | ->col("first_name", "last_name") //Select the "first_name" and "last_name" columns 67 | ->hydrate("name") //Join them with an array of their two cells as "name" 68 | ->td(array(null, "name")) //Select the "name" cells from any row 69 | ->callback('implode') //Implode the containing array 70 | ->col("name") //Select the column "name" 71 | ->up() //Make the selected column the transformed data 72 | ->transform($data); //Effectively apply the transformations 73 | print_r($result); //array('Foo Bar', 'Lorem Ipsum', // 74 | 'John Doe'); //The Result 75 | 76 | In the sample above, we've operated in the table dimension to transform 77 | data and extract the raw full names from a table array. 78 | 79 | Respect\Conversion works on four main component types: 80 | 81 | * **Operators**, that really to the conversion work. 82 | * **Selectors**, that allow targeting the data being converted. 83 | * **Types**, the converting dimensions of data being transformed. 84 | * **The Converter**, that knows how to use the components above. 85 | 86 | Let's try a hardcore sample (illustrative, code not implemented yet for this): 87 | 88 | $data = array( 89 | 'All' => array('investment' => 32.0, 'income' => 26.5) 90 | 'A' => array('investment' => 12.0, 'income' => 6.5), 91 | 'B' => array('investment' => 9.0, 'income' => 5.5), 92 | ); 93 | $result = Converter::chart() //Operate the table as a dataseries for a chart 94 | ->rowSeries("All") //Select the first row series 95 | ->line("#000", 3) //Make it a black chart line with 3px width 96 | ->rowSeries("A", "B") //Select all row series 97 | ->line(null, 1) //Make them a line chart with random color and 1px width 98 | ->image() //Operate on the image dimension 99 | ->background() //Select the image background 100 | ->color("white") //Make the background white (default is transparent) 101 | ->frames() //Select all frames (all lines from chart) 102 | ->flatten() //Merge lines into a single image 103 | ->canvas() //Select the canvas 104 | ->grow(20, 20) //Grow it by 20px, simulating a 10px border 105 | ->format() //Select the format 106 | ->type('png') //Make it PNG 107 | ->transform($data); //Effectively apply the transformations 108 | 109 | This will generate this image: 110 | 111 | //TODO CODE AND SAMPLE 112 | 113 | ### 114 | 115 | On the Collection dimension we operate on a list of things. Possible selectors and operators: 116 | 117 | #### Item 118 | 119 | Selects all items. 120 | 121 | $data = array('foo', 'bar', 'baz'); //Sample data 122 | 123 | $result = Converter::collection() //Collection dimension 124 | ->item() //Selects all items 125 | ->{$operator}() //Apply some operator 126 | ->transform($data); //Effectively apply the transformations 127 | 128 | #### Item($key[, $key[, $key...]]) 129 | 130 | Selects an item from its key. 131 | 132 | $data = array('foo', 'bar', 'baz', 'lorem' => 'ipsum'); 133 | 134 | $result = Converter::collection() //Collection dimension 135 | ->item(1) //Selects only the item 1 (bar) 136 | ->{$operator}() //Apply some operator 137 | ->transform($data); //Effectively apply the transformations 138 | 139 | Another Selector samples are: 140 | 141 | ->item("lorem") //Selects only the item named lorem 142 | 143 | ->item("lorem", 0) //Selects the item lorem and the item 0 144 | 145 | #### Item($callback[, $callback[, $callback...]]) 146 | 147 | Selects an item matching a callback function. 148 | 149 | $data = array('foo', 'bar', 'baz', 'lorem' => 'ipsum'); 150 | $strlen3 = function($item) { return strlen($item) === 3; }; 151 | $containsr = function($item) { return false !== stripos('r', $item); }; 152 | 153 | $result = Converter::collection() //Collection dimension 154 | ->item($strlen3) //Selects only items with 3 letters in value 155 | ->{$operator}() //Apply some operator 156 | ->transform($data); //Effectively apply the transformations 157 | 158 | Another selector samples: 159 | ->item($containsr) //Selects only items with the 'r' letter 160 | 161 | ->item($strlen3, 162 | $containsr) //Selects only items with three letters and an 'r' 163 | 164 | Using Respect\Validation `create()` utility you can create callbacks 165 | that matches several patterns including `v::odd()`, `v::even()`, `v::multipleOf()` and 166 | more specific ones like `v::object()->attribute('name')` (item must be an object with the attribute 167 | name). 168 | 169 | use Respect\Validation\Validator as v; 170 | 171 | $validateOdd = v::create(null, null, v::odd()); //closure for $item, $key, $lineNo 172 | 173 | $result = Converter::collection() //Collection dimension 174 | ->item($validateOdd) //Selects only odd items 175 | ->{$operator}() //Apply some operator 176 | ->transform($data); //Effectively apply the transformations 177 | 178 | 179 | #### Item($mixed[, $mixed[, $mixed...]]) 180 | 181 | $result = Converter::collection() //Collection dimension 182 | ->item(0, $cb2) //Selects the item 0 and elements with the 'r' letter 183 | ->{$operator}() //Apply some operator 184 | ->transform($data); //Effectively apply the transformations 185 | 186 | #### Item(x) + Item(y) == Item(x,y) 187 | 188 | An item called after an item... 189 | 190 | Converter::collection() 191 | ->item(0) 192 | ->item(1) 193 | 194 | ...binds to an item with both their arguments equivalent to: 195 | 196 | Converter::collection() 197 | ->item(0,1) 198 | 199 | Bounding also occours with Table\First and Table\Last. 200 | 201 | #### Item\Append($string) 202 | 203 | Appends a string at the end of the item value. 204 | 205 | $data = array('foo', 'bar', 'baz'); //Sample data 206 | 207 | $result = Converter::collection() //Collection dimension 208 | ->item() //Selects all items 209 | ->append('0') //Appends a zero at the end 210 | ->transform($data); //Effectively apply the transformations 211 | 212 | print_r($result); //array('foo0', 'bar0', 'baz0') 213 | 214 | See also: 215 | 216 | * Item\Prepend - Prepends strings to items in a collection 217 | * Td\Prepend - Prepends strings to cells in a table 218 | * Td\Append - Appends strings to cells in a table 219 | * Xpath\Append - Appends strings to XPath results. //TODO 220 | * Xpath\Prepend - Prepends strings to XPath results. //TODO 221 | 222 | #### Item\Callback($callback) 223 | 224 | Applies a callback at any item. 225 | 226 | $data = array('foo', 'bar', 'baz'); //Sample data 227 | 228 | $result = Converter::collection() //Collection dimension 229 | ->item() //Selects all items 230 | ->callback( 231 | 'strrev') //Reverses their content 232 | ->transform($data); //Effectively apply the transformations 233 | 234 | print_r($result); //array('oof', 'rab', 'zab') 235 | 236 | See also: 237 | 238 | * Col\Callback - Applies a callback to table columns. 239 | * Tr\Callback - Applies a callback to table rows. 240 | * Td\Callback - Applies a callback to table cells. 241 | * Leaf\Callback - Applies a callback to tree leaves. 242 | * Branch\Callback - Applies a callback to tree branches. 243 | * Xpath\Callback - Applies a callback to XPath results. //TODO 244 | 245 | #### Item\Delete 246 | 247 | Deletes items. 248 | 249 | $data = array('foo', 'bar', 'baz'); //Sample data 250 | 251 | $result = Converter::collection() //Collection dimension 252 | ->item(1) //Selects item 1 253 | ->delete() //Deletes it 254 | ->transform($data); //Effectively apply the transformations 255 | 256 | print_r($result); //array('foo', 'baz') 257 | 258 | See also: 259 | 260 | * Col\Delete - Deletes columns from a table 261 | * Td\Delete - Deletes cells from a table 262 | * Tr\Delete - Delete rows from a table 263 | * Leaf\Delete - Delete leaves from tree //TODO 264 | * Branch\Delete - Delete branches from a tree //TODO 265 | * Xpath\Delete - Deletes matching XPath results //TODO 266 | 267 | #### Item\Extract 268 | 269 | Extracts inner arrays to the main collection. 270 | 271 | $data = array('foo', 'bar', 'lorem' => 'ipsum'); //Sample data 272 | 273 | $result = Converter::collection() //Collection dimension 274 | ->item('lorem') //Selects item lorem 275 | ->extract() //Extracts their values to the collection 276 | ->transform($data); //Effectively apply the transformations 277 | 278 | print_r($result); //array('foo', 'bar', 'lorem' => 'ipsum') 279 | 280 | #### Item\Name 281 | 282 | Names items in the collection. 283 | 284 | $data = array('foo', 'bar', 'baz'); //Sample data 285 | 286 | $result = Converter::collection() //Collection dimension 287 | ->item('foo') //Selects item lorem 288 | ->name('zero') //Extracts their values to the collection 289 | ->transform($data); //Effectively apply the transformations 290 | 291 | print_r($result); //array('zero' => foo', 'bar', 'baz') 292 | 293 | See also: 294 | 295 | * Col\Name - Names columns in a table 296 | * Td\Name - Names cells in a table 297 | * Tr\Name - Name rows in a table 298 | 299 | #### Item\Prepend($string) 300 | 301 | Prepends a string at the beginning of the item value. 302 | 303 | $data = array('foo', 'bar', 'baz'); //Sample data 304 | 305 | $result = Converter::collection() //Collection dimension 306 | ->item() //Selects all items 307 | ->append('0') //Appends a zero at the end 308 | ->transform($data); //Effectively apply the transformations 309 | 310 | print_r($result); //array('0foo', '0bar', '0baz') 311 | 312 | See also: 313 | 314 | * Item\Append - Appends strings to items in a collection 315 | * Td\Prepend - Prepends strings to cells in a table 316 | * Td\Append - Appends strings to cells in a table 317 | * Xpath\Append - Appends strings to XPath results. //TODO 318 | * Xpath\Prepend - Prepends strings to XPath results. //TODO 319 | 320 | #### Item\Up 321 | 322 | Promotes an item to the main transformation target. 323 | 324 | $data = array('foo', 'bar', 'baz'); //Sample data 325 | 326 | $result = Converter::collection() //Collection dimension 327 | ->item(1) //Selects all items 328 | ->up() //Appends a zero at the end 329 | ->transform($data); //Effectively apply the transformations 330 | 331 | print_r($result); //(string) 'bar' 332 | 333 | See also: 334 | 335 | * Col\Up - Promotes table columns 336 | * Tr\Up - Promotes table rows 337 | * Td\Up - Promotes table cells //TODO 338 | * Leaf\Up - Promotes tree leaves //TODO 339 | * Branch\Up - Promotes tree branches //TODO 340 | * Xpath\Up - Promotes XPath results //TODO 341 | 342 | #### First 343 | 344 | Selects the first item of the collection. Same operators and bindings as Table\Item. 345 | 346 | #### Last 347 | 348 | Selects the last item of the collection. Same operators and bindings as Table\Item; 349 | 350 | ### Tree Dimension 351 | 352 | On the Tree dimension we operate on a hierarchical set of arrays. Possible selectors and operators: 353 | 354 | #### Leaf 355 | 356 | Selects all leaves from the tree. Leaves are scalar values (integers, floats, strings) that 357 | can't "branch" more. 358 | 359 | $data = array('foo', array('bar', 'baz' => array('lorem', 'ipsum'))); 360 | 361 | $result = Converter::tree() //Collection dimension 362 | ->leaf() //Selects all leaves (foo, bar, lorem, ipsum) 363 | ->{$operator}() //Apply some operator 364 | ->transform($data); //Effectively apply the transformations 365 | 366 | #### Leaf($value[, $value[, $value...]]) 367 | 368 | Selects leaves that match some value. 369 | 370 | $data = array('foo', array('bar', 'baz' => array('lorem', 'ipsum', 'bar'))); 371 | 372 | $result = Converter::tree() //Collection dimension 373 | ->leaf('bar') //Selects the two leaves matching bar 374 | ->{$operator}() //Apply some operator 375 | ->transform($data); //Effectively apply the transformations 376 | 377 | 378 | #### Leaf($callback[, $callback[, $callback...]]) 379 | 380 | Selects leaves that match a specific callback from the tree. 381 | 382 | $data = array('foo', array('bar', 'baz' => array('lorem', 'ipsum', 'bar'))); 383 | $strlen3 = function($leaf) { return strlen($leaf) === 3 }; 384 | 385 | $result = Converter::tree() //Collection dimension 386 | ->leaf($strlen3) //Selects leaves with strlen=3 387 | ->{$operator}() //Apply some operator 388 | ->transform($data); //Effectively apply the transformations 389 | 390 | #### Leaf($mixed[, $mixed[, $mixed...]]) 391 | 392 | Mix values and callbacks when selecting leaves. 393 | 394 | $data = array('foo', array('bar', 'baz' => array('lorem', 'ipsum', 'bar'))); 395 | $strlen3 = function($leaf) { return strlen($leaf) === 3 }; 396 | 397 | $result = Converter::tree() //Collection dimension 398 | ->leaf($strlen3, 399 | "ipsum") //Selects leaves with strlen=3 and "ipsum" 400 | ->{$operator}() //Apply some operator 401 | ->transform($data); //Effectively apply the transformations 402 | 403 | #### Leaf(x) + Leaf(y) == Leaf(x, y) 404 | 405 | A leaf called after a leaf... 406 | 407 | Converter::tree() 408 | ->leaf("active") 409 | ->leaf("ativo") 410 | 411 | ...binds to a leaf with both their arguments equivalent to: 412 | 413 | Converter::tree() 414 | ->leaf("active", "ativo") 415 | 416 | #### Leaf\Callback($callback) 417 | 418 | Applies callbacks on leaves from a tree. 419 | 420 | $data = array('foo', array('bar', 'baz' => array('lorem', 'ipsum'))); 421 | 422 | $result = Converter::tree() //Collection dimension 423 | ->leaf() //Selects all leaves (foo, bar, lorem, ipsum) 424 | ->callback( 425 | 'strrev') //Reverse them 426 | ->transform($data); //Effectively apply the transformations 427 | 428 | print_r($result); //array('oof', array('rab', 'baz' => array('merol', 'muspi'))) 429 | 430 | See also: 431 | 432 | * Branch\Callback - Applies a callback to tree branches. 433 | * Col\Callback - Applies a callback to table columns. 434 | * Tr\Callback - Applies a callback to table rows. 435 | * Td\Callback - Applies a callback to table cells. 436 | * Item\Callback - Applies a callback to collection items. 437 | * Xpath\Callback - Applies a callback to XPath results. //TODO 438 | 439 | #### Branch 440 | 441 | Selects all branches from the tree. Branches are structures that hold one ore more leaves. 442 | 443 | //TODO DOCS 444 | 445 | #### Branch($value[, $value[, $value...]]) 446 | 447 | Selects branches that match some value. 448 | 449 | //TODO DOCS 450 | 451 | #### Branch($callback[, $callback[, $callback...]]) 452 | 453 | Selects branches that match a specific callback from the tree. 454 | 455 | //TODO DOCS 456 | 457 | #### Branch($mixed[, $mixed[, $mixed...]]) 458 | 459 | Mix values and callbacks when selecting branches. 460 | 461 | //TODO DOCS 462 | 463 | #### Branch(x) + Branch(y) == Branch(x, y) 464 | 465 | A branch called after a branch... 466 | 467 | Converter::tree() 468 | ->branch(v::attribute('name')) 469 | ->branch(v::attribute('nombre')) 470 | 471 | ...binds to a branch with both their arguments equivalent to: 472 | 473 | Converter::tree() 474 | ->branch(v::attribute('name'), 475 | v::attribute('nombre')) 476 | 477 | #### Branch\Callback($callback) 478 | 479 | Applies callbacks on leaves from a tree. 480 | 481 | $data = array('foo', array('bar', 'baz' => array('lorem', 'ipsum'))); 482 | 483 | $result = Converter::tree() //Collection dimension 484 | ->branc() //Selects all branches 485 | ->callback( 486 | 'implode') //Implode them 487 | ->transform($data); //Effectively apply the transformations 488 | 489 | print_r($result); //array('foo', 'barloremipsum') 490 | 491 | See also: 492 | 493 | * Leaf\Callback - Applies a callback to tree leaves. 494 | * Col\Callback - Applies a callback to table columns. 495 | * Tr\Callback - Applies a callback to table rows. 496 | * Td\Callback - Applies a callback to table cells. 497 | * Item\Callback - Applies a callback to collection items. 498 | * Xpath\Callback - Applies a callback to XPath results. //TODO 499 | 500 | ### Table Dimension 501 | 502 | The table dimension operates on a set of rows and columns represented 503 | by a multi-dimensional vector of associative arrays. 504 | 505 | Possible selectors and operators: 506 | 507 | #### Col 508 | 509 | Selects all columns from the table. 510 | 511 | //TODO DOCS 512 | 513 | #### Col($key[, $key[, $key...]]) 514 | 515 | Selects all columns matching a key or position number from the table. 516 | 517 | //TODO DOCS 518 | 519 | #### Col($callback[, $callback[, $callback...]]) 520 | 521 | Selects all columns matching a callback. 522 | 523 | //TODO DOCS 524 | 525 | #### Col($mixed[, $mixed[, $mixed...]]) 526 | 527 | Mix position, key and callback when selecting columns. 528 | 529 | //TODO DOCS 530 | 531 | #### Col(x) + Col(y) == Col(x, y) 532 | 533 | A col called after a col... 534 | 535 | Converter::table() 536 | ->col('name') 537 | ->col('nombre') 538 | 539 | ...binds to a col with both their arguments equivalent to: 540 | 541 | Converter::table() 542 | ->col('name', 'nombre') 543 | 544 | #### Col(x) + Tr(y) == Td(array(y, x)) 545 | 546 | A tr called after a col... 547 | 548 | Converter::table() 549 | ->col('name') 550 | ->tr(0) 551 | 552 | ...binds to a td with both their arguments equivalent to: 553 | 554 | Converter::table() 555 | ->td(array(0, 'name')); 556 | 557 | #### Tr 558 | 559 | Selects all rows from the table.s 560 | 561 | //TODO DOCS 562 | 563 | #### Tr($key[, $key[, $key...]]) 564 | 565 | Selects all rows matching a key or position number from the table. 566 | 567 | //TODO DOCS 568 | 569 | #### Tr($callback[, $callback[, $callback...]]) 570 | 571 | Selects all rows matching a callback. 572 | 573 | //TODO DOCS 574 | 575 | #### Tr($mixed[, $mixed[, $mixed...]]) 576 | 577 | Mix position, key and callback when selecting rows. 578 | 579 | //TODO DOCS 580 | 581 | #### Tr(x) + Tr(y) == Tr(x, y) 582 | 583 | A tr called after a tr... 584 | 585 | Converter::table() 586 | ->tr('name') 587 | ->tr('nombre') 588 | 589 | ...binds to a tr with both their arguments equivalent to: 590 | 591 | Converter::table() 592 | ->tr('name', 'nombre') 593 | 594 | #### Tr(y) + Col(x) == Td(array(y, x)) 595 | 596 | A tr called after a col... 597 | 598 | Converter::table() 599 | ->col('name') 600 | ->tr(0) 601 | 602 | ...binds to a td with both their arguments equivalent to: 603 | 604 | Converter::table() 605 | ->td(array(0, 'name')); 606 | #### Td 607 | 608 | Selects all cells from a table. 609 | 610 | //TODO DOCS 611 | 612 | #### Td(array($row, $col)[, array($row, $col)[, array($row, $col)...]]) 613 | 614 | Selects specific cells from a table. 615 | 616 | //TODO DOCS 617 | 618 | #### Td(array(null, $col)[, array(null, $col)[, array(null, $col)...]]) 619 | 620 | Selects specific cells from a column in a table. 621 | 622 | //TODO DOCS 623 | 624 | #### Td(array($row, null)[, array($row, null)[, array($row, null)...]]) 625 | 626 | Select specific cells from a row in a table. 627 | 628 | //TODO DOCS 629 | 630 | #### Td($mixed[, $mixed[, $mixed...]]) 631 | 632 | Mix any of the styles above when selecting cells on a table. 633 | 634 | //TODO DOCS 635 | 636 | #### Td(x) + Td(y) == Td(x, y) 637 | 638 | A td called after a td... 639 | 640 | Converter::table() 641 | ->td(array(0,1)) 642 | ->td(array(1,1)) 643 | 644 | ...binds to a td with both their arguments equivalent to: 645 | 646 | Converter::table() 647 | ->td(array(0,1), array(1,1)) 648 | ### Xml Dimension 649 | 650 | The XML dimension operates on a DOMDocument. 651 | 652 | //TODO DOCS AND CODE 653 | 654 | ### Chart Dimension 655 | 656 | The Chart dimension operates on one ore more ImagickDraw objects representing 657 | chart elements. 658 | 659 | //TODO DOCS AND CODE 660 | 661 | ### Image Dimension 662 | 663 | The Image dimension operates on one ore more Imagick objects representing 664 | image elements. 665 | 666 | //TODO DOCS AND CODE 667 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Respect\/Conversion", 3 | "description": "Most awesome conversion engine", 4 | "version": "0.1.1", 5 | "type": "library", 6 | "time": "2012-09-12 00:56:28", 7 | "homepage": "", 8 | "license": "BSD Style", 9 | "authors": [ 10 | { 11 | "name": "Alexandre Gomes Gaigalas", 12 | "email": "alexandre@gaigalas.net" 13 | }, 14 | { 15 | "name": "Nick Lombard", 16 | "email": "github@jigsoft.co.za" 17 | } 18 | ], 19 | "autoload": { 20 | "psr-0": { 21 | "Respect\\Conversion": "src\/" 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /package.ini: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "Conversion" 3 | summary = "Most awesome conversion engine" 4 | desc = "Most awesome conversion engine ever written in PHP." 5 | version = "0.1.1" 6 | stability = "alpha" 7 | channel = "respect.li/pear" 8 | homepage = "" 9 | license = "BSD Style" 10 | author = "Alexandre Gomes Gaigalas " 11 | authors[] = "Nick Lombard " 12 | contributors[] = "Alexandre Gomes Gaigalas " 13 | contributors[] = "Nick Lombard " 14 | 15 | [require] 16 | php = "5.3" 17 | pearinstaller = "1.4.1" 18 | 19 | [roles] 20 | config = "cfg" 21 | bin = "script" 22 | public = "www" 23 | 24 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Conversion 4 | respect.li/pear 5 | Most awesome conversion engine 6 | Most awesome conversion engine ever written in PHP. 7 | 8 | Alexandre Gomes Gaigalas 9 | 10 | alexandre@gaigalas.net 11 | yes 12 | 13 | 14 | Nick Lombard 15 | 16 | github@jigsoft.co.za 17 | yes 18 | 19 | 2012-09-12 20 | 21 | 22 | 0.1.1 23 | 0.1.1 24 | 25 | 26 | alpha 27 | alpha 28 | 29 | BSD Style 30 | - 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 5.3 132 | 133 | 134 | 1.4.1 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | -------------------------------------------------------------------------------- /src/Respect/Conversion/Converter.php: -------------------------------------------------------------------------------- 1 | __call($name, $arguments); 23 | } 24 | 25 | public function bindType(Types\AbstractType $type) 26 | { 27 | $typeClass = get_class($type); 28 | $this->typeName = static::getComponentName($typeClass); 29 | 30 | if ($this->type) { 31 | $interfaceName = static::getComponentBindInterface($typeClass); 32 | 33 | if ($this->type instanceof $interfaceName) 34 | $type = $this->type->{'bindTo'.$this->typeName}($type); 35 | else 36 | $type = new Types\Multi($this->type, $type); 37 | 38 | $this->typeName = static::getComponentName(get_class($type)); 39 | } 40 | 41 | $this->type = $type; 42 | } 43 | 44 | public function bindSelector(Selectors\Common\AbstractSelector $selector) 45 | { 46 | $selectorClass = get_class($selector); 47 | $this->selectorName = static::getComponentName($selectorClass); 48 | 49 | if ($this->selector) { 50 | $interfaceName = static::getComponentBindInterface($selectorClass); 51 | 52 | if ($this->operator) { 53 | $this->operator = new Operators\Common\Common\Sequence($this->operator); 54 | $this->operator->operateUsing($this->type, $this->selector); 55 | $this->selector = new Selectors\Common\Multi; 56 | } elseif ($this->selector instanceof Selectors\Common\Multi) 57 | $this->selector->selectors[] = $selector; 58 | elseif ($this->selector instanceof $interfaceName) 59 | $selector = $this->selector->{'bindTo'.$this->typeName.$this->selectorName}($selector); 60 | else 61 | $selector = new Selectors\Common\Multi($this->selector, $selector); 62 | 63 | $this->selectorName = static::getComponentName(get_class($selector)); 64 | } 65 | 66 | $this->selector = $selector; 67 | } 68 | 69 | public function bindOperator(Operators\Common\Common\AbstractOperator $operator) 70 | { 71 | $operatorClass = get_class($operator); 72 | $this->operatorName = static::getComponentName($operatorClass); 73 | $operator->operateUsing($this->type, $this->selector); 74 | 75 | if ($this->operator) { 76 | $interfaceName = static::getComponentBindInterface($operatorClass); 77 | 78 | if ($this->operator instanceof Operators\Common\Common\Multi) 79 | $this->operator->operators[] = $operator; 80 | elseif ($this->operator instanceof $interfaceName) 81 | $operator = $this->operator->{'bindTo'.$this->typeName.$this->selectorName.$this->operatorName}($operator); 82 | else 83 | $operator = new Operators\Common\Common\Multi($this->operator, $operator); 84 | 85 | $this->operatorName = static::getComponentName(get_class($operator)); 86 | } 87 | 88 | $operator->operateUsing($this->type, $this->selector); 89 | $this->operator = $operator; 90 | } 91 | 92 | protected static function getComponentName($className) 93 | { 94 | return substr($className, (strrpos($className, '\\') ?: -1)+1); 95 | } 96 | 97 | protected static function getComponentBindInterface($className) 98 | { 99 | return $className.'BindInterface'; 100 | } 101 | 102 | protected static function componentInstance($className, array $arguments=array()) 103 | { 104 | $mirror = new \ReflectionClass($className); 105 | return $mirror->newInstanceArgs($arguments); 106 | } 107 | 108 | protected function componentMatches($name, $type) 109 | { 110 | $name = ucfirst($name); 111 | $operatorPrefix = __NAMESPACE__.'\\Operators\\'; 112 | $selectorPrefix = __NAMESPACE__.'\\Selectors\\'; 113 | $typePrefix = __NAMESPACE__.'\\Types\\'; 114 | 115 | if ($type === static::BIND_OPERATOR 116 | && $this->selectorName 117 | && class_exists($class = $operatorPrefix.$this->typeName.'\\'.$this->selectorName.'\\'.$name)) 118 | return $class; 119 | 120 | if ($type === static::BIND_SELECTOR 121 | && $this->typeName 122 | && class_exists($class = $selectorPrefix.$this->typeName.'\\'.$name)) 123 | return $class; 124 | 125 | if ($type === static::BIND_TYPE 126 | && class_exists($class = $typePrefix.$name)) 127 | return $class; 128 | } 129 | 130 | public function __call($name, $arguments) 131 | { 132 | if ($typeClass = $this->componentMatches($name, static::BIND_TYPE)) 133 | $this->bindType(static::componentInstance($typeClass, $arguments)); 134 | elseif ($selectorClass = $this->componentMatches($name, static::BIND_SELECTOR)) 135 | $this->bindSelector(static::componentInstance($selectorClass, $arguments)); 136 | elseif ($operatorClass = $this->componentMatches($name, static::BIND_OPERATOR)) 137 | $this->bindOperator(static::componentInstance($operatorClass, $arguments)); 138 | else 139 | throw new \Exception('Could not find component '.$name); 140 | 141 | 142 | return $this; 143 | } 144 | 145 | public function transform($input) 146 | { 147 | if ($this->operator) 148 | return $this->operator->transform($input); 149 | else 150 | throw new \Exception('Operator not found'); 151 | } 152 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Chart/RowSeries/Line.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/First/Callback.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/First/Delete.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/First/Extract.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/First/Name.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/First/Prepend.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/First/Up.php: -------------------------------------------------------------------------------- 1 | string = $string; 14 | $this->callback = function($v) use ($string) { 15 | return $v.$string; 16 | }; 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Item/Callback.php: -------------------------------------------------------------------------------- 1 | callback; 13 | 14 | foreach ($target as $item => &$line) 15 | foreach ($this->selector->items as $itemSpec) 16 | if (is_callable($itemSpec) && !$cbResult = $itemSpec($line, $item)); 17 | elseif (is_callable($itemSpec) && $cbResult || $item == $itemSpec) 18 | $line = $callback($line); 19 | 20 | return $target; 21 | } 22 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Item/Delete.php: -------------------------------------------------------------------------------- 1 | callback = function($v) { 12 | return null; 13 | }; 14 | } 15 | 16 | public function transform($target) 17 | { 18 | return array_filter(parent::transform($target)); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Item/Extract.php: -------------------------------------------------------------------------------- 1 | $item) 15 | foreach ($this->selector->items as $itemSpec) 16 | if ($itemSpec == $line && is_array($item)) 17 | foreach ($item as $key => $value) 18 | if (!isset($newTarget[$key])) 19 | $newTarget[$key] = $value; 20 | else 21 | $newTarget[] = $value; 22 | elseif (is_string($line) && !isset($newTarget[$line])) 23 | $newTarget[$line] = $item; 24 | elseif (is_numeric($line)) 25 | $newTarget[] = $item; 26 | 27 | return $newTarget; 28 | } 29 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Item/Name.php: -------------------------------------------------------------------------------- 1 | name = $name; 15 | } 16 | 17 | public function transform($target) 18 | { 19 | $newTarget = array(); 20 | 21 | foreach ($target as $item => $line) 22 | foreach ($this->selector->items as $itemSpec) 23 | if (is_callable($itemSpec) && !$cbResult = $itemSpec($line, $item)) 24 | $newTarget[$item] = $line; 25 | elseif ($item == $itemSpec || (is_callable($itemSpec) && $cbResult)) 26 | $newTarget[$this->name] = $line; 27 | else 28 | $newTarget[$item] = $line; 29 | 30 | return $newTarget; 31 | } 32 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Item/Prepend.php: -------------------------------------------------------------------------------- 1 | string = $string; 14 | $this->callback = function($v) use ($string) { 15 | return $string.$v; 16 | }; 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Item/Up.php: -------------------------------------------------------------------------------- 1 | $line) 15 | foreach ($this->selector->items as $itemSpec) 16 | if (is_callable($itemSpec) && !$cbResult = $itemSpec($line, $item)); 17 | elseif (is_callable($itemSpec) && $cbResult || $item == $itemSpec) 18 | $newTarget[$item] = $line; 19 | 20 | return count($newTarget) == 1 ? current($newTarget) : $newTarget; 21 | } 22 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Last/Append.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Last/Callback.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Last/Delete.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Last/Extract.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Last/Name.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Last/Prepend.php: -------------------------------------------------------------------------------- 1 | selector->items = array(key($target)); 14 | return parent::transform($target); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Collection/Last/Up.php: -------------------------------------------------------------------------------- 1 | callback = $callback; 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Common/Common/AbstractOperator.php: -------------------------------------------------------------------------------- 1 | type = $type; 18 | $this->selector = $selector; 19 | return $this; 20 | } 21 | 22 | abstract public function transform($input); 23 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Common/Common/Multi.php: -------------------------------------------------------------------------------- 1 | operators = func_get_args(); 12 | } 13 | 14 | public function transform($input) 15 | { 16 | foreach ($this->operators as $o) 17 | $input = $o->transform($input); 18 | 19 | return $input; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Col/Dehydrate.php: -------------------------------------------------------------------------------- 1 | col = $col; 18 | $this->operationCallback = $operationCallback; 19 | } 20 | 21 | public function transform($target) 22 | { 23 | $this->selector->lines = array(); 24 | $cols = $this->selector->cols; 25 | $col = $this->col; 26 | $callback = $this->operationCallback; 27 | 28 | $this->callback = function($v) use ($cols, $col, $callback) { 29 | $dehydrated = array(); 30 | 31 | $n = 0; 32 | foreach ($v as $key => $vCol) { 33 | if (($n === $col || $key == $col) && is_array($vCol)) { 34 | $nn = 0; 35 | $vCol = $callback ? $callback($vCol) : $vCol; 36 | foreach ($vCol as $cn => $cv) { 37 | $dehydrated[$cn] = $cv; 38 | $n++; 39 | } 40 | } 41 | $n++; 42 | } 43 | foreach ($v as $key => $vCol) { 44 | if (($n !== $col && $key != $col) || !is_array($vCol)) 45 | $dehydrated[$key] = $vCol; 46 | $n++; 47 | } 48 | 49 | return $dehydrated; 50 | }; 51 | 52 | return parent::transform($target); 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Col/Delete.php: -------------------------------------------------------------------------------- 1 | selector->cols ?: array_keys($input); 13 | 14 | array_walk($input, function(&$line, $lineNo) use ($cols) { 15 | $n = 0; 16 | foreach ($line as $key => $col) { 17 | foreach ($cols as $colSpec) 18 | if ((is_numeric($colSpec) && $colSpec === $n) 19 | || (is_string($colSpec) && $colSpec == $key) 20 | || (is_callable($colSpec) && $colSpec($n))) 21 | $line[$key] = null; 22 | $n++; 23 | } 24 | }); 25 | 26 | return $input; 27 | } 28 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Col/Duplicate.php: -------------------------------------------------------------------------------- 1 | name = $name; 17 | $this->operationCallback = $callback; 18 | } 19 | 20 | public function transform($target) 21 | { 22 | $name = $this->name; 23 | $this->selector->lines = array(); 24 | $cols = $this->selector->cols; 25 | $callback = $this->operationCallback; 26 | 27 | $this->callback = function($v) use ($name, $cols, $callback) { 28 | 29 | $n = 0; 30 | foreach ($v as $key => $col) { 31 | if (in_array($key, $cols, true) || in_array($n, $cols, true)) { 32 | $val = $callback ? $callback($v[$key]) : $v[$key]; 33 | $v[$key] = $v[$key]; 34 | $v[$name] = $val; 35 | } 36 | $n++; 37 | } 38 | 39 | return $v; 40 | }; 41 | 42 | return parent::transform($target); 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Col/Hydrate.php: -------------------------------------------------------------------------------- 1 | name = $name; 17 | $this->operationCallback = $callback; 18 | } 19 | 20 | public function transform($target) 21 | { 22 | $name = $this->name; 23 | $this->selector->lines = array(); 24 | $cols = $this->selector->cols; 25 | $callback = $this->operationCallback; 26 | 27 | $this->callback = function($v) use ($name, $cols, $callback) { 28 | $hydrated = array(); 29 | 30 | $n = 0; 31 | foreach ($v as $key => $col) { 32 | if (in_array($key, $cols, true) || in_array($n, $cols, true)) { 33 | $hydrated[$key] = $v[$key]; 34 | unset($v[$key]); 35 | } 36 | $n++; 37 | } 38 | 39 | $v[$name] = $callback ? $callback($hydrated) : $hydrated; 40 | return $v; 41 | }; 42 | 43 | return parent::transform($target); 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Col/Name.php: -------------------------------------------------------------------------------- 1 | name = $name; 15 | } 16 | 17 | public function transform($input) 18 | { 19 | $cols = $this->selector->cols ?: array_keys($input); 20 | $name = $this->name; 21 | 22 | array_walk($input, function(&$line, $lineNo) use ($cols, $name, &$input) { 23 | $newLine = array(); 24 | $n = 0; 25 | foreach ($line as $key => $col) { 26 | foreach ($cols as $colSpec) { 27 | if ((is_numeric($colSpec) && $colSpec === $n) 28 | || (is_string($colSpec) && $colSpec === $key) 29 | || (is_callable($colSpec) && $colSpec($n))) 30 | $newLine[$name] = $col; 31 | else 32 | $newLine[$key] = $col; 33 | } 34 | $n++; 35 | } 36 | $input[$lineNo] = $newLine; 37 | }); 38 | 39 | return $input; 40 | } 41 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Col/Up.php: -------------------------------------------------------------------------------- 1 | selector->cols ?: array_keys($input); 13 | $output = array(); 14 | 15 | array_walk($input, function(&$line, $lineNo) use ($cols, &$output) { 16 | $n = 0; 17 | $output[$lineNo] = array(); 18 | foreach ($line as $key => $col) { 19 | foreach ($cols as $colSpec) 20 | if ((is_numeric($colSpec) && $colSpec === $n) 21 | || (is_string($colSpec) && $colSpec == $key) 22 | || (is_callable($colSpec) && $colSpec($n))) 23 | $output[$lineNo][$key] = $col; 24 | $n++; 25 | } 26 | $output[$lineNo] = count($output[$lineNo]) == 1 ? end($output[$lineNo]) : $output[$lineNo]; 27 | }); 28 | 29 | return count($output) == 1 ? current($output) : $output; 30 | } 31 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Multi/Append.php: -------------------------------------------------------------------------------- 1 | selector->selectors as $s) 13 | $input = $s->buildOperator('Append') 14 | ->operateUsing($this->table, $s) 15 | ->transform($input); 16 | 17 | return $input; 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Multi/Callback.php: -------------------------------------------------------------------------------- 1 | selector->selectors as $s) 13 | $input = static::operatorInstanceFromSelector($s, array($this->callback)) 14 | ->operateUsing($this->table, $s) 15 | ->transform($input); 16 | return $input; 17 | } 18 | 19 | protected static function operatorInstanceFromSelector($selector, array $arguments = array()) 20 | { 21 | $selectorClass = get_class($selector); 22 | $selectorClass = str_replace('\\Selectors\\', '\\Operators\\', $selectorClass); 23 | $operatorClass = $selectorClass.'\\Callback'; 24 | $mirror = new \ReflectionClass($operatorClass); 25 | return $mirror->newInstanceArgs($arguments); 26 | } 27 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Multi/Delete.php: -------------------------------------------------------------------------------- 1 | selector->selectors as $s) 13 | $input = $s->buildOperator('Delete') 14 | ->operateUsing($this->table, $s) 15 | ->transform($input); 16 | 17 | return $input; 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Multi/Name.php: -------------------------------------------------------------------------------- 1 | selector->selectors as $s) 13 | $input = $s->buildOperator('Name') 14 | ->operateUsing($this->table, $s) 15 | ->transform($input); 16 | 17 | return $input; 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Multi/Prepend.php: -------------------------------------------------------------------------------- 1 | selector->selectors as $s) 13 | $input = $s->buildOperator('Prepend') 14 | ->operateUsing($this->table, $s) 15 | ->transform($input); 16 | 17 | return $input; 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Td/Append.php: -------------------------------------------------------------------------------- 1 | callback = function($v) use ($string) { 13 | return $v.$string; 14 | }; 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Td/Callback.php: -------------------------------------------------------------------------------- 1 | selector->tds; 13 | $callback = $this->callback; 14 | 15 | array_walk($input, function(&$line, $lineNo) use ($tds, $callback) { 16 | $n = 0; 17 | foreach ($line as $key => &$col) { 18 | foreach ($tds as $tdSpec) 19 | if (is_callable($tdSpec) && !($cbResult = $tdSpec($lineNo, $n))); 20 | elseif (is_callable($tdSpec) && $cbResult // CALLABLE ----------- 21 | || array(null, null) === $tdSpec // ALL CELLS ---------- 22 | || (is_null($tdSpec[1]) 23 | && array($lineNo, null) === $tdSpec) //all cells from row 24 | || (is_numeric($tdSpec[1]) // NUMERIC ------------ 25 | && array($lineNo, $n) === $tdSpec) //specific cell 26 | || (is_null($tdSpec[0]) 27 | && array(null, $n) === $tdSpec) //all cells from column 28 | 29 | || (is_string($tdSpec[1]) // STRING ------------- 30 | && array($lineNo, $key) === $tdSpec) //specific cells 31 | || (is_string($tdSpec[1]) 32 | && array(null, $key) === $tdSpec)) //all cells from row 33 | $col = call_user_func($callback, $col); 34 | $n++; 35 | } 36 | }); 37 | 38 | return $input; 39 | } 40 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Td/Delete.php: -------------------------------------------------------------------------------- 1 | callback = function() { 13 | return null; 14 | }; 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Td/Name.php: -------------------------------------------------------------------------------- 1 | name = $name; 15 | } 16 | 17 | public function transform($input) 18 | { 19 | $tds = $this->selector->tds ?: null; 20 | $name = $this->name; 21 | 22 | array_walk($input, function(&$line, $lineNo) use ($tds, $name) { 23 | $newLine = array(); 24 | $n = 0; 25 | foreach ($line as $key => &$col) { 26 | foreach ($tds as $tdSpec) 27 | if (is_callable($tdSpec) && !($cbResult = $tdSpec($lineNo, $n))); 28 | elseif (is_callable($tdSpec) && $cbResult // CALLABLE ----------- 29 | || array(null, null) === $tdSpec // ALL CELLS ---------- 30 | || (is_numeric($tdSpec[1]) // NUMERIC ------------ 31 | && array($lineNo, $n) === $tdSpec) //specific cell 32 | || (is_null($tdSpec[1]) 33 | && array($lineNo, null) === $tdSpec) //all cells from row 34 | || (is_null($tdSpec[0]) 35 | && array(null, $n) === $tdSpec) //all cells from column 36 | 37 | || (is_string($tdSpec[1]) // STRING ------------- 38 | && array($lineNo, $key) === $tdSpec)) //all cells from row 39 | $newLine[$name] = $col; 40 | else 41 | $newLine[$key] = $col; 42 | $n++; 43 | } 44 | $line = $newLine; 45 | }); 46 | 47 | return $input; 48 | } 49 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Td/Prepend.php: -------------------------------------------------------------------------------- 1 | callback = function($v) use ($string) { 13 | return $string.$v; 14 | }; 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Tr/Callback.php: -------------------------------------------------------------------------------- 1 | selector->lines; 13 | $callback = $this->callback; 14 | 15 | array_walk($input, function(&$line, $no) use ($lines, $callback) { 16 | 17 | if (empty($lines)) 18 | $line = call_user_func($callback, $line); 19 | else 20 | foreach ($lines as $lineSpec) 21 | if ($no === $lineSpec 22 | || is_callable($lineSpec) && $lineSpec($no)) 23 | $line = call_user_func($callback, $line); 24 | }); 25 | 26 | return $input; 27 | } 28 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Tr/Delete.php: -------------------------------------------------------------------------------- 1 | selector->lines; 13 | 14 | array_walk($input, function(&$line, $no) use ($lines) { 15 | 16 | if (empty($lines)) 17 | $line = null; 18 | else 19 | foreach ($lines as $lineSpec) 20 | if ($no == $lineSpec 21 | || is_callable($lineSpec) && $lineSpec($no)) 22 | $line = null; 23 | }); 24 | 25 | return array_filter($input); 26 | } 27 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Tr/Name.php: -------------------------------------------------------------------------------- 1 | name = $name; 16 | } 17 | 18 | public function transform($input) 19 | { 20 | $lines = $this->selector->lines; 21 | $name = $this->name; 22 | 23 | $newInput = array(); 24 | 25 | foreach ($input as $no => $line) 26 | if (!empty($lines)) 27 | foreach ($lines as $lineSpec) 28 | if ($no == $lineSpec 29 | || is_callable($lineSpec) && $lineSpec($no)) 30 | $newInput[$name] = $line; 31 | else 32 | $newInput[$no] = $line; 33 | 34 | return $newInput; 35 | } 36 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Table/Tr/Up.php: -------------------------------------------------------------------------------- 1 | selector->lines; 14 | $name = $this->name; 15 | 16 | $newInput = array(); 17 | 18 | foreach ($input as $no => $line) 19 | if (!empty($lines)) 20 | foreach ($lines as $lineSpec) 21 | if ($no == $lineSpec 22 | || is_callable($lineSpec) && $lineSpec($no)) 23 | $newInput[$no] = $line; 24 | 25 | return $newInput; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Tree/Branch/Callback.php: -------------------------------------------------------------------------------- 1 | callback; 13 | 14 | return $this->applyCallbackOnBranches($callback, $target); 15 | } 16 | 17 | public function applyCallbackOnBranches($callback, $target) 18 | { 19 | $branches = $this->selector->branches; 20 | 21 | foreach ($target as &$v) { 22 | if (!is_scalar($v)) 23 | $v = $this->applyCallbackOnBranches($callback, $v); 24 | if (!is_scalar($v)) 25 | if ($branches) { 26 | foreach ($branches as $branch) 27 | if (is_callable($branch) && !$cbResult = $branch($v)); 28 | elseif (is_callable($branch) && $cbResult || $branch == $v) 29 | $v = $callback($v); 30 | } else { 31 | $v = $callback($v); 32 | } 33 | } 34 | return $target; 35 | } 36 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Operators/Tree/Leaf/Callback.php: -------------------------------------------------------------------------------- 1 | callback; 13 | $leaves = $this->selector->leaves; 14 | 15 | array_walk_recursive($target, function(&$v) use ($callback, $leaves) { 16 | if (is_scalar($v)) 17 | if ($leaves) { 18 | foreach ($leaves as $leave) 19 | if (is_callable($leave) && !$cbResult = $leave($v)); 20 | elseif ((is_callable($leave) && $cbResult) || $leave == $v) 21 | $v = $callback($v); 22 | } else { 23 | $v = $callback($v); 24 | } 25 | }); 26 | 27 | return $target; 28 | } 29 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Selectors/Chart/RowSeries.php: -------------------------------------------------------------------------------- 1 | series = func_get_args(); 15 | } 16 | 17 | public function bindToChartRowSeries(RowSeries $target) 18 | { 19 | $mirror = new \ReflectionClass(__CLASS__); 20 | return $mirror->newInstanceArgs(array_merge($this->series, $target->series)); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Selectors/Chart/RowSeriesBindInterface.php: -------------------------------------------------------------------------------- 1 | items = func_get_args(); 15 | } 16 | 17 | public function bindToCollectionItem(Item $target) 18 | { 19 | $mirror = new \ReflectionClass(__CLASS__); 20 | return $mirror->newInstanceArgs(array_merge($this->items, $target->items)); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Selectors/Collection/ItemBindInterface.php: -------------------------------------------------------------------------------- 1 | selectors = func_get_args(); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Selectors/Common/MultiBindInterface.php: -------------------------------------------------------------------------------- 1 | newInstanceArgs(array_merge($this->cols, $target->cols)); 13 | } 14 | 15 | public function bindToTableTr(Tr $target) 16 | { 17 | $mirror = new \ReflectionClass(get_called_class()); 18 | return $mirror->newInstanceArgs(array_merge($this->lines, $target->lines)); 19 | } 20 | 21 | public function bindTrCol(Tr $tr, Col $col) 22 | { 23 | $tds = array(); 24 | 25 | if ($tr->lines && $col->cols) 26 | foreach ($tr->lines as $trNo) 27 | foreach ($col->cols as $colNo) 28 | $tds[] = array($trNo, $colNo); 29 | elseif ($tr->lines) 30 | foreach ($tr->lines as $tr) 31 | $tds[] = array($tr, null); 32 | elseif ($col->cols) 33 | foreach ($col->cols as $col) 34 | $tds[] = array(null, $col); 35 | 36 | $mirror = new \ReflectionClass(__NAMESPACE__.'\\Td'); 37 | return $mirror->newInstanceArgs($tds); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Selectors/Table/Col.php: -------------------------------------------------------------------------------- 1 | cols = func_get_args(); 14 | } 15 | 16 | public function bindToTableTr(Tr $target) 17 | { 18 | return $this->bindTrCol($target, $this); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Selectors/Table/ColBindInterface.php: -------------------------------------------------------------------------------- 1 | tds = array_filter(func_get_args()); 15 | } 16 | 17 | public function bindToTableTd(Td $target) 18 | { 19 | $mirror = new \ReflectionClass(__CLASS__); 20 | return $mirror->newInstanceArgs(array_merge($this->tds, $target->tds)); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Selectors/Table/TdBindInterface.php: -------------------------------------------------------------------------------- 1 | lines = func_get_args(); 14 | } 15 | 16 | public function bindToTableCol(Col $target) 17 | { 18 | return $this->bindTrCol($this, $target); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Selectors/Table/TrBindInterface.php: -------------------------------------------------------------------------------- 1 | branches = func_get_args(); 15 | } 16 | public function bindToTreeBranch(Branch $target) 17 | { 18 | 19 | } 20 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Selectors/Tree/BranchBindInterface.php: -------------------------------------------------------------------------------- 1 | leaves = func_get_args(); 15 | } 16 | 17 | public function bindToTreeLeaf(Leaf $target) 18 | { 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /src/Respect/Conversion/Selectors/Tree/LeafBindInterface.php: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | ../library/Respect/ 16 | 17 | 18 | 19 | . 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/src/Respect/Conversion/ConverterTest.php: -------------------------------------------------------------------------------- 1 | input = array( 10 | array('id' => 0, 'name' => 'Alexandre 0', 'internal_code' => 9345343846), 11 | array('id' => 1, 'name' => 'Alexandre', 'internal_code' => 9345343846), 12 | array('id' => 2, 'name' => 'Fulano', 'internal_code' => 933546), 13 | array('id' => 3, 'name' => 'John Doe', 'internal_code' => 9334546), 14 | array('id' => 4, 'name' => 'John Doe 2', 'internal_code' => 9334546), 15 | array('id' => 5, 'name' => 'John Doe 3', 'internal_code' => 9334546) 16 | ); 17 | } 18 | 19 | public function testAbstractOperatorUsesTypesAndSelectorsProperly() 20 | { 21 | $operator = new Operators\Table\Td\Callback('strrev'); 22 | $operator->operateUsing(new Types\Table, new Selectors\Table\Td(array(1,1))); 23 | 24 | $result = $operator->transform($this->input); 25 | $this->assertEquals('erdnaxelA', $result[1]['name']); 26 | 27 | return $result; 28 | } 29 | 30 | public function testSequenceAppliesToItsChildrenInCorrectSequence() 31 | { 32 | $type = new Types\Table; 33 | $selector = new Selectors\Table\Td(array(1,1)); 34 | $op1 = new Operators\Table\Td\Callback('strrev'); 35 | $op2 = new Operators\Table\Td\Callback('ucfirst'); 36 | $op1->operateUsing($type, $selector); 37 | $op2->operateUsing($type, $selector); 38 | $operator = new Operators\Common\Common\Sequence($op1, $op2); 39 | $operator2 = new Operators\Common\Common\Sequence($op2, $op1); 40 | 41 | $result = array(); 42 | $result[] = $operator->transform($this->input); 43 | $this->assertEquals('ErdnaxelA', $result[0][1]['name']); 44 | $result[] = $operator2->transform($this->input); 45 | $this->assertEquals('erdnaxelA', $result[1][1]['name']); 46 | 47 | return $result; 48 | } 49 | public function testTableMultiDeleteAppliesToItsChildrenInCorrectSequence() 50 | { 51 | $type = new Types\Table; 52 | $selector1 = new Selectors\Table\Col(1); 53 | $op1 = new Operators\Table\Col\Delete; 54 | $op1->operateUsing($type, $selector1); 55 | $selector2 = new Selectors\Table\Tr(1); 56 | $op2 = new Operators\Table\Tr\Delete; 57 | $op2->operateUsing($type, $selector2); 58 | $operator = new Operators\Common\Common\Sequence($op1, $op2); 59 | 60 | $result = $operator->transform($this->input); 61 | $this->assertEquals(count($this->input)-1, count($result)); 62 | 63 | return $result; 64 | } 65 | 66 | protected function abstractTableColOperatorTest($name, array $colParams, array $operatorParams, $verifier) 67 | { 68 | $type = new Types\Table; 69 | $selectorClass = new \ReflectionClass('Respect\Conversion\Selectors\Table\Col'); 70 | $selector = $selectorClass->newInstanceArgs($colParams); 71 | $operatorClass = new \ReflectionClass('Respect\Conversion\Operators\Table\Col\\'.$name); 72 | $operator = $operatorClass->newInstanceArgs($operatorParams); 73 | $operator->operateUsing($type, $selector); 74 | 75 | $result = $operator->transform($this->input); 76 | 77 | foreach ($result as $tr => $line) { 78 | $n = 0; 79 | foreach ($line as $td => $cell) { 80 | if (!empty($colParams)) 81 | if (in_array($n, $colParams, true) || in_array($td, $colParams, true)) 82 | $this->assertEquals(call_user_func($verifier, $this->input[$tr][$td], $td), $result[$tr][$td]); 83 | else 84 | $this->assertEquals($this->input[$tr][$td], $result[$tr][$td], $td); 85 | else 86 | $this->assertEquals(call_user_func($verifier, $this->input[$tr][$td], $td), $result[$tr][$td]); 87 | $n++; 88 | } 89 | } 90 | 91 | return $result; 92 | } 93 | protected function abstractTableTrOperatorTest($name, array $rowParams, array $operatorParams, $verifier) 94 | { 95 | $type = new Types\Table; 96 | $selectorClass = new \ReflectionClass('Respect\Conversion\Selectors\Table\Tr'); 97 | $selector = $selectorClass->newInstanceArgs($rowParams); 98 | $operatorClass = new \ReflectionClass('Respect\Conversion\Operators\Table\Tr\\'.$name); 99 | $operator = $operatorClass->newInstanceArgs($operatorParams); 100 | $operator->operateUsing($type, $selector); 101 | 102 | $result = $operator->transform($this->input); 103 | 104 | $n = 0; 105 | foreach ($result as $tr => $line) { 106 | if (!empty($rowParams)) 107 | if (in_array($n, $rowParams)) 108 | $this->assertEquals(call_user_func($verifier, $this->input[$tr], $tr, $n), $result[$tr]); 109 | else 110 | $this->assertEquals($this->input[$tr], $result[$tr], $tr, $n); 111 | else 112 | $this->assertEquals(call_user_func($verifier, $this->input[$tr], $tr, $n), $result[$tr]); 113 | $n++; 114 | } 115 | 116 | return array_filter($result); 117 | } 118 | 119 | 120 | public function testTableColDeleteAssocAppliesOnlyToSingleColumn() 121 | { 122 | return $this->abstractTableColOperatorTest('Delete', array("name"), array(), function($v) { 123 | return null; 124 | }); 125 | } 126 | 127 | public function testTableColDeleteAssocAppliesOnlyToSelectedColumns() 128 | { 129 | return $this->abstractTableColOperatorTest('Delete', array("internal_code", "name"), array(), function($v) { 130 | return null; 131 | }); 132 | } 133 | 134 | public function testTableColDeleteAppliesOnlyToSingleColumn() 135 | { 136 | return $this->abstractTableColOperatorTest('Delete', array(1), array(), function($v) { 137 | return null; 138 | }); 139 | } 140 | 141 | public function testTableColDeleteAppliesToAllColumns() 142 | { 143 | return $this->abstractTableColOperatorTest('Delete', array(), array(), function($v) { 144 | return null; 145 | }); 146 | } 147 | 148 | public function testTableColDeleteAppliesOnlyToSelectedColumns() 149 | { 150 | return $this->abstractTableColOperatorTest('Delete', array(0,2,3), array(), function($v) { 151 | return null; 152 | }); 153 | } 154 | 155 | public function testTableTrCallbackAppliesOnlyToSingleRow() 156 | { 157 | $input = $this->input; 158 | return $this->abstractTableTrOperatorTest('Callback', array(1), array('implode'), function($v, $k, $n) use($input) { 159 | return $n == 1 ? implode($v) : $v; 160 | }); 161 | } 162 | 163 | public function testTableTrCallbackAppliesToAllRows() 164 | { 165 | $input = $this->input; 166 | return $this->abstractTableTrOperatorTest('Callback', array(), array('implode'), function($v, $k, $n) use($input) { 167 | return implode($v); 168 | }); 169 | } 170 | 171 | public function testTableTrCallbackAppliesOnlyToSelectedRows() 172 | { 173 | $input = $this->input; 174 | return $this->abstractTableTrOperatorTest('Callback', array(0,2,3), array('implode'), function($v, $k, $n) use($input) { 175 | return in_array($n, (array(0,2,3))) ? implode($v) : $v; 176 | }); 177 | } 178 | 179 | public function testTableTrDeleteAppliesOnlyToSingleRow() 180 | { 181 | $type = new Types\Table; 182 | $selector = new Selectors\Table\Tr(0); 183 | $operator = new Operators\Table\Tr\Delete(); 184 | $operator->operateUsing($type, $selector); 185 | 186 | $result = $operator->transform($this->input); 187 | $this->assertEquals(count($this->input)-1, count($result)); 188 | } 189 | 190 | public function testTableTrDeleteAppliesToAllRows() 191 | { 192 | $type = new Types\Table; 193 | $selector = new Selectors\Table\Tr(); 194 | $operator = new Operators\Table\Tr\Delete(); 195 | $operator->operateUsing($type, $selector); 196 | 197 | $result = $operator->transform($this->input); 198 | $this->assertEquals(0, count($result)); 199 | } 200 | 201 | public function testTableTrDeleteAppliesOnlyToSelectedRows() 202 | { 203 | $type = new Types\Table; 204 | $selector = new Selectors\Table\Tr(0,2,3); 205 | $operator = new Operators\Table\Tr\Delete(); 206 | $operator->operateUsing($type, $selector); 207 | 208 | $result = $operator->transform($this->input); 209 | $this->assertEquals(count($this->input)-3, count($result)); 210 | } 211 | 212 | public function testTableColNameAppliesToColumns() 213 | { 214 | $type = new Types\Table; 215 | $selector = new Selectors\Table\Col(0); 216 | $operator = new Operators\Table\Col\Name("Código"); 217 | $operator->operateUsing($type, $selector); 218 | 219 | $result = $operator->transform($this->input); 220 | 221 | foreach ($result as $tr => $line) { 222 | $n = 0; 223 | foreach ($line as $td => $cell) { 224 | if ($n === 0) 225 | $this->assertEquals("Código", $td); 226 | else 227 | $this->assertEquals(array_search($cell, $this->input[$tr], true), $td); 228 | 229 | $n++; 230 | } 231 | } 232 | } 233 | 234 | public function testTableColNameAssocAppliesToColumns() 235 | { 236 | $type = new Types\Table; 237 | $selector = new Selectors\Table\Col("name"); 238 | $operator = new Operators\Table\Col\Name("Full Name"); 239 | $operator->operateUsing($type, $selector); 240 | 241 | $result = $operator->transform($this->input); 242 | 243 | foreach ($result as $tr => $line) { 244 | $n = 0; 245 | if (empty($line)) 246 | $this->fail('Empty line'); 247 | foreach ($line as $td => $cell) { 248 | if ($n === 1) 249 | $this->assertEquals("Full Name", $td); 250 | else 251 | $this->assertEquals(array_search($cell, $this->input[$tr], true), $td); 252 | 253 | $n++; 254 | } 255 | } 256 | } 257 | 258 | public function testTableTdCallbackAppliesToSpecificCells() 259 | { 260 | $result = Converter::table() 261 | ->td(array(1,1)) 262 | ->callback('strrev') 263 | ->transform($this->input); 264 | 265 | $this->assertEquals('erdnaxelA', $result[1]["name"]); 266 | } 267 | public function testTableTdAssocCallbackAppliesToSpecificCells() 268 | { 269 | $result = Converter::table() 270 | ->td(array(1,"name")) 271 | ->callback('strrev') 272 | ->transform($this->input); 273 | 274 | $this->assertEquals('erdnaxelA', $result[1]["name"]); 275 | } 276 | 277 | public function testTableColCallbackAppliesToSpecificColsUsingClosureSpec() 278 | { 279 | $result = Converter::table() 280 | ->td(function($n) { return $n === 1; }) 281 | ->callback('strrev') 282 | ->transform($this->input); 283 | 284 | $this->assertEquals('erdnaxelA', $result[1]["name"]); 285 | } 286 | public function testTableTrCallbackAppliesToSpecificRowsUsingClosureSpec() 287 | { 288 | $result = Converter::table() 289 | ->tr(function($n) { return $n === 1; }) 290 | ->callback('implode') 291 | ->transform($this->input); 292 | 293 | $this->assertEquals('1Alexandre9345343846', $result[1]); 294 | } 295 | public function testTableTdCallbackAppliesToSpecificCellsUsingClosureSpec() 296 | { 297 | $result = Converter::table() 298 | ->td(function($tr, $col) { return $tr === 1 && $col === 1; }) 299 | ->callback('strrev') 300 | ->transform($this->input); 301 | 302 | $this->assertEquals('erdnaxelA', $result[1]["name"]); 303 | } 304 | 305 | 306 | public function testTableTdDeleteAppliesToSpecificCells() 307 | { 308 | $result = Converter::table() 309 | ->td(array(1,1)) 310 | ->delete() 311 | ->transform($this->input); 312 | 313 | $this->assertEquals(null, $result[1]["name"]); 314 | } 315 | 316 | public function testTableTdNameAppliesToSpecificCells() 317 | { 318 | $result = Converter::table() 319 | ->td(array(1,1)) 320 | ->name("something") 321 | ->transform($this->input); 322 | 323 | $this->assertEquals('Alexandre', $result[1]["something"]); 324 | } 325 | public function testTableTrNameAppliesToSpecificRows() 326 | { 327 | $result = Converter::table() 328 | ->tr(1) 329 | ->name("something") 330 | ->transform($this->input); 331 | 332 | $this->assertEquals('Alexandre', $result["something"]["name"]); 333 | } 334 | public function testTableColNameAppliesToSpecificCols() 335 | { 336 | $result = Converter::table() 337 | ->col(1) 338 | ->name("something") 339 | ->transform($this->input); 340 | 341 | $this->assertEquals('Alexandre', $result[1]["something"]); 342 | $this->assertEquals('Alexandre 0', $result[0]["something"]); 343 | } 344 | public function testTableColPrependAppliesToSpecificCols() 345 | { 346 | $result = Converter::table() 347 | ->td(array(null,1)) 348 | ->prepend("something") 349 | ->transform($this->input); 350 | 351 | $this->assertEquals('somethingAlexandre', $result[1]["name"]); 352 | $this->assertEquals('somethingAlexandre 0', $result[0]["name"]); 353 | } 354 | 355 | public function testTableColPrependAppliesToSpecificCells() 356 | { 357 | $result = Converter::table() 358 | ->td(array(1,1)) 359 | ->prepend("something") 360 | ->transform($this->input); 361 | 362 | $this->assertEquals('somethingAlexandre', $result[1]["name"]); 363 | $this->assertEquals(1, $result[1]["id"]); 364 | } 365 | public function testTableColAppendAppliesToSpecificCols() 366 | { 367 | $result = Converter::table() 368 | ->td(array(null,1)) 369 | ->append("something") 370 | ->transform($this->input); 371 | 372 | $this->assertEquals('Alexandresomething', $result[1]["name"]); 373 | $this->assertEquals('Alexandre 0something', $result[0]["name"]); 374 | } 375 | 376 | public function testTableColAppendAppliesToSpecificCells() 377 | { 378 | $result = Converter::table() 379 | ->td(array(1,1)) 380 | ->append("something") 381 | ->transform($this->input); 382 | 383 | $this->assertEquals('Alexandresomething', $result[1]["name"]); 384 | $this->assertEquals(1, $result[1]["id"]); 385 | } 386 | 387 | public function testTableColDuplicateAppliesToSpecificCols() 388 | { 389 | $result = Converter::table() 390 | ->col(1) 391 | ->duplicate("something") 392 | ->transform($this->input); 393 | 394 | $this->assertEquals('Alexandre', $result[1]["name"]); 395 | $this->assertEquals('Alexandre', $result[1]["something"]); 396 | } 397 | 398 | 399 | public function testTableColDuplicateAppliesToSpecificColsCallback() 400 | { 401 | $result = Converter::table() 402 | ->col(1) 403 | ->duplicate("something", 'strrev') 404 | ->transform($this->input); 405 | 406 | $this->assertEquals('Alexandre', $result[1]["name"]); 407 | $this->assertEquals('erdnaxelA', $result[1]["something"]); 408 | } 409 | 410 | public function testTableColHydrateAppliesToSpecificCols() 411 | { 412 | $result = Converter::table() 413 | ->col(0,1) 414 | ->hydrate("something") 415 | ->transform($this->input); 416 | 417 | $this->assertSame(array('id'=>1, 'name'=>'Alexandre'), $result[1]["something"]); 418 | $this->assertSame(array('id'=>0, 'name'=>'Alexandre 0'), $result[0]["something"]); 419 | 420 | $result = Converter::table() 421 | ->col("id", 1) 422 | ->dehydrate(0) 423 | ->transform($result); 424 | 425 | 426 | $this->assertSame($this->input, $result); 427 | } 428 | 429 | 430 | public function testCollectionItemAppendAppliesToSpecificItemsCallback() 431 | { 432 | $result = Converter::collection() 433 | ->item(function($v, $k) {return $v == 'bar' && $k == 1;}) 434 | ->append("something") 435 | ->transform(array('foo', 'bar', 'baz')); 436 | 437 | $this->assertEquals('barsomething', $result[1]); 438 | } 439 | 440 | public function testCollectionItemAppendAppliesToSpecificItems() 441 | { 442 | $result = Converter::collection() 443 | ->item(1) 444 | ->append("something") 445 | ->transform(array('foo', 'bar', 'baz')); 446 | 447 | $this->assertEquals('barsomething', $result[1]); 448 | } 449 | 450 | public function testCollectionItemNameAppliesToSpecificItems() 451 | { 452 | $result = Converter::collection() 453 | ->item(1) 454 | ->name("something") 455 | ->transform(array('foo', 'bar', 'baz')); 456 | 457 | $this->assertEquals(array('foo', 'something'=>'bar', 2 => 'baz'), $result); 458 | } 459 | 460 | public function testCollectionItemExtractAppliesToSpecificItems() 461 | { 462 | $result = Converter::collection() 463 | ->item(1) 464 | ->extract() 465 | ->transform(array('foo', array('lorem' => 'bar', 'ipsum'), 'baz')); 466 | 467 | $this->assertEquals(array('foo', 'ipsum', 'lorem' => 'bar', 'baz'), $result); 468 | } 469 | public function testCollectionItemExtractAppliesToSpecificItemsAssoc() 470 | { 471 | $result = Converter::collection() 472 | ->item("doo") 473 | ->extract() 474 | ->transform(array('foo', 'doo' => array('lorem' => 'bar', 'ipsum'), 'baz')); 475 | 476 | $this->assertEquals(array('foo', 'ipsum', 'lorem' => 'bar', 'baz'), $result); 477 | } 478 | 479 | public function testCollectionFirstExtractAppliesToSpecificItemsAssoc() 480 | { 481 | $result = Converter::collection() 482 | ->first() 483 | ->extract() 484 | ->transform(array('doo' => array('lorem' => 'bar', 'ipsum'), 'baz', 'foo')); 485 | 486 | $this->assertEquals(array('lorem' => 'bar', 'ipsum', 'baz', 'foo'), $result); 487 | } 488 | public function testCollectionFirstAppendAppliesToSpecificItemsAssoc() 489 | { 490 | $result = Converter::collection() 491 | ->first() 492 | ->append("gloo") 493 | ->transform(array('foo', 'baz', 'bar')); 494 | 495 | $this->assertEquals(array('foogloo', 'baz', 'bar'), $result); 496 | } 497 | public function testCollectionFirstPrependAppliesToSpecificItemsAssoc() 498 | { 499 | $result = Converter::collection() 500 | ->first() 501 | ->prepend("gloo") 502 | ->transform(array('foo', 'baz', 'bar')); 503 | 504 | $this->assertEquals(array('gloofoo', 'baz', 'bar'), $result); 505 | } 506 | public function testCollectionFirstCallbackAppliesToSpecificItemsAssoc() 507 | { 508 | $result = Converter::collection() 509 | ->first() 510 | ->callback("strrev") 511 | ->transform(array('foo', 'baz', 'bar')); 512 | 513 | $this->assertEquals(array('oof', 'baz', 'bar'), $result); 514 | } 515 | public function testCollectionFirstDeleteAppliesToSpecificItemsAssoc() 516 | { 517 | $result = Converter::collection() 518 | ->first() 519 | ->delete() 520 | ->transform(array('foo', 'baz', 'bar')); 521 | 522 | $this->assertEquals(array(1 => 'baz', 2 => 'bar'), $result); 523 | } 524 | public function testCollectionFirstNameAppliesToSpecificItemsAssoc() 525 | { 526 | $result = Converter::collection() 527 | ->first() 528 | ->name("something") 529 | ->transform(array('foo', 'baz', 'bar')); 530 | 531 | $this->assertEquals(array('something' => 'foo', 1 => 'baz', 2 => 'bar'), $result); 532 | } 533 | 534 | public function testCollectionLastExtractAppliesToSpecificItemsAssoc() 535 | { 536 | $result = Converter::collection() 537 | ->last() 538 | ->extract() 539 | ->transform(array('baz', 'foo', 'doo' => array('lorem' => 'bar', 'ipsum'))); 540 | 541 | $this->assertEquals(array('baz', 'foo', 'lorem' => 'bar', 'ipsum'), $result); 542 | } 543 | public function testCollectionLastAppendAppliesToSpecificItemsAssoc() 544 | { 545 | $result = Converter::collection() 546 | ->last() 547 | ->append("gloo") 548 | ->transform(array('foo', 'baz', 'bar')); 549 | 550 | $this->assertEquals(array('foo', 'baz', 'bargloo'), $result); 551 | } 552 | public function testCollectionLastPrependAppliesToSpecificItemsAssoc() 553 | { 554 | $result = Converter::collection() 555 | ->last() 556 | ->prepend("gloo") 557 | ->transform(array('foo', 'baz', 'bar')); 558 | 559 | $this->assertEquals(array('foo', 'baz', 'gloobar'), $result); 560 | } 561 | public function testCollectionLastCallbackAppliesToSpecificItemsAssoc() 562 | { 563 | $result = Converter::collection() 564 | ->last() 565 | ->callback("strrev") 566 | ->transform(array('foo', 'baz', 'bar')); 567 | 568 | $this->assertEquals(array('foo', 'baz', 'rab'), $result); 569 | } 570 | public function testCollectionLastDeleteAppliesToSpecificItemsAssoc() 571 | { 572 | $result = Converter::collection() 573 | ->last() 574 | ->delete() 575 | ->transform(array('foo', 'baz', 'bar')); 576 | 577 | $this->assertEquals(array(0 => 'foo', 1 => 'baz'), $result); 578 | } 579 | public function testCollectionLastNameAppliesToSpecificItemsAssoc() 580 | { 581 | $result = Converter::collection() 582 | ->last() 583 | ->name("something") 584 | ->transform(array('foo', 'baz', 'bar')); 585 | 586 | $this->assertEquals(array(0 => 'foo', 1 => 'baz', 'something' => 'bar'), $result); 587 | } 588 | public function testTreeLeafCallbackAppliesToLeaves() 589 | { 590 | $result = Converter::tree() 591 | ->leaf() 592 | ->callback("strrev") 593 | ->transform($this->input); 594 | 595 | $this->assertEquals('erdnaxelA', $result[1]["name"]); 596 | } 597 | public function testTreeLeafCallbackAppliesToLeavesVerifier() 598 | { 599 | $result = Converter::tree() 600 | ->leaf("Alexandre") 601 | ->callback("strrev") 602 | ->transform($this->input); 603 | 604 | $this->assertEquals('erdnaxelA', $result[1]["name"]); 605 | $this->assertEquals('Alexandre 0', $result[0]["name"]); 606 | } 607 | public function testTreeLeafCallbackAppliesToLeavesVerifierCallback() 608 | { 609 | $result = Converter::tree() 610 | ->leaf(function($v){return $v == 'Alexandre';}) 611 | ->callback("strrev") 612 | ->transform($this->input); 613 | 614 | $this->assertEquals('erdnaxelA', $result[1]["name"]); 615 | $this->assertEquals('Alexandre 0', $result[0]["name"]); 616 | } 617 | public function testTreeBranchCallbackAppliesToLeaves() 618 | { 619 | $result = Converter::tree() 620 | ->branch() 621 | ->callback("implode") 622 | ->transform($this->input); 623 | 624 | $this->assertEquals('1Alexandre9345343846', $result[1]); 625 | } 626 | 627 | public function testTreeBranchCallbackAppliesToLeavesVerifier() 628 | { 629 | $result = Converter::tree() 630 | ->branch(function($v) { 631 | return isset($v['name']) && $v['name'] == 'Alexandre'; 632 | })->callback("implode") 633 | ->transform($this->input); 634 | 635 | $this->assertEquals('1Alexandre9345343846', $result[1]); 636 | $this->assertEquals(1, count(array_filter($result, 'is_string'))); 637 | } 638 | public function testTreeBranchCallbackAppliesToLeavesMulti() 639 | { 640 | $this->input[1]["name"] = str_split($this->input[1]["name"]); 641 | $result = Converter::tree() 642 | ->branch() 643 | ->callback("implode") 644 | ->transform($this->input); 645 | 646 | $this->assertEquals('1Alexandre9345343846', $result[1]); 647 | } 648 | public function testCollectionFirstUp() 649 | { 650 | $result = Converter::collection() 651 | ->first() 652 | ->up() 653 | ->transform($this->input); 654 | 655 | $this->assertEquals($this->input[0], $result); 656 | } 657 | public function testCollectionLastUp() 658 | { 659 | $result = Converter::collection() 660 | ->last() 661 | ->up() 662 | ->transform($this->input); 663 | 664 | $this->assertEquals(end($this->input), $result); 665 | } 666 | public function testCollectionItemUp() 667 | { 668 | $result = Converter::collection() 669 | ->item(2) 670 | ->up() 671 | ->transform($this->input); 672 | 673 | $this->assertEquals($this->input[2], $result); 674 | } 675 | public function testCollectionItemUpMultiple() 676 | { 677 | $result = Converter::collection() 678 | ->item(2,3) 679 | ->up() 680 | ->transform($this->input); 681 | 682 | $this->assertEquals(array_slice($this->input,2,2), array_values($result)); 683 | } 684 | public function testTableColUp() 685 | { 686 | $result = Converter::table() 687 | ->col(1) 688 | ->up() 689 | ->transform($this->input); 690 | 691 | $expected = array('Alexandre 0', 'Alexandre', 'Fulano', 'John Doe', 'John Doe 2', 'John Doe 3'); 692 | $this->assertEquals($expected, $result); 693 | } 694 | 695 | public function testTableColUpMultiple() 696 | { 697 | $result = Converter::table() 698 | ->col(1, 2) 699 | ->up() 700 | ->transform($this->input); 701 | 702 | $expected = array ( 703 | 0 => 704 | array ( 705 | 'name' => 'Alexandre 0', 706 | 'internal_code' => 9345343846, 707 | ), 708 | 1 => 709 | array ( 710 | 'name' => 'Alexandre', 711 | 'internal_code' => 9345343846, 712 | ), 713 | 2 => 714 | array ( 715 | 'name' => 'Fulano', 716 | 'internal_code' => 933546, 717 | ), 718 | 3 => 719 | array ( 720 | 'name' => 'John Doe', 721 | 'internal_code' => 9334546, 722 | ), 723 | 4 => 724 | array ( 725 | 'name' => 'John Doe 2', 726 | 'internal_code' => 9334546, 727 | ), 728 | 5 => 729 | array ( 730 | 'name' => 'John Doe 3', 731 | 'internal_code' => 9334546, 732 | ), 733 | ); 734 | $this->assertEquals($expected, $result); 735 | } 736 | 737 | public function testTableColHydrateAppliesToSpecificColsWithCallback() 738 | { 739 | $result = Converter::table() 740 | ->col(0,1) 741 | ->hydrate("something", $cb = function($v) { 742 | return array_map('strrev', $v); 743 | }) 744 | ->transform($this->input); 745 | 746 | $this->assertSame(array('id'=>'1', 'name'=>'erdnaxelA'), $result[1]["something"]); 747 | $this->assertSame(array('id'=>'0', 'name'=>'0 erdnaxelA'), $result[0]["something"]); 748 | 749 | $result = Converter::table() 750 | ->col("id", 1) 751 | ->dehydrate(0, $cb) 752 | ->transform($result); 753 | 754 | $this->assertEquals($this->input, $result); 755 | } 756 | 757 | public function testTableTdCallbackAppliesToCellsFromColumn() 758 | { 759 | $result = Converter::table() 760 | ->td(array(null,1)) 761 | ->callback('strrev') 762 | ->transform($this->input); 763 | 764 | $this->assertEquals('0 erdnaxelA', $result[0]["name"]); 765 | $this->assertEquals('erdnaxelA', $result[1]["name"]); 766 | $this->assertEquals('onaluF', $result[2]["name"]); 767 | $this->assertEquals('eoD nhoJ', $result[3]["name"]); 768 | $this->assertEquals('2 eoD nhoJ', $result[4]["name"]); 769 | $this->assertEquals('3 eoD nhoJ', $result[5]["name"]); 770 | } 771 | 772 | public function testTableTdCallbackAppliesToCellsFromRow() 773 | { 774 | $result = Converter::table() 775 | ->td(array(1,null)) 776 | ->callback('strrev') 777 | ->transform($this->input); 778 | 779 | $this->assertEquals('erdnaxelA', $result[1]["name"]); 780 | $this->assertEquals('6483435439', $result[1]["internal_code"]); 781 | } 782 | 783 | public function testTableTdCallbackAppliesToAllCells() 784 | { 785 | $phpUnit = $this; 786 | $input = Converter::table() 787 | ->td(array(null,null)) 788 | ->callback(function(){return null;}) 789 | ->transform($this->input); 790 | array_walk_recursive( 791 | $input, 792 | function ($v) use($phpUnit) { 793 | $phpUnit->assertEquals(null, $v); 794 | } 795 | ); 796 | } 797 | 798 | public function testTableColBindsToTableColOnSpecificCells() 799 | { 800 | $selector1 = new Selectors\Table\Col(1,3); 801 | $selector2 = new Selectors\Table\Col(2,4); 802 | $selector = $selector1->bindToTableCol($selector2); 803 | $this->assertEquals(array(1,3,2,4), $selector->cols); 804 | } 805 | 806 | public function testTableColBindsToTableTrOnSpecificCells() 807 | { 808 | $selector1 = new Selectors\Table\Col(1,3); 809 | $selector2 = new Selectors\Table\Tr(2,4); 810 | $selector = $selector1->bindToTableTr($selector2); 811 | $this->assertEquals($expected = array( 812 | array(2,1), 813 | array(2,3), 814 | array(4,1), 815 | array(4,3) 816 | ), $selector->tds); 817 | $selector = $selector2->bindToTableCol($selector1); 818 | $this->assertEquals($expected, $selector->tds); 819 | } 820 | 821 | public function testTableColBindsToTableTrOnCellsFromRow() 822 | { 823 | $selector1 = new Selectors\Table\Col(1,3); 824 | $selector2 = new Selectors\Table\Tr(); 825 | $selector = $selector1->bindToTableTr($selector2); 826 | $this->assertEquals($expected = array( 827 | array(null,1), 828 | array(null,3) 829 | ), $selector->tds); 830 | $selector = $selector2->bindToTableCol($selector1); 831 | $this->assertEquals($expected, $selector->tds); 832 | } 833 | 834 | public function testTableColBindsToTableTrOnCellsFromCol() 835 | { 836 | $selector1 = new Selectors\Table\Col(null); 837 | $selector2 = new Selectors\Table\Tr(2,4); 838 | $selector = $selector1->bindToTableTr($selector2); 839 | $this->assertEquals($expected = array( 840 | array(2,null), 841 | array(4,null) 842 | ), $selector->tds); 843 | $selector = $selector2->bindToTableCol($selector1); 844 | $this->assertEquals($expected, $selector->tds); 845 | } 846 | public function testTableColBindsToTableTrOnAllCells() 847 | { 848 | $selector1 = new Selectors\Table\Col(); 849 | $selector2 = new Selectors\Table\Tr(); 850 | $selector = $selector1->bindToTableTr($selector2); 851 | $this->assertEquals($expected = array(), $selector->tds); 852 | $selector = $selector2->bindToTableCol($selector1); 853 | $this->assertEquals($expected, $selector->tds); 854 | } 855 | 856 | public function testTableTdBindsToTableTdInOrder() 857 | { 858 | $selector1 = new Selectors\Table\Td(array(0,2)); 859 | $selector2 = new Selectors\Table\Td(array(3,4)); 860 | $selector = $selector1->bindToTableTd($selector2); 861 | $this->assertEquals(array( 862 | array(0,2), 863 | array(3,4) 864 | ), $selector->tds); 865 | $selector = $selector2->bindToTableTd($selector1); 866 | $this->assertEquals(array( 867 | array(3,4), 868 | array(0,2) 869 | ), $selector->tds); 870 | } 871 | 872 | public function testConverterAppliesChainProperly() 873 | { 874 | $expected = $this->testAbstractOperatorUsesTypesAndSelectorsProperly(); 875 | $result = Converter::table() 876 | ->td(array(1,1)) 877 | ->callback('strrev') 878 | ->transform($this->input); 879 | $this->assertEquals($expected, $result, 'testAbstractOperatorUsesTypesAndSelectorsProperly'); 880 | 881 | // --- 882 | 883 | $expected = $this->testSequenceAppliesToItsChildrenInCorrectSequence(); 884 | $result = array(Converter::table() 885 | ->td(array(1,1)) 886 | ->callback('strrev') 887 | ->callback('ucfirst') 888 | ->transform($this->input), 889 | Converter::table() 890 | ->td(array(1,1)) 891 | ->callback('ucfirst') 892 | ->callback('strrev') 893 | ->transform($this->input) 894 | ); 895 | $this->assertEquals($expected, $result, 'testSequenceAppliesToItsChildrenInCorrectSequence'); 896 | 897 | // --- 898 | 899 | $expected = $this->testTableColDeleteAppliesOnlyToSingleColumn(); 900 | $result = Converter::table() 901 | ->col(1) 902 | ->delete() 903 | ->transform($this->input); 904 | $this->assertEquals($expected, $result, 'testTableColDeleteAppliesOnlyToSingleColumn'); 905 | 906 | // --- 907 | 908 | $expected = $this->testTableColDeleteAppliesToAllColumns(); 909 | $result = Converter::table() 910 | ->col() 911 | ->delete() 912 | ->transform($this->input); 913 | $this->assertEquals($expected, $result, 'testTableColDeleteAppliesToAllColumns'); 914 | 915 | // --- 916 | 917 | $expected = $this->testTableColDeleteAppliesOnlyToSelectedColumns(); 918 | $result = Converter::table() 919 | ->col(0,2,3) 920 | ->delete() 921 | ->transform($this->input); 922 | $this->assertEquals($expected, $result, 'testTableColDeleteAppliesOnlyToSelectedColumns'); 923 | 924 | // --- 925 | 926 | } 927 | 928 | public function testSample1OnReadme() 929 | { 930 | 931 | $data = array( 932 | array('id' => 0, 'first_name' => 'Foo', 'last_name' => 'Bar'), 933 | array('id' => 1, 'first_name' => 'Lorem', 'last_name' => 'Ipsum'), 934 | array('id' => 2, 'first_name' => 'John', 'last_name' => 'Doe'), 935 | ); 936 | $result = Converter::table() //Operating in the table dimension 937 | ->col("id") //Select the column "id" 938 | ->delete() //And delete it. 939 | ->td(array(null, "first_name")) //Select the cells from the column "first_name" 940 | ->append(" ") //And append a " " (blank space) 941 | ->col("first_name", "last_name") //Select the "first_name" and "last_name" columns 942 | ->hydrate("name") //Join them with an array of their two cells as "name" 943 | ->td(array(null, "name")) //Select the "name" cells from any row 944 | ->callback('implode') //Implode the containing array 945 | ->col("name") //Select the column "name" 946 | ->up() //Make the selected column the transformed data 947 | ->transform($data); //Effectively apply the transformations 948 | 949 | $this->assertEquals(array('Foo Bar', 'Lorem Ipsum', 'John Doe'), $result); 950 | } 951 | } --------------------------------------------------------------------------------