diff --git a/.gitignore b/.gitignore index 0c35599..1bfa395 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,5 @@ joindin-api/ joindin-web2/ Guardfile .vagrant.v* -puppet/hieradata/common.yaml /vendor/ Homestead.yaml diff --git a/.gitmodules b/.gitmodules index 0d8fc0a..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,18 +0,0 @@ -[submodule "puppet/modules/apache"] - path = puppet/modules/apache - url = https://github.com/example42/puppet-apache -[submodule "puppet/modules/puppi"] - path = puppet/modules/puppi - url = https://github.com/example42/puppi -[submodule "puppet/modules/mysql"] - path = puppet/modules/mysql - url = https://github.com/example42/puppet-mysql -[submodule "puppet/modules/stdlib"] - path = puppet/modules/stdlib - url = https://github.com/puppetlabs/puppetlabs-stdlib -[submodule "puppet/modules/wget"] - path = puppet/modules/wget - url = https://github.com/maestrodev/puppet-wget -[submodule "puppet/modules/nodejs"] - path = puppet/modules/nodejs - url = https://github.com/willdurand/puppet-nodejs diff --git a/puppet/hiera.yaml b/puppet/hiera.yaml deleted file mode 100644 index 0732541..0000000 --- a/puppet/hiera.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -:hierarchy: - - "%{::osfamily}-pkgs" - - "%{::osfamily}-repos" - - "%{::vm_type}" - - "%{::vm_env}" - - common - -:backends: - - yaml - -:yaml: - :datadir: - /vagrant/puppet/hieradata diff --git a/puppet/hieradata/common.yaml.dist b/puppet/hieradata/common.yaml.dist deleted file mode 100644 index 1947226..0000000 --- a/puppet/hieradata/common.yaml.dist +++ /dev/null @@ -1,20 +0,0 @@ ---- -joindin::web::host: 'dev.joind.in' -joindin::web::port: '80' # Check `VagrantFile` for port forwarding settings - -# Database credentials. Test database will be setup with _test prefixed to these variables. -joindin::app:dbname: 'joindin' -joindin::app:dbuser: 'joindin' -joindin::app:dbpass: 'password' - -joindin::sql:dbname: 'joindin' -joindin::sql:dbuser: 'joindin' -joindin::sql:dbpass: 'password' - -# True if phpmyadmin needs to be installed, false if not. -joindin::web::phpmyadmin: true - -# True if the test suite needs to be installed, false for faster provisioning with no tests -joindin::test::tests: true - -debug: true diff --git a/puppet/manifests/joindin.pp b/puppet/manifests/joindin.pp deleted file mode 100644 index d155ea1..0000000 --- a/puppet/manifests/joindin.pp +++ /dev/null @@ -1,18 +0,0 @@ - -# Set default path for Exec calls -Exec { - path => [ '/bin/', '/sbin/' , '/usr/bin/', '/usr/sbin/' ] -} - -node default { - include joindin -} - -notify { 'urls': - message => 'VM is ready. You can view the application on - `http://dev.joind.in/` - `http://api.dev.joind.in/` - `http://legacy.dev.joind.in/` - ', - require => Class['joindin'], -} diff --git a/puppet/modules/apache b/puppet/modules/apache deleted file mode 160000 index d342824..0000000 --- a/puppet/modules/apache +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d3428244685a384b2c995c184d4811210d3d0f09 diff --git a/puppet/modules/elasticsearch/CHANGELOG.md b/puppet/modules/elasticsearch/CHANGELOG.md deleted file mode 100644 index 3914fa8..0000000 --- a/puppet/modules/elasticsearch/CHANGELOG.md +++ /dev/null @@ -1,400 +0,0 @@ -##0.9.9 ( Sep 01, 2015 ) - -###Summary -Bugfix release and extra features - -####Features -* Work with ES 2.x -* Add Java 8 detection in debian init script -* Improve offline plugin installation - -####Bugfixes -* Fix a bug with new ruby versions but older puppet versions causing type error -* Fix config tempate to use correct ruby scoping -* Fix regex retrieving proxy port while downloading plugin -* Fix systemd template for better variable handling -* Template define was using wrong pathing for removal - - -####Changes - -####Testing changes - -####Known bugs -* Possible package conflicts when using ruby/python defines with main package name - - -##0.9.8 ( Jul 07, 2015 ) - -###Summary - - -####Features -* Work with ES 2.x - -####Bugfixes -* Fix plugin to maintain backwards compatibility - -####Changes - -####Testing changes -* ensure testing works with Puppet 4.x ( Rspec and Acceptance ) - -####Known bugs -* Possible package conflicts when using ruby/python defines with main package name - - -##0.9.7 ( Jun 24, 2015 ) - -###Summary -This releases adds several important features and fixes an important plugin installation issue with ES 1.6 and higher. - -####Features -* Automate plugin dir extraction -* use init service provider for Amazon Linux -* Add Puppetlabs/apt and ceritsc/yum as required modules -* Added Timeout to fetching facts in case ES does not respond -* Add proxy settings for package download - -####Bugfixes -* Fixed systemd template to fix issue with LimitMEMLOCK setting -* Improve package version handling when specifying a version -* Add tmpfiles.d file to manage sub dir in /var/run path -* Fix plugin installations for ES 1.6 and higher - -####Changes -* Removed Modulefile, only maintaining metadata.json file - -####Testing changes -* Added unit testing for package pinning feature -* Added integration testing with Elasticsearch to find issues earlier -* Fix OpenSuse 13 testing - -####Known bugs -* Possible package conflicts when using ruby/python defines with main package name - - -##0.9.6 ( May 28, 2015 ) - -###Summary -Bugfix release 0.9.6 - -####Features -* Implemented package version pinning to avoid accidental upgrading -* Added support for Debian 8 -* Added support for upgrading plugins -* Managing LimitNOFILE and LimitMEMLOCK settings in systemd - -####Bugfixes - -####Changes -* Dropped official support for PE 3.1.x and 3.2.x - -####Testing changes -* Several testing changes implemented to increase coverage - -####Known bugs -* Possible package conflicts when using ruby/python defines with main package name - - -##0.9.5( Apr 16, 2015 ) - -###Summary -Bugfix release 0.9.5 - -We reverted the change that implemented the full 40 character for the apt repo key. -This caused issues with some older versions of the puppetlabs-apt module - -####Features - -####Bugfixes -* Revert using the full 40 character for the apt repo key. - -####Changes - -####Testing changes - -####Known bugs -* Possible package conflicts when using ruby/python defines with main package name - - -##0.9.4( Apr 14, 2015 ) - -###Summary -Bugfix release 0.9.4 - -####Features -* Add the ability to create and populate scripts - -####Bugfixes -* add support for init_defaults_file to elasticsearch::instance -* Update apt key to full 40characters - -####Changes -* Fix readme regarding module_dir with plugins - -####Testing changes -* Adding staged removal test -* Convert git urls to https -* Add centos7 node config - -####Known bugs -* Possible package conflicts when using ruby/python defines with main package name - - -##0.9.3( Mar 24, 2015 ) - -###Summary -Bugfix release 0.9.3 - -####Features - -####Bugfixes -* Not setting repo_version did not give the correct error -* Systemd file did not contain User/Group values - -####Changes -* Brand rename from Elasticsearch to Elastic - -####Testing changes -* Moved from multiple Gemfiles to single Gemfile - -####Known bugs -* Possible package conflicts when using ruby/python defines with main package name - -##0.9.2( Mar 06, 2015 ) - -###Summary -Bugfix release 0.9.2 - -####Features -* Introducing es_instance_conn_validator resource to verify instance availability - -####Bugfixes -* Fix missing data path when using the path config setting but not setting the data path - -####Changes -None - -####Testing changes -None - -####Known bugs -* Possible package conflicts when using ruby/python defines with main package name - -##0.9.1 ( Feb 23, 2015 ) - -###Summary -This is the first bug fix release for 0.9 version. -A bug was reported with the recursive file management. - -####Features -None - -####Bugfixes -* Fix recursive file management -* Set undefined variables to work with strict_variables - -####Changes -None - -####Testing changes -None - -####Known bugs -* Possible package conflicts when using ruby/python defines with main package name - -##0.9.0 ( Feb 02, 2015 ) - -###Summary -This release is the first one towards 1.0 release. -Our planning is to provide LTS releases with the puppet module - -####Features -* Support for using hiera to define instances and plugins. -* Support for OpenSuSE 13.x -* Custom facts about the installed Elasticsearch instance(s) -* Proxy host/port support for the plugin installation -* Ability to supply a custom logging.yml template - -####Bugfixes -* Ensure file owners are correct accross all related files -* Fix of possible service name conflict -* Empty main config would fail with instances -* Removal of standard files from packages we dont use -* Ensuring correct sequence of plugin and template defines -* Added ES_CLASSPATH export to init scripts - -####Changes -* Java installation to use puppetlabs-java module -* Added Support and testing for Puppet 3.7 and PE 3.7 -* Improve metadata.json based on scoring from Forge - - -####Testing changes -* Added testing against Puppet 3.7 and PE 3.7 -* Using rspec3 -* Using rspec-puppet-facts gem simplifies rspec testing - -####Known Bugs -* Possible package conflicts when using ruby/python defines with main package name - -##0.4.0 ( Jun 18, 2014 ) - Backwards compatible breaking release - -###Summary -This release introduces instances to facilitate the option to have more then a single instance running on the host system. - -####Features -* Rewrite module to incorperate multi instance support -* New readme layout - -####Bugfixes -* None - -####Changes -* Adding ec2-linux osfamily for repo management -* Retry behaviour for plugin installation - -####Testing changes -* Adding Puppet 3.6.x testing -* Ubuntu 14.04 testing -* Using new docker images -* Pin rspec to 2.14.x - -####Known Bugs -* No known bugs - -##0.3.2 ( May 15, 2014 ) -* Add support for SLC/Scientific Linux CERN ( PR #121 ) -* Add support for custom package names ( PR #122 ) -* Fix python and ruby client defines to avoid name clashes. -* Add ability to use stage instead of anchor for repo class -* Minor fixes to system tests - -##0.3.1 ( April 22, 2014 ) -* Ensure we create the plugin directory before installing plugins -* Added Puppet 3.5.x to rspec and system tests - -##0.3.0 ( April 2, 2014 ) -* Fix minor issue with yumrepo in repo class ( PR #92 ) -* Implement OpenSuse support -* Implement Junit reporting for tests -* Adding more system tests and convert to Docker images -* Use Augeas for managing the defaults file -* Add retry to package download exec -* Add management to manage the logging.yml file -* Improve inline documentation -* Improve support for Debian 6 -* Improve augeas for values with spaces -* Run plugin install as ES user ( PR #108 ) -* Fix rights for the plugin directory -* Pin Rake for Ruby 1.8.7 -* Adding new metadata for Forge. -* Increase time for retry to insert the template - -##0.2.4 ( Feb 21, 2014 ) -* Set puppetlabs-stdlib dependency version from 3.0.0 to 3.2.0 to be inline with other modules -* Let puppet run fail when template insert fails -* Documentation improvements ( PR #77, #78, #83 ) -* Added beaker system tests -* Fixed template define after failing system tests -* Some fixes so variables are more inline with intended structure - -##0.2.3 ( Feb 06, 2014 ) -* Add repository management feature -* Improve testing coverage and implement basic resource coverage reporting -* Add puppet 3.4.x testing -* Fix dependency in template define ( PR #72 ) -* For apt repo change from key server to key file - -##0.2.2 ( Jan 23, 2014 ) -* Ensure exec names are unique. This caused issues when using our logstash module -* Add spec tests for plugin define - -##0.2.1 ( Jan 22, 2014 ) -* Simplify the management of the defaults file ( PR #64 ) -* Doc improvements for the plugin define ( PR #66 ) -* Allow creation of data directory ( PR #68 ) -* Fail early when package version and package_url are defined - -##0.2.0 ( Nov 19, 2013 ) -* Large rewrite of the entire module described below -* Make the core more dynamic for different service providers and multi instance capable -* Add better testing and devided into different files -* Fix template function. Replace of template is now only done when the file is changed -* Add different ways to install the package except from the repository ( puppet/http/https/ftp/file ) -* Update java class to install openjdk 1.7 -* Add tests for python function -* Update config file template to fix scoping issue ( from PR #57 ) -* Add validation of templates -* Small changes for preperation for system tests -* Update readme for new functionality -* Added more test scenario's -* Added puppet parser validate task for added checking -* Ensure we don't add stuff when removing the module -* Update python client define -* Add ruby client define -* Add tests for ruby clients and update python client tests - -##0.1.3 ( Sep 06, 2013 ) -* Exec path settings has been updated to fix warnings ( PR #37, #47 ) -* Adding define to install python bindings ( PR #43 ) -* Scope deprecation fixes ( PR #41 ) -* feature to install plugins ( PR #40 ) - -##0.1.2 ( Jun 21, 2013 ) -* Update rake file to ignore the param inherit -* Added missing documentation to the template define -* Fix for template define to allow multiple templates ( PR #36 by Bruce Morrison ) - -##0.1.1 ( Jun 14, 2013 ) -* Add Oracle Linux to the OS list ( PR #25 by Stas Alekseev ) -* Respect the restart_on_change on the defaults ( PR #29 by Simon Effenberg ) -* Make sure the config can be empty as advertised in the readme -* Remove dependency cycle when the defaults file is updated ( PR #31 by Bruce Morrison ) -* Enable retry on the template insert in case ES isn't started yet ( PR #32 by Bruce Morrison ) -* Update templates to avoid deprecation notice with Puppet 3.2.x -* Update template define to avoid auto insert issue with ES -* Update spec tests to reflect changes to template define - -##0.1.0 ( May 09, 2013 ) -* Populate .gitignore ( PR #19 by Igor Galić ) -* Add ability to install initfile ( PR #20 by Justin Lambert ) -* Add ability to manage default file service parameters ( PR #21 by Mathieu Bornoz ) -* Providing complete containment of the module ( PR #24 by Brian Lalor ) -* Add ability to specify package version ( PR #25 by Justin Lambert ) -* Adding license file - -##0.0.7 ( Mar 23, 2013 ) -* Ensure config directory is created and managed ( PR #13 by Martin Seener ) -* Dont backup package if it changes -* Create explicit dependency on template directory ( PR #16 by Igor Galić ) -* Make the config directory variable ( PR #17 by Igor Galić and PR #18 by Vincent Janelle ) -* Fixing template define - -##0.0.6 ( Mar 05, 2013 ) -* Fixing issue with configuration not printing out arrays -* New feature to write the config hash shorter -* Updated readme to reflect the new feature -* Adding spec tests for config file generation - -##0.0.5 ( Mar 03, 2013 ) -* Option to disable restart on config file change ( PR #10 by Chris Boulton ) - -##0.0.4 ( Mar 02, 2013 ) -* Fixed a major issue with the config template ( Issue #9 ) - -##0.0.3 ( Mar 02, 2013 ) -* Adding spec tests -* Fixed init issue on Ubuntu ( Issue #6 by Marcus Furlong ) -* Fixed config template problem ( Issue #8 by surfchris ) -* New feature to manage templates - -##0.0.2 ( Feb 16, 2013 ) -* Feature to supply a package instead of being dependent on the repository -* Feature to install java in case one doesn't manage it externally -* Adding RedHat and Amazon as Operating systems -* fixed a typo - its a shard not a shared :) ( PR #5 by Martin Seener ) - -##0.0.1 ( Jan 13, 2013 ) -* Initial release of the module diff --git a/puppet/modules/elasticsearch/CONTRIBUTING.md b/puppet/modules/elasticsearch/CONTRIBUTING.md deleted file mode 100644 index 80f5cdd..0000000 --- a/puppet/modules/elasticsearch/CONTRIBUTING.md +++ /dev/null @@ -1,46 +0,0 @@ -If you have a bugfix or new feature that you would like to contribute to this puppet module, please find or open an issue about it first. Talk about what you would like to do. It may be that somebody is already working on it, or that there are particular issues that you should know about before implementing the change. - -We enjoy working with contributors to get their code accepted. There are many approaches to fixing a problem and it is important to find the best approach before writing too much code. - -The process for contributing to any of the Elastic repositories is similar. - -1. Sign the contributor license agreement -Please make sure you have signed the [Contributor License Agreement](http://www.elastic.co/contributor-agreement/). We are not asking you to assign copyright to us, but to give us the right to distribute your code without restriction. We ask this of all contributors in order to assure our users of the origin and continuing existence of the code. You only need to sign the CLA once. - -2. Run the rspec tests and ensure it completes without errors with your changes. - -3. Run the acceptance tests - -These instructions are for Ubuntu 14.04 - -* install docker 0.11.1 - * wget https://get.docker.io/ubuntu/pool/main/l/lxc-docker/lxc-docker_0.11.1_amd64.deb - * wget https://get.docker.io/ubuntu/pool/main/l/lxc-docker-0.11.1/lxc-docker-0.11.1_0.11.1_amd64.deb - * sudo dpkg -i lxc-docker_0.11.1_amd64.deb lxc-docker-0.11.1_0.11.1_amd64.deb - * sudo usermod -a -G docker $USER -* export RS_SET='ubuntu-server-1404-x64' # see spec/acceptance/nodesets for more -* export VM_PUPPET_VERSION='3.7.0' -* wget https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.1.0.deb -* wget https://forgeapi.puppetlabs.com/v3/files/puppetlabs-stdlib-3.2.0.tar.gz -* wget https://forgeapi.puppetlabs.com/v3/files/puppetlabs-apt-1.4.2.tar.gz -* export files_dir=$(pwd) -* bundle install -* bundle exec rspec --require ci/reporter/rspec --format CI::Reporter::RSpecFormatter spec/acceptance/*_spec.rb - -``` - Hypervisor for ubuntu-14-04 is docker - Beaker::Hypervisor, found some docker boxes to create - Provisioning docker - provisioning ubuntu-14-04 - ... - Finished in 18 minutes 6 seconds - 224 examples, 0 failures, 3 pending -``` - -4. Rebase your changes -Update your local repository with the most recent code from the main this puppet module repository, and rebase your branch on top of the latest master branch. We prefer your changes to be squashed into a single commit. - -5. Submit a pull request -Push your local changes to your forked copy of the repository and submit a pull request. In the pull request, describe what your changes do and mention the number of the issue where discussion has taken place, eg “Closes #123″. - -Then sit back and wait. There will probably be discussion about the pull request and, if any changes are needed, we would love to work with you to get your pull request merged into this puppet module. diff --git a/puppet/modules/elasticsearch/CONTRIBUTORS b/puppet/modules/elasticsearch/CONTRIBUTORS deleted file mode 100644 index ad0eb76..0000000 --- a/puppet/modules/elasticsearch/CONTRIBUTORS +++ /dev/null @@ -1,20 +0,0 @@ -The following is a list of people who have contributed ideas, code, bug -reports, or in general have helped this puppet module along its way. - -Project Owner -* Richard Pijnenburg (electrical) - -Contributors: -Martin Seener (martinseener) -Marcus Furlong (furlongm) -Chris Boulton (chrisboulton) -Igor Galić (igalic) -Vincent Janelle (vjanelle) -Mathieu Bornoz (mbornoz) -Justin Lambert (jlambert121) -Brian Lalor (blalor) -Stas Alekseev (salekseev) -Simon Effenberg (Savar) -Bruce Morrison (brucem) -deanmalmgren -Matteo Sessa (msessa-cotd) diff --git a/puppet/modules/elasticsearch/Gemfile b/puppet/modules/elasticsearch/Gemfile deleted file mode 100644 index 7b909a4..0000000 --- a/puppet/modules/elasticsearch/Gemfile +++ /dev/null @@ -1,34 +0,0 @@ -source 'https://rubygems.org' - -puppetversion = ENV['PUPPET_VERSION'] || '~> 3.8.0' -gem 'puppet', puppetversion, :require => false - -#gem 'beaker', :git => 'https://github.com/puppetlabs/beaker.git', :branch => 'master' -gem 'beaker', :git => 'https://github.com/electrical/beaker.git', :branch => 'aoi_var' -gem 'beaker-rspec', :git => 'https://github.com/puppetlabs/beaker-rspec.git', :branch => 'master' -gem 'metadata-json-lint', :git => 'https://github.com/nibalizer/metadata-json-lint.git', :branch => 'master' -gem 'rspec-puppet', '2.2.0' -gem 'specinfra', :git => 'https://github.com/electrical/specinfra.git', :branch => 'pkg_check' - -gem 'pry' -gem 'docker-api', '~> 1.0' -gem 'rubysl-securerandom' -gem 'ci_reporter_rspec' -gem 'rspec', '~> 3.0' -gem 'rake' -gem 'puppet-doc-lint' -gem 'puppet-lint' -gem 'puppetlabs_spec_helper' -gem 'puppet-syntax' -gem 'rspec-puppet-facts' -gem 'webmock' - -# Extra Puppet-lint gems -gem 'puppet-lint-appends-check', :require => false -gem 'puppet-lint-version_comparison-check', :require => false -gem 'puppet-lint-unquoted_string-check', :require => false -gem 'puppet-lint-undef_in_function-check', :require => false -gem 'puppet-lint-trailing_comma-check', :require => false -gem 'puppet-lint-leading_zero-check', :require => false -gem 'puppet-lint-file_ensure-check', :require => false -gem 'puppet-lint-empty_string-check', :require => false diff --git a/puppet/modules/elasticsearch/Gemfile.lock b/puppet/modules/elasticsearch/Gemfile.lock deleted file mode 100644 index 6f0c404..0000000 --- a/puppet/modules/elasticsearch/Gemfile.lock +++ /dev/null @@ -1,391 +0,0 @@ -GIT - remote: https://github.com/electrical/beaker.git - revision: 3095cd0fa64bfd265a338ef653c01c044fe9ef58 - branch: aoi_var - specs: - beaker (2.14.1) - aws-sdk (~> 1.57) - docker-api - fission (~> 0.4) - fog (~> 1.25) - google-api-client (~> 0.8) - hocon (~> 0.1) - inifile (~> 2.0) - json (~> 1.8) - minitest (~> 5.4) - net-scp (~> 1.2) - net-ssh (~> 2.9) - rbvmomi (~> 1.8) - rsync (~> 1.0.9) - unf (~> 0.1) - -GIT - remote: https://github.com/electrical/specinfra.git - revision: aac8075ffc80555a105912b944fd860130566a1d - branch: pkg_check - specs: - specinfra (2.43.0) - net-scp - net-ssh (~> 2.7) - net-telnet - sfl - -GIT - remote: https://github.com/nibalizer/metadata-json-lint.git - revision: 575420f268bae4cc601de96da3fe0704163963fa - branch: master - specs: - metadata-json-lint (0.0.6) - json - spdx-licenses (~> 1.0) - -GIT - remote: https://github.com/puppetlabs/beaker-rspec.git - revision: 49c45f6102fe85a8f34d70139af507bc31a45fea - branch: master - specs: - beaker-rspec (5.2.1) - beaker (~> 2.0) - rspec - serverspec (~> 2) - specinfra (~> 2) - -GEM - remote: https://rubygems.org/ - specs: - CFPropertyList (2.2.8) - activesupport (4.2.4) - i18n (~> 0.7) - json (~> 1.7, >= 1.7.7) - minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) - tzinfo (~> 1.1) - addressable (2.3.8) - autoparse (0.3.3) - addressable (>= 2.3.1) - extlib (>= 0.9.15) - multi_json (>= 1.0.0) - aws-sdk (1.65.0) - aws-sdk-v1 (= 1.65.0) - aws-sdk-v1 (1.65.0) - json (~> 1.4) - nokogiri (~> 1.8.1) - axiom-types (0.1.1) - descendants_tracker (~> 0.0.4) - ice_nine (~> 0.11.0) - thread_safe (~> 0.3, >= 0.3.1) - builder (3.2.2) - ci_reporter (2.0.0) - builder (>= 2.1.2) - ci_reporter_rspec (1.0.0) - ci_reporter (~> 2.0) - rspec (>= 2.14, < 4) - coderay (1.1.0) - coercible (1.0.0) - descendants_tracker (~> 0.0.1) - crack (0.4.2) - safe_yaml (~> 1.0.0) - descendants_tracker (0.0.4) - thread_safe (~> 0.3, >= 0.3.1) - diff-lcs (1.2.5) - docker-api (1.22.3) - excon (>= 0.38.0) - json - equalizer (0.0.11) - excon (0.45.4) - extlib (0.9.16) - facter (2.4.4) - CFPropertyList (~> 2.2.6) - facterdb (0.2.1) - facter - jgrep - json - faraday (0.9.1) - multipart-post (>= 1.2, < 3) - fission (0.5.0) - CFPropertyList (~> 2.2) - fog (1.33.0) - fog-atmos - fog-aws (>= 0.6.0) - fog-brightbox (~> 0.4) - fog-core (~> 1.32) - fog-dynect - fog-ecloud (= 0.1.1) - fog-google (>= 0.0.2) - fog-json - fog-local - fog-powerdns (>= 0.1.1) - fog-profitbricks - fog-radosgw (>= 0.0.2) - fog-riakcs - fog-sakuracloud (>= 0.0.4) - fog-serverlove - fog-softlayer - fog-storm_on_demand - fog-terremark - fog-vmfusion - fog-voxel - fog-xml (~> 0.1.1) - ipaddress (~> 0.5) - nokogiri (~> 1.8.1) - fog-atmos (0.1.0) - fog-core - fog-xml - fog-aws (0.7.6) - fog-core (~> 1.27) - fog-json (~> 1.0) - fog-xml (~> 0.1) - ipaddress (~> 0.8) - fog-brightbox (0.9.0) - fog-core (~> 1.22) - fog-json - inflecto (~> 0.0.2) - fog-core (1.32.1) - builder - excon (~> 0.45) - formatador (~> 0.2) - mime-types - net-scp (~> 1.1) - net-ssh (>= 2.1.3) - fog-dynect (0.0.2) - fog-core - fog-json - fog-xml - fog-ecloud (0.1.1) - fog-core - fog-xml - fog-google (0.0.7) - fog-core - fog-json - fog-xml - fog-json (1.0.2) - fog-core (~> 1.0) - multi_json (~> 1.10) - fog-local (0.2.1) - fog-core (~> 1.27) - fog-powerdns (0.1.1) - fog-core (~> 1.27) - fog-json (~> 1.0) - fog-xml (~> 0.1) - fog-profitbricks (0.0.5) - fog-core - fog-xml - nokogiri - fog-radosgw (0.0.4) - fog-core (>= 1.21.0) - fog-json - fog-xml (>= 0.0.1) - fog-riakcs (0.1.0) - fog-core - fog-json - fog-xml - fog-sakuracloud (1.0.1) - fog-core - fog-json - fog-serverlove (0.1.2) - fog-core - fog-json - fog-softlayer (0.4.7) - fog-core - fog-json - fog-storm_on_demand (0.1.1) - fog-core - fog-json - fog-terremark (0.1.0) - fog-core - fog-xml - fog-vmfusion (0.1.0) - fission - fog-core - fog-voxel (0.1.0) - fog-core - fog-xml - fog-xml (0.1.2) - fog-core - nokogiri (~> 1.8.1) - formatador (0.2.5) - google-api-client (0.8.6) - activesupport (>= 3.2) - addressable (~> 2.3) - autoparse (~> 0.3) - extlib (~> 0.9) - faraday (~> 0.9) - googleauth (~> 0.3) - launchy (~> 2.4) - multi_json (~> 1.10) - retriable (~> 1.4) - signet (~> 0.6) - googleauth (0.4.2) - faraday (~> 0.9) - jwt (~> 1.4) - logging (~> 2.0) - memoist (~> 0.12) - multi_json (~> 1.11) - signet (~> 0.6) - hiera (1.3.4) - json_pure - hocon (0.9.3) - i18n (0.7.0) - ice_nine (0.11.1) - inflecto (0.0.2) - inifile (2.0.2) - ipaddress (0.8.0) - jgrep (1.3.3) - json - json (1.8.3) - json_pure (1.8.2) - jwt (1.5.1) - launchy (2.4.3) - addressable (~> 2.3) - little-plugger (1.1.4) - logging (2.0.0) - little-plugger (~> 1.1) - multi_json (~> 1.10) - memoist (0.12.0) - metaclass (0.0.4) - method_source (0.8.2) - mime-types (2.6.1) - mini_portile (0.6.2) - minitest (5.8.0) - mocha (1.1.0) - metaclass (~> 0.0.1) - multi_json (1.11.2) - multipart-post (2.0.0) - net-scp (1.2.1) - net-ssh (>= 2.6.5) - net-ssh (2.9.2) - net-telnet (0.1.1) - nokogiri (~> 1.8.1) - mini_portile (~> 0.6.0) - pry (0.10.1) - coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) - puppet (3.8.2) - facter (> 1.6, < 3) - hiera (~> 1.0) - json_pure - puppet-doc-lint (0.3.0) - facter - puppet - rdoc (>= 3.12, < 4.0) - virtus (~> 1.0.1) - puppet-lint (1.1.0) - puppet-lint-appends-check (0.1.0) - puppet-lint (~> 1.0) - puppet-lint-empty_string-check (0.2.1) - puppet-lint (~> 1.0) - puppet-lint-file_ensure-check (0.2.1) - puppet-lint (~> 1.0) - puppet-lint-leading_zero-check (0.1.0) - puppet-lint (~> 1.0) - puppet-lint-trailing_comma-check (0.3.1) - puppet-lint (~> 1.0) - puppet-lint-undef_in_function-check (0.1.0) - puppet-lint (~> 1.0) - puppet-lint-unquoted_string-check (0.2.5) - puppet-lint (~> 1.0) - puppet-lint-version_comparison-check (0.1.2) - puppet-lint (~> 1.0) - puppet-syntax (2.0.0) - rake - puppetlabs_spec_helper (0.10.3) - mocha - puppet-lint - puppet-syntax - rake - rspec-puppet - rake (10.4.2) - rbvmomi (1.8.2) - builder - nokogiri (~> 1.8.1) - trollop - rdoc (3.12.2) - json (~> 1.4) - retriable (1.4.1) - rspec (3.3.0) - rspec-core (~> 3.3.0) - rspec-expectations (~> 3.3.0) - rspec-mocks (~> 3.3.0) - rspec-core (3.3.2) - rspec-support (~> 3.3.0) - rspec-expectations (3.3.1) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.3.0) - rspec-its (1.2.0) - rspec-core (>= 3.0.0) - rspec-expectations (>= 3.0.0) - rspec-mocks (3.3.2) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.3.0) - rspec-puppet (2.2.0) - rspec - rspec-puppet-facts (1.0.2) - facter - facterdb (>= 0.2.0) - json - rspec-support (3.3.0) - rsync (1.0.9) - rubysl-securerandom (2.0.0) - safe_yaml (1.0.4) - serverspec (2.23.0) - multi_json - rspec (~> 3.0) - rspec-its - specinfra (~> 2.43) - sfl (2.2) - signet (0.6.1) - addressable (~> 2.3) - extlib (~> 0.9) - faraday (~> 0.9) - jwt (~> 1.5) - multi_json (~> 1.10) - slop (3.6.0) - spdx-licenses (1.0.0) - json - thread_safe (0.3.5) - trollop (2.1.2) - tzinfo (1.2.2) - thread_safe (~> 0.1) - unf (0.1.4) - unf_ext - unf_ext (0.0.7.1) - virtus (1.0.5) - axiom-types (~> 0.1) - coercible (~> 1.0) - descendants_tracker (~> 0.0, >= 0.0.3) - equalizer (~> 0.0, >= 0.0.9) - webmock (1.21.0) - addressable (>= 2.3.6) - crack (>= 0.3.2) - -PLATFORMS - ruby - -DEPENDENCIES - beaker! - beaker-rspec! - ci_reporter_rspec - docker-api (~> 1.0) - metadata-json-lint! - pry - puppet (~> 3.8.0) - puppet-doc-lint - puppet-lint - puppet-lint-appends-check - puppet-lint-empty_string-check - puppet-lint-file_ensure-check - puppet-lint-leading_zero-check - puppet-lint-trailing_comma-check - puppet-lint-undef_in_function-check - puppet-lint-unquoted_string-check - puppet-lint-version_comparison-check - puppet-syntax - puppetlabs_spec_helper - rake - rspec (~> 3.0) - rspec-puppet (= 2.2.0) - rspec-puppet-facts - rubysl-securerandom - specinfra! - webmock diff --git a/puppet/modules/elasticsearch/LICENSE b/puppet/modules/elasticsearch/LICENSE deleted file mode 100644 index b4d5528..0000000 --- a/puppet/modules/elasticsearch/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2012-2015 Elasticsearch '1.4.2' -} -``` - -Note: This will only work when using the repository. - -####Automatic upgrade of the software ( default set to false ) -``` -class { 'elasticsearch': - autoupgrade => true -} -``` - -####Removal/decommissioning -```puppet -class { 'elasticsearch': - ensure => 'absent' -} -``` - -####Install everything but disable service(s) afterwards -```puppet -class { 'elasticsearch': - status => 'disabled' -} -``` - -###Instances - -This module works with the concept of instances. For service to start you need to specify at least one instance. - -####Quick setup -```puppet -elasticsearch::instance { 'es-01': } -``` - -This will set up its own data directory and set the node name to `$hostname-$instance_name` - -####Advanced options - -Instance specific options can be given: - -```puppet -elasticsearch::instance { 'es-01': - config => { }, # Configuration hash - init_defaults => { }, # Init defaults hash - datadir => [ ], # Data directory -} -``` - -See [Advanced features](#advanced-features) for more information - -###Plug-ins - -Install [a variety of plugins](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-plugins.html#known-plugins). Note that `module_dir` is where the plugin will install itself to and must match that published by the plugin author; it is not where you would like to install it yourself. - -####From official repository -```puppet -elasticsearch::plugin{'lmenezes/elasticsearch-kopf': - instances => 'instance_name' -} -``` -####From custom url -```puppet -elasticsearch::plugin{ 'jetty': - url => 'https://oss-es-plugins.s3.amazonaws.com/elasticsearch-jetty/elasticsearch-jetty-1.2.1.zip', - instances => 'instance_name' -} -``` - - -####Using a proxy -You can also use a proxy if required by setting the `proxy_host` and `proxy_port` options: -```puppet -elasticsearch::plugin { 'lmenezes/elasticsearch-kopf', - instances => 'instance_name', - proxy_host => 'proxy.host.com', - proxy_port => 3128 -} -``` - -#####Plugin name could be: -* `elasticsearch/plugin/version` for official elasticsearch plugins (download from download.elasticsearch.org) -* `groupId/artifactId/version` for community plugins (download from maven central or oss sonatype) -* `username/repository` for site plugins (download from github master) - -####Upgrading plugins -When you specify a certain plugin version, you can upgrade that plugin by specifying the new version. - -```puppet -elasticsearch::plugin { 'elasticsearch/elasticsearch-cloud-aws/2.1.1': -} -``` - -And to upgrade, you would simply change it to - -```puppet -elasticsearch::plugin { 'elasticsearch/elasticsearch-cloud-aws/2.4.1': -} -``` - -Please note that this does not work when you specify 'latest' as a version number. - -###Scripts - -Install [scripts](http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html) to be used by Elasticsearch. -These scripts are shared accross all defined instances on the same host. - -```puppet -elasticsearch::script { 'myscript': - ensure => 'present', - source => 'puppet:///path/to/my/script.groovy' -} -``` - -###Templates - -#### Add a new template using a file - -This will install and/or replace the template in Elasticsearch: - -```puppet -elasticsearch::template { 'templatename': - file => 'puppet:///path/to/template.json' -} -``` - -#### Add a new template using content - -This will install and/or replace the template in Elasticsearch: - -```puppet -elasticsearch::template { 'templatename': - content => '{"template":"*","settings":{"number_of_replicas":0}}' -} -``` - -#### Delete a template - -```puppet -elasticsearch::template { 'templatename': - ensure => 'absent' -} -``` - -#### Host - -By default it uses localhost:9200 as host. you can change this with the `host` and `port` variables - -```puppet -elasticsearch::template { 'templatename': - host => $::ipaddress, - port => 9200 -} -``` - -###Bindings / Clients - -Install a variety of [clients/bindings](http://www.elasticsearch.org/guide/en/elasticsearch/client/community/current/clients.html): - -####Python - -```puppet -elasticsearch::python { 'rawes': } -``` - -####Ruby -```puppet -elasticsearch::ruby { 'elasticsearch': } -``` - -###Connection Validator - -This module offers a way to make sure an instance has been started and is up and running before -doing a next action. This is done via the use of the `es_instance_conn_validator` resource. -```puppet -es_instance_conn_validator { 'myinstance' : - server => 'es.example.com', - port => '9200', -} -``` - -A common use would be for example : - -```puppet -class { 'kibana4' : - require => Es_Instance_Conn_Validator['myinstance'], -} -``` - -###Package installation - -There are 2 different ways of installing the software - -####Repository - -This option allows you to use an existing repository for package installation. -The `repo_version` corresponds with the major version of Elasticsearch. - -```puppet -class { 'elasticsearch': - manage_repo => true, - repo_version => '1.4', -} -``` - -####Remote package source - -When a repository is not available or preferred you can install the packages from a remote source: - -#####http/https/ftp -```puppet -class { 'elasticsearch': - package_url => 'https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.4.2.deb', - proxy_url => 'http://proxy.example.com:8080/', -} -``` -Setting proxy_url to a location will enable download using the provided proxy -server. This parameter is also used by elasticsearch::plugin. Setting the port -in the proxy_url is mandatory. proxy_url defaults to undef (proxy disabled). - -#####puppet:// -```puppet -class { 'elasticsearch': - package_url => 'puppet:///path/to/elasticsearch-1.4.2.deb' -} -``` - -#####Local file -```puppet -class { 'elasticsearch': - package_url => 'file:/path/to/elasticsearch-1.4.2.deb' -} -``` - -###Java installation - -Most sites will manage Java separately; however, this module can attempt to install Java as well. -This is done by using the [puppetlabs-java](https://forge.puppetlabs.com/puppetlabs/java) module. - -```puppet -class { 'elasticsearch': - java_install => true -} -``` - -Specify a particular Java package/version to be installed: - -```puppet -class { 'elasticsearch': - java_install => true, - java_package => 'packagename' -} -``` - -###Service management - -Currently only the basic SysV-style [init](https://en.wikipedia.org/wiki/Init) and [Systemd](http://en.wikipedia.org/wiki/Systemd) service providers are supported, but other systems could be implemented as necessary (pull requests welcome). - - -####Defaults File - -The *defaults* file (`/etc/defaults/elasticsearch` or `/etc/sysconfig/elasticsearch`) for the Elasticsearch service can be populated as necessary. This can either be a static file resource or a simple key value-style [hash](http://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#hashes) object, the latter being particularly well-suited to pulling out of a data source such as Hiera. - -#####file source -```puppet -class { 'elasticsearch': - init_defaults_file => 'puppet:///path/to/defaults' -} -``` -#####hash representation -```puppet -$config_hash = { - 'ES_USER' => 'elasticsearch', - 'ES_GROUP' => 'elasticsearch', -} - -class { 'elasticsearch': - init_defaults => $config_hash -} -``` - -Note: `init_defaults` hash can be passed to the main class and to the instance. - -##Advanced features - -###Package version pinning - -The module supports pinning the package version to avoid accidental upgrades that are not done by Puppet. -To enable this feature: - -```puppet -class { 'elasticsearch': - package_pin => true, - version => '1.5.2', -} -``` - -In this example we pin the package version to 1.5.2. - - -###Data directories - -There are 4 different ways of setting data directories for Elasticsearch. -In every case the required configuration options are placed in the `elasticsearch.yml` file. - -####Default -By default we use: - -`/usr/share/elasticsearch/data/$instance_name` - -Which provides a data directory per instance. - - -####Single global data directory - -```puppet -class { 'elasticsearch': - datadir => '/var/lib/elasticsearch-data' -} -``` -Creates the following for each instance: - -`/var/lib/elasticsearch-data/$instance_name` - -####Multiple Global data directories - -```puppet -class { 'elasticsearch': - datadir => [ '/var/lib/es-data1', '/var/lib/es-data2'] -} -``` -Creates the following for each instance: -`/var/lib/es-data1/$instance_name` -and -`/var/lib/es-data2/$instance_name` - - -####Single instance data directory - -```puppet -class { 'elasticsearch': } - -elasticsearch::instance { 'es-01': - datadir => '/var/lib/es-data-es01' -} -``` -Creates the following for this instance: -`/var/lib/es-data-es01` - -####Multiple instance data directories - -```puppet -class { 'elasticsearch': } - -elasticsearch::instance { 'es-01': - datadir => ['/var/lib/es-data1-es01', '/var/lib/es-data2-es01'] -} -``` -Creates the following for this instance: -`/var/lib/es-data1-es01` -and -`/var/lib/es-data2-es01` - - -###Main and instance configurations - -The `config` option in both the main class and the instances can be configured to work together. - -The options in the `instance` config hash will merged with the ones from the main class and override any duplicates. - -#### Simple merging - -```puppet -class { 'elasticsearch': - config => { 'cluster.name' => 'clustername' } -} - -elasticsearch::instance { 'es-01': - config => { 'node.name' => 'nodename' } -} -elasticsearch::instance { 'es-02': - config => { 'node.name' => 'nodename2' } -} - -``` - -This example merges the `cluster.name` together with the `node.name` option. - -#### Overriding - -When duplicate options are provided, the option in the instance config overrides the ones from the main class. - -```puppet -class { 'elasticsearch': - config => { 'cluster.name' => 'clustername' } -} - -elasticsearch::instance { 'es-01': - config => { 'node.name' => 'nodename', 'cluster.name' => 'otherclustername' } -} - -elasticsearch::instance { 'es-02': - config => { 'node.name' => 'nodename2' } -} -``` - -This will set the cluster name to `otherclustername` for the instance `es-01` but will keep it to `clustername` for instance `es-02` - -####Configuration writeup - -The `config` hash can be written in 2 different ways: - -##### Full hash writeup - -Instead of writing the full hash representation: -```puppet -class { 'elasticsearch': - config => { - 'cluster' => { - 'name' => 'ClusterName', - 'routing' => { - 'allocation' => { - 'awareness' => { - 'attributes' => 'rack' - } - } - } - } - } -} -``` -##### Short hash writeup -```puppet -class { 'elasticsearch': - config => { - 'cluster' => { - 'name' => 'ClusterName', - 'routing.allocation.awareness.attributes' => 'rack' - } - } -} -``` - - -##Limitations - -This module has been built on and tested against Puppet 3.2 and higher. - -The module has been tested on: - -* Debian 6/7/8 -* CentOS 6/7 -* Ubuntu 12.04, 14.04 -* OpenSuSE 13.x - -Other distro's that have been reported to work: - -* RHEL 6 -* OracleLinux 6 -* Scientific 6 - -Testing on other platforms has been light and cannot be guaranteed. - -##Development - - -##Support - -Need help? Join us in [#elasticsearch](https://webchat.freenode.net?channels=%23elasticsearch) on Freenode IRC or on the [discussion forum](https://discuss.elastic.co/). diff --git a/puppet/modules/elasticsearch/checksums.json b/puppet/modules/elasticsearch/checksums.json deleted file mode 100644 index dde8b14..0000000 --- a/puppet/modules/elasticsearch/checksums.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "CHANGELOG.md": "97b18c5af83cc0f06f71791a8f00a637", - "CONTRIBUTING.md": "c2985e231626a62f65cb661eaa346794", - "CONTRIBUTORS": "14df2fd27cf7b6ca9833527f2ba93442", - "Gemfile": "958613c7f81a6ad9f16ab090031454b0", - "Gemfile.lock": "ee5e0ae4e636be7b57ca380f5f3193eb", - "LICENSE": "a901c0476a59f754aad3b357e7f53786", - "README.md": "db8644a33f7957e952a0a4fbba848e3d", - "lib/facter/es_facts.rb": "1f5f6e4b25892f25ee8a9e6591683a93", - "lib/puppet/parser/functions/array_suffix.rb": "f4d8cfd448698eb9594f49bb2ed3c263", - "lib/puppet/parser/functions/plugin_dir.rb": "f26b6578f9ab2dcbc61287afef04357a", - "lib/puppet/provider/es_instance_conn_validator/tcp_port.rb": "1f20143aa8023524ad568cabc0fc36c8", - "lib/puppet/type/es_instance_conn_validator.rb": "60016925ceb392dad8e4d1c7f4bcbea7", - "lib/puppet/util/es_instance_validator.rb": "ded80d7d5ae1467f1060a57de7210cad", - "manifests/config.pp": "68db5a4960d52c81d226bc23de0535d8", - "manifests/init.pp": "29b70f4a4378cf13cff3b77dfc2d7ff6", - "manifests/instance.pp": "7761f6f7929290840f1bf6cc035c7fd6", - "manifests/package.pp": "01296c08acf83622b1ac0617777bb042", - "manifests/params.pp": "e265ed46f35222e4ac28351d287958bc", - "manifests/plugin.pp": "4fd0b49d76af84479803f33444d4b5e8", - "manifests/python.pp": "109f076fea175ffef78da479952dc1a0", - "manifests/repo.pp": "ab5f1d500e278f04b6ac248ea8b52621", - "manifests/ruby.pp": "dd72a2538e23bba1c47618c9b3e6d66f", - "manifests/script.pp": "d609aa414a3c60ecabe33ec97c4533f5", - "manifests/service/init.pp": "dc6817e1414e59f1fe23470c38a03c5d", - "manifests/service/systemd.pp": "4c98c2ea7d6273fa9a3b35075a9782e0", - "manifests/service.pp": "b34e3bb5a3984de44c9ad2566734576e", - "manifests/template.pp": "4d2944bdfed2495cdcd95326b2a0aa0e", - "metadata.json": "4a23421fd2b1481d264009a3d53f2c54", - "templates/etc/elasticsearch/elasticsearch.yml.erb": "72bea984e864802f684f28e59b804f3c", - "templates/etc/elasticsearch/logging.yml.erb": "99062dbf00c6b96d9bec7382dadafb9d", - "templates/etc/init.d/elasticsearch.Debian.erb": "34f518d4ba48819e48b1f10ef29c8dac", - "templates/etc/init.d/elasticsearch.RedHat.erb": "0627cd64bbeab97904e21b595b5007ee", - "templates/etc/init.d/elasticsearch.systemd.erb": "3f94ed7e9bc7185b9fe687e9798589c5", - "templates/etc/sysconfig/defaults.erb": "57b40f8213c0c05d5dcf185bf00a25b7", - "templates/usr/lib/tmpfiles.d/elasticsearch.conf.erb": "c1f7ed94a017e6b919504c904be7d259" -} \ No newline at end of file diff --git a/puppet/modules/elasticsearch/lib/facter/es_facts.rb b/puppet/modules/elasticsearch/lib/facter/es_facts.rb deleted file mode 100644 index d9b4bca..0000000 --- a/puppet/modules/elasticsearch/lib/facter/es_facts.rb +++ /dev/null @@ -1,99 +0,0 @@ -require 'net/http' -require 'json' -require 'yaml' - -module EsFacts - - def self.add_fact(prefix, key, value) - key = "#{prefix}_#{key}".to_sym - ::Facter.add(key) do - setcode { value } - end - end - - def self.run - - dir_prefix = '/etc/elasticsearch' - ports = [] - - # only when the directory exists we need to process the stuff - if File.directory?(dir_prefix) - - Dir.foreach(dir_prefix) { |dir| - next if dir == '.' - if File.exists?("#{dir_prefix}/#{dir}/elasticsearch.yml") - config_data = YAML.load_file("#{dir_prefix}/#{dir}/elasticsearch.yml") - unless config_data['http'].nil? - next if config_data['http']['enabled'] == 'false' - if config_data['http']['port'].nil? - port = "9200" - else - port = config_data['http']['port'] - end - else - port = "9200" - end - ports << port - end - } - - begin - if ports.count > 0 - - add_fact('elasticsearch', 'ports', ports.join(",") ) - ports.each do |port| - - key_prefix = "elasticsearch_#{port}" - - uri = URI("http://localhost:#{port}") - http = Net::HTTP.new(uri.host, uri.port) - http.read_timeout = 10 - response = http.get("/") - json_data = JSON.parse(response.body) - next if json_data['status'] && json_data['status'] != 200 - - add_fact(key_prefix, 'name', json_data['name']) - add_fact(key_prefix, 'version', json_data['version']['number']) - - uri2 = URI("http://localhost:#{port}/_nodes/#{json_data['name']}") - http2 = Net::HTTP.new(uri2.host, uri2.port) - http2.read_timeout = 10 - response2 = http2.get(uri2.path) - json_data_node = JSON.parse(response2.body) - - add_fact(key_prefix, 'cluster_name', json_data_node['cluster_name']) - node_data = json_data_node['nodes'].first - - add_fact(key_prefix, 'node_id', node_data[0]) - - nodes_data = json_data_node['nodes'][node_data[0]] - - process = nodes_data['process'] - add_fact(key_prefix, 'mlockall', process['mlockall']) - - plugins = nodes_data['plugins'] - - plugin_names = [] - plugins.each do |plugin| - plugin_names << plugin['name'] - - plugin.each do |key, value| - prefix = "#{key_prefix}_plugin_#{plugin['name']}" - add_fact(prefix, key, value) unless key == 'name' - end - end - add_fact(key_prefix, 'plugins', plugin_names.join(",")) - - end - - end - rescue - end - - end - - end - -end - -EsFacts.run diff --git a/puppet/modules/elasticsearch/lib/puppet/parser/functions/array_suffix.rb b/puppet/modules/elasticsearch/lib/puppet/parser/functions/array_suffix.rb deleted file mode 100644 index 0f2da68..0000000 --- a/puppet/modules/elasticsearch/lib/puppet/parser/functions/array_suffix.rb +++ /dev/null @@ -1,45 +0,0 @@ -# -# suffix.rb -# - -module Puppet::Parser::Functions - newfunction(:array_suffix, :type => :rvalue, :doc => <<-EOS -This function applies a suffix to all elements in an array. - -*Examples:* - - array_suffix(['a','b','c'], 'p') - -Will return: ['ap','bp','cp'] - EOS - ) do |arguments| - - # Technically we support two arguments but only first is mandatory ... - raise(Puppet::ParseError, "array_suffix(): Wrong number of arguments " + - "given (#{arguments.size} for 1)") if arguments.size < 1 - - array = arguments[0] - - unless array.is_a?(Array) - raise Puppet::ParseError, "array_suffix(): expected first argument to be an Array, got #{array.inspect}" - end - - suffix = arguments[1] if arguments[1] - - if suffix - unless suffix.is_a? String - raise Puppet::ParseError, "array_suffix(): expected second argument to be a String, got #{suffix.inspect}" - end - end - - # Turn everything into string same as join would do ... - result = array.collect do |i| - i = i.to_s - suffix ? i + suffix : i - end - - return result - end -end - -# vim: set ts=2 sw=2 et : diff --git a/puppet/modules/elasticsearch/lib/puppet/parser/functions/plugin_dir.rb b/puppet/modules/elasticsearch/lib/puppet/parser/functions/plugin_dir.rb deleted file mode 100644 index 94c1ce1..0000000 --- a/puppet/modules/elasticsearch/lib/puppet/parser/functions/plugin_dir.rb +++ /dev/null @@ -1,43 +0,0 @@ -module Puppet::Parser::Functions - newfunction(:plugin_dir, :type => :rvalue, :doc => <<-EOS - Extracts the end plugin directory of the name - EOS - ) do |arguments| - - if arguments.size < 1 then - raise(Puppet::ParseError, "plugin_dir(): No arguments given") - elsif arguments.size > 2 then - raise(Puppet::ParseError, "plugin_dir(): Too many arguments given (#{arguments.size})") - else - - unless arguments[0].is_a?(String) - raise(Puppet::ParseError, 'plugin_dir(): Requires string as first argument') - end - - plugin_name = arguments[0] - items = plugin_name.split("/") - - if items.count == 1 - endname = items[0] - elsif items.count > 1 - plugin = items[1] - if plugin.include?('-') # example elasticsearch-head - if plugin.start_with?('elasticsearch-') - endname = plugin.gsub('elasticsearch-', '') - elsif plugin.start_with?('es-') - endname = plugin.gsub('es-', '') - else - endname = plugin - end - else - endname = plugin - end - else - raise(Puppet::ParseError, "Unable to parse plugin name: #{plugin_name}") - end - - return endname - - end - end -end diff --git a/puppet/modules/elasticsearch/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb b/puppet/modules/elasticsearch/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb deleted file mode 100644 index 3cd1ef6..0000000 --- a/puppet/modules/elasticsearch/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb +++ /dev/null @@ -1,51 +0,0 @@ -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__),"..","..","..")) -require 'puppet/util/es_instance_validator' - -# This file contains a provider for the resource type `es_instance_conn_validator`, -# which validates the Elasticsearch instance connection by attempting an https connection. - -Puppet::Type.type(:es_instance_conn_validator).provide(:tcp_port) do - desc "A provider for the resource type `es_instance_conn_validator`, - which validates the connection by attempting an https - connection to the Elasticsearch instance." - - def exists? - start_time = Time.now - timeout = resource[:timeout] - - success = validator.attempt_connection - - while success == false && ((Time.now - start_time) < timeout) - # It can take several seconds for the Elasticsearch instance to start up; - # especially on the first install. Therefore, our first connection attempt - # may fail. Here we have somewhat arbitrarily chosen to retry every 2 - # seconds until the configurable timeout has expired. - Puppet.debug("Failed to connect to the Elasticsearch instance; sleeping 2 seconds before retry") - sleep 2 - success = validator.attempt_connection - end - - if success - Puppet.debug("Connected to the ES instance in #{Time.now - start_time} seconds.") - else - Puppet.notice("Failed to connect to the ES instance within timeout window of #{timeout} seconds; giving up.") - end - - success - end - - def create - # If `#create` is called, that means that `#exists?` returned false, which - # means that the connection could not be established... so we need to - # cause a failure here. - raise Puppet::Error, "Unable to connect to ES instance ! (#{@validator.instance_server}:#{@validator.instance_port})" - end - - private - - # @api private - def validator - @validator ||= Puppet::Util::EsInstanceValidator.new(resource[:server], resource[:port]) - end - -end diff --git a/puppet/modules/elasticsearch/lib/puppet/type/es_instance_conn_validator.rb b/puppet/modules/elasticsearch/lib/puppet/type/es_instance_conn_validator.rb deleted file mode 100644 index 5ecd14d..0000000 --- a/puppet/modules/elasticsearch/lib/puppet/type/es_instance_conn_validator.rb +++ /dev/null @@ -1,38 +0,0 @@ -Puppet::Type.newtype(:es_instance_conn_validator) do - - @doc = "Verify that a connection can be successfully established between a node - and the Elasticsearch instance. It could potentially be used for other - purposes such as monitoring." - - ensurable do - defaultvalues - defaultto :present - end - - newparam(:name, :namevar => true) do - desc 'An arbitrary name used as the identity of the resource.' - end - - newparam(:server) do - desc 'DNS name or IP address of the server where Elasticsearch instance should be running.' - defaultto 'localhost' - end - - newparam(:port) do - desc 'The port that the Elasticsearch instance should be listening on.' - defaultto 9200 - end - - newparam(:timeout) do - desc 'The max number of seconds that the validator should wait before giving up and deciding that the Elasticsearch instance is not running; defaults to 60 seconds.' - defaultto 60 - validate do |value| - # This will raise an error if the string is not convertible to an integer - Integer(value) - end - munge do |value| - Integer(value) - end - end - -end diff --git a/puppet/modules/elasticsearch/lib/puppet/util/es_instance_validator.rb b/puppet/modules/elasticsearch/lib/puppet/util/es_instance_validator.rb deleted file mode 100644 index e097314..0000000 --- a/puppet/modules/elasticsearch/lib/puppet/util/es_instance_validator.rb +++ /dev/null @@ -1,36 +0,0 @@ -require 'socket' -require 'timeout' - -module Puppet - module Util - class EsInstanceValidator - attr_reader :instance_server - attr_reader :instance_port - - def initialize(instance_server, instance_port) - @instance_server = instance_server - @instance_port = instance_port - end - - # Utility method; attempts to make an https connection to the Elasticsearch instance. - # This is abstracted out into a method so that it can be called multiple times - # for retry attempts. - # - # @return true if the connection is successful, false otherwise. - def attempt_connection - Timeout::timeout(Puppet[:configtimeout]) do - begin - TCPSocket.new(@instance_server, @instance_port).close - true - rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e - Puppet.debug "Unable to connect to Elasticsearch instance (#{@instance_server}:#{@instance_port}): #{e.message}" - false - end - end - rescue Timeout::Error - false - end - end - end -end - diff --git a/puppet/modules/elasticsearch/manifests/config.pp b/puppet/modules/elasticsearch/manifests/config.pp deleted file mode 100644 index 405c653..0000000 --- a/puppet/modules/elasticsearch/manifests/config.pp +++ /dev/null @@ -1,139 +0,0 @@ -# == Class: elasticsearch::config -# -# This class exists to coordinate all configuration related actions, -# functionality and logical units in a central place. -# -# -# === Parameters -# -# This class does not provide any parameters. -# -# -# === Examples -# -# This class may be imported by other classes to use its functionality: -# class { 'elasticsearch::config': } -# -# It is not intended to be used directly by external resources like node -# definitions or other modules. -# -# -# === Authors -# -# * Richard Pijnenburg -# -class elasticsearch::config { - - #### Configuration - - File { - owner => $elasticsearch::elasticsearch_user, - group => $elasticsearch::elasticsearch_group, - } - - Exec { - path => [ '/bin', '/usr/bin', '/usr/local/bin' ], - cwd => '/', - } - - if ( $elasticsearch::ensure == 'present' ) { - - $notify_service = $elasticsearch::restart_on_change ? { - true => Class['elasticsearch::service'], - false => undef, - } - - file { $elasticsearch::configdir: - ensure => directory, - mode => '0644', - } - - file { $elasticsearch::params::logdir: - ensure => 'directory', - group => undef, - mode => '0644', - recurse => true, - } - - file { $elasticsearch::params::homedir: - ensure => 'directory', - } - - file { "${elasticsearch::params::homedir}/bin": - ensure => 'directory', - recurse => true, - mode => '0755', - } - - file { $elasticsearch::plugindir: - ensure => 'directory', - recurse => true, - } - - file { $elasticsearch::datadir: - ensure => 'directory', - } - - file { "${elasticsearch::homedir}/lib": - ensure => 'directory', - recurse => true, - } - - if $elasticsearch::params::pid_dir { - file { $elasticsearch::params::pid_dir: - ensure => 'directory', - group => undef, - recurse => true, - } - - if ($elasticsearch::service_providers == 'systemd') { - $user = $elasticsearch::elasticsearch_user - $group = $elasticsearch::elasticsearch_group - $pid_dir = $elasticsearch::params::pid_dir - - file { '/usr/lib/tmpfiles.d/elasticsearch.conf': - ensure => 'file', - content => template("${module_name}/usr/lib/tmpfiles.d/elasticsearch.conf.erb"), - owner => 'root', - group => 'root', - } - } - } - - file { "${elasticsearch::params::homedir}/templates_import": - ensure => 'directory', - mode => '0644', - } - - file { "${elasticsearch::params::homedir}/scripts": - ensure => 'directory', - mode => '0644', - } - - # Removal of files that are provided with the package which we don't use - file { '/etc/init.d/elasticsearch': - ensure => 'absent', - } - file { '/lib/systemd/system/elasticsearch.service': - ensure => 'absent', - } - - $new_init_defaults = { 'CONF_DIR' => $elasticsearch::configdir } - augeas { "${elasticsearch::params::defaults_location}/elasticsearch": - incl => "${elasticsearch::params::defaults_location}/elasticsearch", - lens => 'Shellvars.lns', - changes => template("${module_name}/etc/sysconfig/defaults.erb"), - } - - file { '/etc/elasticsearch/elasticsearch.yml': - ensure => 'absent', - } - file { '/etc/elasticsearch/logging.yml': - ensure => 'absent', - } - - } elsif ( $elasticsearch::ensure == 'absent' ) { - # don't remove anything for now - } - -} diff --git a/puppet/modules/elasticsearch/manifests/init.pp b/puppet/modules/elasticsearch/manifests/init.pp deleted file mode 100644 index 7243861..0000000 --- a/puppet/modules/elasticsearch/manifests/init.pp +++ /dev/null @@ -1,414 +0,0 @@ -# == Class: elasticsearch -# -# This class is able to install or remove elasticsearch on a node. -# It manages the status of the related service. -# -# === Parameters -# -# [*ensure*] -# String. Controls if the managed resources shall be present or -# absent. If set to absent: -# * The managed software packages are being uninstalled. -# * Any traces of the packages will be purged as good as possible. This may -# include existing configuration files. The exact behavior is provider -# dependent. Q.v.: -# * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP] -# * {Puppet's package provider source code}[http://j.mp/wtVCaL] -# * System modifications (if any) will be reverted as good as possible -# (e.g. removal of created users, services, changed log settings, ...). -# * This is thus destructive and should be used with care. -# Defaults to present. -# -# [*autoupgrade*] -# Boolean. If set to true, any managed package gets upgraded -# on each Puppet run when the package provider is able to find a newer -# version than the present one. The exact behavior is provider dependent. -# Q.v.: -# * Puppet type reference: {package, "upgradeable"}[http://j.mp/xbxmNP] -# * {Puppet's package provider source code}[http://j.mp/wtVCaL] -# Defaults to false. -# -# [*status*] -# String to define the status of the service. Possible values: -# * enabled: Service is running and will be started at boot time. -# * disabled: Service is stopped and will not be started at boot -# time. -# * running: Service is running but will not be started at boot time. -# You can use this to start a service on the first Puppet run instead of -# the system startup. -# * unmanaged: Service will not be started at boot time and Puppet -# does not care whether the service is running or not. For example, this may -# be useful if a cluster management software is used to decide when to start -# the service plus assuring it is running on the desired node. -# Defaults to enabled. The singular form ("service") is used for the -# sake of convenience. Of course, the defined status affects all services if -# more than one is managed (see service.pp to check if this is the -# case). -# -# [*version*] -# String to set the specific version you want to install. -# Defaults to false. -# -# [*restart_on_change*] -# Boolean that determines if the application should be automatically restarted -# whenever the configuration changes. Disabling automatic restarts on config -# changes may be desired in an environment where you need to ensure restarts -# occur in a controlled/rolling manner rather than during a Puppet run. -# -# Defaults to true, which will restart the application on any config -# change. Setting to false disables the automatic restart. -# -# [*configdir*] -# Path to directory containing the elasticsearch configuration. -# Use this setting if your packages deviate from the norm (/etc/elasticsearch) -# -# [*plugindir*] -# Path to directory containing the elasticsearch plugins -# Use this setting if your packages deviate from the norm (/usr/share/elasticsearch/plugins) -# -# [*plugintool*] -# Path to directory containing the elasticsearch plugin installation script -# Use this setting if your packages deviate from the norm (/usr/share/elasticsearch/bin/plugin) -# -# [*package_url*] -# Url to the package to download. -# This can be a http,https or ftp resource for remote packages -# puppet:// resource or file:/ for local packages -# -# [*package_provider*] -# Way to install the packages, currently only packages are supported. -# -# [*package_dir*] -# Directory where the packages are downloaded to -# -# [*package_name*] -# Name of the package to install -# -# [*purge_package_dir*] -# Purge package directory on removal -# -# [*package_dl_timeout*] -# For http,https and ftp downloads you can set howlong the exec resource may take. -# Defaults to: 600 seconds -# -# [*proxy_url*] -# For http and https downloads you can set a proxy server to use -# Format: proto://[user:pass@]server[:port]/ -# Defaults to: undef (proxy disabled) -# -# [*elasticsearch_user*] -# The user Elasticsearch should run as. This also sets the file rights. -# -# [*elasticsearch_group*] -# The group Elasticsearch should run as. This also sets the file rights -# -# [*purge_configdir*] -# Purge the config directory for any unmanaged files -# -# [*service_provider*] -# Service provider to use. By Default when a single service provider is possibe that one is selected. -# -# [*init_defaults*] -# Defaults file content in hash representation -# -# [*init_defaults_file*] -# Defaults file as puppet resource -# -# [*init_template*] -# Service file as a template -# -# [*config*] -# Elasticsearch configuration hash -# -# [*datadir*] -# Allows you to set the data directory of Elasticsearch -# -# [*java_install*] -# Install java which is required for Elasticsearch. -# Defaults to: false -# -# [*java_package*] -# If you like to install a custom java package, put the name here. -# -# [*manage_repo*] -# Enable repo management by enabling our official repositories -# -# [*repo_version*] -# Our repositories are versioned per major version (0.90, 1.0) select here which version you want -# -# [*logging_config*] -# Hash representation of information you want in the logging.yml file -# -# [*logging_file*] -# Instead of a hash you can supply a puppet:// file source for the logging.yml file -# -# [*logging_template*] -# Use a custom logging template - just supply the reative path ie ${module}/elasticsearch/logging.yml.erb -# -# [*default_logging_level*] -# Default logging level for Elasticsearch. -# Defaults to: INFO -# -# [*repo_stage*] -# Use stdlib stage setup for managing the repo, instead of anchoring -# -# [*instances*] -# Define instances via a hash. This is mainly used with Hiera's auto binding -# Defaults to: undef -# -# [*instances_hiera_merge*] -# Enable Hiera's merging function for the instances -# Defaults to: false -# -# [*plugins*] -# Define plugins via a hash. This is mainly used with Hiera's auto binding -# Defaults to: undef -# -# [*plugins_hiera_merge*] -# Enable Hiera's merging function for the plugins -# Defaults to: false -# -# [*package_pin*] -# Enables package version pinning. -# This pins the package version to the set version number and avoids -# package upgrades. -# Defaults to: true -# -# The default values for the parameters are set in elasticsearch::params. Have -# a look at the corresponding params.pp manifest file if you need more -# technical information about them. -# -# === Examples -# -# * Installation, make sure service is running and will be started at boot time: -# class { 'elasticsearch': } -# -# * Removal/decommissioning: -# class { 'elasticsearch': -# ensure => 'absent', -# } -# -# * Install everything but disable service(s) afterwards -# class { 'elasticsearch': -# status => 'disabled', -# } -# -# -# === Authors -# -# * Richard Pijnenburg -# -class elasticsearch( - $ensure = $elasticsearch::params::ensure, - $status = $elasticsearch::params::status, - $restart_on_change = $elasticsearch::params::restart_on_change, - $autoupgrade = $elasticsearch::params::autoupgrade, - $version = false, - $package_provider = 'package', - $package_url = undef, - $package_dir = $elasticsearch::params::package_dir, - $package_name = $elasticsearch::params::package, - $package_pin = true, - $purge_package_dir = $elasticsearch::params::purge_package_dir, - $package_dl_timeout = $elasticsearch::params::package_dl_timeout, - $proxy_url = undef, - $elasticsearch_user = $elasticsearch::params::elasticsearch_user, - $elasticsearch_group = $elasticsearch::params::elasticsearch_group, - $configdir = $elasticsearch::params::configdir, - $purge_configdir = $elasticsearch::params::purge_configdir, - $service_provider = 'init', - $init_defaults = undef, - $init_defaults_file = undef, - $init_template = undef, - $config = undef, - $datadir = $elasticsearch::params::datadir, - $plugindir = $elasticsearch::params::plugindir, - $plugintool = $elasticsearch::params::plugintool, - $java_install = false, - $java_package = undef, - $manage_repo = false, - $repo_version = undef, - $logging_file = undef, - $logging_config = undef, - $logging_template = undef, - $default_logging_level = $elasticsearch::params::default_logging_level, - $repo_stage = false, - $instances = undef, - $instances_hiera_merge = false, - $plugins = undef, - $plugins_hiera_merge = false -) inherits elasticsearch::params { - - anchor {'elasticsearch::begin': } - - - #### Validate parameters - - # ensure - if ! ($ensure in [ 'present', 'absent' ]) { - fail("\"${ensure}\" is not a valid ensure parameter value") - } - - # autoupgrade - validate_bool($autoupgrade) - - # service status - if ! ($status in [ 'enabled', 'disabled', 'running', 'unmanaged' ]) { - fail("\"${status}\" is not a valid status parameter value") - } - - # restart on change - validate_bool($restart_on_change) - - # purge conf dir - validate_bool($purge_configdir) - - if is_array($elasticsearch::params::service_providers) { - # Verify the service provider given is in the array - if ! ($service_provider in $elasticsearch::params::service_providers) { - fail("\"${service_provider}\" is not a valid provider for \"${::operatingsystem}\"") - } - $real_service_provider = $service_provider - } else { - # There is only one option so simply set it - $real_service_provider = $elasticsearch::params::service_providers - } - - if ($package_url != undef and $version != false) { - fail('Unable to set the version number when using package_url option.') - } - - if $ensure == 'present' { - # validate config hash - if ($config != undef) { - validate_hash($config) - } - } - - # java install validation - validate_bool($java_install) - - validate_bool($manage_repo) - - if ($manage_repo == true) { - if $repo_version == undef { - fail('Please fill in a repository version at $repo_version') - } else { - validate_string($repo_version) - } - } - - if ($version != false) { - case $::osfamily { - 'RedHat', 'Linux', 'Suse': { - if ($version =~ /.+-\d/) { - $real_version = $version - } else { - $real_version = "${version}-1" - } - } - default: { - $real_version = $version - } - } - } - - #### Manage actions - - # package(s) - class { 'elasticsearch::package': } - - # configuration - class { 'elasticsearch::config': } - - # Hiera support for instances - validate_bool($instances_hiera_merge) - - if $instances_hiera_merge == true { - $x_instances = hiera_hash('elasticsearch::instances', $::elasticsearch::instances) - } else { - $x_instances = $instances - } - - if $x_instances { - validate_hash($x_instances) - create_resources('elasticsearch::instance', $x_instances) - } - - # Hiera support for plugins - validate_bool($plugins_hiera_merge) - - if $plugins_hiera_merge == true { - $x_plugins = hiera_hash('elasticsearch::plugins', $::elasticsearch::plugins) - } else { - $x_plugins = $plugins - } - - if $x_plugins { - validate_hash($x_plugins) - create_resources('elasticsearch::plugin', $x_plugins) - } - - - if $java_install == true { - # Install java - class { '::java': - package => $java_package, - distribution => 'jre', - } - - # ensure we first install java, the package and then the rest - Anchor['elasticsearch::begin'] - -> Class['::java'] - -> Class['elasticsearch::package'] - } - - if ($manage_repo == true) { - - if ($repo_stage == false) { - # use anchor for ordering - - # Set up repositories - class { 'elasticsearch::repo': } - - # Ensure that we set up the repositories before trying to install - # the packages - Anchor['elasticsearch::begin'] - -> Class['elasticsearch::repo'] - -> Class['elasticsearch::package'] - - } else { - # use staging for ordering - - if !(defined(Stage[$repo_stage])) { - stage { $repo_stage: before => Stage['main'] } - } - - class { 'elasticsearch::repo': - stage => $repo_stage, - } - } - } - - #### Manage relationships - - if $ensure == 'present' { - - # we need the software before configuring it - Anchor['elasticsearch::begin'] - -> Class['elasticsearch::package'] - -> Class['elasticsearch::config'] - -> Elasticsearch::Instance <| |> - -> Elasticsearch::Template <| |> - - } else { - - # make sure all services are getting stopped before software removal - Anchor['elasticsearch::begin'] - -> Elasticsearch::Instance <| |> - -> Class['elasticsearch::config'] - -> Class['elasticsearch::package'] - - } - -} diff --git a/puppet/modules/elasticsearch/manifests/instance.pp b/puppet/modules/elasticsearch/manifests/instance.pp deleted file mode 100644 index afc259f..0000000 --- a/puppet/modules/elasticsearch/manifests/instance.pp +++ /dev/null @@ -1,311 +0,0 @@ -# == Define: elasticsearch::instance -# -# This define allows you to create or remove an elasticsearch instance -# -# === Parameters -# -# [*ensure*] -# String. Controls if the managed resources shall be present or -# absent. If set to absent: -# * The managed software packages are being uninstalled. -# * Any traces of the packages will be purged as good as possible. This may -# include existing configuration files. The exact behavior is provider -# dependent. Q.v.: -# * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP] -# * {Puppet's package provider source code}[http://j.mp/wtVCaL] -# * System modifications (if any) will be reverted as good as possible -# (e.g. removal of created users, services, changed log settings, ...). -# * This is thus destructive and should be used with care. -# Defaults to present. -# -# [*status*] -# String to define the status of the service. Possible values: -# * enabled: Service is running and will be started at boot time. -# * disabled: Service is stopped and will not be started at boot -# time. -# * running: Service is running but will not be started at boot time. -# You can use this to start a service on the first Puppet run instead of -# the system startup. -# * unmanaged: Service will not be started at boot time and Puppet -# does not care whether the service is running or not. For example, this may -# be useful if a cluster management software is used to decide when to start -# the service plus assuring it is running on the desired node. -# Defaults to enabled. The singular form ("service") is used for the -# sake of convenience. Of course, the defined status affects all services if -# more than one is managed (see service.pp to check if this is the -# case). -# -# [*config*] -# Elasticsearch configuration hash -# -# [*configdir*] -# Path to directory containing the elasticsearch configuration. -# Use this setting if your packages deviate from the norm (/etc/elasticsearch) -# -# [*datadir*] -# Allows you to set the data directory of Elasticsearch -# -# [*logging_file*] -# Instead of a hash you can supply a puppet:// file source for the logging.yml file -# -# [*logging_config*] -# Hash representation of information you want in the logging.yml file -# -# [*logging_template*] -# Use a custom logging template - just supply the reative path ie ${module}/elasticsearch/logging.yml.erb -# -# [*logging_level*] -# Default logging level for Elasticsearch. -# Defaults to: INFO -# -# [*init_defaults*] -# Defaults file content in hash representation -# -# [*init_defaults_file*] -# Defaults file as puppet resource -# -# === Authors -# -# * Richard Pijnenburg -# -define elasticsearch::instance( - $ensure = $elasticsearch::ensure, - $status = $elasticsearch::status, - $config = undef, - $configdir = undef, - $datadir = undef, - $logging_file = undef, - $logging_config = undef, - $logging_template = undef, - $logging_level = $elasticsearch::default_logging_level, - $init_defaults = undef, - $init_defaults_file = undef -) { - - require elasticsearch::params - - File { - owner => $elasticsearch::elasticsearch_user, - group => $elasticsearch::elasticsearch_group, - } - - Exec { - path => [ '/bin', '/usr/bin', '/usr/local/bin' ], - cwd => '/', - } - - # ensure - if ! ($ensure in [ 'present', 'absent' ]) { - fail("\"${ensure}\" is not a valid ensure parameter value") - } - - $notify_service = $elasticsearch::restart_on_change ? { - true => Elasticsearch::Service[$name], - false => undef, - } - - # Instance config directory - if ($configdir == undef) { - $instance_configdir = "${elasticsearch::configdir}/${name}" - } else { - $instance_configdir = $configdir - } - - if ($ensure == 'present') { - - # Configuration hash - if ($config == undef) { - $instance_config = {} - } else { - validate_hash($config) - $instance_config = $config - } - - if(has_key($instance_config, 'node.name')) { - $instance_node_name = {} - } elsif(has_key($instance_config,'node')) { - if(has_key($instance_config['node'], 'name')) { - $instance_node_name = {} - } else { - $instance_node_name = { 'node.name' => "${::hostname}-${name}" } - } - } else { - $instance_node_name = { 'node.name' => "${::hostname}-${name}" } - } - - # String or array for data dir(s) - if ($datadir == undef) { - if (is_array($elasticsearch::datadir)) { - $instance_datadir = array_suffix($elasticsearch::datadir, "/${name}") - } else { - $instance_datadir = "${elasticsearch::datadir}/${name}" - } - } else { - $instance_datadir = $datadir - } - - # Logging file or hash - if ($logging_file != undef) { - $logging_source = $logging_file - $logging_content = undef - } elsif ($elasticsearch::logging_file != undef) { - $logging_source = $elasticsearch::logging_file - $logging_content = undef - } else { - - if(is_hash($elasticsearch::logging_config)) { - $main_logging_config = $elasticsearch::logging_config - } else { - $main_logging_config = { } - } - - if(is_hash($logging_config)) { - $instance_logging_config = $logging_config - } else { - $instance_logging_config = { } - } - $logging_hash = merge($elasticsearch::params::logging_defaults, $main_logging_config, $instance_logging_config) - if ($logging_template != undef ) { - $logging_content = template($logging_template) - } elsif ($elasticsearch::logging_template != undef) { - $logging_content = template($elasticsearch::logging_template) - } else { - $logging_content = template("${module_name}/etc/elasticsearch/logging.yml.erb") - } - $logging_source = undef - } - - if ($elasticsearch::config != undef) { - $main_config = $elasticsearch::config - } else { - $main_config = { } - } - - if(has_key($instance_config, 'path.data')) { - $instance_datadir_config = { 'path.data' => $instance_datadir } - } elsif(has_key($instance_config, 'path')) { - if(has_key($instance_config['path'], 'data')) { - $instance_datadir_config = { 'path' => { 'data' => $instance_datadir } } - } else { - $instance_datadir_config = { 'path.data' => $instance_datadir } - } - } else { - $instance_datadir_config = { 'path.data' => $instance_datadir } - } - - if(is_array($instance_datadir)) { - $dirs = join($instance_datadir, ' ') - } else { - $dirs = $instance_datadir - } - - exec { "mkdir_datadir_elasticsearch_${name}": - command => "mkdir -p ${dirs}", - creates => $instance_datadir, - require => Class['elasticsearch::package'], - before => Elasticsearch::Service[$name], - } - - file { $instance_datadir: - ensure => 'directory', - owner => $elasticsearch::elasticsearch_user, - group => undef, - mode => '0644', - require => [ Exec["mkdir_datadir_elasticsearch_${name}"], Class['elasticsearch::package'] ], - before => Elasticsearch::Service[$name], - } - - exec { "mkdir_configdir_elasticsearch_${name}": - command => "mkdir -p ${instance_configdir}", - creates => $elasticsearch::configdir, - require => Class['elasticsearch::package'], - before => Elasticsearch::Service[$name], - } - - file { $instance_configdir: - ensure => 'directory', - mode => '0644', - purge => $elasticsearch::purge_configdir, - force => $elasticsearch::purge_configdir, - require => [ Exec["mkdir_configdir_elasticsearch_${name}"], Class['elasticsearch::package'] ], - before => Elasticsearch::Service[$name], - } - - file { "${instance_configdir}/logging.yml": - ensure => file, - content => $logging_content, - source => $logging_source, - mode => '0644', - notify => $notify_service, - require => Class['elasticsearch::package'], - before => Elasticsearch::Service[$name], - } - - file { "${instance_configdir}/scripts": - ensure => 'link', - target => "${elasticsearch::params::homedir}/scripts", - } - - # build up new config - $instance_conf = merge($main_config, $instance_node_name, $instance_config, $instance_datadir_config) - - # defaults file content - # ensure user did not provide both init_defaults and init_defaults_file - if (($init_defaults != undef) and ($init_defaults_file != undef)) { - fail ('Only one of $init_defaults and $init_defaults_file should be defined') - } - - if (is_hash($elasticsearch::init_defaults)) { - $global_init_defaults = $elasticsearch::init_defaults - } else { - $global_init_defaults = { } - } - - $instance_init_defaults_main = { 'CONF_DIR' => $instance_configdir, 'CONF_FILE' => "${instance_configdir}/elasticsearch.yml", 'LOG_DIR' => "/var/log/elasticsearch/${name}", 'ES_HOME' => '/usr/share/elasticsearch' } - - if (is_hash($init_defaults)) { - $instance_init_defaults = $init_defaults - } else { - $instance_init_defaults = { } - } - $init_defaults_new = merge($global_init_defaults, $instance_init_defaults_main, $instance_init_defaults ) - - $user = $elasticsearch::elasticsearch_user - $group = $elasticsearch::elasticsearch_group - - file { "${instance_configdir}/elasticsearch.yml": - ensure => file, - content => template("${module_name}/etc/elasticsearch/elasticsearch.yml.erb"), - mode => '0644', - notify => $notify_service, - require => Class['elasticsearch::package'], - } - - $require_service = Class['elasticsearch::package'] - $before_service = undef - - } else { - - file { $instance_configdir: - ensure => 'absent', - recurse => true, - force => true, - } - - $require_service = undef - $before_service = File[$instance_configdir] - - $init_defaults_new = {} - } - - elasticsearch::service { $name: - ensure => $ensure, - status => $status, - init_defaults => $init_defaults_new, - init_defaults_file => $init_defaults_file, - init_template => "${module_name}/etc/init.d/${elasticsearch::params::init_template}", - require => $require_service, - before => $before_service, - } - -} diff --git a/puppet/modules/elasticsearch/manifests/package.pp b/puppet/modules/elasticsearch/manifests/package.pp deleted file mode 100644 index 17ebac7..0000000 --- a/puppet/modules/elasticsearch/manifests/package.pp +++ /dev/null @@ -1,190 +0,0 @@ -# == Class: elasticsearch::package -# -# This class exists to coordinate all software package management related -# actions, functionality and logical units in a central place. -# -# -# === Parameters -# -# This class does not provide any parameters. -# -# -# === Examples -# -# This class may be imported by other classes to use its functionality: -# class { 'elasticsearch::package': } -# -# It is not intended to be used directly by external resources like node -# definitions or other modules. -# -# -# === Authors -# -# * Richard Pijnenburg -# -class elasticsearch::package { - - Exec { - path => [ '/bin', '/usr/bin', '/usr/local/bin' ], - cwd => '/', - tries => 3, - try_sleep => 10, - } - - #### Package management - - # set params: in operation - if $elasticsearch::ensure == 'present' { - - # Check if we want to install a specific version or not - if $elasticsearch::version == false { - - $package_ensure = $elasticsearch::autoupgrade ? { - true => 'latest', - false => 'present', - } - - } else { - - # install specific version - $package_ensure = $elasticsearch::real_version - - } - - # action - if ($elasticsearch::package_url != undef) { - - case $elasticsearch::package_provider { - 'package': { $before = Package[$elasticsearch::package_name] } - default: { fail("software provider \"${elasticsearch::package_provider}\".") } - } - - $package_dir = $elasticsearch::package_dir - - # Create directory to place the package file - exec { 'create_package_dir_elasticsearch': - cwd => '/', - path => ['/usr/bin', '/bin'], - command => "mkdir -p ${elasticsearch::package_dir}", - creates => $elasticsearch::package_dir, - } - - file { $package_dir: - ensure => 'directory', - purge => $elasticsearch::purge_package_dir, - force => $elasticsearch::purge_package_dir, - backup => false, - require => Exec['create_package_dir_elasticsearch'], - } - - $filenameArray = split($elasticsearch::package_url, '/') - $basefilename = $filenameArray[-1] - - $sourceArray = split($elasticsearch::package_url, ':') - $protocol_type = $sourceArray[0] - - $extArray = split($basefilename, '\.') - $ext = $extArray[-1] - - $pkg_source = "${package_dir}/${basefilename}" - - case $protocol_type { - - 'puppet': { - - file { $pkg_source: - ensure => file, - source => $elasticsearch::package_url, - require => File[$package_dir], - backup => false, - before => $before, - } - - } - 'ftp', 'https', 'http': { - - if $elasticsearch::proxy_url != undef { - $exec_environment = [ - 'use_proxy=yes', - "http_proxy=${elasticsearch::proxy_url}", - "https_proxy=${elasticsearch::proxy_url}", - ] - } - - exec { 'download_package_elasticsearch': - command => "${elasticsearch::params::download_tool} ${pkg_source} ${elasticsearch::package_url} 2> /dev/null", - creates => $pkg_source, - environment => $exec_environment, - timeout => $elasticsearch::package_dl_timeout, - require => File[$package_dir], - before => $before, - } - - } - 'file': { - - $source_path = $sourceArray[1] - file { $pkg_source: - ensure => file, - source => $source_path, - require => File[$package_dir], - backup => false, - before => $before, - } - - } - default: { - fail("Protocol must be puppet, file, http, https, or ftp. You have given \"${protocol_type}\"") - } - } - - if ($elasticsearch::package_provider == 'package') { - - case $ext { - 'deb': { $pkg_provider = 'dpkg' } - 'rpm': { $pkg_provider = 'rpm' } - default: { fail("Unknown file extention \"${ext}\".") } - } - - } - - } else { - $pkg_source = undef - $pkg_provider = undef - } - - # Package removal - } else { - - $pkg_source = undef - if ($::operatingsystem == 'OpenSuSE') { - $pkg_provider = 'rpm' - } else { - $pkg_provider = undef - } - $package_ensure = 'purged' - - $package_dir = $elasticsearch::package_dir - - file { $package_dir: - ensure => 'absent', - purge => true, - force => true, - backup => false, - } - - } - - if ($elasticsearch::package_provider == 'package') { - - package { $elasticsearch::package_name: - ensure => $package_ensure, - source => $pkg_source, - provider => $pkg_provider, - } - - } else { - fail("\"${elasticsearch::package_provider}\" is not supported") - } - -} diff --git a/puppet/modules/elasticsearch/manifests/params.pp b/puppet/modules/elasticsearch/manifests/params.pp deleted file mode 100644 index 0e2d76b..0000000 --- a/puppet/modules/elasticsearch/manifests/params.pp +++ /dev/null @@ -1,220 +0,0 @@ -# == Class: elasticsearch::params -# -# This class exists to -# 1. Declutter the default value assignment for class parameters. -# 2. Manage internally used module variables in a central place. -# -# Therefore, many operating system dependent differences (names, paths, ...) -# are addressed in here. -# -# -# === Parameters -# -# This class does not provide any parameters. -# -# -# === Examples -# -# This class is not intended to be used directly. -# -# -# === Links -# -# * {Puppet Docs: Using Parameterized Classes}[http://j.mp/nVpyWY] -# -# -# === Authors -# -# * Richard Pijnenburg -# -class elasticsearch::params { - - #### Default values for the parameters of the main module class, init.pp - - # ensure - $ensure = 'present' - - # autoupgrade - $autoupgrade = false - - # service status - $status = 'enabled' - - # restart on configuration change? - $restart_on_change = true - - # Purge configuration directory - $purge_configdir = false - - $purge_package_dir = false - - # package download timeout - $package_dl_timeout = 600 # 300 seconds is default of puppet - - $default_logging_level = 'INFO' - - $logging_defaults = { - 'action' => 'DEBUG', - 'com.amazonaws' => 'WARN', - 'index.search.slowlog' => 'TRACE, index_search_slow_log_file', - 'index.indexing.slowlog' => 'TRACE, index_indexing_slow_log_file', - } - - #### Internal module values - - # User and Group for the files and user to run the service as. - case $::kernel { - 'Linux': { - $elasticsearch_user = 'elasticsearch' - $elasticsearch_group = 'elasticsearch' - } - 'Darwin': { - $elasticsearch_user = 'elasticsearch' - $elasticsearch_group = 'elasticsearch' - } - default: { - fail("\"${module_name}\" provides no user/group default value - for \"${::kernel}\"") - } - } - - # Download tool - - case $::kernel { - 'Linux': { - $download_tool = 'wget --no-check-certificate -O' - } - 'Darwin': { - $download_tool = 'curl --insecure -o' - } - default: { - fail("\"${module_name}\" provides no download tool default value - for \"${::kernel}\"") - } - } - - # Different path definitions - case $::kernel { - 'Linux': { - $configdir = '/etc/elasticsearch' - $logdir = '/var/log/elasticsearch' - $package_dir = '/opt/elasticsearch/swdl' - $installpath = '/opt/elasticsearch' - $homedir = '/usr/share/elasticsearch' - $plugindir = "${homedir}/plugins" - $plugintool = "${homedir}/bin/plugin" - $datadir = '/usr/share/elasticsearch/data' - } - default: { - fail("\"${module_name}\" provides no config directory default value - for \"${::kernel}\"") - } - } - - # packages - case $::operatingsystem { - 'RedHat', 'CentOS', 'Fedora', 'Scientific', 'Amazon', 'OracleLinux', 'SLC': { - # main application - $package = [ 'elasticsearch' ] - } - 'Debian', 'Ubuntu': { - # main application - $package = [ 'elasticsearch' ] - } - 'OpenSuSE': { - $package = [ 'elasticsearch' ] - } - default: { - fail("\"${module_name}\" provides no package default value - for \"${::operatingsystem}\"") - } - } - - # service parameters - case $::operatingsystem { - 'RedHat', 'CentOS', 'Fedora', 'Scientific', 'OracleLinux', 'SLC': { - $service_name = 'elasticsearch' - $service_hasrestart = true - $service_hasstatus = true - $service_pattern = $service_name - $defaults_location = '/etc/sysconfig' - $pid_dir = '/var/run/elasticsearch' - - if versioncmp($::operatingsystemmajrelease, '7') >= 0 { - $init_template = 'elasticsearch.systemd.erb' - $service_providers = 'systemd' - } else { - $init_template = 'elasticsearch.RedHat.erb' - $service_providers = 'init' - } - - } - 'Amazon': { - $service_name = 'elasticsearch' - $service_hasrestart = true - $service_hasstatus = true - $service_pattern = $service_name - $defaults_location = '/etc/sysconfig' - $pid_dir = '/var/run/elasticsearch' - $init_template = 'elasticsearch.RedHat.erb' - $service_providers = 'init' - } - 'Debian': { - $service_name = 'elasticsearch' - $service_hasrestart = true - $service_hasstatus = true - $service_pattern = $service_name - $defaults_location = '/etc/default' - if versioncmp($::operatingsystemmajrelease, '8') >= 0 { - $init_template = 'elasticsearch.systemd.erb' - $service_providers = 'systemd' - $pid_dir = '/var/run/elasticsearch' - } else { - $init_template = 'elasticsearch.Debian.erb' - $service_providers = [ 'init' ] - $pid_dir = false - } - } - 'Ubuntu': { - $service_name = 'elasticsearch' - $service_hasrestart = true - $service_hasstatus = true - $service_pattern = $service_name - $defaults_location = '/etc/default' - - if versioncmp($::operatingsystemmajrelease, '15') >= 0 { - $init_template = 'elasticsearch.systemd.erb' - $service_providers = 'systemd' - $pid_dir = '/var/run/elasticsearch' - } else { - $init_template = 'elasticsearch.Debian.erb' - $service_providers = [ 'init' ] - $pid_dir = false - } - } - 'Darwin': { - $service_name = 'FIXME/TODO' - $service_hasrestart = true - $service_hasstatus = true - $service_pattern = $service_name - $service_providers = 'launchd' - $defaults_location = false - $pid_dir = false - } - 'OpenSuSE': { - $service_name = 'elasticsearch' - $service_hasrestart = true - $service_hasstatus = true - $service_pattern = $service_name - $service_providers = 'systemd' - $defaults_location = '/etc/sysconfig' - $init_template = 'elasticsearch.systemd.erb' - $pid_dir = '/var/run/elasticsearch' - } - default: { - fail("\"${module_name}\" provides no service parameters - for \"${::operatingsystem}\"") - } - } - -} diff --git a/puppet/modules/elasticsearch/manifests/plugin.pp b/puppet/modules/elasticsearch/manifests/plugin.pp deleted file mode 100644 index 6e62ee8..0000000 --- a/puppet/modules/elasticsearch/manifests/plugin.pp +++ /dev/null @@ -1,180 +0,0 @@ -# == Define: elasticsearch::plugin -# -# This define allows you to install arbitrary Elasticsearch plugins -# either by using the default repositories or by specifying an URL -# -# All default values are defined in the elasticsearch::params class. -# -# -# === Parameters -# -# [*module_dir*] -# Directory name where the module will be installed -# Value type is string -# Default value: None -# This variable is deprecated -# -# [*ensure*] -# Whether the plugin will be installed or removed. -# Set to 'absent' to ensure a plugin is not installed -# Value type is string -# Default value: present -# This variable is optional -# -# [*url*] -# Specify an URL where to download the plugin from. -# Value type is string -# Default value: None -# This variable is optional -# -# [*source*] -# Specify the source of the plugin. -# This will copy over the plugin to the node and use it for installation. -# Useful for offline installation -# Value type is string -# This variable is optional -# -# [*proxy_host*] -# Proxy host to use when installing the plugin -# Value type is string -# Default value: None -# This variable is optional -# -# [*proxy_port*] -# Proxy port to use when installing the plugin -# Value type is number -# Default value: None -# This variable is optional -# -# [*instances*] -# Specify all the instances related -# value type is string or array -# -# === Examples -# -# # From official repository -# elasticsearch::plugin{'mobz/elasticsearch-head': module_dir => 'head'} -# -# # From custom url -# elasticsearch::plugin{ 'elasticsearch-jetty': -# module_dir => 'elasticsearch-jetty', -# url => 'https://oss-es-plugins.s3.amazonaws.com/elasticsearch-jetty/elasticsearch-jetty-0.90.0.zip', -# } -# -# === Authors -# -# * Matteo Sessa -# * Dennis Konert -# * Richard Pijnenburg -# -define elasticsearch::plugin( - $instances, - $module_dir = undef, - $ensure = 'present', - $url = undef, - $source = undef, - $proxy_host = undef, - $proxy_port = undef, -) { - - include elasticsearch - - Exec { - path => [ '/bin', '/usr/bin', '/usr/local/bin' ], - cwd => '/', - user => $elasticsearch::elasticsearch_user, - tries => 6, - try_sleep => 10, - timeout => 600, - } - - $notify_service = $elasticsearch::restart_on_change ? { - false => undef, - default => Elasticsearch::Service[$instances], - } - - if ($module_dir != undef) { - warning("module_dir settings is deprecated for plugin ${name}. The directory is now auto detected.") - $plugin_dir = $module_dir - } else { - $plugin_dir = plugin_dir($name) - } - - # set proxy by override or parse and use proxy_url from - # elasticsearch::proxy_url or use no proxy at all - - if ($proxy_host != undef and $proxy_port != undef) { - $proxy = " -DproxyPort=${proxy_port} -DproxyHost=${proxy_host}" - } - elsif ($elasticsearch::proxy_url != undef) { - $proxy_host_from_url = regsubst($elasticsearch::proxy_url, '(http|https)://([^:]+)(|:\d+).+', '\2') - $proxy_port_from_url = regsubst($elasticsearch::proxy_url, '(?:http|https)://[^:/]+(?::([0-9]+))?(?:/.*)?', '\1') - - # validate parsed values before using them - if (is_string($proxy_host_from_url) and is_integer($proxy_port_from_url)) { - $proxy = " -DproxyPort=${proxy_port_from_url} -DproxyHost=${proxy_host_from_url}" - } - } - else { - $proxy = '' # lint:ignore:empty_string_assignment - } - - if ($source != undef) { - - $filenameArray = split($source, '/') - $basefilename = $filenameArray[-1] - - file { "/tmp/${basefilename}": - ensure => 'file', - source => $source, - } - - $real_url = "file:///tmp/${basefilename}" - } elsif ($url != undef) { - validate_string($url) - $real_url = $url - } else { - $real_url = undef - } - - if ($real_url == undef) { - $install_cmd = "${elasticsearch::plugintool}${proxy} install ${name}" - $exec_rets = [0,] - } else { - $install_cmd = "${elasticsearch::plugintool}${proxy} install ${name} --url ${real_url}" - $exec_rets = [0,1] - } - - case $ensure { - 'installed', 'present': { - $name_file_path = "${elasticsearch::plugindir}/${plugin_dir}/.name" - exec {"purge_plugin_${plugin_dir}_old": - command => "${elasticsearch::plugintool} --remove ${plugin_dir}", - onlyif => "test -e ${elasticsearch::plugindir}/${plugin_dir} && test \"$(cat ${name_file_path})\" != '${name}'", - before => Exec["install_plugin_${name}"], - } - exec {"install_plugin_${name}": - command => $install_cmd, - creates => "${elasticsearch::plugindir}/${plugin_dir}", - returns => $exec_rets, - notify => $notify_service, - require => File[$elasticsearch::plugindir], - } - file {$name_file_path: - ensure => file, - content => "${name}", # lint:ignore:only_variable_string - require => Exec["install_plugin_${name}"], - } - } - 'absent': { - exec {"remove_plugin_${name}": - command => "${elasticsearch::plugintool} --remove ${plugin_dir}", - onlyif => "test -d ${elasticsearch::plugindir}/${plugin_dir}", - notify => $notify_service, - } - } - default: { - fail("${ensure} is not a valid ensure command.") - } - } -} diff --git a/puppet/modules/elasticsearch/manifests/python.pp b/puppet/modules/elasticsearch/manifests/python.pp deleted file mode 100644 index fee783a..0000000 --- a/puppet/modules/elasticsearch/manifests/python.pp +++ /dev/null @@ -1,70 +0,0 @@ -# == Define: elasticsearch::python -# -# there are many python bindings for elasticsearch. This provides all -# the ones we know about http://www.elasticsearch.org/guide/clients/ -# -# === Parameters -# -# [*ensure*] -# String. Controls if the managed resources shall be present or -# absent. If set to absent: -# * The managed software packages are being uninstalled. -# * Any traces of the packages will be purged as good as possible. This may -# include existing configuration files. The exact behavior is provider -# dependent. Q.v.: -# * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP] -# * {Puppet's package provider source code}[http://j.mp/wtVCaL] -# * System modifications (if any) will be reverted as good as possible -# (e.g. removal of created users, services, changed log settings, ...). -# * This is thus destructive and should be used with care. -# Defaults to present. -# -# === Examples -# -# elasticsearch::python { 'pyes':; } -# -# === Authors -# -# * Richard Pijnenburg -# -define elasticsearch::python ( - $ensure = 'present' -) { - - if ! ($ensure in [ 'present', 'absent' ]) { - fail("\"${ensure}\" is not a valid ensure parameter value") - } - - # make sure the package name is valid and setup the provider as - # necessary - case $name { - 'pyes': { - $provider = 'pip' - } - 'rawes': { - $provider = 'pip' - } - 'pyelasticsearch': { - $provider = 'pip' - } - 'ESClient': { - $provider = 'pip' - } - 'elasticutils': { - $provider = 'pip' - } - 'elasticsearch': { - $provider = 'pip' - } - default: { - fail("unknown python binding package '${name}'") - } - } - - package { "python_${name}": - ensure => $ensure, - name => $name, - provider => $provider, - } - -} diff --git a/puppet/modules/elasticsearch/manifests/repo.pp b/puppet/modules/elasticsearch/manifests/repo.pp deleted file mode 100644 index 19a8f59..0000000 --- a/puppet/modules/elasticsearch/manifests/repo.pp +++ /dev/null @@ -1,106 +0,0 @@ -# == Class: elasticsearch::repo -# -# This class exists to install and manage yum and apt repositories -# that contain elasticsearch official elasticsearch packages -# -# -# === Parameters -# -# This class does not provide any parameters. -# -# -# === Examples -# -# This class may be imported by other classes to use its functionality: -# class { 'elasticsearch::repo': } -# -# It is not intended to be used directly by external resources like node -# definitions or other modules. -# -# -# === Authors -# -# * Phil Fenstermacher -# * Richard Pijnenburg -# -class elasticsearch::repo { - - Exec { - path => [ '/bin', '/usr/bin', '/usr/local/bin' ], - cwd => '/', - } - - case $::osfamily { - 'Debian': { - if !defined(Class['apt']) { - class { 'apt': } - } - - apt::source { 'elasticsearch': - location => "http://packages.elastic.co/elasticsearch/${elasticsearch::repo_version}/debian", - release => 'stable', - repos => 'main', - key => 'D88E42B4', - key_source => 'http://packages.elastic.co/GPG-KEY-elasticsearch', - include_src => false, - } - } - 'RedHat', 'Linux': { - yumrepo { 'elasticsearch': - descr => 'elasticsearch repo', - baseurl => "http://packages.elastic.co/elasticsearch/${elasticsearch::repo_version}/centos", - gpgcheck => 1, - gpgkey => 'http://packages.elastic.co/GPG-KEY-elasticsearch', - enabled => 1, - } - } - 'Suse': { - exec { 'elasticsearch_suse_import_gpg': - command => 'rpmkeys --import http://packages.elastic.co/GPG-KEY-elasticsearch', - unless => 'test $(rpm -qa gpg-pubkey | grep -i "D88E42B4" | wc -l) -eq 1 ', - notify => [ Zypprepo['elasticsearch'] ], - } - - zypprepo { 'elasticsearch': - baseurl => "http://packages.elastic.co/elasticsearch/${elasticsearch::repo_version}/centos", - enabled => 1, - autorefresh => 1, - name => 'elasticsearch', - gpgcheck => 1, - gpgkey => 'http://packages.elastic.co/GPG-KEY-elasticsearch', - type => 'yum', - } - } - default: { - fail("\"${module_name}\" provides no repository information for OSfamily \"${::osfamily}\"") - } - } - - # Package pinning - if ($elasticsearch::package_pin == true and $elasticsearch::version != false) { - case $::osfamily { - 'Debian': { - if !defined(Class['apt']) { - class { 'apt': } - } - - apt::pin { $elasticsearch::package_name: - ensure => 'present', - packages => $elasticsearch::package_name, - version => $elasticsearch::real_version, - priority => 1000, - } - } - 'RedHat', 'Linux': { - - yum::versionlock { "0:elasticsearch-${elasticsearch::real_version}.noarch": - ensure => 'present', - } - } - default: { - warning("Unable to pin package for OSfamily \"${::osfamily}\".") - } - } - } - -} diff --git a/puppet/modules/elasticsearch/manifests/ruby.pp b/puppet/modules/elasticsearch/manifests/ruby.pp deleted file mode 100644 index aba0bd7..0000000 --- a/puppet/modules/elasticsearch/manifests/ruby.pp +++ /dev/null @@ -1,67 +0,0 @@ -# == Define: elasticsearch::ruby -# -# there are many ruby bindings for elasticsearch. This provides all -# the ones we know about http://www.elasticsearch.org/guide/clients/ -# -# === Parameters -# -# [*ensure*] -# String. Controls if the managed resources shall be present or -# absent. If set to absent: -# * The managed software packages are being uninstalled. -# * Any traces of the packages will be purged as good as possible. This may -# include existing configuration files. The exact behavior is provider -# dependent. Q.v.: -# * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP] -# * {Puppet's package provider source code}[http://j.mp/wtVCaL] -# * System modifications (if any) will be reverted as good as possible -# (e.g. removal of created users, services, changed log settings, ...). -# * This is thus destructive and should be used with care. -# Defaults to present. -# -# === Examples -# -# elasticsearch::ruby { 'elasticsearch':; } -# -# === Authors -# -# * Richard Pijnenburg -# -define elasticsearch::ruby ( - $ensure = 'present' -) { - - if ! ($ensure in [ 'present', 'absent' ]) { - fail("\"${ensure}\" is not a valid ensure parameter value") - } - - # make sure the package name is valid and setup the provider as - # necessary - case $name { - 'tire': { - $provider = 'gem' - } - 'stretcher': { - $provider = 'gem' - } - 'elastic_searchable': { - $provider = 'gem' - } - 'elasticsearch': { - $provider = 'gem' - } - 'flex': { - $provider = 'gem' - } - default: { - fail("unknown ruby client package '${name}'") - } - } - - package { "ruby_${name}": - ensure => $ensure, - name => $name, - provider => $provider, - } - -} diff --git a/puppet/modules/elasticsearch/manifests/script.pp b/puppet/modules/elasticsearch/manifests/script.pp deleted file mode 100644 index c4c0158..0000000 --- a/puppet/modules/elasticsearch/manifests/script.pp +++ /dev/null @@ -1,55 +0,0 @@ -# == Define: elasticsearch::script -# -# This define allows you to insert, update or delete scripts that are used within Elasticsearch -# -# === Parameters -# -# [*ensure*] -# String. Controls if the managed resources shall be present or -# absent. If set to absent: -# * The managed software packages are being uninstalled. -# * Any traces of the packages will be purged as good as possible. This may -# include existing configuration files. The exact behavior is provider -# dependent. Q.v.: -# * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP] -# * {Puppet's package provider source code}[http://j.mp/wtVCaL] -# * System modifications (if any) will be reverted as good as possible -# (e.g. removal of created users, services, changed log settings, ...). -# * This is thus destructive and should be used with care. -# Defaults to present. -# -# [*source*] -# Puppet source of the script -# Value type is string -# Default value: undef -# This variable is mandatory -# -# === Authors -# -# * Richard Pijnenburg -# -define elasticsearch::script( - $source, - $ensure = 'present', -) { - - require elasticsearch - - # ensure - if ! ($ensure in [ 'present', 'absent' ]) { - fail("\"${ensure}\" is not a valid ensure parameter value") - } - - validate_re($source, '^puppet://') - - $filenameArray = split($source, '/') - $basefilename = $filenameArray[-1] - - file { "${elasticsearch::params::homedir}/scripts/${basefilename}": - ensure => $ensure, - source => $source, - owner => $elasticsearch::elasticsearch_user, - group => $elasticsearch::elasticsearch_group, - mode => '0644', - } -} diff --git a/puppet/modules/elasticsearch/manifests/service.pp b/puppet/modules/elasticsearch/manifests/service.pp deleted file mode 100644 index 7cd0dfa..0000000 --- a/puppet/modules/elasticsearch/manifests/service.pp +++ /dev/null @@ -1,91 +0,0 @@ -# == Class: elasticsearch::service -# -# This class exists to coordinate all service management related actions, -# functionality and logical units in a central place. -# -# Note: "service" is the Puppet term and type for background processes -# in general and is used in a platform-independent way. E.g. "service" means -# "daemon" in relation to Unix-like systems. -# -# -# === Parameters -# -# [*ensure*] -# String. Controls if the managed resources shall be present or -# absent. If set to absent: -# * The managed software packages are being uninstalled. -# * Any traces of the packages will be purged as good as possible. This may -# include existing configuration files. The exact behavior is provider -# dependent. Q.v.: -# * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP] -# * {Puppet's package provider source code}[http://j.mp/wtVCaL] -# * System modifications (if any) will be reverted as good as possible -# (e.g. removal of created users, services, changed log settings, ...). -# * This is thus destructive and should be used with care. -# Defaults to present. -# -# [*status*] -# String to define the status of the service. Possible values: -# * enabled: Service is running and will be started at boot time. -# * disabled: Service is stopped and will not be started at boot -# time. -# * running: Service is running but will not be started at boot time. -# You can use this to start a service on the first Puppet run instead of -# the system startup. -# * unmanaged: Service will not be started at boot time and Puppet -# does not care whether the service is running or not. For example, this may -# be useful if a cluster management software is used to decide when to start -# the service plus assuring it is running on the desired node. -# Defaults to enabled. The singular form ("service") is used for the -# sake of convenience. Of course, the defined status affects all services if -# more than one is managed (see service.pp to check if this is the -# case). -# -# [*init_defaults*] -# Defaults file content in hash representation -# -# [*init_defaults_file*] -# Defaults file as puppet resource -# -# [*init_template*] -# Service file as a template -# -# === Authors -# -# * Richard Pijnenburg -# -define elasticsearch::service( - $ensure = $elasticsearch::ensure, - $status = $elasticsearch::status, - $init_defaults_file = undef, - $init_defaults = undef, - $init_template = undef, -) { - - case $elasticsearch::real_service_provider { - - 'init': { - elasticsearch::service::init { $name: - ensure => $ensure, - status => $status, - init_defaults_file => $init_defaults_file, - init_defaults => $init_defaults, - init_template => $init_template, - } - } - 'systemd': { - elasticsearch::service::systemd { $name: - ensure => $ensure, - status => $status, - init_defaults_file => $init_defaults_file, - init_defaults => $init_defaults, - init_template => $init_template, - } - } - default: { - fail("Unknown service provider ${elasticsearch::real_service_provider}") - } - - } - -} diff --git a/puppet/modules/elasticsearch/manifests/service/init.pp b/puppet/modules/elasticsearch/manifests/service/init.pp deleted file mode 100644 index 0d37e1d..0000000 --- a/puppet/modules/elasticsearch/manifests/service/init.pp +++ /dev/null @@ -1,195 +0,0 @@ -# == Define: elasticsearch::service::init -# -# This class exists to coordinate all service management related actions, -# functionality and logical units in a central place. -# -# Note: "service" is the Puppet term and type for background processes -# in general and is used in a platform-independent way. E.g. "service" means -# "daemon" in relation to Unix-like systems. -# -# -# === Parameters -# -# [*ensure*] -# String. Controls if the managed resources shall be present or -# absent. If set to absent: -# * The managed software packages are being uninstalled. -# * Any traces of the packages will be purged as good as possible. This may -# include existing configuration files. The exact behavior is provider -# dependent. Q.v.: -# * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP] -# * {Puppet's package provider source code}[http://j.mp/wtVCaL] -# * System modifications (if any) will be reverted as good as possible -# (e.g. removal of created users, services, changed log settings, ...). -# * This is thus destructive and should be used with care. -# Defaults to present. -# -# [*status*] -# String to define the status of the service. Possible values: -# * enabled: Service is running and will be started at boot time. -# * disabled: Service is stopped and will not be started at boot -# time. -# * running: Service is running but will not be started at boot time. -# You can use this to start a service on the first Puppet run instead of -# the system startup. -# * unmanaged: Service will not be started at boot time and Puppet -# does not care whether the service is running or not. For example, this may -# be useful if a cluster management software is used to decide when to start -# the service plus assuring it is running on the desired node. -# Defaults to enabled. The singular form ("service") is used for the -# sake of convenience. Of course, the defined status affects all services if -# more than one is managed (see service.pp to check if this is the -# case). -# -# [*init_defaults*] -# Defaults file content in hash representation -# -# [*init_defaults_file*] -# Defaults file as puppet resource -# -# [*init_template*] -# Service file as a template -# -# === Authors -# -# * Richard Pijnenburg -# -define elasticsearch::service::init( - $ensure = $elasticsearch::ensure, - $status = $elasticsearch::status, - $init_defaults_file = undef, - $init_defaults = undef, - $init_template = undef, -) { - - #### Service management - - # set params: in operation - if $ensure == 'present' { - - case $status { - # make sure service is currently running, start it on boot - 'enabled': { - $service_ensure = 'running' - $service_enable = true - } - # make sure service is currently stopped, do not start it on boot - 'disabled': { - $service_ensure = 'stopped' - $service_enable = false - } - # make sure service is currently running, do not start it on boot - 'running': { - $service_ensure = 'running' - $service_enable = false - } - # do not start service on boot, do not care whether currently running - # or not - 'unmanaged': { - $service_ensure = undef - $service_enable = false - } - # unknown status - # note: don't forget to update the parameter check in init.pp if you - # add a new or change an existing status. - default: { - fail("\"${status}\" is an unknown service status value") - } - } - - # set params: removal - } else { - - # make sure the service is stopped and disabled (the removal itself will be - # done by package.pp) - $service_ensure = 'stopped' - $service_enable = false - - } - - $notify_service = $elasticsearch::restart_on_change ? { - true => Service["elasticsearch-instance-${name}"], - false => undef, - } - - - if ( $status != 'unmanaged' and $ensure == 'present' ) { - - # defaults file content. Either from a hash or file - if ($init_defaults_file != undef) { - file { "${elasticsearch::params::defaults_location}/elasticsearch-${name}": - ensure => $ensure, - source => $init_defaults_file, - owner => 'root', - group => 'root', - mode => '0644', - before => Service["elasticsearch-instance-${name}"], - notify => $notify_service, - } - - } elsif ($init_defaults != undef and is_hash($init_defaults) ) { - - if(has_key($init_defaults, 'ES_USER')) { - if($init_defaults['ES_USER'] != $elasticsearch::elasticsearch_user) { - fail('Found ES_USER setting for init_defaults but is not same as elasticsearch_user setting. Please use elasticsearch_user setting.') - } - } - - $init_defaults_pre_hash = { 'ES_USER' => $elasticsearch::elasticsearch_user, 'ES_GROUP' => $elasticsearch::elasticsearch_group, 'MAX_OPEN_FILES' => '65535' } - $new_init_defaults = merge($init_defaults_pre_hash, $init_defaults) - - augeas { "defaults_${name}": - incl => "${elasticsearch::params::defaults_location}/elasticsearch-${name}", - lens => 'Shellvars.lns', - changes => template("${module_name}/etc/sysconfig/defaults.erb"), - before => Service["elasticsearch-instance-${name}"], - notify => $notify_service, - } - - } - - # init file from template - if ($init_template != undef) { - - file { "/etc/init.d/elasticsearch-${name}": - ensure => $ensure, - content => template($init_template), - owner => 'root', - group => 'root', - mode => '0755', - before => Service["elasticsearch-instance-${name}"], - notify => $notify_service, - } - - } - - } elsif ($status != 'unmanaged') { - - file { "/etc/init.d/elasticsearch-${name}": - ensure => 'absent', - subscribe => Service["elasticsearch-instance-${name}"], - } - - file { "${elasticsearch::params::defaults_location}/elasticsearch-${name}": - ensure => 'absent', - subscribe => Service["elasticsearch-${$name}"], - } - - } - - - if ( $status != 'unmanaged') { - - # action - service { "elasticsearch-instance-${name}": - ensure => $service_ensure, - enable => $service_enable, - name => "elasticsearch-${name}", - hasstatus => $elasticsearch::params::service_hasstatus, - hasrestart => $elasticsearch::params::service_hasrestart, - pattern => $elasticsearch::params::service_pattern, - } - - } - -} diff --git a/puppet/modules/elasticsearch/manifests/service/systemd.pp b/puppet/modules/elasticsearch/manifests/service/systemd.pp deleted file mode 100644 index fb7912f..0000000 --- a/puppet/modules/elasticsearch/manifests/service/systemd.pp +++ /dev/null @@ -1,216 +0,0 @@ -# == Define: elasticsearch::service::systemd -# -# This define exists to coordinate all service management related actions, -# functionality and logical units in a central place. -# -# Note: "service" is the Puppet term and type for background processes -# in general and is used in a platform-independent way. E.g. "service" means -# "daemon" in relation to Unix-like systems. -# -# -# === Parameters -# -# [*ensure*] -# String. Controls if the managed resources shall be present or -# absent. If set to absent: -# * The managed software packages are being uninstalled. -# * Any traces of the packages will be purged as good as possible. This may -# include existing configuration files. The exact behavior is provider -# dependent. Q.v.: -# * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP] -# * {Puppet's package provider source code}[http://j.mp/wtVCaL] -# * System modifications (if any) will be reverted as good as possible -# (e.g. removal of created users, services, changed log settings, ...). -# * This is thus destructive and should be used with care. -# Defaults to present. -# -# [*status*] -# String to define the status of the service. Possible values: -# * enabled: Service is running and will be started at boot time. -# * disabled: Service is stopped and will not be started at boot -# time. -# * running: Service is running but will not be started at boot time. -# You can use this to start a service on the first Puppet run instead of -# the system startup. -# * unmanaged: Service will not be started at boot time and Puppet -# does not care whether the service is running or not. For example, this may -# be useful if a cluster management software is used to decide when to start -# the service plus assuring it is running on the desired node. -# Defaults to enabled. The singular form ("service") is used for the -# sake of convenience. Of course, the defined status affects all services if -# more than one is managed (see service.pp to check if this is the -# case). -# -# [*init_defaults*] -# Defaults file content in hash representation -# -# [*init_defaults_file*] -# Defaults file as puppet resource -# -# [*init_template*] -# Service file as a template -# -# === Authors -# -# * Richard Pijnenburg -# -define elasticsearch::service::systemd( - $ensure = $elasticsearch::ensure, - $status = $elasticsearch::status, - $init_defaults_file = undef, - $init_defaults = undef, - $init_template = undef, -) { - - #### Service management - - # set params: in operation - if $ensure == 'present' { - - case $status { - # make sure service is currently running, start it on boot - 'enabled': { - $service_ensure = 'running' - $service_enable = true - } - # make sure service is currently stopped, do not start it on boot - 'disabled': { - $service_ensure = 'stopped' - $service_enable = false - } - # make sure service is currently running, do not start it on boot - 'running': { - $service_ensure = 'running' - $service_enable = false - } - # do not start service on boot, do not care whether currently running - # or not - 'unmanaged': { - $service_ensure = undef - $service_enable = false - } - # unknown status - # note: don't forget to update the parameter check in init.pp if you - # add a new or change an existing status. - default: { - fail("\"${status}\" is an unknown service status value") - } - } - } else { - # make sure the service is stopped and disabled (the removal itself will be - # done by package.pp) - $service_ensure = 'stopped' - $service_enable = false - } - - $notify_service = $elasticsearch::restart_on_change ? { - true => [ Exec["systemd_reload_${name}"], Service["elasticsearch-instance-${name}"] ], - false => Exec["systemd_reload_${name}"] - } - - if ( $status != 'unmanaged' and $ensure == 'present' ) { - - # defaults file content. Either from a hash or file - if ($init_defaults_file != undef) { - file { "${elasticsearch::params::defaults_location}/elasticsearch-${name}": - ensure => $ensure, - source => $init_defaults_file, - owner => 'root', - group => 'root', - mode => '0644', - before => Service["elasticsearch-instance-${name}"], - notify => $notify_service, - } - - } else { - if ($init_defaults != undef and is_hash($init_defaults) ) { - - if(has_key($init_defaults, 'ES_USER')) { - if($init_defaults['ES_USER'] != $elasticsearch::elasticsearch_user) { - fail('Found ES_USER setting for init_defaults but is not same as elasticsearch_user setting. Please use elasticsearch_user setting.') - } - } - } - $init_defaults_pre_hash = { 'ES_USER' => $elasticsearch::elasticsearch_user, 'ES_GROUP' => $elasticsearch::elasticsearch_group, 'MAX_OPEN_FILES' => '65535' } - $new_init_defaults = merge($init_defaults_pre_hash, $init_defaults) - - augeas { "defaults_${name}": - incl => "${elasticsearch::params::defaults_location}/elasticsearch-${name}", - lens => 'Shellvars.lns', - changes => template("${module_name}/etc/sysconfig/defaults.erb"), - before => Service["elasticsearch-instance-${name}"], - notify => $notify_service, - } - } - - # init file from template - if ($init_template != undef) { - - $user = $elasticsearch::elasticsearch_user - $group = $elasticsearch::elasticsearch_group - $pid_dir = $elasticsearch::pid_dir - $defaults_location = $elasticsearch::defaults_location - - if ($new_init_defaults != undef and is_hash($new_init_defaults) and has_key($new_init_defaults, 'MAX_OPEN_FILES')) { - $nofile = $new_init_defaults['MAX_OPEN_FILES'] - }else{ - $nofile = '65535' - } - - if ($new_init_defaults != undef and is_hash($new_init_defaults) and has_key($new_init_defaults, 'MAX_LOCKED_MEMORY')) { - $memlock = $new_init_defaults['MAX_LOCKED_MEMORY'] - }else{ - $memlock = undef - } - - file { "/lib/systemd/system/elasticsearch-${name}.service": - ensure => $ensure, - content => template($init_template), - before => Service["elasticsearch-instance-${name}"], - notify => $notify_service, - } - - } - - $service_require = Exec["systemd_reload_${name}"] - - } elsif($status != 'unmanaged') { - - file { "/lib/systemd/system/elasticsearch-${name}.service": - ensure => 'absent', - subscribe => Service["elasticsearch-instance-${name}"], - notify => Exec["systemd_reload_${name}"], - } - - file { "${elasticsearch::params::defaults_location}/elasticsearch-${name}": - ensure => 'absent', - subscribe => Service["elasticsearch-instance-${name}"], - notify => Exec["systemd_reload_${name}"], - } - - $service_require = undef - - } - - exec { "systemd_reload_${name}": - command => '/bin/systemctl daemon-reload', - refreshonly => true, - } - - if ($status != 'unmanaged') { - - # action - service { "elasticsearch-instance-${name}": - ensure => $service_ensure, - enable => $service_enable, - name => "elasticsearch-${name}.service", - hasstatus => $elasticsearch::params::service_hasstatus, - hasrestart => $elasticsearch::params::service_hasrestart, - pattern => $elasticsearch::params::service_pattern, - provider => 'systemd', - require => $service_require, - } - - } - -} diff --git a/puppet/modules/elasticsearch/manifests/template.pp b/puppet/modules/elasticsearch/manifests/template.pp deleted file mode 100644 index 4de9316..0000000 --- a/puppet/modules/elasticsearch/manifests/template.pp +++ /dev/null @@ -1,145 +0,0 @@ -# == Define: elasticsearch::template -# -# This define allows you to insert, update or delete templates that are used within Elasticsearch for the indexes -# -# === Parameters -# -# [*ensure*] -# String. Controls if the managed resources shall be present or -# absent. If set to absent: -# * The managed software packages are being uninstalled. -# * Any traces of the packages will be purged as good as possible. This may -# include existing configuration files. The exact behavior is provider -# dependent. Q.v.: -# * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP] -# * {Puppet's package provider source code}[http://j.mp/wtVCaL] -# * System modifications (if any) will be reverted as good as possible -# (e.g. removal of created users, services, changed log settings, ...). -# * This is thus destructive and should be used with care. -# Defaults to present. -# -# [*file*] -# File path of the template ( json file ) -# Value type is string -# Default value: undef -# This variable is optional -# -# [*content*] -# Contents of the template ( json ) -# Value type is string -# Default value: undef -# This variable is optional -# -# [*host*] -# Host name or IP address of the ES instance to connect to -# Value type is string -# Default value: localhost -# This variable is optional -# -# [*port*] -# Port number of the ES instance to connect to -# Value type is number -# Default value: 9200 -# This variable is optional -# -# === Authors -# -# * Richard Pijnenburg -# -define elasticsearch::template( - $ensure = 'present', - $file = undef, - $content = undef, - $host = 'localhost', - $port = 9200 -) { - - require elasticsearch - - # ensure - if ! ($ensure in [ 'present', 'absent' ]) { - fail("\"${ensure}\" is not a valid ensure parameter value") - } - - if ! is_integer($port) { - fail("\"${port}\" is not an integer") - } - - Exec { - path => [ '/bin', '/usr/bin', '/usr/local/bin' ], - cwd => '/', - tries => 6, - try_sleep => 10, - } - - # Build up the url - $es_url = "http://${host}:${port}/_template/${name}" - - # Can't do a replace and delete at the same time - - if ($ensure == 'present') { - - # Fail when no file or content is supplied - if $file == undef and $content == undef { - fail('The variables "file" and "content" cannot be empty when inserting or updating a template.') - } elsif $file != undef and $content != undef { - fail('The variables "file" and "content" cannot be used together when inserting or updating a template.') - } else { # we are good to go. notify to insert in case we deleted - $insert_notify = Exec[ "insert_template_${name}" ] - } - - } else { - - $insert_notify = undef - - } - - # Delete the existing template - # First check if it exists of course - exec { "delete_template_${name}": - command => "curl -s -XDELETE ${es_url}", - onlyif => "test $(curl -s '${es_url}?pretty=true' | wc -l) -gt 1", - notify => $insert_notify, - refreshonly => true, - } - - if ($ensure == 'absent') { - - # delete the template file on disk and then on the server - file { "${elasticsearch::params::homedir}/templates_import/elasticsearch-template-${name}.json": - ensure => 'absent', - notify => Exec[ "delete_template_${name}" ], - require => File[ "${elasticsearch::params::homedir}/templates_import" ], - } - } - - if ($ensure == 'present') { - - if $content == undef { - # place the template file using the file source - file { "${elasticsearch::params::homedir}/templates_import/elasticsearch-template-${name}.json": - ensure => file, - source => $file, - notify => Exec[ "delete_template_${name}" ], - require => File[ "${elasticsearch::params::homedir}/templates_import" ], - } - } else { - # place the template file using content - file { "${elasticsearch::params::homedir}/templates_import/elasticsearch-template-${name}.json": - ensure => file, - content => $content, - notify => Exec[ "delete_template_${name}" ], - require => File[ "${elasticsearch::params::homedir}/templates_import" ], - } - } - - exec { "insert_template_${name}": - command => "curl -sL -w \"%{http_code}\\n\" -XPUT ${es_url} -d @${elasticsearch::params::homedir}/templates_import/elasticsearch-template-${name}.json -o /dev/null | egrep \"(200|201)\" > /dev/null", - unless => "test $(curl -s '${es_url}?pretty=true' | wc -l) -gt 1", - refreshonly => true, - loglevel => 'debug', - } - - } - -} diff --git a/puppet/modules/elasticsearch/metadata.json b/puppet/modules/elasticsearch/metadata.json deleted file mode 100644 index b6369ed..0000000 --- a/puppet/modules/elasticsearch/metadata.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "name": "elasticsearch-elasticsearch", - "version": "0.9.9", - "author": "elasticsearch", - "summary": "Module for managing and configuring Elasticsearch nodes", - "license": "Apache-2.0", - "source": "https://github.com/elastic/puppet-elasticsearch", - "project_page": "https://github.com/elastic/puppet-elasticsearch", - "issues_url": "https://github.com/elastic/puppet-elasticsearch/issues", - "description": "Module for managing and configuring Elasticsearch nodes", - "operatingsystem_support": [ - { - "operatingsystem": "RedHat", - "operatingsystemrelease": [ - "5", - "6", - "7" - ] - }, - { - "operatingsystem": "CentOS", - "operatingsystemrelease": [ - "5", - "6", - "7" - ] - }, - { - "operatingsystem": "OracleLinux", - "operatingsystemrelease": [ - "5", - "6", - "7" - ] - }, - { - "operatingsystem": "Scientific", - "operatingsystemrelease": [ - "5", - "6", - "7" - ] - }, - { - "operatingsystem": "Debian", - "operatingsystemrelease": [ - "6", - "7", - "8" - ] - }, - { - "operatingsystem": "Ubuntu", - "operatingsystemrelease": [ - "10.04", - "12.04", - "14.04" - ] - }, - { - "operatingsystem": "OpenSuSE", - "operatingsystemrelease": [ - "12", - "13" - ] - } - ], - "requirements": [ - { - "name": "pe", - "version_requirement": ">= 3.3.2" - }, - { - "name": "puppet", - "version_requirement": ">=3.2.0 <4.3.0" - } - ], - "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":">= 3.2.0 < 5.0.0"}, - {"name":"puppetlabs/apt","version_requirement":">= 1.4.0 < 2.0.0"}, - {"name":"ceritsc/yum","version_requirement":">= 0.9.6 < 1.0.0"} - ] -} diff --git a/puppet/modules/elasticsearch/templates/etc/elasticsearch/elasticsearch.yml.erb b/puppet/modules/elasticsearch/templates/etc/elasticsearch/elasticsearch.yml.erb deleted file mode 100644 index b9d561c..0000000 --- a/puppet/modules/elasticsearch/templates/etc/elasticsearch/elasticsearch.yml.erb +++ /dev/null @@ -1,93 +0,0 @@ -<%- - - # Function to make a structured and sorted yaml representation out of a hash - def recursive_hash_to_yml_string(hash, depth=0) - spacer = "" - depth.times { spacer += " "} - hash.keys.sort.each do |sorted_key| - @yml_string += spacer + sorted_key + ": " - if hash[sorted_key].is_a?(::Array) - keyspacer = "" - sorted_key.length.times { keyspacer += " " } - @yml_string += "\n" - hash[sorted_key].each do |item| - @yml_string += spacer + keyspacer + "- " + item +"\n" - end - elsif hash[sorted_key].is_a?(::Hash) - @yml_string += "\n" - recursive_hash_to_yml_string(hash[sorted_key], depth+1) - else - @yml_string += "#{hash[sorted_key].to_s}\n" - end - end - end - - # Function to transform shorted write up of the keys into full hash representation - def transform(hash) - return_vals = [] - - hash.each do |key,val| - if m = /^([^.]+)\.(.*)$/.match(key) - temp = { m[1] => { m[2] => val } } - transform(temp).each do |stuff| - return_vals << stuff - end - else - if val.is_a?(::Hash) - transform(val).each do |stuff| - return_vals << { key => stuff } - end - else - return_vals << { key => val } - end - end - end - - return_vals - end - - # Function to deep merge hashes with same keys - class ::Hash - def deep_merge_with_array_values_concatenated(hash) - target = dup - - hash.keys.each do |key| - if hash[key].is_a? ::Hash and self[key].is_a? ::Hash - target[key] = target[key].deep_merge_with_array_values_concatenated(hash[key]) - next - end - - if hash[key].is_a?(::Array) && target[key].is_a?(::Array) - target[key] = target[key] + hash[key] - else - target[key] = hash[key] - end - end - - target - end - end - - # initial string - @yml_string = "### MANAGED BY PUPPET ###\n" - - if !@instance_conf.empty? - - @yml_string += "---\n" - - ## Transform shorted keys into full write up - transformed_config = transform(@instance_conf) - - # Merge it back into a hash - tmphash = { } - transformed_config.each do |subhash| - tmphash = tmphash.deep_merge_with_array_values_concatenated(subhash) - end - - # Transform it into yaml - recursive_hash_to_yml_string(tmphash) - - end - --%> -<%= @yml_string -%> diff --git a/puppet/modules/elasticsearch/templates/etc/elasticsearch/logging.yml.erb b/puppet/modules/elasticsearch/templates/etc/elasticsearch/logging.yml.erb deleted file mode 100644 index e24d414..0000000 --- a/puppet/modules/elasticsearch/templates/etc/elasticsearch/logging.yml.erb +++ /dev/null @@ -1,52 +0,0 @@ -# This file is managed by Puppet, do not edit manually, your changes *will* be overwritten! -# -# Please see the source file for context and more information: -# -# https://github.com/elasticsearch/elasticsearch/blob/master/config/logging.yml -# - -es.logger.level: <%= @logging_level %> -rootLogger: <%= @logging_level %>, console, file - -# ----- Configuration set by Puppet --------------------------------------------- - -<% @logging_hash.sort.each do |key,value| %> -logger.<%= key %>: <%= value %> -<% end %> - -# ------------------------------------------------------------------------------- - -additivity: - index.search.slowlog: false - index.indexing.slowlog: false - -appender: - console: - type: console - layout: - type: consolePattern - conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" - - file: - type: dailyRollingFile - file: ${path.logs}/${cluster.name}.log - datePattern: "'.'yyyy-MM-dd" - layout: - type: pattern - conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" - - index_search_slow_log_file: - type: dailyRollingFile - file: ${path.logs}/${cluster.name}_index_search_slowlog.log - datePattern: "'.'yyyy-MM-dd" - layout: - type: pattern - conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" - - index_indexing_slow_log_file: - type: dailyRollingFile - file: ${path.logs}/${cluster.name}_index_indexing_slowlog.log - datePattern: "'.'yyyy-MM-dd" - layout: - type: pattern - conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" diff --git a/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.Debian.erb b/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.Debian.erb deleted file mode 100644 index 3b78eeb..0000000 --- a/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.Debian.erb +++ /dev/null @@ -1,205 +0,0 @@ -#!/bin/sh -# -# /etc/init.d/elasticsearch-<%= @name %> -- startup script for Elasticsearch -# -# Written by Miquel van Smoorenburg . -# Modified for Debian GNU/Linux by Ian Murdock . -# Modified for Tomcat by Stefan Gybas . -# Modified for Tomcat6 by Thierry Carrez . -# Additional improvements by Jason Brittain . -# Modified by Nicolas Huray for Elasticsearch . -# -### BEGIN INIT INFO -# Provides: elasticsearch-<%= @name %> -# Required-Start: $network $remote_fs $named -# Required-Stop: $network $remote_fs $named -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Starts elasticsearch-<%= @name %> -# Description: Starts elasticsearch-<%= @name %> using start-stop-daemon -### END INIT INFO - -PATH=/bin:/usr/bin:/sbin:/usr/sbin -NAME=elasticsearch-<%= @name %> -DESC="Elasticsearch Server <%= @name %>" -DEFAULT=/etc/default/$NAME - -if [ `id -u` -ne 0 ]; then - echo "You need root privileges to run this script" - exit 1 -fi - - -. /lib/lsb/init-functions - -if [ -r /etc/default/rcS ]; then - . /etc/default/rcS -fi - - -# The following variables can be overwritten in $DEFAULT - -# Run Elasticsearch as this user ID and group ID -ES_USER=elasticsearch -ES_GROUP=elasticsearch - -# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-8-oracle /usr/lib/jvm/java-8-openjdk /usr/lib/jvm/java-8-openjdk-amd64/ /usr/lib/jvm/java-8-openjdk-armhf /usr/lib/jvm/java-8-openjdk-i386/ /usr/lib/jvm/java-7-oracle /usr/lib/jvm/java-7-openjdk /usr/lib/jvm/java-7-openjdk-amd64/ /usr/lib/jvm/java-7-openjdk-armhf /usr/lib/jvm/java-7-openjdk-i386/ /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-openjdk-armhf /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/default-java" - - -# Look for the right JVM to use -for jdir in $JDK_DIRS; do - if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then - JAVA_HOME="$jdir" - fi -done -export JAVA_HOME - -# Directory where the Elasticsearch binary distribution resides -ES_HOME=/usr/share/$NAME - -# Heap Size (defaults to 256m min, 1g max) -#ES_HEAP_SIZE=2g - -# Heap new generation -#ES_HEAP_NEWSIZE= - -# max direct memory -#ES_DIRECT_SIZE= - -# Additional Java OPTS -#ES_JAVA_OPTS= - -# Maximum number of open files -MAX_OPEN_FILES=65535 - -# Maximum amount of locked memory -#MAX_LOCKED_MEMORY= - -# Elasticsearch log directory -LOG_DIR=/var/log/$NAME - -# Elasticsearch data directory -DATA_DIR=/var/lib/$NAME - -# Elasticsearch work directory -WORK_DIR=/tmp/$NAME - -# Elasticsearch configuration directory -CONF_DIR=/etc/$NAME - -# Elasticsearch configuration file (elasticsearch.yml) -CONF_FILE=$CONF_DIR/elasticsearch.yml - -# Maximum number of VMA (Virtual Memory Areas) a process can own -MAX_MAP_COUNT=262144 - -# End of variables that can be overwritten in $DEFAULT - -# overwrite settings from default file -if [ -f "$DEFAULT" ]; then - . "$DEFAULT" -fi - -# Define other required variables -PID_FILE=/var/run/$NAME.pid -DAEMON=$ES_HOME/bin/elasticsearch -DAEMON_OPTS="-d -p $PID_FILE -Des.default.config=$CONF_FILE -Des.default.path.home=$ES_HOME -Des.default.path.logs=$LOG_DIR -Des.default.path.data=$DATA_DIR -Des.default.path.work=$WORK_DIR -Des.default.path.conf=$CONF_DIR" - -export ES_HEAP_SIZE -export ES_HEAP_NEWSIZE -export ES_DIRECT_SIZE -export ES_JAVA_OPTS -export ES_CLASSPATH - -# Check DAEMON exists -test -x $DAEMON || exit 0 - -checkJava() { - if [ -x "$JAVA_HOME/bin/java" ]; then - JAVA="$JAVA_HOME/bin/java" - else - JAVA=`which java` - fi - - if [ ! -x "$JAVA" ]; then - echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME" - exit 1 - fi -} - -case "$1" in - start) - checkJava - - if [ -n "$MAX_LOCKED_MEMORY" -a -z "$ES_HEAP_SIZE" ]; then - log_failure_msg "MAX_LOCKED_MEMORY is set - ES_HEAP_SIZE must also be set" - exit 1 - fi - - log_daemon_msg "Starting $DESC" - - pid=`pidofproc -p $PID_FILE elasticsearch` - if [ -n "$pid" ] ; then - log_begin_msg "Already running." - log_end_msg 0 - exit 0 - fi - - # Prepare environment - mkdir -p "$LOG_DIR" "$DATA_DIR" "$WORK_DIR" && chown "$ES_USER":"$ES_GROUP" "$LOG_DIR" "$DATA_DIR" "$WORK_DIR" - touch "$PID_FILE" && chown "$ES_USER":"$ES_GROUP" "$PID_FILE" - - if [ -n "$MAX_OPEN_FILES" ]; then - ulimit -n $MAX_OPEN_FILES - fi - - if [ -n "$MAX_LOCKED_MEMORY" ]; then - ulimit -l $MAX_LOCKED_MEMORY - fi - - if [ -n "$MAX_MAP_COUNT" ]; then - sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT - fi - - # Start Daemon - start-stop-daemon --start -b --user "$ES_USER" -c "$ES_USER" --pidfile "$PID_FILE" --exec $DAEMON -- $DAEMON_OPTS - log_end_msg $? - ;; - stop) - log_daemon_msg "Stopping $DESC" - - if [ -f "$PID_FILE" ]; then - start-stop-daemon --stop --pidfile "$PID_FILE" \ - --user "$ES_USER" \ - --retry=TERM/20/KILL/5 >/dev/null - if [ $? -eq 1 ]; then - log_progress_msg "$DESC is not running but pid file exists, cleaning up" - elif [ $? -eq 3 ]; then - PID="`cat $PID_FILE`" - log_failure_msg "Failed to stop $DESC (pid $PID)" - exit 1 - fi - rm -f "$PID_FILE" - else - log_progress_msg "(not running)" - fi - log_end_msg 0 - ;; - status) - status_of_proc -p $PID_FILE elasticsearch elasticsearch && exit 0 || exit $? - ;; - restart|force-reload) - if [ -f "$PID_FILE" ]; then - $0 stop - sleep 1 - fi - $0 start - ;; - *) - log_success_msg "Usage: $0 {start|stop|restart|force-reload|status}" - exit 1 - ;; -esac - -exit 0 diff --git a/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.RedHat.erb b/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.RedHat.erb deleted file mode 100644 index 2e7f0cf..0000000 --- a/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.RedHat.erb +++ /dev/null @@ -1,160 +0,0 @@ -#!/bin/sh -# -# elasticsearch<%= @name %> -# -# chkconfig: 2345 80 20 -# description: Starts and stops a single elasticsearch instance on this system -# - -### BEGIN INIT INFO -# Provides: Elasticsearch-<%= @name %> -# Required-Start: $network $named -# Required-Stop: $network $named -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: This service manages the elasticsearch daemon -# Description: Elasticsearch is a very scalable, schema-free and high-performance search solution supporting multi-tenancy and near realtime search. -### END INIT INFO - -# -# init.d / servicectl compatibility (openSUSE) -# -if [ -f /etc/rc.status ]; then - . /etc/rc.status - rc_reset -fi - -# -# Source function library. -# -if [ -f /etc/rc.d/init.d/functions ]; then - . /etc/rc.d/init.d/functions -fi - -exec="/usr/share/elasticsearch/bin/elasticsearch" -prog="elasticsearch-<%= @name %>" -pidfile=/var/run/elasticsearch/${prog}.pid - -[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog - -export ES_HEAP_SIZE -export ES_HEAP_NEWSIZE -export ES_DIRECT_SIZE -export ES_JAVA_OPTS -export ES_CLASSPATH -export JAVA_HOME - -lockfile=/var/lock/subsys/$prog - -# backwards compatibility for old config sysconfig files, pre 0.90.1 -if [ -n $USER ] && [ -z $ES_USER ] ; then - ES_USER=$USER -fi - -checkJava() { - if [ -x "$JAVA_HOME/bin/java" ]; then - JAVA="$JAVA_HOME/bin/java" - else - JAVA=`which java` - fi - - if [ ! -x "$JAVA" ]; then - echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME" - exit 1 - fi -} - -start() { - checkJava - [ -x $exec ] || exit 5 - [ -f $CONF_FILE ] || exit 6 - if [ -n "$MAX_LOCKED_MEMORY" -a -z "$ES_HEAP_SIZE" ]; then - echo "MAX_LOCKED_MEMORY is set - ES_HEAP_SIZE must also be set" - return 7 - fi - if [ -n "$MAX_OPEN_FILES" ]; then - ulimit -n $MAX_OPEN_FILES - fi - if [ -n "$MAX_LOCKED_MEMORY" ]; then - ulimit -l $MAX_LOCKED_MEMORY - fi - if [ -n "$MAX_MAP_COUNT" ]; then - sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT - fi - if [ -n "$WORK_DIR" ]; then - mkdir -p "$WORK_DIR" - chown "$ES_USER":"$ES_GROUP" "$WORK_DIR" - fi - echo -n $"Starting $prog: " - # if not running, start it up here, usually something like "daemon $exec" - daemon --user $ES_USER --pidfile $pidfile $exec -p $pidfile -d -Des.default.path.home=$ES_HOME -Des.default.path.logs=$LOG_DIR -Des.default.path.data=$DATA_DIR -Des.default.path.work=$WORK_DIR -Des.default.path.conf=$CONF_DIR - retval=$? - echo - [ $retval -eq 0 ] && touch $lockfile - return $retval -} - -stop() { - echo -n $"Stopping $prog: " - # stop it here, often "killproc $prog" - killproc -p $pidfile -d 20 $prog - retval=$? - echo - [ $retval -eq 0 ] && rm -f $lockfile - return $retval -} - -restart() { - stop - start -} - -reload() { - restart -} - -force_reload() { - restart -} - -rh_status() { - # run checks to determine if the service is running or use generic status - status -p $pidfile $prog -} - -rh_status_q() { - rh_status >/dev/null 2>&1 -} - - -case "$1" in - start) - rh_status_q && exit 0 - $1 - ;; - stop) - rh_status_q || exit 0 - $1 - ;; - restart) - $1 - ;; - reload) - rh_status_q || exit 7 - $1 - ;; - force-reload) - force_reload - ;; - status) - rh_status - ;; - condrestart|try-restart) - rh_status_q || exit 0 - restart - ;; - *) - echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" - exit 2 -esac -exit $? diff --git a/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.systemd.erb b/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.systemd.erb deleted file mode 100644 index 3c9f6e8..0000000 --- a/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.systemd.erb +++ /dev/null @@ -1,24 +0,0 @@ -[Unit] -Description=Starts and stops a single elasticsearch instance on this system -Documentation=http://www.elasticsearch.org - -[Service] -Type=forking -EnvironmentFile=<%= @defaults_location %>/elasticsearch-<%= @name %> -User=<%= @user %> -Group=<%= @group %> -PIDFile=<%= @pid_dir %>/elasticsearch-<%= @name %>.pid -ExecStart=/usr/share/elasticsearch/bin/elasticsearch -d -p <%= @pid_dir %>/elasticsearch-<%= @name %>.pid -Des.default.config=${CONF_FILE} -Des.default.path.home=${ES_HOME} -Des.default.path.logs=${LOG_DIR} -Des.default.path.data=${DATA_DIR} -Des.default.path.work=${WORK_DIR} -Des.default.path.conf=${CONF_DIR} -# See MAX_OPEN_FILES in sysconfig -LimitNOFILE=<%= @nofile %> -# See MAX_LOCKED_MEMORY in sysconfig, use "infinity" when MAX_LOCKED_MEMORY=unlimited and using bootstrap.mlockall: true -<% if @memlock == 'unlimited' %> -LimitMEMLOCK=infinity -<% elsif @memlock %> -LimitMEMLOCK=<%= @memlock %> -<% end %> -# Shutdown delay in seconds, before process is tried to be killed with KILL (if configured) -TimeoutStopSec=20 - -[Install] -WantedBy=multi-user.target diff --git a/puppet/modules/elasticsearch/templates/etc/sysconfig/defaults.erb b/puppet/modules/elasticsearch/templates/etc/sysconfig/defaults.erb deleted file mode 100644 index 7dad4e0..0000000 --- a/puppet/modules/elasticsearch/templates/etc/sysconfig/defaults.erb +++ /dev/null @@ -1,3 +0,0 @@ -<% @new_init_defaults.sort.map do |key, value| -%> -set <%= key %> '<%= value %>' -<% end -%> diff --git a/puppet/modules/elasticsearch/templates/usr/lib/tmpfiles.d/elasticsearch.conf.erb b/puppet/modules/elasticsearch/templates/usr/lib/tmpfiles.d/elasticsearch.conf.erb deleted file mode 100644 index ec6197d..0000000 --- a/puppet/modules/elasticsearch/templates/usr/lib/tmpfiles.d/elasticsearch.conf.erb +++ /dev/null @@ -1 +0,0 @@ -d <%= @pid_dir %> 0755 <%= @user %> <%= @group %> - - diff --git a/puppet/modules/java/CHANGELOG.md b/puppet/modules/java/CHANGELOG.md deleted file mode 100644 index 884dfec..0000000 --- a/puppet/modules/java/CHANGELOG.md +++ /dev/null @@ -1,164 +0,0 @@ -## 2015-10-07 - Supported Release 1.4.2 -### Summary -This release fixes the fact to not trigger java every time on OS X when it is not available. - -#### Bugfixes -- Causes java\_version fact to not run `java` when java is not installed on OS X - -## 2015-07-16 - Supported Release 1.4.1 -### Summary -This release updates the metadata for the upcoming release of PE and update params for OEL to match metadata - -#### Bugfixes: -- Add missing OEL to params - -##2015-07-07 - Supported Release 1.4.0 -###Summary -This release adds several new features, bugfixes, documentation updates, and test improvements. - -####Features: -- Puppet 4 support and testing -- Adds support for several Operating Systems - - Ubuntu 15.04 - - OpenBSD 5.6, 5.7 - - Fedora 20, 21, 22 - -####Bugfixes: -- Fixes java_version fact to work on large systems. (MODULES-1749) -- Improves maintainability of java_version fact. -- Fixes java package names on Fedora 21+. -- Fixes java install problems on Puppet 3.7.5 - 3.8.1 (PUP-4520) -- Fixes create-java-alternatives commands on RedHat distros. -- Fixes bug with Debian systems missing java-common package. - -##2015-01-20 - Supported Release 1.3.0 -###Summary -This release adds 3 new facts for determining Java version, adds RHEL alternatives support, adds utopic support, and fixes the flag for `update-java-alternatives` when installed from a headless pacakge. - -####Features -- Added RHEL support for alternatives -- New facts - - java_major_version - - java_patch_level - - java_version -- Add support for utopic - -####Bugfixes -- Use `--jre-headless` in the `update-java-alternatives` command when installed from a `headless` package - -##2014-11-11 - Supported Version 1.2.0 - -###Summary: -This release adds SLES 12 support and is tested for Future Parser Support - -####Bugfixes: -- Several readme updates -- Testcase flexability increased - -####Features: -- Add SLES 12 support -- Future Parser tested -- Validated against PE 3.7 - -##2014-08-25 - Supported Version 1.1.2 - -###Summary: -This release begins the support coverage of the puppetlabs-java module. - -###Bugfixes: -- Update java alternative values from deprecated names -- Readme updated -- Testing updated - -##2014-05-02 - Version 1.1.1 - -###Summary: - -Add support for new versions of Debian and Ubuntu! - -####Features: -- Add support for Ubuntu Trusty (14.04) -- Add support for Debian Jessie (8.x) - -##2014-01-06 - Version 1.1.0 - -####Summary: - -Primarily a release for Ubuntu users! - -####Features: -- Add support for Ubuntu Saucy (13.10) -- Add `java_home` parameter for centralized setting of JAVA_HOME. -- Add Scientific Linux - -###Bugfixes: -- Plus signs are valid in debian/ubuntu package names. - -##2013-08-01 - Version 1.0.1 - -Matthaus Owens -* Update java packages for Fedora systems - -##2013-07-29 - Version 1.0.0 - -####Detailed Changes - -Krzysztof Suszyński -* Adding support for Oracle Enterprise Linux - -Peter Drake -* Add support for natty - -Robert Munteanu -* Add support for OpenSUSE - -Martin Jackson -* Added support Amazon Linux using facter >= 1.7.x - -Gareth Rushgrove -Brett Porter -* Fixes for older versions of CentOS -* Improvements to module build and tests - -Nathan R Valentine -* Add support for Ubuntu quantal and raring - -Sharif Nassar -* Add support for Debian alternatives, and more than one JDK/JRE per platform. - -##2013-04-04 - Version 0.3.0 -Reid Vandewiele - -* Refactor, introduce params pattern - -##2012-11-15 - Version 0.2.0 -Scott Schneider -* Add Solaris support - -##2011-06-16 - Version 0.1.5 -Jeff McCune -* Add Debian based distro (Lucid) support - -##2011-06-02 - Version 0.1.4 -Jeff McCune -* Fix class composition ordering problems - -##2011-05-28 - Version 0.1.3 -Jeff McCune -* Remove stages - -##2011-05-26 - Version 0.1.2 -Jeff McCune -* Changes JRE/JDK selection class parameter to $distribution - -##2011-05-25 - Version 0.1.1 -Jeff McCune -* Re-did versioning to follow semantic versioning -* Add validation of class parameters - -##2011-05-24 - Version 0.1.0 -Jeff McCune -* Default to JDK version 6u25 - -##2011-05-24 - Version 0.0.1 -Jeff McCune -* Initial release diff --git a/puppet/modules/java/CONTRIBUTING.md b/puppet/modules/java/CONTRIBUTING.md deleted file mode 100644 index f1cbde4..0000000 --- a/puppet/modules/java/CONTRIBUTING.md +++ /dev/null @@ -1,220 +0,0 @@ -Checklist (and a short version for the impatient) -================================================= - - * Commits: - - - Make commits of logical units. - - - Check for unnecessary whitespace with "git diff --check" before - committing. - - - Commit using Unix line endings (check the settings around "crlf" in - git-config(1)). - - - Do not check in commented out code or unneeded files. - - - The first line of the commit message should be a short - description (50 characters is the soft limit, excluding ticket - number(s)), and should skip the full stop. - - - Associate the issue in the message. The first line should include - the issue number in the form "(#XXXX) Rest of message". - - - The body should provide a meaningful commit message, which: - - - uses the imperative, present tense: "change", not "changed" or - "changes". - - - includes motivation for the change, and contrasts its - implementation with the previous behavior. - - - Make sure that you have tests for the bug you are fixing, or - feature you are adding. - - - Make sure the test suites passes after your commit: - `bundle exec rspec spec/acceptance` More information on [testing](#Testing) below - - - When introducing a new feature, make sure it is properly - documented in the README.md - - * Submission: - - * Pre-requisites: - - - Make sure you have a [GitHub account](https://github.com/join) - - - [Create a ticket](https://tickets.puppetlabs.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppetlabs.com/browse/) you are patching for. - - * Preferred method: - - - Fork the repository on GitHub. - - - Push your changes to a topic branch in your fork of the - repository. (the format ticket/1234-short_description_of_change is - usually preferred for this project). - - - Submit a pull request to the repository in the puppetlabs - organization. - -The long version -================ - - 1. Make separate commits for logically separate changes. - - Please break your commits down into logically consistent units - which include new or changed tests relevant to the rest of the - change. The goal of doing this is to make the diff easier to - read for whoever is reviewing your code. In general, the easier - your diff is to read, the more likely someone will be happy to - review it and get it into the code base. - - If you are going to refactor a piece of code, please do so as a - separate commit from your feature or bug fix changes. - - We also really appreciate changes that include tests to make - sure the bug is not re-introduced, and that the feature is not - accidentally broken. - - Describe the technical detail of the change(s). If your - description starts to get too long, that is a good sign that you - probably need to split up your commit into more finely grained - pieces. - - Commits which plainly describe the things which help - reviewers check the patch and future developers understand the - code are much more likely to be merged in with a minimum of - bike-shedding or requested changes. Ideally, the commit message - would include information, and be in a form suitable for - inclusion in the release notes for the version of Puppet that - includes them. - - Please also check that you are not introducing any trailing - whitespace or other "whitespace errors". You can do this by - running "git diff --check" on your changes before you commit. - - 2. Sending your patches - - To submit your changes via a GitHub pull request, we _highly_ - recommend that you have them on a topic branch, instead of - directly on "master". - It makes things much easier to keep track of, especially if - you decide to work on another thing before your first change - is merged in. - - GitHub has some pretty good - [general documentation](http://help.github.com/) on using - their site. They also have documentation on - [creating pull requests](http://help.github.com/send-pull-requests/). - - In general, after pushing your topic branch up to your - repository on GitHub, you can switch to the branch in the - GitHub UI and click "Pull Request" towards the top of the page - in order to open a pull request. - - - 3. Update the related GitHub issue. - - If there is a GitHub issue associated with the change you - submitted, then you should update the ticket to include the - location of your branch, along with any other commentary you - may wish to make. - -Testing -======= - -Getting Started ---------------- - -Our puppet modules provide [`Gemfile`](./Gemfile)s which can tell a ruby -package manager such as [bundler](http://bundler.io/) what Ruby packages, -or Gems, are required to build, develop, and test this software. - -Please make sure you have [bundler installed](http://bundler.io/#getting-started) -on your system, then use it to install all dependencies needed for this project, -by running - -```shell -% bundle install -Fetching gem metadata from https://rubygems.org/........ -Fetching gem metadata from https://rubygems.org/.. -Using rake (10.1.0) -Using builder (3.2.2) --- 8><-- many more --><8 -- -Using rspec-system-puppet (2.2.0) -Using serverspec (0.6.3) -Using rspec-system-serverspec (1.0.0) -Using bundler (1.3.5) -Your bundle is complete! -Use `bundle show [gemname]` to see where a bundled gem is installed. -``` - -NOTE some systems may require you to run this command with sudo. - -If you already have those gems installed, make sure they are up-to-date: - -```shell -% bundle update -``` - -With all dependencies in place and up-to-date we can now run the tests: - -```shell -% rake spec -``` - -This will execute all the [rspec tests](http://rspec-puppet.com/) tests -under [spec/defines](./spec/defines), [spec/classes](./spec/classes), -and so on. rspec tests may have the same kind of dependencies as the -module they are testing. While the module defines in its [Modulefile](./Modulefile), -rspec tests define them in [.fixtures.yml](./fixtures.yml). - -Some puppet modules also come with [beaker](https://github.com/puppetlabs/beaker) -tests. These tests spin up a virtual machine under -[VirtualBox](https://www.virtualbox.org/)) with, controlling it with -[Vagrant](http://www.vagrantup.com/) to actually simulate scripted test -scenarios. In order to run these, you will need both of those tools -installed on your system. - -You can run them by issuing the following command - -```shell -% rake spec_clean -% rspec spec/acceptance -``` - -This will now download a pre-fabricated image configured in the [default node-set](./spec/acceptance/nodesets/default.yml), -install puppet, copy this module and install its dependencies per [spec/spec_helper_acceptance.rb](./spec/spec_helper_acceptance.rb) -and then run all the tests under [spec/acceptance](./spec/acceptance). - -Writing Tests -------------- - -XXX getting started writing tests. - -If you have commit access to the repository -=========================================== - -Even if you have commit access to the repository, you will still need to -go through the process above, and have someone else review and merge -in your changes. The rule is that all changes must be reviewed by a -developer on the project (that did not write the code) to ensure that -all changes go through a code review process. - -Having someone other than the author of the topic branch recorded as -performing the merge is the record that they performed the code -review. - - -Additional Resources -==================== - -* [Getting additional help](http://puppetlabs.com/community/get-help) - -* [Writing tests](http://projects.puppetlabs.com/projects/puppet/wiki/Development_Writing_Tests) - -* [Patchwork](https://patchwork.puppetlabs.com) - -* [General GitHub documentation](http://help.github.com/) - -* [GitHub pull request documentation](http://help.github.com/send-pull-requests/) - diff --git a/puppet/modules/java/Gemfile b/puppet/modules/java/Gemfile deleted file mode 100644 index bfe64b1..0000000 --- a/puppet/modules/java/Gemfile +++ /dev/null @@ -1,48 +0,0 @@ -source ENV['GEM_SOURCE'] || "https://rubygems.org" - -def location_for(place, fake_version = nil) - if place =~ /^(git:[^#]*)#(.*)/ - [fake_version, { :git => $1, :branch => $2, :require => false }].compact - elsif place =~ /^file:\/\/(.*)/ - ['>= 0', { :path => File.expand_path($1), :require => false }] - else - [place, { :require => false }] - end -end - -group :development, :unit_tests do - gem 'rspec-core', '3.1.7', :require => false - gem 'puppetlabs_spec_helper', :require => false - gem 'simplecov', :require => false - gem 'puppet_facts', :require => false - gem 'json', :require => false -end - -group :system_tests do - if beaker_version = ENV['BEAKER_VERSION'] - gem 'beaker', *location_for(beaker_version) - end - if beaker_rspec_version = ENV['BEAKER_RSPEC_VERSION'] - gem 'beaker-rspec', *location_for(beaker_rspec_version) - else - gem 'beaker-rspec', :require => false - end - gem 'serverspec', :require => false - gem 'beaker-puppet_install_helper', :require => false -end - - - -if facterversion = ENV['FACTER_GEM_VERSION'] - gem 'facter', facterversion, :require => false -else - gem 'facter', :require => false -end - -if puppetversion = ENV['PUPPET_GEM_VERSION'] - gem 'puppet', puppetversion, :require => false -else - gem 'puppet', :require => false -end - -# vim:ft=ruby diff --git a/puppet/modules/java/LICENSE b/puppet/modules/java/LICENSE deleted file mode 100644 index a33e812..0000000 --- a/puppet/modules/java/LICENSE +++ /dev/null @@ -1,17 +0,0 @@ -Puppet Java Module - Puppet module for managing Java - -Copyright (C) 2011 Puppet Labs Inc - -Puppet Labs can be contacted at: info@puppetlabs.com - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/puppet/modules/java/README.markdown b/puppet/modules/java/README.markdown deleted file mode 100644 index 5442157..0000000 --- a/puppet/modules/java/README.markdown +++ /dev/null @@ -1,123 +0,0 @@ -#java - -####Table of Contents - -1. [Overview](#overview) -2. [Module Description - What the module does and why it is useful](#module-description) -3. [Setup - The basics of getting started with the java module](#setup) - * [Beginning with the java module](#beginning-with-the-java-module) -4. [Usage - Configuration options and additional functionality](#usage) -5. [Reference - An under-the-hood peek at what the module is doing and how](#reference) -6. [Limitations - OS compatibility, etc.](#limitations) -7. [Development - Guide for contributing to the module](#development) - -##Overview - -Installs the correct Java package on various platforms. - -##Module Description - -The java module can automatically install Java jdk or jre on a wide variety of systems. Java is a base component for many software platforms, but Java system packages don't always follow packaging conventions. The java module simplifies the Java installation process. - -##Setup - -###Beginning with the java module -To install the correct Java package on your system, include the `java` class: `include java`. - -##Usage - -The java module installs the correct jdk or jre package on a wide variety of systems. By default, the module will install the jdk package, but you can set different installation parameters as needed. For example, to install jre instead of jdk, you would set the distribution parameter: - -~~~ -class { 'java': - distribution => 'jre', -} -~~~ - -##Reference - -###Classes - -####Public classes - -* `java`: Installs and manages the Java package. - -####Private classes - -* `java::config`: Configures the Java alternatives. - -* `java::params`: Builds a hash of jdk/jre packages for all compatible operating systems. - -####Parameters -The following parameters are available in `java`: - -##### `distribution` -Specifies the Java distribution to install. -Valid options: 'jdk', 'jre', or, where the platform supports alternative packages, 'sun-jdk', 'sun-jre', 'oracle-jdk', 'oracle-jre'. Default: 'jdk'. - -#####`java_alternative` -Specifies the name of the Java alternative to use. If you set this parameter, *you must also set the `java_alternative_path`.* -Valid options: Run command `update-java-alternatives -l` for a list of available choices. Default: OS and distribution dependent defaults on *deb systems, undef on others. - -#####`java_alternative_path` -*Required when `java_alternative` is specified.* Defines the path to the `java` command. -Valid option: String. Default: OS and distribution dependent defaults on *deb systems, undef on others. - -#####`package` -Specifies the name of the Java package. This is configurable in case you want to install a non-standard Java package. If not set, the module will install the appropriate package for the `distribution` parameter and target platform. If you set `package`, the `distribution` parameter will do nothing. -Valid option: String. Default: undef. - -#####`version` -Sets the version of Java to install, if you want to ensure a particular version. -Valid options: 'present', 'installed', 'latest', or a string matching `/^[.+_0-9a-zA-Z:-]+$/`. Default: 'present'. - - -###Facts - -The java module includes a few facts to describe the version of Java installed on the system: - -* `java_major_version`: The major version of Java. -* `java_patch_level`: The patch level of Java. -* `java_version`: The full Java version string. - -**Note:** The facts return `nil` if Java is not installed on the system. - -##Limitations - -This module cannot guarantee installation of Java versions that are not available on platform repositories. - -This module only manages a singular installation of Java, meaning it is not possible to manage e.g. OpenJDK 7, Oracle Java 7 and Oracle Java 8 in parallel on the same system. - -Oracle Java packages are not included in Debian 7 and Ubuntu 12.04/14.04 repositories. To install Java on those systems, you'll need to package Oracle JDK/JRE, and then the module will be able to install the package. For more information on how to package Oracle JDK/JRE, see the [Debian wiki](http://wiki.debian.org/JavaPackage). - -This module is officially [supported](https://forge.puppetlabs.com/supported) for the following Java versions and platforms: - -OpenJDK is supported on: - -* Red Hat Enterprise Linux (RHEL) 5, 6, 7 -* CentOS 5, 6, 7 -* Oracle Linux 6, 7 -* Scientific Linux 5, 6 -* Debian 6, 7 -* Ubuntu 10.04, 12.04, 14.04 -* Solaris 11 -* SLES 11 SP1, 12 -* OpenBSD 5.6, 5.7 - -Sun Java is supported on: - -* Debian 6 - -### A note to OpenBSD -OpenBSD packages install Java JRE/JDK in a unique directory structure, not linking -the binaries to a standard directory. Because of that, the path to this location -is hardcoded in the java_version fact. Whenever a Java upgrade to a newer -version/path will be done on OpenBSD, it has to be adapted there. - -##Development - -Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad hardware, software, and deployment configurations that Puppet is intended to serve. We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. For more information, see our [module contribution guide.](https://docs.puppetlabs.com/forge/contributing.html) - -##Contributors - -The list of contributors can be found at: [https://github.com/puppetlabs/puppetlabs-java/graphs/contributors](https://github.com/puppetlabs/puppetlabs-java/graphs/contributors). diff --git a/puppet/modules/java/Rakefile b/puppet/modules/java/Rakefile deleted file mode 100644 index 181157e..0000000 --- a/puppet/modules/java/Rakefile +++ /dev/null @@ -1,10 +0,0 @@ -require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet-lint/tasks/puppet-lint' - -PuppetLint.configuration.fail_on_warnings = true -PuppetLint.configuration.send('relative') -PuppetLint.configuration.send('disable_80chars') -PuppetLint.configuration.send('disable_class_inherits_from_params_class') -PuppetLint.configuration.send('disable_documentation') -PuppetLint.configuration.send('disable_single_quote_string_with_variables') -PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] diff --git a/puppet/modules/java/checksums.json b/puppet/modules/java/checksums.json deleted file mode 100644 index 7b7827f..0000000 --- a/puppet/modules/java/checksums.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "CHANGELOG.md": "75ff8a0b41466a4b7d0c933e7e4cd6f1", - "CONTRIBUTING.md": "e2b8e8e433fc76b3798b7fe435f49375", - "Gemfile": "e6e6eb07f0bfc9bb1e328895ca49b3f5", - "LICENSE": "927881786db06d253bfed0ecf1b42b21", - "README.markdown": "ce31711e3f7c4378825dd7aa31feafff", - "Rakefile": "d953eb985f82600dc3b9ac6e1f2cfe64", - "lib/facter/java_major_version.rb": "b409cf1ff3874c45964f9f1857de0dba", - "lib/facter/java_patch_level.rb": "48e4b129cad5d9406125747c60bd38e4", - "lib/facter/java_version.rb": "1cacbaad9e857ca21a95d6af6ddbcf81", - "manifests/config.pp": "368ed5e1b6dc066bd6c81c56b11483ae", - "manifests/init.pp": "61d45b2d228a3dfc9bbdba3d7b98a3f0", - "manifests/params.pp": "5e10ef4561b1319b921e14b314f0e690", - "metadata.json": "c2fcf71f2c78c9fe693f482d3e9a664a", - "spec/acceptance/install_spec.rb": "74389e626c11feb5f8c32c969a491c55", - "spec/acceptance/nodesets/centos-5-vcloud.yml": "db8b5af87d2c931a25f8a9108005500c", - "spec/acceptance/nodesets/centos-59-x64-pe.yml": "255100fb63e3b7c204e24dc9464ae904", - "spec/acceptance/nodesets/centos-59-x64.yml": "57eb3e471b9042a8ea40978c467f8151", - "spec/acceptance/nodesets/centos-6-vcloud.yml": "bdf9ce9d3b0f0b4995666ae9d64d878d", - "spec/acceptance/nodesets/centos-64-x64-fusion.yml": "f5da18ffa623c6a13d9f48521b1bfa39", - "spec/acceptance/nodesets/centos-64-x64-pe.yml": "ec075d95760df3d4702abea1ce0a829b", - "spec/acceptance/nodesets/centos-64-x64.yml": "092dd2c588a9f87fa1fb12997c0723ef", - "spec/acceptance/nodesets/centos-65-x64.yml": "3e5c36e6aa5a690229e720f4048bb8af", - "spec/acceptance/nodesets/centos-7-vcloud.yml": "809df5eb18752a766b981a0d9a39a09a", - "spec/acceptance/nodesets/debian-6-vcloud.yml": "c36f0196a9cf8c6b717954a5d86f3028", - "spec/acceptance/nodesets/debian-607-x64.yml": "d566bf76f534e2af7c9a4605316d232c", - "spec/acceptance/nodesets/debian-7-vcloud.yml": "72417285da99ae233b54dace2d55bd29", - "spec/acceptance/nodesets/debian-70rc1-x64.yml": "31ccca73af7b74e1cc2fb0035c230b2c", - "spec/acceptance/nodesets/default.yml": "092dd2c588a9f87fa1fb12997c0723ef", - "spec/acceptance/nodesets/fedora-18-x64.yml": "acc126fa764c39a3b1df36e9224a21d9", - "spec/acceptance/nodesets/redhat-7-vcloud.yml": "91b55d29f059e23383c7bc352b5d671d", - "spec/acceptance/nodesets/sles-11-vcloud.yml": "eddc31f492c1c7c8b750528e026096e6", - "spec/acceptance/nodesets/sles-11sp1-x64.yml": "fa0046bd89c1ab4ba9521ad79db234cd", - "spec/acceptance/nodesets/solaris-11-vcloud.yml": "a63713a8009fbbf1839569de1bd228dc", - "spec/acceptance/nodesets/ubuntu-1004-vcloud.yml": "c437745eb39d41786b001b468185d052", - "spec/acceptance/nodesets/ubuntu-1404-vcloud.yml": "26b68a7d544585a0dd4709404e65b282", - "spec/acceptance/nodesets/ubuntu-server-10044-x64.yml": "75e86400b7889888dc0781c0ae1a1297", - "spec/acceptance/nodesets/ubuntu-server-12042-x64.yml": "d30d73e34cd50b043c7d14e305955269", - "spec/acceptance/nodesets/ubuntu-server-1404-x64.yml": "5f0aed10098ac5b78e4217bb27c7aaf0", - "spec/acceptance/nodesets/ubuntu-server-1504-x64.yml": "7f2e0396dae561b4ec7ed3ca1b72d0b2", - "spec/classes/java_spec.rb": "45a3cac8594fd36a38f3a118a689c890", - "spec/spec.opts": "a600ded995d948e393fbe2320ba8e51c", - "spec/spec_helper.rb": "a54c7adb72289c1b4d86061c2e545643", - "spec/spec_helper_acceptance.rb": "1ccb28b3440cbee9245d5e4fb8a7e25f", - "spec/unit/facter/java_major_version_spec.rb": "9d4bec0e8132a8914525f1bb19a51b38", - "spec/unit/facter/java_patch_level_spec.rb": "05374e6210d53e872bb3664490e615dd", - "spec/unit/facter/java_version_spec.rb": "e96b09e331c5764e53f9df61749cf3fe", - "tests/alternative.pp": "13871502638413326ff8813dac13529b", - "tests/init.pp": "91a343f9a46d8122c30df67c3d143508" -} \ No newline at end of file diff --git a/puppet/modules/java/lib/facter/java_major_version.rb b/puppet/modules/java/lib/facter/java_major_version.rb deleted file mode 100644 index b0a0aae..0000000 --- a/puppet/modules/java/lib/facter/java_major_version.rb +++ /dev/null @@ -1,20 +0,0 @@ -# Fact: java_major_version -# -# Purpose: get Java's major version -# -# Resolution: -# Tests for presence of java, returns nil if not present -# returns output of "java -version" and splits on \n + '"' -# eg. -# -# Caveats: -# none -# -# Notes: -# None -Facter.add(:java_major_version) do - setcode do - java_version = Facter.value(:java_version) - java_patch_level = java_version.strip.split('_')[0].split('.')[1] unless java_version.nil? - end -end \ No newline at end of file diff --git a/puppet/modules/java/lib/facter/java_patch_level.rb b/puppet/modules/java/lib/facter/java_patch_level.rb deleted file mode 100644 index 1d7921f..0000000 --- a/puppet/modules/java/lib/facter/java_patch_level.rb +++ /dev/null @@ -1,18 +0,0 @@ -# Fact: java_patch_level -# -# Purpose: get Java's patch level -# -# Resolution: -# Uses java_version fact splits on the patch number (after _) -# -# Caveats: -# none -# -# Notes: -# None -Facter.add(:java_patch_level) do - setcode do - java_version = Facter.value(:java_version) - java_patch_level = java_version.strip.split('_')[1] unless java_version.nil? - end -end \ No newline at end of file diff --git a/puppet/modules/java/lib/facter/java_version.rb b/puppet/modules/java/lib/facter/java_version.rb deleted file mode 100644 index e3ce186..0000000 --- a/puppet/modules/java/lib/facter/java_version.rb +++ /dev/null @@ -1,52 +0,0 @@ -# Fact: java_version -# -# Purpose: get full java version string -# -# Resolution: -# Tests for presence of java, returns nil if not present -# returns output of "java -version" and splits on \n + '"' -# -# Caveats: -# none -# -# Notes: -# None -Facter.add(:java_version) do - # the OS-specific overrides need to be able to return nil, - # to indicate "no java available". Usually returning nil - # would mean that facter falls back to a lower priority - # resolution, which would then trigger MODULES-2637. To - # avoid that, we confine the "default" here to not run - # on those OS. - # Additionally, facter versions prior to 2.0.1 only support - # positive matches, so this needs to be done manually in setcode. - setcode do - unless [ 'openbsd', 'darwin' ].include? Facter.value(:operatingsystem).downcase - if Facter::Util::Resolution.which('java') - Facter::Util::Resolution.exec('java -Xmx8m -version 2>&1').lines.first.split(/"/)[1].strip - end - end - end -end - -Facter.add(:java_version) do - confine :operatingsystem => 'OpenBSD' - has_weight 100 - setcode do - Facter::Util::Resolution.with_env("PATH" => '/usr/local/jdk-1.7.0/jre/bin:/usr/local/jre-1.7.0/bin') do - if Facter::Util::Resolution.which('java') - Facter::Util::Resolution.exec('java -Xmx8m -version 2>&1').lines.first.split(/"/)[1].strip - end - end - end -end - -Facter.add(:java_version) do - confine :operatingsystem => 'Darwin' - has_weight 100 - setcode do - unless /Unable to find any JVMs matching version/ =~ Facter::Util::Resolution.exec('/usr/libexec/java_home --failfast 2>&1') - Facter::Util::Resolution.exec('java -Xmx8m -version 2>&1').lines.first.split(/"/)[1].strip - end - end -end diff --git a/puppet/modules/java/manifests/config.pp b/puppet/modules/java/manifests/config.pp deleted file mode 100644 index b15d911..0000000 --- a/puppet/modules/java/manifests/config.pp +++ /dev/null @@ -1,37 +0,0 @@ -# On Debian systems, if alternatives are set, manually assign them. -class java::config ( ) { - case $::osfamily { - 'Debian': { - if $java::use_java_alternative != undef and $java::use_java_alternative_path != undef { - exec { 'update-java-alternatives': - path => '/usr/bin:/usr/sbin:/bin:/sbin', - command => "update-java-alternatives --set ${java::use_java_alternative} ${java::jre_flag}", - unless => "test /etc/alternatives/java -ef '${java::use_java_alternative_path}'", - } - } - } - 'RedHat': { - if $java::use_java_alternative != undef and $java::use_java_alternative_path != undef { - # The standard packages install alternatives, custom packages do not - # For the stanard packages java::params needs these added. - if $java::use_java_package_name != $java::default_package_name { - exec { 'create-java-alternatives': - path => '/usr/bin:/usr/sbin:/bin:/sbin', - command => "alternatives --install /usr/bin/java java ${$java::use_java_alternative_path} 20000" , - unless => "alternatives --display java | grep -q ${$java::use_java_alternative_path}", - before => Exec['update-java-alternatives'] - } - } - - exec { 'update-java-alternatives': - path => '/usr/bin:/usr/sbin', - command => "alternatives --set java ${$java::use_java_alternative_path}" , - unless => "test /etc/alternatives/java -ef '${java::use_java_alternative_path}'", - } - } - } - default: { - # Do nothing. - } - } -} diff --git a/puppet/modules/java/manifests/init.pp b/puppet/modules/java/manifests/init.pp deleted file mode 100644 index 19d3d79..0000000 --- a/puppet/modules/java/manifests/init.pp +++ /dev/null @@ -1,108 +0,0 @@ -# Class: java -# -# This module manages the Java runtime package -# -# Parameters: -# -# [*distribution*] -# The java distribution to install. Can be one of "jdk" or "jre", -# or other platform-specific options where there are multiple -# implementations available (eg: OpenJDK vs Oracle JDK). -# -# -# [*version*] -# The version of java to install. By default, this module simply ensures -# that java is present, and does not require a specific version. -# -# [*package*] -# The name of the java package. This is configurable in case a non-standard -# java package is desired. -# -# [*java_alternative*] -# The name of the java alternative to use on Debian systems. -# "update-java-alternatives -l" will show which choices are available. -# If you specify a particular package, you will almost always also -# want to specify which java_alternative to choose. If you set -# this, you also need to set the path below. -# -# [*java_alternative_path*] -# The path to the "java" command on Debian systems. Since the -# alternatives system makes it difficult to verify which -# alternative is actually enabled, this is required to ensure the -# correct JVM is enabled. -# -# Actions: -# -# Requires: -# -# Sample Usage: -# -class java( - $distribution = 'jdk', - $version = 'present', - $package = undef, - $java_alternative = undef, - $java_alternative_path = undef -) { - include java::params - - validate_re($version, 'present|installed|latest|^[.+_0-9a-zA-Z:-]+$') - - if has_key($java::params::java, $distribution) { - $default_package_name = $java::params::java[$distribution]['package'] - $default_alternative = $java::params::java[$distribution]['alternative'] - $default_alternative_path = $java::params::java[$distribution]['alternative_path'] - $java_home = $java::params::java[$distribution]['java_home'] - } else { - fail("Java distribution ${distribution} is not supported.") - } - - $use_java_package_name = $package ? { - undef => $default_package_name, - default => $package, - } - - ## If $java_alternative is set, use that. - ## Elsif the DEFAULT package is being used, then use $default_alternative. - ## Else undef - $use_java_alternative = $java_alternative ? { - undef => $use_java_package_name ? { - $default_package_name => $default_alternative, - default => undef, - }, - default => $java_alternative, - } - - ## Same logic as $java_alternative above. - $use_java_alternative_path = $java_alternative_path ? { - undef => $use_java_package_name ? { - $default_package_name => $default_alternative_path, - default => undef, - }, - default => $java_alternative_path, - } - - $jre_flag = $use_java_package_name ? { - /headless/ => '--jre-headless', - default => '--jre' - } - - if $::osfamily == 'Debian' { - # Needed for update-java-alternatives - package { 'java-common': - ensure => present, - before => Class['java::config'], - } - } - - anchor { 'java::begin:': } - -> - package { 'java': - ensure => $version, - name => $use_java_package_name, - } - -> - class { 'java::config': } - -> anchor { 'java::end': } - -} diff --git a/puppet/modules/java/manifests/params.pp b/puppet/modules/java/manifests/params.pp deleted file mode 100644 index 985a62c..0000000 --- a/puppet/modules/java/manifests/params.pp +++ /dev/null @@ -1,172 +0,0 @@ -# Class: java::params -# -# This class builds a hash of JDK/JRE packages and (for Debian) -# alternatives. For wheezy/precise, we provide Oracle JDK/JRE -# options, even though those are not in the package repositories. -# -# For more info on how to package Oracle JDK/JRE, see the Debian wiki: -# http://wiki.debian.org/JavaPackage -# -# Because the alternatives system makes it very difficult to tell -# which Java alternative is enabled, we hard code the path to bin/java -# for the config class to test if it is enabled. -class java::params { - - case $::osfamily { - 'RedHat': { - case $::operatingsystem { - 'RedHat', 'CentOS', 'OracleLinux', 'Scientific', 'OEL': { - if (versioncmp($::operatingsystemrelease, '5.0') < 0) { - $jdk_package = 'java-1.6.0-sun-devel' - $jre_package = 'java-1.6.0-sun' - } - elsif (versioncmp($::operatingsystemrelease, '6.3') < 0) { - $jdk_package = 'java-1.6.0-openjdk-devel' - $jre_package = 'java-1.6.0-openjdk' - } - else { - $jdk_package = 'java-1.7.0-openjdk-devel' - $jre_package = 'java-1.7.0-openjdk' - } - } - 'Fedora': { - if (versioncmp($::operatingsystemrelease, '21') < 0) { - $jdk_package = 'java-1.7.0-openjdk-devel' - $jre_package = 'java-1.7.0-openjdk' - } - else { - $jdk_package = 'java-1.8.0-openjdk-devel' - $jre_package = 'java-1.8.0-openjdk' - } - } - 'Amazon': { - $jdk_package = 'java-1.7.0-openjdk-devel' - $jre_package = 'java-1.7.0-openjdk' - } - default: { fail("unsupported os ${::operatingsystem}") } - } - $java = { - 'jdk' => { 'package' => $jdk_package, }, - 'jre' => { 'package' => $jre_package, }, - } - } - 'Debian': { - case $::lsbdistcodename { - 'lenny', 'squeeze', 'lucid', 'natty': { - $java = { - 'jdk' => { - 'package' => 'openjdk-6-jdk', - 'alternative' => "java-6-openjdk-${::architecture}", - 'alternative_path' => '/usr/lib/jvm/java-6-openjdk/jre/bin/java', - 'java_home' => '/usr/lib/jvm/java-6-openjdk/jre/', - }, - 'jre' => { - 'package' => 'openjdk-6-jre-headless', - 'alternative' => "java-6-openjdk-${::architecture}", - 'alternative_path' => '/usr/lib/jvm/java-6-openjdk/jre/bin/java', - 'java_home' => '/usr/lib/jvm/java-6-openjdk/jre/', - }, - 'sun-jre' => { - 'package' => 'sun-java6-jre', - 'alternative' => 'java-6-sun', - 'alternative_path' => '/usr/lib/jvm/java-6-sun/jre/bin/java', - 'java_home' => '/usr/lib/jvm/java-6-sun/jre/', - }, - 'sun-jdk' => { - 'package' => 'sun-java6-jdk', - 'alternative' => 'java-6-sun', - 'alternative_path' => '/usr/lib/jvm/java-6-sun/jre/bin/java', - 'java_home' => '/usr/lib/jvm/java-6-sun/jre/', - }, - } - } - 'wheezy', 'jessie', 'precise','quantal','raring','saucy', 'trusty', 'utopic': { - $java = { - 'jdk' => { - 'package' => 'openjdk-7-jdk', - 'alternative' => "java-1.7.0-openjdk-${::architecture}", - 'alternative_path' => "/usr/lib/jvm/java-1.7.0-openjdk-${::architecture}/bin/java", - 'java_home' => "/usr/lib/jvm/java-1.7.0-openjdk-${::architecture}/", - }, - 'jre' => { - 'package' => 'openjdk-7-jre-headless', - 'alternative' => "java-1.7.0-openjdk-${::architecture}", - 'alternative_path' => "/usr/lib/jvm/java-1.7.0-openjdk-${::architecture}/bin/java", - 'java_home' => "/usr/lib/jvm/java-1.7.0-openjdk-${::architecture}/", - }, - 'oracle-jre' => { - 'package' => 'oracle-j2re1.7', - 'alternative' => 'j2re1.7-oracle', - 'alternative_path' => '/usr/lib/jvm/j2re1.7-oracle/bin/java', - 'java_home' => '/usr/lib/jvm/j2re1.7-oracle/', - }, - 'oracle-jdk' => { - 'package' => 'oracle-j2sdk1.7', - 'alternative' => 'j2sdk1.7-oracle', - 'alternative_path' => '/usr/lib/jvm/j2sdk1.7-oracle/jre/bin/java', - 'java_home' => '/usr/lib/jvm/j2sdk1.7-oracle/jre/', - }, - } - } - 'vivid': { - $java = { - 'jdk' => { - 'package' => 'openjdk-8-jdk', - 'alternative' => "java-1.8.0-openjdk-${::architecture}", - 'alternative_path' => "/usr/lib/jvm/java-1.8.0-openjdk-${::architecture}/bin/java", - 'java_home' => "/usr/lib/jvm/java-1.8.0-openjdk-${::architecture}/", - }, - 'jre' => { - 'package' => 'openjdk-8-jre-headless', - 'alternative' => "java-1.8.0-openjdk-${::architecture}", - 'alternative_path' => "/usr/lib/jvm/java-1.8.0-openjdk-${::architecture}/bin/java", - 'java_home' => "/usr/lib/jvm/java-1.8.0-openjdk-${::architecture}/", - } - } - } - default: { fail("unsupported release ${::lsbdistcodename}") } - } - } - 'OpenBSD': { - $java = { - 'jdk' => { 'package' => 'jdk', }, - 'jre' => { 'package' => 'jre', }, - } - } - 'Solaris': { - $java = { - 'jdk' => { 'package' => 'developer/java/jdk-7', }, - 'jre' => { 'package' => 'runtime/java/jre-7', }, - } - } - 'Suse': { - case $::operatingsystem { - 'SLES': { - case $::operatingsystemmajrelease{ - default: { - $jdk_package = 'java-1_6_0-ibm-devel' - $jre_package = 'java-1_6_0-ibm' - } - '12': { - $jdk_package = 'java-1_7_0-openjdk-devel' - $jre_package = 'java-1_7_0-openjdk' - } - } - } - 'OpenSuSE': { - $jdk_package = 'java-1_7_0-openjdk-devel' - $jre_package = 'java-1_7_0-openjdk' - } - default: { - $jdk_package = 'java-1_6_0-ibm-devel' - $jre_package = 'java-1_6_0-ibm' - } - } - $java = { - 'jdk' => { 'package' => $jdk_package, }, - 'jre' => { 'package' => $jre_package, }, - } - } - default: { fail("unsupported platform ${::osfamily}") } - } -} diff --git a/puppet/modules/java/metadata.json b/puppet/modules/java/metadata.json deleted file mode 100644 index b583726..0000000 --- a/puppet/modules/java/metadata.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "name": "puppetlabs-java", - "version": "1.4.2", - "author": "puppetlabs", - "summary": "Installs the correct Java package on various platforms.", - "license": "Apache-2.0", - "source": "git://github.com/puppetlabs/puppetlabs-java", - "project_page": "https://github.com/puppetlabs/puppetlabs-java", - "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", - "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":">= 2.4.0 < 5.0.0"} - ], - "operatingsystem_support": [ - { - "operatingsystem": "RedHat", - "operatingsystemrelease": [ - "5", - "6", - "7" - ] - }, - { - "operatingsystem": "CentOS", - "operatingsystemrelease": [ - "5", - "6", - "7" - ] - }, - { - "operatingsystem": "OracleLinux", - "operatingsystemrelease": [ - "6", - "7" - ] - }, - { - "operatingsystem": "Scientific", - "operatingsystemrelease": [ - "5", - "6" - ] - }, - { - "operatingsystem": "Fedora", - "operatingsystemrelease": [ - "20", - "21", - "22" - ] - }, - { - "operatingsystem": "Debian", - "operatingsystemrelease": [ - "6", - "7" - ] - }, - { - "operatingsystem": "Ubuntu", - "operatingsystemrelease": [ - "10.04", - "12.04", - "14.04" - ] - }, - { - "operatingsystem": "SLES", - "operatingsystemrelease": [ - "11 SP1", - "12" - ] - }, - { - "operatingsystem": "Solaris", - "operatingsystemrelease": [ - "11" - ] - } - ], - "requirements": [ - { - "name": "pe", - "version_requirement": ">= 3.0.0 < 2015.3.0" - }, - { - "name": "puppet", - "version_requirement": ">= 3.0.0 < 5.0.0" - } - ] -} diff --git a/puppet/modules/java/spec/acceptance/install_spec.rb b/puppet/modules/java/spec/acceptance/install_spec.rb deleted file mode 100644 index cd6364f..0000000 --- a/puppet/modules/java/spec/acceptance/install_spec.rb +++ /dev/null @@ -1,219 +0,0 @@ -require 'spec_helper_acceptance' - -#RedHat, CentOS, Scientific, Oracle prior to 5.0 : Sun Java JDK/JRE 1.6 -#RedHat, CentOS, Scientific, Oracle 5.0 < x < 6.3 : OpenJDK Java JDK/JRE 1.6 -#RedHat, CentOS, Scientific, Oracle after 6.3 : OpenJDK Java JDK/JRE 1.7 -#Debian 5/6 & Ubuntu 10.04/11.04 : OpenJDK Java JDK/JRE 1.6 or Sun Java JDK/JRE 1.6 -#Debian 7/Jesse & Ubuntu 12.04 - 14.04 : OpenJDK Java JDK/JRE 1.7 or Oracle Java JDK/JRE 1.6 -#Solaris (what versions?) : Java JDK/JRE 1.7 -#OpenSuSE : OpenJDK Java JDK/JRE 1.7 -#SLES : IBM Java JDK/JRE 1.6 - -# C14677 -# C14678 -# C14679 -# C14680 -# C14681 -# C14682 -# C14684 -# C14687 -# C14692 -# C14696 -# C14697 -# C14700 check on solaris 11 -# C14701 check on sles 11 -# C14703 -# C14723 Where is oracle linux 5? -# C14724 Where is oracle linux 5? -# C14771 Where is redhat 7? Centos 7? -describe "installing java", :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do - describe "jre" do - it 'should install jre' do - pp = <<-EOS - class { 'java': - distribution => 'jre', - } - EOS - - # With the version of java that ships with pe on debian wheezy, update-alternatives - # throws an error on the first run due to missing alternative for policytool. It still - # updates the alternatives for java - if fact('operatingsystem') == 'Debian' and fact('lsbdistcodename') == 'wheezy' - apply_manifest(pp) - else - apply_manifest(pp, :catch_failures => true) - end - apply_manifest(pp, :catch_changes => true) - end - end - describe "jdk" do - it 'should install jdk' do - pp = <<-EOS - class { 'java': } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - end - end -end -# C14686 -describe 'sun', :if => (fact('operatingsystem') == 'Debian' and fact('operatingsystemrelease').match(/(5|6)/)) do - before :all do - pp = <<-EOS - file_line { 'non-free source': - path => '/etc/apt/sources.list', - match => "deb http://osmirror.delivery.puppetlabs.net/debian/ ${::lsbdistcodename} main", - line => "deb http://osmirror.delivery.puppetlabs.net/debian/ ${::lsbdistcodename} main non-free", - } - EOS - apply_manifest(pp) - shell('apt-get update') - shell('echo "sun-java6-jdk shared/accepted-sun-dlj-v1-1 select true" | debconf-set-selections') - shell('echo "sun-java6-jre shared/accepted-sun-dlj-v1-1 select true" | debconf-set-selections') - end - describe 'jre' do - it 'should install sun-jre' do - pp = <<-EOS - class { 'java': - distribution => 'sun-jre', - } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - end - end - describe 'jdk' do - it 'should install sun-jdk' do - pp = <<-EOS - class { 'java': - distribution => 'sun-jdk', - } - EOS - - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - end - end -end - -# C14704 -# C14705 -# C15006 -describe 'oracle', :if => ( - (fact('operatingsystem') == 'Debian') and (fact('operatingsystemrelease').match(/^7/)) or - (fact('operatingsystem') == 'Ubuntu') and (fact('operatingsystemrelease').match(/^12\.04/)) or - (fact('operatingsystem') == 'Ubuntu') and (fact('operatingsystemrelease').match(/^14\.04/)) -) do - # not supported - # The package is not available from any sources, but if a customer - # custom-builds the package using java-package and adds it to a local - # repository, that is the intention of this version ability - describe 'jre' do - it 'should install oracle-jre' do - pp = <<-EOS - class { 'java': - distribution => 'oracle-jre', - } - EOS - - apply_manifest(pp, :expect_failures => true) - end - end - describe 'jdk' do - it 'should install oracle-jdk' do - pp = <<-EOS - class { 'java': - distribution => 'oracle-jdk', - } - EOS - - apply_manifest(pp, :expect_failures => true) - end - end -end - -describe 'failure cases' do - # C14711 - it 'should fail to install java with an incorrect version' do - pp = <<-EOS - class { 'java': - version => '14.5', - } - EOS - - apply_manifest(pp, :expect_failures => true) - end - - # C14712 - it 'should fail to install java with a blank version' do - pp = <<-EOS - class { 'java': - version => '', - } - EOS - - apply_manifest(pp, :expect_failures => true) - end - - # C14713 - it 'should fail to install java with an incorrect distribution' do - pp = <<-EOS - class { 'java': - distribution => 'xyz', - } - EOS - - apply_manifest(pp, :expect_failures => true) - end - - # C14714 - it 'should fail to install java with a blank distribution' do - pp = <<-EOS - class { 'java': - distribution => '', - } - EOS - - apply_manifest(pp, :expect_failures => true) - end - - # C14715 - it 'should fail to install java with an incorrect package' do - pp = <<-EOS - class { 'java': - package => 'xyz', - } - EOS - - apply_manifest(pp, :expect_failures => true) - end - # C14715 - it 'should fail to install java with an incorrect package' do - pp = <<-EOS - class { 'java': - package => 'xyz', - } - EOS - - apply_manifest(pp, :expect_failures => true) - end - # C14717 - # C14719 - # C14725 - it 'should fail on debian or RHEL when passed fake java_alternative and path' do - pp = <<-EOS - class { 'java': - java_alternative => 'whatever', - java_alternative_path => '/whatever', - } - EOS - - if fact('osfamily') == 'Debian' or fact('osfamily') == 'RedHat' - apply_manifest(pp, :expect_failures => true) - else - apply_manifest(pp, :catch_failures => true) - end - end -end diff --git a/puppet/modules/java/spec/acceptance/nodesets/centos-5-vcloud.yml b/puppet/modules/java/spec/acceptance/nodesets/centos-5-vcloud.yml deleted file mode 100644 index 377d0ee..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/centos-5-vcloud.yml +++ /dev/null @@ -1,15 +0,0 @@ -HOSTS: - 'centos-5-vcloud': - roles: - - master - platform: el-5-x86_64 - hypervisor: vcloud - template: centos-5-x86_64 -CONFIG: - type: foss - ssh: - keys: "~/.ssh/id_rsa-acceptance" - datastore: instance0 - folder: Delivery/Quality Assurance/Enterprise/Dynamic - resourcepool: delivery/Quality Assurance/Enterprise/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/puppet/modules/java/spec/acceptance/nodesets/centos-59-x64-pe.yml b/puppet/modules/java/spec/acceptance/nodesets/centos-59-x64-pe.yml deleted file mode 100644 index 3a6470b..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/centos-59-x64-pe.yml +++ /dev/null @@ -1,12 +0,0 @@ -HOSTS: - centos-59-x64: - roles: - - master - - database - - console - platform: el-5-x86_64 - box : centos-59-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: pe diff --git a/puppet/modules/java/spec/acceptance/nodesets/centos-59-x64.yml b/puppet/modules/java/spec/acceptance/nodesets/centos-59-x64.yml deleted file mode 100644 index 2ad90b8..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/centos-59-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - centos-59-x64: - roles: - - master - platform: el-5-x86_64 - box : centos-59-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: git diff --git a/puppet/modules/java/spec/acceptance/nodesets/centos-6-vcloud.yml b/puppet/modules/java/spec/acceptance/nodesets/centos-6-vcloud.yml deleted file mode 100644 index ca9c1d3..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/centos-6-vcloud.yml +++ /dev/null @@ -1,15 +0,0 @@ -HOSTS: - 'centos-6-vcloud': - roles: - - master - platform: el-6-x86_64 - hypervisor: vcloud - template: centos-6-x86_64 -CONFIG: - type: foss - ssh: - keys: "~/.ssh/id_rsa-acceptance" - datastore: instance0 - folder: Delivery/Quality Assurance/Enterprise/Dynamic - resourcepool: delivery/Quality Assurance/Enterprise/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/puppet/modules/java/spec/acceptance/nodesets/centos-64-x64-fusion.yml b/puppet/modules/java/spec/acceptance/nodesets/centos-64-x64-fusion.yml deleted file mode 100644 index d516673..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/centos-64-x64-fusion.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - centos-64-x64: - roles: - - master - platform: el-6-x86_64 - box : centos-64-x64-fusion503-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-fusion503-nocm.box - hypervisor : fusion -CONFIG: - type: foss diff --git a/puppet/modules/java/spec/acceptance/nodesets/centos-64-x64-pe.yml b/puppet/modules/java/spec/acceptance/nodesets/centos-64-x64-pe.yml deleted file mode 100644 index 7d9242f..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/centos-64-x64-pe.yml +++ /dev/null @@ -1,12 +0,0 @@ -HOSTS: - centos-64-x64: - roles: - - master - - database - - dashboard - platform: el-6-x86_64 - box : centos-64-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: pe diff --git a/puppet/modules/java/spec/acceptance/nodesets/centos-64-x64.yml b/puppet/modules/java/spec/acceptance/nodesets/centos-64-x64.yml deleted file mode 100644 index 05540ed..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/centos-64-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - centos-64-x64: - roles: - - master - platform: el-6-x86_64 - box : centos-64-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: foss diff --git a/puppet/modules/java/spec/acceptance/nodesets/centos-65-x64.yml b/puppet/modules/java/spec/acceptance/nodesets/centos-65-x64.yml deleted file mode 100644 index 4e2cb80..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/centos-65-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - centos-65-x64: - roles: - - master - platform: el-6-x86_64 - box : centos-65-x64-vbox436-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box - hypervisor : vagrant -CONFIG: - type: foss diff --git a/puppet/modules/java/spec/acceptance/nodesets/centos-7-vcloud.yml b/puppet/modules/java/spec/acceptance/nodesets/centos-7-vcloud.yml deleted file mode 100644 index 1cecb6b..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/centos-7-vcloud.yml +++ /dev/null @@ -1,15 +0,0 @@ -HOSTS: - 'centos-7-vcloud': - roles: - - master - platform: el-7-x86_64 - hypervisor: vcloud - template: centos-7-x86_64 -CONFIG: - type: foss - ssh: - keys: "~/.ssh/id_rsa-acceptance" - datastore: instance0 - folder: Delivery/Quality Assurance/Enterprise/Dynamic - resourcepool: delivery/Quality Assurance/Enterprise/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/puppet/modules/java/spec/acceptance/nodesets/debian-6-vcloud.yml b/puppet/modules/java/spec/acceptance/nodesets/debian-6-vcloud.yml deleted file mode 100644 index 658c7d4..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/debian-6-vcloud.yml +++ /dev/null @@ -1,15 +0,0 @@ -HOSTS: - 'debian-6-amd64': - roles: - - master - platform: debian-6-amd64 - hypervisor: vcloud - template: debian-6-x86_64 -CONFIG: - type: foss - ssh: - keys: "~/.ssh/id_rsa-acceptance" - datastore: instance0 - folder: Delivery/Quality Assurance/Enterprise/Dynamic - resourcepool: delivery/Quality Assurance/Enterprise/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/puppet/modules/java/spec/acceptance/nodesets/debian-607-x64.yml b/puppet/modules/java/spec/acceptance/nodesets/debian-607-x64.yml deleted file mode 100644 index 4c8be42..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/debian-607-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - debian-607-x64: - roles: - - master - platform: debian-6-amd64 - box : debian-607-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: git diff --git a/puppet/modules/java/spec/acceptance/nodesets/debian-7-vcloud.yml b/puppet/modules/java/spec/acceptance/nodesets/debian-7-vcloud.yml deleted file mode 100644 index 9323473..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/debian-7-vcloud.yml +++ /dev/null @@ -1,15 +0,0 @@ -HOSTS: - 'debian-7-amd64': - roles: - - master - platform: debian-7-amd64 - hypervisor: vcloud - template: debian-7-x86_64 -CONFIG: - type: foss - ssh: - keys: "~/.ssh/id_rsa-acceptance" - datastore: instance0 - folder: Delivery/Quality Assurance/Enterprise/Dynamic - resourcepool: delivery/Quality Assurance/Enterprise/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/puppet/modules/java/spec/acceptance/nodesets/debian-70rc1-x64.yml b/puppet/modules/java/spec/acceptance/nodesets/debian-70rc1-x64.yml deleted file mode 100644 index 19181c1..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/debian-70rc1-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - debian-70rc1-x64: - roles: - - master - platform: debian-7-amd64 - box : debian-70rc1-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-70rc1-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: git diff --git a/puppet/modules/java/spec/acceptance/nodesets/default.yml b/puppet/modules/java/spec/acceptance/nodesets/default.yml deleted file mode 100644 index 05540ed..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/default.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - centos-64-x64: - roles: - - master - platform: el-6-x86_64 - box : centos-64-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: foss diff --git a/puppet/modules/java/spec/acceptance/nodesets/fedora-18-x64.yml b/puppet/modules/java/spec/acceptance/nodesets/fedora-18-x64.yml deleted file mode 100644 index 624b537..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/fedora-18-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - fedora-18-x64: - roles: - - master - platform: fedora-18-x86_64 - box : fedora-18-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/fedora-18-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: git diff --git a/puppet/modules/java/spec/acceptance/nodesets/redhat-7-vcloud.yml b/puppet/modules/java/spec/acceptance/nodesets/redhat-7-vcloud.yml deleted file mode 100644 index cf8f79a..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/redhat-7-vcloud.yml +++ /dev/null @@ -1,15 +0,0 @@ -HOSTS: - 'redhat-7-vcloud': - roles: - - master - platform: el-7-x86_64 - hypervisor: vcloud - template: redhat-7-x86_64 -CONFIG: - type: foss - ssh: - keys: "~/.ssh/id_rsa-acceptance" - datastore: instance0 - folder: Delivery/Quality Assurance/Enterprise/Dynamic - resourcepool: delivery/Quality Assurance/Enterprise/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/puppet/modules/java/spec/acceptance/nodesets/sles-11-vcloud.yml b/puppet/modules/java/spec/acceptance/nodesets/sles-11-vcloud.yml deleted file mode 100644 index 3f6114a..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/sles-11-vcloud.yml +++ /dev/null @@ -1,16 +0,0 @@ -HOSTS: - 'sles-11-vcloud': - roles: - - master - platform: sles-11-x86_64 - hypervisor: vcloud - template: sles-11-x86_64 - -CONFIG: - type: foss - ssh: - keys: "~/.ssh/id_rsa-acceptance" - datastore: instance0 - folder: Delivery/Quality Assurance/Enterprise/Dynamic - resourcepool: delivery/Quality Assurance/Enterprise/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/puppet/modules/java/spec/acceptance/nodesets/sles-11sp1-x64.yml b/puppet/modules/java/spec/acceptance/nodesets/sles-11sp1-x64.yml deleted file mode 100644 index 554c37a..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/sles-11sp1-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - sles-11sp1-x64: - roles: - - master - platform: sles-11-x86_64 - box : sles-11sp1-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/sles-11sp1-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: git diff --git a/puppet/modules/java/spec/acceptance/nodesets/solaris-11-vcloud.yml b/puppet/modules/java/spec/acceptance/nodesets/solaris-11-vcloud.yml deleted file mode 100644 index f3912ab..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/solaris-11-vcloud.yml +++ /dev/null @@ -1,15 +0,0 @@ -HOSTS: - 'solaris-11-vcloud': - roles: - - master - platform: solaris-11-i386 - hypervisor: vcloud - template: solaris-11-x86_64 -CONFIG: - type: foss - ssh: - keys: "~/.ssh/id_rsa-acceptance" - datastore: instance0 - folder: Delivery/Quality Assurance/Enterprise/Dynamic - resourcepool: delivery/Quality Assurance/Enterprise/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-1004-vcloud.yml b/puppet/modules/java/spec/acceptance/nodesets/ubuntu-1004-vcloud.yml deleted file mode 100644 index 19a918f..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-1004-vcloud.yml +++ /dev/null @@ -1,15 +0,0 @@ -HOSTS: - 'ubuntu-1004-amd64': - roles: - - master - platform: ubuntu-10.04-amd64 - hypervisor: vcloud - template: ubuntu-1004-x86_64 -CONFIG: - type: foss - ssh: - keys: "~/.ssh/id_rsa-acceptance" - datastore: instance0 - folder: Delivery/Quality Assurance/Enterprise/Dynamic - resourcepool: delivery/Quality Assurance/Enterprise/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-1404-vcloud.yml b/puppet/modules/java/spec/acceptance/nodesets/ubuntu-1404-vcloud.yml deleted file mode 100644 index d84b18e..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-1404-vcloud.yml +++ /dev/null @@ -1,15 +0,0 @@ -HOSTS: - 'ubuntu-1404-amd64': - roles: - - master - platform: ubuntu-14.04-amd64 - hypervisor: vcloud - template: ubuntu-1404-x86_64 -CONFIG: - type: foss - ssh: - keys: "~/.ssh/id_rsa-acceptance" - datastore: instance0 - folder: Delivery/Quality Assurance/Enterprise/Dynamic - resourcepool: delivery/Quality Assurance/Enterprise/Dynamic - pooling_api: http://vcloud.delivery.puppetlabs.net/ diff --git a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml b/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml deleted file mode 100644 index 5ca1514..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - ubuntu-server-10044-x64: - roles: - - master - platform: ubuntu-10.04-amd64 - box : ubuntu-server-10044-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: foss diff --git a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml b/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml deleted file mode 100644 index d065b30..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - ubuntu-server-12042-x64: - roles: - - master - platform: ubuntu-12.04-amd64 - box : ubuntu-server-12042-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: foss diff --git a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml deleted file mode 100644 index cba1cd0..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - ubuntu-server-1404-x64: - roles: - - master - platform: ubuntu-14.04-amd64 - box : puppetlabs/ubuntu-14.04-64-nocm - box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm - hypervisor : vagrant -CONFIG: - log_level : debug - type: git diff --git a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-1504-x64.yml b/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-1504-x64.yml deleted file mode 100644 index ee3f024..0000000 --- a/puppet/modules/java/spec/acceptance/nodesets/ubuntu-server-1504-x64.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - ubuntu-server-1504-x64: - roles: - - master - platform: ubuntu-15.04-amd64 - box : puppetlabs/ubuntu-15.04-64-nocm - box_url : https://vagrantcloud.com/puppetlabs/ubuntu-15.04-64-nocm - hypervisor : vagrant -CONFIG: - log_level : debug - type: git diff --git a/puppet/modules/java/spec/classes/java_spec.rb b/puppet/modules/java/spec/classes/java_spec.rb deleted file mode 100644 index d44bedb..0000000 --- a/puppet/modules/java/spec/classes/java_spec.rb +++ /dev/null @@ -1,211 +0,0 @@ -require 'spec_helper' - -describe 'java', :type => :class do - - context 'select openjdk for Centos 5.8' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Centos', :operatingsystemrelease => '5.8'} } - it { should contain_package('java').with_name('java-1.6.0-openjdk-devel') } - end - - context 'select openjdk for Centos 6.3' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Centos', :operatingsystemrelease => '6.3'} } - it { should contain_package('java').with_name('java-1.7.0-openjdk-devel') } - end - - context 'select openjdk for Centos 6.2' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Centos', :operatingsystemrelease => '6.2'} } - it { should contain_package('java').with_name('java-1.6.0-openjdk-devel') } - it { should_not contain_exec('update-java-alternatives') } - end - - context 'select Oracle JRE with alternatives for Centos 6.3' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Centos', :operatingsystemrelease => '6.3'} } - let(:params) { { 'package' => 'jre', 'java_alternative' => '/usr/bin/java', 'java_alternative_path' => '/usr/java/jre1.7.0_67/bin/java'} } - it { should contain_package('java').with_name('jre') } - it { should contain_exec('create-java-alternatives').with_command('alternatives --install /usr/bin/java java /usr/java/jre1.7.0_67/bin/java 20000') } - it { should contain_exec('update-java-alternatives').with_command('alternatives --set java /usr/java/jre1.7.0_67/bin/java') } - end - - context 'select openjdk for Fedora 20' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Fedora', :operatingsystemrelease => '20'} } - it { should contain_package('java').with_name('java-1.7.0-openjdk-devel') } - end - - context 'select openjdk for Fedora 21' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Fedora', :operatingsystemrelease => '21'} } - it { should contain_package('java').with_name('java-1.8.0-openjdk-devel') } - end - - context 'select passed value for Fedora 20' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Fedora', :operatingsystemrelease => '20'} } - let(:params) { { 'distribution' => 'jre' } } - it { should contain_package('java').with_name('java-1.7.0-openjdk') } - end - - context 'select passed value for Fedora 21' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Fedora', :operatingsystemrelease => '21'} } - let(:params) { { 'distribution' => 'jre' } } - it { should contain_package('java').with_name('java-1.8.0-openjdk') } - end - - context 'select passed value for Centos 5.3' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Centos', :operatingsystemrelease => '5.3'} } - let(:params) { { 'package' => 'jdk' } } - it { should contain_package('java').with_name('jdk') } - it { should_not contain_exec('update-java-alternatives') } - end - - context 'select default for Centos 5.3' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Centos', :operatingsystemrelease => '5.3'} } - it { should contain_package('java').with_name('java-1.6.0-openjdk-devel') } - it { should_not contain_exec('update-java-alternatives') } - end - - context 'select default for Debian Wheezy' do - let(:facts) { {:osfamily => 'Debian', :operatingsystem => 'Debian', :lsbdistcodename => 'wheezy', :operatingsystemrelease => '7.1', :architecture => 'amd64',} } - it { should contain_package('java').with_name('openjdk-7-jdk') } - it { should contain_exec('update-java-alternatives').with_command('update-java-alternatives --set java-1.7.0-openjdk-amd64 --jre') } - end - - context 'select Oracle JRE for Debian Wheezy' do - let(:facts) { {:osfamily => 'Debian', :operatingsystem => 'Debian', :lsbdistcodename => 'wheezy', :operatingsystemrelease => '7.1', :architecture => 'amd64',} } - let(:params) { { 'distribution' => 'oracle-jre' } } - it { should contain_package('java').with_name('oracle-j2re1.7') } - it { should contain_exec('update-java-alternatives').with_command('update-java-alternatives --set j2re1.7-oracle --jre') } - end - - context 'select OpenJDK JRE for Debian Wheezy' do - let(:facts) { {:osfamily => 'Debian', :operatingsystem => 'Debian', :lsbdistcodename => 'wheezy', :operatingsystemrelease => '7.1', :architecture => 'amd64',} } - let(:params) { { 'distribution' => 'jre' } } - it { should contain_package('java').with_name('openjdk-7-jre-headless') } - it { should contain_exec('update-java-alternatives').with_command('update-java-alternatives --set java-1.7.0-openjdk-amd64 --jre-headless') } - end - - context 'select default for Debian Squeeze' do - let(:facts) { {:osfamily => 'Debian', :operatingsystem => 'Debian', :lsbdistcodename => 'squeeze', :operatingsystemrelease => '6.0.5', :architecture => 'amd64',} } - it { should contain_package('java').with_name('openjdk-6-jdk') } - it { should contain_exec('update-java-alternatives').with_command('update-java-alternatives --set java-6-openjdk-amd64 --jre') } - end - - context 'select Oracle JRE for Debian Squeeze' do - let(:facts) { {:osfamily => 'Debian', :operatingsystem => 'Debian', :lsbdistcodename => 'squeeze', :operatingsystemrelease => '6.0.5', :architecture => 'amd64',} } - let(:params) { { 'distribution' => 'sun-jre', } } - it { should contain_package('java').with_name('sun-java6-jre') } - it { should contain_exec('update-java-alternatives').with_command('update-java-alternatives --set java-6-sun --jre') } - end - - context 'select OpenJDK JRE for Debian Squeeze' do - let(:facts) { {:osfamily => 'Debian', :operatingsystem => 'Debian', :lsbdistcodename => 'squeeze', :operatingsystemrelease => '6.0.5', :architecture => 'amd64',} } - let(:params) { { 'distribution' => 'jre', } } - it { should contain_package('java').with_name('openjdk-6-jre-headless') } - it { should contain_exec('update-java-alternatives').with_command('update-java-alternatives --set java-6-openjdk-amd64 --jre-headless') } - end - - context 'select random alternative for Debian Wheezy' do - let(:facts) { {:osfamily => 'Debian', :operatingsystem => 'Debian', :lsbdistcodename => 'wheezy', :operatingsystemrelease => '7.1', :architecture => 'amd64',} } - let(:params) { { 'java_alternative' => 'bananafish' } } - it { should contain_package('java').with_name('openjdk-7-jdk') } - it { should contain_exec('update-java-alternatives').with_command('update-java-alternatives --set bananafish --jre') } - end - - context 'select jdk for Ubuntu Vivid (15.04)' do - let(:facts) { {:osfamily => 'Debian', :operatingsystem => 'Ubuntu', :lsbdistcodename => 'vivid', :operatingsystemrelease => '15.04', :architecture => 'amd64',} } - let(:params) { { 'distribution' => 'jdk' } } - it { should contain_package('java').with_name('openjdk-8-jdk') } - end - - context 'select jre for Ubuntu Vivid (15.04)' do - let(:facts) { {:osfamily => 'Debian', :operatingsystem => 'Ubuntu', :lsbdistcodename => 'vivid', :operatingsystemrelease => '15.04', :architecture => 'amd64',} } - let(:params) { { 'distribution' => 'jre' } } - it { should contain_package('java').with_name('openjdk-8-jre-headless') } - end - - context 'select openjdk for Amazon Linux' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Amazon', :operatingsystemrelease => '3.4.43-43.43.amzn1.x86_64'} } - it { should contain_package('java').with_name('java-1.7.0-openjdk-devel') } - end - - context 'select passed value for Amazon Linux' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Amazon', :operatingsystemrelease => '5.3.4.43-43.43.amzn1.x86_64'} } - let(:params) { { 'distribution' => 'jre' } } - it { should contain_package('java').with_name('java-1.7.0-openjdk') } - end - - context 'select openjdk for Oracle Linux' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'OracleLinux', :operatingsystemrelease => '6.4'} } - it { should contain_package('java').with_name('java-1.7.0-openjdk-devel') } - end - - context 'select openjdk for Oracle Linux 6.2' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'OracleLinux', :operatingsystemrelease => '6.2'} } - it { should contain_package('java').with_name('java-1.6.0-openjdk-devel') } - end - - context 'select passed value for Oracle Linux' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'OracleLinux', :operatingsystemrelease => '6.3'} } - let(:params) { { 'distribution' => 'jre' } } - it { should contain_package('java').with_name('java-1.7.0-openjdk') } - end - - context 'select passed value for Scientific Linux' do - let(:facts) { {:osfamily => 'RedHat', :operatingsystem => 'Scientific', :operatingsystemrelease => '6.4'} } - let(:params) { { 'distribution' => 'jre' } } - it { should contain_package('java').with_name('java-1.7.0-openjdk') } - end - - context 'select default for OpenSUSE 12.3' do - let(:facts) { {:osfamily => 'Suse', :operatingsystem => 'OpenSUSE', :operatingsystemrelease => '12.3'}} - it { should contain_package('java').with_name('java-1_7_0-openjdk-devel')} - end - - context 'select jdk for OpenBSD' do - let(:facts) { {:osfamily => 'OpenBSD'} } - it { should contain_package('java').with_name('jdk') } - end - - context 'select jre for OpenBSD' do - let(:facts) { {:osfamily => 'OpenBSD'} } - let(:params) { { 'distribution' => 'jre' } } - it { should contain_package('java').with_name('jre') } - end - - describe 'incompatible OSs' do - [ - { - # C14706 - :osfamily => 'windows', - :operatingsystem => 'windows', - :operatingsystemrelease => '8.1', - }, - { - # C14707 - :osfamily => 'Darwin', - :operatingsystem => 'Darwin', - :operatingsystemrelease => '13.3.0', - }, - { - # C14708 - :osfamily => 'AIX', - :operatingsystem => 'AIX', - :operatingsystemrelease => '7100-02-00-000', - }, - { - # C14708 - :osfamily => 'AIX', - :operatingsystem => 'AIX', - :operatingsystemrelease => '6100-07-04-1216', - }, - { - # C14708 - :osfamily => 'AIX', - :operatingsystem => 'AIX', - :operatingsystemrelease => '5300-12-01-1016', - }, - ].each do |facts| - let(:facts) { facts } - it "should fail on #{facts[:operatingsystem]} #{facts[:operatingsystemrelease]}" do - expect { catalogue }.to raise_error Puppet::Error, /unsupported platform/ - end - end - end -end diff --git a/puppet/modules/java/spec/spec.opts b/puppet/modules/java/spec/spec.opts deleted file mode 100644 index 91cd642..0000000 --- a/puppet/modules/java/spec/spec.opts +++ /dev/null @@ -1,6 +0,0 @@ ---format -s ---colour ---loadby -mtime ---backtrace diff --git a/puppet/modules/java/spec/spec_helper.rb b/puppet/modules/java/spec/spec_helper.rb deleted file mode 100644 index 145dcf5..0000000 --- a/puppet/modules/java/spec/spec_helper.rb +++ /dev/null @@ -1,6 +0,0 @@ -require 'puppetlabs_spec_helper/module_spec_helper' - -RSpec.configure do |c| - # declare an exclusion filter for the tests using with_env on facter 1.6, as the function is not available on 1.6 - c.filter_run_excluding :with_env => true if Facter.version =~ /^1\.6\./ -end diff --git a/puppet/modules/java/spec/spec_helper_acceptance.rb b/puppet/modules/java/spec/spec_helper_acceptance.rb deleted file mode 100644 index 7b378af..0000000 --- a/puppet/modules/java/spec/spec_helper_acceptance.rb +++ /dev/null @@ -1,43 +0,0 @@ -require 'beaker-rspec' -require 'beaker/puppet_install_helper' - -run_puppet_install_helper - -UNSUPPORTED_PLATFORMS = [ "Darwin", "windows" ] - -unless ENV["RS_PROVISION"] == "no" or ENV["BEAKER_provision"] == "no" - hosts.each do |host| - if host['platform'] =~ /sles-1/i || host['platform'] =~ /solaris-1/i - get_stdlib = <<-stdlib - package{'wget':} - exec{'download': - command => "wget -P /root/ https://forgeapi.puppetlabs.com/v3/files/puppetlabs-stdlib-4.3.2.tar.gz --no-check-certificate", - path => ['/opt/csw/bin/','/usr/bin/'] - } - stdlib - apply_manifest_on(host, get_stdlib) - # have to use force otherwise it checks ssl cert even though it is a local file - on host, puppet('module install /root/puppetlabs-stdlib-4.3.2.tar.gz --force') - else - on host, puppet("module install puppetlabs-stdlib") - # For test support - on host, puppet("module install puppetlabs-apt") - end - end -end - -RSpec.configure do |c| - # Project root - proj_root = File.expand_path(File.join(File.dirname(__FILE__), "..")) - - # Readable test descriptions - c.formatter = :documentation - - # Configure all nodes in nodeset - c.before :suite do - # Install module - hosts.each do |host| - copy_module_to(host, :source => proj_root, :module_name => "java") - end - end -end diff --git a/puppet/modules/java/spec/unit/facter/java_major_version_spec.rb b/puppet/modules/java/spec/unit/facter/java_major_version_spec.rb deleted file mode 100644 index 5c83081..0000000 --- a/puppet/modules/java/spec/unit/facter/java_major_version_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -require "spec_helper" - -describe Facter::Util::Fact do - before { - Facter.clear - } - - describe "java_major_version" do - context 'returns major version when java_version fact present' do - before :each do - Facter.fact(:java_version).stubs(:value).returns('1.7.0_71') - end - it do - expect(Facter.fact(:java_major_version).value).to eq("7") - end - end - - context 'returns nil when java not present' do - before :each do - Facter.fact(:java_version).stubs(:value).returns(nil) - end - it do - expect(Facter.fact(:java_major_version).value).to be_nil - end - end - end -end diff --git a/puppet/modules/java/spec/unit/facter/java_patch_level_spec.rb b/puppet/modules/java/spec/unit/facter/java_patch_level_spec.rb deleted file mode 100644 index 5f99eab..0000000 --- a/puppet/modules/java/spec/unit/facter/java_patch_level_spec.rb +++ /dev/null @@ -1,31 +0,0 @@ -require "spec_helper" - -describe Facter::Util::Fact do - before { - Facter.clear - } - - describe "java_patch_level" do - context "if java is installed" do - context 'returns java patch version extracted from java_version fact' do - before :each do - Facter.fact(:java_version).stubs(:value).returns('1.7.0_71') - end - it do - expect(Facter.fact(:java_patch_level).value).to eq("71") - end - end - end - - context "if java is not installed" do - context 'returns nil' do - before :each do - Facter.fact(:java_version).stubs(:value).returns(nil) - end - it do - expect(Facter.fact(:java_patch_level).value).to be_nil - end - end - end - end -end diff --git a/puppet/modules/java/spec/unit/facter/java_version_spec.rb b/puppet/modules/java/spec/unit/facter/java_version_spec.rb deleted file mode 100644 index 7d1aa1b..0000000 --- a/puppet/modules/java/spec/unit/facter/java_version_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -require "spec_helper" - -describe Facter::Util::Fact do - before { - Facter.clear - } - - describe "java_version" do - context 'returns java version when java present' do - context 'on OpenBSD', :with_env => true do - before do - Facter.fact(:operatingsystem).stubs(:value).returns("OpenBSD") - end - let(:facts) { {:operatingsystem => 'OpenBSD'} } - it do - java_version_output = <<-EOS -openjdk version "1.7.0_71" -OpenJDK Runtime Environment (build 1.7.0_71-b14) -OpenJDK 64-Bit Server VM (build 24.71-b01, mixed mode) - EOS - Facter::Util::Resolution.expects(:which).with("java").returns('/usr/local/jdk-1.7.0/jre/bin/java') - Facter::Util::Resolution.expects(:exec).with("java -Xmx8m -version 2>&1").returns(java_version_output) - expect(Facter.value(:java_version)).to eq("1.7.0_71") - end - end - context 'on Darwin' do - before do - Facter.fact(:operatingsystem).stubs(:value).returns("Darwin") - end - let(:facts) { {:operatingsystem => 'Darwin'} } - it do - java_version_output = <<-EOS -java version "1.7.0_71" -Java(TM) SE Runtime Environment (build 1.7.0_71-b14) -Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode) - EOS - Facter::Util::Resolution.expects(:exec).with("/usr/libexec/java_home --failfast 2>&1").returns("/Library/Java/JavaVirtualMachines/jdk1.7.0_71.jdk/Contents/Home") - Facter::Util::Resolution.expects(:exec).with("java -Xmx8m -version 2>&1").returns(java_version_output) - Facter.value(:java_version).should == "1.7.0_71" - end - end - context 'on other systems' do - before do - Facter.fact(:operatingsystem).stubs(:value).returns("MyOS") - end - let(:facts) { {:operatingsystem => 'MyOS'} } - it do - java_version_output = <<-EOS -java version "1.7.0_71" -Java(TM) SE Runtime Environment (build 1.7.0_71-b14) -Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode) - EOS - Facter::Util::Resolution.expects(:exec).with("java -Xmx8m -version 2>&1").returns(java_version_output) - expect(Facter.value(:java_version)).to eq("1.7.0_71") - end - end - end - - context 'returns nil when java not present' do - context 'on OpenBSD', :with_env => true do - before do - Facter.fact(:operatingsystem).stubs(:value).returns("OpenBSD") - end - let(:facts) { {:operatingsystem => 'OpenBSD'} } - it do - Facter::Util::Resolution.stubs(:exec) - expect(Facter.value(:java_version)).to be_nil - end - end - context 'on Darwin' do - before do - Facter.fact(:operatingsystem).stubs(:value).returns("Darwin") - end - let(:facts) { {:operatingsystem => 'Darwin'} } - it do - Facter::Util::Resolution.expects(:exec).at_least(1).with("/usr/libexec/java_home --failfast 2>&1").returns('Unable to find any JVMs matching version "(null)".') - Facter.value(:java_version).should be_nil - end - end - context 'on other systems' do - before do - Facter.fact(:operatingsystem).stubs(:value).returns("MyOS") - end - let(:facts) { {:operatingsystem => 'MyOS'} } - it do - Facter::Util::Resolution.expects(:which).at_least(1).with("java").returns(false) - expect(Facter.value(:java_version)).to be_nil - end - end - end - end -end diff --git a/puppet/modules/java/tests/alternative.pp b/puppet/modules/java/tests/alternative.pp deleted file mode 100644 index f361db6..0000000 --- a/puppet/modules/java/tests/alternative.pp +++ /dev/null @@ -1,5 +0,0 @@ -class { 'java': - package => 'jdk-8u25-linux-x64', - java_alternative => 'jdk1.8.0_25', - java_alternative_path => '/usr/java/jdk1.8.0_25/jre/bin/java' -} diff --git a/puppet/modules/java/tests/init.pp b/puppet/modules/java/tests/init.pp deleted file mode 100644 index bdd923e..0000000 --- a/puppet/modules/java/tests/init.pp +++ /dev/null @@ -1,4 +0,0 @@ -class { 'java': - distribution => 'jdk', - version => 'latest', -} diff --git a/puppet/modules/joindin/files/joindin-ctokens b/puppet/modules/joindin/files/joindin-ctokens deleted file mode 100755 index 79df3dc..0000000 --- a/puppet/modules/joindin/files/joindin-ctokens +++ /dev/null @@ -1,111 +0,0 @@ -#!/bin/sh -# /etc/init.d/joindin-ctokens: ensure that /tmp/ctokens exists -### BEGIN INIT INFO -# Provides: joindin-ctokens -# Required-Start: $remote_fs -# Required-Stop: $remote_fs -# Default-Start: S -# Default-Stop: -### END INIT INFO - -set -e - -PATH=/usr/bin:/usr/sbin:/bin:/sbin -TMP_DIR=ctokens - -. /lib/lsb/init-functions -if [ -f /etc/default/rcS ]; then - . /etc/default/rcS -fi - -# create a directory in /tmp. -# assumes /tmp has a sticky bit set (or is only writeable by root) -set_up_dir () { - DIR="/tmp/$1" - - if [ "$VERBOSE" != no ]; then - log_progress_msg "$DIR" - fi - # if $DIR exists and isn't a directory, move it aside - if [ -e $DIR ] && ! [ -d $DIR ] || [ -h $DIR ]; then - mv "$DIR" "$(mktemp -d $DIR.XXXXXX)" - fi - - error=0 - while :; do - if [ $error -ne 0 ] ; then - # an error means the file-system is readonly or an attacker - # is doing evil things, distinguish by creating a temporary file, - # but give up after a while. - if [ $error -gt 5 ]; then - log_failure_msg "failed to set up $DIR" - return 1 - fi - fn="$(mktemp /tmp/testwriteable.XXXXXXXXXX)" || return 1 - rm "$fn" - fi - mkdir -p -m 01777 "$DIR" || { rm "$DIR" || error=$((error + 1)) ; continue ; } - case "$(LC_ALL=C stat -c '%u %g %a %F' "$DIR")" in - "0 0 1777 directory") - # everything as it is supposed to be - break - ;; - "0 0 "*" directory") - # as it is owned by root, cannot be replaced with a symlink: - chmod 01777 "$DIR" - break - ;; - *" directory") - # if the chown succeeds, the next step can change it savely - chown -h root:root "$DIR" || error=$((error + 1)) - continue - ;; - *) - log_failure_msg "failed to set up $DIR" - return 1 - ;; - esac - done - - return 0 -} - -do_status () { - if [ -d "/tmp/$TMP_DIR" ] ; then - return 0 - else - return 4 - fi -} - -case "$1" in - start) - if [ "$VERBOSE" != no ]; then - log_begin_msg "Setting up /tmp/$TMP_DIR directory..." - fi - set_up_dir "$TMP_DIR" - if [ "$VERBOSE" != no ]; then - log_end_msg 0 - fi - ;; - - restart|reload|force-reload) - : - ;; - - stop) - : - ;; - - status) - do_status - ;; - *) - log_success_msg "Usage: /etc/init.d/joindin-ctokens {start|stop|status|restart|reload|force-reload}" - exit 1 - ;; -esac - -exit 0 - -# vim:set ai et sts=2 sw=2 tw=0: diff --git a/puppet/modules/joindin/files/mailcatcher b/puppet/modules/joindin/files/mailcatcher deleted file mode 100755 index 018c9da..0000000 --- a/puppet/modules/joindin/files/mailcatcher +++ /dev/null @@ -1,152 +0,0 @@ -#! /bin/sh -### BEGIN INIT INFO -# Provides: mailcatcher -# Required-Start: $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Example initscript -# Description: This file should be used to construct scripts to be -# placed in /etc/init.d. -### END INIT INFO - -# Do NOT "set -e" - -# PATH should only include /usr/* if it runs after the mountnfs.sh script -PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/rvm/gems/ruby-1.9.3-p547/bin -DESC="Super simple SMTP server" -NAME=mailcatcher -DAEMON=/usr/local/rvm/wrappers/default/$NAME -DAEMON_ARGS=" --http-ip 0.0.0.0" -PIDFILE=/var/run/$NAME.pid -SCRIPTNAME=/etc/init.d/$NAME - -# Exit if the package is not installed -[ -x "$DAEMON" ] || exit 0 - -# Read configuration variable file if it is present -[ -r /etc/default/$NAME ] && . /etc/default/$NAME - -# Load the VERBOSE setting and other rcS variables -. /lib/init/vars.sh - -# Define LSB log_* functions. -# Depend on lsb-base (>= 3.2-14) to ensure that this file is present -# and status_of_proc is working. -. /lib/lsb/init-functions - -# -# Function that starts the daemon/service -# -do_start() -{ - # Return - # 0 if daemon has been started - # 1 if daemon was already running - # 2 if daemon could not be started - start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ - || return 1 - start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ - $DAEMON_ARGS \ - || return 2 - # Add code here, if necessary, that waits for the process to be ready - # to handle requests from services started subsequently which depend - # on this one. As a last resort, sleep for some time. - - # Create the PIDFILE - pidof mailcatcher >> $PIDFILE -} - -# -# Function that stops the daemon/service -# -do_stop() -{ - # Return - # 0 if daemon has been stopped - # 1 if daemon was already stopped - # 2 if daemon could not be stopped - # other if a failure occurred - - if [ -f "$PIDFILE" ] - then - kill `cat $PIDFILE` - rm -f $PIDFILE - return 0 - else - return 1 - fi -} - -# -# Function that sends a SIGHUP to the daemon/service -# -do_reload() { - # - # If the daemon can reload its configuration without - # restarting (for example, when it is sent a SIGHUP), - # then implement that here. - # - start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME - return 0 -} - -case "$1" in - start) - [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" - do_start - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - stop) - [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" - do_stop - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - status) - status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? - ;; - #reload|force-reload) - # - # If do_reload() is not implemented then leave this commented out - # and leave 'force-reload' as an alias for 'restart'. - # - #log_daemon_msg "Reloading $DESC" "$NAME" - #do_reload - #log_end_msg $? - #;; - restart|force-reload) - # - # If the "reload" option is implemented then remove the - # 'force-reload' alias - # - log_daemon_msg "Restarting $DESC" "$NAME" - do_stop - case "$?" in - 0|1) - do_start - case "$?" in - 0) log_end_msg 0 ;; - 1) log_end_msg 1 ;; # Old process is still running - *) log_end_msg 1 ;; # Failed to start - esac - ;; - *) - # Failed to stop - log_end_msg 1 - ;; - esac - ;; - *) - #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 - echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 - exit 3 - ;; -esac - -: diff --git a/puppet/modules/joindin/files/mailcatcher.ini b/puppet/modules/joindin/files/mailcatcher.ini deleted file mode 100644 index fa66e78..0000000 --- a/puppet/modules/joindin/files/mailcatcher.ini +++ /dev/null @@ -1 +0,0 @@ -sendmail_path = /usr/local/rvm/wrappers/default/catchmail diff --git a/puppet/modules/joindin/files/mysql_overrides.cnf b/puppet/modules/joindin/files/mysql_overrides.cnf deleted file mode 100644 index 3b3981b..0000000 --- a/puppet/modules/joindin/files/mysql_overrides.cnf +++ /dev/null @@ -1,9 +0,0 @@ - -[mysqld] - -# bind to 0.0.0.0 so that we can access MySQL from the outside -# Don't do this on a production system! -bind-address = 0.0.0.0 - -# Skip reverse DNS lookup of clients -skip-name-resolve diff --git a/puppet/modules/joindin/files/phpmyadmin.conf b/puppet/modules/joindin/files/phpmyadmin.conf deleted file mode 100644 index 6499568..0000000 --- a/puppet/modules/joindin/files/phpmyadmin.conf +++ /dev/null @@ -1,41 +0,0 @@ -# Maintained by Puppet. Do not modify! -# -# phpMyAdmin - Web based MySQL browser written in php -# -# Allows only localhost by default -# -# But allowing phpMyAdmin to anyone other than localhost should be considered -# dangerous unless properly secured by SSL - -Alias /phpMyAdmin /usr/share/phpmyadmin -Alias /phpmyadmin /usr/share/phpmyadmin - -# These directories do not require access over HTTP - taken from the original -# phpMyAdmin upstream tarball -# - - Order Deny,Allow - Deny from All - Allow from None - - - - Order Deny,Allow - Deny from All - Allow from None - - - - Order Deny,Allow - Deny from All - Allow from None - - -# This configuration prevents mod_security at phpMyAdmin directories from -# filtering SQL etc. This may break your mod_security implementation. -# -# -# -# SecRuleInheritance Off -# -# diff --git a/puppet/modules/joindin/files/tests/pdepend b/puppet/modules/joindin/files/tests/pdepend deleted file mode 100644 index 7c36aa5..0000000 Binary files a/puppet/modules/joindin/files/tests/pdepend and /dev/null differ diff --git a/puppet/modules/joindin/files/tests/phing.phar b/puppet/modules/joindin/files/tests/phing.phar deleted file mode 100644 index 222e63f..0000000 Binary files a/puppet/modules/joindin/files/tests/phing.phar and /dev/null differ diff --git a/puppet/modules/joindin/files/tests/phpcpd b/puppet/modules/joindin/files/tests/phpcpd deleted file mode 100644 index 9c6d58e..0000000 --- a/puppet/modules/joindin/files/tests/phpcpd +++ /dev/null @@ -1,16872 +0,0 @@ -#!/usr/bin/env php - '/php-timer/Timer.php', - 'sebastianbergmann\\finderfacade\\configuration' => '/finder-facade/Configuration.php', - 'sebastianbergmann\\finderfacade\\finderfacade' => '/finder-facade/FinderFacade.php', - 'sebastianbergmann\\phpcpd\\cli\\application' => '/src/CLI/Application.php', - 'sebastianbergmann\\phpcpd\\cli\\command' => '/src/CLI/Command.php', - 'sebastianbergmann\\phpcpd\\codeclone' => '/src/CodeClone.php', - 'sebastianbergmann\\phpcpd\\codeclonefile' => '/src/CodeCloneFile.php', - 'sebastianbergmann\\phpcpd\\codeclonemap' => '/src/CodeCloneMap.php', - 'sebastianbergmann\\phpcpd\\detector\\detector' => '/src/Detector/Detector.php', - 'sebastianbergmann\\phpcpd\\detector\\strategy\\abstractstrategy' => '/src/Detector/Strategy/Abstract.php', - 'sebastianbergmann\\phpcpd\\detector\\strategy\\defaultstrategy' => '/src/Detector/Strategy/Default.php', - 'sebastianbergmann\\phpcpd\\log\\abstractxmllogger' => '/src/Log/AbstractXmlLogger.php', - 'sebastianbergmann\\phpcpd\\log\\pmd' => '/src/Log/PMD.php', - 'sebastianbergmann\\phpcpd\\log\\text' => '/src/Log/Text.php', - 'sebastianbergmann\\version' => '/version/Version.php', - 'symfony\\component\\console\\application' => '/symfony/console/Symfony/Component/Console/Application.php', - 'symfony\\component\\console\\command\\command' => '/symfony/console/Symfony/Component/Console/Command/Command.php', - 'symfony\\component\\console\\command\\helpcommand' => '/symfony/console/Symfony/Component/Console/Command/HelpCommand.php', - 'symfony\\component\\console\\command\\listcommand' => '/symfony/console/Symfony/Component/Console/Command/ListCommand.php', - 'symfony\\component\\console\\consoleevents' => '/symfony/console/Symfony/Component/Console/ConsoleEvents.php', - 'symfony\\component\\console\\descriptor\\applicationdescription' => '/symfony/console/Symfony/Component/Console/Descriptor/ApplicationDescription.php', - 'symfony\\component\\console\\descriptor\\descriptor' => '/symfony/console/Symfony/Component/Console/Descriptor/Descriptor.php', - 'symfony\\component\\console\\descriptor\\descriptorinterface' => '/symfony/console/Symfony/Component/Console/Descriptor/DescriptorInterface.php', - 'symfony\\component\\console\\descriptor\\jsondescriptor' => '/symfony/console/Symfony/Component/Console/Descriptor/JsonDescriptor.php', - 'symfony\\component\\console\\descriptor\\markdowndescriptor' => '/symfony/console/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php', - 'symfony\\component\\console\\descriptor\\textdescriptor' => '/symfony/console/Symfony/Component/Console/Descriptor/TextDescriptor.php', - 'symfony\\component\\console\\descriptor\\xmldescriptor' => '/symfony/console/Symfony/Component/Console/Descriptor/XmlDescriptor.php', - 'symfony\\component\\console\\event\\consolecommandevent' => '/symfony/console/Symfony/Component/Console/Event/ConsoleCommandEvent.php', - 'symfony\\component\\console\\event\\consoleevent' => '/symfony/console/Symfony/Component/Console/Event/ConsoleEvent.php', - 'symfony\\component\\console\\event\\consoleexceptionevent' => '/symfony/console/Symfony/Component/Console/Event/ConsoleExceptionEvent.php', - 'symfony\\component\\console\\event\\consoleterminateevent' => '/symfony/console/Symfony/Component/Console/Event/ConsoleTerminateEvent.php', - 'symfony\\component\\console\\formatter\\outputformatter' => '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php', - 'symfony\\component\\console\\formatter\\outputformatterinterface' => '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterInterface.php', - 'symfony\\component\\console\\formatter\\outputformatterstyle' => '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyle.php', - 'symfony\\component\\console\\formatter\\outputformatterstyleinterface' => '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php', - 'symfony\\component\\console\\formatter\\outputformatterstylestack' => '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php', - 'symfony\\component\\console\\helper\\descriptorhelper' => '/symfony/console/Symfony/Component/Console/Helper/DescriptorHelper.php', - 'symfony\\component\\console\\helper\\dialoghelper' => '/symfony/console/Symfony/Component/Console/Helper/DialogHelper.php', - 'symfony\\component\\console\\helper\\formatterhelper' => '/symfony/console/Symfony/Component/Console/Helper/FormatterHelper.php', - 'symfony\\component\\console\\helper\\helper' => '/symfony/console/Symfony/Component/Console/Helper/Helper.php', - 'symfony\\component\\console\\helper\\helperinterface' => '/symfony/console/Symfony/Component/Console/Helper/HelperInterface.php', - 'symfony\\component\\console\\helper\\helperset' => '/symfony/console/Symfony/Component/Console/Helper/HelperSet.php', - 'symfony\\component\\console\\helper\\progresshelper' => '/symfony/console/Symfony/Component/Console/Helper/ProgressHelper.php', - 'symfony\\component\\console\\helper\\tablehelper' => '/symfony/console/Symfony/Component/Console/Helper/TableHelper.php', - 'symfony\\component\\console\\input\\argvinput' => '/symfony/console/Symfony/Component/Console/Input/ArgvInput.php', - 'symfony\\component\\console\\input\\arrayinput' => '/symfony/console/Symfony/Component/Console/Input/ArrayInput.php', - 'symfony\\component\\console\\input\\input' => '/symfony/console/Symfony/Component/Console/Input/Input.php', - 'symfony\\component\\console\\input\\inputargument' => '/symfony/console/Symfony/Component/Console/Input/InputArgument.php', - 'symfony\\component\\console\\input\\inputdefinition' => '/symfony/console/Symfony/Component/Console/Input/InputDefinition.php', - 'symfony\\component\\console\\input\\inputinterface' => '/symfony/console/Symfony/Component/Console/Input/InputInterface.php', - 'symfony\\component\\console\\input\\inputoption' => '/symfony/console/Symfony/Component/Console/Input/InputOption.php', - 'symfony\\component\\console\\input\\stringinput' => '/symfony/console/Symfony/Component/Console/Input/StringInput.php', - 'symfony\\component\\console\\output\\consoleoutput' => '/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php', - 'symfony\\component\\console\\output\\consoleoutputinterface' => '/symfony/console/Symfony/Component/Console/Output/ConsoleOutputInterface.php', - 'symfony\\component\\console\\output\\nulloutput' => '/symfony/console/Symfony/Component/Console/Output/NullOutput.php', - 'symfony\\component\\console\\output\\output' => '/symfony/console/Symfony/Component/Console/Output/Output.php', - 'symfony\\component\\console\\output\\outputinterface' => '/symfony/console/Symfony/Component/Console/Output/OutputInterface.php', - 'symfony\\component\\console\\output\\streamoutput' => '/symfony/console/Symfony/Component/Console/Output/StreamOutput.php', - 'symfony\\component\\console\\shell' => '/symfony/console/Symfony/Component/Console/Shell.php', - 'symfony\\component\\console\\tester\\applicationtester' => '/symfony/console/Symfony/Component/Console/Tester/ApplicationTester.php', - 'symfony\\component\\console\\tester\\commandtester' => '/symfony/console/Symfony/Component/Console/Tester/CommandTester.php', - 'symfony\\component\\finder\\adapter\\abstractadapter' => '/symfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php', - 'symfony\\component\\finder\\adapter\\abstractfindadapter' => '/symfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php', - 'symfony\\component\\finder\\adapter\\adapterinterface' => '/symfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php', - 'symfony\\component\\finder\\adapter\\bsdfindadapter' => '/symfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php', - 'symfony\\component\\finder\\adapter\\gnufindadapter' => '/symfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php', - 'symfony\\component\\finder\\adapter\\phpadapter' => '/symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php', - 'symfony\\component\\finder\\comparator\\comparator' => '/symfony/finder/Symfony/Component/Finder/Comparator/Comparator.php', - 'symfony\\component\\finder\\comparator\\datecomparator' => '/symfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php', - 'symfony\\component\\finder\\comparator\\numbercomparator' => '/symfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.php', - 'symfony\\component\\finder\\exception\\accessdeniedexception' => '/symfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php', - 'symfony\\component\\finder\\exception\\adapterfailureexception' => '/symfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php', - 'symfony\\component\\finder\\exception\\exceptioninterface' => '/symfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php', - 'symfony\\component\\finder\\exception\\operationnotpermitedexception' => '/symfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.php', - 'symfony\\component\\finder\\exception\\shellcommandfailureexception' => '/symfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php', - 'symfony\\component\\finder\\expression\\expression' => '/symfony/finder/Symfony/Component/Finder/Expression/Expression.php', - 'symfony\\component\\finder\\expression\\glob' => '/symfony/finder/Symfony/Component/Finder/Expression/Glob.php', - 'symfony\\component\\finder\\expression\\regex' => '/symfony/finder/Symfony/Component/Finder/Expression/Regex.php', - 'symfony\\component\\finder\\expression\\valueinterface' => '/symfony/finder/Symfony/Component/Finder/Expression/ValueInterface.php', - 'symfony\\component\\finder\\finder' => '/symfony/finder/Symfony/Component/Finder/Finder.php', - 'symfony\\component\\finder\\glob' => '/symfony/finder/Symfony/Component/Finder/Glob.php', - 'symfony\\component\\finder\\iterator\\customfilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php', - 'symfony\\component\\finder\\iterator\\daterangefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php', - 'symfony\\component\\finder\\iterator\\depthrangefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php', - 'symfony\\component\\finder\\iterator\\excludedirectoryfilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php', - 'symfony\\component\\finder\\iterator\\filecontentfilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php', - 'symfony\\component\\finder\\iterator\\filenamefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php', - 'symfony\\component\\finder\\iterator\\filepathsiterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php', - 'symfony\\component\\finder\\iterator\\filetypefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php', - 'symfony\\component\\finder\\iterator\\filteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php', - 'symfony\\component\\finder\\iterator\\multiplepcrefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php', - 'symfony\\component\\finder\\iterator\\pathfilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php', - 'symfony\\component\\finder\\iterator\\recursivedirectoryiterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php', - 'symfony\\component\\finder\\iterator\\sizerangefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php', - 'symfony\\component\\finder\\iterator\\sortableiterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.php', - 'symfony\\component\\finder\\shell\\command' => '/symfony/finder/Symfony/Component/Finder/Shell/Command.php', - 'symfony\\component\\finder\\shell\\shell' => '/symfony/finder/Symfony/Component/Finder/Shell/Shell.php', - 'symfony\\component\\finder\\splfileinfo' => '/symfony/finder/Symfony/Component/Finder/SplFileInfo.php', - 'theseer\\fdom\\fdomdocument' => '/fdomdocument/fDOMDocument.php', - 'theseer\\fdom\\fdomdocumentfragment' => '/fdomdocument/fDOMDocumentFragment.php', - 'theseer\\fdom\\fdomelement' => '/fdomdocument/fDOMElement.php', - 'theseer\\fdom\\fdomexception' => '/fdomdocument/fDOMException.php', - 'theseer\\fdom\\fdomnode' => '/fdomdocument/fDOMNode.php', - 'theseer\\fdom\\fdomxpath' => '/fdomdocument/fDOMXPath.php', - 'theseer\\fdom\\xpathquery' => '/fdomdocument/XPathQuery.php', - 'theseer\\fdom\\xpathqueryexception' => '/fdomdocument/XPathQueryException.php' - ); - } - - $class = strtolower($class); - - if (isset($classes[$class])) { - require 'phar://phpcpd-2.0.0.phar' . $classes[$class]; - } - } -); - -Phar::mapPhar('phpcpd-2.0.0.phar'); - -$application = new SebastianBergmann\PHPCPD\CLI\Application; -$application->run(); - -__HALT_COMPILER(); ?> -#$jphpcpd-2.0.0.pharversion/Version.php|R/-xsrc/CodeCloneMap.php>|R>zϴsrc/CodeCloneFile.phpU |RU tUsrc/Detector/Detector.php|RV '"src/Detector/Strategy/Abstract.php |R !src/Detector/Strategy/Default.phpJ|RJlsrc/Log/Text.php]|R]LҶsrc/Log/PMD.php|R#ssrc/Log/AbstractXmlLogger.php|R3|~src/CodeClone.phpu|Ru3sRsrc/CLI/Command.php|Rn?src/CLI/Application.php|RA]9symfony/finder/Symfony/Component/Finder/Shell/Command.php|Rz[@7symfony/finder/Symfony/Component/Finder/Shell/Shell.php|R2Gsymfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php|R)Lsymfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php|R UNsymfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php|RʽEsymfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.php |R jMsymfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php|Rils_Lsymfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php|RxPKsymfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php|R{^ǶOsymfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php |R 6sKsymfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpb|Rbn Fsymfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php -|R -ɔCsymfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php|R,GOsymfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php*|R*nIsymfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php|Rz"Ssymfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php|R߶Bsymfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php -|R -kABsymfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php -|R -}]>symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php{ -|R{ -9!2Gsymfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php)|R)QJDsymfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php |R Csymfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php|R 0symfony/finder/Symfony/Component/Finder/Glob.phpb |Rb g@M7symfony/finder/Symfony/Component/Finder/SplFileInfo.php|R59Gsymfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.php -|R -PEsymfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php|R Asymfony/finder/Symfony/Component/Finder/Comparator/Comparator.php -|R -|FzAsymfony/finder/Symfony/Component/Finder/Expression/Expression.php$ -|R$ -<symfony/finder/Symfony/Component/Finder/Expression/Regex.php|R[ǐ;symfony/finder/Symfony/Component/Finder/Expression/Glob.php|REEsymfony/finder/Symfony/Component/Finder/Expression/ValueInterface.phpH|RH"Ssymfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.php|RPKsymfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php|RcW޶Hsymfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php|R7Rsymfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php9|R9Msymfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php|R>@2symfony/finder/Symfony/Component/Finder/Finder.phpV|RV=symfony/console/Symfony/Component/Console/Command/Command.php>|R> uAsymfony/console/Symfony/Component/Console/Command/HelpCommand.php -|R -#Asymfony/console/Symfony/Component/Console/Command/ListCommand.phpV -|RV -7ȔCsymfony/console/Symfony/Component/Console/Descriptor/Descriptor.php> |R> {Lsymfony/console/Symfony/Component/Console/Descriptor/DescriptorInterface.php||R|Gsymfony/console/Symfony/Component/Console/Descriptor/TextDescriptor.php|R_F\Fsymfony/console/Symfony/Component/Console/Descriptor/XmlDescriptor.php!|R!(Osymfony/console/Symfony/Component/Console/Descriptor/ApplicationDescription.php |R sXGsymfony/console/Symfony/Component/Console/Descriptor/JsonDescriptor.php/|R/|,Ksymfony/console/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php|Rl9symfony/console/Symfony/Component/Console/Application.php|Rդw;symfony/console/Symfony/Component/Console/ConsoleEvents.php|R\0E;symfony/console/Symfony/Component/Console/Helper/Helper.php|RZ\>symfony/console/Symfony/Component/Console/Helper/HelperSet.phpv |Rv @symfony/console/Symfony/Component/Console/Helper/TableHelper.php)|R)" Dsymfony/console/Symfony/Component/Console/Helper/HelperInterface.php|Rz׶Csymfony/console/Symfony/Component/Console/Helper/ProgressHelper.php-|R-Ԭ;Esymfony/console/Symfony/Component/Console/Helper/DescriptorHelper.php |R կAsymfony/console/Symfony/Component/Console/Helper/DialogHelper.php?|R?Dsymfony/console/Symfony/Component/Console/Helper/FormatterHelper.php|RgseBsymfony/console/Symfony/Component/Console/Output/ConsoleOutput.php |R eAsymfony/console/Symfony/Component/Console/Output/StreamOutput.phpM |RM XzKsymfony/console/Symfony/Component/Console/Output/ConsoleOutputInterface.php|R:2p?symfony/console/Symfony/Component/Console/Output/NullOutput.php|RF$_;symfony/console/Symfony/Component/Console/Output/Output.php|RD{rDsymfony/console/Symfony/Component/Console/Output/OutputInterface.phpM |RM z3symfony/console/Symfony/Component/Console/Shell.phpF|RF_=symfony/console/Symfony/Component/Console/Input/ArgvInput.php)|R)Q?symfony/console/Symfony/Component/Console/Input/StringInput.php -|R -΂=Bsymfony/console/Symfony/Component/Console/Input/InputInterface.php&|R&o3޶?symfony/console/Symfony/Component/Console/Input/InputOption.phpV|RVOö9symfony/console/Symfony/Component/Console/Input/Input.php|R(Q/Asymfony/console/Symfony/Component/Console/Input/InputArgument.php |R '>symfony/console/Symfony/Component/Console/Input/ArrayInput.php%|R%pCsymfony/console/Symfony/Component/Console/Input/InputDefinition.php.|R.ʶPsymfony/console/Symfony/Component/Console/Formatter/OutputFormatterInterface.php|RJp˶Gsymfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php|R^Lsymfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyle.php |R ƩQsymfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php -|R -dBUsymfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php|R5@symfony/console/Symfony/Component/Console/Event/ConsoleEvent.php|R -Gsymfony/console/Symfony/Component/Console/Event/ConsoleCommandEvent.php|RuIsymfony/console/Symfony/Component/Console/Event/ConsoleTerminateEvent.php |R (Isymfony/console/Symfony/Component/Console/Event/ConsoleExceptionEvent.php;|R;4֍Bsymfony/console/Symfony/Component/Console/Tester/CommandTester.php |R ,ѶFsymfony/console/Symfony/Component/Console/Tester/ApplicationTester.phpY |RY A$ܶphp-timer/Timer.php6|R6#X6fdomdocument/fDOMException.php|R$fdomdocument/XPathQueryException.php|Rֶfdomdocument/fDOMDocument.phpP|RP'3%fdomdocument/fDOMDocumentFragment.php9 |R9 t%fdomdocument/fDOMElement.php,|R,uOfdomdocument/fDOMNode.phpK -|RK -A~ fdomdocument/XPathQuery.phpi|RifBfdomdocument/fDOMXPath.php|R@QͶfinder-facade/FinderFacade.php|RՍfinder-facade/Configuration.php{|R{r. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package Version - * @author Sebastian Bergmann - * @copyright 2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/version - * @since File available since Release 1.0.0 - */ - -namespace SebastianBergmann -{ - /** - * @package Version - * @author Sebastian Bergmann - * @copyright 2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/version - * @since Class available since Release 1.0.0 - */ - class Version - { - private $path; - private $release; - private $version; - - /** - * @param string $release - * @param string $path - */ - public function __construct($release, $path) - { - $this->release = $release; - $this->path = $path; - } - - /** - * @return string - */ - public function getVersion() - { - if ($this->version === NULL) { - if (count(explode('.', $this->release)) == 3) { - $this->version = $this->release; - } else { - $this->version = $this->release . '-dev'; - } - - $git = $this->getGitInformation($this->path); - - if ($git) { - if (count(explode('.', $this->release)) == 3) { - $this->version = $git; - } else { - $git = explode('-', $git); - - $this->version = $this->release . '-' . $git[2]; - } - } - } - - return $this->version; - } - - /** - * @param string $path - * @return boolean|string - */ - private function getGitInformation($path) - { - if (!$this->isGitRepository($path)) { - return FALSE; - } - - $dir = getcwd(); - chdir($path); - $result = exec('git describe --tags 2>&1', $output, $returnCode); - chdir($dir); - - if ($returnCode !== 0) { - return FALSE; - } - - return $result; - } - - /** - * @param string $path - * @return boolean - */ - private function isGitRepository($path) - { - if (is_dir($path . DIRECTORY_SEPARATOR . '.git')) { - return TRUE; - } - - $path = dirname($path); - - if (strlen($path) == strlen(dirname($path))) { - return FALSE; - } - - return $this->isGitRepository($path); - } - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phpcpd - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.1.0 - */ - -namespace SebastianBergmann\PHPCPD; - -use SebastianBergmann\PHPCPD\CodeClone; - -/** - * A map of exact clones. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phpcpd/tree - * @since Class available since Release 1.1.0 - */ -class CodeCloneMap implements \Countable, \Iterator -{ - /** - * @var CodeClone[] The clones in the clone map - */ - protected $clones = array(); - - /** - * @var CodeClone[] The clones in the clone map, stored by ID - */ - protected $clonesById = array(); - - /** - * @var integer Current position while iterating the clone map - */ - protected $position = 0; - - /** - * @var integer Number of duplicate lines in the clone map - */ - protected $numDuplicateLines = 0; - - /** - * @var integer Number of lines analyzed - */ - protected $numLines = 0; - - /** - * Adds a clone to the map. - * - * @param CodeClone $clone - */ - public function addClone(CodeClone $clone) - { - $id = $clone->getId(); - - if (!isset($this->clonesById[$id])) { - $this->clones[] = $clone; - $this->clonesById[$id] = $clone; - } else { - $existClone = $this->clonesById[$id]; - - foreach ($clone->getFiles() as $file) { - $existClone->addFile($file); - } - } - - $this->numDuplicateLines += $clone->getSize(); - } - - /** - * Returns the clones stored in this map. - * - * @return CodeClone[] - */ - public function getClones() - { - return $this->clones; - } - - /** - * Returns the percentage of duplicated code lines in the project. - * - * @return string - */ - public function getPercentage() - { - if ($this->numLines > 0) { - $percent = ($this->numDuplicateLines / $this->numLines) * 100; - } else { - $percent = 100; - } - - return sprintf('%01.2F%%', $percent); - } - - /** - * Returns the number of lines analyzed. - * - * @return integer - */ - public function getNumLines() - { - return $this->numLines; - } - - /** - * Sets the number of physical source code lines in the project. - * - * @param integer $numLines - */ - public function setNumLines($numLines) - { - $this->numLines = $numLines; - } - - /** - * Returns the number of clones stored in this map. - */ - public function count() - { - return count($this->clones); - } - - /** - * Rewinds the Iterator to the first element. - */ - public function rewind() - { - $this->position = 0; - } - - /** - * Checks if there is a current element after calls to rewind() or next(). - * - * @return boolean - */ - public function valid() - { - return $this->position < count($this->clones); - } - - /** - * Returns the key of the current element. - * - * @return integer - */ - public function key() - { - return $this->position; - } - - /** - * Returns the current element. - * - * @return CodeClone - */ - public function current() - { - return $this->clones[$this->position]; - } - - /** - * Moves forward to next element. - */ - public function next() - { - $this->position++; - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phpcpd - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.5.0 - */ -namespace SebastianBergmann\PHPCPD; - -/** - * Represents an exact code clone file. - * - * @author Alexander Kazakov - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phpcpd/tree - * @since Class available since Release 1.5.0 - */ -class CodeCloneFile -{ - /** - * @var string - */ - private $id; - - /** - * @var string - */ - private $name; - - /** - * @var integer - */ - private $startLine; - - /** - * @param string $name - * @param integer $startLine - */ - public function __construct($name, $startLine) - { - $this->name = $name; - $this->startLine = $startLine; - $this->id = $this->name . ':' . $this->startLine; - } - - /** - * @return string - */ - public function getId() - { - return $this->id; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * @return integer - */ - public function getStartLine() - { - return $this->startLine; - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phpcpd - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.0.0 - */ - -namespace SebastianBergmann\PHPCPD\Detector; - -use SebastianBergmann\PHPCPD\Detector\Strategy\AbstractStrategy; -use SebastianBergmann\PHPCPD\CodeCloneMap; -use Symfony\Component\Console\Helper\ProgressHelper; - -/** - * PHPCPD code analyser. - * - * @author Johann-Peter Hartmann - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phpcpd/tree - * @since Class available since Release 1.0.0 - */ -class Detector -{ - /** - * @var SebastianBergmann\PHPCPD\Detector\Strategy\AbstractStrategy - */ - protected $strategy; - - /** - * @var Symfony\Component\Console\Helper\ProgressHelper - */ - protected $progressHelper; - - /** - * Constructor. - * - * @param AbstractStrategy $strategy - * @since Method available since Release 1.3.0 - */ - public function __construct(AbstractStrategy $strategy, ProgressHelper $progressHelper = null) - { - $this->strategy = $strategy; - $this->progressHelper = $progressHelper; - } - - /** - * Copy & Paste Detection (CPD). - * - * @param Iterator|array $files List of files to process - * @param integer $minLines Minimum number of identical lines - * @param integer $minTokens Minimum number of identical tokens - * @param boolean $fuzzy - * @return CodeCloneMap Map of exact clones found in the list of files - */ - public function copyPasteDetection($files, $minLines = 5, $minTokens = 70, $fuzzy = false) - { - $result = new CodeCloneMap; - - foreach ($files as $file) { - $this->strategy->processFile( - $file, - $minLines, - $minTokens, - $result, - $fuzzy - ); - - if ($this->progressHelper !== null) { - $this->progressHelper->advance(); - } - } - - return $result; - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phpcpd - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.4.0 - */ - -namespace SebastianBergmann\PHPCPD\Detector\Strategy; - -use SebastianBergmann\PHPCPD\CodeCloneMap; - -/** - * Abstract base class for strategies to detect code clones. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phpcpd/tree - * @since Class available since Release 1.4.0 - */ -abstract class AbstractStrategy -{ - /** - * @var integer[] List of tokens to ignore - */ - protected $tokensIgnoreList = array( - T_INLINE_HTML => true, - T_COMMENT => true, - T_DOC_COMMENT => true, - T_OPEN_TAG => true, - T_OPEN_TAG_WITH_ECHO => true, - T_CLOSE_TAG => true, - T_WHITESPACE => true, - T_USE => true, - T_NS_SEPARATOR => true - ); - - /** - * @var string[] - */ - protected $hashes = array(); - - /** - * Copy & Paste Detection (CPD). - * - * @param string $file - * @param integer $minLines - * @param integer $minTokens - * @param CodeCloneMap $result - * @param boolean $fuzzy - */ - abstract public function processFile($file, $minLines, $minTokens, CodeCloneMap $result, $fuzzy = false); -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phpcpd - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.4.0 - */ - -namespace SebastianBergmann\PHPCPD\Detector\Strategy; - -use SebastianBergmann\PHPCPD\CodeClone; -use SebastianBergmann\PHPCPD\CodeCloneFile; -use SebastianBergmann\PHPCPD\CodeCloneMap; - -/** - * Default strategy for detecting code clones. - * - * @author Johann-Peter Hartmann - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phpcpd/tree - * @since Class available since Release 1.4.0 - */ -class DefaultStrategy extends AbstractStrategy -{ - /** - * Copy & Paste Detection (CPD). - * - * @param string $file - * @param integer $minLines - * @param integer $minTokens - * @param CodeCloneMap $result - * @param boolean $fuzzy - * @author Johann-Peter Hartmann - */ - public function processFile($file, $minLines, $minTokens, CodeCloneMap $result, $fuzzy = false) - { - $buffer = file_get_contents($file); - $currentTokenPositions = array(); - $currentTokenRealPositions = array(); - $currentSignature = ''; - $tokens = token_get_all($buffer); - $tokenNr = 0; - $lastTokenLine = 0; - - $result->setNumLines( - $result->getNumLines() + substr_count($buffer, "\n") - ); - - unset($buffer); - - foreach (array_keys($tokens) as $key) { - $token = $tokens[$key]; - - if (is_array($token)) { - if (!isset($this->tokensIgnoreList[$token[0]])) { - if ($tokenNr == 0) { - $currentTokenPositions[$tokenNr] = $token[2] - $lastTokenLine; - } else { - $currentTokenPositions[$tokenNr] = $currentTokenPositions[$tokenNr - 1] + - $token[2] - $lastTokenLine; - } - - $currentTokenRealPositions[$tokenNr++] = $token[2]; - - if ($fuzzy && $token[0] == T_VARIABLE) { - $token[1] = 'variable'; - } - - $currentSignature .= chr($token[0] & 255) . - pack('N*', crc32($token[1])); - } - - $lastTokenLine = $token[2]; - } - } - - $count = count($currentTokenPositions); - $firstLine = 0; - $firstRealLine = 0; - $found = false; - $tokenNr = 0; - - while ($tokenNr <= $count - $minTokens) { - $line = $currentTokenPositions[$tokenNr]; - $realLine = $currentTokenRealPositions[$tokenNr]; - - $hash = substr( - md5( - substr( - $currentSignature, - $tokenNr * 5, - $minTokens * 5 - ), - true - ), - 0, - 8 - ); - - if (isset($this->hashes[$hash])) { - $found = true; - - if ($firstLine === 0) { - $firstLine = $line; - $firstRealLine = $realLine; - $firstHash = $hash; - $firstToken = $tokenNr; - } - } else { - if ($found) { - $fileA = $this->hashes[$firstHash][0]; - $firstLineA = $this->hashes[$firstHash][1]; - $lastToken = ($tokenNr - 1) + $minTokens - 1; - $lastLine = $currentTokenPositions[$lastToken]; - $lastRealLine = $currentTokenRealPositions[$lastToken]; - $numLines = $lastLine + 1 - $firstLine; - $realNumLines = $lastRealLine +1 - $firstRealLine; - - if ($numLines >= $minLines && - ($fileA != $file || - $firstLineA != $firstRealLine)) { - $result->addClone( - new CodeClone( - new CodeCloneFile($fileA, $firstLineA), - new CodeCloneFile($file, $firstRealLine), - $realNumLines, - $lastToken + 1 - $firstToken - ) - ); - } - - $found = false; - $firstLine = 0; - } - - $this->hashes[$hash] = array($file, $realLine); - } - - $tokenNr++; - } - - if ($found) { - $fileA = $this->hashes[$firstHash][0]; - $firstLineA = $this->hashes[$firstHash][1]; - $lastToken = ($tokenNr - 1) + $minTokens - 1; - $lastLine = $currentTokenPositions[$lastToken]; - $lastRealLine = $currentTokenRealPositions[$lastToken]; - $numLines = $lastLine + 1 - $firstLine; - $realNumLines = $lastRealLine +1 - $firstRealLine; - - if ($numLines >= $minLines && - ($fileA != $file || $firstLineA != $firstRealLine)) { - $result->addClone( - new CodeClone( - new CodeCloneFile($fileA, $firstLineA), - new CodeCloneFile($file, $firstRealLine), - $realNumLines, - $lastToken + 1 - $firstToken - ) - ); - } - - $found = false; - } - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phpcpd - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 2.0.0 - */ - -namespace SebastianBergmann\PHPCPD\Log; - -use SebastianBergmann\PHPCPD\CodeCloneMap; -use SebastianBergmann\PHPCPD\CodeClone; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * A ResultPrinter for the TextUI. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phpcpd/tree - * @since Class available since Release 2.0.0 - */ -class Text -{ - /** - * Prints a result set from Detector::copyPasteDetection(). - * - * @param OutputInterface $output - * @param CodeCloneMap $clones - */ - public function printResult(OutputInterface $output, CodeCloneMap $clones) - { - $numClones = count($clones); - $verbose = $output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL; - - if ($numClones > 0) { - $buffer = ''; - $files = array(); - $lines = 0; - - foreach ($clones as $clone) { - foreach ($clone->getFiles() as $file) { - $filename = $file->getName(); - - if (!isset($files[$filename])) { - $files[$filename] = true; - } - } - - $lines += $clone->getSize() * (count($clone->getFiles()) - 1); - $buffer .= "\n -"; - - foreach ($clone->getFiles() as $file) { - $buffer .= sprintf( - "\r\t%s:%d-%d\n ", - $file->getName(), - $file->getStartLine(), - $file->getStartLine() + $clone->getSize() - ); - } - - if ($verbose) { - $buffer .= "\n" . $clone->getLines(' '); - } - } - - $output->write( - sprintf( - "Found %d exact clones with %d duplicated lines in %d files:\n%s", - $numClones, - $lines, - count($files), - $buffer - ) - ); - } - - $output->write( - sprintf( - "%s%s duplicated lines out of %d total lines of code.\n\n", - $numClones > 0 ? "\n" : '', - $clones->getPercentage(), - $clones->getNumLines() - ) - ); - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phpcpd - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.0.0 - */ - -namespace SebastianBergmann\PHPCPD\Log; - -use SebastianBergmann\PHPCPD\CodeCloneMap; - -/** - * Implementation of AbstractXmlLogger that writes in PMD-CPD format. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phpcpd/tree - * @since Class available since Release 1.0.0 - */ -class PMD extends AbstractXmlLogger -{ - /** - * Processes a list of clones. - * - * @param CodeCloneMap $clones - */ - public function processClones(CodeCloneMap $clones) - { - $cpd = $this->document->createElement('pmd-cpd'); - $this->document->appendChild($cpd); - - foreach ($clones as $clone) { - $duplication = $cpd->appendChild( - $this->document->createElement('duplication') - ); - - $duplication->setAttribute('lines', $clone->getSize()); - $duplication->setAttribute('tokens', $clone->getTokens()); - - foreach ($clone->getFiles() as $codeCloneFile) { - $file = $duplication->appendChild( - $this->document->createElement('file') - ); - - $file->setAttribute('path', $codeCloneFile->getName()); - $file->setAttribute('line', $codeCloneFile->getStartLine()); - - } - - $duplication->appendChild( - $this->document->createElement( - 'codefragment', - htmlspecialchars( - $this->convertToUtf8($clone->getLines()), - ENT_COMPAT, - 'UTF-8' - ) - ) - ); - } - - $this->flush(); - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phpcpd - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.0.0 - */ - -namespace SebastianBergmann\PHPCPD\Log; - -use SebastianBergmann\PHPCPD\CodeCloneMap; - -/** - * Base class for XML loggers. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phpcpd/tree - * @since Class available since Release 1.0.0 - */ -abstract class AbstractXmlLogger -{ - protected $document; - - /** - * Constructor. - * - * @param string $filename - */ - public function __construct($filename) - { - $this->document = new \DOMDocument('1.0', 'UTF-8'); - $this->document->formatOutput = true; - - $this->filename = $filename; - } - - /** - * Writes the XML document to the file. - */ - protected function flush() - { - file_put_contents($this->filename, $this->document->saveXML()); - } - - /** - * Converts a string to UTF-8 encoding. - * - * @param string $string - * @return string - */ - protected function convertToUtf8($string) - { - if (!$this->isUtf8($string)) { - if (function_exists('mb_convert_encoding')) { - $string = mb_convert_encoding($string, 'UTF-8'); - } else { - $string = utf8_encode($string); - } - } - - return $string; - } - - /** - * Checks a string for UTF-8 encoding. - * - * @param string $string - * @return boolean - */ - protected function isUtf8($string) - { - $length = strlen($string); - - for ($i = 0; $i < $length; $i++) { - if (ord($string[$i]) < 0x80) { - $n = 0; - } elseif ((ord($string[$i]) & 0xE0) == 0xC0) { - $n = 1; - } elseif ((ord($string[$i]) & 0xF0) == 0xE0) { - $n = 2; - } elseif ((ord($string[$i]) & 0xF0) == 0xF0) { - $n = 3; - } else { - return false; - } - - for ($j = 0; $j < $n; $j++) { - if ((++$i == $length) || ((ord($string[$i]) & 0xC0) != 0x80)) { - return false; - } - } - } - - return true; - } - - /** - * Processes a list of clones. - * - * @param CodeCloneMap $clones - */ - abstract public function processClones(CodeCloneMap $clones); -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phpcpd - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.1.0 - */ - -namespace SebastianBergmann\PHPCPD; - -use SebastianBergmann\PHPCPD\CodeCloneFile; - -/** - * Represents an exact code clone. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phpcpd/tree - * @since Class available since Release 1.1.0 - */ -class CodeClone -{ - /** - * @var integer Size of the clone (lines) - */ - private $size; - - /** - * @var integer Size of the clone (tokens) - */ - private $tokens; - - /** - * @var CodeCloneFile[] Files with this code clone - */ - private $files = array(); - - /** - * @var string Unique ID of Code Duplicate Fragment - */ - private $id; - - /** - * @var Lines of the clone - */ - private $lines = ''; - - /** - * Constructor. - * - * @param CodeCloneFile $fileA - * @param CodeCloneFile $fileB - * @param integer $size - * @param integer $tokens - */ - public function __construct(CodeCloneFile $fileA, CodeCloneFile $fileB, $size, $tokens) - { - $this->addFile($fileA); - $this->addFile($fileB); - - $this->size = $size; - $this->tokens = $tokens; - $this->id = md5($this->getLines()); - } - - /** - * Add file with clone - * - * @param CodeCloneFile $file - */ - public function addFile(CodeCloneFile $file) - { - $id = $file->getId(); - - if (!isset($this->files[$id])) { - $this->files[$id] = $file; - } - } - - /** - * Get files with clone - * - * @return CodeCloneFile[] - */ - public function getFiles() - { - return $this->files; - } - - /** - * Returns the lines of the clone. - * - * @param string $prefix - * @return string The lines of the clone - */ - public function getLines($prefix = '') - { - $file = current($this->files); - - if (empty($this->lines)) { - $lines = array_slice( - file($file->getName()), - $file->getStartLine() - 1, - $this->size - ); - - $indent = array(); - - foreach ($lines as &$line) { - $line = rtrim($line, " \t\0\x0B"); - $line = str_replace("\t", " ", $line); - $_indent = strlen($line) - strlen(ltrim($line)); - - if ($_indent > 1) { - $indent[] = $_indent; - } - } - - $indent = empty($indent) ? 0 : min($indent); - - if ($indent > 0) { - foreach ($lines as &$line) { - if (strlen($line > 1)) { - $line = $prefix . substr($line, $indent); - } - } - } - - $this->lines = join('', $lines); - } - - return $this->lines; - } - - /** - * @return string - */ - public function getId() - { - return $this->id; - } - - /** - * @return integer - */ - public function getSize() - { - return $this->size; - } - - /** - * @return integer - */ - public function getTokens() - { - return $this->tokens; - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phpcpd - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 2.0.0 - */ - -namespace SebastianBergmann\PHPCPD\CLI; - -use SebastianBergmann\PHPCPD\Detector\Detector; -use SebastianBergmann\PHPCPD\Detector\Strategy\DefaultStrategy; -use SebastianBergmann\PHPCPD\Log\PMD; -use SebastianBergmann\PHPCPD\Log\Text; -use SebastianBergmann\FinderFacade\FinderFacade; -use Symfony\Component\Console\Command\Command as AbstractCommand; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phpcpd/tree - * @since Class available since Release 2.0.0 - */ -class Command extends AbstractCommand -{ - /** - * Configures the current command. - */ - protected function configure() - { - $this->setName('phpcpd') - ->setDefinition( - array( - new InputArgument( - 'values', - InputArgument::IS_ARRAY - ) - ) - ) - ->addOption( - 'names', - null, - InputOption::VALUE_REQUIRED, - 'A comma-separated list of file names to check', - array('*.php') - ) - ->addOption( - 'names-exclude', - null, - InputOption::VALUE_REQUIRED, - 'A comma-separated list of file names to exclude', - array() - ) - ->addOption( - 'exclude', - null, - InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, - 'Exclude a directory from code analysis' - ) - ->addOption( - 'log-pmd', - null, - InputOption::VALUE_REQUIRED, - 'Write result in PMD-CPD XML format to file' - ) - ->addOption( - 'min-lines', - null, - InputOption::VALUE_REQUIRED, - 'Minimum number of identical lines', - 5 - ) - ->addOption( - 'min-tokens', - null, - InputOption::VALUE_REQUIRED, - 'Minimum number of identical tokens', - 70 - ) - ->addOption( - 'fuzzy', - null, - InputOption::VALUE_NONE, - 'Fuzz variable names' - ) - ->addOption( - 'progress', - null, - InputOption::VALUE_NONE, - 'Show progress bar' - ); - } - - /** - * Executes the current command. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * - * @return null|integer null or 0 if everything went fine, or an error code - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $finder = new FinderFacade( - $input->getArgument('values'), - $input->getOption('exclude'), - $this->handleCSVOption($input, 'names'), - $this->handleCSVOption($input, 'names-exclude') - ); - - $files = $finder->findFiles(); - - if (empty($files)) { - $output->writeln('No files found to scan'); - exit(1); - } - - $progressHelper = null; - - if ($input->getOption('progress')) { - $progressHelper = $this->getHelperSet()->get('progress'); - $progressHelper->start($output, count($files)); - } - - $strategy = new DefaultStrategy; - $detector = new Detector($strategy, $progressHelper); - $quiet = $output->getVerbosity() == OutputInterface::VERBOSITY_QUIET; - - $clones = $detector->copyPasteDetection( - $files, - $input->getOption('min-lines'), - $input->getOption('min-tokens'), - $input->getOption('fuzzy') - ); - - if ($input->getOption('progress')) { - $progressHelper->finish(); - $output->writeln(''); - } - - if (!$quiet) { - $printer = new Text; - $printer->printResult($output, $clones); - unset($printer); - } - - $logPmd = $input->getOption('log-pmd'); - - if ($logPmd) { - $pmd = new PMD($logPmd); - $pmd->processClones($clones); - unset($pmd); - } - - if (!$quiet) { - print \PHP_Timer::resourceUsage() . "\n"; - } - - if (count($clones) > 0) { - exit(1); - } - } - - /** - * @param Symfony\Component\Console\Input\InputOption $input - * @param string $option - * @return array - */ - private function handleCSVOption(InputInterface $input, $option) - { - $result = $input->getOption($option); - - if (!is_array($result)) { - $result = explode(',', $result); - array_map('trim', $result); - } - - return $result; - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phpcpd - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 2.0.0 - */ - -namespace SebastianBergmann\PHPCPD\CLI; - -use SebastianBergmann\Version; -use Symfony\Component\Console\Application as AbstractApplication; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\ArrayInput; - -/** - * TextUI frontend for PHPCPD. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phpcpd/tree - * @since Class available since Release 2.0.0 - */ -class Application extends AbstractApplication -{ - public function __construct() - { - $version = new Version('2.0.0', __DIR__); - parent::__construct('phpcpd', $version->getVersion()); - } - - /** - * Gets the name of the command based on input. - * - * @param InputInterface $input The input interface - * - * @return string The command name - */ - protected function getCommandName(InputInterface $input) - { - return 'phpcpd'; - } - - /** - * Gets the default commands that should always be available. - * - * @return array An array of default Command instances - */ - protected function getDefaultCommands() - { - $defaultCommands = parent::getDefaultCommands(); - - $defaultCommands[] = new Command; - - return $defaultCommands; - } - - /** - * Overridden so that the application doesn't expect the command - * name to be the first argument. - */ - public function getDefinition() - { - $inputDefinition = parent::getDefinition(); - $inputDefinition->setArguments(); - - return $inputDefinition; - } - - /** - * Runs the current application. - * - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * - * @return integer 0 if everything went fine, or an error code - */ - public function doRun(InputInterface $input, OutputInterface $output) - { - if (!$input->hasParameterOption('--quiet')) { - $output->write( - sprintf( - "phpcpd %s by Sebastian Bergmann.\n\n", - $this->getVersion() - ) - ); - } - - if ($input->hasParameterOption('--version') || - $input->hasParameterOption('-V')) { - exit; - } - - if (!$input->getFirstArgument()) { - $input = new ArrayInput(array('--help')); - } - - parent::doRun($input, $output); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Shell; - -/** - * @author Jean-François Simon - */ -class Command -{ - /** - * @var Command|null - */ - private $parent; - - /** - * @var array - */ - private $bits; - - /** - * @var array - */ - private $labels; - - /** - * @var \Closure|null - */ - private $errorHandler; - - /** - * Constructor. - * - * @param Command $parent Parent command - */ - public function __construct(Command $parent = null) - { - $this->parent = $parent; - $this->bits = array(); - $this->labels = array(); - } - - /** - * Returns command as string. - * - * @return string - */ - public function __toString() - { - return $this->join(); - } - - /** - * Creates a new Command instance. - * - * @param Command $parent Parent command - * - * @return Command New Command instance - */ - public static function create(Command $parent = null) - { - return new self($parent); - } - - /** - * Escapes special chars from input. - * - * @param string $input A string to escape - * - * @return string The escaped string - */ - public static function escape($input) - { - return escapeshellcmd($input); - } - - /** - * Quotes input. - * - * @param string $input An argument string - * - * @return string The quoted string - */ - public static function quote($input) - { - return escapeshellarg($input); - } - - /** - * Appends a string or a Command instance. - * - * @param string|Command $bit - * - * @return Command The current Command instance - */ - public function add($bit) - { - $this->bits[] = $bit; - - return $this; - } - - /** - * Prepends a string or a command instance. - * - * @param string|Command $bit - * - * @return Command The current Command instance - */ - public function top($bit) - { - array_unshift($this->bits, $bit); - - foreach ($this->labels as $label => $index) { - $this->labels[$label] += 1; - } - - return $this; - } - - /** - * Appends an argument, will be quoted. - * - * @param string $arg - * - * @return Command The current Command instance - */ - public function arg($arg) - { - $this->bits[] = self::quote($arg); - - return $this; - } - - /** - * Appends escaped special command chars. - * - * @param string $esc - * - * @return Command The current Command instance - */ - public function cmd($esc) - { - $this->bits[] = self::escape($esc); - - return $this; - } - - /** - * Inserts a labeled command to feed later. - * - * @param string $label The unique label - * - * @return Command The current Command instance - * - * @throws \RuntimeException If label already exists - */ - public function ins($label) - { - if (isset($this->labels[$label])) { - throw new \RuntimeException(sprintf('Label "%s" already exists.', $label)); - } - - $this->bits[] = self::create($this); - $this->labels[$label] = count($this->bits)-1; - - return $this->bits[$this->labels[$label]]; - } - - /** - * Retrieves a previously labeled command. - * - * @param string $label - * - * @return Command The labeled command - * - * @throws \RuntimeException - */ - public function get($label) - { - if (!isset($this->labels[$label])) { - throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label)); - } - - return $this->bits[$this->labels[$label]]; - } - - /** - * Returns parent command (if any). - * - * @return Command Parent command - * - * @throws \RuntimeException If command has no parent - */ - public function end() - { - if (null === $this->parent) { - throw new \RuntimeException('Calling end on root command doesn\'t make sense.'); - } - - return $this->parent; - } - - /** - * Counts bits stored in command. - * - * @return int The bits count - */ - public function length() - { - return count($this->bits); - } - - /** - * @param \Closure $errorHandler - * - * @return Command - */ - public function setErrorHandler(\Closure $errorHandler) - { - $this->errorHandler = $errorHandler; - - return $this; - } - - /** - * @return callable|null - */ - public function getErrorHandler() - { - return $this->errorHandler; - } - - /** - * Executes current command. - * - * @return array The command result - * - * @throws \RuntimeException - */ - public function execute() - { - if (null === $this->errorHandler) { - exec($this->join(), $output); - } else { - $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes); - $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY); - - if ($error = stream_get_contents($pipes[2])) { - call_user_func($this->errorHandler, $error); - } - - proc_close($process); - } - - return $output ?: array(); - } - - /** - * Joins bits. - * - * @return string - */ - public function join() - { - return implode(' ', array_filter( - array_map(function($bit) { - return $bit instanceof Command ? $bit->join() : ($bit ?: null); - }, $this->bits), - function($bit) { return null !== $bit; } - )); - } - - /** - * Insert a string or a Command instance before the bit at given position $index (index starts from 0). - * - * @param string|Command $bit - * @param integer $index - * - * @return Command The current Command instance - */ - public function addAtIndex($bit, $index) - { - array_splice($this->bits, $index, 0, $bit); - - return $this; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Shell; - -/** - * @author Jean-François Simon - */ -class Shell -{ - const TYPE_UNIX = 1; - const TYPE_DARWIN = 2; - const TYPE_CYGWIN = 3; - const TYPE_WINDOWS = 4; - const TYPE_BSD = 5; - - /** - * @var string|null - */ - private $type; - - /** - * Returns guessed OS type. - * - * @return int - */ - public function getType() - { - if (null === $this->type) { - $this->type = $this->guessType(); - } - - return $this->type; - } - - /** - * Tests if a command is available. - * - * @param string $command - * - * @return bool - */ - public function testCommand($command) - { - if (self::TYPE_WINDOWS === $this->type) { - // todo: find a way to test if windows command exists - return false; - } - - if (!function_exists('exec')) { - return false; - } - - // todo: find a better way (command could not be available) - exec('command -v '.$command, $output, $code); - - return 0 === $code && count($output) > 0; - } - - /** - * Guesses OS type. - * - * @return int - */ - private function guessType() - { - $os = strtolower(PHP_OS); - - if (false !== strpos($os, 'cygwin')) { - return self::TYPE_CYGWIN; - } - - if (false !== strpos($os, 'darwin')) { - return self::TYPE_DARWIN; - } - - if (false !== strpos($os, 'bsd')) { - return self::TYPE_BSD; - } - - if (0 === strpos($os, 'win')) { - return self::TYPE_WINDOWS; - } - - return self::TYPE_UNIX; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * PathFilterIterator filters files by path patterns (e.g. some/special/dir). - * - * @author Fabien Potencier - * @author Włodzimierz Gajda - */ -class PathFilterIterator extends MultiplePcreFilterIterator -{ - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $filename = $this->current()->getRelativePathname(); - - if (defined('PHP_WINDOWS_VERSION_MAJOR')) { - $filename = strtr($filename, '\\', '/'); - } - - // should at least not match one rule to exclude - foreach ($this->noMatchRegexps as $regex) { - if (preg_match($regex, $filename)) { - return false; - } - } - - // should at least match one rule - $match = true; - if ($this->matchRegexps) { - $match = false; - foreach ($this->matchRegexps as $regex) { - if (preg_match($regex, $filename)) { - return true; - } - } - } - - return $match; - } - - /** - * Converts strings to regexp. - * - * PCRE patterns are left unchanged. - * - * Default conversion: - * 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/' - * - * Use only / as directory separator (on Windows also). - * - * @param string $str Pattern: regexp or dirname. - * - * @return string regexp corresponding to a given string or regexp - */ - protected function toRegex($str) - { - return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Comparator\DateComparator; - -/** - * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates). - * - * @author Fabien Potencier - */ -class DateRangeFilterIterator extends FilterIterator -{ - private $comparators = array(); - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param DateComparator[] $comparators An array of DateComparator instances - */ - public function __construct(\Iterator $iterator, array $comparators) - { - $this->comparators = $comparators; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - - if (!$fileinfo->isFile()) { - return true; - } - - $filedate = $fileinfo->getMTime(); - foreach ($this->comparators as $compare) { - if (!$compare->test($filedate)) { - return false; - } - } - - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings). - * - * @author Fabien Potencier - * @author Włodzimierz Gajda - */ -class FilecontentFilterIterator extends MultiplePcreFilterIterator -{ - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - if (!$this->matchRegexps && !$this->noMatchRegexps) { - return true; - } - - $fileinfo = $this->current(); - - if ($fileinfo->isDir() || !$fileinfo->isReadable()) { - return false; - } - - $content = $fileinfo->getContents(); - if (!$content) { - return false; - } - - // should at least not match one rule to exclude - foreach ($this->noMatchRegexps as $regex) { - if (preg_match($regex, $content)) { - return false; - } - } - - // should at least match one rule - $match = true; - if ($this->matchRegexps) { - $match = false; - foreach ($this->matchRegexps as $regex) { - if (preg_match($regex, $content)) { - return true; - } - } - } - - return $match; - } - - /** - * Converts string to regexp if necessary. - * - * @param string $str Pattern: string or regexp - * - * @return string regexp corresponding to a given string or regexp - */ - protected function toRegex($str) - { - return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * SortableIterator applies a sort on a given Iterator. - * - * @author Fabien Potencier - */ -class SortableIterator implements \IteratorAggregate -{ - const SORT_BY_NAME = 1; - const SORT_BY_TYPE = 2; - const SORT_BY_ACCESSED_TIME = 3; - const SORT_BY_CHANGED_TIME = 4; - const SORT_BY_MODIFIED_TIME = 5; - - private $iterator; - private $sort; - - /** - * Constructor. - * - * @param \Traversable $iterator The Iterator to filter - * @param integer|callback $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) - * - * @throws \InvalidArgumentException - */ - public function __construct(\Traversable $iterator, $sort) - { - $this->iterator = $iterator; - - if (self::SORT_BY_NAME === $sort) { - $this->sort = function ($a, $b) { - return strcmp($a->getRealpath(), $b->getRealpath()); - }; - } elseif (self::SORT_BY_TYPE === $sort) { - $this->sort = function ($a, $b) { - if ($a->isDir() && $b->isFile()) { - return -1; - } elseif ($a->isFile() && $b->isDir()) { - return 1; - } - - return strcmp($a->getRealpath(), $b->getRealpath()); - }; - } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { - $this->sort = function ($a, $b) { - return ($a->getATime() > $b->getATime()); - }; - } elseif (self::SORT_BY_CHANGED_TIME === $sort) { - $this->sort = function ($a, $b) { - return ($a->getCTime() > $b->getCTime()); - }; - } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { - $this->sort = function ($a, $b) { - return ($a->getMTime() > $b->getMTime()); - }; - } elseif (is_callable($sort)) { - $this->sort = $sort; - } else { - throw new \InvalidArgumentException('The SortableIterator takes a PHP callback or a valid built-in sort algorithm as an argument.'); - } - } - - public function getIterator() - { - $array = iterator_to_array($this->iterator, true); - uasort($array, $this->sort); - - return new \ArrayIterator($array); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * DepthRangeFilterIterator limits the directory depth. - * - * @author Fabien Potencier - */ -class DepthRangeFilterIterator extends FilterIterator -{ - private $minDepth = 0; - - /** - * Constructor. - * - * @param \RecursiveIteratorIterator $iterator The Iterator to filter - * @param int $minDepth The min depth - * @param int $maxDepth The max depth - */ - public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX) - { - $this->minDepth = $minDepth; - $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - return $this->getInnerIterator()->getDepth() >= $this->minDepth; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Comparator\NumberComparator; - -/** - * SizeRangeFilterIterator filters out files that are not in the given size range. - * - * @author Fabien Potencier - */ -class SizeRangeFilterIterator extends FilterIterator -{ - private $comparators = array(); - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param NumberComparator[] $comparators An array of NumberComparator instances - */ - public function __construct(\Iterator $iterator, array $comparators) - { - $this->comparators = $comparators; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - if (!$fileinfo->isFile()) { - return true; - } - - $filesize = $fileinfo->getSize(); - foreach ($this->comparators as $compare) { - if (!$compare->test($filesize)) { - return false; - } - } - - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Expression\Expression; - -/** - * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string). - * - * @author Fabien Potencier - */ -class FilenameFilterIterator extends MultiplePcreFilterIterator -{ - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $filename = $this->current()->getFilename(); - - // should at least not match one rule to exclude - foreach ($this->noMatchRegexps as $regex) { - if (preg_match($regex, $filename)) { - return false; - } - } - - // should at least match one rule - $match = true; - if ($this->matchRegexps) { - $match = false; - foreach ($this->matchRegexps as $regex) { - if (preg_match($regex, $filename)) { - return true; - } - } - } - - return $match; - } - - /** - * Converts glob to regexp. - * - * PCRE patterns are left unchanged. - * Glob strings are transformed with Glob::toRegex(). - * - * @param string $str Pattern: glob or regexp - * - * @return string regexp corresponding to a given glob or regexp - */ - protected function toRegex($str) - { - return Expression::create($str)->getRegex()->render(); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Exception\AccessDeniedException; -use Symfony\Component\Finder\SplFileInfo; - -/** - * Extends the \RecursiveDirectoryIterator to support relative paths - * - * @author Victor Berchet - */ -class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator -{ - /** - * @var boolean - */ - private $ignoreUnreadableDirs; - - /** - * @var Boolean - */ - private $rewindable; - - /** - * Constructor. - * - * @param string $path - * @param int $flags - * @param boolean $ignoreUnreadableDirs - * - * @throws \RuntimeException - */ - public function __construct($path, $flags, $ignoreUnreadableDirs = false) - { - if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { - throw new \RuntimeException('This iterator only support returning current as fileinfo.'); - } - - parent::__construct($path, $flags); - $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; - } - - /** - * Return an instance of SplFileInfo with support for relative paths - * - * @return SplFileInfo File information - */ - public function current() - { - return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname()); - } - - /** - * @return \RecursiveIterator - * - * @throws AccessDeniedException - */ - public function getChildren() - { - try { - return parent::getChildren(); - } catch (\UnexpectedValueException $e) { - if ($this->ignoreUnreadableDirs) { - // If directory is unreadable and finder is set to ignore it, a fake empty content is returned. - return new \RecursiveArrayIterator(array()); - } else { - throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); - } - } - } - - /** - * Do nothing for non rewindable stream - */ - public function rewind() - { - if (false === $this->isRewindable()) { - return; - } - - // @see https://bugs.php.net/bug.php?id=49104 - parent::next(); - - parent::rewind(); - } - - /** - * Checks if the stream is rewindable. - * - * @return Boolean true when the stream is rewindable, false otherwise - */ - public function isRewindable() - { - if (null !== $this->rewindable) { - return $this->rewindable; - } - - if (false !== $stream = @opendir($this->getPath())) { - $infos = stream_get_meta_data($stream); - closedir($stream); - - if ($infos['seekable']) { - return $this->rewindable = true; - } - } - - return $this->rewindable = false; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * FileTypeFilterIterator only keeps files, directories, or both. - * - * @author Fabien Potencier - */ -class FileTypeFilterIterator extends FilterIterator -{ - const ONLY_FILES = 1; - const ONLY_DIRECTORIES = 2; - - private $mode; - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param integer $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) - */ - public function __construct(\Iterator $iterator, $mode) - { - $this->mode = $mode; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) { - return false; - } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) { - return false; - } - - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\SplFileInfo; - -/** - * Iterate over shell command result. - * - * @author Jean-François Simon - */ -class FilePathsIterator extends \ArrayIterator -{ - /** - * @var string - */ - private $baseDir; - - /** - * @var int - */ - private $baseDirLength; - - /** - * @var string - */ - private $subPath; - - /** - * @var string - */ - private $subPathname; - - /** - * @var SplFileInfo - */ - private $current; - - /** - * @param array $paths List of paths returned by shell command - * @param string $baseDir Base dir for relative path building - */ - public function __construct(array $paths, $baseDir) - { - $this->baseDir = $baseDir; - $this->baseDirLength = strlen($baseDir); - - parent::__construct($paths); - } - - /** - * @param string $name - * @param array $arguments - * - * @return mixed - */ - public function __call($name, array $arguments) - { - return call_user_func_array(array($this->current(), $name), $arguments); - } - - /** - * Return an instance of SplFileInfo with support for relative paths. - * - * @return SplFileInfo File information - */ - public function current() - { - return $this->current; - } - - /** - * @return string - */ - public function key() - { - return $this->current->getPathname(); - } - - public function next() - { - parent::next(); - $this->buildProperties(); - } - - public function rewind() - { - parent::rewind(); - $this->buildProperties(); - } - - /** - * @return string - */ - public function getSubPath() - { - return $this->subPath; - } - - /** - * @return string - */ - public function getSubPathname() - { - return $this->subPathname; - } - - private function buildProperties() - { - $absolutePath = parent::current(); - - if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) { - $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\'); - $dir = dirname($this->subPathname); - $this->subPath = '.' === $dir ? '' : $dir; - } else { - $this->subPath = $this->subPathname = ''; - } - - $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * This iterator just overrides the rewind method in order to correct a PHP bug. - * - * @see https://bugs.php.net/bug.php?id=49104 - * - * @author Alex Bogomazov - */ -abstract class FilterIterator extends \FilterIterator -{ - /** - * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after - * rewind in some cases. - * - * @see FilterIterator::rewind() - */ - public function rewind() - { - $iterator = $this; - while ($iterator instanceof \OuterIterator) { - $innerIterator = $iterator->getInnerIterator(); - - if ($innerIterator instanceof RecursiveDirectoryIterator) { - if ($innerIterator->isRewindable()) { - $innerIterator->next(); - $innerIterator->rewind(); - } - } elseif ($iterator->getInnerIterator() instanceof \FilesystemIterator) { - $iterator->getInnerIterator()->next(); - $iterator->getInnerIterator()->rewind(); - } - $iterator = $iterator->getInnerIterator(); - } - - parent::rewind(); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Expression\Expression; - -/** - * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings). - * - * @author Fabien Potencier - */ -abstract class MultiplePcreFilterIterator extends FilterIterator -{ - protected $matchRegexps; - protected $noMatchRegexps; - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param array $matchPatterns An array of patterns that need to match - * @param array $noMatchPatterns An array of patterns that need to not match - */ - public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) - { - $this->matchRegexps = array(); - foreach ($matchPatterns as $pattern) { - $this->matchRegexps[] = $this->toRegex($pattern); - } - - $this->noMatchRegexps = array(); - foreach ($noMatchPatterns as $pattern) { - $this->noMatchRegexps[] = $this->toRegex($pattern); - } - - parent::__construct($iterator); - } - - /** - * Checks whether the string is a regex. - * - * @param string $str - * - * @return Boolean Whether the given string is a regex - */ - protected function isRegex($str) - { - return Expression::create($str)->isRegex(); - } - - /** - * Converts string into regexp. - * - * @param string $str Pattern - * - * @return string regexp corresponding to a given string - */ - abstract protected function toRegex($str); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * CustomFilterIterator filters files by applying anonymous functions. - * - * The anonymous function receives a \SplFileInfo and must return false - * to remove files. - * - * @author Fabien Potencier - */ -class CustomFilterIterator extends FilterIterator -{ - private $filters = array(); - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param array $filters An array of PHP callbacks - * - * @throws \InvalidArgumentException - */ - public function __construct(\Iterator $iterator, array $filters) - { - foreach ($filters as $filter) { - if (!is_callable($filter)) { - throw new \InvalidArgumentException('Invalid PHP callback.'); - } - } - $this->filters = $filters; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - - foreach ($this->filters as $filter) { - if (false === call_user_func($filter, $fileinfo)) { - return false; - } - } - - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * ExcludeDirectoryFilterIterator filters out directories. - * - * @author Fabien Potencier - */ -class ExcludeDirectoryFilterIterator extends FilterIterator -{ - private $patterns; - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param array $directories An array of directories to exclude - */ - public function __construct(\Iterator $iterator, array $directories) - { - $this->patterns = array(); - foreach ($directories as $directory) { - $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#'; - } - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); - $path = strtr($path, '\\', '/'); - foreach ($this->patterns as $pattern) { - if (preg_match($pattern, $path)) { - return false; - } - } - - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -use Symfony\Component\Finder\Shell\Shell; -use Symfony\Component\Finder\Shell\Command; -use Symfony\Component\Finder\Iterator\SortableIterator; -use Symfony\Component\Finder\Expression\Expression; - -/** - * Shell engine implementation using BSD find command. - * - * @author Jean-François Simon - */ -class BsdFindAdapter extends AbstractFindAdapter -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'bsd_find'; - } - - /** - * {@inheritdoc} - */ - protected function canBeUsed() - { - return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed(); - } - - /** - * {@inheritdoc} - */ - protected function buildFormatSorting(Command $command, $sort) - { - switch ($sort) { - case SortableIterator::SORT_BY_NAME: - $command->ins('sort')->add('| sort'); - - return; - case SortableIterator::SORT_BY_TYPE: - $format = '%HT'; - break; - case SortableIterator::SORT_BY_ACCESSED_TIME: - $format = '%a'; - break; - case SortableIterator::SORT_BY_CHANGED_TIME: - $format = '%c'; - break; - case SortableIterator::SORT_BY_MODIFIED_TIME: - $format = '%m'; - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); - } - - $command - ->add('-print0 | xargs -0 stat -f') - ->arg($format.'%t%N') - ->add('| sort | cut -f 2'); - } - - /** - * {@inheritdoc} - */ - protected function buildFindCommand(Command $command, $dir) - { - parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1); - - return $command; - } - - /** - * {@inheritdoc} - */ - protected function buildContentFiltering(Command $command, array $contains, $not = false) - { - foreach ($contains as $contain) { - $expr = Expression::create($contain); - - // todo: avoid forking process for each $pattern by using multiple -e options - $command - ->add('| grep -v \'^$\'') - ->add('| xargs -I{} grep -I') - ->add($expr->isCaseSensitive() ? null : '-i') - ->add($not ? '-L' : '-l') - ->add('-Ee')->arg($expr->renderPattern()) - ->add('{}') - ; - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -use Symfony\Component\Finder\Shell\Shell; -use Symfony\Component\Finder\Shell\Command; -use Symfony\Component\Finder\Iterator\SortableIterator; -use Symfony\Component\Finder\Expression\Expression; - -/** - * Shell engine implementation using GNU find command. - * - * @author Jean-François Simon - */ -class GnuFindAdapter extends AbstractFindAdapter -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'gnu_find'; - } - - /** - * {@inheritdoc} - */ - protected function buildFormatSorting(Command $command, $sort) - { - switch ($sort) { - case SortableIterator::SORT_BY_NAME: - $command->ins('sort')->add('| sort'); - - return; - case SortableIterator::SORT_BY_TYPE: - $format = '%y'; - break; - case SortableIterator::SORT_BY_ACCESSED_TIME: - $format = '%A@'; - break; - case SortableIterator::SORT_BY_CHANGED_TIME: - $format = '%C@'; - break; - case SortableIterator::SORT_BY_MODIFIED_TIME: - $format = '%T@'; - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); - } - - $command - ->get('find') - ->add('-printf') - ->arg($format.' %h/%f\\n') - ->add('| sort | cut') - ->arg('-d ') - ->arg('-f2-') - ; - } - - /** - * {@inheritdoc} - */ - protected function canBeUsed() - { - return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed(); - } - - /** - * {@inheritdoc} - */ - protected function buildFindCommand(Command $command, $dir) - { - return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended'); - } - - /** - * {@inheritdoc} - */ - protected function buildContentFiltering(Command $command, array $contains, $not = false) - { - foreach ($contains as $contain) { - $expr = Expression::create($contain); - - // todo: avoid forking process for each $pattern by using multiple -e options - $command - ->add('| xargs -I{} -r grep -I') - ->add($expr->isCaseSensitive() ? null : '-i') - ->add($not ? '-L' : '-l') - ->add('-Ee')->arg($expr->renderPattern()) - ->add('{}') - ; - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -use Symfony\Component\Finder\Iterator; - -/** - * PHP finder engine implementation. - * - * @author Jean-François Simon - */ -class PhpAdapter extends AbstractAdapter -{ - /** - * {@inheritdoc} - */ - public function searchInDirectory($dir) - { - $flags = \RecursiveDirectoryIterator::SKIP_DOTS; - - if ($this->followLinks) { - $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; - } - - $iterator = new \RecursiveIteratorIterator( - new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs), - \RecursiveIteratorIterator::SELF_FIRST - ); - - if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) { - $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth); - } - - if ($this->mode) { - $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); - } - - if ($this->exclude) { - $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); - } - - if ($this->names || $this->notNames) { - $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); - } - - if ($this->contains || $this->notContains) { - $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); - } - - if ($this->sizes) { - $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes); - } - - if ($this->dates) { - $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates); - } - - if ($this->filters) { - $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); - } - - if ($this->sort) { - $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); - $iterator = $iteratorAggregate->getIterator(); - } - - if ($this->paths || $this->notPaths) { - $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths); - } - - return $iterator; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'php'; - } - - /** - * {@inheritdoc} - */ - protected function canBeUsed() - { - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -use Symfony\Component\Finder\Exception\AccessDeniedException; -use Symfony\Component\Finder\Iterator; -use Symfony\Component\Finder\Shell\Shell; -use Symfony\Component\Finder\Expression\Expression; -use Symfony\Component\Finder\Shell\Command; -use Symfony\Component\Finder\Iterator\SortableIterator; -use Symfony\Component\Finder\Comparator\NumberComparator; -use Symfony\Component\Finder\Comparator\DateComparator; - -/** - * Shell engine implementation using GNU find command. - * - * @author Jean-François Simon - */ -abstract class AbstractFindAdapter extends AbstractAdapter -{ - /** - * @var Shell - */ - protected $shell; - - /** - * Constructor. - */ - public function __construct() - { - $this->shell = new Shell(); - } - - /** - * {@inheritdoc} - */ - public function searchInDirectory($dir) - { - // having "/../" in path make find fail - $dir = realpath($dir); - - // searching directories containing or not containing strings leads to no result - if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) { - return new Iterator\FilePathsIterator(array(), $dir); - } - - $command = Command::create(); - $find = $this->buildFindCommand($command, $dir); - - if ($this->followLinks) { - $find->add('-follow'); - } - - $find->add('-mindepth')->add($this->minDepth + 1); - - if (PHP_INT_MAX !== $this->maxDepth) { - $find->add('-maxdepth')->add($this->maxDepth + 1); - } - - if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) { - $find->add('-type d'); - } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) { - $find->add('-type f'); - } - - $this->buildNamesFiltering($find, $this->names); - $this->buildNamesFiltering($find, $this->notNames, true); - $this->buildPathsFiltering($find, $dir, $this->paths); - $this->buildPathsFiltering($find, $dir, $this->notPaths, true); - $this->buildSizesFiltering($find, $this->sizes); - $this->buildDatesFiltering($find, $this->dates); - - $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs'); - $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut'); - - if ($useGrep && ($this->contains || $this->notContains)) { - $grep = $command->ins('grep'); - $this->buildContentFiltering($grep, $this->contains); - $this->buildContentFiltering($grep, $this->notContains, true); - } - - if ($useSort) { - $this->buildSorting($command, $this->sort); - } - - $command->setErrorHandler( - $this->ignoreUnreadableDirs - // If directory is unreadable and finder is set to ignore it, `stderr` is ignored. - ? function ($stderr) { return; } - : function ($stderr) { throw new AccessDeniedException($stderr); } - ); - - $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute()); - $iterator = new Iterator\FilePathsIterator($paths, $dir); - - if ($this->exclude) { - $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); - } - - if (!$useGrep && ($this->contains || $this->notContains)) { - $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); - } - - if ($this->filters) { - $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); - } - - if (!$useSort && $this->sort) { - $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); - $iterator = $iteratorAggregate->getIterator(); - } - - return $iterator; - } - - /** - * {@inheritdoc} - */ - protected function canBeUsed() - { - return $this->shell->testCommand('find'); - } - - /** - * @param Command $command - * @param string $dir - * - * @return Command - */ - protected function buildFindCommand(Command $command, $dir) - { - return $command - ->ins('find') - ->add('find ') - ->arg($dir) - ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions - } - - /** - * @param Command $command - * @param string[] $names - * @param Boolean $not - */ - private function buildNamesFiltering(Command $command, array $names, $not = false) - { - if (0 === count($names)) { - return; - } - - $command->add($not ? '-not' : null)->cmd('('); - - foreach ($names as $i => $name) { - $expr = Expression::create($name); - - // Find does not support expandable globs ("*.{a,b}" syntax). - if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { - $expr = Expression::create($expr->getGlob()->toRegex(false)); - } - - // Fixes 'not search' and 'full path matching' regex problems. - // - Jokers '.' are replaced by [^/]. - // - We add '[^/]*' before and after regex (if no ^|$ flags are present). - if ($expr->isRegex()) { - $regex = $expr->getRegex(); - $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*') - ->setStartFlag(false) - ->setStartJoker(true) - ->replaceJokers('[^/]'); - if (!$regex->hasEndFlag() || $regex->hasEndJoker()) { - $regex->setEndJoker(false)->append('[^/]*'); - } - } - - $command - ->add($i > 0 ? '-or' : null) - ->add($expr->isRegex() - ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') - : ($expr->isCaseSensitive() ? '-name' : '-iname') - ) - ->arg($expr->renderPattern()); - } - - $command->cmd(')'); - } - - /** - * @param Command $command - * @param string $dir - * @param string[] $paths - * @param Boolean $not - */ - private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false) - { - if (0 === count($paths)) { - return; - } - - $command->add($not ? '-not' : null)->cmd('('); - - foreach ($paths as $i => $path) { - $expr = Expression::create($path); - - // Find does not support expandable globs ("*.{a,b}" syntax). - if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { - $expr = Expression::create($expr->getGlob()->toRegex(false)); - } - - // Fixes 'not search' regex problems. - if ($expr->isRegex()) { - $regex = $expr->getRegex(); - $regex->prepend($regex->hasStartFlag() ? $dir.DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag()); - } else { - $expr->prepend('*')->append('*'); - } - - $command - ->add($i > 0 ? '-or' : null) - ->add($expr->isRegex() - ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') - : ($expr->isCaseSensitive() ? '-path' : '-ipath') - ) - ->arg($expr->renderPattern()); - } - - $command->cmd(')'); - } - - /** - * @param Command $command - * @param NumberComparator[] $sizes - */ - private function buildSizesFiltering(Command $command, array $sizes) - { - foreach ($sizes as $i => $size) { - $command->add($i > 0 ? '-and' : null); - - switch ($size->getOperator()) { - case '<=': - $command->add('-size -'.($size->getTarget() + 1).'c'); - break; - case '>=': - $command->add('-size +'. ($size->getTarget() - 1).'c'); - break; - case '>': - $command->add('-size +'.$size->getTarget().'c'); - break; - case '!=': - $command->add('-size -'.$size->getTarget().'c'); - $command->add('-size +'.$size->getTarget().'c'); - case '<': - default: - $command->add('-size -'.$size->getTarget().'c'); - } - } - } - - /** - * @param Command $command - * @param DateComparator[] $dates - */ - private function buildDatesFiltering(Command $command, array $dates) - { - foreach ($dates as $i => $date) { - $command->add($i > 0 ? '-and' : null); - - $mins = (int) round((time()-$date->getTarget()) / 60); - - if (0 > $mins) { - // mtime is in the future - $command->add(' -mmin -0'); - // we will have no result so we don't need to continue - return; - } - - switch ($date->getOperator()) { - case '<=': - $command->add('-mmin +'.($mins - 1)); - break; - case '>=': - $command->add('-mmin -'.($mins + 1)); - break; - case '>': - $command->add('-mmin -'.$mins); - break; - case '!=': - $command->add('-mmin +'.$mins.' -or -mmin -'.$mins); - break; - case '<': - default: - $command->add('-mmin +'.$mins); - } - } - } - - /** - * @param Command $command - * @param string $sort - * - * @throws \InvalidArgumentException - */ - private function buildSorting(Command $command, $sort) - { - $this->buildFormatSorting($command, $sort); - } - - /** - * @param Command $command - * @param string $sort - */ - abstract protected function buildFormatSorting(Command $command, $sort); - - /** - * @param Command $command - * @param array $contains - * @param Boolean $not - */ - abstract protected function buildContentFiltering(Command $command, array $contains, $not = false); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -/** - * @author Jean-François Simon - */ -interface AdapterInterface -{ - /** - * @param Boolean $followLinks - * - * @return AdapterInterface Current instance - */ - public function setFollowLinks($followLinks); - - /** - * @param integer $mode - * - * @return AdapterInterface Current instance - */ - public function setMode($mode); - - /** - * @param array $exclude - * - * @return AdapterInterface Current instance - */ - public function setExclude(array $exclude); - - /** - * @param array $depths - * - * @return AdapterInterface Current instance - */ - public function setDepths(array $depths); - - /** - * @param array $names - * - * @return AdapterInterface Current instance - */ - public function setNames(array $names); - - /** - * @param array $notNames - * - * @return AdapterInterface Current instance - */ - public function setNotNames(array $notNames); - - /** - * @param array $contains - * - * @return AdapterInterface Current instance - */ - public function setContains(array $contains); - - /** - * @param array $notContains - * - * @return AdapterInterface Current instance - */ - public function setNotContains(array $notContains); - - /** - * @param array $sizes - * - * @return AdapterInterface Current instance - */ - public function setSizes(array $sizes); - - /** - * @param array $dates - * - * @return AdapterInterface Current instance - */ - public function setDates(array $dates); - - /** - * @param array $filters - * - * @return AdapterInterface Current instance - */ - public function setFilters(array $filters); - - /** - * @param \Closure|integer $sort - * - * @return AdapterInterface Current instance - */ - public function setSort($sort); - - /** - * @param array $paths - * - * @return AdapterInterface Current instance - */ - public function setPath(array $paths); - - /** - * @param array $notPaths - * - * @return AdapterInterface Current instance - */ - public function setNotPath(array $notPaths); - - /** - * @param boolean $ignore - * - * @return AdapterInterface Current instance - */ - public function ignoreUnreadableDirs($ignore = true); - - /** - * @param string $dir - * - * @return \Iterator Result iterator - */ - public function searchInDirectory($dir); - - /** - * Tests adapter support for current platform. - * - * @return Boolean - */ - public function isSupported(); - - /** - * Returns adapter name. - * - * @return string - */ - public function getName(); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -/** - * Interface for finder engine implementations. - * - * @author Jean-François Simon - */ -abstract class AbstractAdapter implements AdapterInterface -{ - protected $followLinks = false; - protected $mode = 0; - protected $minDepth = 0; - protected $maxDepth = PHP_INT_MAX; - protected $exclude = array(); - protected $names = array(); - protected $notNames = array(); - protected $contains = array(); - protected $notContains = array(); - protected $sizes = array(); - protected $dates = array(); - protected $filters = array(); - protected $sort = false; - protected $paths = array(); - protected $notPaths = array(); - protected $ignoreUnreadableDirs = false; - - private static $areSupported = array(); - - /** - * {@inheritDoc} - */ - public function isSupported() - { - $name = $this->getName(); - - if (!array_key_exists($name, self::$areSupported)) { - self::$areSupported[$name] = $this->canBeUsed(); - } - - return self::$areSupported[$name]; - } - - /** - * {@inheritdoc} - */ - public function setFollowLinks($followLinks) - { - $this->followLinks = $followLinks; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setMode($mode) - { - $this->mode = $mode; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setDepths(array $depths) - { - $this->minDepth = 0; - $this->maxDepth = PHP_INT_MAX; - - foreach ($depths as $comparator) { - switch ($comparator->getOperator()) { - case '>': - $this->minDepth = $comparator->getTarget() + 1; - break; - case '>=': - $this->minDepth = $comparator->getTarget(); - break; - case '<': - $this->maxDepth = $comparator->getTarget() - 1; - break; - case '<=': - $this->maxDepth = $comparator->getTarget(); - break; - default: - $this->minDepth = $this->maxDepth = $comparator->getTarget(); - } - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setExclude(array $exclude) - { - $this->exclude = $exclude; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setNames(array $names) - { - $this->names = $names; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setNotNames(array $notNames) - { - $this->notNames = $notNames; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setContains(array $contains) - { - $this->contains = $contains; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setNotContains(array $notContains) - { - $this->notContains = $notContains; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setSizes(array $sizes) - { - $this->sizes = $sizes; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setDates(array $dates) - { - $this->dates = $dates; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setFilters(array $filters) - { - $this->filters = $filters; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setSort($sort) - { - $this->sort = $sort; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setPath(array $paths) - { - $this->paths = $paths; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setNotPath(array $notPaths) - { - $this->notPaths = $notPaths; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function ignoreUnreadableDirs($ignore = true) - { - $this->ignoreUnreadableDirs = (Boolean) $ignore; - - return $this; - } - - /** - * Returns whether the adapter is supported in the current environment. - * - * This method should be implemented in all adapters. Do not implement - * isSupported in the adapters as the generic implementation provides a cache - * layer. - * - * @see isSupported - * - * @return Boolean Whether the adapter is supported - */ - abstract protected function canBeUsed(); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -/** - * Glob matches globbing patterns against text. - * - * if match_glob("foo.*", "foo.bar") echo "matched\n"; - * - * // prints foo.bar and foo.baz - * $regex = glob_to_regex("foo.*"); - * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t) - * { - * if (/$regex/) echo "matched: $car\n"; - * } - * - * Glob implements glob(3) style matching that can be used to match - * against text, rather than fetching names from a filesystem. - * - * Based on the Perl Text::Glob module. - * - * @author Fabien Potencier PHP port - * @author Richard Clamp Perl version - * @copyright 2004-2005 Fabien Potencier - * @copyright 2002 Richard Clamp - */ -class Glob -{ - /** - * Returns a regexp which is the equivalent of the glob pattern. - * - * @param string $glob The glob pattern - * @param Boolean $strictLeadingDot - * @param Boolean $strictWildcardSlash - * - * @return string regex The regexp - */ - public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true) - { - $firstByte = true; - $escaping = false; - $inCurlies = 0; - $regex = ''; - $sizeGlob = strlen($glob); - for ($i = 0; $i < $sizeGlob; $i++) { - $car = $glob[$i]; - if ($firstByte) { - if ($strictLeadingDot && '.' !== $car) { - $regex .= '(?=[^\.])'; - } - - $firstByte = false; - } - - if ('/' === $car) { - $firstByte = true; - } - - if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { - $regex .= "\\$car"; - } elseif ('*' === $car) { - $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); - } elseif ('?' === $car) { - $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); - } elseif ('{' === $car) { - $regex .= $escaping ? '\\{' : '('; - if (!$escaping) { - ++$inCurlies; - } - } elseif ('}' === $car && $inCurlies) { - $regex .= $escaping ? '}' : ')'; - if (!$escaping) { - --$inCurlies; - } - } elseif (',' === $car && $inCurlies) { - $regex .= $escaping ? ',' : '|'; - } elseif ('\\' === $car) { - if ($escaping) { - $regex .= '\\\\'; - $escaping = false; - } else { - $escaping = true; - } - - continue; - } else { - $regex .= $car; - } - $escaping = false; - } - - return '#^'.$regex.'$#'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -/** - * Extends \SplFileInfo to support relative paths - * - * @author Fabien Potencier - */ -class SplFileInfo extends \SplFileInfo -{ - private $relativePath; - private $relativePathname; - - /** - * Constructor - * - * @param string $file The file name - * @param string $relativePath The relative path - * @param string $relativePathname The relative path name - */ - public function __construct($file, $relativePath, $relativePathname) - { - parent::__construct($file); - $this->relativePath = $relativePath; - $this->relativePathname = $relativePathname; - } - - /** - * Returns the relative path - * - * @return string the relative path - */ - public function getRelativePath() - { - return $this->relativePath; - } - - /** - * Returns the relative path name - * - * @return string the relative path name - */ - public function getRelativePathname() - { - return $this->relativePathname; - } - - /** - * Returns the contents of the file - * - * @return string the contents of the file - * - * @throws \RuntimeException - */ - public function getContents() - { - $level = error_reporting(0); - $content = file_get_contents($this->getPathname()); - error_reporting($level); - if (false === $content) { - $error = error_get_last(); - throw new \RuntimeException($error['message']); - } - - return $content; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * NumberComparator compiles a simple comparison to an anonymous - * subroutine, which you can call with a value to be tested again. - * - * Now this would be very pointless, if NumberCompare didn't understand - * magnitudes. - * - * The target value may use magnitudes of kilobytes (k, ki), - * megabytes (m, mi), or gigabytes (g, gi). Those suffixed - * with an i use the appropriate 2**n version in accordance with the - * IEC standard: http://physics.nist.gov/cuu/Units/binary.html - * - * Based on the Perl Number::Compare module. - * - * @author Fabien Potencier PHP port - * @author Richard Clamp Perl version - * - * @copyright 2004-2005 Fabien Potencier - * @copyright 2002 Richard Clamp - * - * @see http://physics.nist.gov/cuu/Units/binary.html - */ -class NumberComparator extends Comparator -{ - /** - * Constructor. - * - * @param string $test A comparison string - * - * @throws \InvalidArgumentException If the test is not understood - */ - public function __construct($test) - { - if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { - throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test)); - } - - $target = $matches[2]; - if (!is_numeric($target)) { - throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target)); - } - if (isset($matches[3])) { - // magnitude - switch (strtolower($matches[3])) { - case 'k': - $target *= 1000; - break; - case 'ki': - $target *= 1024; - break; - case 'm': - $target *= 1000000; - break; - case 'mi': - $target *= 1024*1024; - break; - case 'g': - $target *= 1000000000; - break; - case 'gi': - $target *= 1024*1024*1024; - break; - } - } - - $this->setTarget($target); - $this->setOperator(isset($matches[1]) ? $matches[1] : '=='); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * DateCompare compiles date comparisons. - * - * @author Fabien Potencier - */ -class DateComparator extends Comparator -{ - - /** - * Constructor. - * - * @param string $test A comparison string - * - * @throws \InvalidArgumentException If the test is not understood - */ - public function __construct($test) - { - if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { - throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); - } - - try { - $date = new \DateTime($matches[2]); - $target = $date->format('U'); - } catch (\Exception $e) { - throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); - } - - $operator = isset($matches[1]) ? $matches[1] : '=='; - if ('since' === $operator || 'after' === $operator) { - $operator = '>'; - } - - if ('until' === $operator || 'before' === $operator) { - $operator = '<'; - } - - $this->setOperator($operator); - $this->setTarget($target); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * Comparator. - * - * @author Fabien Potencier - */ -class Comparator -{ - private $target; - private $operator = '=='; - - /** - * Gets the target value. - * - * @return string The target value - */ - public function getTarget() - { - return $this->target; - } - - /** - * Sets the target value. - * - * @param string $target The target value - */ - public function setTarget($target) - { - $this->target = $target; - } - - /** - * Gets the comparison operator. - * - * @return string The operator - */ - public function getOperator() - { - return $this->operator; - } - - /** - * Sets the comparison operator. - * - * @param string $operator A valid operator - * - * @throws \InvalidArgumentException - */ - public function setOperator($operator) - { - if (!$operator) { - $operator = '=='; - } - - if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) { - throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); - } - - $this->operator = $operator; - } - - /** - * Tests against the target. - * - * @param mixed $test A test value - * - * @return Boolean - */ - public function test($test) - { - switch ($this->operator) { - case '>': - return $test > $this->target; - case '>=': - return $test >= $this->target; - case '<': - return $test < $this->target; - case '<=': - return $test <= $this->target; - case '!=': - return $test != $this->target; - } - - return $test == $this->target; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Expression; - -/** - * @author Jean-François Simon - */ -class Expression implements ValueInterface -{ - const TYPE_REGEX = 1; - const TYPE_GLOB = 2; - - /** - * @var ValueInterface - */ - private $value; - - /** - * @param string $expr - * - * @return Expression - */ - public static function create($expr) - { - return new self($expr); - } - - /** - * @param string $expr - */ - public function __construct($expr) - { - try { - $this->value = Regex::create($expr); - } catch (\InvalidArgumentException $e) { - $this->value = new Glob($expr); - } - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(); - } - - /** - * {@inheritdoc} - */ - public function render() - { - return $this->value->render(); - } - - /** - * {@inheritdoc} - */ - public function renderPattern() - { - return $this->value->renderPattern(); - } - - /** - * @return bool - */ - public function isCaseSensitive() - { - return $this->value->isCaseSensitive(); - } - - /** - * @return int - */ - public function getType() - { - return $this->value->getType(); - } - - /** - * {@inheritdoc} - */ - public function prepend($expr) - { - $this->value->prepend($expr); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function append($expr) - { - $this->value->append($expr); - - return $this; - } - - /** - * @return bool - */ - public function isRegex() - { - return self::TYPE_REGEX === $this->value->getType(); - } - - /** - * @return bool - */ - public function isGlob() - { - return self::TYPE_GLOB === $this->value->getType(); - } - - /** - * @throws \LogicException - * - * @return Glob - */ - public function getGlob() - { - if (self::TYPE_GLOB !== $this->value->getType()) { - throw new \LogicException('Regex cant be transformed to glob.'); - } - - return $this->value; - } - - /** - * @return Regex - */ - public function getRegex() - { - return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex(); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Expression; - -/** - * @author Jean-François Simon - */ -class Regex implements ValueInterface -{ - const START_FLAG = '^'; - const END_FLAG = '$'; - const BOUNDARY = '~'; - const JOKER = '.*'; - const ESCAPING = '\\'; - - /** - * @var string - */ - private $pattern; - - /** - * @var array - */ - private $options; - - /** - * @var bool - */ - private $startFlag; - - /** - * @var bool - */ - private $endFlag; - - /** - * @var bool - */ - private $startJoker; - - /** - * @var bool - */ - private $endJoker; - - /** - * @param string $expr - * - * @return Regex - * - * @throws \InvalidArgumentException - */ - public static function create($expr) - { - if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) { - $start = substr($m[1], 0, 1); - $end = substr($m[1], -1); - - if (($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start)) || ($start === '{' && $end === '}')) { - return new self(substr($m[1], 1, -1), $m[2], $end); - } - } - - throw new \InvalidArgumentException('Given expression is not a regex.'); - } - - /** - * @param string $pattern - * @param string $options - * @param string $delimiter - */ - public function __construct($pattern, $options = '', $delimiter = null) - { - if (null !== $delimiter) { - // removes delimiter escaping - $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern); - } - - $this->parsePattern($pattern); - $this->options = $options; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(); - } - - /** - * {@inheritdoc} - */ - public function render() - { - return self::BOUNDARY - .$this->renderPattern() - .self::BOUNDARY - .$this->options; - } - - /** - * {@inheritdoc} - */ - public function renderPattern() - { - return ($this->startFlag ? self::START_FLAG : '') - .($this->startJoker ? self::JOKER : '') - .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern) - .($this->endJoker ? self::JOKER : '') - .($this->endFlag ? self::END_FLAG : ''); - } - - /** - * {@inheritdoc} - */ - public function isCaseSensitive() - { - return !$this->hasOption('i'); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - return Expression::TYPE_REGEX; - } - - /** - * {@inheritdoc} - */ - public function prepend($expr) - { - $this->pattern = $expr.$this->pattern; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function append($expr) - { - $this->pattern .= $expr; - - return $this; - } - - /** - * @param string $option - * - * @return bool - */ - public function hasOption($option) - { - return false !== strpos($this->options, $option); - } - - /** - * @param string $option - * - * @return Regex - */ - public function addOption($option) - { - if (!$this->hasOption($option)) { - $this->options.= $option; - } - - return $this; - } - - /** - * @param string $option - * - * @return Regex - */ - public function removeOption($option) - { - $this->options = str_replace($option, '', $this->options); - - return $this; - } - - /** - * @param bool $startFlag - * - * @return Regex - */ - public function setStartFlag($startFlag) - { - $this->startFlag = $startFlag; - - return $this; - } - - /** - * @return bool - */ - public function hasStartFlag() - { - return $this->startFlag; - } - - /** - * @param bool $endFlag - * - * @return Regex - */ - public function setEndFlag($endFlag) - { - $this->endFlag = (bool) $endFlag; - - return $this; - } - - /** - * @return bool - */ - public function hasEndFlag() - { - return $this->endFlag; - } - - /** - * @param bool $startJoker - * - * @return Regex - */ - public function setStartJoker($startJoker) - { - $this->startJoker = $startJoker; - - return $this; - } - - /** - * @return bool - */ - public function hasStartJoker() - { - return $this->startJoker; - } - - /** - * @param bool $endJoker - * - * @return Regex - */ - public function setEndJoker($endJoker) - { - $this->endJoker = (bool) $endJoker; - - return $this; - } - - /** - * @return bool - */ - public function hasEndJoker() - { - return $this->endJoker; - } - - /** - * @param array $replacement - * - * @return Regex - */ - public function replaceJokers($replacement) - { - $replace = function ($subject) use ($replacement) { - $subject = $subject[0]; - $replace = 0 === substr_count($subject, '\\') % 2; - - return $replace ? str_replace('.', $replacement, $subject) : $subject; - }; - - $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern); - - return $this; - } - - /** - * @param string $pattern - */ - private function parsePattern($pattern) - { - if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) { - $pattern = substr($pattern, 1); - } - - if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) { - $pattern = substr($pattern, 2); - } - - if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) { - $pattern = substr($pattern, 0, -1); - } - - if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) { - $pattern = substr($pattern, 0, -2); - } - - $this->pattern = $pattern; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Expression; - -/** - * @author Jean-François Simon - */ -class Glob implements ValueInterface -{ - /** - * @var string - */ - private $pattern; - - /** - * @param string $pattern - */ - public function __construct($pattern) - { - $this->pattern = $pattern; - } - - /** - * {@inheritdoc} - */ - public function render() - { - return $this->pattern; - } - - /** - * {@inheritdoc} - */ - public function renderPattern() - { - return $this->pattern; - } - - /** - * {@inheritdoc} - */ - public function getType() - { - return Expression::TYPE_GLOB; - } - - /** - * {@inheritdoc} - */ - public function isCaseSensitive() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function prepend($expr) - { - $this->pattern = $expr.$this->pattern; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function append($expr) - { - $this->pattern .= $expr; - - return $this; - } - - /** - * Tests if glob is expandable ("*.{a,b}" syntax). - * - * @return bool - */ - public function isExpandable() - { - return false !== strpos($this->pattern, '{') - && false !== strpos($this->pattern, '}'); - } - - /** - * @param bool $strictLeadingDot - * @param bool $strictWildcardSlash - * - * @return Regex - */ - public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true) - { - $firstByte = true; - $escaping = false; - $inCurlies = 0; - $regex = ''; - $sizeGlob = strlen($this->pattern); - for ($i = 0; $i < $sizeGlob; $i++) { - $car = $this->pattern[$i]; - if ($firstByte) { - if ($strictLeadingDot && '.' !== $car) { - $regex .= '(?=[^\.])'; - } - - $firstByte = false; - } - - if ('/' === $car) { - $firstByte = true; - } - - if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { - $regex .= "\\$car"; - } elseif ('*' === $car) { - $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); - } elseif ('?' === $car) { - $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); - } elseif ('{' === $car) { - $regex .= $escaping ? '\\{' : '('; - if (!$escaping) { - ++$inCurlies; - } - } elseif ('}' === $car && $inCurlies) { - $regex .= $escaping ? '}' : ')'; - if (!$escaping) { - --$inCurlies; - } - } elseif (',' === $car && $inCurlies) { - $regex .= $escaping ? ',' : '|'; - } elseif ('\\' === $car) { - if ($escaping) { - $regex .= '\\\\'; - $escaping = false; - } else { - $escaping = true; - } - - continue; - } else { - $regex .= $car; - } - $escaping = false; - } - - return new Regex('^'.$regex.'$'); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Expression; - -/** - * @author Jean-François Simon - */ -interface ValueInterface -{ - /** - * Renders string representation of expression. - * - * @return string - */ - public function render(); - - /** - * Renders string representation of pattern. - * - * @return string - */ - public function renderPattern(); - - /** - * Returns value case sensitivity. - * - * @return bool - */ - public function isCaseSensitive(); - - /** - * Returns expression type. - * - * @return int - */ - public function getType(); - - /** - * @param string $expr - * - * @return ValueInterface - */ - public function prepend($expr); - - /** - * @param string $expr - * - * @return ValueInterface - */ - public function append($expr); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Jean-François Simon - */ -class OperationNotPermitedException extends AdapterFailureException -{ -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Jean-François Simon - */ -class AccessDeniedException extends \UnexpectedValueException -{ -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Jean-François Simon - */ -interface ExceptionInterface -{ - /** - * @return \Symfony\Component\Finder\Adapter\AdapterInterface - */ - public function getAdapter(); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -use Symfony\Component\Finder\Adapter\AdapterInterface; -use Symfony\Component\Finder\Shell\Command; - -/** - * @author Jean-François Simon - */ -class ShellCommandFailureException extends AdapterFailureException -{ - /** - * @var Command - */ - private $command; - - /** - * @param AdapterInterface $adapter - * @param Command $command - * @param \Exception|null $previous - */ - public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null) - { - $this->command = $command; - parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous); - } - - /** - * @return Command - */ - public function getCommand() - { - return $this->command; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -use Symfony\Component\Finder\Adapter\AdapterInterface; - -/** - * Base exception for all adapter failures. - * - * @author Jean-François Simon - */ -class AdapterFailureException extends \RuntimeException implements ExceptionInterface -{ - /** - * @var \Symfony\Component\Finder\Adapter\AdapterInterface - */ - private $adapter; - - /** - * @param AdapterInterface $adapter - * @param string|null $message - * @param \Exception|null $previous - */ - public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null) - { - $this->adapter = $adapter; - parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous); - } - - /** - * {@inheritdoc} - */ - public function getAdapter() - { - return $this->adapter; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -use Symfony\Component\Finder\Adapter\AdapterInterface; -use Symfony\Component\Finder\Adapter\GnuFindAdapter; -use Symfony\Component\Finder\Adapter\BsdFindAdapter; -use Symfony\Component\Finder\Adapter\PhpAdapter; -use Symfony\Component\Finder\Exception\ExceptionInterface; - -/** - * Finder allows to build rules to find files and directories. - * - * It is a thin wrapper around several specialized iterator classes. - * - * All rules may be invoked several times. - * - * All methods return the current Finder object to allow easy chaining: - * - * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); - * - * @author Fabien Potencier - * - * @api - */ -class Finder implements \IteratorAggregate, \Countable -{ - const IGNORE_VCS_FILES = 1; - const IGNORE_DOT_FILES = 2; - - private $mode = 0; - private $names = array(); - private $notNames = array(); - private $exclude = array(); - private $filters = array(); - private $depths = array(); - private $sizes = array(); - private $followLinks = false; - private $sort = false; - private $ignore = 0; - private $dirs = array(); - private $dates = array(); - private $iterators = array(); - private $contains = array(); - private $notContains = array(); - private $adapters = array(); - private $paths = array(); - private $notPaths = array(); - private $ignoreUnreadableDirs = false; - - private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'); - - /** - * Constructor. - */ - public function __construct() - { - $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; - - $this - ->addAdapter(new GnuFindAdapter()) - ->addAdapter(new BsdFindAdapter()) - ->addAdapter(new PhpAdapter(), -50) - ->setAdapter('php') - ; - } - - /** - * Creates a new Finder. - * - * @return Finder A new Finder instance - * - * @api - */ - public static function create() - { - return new static(); - } - - /** - * Registers a finder engine implementation. - * - * @param AdapterInterface $adapter An adapter instance - * @param integer $priority Highest is selected first - * - * @return Finder The current Finder instance - */ - public function addAdapter(Adapter\AdapterInterface $adapter, $priority = 0) - { - $this->adapters[$adapter->getName()] = array( - 'adapter' => $adapter, - 'priority' => $priority, - 'selected' => false, - ); - - return $this->sortAdapters(); - } - - /** - * Sets the selected adapter to the best one according to the current platform the code is run on. - * - * @return Finder The current Finder instance - */ - public function useBestAdapter() - { - $this->resetAdapterSelection(); - - return $this->sortAdapters(); - } - - /** - * Selects the adapter to use. - * - * @param string $name - * - * @throws \InvalidArgumentException - * - * @return Finder The current Finder instance - */ - public function setAdapter($name) - { - if (!isset($this->adapters[$name])) { - throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name)); - } - - $this->resetAdapterSelection(); - $this->adapters[$name]['selected'] = true; - - return $this->sortAdapters(); - } - - /** - * Removes all adapters registered in the finder. - * - * @return Finder The current Finder instance - */ - public function removeAdapters() - { - $this->adapters = array(); - - return $this; - } - - /** - * Returns registered adapters ordered by priority without extra information. - * - * @return AdapterInterface[] - */ - public function getAdapters() - { - return array_values(array_map(function(array $adapter) { - return $adapter['adapter']; - }, $this->adapters)); - } - - /** - * Restricts the matching to directories only. - * - * @return Finder The current Finder instance - * - * @api - */ - public function directories() - { - $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES; - - return $this; - } - - /** - * Restricts the matching to files only. - * - * @return Finder The current Finder instance - * - * @api - */ - public function files() - { - $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES; - - return $this; - } - - /** - * Adds tests for the directory depth. - * - * Usage: - * - * $finder->depth('> 1') // the Finder will start matching at level 1. - * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. - * - * @param int $level The depth level expression - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\DepthRangeFilterIterator - * @see Symfony\Component\Finder\Comparator\NumberComparator - * - * @api - */ - public function depth($level) - { - $this->depths[] = new Comparator\NumberComparator($level); - - return $this; - } - - /** - * Adds tests for file dates (last modified). - * - * The date must be something that strtotime() is able to parse: - * - * $finder->date('since yesterday'); - * $finder->date('until 2 days ago'); - * $finder->date('> now - 2 hours'); - * $finder->date('>= 2005-10-15'); - * - * @param string $date A date rage string - * - * @return Finder The current Finder instance - * - * @see strtotime - * @see Symfony\Component\Finder\Iterator\DateRangeFilterIterator - * @see Symfony\Component\Finder\Comparator\DateComparator - * - * @api - */ - public function date($date) - { - $this->dates[] = new Comparator\DateComparator($date); - - return $this; - } - - /** - * Adds rules that files must match. - * - * You can use patterns (delimited with / sign), globs or simple strings. - * - * $finder->name('*.php') - * $finder->name('/\.php$/') // same as above - * $finder->name('test.php') - * - * @param string $pattern A pattern (a regexp, a glob, or a string) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator - * - * @api - */ - public function name($pattern) - { - $this->names[] = $pattern; - - return $this; - } - - /** - * Adds rules that files must not match. - * - * @param string $pattern A pattern (a regexp, a glob, or a string) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator - * - * @api - */ - public function notName($pattern) - { - $this->notNames[] = $pattern; - - return $this; - } - - /** - * Adds tests that file contents must match. - * - * Strings or PCRE patterns can be used: - * - * $finder->contains('Lorem ipsum') - * $finder->contains('/Lorem ipsum/i') - * - * @param string $pattern A pattern (string or regexp) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator - */ - public function contains($pattern) - { - $this->contains[] = $pattern; - - return $this; - } - - /** - * Adds tests that file contents must not match. - * - * Strings or PCRE patterns can be used: - * - * $finder->notContains('Lorem ipsum') - * $finder->notContains('/Lorem ipsum/i') - * - * @param string $pattern A pattern (string or regexp) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator - */ - public function notContains($pattern) - { - $this->notContains[] = $pattern; - - return $this; - } - - /** - * Adds rules that filenames must match. - * - * You can use patterns (delimited with / sign) or simple strings. - * - * $finder->path('some/special/dir') - * $finder->path('/some\/special\/dir/') // same as above - * - * Use only / as dirname separator. - * - * @param string $pattern A pattern (a regexp or a string) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator - */ - public function path($pattern) - { - $this->paths[] = $pattern; - - return $this; - } - - /** - * Adds rules that filenames must not match. - * - * You can use patterns (delimited with / sign) or simple strings. - * - * $finder->notPath('some/special/dir') - * $finder->notPath('/some\/special\/dir/') // same as above - * - * Use only / as dirname separator. - * - * @param string $pattern A pattern (a regexp or a string) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator - */ - public function notPath($pattern) - { - $this->notPaths[] = $pattern; - - return $this; - } - - /** - * Adds tests for file sizes. - * - * $finder->size('> 10K'); - * $finder->size('<= 1Ki'); - * $finder->size(4); - * - * @param string $size A size range string - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SizeRangeFilterIterator - * @see Symfony\Component\Finder\Comparator\NumberComparator - * - * @api - */ - public function size($size) - { - $this->sizes[] = new Comparator\NumberComparator($size); - - return $this; - } - - /** - * Excludes directories. - * - * @param string|array $dirs A directory path or an array of directories - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator - * - * @api - */ - public function exclude($dirs) - { - $this->exclude = array_merge($this->exclude, (array) $dirs); - - return $this; - } - - /** - * Excludes "hidden" directories and files (starting with a dot). - * - * @param Boolean $ignoreDotFiles Whether to exclude "hidden" files or not - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator - * - * @api - */ - public function ignoreDotFiles($ignoreDotFiles) - { - if ($ignoreDotFiles) { - $this->ignore = $this->ignore | static::IGNORE_DOT_FILES; - } else { - $this->ignore = $this->ignore & ~static::IGNORE_DOT_FILES; - } - - return $this; - } - - /** - * Forces the finder to ignore version control directories. - * - * @param Boolean $ignoreVCS Whether to exclude VCS files or not - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator - * - * @api - */ - public function ignoreVCS($ignoreVCS) - { - if ($ignoreVCS) { - $this->ignore = $this->ignore | static::IGNORE_VCS_FILES; - } else { - $this->ignore = $this->ignore & ~static::IGNORE_VCS_FILES; - } - - return $this; - } - - /** - * Adds VCS patterns. - * - * @see ignoreVCS - * - * @param string|string[] $pattern VCS patterns to ignore - */ - public static function addVCSPattern($pattern) - { - foreach ((array) $pattern as $p) { - self::$vcsPatterns[] = $p; - } - - self::$vcsPatterns = array_unique(self::$vcsPatterns); - } - - /** - * Sorts files and directories by an anonymous function. - * - * The anonymous function receives two \SplFileInfo instances to compare. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @param \Closure $closure An anonymous function - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sort(\Closure $closure) - { - $this->sort = $closure; - - return $this; - } - - /** - * Sorts files and directories by name. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sortByName() - { - $this->sort = Iterator\SortableIterator::SORT_BY_NAME; - - return $this; - } - - /** - * Sorts files and directories by type (directories before files), then by name. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sortByType() - { - $this->sort = Iterator\SortableIterator::SORT_BY_TYPE; - - return $this; - } - - /** - * Sorts files and directories by the last accessed time. - * - * This is the time that the file was last accessed, read or written to. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sortByAccessedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME; - - return $this; - } - - /** - * Sorts files and directories by the last inode changed time. - * - * This is the time that the inode information was last modified (permissions, owner, group or other metadata). - * - * On Windows, since inode is not available, changed time is actually the file creation time. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sortByChangedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME; - - return $this; - } - - /** - * Sorts files and directories by the last modified time. - * - * This is the last time the actual contents of the file were last modified. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sortByModifiedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME; - - return $this; - } - - /** - * Filters the iterator with an anonymous function. - * - * The anonymous function receives a \SplFileInfo and must return false - * to remove files. - * - * @param \Closure $closure An anonymous function - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\CustomFilterIterator - * - * @api - */ - public function filter(\Closure $closure) - { - $this->filters[] = $closure; - - return $this; - } - - /** - * Forces the following of symlinks. - * - * @return Finder The current Finder instance - * - * @api - */ - public function followLinks() - { - $this->followLinks = true; - - return $this; - } - - /** - * Tells finder to ignore unreadable directories. - * - * By default, scanning unreadable directories content throws an AccessDeniedException. - * - * @param boolean $ignore - * - * @return Finder The current Finder instance - */ - public function ignoreUnreadableDirs($ignore = true) - { - $this->ignoreUnreadableDirs = (Boolean) $ignore; - - return $this; - } - - /** - * Searches files and directories which match defined rules. - * - * @param string|array $dirs A directory path or an array of directories - * - * @return Finder The current Finder instance - * - * @throws \InvalidArgumentException if one of the directories does not exist - * - * @api - */ - public function in($dirs) - { - $resolvedDirs = array(); - - foreach ((array) $dirs as $dir) { - if (is_dir($dir)) { - $resolvedDirs[] = $dir; - } elseif ($glob = glob($dir, GLOB_ONLYDIR)) { - $resolvedDirs = array_merge($resolvedDirs, $glob); - } else { - throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir)); - } - } - - $this->dirs = array_merge($this->dirs, $resolvedDirs); - - return $this; - } - - /** - * Returns an Iterator for the current Finder configuration. - * - * This method implements the IteratorAggregate interface. - * - * @return \Iterator An iterator - * - * @throws \LogicException if the in() method has not been called - */ - public function getIterator() - { - if (0 === count($this->dirs) && 0 === count($this->iterators)) { - throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.'); - } - - if (1 === count($this->dirs) && 0 === count($this->iterators)) { - return $this->searchInDirectory($this->dirs[0]); - } - - $iterator = new \AppendIterator(); - foreach ($this->dirs as $dir) { - $iterator->append($this->searchInDirectory($dir)); - } - - foreach ($this->iterators as $it) { - $iterator->append($it); - } - - return $iterator; - } - - /** - * Appends an existing set of files/directories to the finder. - * - * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. - * - * @param mixed $iterator - * - * @return Finder The finder - * - * @throws \InvalidArgumentException When the given argument is not iterable. - */ - public function append($iterator) - { - if ($iterator instanceof \IteratorAggregate) { - $this->iterators[] = $iterator->getIterator(); - } elseif ($iterator instanceof \Iterator) { - $this->iterators[] = $iterator; - } elseif ($iterator instanceof \Traversable || is_array($iterator)) { - $it = new \ArrayIterator(); - foreach ($iterator as $file) { - $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file)); - } - $this->iterators[] = $it; - } else { - throw new \InvalidArgumentException('Finder::append() method wrong argument type.'); - } - - return $this; - } - - /** - * Counts all the results collected by the iterators. - * - * @return int - */ - public function count() - { - return iterator_count($this->getIterator()); - } - - /** - * @return Finder The current Finder instance - */ - private function sortAdapters() - { - uasort($this->adapters, function (array $a, array $b) { - if ($a['selected'] || $b['selected']) { - return $a['selected'] ? -1 : 1; - } - - return $a['priority'] > $b['priority'] ? -1 : 1; - }); - - return $this; - } - - /** - * @param $dir - * - * @return \Iterator - * - * @throws \RuntimeException When none of the adapters are supported - */ - private function searchInDirectory($dir) - { - if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { - $this->exclude = array_merge($this->exclude, self::$vcsPatterns); - } - - if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { - $this->notPaths[] = '#(^|/)\..+(/|$)#'; - } - - foreach ($this->adapters as $adapter) { - if ($adapter['adapter']->isSupported()) { - try { - return $this - ->buildAdapter($adapter['adapter']) - ->searchInDirectory($dir); - } catch (ExceptionInterface $e) {} - } - } - - throw new \RuntimeException('No supported adapter found.'); - } - - /** - * @param AdapterInterface $adapter - * - * @return AdapterInterface - */ - private function buildAdapter(AdapterInterface $adapter) - { - return $adapter - ->setFollowLinks($this->followLinks) - ->setDepths($this->depths) - ->setMode($this->mode) - ->setExclude($this->exclude) - ->setNames($this->names) - ->setNotNames($this->notNames) - ->setContains($this->contains) - ->setNotContains($this->notContains) - ->setSizes($this->sizes) - ->setDates($this->dates) - ->setFilters($this->filters) - ->setSort($this->sort) - ->setPath($this->paths) - ->setNotPath($this->notPaths) - ->ignoreUnreadableDirs($this->ignoreUnreadableDirs); - } - - /** - * Unselects all adapters. - */ - private function resetAdapterSelection() - { - $this->adapters = array_map(function (array $properties) { - $properties['selected'] = false; - - return $properties; - }, $this->adapters); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Helper\HelperSet; - -/** - * Base class for all commands. - * - * @author Fabien Potencier - * - * @api - */ -class Command -{ - private $application; - private $name; - private $aliases; - private $definition; - private $help; - private $description; - private $ignoreValidationErrors; - private $applicationDefinitionMerged; - private $applicationDefinitionMergedWithArgs; - private $code; - private $synopsis; - private $helperSet; - - /** - * Constructor. - * - * @param string $name The name of the command - * - * @throws \LogicException When the command name is empty - * - * @api - */ - public function __construct($name = null) - { - $this->definition = new InputDefinition(); - $this->ignoreValidationErrors = false; - $this->applicationDefinitionMerged = false; - $this->applicationDefinitionMergedWithArgs = false; - $this->aliases = array(); - - if (null !== $name) { - $this->setName($name); - } - - $this->configure(); - - if (!$this->name) { - throw new \LogicException('The command name cannot be empty.'); - } - } - - /** - * Ignores validation errors. - * - * This is mainly useful for the help command. - */ - public function ignoreValidationErrors() - { - $this->ignoreValidationErrors = true; - } - - /** - * Sets the application instance for this command. - * - * @param Application $application An Application instance - * - * @api - */ - public function setApplication(Application $application = null) - { - $this->application = $application; - if ($application) { - $this->setHelperSet($application->getHelperSet()); - } else { - $this->helperSet = null; - } - } - - /** - * Sets the helper set. - * - * @param HelperSet $helperSet A HelperSet instance - */ - public function setHelperSet(HelperSet $helperSet) - { - $this->helperSet = $helperSet; - } - - /** - * Gets the helper set. - * - * @return HelperSet A HelperSet instance - */ - public function getHelperSet() - { - return $this->helperSet; - } - - /** - * Gets the application instance for this command. - * - * @return Application An Application instance - * - * @api - */ - public function getApplication() - { - return $this->application; - } - - /** - * Checks whether the command is enabled or not in the current environment - * - * Override this to check for x or y and return false if the command can not - * run properly under the current conditions. - * - * @return Boolean - */ - public function isEnabled() - { - return true; - } - - /** - * Configures the current command. - */ - protected function configure() - { - } - - /** - * Executes the current command. - * - * This method is not abstract because you can use this class - * as a concrete class. In this case, instead of defining the - * execute() method, you set the code to execute by passing - * a Closure to the setCode() method. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * - * @return null|integer null or 0 if everything went fine, or an error code - * - * @throws \LogicException When this abstract method is not implemented - * @see setCode() - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - throw new \LogicException('You must override the execute() method in the concrete command class.'); - } - - /** - * Interacts with the user. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - */ - protected function interact(InputInterface $input, OutputInterface $output) - { - } - - /** - * Initializes the command just after the input has been validated. - * - * This is mainly useful when a lot of commands extends one main command - * where some things need to be initialized based on the input arguments and options. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - */ - protected function initialize(InputInterface $input, OutputInterface $output) - { - } - - /** - * Runs the command. - * - * The code to execute is either defined directly with the - * setCode() method or by overriding the execute() method - * in a sub-class. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * - * @return integer The command exit code - * - * @throws \Exception - * - * @see setCode() - * @see execute() - * - * @api - */ - public function run(InputInterface $input, OutputInterface $output) - { - // force the creation of the synopsis before the merge with the app definition - $this->getSynopsis(); - - // add the application arguments and options - $this->mergeApplicationDefinition(); - - // bind the input against the command specific arguments/options - try { - $input->bind($this->definition); - } catch (\Exception $e) { - if (!$this->ignoreValidationErrors) { - throw $e; - } - } - - $this->initialize($input, $output); - - if ($input->isInteractive()) { - $this->interact($input, $output); - } - - $input->validate(); - - if ($this->code) { - $statusCode = call_user_func($this->code, $input, $output); - } else { - $statusCode = $this->execute($input, $output); - } - - return is_numeric($statusCode) ? (int) $statusCode : 0; - } - - /** - * Sets the code to execute when running this command. - * - * If this method is used, it overrides the code defined - * in the execute() method. - * - * @param callable $code A callable(InputInterface $input, OutputInterface $output) - * - * @return Command The current instance - * - * @throws \InvalidArgumentException - * - * @see execute() - * - * @api - */ - public function setCode($code) - { - if (!is_callable($code)) { - throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.'); - } - - $this->code = $code; - - return $this; - } - - /** - * Merges the application definition with the command definition. - * - * This method is not part of public API and should not be used directly. - * - * @param Boolean $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments - */ - public function mergeApplicationDefinition($mergeArgs = true) - { - if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) { - return; - } - - if ($mergeArgs) { - $currentArguments = $this->definition->getArguments(); - $this->definition->setArguments($this->application->getDefinition()->getArguments()); - $this->definition->addArguments($currentArguments); - } - - $this->definition->addOptions($this->application->getDefinition()->getOptions()); - - $this->applicationDefinitionMerged = true; - if ($mergeArgs) { - $this->applicationDefinitionMergedWithArgs = true; - } - } - - /** - * Sets an array of argument and option instances. - * - * @param array|InputDefinition $definition An array of argument and option instances or a definition instance - * - * @return Command The current instance - * - * @api - */ - public function setDefinition($definition) - { - if ($definition instanceof InputDefinition) { - $this->definition = $definition; - } else { - $this->definition->setDefinition($definition); - } - - $this->applicationDefinitionMerged = false; - - return $this; - } - - /** - * Gets the InputDefinition attached to this Command. - * - * @return InputDefinition An InputDefinition instance - * - * @api - */ - public function getDefinition() - { - return $this->definition; - } - - /** - * Gets the InputDefinition to be used to create XML and Text representations of this Command. - * - * Can be overridden to provide the original command representation when it would otherwise - * be changed by merging with the application InputDefinition. - * - * This method is not part of public API and should not be used directly. - * - * @return InputDefinition An InputDefinition instance - */ - public function getNativeDefinition() - { - return $this->getDefinition(); - } - - /** - * Adds an argument. - * - * @param string $name The argument name - * @param integer $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL - * @param string $description A description text - * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) - * - * @return Command The current instance - * - * @api - */ - public function addArgument($name, $mode = null, $description = '', $default = null) - { - $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); - - return $this; - } - - /** - * Adds an option. - * - * @param string $name The option name - * @param string $shortcut The shortcut (can be null) - * @param integer $mode The option mode: One of the InputOption::VALUE_* constants - * @param string $description A description text - * @param mixed $default The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE) - * - * @return Command The current instance - * - * @api - */ - public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null) - { - $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); - - return $this; - } - - /** - * Sets the name of the command. - * - * This method can set both the namespace and the name if - * you separate them by a colon (:) - * - * $command->setName('foo:bar'); - * - * @param string $name The command name - * - * @return Command The current instance - * - * @throws \InvalidArgumentException When command name given is empty - * - * @api - */ - public function setName($name) - { - $this->validateName($name); - - $this->name = $name; - - return $this; - } - - /** - * Returns the command name. - * - * @return string The command name - * - * @api - */ - public function getName() - { - return $this->name; - } - - /** - * Sets the description for the command. - * - * @param string $description The description for the command - * - * @return Command The current instance - * - * @api - */ - public function setDescription($description) - { - $this->description = $description; - - return $this; - } - - /** - * Returns the description for the command. - * - * @return string The description for the command - * - * @api - */ - public function getDescription() - { - return $this->description; - } - - /** - * Sets the help for the command. - * - * @param string $help The help for the command - * - * @return Command The current instance - * - * @api - */ - public function setHelp($help) - { - $this->help = $help; - - return $this; - } - - /** - * Returns the help for the command. - * - * @return string The help for the command - * - * @api - */ - public function getHelp() - { - return $this->help; - } - - /** - * Returns the processed help for the command replacing the %command.name% and - * %command.full_name% patterns with the real values dynamically. - * - * @return string The processed help for the command - */ - public function getProcessedHelp() - { - $name = $this->name; - - $placeholders = array( - '%command.name%', - '%command.full_name%' - ); - $replacements = array( - $name, - $_SERVER['PHP_SELF'].' '.$name - ); - - return str_replace($placeholders, $replacements, $this->getHelp()); - } - - /** - * Sets the aliases for the command. - * - * @param array $aliases An array of aliases for the command - * - * @return Command The current instance - * - * @api - */ - public function setAliases($aliases) - { - foreach ($aliases as $alias) { - $this->validateName($alias); - } - - $this->aliases = $aliases; - - return $this; - } - - /** - * Returns the aliases for the command. - * - * @return array An array of aliases for the command - * - * @api - */ - public function getAliases() - { - return $this->aliases; - } - - /** - * Returns the synopsis for the command. - * - * @return string The synopsis - */ - public function getSynopsis() - { - if (null === $this->synopsis) { - $this->synopsis = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis())); - } - - return $this->synopsis; - } - - /** - * Gets a helper instance by name. - * - * @param string $name The helper name - * - * @return mixed The helper value - * - * @throws \InvalidArgumentException if the helper is not defined - * - * @api - */ - public function getHelper($name) - { - return $this->helperSet->get($name); - } - - /** - * Returns a text representation of the command. - * - * @return string A string representing the command - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asText() - { - $descriptor = new TextDescriptor(); - - return $descriptor->describe($this); - } - - /** - * Returns an XML representation of the command. - * - * @param Boolean $asDom Whether to return a DOM or an XML string - * - * @return string|\DOMDocument An XML string representing the command - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asXml($asDom = false) - { - $descriptor = new XmlDescriptor(); - - return $descriptor->describe($this, array('as_dom' => $asDom)); - } - - private function validateName($name) - { - if (!preg_match('/^[^\:]+(\:[^\:]+)*$/', $name)) { - throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Helper\DescriptorHelper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * HelpCommand displays the help for a given command. - * - * @author Fabien Potencier - */ -class HelpCommand extends Command -{ - private $command; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->ignoreValidationErrors(); - - $this - ->setName('help') - ->setDefinition(array( - new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), - new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats'), - new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), - )) - ->setDescription('Displays help for a command') - ->setHelp(<<%command.name% command displays help for a given command: - - php %command.full_name% list - -You can also output the help in other formats by using the --format option: - - php %command.full_name% --format=xml list - -To display the list of available commands, please use the list command. -EOF - ) - ; - } - - /** - * Sets the command - * - * @param Command $command The command to set - */ - public function setCommand(Command $command) - { - $this->command = $command; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - if (null === $this->command) { - $this->command = $this->getApplication()->find($input->getArgument('command_name')); - } - - if ($input->getOption('xml')) { - $input->setOption('format', 'xml'); - } - - $helper = new DescriptorHelper(); - $helper->describe($output, $this->command, $input->getOption('format'), $input->getOption('raw')); - $this->command = null; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Helper\DescriptorHelper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputDefinition; - -/** - * ListCommand displays the list of all available commands for the application. - * - * @author Fabien Potencier - */ -class ListCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setName('list') - ->setDefinition($this->createDefinition()) - ->setDescription('Lists commands') - ->setHelp(<<%command.name% command lists all commands: - - php %command.full_name% - -You can also display the commands for a specific namespace: - - php %command.full_name% test - -You can also output the information in other formats by using the --format option: - - php %command.full_name% --format=xml - -It's also possible to get raw list of commands (useful for embedding command runner): - - php %command.full_name% --raw -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - public function getNativeDefinition() - { - return $this->createDefinition(); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - if ($input->getOption('xml')) { - $input->setOption('format', 'xml'); - } - - $helper = new DescriptorHelper(); - $helper->describe($output, $this->getApplication(), $input->getOption('format'), $input->getOption('raw'), $input->getArgument('namespace')); - } - - /** - * {@inheritdoc} - */ - private function createDefinition() - { - return new InputDefinition(array( - new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), - new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'), - new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats'), - )); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * @author Jean-François Simon - */ -abstract class Descriptor implements DescriptorInterface -{ - public function describe($object, array $options = array()) - { - switch (true) { - case $object instanceof InputArgument: - return $this->describeInputArgument($object, $options); - case $object instanceof InputOption: - return $this->describeInputOption($object, $options); - case $object instanceof InputDefinition: - return $this->describeInputDefinition($object, $options); - case $object instanceof Command: - return $this->describeCommand($object, $options); - case $object instanceof Application: - return $this->describeApplication($object, $options); - } - - throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object))); - } - - /** - * Describes an InputArgument instance. - * - * @param InputArgument $argument - * @param array $options - * - * @return string|mixed - */ - abstract protected function describeInputArgument(InputArgument $argument, array $options = array()); - - /** - * Describes an InputOption instance. - * - * @param InputOption $option - * @param array $options - * - * @return string|mixed - */ - abstract protected function describeInputOption(InputOption $option, array $options = array()); - - /** - * Describes an InputDefinition instance. - * - * @param InputDefinition $definition - * @param array $options - * - * @return string|mixed - */ - abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array()); - - /** - * Describes a Command instance. - * - * @param Command $command - * @param array $options - * - * @return string|mixed - */ - abstract protected function describeCommand(Command $command, array $options = array()); - - /** - * Describes an Application instance. - * - * @param Application $application - * @param array $options - * - * @return string|mixed - */ - abstract protected function describeApplication(Application $application, array $options = array()); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -/** - * Descriptor interface. - * - * @author Jean-François Simon - */ -interface DescriptorInterface -{ - /** - * Describes an InputArgument instance. - * - * @param object $object - * @param array $options - * - * @return string|mixed - */ - public function describe($object, array $options = array()); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * Text descriptor. - * - * @author Jean-François Simon - */ -class TextDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) - { - if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) { - $default = sprintf(' (default: %s)', $this->formatDefaultValue($argument->getDefault())); - } else { - $default = ''; - } - - $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($argument->getName()); - $output = str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription()); - $output = sprintf(" %-${nameWidth}s %s%s", $argument->getName(), $output, $default); - - return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output; - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = array()) - { - if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) { - $default = sprintf(' (default: %s)', $this->formatDefaultValue($option->getDefault())); - } else { - $default = ''; - } - - $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($option->getName()); - $nameWithShortcutWidth = $nameWidth - strlen($option->getName()) - 2; - - $output = sprintf(" %s %-${nameWithShortcutWidth}s%s%s%s", - '--'.$option->getName(), - $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '', - str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $option->getDescription()), - $default, - $option->isArray() ? ' (multiple values allowed)' : '' - ); - - return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output; - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) - { - $nameWidth = 0; - foreach ($definition->getOptions() as $option) { - $nameLength = strlen($option->getName()) + 2; - if ($option->getShortcut()) { - $nameLength += strlen($option->getShortcut()) + 3; - } - $nameWidth = max($nameWidth, $nameLength); - } - foreach ($definition->getArguments() as $argument) { - $nameWidth = max($nameWidth, strlen($argument->getName())); - } - ++$nameWidth; - - $messages = array(); - - if ($definition->getArguments()) { - $messages[] = 'Arguments:'; - foreach ($definition->getArguments() as $argument) { - $messages[] = $this->describeInputArgument($argument, array('name_width' => $nameWidth)); - } - $messages[] = ''; - } - - if ($definition->getOptions()) { - $messages[] = 'Options:'; - foreach ($definition->getOptions() as $option) { - $messages[] = $this->describeInputOption($option, array('name_width' => $nameWidth)); - } - $messages[] = ''; - } - - $output = implode("\n", $messages); - - return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output; - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = array()) - { - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - $messages = array('Usage:', ' '.$command->getSynopsis(), ''); - - if ($command->getAliases()) { - $messages[] = 'Aliases: '.implode(', ', $command->getAliases()).''; - } - - $messages[] = $this->describeInputDefinition($command->getNativeDefinition()); - - if ($help = $command->getProcessedHelp()) { - $messages[] = 'Help:'; - $messages[] = ' '.str_replace("\n", "\n ", $help)."\n"; - } - - $output = implode("\n", $messages); - - return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output; - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = array()) - { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; - $description = new ApplicationDescription($application, $describedNamespace); - $messages = array(); - - if (isset($options['raw_text']) && $options['raw_text']) { - $width = $this->getColumnWidth($description->getCommands()); - - foreach ($description->getCommands() as $command) { - $messages[] = sprintf("%-${width}s %s", $command->getName(), $command->getDescription()); - } - } else { - $width = $this->getColumnWidth($description->getCommands()); - - $messages[] = $application->getHelp(); - $messages[] = ''; - - if ($describedNamespace) { - $messages[] = sprintf("Available commands for the \"%s\" namespace:", $describedNamespace); - } else { - $messages[] = 'Available commands:'; - } - - // add commands by namespace - foreach ($description->getNamespaces() as $namespace) { - if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { - $messages[] = ''.$namespace['id'].''; - } - - foreach ($namespace['commands'] as $name) { - $messages[] = sprintf(" %-${width}s %s", $name, $description->getCommand($name)->getDescription()); - } - } - } - - $output = implode("\n", $messages); - - return isset($options['raw_text']) && $options['raw_text'] ? strip_tags($output) : $output; - } - - /** - * Formats input option/argument default value. - * - * @param mixed $default - * - * @return string - */ - private function formatDefaultValue($default) - { - if (version_compare(PHP_VERSION, '5.4', '<')) { - return str_replace('\/', '/', json_encode($default)); - } - - return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); - } - - /** - * @param Command[] $commands - * - * @return int - */ - private function getColumnWidth(array $commands) - { - $width = 0; - foreach ($commands as $command) { - $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width; - } - - return $width + 2; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * XML descriptor. - * - * @author Jean-François Simon - */ -class XmlDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - - $dom->appendChild($objectXML = $dom->createElement('argument')); - $objectXML->setAttribute('name', $argument->getName()); - $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); - $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); - $objectXML->appendChild($descriptionXML = $dom->createElement('description')); - $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); - - $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); - $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array())); - foreach ($defaults as $default) { - $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); - $defaultXML->appendChild($dom->createTextNode($default)); - } - - return $this->output($dom, $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = array()) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - - $dom->appendChild($objectXML = $dom->createElement('option')); - $objectXML->setAttribute('name', '--'.$option->getName()); - $pos = strpos($option->getShortcut(), '|'); - if (false !== $pos) { - $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); - $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut()))); - } else { - $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); - } - $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); - $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); - $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); - $objectXML->appendChild($descriptionXML = $dom->createElement('description')); - $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); - - if ($option->acceptValue()) { - $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array())); - $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); - - if (!empty($defaults)) { - foreach ($defaults as $default) { - $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); - $defaultXML->appendChild($dom->createTextNode($default)); - } - } - } - - return $this->output($dom, $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($definitionXML = $dom->createElement('definition')); - - $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); - foreach ($definition->getArguments() as $argument) { - $this->appendDocument($argumentsXML, $this->describeInputArgument($argument, array('as_dom' => true))); - } - - $definitionXML->appendChild($optionsXML = $dom->createElement('options')); - foreach ($definition->getOptions() as $option) { - $this->appendDocument($optionsXML, $this->describeInputOption($option, array('as_dom' => true))); - } - - return $this->output($dom, $options); - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = array()) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($commandXML = $dom->createElement('command')); - - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - - $commandXML->setAttribute('id', $command->getName()); - $commandXML->setAttribute('name', $command->getName()); - - $commandXML->appendChild($usageXML = $dom->createElement('usage')); - $usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), ''))); - - $commandXML->appendChild($descriptionXML = $dom->createElement('description')); - $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); - - $commandXML->appendChild($helpXML = $dom->createElement('help')); - $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); - - $commandXML->appendChild($aliasesXML = $dom->createElement('aliases')); - foreach ($command->getAliases() as $alias) { - $aliasesXML->appendChild($aliasXML = $dom->createElement('alias')); - $aliasXML->appendChild($dom->createTextNode($alias)); - } - - $definitionXML = $this->describeInputDefinition($command->getNativeDefinition(), array('as_dom' => true)); - $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); - - return $this->output($dom, $options); - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = array()) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($rootXml = $dom->createElement('symfony')); - $rootXml->appendChild($commandsXML = $dom->createElement('commands')); - - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; - $description = new ApplicationDescription($application, $describedNamespace); - - if ($describedNamespace) { - $commandsXML->setAttribute('namespace', $describedNamespace); - } - - foreach ($description->getCommands() as $command) { - $this->appendDocument($commandsXML, $this->describeCommand($command, array('as_dom' => true))); - } - - if (!$describedNamespace) { - $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); - - foreach ($description->getNamespaces() as $namespace) { - $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); - $namespaceArrayXML->setAttribute('id', $namespace['id']); - - foreach ($namespace['commands'] as $name) { - $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); - $commandXML->appendChild($dom->createTextNode($name)); - } - } - } - - return $this->output($dom, $options); - } - - /** - * Appends document children to parent node. - * - * @param \DOMNode $parentNode - * @param \DOMNode $importedParent - */ - private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) - { - foreach ($importedParent->childNodes as $childNode) { - $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); - } - } - - /** - * Outputs document as DOMDocument or string according to options. - * - * @param \DOMDocument $dom - * @param array $options - * - * @return \DOMDocument|string - */ - private function output(\DOMDocument $dom, array $options) - { - if (isset($options['as_dom']) && $options['as_dom']) { - return $dom; - } - - $dom->formatOutput = true; - - return $dom->saveXML(); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; - -/** - * @author Jean-François Simon - */ -class ApplicationDescription -{ - const GLOBAL_NAMESPACE = '_global'; - - /** - * @var Application - */ - private $application; - - /** - * @var null|string - */ - private $namespace; - - /** - * @var array - */ - private $namespaces; - - /** - * @var Command[] - */ - private $commands; - - /** - * @var Command[] - */ - private $aliases; - - /** - * Constructor. - * - * @param Application $application - * @param string|null $namespace - */ - public function __construct(Application $application, $namespace = null) - { - $this->application = $application; - $this->namespace = $namespace; - } - - /** - * @return array - */ - public function getNamespaces() - { - if (null === $this->namespaces) { - $this->inspectApplication(); - } - - return $this->namespaces; - } - - /** - * @return Command[] - */ - public function getCommands() - { - if (null === $this->commands) { - $this->inspectApplication(); - } - - return $this->commands; - } - - /** - * @param string $name - * - * @return Command - * - * @throws \InvalidArgumentException - */ - public function getCommand($name) - { - if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { - throw new \InvalidArgumentException(sprintf('Command %s does not exist.', $name)); - } - - return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; - } - - private function inspectApplication() - { - $this->commands = array(); - $this->namespaces = array(); - - $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null); - foreach ($this->sortCommands($all) as $namespace => $commands) { - $names = array(); - - /** @var Command $command */ - foreach ($commands as $name => $command) { - if (!$command->getName()) { - continue; - } - - if ($command->getName() === $name) { - $this->commands[$name] = $command; - } else { - $this->aliases[$name] = $command; - } - - $names[] = $name; - } - - $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names); - } - } - - /** - * @param array $commands - * - * @return array - */ - private function sortCommands(array $commands) - { - $namespacedCommands = array(); - foreach ($commands as $name => $command) { - $key = $this->application->extractNamespace($name, 1); - if (!$key) { - $key = '_global'; - } - - $namespacedCommands[$key][$name] = $command; - } - ksort($namespacedCommands); - - foreach ($namespacedCommands as &$commands) { - ksort($commands); - } - - return $namespacedCommands; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * JSON descriptor. - * - * @author Jean-François Simon - */ -class JsonDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) - { - return $this->output(array( - 'name' => $argument->getName(), - 'is_required' => $argument->isRequired(), - 'is_array' => $argument->isArray(), - 'description' => $argument->getDescription(), - 'default' => $argument->getDefault(), - ), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = array()) - { - return $this->output(array( - 'name' => '--'.$option->getName(), - 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '', - 'accept_value' => $option->acceptValue(), - 'is_value_required' => $option->isValueRequired(), - 'is_multiple' => $option->isArray(), - 'description' => $option->getDescription(), - 'default' => $option->getDefault(), - ), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) - { - $inputArguments = array(); - foreach ($definition->getArguments() as $name => $argument) { - $inputArguments[$name] = $this->describeInputArgument($argument, array('as_array' => true)); - } - - $inputOptions = array(); - foreach ($definition->getOptions() as $name => $option) { - $inputOptions[$name] = $this->describeInputOption($option, array('as_array' => true)); - } - - return $this->output(array('arguments' => $inputArguments, 'options' => $inputOptions), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = array()) - { - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - - return $this->output(array( - 'name' => $command->getName(), - 'usage' => $command->getSynopsis(), - 'description' => $command->getDescription(), - 'help' => $command->getProcessedHelp(), - 'aliases' => $command->getAliases(), - 'definition' => $this->describeInputDefinition($command->getNativeDefinition(), array('as_array' => true)), - ), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = array()) - { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; - $description = new ApplicationDescription($application, $describedNamespace); - $commands = array(); - - foreach ($description->getCommands() as $command) { - $commands[] = $this->describeCommand($command, array('as_array' => true)); - } - - $data = $describedNamespace - ? array('commands' => $commands, 'namespace' => $describedNamespace) - : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces())); - - return $this->output($data, $options); - } - - /** - * Outputs data as array or string according to options. - * - * @param array $data - * @param array $options - * - * @return array|string - */ - private function output(array $data, array $options) - { - if (isset($options['as_array']) && $options['as_array']) { - return $data; - } - - return json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * Markdown descriptor. - * - * @author Jean-François Simon - */ -class MarkdownDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) - { - return '**'.$argument->getName().':**'."\n\n" - .'* Name: '.($argument->getName() ?: '')."\n" - .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" - .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" - .'* Description: '.($argument->getDescription() ?: '')."\n" - .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'; - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = array()) - { - return '**'.$option->getName().':**'."\n\n" - .'* Name: `--'.$option->getName().'`'."\n" - .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '')."\n" - .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" - .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" - .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" - .'* Description: '.($option->getDescription() ?: '')."\n" - .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'; - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) - { - $blocks = array(); - - if (count($definition->getArguments()) > 0) { - $blocks[] = '### Arguments:'; - foreach ($definition->getArguments() as $argument) { - $blocks[] = $this->describeInputArgument($argument); - } - } - - if (count($definition->getOptions()) > 0) { - $blocks[] = '### Options:'; - foreach ($definition->getOptions() as $option) { - $blocks[] = $this->describeInputOption($option); - } - } - - return implode("\n\n", $blocks); - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = array()) - { - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - - $markdown = $command->getName()."\n" - .str_repeat('-', strlen($command->getName()))."\n\n" - .'* Description: '.($command->getDescription() ?: '')."\n" - .'* Usage: `'.$command->getSynopsis().'`'."\n" - .'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : ''); - - if ($help = $command->getProcessedHelp()) { - $markdown .= "\n\n".$help; - } - - if ($definitionMarkdown = $this->describeInputDefinition($command->getNativeDefinition())) { - $markdown .= "\n\n".$definitionMarkdown; - } - - return $markdown; - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = array()) - { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; - $description = new ApplicationDescription($application, $describedNamespace); - $blocks = array($application->getName()."\n".str_repeat('=', strlen($application->getName()))); - - foreach ($description->getNamespaces() as $namespace) { - if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { - $blocks[] = '**'.$namespace['id'].':**'; - } - - $blocks[] = implode("\n", array_map(function ($commandName) { - return '* '.$commandName; - } , $namespace['commands'])); - } - - foreach ($description->getCommands() as $command) { - $blocks[] = $this->describeCommand($command); - } - - return implode("\n\n", $blocks); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Command\HelpCommand; -use Symfony\Component\Console\Command\ListCommand; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Helper\FormatterHelper; -use Symfony\Component\Console\Helper\DialogHelper; -use Symfony\Component\Console\Helper\ProgressHelper; -use Symfony\Component\Console\Helper\TableHelper; -use Symfony\Component\Console\Event\ConsoleCommandEvent; -use Symfony\Component\Console\Event\ConsoleExceptionEvent; -use Symfony\Component\Console\Event\ConsoleTerminateEvent; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; - -/** - * An Application is the container for a collection of commands. - * - * It is the main entry point of a Console application. - * - * This class is optimized for a standard CLI environment. - * - * Usage: - * - * $app = new Application('myapp', '1.0 (stable)'); - * $app->add(new SimpleCommand()); - * $app->run(); - * - * @author Fabien Potencier - * - * @api - */ -class Application -{ - private $commands; - private $wantHelps = false; - private $runningCommand; - private $name; - private $version; - private $catchExceptions; - private $autoExit; - private $definition; - private $helperSet; - private $dispatcher; - - /** - * Constructor. - * - * @param string $name The name of the application - * @param string $version The version of the application - * - * @api - */ - public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') - { - $this->name = $name; - $this->version = $version; - $this->catchExceptions = true; - $this->autoExit = true; - $this->commands = array(); - $this->helperSet = $this->getDefaultHelperSet(); - $this->definition = $this->getDefaultInputDefinition(); - - foreach ($this->getDefaultCommands() as $command) { - $this->add($command); - } - } - - public function setDispatcher(EventDispatcherInterface $dispatcher) - { - $this->dispatcher = $dispatcher; - } - - /** - * Runs the current application. - * - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * - * @return integer 0 if everything went fine, or an error code - * - * @throws \Exception When doRun returns Exception - * - * @api - */ - public function run(InputInterface $input = null, OutputInterface $output = null) - { - if (null === $input) { - $input = new ArgvInput(); - } - - if (null === $output) { - $output = new ConsoleOutput(); - } - - $this->configureIO($input, $output); - - try { - $exitCode = $this->doRun($input, $output); - } catch (\Exception $e) { - if (!$this->catchExceptions) { - throw $e; - } - - if ($output instanceof ConsoleOutputInterface) { - $this->renderException($e, $output->getErrorOutput()); - } else { - $this->renderException($e, $output); - } - - $exitCode = $e->getCode(); - if (is_numeric($exitCode)) { - $exitCode = (int) $exitCode; - if (0 === $exitCode) { - $exitCode = 1; - } - } else { - $exitCode = 1; - } - } - - if ($this->autoExit) { - if ($exitCode > 255) { - $exitCode = 255; - } - // @codeCoverageIgnoreStart - exit($exitCode); - // @codeCoverageIgnoreEnd - } - - return $exitCode; - } - - /** - * Runs the current application. - * - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * - * @return integer 0 if everything went fine, or an error code - */ - public function doRun(InputInterface $input, OutputInterface $output) - { - if (true === $input->hasParameterOption(array('--version', '-V'))) { - $output->writeln($this->getLongVersion()); - - return 0; - } - - $name = $this->getCommandName($input); - if (true === $input->hasParameterOption(array('--help', '-h'))) { - if (!$name) { - $name = 'help'; - $input = new ArrayInput(array('command' => 'help')); - } else { - $this->wantHelps = true; - } - } - - if (!$name) { - $name = 'list'; - $input = new ArrayInput(array('command' => 'list')); - } - - // the command name MUST be the first element of the input - $command = $this->find($name); - - $this->runningCommand = $command; - $exitCode = $this->doRunCommand($command, $input, $output); - $this->runningCommand = null; - - return $exitCode; - } - - /** - * Set a helper set to be used with the command. - * - * @param HelperSet $helperSet The helper set - * - * @api - */ - public function setHelperSet(HelperSet $helperSet) - { - $this->helperSet = $helperSet; - } - - /** - * Get the helper set associated with the command. - * - * @return HelperSet The HelperSet instance associated with this command - * - * @api - */ - public function getHelperSet() - { - return $this->helperSet; - } - - /** - * Set an input definition set to be used with this application - * - * @param InputDefinition $definition The input definition - * - * @api - */ - public function setDefinition(InputDefinition $definition) - { - $this->definition = $definition; - } - - /** - * Gets the InputDefinition related to this Application. - * - * @return InputDefinition The InputDefinition instance - */ - public function getDefinition() - { - return $this->definition; - } - - /** - * Gets the help message. - * - * @return string A help message. - */ - public function getHelp() - { - $messages = array( - $this->getLongVersion(), - '', - 'Usage:', - ' [options] command [arguments]', - '', - 'Options:', - ); - - foreach ($this->getDefinition()->getOptions() as $option) { - $messages[] = sprintf(' %-29s %s %s', - '--'.$option->getName().'', - $option->getShortcut() ? '-'.$option->getShortcut().'' : ' ', - $option->getDescription() - ); - } - - return implode(PHP_EOL, $messages); - } - - /** - * Sets whether to catch exceptions or not during commands execution. - * - * @param Boolean $boolean Whether to catch exceptions or not during commands execution - * - * @api - */ - public function setCatchExceptions($boolean) - { - $this->catchExceptions = (Boolean) $boolean; - } - - /** - * Sets whether to automatically exit after a command execution or not. - * - * @param Boolean $boolean Whether to automatically exit after a command execution or not - * - * @api - */ - public function setAutoExit($boolean) - { - $this->autoExit = (Boolean) $boolean; - } - - /** - * Gets the name of the application. - * - * @return string The application name - * - * @api - */ - public function getName() - { - return $this->name; - } - - /** - * Sets the application name. - * - * @param string $name The application name - * - * @api - */ - public function setName($name) - { - $this->name = $name; - } - - /** - * Gets the application version. - * - * @return string The application version - * - * @api - */ - public function getVersion() - { - return $this->version; - } - - /** - * Sets the application version. - * - * @param string $version The application version - * - * @api - */ - public function setVersion($version) - { - $this->version = $version; - } - - /** - * Returns the long version of the application. - * - * @return string The long application version - * - * @api - */ - public function getLongVersion() - { - if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) { - return sprintf('%s version %s', $this->getName(), $this->getVersion()); - } - - return 'Console Tool'; - } - - /** - * Registers a new command. - * - * @param string $name The command name - * - * @return Command The newly created command - * - * @api - */ - public function register($name) - { - return $this->add(new Command($name)); - } - - /** - * Adds an array of command objects. - * - * @param Command[] $commands An array of commands - * - * @api - */ - public function addCommands(array $commands) - { - foreach ($commands as $command) { - $this->add($command); - } - } - - /** - * Adds a command object. - * - * If a command with the same name already exists, it will be overridden. - * - * @param Command $command A Command object - * - * @return Command The registered command - * - * @api - */ - public function add(Command $command) - { - $command->setApplication($this); - - if (!$command->isEnabled()) { - $command->setApplication(null); - - return; - } - - $this->commands[$command->getName()] = $command; - - foreach ($command->getAliases() as $alias) { - $this->commands[$alias] = $command; - } - - return $command; - } - - /** - * Returns a registered command by name or alias. - * - * @param string $name The command name or alias - * - * @return Command A Command object - * - * @throws \InvalidArgumentException When command name given does not exist - * - * @api - */ - public function get($name) - { - if (!isset($this->commands[$name])) { - throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name)); - } - - $command = $this->commands[$name]; - - if ($this->wantHelps) { - $this->wantHelps = false; - - $helpCommand = $this->get('help'); - $helpCommand->setCommand($command); - - return $helpCommand; - } - - return $command; - } - - /** - * Returns true if the command exists, false otherwise. - * - * @param string $name The command name or alias - * - * @return Boolean true if the command exists, false otherwise - * - * @api - */ - public function has($name) - { - return isset($this->commands[$name]); - } - - /** - * Returns an array of all unique namespaces used by currently registered commands. - * - * It does not returns the global namespace which always exists. - * - * @return array An array of namespaces - */ - public function getNamespaces() - { - $namespaces = array(); - foreach ($this->commands as $command) { - $namespaces[] = $this->extractNamespace($command->getName()); - - foreach ($command->getAliases() as $alias) { - $namespaces[] = $this->extractNamespace($alias); - } - } - - return array_values(array_unique(array_filter($namespaces))); - } - - /** - * Finds a registered namespace by a name or an abbreviation. - * - * @param string $namespace A namespace or abbreviation to search for - * - * @return string A registered namespace - * - * @throws \InvalidArgumentException When namespace is incorrect or ambiguous - */ - public function findNamespace($namespace) - { - $allNamespaces = $this->getNamespaces(); - $found = ''; - foreach (explode(':', $namespace) as $i => $part) { - // select sub-namespaces matching the current namespace we found - $namespaces = array(); - foreach ($allNamespaces as $n) { - if ('' === $found || 0 === strpos($n, $found)) { - $namespaces[$n] = explode(':', $n); - } - } - - $abbrevs = static::getAbbreviations(array_unique(array_values(array_filter(array_map(function ($p) use ($i) { return isset($p[$i]) ? $p[$i] : ''; }, $namespaces))))); - - if (!isset($abbrevs[$part])) { - $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); - - if (1 <= $i) { - $part = $found.':'.$part; - } - - if ($alternatives = $this->findAlternativeNamespace($part, $abbrevs)) { - if (1 == count($alternatives)) { - $message .= "\n\nDid you mean this?\n "; - } else { - $message .= "\n\nDid you mean one of these?\n "; - } - - $message .= implode("\n ", $alternatives); - } - - throw new \InvalidArgumentException($message); - } - - // there are multiple matches, but $part is an exact match of one of them so we select it - if (in_array($part, $abbrevs[$part])) { - $abbrevs[$part] = array($part); - } - - if (count($abbrevs[$part]) > 1) { - throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions($abbrevs[$part]))); - } - - $found .= $found ? ':' . $abbrevs[$part][0] : $abbrevs[$part][0]; - } - - return $found; - } - - /** - * Finds a command by name or alias. - * - * Contrary to get, this command tries to find the best - * match if you give it an abbreviation of a name or alias. - * - * @param string $name A command name or a command alias - * - * @return Command A Command instance - * - * @throws \InvalidArgumentException When command name is incorrect or ambiguous - * - * @api - */ - public function find($name) - { - // namespace - $namespace = ''; - $searchName = $name; - if (false !== $pos = strrpos($name, ':')) { - $namespace = $this->findNamespace(substr($name, 0, $pos)); - $searchName = $namespace.substr($name, $pos); - } - - // name - $commands = array(); - foreach ($this->commands as $command) { - $extractedNamespace = $this->extractNamespace($command->getName()); - if ($extractedNamespace === $namespace - || !empty($namespace) && 0 === strpos($extractedNamespace, $namespace) - ) { - $commands[] = $command->getName(); - } - } - - $abbrevs = static::getAbbreviations(array_unique($commands)); - if (isset($abbrevs[$searchName]) && 1 == count($abbrevs[$searchName])) { - return $this->get($abbrevs[$searchName][0]); - } - - if (isset($abbrevs[$searchName]) && in_array($searchName, $abbrevs[$searchName])) { - return $this->get($searchName); - } - - if (isset($abbrevs[$searchName]) && count($abbrevs[$searchName]) > 1) { - $suggestions = $this->getAbbreviationSuggestions($abbrevs[$searchName]); - - throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions)); - } - - // aliases - $aliases = array(); - foreach ($this->commands as $command) { - foreach ($command->getAliases() as $alias) { - $extractedNamespace = $this->extractNamespace($alias); - if ($extractedNamespace === $namespace - || !empty($namespace) && 0 === strpos($extractedNamespace, $namespace) - ) { - $aliases[] = $alias; - } - } - } - - $aliases = static::getAbbreviations(array_unique($aliases)); - if (!isset($aliases[$searchName])) { - $message = sprintf('Command "%s" is not defined.', $name); - - if ($alternatives = $this->findAlternativeCommands($searchName, $abbrevs)) { - if (1 == count($alternatives)) { - $message .= "\n\nDid you mean this?\n "; - } else { - $message .= "\n\nDid you mean one of these?\n "; - } - $message .= implode("\n ", $alternatives); - } - - throw new \InvalidArgumentException($message); - } - - if (count($aliases[$searchName]) > 1) { - throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $this->getAbbreviationSuggestions($aliases[$searchName]))); - } - - return $this->get($aliases[$searchName][0]); - } - - /** - * Gets the commands (registered in the given namespace if provided). - * - * The array keys are the full names and the values the command instances. - * - * @param string $namespace A namespace name - * - * @return Command[] An array of Command instances - * - * @api - */ - public function all($namespace = null) - { - if (null === $namespace) { - return $this->commands; - } - - $commands = array(); - foreach ($this->commands as $name => $command) { - if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { - $commands[$name] = $command; - } - } - - return $commands; - } - - /** - * Returns an array of possible abbreviations given a set of names. - * - * @param array $names An array of names - * - * @return array An array of abbreviations - */ - public static function getAbbreviations($names) - { - $abbrevs = array(); - foreach ($names as $name) { - for ($len = strlen($name); $len > 0; --$len) { - $abbrev = substr($name, 0, $len); - $abbrevs[$abbrev][] = $name; - } - } - - return $abbrevs; - } - - /** - * Returns a text representation of the Application. - * - * @param string $namespace An optional namespace name - * @param boolean $raw Whether to return raw command list - * - * @return string A string representing the Application - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asText($namespace = null, $raw = false) - { - $descriptor = new TextDescriptor(); - - return $descriptor->describe($this, array('namespace' => $namespace, 'raw_text' => $raw)); - } - - /** - * Returns an XML representation of the Application. - * - * @param string $namespace An optional namespace name - * @param Boolean $asDom Whether to return a DOM or an XML string - * - * @return string|\DOMDocument An XML string representing the Application - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asXml($namespace = null, $asDom = false) - { - $descriptor = new XmlDescriptor(); - - return $descriptor->describe($this, array('namespace' => $namespace, 'as_dom' => $asDom)); - } - - /** - * Renders a caught exception. - * - * @param \Exception $e An exception instance - * @param OutputInterface $output An OutputInterface instance - */ - public function renderException($e, $output) - { - $strlen = function ($string) { - if (!function_exists('mb_strlen')) { - return strlen($string); - } - - if (false === $encoding = mb_detect_encoding($string)) { - return strlen($string); - } - - return mb_strlen($string, $encoding); - }; - - do { - $title = sprintf(' [%s] ', get_class($e)); - $len = $strlen($title); - $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX; - $formatter = $output->getFormatter(); - $lines = array(); - foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) { - foreach (str_split($line, $width - 4) as $line) { - // pre-format lines to get the right string length - $lineLength = $strlen(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4; - $lines[] = array($line, $lineLength); - - $len = max($lineLength, $len); - } - } - - $messages = array('', ''); - $messages[] = $emptyLine = $formatter->format(sprintf('%s', str_repeat(' ', $len))); - $messages[] = $formatter->format(sprintf('%s%s', $title, str_repeat(' ', max(0, $len - $strlen($title))))); - foreach ($lines as $line) { - $messages[] = $formatter->format(sprintf(' %s %s', $line[0], str_repeat(' ', $len - $line[1]))); - } - $messages[] = $emptyLine; - $messages[] = ''; - $messages[] = ''; - - $output->writeln($messages, OutputInterface::OUTPUT_RAW); - - if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $output->writeln('Exception trace:'); - - // exception related properties - $trace = $e->getTrace(); - array_unshift($trace, array( - 'function' => '', - 'file' => $e->getFile() != null ? $e->getFile() : 'n/a', - 'line' => $e->getLine() != null ? $e->getLine() : 'n/a', - 'args' => array(), - )); - - for ($i = 0, $count = count($trace); $i < $count; $i++) { - $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; - $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; - $function = $trace[$i]['function']; - $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; - $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; - - $output->writeln(sprintf(' %s%s%s() at %s:%s', $class, $type, $function, $file, $line)); - } - - $output->writeln(""); - $output->writeln(""); - } - } while ($e = $e->getPrevious()); - - if (null !== $this->runningCommand) { - $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName()))); - $output->writeln(""); - $output->writeln(""); - } - } - - /** - * Tries to figure out the terminal width in which this application runs - * - * @return int|null - */ - protected function getTerminalWidth() - { - $dimensions = $this->getTerminalDimensions(); - - return $dimensions[0]; - } - - /** - * Tries to figure out the terminal height in which this application runs - * - * @return int|null - */ - protected function getTerminalHeight() - { - $dimensions = $this->getTerminalDimensions(); - - return $dimensions[1]; - } - - /** - * Tries to figure out the terminal dimensions based on the current environment - * - * @return array Array containing width and height - */ - public function getTerminalDimensions() - { - if (defined('PHP_WINDOWS_VERSION_BUILD')) { - // extract [w, H] from "wxh (WxH)" - if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) { - return array((int) $matches[1], (int) $matches[2]); - } - // extract [w, h] from "wxh" - if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) { - return array((int) $matches[1], (int) $matches[2]); - } - } - - if ($sttyString = $this->getSttyColumns()) { - // extract [w, h] from "rows h; columns w;" - if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { - return array((int) $matches[2], (int) $matches[1]); - } - // extract [w, h] from "; h rows; w columns" - if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { - return array((int) $matches[2], (int) $matches[1]); - } - } - - return array(null, null); - } - - /** - * Configures the input and output instances based on the user arguments and options. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - */ - protected function configureIO(InputInterface $input, OutputInterface $output) - { - if (true === $input->hasParameterOption(array('--ansi'))) { - $output->setDecorated(true); - } elseif (true === $input->hasParameterOption(array('--no-ansi'))) { - $output->setDecorated(false); - } - - if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) { - $input->setInteractive(false); - } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('dialog')) { - $inputStream = $this->getHelperSet()->get('dialog')->getInputStream(); - if (!@posix_isatty($inputStream)) { - $input->setInteractive(false); - } - } - - if (true === $input->hasParameterOption(array('--quiet', '-q'))) { - $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); - } else { - if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) { - $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); - } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) { - $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); - } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) { - $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); - } - } - } - - /** - * Runs the current command. - * - * If an event dispatcher has been attached to the application, - * events are also dispatched during the life-cycle of the command. - * - * @param Command $command A Command instance - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * - * @return integer 0 if everything went fine, or an error code - */ - protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) - { - if (null === $this->dispatcher) { - return $command->run($input, $output); - } - - $event = new ConsoleCommandEvent($command, $input, $output); - $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event); - - try { - $exitCode = $command->run($input, $output); - } catch (\Exception $e) { - $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode()); - $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); - - $event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode()); - $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); - - throw $event->getException(); - } - - $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); - $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); - - return $event->getExitCode(); - } - - /** - * Gets the name of the command based on input. - * - * @param InputInterface $input The input interface - * - * @return string The command name - */ - protected function getCommandName(InputInterface $input) - { - return $input->getFirstArgument(); - } - - /** - * Gets the default input definition. - * - * @return InputDefinition An InputDefinition instance - */ - protected function getDefaultInputDefinition() - { - return new InputDefinition(array( - new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), - - new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message.'), - new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message.'), - new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), - new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version.'), - new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output.'), - new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output.'), - new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question.'), - )); - } - - /** - * Gets the default commands that should always be available. - * - * @return Command[] An array of default Command instances - */ - protected function getDefaultCommands() - { - return array(new HelpCommand(), new ListCommand()); - } - - /** - * Gets the default helper set with the helpers that should always be available. - * - * @return HelperSet A HelperSet instance - */ - protected function getDefaultHelperSet() - { - return new HelperSet(array( - new FormatterHelper(), - new DialogHelper(), - new ProgressHelper(), - new TableHelper(), - )); - } - - /** - * Runs and parses stty -a if it's available, suppressing any error output - * - * @return string - */ - private function getSttyColumns() - { - if (!function_exists('proc_open')) { - return; - } - - $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); - $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); - if (is_resource($process)) { - $info = stream_get_contents($pipes[1]); - fclose($pipes[1]); - fclose($pipes[2]); - proc_close($process); - - return $info; - } - } - - /** - * Runs and parses mode CON if it's available, suppressing any error output - * - * @return string x or null if it could not be parsed - */ - private function getConsoleMode() - { - if (!function_exists('proc_open')) { - return; - } - - $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); - $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); - if (is_resource($process)) { - $info = stream_get_contents($pipes[1]); - fclose($pipes[1]); - fclose($pipes[2]); - proc_close($process); - - if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { - return $matches[2].'x'.$matches[1]; - } - } - } - - /** - * Returns abbreviated suggestions in string format. - * - * @param array $abbrevs Abbreviated suggestions to convert - * - * @return string A formatted string of abbreviated suggestions - */ - private function getAbbreviationSuggestions($abbrevs) - { - return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : ''); - } - - /** - * Returns the namespace part of the command name. - * - * This method is not part of public API and should not be used directly. - * - * @param string $name The full name of the command - * @param string $limit The maximum number of parts of the namespace - * - * @return string The namespace of the command - */ - public function extractNamespace($name, $limit = null) - { - $parts = explode(':', $name); - array_pop($parts); - - return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit)); - } - - /** - * Finds alternative commands of $name - * - * @param string $name The full name of the command - * @param array $abbrevs The abbreviations - * - * @return array A sorted array of similar commands - */ - private function findAlternativeCommands($name, $abbrevs) - { - $callback = function($item) { - return $item->getName(); - }; - - return $this->findAlternatives($name, $this->commands, $abbrevs, $callback); - } - - /** - * Finds alternative namespace of $name - * - * @param string $name The full name of the namespace - * @param array $abbrevs The abbreviations - * - * @return array A sorted array of similar namespace - */ - private function findAlternativeNamespace($name, $abbrevs) - { - return $this->findAlternatives($name, $this->getNamespaces(), $abbrevs); - } - - /** - * Finds alternative of $name among $collection, - * if nothing is found in $collection, try in $abbrevs - * - * @param string $name The string - * @param array|Traversable $collection The collection - * @param array $abbrevs The abbreviations - * @param Closure|string|array $callback The callable to transform collection item before comparison - * - * @return array A sorted array of similar string - */ - private function findAlternatives($name, $collection, $abbrevs, $callback = null) - { - $alternatives = array(); - - foreach ($collection as $item) { - if (null !== $callback) { - $item = call_user_func($callback, $item); - } - - $lev = levenshtein($name, $item); - if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { - $alternatives[$item] = $lev; - } - } - - if (!$alternatives) { - foreach ($abbrevs as $key => $values) { - $lev = levenshtein($name, $key); - if ($lev <= strlen($name) / 3 || false !== strpos($key, $name)) { - foreach ($values as $value) { - $alternatives[$value] = $lev; - } - } - } - } - - asort($alternatives); - - return array_keys($alternatives); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -/** - * Contains all events dispatched by an Application. - * - * @author Francesco Levorato - */ -final class ConsoleEvents -{ - /** - * The COMMAND event allows you to attach listeners before any command is - * executed by the console. It also allows you to modify the command, input and output - * before they are handled to the command. - * - * The event listener method receives a Symfony\Component\Console\Event\ConsoleCommandEvent - * instance. - * - * @var string - */ - const COMMAND = 'console.command'; - - /** - * The TERMINATE event allows you to attach listeners after a command is - * executed by the console. - * - * The event listener method receives a Symfony\Component\Console\Event\ConsoleTerminateEvent - * instance. - * - * @var string - */ - const TERMINATE = 'console.terminate'; - - /** - * The EXCEPTION event occurs when an uncaught exception appears. - * - * This event allows you to deal with the exception or - * to modify the thrown exception. The event listener method receives - * a Symfony\Component\Console\Event\ConsoleExceptionEvent - * instance. - * - * @var string - */ - const EXCEPTION = 'console.exception'; -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -/** - * Helper is the base class for all helper classes. - * - * @author Fabien Potencier - */ -abstract class Helper implements HelperInterface -{ - protected $helperSet = null; - - /** - * Sets the helper set associated with this helper. - * - * @param HelperSet $helperSet A HelperSet instance - */ - public function setHelperSet(HelperSet $helperSet = null) - { - $this->helperSet = $helperSet; - } - - /** - * Gets the helper set associated with this helper. - * - * @return HelperSet A HelperSet instance - */ - public function getHelperSet() - { - return $this->helperSet; - } - - /** - * Returns the length of a string, using mb_strlen if it is available. - * - * @param string $string The string to check its length - * - * @return integer The length of the string - */ - protected function strlen($string) - { - if (!function_exists('mb_strlen')) { - return strlen($string); - } - - if (false === $encoding = mb_detect_encoding($string)) { - return strlen($string); - } - - return mb_strlen($string, $encoding); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Command\Command; - -/** - * HelperSet represents a set of helpers to be used with a command. - * - * @author Fabien Potencier - */ -class HelperSet -{ - private $helpers; - private $command; - - /** - * Constructor. - * - * @param Helper[] $helpers An array of helper. - */ - public function __construct(array $helpers = array()) - { - $this->helpers = array(); - foreach ($helpers as $alias => $helper) { - $this->set($helper, is_int($alias) ? null : $alias); - } - } - - /** - * Sets a helper. - * - * @param HelperInterface $helper The helper instance - * @param string $alias An alias - */ - public function set(HelperInterface $helper, $alias = null) - { - $this->helpers[$helper->getName()] = $helper; - if (null !== $alias) { - $this->helpers[$alias] = $helper; - } - - $helper->setHelperSet($this); - } - - /** - * Returns true if the helper if defined. - * - * @param string $name The helper name - * - * @return Boolean true if the helper is defined, false otherwise - */ - public function has($name) - { - return isset($this->helpers[$name]); - } - - /** - * Gets a helper value. - * - * @param string $name The helper name - * - * @return HelperInterface The helper instance - * - * @throws \InvalidArgumentException if the helper is not defined - */ - public function get($name) - { - if (!$this->has($name)) { - throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); - } - - return $this->helpers[$name]; - } - - /** - * Sets the command associated with this helper set. - * - * @param Command $command A Command instance - */ - public function setCommand(Command $command = null) - { - $this->command = $command; - } - - /** - * Gets the command associated with this helper set. - * - * @return Command A Command instance - */ - public function getCommand() - { - return $this->command; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Output\OutputInterface; -use InvalidArgumentException; - -/** - * Provides helpers to display table output. - * - * @author Саша Стаменковић - */ -class TableHelper extends Helper -{ - const LAYOUT_DEFAULT = 0; - const LAYOUT_BORDERLESS = 1; - - /** - * Table headers. - * - * @var array - */ - private $headers = array(); - - /** - * Table rows. - * - * @var array - */ - private $rows = array(); - - // Rendering options - private $paddingChar; - private $horizontalBorderChar; - private $verticalBorderChar; - private $crossingChar; - private $cellHeaderFormat; - private $cellRowFormat; - private $borderFormat; - private $padType; - - /** - * Column widths cache. - * - * @var array - */ - private $columnWidths = array(); - - /** - * Number of columns cache. - * - * @var array - */ - private $numberOfColumns; - - /** - * @var OutputInterface - */ - private $output; - - public function __construct() - { - $this->setLayout(self::LAYOUT_DEFAULT); - } - - /** - * Sets table layout type. - * - * @param int $layout self::LAYOUT_* - * - * @return TableHelper - */ - public function setLayout($layout) - { - switch ($layout) { - case self::LAYOUT_BORDERLESS: - $this - ->setPaddingChar(' ') - ->setHorizontalBorderChar('=') - ->setVerticalBorderChar(' ') - ->setCrossingChar(' ') - ->setCellHeaderFormat('%s') - ->setCellRowFormat('%s') - ->setBorderFormat('%s') - ->setPadType(STR_PAD_RIGHT) - ; - break; - - case self::LAYOUT_DEFAULT: - $this - ->setPaddingChar(' ') - ->setHorizontalBorderChar('-') - ->setVerticalBorderChar('|') - ->setCrossingChar('+') - ->setCellHeaderFormat('%s') - ->setCellRowFormat('%s') - ->setBorderFormat('%s') - ->setPadType(STR_PAD_RIGHT) - ; - break; - - default: - throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout)); - break; - }; - - return $this; - } - - public function setHeaders(array $headers) - { - $this->headers = array_values($headers); - - return $this; - } - - public function setRows(array $rows) - { - $this->rows = array(); - - return $this->addRows($rows); - } - - public function addRows(array $rows) - { - foreach ($rows as $row) { - $this->addRow($row); - } - - return $this; - } - - public function addRow(array $row) - { - $this->rows[] = array_values($row); - - return $this; - } - - public function setRow($column, array $row) - { - $this->rows[$column] = $row; - - return $this; - } - - /** - * Sets padding character, used for cell padding. - * - * @param string $paddingChar - * - * @return TableHelper - */ - public function setPaddingChar($paddingChar) - { - $this->paddingChar = $paddingChar; - - return $this; - } - - /** - * Sets horizontal border character. - * - * @param string $horizontalBorderChar - * - * @return TableHelper - */ - public function setHorizontalBorderChar($horizontalBorderChar) - { - $this->horizontalBorderChar = $horizontalBorderChar; - - return $this; - } - - /** - * Sets vertical border character. - * - * @param string $verticalBorderChar - * - * @return TableHelper - */ - public function setVerticalBorderChar($verticalBorderChar) - { - $this->verticalBorderChar = $verticalBorderChar; - - return $this; - } - - /** - * Sets crossing character. - * - * @param string $crossingChar - * - * @return TableHelper - */ - public function setCrossingChar($crossingChar) - { - $this->crossingChar = $crossingChar; - - return $this; - } - - /** - * Sets header cell format. - * - * @param string $cellHeaderFormat - * - * @return TableHelper - */ - public function setCellHeaderFormat($cellHeaderFormat) - { - $this->cellHeaderFormat = $cellHeaderFormat; - - return $this; - } - - /** - * Sets row cell format. - * - * @param string $cellRowFormat - * - * @return TableHelper - */ - public function setCellRowFormat($cellRowFormat) - { - $this->cellRowFormat = $cellRowFormat; - - return $this; - } - - /** - * Sets table border format. - * - * @param string $borderFormat - * - * @return TableHelper - */ - public function setBorderFormat($borderFormat) - { - $this->borderFormat = $borderFormat; - - return $this; - } - - /** - * Sets cell padding type. - * - * @param integer $padType STR_PAD_* - * - * @return TableHelper - */ - public function setPadType($padType) - { - $this->padType = $padType; - - return $this; - } - - /** - * Renders table to output. - * - * Example: - * +---------------+-----------------------+------------------+ - * | ISBN | Title | Author | - * +---------------+-----------------------+------------------+ - * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | - * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | - * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | - * +---------------+-----------------------+------------------+ - * - * @param OutputInterface $output - */ - public function render(OutputInterface $output) - { - $this->output = $output; - - $this->renderRowSeparator(); - $this->renderRow($this->headers, $this->cellHeaderFormat); - if (!empty($this->headers)) { - $this->renderRowSeparator(); - } - foreach ($this->rows as $row) { - $this->renderRow($row, $this->cellRowFormat); - } - if (!empty($this->rows)) { - $this->renderRowSeparator(); - } - - $this->cleanup(); - } - - /** - * Renders horizontal header separator. - * - * Example: +-----+-----------+-------+ - */ - private function renderRowSeparator() - { - if (0 === $count = $this->getNumberOfColumns()) { - return; - } - - $markup = $this->crossingChar; - for ($column = 0; $column < $count; $column++) { - $markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column)) - .$this->crossingChar - ; - } - - $this->output->writeln(sprintf($this->borderFormat, $markup)); - } - - /** - * Renders vertical column separator. - */ - private function renderColumnSeparator() - { - $this->output->write(sprintf($this->borderFormat, $this->verticalBorderChar)); - } - - /** - * Renders table row. - * - * Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | - * - * @param array $row - * @param string $cellFormat - */ - private function renderRow(array $row, $cellFormat) - { - if (empty($row)) { - return; - } - - $this->renderColumnSeparator(); - for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) { - $this->renderCell($row, $column, $cellFormat); - $this->renderColumnSeparator(); - } - $this->output->writeln(''); - } - - /** - * Renders table cell with padding. - * - * @param array $row - * @param integer $column - * @param string $cellFormat - */ - private function renderCell(array $row, $column, $cellFormat) - { - $cell = isset($row[$column]) ? $row[$column] : ''; - $width = $this->getColumnWidth($column); - - // str_pad won't work properly with multi-byte strings, we need to fix the padding - if (function_exists('mb_strlen') && false !== $encoding = mb_detect_encoding($cell)) { - $width += strlen($cell) - mb_strlen($cell, $encoding); - } - - $this->output->write(sprintf( - $cellFormat, - str_pad( - $this->paddingChar.$cell.$this->paddingChar, - $width, - $this->paddingChar, - $this->padType - ) - )); - } - - /** - * Gets number of columns for this table. - * - * @return int - */ - private function getNumberOfColumns() - { - if (null !== $this->numberOfColumns) { - return $this->numberOfColumns; - } - - $columns = array(0); - $columns[] = count($this->headers); - foreach ($this->rows as $row) { - $columns[] = count($row); - } - - return $this->numberOfColumns = max($columns); - } - - /** - * Gets column width. - * - * @param integer $column - * - * @return int - */ - private function getColumnWidth($column) - { - if (isset($this->columnWidths[$column])) { - return $this->columnWidths[$column]; - } - - $lengths = array(0); - $lengths[] = $this->getCellWidth($this->headers, $column); - foreach ($this->rows as $row) { - $lengths[] = $this->getCellWidth($row, $column); - } - - return $this->columnWidths[$column] = max($lengths) + 2; - } - - /** - * Gets cell width. - * - * @param array $row - * @param integer $column - * - * @return int - */ - private function getCellWidth(array $row, $column) - { - if ($column < 0) { - return 0; - } - - if (isset($row[$column])) { - return $this->strlen($row[$column]); - } - - return $this->getCellWidth($row, $column - 1); - } - - /** - * Called after rendering to cleanup cache data. - */ - private function cleanup() - { - $this->columnWidths = array(); - $this->numberOfColumns = null; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'table'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -/** - * HelperInterface is the interface all helpers must implement. - * - * @author Fabien Potencier - * - * @api - */ -interface HelperInterface -{ - /** - * Sets the helper set associated with this helper. - * - * @param HelperSet $helperSet A HelperSet instance - * - * @api - */ - public function setHelperSet(HelperSet $helperSet = null); - - /** - * Gets the helper set associated with this helper. - * - * @return HelperSet A HelperSet instance - * - * @api - */ - public function getHelperSet(); - - /** - * Returns the canonical name of this helper. - * - * @return string The canonical name - * - * @api - */ - public function getName(); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Output\OutputInterface; - -/** - * The Progress class provides helpers to display progress output. - * - * @author Chris Jones - * @author Fabien Potencier - */ -class ProgressHelper extends Helper -{ - const FORMAT_QUIET = ' %percent%%'; - const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%'; - const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%'; - const FORMAT_QUIET_NOMAX = ' %current%'; - const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]'; - const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%'; - - // options - private $barWidth = 28; - private $barChar = '='; - private $emptyBarChar = '-'; - private $progressChar = '>'; - private $format = null; - private $redrawFreq = 1; - - private $lastMessagesLength; - private $barCharOriginal; - - /** - * @var OutputInterface - */ - private $output; - - /** - * Current step - * - * @var integer - */ - private $current; - - /** - * Maximum number of steps - * - * @var integer - */ - private $max; - - /** - * Start time of the progress bar - * - * @var integer - */ - private $startTime; - - /** - * List of formatting variables - * - * @var array - */ - private $defaultFormatVars = array( - 'current', - 'max', - 'bar', - 'percent', - 'elapsed', - ); - - /** - * Available formatting variables - * - * @var array - */ - private $formatVars; - - /** - * Stored format part widths (used for padding) - * - * @var array - */ - private $widths = array( - 'current' => 4, - 'max' => 4, - 'percent' => 3, - 'elapsed' => 6, - ); - - /** - * Various time formats - * - * @var array - */ - private $timeFormats = array( - array(0, '???'), - array(2, '1 sec'), - array(59, 'secs', 1), - array(60, '1 min'), - array(3600, 'mins', 60), - array(5400, '1 hr'), - array(86400, 'hrs', 3600), - array(129600, '1 day'), - array(604800, 'days', 86400), - ); - - /** - * Sets the progress bar width. - * - * @param int $size The progress bar size - */ - public function setBarWidth($size) - { - $this->barWidth = (int) $size; - } - - /** - * Sets the bar character. - * - * @param string $char A character - */ - public function setBarCharacter($char) - { - $this->barChar = $char; - } - - /** - * Sets the empty bar character. - * - * @param string $char A character - */ - public function setEmptyBarCharacter($char) - { - $this->emptyBarChar = $char; - } - - /** - * Sets the progress bar character. - * - * @param string $char A character - */ - public function setProgressCharacter($char) - { - $this->progressChar = $char; - } - - /** - * Sets the progress bar format. - * - * @param string $format The format - */ - public function setFormat($format) - { - $this->format = $format; - } - - /** - * Sets the redraw frequency. - * - * @param int $freq The frequency in steps - */ - public function setRedrawFrequency($freq) - { - $this->redrawFreq = (int) $freq; - } - - /** - * Starts the progress output. - * - * @param OutputInterface $output An Output instance - * @param integer $max Maximum steps - */ - public function start(OutputInterface $output, $max = null) - { - $this->startTime = time(); - $this->current = 0; - $this->max = (int) $max; - $this->output = $output; - $this->lastMessagesLength = 0; - $this->barCharOriginal = ''; - - if (null === $this->format) { - switch ($output->getVerbosity()) { - case OutputInterface::VERBOSITY_QUIET: - $this->format = self::FORMAT_QUIET_NOMAX; - if ($this->max > 0) { - $this->format = self::FORMAT_QUIET; - } - break; - case OutputInterface::VERBOSITY_VERBOSE: - case OutputInterface::VERBOSITY_VERY_VERBOSE: - case OutputInterface::VERBOSITY_DEBUG: - $this->format = self::FORMAT_VERBOSE_NOMAX; - if ($this->max > 0) { - $this->format = self::FORMAT_VERBOSE; - } - break; - default: - $this->format = self::FORMAT_NORMAL_NOMAX; - if ($this->max > 0) { - $this->format = self::FORMAT_NORMAL; - } - break; - } - } - - $this->initialize(); - } - - /** - * Advances the progress output X steps. - * - * @param integer $step Number of steps to advance - * @param Boolean $redraw Whether to redraw or not - * - * @throws \LogicException - */ - public function advance($step = 1, $redraw = false) - { - if (null === $this->startTime) { - throw new \LogicException('You must start the progress bar before calling advance().'); - } - - if (0 === $this->current) { - $redraw = true; - } - - $this->current += $step; - if ($redraw || 0 === $this->current % $this->redrawFreq) { - $this->display(); - } - } - - /** - * Sets the current progress. - * - * @param integer $current The current progress - * @param Boolean $redraw Whether to redraw or not - * - * @throws \LogicException - */ - public function setCurrent($current, $redraw = false) - { - if (null === $this->startTime) { - throw new \LogicException('You must start the progress bar before calling setCurrent().'); - } - - $current = (int) $current; - - if ($current < $this->current) { - throw new \LogicException('You can\'t regress the progress bar'); - } - - if (0 === $this->current) { - $redraw = true; - } - - $this->current = $current; - if ($redraw || 0 === $this->current % $this->redrawFreq) { - $this->display(); - } - } - - /** - * Outputs the current progress string. - * - * @param Boolean $finish Forces the end result - * - * @throws \LogicException - */ - public function display($finish = false) - { - if (null === $this->startTime) { - throw new \LogicException('You must start the progress bar before calling display().'); - } - - $message = $this->format; - foreach ($this->generate($finish) as $name => $value) { - $message = str_replace("%{$name}%", $value, $message); - } - $this->overwrite($this->output, $message); - } - - /** - * Finishes the progress output. - */ - public function finish() - { - if (null === $this->startTime) { - throw new \LogicException('You must start the progress bar before calling finish().'); - } - - if (null !== $this->startTime) { - if (!$this->max) { - $this->barChar = $this->barCharOriginal; - $this->display(true); - } - $this->startTime = null; - $this->output->writeln(''); - $this->output = null; - } - } - - /** - * Initializes the progress helper. - */ - private function initialize() - { - $this->formatVars = array(); - foreach ($this->defaultFormatVars as $var) { - if (false !== strpos($this->format, "%{$var}%")) { - $this->formatVars[$var] = true; - } - } - - if ($this->max > 0) { - $this->widths['max'] = $this->strlen($this->max); - $this->widths['current'] = $this->widths['max']; - } else { - $this->barCharOriginal = $this->barChar; - $this->barChar = $this->emptyBarChar; - } - } - - /** - * Generates the array map of format variables to values. - * - * @param Boolean $finish Forces the end result - * - * @return array Array of format vars and values - */ - private function generate($finish = false) - { - $vars = array(); - $percent = 0; - if ($this->max > 0) { - $percent = (double) $this->current / $this->max; - } - - if (isset($this->formatVars['bar'])) { - $completeBars = 0; - - if ($this->max > 0) { - $completeBars = floor($percent * $this->barWidth); - } else { - if (!$finish) { - $completeBars = floor($this->current % $this->barWidth); - } else { - $completeBars = $this->barWidth; - } - } - - $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar); - $bar = str_repeat($this->barChar, $completeBars); - if ($completeBars < $this->barWidth) { - $bar .= $this->progressChar; - $bar .= str_repeat($this->emptyBarChar, $emptyBars); - } - - $vars['bar'] = $bar; - } - - if (isset($this->formatVars['elapsed'])) { - $elapsed = time() - $this->startTime; - $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT); - } - - if (isset($this->formatVars['current'])) { - $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT); - } - - if (isset($this->formatVars['max'])) { - $vars['max'] = $this->max; - } - - if (isset($this->formatVars['percent'])) { - $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT); - } - - return $vars; - } - - /** - * Converts seconds into human-readable format. - * - * @param integer $secs Number of seconds - * - * @return string Time in readable format - */ - private function humaneTime($secs) - { - $text = ''; - foreach ($this->timeFormats as $format) { - if ($secs < $format[0]) { - if (count($format) == 2) { - $text = $format[1]; - break; - } else { - $text = ceil($secs / $format[2]).' '.$format[1]; - break; - } - } - } - - return $text; - } - - /** - * Overwrites a previous message to the output. - * - * @param OutputInterface $output An Output instance - * @param string $message The message - */ - private function overwrite(OutputInterface $output, $message) - { - $length = $this->strlen($message); - - // append whitespace to match the last line's length - if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) { - $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); - } - - // carriage return - $output->write("\x0D"); - $output->write($message); - - $this->lastMessagesLength = $this->strlen($message); - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'progress'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Descriptor\DescriptorInterface; -use Symfony\Component\Console\Descriptor\JsonDescriptor; -use Symfony\Component\Console\Descriptor\MarkdownDescriptor; -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * This class adds helper method to describe objects in various formats. - * - * @author Jean-François Simon - */ -class DescriptorHelper extends Helper -{ - /** - * @var DescriptorInterface[] - */ - private $descriptors = array(); - - /** - * Constructor. - */ - public function __construct() - { - $this - ->register('txt', new TextDescriptor()) - ->register('xml', new XmlDescriptor()) - ->register('json', new JsonDescriptor()) - ->register('md', new MarkdownDescriptor()) - ; - } - - /** - * Describes an object if supported. - * - * @param OutputInterface $output - * @param object $object - * @param string $format - * @param boolean $raw - */ - public function describe(OutputInterface $output, $object, $format = null, $raw = false, $namespace = null) - { - $options = array('raw_text' => $raw, 'format' => $format ?: 'txt', 'namespace' => $namespace); - $type = !$raw && 'txt' === $options['format'] ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW; - - if (!isset($this->descriptors[$options['format']])) { - throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); - } - - $descriptor = $this->descriptors[$options['format']]; - - $output->writeln($descriptor->describe($object, $options), $type); - } - - /** - * Registers a descriptor. - * - * @param string $format - * @param DescriptorInterface $descriptor - * - * @return DescriptorHelper - */ - public function register($format, DescriptorInterface $descriptor) - { - $this->descriptors[$format] = $descriptor; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'descriptor'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; - -/** - * The Dialog class provides helpers to interact with the user. - * - * @author Fabien Potencier - */ -class DialogHelper extends Helper -{ - private $inputStream; - private static $shell; - private static $stty; - - /** - * Asks the user to select a value. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param array $choices List of choices to pick from - * @param Boolean $default The default answer if the user enters nothing - * @param Boolean|integer $attempts Max number of times to ask before giving up (false by default, which means infinite) - * @param string $errorMessage Message which will be shown if invalid value from choice list would be picked - * @param Boolean $multiselect Select more than one value separated by comma - * - * @return integer|string|array The selected value or values (the key of the choices array) - * - * @throws \InvalidArgumentException - */ - public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false) - { - $width = max(array_map('strlen', array_keys($choices))); - - $messages = (array) $question; - foreach ($choices as $key => $value) { - $messages[] = sprintf(" [%-${width}s] %s", $key, $value); - } - - $output->writeln($messages); - - $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) { - // Collapse all spaces. - $selectedChoices = str_replace(" ", "", $picked); - - if ($multiselect) { - // Check for a separated comma values - if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) { - throw new \InvalidArgumentException(sprintf($errorMessage, $picked)); - } - $selectedChoices = explode(",", $selectedChoices); - } else { - $selectedChoices = array($picked); - } - - $multiselectChoices = array(); - - foreach ($selectedChoices as $value) { - if (empty($choices[$value])) { - throw new \InvalidArgumentException(sprintf($errorMessage, $value)); - } - array_push($multiselectChoices, $value); - } - - if ($multiselect) { - return $multiselectChoices; - } - - return $picked; - }, $attempts, $default); - - return $result; - } - - /** - * Asks a question to the user. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param string $default The default answer if none is given by the user - * @param array $autocomplete List of values to autocomplete - * - * @return string The user answer - * - * @throws \RuntimeException If there is no data to read in the input stream - */ - public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null) - { - $output->write($question); - - $inputStream = $this->inputStream ?: STDIN; - - if (null === $autocomplete || !$this->hasSttyAvailable()) { - $ret = fgets($inputStream, 4096); - if (false === $ret) { - throw new \RuntimeException('Aborted'); - } - $ret = trim($ret); - } else { - $ret = ''; - - $i = 0; - $ofs = -1; - $matches = $autocomplete; - $numMatches = count($matches); - - $sttyMode = shell_exec('stty -g'); - - // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) - shell_exec('stty -icanon -echo'); - - // Add highlighted text style - $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); - - // Read a keypress - while (!feof($inputStream)) { - $c = fread($inputStream, 1); - - // Backspace Character - if ("\177" === $c) { - if (0 === $numMatches && 0 !== $i) { - $i--; - // Move cursor backwards - $output->write("\033[1D"); - } - - if ($i === 0) { - $ofs = -1; - $matches = $autocomplete; - $numMatches = count($matches); - } else { - $numMatches = 0; - } - - // Pop the last character off the end of our string - $ret = substr($ret, 0, $i); - } elseif ("\033" === $c) { // Did we read an escape sequence? - $c .= fread($inputStream, 2); - - // A = Up Arrow. B = Down Arrow - if ('A' === $c[2] || 'B' === $c[2]) { - if ('A' === $c[2] && -1 === $ofs) { - $ofs = 0; - } - - if (0 === $numMatches) { - continue; - } - - $ofs += ('A' === $c[2]) ? -1 : 1; - $ofs = ($numMatches + $ofs) % $numMatches; - } - } elseif (ord($c) < 32) { - if ("\t" === $c || "\n" === $c) { - if ($numMatches > 0 && -1 !== $ofs) { - $ret = $matches[$ofs]; - // Echo out remaining chars for current match - $output->write(substr($ret, $i)); - $i = strlen($ret); - } - - if ("\n" === $c) { - $output->write($c); - break; - } - - $numMatches = 0; - } - - continue; - } else { - $output->write($c); - $ret .= $c; - $i++; - - $numMatches = 0; - $ofs = 0; - - foreach ($autocomplete as $value) { - // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) - if (0 === strpos($value, $ret) && $i !== strlen($value)) { - $matches[$numMatches++] = $value; - } - } - } - - // Erase characters from cursor to end of line - $output->write("\033[K"); - - if ($numMatches > 0 && -1 !== $ofs) { - // Save cursor position - $output->write("\0337"); - // Write highlighted text - $output->write(''.substr($matches[$ofs], $i).''); - // Restore cursor position - $output->write("\0338"); - } - } - - // Reset stty so it behaves normally again - shell_exec(sprintf('stty %s', $sttyMode)); - } - - return strlen($ret) > 0 ? $ret : $default; - } - - /** - * Asks a confirmation to the user. - * - * The question will be asked until the user answers by nothing, yes, or no. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param Boolean $default The default answer if the user enters nothing - * - * @return Boolean true if the user has confirmed, false otherwise - */ - public function askConfirmation(OutputInterface $output, $question, $default = true) - { - $answer = 'z'; - while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) { - $answer = $this->ask($output, $question); - } - - if (false === $default) { - return $answer && 'y' == strtolower($answer[0]); - } - - return !$answer || 'y' == strtolower($answer[0]); - } - - /** - * Asks a question to the user, the response is hidden - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question - * @param Boolean $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not - * - * @return string The answer - * - * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden - */ - public function askHiddenResponse(OutputInterface $output, $question, $fallback = true) - { - if (defined('PHP_WINDOWS_VERSION_BUILD')) { - $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; - - // handle code running from a phar - if ('phar:' === substr(__FILE__, 0, 5)) { - $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; - copy($exe, $tmpExe); - $exe = $tmpExe; - } - - $output->write($question); - $value = rtrim(shell_exec($exe)); - $output->writeln(''); - - if (isset($tmpExe)) { - unlink($tmpExe); - } - - return $value; - } - - if ($this->hasSttyAvailable()) { - $output->write($question); - - $sttyMode = shell_exec('stty -g'); - - shell_exec('stty -echo'); - $value = fgets($this->inputStream ?: STDIN, 4096); - shell_exec(sprintf('stty %s', $sttyMode)); - - if (false === $value) { - throw new \RuntimeException('Aborted'); - } - - $value = trim($value); - $output->writeln(''); - - return $value; - } - - if (false !== $shell = $this->getShell()) { - $output->write($question); - $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword'; - $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); - $value = rtrim(shell_exec($command)); - $output->writeln(''); - - return $value; - } - - if ($fallback) { - return $this->ask($output, $question); - } - - throw new \RuntimeException('Unable to hide the response'); - } - - /** - * Asks for a value and validates the response. - * - * The validator receives the data to validate. It must return the - * validated data when the data is valid and throw an exception - * otherwise. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param callable $validator A PHP callback - * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) - * @param string $default The default answer if none is given by the user - * @param array $autocomplete List of values to autocomplete - * - * @return mixed - * - * @throws \Exception When any of the validators return an error - */ - public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null) - { - $that = $this; - - $interviewer = function() use ($output, $question, $default, $autocomplete, $that) { - return $that->ask($output, $question, $default, $autocomplete); - }; - - return $this->validateAttempts($interviewer, $output, $validator, $attempts); - } - - /** - * Asks for a value, hide and validates the response. - * - * The validator receives the data to validate. It must return the - * validated data when the data is valid and throw an exception - * otherwise. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param callable $validator A PHP callback - * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) - * @param Boolean $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not - * - * @return string The response - * - * @throws \Exception When any of the validators return an error - * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden - * - */ - public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true) - { - $that = $this; - - $interviewer = function() use ($output, $question, $fallback, $that) { - return $that->askHiddenResponse($output, $question, $fallback); - }; - - return $this->validateAttempts($interviewer, $output, $validator, $attempts); - } - - /** - * Sets the input stream to read from when interacting with the user. - * - * This is mainly useful for testing purpose. - * - * @param resource $stream The input stream - */ - public function setInputStream($stream) - { - $this->inputStream = $stream; - } - - /** - * Returns the helper's input stream - * - * @return string - */ - public function getInputStream() - { - return $this->inputStream; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'dialog'; - } - - /** - * Return a valid unix shell - * - * @return string|Boolean The valid shell name, false in case no valid shell is found - */ - private function getShell() - { - if (null !== self::$shell) { - return self::$shell; - } - - self::$shell = false; - - if (file_exists('/usr/bin/env')) { - // handle other OSs with bash/zsh/ksh/csh if available to hide the answer - $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; - foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) { - if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { - self::$shell = $sh; - break; - } - } - } - - return self::$shell; - } - - private function hasSttyAvailable() - { - if (null !== self::$stty) { - return self::$stty; - } - - exec('stty 2>&1', $output, $exitcode); - - return self::$stty = $exitcode === 0; - } - - /** - * Validate an attempt - * - * @param callable $interviewer A callable that will ask for a question and return the result - * @param OutputInterface $output An Output instance - * @param callable $validator A PHP callback - * @param integer $attempts Max number of times to ask before giving up ; false will ask infinitely - * - * @return string The validated response - * - * @throws \Exception In case the max number of attempts has been reached and no valid response has been given - */ - private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts) - { - $error = null; - while (false === $attempts || $attempts--) { - if (null !== $error) { - $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error')); - } - - try { - return call_user_func($validator, $interviewer()); - } catch (\Exception $error) { - } - } - - throw $error; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Formatter\OutputFormatter; - -/** - * The Formatter class provides helpers to format messages. - * - * @author Fabien Potencier - */ -class FormatterHelper extends Helper -{ - /** - * Formats a message within a section. - * - * @param string $section The section name - * @param string $message The message - * @param string $style The style to apply to the section - * - * @return string The format section - */ - public function formatSection($section, $message, $style = 'info') - { - return sprintf('<%s>[%s] %s', $style, $section, $style, $message); - } - - /** - * Formats a message as a block of text. - * - * @param string|array $messages The message to write in the block - * @param string $style The style to apply to the whole block - * @param Boolean $large Whether to return a large block - * - * @return string The formatter message - */ - public function formatBlock($messages, $style, $large = false) - { - $messages = (array) $messages; - - $len = 0; - $lines = array(); - foreach ($messages as $message) { - $message = OutputFormatter::escape($message); - $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); - $len = max($this->strlen($message) + ($large ? 4 : 2), $len); - } - - $messages = $large ? array(str_repeat(' ', $len)) : array(); - foreach ($lines as $line) { - $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); - } - if ($large) { - $messages[] = str_repeat(' ', $len); - } - - foreach ($messages as &$message) { - $message = sprintf('<%s>%s', $style, $message, $style); - } - - return implode("\n", $messages); - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'formatter'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; -use Symfony\Component\Console\Output\ConsoleOutputInterface; - -/** - * ConsoleOutput is the default class for all CLI output. It uses STDOUT. - * - * This class is a convenient wrapper around `StreamOutput`. - * - * $output = new ConsoleOutput(); - * - * This is equivalent to: - * - * $output = new StreamOutput(fopen('php://stdout', 'w')); - * - * @author Fabien Potencier - * - * @api - */ -class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface -{ - private $stderr; - - /** - * Constructor. - * - * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) - * @param Boolean|null $decorated Whether to decorate messages (null for auto-guessing) - * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) - * - * @api - */ - public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) - { - $outputStream = 'php://stdout'; - if (!$this->hasStdoutSupport()) { - $outputStream = 'php://output'; - } - - parent::__construct(fopen($outputStream, 'w'), $verbosity, $decorated, $formatter); - - $this->stderr = new StreamOutput(fopen('php://stderr', 'w'), $verbosity, $decorated, $formatter); - } - - /** - * {@inheritdoc} - */ - public function setDecorated($decorated) - { - parent::setDecorated($decorated); - $this->stderr->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - parent::setFormatter($formatter); - $this->stderr->setFormatter($formatter); - } - - /** - * {@inheritdoc} - */ - public function setVerbosity($level) - { - parent::setVerbosity($level); - $this->stderr->setVerbosity($level); - } - - /** - * {@inheritdoc} - */ - public function getErrorOutput() - { - return $this->stderr; - } - - /** - * {@inheritdoc} - */ - public function setErrorOutput(OutputInterface $error) - { - $this->stderr = $error; - } - - /** - * Returns true if current environment supports writing console output to - * STDOUT. - * - * IBM iSeries (OS400) exhibits character-encoding issues when writing to - * STDOUT and doesn't properly convert ASCII to EBCDIC, resulting in garbage - * output. - * - * @return boolean - */ - protected function hasStdoutSupport() - { - return ('OS400' != php_uname('s')); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * StreamOutput writes the output to a given stream. - * - * Usage: - * - * $output = new StreamOutput(fopen('php://stdout', 'w')); - * - * As `StreamOutput` can use any stream, you can also use a file: - * - * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); - * - * @author Fabien Potencier - * - * @api - */ -class StreamOutput extends Output -{ - private $stream; - - /** - * Constructor. - * - * @param mixed $stream A stream resource - * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) - * @param Boolean|null $decorated Whether to decorate messages (null for auto-guessing) - * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) - * - * @throws \InvalidArgumentException When first argument is not a real stream - * - * @api - */ - public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) - { - if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) { - throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); - } - - $this->stream = $stream; - - if (null === $decorated) { - $decorated = $this->hasColorSupport(); - } - - parent::__construct($verbosity, $decorated, $formatter); - } - - /** - * Gets the stream attached to this StreamOutput instance. - * - * @return resource A stream resource - */ - public function getStream() - { - return $this->stream; - } - - /** - * {@inheritdoc} - */ - protected function doWrite($message, $newline) - { - if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) { - // @codeCoverageIgnoreStart - // should never happen - throw new \RuntimeException('Unable to write output.'); - // @codeCoverageIgnoreEnd - } - - fflush($this->stream); - } - - /** - * Returns true if the stream supports colorization. - * - * Colorization is disabled if not supported by the stream: - * - * - windows without ansicon and ConEmu - * - non tty consoles - * - * @return Boolean true if the stream supports colorization, false otherwise - */ - protected function hasColorSupport() - { - // @codeCoverageIgnoreStart - if (DIRECTORY_SEPARATOR == '\\') { - return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI'); - } - - return function_exists('posix_isatty') && @posix_isatty($this->stream); - // @codeCoverageIgnoreEnd - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Output\OutputInterface; - -/** - * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. - * This adds information about stderr output stream. - * - * @author Dariusz Górecki - */ -interface ConsoleOutputInterface extends OutputInterface -{ - /** - * Gets the OutputInterface for errors. - * - * @return OutputInterface - */ - public function getErrorOutput(); - - /** - * Sets the OutputInterface used for errors. - * - * @param OutputInterface $error - */ - public function setErrorOutput(OutputInterface $error); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * NullOutput suppresses all output. - * - * $output = new NullOutput(); - * - * @author Fabien Potencier - * @author Tobias Schultze - * - * @api - */ -class NullOutput implements OutputInterface -{ - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function getFormatter() - { - // to comply with the interface we must return a OutputFormatterInterface - return new OutputFormatter(); - } - - /** - * {@inheritdoc} - */ - public function setDecorated($decorated) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function isDecorated() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function setVerbosity($level) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function getVerbosity() - { - return self::VERBOSITY_QUIET; - } - - /** - * {@inheritdoc} - */ - public function writeln($messages, $type = self::OUTPUT_NORMAL) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) - { - // do nothing - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; -use Symfony\Component\Console\Formatter\OutputFormatter; - -/** - * Base class for output classes. - * - * There are five levels of verbosity: - * - * * normal: no option passed (normal output) - * * verbose: -v (more output) - * * very verbose: -vv (highly extended output) - * * debug: -vvv (all debug output) - * * quiet: -q (no output) - * - * @author Fabien Potencier - * - * @api - */ -abstract class Output implements OutputInterface -{ - private $verbosity; - private $formatter; - - /** - * Constructor. - * - * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) - * @param Boolean $decorated Whether to decorate messages - * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) - * - * @api - */ - public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null) - { - $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; - $this->formatter = null === $formatter ? new OutputFormatter() : $formatter; - $this->formatter->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - $this->formatter = $formatter; - } - - /** - * {@inheritdoc} - */ - public function getFormatter() - { - return $this->formatter; - } - - /** - * {@inheritdoc} - */ - public function setDecorated($decorated) - { - $this->formatter->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function isDecorated() - { - return $this->formatter->isDecorated(); - } - - /** - * {@inheritdoc} - */ - public function setVerbosity($level) - { - $this->verbosity = (int) $level; - } - - /** - * {@inheritdoc} - */ - public function getVerbosity() - { - return $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function writeln($messages, $type = self::OUTPUT_NORMAL) - { - $this->write($messages, true, $type); - } - - /** - * {@inheritdoc} - */ - public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) - { - if (self::VERBOSITY_QUIET === $this->verbosity) { - return; - } - - $messages = (array) $messages; - - foreach ($messages as $message) { - switch ($type) { - case OutputInterface::OUTPUT_NORMAL: - $message = $this->formatter->format($message); - break; - case OutputInterface::OUTPUT_RAW: - break; - case OutputInterface::OUTPUT_PLAIN: - $message = strip_tags($this->formatter->format($message)); - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type)); - } - - $this->doWrite($message, $newline); - } - } - - /** - * Writes a message to the output. - * - * @param string $message A message to write to the output - * @param Boolean $newline Whether to add a newline or not - */ - abstract protected function doWrite($message, $newline); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * OutputInterface is the interface implemented by all Output classes. - * - * @author Fabien Potencier - * - * @api - */ -interface OutputInterface -{ - const VERBOSITY_QUIET = 0; - const VERBOSITY_NORMAL = 1; - const VERBOSITY_VERBOSE = 2; - const VERBOSITY_VERY_VERBOSE = 3; - const VERBOSITY_DEBUG = 4; - - const OUTPUT_NORMAL = 0; - const OUTPUT_RAW = 1; - const OUTPUT_PLAIN = 2; - - /** - * Writes a message to the output. - * - * @param string|array $messages The message as an array of lines or a single string - * @param Boolean $newline Whether to add a newline - * @param integer $type The type of output (one of the OUTPUT constants) - * - * @throws \InvalidArgumentException When unknown output type is given - * - * @api - */ - public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL); - - /** - * Writes a message to the output and adds a newline at the end. - * - * @param string|array $messages The message as an array of lines of a single string - * @param integer $type The type of output (one of the OUTPUT constants) - * - * @throws \InvalidArgumentException When unknown output type is given - * - * @api - */ - public function writeln($messages, $type = self::OUTPUT_NORMAL); - - /** - * Sets the verbosity of the output. - * - * @param integer $level The level of verbosity (one of the VERBOSITY constants) - * - * @api - */ - public function setVerbosity($level); - - /** - * Gets the current verbosity of the output. - * - * @return integer The current level of verbosity (one of the VERBOSITY constants) - * - * @api - */ - public function getVerbosity(); - - /** - * Sets the decorated flag. - * - * @param Boolean $decorated Whether to decorate the messages - * - * @api - */ - public function setDecorated($decorated); - - /** - * Gets the decorated flag. - * - * @return Boolean true if the output will decorate messages, false otherwise - * - * @api - */ - public function isDecorated(); - - /** - * Sets output formatter. - * - * @param OutputFormatterInterface $formatter - * - * @api - */ - public function setFormatter(OutputFormatterInterface $formatter); - - /** - * Returns current output formatter instance. - * - * @return OutputFormatterInterface - * - * @api - */ - public function getFormatter(); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Input\StringInput; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Process\ProcessBuilder; -use Symfony\Component\Process\PhpExecutableFinder; - -/** - * A Shell wraps an Application to add shell capabilities to it. - * - * Support for history and completion only works with a PHP compiled - * with readline support (either --with-readline or --with-libedit) - * - * @author Fabien Potencier - * @author Martin Hasoň - */ -class Shell -{ - private $application; - private $history; - private $output; - private $hasReadline; - private $processIsolation; - - /** - * Constructor. - * - * If there is no readline support for the current PHP executable - * a \RuntimeException exception is thrown. - * - * @param Application $application An application instance - */ - public function __construct(Application $application) - { - $this->hasReadline = function_exists('readline'); - $this->application = $application; - $this->history = getenv('HOME').'/.history_'.$application->getName(); - $this->output = new ConsoleOutput(); - $this->processIsolation = false; - } - - /** - * Runs the shell. - */ - public function run() - { - $this->application->setAutoExit(false); - $this->application->setCatchExceptions(true); - - if ($this->hasReadline) { - readline_read_history($this->history); - readline_completion_function(array($this, 'autocompleter')); - } - - $this->output->writeln($this->getHeader()); - $php = null; - if ($this->processIsolation) { - $finder = new PhpExecutableFinder(); - $php = $finder->find(); - $this->output->writeln(<<Running with process isolation, you should consider this: - * each command is executed as separate process, - * commands don't support interactivity, all params must be passed explicitly, - * commands output is not colorized. - -EOF - ); - } - - while (true) { - $command = $this->readline(); - - if (false === $command) { - $this->output->writeln("\n"); - - break; - } - - if ($this->hasReadline) { - readline_add_history($command); - readline_write_history($this->history); - } - - if ($this->processIsolation) { - $pb = new ProcessBuilder(); - - $process = $pb - ->add($php) - ->add($_SERVER['argv'][0]) - ->add($command) - ->inheritEnvironmentVariables(true) - ->getProcess() - ; - - $output = $this->output; - $process->run(function($type, $data) use ($output) { - $output->writeln($data); - }); - - $ret = $process->getExitCode(); - } else { - $ret = $this->application->run(new StringInput($command), $this->output); - } - - if (0 !== $ret) { - $this->output->writeln(sprintf('The command terminated with an error status (%s)', $ret)); - } - } - } - - /** - * Returns the shell header. - * - * @return string The header string - */ - protected function getHeader() - { - return <<{$this->application->getName()} shell ({$this->application->getVersion()}). - -At the prompt, type help for some help, -or list to get a list of available commands. - -To exit the shell, type ^D. - -EOF; - } - - /** - * Renders a prompt. - * - * @return string The prompt - */ - protected function getPrompt() - { - // using the formatter here is required when using readline - return $this->output->getFormatter()->format($this->application->getName().' > '); - } - - protected function getOutput() - { - return $this->output; - } - - protected function getApplication() - { - return $this->application; - } - - /** - * Tries to return autocompletion for the current entered text. - * - * @param string $text The last segment of the entered text - * - * @return Boolean|array A list of guessed strings or true - */ - private function autocompleter($text) - { - $info = readline_info(); - $text = substr($info['line_buffer'], 0, $info['end']); - - if ($info['point'] !== $info['end']) { - return true; - } - - // task name? - if (false === strpos($text, ' ') || !$text) { - return array_keys($this->application->all()); - } - - // options and arguments? - try { - $command = $this->application->find(substr($text, 0, strpos($text, ' '))); - } catch (\Exception $e) { - return true; - } - - $list = array('--help'); - foreach ($command->getDefinition()->getOptions() as $option) { - $list[] = '--'.$option->getName(); - } - - return $list; - } - - /** - * Reads a single line from standard input. - * - * @return string The single line from standard input - */ - private function readline() - { - if ($this->hasReadline) { - $line = readline($this->getPrompt()); - } else { - $this->output->write($this->getPrompt()); - $line = fgets(STDIN, 1024); - $line = (!$line && strlen($line) == 0) ? false : rtrim($line); - } - - return $line; - } - - public function getProcessIsolation() - { - return $this->processIsolation; - } - - public function setProcessIsolation($processIsolation) - { - $this->processIsolation = (Boolean) $processIsolation; - - if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) { - throw new \RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.'); - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * ArgvInput represents an input coming from the CLI arguments. - * - * Usage: - * - * $input = new ArgvInput(); - * - * By default, the `$_SERVER['argv']` array is used for the input values. - * - * This can be overridden by explicitly passing the input values in the constructor: - * - * $input = new ArgvInput($_SERVER['argv']); - * - * If you pass it yourself, don't forget that the first element of the array - * is the name of the running application. - * - * When passing an argument to the constructor, be sure that it respects - * the same rules as the argv one. It's almost always better to use the - * `StringInput` when you want to provide your own input. - * - * @author Fabien Potencier - * - * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html - * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 - * - * @api - */ -class ArgvInput extends Input -{ - private $tokens; - private $parsed; - - /** - * Constructor. - * - * @param array $argv An array of parameters from the CLI (in the argv format) - * @param InputDefinition $definition A InputDefinition instance - * - * @api - */ - public function __construct(array $argv = null, InputDefinition $definition = null) - { - if (null === $argv) { - $argv = $_SERVER['argv']; - } - - // strip the application name - array_shift($argv); - - $this->tokens = $argv; - - parent::__construct($definition); - } - - protected function setTokens(array $tokens) - { - $this->tokens = $tokens; - } - - /** - * Processes command line arguments. - */ - protected function parse() - { - $parseOptions = true; - $this->parsed = $this->tokens; - while (null !== $token = array_shift($this->parsed)) { - if ($parseOptions && '' == $token) { - $this->parseArgument($token); - } elseif ($parseOptions && '--' == $token) { - $parseOptions = false; - } elseif ($parseOptions && 0 === strpos($token, '--')) { - $this->parseLongOption($token); - } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { - $this->parseShortOption($token); - } else { - $this->parseArgument($token); - } - } - } - - /** - * Parses a short option. - * - * @param string $token The current token. - */ - private function parseShortOption($token) - { - $name = substr($token, 1); - - if (strlen($name) > 1) { - if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { - // an option with a value (with no space) - $this->addShortOption($name[0], substr($name, 1)); - } else { - $this->parseShortOptionSet($name); - } - } else { - $this->addShortOption($name, null); - } - } - - /** - * Parses a short option set. - * - * @param string $name The current token - * - * @throws \RuntimeException When option given doesn't exist - */ - private function parseShortOptionSet($name) - { - $len = strlen($name); - for ($i = 0; $i < $len; $i++) { - if (!$this->definition->hasShortcut($name[$i])) { - throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i])); - } - - $option = $this->definition->getOptionForShortcut($name[$i]); - if ($option->acceptValue()) { - $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); - - break; - } else { - $this->addLongOption($option->getName(), null); - } - } - } - - /** - * Parses a long option. - * - * @param string $token The current token - */ - private function parseLongOption($token) - { - $name = substr($token, 2); - - if (false !== $pos = strpos($name, '=')) { - $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1)); - } else { - $this->addLongOption($name, null); - } - } - - /** - * Parses an argument. - * - * @param string $token The current token - * - * @throws \RuntimeException When too many arguments are given - */ - private function parseArgument($token) - { - $c = count($this->arguments); - - // if input is expecting another argument, add it - if ($this->definition->hasArgument($c)) { - $arg = $this->definition->getArgument($c); - $this->arguments[$arg->getName()] = $arg->isArray()? array($token) : $token; - - // if last argument isArray(), append token to last argument - } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { - $arg = $this->definition->getArgument($c - 1); - $this->arguments[$arg->getName()][] = $token; - - // unexpected argument - } else { - throw new \RuntimeException('Too many arguments.'); - } - } - - /** - * Adds a short option value. - * - * @param string $shortcut The short option key - * @param mixed $value The value for the option - * - * @throws \RuntimeException When option given doesn't exist - */ - private function addShortOption($shortcut, $value) - { - if (!$this->definition->hasShortcut($shortcut)) { - throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); - } - - $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); - } - - /** - * Adds a long option value. - * - * @param string $name The long option key - * @param mixed $value The value for the option - * - * @throws \RuntimeException When option given doesn't exist - */ - private function addLongOption($name, $value) - { - if (!$this->definition->hasOption($name)) { - throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name)); - } - - $option = $this->definition->getOption($name); - - // Convert false values (from a previous call to substr()) to null - if (false === $value) { - $value = null; - } - - if (null !== $value && !$option->acceptValue()) { - throw new \RuntimeException(sprintf('The "--%s" option does not accept a value.', $name, $value)); - } - - if (null === $value && $option->acceptValue() && count($this->parsed)) { - // if option accepts an optional or mandatory argument - // let's see if there is one provided - $next = array_shift($this->parsed); - if (isset($next[0]) && '-' !== $next[0]) { - $value = $next; - } elseif (empty($next)) { - $value = ''; - } else { - array_unshift($this->parsed, $next); - } - } - - if (null === $value) { - if ($option->isValueRequired()) { - throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name)); - } - - if (!$option->isArray()) { - $value = $option->isValueOptional() ? $option->getDefault() : true; - } - } - - if ($option->isArray()) { - $this->options[$name][] = $value; - } else { - $this->options[$name] = $value; - } - } - - /** - * Returns the first argument from the raw parameters (not parsed). - * - * @return string The value of the first argument or null otherwise - */ - public function getFirstArgument() - { - foreach ($this->tokens as $token) { - if ($token && '-' === $token[0]) { - continue; - } - - return $token; - } - } - - /** - * Returns true if the raw parameters (not parsed) contain a value. - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * - * @return Boolean true if the value is contained in the raw parameters - */ - public function hasParameterOption($values) - { - $values = (array) $values; - - foreach ($this->tokens as $token) { - foreach ($values as $value) { - if ($token === $value || 0 === strpos($token, $value.'=')) { - return true; - } - } - } - - return false; - } - - /** - * Returns the value of a raw option (not parsed). - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found - * - * @return mixed The option value - */ - public function getParameterOption($values, $default = false) - { - $values = (array) $values; - - $tokens = $this->tokens; - while ($token = array_shift($tokens)) { - foreach ($values as $value) { - if ($token === $value || 0 === strpos($token, $value.'=')) { - if (false !== $pos = strpos($token, '=')) { - return substr($token, $pos + 1); - } - - return array_shift($tokens); - } - } - } - - return $default; - } - - /** - * Returns a stringified representation of the args passed to the command - * - * @return string - */ - public function __toString() - { - $self = $this; - $tokens = array_map(function ($token) use ($self) { - if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { - return $match[1] . $self->escapeToken($match[2]); - } - - if ($token && $token[0] !== '-') { - return $self->escapeToken($token); - } - - return $token; - }, $this->tokens); - - return implode(' ', $tokens); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * StringInput represents an input provided as a string. - * - * Usage: - * - * $input = new StringInput('foo --bar="foobar"'); - * - * @author Fabien Potencier - * - * @api - */ -class StringInput extends ArgvInput -{ - const REGEX_STRING = '([^\s]+?)(?:\s|(?setTokens($this->tokenize($input)); - - if (null !== $definition) { - $this->bind($definition); - } - } - - /** - * Tokenizes a string. - * - * @param string $input The input to tokenize - * - * @return array An array of tokens - * - * @throws \InvalidArgumentException When unable to parse input (should never happen) - */ - private function tokenize($input) - { - $tokens = array(); - $length = strlen($input); - $cursor = 0; - while ($cursor < $length) { - if (preg_match('/\s+/A', $input, $match, null, $cursor)) { - } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) { - $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2))); - } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) { - $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2)); - } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) { - $tokens[] = stripcslashes($match[1]); - } else { - // should never happen - // @codeCoverageIgnoreStart - throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10))); - // @codeCoverageIgnoreEnd - } - - $cursor += strlen($match[0]); - } - - return $tokens; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * InputInterface is the interface implemented by all input classes. - * - * @author Fabien Potencier - */ -interface InputInterface -{ - /** - * Returns the first argument from the raw parameters (not parsed). - * - * @return string The value of the first argument or null otherwise - */ - public function getFirstArgument(); - - /** - * Returns true if the raw parameters (not parsed) contain a value. - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The values to look for in the raw parameters (can be an array) - * - * @return Boolean true if the value is contained in the raw parameters - */ - public function hasParameterOption($values); - - /** - * Returns the value of a raw option (not parsed). - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found - * - * @return mixed The option value - */ - public function getParameterOption($values, $default = false); - - /** - * Binds the current Input instance with the given arguments and options. - * - * @param InputDefinition $definition A InputDefinition instance - */ - public function bind(InputDefinition $definition); - - /** - * Validates if arguments given are correct. - * - * Throws an exception when not enough arguments are given. - * - * @throws \RuntimeException - */ - public function validate(); - - /** - * Returns all the given arguments merged with the default values. - * - * @return array - */ - public function getArguments(); - - /** - * Gets argument by name. - * - * @param string $name The name of the argument - * - * @return mixed - */ - public function getArgument($name); - - /** - * Sets an argument value by name. - * - * @param string $name The argument name - * @param string $value The argument value - * - * @throws \InvalidArgumentException When argument given doesn't exist - */ - public function setArgument($name, $value); - - /** - * Returns true if an InputArgument object exists by name or position. - * - * @param string|integer $name The InputArgument name or position - * - * @return Boolean true if the InputArgument object exists, false otherwise - */ - public function hasArgument($name); - - /** - * Returns all the given options merged with the default values. - * - * @return array - */ - public function getOptions(); - - /** - * Gets an option by name. - * - * @param string $name The name of the option - * - * @return mixed - */ - public function getOption($name); - - /** - * Sets an option value by name. - * - * @param string $name The option name - * @param string $value The option value - * - * @throws \InvalidArgumentException When option given doesn't exist - */ - public function setOption($name, $value); - - /** - * Returns true if an InputOption object exists by name. - * - * @param string $name The InputOption name - * - * @return Boolean true if the InputOption object exists, false otherwise - */ - public function hasOption($name); - - /** - * Is this input means interactive? - * - * @return Boolean - */ - public function isInteractive(); - - /** - * Sets the input interactivity. - * - * @param Boolean $interactive If the input should be interactive - */ - public function setInteractive($interactive); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * Represents a command line option. - * - * @author Fabien Potencier - * - * @api - */ -class InputOption -{ - const VALUE_NONE = 1; - const VALUE_REQUIRED = 2; - const VALUE_OPTIONAL = 4; - const VALUE_IS_ARRAY = 8; - - private $name; - private $shortcut; - private $mode; - private $default; - private $description; - - /** - * Constructor. - * - * @param string $name The option name - * @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts - * @param integer $mode The option mode: One of the VALUE_* constants - * @param string $description A description text - * @param mixed $default The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE) - * - * @throws \InvalidArgumentException If option mode is invalid or incompatible - * - * @api - */ - public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null) - { - if (0 === strpos($name, '--')) { - $name = substr($name, 2); - } - - if (empty($name)) { - throw new \InvalidArgumentException('An option name cannot be empty.'); - } - - if (empty($shortcut)) { - $shortcut = null; - } - - if (null !== $shortcut) { - if (is_array($shortcut)) { - $shortcut = implode('|', $shortcut); - } - $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); - $shortcuts = array_filter($shortcuts); - $shortcut = implode('|', $shortcuts); - - if (empty($shortcut)) { - throw new \InvalidArgumentException('An option shortcut cannot be empty.'); - } - } - - if (null === $mode) { - $mode = self::VALUE_NONE; - } elseif (!is_int($mode) || $mode > 15 || $mode < 1) { - throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); - } - - $this->name = $name; - $this->shortcut = $shortcut; - $this->mode = $mode; - $this->description = $description; - - if ($this->isArray() && !$this->acceptValue()) { - throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); - } - - $this->setDefault($default); - } - - /** - * Returns the option shortcut. - * - * @return string The shortcut - */ - public function getShortcut() - { - return $this->shortcut; - } - - /** - * Returns the option name. - * - * @return string The name - */ - public function getName() - { - return $this->name; - } - - /** - * Returns true if the option accepts a value. - * - * @return Boolean true if value mode is not self::VALUE_NONE, false otherwise - */ - public function acceptValue() - { - return $this->isValueRequired() || $this->isValueOptional(); - } - - /** - * Returns true if the option requires a value. - * - * @return Boolean true if value mode is self::VALUE_REQUIRED, false otherwise - */ - public function isValueRequired() - { - return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); - } - - /** - * Returns true if the option takes an optional value. - * - * @return Boolean true if value mode is self::VALUE_OPTIONAL, false otherwise - */ - public function isValueOptional() - { - return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); - } - - /** - * Returns true if the option can take multiple values. - * - * @return Boolean true if mode is self::VALUE_IS_ARRAY, false otherwise - */ - public function isArray() - { - return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); - } - - /** - * Sets the default value. - * - * @param mixed $default The default value - * - * @throws \LogicException When incorrect default value is given - */ - public function setDefault($default = null) - { - if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { - throw new \LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.'); - } - - if ($this->isArray()) { - if (null === $default) { - $default = array(); - } elseif (!is_array($default)) { - throw new \LogicException('A default value for an array option must be an array.'); - } - } - - $this->default = $this->acceptValue() ? $default : false; - } - - /** - * Returns the default value. - * - * @return mixed The default value - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns the description text. - * - * @return string The description text - */ - public function getDescription() - { - return $this->description; - } - - /** - * Checks whether the given option equals this one - * - * @param InputOption $option option to compare - * @return Boolean - */ - public function equals(InputOption $option) - { - return $option->getName() === $this->getName() - && $option->getShortcut() === $this->getShortcut() - && $option->getDefault() === $this->getDefault() - && $option->isArray() === $this->isArray() - && $option->isValueRequired() === $this->isValueRequired() - && $option->isValueOptional() === $this->isValueOptional() - ; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * Input is the base class for all concrete Input classes. - * - * Three concrete classes are provided by default: - * - * * `ArgvInput`: The input comes from the CLI arguments (argv) - * * `StringInput`: The input is provided as a string - * * `ArrayInput`: The input is provided as an array - * - * @author Fabien Potencier - */ -abstract class Input implements InputInterface -{ - protected $definition; - protected $options; - protected $arguments; - protected $interactive = true; - - /** - * Constructor. - * - * @param InputDefinition $definition A InputDefinition instance - */ - public function __construct(InputDefinition $definition = null) - { - if (null === $definition) { - $this->arguments = array(); - $this->options = array(); - $this->definition = new InputDefinition(); - } else { - $this->bind($definition); - $this->validate(); - } - } - - /** - * Binds the current Input instance with the given arguments and options. - * - * @param InputDefinition $definition A InputDefinition instance - */ - public function bind(InputDefinition $definition) - { - $this->arguments = array(); - $this->options = array(); - $this->definition = $definition; - - $this->parse(); - } - - /** - * Processes command line arguments. - */ - abstract protected function parse(); - - /** - * Validates the input. - * - * @throws \RuntimeException When not enough arguments are given - */ - public function validate() - { - if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) { - throw new \RuntimeException('Not enough arguments.'); - } - } - - /** - * Checks if the input is interactive. - * - * @return Boolean Returns true if the input is interactive - */ - public function isInteractive() - { - return $this->interactive; - } - - /** - * Sets the input interactivity. - * - * @param Boolean $interactive If the input should be interactive - */ - public function setInteractive($interactive) - { - $this->interactive = (Boolean) $interactive; - } - - /** - * Returns the argument values. - * - * @return array An array of argument values - */ - public function getArguments() - { - return array_merge($this->definition->getArgumentDefaults(), $this->arguments); - } - - /** - * Returns the argument value for a given argument name. - * - * @param string $name The argument name - * - * @return mixed The argument value - * - * @throws \InvalidArgumentException When argument given doesn't exist - */ - public function getArgument($name) - { - if (!$this->definition->hasArgument($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); - } - - return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault(); - } - - /** - * Sets an argument value by name. - * - * @param string $name The argument name - * @param string $value The argument value - * - * @throws \InvalidArgumentException When argument given doesn't exist - */ - public function setArgument($name, $value) - { - if (!$this->definition->hasArgument($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); - } - - $this->arguments[$name] = $value; - } - - /** - * Returns true if an InputArgument object exists by name or position. - * - * @param string|integer $name The InputArgument name or position - * - * @return Boolean true if the InputArgument object exists, false otherwise - */ - public function hasArgument($name) - { - return $this->definition->hasArgument($name); - } - - /** - * Returns the options values. - * - * @return array An array of option values - */ - public function getOptions() - { - return array_merge($this->definition->getOptionDefaults(), $this->options); - } - - /** - * Returns the option value for a given option name. - * - * @param string $name The option name - * - * @return mixed The option value - * - * @throws \InvalidArgumentException When option given doesn't exist - */ - public function getOption($name) - { - if (!$this->definition->hasOption($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); - } - - return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); - } - - /** - * Sets an option value by name. - * - * @param string $name The option name - * @param string $value The option value - * - * @throws \InvalidArgumentException When option given doesn't exist - */ - public function setOption($name, $value) - { - if (!$this->definition->hasOption($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); - } - - $this->options[$name] = $value; - } - - /** - * Returns true if an InputOption object exists by name. - * - * @param string $name The InputOption name - * - * @return Boolean true if the InputOption object exists, false otherwise - */ - public function hasOption($name) - { - return $this->definition->hasOption($name); - } - - /** - * Escapes a token through escapeshellarg if it contains unsafe chars - * - * @param string $token - * - * @return string - */ - public function escapeToken($token) - { - return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * Represents a command line argument. - * - * @author Fabien Potencier - * - * @api - */ -class InputArgument -{ - const REQUIRED = 1; - const OPTIONAL = 2; - const IS_ARRAY = 4; - - private $name; - private $mode; - private $default; - private $description; - - /** - * Constructor. - * - * @param string $name The argument name - * @param integer $mode The argument mode: self::REQUIRED or self::OPTIONAL - * @param string $description A description text - * @param mixed $default The default value (for self::OPTIONAL mode only) - * - * @throws \InvalidArgumentException When argument mode is not valid - * - * @api - */ - public function __construct($name, $mode = null, $description = '', $default = null) - { - if (null === $mode) { - $mode = self::OPTIONAL; - } elseif (!is_int($mode) || $mode > 7 || $mode < 1) { - throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); - } - - $this->name = $name; - $this->mode = $mode; - $this->description = $description; - - $this->setDefault($default); - } - - /** - * Returns the argument name. - * - * @return string The argument name - */ - public function getName() - { - return $this->name; - } - - /** - * Returns true if the argument is required. - * - * @return Boolean true if parameter mode is self::REQUIRED, false otherwise - */ - public function isRequired() - { - return self::REQUIRED === (self::REQUIRED & $this->mode); - } - - /** - * Returns true if the argument can take multiple values. - * - * @return Boolean true if mode is self::IS_ARRAY, false otherwise - */ - public function isArray() - { - return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); - } - - /** - * Sets the default value. - * - * @param mixed $default The default value - * - * @throws \LogicException When incorrect default value is given - */ - public function setDefault($default = null) - { - if (self::REQUIRED === $this->mode && null !== $default) { - throw new \LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.'); - } - - if ($this->isArray()) { - if (null === $default) { - $default = array(); - } elseif (!is_array($default)) { - throw new \LogicException('A default value for an array argument must be an array.'); - } - } - - $this->default = $default; - } - - /** - * Returns the default value. - * - * @return mixed The default value - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns the description text. - * - * @return string The description text - */ - public function getDescription() - { - return $this->description; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * ArrayInput represents an input provided as an array. - * - * Usage: - * - * $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar')); - * - * @author Fabien Potencier - * - * @api - */ -class ArrayInput extends Input -{ - private $parameters; - - /** - * Constructor. - * - * @param array $parameters An array of parameters - * @param InputDefinition $definition A InputDefinition instance - * - * @api - */ - public function __construct(array $parameters, InputDefinition $definition = null) - { - $this->parameters = $parameters; - - parent::__construct($definition); - } - - /** - * Returns the first argument from the raw parameters (not parsed). - * - * @return string The value of the first argument or null otherwise - */ - public function getFirstArgument() - { - foreach ($this->parameters as $key => $value) { - if ($key && '-' === $key[0]) { - continue; - } - - return $value; - } - } - - /** - * Returns true if the raw parameters (not parsed) contain a value. - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The values to look for in the raw parameters (can be an array) - * - * @return Boolean true if the value is contained in the raw parameters - */ - public function hasParameterOption($values) - { - $values = (array) $values; - - foreach ($this->parameters as $k => $v) { - if (!is_int($k)) { - $v = $k; - } - - if (in_array($v, $values)) { - return true; - } - } - - return false; - } - - /** - * Returns the value of a raw option (not parsed). - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found - * - * @return mixed The option value - */ - public function getParameterOption($values, $default = false) - { - $values = (array) $values; - - foreach ($this->parameters as $k => $v) { - if (is_int($k) && in_array($v, $values)) { - return true; - } elseif (in_array($k, $values)) { - return $v; - } - } - - return $default; - } - - /** - * Returns a stringified representation of the args passed to the command - * - * @return string - */ - public function __toString() - { - $params = array(); - foreach ($this->parameters as $param => $val) { - if ($param && '-' === $param[0]) { - $params[] = $param . ('' != $val ? '='.$this->escapeToken($val) : ''); - } else { - $params[] = $this->escapeToken($val); - } - } - - return implode(' ', $params); - } - - /** - * Processes command line arguments. - */ - protected function parse() - { - foreach ($this->parameters as $key => $value) { - if (0 === strpos($key, '--')) { - $this->addLongOption(substr($key, 2), $value); - } elseif ('-' === $key[0]) { - $this->addShortOption(substr($key, 1), $value); - } else { - $this->addArgument($key, $value); - } - } - } - - /** - * Adds a short option value. - * - * @param string $shortcut The short option key - * @param mixed $value The value for the option - * - * @throws \InvalidArgumentException When option given doesn't exist - */ - private function addShortOption($shortcut, $value) - { - if (!$this->definition->hasShortcut($shortcut)) { - throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); - } - - $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); - } - - /** - * Adds a long option value. - * - * @param string $name The long option key - * @param mixed $value The value for the option - * - * @throws \InvalidArgumentException When option given doesn't exist - * @throws \InvalidArgumentException When a required value is missing - */ - private function addLongOption($name, $value) - { - if (!$this->definition->hasOption($name)) { - throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); - } - - $option = $this->definition->getOption($name); - - if (null === $value) { - if ($option->isValueRequired()) { - throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name)); - } - - $value = $option->isValueOptional() ? $option->getDefault() : true; - } - - $this->options[$name] = $value; - } - - /** - * Adds an argument value. - * - * @param string $name The argument name - * @param mixed $value The value for the argument - * - * @throws \InvalidArgumentException When argument given doesn't exist - */ - private function addArgument($name, $value) - { - if (!$this->definition->hasArgument($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); - } - - $this->arguments[$name] = $value; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -if (!defined('JSON_UNESCAPED_UNICODE')) { - define('JSON_UNESCAPED_SLASHES', 64); - define('JSON_UNESCAPED_UNICODE', 256); -} - -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; - -/** - * A InputDefinition represents a set of valid command line arguments and options. - * - * Usage: - * - * $definition = new InputDefinition(array( - * new InputArgument('name', InputArgument::REQUIRED), - * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), - * )); - * - * @author Fabien Potencier - * - * @api - */ -class InputDefinition -{ - private $arguments; - private $requiredCount; - private $hasAnArrayArgument = false; - private $hasOptional; - private $options; - private $shortcuts; - - /** - * Constructor. - * - * @param array $definition An array of InputArgument and InputOption instance - * - * @api - */ - public function __construct(array $definition = array()) - { - $this->setDefinition($definition); - } - - /** - * Sets the definition of the input. - * - * @param array $definition The definition array - * - * @api - */ - public function setDefinition(array $definition) - { - $arguments = array(); - $options = array(); - foreach ($definition as $item) { - if ($item instanceof InputOption) { - $options[] = $item; - } else { - $arguments[] = $item; - } - } - - $this->setArguments($arguments); - $this->setOptions($options); - } - - /** - * Sets the InputArgument objects. - * - * @param InputArgument[] $arguments An array of InputArgument objects - * - * @api - */ - public function setArguments($arguments = array()) - { - $this->arguments = array(); - $this->requiredCount = 0; - $this->hasOptional = false; - $this->hasAnArrayArgument = false; - $this->addArguments($arguments); - } - - /** - * Adds an array of InputArgument objects. - * - * @param InputArgument[] $arguments An array of InputArgument objects - * - * @api - */ - public function addArguments($arguments = array()) - { - if (null !== $arguments) { - foreach ($arguments as $argument) { - $this->addArgument($argument); - } - } - } - - /** - * Adds an InputArgument object. - * - * @param InputArgument $argument An InputArgument object - * - * @throws \LogicException When incorrect argument is given - * - * @api - */ - public function addArgument(InputArgument $argument) - { - if (isset($this->arguments[$argument->getName()])) { - throw new \LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName())); - } - - if ($this->hasAnArrayArgument) { - throw new \LogicException('Cannot add an argument after an array argument.'); - } - - if ($argument->isRequired() && $this->hasOptional) { - throw new \LogicException('Cannot add a required argument after an optional one.'); - } - - if ($argument->isArray()) { - $this->hasAnArrayArgument = true; - } - - if ($argument->isRequired()) { - ++$this->requiredCount; - } else { - $this->hasOptional = true; - } - - $this->arguments[$argument->getName()] = $argument; - } - - /** - * Returns an InputArgument by name or by position. - * - * @param string|integer $name The InputArgument name or position - * - * @return InputArgument An InputArgument object - * - * @throws \InvalidArgumentException When argument given doesn't exist - * - * @api - */ - public function getArgument($name) - { - if (!$this->hasArgument($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); - } - - $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; - - return $arguments[$name]; - } - - /** - * Returns true if an InputArgument object exists by name or position. - * - * @param string|integer $name The InputArgument name or position - * - * @return Boolean true if the InputArgument object exists, false otherwise - * - * @api - */ - public function hasArgument($name) - { - $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; - - return isset($arguments[$name]); - } - - /** - * Gets the array of InputArgument objects. - * - * @return InputArgument[] An array of InputArgument objects - * - * @api - */ - public function getArguments() - { - return $this->arguments; - } - - /** - * Returns the number of InputArguments. - * - * @return integer The number of InputArguments - */ - public function getArgumentCount() - { - return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments); - } - - /** - * Returns the number of required InputArguments. - * - * @return integer The number of required InputArguments - */ - public function getArgumentRequiredCount() - { - return $this->requiredCount; - } - - /** - * Gets the default values. - * - * @return array An array of default values - */ - public function getArgumentDefaults() - { - $values = array(); - foreach ($this->arguments as $argument) { - $values[$argument->getName()] = $argument->getDefault(); - } - - return $values; - } - - /** - * Sets the InputOption objects. - * - * @param InputOption[] $options An array of InputOption objects - * - * @api - */ - public function setOptions($options = array()) - { - $this->options = array(); - $this->shortcuts = array(); - $this->addOptions($options); - } - - /** - * Adds an array of InputOption objects. - * - * @param InputOption[] $options An array of InputOption objects - * - * @api - */ - public function addOptions($options = array()) - { - foreach ($options as $option) { - $this->addOption($option); - } - } - - /** - * Adds an InputOption object. - * - * @param InputOption $option An InputOption object - * - * @throws \LogicException When option given already exist - * - * @api - */ - public function addOption(InputOption $option) - { - if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { - throw new \LogicException(sprintf('An option named "%s" already exists.', $option->getName())); - } - - if ($option->getShortcut()) { - foreach (explode('|', $option->getShortcut()) as $shortcut) { - if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) { - throw new \LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut)); - } - } - } - - $this->options[$option->getName()] = $option; - if ($option->getShortcut()) { - foreach (explode('|', $option->getShortcut()) as $shortcut) { - $this->shortcuts[$shortcut] = $option->getName(); - } - } - } - - /** - * Returns an InputOption by name. - * - * @param string $name The InputOption name - * - * @return InputOption A InputOption object - * - * @throws \InvalidArgumentException When option given doesn't exist - * - * @api - */ - public function getOption($name) - { - if (!$this->hasOption($name)) { - throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); - } - - return $this->options[$name]; - } - - /** - * Returns true if an InputOption object exists by name. - * - * @param string $name The InputOption name - * - * @return Boolean true if the InputOption object exists, false otherwise - * - * @api - */ - public function hasOption($name) - { - return isset($this->options[$name]); - } - - /** - * Gets the array of InputOption objects. - * - * @return InputOption[] An array of InputOption objects - * - * @api - */ - public function getOptions() - { - return $this->options; - } - - /** - * Returns true if an InputOption object exists by shortcut. - * - * @param string $name The InputOption shortcut - * - * @return Boolean true if the InputOption object exists, false otherwise - */ - public function hasShortcut($name) - { - return isset($this->shortcuts[$name]); - } - - /** - * Gets an InputOption by shortcut. - * - * @param string $shortcut the Shortcut name - * - * @return InputOption An InputOption object - */ - public function getOptionForShortcut($shortcut) - { - return $this->getOption($this->shortcutToName($shortcut)); - } - - /** - * Gets an array of default values. - * - * @return array An array of all default values - */ - public function getOptionDefaults() - { - $values = array(); - foreach ($this->options as $option) { - $values[$option->getName()] = $option->getDefault(); - } - - return $values; - } - - /** - * Returns the InputOption name given a shortcut. - * - * @param string $shortcut The shortcut - * - * @return string The InputOption name - * - * @throws \InvalidArgumentException When option given does not exist - */ - private function shortcutToName($shortcut) - { - if (!isset($this->shortcuts[$shortcut])) { - throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); - } - - return $this->shortcuts[$shortcut]; - } - - /** - * Gets the synopsis. - * - * @return string The synopsis - */ - public function getSynopsis() - { - $elements = array(); - foreach ($this->getOptions() as $option) { - $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; - $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName()); - } - - foreach ($this->getArguments() as $argument) { - $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : '')); - - if ($argument->isArray()) { - $elements[] = sprintf('... [%sN]', $argument->getName()); - } - } - - return implode(' ', $elements); - } - - /** - * Returns a textual representation of the InputDefinition. - * - * @return string A string representing the InputDefinition - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asText() - { - $descriptor = new TextDescriptor(); - - return $descriptor->describe($this); - } - - /** - * Returns an XML representation of the InputDefinition. - * - * @param Boolean $asDom Whether to return a DOM or an XML string - * - * @return string|\DOMDocument An XML string representing the InputDefinition - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asXml($asDom = false) - { - $descriptor = new XmlDescriptor(); - - return $descriptor->describe($this, array('as_dom' => $asDom)); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter interface for console output. - * - * @author Konstantin Kudryashov - * - * @api - */ -interface OutputFormatterInterface -{ - /** - * Sets the decorated flag. - * - * @param Boolean $decorated Whether to decorate the messages or not - * - * @api - */ - public function setDecorated($decorated); - - /** - * Gets the decorated flag. - * - * @return Boolean true if the output will decorate messages, false otherwise - * - * @api - */ - public function isDecorated(); - - /** - * Sets a new style. - * - * @param string $name The style name - * @param OutputFormatterStyleInterface $style The style instance - * - * @api - */ - public function setStyle($name, OutputFormatterStyleInterface $style); - - /** - * Checks if output formatter has style with specified name. - * - * @param string $name - * - * @return Boolean - * - * @api - */ - public function hasStyle($name); - - /** - * Gets style options from style with specified name. - * - * @param string $name - * - * @return OutputFormatterStyleInterface - * - * @api - */ - public function getStyle($name); - - /** - * Formats a message according to the given styles. - * - * @param string $message The message to style - * - * @return string The styled message - * - * @api - */ - public function format($message); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter class for console output. - * - * @author Konstantin Kudryashov - * - * @api - */ -class OutputFormatter implements OutputFormatterInterface -{ - /** - * The pattern to phrase the format. - */ - const FORMAT_PATTERN = '#(\\\\?)<(/?)([a-z][a-z0-9_=;-]*)?>((?: [^<\\\\]+ | (?!<(?:/?[a-z]|/>)). | .(?<=\\\\<) )*)#isx'; - - private $decorated; - private $styles = array(); - private $styleStack; - - /** - * Escapes "<" special char in given text. - * - * @param string $text Text to escape - * - * @return string Escaped text - */ - public static function escape($text) - { - return preg_replace('/([^\\\\]?) FormatterStyle" instances - * - * @api - */ - public function __construct($decorated = null, array $styles = array()) - { - $this->decorated = (Boolean) $decorated; - - $this->setStyle('error', new OutputFormatterStyle('white', 'red')); - $this->setStyle('info', new OutputFormatterStyle('green')); - $this->setStyle('comment', new OutputFormatterStyle('yellow')); - $this->setStyle('question', new OutputFormatterStyle('black', 'cyan')); - - foreach ($styles as $name => $style) { - $this->setStyle($name, $style); - } - - $this->styleStack = new OutputFormatterStyleStack(); - } - - /** - * Sets the decorated flag. - * - * @param Boolean $decorated Whether to decorate the messages or not - * - * @api - */ - public function setDecorated($decorated) - { - $this->decorated = (Boolean) $decorated; - } - - /** - * Gets the decorated flag. - * - * @return Boolean true if the output will decorate messages, false otherwise - * - * @api - */ - public function isDecorated() - { - return $this->decorated; - } - - /** - * Sets a new style. - * - * @param string $name The style name - * @param OutputFormatterStyleInterface $style The style instance - * - * @api - */ - public function setStyle($name, OutputFormatterStyleInterface $style) - { - $this->styles[strtolower($name)] = $style; - } - - /** - * Checks if output formatter has style with specified name. - * - * @param string $name - * - * @return Boolean - * - * @api - */ - public function hasStyle($name) - { - return isset($this->styles[strtolower($name)]); - } - - /** - * Gets style options from style with specified name. - * - * @param string $name - * - * @return OutputFormatterStyleInterface - * - * @throws \InvalidArgumentException When style isn't defined - * - * @api - */ - public function getStyle($name) - { - if (!$this->hasStyle($name)) { - throw new \InvalidArgumentException(sprintf('Undefined style: %s', $name)); - } - - return $this->styles[strtolower($name)]; - } - - /** - * Formats a message according to the given styles. - * - * @param string $message The message to style - * - * @return string The styled message - * - * @api - */ - public function format($message) - { - $message = preg_replace_callback(self::FORMAT_PATTERN, array($this, 'replaceStyle'), $message); - - return str_replace('\\<', '<', $message); - } - - /** - * @return OutputFormatterStyleStack - */ - public function getStyleStack() - { - return $this->styleStack; - } - - /** - * Replaces style of the output. - * - * All escaped tags and tags that reference unknown styles are kept as is. - * - * @param array $match - * - * @return string The replaced style - */ - private function replaceStyle($match) - { - // we got "\<" escaped char - if ('\\' === $match[1]) { - return $this->applyCurrentStyle($match[0]); - } - - if ('' === $match[3]) { - if ('/' === $match[2]) { - // we got "" tag - $this->styleStack->pop(); - - return $this->applyCurrentStyle($match[4]); - } - - // we got "<>" tag - return '<>'.$this->applyCurrentStyle($match[4]); - } - - if (isset($this->styles[strtolower($match[3])])) { - $style = $this->styles[strtolower($match[3])]; - } else { - $style = $this->createStyleFromString($match[3]); - - if (false === $style) { - return $this->applyCurrentStyle($match[0]); - } - } - - if ('/' === $match[2]) { - $this->styleStack->pop($style); - } else { - $this->styleStack->push($style); - } - - return $this->applyCurrentStyle($match[4]); - } - - /** - * Tries to create new style instance from string. - * - * @param string $string - * - * @return OutputFormatterStyle|Boolean false if string is not format string - */ - private function createStyleFromString($string) - { - if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) { - return false; - } - - $style = new OutputFormatterStyle(); - foreach ($matches as $match) { - array_shift($match); - - if ('fg' == $match[0]) { - $style->setForeground($match[1]); - } elseif ('bg' == $match[0]) { - $style->setBackground($match[1]); - } else { - $style->setOption($match[1]); - } - } - - return $style; - } - - /** - * Applies current style from stack to text, if must be applied. - * - * @param string $text Input text - * - * @return string Styled text - */ - private function applyCurrentStyle($text) - { - return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter style class for defining styles. - * - * @author Konstantin Kudryashov - * - * @api - */ -class OutputFormatterStyle implements OutputFormatterStyleInterface -{ - private static $availableForegroundColors = array( - 'black' => 30, - 'red' => 31, - 'green' => 32, - 'yellow' => 33, - 'blue' => 34, - 'magenta' => 35, - 'cyan' => 36, - 'white' => 37 - ); - private static $availableBackgroundColors = array( - 'black' => 40, - 'red' => 41, - 'green' => 42, - 'yellow' => 43, - 'blue' => 44, - 'magenta' => 45, - 'cyan' => 46, - 'white' => 47 - ); - private static $availableOptions = array( - 'bold' => 1, - 'underscore' => 4, - 'blink' => 5, - 'reverse' => 7, - 'conceal' => 8 - ); - - private $foreground; - private $background; - private $options = array(); - - /** - * Initializes output formatter style. - * - * @param string $foreground The style foreground color name - * @param string $background The style background color name - * @param array $options The style options - * - * @api - */ - public function __construct($foreground = null, $background = null, array $options = array()) - { - if (null !== $foreground) { - $this->setForeground($foreground); - } - if (null !== $background) { - $this->setBackground($background); - } - if (count($options)) { - $this->setOptions($options); - } - } - - /** - * Sets style foreground color. - * - * @param string $color The color name - * - * @throws \InvalidArgumentException When the color name isn't defined - * - * @api - */ - public function setForeground($color = null) - { - if (null === $color) { - $this->foreground = null; - - return; - } - - if (!isset(static::$availableForegroundColors[$color])) { - throw new \InvalidArgumentException(sprintf( - 'Invalid foreground color specified: "%s". Expected one of (%s)', - $color, - implode(', ', array_keys(static::$availableForegroundColors)) - )); - } - - $this->foreground = static::$availableForegroundColors[$color]; - } - - /** - * Sets style background color. - * - * @param string $color The color name - * - * @throws \InvalidArgumentException When the color name isn't defined - * - * @api - */ - public function setBackground($color = null) - { - if (null === $color) { - $this->background = null; - - return; - } - - if (!isset(static::$availableBackgroundColors[$color])) { - throw new \InvalidArgumentException(sprintf( - 'Invalid background color specified: "%s". Expected one of (%s)', - $color, - implode(', ', array_keys(static::$availableBackgroundColors)) - )); - } - - $this->background = static::$availableBackgroundColors[$color]; - } - - /** - * Sets some specific style option. - * - * @param string $option The option name - * - * @throws \InvalidArgumentException When the option name isn't defined - * - * @api - */ - public function setOption($option) - { - if (!isset(static::$availableOptions[$option])) { - throw new \InvalidArgumentException(sprintf( - 'Invalid option specified: "%s". Expected one of (%s)', - $option, - implode(', ', array_keys(static::$availableOptions)) - )); - } - - if (false === array_search(static::$availableOptions[$option], $this->options)) { - $this->options[] = static::$availableOptions[$option]; - } - } - - /** - * Unsets some specific style option. - * - * @param string $option The option name - * - * @throws \InvalidArgumentException When the option name isn't defined - * - */ - public function unsetOption($option) - { - if (!isset(static::$availableOptions[$option])) { - throw new \InvalidArgumentException(sprintf( - 'Invalid option specified: "%s". Expected one of (%s)', - $option, - implode(', ', array_keys(static::$availableOptions)) - )); - } - - $pos = array_search(static::$availableOptions[$option], $this->options); - if (false !== $pos) { - unset($this->options[$pos]); - } - } - - /** - * Sets multiple style options at once. - * - * @param array $options - */ - public function setOptions(array $options) - { - $this->options = array(); - - foreach ($options as $option) { - $this->setOption($option); - } - } - - /** - * Applies the style to a given text. - * - * @param string $text The text to style - * - * @return string - */ - public function apply($text) - { - $codes = array(); - - if (null !== $this->foreground) { - $codes[] = $this->foreground; - } - if (null !== $this->background) { - $codes[] = $this->background; - } - if (count($this->options)) { - $codes = array_merge($codes, $this->options); - } - - if (0 === count($codes)) { - return $text; - } - - return sprintf("\033[%sm%s\033[0m", implode(';', $codes), $text); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * @author Jean-François Simon - */ -class OutputFormatterStyleStack -{ - /** - * @var OutputFormatterStyleInterface[] - */ - private $styles; - - /** - * @var OutputFormatterStyleInterface - */ - private $emptyStyle; - - /** - * Constructor. - * - * @param OutputFormatterStyleInterface $emptyStyle - */ - public function __construct(OutputFormatterStyleInterface $emptyStyle = null) - { - $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle(); - $this->reset(); - } - - /** - * Resets stack (ie. empty internal arrays). - */ - public function reset() - { - $this->styles = array(); - } - - /** - * Pushes a style in the stack. - * - * @param OutputFormatterStyleInterface $style - */ - public function push(OutputFormatterStyleInterface $style) - { - $this->styles[] = $style; - } - - /** - * Pops a style from the stack. - * - * @param OutputFormatterStyleInterface $style - * - * @return OutputFormatterStyleInterface - * - * @throws \InvalidArgumentException When style tags incorrectly nested - */ - public function pop(OutputFormatterStyleInterface $style = null) - { - if (empty($this->styles)) { - return $this->emptyStyle; - } - - if (null === $style) { - return array_pop($this->styles); - } - - foreach (array_reverse($this->styles, true) as $index => $stackedStyle) { - if ($style->apply('') === $stackedStyle->apply('')) { - $this->styles = array_slice($this->styles, 0, $index); - - return $stackedStyle; - } - } - - throw new \InvalidArgumentException('Incorrectly nested style tag found.'); - } - - /** - * Computes current style with stacks top codes. - * - * @return OutputFormatterStyle - */ - public function getCurrent() - { - if (empty($this->styles)) { - return $this->emptyStyle; - } - - return $this->styles[count($this->styles)-1]; - } - - /** - * @param OutputFormatterStyleInterface $emptyStyle - * - * @return OutputFormatterStyleStack - */ - public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle) - { - $this->emptyStyle = $emptyStyle; - - return $this; - } - - /** - * @return OutputFormatterStyleInterface - */ - public function getEmptyStyle() - { - return $this->emptyStyle; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter style interface for defining styles. - * - * @author Konstantin Kudryashov - * - * @api - */ -interface OutputFormatterStyleInterface -{ - /** - * Sets style foreground color. - * - * @param string $color The color name - * - * @api - */ - public function setForeground($color = null); - - /** - * Sets style background color. - * - * @param string $color The color name - * - * @api - */ - public function setBackground($color = null); - - /** - * Sets some specific style option. - * - * @param string $option The option name - * - * @api - */ - public function setOption($option); - - /** - * Unsets some specific style option. - * - * @param string $option The option name - */ - public function unsetOption($option); - - /** - * Sets multiple style options at once. - * - * @param array $options - */ - public function setOptions(array $options); - - /** - * Applies the style to a given text. - * - * @param string $text The text to style - * - * @return string - */ - public function apply($text); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\EventDispatcher\Event; - -/** - * Allows to inspect input and output of a command. - * - * @author Francesco Levorato - */ -class ConsoleEvent extends Event -{ - protected $command; - - private $input; - private $output; - - public function __construct(Command $command, InputInterface $input, OutputInterface $output) - { - $this->command = $command; - $this->input = $input; - $this->output = $output; - } - - /** - * Gets the command that is executed. - * - * @return Command A Command instance - */ - public function getCommand() - { - return $this->command; - } - - /** - * Gets the input instance. - * - * @return InputInterface An InputInterface instance - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance. - * - * @return OutputInterface An OutputInterface instance - */ - public function getOutput() - { - return $this->output; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -use Symfony\Component\Console\Command\Command; - -/** - * Allows to do things before the command is executed. - * - * @author Fabien Potencier - */ -class ConsoleCommandEvent extends ConsoleEvent -{ -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Allows to manipulate the exit code of a command after its execution. - * - * @author Francesco Levorato - */ -class ConsoleTerminateEvent extends ConsoleEvent -{ - /** - * The exit code of the command. - * - * @var integer - */ - private $exitCode; - - public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode) - { - parent::__construct($command, $input, $output); - - $this->setExitCode($exitCode); - } - - /** - * Sets the exit code. - * - * @param integer $exitCode The command exit code - */ - public function setExitCode($exitCode) - { - $this->exitCode = $exitCode; - } - - /** - * Gets the exit code. - * - * @return integer The command exit code - */ - public function getExitCode() - { - return $this->exitCode; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Allows to handle exception thrown in a command. - * - * @author Fabien Potencier - */ -class ConsoleExceptionEvent extends ConsoleEvent -{ - private $exception; - private $exitCode; - - public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode) - { - parent::__construct($command, $input, $output); - - $this->setException($exception); - $this->exitCode = $exitCode; - } - - /** - * Returns the thrown exception. - * - * @return \Exception The thrown exception - */ - public function getException() - { - return $this->exception; - } - - /** - * Replaces the thrown exception. - * - * This exception will be thrown if no response is set in the event. - * - * @param \Exception $exception The thrown exception - */ - public function setException(\Exception $exception) - { - $this->exception = $exception; - } - - /** - * Gets the exit code. - * - * @return integer The command exit code - */ - public function getExitCode() - { - return $this->exitCode; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tester; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Output\StreamOutput; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Eases the testing of console commands. - * - * @author Fabien Potencier - */ -class CommandTester -{ - private $command; - private $input; - private $output; - - /** - * Constructor. - * - * @param Command $command A Command instance to test. - */ - public function __construct(Command $command) - { - $this->command = $command; - } - - /** - * Executes the command. - * - * Available options: - * - * * interactive: Sets the input interactive flag - * * decorated: Sets the output decorated flag - * * verbosity: Sets the output verbosity flag - * - * @param array $input An array of arguments and options - * @param array $options An array of options - * - * @return integer The command exit code - */ - public function execute(array $input, array $options = array()) - { - $this->input = new ArrayInput($input); - if (isset($options['interactive'])) { - $this->input->setInteractive($options['interactive']); - } - - $this->output = new StreamOutput(fopen('php://memory', 'w', false)); - if (isset($options['decorated'])) { - $this->output->setDecorated($options['decorated']); - } - if (isset($options['verbosity'])) { - $this->output->setVerbosity($options['verbosity']); - } - - return $this->command->run($this->input, $this->output); - } - - /** - * Gets the display returned by the last execution of the command. - * - * @param Boolean $normalize Whether to normalize end of lines to \n or not - * - * @return string The display - */ - public function getDisplay($normalize = false) - { - rewind($this->output->getStream()); - - $display = stream_get_contents($this->output->getStream()); - - if ($normalize) { - $display = str_replace(PHP_EOL, "\n", $display); - } - - return $display; - } - - /** - * Gets the input instance used by the last execution of the command. - * - * @return InputInterface The current input instance - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance used by the last execution of the command. - * - * @return OutputInterface The current output instance - */ - public function getOutput() - { - return $this->output; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tester; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\StreamOutput; - -/** - * Eases the testing of console applications. - * - * When testing an application, don't forget to disable the auto exit flag: - * - * $application = new Application(); - * $application->setAutoExit(false); - * - * @author Fabien Potencier - */ -class ApplicationTester -{ - private $application; - private $input; - private $output; - - /** - * Constructor. - * - * @param Application $application An Application instance to test. - */ - public function __construct(Application $application) - { - $this->application = $application; - } - - /** - * Executes the application. - * - * Available options: - * - * * interactive: Sets the input interactive flag - * * decorated: Sets the output decorated flag - * * verbosity: Sets the output verbosity flag - * - * @param array $input An array of arguments and options - * @param array $options An array of options - * - * @return integer The command exit code - */ - public function run(array $input, $options = array()) - { - $this->input = new ArrayInput($input); - if (isset($options['interactive'])) { - $this->input->setInteractive($options['interactive']); - } - - $this->output = new StreamOutput(fopen('php://memory', 'w', false)); - if (isset($options['decorated'])) { - $this->output->setDecorated($options['decorated']); - } - if (isset($options['verbosity'])) { - $this->output->setVerbosity($options['verbosity']); - } - - return $this->application->run($this->input, $this->output); - } - - /** - * Gets the display returned by the last execution of the application. - * - * @param Boolean $normalize Whether to normalize end of lines to \n or not - * - * @return string The display - */ - public function getDisplay($normalize = false) - { - rewind($this->output->getStream()); - - $display = stream_get_contents($this->output->getStream()); - - if ($normalize) { - $display = str_replace(PHP_EOL, "\n", $display); - } - - return $display; - } - - /** - * Gets the input instance used by the last execution of the application. - * - * @return InputInterface The current input instance - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance used by the last execution of the application. - * - * @return OutputInterface The current output instance - */ - public function getOutput() - { - return $this->output; - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package PHP - * @subpackage Timer - * @author Sebastian Bergmann - * @copyright 2010-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/php-timer - * @since File available since Release 1.0.0 - */ - -/** - * Utility class for timing. - * - * @package PHP - * @subpackage Timer - * @author Sebastian Bergmann - * @copyright 2010-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @version Release: @package_version@ - * @link http://github.com/sebastianbergmann/php-timer - * @since Class available since Release 1.0.0 - */ -class PHP_Timer -{ - /** - * @var array - */ - private static $times = array( - 'hour' => 3600000, - 'minute' => 60000, - 'second' => 1000 - ); - - /** - * @var array - */ - private static $startTimes = array(); - - /** - * @var float - */ - public static $requestTime; - - /** - * Starts the timer. - */ - public static function start() - { - array_push(self::$startTimes, microtime(TRUE)); - } - - /** - * Stops the timer and returns the elapsed time. - * - * @return float - */ - public static function stop() - { - return microtime(TRUE) - array_pop(self::$startTimes); - } - - /** - * Formats the elapsed time as a string. - * - * @param float $time - * @return string - */ - public static function secondsToTimeString($time) - { - $ms = round($time * 1000); - - foreach (self::$times as $unit => $value) { - if ($ms >= $value) { - $time = floor($ms / $value * 100.0) / 100.0; - return $time . ' ' . ($time == 1 ? $unit : $unit . 's'); - } - } - - return $ms . ' ms'; - } - - /** - * Formats the elapsed time since the start of the request as a string. - * - * @return string - */ - public static function timeSinceStartOfRequest() - { - return self::secondsToTimeString(microtime(TRUE) - self::$requestTime); - } - - /** - * Returns the resources (time, memory) of the request as a string. - * - * @return string - */ - public static function resourceUsage() - { - return sprintf( - 'Time: %s, Memory: %4.2fMb', - self::timeSinceStartOfRequest(), - memory_get_peak_usage(TRUE) / 1048576 - ); - } -} - -if (isset($_SERVER['REQUEST_TIME_FLOAT'])) { - PHP_Timer::$requestTime = $_SERVER['REQUEST_TIME_FLOAT']; -} - -else { - PHP_Timer::$requestTime = microtime(TRUE); -} - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license BSD License - */ - -namespace TheSeer\fDOM { - - /** - * fDOMException - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMException extends \Exception { - - const LoadError = 1; - const ParseError = 2; - const SaveError = 3; - const QueryError = 4; - const RegistrationFailed = 5; - const NoDOMXPath = 6; - const UnboundPrefix = 7; - const SetFailedError = 8; - const NameInvalid = 9; - - /** - * List of libxml error objects - * - * @var array - */ - private $errorList; - - - /** - * Full Error message - * - * @var string - */ - private $fullMessage = null; - - - /** - * Short Error Message - * - * @var string - */ - private $shortMessage = null; - - - private static $fullMesageMode = true; - - /** - * Constructor - * - * @param string $message Exception message - * @param integer $code Exception code - * @param Exception $chain optional chained exception - * - */ - public function __construct($message, $code = 0, \Exception $chain = NULL) { - $this->shortMessage = $message; - $this->errorList = libxml_get_errors(); - libxml_clear_errors(); - parent :: __construct($message, $code, $chain); - - $this->fullMessage = $message."\n\n"; - - foreach ($this->errorList as $error) { - // hack, skip "attempt to load external pseudo error" - if ($error->code=='1543') { - continue; - } - - if (empty($error->file)) { - $this->fullMessage .= '[XML-STRING] '; - } else { - $this->fullMessage .= '['.$error->file.'] '; - } - - $this->fullMessage .= '[Line: '.$error->line.' - Column: '.$error->column.'] '; - - switch ($error->level) { - case LIBXML_ERR_WARNING: - $this->fullMessage .= "Warning $error->code: "; - break; - case LIBXML_ERR_ERROR: - $this->fullMessage .= "Error $error->code: "; - break; - case LIBXML_ERR_FATAL: - $this->fullMessage .= "Fatal Error $error->code: "; - break; - } - - $this->fullMessage .= str_replace("\n", '', $error->message)."\n"; - - if (self::$fullMesageMode) { - $this->message = $this->fullMessage; - } - - } - } - - /** - * Accessor to fullMessage - * - * @return string - */ - public function getFullMessage() { - return $this->fullMessage; - } - - /** - * Access to shortMessage - * - * @return string - */ - public function getShortMessage() { - return $this->shortMessage; - } - - /** - * Accessor to errorList objets - * - * @return array - */ - public function getErrorList() { - return $this->errorList; - } - - /** - * Toggle wehter getMessage() should return full or only exception message - * - * @param boolean $full Flag to enable or disable full message output - * - * @return void - */ - public function toggleFullMessage($full = true) { - $this->message = $full ? $this->fullMessage : $this->shortMessage; - } - - /** - * Magic method for string context - * - * @return string - */ - public function __toString() { - return $this->fullMessage; - } - - } // fDOMException - -} - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - class XPathQueryException extends \Exception { - const KeyNotFound = 1; - } - -} - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * fDOMDocument extension to PHP's DOMDocument. - * This class adds various convenience methods to simplify APIs - * It is set to final since further extending it would even more - * break the Object structure after use of registerNodeClass. - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMDocument extends \DOMDocument { - - /** - * XPath Object instance - * - * @var fDOMXPath - */ - private $xp = NULL; - - /** - * List of registered prefixes and their namespace uri - * @var Array - */ - private $prefixes = array(); - - /** - * Extended DOMDocument constructor - * - * @param string $version XML Version, should be 1.0 - * @param string $encoding Encoding, defaults to utf-8 - * @param array $streamOptions optional stream options array - * - * @return fDOMDocument - */ - public function __construct($version = '1.0', $encoding = 'utf-8', $streamOptions = NULL) { - if (!is_null($streamOptions)) { - $this->setStreamContext($streamOptions); - } - - libxml_use_internal_errors(TRUE); - $rc = parent::__construct($version, $encoding); - - $this->registerNodeClass('\DOMDocument', get_called_class()); - $this->registerNodeClass('\DOMNode', 'TheSeer\fDOM\fDOMNode'); - $this->registerNodeClass('\DOMElement', 'TheSeer\fDOM\fDOMElement'); - $this->registerNodeClass('\DOMDocumentFragment', 'TheSeer\fDOM\fDOMDocumentFragment'); - - return $rc; - } - - /** - * Reset XPath object so the clone gets a new instance when needed - */ - public function __clone() { - $this->xp = new fDOMXPath($this); - foreach($this->prefixes as $prefix => $uri) { - $this->xp->registerNamespace($prefix, $uri); - } - } - - public function __toString() { - return $this->C14N(); - } - - /** - * Set Stream context options - * - * @param Array $options Stream context options - * - * @return boolean true on success, false on failure - */ - public function setStreamContext(Array $options) { - if (!count($options)) { - return FALSE; - } - $context = stream_context_create($options); - libxml_set_streams_context($context); - return TRUE; - } - - /** - * Wrapper to DOMDocument load with exception handling - * Returns true on success to satisfy the compatibilty of the original DOM Api - * - * @param string $fname File to load - * @param int|null $options LibXML Flags to pass - * - * @throws fDOMException - * - * @return bool|mixed - */ - public function load($fname, $options = LIBXML_NONET) { - $this->xp = NULL; - $tmp = parent :: load($fname, $options); - if (!$tmp || libxml_get_last_error()) { - throw new fDOMException("loading file '$fname' failed.", fDOMException::LoadError); - } - return TRUE; - } - - /** - * Wrapper to DOMDocument loadXML with exception handling - * Returns true on success to satisfy the compatibilty of the original DOM Api - * - * @param string $source XML source code - * @param integer $options LibXML option flags - * - * @throws fDOMException - * - * @return boolean - */ - public function loadXML($source, $options = LIBXML_NONET) { - $this->xp = NULL; - $tmp = parent :: loadXML($source, $options); - if (!$tmp || libxml_get_last_error()) { - throw new fDOMException('parsing string failed', fDOMException::ParseError); - } - return TRUE; - } - - /** - * Wrapper to DOMDocument loadHTMLFile with exception handling. - * Returns true on success to satisfy the compatibilty of the original DOM Api - * - * @param string $fname html file to load - * @param integer $options Options bitmask (@see DOMDocument::loadHTMLFile) - * - * @throws fDOMException - * - * @return boolean - */ - public function loadHTMLFile($fname, $options = NULL) { - $this->xp = NULL; - if (version_compare(PHP_VERSION, '5.4.0', '<')) { - if ($options != NULL) { - throw new fDOMException('Passing options requires PHP 5.4.0+', fDOMException::LoadError); - } - $tmp = parent :: loadHTMLFile($fname); - } else { - $tmp = parent :: loadHTMLFile($fname, $options); - } - if (!$tmp || libxml_get_last_error()) { - throw new fDOMException("loading html file '$fname' failed", fDOMException::LoadError); - } - return TRUE; - } - - /** - * Wrapper to DOMDocument loadHTML with exception handling - * Returns true on success to satisfy the compatibilty of the original DOM Api - * - * @param string $source html source code - * @param integer $options Options bitmask (@see DOMDocument::loadHTML) - * - * @throws fDOMException - * - * @return boolean - */ - public function loadHTML($source, $options = NULL) { - $this->xp = NULL; - if (version_compare(PHP_VERSION, '5.4.0', '<')) { - if ($options != NULL) { - throw new fDOMException('Passing options requires PHP 5.4.0+', fDOMException::LoadError); - } - $tmp = parent :: loadHTML($source); - } else { - $tmp = parent :: loadHTML($source, $options); - } - if (!$tmp || libxml_get_last_error()) { - throw new fDOMException('parsing html string failed', fDOMException::ParseError); - } - return TRUE; - } - - /** - * Wrapper to DOMDocument::save with exception handling - * - * @param string $filename filename to save to - * @param integer $options Options bitmask (@see DOMDocument::save) - * - * @throws fDOMException - * - * @return integer bytes saved - */ - public function save($filename, $options = NULL) { - $tmp = parent::save($filename, $options); - if (!$tmp) { - throw new fDOMException('saving xml file failed', fDOMException::SaveError); - } - return $tmp; - } - - /** - * Wrapper to DOMDocument::saveHTML with exception handling - * - * @param DOMNode|null $node Context DOMNode (optional) - * - * @throws fDOMException - * @return string html content - */ - public function saveHTML(\DOMNode $node = NULL) { - if (version_compare(PHP_VERSION, '5.3.6', '<') && $node != NULL) { - throw new fDOMException('Passing a context node requires PHP 5.3.6+', fDOMException::SaveError); - } - $tmp = parent::saveHTML($node); - if (!$tmp) { - throw new fDOMException('serializing to HTML failed', fDOMException::SaveError); - } - return $tmp; - } - - /** - * Wrapper to DOMDocument::saveHTMLfile with exception handling - * - * @param string $filename filename to save to - * @param integer $options Options bitmask (@see DOMDocument::saveHTMLFile) - * - * @throws fDOMException - * - * @return integer bytes saved - */ - public function saveHTMLFile($filename, $options = NULL) { - $tmp = parent::saveHTMLFile($filename, $options); - if (!$tmp) { - throw new fDOMException('saving to HTML file failed', fDOMException::SaveError); - } - return $tmp; - } - - /** - * Wrapper to DOMDocument::saveXML with exception handling - * - * @param \DOMNode $node node to start serializing at - * @param integer $options options flags as bitmask - * - * @throws fDOMException - * - * @return string serialized XML - */ - public function saveXML(\DOMNode $node = NULL, $options = NULL) { - try { - $tmp = parent::saveXML($node, $options); - if (!$tmp) { - throw new fDOMException('serializing to XML failed', fDOMException::SaveError); - } - return $tmp; - } catch (\Exception $e) { - if (!$e instanceof fDOMException) { - throw new fDOMException($e->getMessage(), fDOMException::SaveError, $e); - } - throw $e; - } - } - - /** - * get Instance of DOMXPath Object for current DOM - * - * @throws fDOMException - * - * @return fDOMXPath - */ - public function getDOMXPath() { - if (is_null($this->xp)) { - $this->xp = new fDOMXPath($this); - } - if (!$this->xp) { - throw new fDOMException('creating DOMXPath object failed.', fDOMException::NoDOMXPath); - } - return $this->xp; - } - - /** - * Convert a given DOMNodeList into a DOMFragment - * - * @param \DOMNodeList $list The Nodelist to process - * @param boolean $move Signale if nodes are to be moved into fragment or not - * - * @return fDOMDocumentFragment - */ - public function nodeList2Fragment(\DOMNodeList $list, $move=FALSE) { - $frag = $this->createDocumentFragment(); - /** @var fDOMNode $node */ - foreach($list as $node) { - $frag->appendChild($move ? $node : $node->cloneNode(TRUE)); - } - return $frag; - } - - /** - * Perform an xpath query - * - * @param String $q query string containing xpath - * @param \DOMNode|null $ctx (optional) Context DOMNode - * @param boolean $registerNodeNS Register flag pass through - * - * @return \DOMNodeList - */ - public function query($q, \DOMNode $ctx = NULL, $registerNodeNS = TRUE) { - if (is_null($this->xp)) { - $this->getDOMXPath(); - } - return $this->xp->evaluate($q, $ctx, $registerNodeNS); - } - - /** - * Perform an xpath query and return only the 1st match - * - * @param String $q query string containing xpath - * @param \DOMNode $ctx (optional) Context DOMNode - * @param boolean $registerNodeNS Register flag pass thru - * - * @return fDOMNode - */ - public function queryOne($q, \DOMNode $ctx = NULL, $registerNodeNS = TRUE) { - if (is_null($this->xp)) { - $this->getDOMXPath(); - } - return $this->xp->queryOne($q, $ctx, $registerNodeNS); - } - - /** - * Forwarder to fDOMXPath's prepare method allowing for easy and secure - * placeholder replacement comparable to sql's prepared statements - * . - * @param string $xpath String containing xpath with :placeholder markup - * @param array $valueMap Array containing keys (:placeholder) and value pairs to be quoted - * - * @return string - */ - public function prepareQuery($xpath, array $valueMap) { - if (is_null($this->xp)) { - $this->getDOMXPath(); - } - return $this->xp->prepare($xpath, $valueMap); - } - - /** - * Forward to DOMXPath->registerNamespace() - * - * @param string $prefix The prefix to use - * @param string $uri The uri to assign to this prefix - * - * @throws fDOMException - * - * @return void - */ - public function registerNamespace($prefix, $uri) { - if (is_null($this->xp)) { - $this->getDOMXPath(); - } - if (!$this->xp->registerNamespace($prefix, $uri)) { - throw new fDOMException("Registering namespace '$uri' with prefix '$prefix' failed.", fDOMException::RegistrationFailed); - } - $this->prefixes[$prefix] = $uri; - } - - /** - * Forward to DOMXPath->registerPHPFunctions() - * - * @param mixed $restrict Array of function names or string with functionname to restrict callabilty to - * - * @throws fDOMException - * - * @return void - */ - public function registerPHPFunctions($restrict = NULL) { - if (is_null($this->xp)) { - $this->getDOMXPath(); - } - $this->xp->registerPHPFunctions($restrict); - if (libxml_get_last_error()) { - throw new fDOMException("Registering php functions failed.", fDOMException::RegistrationFailed); - } - } - - /** - * Create a new element in namespace defined by given prefix - * - * @param string $prefix Namespace prefix for node to create - * @param string $name Name of not element to create - * @param string $content Optional content to be set - * @param bool $asTextNode Create content as textNode rather then setting nodeValue - * - * @throws fDOMException - * - * @return fDOMElement Reference to created fDOMElement - */ - public function createElementPrefix($prefix, $name, $content = NULL, $asTextNode = FALSE) { - if (!isset($this->prefixes[$prefix])) { - throw new fDOMException("'$prefix' not bound", fDOMException::UnboundPrefix); - } - return $this->createElementNS($this->prefixes[$prefix], $prefix.':'.$name, $content, $asTextNode); - } - - /** - * Create a new fDOMElement and return it, optionally set content - * - * @param string $name Name of node to create - * @param null $content Content to set (optional) - * @param bool $asTextNode Create content as textNode rather then setting nodeValue - * - * @throws fDOMException - * - * @return fDOMElement Reference to created fDOMElement - */ - public function createElement($name, $content = NULL, $asTextnode = FALSE) { - try { - $node = parent::createElement($name); - if (!$node) { - throw new fDOMException("Creating element with name '$name' failed", fDOMException::NameInvalid); - } - if ($content !== NULL) { - if ($asTextnode) { - $node->appendChild($this->createTextnode($content)); - } else { - $node->nodeValue = $content; - } - if (libxml_get_errors()) { - throw new fDOMException("Setting content value failed", fDOMException::SetFailedError); - } - } - } catch (\DOMException $e) { - throw new fDOMException("Creating elemnt with name '$name' failed", 0, $e); - } - return $node; - } - - /** - * Create a new fDOMElement within given namespace and return it - * - * @param string $namespace Namespace URI for node to create - * @param string $name Name of node to create - * @param null $content Content to set (optional) - * @param bool $asTextNode Create content as textNode rather then setting nodeValue - * - * @throws fDOMException - * - * @return fDOMElement - */ - public function createElementNS($namespace, $name, $content = NULL, $asTextNode = FALSE) { - $node = parent::createElementNS($namespace, $name); - if (!$node) { - throw new fDOMException("Creating element with name '$name' failed", fDOMException::NameInvalid); - } - if ($content !== NULL) { - if ($asTextNode) { - $node->appendChild($this->createTextnode($content)); - } else { - $node->nodeValue = $content; - } - if (libxml_get_errors()) { - throw new fDOMException("Setting content value failed", fDOMException::SetFailedError); - } - } - return $node; - } - - /** - * Check if the given node is in the same document - * - * @param \DOMNode $node Node to compare with - * - * @return boolean true on match, false if they differ - * - */ - public function inSameDocument(\DOMNode $node) { - if ($node instanceof \DOMDocument) { - return $this->isSameNode($node); - } - return $this->isSameNode($node->ownerDocument); - } - - /** - * Create a new element and append it as documentElement - * - * @param $name Name of not element to create - * @param $content Optional content to be set - * - * @return fDOMElement Reference to created fDOMElement - */ - public function appendElement($name, $content = NULL, $asTextNode = FALSE) { - return $this->appendChild( - $this->createElement($name, $content, $asTextNode) - ); - } - - /** - * Create a new element in given namespace and append it as documentElement - * - * @param $ns Namespace of node to create - * @param $name Name of not element to create - * @param $content Optional content to be set - * - * @return fDOMElement Reference to created fDOMElement - */ - public function appendElementNS($ns, $name, $content = NULL, $asTextNode = FALSE) { - return $this->appendChild( - $this->createElementNS($ns, $name, $content, $asTextNode) - ); - } - - } // fDOMDocument - -} - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * fDOMDocumentFragment - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMDocumentFragment extends \DOMDocumentFragment { - - public function __toString() { - return $this->C14N(); - } - - /** - * Wrapper to standard method with exception support - * - * @param string $str Data string to parse and append - * - * @return boolean true on success - */ - public function appendXML($str) { - if (!parent::appendXML($str)) { - throw new fDOMException('Appending xml string failed', fDOMException::ParseError); - } - return true; - } - - /** - * Check if the given node is in the same document - * - * @param \DOMNode $node Node to compare with - * - * @return boolean true on match, false if they differ - * - */ - public function inSameDocument(\DOMNode $node) { - return $this->ownerDocument->inSameDocument($node); - } - - } // fDOMDocumentFragment - -} - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * fDomElement - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMElement extends \DOMElement { - - public function __toString() { - return $this->C14N(); - } - - /** - * Forward to fDomDocument->query() - * - * @param string $q XPath to use - * @param \DOMNode $ctx \DOMNode to overwrite context - * @param boolean $registerNodeNS Register flag pass thru - * - * @return \DomNodeList - */ - public function query($q, \DOMNode $ctx = null, $registerNodeNS = true) { - return $this->ownerDocument->query($q, $ctx ? $ctx : $this, $registerNodeNS); - } - - /** - * Forward to fDomDocument->queryOne() - * - * @param string $q XPath to use - * @param \DOMNode $ctx (optional) \DOMNode to overwrite context - * @param boolean $registerNodeNS Register flag pass thru - * - * @return mixed - */ - public function queryOne($q, \DOMNode $ctx = null, $registerNodeNS = true) { - return $this->ownerDocument->queryOne($q, $ctx ? $ctx : $this, $registerNodeNS); - } - - /** - * Parse and append XML String to node - * - * @param String $str string to process - * - * @return fDomDocumentFragment Reference to the created Fragment - */ - public function appendXML($str) { - $frag = $this->ownerDocument->createDocumentFragment(); - $frag->appendXML($str); - $this->appendChild($frag); - return $frag; - } - - /** - * Create a new element and append it - * - * @param string $name Name of not element to create - * @param string $content Optional content to be set - * - * @return fDOMElement Reference to created fDOMElement - */ - public function appendElement($name, $content = null) { - $node = $this->ownerDocument->createElement($name, $content); - $this->appendChild($node); - return $node; - } - - /** - * Create a new element in given namespace and append it - * - * @param string $ns Namespace of node to create - * @param string $name Name of not element to create - * @param string $content Optional content to be set - * - * @return fDOMElement Reference to created fDOMElement - */ - public function appendElementNS($ns, $name, $content = null) { - $node = $this->ownerDocument->createElementNS($ns, $name, $content); - $this->appendChild($node); - return $node; - } - - /** - * Create a new element in given namespace and append it - * - * @param string $prefix Namespace prefix for node to create - * @param string $name Name of not element to create - * @param string $content Optional content to be set - * - * @return fDOMElement Reference to created fDOMElement - */ - public function appendElementPrefix($prefix, $name, $content = null) { - $node = $this->ownerDocument->createElementPrefix($prefix, $name, $content); - $this->appendChild($node); - return $node; - } - - /** - * Create a new text node and append it - * - * @param string $content Text content to be added - * - * @return \DOMText - */ - public function appendTextNode($content) { - $text = $this->ownerDocument->createTextNode($content); - $this->appendChild($text); - return $text; - } - - /** - * Wrapper to DomElement->getAttribute with default value option - * - * Note: A set but emptry attribute does NOT trigger use of the default - * - * @param string $attr Attribute to access - * @param string $default Default value to use if the attribute is not set - * - * @return string - */ - public function getAttribute($attr, $default='') { - return $this->hasAttribute($attr) ? parent::getAttribute($attr) : $default; - } - - /** - * Wrapper to DomElement->getAttributeNS with default value option - * - * Note: A set but empty attribute does NOT trigger use of the default - * - * @param string $ns Namespace of attribute - * @param string $attr Attribute to access - * @param string $default Default value to use if the attribute is not set - * - * @return string - */ - public function getAttributeNS($ns, $attr, $default='') { - return $this->hasAttributeNS($ns, $attr) ? parent::getAttributeNS($ns, $attr) : $default; - } - - /** - * Wrapper to DOMElement::setAttribute with additional entities support - * - * @param string $attr Attribute name to set - * @param string $value Value to set attribute to - * @param bool $keepEntitites Flag to signale if entities should be kept - * - * @throws fDOMException - * - * @return DOMAttr - * - * @see DOMElement::setAttribute() - */ - public function setAttribute($attr, $value, $keepEntities=false) { - if ($keepEntities === true) { - $attrNode = $this->ownerDocument->createAttribute($attr); - if (!$attrNode) { - throw new fDOMException("Setting attribute '$attr' failed.", fDOMException::SetFailedError); - } - $attrNode->value = $value; - $this->appendChild($attrNode); - return $attrNode; - } - return parent::setAttribute($attr, $value); - } - - /** - * Wrapper to namespace aware DOMElement::setAttributeNS with additional entities support - * - * @param string $ns namespace attribute should be in - * @param string $attr Attribute name to set - * @param string $value Value to set attribute to - * @param boolean $keepEntitites Flag to signale if entities should be kept - * - * @return \DOMAttr - * - * @see DOMElement::setAttribute() - */ - public function setAttributeNS($ns, $attr, $value, $keepEntities=false) { - if ($keepEntities === true) { - $attrNode = $this->ownerDocument->createAttributeNS($ns, $attr); - if (!$attrNode) { - throw new fDOMException("Setting attribute '$attr' failed.", fDOMException::SetFailedError); - } - $attrNode->value = $value; - $this->appendChild($attrNode); - return $attrNode; - } - return parent::setAttributeNS($ns, $attr, $value); - } - - /** - * Helper to add multiple attributes to an element - * - * @param array $attr Attributes to add as key-value pair - * @param bool $keepEntities Flag wether to keep entities - * - * @return array List with references to created DOMAttr - */ - public function setAttributes(array $attr, $keepEntities=false) { - $attList = array(); - foreach($attr as $name => $value) { - $attList[] = $this->setAttribute($name, $value, $keepEntities); - } - return $attList; - } - - /** - * Helper to add multiple attributes with the given namespace and prefix - * - * @param string $ns Namespace of attribute - * @param string $prefix Namespace prefix for attribute to create - * @param array $attr Attributes to add - * @param bool $keepEntities Flag wether to keep entities - * - * @return void - */ - public function setAttributesNS($ns, $prefix, array $attr, $keepEntities=false) { - foreach($attr as $name => $value) { - $this->setAttributeNS($ns, $prefix.':'.$name, $value, $keepEntities); - } - } - - /** - * Helper method to get children by name - * - * @param string $tagName tagname to search for - * - * @return DomNodeList - */ - public function getChildrenByTagName($tagName) { - return $this->query("*[local-name()='$tagName']"); - } - - /** - * Helper method to get children by name and namespace - * - * @param string $ns namespace nodes have to be in - * @param string $tagName tagname to search for - * - * @return DomNodeList - */ - public function getChildrenByTagNameNS($ns, $tagName) { - return $this->query("*[local-name()='$tagName' and namespace-uri()='$ns']"); - } - - /** - * Check if the given node is in the same document - * - * @param \DomNode $node Node to compare with - * - * @return boolean true on match, false if they differ - * - */ - public function inSameDocument(\DomNode $node) { - return $this->ownerDocument->inSameDocument($node); - } - - } // fDOMElement - -} - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * fDomNode - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMNode extends \DOMNode { - - public function __toString() { - return $this->C14N(); - } - - /** - * Check if the given node is in the same document - * - * @param \DomNode $node Node to compare with - * - * @return boolean true on match, false if they differ - * - */ - public function inSameDocument(\DOMNode $node) { - return $this->ownerDocument->inSameDocument($node); - } - - } // fDOMNode - -} - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * Class XPathQuery - * - * @package TheSeer\fDOM - */ - class XPathQuery { - - /** - * @var string - */ - private $query; - - /** - * Key-value Map for bound values - * - * @var array - */ - private $values = array(); - - /** - * @param string $query - */ - public function __construct($query) { - $this->setQuery($query); - } - - /** - * @param string $query - */ - private function setQuery($query) { - $this->query = $query; - $res = preg_match_all('/(:(\w*))/', $query, $matches); - if ($res > 0) { - $this->values = array_fill_keys($matches[2], ''); - } - } - - public function getKeys() { - return array_keys($this->values); - } - - public function bind($key, $value) { - if (!array_key_exists($key, $this->values)) { - throw new XPathQueryException("'$key' not found in query'", XPathQueryException::KeyNotFound ); - } - $this->values[$key] = $value; - } - - public function generate(\DOMNode $ctx, array $values = NULL) { - return $this->buildQuery($this->getXPathObjectFor($ctx), $values); - } - - public function evaluate(\DOMNode $ctx, array $values = NULL, $registerNodeNS = TRUE) { - $xp = $this->getXPathObjectFor($ctx); - return $xp->evaluate($this->buildQuery($xp, $values), $ctx, $registerNodeNS); - } - - public function query(\DOMNode $ctx, array $values = NULL, $registerNodeNS = TRUE) { - $xp = $this->getXPathObjectFor($ctx); - return $xp->evaluate($this->buildQuery($xp, $values), $ctx, $registerNodeNS); - } - - public function queryOne(\DOMNode $ctx, array $values = NULL, $registerNodeNS = TRUE) { - $xp = $this->getXPathObjectFor($ctx); - return $xp->queryOne($this->buildQuery($xp, $values), $ctx, $registerNodeNS); - } - - private function getXPathObjectFor(\DOMNode $ctx) { - $dom = $ctx instanceof \DOMDocument ? $ctx : $ctx->ownerDocument; - if ($dom instanceOf fDOMDocument) { - return $dom->getDOMXPath(); - } - return new fDOMXPath($dom); - } - - private function buildQuery(fDOMXPath $xp, array $values = NULL) { - $backup = $this->values; - if (count($values) > 0) { - foreach($values as $k => $v) { - $this->bind($k, $v); - } - } - $query = $xp->prepare($this->query, $this->values); - $this->values = $backup; - return $query; - } - } - -} - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * fDOMXPath extension to PHP's DOMXPath. - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMXPath extends \DOMXPath { - - protected $doc; - - public function __construct(\DOMDocument $doc) { - parent::__construct($doc); - $this->doc = $doc; - } - - public function prepare($xpath, array $valueMap) { - if (count($valueMap)==0) { - return $xpath; - } - foreach($valueMap as $key => $value) { - $xpath = str_replace(':'.$key, $this->quote($value), $xpath); - } - return $xpath; - } - - public function query($q, \DOMNode $ctx = null, $registerNodeNS = true) { - libxml_clear_errors(); - if (version_compare(PHP_VERSION, '5.3.3', '<')) { - $rc = parent::query($q, ($ctx instanceof \DOMNode) ? $ctx : $this->doc->documentElement); - } else { - $rc = parent::query($q, ($ctx instanceof \DOMNode) ? $ctx : $this->doc->documentElement, $registerNodeNS); - } - - if (libxml_get_last_error()) { - throw new fDOMException('evaluating xpath expression failed.', fDOMException::QueryError); - } - return $rc; - } - - public function evaluate($q, \DOMNode $ctx = null, $registerNodeNS = true) { - libxml_clear_errors(); - if (version_compare(PHP_VERSION, '5.3.3', '<')) { - $rc = parent::evaluate($q, ($ctx instanceof \DOMNode) ? $ctx : $this->doc->documentElement); - } else { - $rc = parent::evaluate($q, ($ctx instanceof \DOMNode) ? $ctx : $this->doc->documentElement, $registerNodeNS); - } - if (libxml_get_last_error()) { - throw new fDOMException('evaluating xpath expression failed.', fDOMException::QueryError); - } - return $rc; - } - - public function queryOne($q, \DOMNode $ctx = null, $registerNodeNS = true) { - $rc = $this->evaluate($q, $ctx, $registerNodeNS); - if ($rc instanceof \DOMNodelist) { - return $rc->item(0); - } - return $rc; - } - - public function quote($str) { - if (strpos($str, '"') === false) { - return '"'.$str.'"'; - } - $parts = explode('"', $str); - return 'concat("' . join('",\'"\',"', $parts).'")'; - } - } -}. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package FinderFacade - * @author Sebastian Bergmann - * @copyright 2012-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.0.0 - */ - -namespace SebastianBergmann\FinderFacade -{ - use Symfony\Component\Finder\Finder; - - /** - * Convenience wrapper for Symfony's Finder component. - * - * @author Sebastian Bergmann - * @copyright 2012-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @version Release: @package_version@ - * @link http://github.com/sebastianbergmann/finder-facade/tree - * @since Class available since Release 1.0.0 - */ - class FinderFacade - { - /** - * @var array - */ - protected $items = array(); - - /** - * @var array - */ - protected $excludes = array(); - - /** - * @var array - */ - protected $names = array(); - - - /** - * @var array - */ - protected $notNames = array(); - - /** - * @param array $items - * @param array $excludes - * @param array $names - * @param array $notNames - */ - public function __construct(array $items = array(), array $excludes = array(), array $names = array(), array $notNames = array()) - { - $this->items = $items; - $this->excludes = $excludes; - $this->names = $names; - $this->notNames = $notNames; - } - - /** - * @return array - */ - public function findFiles() - { - $files = array(); - $finder = new Finder; - $iterate = FALSE; - - foreach ($this->items as $item) { - if (!is_file($item)) { - $finder->in($item); - $iterate = TRUE; - } - - else { - $files[] = realpath($item); - } - } - - foreach ($this->excludes as $exclude) { - $finder->exclude($exclude); - } - - foreach ($this->names as $name) { - $finder->name($name); - } - - foreach ($this->notNames as $notName) { - $finder->notName($notName); - } - - if ($iterate) { - foreach ($finder as $file) { - $files[] = $file->getRealpath(); - } - } - - return $files; - } - - /** - * @param string $file - */ - public function loadConfiguration($file) - { - $configuration = new Configuration($file); - $configuration = $configuration->parse(); - - $this->items = $configuration['items']; - $this->excludes = $configuration['excludes']; - $this->names = $configuration['names']; - $this->notNames = $configuration['notNames']; - } - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package FinderFacade - * @author Sebastian Bergmann - * @copyright 2012-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.0.0 - */ - -namespace SebastianBergmann\FinderFacade -{ - use TheSeer\fDOM\fDOMDocument; - - /** - * - * - * - * /path/to/directory - * /path/to/file - * - * /path/to/directory - * *.php - * - * - * - * @author Sebastian Bergmann - * @copyright 2012-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @version Release: @package_version@ - * @link http://github.com/sebastianbergmann/finder-facade/tree - * @since Class available since Release 1.0.0 - */ - class Configuration - { - /** - * @var string - */ - protected $basePath; - - /** - * @var fDOMDocument - */ - protected $xml; - - /** - * @param string $file - */ - public function __construct($file) - { - $this->basePath = dirname($file); - - $this->xml = new fDOMDocument; - $this->xml->load($file); - } - - /** - * @param string $xpath - * @return array - */ - public function parse($xpath = '') - { - $result = array( - 'items' => array(), 'excludes' => array(), 'names' => array(), 'notNames' => array() - ); - - foreach ($this->xml->getDOMXPath()->query($xpath . 'include/directory') as $item) { - $result['items'][] = $this->toAbsolutePath($item->nodeValue); - } - - foreach ($this->xml->getDOMXPath()->query($xpath . 'include/file') as $item) { - $result['items'][] = $this->toAbsolutePath($item->nodeValue); - } - - foreach ($this->xml->getDOMXPath()->query($xpath . 'exclude') as $exclude) { - $result['excludes'][] = $exclude->nodeValue; - } - - foreach ($this->xml->getDOMXPath()->query($xpath . 'name') as $name) { - $result['names'][] = $name->nodeValue; - } - - foreach ($this->xml->getDOMXPath()->query($xpath . 'notName') as $name) { - $result['notNames'][] = $name->nodeValue; - } - - return $result; - } - - /** - * @param string $path - * @return string - */ - protected function toAbsolutePath($path) - { - // Check whether the path is already absolute. - if ($path[0] === '/' || $path[0] === '\\' || - (strlen($path) > 3 && ctype_alpha($path[0]) && - $path[1] === ':' && ($path[2] === '\\' || $path[2] === '/'))) { - return $path; - } - - // Check whether a stream is used. - if (strpos($path, '://') !== FALSE) { - return $path; - } - - return $this->basePath . DIRECTORY_SEPARATOR . $path; - } - } -} -$H.VIX\juR<13GBMB \ No newline at end of file diff --git a/puppet/modules/joindin/files/tests/phpdoc b/puppet/modules/joindin/files/tests/phpdoc deleted file mode 100644 index fe87b7d..0000000 Binary files a/puppet/modules/joindin/files/tests/phpdoc and /dev/null differ diff --git a/puppet/modules/joindin/files/tests/phploc b/puppet/modules/joindin/files/tests/phploc deleted file mode 100644 index d7b63d2..0000000 --- a/puppet/modules/joindin/files/tests/phploc +++ /dev/null @@ -1,17382 +0,0 @@ -#!/usr/bin/env php - '/finder-facade/Configuration.php', - 'sebastianbergmann\\finderfacade\\finderfacade' => '/finder-facade/FinderFacade.php', - 'sebastianbergmann\\git' => '/git/Git.php', - 'sebastianbergmann\\phploc\\analyser' => '/src/Analyser.php', - 'sebastianbergmann\\phploc\\cli\\application' => '/src/CLI/Application.php', - 'sebastianbergmann\\phploc\\cli\\command' => '/src/CLI/Command.php', - 'sebastianbergmann\\phploc\\log\\csv\\history' => '/src/Log/CSV/History.php', - 'sebastianbergmann\\phploc\\log\\csv\\single' => '/src/Log/CSV/Single.php', - 'sebastianbergmann\\phploc\\log\\text' => '/src/Log/Text.php', - 'sebastianbergmann\\phploc\\log\\xml' => '/src/Log/XML.php', - 'sebastianbergmann\\version' => '/version/Version.php', - 'symfony\\component\\console\\application' => '/symfony/console/Symfony/Component/Console/Application.php', - 'symfony\\component\\console\\command\\command' => '/symfony/console/Symfony/Component/Console/Command/Command.php', - 'symfony\\component\\console\\command\\helpcommand' => '/symfony/console/Symfony/Component/Console/Command/HelpCommand.php', - 'symfony\\component\\console\\command\\listcommand' => '/symfony/console/Symfony/Component/Console/Command/ListCommand.php', - 'symfony\\component\\console\\consoleevents' => '/symfony/console/Symfony/Component/Console/ConsoleEvents.php', - 'symfony\\component\\console\\descriptor\\applicationdescription' => '/symfony/console/Symfony/Component/Console/Descriptor/ApplicationDescription.php', - 'symfony\\component\\console\\descriptor\\descriptor' => '/symfony/console/Symfony/Component/Console/Descriptor/Descriptor.php', - 'symfony\\component\\console\\descriptor\\descriptorinterface' => '/symfony/console/Symfony/Component/Console/Descriptor/DescriptorInterface.php', - 'symfony\\component\\console\\descriptor\\jsondescriptor' => '/symfony/console/Symfony/Component/Console/Descriptor/JsonDescriptor.php', - 'symfony\\component\\console\\descriptor\\markdowndescriptor' => '/symfony/console/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php', - 'symfony\\component\\console\\descriptor\\textdescriptor' => '/symfony/console/Symfony/Component/Console/Descriptor/TextDescriptor.php', - 'symfony\\component\\console\\descriptor\\xmldescriptor' => '/symfony/console/Symfony/Component/Console/Descriptor/XmlDescriptor.php', - 'symfony\\component\\console\\event\\consolecommandevent' => '/symfony/console/Symfony/Component/Console/Event/ConsoleCommandEvent.php', - 'symfony\\component\\console\\event\\consoleevent' => '/symfony/console/Symfony/Component/Console/Event/ConsoleEvent.php', - 'symfony\\component\\console\\event\\consoleexceptionevent' => '/symfony/console/Symfony/Component/Console/Event/ConsoleExceptionEvent.php', - 'symfony\\component\\console\\event\\consoleterminateevent' => '/symfony/console/Symfony/Component/Console/Event/ConsoleTerminateEvent.php', - 'symfony\\component\\console\\formatter\\outputformatter' => '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php', - 'symfony\\component\\console\\formatter\\outputformatterinterface' => '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterInterface.php', - 'symfony\\component\\console\\formatter\\outputformatterstyle' => '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyle.php', - 'symfony\\component\\console\\formatter\\outputformatterstyleinterface' => '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php', - 'symfony\\component\\console\\formatter\\outputformatterstylestack' => '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php', - 'symfony\\component\\console\\helper\\descriptorhelper' => '/symfony/console/Symfony/Component/Console/Helper/DescriptorHelper.php', - 'symfony\\component\\console\\helper\\dialoghelper' => '/symfony/console/Symfony/Component/Console/Helper/DialogHelper.php', - 'symfony\\component\\console\\helper\\formatterhelper' => '/symfony/console/Symfony/Component/Console/Helper/FormatterHelper.php', - 'symfony\\component\\console\\helper\\helper' => '/symfony/console/Symfony/Component/Console/Helper/Helper.php', - 'symfony\\component\\console\\helper\\helperinterface' => '/symfony/console/Symfony/Component/Console/Helper/HelperInterface.php', - 'symfony\\component\\console\\helper\\helperset' => '/symfony/console/Symfony/Component/Console/Helper/HelperSet.php', - 'symfony\\component\\console\\helper\\inputawarehelper' => '/symfony/console/Symfony/Component/Console/Helper/InputAwareHelper.php', - 'symfony\\component\\console\\helper\\progresshelper' => '/symfony/console/Symfony/Component/Console/Helper/ProgressHelper.php', - 'symfony\\component\\console\\helper\\tablehelper' => '/symfony/console/Symfony/Component/Console/Helper/TableHelper.php', - 'symfony\\component\\console\\input\\argvinput' => '/symfony/console/Symfony/Component/Console/Input/ArgvInput.php', - 'symfony\\component\\console\\input\\arrayinput' => '/symfony/console/Symfony/Component/Console/Input/ArrayInput.php', - 'symfony\\component\\console\\input\\input' => '/symfony/console/Symfony/Component/Console/Input/Input.php', - 'symfony\\component\\console\\input\\inputargument' => '/symfony/console/Symfony/Component/Console/Input/InputArgument.php', - 'symfony\\component\\console\\input\\inputawareinterface' => '/symfony/console/Symfony/Component/Console/Input/InputAwareInterface.php', - 'symfony\\component\\console\\input\\inputdefinition' => '/symfony/console/Symfony/Component/Console/Input/InputDefinition.php', - 'symfony\\component\\console\\input\\inputinterface' => '/symfony/console/Symfony/Component/Console/Input/InputInterface.php', - 'symfony\\component\\console\\input\\inputoption' => '/symfony/console/Symfony/Component/Console/Input/InputOption.php', - 'symfony\\component\\console\\input\\stringinput' => '/symfony/console/Symfony/Component/Console/Input/StringInput.php', - 'symfony\\component\\console\\output\\bufferedoutput' => '/symfony/console/Symfony/Component/Console/Output/BufferedOutput.php', - 'symfony\\component\\console\\output\\consoleoutput' => '/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php', - 'symfony\\component\\console\\output\\consoleoutputinterface' => '/symfony/console/Symfony/Component/Console/Output/ConsoleOutputInterface.php', - 'symfony\\component\\console\\output\\nulloutput' => '/symfony/console/Symfony/Component/Console/Output/NullOutput.php', - 'symfony\\component\\console\\output\\output' => '/symfony/console/Symfony/Component/Console/Output/Output.php', - 'symfony\\component\\console\\output\\outputinterface' => '/symfony/console/Symfony/Component/Console/Output/OutputInterface.php', - 'symfony\\component\\console\\output\\streamoutput' => '/symfony/console/Symfony/Component/Console/Output/StreamOutput.php', - 'symfony\\component\\console\\shell' => '/symfony/console/Symfony/Component/Console/Shell.php', - 'symfony\\component\\console\\tester\\applicationtester' => '/symfony/console/Symfony/Component/Console/Tester/ApplicationTester.php', - 'symfony\\component\\console\\tester\\commandtester' => '/symfony/console/Symfony/Component/Console/Tester/CommandTester.php', - 'symfony\\component\\finder\\adapter\\abstractadapter' => '/symfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php', - 'symfony\\component\\finder\\adapter\\abstractfindadapter' => '/symfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php', - 'symfony\\component\\finder\\adapter\\adapterinterface' => '/symfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php', - 'symfony\\component\\finder\\adapter\\bsdfindadapter' => '/symfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php', - 'symfony\\component\\finder\\adapter\\gnufindadapter' => '/symfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php', - 'symfony\\component\\finder\\adapter\\phpadapter' => '/symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php', - 'symfony\\component\\finder\\comparator\\comparator' => '/symfony/finder/Symfony/Component/Finder/Comparator/Comparator.php', - 'symfony\\component\\finder\\comparator\\datecomparator' => '/symfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php', - 'symfony\\component\\finder\\comparator\\numbercomparator' => '/symfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.php', - 'symfony\\component\\finder\\exception\\accessdeniedexception' => '/symfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php', - 'symfony\\component\\finder\\exception\\adapterfailureexception' => '/symfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php', - 'symfony\\component\\finder\\exception\\exceptioninterface' => '/symfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php', - 'symfony\\component\\finder\\exception\\operationnotpermitedexception' => '/symfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.php', - 'symfony\\component\\finder\\exception\\shellcommandfailureexception' => '/symfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php', - 'symfony\\component\\finder\\expression\\expression' => '/symfony/finder/Symfony/Component/Finder/Expression/Expression.php', - 'symfony\\component\\finder\\expression\\glob' => '/symfony/finder/Symfony/Component/Finder/Expression/Glob.php', - 'symfony\\component\\finder\\expression\\regex' => '/symfony/finder/Symfony/Component/Finder/Expression/Regex.php', - 'symfony\\component\\finder\\expression\\valueinterface' => '/symfony/finder/Symfony/Component/Finder/Expression/ValueInterface.php', - 'symfony\\component\\finder\\finder' => '/symfony/finder/Symfony/Component/Finder/Finder.php', - 'symfony\\component\\finder\\glob' => '/symfony/finder/Symfony/Component/Finder/Glob.php', - 'symfony\\component\\finder\\iterator\\customfilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php', - 'symfony\\component\\finder\\iterator\\daterangefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php', - 'symfony\\component\\finder\\iterator\\depthrangefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php', - 'symfony\\component\\finder\\iterator\\excludedirectoryfilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php', - 'symfony\\component\\finder\\iterator\\filecontentfilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php', - 'symfony\\component\\finder\\iterator\\filenamefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php', - 'symfony\\component\\finder\\iterator\\filepathsiterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php', - 'symfony\\component\\finder\\iterator\\filetypefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php', - 'symfony\\component\\finder\\iterator\\filteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php', - 'symfony\\component\\finder\\iterator\\multiplepcrefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php', - 'symfony\\component\\finder\\iterator\\pathfilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php', - 'symfony\\component\\finder\\iterator\\recursivedirectoryiterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php', - 'symfony\\component\\finder\\iterator\\sizerangefilteriterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php', - 'symfony\\component\\finder\\iterator\\sortableiterator' => '/symfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.php', - 'symfony\\component\\finder\\shell\\command' => '/symfony/finder/Symfony/Component/Finder/Shell/Command.php', - 'symfony\\component\\finder\\shell\\shell' => '/symfony/finder/Symfony/Component/Finder/Shell/Shell.php', - 'symfony\\component\\finder\\splfileinfo' => '/symfony/finder/Symfony/Component/Finder/SplFileInfo.php', - 'theseer\\fdom\\fdomdocument' => '/fdomdocument/fDOMDocument.php', - 'theseer\\fdom\\fdomdocumentfragment' => '/fdomdocument/fDOMDocumentFragment.php', - 'theseer\\fdom\\fdomelement' => '/fdomdocument/fDOMElement.php', - 'theseer\\fdom\\fdomexception' => '/fdomdocument/fDOMException.php', - 'theseer\\fdom\\fdomnode' => '/fdomdocument/fDOMNode.php', - 'theseer\\fdom\\fdomxpath' => '/fdomdocument/fDOMXPath.php', - 'theseer\\fdom\\xpathquery' => '/fdomdocument/XPathQuery.php', - 'theseer\\fdom\\xpathqueryexception' => '/fdomdocument/XPathQueryException.php' - ); - } - - $class = strtolower($class); - - if (isset($classes[$class])) { - require 'phar://phploc-2.0.4.phar' . $classes[$class]; - } - } -); - -Phar::mapPhar('phploc-2.0.4.phar'); - -$application = new SebastianBergmann\PHPLOC\CLI\Application; -$application->run(); - -__HALT_COMPILER(); ?> -X$iphploc-2.0.4.pharversion/Version.php]R/-xsrc/Analyser.phpo]Roksrc/Log/Text.php&]R&eVsrc/Log/XML.php ]R Aksrc/Log/CSV/Single.php]Rʖehsrc/Log/CSV/History.php" ]R" 2src/CLI/Command.phpk(]Rk(F.ȶsrc/CLI/Application.phpD]RD~9symfony/finder/Symfony/Component/Finder/Shell/Command.php]Rp7symfony/finder/Symfony/Component/Finder/Shell/Shell.php]R2Gsymfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php]R)Lsymfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php]R UNsymfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php]RʽEsymfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.php ]R jMsymfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php]Rils_Lsymfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php]RxPKsymfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php]R{^ǶOsymfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php ]R 6sKsymfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpb]Rbn Fsymfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php -]R -ɔCsymfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php]R,GOsymfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php]R - -Isymfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php]Rz"Ssymfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php]RdBsymfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php -]R -kABsymfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php -]R -}]>symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php{ -]R{ -9!2Gsymfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php)]R)QJDsymfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php ]R Csymfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php]R 0symfony/finder/Symfony/Component/Finder/Glob.phpb ]Rb g@M7symfony/finder/Symfony/Component/Finder/SplFileInfo.php]R59Gsymfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.php -]R -PEsymfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php]R Asymfony/finder/Symfony/Component/Finder/Comparator/Comparator.php -]R -|FzAsymfony/finder/Symfony/Component/Finder/Expression/Expression.php& -]R& - 뇶<symfony/finder/Symfony/Component/Finder/Expression/Regex.php]R[ǐ;symfony/finder/Symfony/Component/Finder/Expression/Glob.php]REEsymfony/finder/Symfony/Component/Finder/Expression/ValueInterface.phpH]RH"Ssymfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.php]RPKsymfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php]RcW޶Hsymfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php]R7Rsymfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php9]R9Msymfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php]R>@2symfony/finder/Symfony/Component/Finder/Finder.phpV]RV=symfony/console/Symfony/Component/Console/Command/Command.php7@]R7@ƘAsymfony/console/Symfony/Component/Console/Command/HelpCommand.php_ -]R_ -mAsymfony/console/Symfony/Component/Console/Command/ListCommand.php -]R - xCsymfony/console/Symfony/Component/Console/Descriptor/Descriptor.php ]R mLsymfony/console/Symfony/Component/Console/Descriptor/DescriptorInterface.php]RJZ0<Gsymfony/console/Symfony/Component/Console/Descriptor/TextDescriptor.php]RFsymfony/console/Symfony/Component/Console/Descriptor/XmlDescriptor.php%]R%ﶲͶOsymfony/console/Symfony/Component/Console/Descriptor/ApplicationDescription.php ]R sXGsymfony/console/Symfony/Component/Console/Descriptor/JsonDescriptor.phpu]RuDKsymfony/console/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php.]R.lP9symfony/console/Symfony/Component/Console/Application.php]RPJ;symfony/console/Symfony/Component/Console/ConsoleEvents.php]R\0E;symfony/console/Symfony/Component/Console/Helper/Helper.php]RZ\>symfony/console/Symfony/Component/Console/Helper/HelperSet.php ]R Esymfony/console/Symfony/Component/Console/Helper/InputAwareHelper.php]Rs H@symfony/console/Symfony/Component/Console/Helper/TableHelper.php.]R.OeDsymfony/console/Symfony/Component/Console/Helper/HelperInterface.php]Rz׶Csymfony/console/Symfony/Component/Console/Helper/ProgressHelper.phpp.]Rp.XTEsymfony/console/Symfony/Component/Console/Helper/DescriptorHelper.php -]R -"U1Asymfony/console/Symfony/Component/Console/Helper/DialogHelper.php<@]R<@mDsymfony/console/Symfony/Component/Console/Helper/FormatterHelper.php]RgseBsymfony/console/Symfony/Component/Console/Output/ConsoleOutput.php ]R eAsymfony/console/Symfony/Component/Console/Output/StreamOutput.phpM ]RM XzCsymfony/console/Symfony/Component/Console/Output/BufferedOutput.phph]Rht|X4Ksymfony/console/Symfony/Component/Console/Output/ConsoleOutputInterface.php]R:2p?symfony/console/Symfony/Component/Console/Output/NullOutput.php]RF$_;symfony/console/Symfony/Component/Console/Output/Output.php;]R;sQDsymfony/console/Symfony/Component/Console/Output/OutputInterface.phpM ]RM z3symfony/console/Symfony/Component/Console/Shell.php%]R%?OŶ=symfony/console/Symfony/Component/Console/Input/ArgvInput.php)]R)Q?symfony/console/Symfony/Component/Console/Input/StringInput.php -]R -΂=Bsymfony/console/Symfony/Component/Console/Input/InputInterface.php&]R&o3޶?symfony/console/Symfony/Component/Console/Input/InputOption.phpV]RVOö9symfony/console/Symfony/Component/Console/Input/Input.php]RQkTAsymfony/console/Symfony/Component/Console/Input/InputArgument.php ]R '>symfony/console/Symfony/Component/Console/Input/ArrayInput.php%]R%pCsymfony/console/Symfony/Component/Console/Input/InputDefinition.php(0]R(01EGsymfony/console/Symfony/Component/Console/Input/InputAwareInterface.php^]R^9KhPsymfony/console/Symfony/Component/Console/Formatter/OutputFormatterInterface.php]RJp˶Gsymfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php ]R  +<Lsymfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyle.php&]R&onjQsymfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php -]R -v Usymfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php]R5@symfony/console/Symfony/Component/Console/Event/ConsoleEvent.php]R -Gsymfony/console/Symfony/Component/Console/Event/ConsoleCommandEvent.php]R||-&Isymfony/console/Symfony/Component/Console/Event/ConsoleTerminateEvent.php&]R&ZIsymfony/console/Symfony/Component/Console/Event/ConsoleExceptionEvent.phpA]RAsKBsymfony/console/Symfony/Component/Console/Tester/CommandTester.php]R~H(RFsymfony/console/Symfony/Component/Console/Tester/ApplicationTester.phpf ]Rf hr git/Git.php;]R;fdomdocument/fDOMException.php]R$fdomdocument/XPathQueryException.php]Rֶfdomdocument/fDOMDocument.phpP]RP'3%fdomdocument/fDOMDocumentFragment.php9 ]R9 t%fdomdocument/fDOMElement.php,]R,uOfdomdocument/fDOMNode.phpK -]RK -A~ fdomdocument/XPathQuery.phpi]RifBfdomdocument/fDOMXPath.php]R@QͶfinder-facade/FinderFacade.php]RՍfinder-facade/Configuration.php{]R{r. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package Version - * @author Sebastian Bergmann - * @copyright 2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/version - * @since File available since Release 1.0.0 - */ - -namespace SebastianBergmann -{ - /** - * @package Version - * @author Sebastian Bergmann - * @copyright 2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/version - * @since Class available since Release 1.0.0 - */ - class Version - { - private $path; - private $release; - private $version; - - /** - * @param string $release - * @param string $path - */ - public function __construct($release, $path) - { - $this->release = $release; - $this->path = $path; - } - - /** - * @return string - */ - public function getVersion() - { - if ($this->version === NULL) { - if (count(explode('.', $this->release)) == 3) { - $this->version = $this->release; - } else { - $this->version = $this->release . '-dev'; - } - - $git = $this->getGitInformation($this->path); - - if ($git) { - if (count(explode('.', $this->release)) == 3) { - $this->version = $git; - } else { - $git = explode('-', $git); - - $this->version = $this->release . '-' . $git[2]; - } - } - } - - return $this->version; - } - - /** - * @param string $path - * @return boolean|string - */ - private function getGitInformation($path) - { - if (!$this->isGitRepository($path)) { - return FALSE; - } - - $dir = getcwd(); - chdir($path); - $result = exec('git describe --tags 2>&1', $output, $returnCode); - chdir($dir); - - if ($returnCode !== 0) { - return FALSE; - } - - return $result; - } - - /** - * @param string $path - * @return boolean - */ - private function isGitRepository($path) - { - if (is_dir($path . DIRECTORY_SEPARATOR . '.git')) { - return TRUE; - } - - $path = dirname($path); - - if (strlen($path) == strlen(dirname($path))) { - return FALSE; - } - - return $this->isGitRepository($path); - } - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phploc - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.0.0 - */ - -namespace SebastianBergmann\PHPLOC -{ - // @codeCoverageIgnoreStart - if (!defined('T_TRAIT')) { - define('T_TRAIT', 1000); - } - // @codeCoverageIgnoreEnd - - /** - * PHPLOC code analyser. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phploc/tree - * @since Class available since Release 1.0.0 - */ - class Analyser - { - /** - * @var array - */ - private $namespaces = array(); - - /** - * @var array - */ - private $classes = array(); - - /** - * @var array - */ - private $constants = array(); - - /** - * @var array - */ - private $possibleConstantAccesses = array(); - - /** - * @var array - */ - private $count = array( - 'files' => 0, - 'loc' => 0, - 'lloc' => 0, - 'llocClasses' => 0, - 'llocFunctions' => 0, - 'llocGlobal' => 0, - 'cloc' => 0, - 'ccn' => 0, - 'ccnMethods' => 0, - 'interfaces' => 0, - 'traits' => 0, - 'classes' => 0, - 'abstractClasses' => 0, - 'concreteClasses' => 0, - 'functions' => 0, - 'namedFunctions' => 0, - 'anonymousFunctions' => 0, - 'methods' => 0, - 'publicMethods' => 0, - 'nonPublicMethods' => 0, - 'nonStaticMethods' => 0, - 'staticMethods' => 0, - 'constants' => 0, - 'classConstants' => 0, - 'globalConstants' => 0, - 'testClasses' => 0, - 'testMethods' => 0, - 'ccnByLloc' => 0, - 'ccnByNom' => 0, - 'llocByNoc' => 0, - 'llocByNom' => 0, - 'llocByNof' => 0, - 'methodCalls' => 0, - 'staticMethodCalls' => 0, - 'instanceMethodCalls' => 0, - 'attributeAccesses' => 0, - 'staticAttributeAccesses' => 0, - 'instanceAttributeAccesses' => 0, - 'globalAccesses' => 0, - 'globalVariableAccesses' => 0, - 'superGlobalVariableAccesses' => 0, - 'globalConstantAccesses' => 0, - ); - - /** - * @var array - */ - private $superGlobals = array( - '$_ENV' => TRUE, - '$_POST' => TRUE, - '$_GET' => TRUE, - '$_COOKIE' => TRUE, - '$_SERVER' => TRUE, - '$_FILES' => TRUE, - '$_REQUEST' => TRUE, - '$HTTP_ENV_VARS' => TRUE, - '$HTTP_POST_VARS' => TRUE, - '$HTTP_GET_VARS' => TRUE, - '$HTTP_COOKIE_VARS' => TRUE, - '$HTTP_SERVER_VARS' => TRUE, - '$HTTP_POST_FILES' => TRUE - ); - - /** - * Processes a set of files. - * - * @param array $files - * @param boolean $countTests - * @return array - * @since Method available since Release 1.2.0 - */ - public function countFiles(array $files, $countTests) - { - if ($countTests) { - foreach ($files as $file) { - $this->preProcessFile($file); - } - } - - $directories = array(); - - foreach ($files as $file) { - $directory = dirname($file); - - if (!isset($directories[$directory])) { - $directories[$directory] = TRUE; - } - - $this->countFile($file, $countTests); - } - - $count = $this->count; - - $count['directories'] = count($directories) - 1; - $count['namespaces'] = count($this->namespaces); - $count['classes'] = $count['abstractClasses'] + - $count['concreteClasses']; - $count['functions'] = $count['namedFunctions'] + - $count['anonymousFunctions']; - $count['constants'] = $count['classConstants'] + - $count['globalConstants']; - $count['attributeAccesses'] = $count['staticAttributeAccesses'] + - $count['instanceAttributeAccesses']; - $count['methodCalls'] = $count['staticMethodCalls'] + - $count['instanceMethodCalls']; - $count['llocGlobal'] = $count['lloc'] - - $count['llocClasses'] - - $count['llocFunctions']; - $count['ncloc'] = $count['loc'] - $count['cloc']; - - foreach ($this->possibleConstantAccesses as $possibleConstantAccess) { - if (in_array($possibleConstantAccess, $this->constants)) { - $count['globalConstantAccesses']++; - } - } - - $count['globalAccesses'] = $count['globalConstantAccesses'] + - $count['globalVariableAccesses'] + - $count['superGlobalVariableAccesses']; - - if ($count['lloc'] > 0) { - $count['ccnByLloc'] = $count['ccn'] / $count['lloc']; - } - - if ($count['methods'] > 0) { - $count['ccnByNom'] = ($count['methods'] + - $count['ccnMethods']) / - $count['methods']; - } - - if ($count['classes'] > 0) { - $count['llocByNoc'] = $count['llocClasses'] / $count['classes']; - } - - if ($count['methods'] > 0) { - $count['llocByNom'] = $count['llocClasses'] / $count['methods']; - } - - if ($count['functions'] > 0) { - $count['llocByNof'] = $count['llocFunctions'] / $count['functions']; - } - - return $count; - } - - /** - * Pre-processes a single file. - * - * @param string $filename - * @since Method available since Release 1.2.0 - */ - public function preProcessFile($filename) - { - $tokens = token_get_all(file_get_contents($filename)); - $numTokens = count($tokens); - $namespace = FALSE; - - for ($i = 0; $i < $numTokens; $i++) { - if (is_string($tokens[$i])) { - continue; - } - - switch ($tokens[$i][0]) { - case T_NAMESPACE: { - $namespace = $this->getNamespaceName($tokens, $i); - } - break; - - case T_CLASS: { - if (!$this->isClassDeclaration($tokens, $i)) { - continue; - } - - $className = $this->getClassName($namespace, $tokens, $i); - - if (isset($tokens[$i+4]) && is_array($tokens[$i+4]) && - $tokens[$i+4][0] == T_EXTENDS) { - $parent = $this->getClassName( - $namespace, $tokens, $i + 4 - ); - } else { - $parent = NULL; - } - - $this->classes[$className] = $parent; - } - break; - } - } - } - - /** - * Processes a single file. - * - * @param string $filename - * @param boolean $countTests - */ - public function countFile($filename, $countTests) - { - $buffer = file_get_contents($filename); - $this->count['loc'] += substr_count($buffer, "\n"); - $tokens = token_get_all($buffer); - $numTokens = count($tokens); - - unset($buffer); - - $this->count['files']++; - - $blocks = array(); - $currentBlock = FALSE; - $namespace = FALSE; - $className = NULL; - $functionName = NULL; - $testClass = FALSE; - - for ($i = 0; $i < $numTokens; $i++) { - if (is_string($tokens[$i])) { - $token = trim($tokens[$i]); - - if ($token == ';') { - if ($className !== NULL && !$testClass) { - $this->count['llocClasses']++; - } - - else if ($functionName !== NULL) { - $this->count['llocFunctions']++; - } - - $this->count['lloc']++; - } - - else if ($token == '?' && !$testClass) { - if ($className !== NULL) { - $this->count['ccnMethods']++; - } - - $this->count['ccn']++; - } - - else if ($token == '{') { - if ($currentBlock == T_CLASS) { - $block = $className; - } - - else if ($currentBlock == T_FUNCTION) { - $block = $functionName; - } - - else { - $block = FALSE; - } - - array_push($blocks, $block); - - $currentBlock = FALSE; - } - - else if ($token == '}') { - $block = array_pop($blocks); - - if ($block !== FALSE && $block !== NULL) { - if ($block == $functionName) { - $functionName = NULL; - } - - else if ($block == $className) { - $className = NULL; - $testClass = FALSE; - } - } - } - - continue; - } - - list ($token, $value) = $tokens[$i]; - - switch ($token) { - case T_NAMESPACE: { - $namespace = $this->getNamespaceName($tokens, $i); - - if (!isset($this->namespaces[$namespace])) { - $this->namespaces[$namespace] = TRUE; - } - } - break; - - case T_CLASS: - case T_INTERFACE: - case T_TRAIT: { - if (!$this->isClassDeclaration($tokens, $i)) { - continue; - } - - $className = $this->getClassName( - $namespace, $tokens, $i - ); - $currentBlock = T_CLASS; - - if ($token == T_TRAIT) { - $this->count['traits']++; - } - - else if ($token == T_INTERFACE) { - $this->count['interfaces']++; - } - - else { - if ($countTests && $this->isTestClass($className)) { - $testClass = TRUE; - $this->count['testClasses']++; - } else { - if (isset($tokens[$i-2]) && - is_array($tokens[$i-2]) && - $tokens[$i-2][0] == T_ABSTRACT) { - $this->count['abstractClasses']++; - } else { - $this->count['concreteClasses']++; - } - } - } - } - break; - - case T_FUNCTION: { - $currentBlock = T_FUNCTION; - - if (is_array($tokens[$i+2]) && - $tokens[$i+2][0] == T_STRING) { - $functionName = $tokens[$i+2][1]; - } - - else if ($tokens[$i+2] == '&' && - is_array($tokens[$i+3]) && - $tokens[$i+3][0] == T_STRING) { - $functionName = $tokens[$i+3][1]; - } - - else { - $currentBlock = 'anonymous function'; - $functionName = 'anonymous function'; - $this->count['anonymousFunctions']++; - } - - if ($currentBlock == T_FUNCTION) { - if ($className === NULL && - $functionName != 'anonymous function') { - $this->count['namedFunctions']++; - } else { - $static = FALSE; - $visibility = T_PUBLIC; - - for ($j = $i; $j > 0; $j--) { - if (is_string($tokens[$j])) { - if ($tokens[$j] == '{' || - $tokens[$j] == '}' || - $tokens[$j] == ';') { - break; - } - - continue; - } - - if (isset($tokens[$j][0])) { - switch ($tokens[$j][0]) { - case T_PRIVATE: { - $visibility = T_PRIVATE; - } - break; - - case T_PROTECTED: { - $visibility = T_PROTECTED; - } - break; - - case T_STATIC: { - $static = TRUE; - } - break; - } - } - } - - if ($testClass && - $this->isTestMethod($functionName, $visibility, $static, $tokens, $i)) { - $this->count['testMethods']++; - } - - else if (!$testClass) { - if (!$static) { - $this->count['nonStaticMethods']++; - } else { - $this->count['staticMethods']++; - } - - if ($visibility == T_PUBLIC) { - $this->count['publicMethods']++; - } else { - $this->count['nonPublicMethods']++; - } - - $this->count['methods']++; - } - } - } - } - break; - - case T_CURLY_OPEN: { - $currentBlock = T_CURLY_OPEN; - array_push($blocks, $currentBlock); - } - break; - - case T_DOLLAR_OPEN_CURLY_BRACES: { - $currentBlock = T_DOLLAR_OPEN_CURLY_BRACES; - array_push($blocks, $currentBlock); - } - break; - - case T_IF: - case T_ELSEIF: - case T_FOR: - case T_FOREACH: - case T_WHILE: - case T_CASE: - case T_CATCH: - case T_BOOLEAN_AND: - case T_LOGICAL_AND: - case T_BOOLEAN_OR: - case T_LOGICAL_OR: { - if (!$testClass) { - if ($className !== NULL) { - $this->count['ccnMethods']++; - } - - $this->count['ccn']++; - } - } - break; - - case T_COMMENT: { - $this->count['cloc']++; - } - break; - - case T_DOC_COMMENT: { - $this->count['cloc'] += substr_count($value, "\n") + 1; - } - break; - - case T_CONST: { - $this->count['classConstants']++; - } - break; - - case T_STRING: { - if ($value == 'define') { - $this->count['globalConstants']++; - - $j = $i + 1; - - while (isset($tokens[$j]) && $tokens[$j] != ';') { - if (is_array($tokens[$j]) && - $tokens[$j][0] == T_CONSTANT_ENCAPSED_STRING) { - $this->constants[] = str_replace( - '\'', '', $tokens[$j][1] - ); - - break; - } - - $j++; - } - } - - else { - $this->possibleConstantAccesses[] = $value; - } - } - break; - - case T_DOUBLE_COLON: - case T_OBJECT_OPERATOR: { - $n = $this->getNextNonWhitespaceTokenPos($tokens, $i); - $nn = $this->getNextNonWhitespaceTokenPos($tokens, $n); - - if ($n && $nn && - isset($tokens[$n][0]) && - ($tokens[$n][0] == T_STRING || - $tokens[$n][0] == T_VARIABLE) && - $tokens[$nn] == '(') { - if ($token == T_DOUBLE_COLON) { - $this->count['staticMethodCalls']++; - } else { - $this->count['instanceMethodCalls']++; - } - } else { - if ($token == T_DOUBLE_COLON && - $tokens[$n][0] == T_VARIABLE) { - $this->count['staticAttributeAccesses']++; - } - - else if ($token == T_OBJECT_OPERATOR) { - $this->count['instanceAttributeAccesses']++; - } - } - } - break; - - case T_GLOBAL: { - $this->count['globalVariableAccesses']++; - } - break; - - case T_VARIABLE: { - if ($value == '$GLOBALS') { - $this->count['globalVariableAccesses']++; - } - - else if (isset($this->superGlobals[$value])) { - $this->count['superGlobalVariableAccesses']++; - } - } - break; - } - } - } - - /** - * @param array $tokens - * @param integer $i - * @return string - * @since Method available since Release 1.3.0 - */ - private function getNamespaceName(array $tokens, $i) - { - if (isset($tokens[$i+2][1])) { - $namespace = $tokens[$i+2][1]; - - for ($j = $i+3; ; $j += 2) { - if (isset($tokens[$j]) && $tokens[$j][0] == T_NS_SEPARATOR) { - $namespace .= '\\' . $tokens[$j+1][1]; - } else { - break; - } - } - - return $namespace; - } - - return FALSE; - } - - /** - * @param string $namespace - * @param array $tokens - * @param integer $i - * @return string - * @since Method available since Release 1.3.0 - */ - private function getClassName($namespace, array $tokens, $i) - { - $i += 2; - $namespaced = FALSE; - - if (!isset($tokens[$i][1])) { - return 'invalid class name'; - } - - $className = $tokens[$i][1]; - - if ($className === '\\') { - $namespaced = TRUE; - } - - while (is_array($tokens[$i+1]) && $tokens[$i+1][0] !== T_WHITESPACE) { - $className .= $tokens[++$i][1]; - } - - if (!$namespaced && $namespace !== FALSE) { - $className = $namespace . '\\' . $className; - } - - return $className; - } - - /** - * @param string $className - * @return boolean - * @since Method available since Release 1.2.0 - */ - private function isTestClass($className) - { - $parent = $this->classes[$className]; - $result = FALSE; - - // Check ancestry for PHPUnit_Framework_TestCase. - while ($parent !== NULL) { - if ($parent == 'PHPUnit_Framework_TestCase' || - $parent == '\\PHPUnit_Framework_TestCase') { - $result = TRUE; - break; - } - - if (isset($this->classes[$parent])) { - $parent = $this->classes[$parent]; - } - - // Class has a parent that is declared in a file - // that was not pre-processed. - else { - break; - } - } - - // Fallback: Treat the class as a test case class if the name - // of the parent class ends with "TestCase". - if (!$result) { - if (substr($this->classes[$className], -8) == 'TestCase') { - $result = TRUE; - } - } - - return $result; - } - - /** - * @param string $functionName - * @param integer $visibility - * @param boolean $static - * @param array $tokens - * @param integer $currentToken - * @return boolean - * @since Method available since Release 2.0.0 - */ - private function isTestMethod($functionName, $visibility, $static, array $tokens, $currentToken) { - if ($static || $visibility != T_PUBLIC) { - return FALSE; - } - - if (strpos($functionName, 'test') === 0) { - return TRUE; - } - - while ($tokens[$currentToken][0] != T_DOC_COMMENT) { - if ($tokens[$currentToken] == '{' || $tokens[$currentToken] == '}') { - return FALSE; - } - - --$currentToken; - } - - return strpos($tokens[$currentToken][1], '@test') !== FALSE || - strpos($tokens[$currentToken][1], '@scenario') !== FALSE; - } - - /** - * @param array $tokens - * @param integer $start - * @return boolean - */ - private function getNextNonWhitespaceTokenPos(array $tokens, $start) - { - if (isset($tokens[$start+1])) { - if (isset($tokens[$start+1][0]) && - $tokens[$start+1][0] == T_WHITESPACE && - isset($tokens[$start+2])) { - return $start + 2; - } else { - return $start + 1; - } - } - - return FALSE; - } - - /** - * @param array $tokens - * @param integer $start - * @return boolean - */ - private function getPreviousNonWhitespaceTokenPos(array $tokens, $start) - { - if (isset($tokens[$start-1])) { - if (isset($tokens[$start-1][0]) && - $tokens[$start-1][0] == T_WHITESPACE && - isset($tokens[$start-2])) { - return $start - 2; - } else { - return $start - 1; - } - } - - return FALSE; - } - - private function isClassDeclaration($tokens, $i) - { - $n = $this->getPreviousNonWhitespaceTokenPos($tokens, $i); - - if (isset($tokens[$n]) && is_array($tokens[$n]) && - $tokens[$n][0] == T_DOUBLE_COLON) { - return FALSE; - } - - return TRUE; - } - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phploc - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 2.0.0 - */ - -namespace SebastianBergmann\PHPLOC\Log -{ - use Symfony\Component\Console\Output\OutputInterface; - - /** - * A ResultPrinter for the TextUI. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phploc/tree - * @since Class available since Release 1.0.0 - */ - class Text - { - /** - * Prints a result set. - * - * @param OutputInterface $output - * @param array $count - * @param boolean $printTests - */ - public function printResult(OutputInterface $output, array $count, $printTests) - { - if ($count['directories'] > 0) { - $output->write( - sprintf( - "Directories %10d\n" . - "Files %10d\n\n", - - $count['directories'], - $count['files'] - ) - ); - } - - $format = <<write( - sprintf( - $format, - $count['loc'], - $count['cloc'], - $count['loc'] > 0 ? ($count['cloc'] / $count['loc']) * 100 : 0, - $count['ncloc'], - $count['loc'] > 0 ? ($count['ncloc'] / $count['loc']) * 100 : 0, - $count['lloc'], - $count['loc'] > 0 ? ($count['lloc'] / $count['loc']) * 100 : 0, - $count['llocClasses'], - $count['lloc'] > 0 ? ($count['llocClasses'] / $count['lloc']) * 100 : 0, - $count['llocByNoc'], - $count['llocByNom'], - $count['llocFunctions'], - $count['lloc'] > 0 ? ($count['llocFunctions'] / $count['lloc']) * 100 : 0, - $count['llocByNof'], - $count['llocGlobal'], - $count['lloc'] > 0 ? ($count['llocGlobal'] / $count['lloc']) * 100 : 0, - $count['ccnByLloc'], - $count['ccnByNom'], - $count['globalAccesses'], - $count['globalConstantAccesses'], - $count['globalAccesses'] > 0 ? ($count['globalConstantAccesses'] / $count['globalAccesses']) * 100 : 0, - $count['globalVariableAccesses'], - $count['globalAccesses'] > 0 ? ($count['globalVariableAccesses'] / $count['globalAccesses']) * 100 : 0, - $count['superGlobalVariableAccesses'], - $count['globalAccesses'] > 0 ? ($count['superGlobalVariableAccesses'] / $count['globalAccesses']) * 100 : 0, - $count['attributeAccesses'], - $count['instanceAttributeAccesses'], - $count['attributeAccesses'] > 0 ? ($count['instanceAttributeAccesses'] / $count['attributeAccesses']) * 100 : 0, - $count['staticAttributeAccesses'], - $count['attributeAccesses'] > 0 ? ($count['staticAttributeAccesses'] / $count['attributeAccesses']) * 100 : 0, - $count['methodCalls'], - $count['instanceMethodCalls'], - $count['methodCalls'] > 0 ? ($count['instanceMethodCalls'] / $count['methodCalls']) * 100 : 0, - $count['staticMethodCalls'], - $count['methodCalls'] > 0 ? ($count['staticMethodCalls'] / $count['methodCalls']) * 100 : 0, - $count['namespaces'], - $count['interfaces'], - $count['traits'], - $count['classes'], - $count['abstractClasses'], - $count['classes'] > 0 ? ($count['abstractClasses'] / $count['classes']) * 100 : 0, - $count['concreteClasses'], - $count['classes'] > 0 ? ($count['concreteClasses'] / $count['classes']) * 100 : 0, - $count['methods'], - $count['nonStaticMethods'], - $count['methods'] > 0 ? ($count['nonStaticMethods'] / $count['methods']) * 100 : 0, - $count['staticMethods'], - $count['methods'] > 0 ? ($count['staticMethods'] / $count['methods']) * 100 : 0, - $count['publicMethods'], - $count['methods'] > 0 ? ($count['publicMethods'] / $count['methods']) * 100 : 0, - $count['nonPublicMethods'], - $count['methods'] > 0 ? ($count['nonPublicMethods'] / $count['methods']) * 100 : 0, - $count['functions'], - $count['namedFunctions'], - $count['functions'] > 0 ? ($count['namedFunctions'] / $count['functions']) * 100 : 0, - $count['anonymousFunctions'], - $count['functions'] > 0 ? ($count['anonymousFunctions'] / $count['functions']) * 100 : 0, - $count['constants'], - $count['globalConstants'], - $count['constants'] > 0 ? ($count['globalConstants'] / $count['constants']) * 100 : 0, - $count['classConstants'], - $count['constants'] > 0 ? ($count['classConstants'] / $count['constants']) * 100 : 0 - ) - ); - - if ($printTests) { - $output->write( - sprintf( - "\nTests\n" . - " Classes %10d\n" . - " Methods %10d\n", - - $count['testClasses'], - $count['testMethods'] - ) - ); - } - } - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phploc - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.1.0 - */ - -namespace SebastianBergmann\PHPLOC\Log -{ - /** - * An XML ResultPrinter for the TextUI. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phploc/tree - * @since Class available since Release 1.1.0 - */ - class XML - { - /** - * Prints a result set. - * - * @param string $filename - * @param array $count - */ - public function printResult($filename, array $count) - { - $document = new \DOMDocument('1.0', 'UTF-8'); - $document->formatOutput = TRUE; - - $root = $document->createElement('phploc'); - $document->appendChild($root); - - if ($count['directories'] > 0) { - $root->appendChild( - $document->createElement('directories', $count['directories']) - ); - - $root->appendChild( - $document->createElement('files', $count['files']) - ); - } - - unset($count['directories']); - unset($count['files']); - - foreach ($count as $k => $v) { - $root->appendChild( - $document->createElement($k, $v) - ); - } - - file_put_contents($filename, $document->saveXML()); - } - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phploc - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 2.0.0 - */ - -namespace SebastianBergmann\PHPLOC\Log\CSV -{ - /** - * A CSV ResultPrinter for the TextUI. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phploc/tree - * @since Class available since Release 1.6.0 - */ - class Single - { - /** - * Prints a result set. - * - * @param string $filename - * @param array $count - */ - public function printResult($filename, array $count) - { - file_put_contents( - $filename, - $this->getKeysLine($count) . $this->getValuesLine($count) - ); - } - - /** - * @param array $count - * @return string - */ - protected function getKeysLine(array $count) - { - $keys = array( - 'Directories', - 'Files', - 'Lines of Code (LOC)', - 'Cyclomatic Complexity / Lines of Code', - 'Comment Lines of Code (CLOC)', - 'Non-Comment Lines of Code (NCLOC)', - 'Logical Lines of Code (LLOC)', - 'LLOC outside functions or classes', - 'Namespaces', - 'Interfaces', - 'Traits', - 'Classes', - 'Abstract Classes', - 'Concrete Classes', - 'Classes Length (LLOC)', - 'Average Class Length (LLOC)', - 'Methods', - 'Non-Static Methods', - 'Static Methods', - 'Public Methods', - 'Non-Public Methods', - 'Average Method Length (LLOC)', - 'Cyclomatic Complexity / Number of Methods', - 'Functions', - 'Named Functions', - 'Anonymous Functions', - 'Functions Length (LLOC)', - 'Average Function Length (LLOC)', - 'Constants', - 'Global Constants', - 'Class Constants', - 'Attribute Accesses', - 'Non-Static Attribute Accesses', - 'Static Attribute Accesses', - 'Method Calls', - 'Non-Static Method Calls', - 'Static Method Calls', - 'Global Accesses', - 'Global Variable Accesses', - 'Super-Global Variable Accesses', - 'Global Constant Accesses', - 'Test Classes', - 'Test Methods' - ); - - return implode(',', $keys) . PHP_EOL; - } - - /** - * @param array $count - * @return string - */ - protected function getValuesLine(array $count) - { - $values = array( - $count['directories'], - $count['files'], - $count['loc'], - $count['ccnByLloc'], - $count['cloc'], - $count['ncloc'], - $count['lloc'], - $count['llocGlobal'], - $count['namespaces'], - $count['interfaces'], - $count['traits'], - $count['classes'], - $count['abstractClasses'], - $count['concreteClasses'], - $count['llocClasses'], - $count['llocByNoc'], - $count['methods'], - $count['nonStaticMethods'], - $count['staticMethods'], - $count['publicMethods'], - $count['nonPublicMethods'], - $count['llocByNom'], - $count['ccnByNom'], - $count['functions'], - $count['namedFunctions'], - $count['anonymousFunctions'], - $count['llocFunctions'], - $count['llocByNof'], - $count['constants'], - $count['globalConstants'], - $count['classConstants'], - $count['attributeAccesses'], - $count['instanceAttributeAccesses'], - $count['staticAttributeAccesses'], - $count['methodCalls'], - $count['instanceMethodCalls'], - $count['staticMethodCalls'], - $count['globalAccesses'], - $count['globalVariableAccesses'], - $count['superGlobalVariableAccesses'], - $count['globalConstantAccesses'], - $count['testClasses'], - $count['testMethods'] - ); - - return '"' . implode('","', $values) . '"' . PHP_EOL; - } - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phploc - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 2.0.0 - */ - -namespace SebastianBergmann\PHPLOC\Log\CSV -{ - /** - * A CSV ResultPrinter for the TextUI. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phploc/tree - * @since Class available since Release 2.0.0 - */ - class History extends Single - { - /** - * Prints a result set. - * - * @param string $filename - * @param array $count - */ - public function printResult($filename, array $count) - { - $buffer = $this->getKeysLine($count); - - foreach ($count as $date => $data) { - $buffer .= $date . ',' . $this->getValuesLine($data); - } - - file_put_contents($filename, $buffer); - } - - /** - * @param array $count - * @return string - */ - protected function getKeysLine(array $count) - { - return 'Date,' . parent::getKeysLine($count); - } - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phploc - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 2.0.0 - */ - -namespace SebastianBergmann\PHPLOC\CLI -{ - use SebastianBergmann\FinderFacade\FinderFacade; - use SebastianBergmann\Git; - use SebastianBergmann\PHPLOC\Analyser; - use SebastianBergmann\PHPLOC\Log\CSV\History; - use SebastianBergmann\PHPLOC\Log\CSV\Single; - use SebastianBergmann\PHPLOC\Log\Text; - use SebastianBergmann\PHPLOC\Log\XML; - use Symfony\Component\Console\Command\Command as AbstractCommand; - use Symfony\Component\Console\Input\InputArgument; - use Symfony\Component\Console\Input\InputInterface; - use Symfony\Component\Console\Input\InputOption; - use Symfony\Component\Console\Output\OutputInterface; - - /** - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phploc/tree - * @since Class available since Release 2.0.0 - */ - class Command extends AbstractCommand - { - /** - * Configures the current command. - */ - protected function configure() - { - $this->setName('phploc') - ->setDefinition( - array( - new InputArgument( - 'values', - InputArgument::IS_ARRAY - ) - ) - ) - ->addOption( - 'names', - NULL, - InputOption::VALUE_REQUIRED, - 'A comma-separated list of file names to check', - array('*.php') - ) - ->addOption( - 'names-exclude', - NULL, - InputOption::VALUE_REQUIRED, - 'A comma-separated list of file names to exclude', - array() - ) - ->addOption( - 'count-tests', - NULL, - InputOption::VALUE_NONE, - 'Count PHPUnit test case classes and test methods' - ) - ->addOption( - 'git-repository', - NULL, - InputOption::VALUE_REQUIRED, - 'Collect metrics over the history of a Git repository' - ) - ->addOption( - 'exclude', - NULL, - InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, - 'Exclude a directory from code analysis' - ) - ->addOption( - 'log-csv', - NULL, - InputOption::VALUE_REQUIRED, - 'Write result in CSV format to file' - ) - ->addOption( - 'log-xml', - NULL, - InputOption::VALUE_REQUIRED, - 'Write result in XML format to file' - ) - ->addOption( - 'progress', - null, - InputOption::VALUE_NONE, - 'Show progress bar' - ); - } - - /** - * Executes the current command. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * - * @return null|integer null or 0 if everything went fine, or an error code - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - if (!$input->getOption('git-repository')) { - return $this->executeSingle($input, $output); - } else { - return $this->executeHistory($input, $output); - } - } - - /** - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * - * @return null|integer null or 0 if everything went fine, or an error code - */ - private function executeSingle(InputInterface $input, OutputInterface $output) - { - $count = $this->count( - $input->getArgument('values'), - $input->getOption('exclude'), - $this->handleCSVOption($input, 'names'), - $this->handleCSVOption($input, 'names-exclude'), - $input->getOption('count-tests') - ); - - if (!$count) { - $output->writeln('No files found to scan'); - exit(1); - } - - $printer = new Text; - - $printer->printResult( - $output, $count, $input->getOption('count-tests') - ); - - if ($input->getOption('log-csv')) { - $printer = new Single; - $printer->printResult($input->getOption('log-csv'), $count); - } - - if ($input->getOption('log-xml')) { - $printer = new XML; - $printer->printResult($input->getOption('log-xml'), $count); - } - } - - /** - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * - * @return null|integer null or 0 if everything went fine, or an error code - */ - private function executeHistory(InputInterface $input, OutputInterface $output) - { - $git = new Git($input->getOption('git-repository')); - $currentBranch = $git->getCurrentBranch(); - $revisions = $git->getRevisions(); - $count = array(); - $progressHelper = NULL; - - if ($input->getOption('progress')) { - $progressHelper = $this->getHelperSet()->get('progress'); - $progressHelper->start($output, count($revisions)); - } - - foreach ($revisions as $revision) { - $git->checkout($revision['sha1']); - - $directories = array(); - - foreach ($input->getArgument('values') as $value) { - $directory = realpath($value); - - if ($directory) { - $directories[] = $directory; - } - } - - $_count = $this->count( - $directories, - $input->getOption('exclude'), - $this->handleCSVOption($input, 'names'), - $this->handleCSVOption($input, 'names-exclude'), - $input->getOption('count-tests') - ); - - if ($_count) { - $count[$revision['date']->format(\DateTime::W3C)] = $_count; - } - - if ($progressHelper !== NULL) { - $progressHelper->advance(); - } - } - - $git->checkout($currentBranch); - - if ($progressHelper !== NULL) { - $progressHelper->finish(); - $output->writeln(''); - } - - if ($input->getOption('log-csv')) { - $printer = new History; - $printer->printResult($input->getOption('log-csv'), $count); - } - } - - private function count(array $arguments, $excludes, $names, $namesExclude, $countTests) - { - $finder = new FinderFacade($arguments, $excludes, $names, $namesExclude); - $files = $finder->findFiles(); - - if (empty($files)) { - return FALSE; - } - - $analyser = new Analyser; - - return $analyser->countFiles($files, $countTests); - } - - /** - * @param Symfony\Component\Console\Input\InputOption $input - * @param string $option - * @return array - */ - private function handleCSVOption(InputInterface $input, $option) - { - $result = $input->getOption($option); - - if (!is_array($result)) { - $result = explode(',', $result); - array_map('trim', $result); - } - - return $result; - } - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package phploc - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 2.0.0 - */ - -namespace SebastianBergmann\PHPLOC\CLI -{ - use SebastianBergmann\Version; - use Symfony\Component\Console\Application as AbstractApplication; - use Symfony\Component\Console\Input\InputInterface; - use Symfony\Component\Console\Input\ArgvInput; - use Symfony\Component\Console\Output\OutputInterface; - use Symfony\Component\Console\Input\ArrayInput; - - /** - * TextUI frontend for PHPLOC. - * - * @author Sebastian Bergmann - * @copyright 2009-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://github.com/sebastianbergmann/phploc/tree - * @since Class available since Release 2.0.0 - */ - class Application extends AbstractApplication - { - public function __construct() - { - $version = new Version('2.0.4', __DIR__); - parent::__construct('phploc', $version->getVersion()); - } - - /** - * Gets the name of the command based on input. - * - * @param InputInterface $input The input interface - * - * @return string The command name - */ - protected function getCommandName(InputInterface $input) - { - return 'phploc'; - } - - /** - * Gets the default commands that should always be available. - * - * @return array An array of default Command instances - */ - protected function getDefaultCommands() - { - $defaultCommands = parent::getDefaultCommands(); - - $defaultCommands[] = new Command; - - return $defaultCommands; - } - - /** - * Overridden so that the application doesn't expect the command - * name to be the first argument. - */ - public function getDefinition() - { - $inputDefinition = parent::getDefinition(); - $inputDefinition->setArguments(); - - return $inputDefinition; - } - - /** - * Runs the current application. - * - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * - * @return integer 0 if everything went fine, or an error code - */ - public function doRun(InputInterface $input, OutputInterface $output) - { - if (!$input->hasParameterOption('--quiet')) { - $output->write( - sprintf( - "phploc %s by Sebastian Bergmann.\n\n", $this->getVersion() - ) - ); - } - - if ($input->hasParameterOption('--version') || - $input->hasParameterOption('-V')) { - exit; - } - - if (!$input->getFirstArgument()) { - $input = new ArrayInput(array('--help')); - } - - parent::doRun($input, $output); - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Shell; - -/** - * @author Jean-François Simon - */ -class Command -{ - /** - * @var Command|null - */ - private $parent; - - /** - * @var array - */ - private $bits = array(); - - /** - * @var array - */ - private $labels = array(); - - /** - * @var \Closure|null - */ - private $errorHandler; - - /** - * Constructor. - * - * @param Command|null $parent Parent command - */ - public function __construct(Command $parent = null) - { - $this->parent = $parent; - } - - /** - * Returns command as string. - * - * @return string - */ - public function __toString() - { - return $this->join(); - } - - /** - * Creates a new Command instance. - * - * @param Command|null $parent Parent command - * - * @return Command New Command instance - */ - public static function create(Command $parent = null) - { - return new self($parent); - } - - /** - * Escapes special chars from input. - * - * @param string $input A string to escape - * - * @return string The escaped string - */ - public static function escape($input) - { - return escapeshellcmd($input); - } - - /** - * Quotes input. - * - * @param string $input An argument string - * - * @return string The quoted string - */ - public static function quote($input) - { - return escapeshellarg($input); - } - - /** - * Appends a string or a Command instance. - * - * @param string|Command $bit - * - * @return Command The current Command instance - */ - public function add($bit) - { - $this->bits[] = $bit; - - return $this; - } - - /** - * Prepends a string or a command instance. - * - * @param string|Command $bit - * - * @return Command The current Command instance - */ - public function top($bit) - { - array_unshift($this->bits, $bit); - - foreach ($this->labels as $label => $index) { - $this->labels[$label] += 1; - } - - return $this; - } - - /** - * Appends an argument, will be quoted. - * - * @param string $arg - * - * @return Command The current Command instance - */ - public function arg($arg) - { - $this->bits[] = self::quote($arg); - - return $this; - } - - /** - * Appends escaped special command chars. - * - * @param string $esc - * - * @return Command The current Command instance - */ - public function cmd($esc) - { - $this->bits[] = self::escape($esc); - - return $this; - } - - /** - * Inserts a labeled command to feed later. - * - * @param string $label The unique label - * - * @return Command The current Command instance - * - * @throws \RuntimeException If label already exists - */ - public function ins($label) - { - if (isset($this->labels[$label])) { - throw new \RuntimeException(sprintf('Label "%s" already exists.', $label)); - } - - $this->bits[] = self::create($this); - $this->labels[$label] = count($this->bits)-1; - - return $this->bits[$this->labels[$label]]; - } - - /** - * Retrieves a previously labeled command. - * - * @param string $label - * - * @return Command The labeled command - * - * @throws \RuntimeException - */ - public function get($label) - { - if (!isset($this->labels[$label])) { - throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label)); - } - - return $this->bits[$this->labels[$label]]; - } - - /** - * Returns parent command (if any). - * - * @return Command Parent command - * - * @throws \RuntimeException If command has no parent - */ - public function end() - { - if (null === $this->parent) { - throw new \RuntimeException('Calling end on root command doesn\'t make sense.'); - } - - return $this->parent; - } - - /** - * Counts bits stored in command. - * - * @return int The bits count - */ - public function length() - { - return count($this->bits); - } - - /** - * @param \Closure $errorHandler - * - * @return Command - */ - public function setErrorHandler(\Closure $errorHandler) - { - $this->errorHandler = $errorHandler; - - return $this; - } - - /** - * @return \Closure|null - */ - public function getErrorHandler() - { - return $this->errorHandler; - } - - /** - * Executes current command. - * - * @return array The command result - * - * @throws \RuntimeException - */ - public function execute() - { - if (null === $this->errorHandler) { - exec($this->join(), $output); - } else { - $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes); - $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY); - - if ($error = stream_get_contents($pipes[2])) { - call_user_func($this->errorHandler, $error); - } - - proc_close($process); - } - - return $output ?: array(); - } - - /** - * Joins bits. - * - * @return string - */ - public function join() - { - return implode(' ', array_filter( - array_map(function($bit) { - return $bit instanceof Command ? $bit->join() : ($bit ?: null); - }, $this->bits), - function($bit) { return null !== $bit; } - )); - } - - /** - * Insert a string or a Command instance before the bit at given position $index (index starts from 0). - * - * @param string|Command $bit - * @param integer $index - * - * @return Command The current Command instance - */ - public function addAtIndex($bit, $index) - { - array_splice($this->bits, $index, 0, $bit); - - return $this; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Shell; - -/** - * @author Jean-François Simon - */ -class Shell -{ - const TYPE_UNIX = 1; - const TYPE_DARWIN = 2; - const TYPE_CYGWIN = 3; - const TYPE_WINDOWS = 4; - const TYPE_BSD = 5; - - /** - * @var string|null - */ - private $type; - - /** - * Returns guessed OS type. - * - * @return int - */ - public function getType() - { - if (null === $this->type) { - $this->type = $this->guessType(); - } - - return $this->type; - } - - /** - * Tests if a command is available. - * - * @param string $command - * - * @return bool - */ - public function testCommand($command) - { - if (self::TYPE_WINDOWS === $this->type) { - // todo: find a way to test if windows command exists - return false; - } - - if (!function_exists('exec')) { - return false; - } - - // todo: find a better way (command could not be available) - exec('command -v '.$command, $output, $code); - - return 0 === $code && count($output) > 0; - } - - /** - * Guesses OS type. - * - * @return int - */ - private function guessType() - { - $os = strtolower(PHP_OS); - - if (false !== strpos($os, 'cygwin')) { - return self::TYPE_CYGWIN; - } - - if (false !== strpos($os, 'darwin')) { - return self::TYPE_DARWIN; - } - - if (false !== strpos($os, 'bsd')) { - return self::TYPE_BSD; - } - - if (0 === strpos($os, 'win')) { - return self::TYPE_WINDOWS; - } - - return self::TYPE_UNIX; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * PathFilterIterator filters files by path patterns (e.g. some/special/dir). - * - * @author Fabien Potencier - * @author Włodzimierz Gajda - */ -class PathFilterIterator extends MultiplePcreFilterIterator -{ - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $filename = $this->current()->getRelativePathname(); - - if (defined('PHP_WINDOWS_VERSION_MAJOR')) { - $filename = strtr($filename, '\\', '/'); - } - - // should at least not match one rule to exclude - foreach ($this->noMatchRegexps as $regex) { - if (preg_match($regex, $filename)) { - return false; - } - } - - // should at least match one rule - $match = true; - if ($this->matchRegexps) { - $match = false; - foreach ($this->matchRegexps as $regex) { - if (preg_match($regex, $filename)) { - return true; - } - } - } - - return $match; - } - - /** - * Converts strings to regexp. - * - * PCRE patterns are left unchanged. - * - * Default conversion: - * 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/' - * - * Use only / as directory separator (on Windows also). - * - * @param string $str Pattern: regexp or dirname. - * - * @return string regexp corresponding to a given string or regexp - */ - protected function toRegex($str) - { - return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Comparator\DateComparator; - -/** - * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates). - * - * @author Fabien Potencier - */ -class DateRangeFilterIterator extends FilterIterator -{ - private $comparators = array(); - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param DateComparator[] $comparators An array of DateComparator instances - */ - public function __construct(\Iterator $iterator, array $comparators) - { - $this->comparators = $comparators; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - - if (!$fileinfo->isFile()) { - return true; - } - - $filedate = $fileinfo->getMTime(); - foreach ($this->comparators as $compare) { - if (!$compare->test($filedate)) { - return false; - } - } - - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings). - * - * @author Fabien Potencier - * @author Włodzimierz Gajda - */ -class FilecontentFilterIterator extends MultiplePcreFilterIterator -{ - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - if (!$this->matchRegexps && !$this->noMatchRegexps) { - return true; - } - - $fileinfo = $this->current(); - - if ($fileinfo->isDir() || !$fileinfo->isReadable()) { - return false; - } - - $content = $fileinfo->getContents(); - if (!$content) { - return false; - } - - // should at least not match one rule to exclude - foreach ($this->noMatchRegexps as $regex) { - if (preg_match($regex, $content)) { - return false; - } - } - - // should at least match one rule - $match = true; - if ($this->matchRegexps) { - $match = false; - foreach ($this->matchRegexps as $regex) { - if (preg_match($regex, $content)) { - return true; - } - } - } - - return $match; - } - - /** - * Converts string to regexp if necessary. - * - * @param string $str Pattern: string or regexp - * - * @return string regexp corresponding to a given string or regexp - */ - protected function toRegex($str) - { - return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * SortableIterator applies a sort on a given Iterator. - * - * @author Fabien Potencier - */ -class SortableIterator implements \IteratorAggregate -{ - const SORT_BY_NAME = 1; - const SORT_BY_TYPE = 2; - const SORT_BY_ACCESSED_TIME = 3; - const SORT_BY_CHANGED_TIME = 4; - const SORT_BY_MODIFIED_TIME = 5; - - private $iterator; - private $sort; - - /** - * Constructor. - * - * @param \Traversable $iterator The Iterator to filter - * @param integer|callback $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) - * - * @throws \InvalidArgumentException - */ - public function __construct(\Traversable $iterator, $sort) - { - $this->iterator = $iterator; - - if (self::SORT_BY_NAME === $sort) { - $this->sort = function ($a, $b) { - return strcmp($a->getRealpath(), $b->getRealpath()); - }; - } elseif (self::SORT_BY_TYPE === $sort) { - $this->sort = function ($a, $b) { - if ($a->isDir() && $b->isFile()) { - return -1; - } elseif ($a->isFile() && $b->isDir()) { - return 1; - } - - return strcmp($a->getRealpath(), $b->getRealpath()); - }; - } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { - $this->sort = function ($a, $b) { - return ($a->getATime() > $b->getATime()); - }; - } elseif (self::SORT_BY_CHANGED_TIME === $sort) { - $this->sort = function ($a, $b) { - return ($a->getCTime() > $b->getCTime()); - }; - } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { - $this->sort = function ($a, $b) { - return ($a->getMTime() > $b->getMTime()); - }; - } elseif (is_callable($sort)) { - $this->sort = $sort; - } else { - throw new \InvalidArgumentException('The SortableIterator takes a PHP callback or a valid built-in sort algorithm as an argument.'); - } - } - - public function getIterator() - { - $array = iterator_to_array($this->iterator, true); - uasort($array, $this->sort); - - return new \ArrayIterator($array); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * DepthRangeFilterIterator limits the directory depth. - * - * @author Fabien Potencier - */ -class DepthRangeFilterIterator extends FilterIterator -{ - private $minDepth = 0; - - /** - * Constructor. - * - * @param \RecursiveIteratorIterator $iterator The Iterator to filter - * @param int $minDepth The min depth - * @param int $maxDepth The max depth - */ - public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX) - { - $this->minDepth = $minDepth; - $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - return $this->getInnerIterator()->getDepth() >= $this->minDepth; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Comparator\NumberComparator; - -/** - * SizeRangeFilterIterator filters out files that are not in the given size range. - * - * @author Fabien Potencier - */ -class SizeRangeFilterIterator extends FilterIterator -{ - private $comparators = array(); - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param NumberComparator[] $comparators An array of NumberComparator instances - */ - public function __construct(\Iterator $iterator, array $comparators) - { - $this->comparators = $comparators; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - if (!$fileinfo->isFile()) { - return true; - } - - $filesize = $fileinfo->getSize(); - foreach ($this->comparators as $compare) { - if (!$compare->test($filesize)) { - return false; - } - } - - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Expression\Expression; - -/** - * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string). - * - * @author Fabien Potencier - */ -class FilenameFilterIterator extends MultiplePcreFilterIterator -{ - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $filename = $this->current()->getFilename(); - - // should at least not match one rule to exclude - foreach ($this->noMatchRegexps as $regex) { - if (preg_match($regex, $filename)) { - return false; - } - } - - // should at least match one rule - $match = true; - if ($this->matchRegexps) { - $match = false; - foreach ($this->matchRegexps as $regex) { - if (preg_match($regex, $filename)) { - return true; - } - } - } - - return $match; - } - - /** - * Converts glob to regexp. - * - * PCRE patterns are left unchanged. - * Glob strings are transformed with Glob::toRegex(). - * - * @param string $str Pattern: glob or regexp - * - * @return string regexp corresponding to a given glob or regexp - */ - protected function toRegex($str) - { - return Expression::create($str)->getRegex()->render(); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Exception\AccessDeniedException; -use Symfony\Component\Finder\SplFileInfo; - -/** - * Extends the \RecursiveDirectoryIterator to support relative paths - * - * @author Victor Berchet - */ -class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator -{ - /** - * @var boolean - */ - private $ignoreUnreadableDirs; - - /** - * @var Boolean - */ - private $rewindable; - - /** - * Constructor. - * - * @param string $path - * @param int $flags - * @param boolean $ignoreUnreadableDirs - * - * @throws \RuntimeException - */ - public function __construct($path, $flags, $ignoreUnreadableDirs = false) - { - if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { - throw new \RuntimeException('This iterator only support returning current as fileinfo.'); - } - - parent::__construct($path, $flags); - $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; - } - - /** - * Return an instance of SplFileInfo with support for relative paths - * - * @return SplFileInfo File information - */ - public function current() - { - return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname()); - } - - /** - * @return \RecursiveIterator - * - * @throws AccessDeniedException - */ - public function getChildren() - { - try { - return parent::getChildren(); - } catch (\UnexpectedValueException $e) { - if ($this->ignoreUnreadableDirs) { - // If directory is unreadable and finder is set to ignore it, a fake empty content is returned. - return new \RecursiveArrayIterator(array()); - } else { - throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); - } - } - } - - /** - * Do nothing for non rewindable stream - */ - public function rewind() - { - if (false === $this->isRewindable()) { - return; - } - - // @see https://bugs.php.net/bug.php?id=49104 - parent::next(); - - parent::rewind(); - } - - /** - * Checks if the stream is rewindable. - * - * @return Boolean true when the stream is rewindable, false otherwise - */ - public function isRewindable() - { - if (null !== $this->rewindable) { - return $this->rewindable; - } - - if (false !== $stream = @opendir($this->getPath())) { - $infos = stream_get_meta_data($stream); - closedir($stream); - - if ($infos['seekable']) { - return $this->rewindable = true; - } - } - - return $this->rewindable = false; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * FileTypeFilterIterator only keeps files, directories, or both. - * - * @author Fabien Potencier - */ -class FileTypeFilterIterator extends FilterIterator -{ - const ONLY_FILES = 1; - const ONLY_DIRECTORIES = 2; - - private $mode; - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param integer $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) - */ - public function __construct(\Iterator $iterator, $mode) - { - $this->mode = $mode; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) { - return false; - } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) { - return false; - } - - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\SplFileInfo; - -/** - * Iterate over shell command result. - * - * @author Jean-François Simon - */ -class FilePathsIterator extends \ArrayIterator -{ - /** - * @var string - */ - private $baseDir; - - /** - * @var int - */ - private $baseDirLength; - - /** - * @var string - */ - private $subPath; - - /** - * @var string - */ - private $subPathname; - - /** - * @var SplFileInfo - */ - private $current; - - /** - * @param array $paths List of paths returned by shell command - * @param string $baseDir Base dir for relative path building - */ - public function __construct(array $paths, $baseDir) - { - $this->baseDir = $baseDir; - $this->baseDirLength = strlen($baseDir); - - parent::__construct($paths); - } - - /** - * @param string $name - * @param array $arguments - * - * @return mixed - */ - public function __call($name, array $arguments) - { - return call_user_func_array(array($this->current(), $name), $arguments); - } - - /** - * Return an instance of SplFileInfo with support for relative paths. - * - * @return SplFileInfo File information - */ - public function current() - { - return $this->current; - } - - /** - * @return string - */ - public function key() - { - return $this->current->getPathname(); - } - - public function next() - { - parent::next(); - $this->buildProperties(); - } - - public function rewind() - { - parent::rewind(); - $this->buildProperties(); - } - - /** - * @return string - */ - public function getSubPath() - { - return $this->subPath; - } - - /** - * @return string - */ - public function getSubPathname() - { - return $this->subPathname; - } - - private function buildProperties() - { - $absolutePath = parent::current(); - - if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) { - $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\'); - $dir = dirname($this->subPathname); - $this->subPath = '.' === $dir ? '' : $dir; - } else { - $this->subPath = $this->subPathname = ''; - } - - $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * This iterator just overrides the rewind method in order to correct a PHP bug. - * - * @see https://bugs.php.net/bug.php?id=49104 - * - * @author Alex Bogomazov - */ -abstract class FilterIterator extends \FilterIterator -{ - /** - * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after - * rewind in some cases. - * - * @see FilterIterator::rewind() - */ - public function rewind() - { - $iterator = $this; - while ($iterator instanceof \OuterIterator) { - $innerIterator = $iterator->getInnerIterator(); - - if ($innerIterator instanceof RecursiveDirectoryIterator) { - if ($innerIterator->isRewindable()) { - $innerIterator->next(); - $innerIterator->rewind(); - } - } elseif ($iterator->getInnerIterator() instanceof \FilesystemIterator) { - $iterator->getInnerIterator()->next(); - $iterator->getInnerIterator()->rewind(); - } - $iterator = $iterator->getInnerIterator(); - } - - parent::rewind(); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Expression\Expression; - -/** - * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings). - * - * @author Fabien Potencier - */ -abstract class MultiplePcreFilterIterator extends FilterIterator -{ - protected $matchRegexps = array(); - protected $noMatchRegexps = array(); - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param array $matchPatterns An array of patterns that need to match - * @param array $noMatchPatterns An array of patterns that need to not match - */ - public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) - { - foreach ($matchPatterns as $pattern) { - $this->matchRegexps[] = $this->toRegex($pattern); - } - - foreach ($noMatchPatterns as $pattern) { - $this->noMatchRegexps[] = $this->toRegex($pattern); - } - - parent::__construct($iterator); - } - - /** - * Checks whether the string is a regex. - * - * @param string $str - * - * @return Boolean Whether the given string is a regex - */ - protected function isRegex($str) - { - return Expression::create($str)->isRegex(); - } - - /** - * Converts string into regexp. - * - * @param string $str Pattern - * - * @return string regexp corresponding to a given string - */ - abstract protected function toRegex($str); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * CustomFilterIterator filters files by applying anonymous functions. - * - * The anonymous function receives a \SplFileInfo and must return false - * to remove files. - * - * @author Fabien Potencier - */ -class CustomFilterIterator extends FilterIterator -{ - private $filters = array(); - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param array $filters An array of PHP callbacks - * - * @throws \InvalidArgumentException - */ - public function __construct(\Iterator $iterator, array $filters) - { - foreach ($filters as $filter) { - if (!is_callable($filter)) { - throw new \InvalidArgumentException('Invalid PHP callback.'); - } - } - $this->filters = $filters; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - - foreach ($this->filters as $filter) { - if (false === call_user_func($filter, $fileinfo)) { - return false; - } - } - - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * ExcludeDirectoryFilterIterator filters out directories. - * - * @author Fabien Potencier - */ -class ExcludeDirectoryFilterIterator extends FilterIterator -{ - private $patterns = array(); - - /** - * Constructor. - * - * @param \Iterator $iterator The Iterator to filter - * @param array $directories An array of directories to exclude - */ - public function __construct(\Iterator $iterator, array $directories) - { - foreach ($directories as $directory) { - $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#'; - } - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return Boolean true if the value should be kept, false otherwise - */ - public function accept() - { - $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); - $path = strtr($path, '\\', '/'); - foreach ($this->patterns as $pattern) { - if (preg_match($pattern, $path)) { - return false; - } - } - - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -use Symfony\Component\Finder\Shell\Shell; -use Symfony\Component\Finder\Shell\Command; -use Symfony\Component\Finder\Iterator\SortableIterator; -use Symfony\Component\Finder\Expression\Expression; - -/** - * Shell engine implementation using BSD find command. - * - * @author Jean-François Simon - */ -class BsdFindAdapter extends AbstractFindAdapter -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'bsd_find'; - } - - /** - * {@inheritdoc} - */ - protected function canBeUsed() - { - return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed(); - } - - /** - * {@inheritdoc} - */ - protected function buildFormatSorting(Command $command, $sort) - { - switch ($sort) { - case SortableIterator::SORT_BY_NAME: - $command->ins('sort')->add('| sort'); - - return; - case SortableIterator::SORT_BY_TYPE: - $format = '%HT'; - break; - case SortableIterator::SORT_BY_ACCESSED_TIME: - $format = '%a'; - break; - case SortableIterator::SORT_BY_CHANGED_TIME: - $format = '%c'; - break; - case SortableIterator::SORT_BY_MODIFIED_TIME: - $format = '%m'; - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); - } - - $command - ->add('-print0 | xargs -0 stat -f') - ->arg($format.'%t%N') - ->add('| sort | cut -f 2'); - } - - /** - * {@inheritdoc} - */ - protected function buildFindCommand(Command $command, $dir) - { - parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1); - - return $command; - } - - /** - * {@inheritdoc} - */ - protected function buildContentFiltering(Command $command, array $contains, $not = false) - { - foreach ($contains as $contain) { - $expr = Expression::create($contain); - - // todo: avoid forking process for each $pattern by using multiple -e options - $command - ->add('| grep -v \'^$\'') - ->add('| xargs -I{} grep -I') - ->add($expr->isCaseSensitive() ? null : '-i') - ->add($not ? '-L' : '-l') - ->add('-Ee')->arg($expr->renderPattern()) - ->add('{}') - ; - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -use Symfony\Component\Finder\Shell\Shell; -use Symfony\Component\Finder\Shell\Command; -use Symfony\Component\Finder\Iterator\SortableIterator; -use Symfony\Component\Finder\Expression\Expression; - -/** - * Shell engine implementation using GNU find command. - * - * @author Jean-François Simon - */ -class GnuFindAdapter extends AbstractFindAdapter -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'gnu_find'; - } - - /** - * {@inheritdoc} - */ - protected function buildFormatSorting(Command $command, $sort) - { - switch ($sort) { - case SortableIterator::SORT_BY_NAME: - $command->ins('sort')->add('| sort'); - - return; - case SortableIterator::SORT_BY_TYPE: - $format = '%y'; - break; - case SortableIterator::SORT_BY_ACCESSED_TIME: - $format = '%A@'; - break; - case SortableIterator::SORT_BY_CHANGED_TIME: - $format = '%C@'; - break; - case SortableIterator::SORT_BY_MODIFIED_TIME: - $format = '%T@'; - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); - } - - $command - ->get('find') - ->add('-printf') - ->arg($format.' %h/%f\\n') - ->add('| sort | cut') - ->arg('-d ') - ->arg('-f2-') - ; - } - - /** - * {@inheritdoc} - */ - protected function canBeUsed() - { - return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed(); - } - - /** - * {@inheritdoc} - */ - protected function buildFindCommand(Command $command, $dir) - { - return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended'); - } - - /** - * {@inheritdoc} - */ - protected function buildContentFiltering(Command $command, array $contains, $not = false) - { - foreach ($contains as $contain) { - $expr = Expression::create($contain); - - // todo: avoid forking process for each $pattern by using multiple -e options - $command - ->add('| xargs -I{} -r grep -I') - ->add($expr->isCaseSensitive() ? null : '-i') - ->add($not ? '-L' : '-l') - ->add('-Ee')->arg($expr->renderPattern()) - ->add('{}') - ; - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -use Symfony\Component\Finder\Iterator; - -/** - * PHP finder engine implementation. - * - * @author Jean-François Simon - */ -class PhpAdapter extends AbstractAdapter -{ - /** - * {@inheritdoc} - */ - public function searchInDirectory($dir) - { - $flags = \RecursiveDirectoryIterator::SKIP_DOTS; - - if ($this->followLinks) { - $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; - } - - $iterator = new \RecursiveIteratorIterator( - new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs), - \RecursiveIteratorIterator::SELF_FIRST - ); - - if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) { - $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth); - } - - if ($this->mode) { - $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); - } - - if ($this->exclude) { - $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); - } - - if ($this->names || $this->notNames) { - $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); - } - - if ($this->contains || $this->notContains) { - $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); - } - - if ($this->sizes) { - $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes); - } - - if ($this->dates) { - $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates); - } - - if ($this->filters) { - $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); - } - - if ($this->sort) { - $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); - $iterator = $iteratorAggregate->getIterator(); - } - - if ($this->paths || $this->notPaths) { - $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths); - } - - return $iterator; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'php'; - } - - /** - * {@inheritdoc} - */ - protected function canBeUsed() - { - return true; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -use Symfony\Component\Finder\Exception\AccessDeniedException; -use Symfony\Component\Finder\Iterator; -use Symfony\Component\Finder\Shell\Shell; -use Symfony\Component\Finder\Expression\Expression; -use Symfony\Component\Finder\Shell\Command; -use Symfony\Component\Finder\Iterator\SortableIterator; -use Symfony\Component\Finder\Comparator\NumberComparator; -use Symfony\Component\Finder\Comparator\DateComparator; - -/** - * Shell engine implementation using GNU find command. - * - * @author Jean-François Simon - */ -abstract class AbstractFindAdapter extends AbstractAdapter -{ - /** - * @var Shell - */ - protected $shell; - - /** - * Constructor. - */ - public function __construct() - { - $this->shell = new Shell(); - } - - /** - * {@inheritdoc} - */ - public function searchInDirectory($dir) - { - // having "/../" in path make find fail - $dir = realpath($dir); - - // searching directories containing or not containing strings leads to no result - if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) { - return new Iterator\FilePathsIterator(array(), $dir); - } - - $command = Command::create(); - $find = $this->buildFindCommand($command, $dir); - - if ($this->followLinks) { - $find->add('-follow'); - } - - $find->add('-mindepth')->add($this->minDepth + 1); - - if (PHP_INT_MAX !== $this->maxDepth) { - $find->add('-maxdepth')->add($this->maxDepth + 1); - } - - if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) { - $find->add('-type d'); - } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) { - $find->add('-type f'); - } - - $this->buildNamesFiltering($find, $this->names); - $this->buildNamesFiltering($find, $this->notNames, true); - $this->buildPathsFiltering($find, $dir, $this->paths); - $this->buildPathsFiltering($find, $dir, $this->notPaths, true); - $this->buildSizesFiltering($find, $this->sizes); - $this->buildDatesFiltering($find, $this->dates); - - $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs'); - $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut'); - - if ($useGrep && ($this->contains || $this->notContains)) { - $grep = $command->ins('grep'); - $this->buildContentFiltering($grep, $this->contains); - $this->buildContentFiltering($grep, $this->notContains, true); - } - - if ($useSort) { - $this->buildSorting($command, $this->sort); - } - - $command->setErrorHandler( - $this->ignoreUnreadableDirs - // If directory is unreadable and finder is set to ignore it, `stderr` is ignored. - ? function ($stderr) { return; } - : function ($stderr) { throw new AccessDeniedException($stderr); } - ); - - $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute()); - $iterator = new Iterator\FilePathsIterator($paths, $dir); - - if ($this->exclude) { - $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); - } - - if (!$useGrep && ($this->contains || $this->notContains)) { - $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); - } - - if ($this->filters) { - $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); - } - - if (!$useSort && $this->sort) { - $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); - $iterator = $iteratorAggregate->getIterator(); - } - - return $iterator; - } - - /** - * {@inheritdoc} - */ - protected function canBeUsed() - { - return $this->shell->testCommand('find'); - } - - /** - * @param Command $command - * @param string $dir - * - * @return Command - */ - protected function buildFindCommand(Command $command, $dir) - { - return $command - ->ins('find') - ->add('find ') - ->arg($dir) - ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions - } - - /** - * @param Command $command - * @param string[] $names - * @param Boolean $not - */ - private function buildNamesFiltering(Command $command, array $names, $not = false) - { - if (0 === count($names)) { - return; - } - - $command->add($not ? '-not' : null)->cmd('('); - - foreach ($names as $i => $name) { - $expr = Expression::create($name); - - // Find does not support expandable globs ("*.{a,b}" syntax). - if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { - $expr = Expression::create($expr->getGlob()->toRegex(false)); - } - - // Fixes 'not search' and 'full path matching' regex problems. - // - Jokers '.' are replaced by [^/]. - // - We add '[^/]*' before and after regex (if no ^|$ flags are present). - if ($expr->isRegex()) { - $regex = $expr->getRegex(); - $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*') - ->setStartFlag(false) - ->setStartJoker(true) - ->replaceJokers('[^/]'); - if (!$regex->hasEndFlag() || $regex->hasEndJoker()) { - $regex->setEndJoker(false)->append('[^/]*'); - } - } - - $command - ->add($i > 0 ? '-or' : null) - ->add($expr->isRegex() - ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') - : ($expr->isCaseSensitive() ? '-name' : '-iname') - ) - ->arg($expr->renderPattern()); - } - - $command->cmd(')'); - } - - /** - * @param Command $command - * @param string $dir - * @param string[] $paths - * @param Boolean $not - */ - private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false) - { - if (0 === count($paths)) { - return; - } - - $command->add($not ? '-not' : null)->cmd('('); - - foreach ($paths as $i => $path) { - $expr = Expression::create($path); - - // Find does not support expandable globs ("*.{a,b}" syntax). - if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { - $expr = Expression::create($expr->getGlob()->toRegex(false)); - } - - // Fixes 'not search' regex problems. - if ($expr->isRegex()) { - $regex = $expr->getRegex(); - $regex->prepend($regex->hasStartFlag() ? $dir.DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag()); - } else { - $expr->prepend('*')->append('*'); - } - - $command - ->add($i > 0 ? '-or' : null) - ->add($expr->isRegex() - ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') - : ($expr->isCaseSensitive() ? '-path' : '-ipath') - ) - ->arg($expr->renderPattern()); - } - - $command->cmd(')'); - } - - /** - * @param Command $command - * @param NumberComparator[] $sizes - */ - private function buildSizesFiltering(Command $command, array $sizes) - { - foreach ($sizes as $i => $size) { - $command->add($i > 0 ? '-and' : null); - - switch ($size->getOperator()) { - case '<=': - $command->add('-size -'.($size->getTarget() + 1).'c'); - break; - case '>=': - $command->add('-size +'. ($size->getTarget() - 1).'c'); - break; - case '>': - $command->add('-size +'.$size->getTarget().'c'); - break; - case '!=': - $command->add('-size -'.$size->getTarget().'c'); - $command->add('-size +'.$size->getTarget().'c'); - case '<': - default: - $command->add('-size -'.$size->getTarget().'c'); - } - } - } - - /** - * @param Command $command - * @param DateComparator[] $dates - */ - private function buildDatesFiltering(Command $command, array $dates) - { - foreach ($dates as $i => $date) { - $command->add($i > 0 ? '-and' : null); - - $mins = (int) round((time()-$date->getTarget()) / 60); - - if (0 > $mins) { - // mtime is in the future - $command->add(' -mmin -0'); - // we will have no result so we don't need to continue - return; - } - - switch ($date->getOperator()) { - case '<=': - $command->add('-mmin +'.($mins - 1)); - break; - case '>=': - $command->add('-mmin -'.($mins + 1)); - break; - case '>': - $command->add('-mmin -'.$mins); - break; - case '!=': - $command->add('-mmin +'.$mins.' -or -mmin -'.$mins); - break; - case '<': - default: - $command->add('-mmin +'.$mins); - } - } - } - - /** - * @param Command $command - * @param string $sort - * - * @throws \InvalidArgumentException - */ - private function buildSorting(Command $command, $sort) - { - $this->buildFormatSorting($command, $sort); - } - - /** - * @param Command $command - * @param string $sort - */ - abstract protected function buildFormatSorting(Command $command, $sort); - - /** - * @param Command $command - * @param array $contains - * @param Boolean $not - */ - abstract protected function buildContentFiltering(Command $command, array $contains, $not = false); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -/** - * @author Jean-François Simon - */ -interface AdapterInterface -{ - /** - * @param Boolean $followLinks - * - * @return AdapterInterface Current instance - */ - public function setFollowLinks($followLinks); - - /** - * @param integer $mode - * - * @return AdapterInterface Current instance - */ - public function setMode($mode); - - /** - * @param array $exclude - * - * @return AdapterInterface Current instance - */ - public function setExclude(array $exclude); - - /** - * @param array $depths - * - * @return AdapterInterface Current instance - */ - public function setDepths(array $depths); - - /** - * @param array $names - * - * @return AdapterInterface Current instance - */ - public function setNames(array $names); - - /** - * @param array $notNames - * - * @return AdapterInterface Current instance - */ - public function setNotNames(array $notNames); - - /** - * @param array $contains - * - * @return AdapterInterface Current instance - */ - public function setContains(array $contains); - - /** - * @param array $notContains - * - * @return AdapterInterface Current instance - */ - public function setNotContains(array $notContains); - - /** - * @param array $sizes - * - * @return AdapterInterface Current instance - */ - public function setSizes(array $sizes); - - /** - * @param array $dates - * - * @return AdapterInterface Current instance - */ - public function setDates(array $dates); - - /** - * @param array $filters - * - * @return AdapterInterface Current instance - */ - public function setFilters(array $filters); - - /** - * @param \Closure|integer $sort - * - * @return AdapterInterface Current instance - */ - public function setSort($sort); - - /** - * @param array $paths - * - * @return AdapterInterface Current instance - */ - public function setPath(array $paths); - - /** - * @param array $notPaths - * - * @return AdapterInterface Current instance - */ - public function setNotPath(array $notPaths); - - /** - * @param boolean $ignore - * - * @return AdapterInterface Current instance - */ - public function ignoreUnreadableDirs($ignore = true); - - /** - * @param string $dir - * - * @return \Iterator Result iterator - */ - public function searchInDirectory($dir); - - /** - * Tests adapter support for current platform. - * - * @return Boolean - */ - public function isSupported(); - - /** - * Returns adapter name. - * - * @return string - */ - public function getName(); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Adapter; - -/** - * Interface for finder engine implementations. - * - * @author Jean-François Simon - */ -abstract class AbstractAdapter implements AdapterInterface -{ - protected $followLinks = false; - protected $mode = 0; - protected $minDepth = 0; - protected $maxDepth = PHP_INT_MAX; - protected $exclude = array(); - protected $names = array(); - protected $notNames = array(); - protected $contains = array(); - protected $notContains = array(); - protected $sizes = array(); - protected $dates = array(); - protected $filters = array(); - protected $sort = false; - protected $paths = array(); - protected $notPaths = array(); - protected $ignoreUnreadableDirs = false; - - private static $areSupported = array(); - - /** - * {@inheritDoc} - */ - public function isSupported() - { - $name = $this->getName(); - - if (!array_key_exists($name, self::$areSupported)) { - self::$areSupported[$name] = $this->canBeUsed(); - } - - return self::$areSupported[$name]; - } - - /** - * {@inheritdoc} - */ - public function setFollowLinks($followLinks) - { - $this->followLinks = $followLinks; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setMode($mode) - { - $this->mode = $mode; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setDepths(array $depths) - { - $this->minDepth = 0; - $this->maxDepth = PHP_INT_MAX; - - foreach ($depths as $comparator) { - switch ($comparator->getOperator()) { - case '>': - $this->minDepth = $comparator->getTarget() + 1; - break; - case '>=': - $this->minDepth = $comparator->getTarget(); - break; - case '<': - $this->maxDepth = $comparator->getTarget() - 1; - break; - case '<=': - $this->maxDepth = $comparator->getTarget(); - break; - default: - $this->minDepth = $this->maxDepth = $comparator->getTarget(); - } - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setExclude(array $exclude) - { - $this->exclude = $exclude; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setNames(array $names) - { - $this->names = $names; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setNotNames(array $notNames) - { - $this->notNames = $notNames; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setContains(array $contains) - { - $this->contains = $contains; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setNotContains(array $notContains) - { - $this->notContains = $notContains; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setSizes(array $sizes) - { - $this->sizes = $sizes; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setDates(array $dates) - { - $this->dates = $dates; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setFilters(array $filters) - { - $this->filters = $filters; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setSort($sort) - { - $this->sort = $sort; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setPath(array $paths) - { - $this->paths = $paths; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setNotPath(array $notPaths) - { - $this->notPaths = $notPaths; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function ignoreUnreadableDirs($ignore = true) - { - $this->ignoreUnreadableDirs = (Boolean) $ignore; - - return $this; - } - - /** - * Returns whether the adapter is supported in the current environment. - * - * This method should be implemented in all adapters. Do not implement - * isSupported in the adapters as the generic implementation provides a cache - * layer. - * - * @see isSupported - * - * @return Boolean Whether the adapter is supported - */ - abstract protected function canBeUsed(); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -/** - * Glob matches globbing patterns against text. - * - * if match_glob("foo.*", "foo.bar") echo "matched\n"; - * - * // prints foo.bar and foo.baz - * $regex = glob_to_regex("foo.*"); - * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t) - * { - * if (/$regex/) echo "matched: $car\n"; - * } - * - * Glob implements glob(3) style matching that can be used to match - * against text, rather than fetching names from a filesystem. - * - * Based on the Perl Text::Glob module. - * - * @author Fabien Potencier PHP port - * @author Richard Clamp Perl version - * @copyright 2004-2005 Fabien Potencier - * @copyright 2002 Richard Clamp - */ -class Glob -{ - /** - * Returns a regexp which is the equivalent of the glob pattern. - * - * @param string $glob The glob pattern - * @param Boolean $strictLeadingDot - * @param Boolean $strictWildcardSlash - * - * @return string regex The regexp - */ - public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true) - { - $firstByte = true; - $escaping = false; - $inCurlies = 0; - $regex = ''; - $sizeGlob = strlen($glob); - for ($i = 0; $i < $sizeGlob; $i++) { - $car = $glob[$i]; - if ($firstByte) { - if ($strictLeadingDot && '.' !== $car) { - $regex .= '(?=[^\.])'; - } - - $firstByte = false; - } - - if ('/' === $car) { - $firstByte = true; - } - - if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { - $regex .= "\\$car"; - } elseif ('*' === $car) { - $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); - } elseif ('?' === $car) { - $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); - } elseif ('{' === $car) { - $regex .= $escaping ? '\\{' : '('; - if (!$escaping) { - ++$inCurlies; - } - } elseif ('}' === $car && $inCurlies) { - $regex .= $escaping ? '}' : ')'; - if (!$escaping) { - --$inCurlies; - } - } elseif (',' === $car && $inCurlies) { - $regex .= $escaping ? ',' : '|'; - } elseif ('\\' === $car) { - if ($escaping) { - $regex .= '\\\\'; - $escaping = false; - } else { - $escaping = true; - } - - continue; - } else { - $regex .= $car; - } - $escaping = false; - } - - return '#^'.$regex.'$#'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -/** - * Extends \SplFileInfo to support relative paths - * - * @author Fabien Potencier - */ -class SplFileInfo extends \SplFileInfo -{ - private $relativePath; - private $relativePathname; - - /** - * Constructor - * - * @param string $file The file name - * @param string $relativePath The relative path - * @param string $relativePathname The relative path name - */ - public function __construct($file, $relativePath, $relativePathname) - { - parent::__construct($file); - $this->relativePath = $relativePath; - $this->relativePathname = $relativePathname; - } - - /** - * Returns the relative path - * - * @return string the relative path - */ - public function getRelativePath() - { - return $this->relativePath; - } - - /** - * Returns the relative path name - * - * @return string the relative path name - */ - public function getRelativePathname() - { - return $this->relativePathname; - } - - /** - * Returns the contents of the file - * - * @return string the contents of the file - * - * @throws \RuntimeException - */ - public function getContents() - { - $level = error_reporting(0); - $content = file_get_contents($this->getPathname()); - error_reporting($level); - if (false === $content) { - $error = error_get_last(); - throw new \RuntimeException($error['message']); - } - - return $content; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * NumberComparator compiles a simple comparison to an anonymous - * subroutine, which you can call with a value to be tested again. - * - * Now this would be very pointless, if NumberCompare didn't understand - * magnitudes. - * - * The target value may use magnitudes of kilobytes (k, ki), - * megabytes (m, mi), or gigabytes (g, gi). Those suffixed - * with an i use the appropriate 2**n version in accordance with the - * IEC standard: http://physics.nist.gov/cuu/Units/binary.html - * - * Based on the Perl Number::Compare module. - * - * @author Fabien Potencier PHP port - * @author Richard Clamp Perl version - * - * @copyright 2004-2005 Fabien Potencier - * @copyright 2002 Richard Clamp - * - * @see http://physics.nist.gov/cuu/Units/binary.html - */ -class NumberComparator extends Comparator -{ - /** - * Constructor. - * - * @param string $test A comparison string - * - * @throws \InvalidArgumentException If the test is not understood - */ - public function __construct($test) - { - if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { - throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test)); - } - - $target = $matches[2]; - if (!is_numeric($target)) { - throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target)); - } - if (isset($matches[3])) { - // magnitude - switch (strtolower($matches[3])) { - case 'k': - $target *= 1000; - break; - case 'ki': - $target *= 1024; - break; - case 'm': - $target *= 1000000; - break; - case 'mi': - $target *= 1024*1024; - break; - case 'g': - $target *= 1000000000; - break; - case 'gi': - $target *= 1024*1024*1024; - break; - } - } - - $this->setTarget($target); - $this->setOperator(isset($matches[1]) ? $matches[1] : '=='); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * DateCompare compiles date comparisons. - * - * @author Fabien Potencier - */ -class DateComparator extends Comparator -{ - - /** - * Constructor. - * - * @param string $test A comparison string - * - * @throws \InvalidArgumentException If the test is not understood - */ - public function __construct($test) - { - if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { - throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); - } - - try { - $date = new \DateTime($matches[2]); - $target = $date->format('U'); - } catch (\Exception $e) { - throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); - } - - $operator = isset($matches[1]) ? $matches[1] : '=='; - if ('since' === $operator || 'after' === $operator) { - $operator = '>'; - } - - if ('until' === $operator || 'before' === $operator) { - $operator = '<'; - } - - $this->setOperator($operator); - $this->setTarget($target); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * Comparator. - * - * @author Fabien Potencier - */ -class Comparator -{ - private $target; - private $operator = '=='; - - /** - * Gets the target value. - * - * @return string The target value - */ - public function getTarget() - { - return $this->target; - } - - /** - * Sets the target value. - * - * @param string $target The target value - */ - public function setTarget($target) - { - $this->target = $target; - } - - /** - * Gets the comparison operator. - * - * @return string The operator - */ - public function getOperator() - { - return $this->operator; - } - - /** - * Sets the comparison operator. - * - * @param string $operator A valid operator - * - * @throws \InvalidArgumentException - */ - public function setOperator($operator) - { - if (!$operator) { - $operator = '=='; - } - - if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) { - throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); - } - - $this->operator = $operator; - } - - /** - * Tests against the target. - * - * @param mixed $test A test value - * - * @return Boolean - */ - public function test($test) - { - switch ($this->operator) { - case '>': - return $test > $this->target; - case '>=': - return $test >= $this->target; - case '<': - return $test < $this->target; - case '<=': - return $test <= $this->target; - case '!=': - return $test != $this->target; - } - - return $test == $this->target; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Expression; - -/** - * @author Jean-François Simon - */ -class Expression implements ValueInterface -{ - const TYPE_REGEX = 1; - const TYPE_GLOB = 2; - - /** - * @var ValueInterface - */ - private $value; - - /** - * @param string $expr - * - * @return Expression - */ - public static function create($expr) - { - return new self($expr); - } - - /** - * @param string $expr - */ - public function __construct($expr) - { - try { - $this->value = Regex::create($expr); - } catch (\InvalidArgumentException $e) { - $this->value = new Glob($expr); - } - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(); - } - - /** - * {@inheritdoc} - */ - public function render() - { - return $this->value->render(); - } - - /** - * {@inheritdoc} - */ - public function renderPattern() - { - return $this->value->renderPattern(); - } - - /** - * @return bool - */ - public function isCaseSensitive() - { - return $this->value->isCaseSensitive(); - } - - /** - * @return int - */ - public function getType() - { - return $this->value->getType(); - } - - /** - * {@inheritdoc} - */ - public function prepend($expr) - { - $this->value->prepend($expr); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function append($expr) - { - $this->value->append($expr); - - return $this; - } - - /** - * @return bool - */ - public function isRegex() - { - return self::TYPE_REGEX === $this->value->getType(); - } - - /** - * @return bool - */ - public function isGlob() - { - return self::TYPE_GLOB === $this->value->getType(); - } - - /** - * @throws \LogicException - * - * @return Glob - */ - public function getGlob() - { - if (self::TYPE_GLOB !== $this->value->getType()) { - throw new \LogicException('Regex can\'t be transformed to glob.'); - } - - return $this->value; - } - - /** - * @return Regex - */ - public function getRegex() - { - return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex(); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Expression; - -/** - * @author Jean-François Simon - */ -class Regex implements ValueInterface -{ - const START_FLAG = '^'; - const END_FLAG = '$'; - const BOUNDARY = '~'; - const JOKER = '.*'; - const ESCAPING = '\\'; - - /** - * @var string - */ - private $pattern; - - /** - * @var array - */ - private $options; - - /** - * @var bool - */ - private $startFlag; - - /** - * @var bool - */ - private $endFlag; - - /** - * @var bool - */ - private $startJoker; - - /** - * @var bool - */ - private $endJoker; - - /** - * @param string $expr - * - * @return Regex - * - * @throws \InvalidArgumentException - */ - public static function create($expr) - { - if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) { - $start = substr($m[1], 0, 1); - $end = substr($m[1], -1); - - if (($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start)) || ($start === '{' && $end === '}')) { - return new self(substr($m[1], 1, -1), $m[2], $end); - } - } - - throw new \InvalidArgumentException('Given expression is not a regex.'); - } - - /** - * @param string $pattern - * @param string $options - * @param string $delimiter - */ - public function __construct($pattern, $options = '', $delimiter = null) - { - if (null !== $delimiter) { - // removes delimiter escaping - $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern); - } - - $this->parsePattern($pattern); - $this->options = $options; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(); - } - - /** - * {@inheritdoc} - */ - public function render() - { - return self::BOUNDARY - .$this->renderPattern() - .self::BOUNDARY - .$this->options; - } - - /** - * {@inheritdoc} - */ - public function renderPattern() - { - return ($this->startFlag ? self::START_FLAG : '') - .($this->startJoker ? self::JOKER : '') - .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern) - .($this->endJoker ? self::JOKER : '') - .($this->endFlag ? self::END_FLAG : ''); - } - - /** - * {@inheritdoc} - */ - public function isCaseSensitive() - { - return !$this->hasOption('i'); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - return Expression::TYPE_REGEX; - } - - /** - * {@inheritdoc} - */ - public function prepend($expr) - { - $this->pattern = $expr.$this->pattern; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function append($expr) - { - $this->pattern .= $expr; - - return $this; - } - - /** - * @param string $option - * - * @return bool - */ - public function hasOption($option) - { - return false !== strpos($this->options, $option); - } - - /** - * @param string $option - * - * @return Regex - */ - public function addOption($option) - { - if (!$this->hasOption($option)) { - $this->options.= $option; - } - - return $this; - } - - /** - * @param string $option - * - * @return Regex - */ - public function removeOption($option) - { - $this->options = str_replace($option, '', $this->options); - - return $this; - } - - /** - * @param bool $startFlag - * - * @return Regex - */ - public function setStartFlag($startFlag) - { - $this->startFlag = $startFlag; - - return $this; - } - - /** - * @return bool - */ - public function hasStartFlag() - { - return $this->startFlag; - } - - /** - * @param bool $endFlag - * - * @return Regex - */ - public function setEndFlag($endFlag) - { - $this->endFlag = (bool) $endFlag; - - return $this; - } - - /** - * @return bool - */ - public function hasEndFlag() - { - return $this->endFlag; - } - - /** - * @param bool $startJoker - * - * @return Regex - */ - public function setStartJoker($startJoker) - { - $this->startJoker = $startJoker; - - return $this; - } - - /** - * @return bool - */ - public function hasStartJoker() - { - return $this->startJoker; - } - - /** - * @param bool $endJoker - * - * @return Regex - */ - public function setEndJoker($endJoker) - { - $this->endJoker = (bool) $endJoker; - - return $this; - } - - /** - * @return bool - */ - public function hasEndJoker() - { - return $this->endJoker; - } - - /** - * @param array $replacement - * - * @return Regex - */ - public function replaceJokers($replacement) - { - $replace = function ($subject) use ($replacement) { - $subject = $subject[0]; - $replace = 0 === substr_count($subject, '\\') % 2; - - return $replace ? str_replace('.', $replacement, $subject) : $subject; - }; - - $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern); - - return $this; - } - - /** - * @param string $pattern - */ - private function parsePattern($pattern) - { - if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) { - $pattern = substr($pattern, 1); - } - - if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) { - $pattern = substr($pattern, 2); - } - - if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) { - $pattern = substr($pattern, 0, -1); - } - - if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) { - $pattern = substr($pattern, 0, -2); - } - - $this->pattern = $pattern; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Expression; - -/** - * @author Jean-François Simon - */ -class Glob implements ValueInterface -{ - /** - * @var string - */ - private $pattern; - - /** - * @param string $pattern - */ - public function __construct($pattern) - { - $this->pattern = $pattern; - } - - /** - * {@inheritdoc} - */ - public function render() - { - return $this->pattern; - } - - /** - * {@inheritdoc} - */ - public function renderPattern() - { - return $this->pattern; - } - - /** - * {@inheritdoc} - */ - public function getType() - { - return Expression::TYPE_GLOB; - } - - /** - * {@inheritdoc} - */ - public function isCaseSensitive() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function prepend($expr) - { - $this->pattern = $expr.$this->pattern; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function append($expr) - { - $this->pattern .= $expr; - - return $this; - } - - /** - * Tests if glob is expandable ("*.{a,b}" syntax). - * - * @return bool - */ - public function isExpandable() - { - return false !== strpos($this->pattern, '{') - && false !== strpos($this->pattern, '}'); - } - - /** - * @param bool $strictLeadingDot - * @param bool $strictWildcardSlash - * - * @return Regex - */ - public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true) - { - $firstByte = true; - $escaping = false; - $inCurlies = 0; - $regex = ''; - $sizeGlob = strlen($this->pattern); - for ($i = 0; $i < $sizeGlob; $i++) { - $car = $this->pattern[$i]; - if ($firstByte) { - if ($strictLeadingDot && '.' !== $car) { - $regex .= '(?=[^\.])'; - } - - $firstByte = false; - } - - if ('/' === $car) { - $firstByte = true; - } - - if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { - $regex .= "\\$car"; - } elseif ('*' === $car) { - $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); - } elseif ('?' === $car) { - $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); - } elseif ('{' === $car) { - $regex .= $escaping ? '\\{' : '('; - if (!$escaping) { - ++$inCurlies; - } - } elseif ('}' === $car && $inCurlies) { - $regex .= $escaping ? '}' : ')'; - if (!$escaping) { - --$inCurlies; - } - } elseif (',' === $car && $inCurlies) { - $regex .= $escaping ? ',' : '|'; - } elseif ('\\' === $car) { - if ($escaping) { - $regex .= '\\\\'; - $escaping = false; - } else { - $escaping = true; - } - - continue; - } else { - $regex .= $car; - } - $escaping = false; - } - - return new Regex('^'.$regex.'$'); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Expression; - -/** - * @author Jean-François Simon - */ -interface ValueInterface -{ - /** - * Renders string representation of expression. - * - * @return string - */ - public function render(); - - /** - * Renders string representation of pattern. - * - * @return string - */ - public function renderPattern(); - - /** - * Returns value case sensitivity. - * - * @return bool - */ - public function isCaseSensitive(); - - /** - * Returns expression type. - * - * @return int - */ - public function getType(); - - /** - * @param string $expr - * - * @return ValueInterface - */ - public function prepend($expr); - - /** - * @param string $expr - * - * @return ValueInterface - */ - public function append($expr); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Jean-François Simon - */ -class OperationNotPermitedException extends AdapterFailureException -{ -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Jean-François Simon - */ -class AccessDeniedException extends \UnexpectedValueException -{ -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Jean-François Simon - */ -interface ExceptionInterface -{ - /** - * @return \Symfony\Component\Finder\Adapter\AdapterInterface - */ - public function getAdapter(); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -use Symfony\Component\Finder\Adapter\AdapterInterface; -use Symfony\Component\Finder\Shell\Command; - -/** - * @author Jean-François Simon - */ -class ShellCommandFailureException extends AdapterFailureException -{ - /** - * @var Command - */ - private $command; - - /** - * @param AdapterInterface $adapter - * @param Command $command - * @param \Exception|null $previous - */ - public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null) - { - $this->command = $command; - parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous); - } - - /** - * @return Command - */ - public function getCommand() - { - return $this->command; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -use Symfony\Component\Finder\Adapter\AdapterInterface; - -/** - * Base exception for all adapter failures. - * - * @author Jean-François Simon - */ -class AdapterFailureException extends \RuntimeException implements ExceptionInterface -{ - /** - * @var \Symfony\Component\Finder\Adapter\AdapterInterface - */ - private $adapter; - - /** - * @param AdapterInterface $adapter - * @param string|null $message - * @param \Exception|null $previous - */ - public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null) - { - $this->adapter = $adapter; - parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous); - } - - /** - * {@inheritdoc} - */ - public function getAdapter() - { - return $this->adapter; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -use Symfony\Component\Finder\Adapter\AdapterInterface; -use Symfony\Component\Finder\Adapter\GnuFindAdapter; -use Symfony\Component\Finder\Adapter\BsdFindAdapter; -use Symfony\Component\Finder\Adapter\PhpAdapter; -use Symfony\Component\Finder\Exception\ExceptionInterface; - -/** - * Finder allows to build rules to find files and directories. - * - * It is a thin wrapper around several specialized iterator classes. - * - * All rules may be invoked several times. - * - * All methods return the current Finder object to allow easy chaining: - * - * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); - * - * @author Fabien Potencier - * - * @api - */ -class Finder implements \IteratorAggregate, \Countable -{ - const IGNORE_VCS_FILES = 1; - const IGNORE_DOT_FILES = 2; - - private $mode = 0; - private $names = array(); - private $notNames = array(); - private $exclude = array(); - private $filters = array(); - private $depths = array(); - private $sizes = array(); - private $followLinks = false; - private $sort = false; - private $ignore = 0; - private $dirs = array(); - private $dates = array(); - private $iterators = array(); - private $contains = array(); - private $notContains = array(); - private $adapters = array(); - private $paths = array(); - private $notPaths = array(); - private $ignoreUnreadableDirs = false; - - private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'); - - /** - * Constructor. - */ - public function __construct() - { - $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; - - $this - ->addAdapter(new GnuFindAdapter()) - ->addAdapter(new BsdFindAdapter()) - ->addAdapter(new PhpAdapter(), -50) - ->setAdapter('php') - ; - } - - /** - * Creates a new Finder. - * - * @return Finder A new Finder instance - * - * @api - */ - public static function create() - { - return new static(); - } - - /** - * Registers a finder engine implementation. - * - * @param AdapterInterface $adapter An adapter instance - * @param integer $priority Highest is selected first - * - * @return Finder The current Finder instance - */ - public function addAdapter(Adapter\AdapterInterface $adapter, $priority = 0) - { - $this->adapters[$adapter->getName()] = array( - 'adapter' => $adapter, - 'priority' => $priority, - 'selected' => false, - ); - - return $this->sortAdapters(); - } - - /** - * Sets the selected adapter to the best one according to the current platform the code is run on. - * - * @return Finder The current Finder instance - */ - public function useBestAdapter() - { - $this->resetAdapterSelection(); - - return $this->sortAdapters(); - } - - /** - * Selects the adapter to use. - * - * @param string $name - * - * @throws \InvalidArgumentException - * - * @return Finder The current Finder instance - */ - public function setAdapter($name) - { - if (!isset($this->adapters[$name])) { - throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name)); - } - - $this->resetAdapterSelection(); - $this->adapters[$name]['selected'] = true; - - return $this->sortAdapters(); - } - - /** - * Removes all adapters registered in the finder. - * - * @return Finder The current Finder instance - */ - public function removeAdapters() - { - $this->adapters = array(); - - return $this; - } - - /** - * Returns registered adapters ordered by priority without extra information. - * - * @return AdapterInterface[] - */ - public function getAdapters() - { - return array_values(array_map(function(array $adapter) { - return $adapter['adapter']; - }, $this->adapters)); - } - - /** - * Restricts the matching to directories only. - * - * @return Finder The current Finder instance - * - * @api - */ - public function directories() - { - $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES; - - return $this; - } - - /** - * Restricts the matching to files only. - * - * @return Finder The current Finder instance - * - * @api - */ - public function files() - { - $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES; - - return $this; - } - - /** - * Adds tests for the directory depth. - * - * Usage: - * - * $finder->depth('> 1') // the Finder will start matching at level 1. - * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. - * - * @param int $level The depth level expression - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\DepthRangeFilterIterator - * @see Symfony\Component\Finder\Comparator\NumberComparator - * - * @api - */ - public function depth($level) - { - $this->depths[] = new Comparator\NumberComparator($level); - - return $this; - } - - /** - * Adds tests for file dates (last modified). - * - * The date must be something that strtotime() is able to parse: - * - * $finder->date('since yesterday'); - * $finder->date('until 2 days ago'); - * $finder->date('> now - 2 hours'); - * $finder->date('>= 2005-10-15'); - * - * @param string $date A date rage string - * - * @return Finder The current Finder instance - * - * @see strtotime - * @see Symfony\Component\Finder\Iterator\DateRangeFilterIterator - * @see Symfony\Component\Finder\Comparator\DateComparator - * - * @api - */ - public function date($date) - { - $this->dates[] = new Comparator\DateComparator($date); - - return $this; - } - - /** - * Adds rules that files must match. - * - * You can use patterns (delimited with / sign), globs or simple strings. - * - * $finder->name('*.php') - * $finder->name('/\.php$/') // same as above - * $finder->name('test.php') - * - * @param string $pattern A pattern (a regexp, a glob, or a string) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator - * - * @api - */ - public function name($pattern) - { - $this->names[] = $pattern; - - return $this; - } - - /** - * Adds rules that files must not match. - * - * @param string $pattern A pattern (a regexp, a glob, or a string) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator - * - * @api - */ - public function notName($pattern) - { - $this->notNames[] = $pattern; - - return $this; - } - - /** - * Adds tests that file contents must match. - * - * Strings or PCRE patterns can be used: - * - * $finder->contains('Lorem ipsum') - * $finder->contains('/Lorem ipsum/i') - * - * @param string $pattern A pattern (string or regexp) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator - */ - public function contains($pattern) - { - $this->contains[] = $pattern; - - return $this; - } - - /** - * Adds tests that file contents must not match. - * - * Strings or PCRE patterns can be used: - * - * $finder->notContains('Lorem ipsum') - * $finder->notContains('/Lorem ipsum/i') - * - * @param string $pattern A pattern (string or regexp) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator - */ - public function notContains($pattern) - { - $this->notContains[] = $pattern; - - return $this; - } - - /** - * Adds rules that filenames must match. - * - * You can use patterns (delimited with / sign) or simple strings. - * - * $finder->path('some/special/dir') - * $finder->path('/some\/special\/dir/') // same as above - * - * Use only / as dirname separator. - * - * @param string $pattern A pattern (a regexp or a string) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator - */ - public function path($pattern) - { - $this->paths[] = $pattern; - - return $this; - } - - /** - * Adds rules that filenames must not match. - * - * You can use patterns (delimited with / sign) or simple strings. - * - * $finder->notPath('some/special/dir') - * $finder->notPath('/some\/special\/dir/') // same as above - * - * Use only / as dirname separator. - * - * @param string $pattern A pattern (a regexp or a string) - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator - */ - public function notPath($pattern) - { - $this->notPaths[] = $pattern; - - return $this; - } - - /** - * Adds tests for file sizes. - * - * $finder->size('> 10K'); - * $finder->size('<= 1Ki'); - * $finder->size(4); - * - * @param string $size A size range string - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SizeRangeFilterIterator - * @see Symfony\Component\Finder\Comparator\NumberComparator - * - * @api - */ - public function size($size) - { - $this->sizes[] = new Comparator\NumberComparator($size); - - return $this; - } - - /** - * Excludes directories. - * - * @param string|array $dirs A directory path or an array of directories - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator - * - * @api - */ - public function exclude($dirs) - { - $this->exclude = array_merge($this->exclude, (array) $dirs); - - return $this; - } - - /** - * Excludes "hidden" directories and files (starting with a dot). - * - * @param Boolean $ignoreDotFiles Whether to exclude "hidden" files or not - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator - * - * @api - */ - public function ignoreDotFiles($ignoreDotFiles) - { - if ($ignoreDotFiles) { - $this->ignore = $this->ignore | static::IGNORE_DOT_FILES; - } else { - $this->ignore = $this->ignore & ~static::IGNORE_DOT_FILES; - } - - return $this; - } - - /** - * Forces the finder to ignore version control directories. - * - * @param Boolean $ignoreVCS Whether to exclude VCS files or not - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator - * - * @api - */ - public function ignoreVCS($ignoreVCS) - { - if ($ignoreVCS) { - $this->ignore = $this->ignore | static::IGNORE_VCS_FILES; - } else { - $this->ignore = $this->ignore & ~static::IGNORE_VCS_FILES; - } - - return $this; - } - - /** - * Adds VCS patterns. - * - * @see ignoreVCS - * - * @param string|string[] $pattern VCS patterns to ignore - */ - public static function addVCSPattern($pattern) - { - foreach ((array) $pattern as $p) { - self::$vcsPatterns[] = $p; - } - - self::$vcsPatterns = array_unique(self::$vcsPatterns); - } - - /** - * Sorts files and directories by an anonymous function. - * - * The anonymous function receives two \SplFileInfo instances to compare. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @param \Closure $closure An anonymous function - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sort(\Closure $closure) - { - $this->sort = $closure; - - return $this; - } - - /** - * Sorts files and directories by name. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sortByName() - { - $this->sort = Iterator\SortableIterator::SORT_BY_NAME; - - return $this; - } - - /** - * Sorts files and directories by type (directories before files), then by name. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sortByType() - { - $this->sort = Iterator\SortableIterator::SORT_BY_TYPE; - - return $this; - } - - /** - * Sorts files and directories by the last accessed time. - * - * This is the time that the file was last accessed, read or written to. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sortByAccessedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME; - - return $this; - } - - /** - * Sorts files and directories by the last inode changed time. - * - * This is the time that the inode information was last modified (permissions, owner, group or other metadata). - * - * On Windows, since inode is not available, changed time is actually the file creation time. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sortByChangedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME; - - return $this; - } - - /** - * Sorts files and directories by the last modified time. - * - * This is the last time the actual contents of the file were last modified. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\SortableIterator - * - * @api - */ - public function sortByModifiedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME; - - return $this; - } - - /** - * Filters the iterator with an anonymous function. - * - * The anonymous function receives a \SplFileInfo and must return false - * to remove files. - * - * @param \Closure $closure An anonymous function - * - * @return Finder The current Finder instance - * - * @see Symfony\Component\Finder\Iterator\CustomFilterIterator - * - * @api - */ - public function filter(\Closure $closure) - { - $this->filters[] = $closure; - - return $this; - } - - /** - * Forces the following of symlinks. - * - * @return Finder The current Finder instance - * - * @api - */ - public function followLinks() - { - $this->followLinks = true; - - return $this; - } - - /** - * Tells finder to ignore unreadable directories. - * - * By default, scanning unreadable directories content throws an AccessDeniedException. - * - * @param boolean $ignore - * - * @return Finder The current Finder instance - */ - public function ignoreUnreadableDirs($ignore = true) - { - $this->ignoreUnreadableDirs = (Boolean) $ignore; - - return $this; - } - - /** - * Searches files and directories which match defined rules. - * - * @param string|array $dirs A directory path or an array of directories - * - * @return Finder The current Finder instance - * - * @throws \InvalidArgumentException if one of the directories does not exist - * - * @api - */ - public function in($dirs) - { - $resolvedDirs = array(); - - foreach ((array) $dirs as $dir) { - if (is_dir($dir)) { - $resolvedDirs[] = $dir; - } elseif ($glob = glob($dir, GLOB_ONLYDIR)) { - $resolvedDirs = array_merge($resolvedDirs, $glob); - } else { - throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir)); - } - } - - $this->dirs = array_merge($this->dirs, $resolvedDirs); - - return $this; - } - - /** - * Returns an Iterator for the current Finder configuration. - * - * This method implements the IteratorAggregate interface. - * - * @return \Iterator An iterator - * - * @throws \LogicException if the in() method has not been called - */ - public function getIterator() - { - if (0 === count($this->dirs) && 0 === count($this->iterators)) { - throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.'); - } - - if (1 === count($this->dirs) && 0 === count($this->iterators)) { - return $this->searchInDirectory($this->dirs[0]); - } - - $iterator = new \AppendIterator(); - foreach ($this->dirs as $dir) { - $iterator->append($this->searchInDirectory($dir)); - } - - foreach ($this->iterators as $it) { - $iterator->append($it); - } - - return $iterator; - } - - /** - * Appends an existing set of files/directories to the finder. - * - * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. - * - * @param mixed $iterator - * - * @return Finder The finder - * - * @throws \InvalidArgumentException When the given argument is not iterable. - */ - public function append($iterator) - { - if ($iterator instanceof \IteratorAggregate) { - $this->iterators[] = $iterator->getIterator(); - } elseif ($iterator instanceof \Iterator) { - $this->iterators[] = $iterator; - } elseif ($iterator instanceof \Traversable || is_array($iterator)) { - $it = new \ArrayIterator(); - foreach ($iterator as $file) { - $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file)); - } - $this->iterators[] = $it; - } else { - throw new \InvalidArgumentException('Finder::append() method wrong argument type.'); - } - - return $this; - } - - /** - * Counts all the results collected by the iterators. - * - * @return int - */ - public function count() - { - return iterator_count($this->getIterator()); - } - - /** - * @return Finder The current Finder instance - */ - private function sortAdapters() - { - uasort($this->adapters, function (array $a, array $b) { - if ($a['selected'] || $b['selected']) { - return $a['selected'] ? -1 : 1; - } - - return $a['priority'] > $b['priority'] ? -1 : 1; - }); - - return $this; - } - - /** - * @param $dir - * - * @return \Iterator - * - * @throws \RuntimeException When none of the adapters are supported - */ - private function searchInDirectory($dir) - { - if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { - $this->exclude = array_merge($this->exclude, self::$vcsPatterns); - } - - if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { - $this->notPaths[] = '#(^|/)\..+(/|$)#'; - } - - foreach ($this->adapters as $adapter) { - if ($adapter['adapter']->isSupported()) { - try { - return $this - ->buildAdapter($adapter['adapter']) - ->searchInDirectory($dir); - } catch (ExceptionInterface $e) {} - } - } - - throw new \RuntimeException('No supported adapter found.'); - } - - /** - * @param AdapterInterface $adapter - * - * @return AdapterInterface - */ - private function buildAdapter(AdapterInterface $adapter) - { - return $adapter - ->setFollowLinks($this->followLinks) - ->setDepths($this->depths) - ->setMode($this->mode) - ->setExclude($this->exclude) - ->setNames($this->names) - ->setNotNames($this->notNames) - ->setContains($this->contains) - ->setNotContains($this->notContains) - ->setSizes($this->sizes) - ->setDates($this->dates) - ->setFilters($this->filters) - ->setSort($this->sort) - ->setPath($this->paths) - ->setNotPath($this->notPaths) - ->ignoreUnreadableDirs($this->ignoreUnreadableDirs); - } - - /** - * Unselects all adapters. - */ - private function resetAdapterSelection() - { - $this->adapters = array_map(function (array $properties) { - $properties['selected'] = false; - - return $properties; - }, $this->adapters); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\BufferedOutput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Helper\HelperSet; - -/** - * Base class for all commands. - * - * @author Fabien Potencier - * - * @api - */ -class Command -{ - private $application; - private $name; - private $aliases = array(); - private $definition; - private $help; - private $description; - private $ignoreValidationErrors = false; - private $applicationDefinitionMerged = false; - private $applicationDefinitionMergedWithArgs = false; - private $code; - private $synopsis; - private $helperSet; - - /** - * Constructor. - * - * @param string|null $name The name of the command; passing null means it must be set in configure() - * - * @throws \LogicException When the command name is empty - * - * @api - */ - public function __construct($name = null) - { - $this->definition = new InputDefinition(); - - if (null !== $name) { - $this->setName($name); - } - - $this->configure(); - - if (!$this->name) { - throw new \LogicException('The command name cannot be empty.'); - } - } - - /** - * Ignores validation errors. - * - * This is mainly useful for the help command. - */ - public function ignoreValidationErrors() - { - $this->ignoreValidationErrors = true; - } - - /** - * Sets the application instance for this command. - * - * @param Application $application An Application instance - * - * @api - */ - public function setApplication(Application $application = null) - { - $this->application = $application; - if ($application) { - $this->setHelperSet($application->getHelperSet()); - } else { - $this->helperSet = null; - } - } - - /** - * Sets the helper set. - * - * @param HelperSet $helperSet A HelperSet instance - */ - public function setHelperSet(HelperSet $helperSet) - { - $this->helperSet = $helperSet; - } - - /** - * Gets the helper set. - * - * @return HelperSet A HelperSet instance - */ - public function getHelperSet() - { - return $this->helperSet; - } - - /** - * Gets the application instance for this command. - * - * @return Application An Application instance - * - * @api - */ - public function getApplication() - { - return $this->application; - } - - /** - * Checks whether the command is enabled or not in the current environment - * - * Override this to check for x or y and return false if the command can not - * run properly under the current conditions. - * - * @return Boolean - */ - public function isEnabled() - { - return true; - } - - /** - * Configures the current command. - */ - protected function configure() - { - } - - /** - * Executes the current command. - * - * This method is not abstract because you can use this class - * as a concrete class. In this case, instead of defining the - * execute() method, you set the code to execute by passing - * a Closure to the setCode() method. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * - * @return null|integer null or 0 if everything went fine, or an error code - * - * @throws \LogicException When this abstract method is not implemented - * @see setCode() - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - throw new \LogicException('You must override the execute() method in the concrete command class.'); - } - - /** - * Interacts with the user. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - */ - protected function interact(InputInterface $input, OutputInterface $output) - { - } - - /** - * Initializes the command just after the input has been validated. - * - * This is mainly useful when a lot of commands extends one main command - * where some things need to be initialized based on the input arguments and options. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - */ - protected function initialize(InputInterface $input, OutputInterface $output) - { - } - - /** - * Runs the command. - * - * The code to execute is either defined directly with the - * setCode() method or by overriding the execute() method - * in a sub-class. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * - * @return integer The command exit code - * - * @throws \Exception - * - * @see setCode() - * @see execute() - * - * @api - */ - public function run(InputInterface $input, OutputInterface $output) - { - // force the creation of the synopsis before the merge with the app definition - $this->getSynopsis(); - - // add the application arguments and options - $this->mergeApplicationDefinition(); - - // bind the input against the command specific arguments/options - try { - $input->bind($this->definition); - } catch (\Exception $e) { - if (!$this->ignoreValidationErrors) { - throw $e; - } - } - - $this->initialize($input, $output); - - if ($input->isInteractive()) { - $this->interact($input, $output); - } - - $input->validate(); - - if ($this->code) { - $statusCode = call_user_func($this->code, $input, $output); - } else { - $statusCode = $this->execute($input, $output); - } - - return is_numeric($statusCode) ? (int) $statusCode : 0; - } - - /** - * Sets the code to execute when running this command. - * - * If this method is used, it overrides the code defined - * in the execute() method. - * - * @param callable $code A callable(InputInterface $input, OutputInterface $output) - * - * @return Command The current instance - * - * @throws \InvalidArgumentException - * - * @see execute() - * - * @api - */ - public function setCode($code) - { - if (!is_callable($code)) { - throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.'); - } - - $this->code = $code; - - return $this; - } - - /** - * Merges the application definition with the command definition. - * - * This method is not part of public API and should not be used directly. - * - * @param Boolean $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments - */ - public function mergeApplicationDefinition($mergeArgs = true) - { - if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) { - return; - } - - if ($mergeArgs) { - $currentArguments = $this->definition->getArguments(); - $this->definition->setArguments($this->application->getDefinition()->getArguments()); - $this->definition->addArguments($currentArguments); - } - - $this->definition->addOptions($this->application->getDefinition()->getOptions()); - - $this->applicationDefinitionMerged = true; - if ($mergeArgs) { - $this->applicationDefinitionMergedWithArgs = true; - } - } - - /** - * Sets an array of argument and option instances. - * - * @param array|InputDefinition $definition An array of argument and option instances or a definition instance - * - * @return Command The current instance - * - * @api - */ - public function setDefinition($definition) - { - if ($definition instanceof InputDefinition) { - $this->definition = $definition; - } else { - $this->definition->setDefinition($definition); - } - - $this->applicationDefinitionMerged = false; - - return $this; - } - - /** - * Gets the InputDefinition attached to this Command. - * - * @return InputDefinition An InputDefinition instance - * - * @api - */ - public function getDefinition() - { - return $this->definition; - } - - /** - * Gets the InputDefinition to be used to create XML and Text representations of this Command. - * - * Can be overridden to provide the original command representation when it would otherwise - * be changed by merging with the application InputDefinition. - * - * This method is not part of public API and should not be used directly. - * - * @return InputDefinition An InputDefinition instance - */ - public function getNativeDefinition() - { - return $this->getDefinition(); - } - - /** - * Adds an argument. - * - * @param string $name The argument name - * @param integer $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL - * @param string $description A description text - * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) - * - * @return Command The current instance - * - * @api - */ - public function addArgument($name, $mode = null, $description = '', $default = null) - { - $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); - - return $this; - } - - /** - * Adds an option. - * - * @param string $name The option name - * @param string $shortcut The shortcut (can be null) - * @param integer $mode The option mode: One of the InputOption::VALUE_* constants - * @param string $description A description text - * @param mixed $default The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE) - * - * @return Command The current instance - * - * @api - */ - public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null) - { - $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); - - return $this; - } - - /** - * Sets the name of the command. - * - * This method can set both the namespace and the name if - * you separate them by a colon (:) - * - * $command->setName('foo:bar'); - * - * @param string $name The command name - * - * @return Command The current instance - * - * @throws \InvalidArgumentException When the name is invalid - * - * @api - */ - public function setName($name) - { - $this->validateName($name); - - $this->name = $name; - - return $this; - } - - /** - * Returns the command name. - * - * @return string The command name - * - * @api - */ - public function getName() - { - return $this->name; - } - - /** - * Sets the description for the command. - * - * @param string $description The description for the command - * - * @return Command The current instance - * - * @api - */ - public function setDescription($description) - { - $this->description = $description; - - return $this; - } - - /** - * Returns the description for the command. - * - * @return string The description for the command - * - * @api - */ - public function getDescription() - { - return $this->description; - } - - /** - * Sets the help for the command. - * - * @param string $help The help for the command - * - * @return Command The current instance - * - * @api - */ - public function setHelp($help) - { - $this->help = $help; - - return $this; - } - - /** - * Returns the help for the command. - * - * @return string The help for the command - * - * @api - */ - public function getHelp() - { - return $this->help; - } - - /** - * Returns the processed help for the command replacing the %command.name% and - * %command.full_name% patterns with the real values dynamically. - * - * @return string The processed help for the command - */ - public function getProcessedHelp() - { - $name = $this->name; - - $placeholders = array( - '%command.name%', - '%command.full_name%' - ); - $replacements = array( - $name, - $_SERVER['PHP_SELF'].' '.$name - ); - - return str_replace($placeholders, $replacements, $this->getHelp()); - } - - /** - * Sets the aliases for the command. - * - * @param array $aliases An array of aliases for the command - * - * @return Command The current instance - * - * @throws \InvalidArgumentException When an alias is invalid - * - * @api - */ - public function setAliases($aliases) - { - foreach ($aliases as $alias) { - $this->validateName($alias); - } - - $this->aliases = $aliases; - - return $this; - } - - /** - * Returns the aliases for the command. - * - * @return array An array of aliases for the command - * - * @api - */ - public function getAliases() - { - return $this->aliases; - } - - /** - * Returns the synopsis for the command. - * - * @return string The synopsis - */ - public function getSynopsis() - { - if (null === $this->synopsis) { - $this->synopsis = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis())); - } - - return $this->synopsis; - } - - /** - * Gets a helper instance by name. - * - * @param string $name The helper name - * - * @return mixed The helper value - * - * @throws \InvalidArgumentException if the helper is not defined - * - * @api - */ - public function getHelper($name) - { - return $this->helperSet->get($name); - } - - /** - * Returns a text representation of the command. - * - * @return string A string representing the command - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asText() - { - $descriptor = new TextDescriptor(); - $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); - $descriptor->describe($output, $this, array('raw_output' => true)); - - return $output->fetch(); - } - - /** - * Returns an XML representation of the command. - * - * @param Boolean $asDom Whether to return a DOM or an XML string - * - * @return string|\DOMDocument An XML string representing the command - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asXml($asDom = false) - { - $descriptor = new XmlDescriptor(); - - if ($asDom) { - return $descriptor->getCommandDocument($this); - } - - $output = new BufferedOutput(); - $descriptor->describe($output, $this); - - return $output->fetch(); - } - - /** - * Validates a command name. - * - * It must be non-empty and parts can optionally be separated by ":". - * - * @param string $name - * - * @throws \InvalidArgumentException When the name is invalid - */ - private function validateName($name) - { - if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) { - throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Helper\DescriptorHelper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * HelpCommand displays the help for a given command. - * - * @author Fabien Potencier - */ -class HelpCommand extends Command -{ - private $command; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->ignoreValidationErrors(); - - $this - ->setName('help') - ->setDefinition(array( - new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), - new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats', 'txt'), - new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), - )) - ->setDescription('Displays help for a command') - ->setHelp(<<%command.name% command displays help for a given command: - - php %command.full_name% list - -You can also output the help in other formats by using the --format option: - - php %command.full_name% --format=xml list - -To display the list of available commands, please use the list command. -EOF - ) - ; - } - - /** - * Sets the command - * - * @param Command $command The command to set - */ - public function setCommand(Command $command) - { - $this->command = $command; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - if (null === $this->command) { - $this->command = $this->getApplication()->find($input->getArgument('command_name')); - } - - if ($input->getOption('xml')) { - $input->setOption('format', 'xml'); - } - - $helper = new DescriptorHelper(); - $helper->describe($output, $this->command, array( - 'format' => $input->getOption('format'), - 'raw' => $input->getOption('raw'), - )); - - $this->command = null; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Helper\DescriptorHelper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputDefinition; - -/** - * ListCommand displays the list of all available commands for the application. - * - * @author Fabien Potencier - */ -class ListCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setName('list') - ->setDefinition($this->createDefinition()) - ->setDescription('Lists commands') - ->setHelp(<<%command.name% command lists all commands: - - php %command.full_name% - -You can also display the commands for a specific namespace: - - php %command.full_name% test - -You can also output the information in other formats by using the --format option: - - php %command.full_name% --format=xml - -It's also possible to get raw list of commands (useful for embedding command runner): - - php %command.full_name% --raw -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - public function getNativeDefinition() - { - return $this->createDefinition(); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - if ($input->getOption('xml')) { - $input->setOption('format', 'xml'); - } - - $helper = new DescriptorHelper(); - $helper->describe($output, $this->getApplication(), array( - 'format' => $input->getOption('format'), - 'raw_text' => $input->getOption('raw'), - 'namespace' => $input->getArgument('namespace'), - )); - } - - /** - * {@inheritdoc} - */ - private function createDefinition() - { - return new InputDefinition(array( - new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), - new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'), - new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats', 'txt'), - )); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author Jean-François Simon - */ -abstract class Descriptor implements DescriptorInterface -{ - /** - * @var OutputInterface - */ - private $output; - - /** - * {@inheritdoc} - */ - public function describe(OutputInterface $output, $object, array $options = array()) - { - $this->output = $output; - - switch (true) { - case $object instanceof InputArgument: - $this->describeInputArgument($object, $options); - break; - case $object instanceof InputOption: - $this->describeInputOption($object, $options); - break; - case $object instanceof InputDefinition: - $this->describeInputDefinition($object, $options); - break; - case $object instanceof Command: - $this->describeCommand($object, $options); - break; - case $object instanceof Application: - $this->describeApplication($object, $options); - break; - default: - throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object))); - } - } - - /** - * Writes content to output. - * - * @param string $content - * @param boolean $decorated - */ - protected function write($content, $decorated = false) - { - $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); - } - - /** - * Describes an InputArgument instance. - * - * @param InputArgument $argument - * @param array $options - * - * @return string|mixed - */ - abstract protected function describeInputArgument(InputArgument $argument, array $options = array()); - - /** - * Describes an InputOption instance. - * - * @param InputOption $option - * @param array $options - * - * @return string|mixed - */ - abstract protected function describeInputOption(InputOption $option, array $options = array()); - - /** - * Describes an InputDefinition instance. - * - * @param InputDefinition $definition - * @param array $options - * - * @return string|mixed - */ - abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array()); - - /** - * Describes a Command instance. - * - * @param Command $command - * @param array $options - * - * @return string|mixed - */ - abstract protected function describeCommand(Command $command, array $options = array()); - - /** - * Describes an Application instance. - * - * @param Application $application - * @param array $options - * - * @return string|mixed - */ - abstract protected function describeApplication(Application $application, array $options = array()); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Descriptor interface. - * - * @author Jean-François Simon - */ -interface DescriptorInterface -{ - /** - * Describes an InputArgument instance. - * - * @param OutputInterface $output - * @param object $object - * @param array $options - */ - public function describe(OutputInterface $output, $object, array $options = array()); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * Text descriptor. - * - * @author Jean-François Simon - */ -class TextDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) - { - if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) { - $default = sprintf(' (default: %s)', $this->formatDefaultValue($argument->getDefault())); - } else { - $default = ''; - } - - $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($argument->getName()); - - $this->writeText(sprintf(" %-${nameWidth}s %s%s", - $argument->getName(), - str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription()), - $default - ), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = array()) - { - if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) { - $default = sprintf(' (default: %s)', $this->formatDefaultValue($option->getDefault())); - } else { - $default = ''; - } - - $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($option->getName()); - $nameWithShortcutWidth = $nameWidth - strlen($option->getName()) - 2; - - $this->writeText(sprintf(" %s %-${nameWithShortcutWidth}s%s%s%s", - '--'.$option->getName(), - $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '', - str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $option->getDescription()), - $default, - $option->isArray() ? ' (multiple values allowed)' : '' - ), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) - { - $nameWidth = 0; - foreach ($definition->getOptions() as $option) { - $nameLength = strlen($option->getName()) + 2; - if ($option->getShortcut()) { - $nameLength += strlen($option->getShortcut()) + 3; - } - $nameWidth = max($nameWidth, $nameLength); - } - foreach ($definition->getArguments() as $argument) { - $nameWidth = max($nameWidth, strlen($argument->getName())); - } - ++$nameWidth; - - if ($definition->getArguments()) { - $this->writeText('Arguments:', $options); - $this->writeText("\n"); - foreach ($definition->getArguments() as $argument) { - $this->describeInputArgument($argument, array_merge($options, array('name_width' => $nameWidth))); - $this->writeText("\n"); - } - } - - if ($definition->getArguments() && $definition->getOptions()) { - $this->writeText("\n"); - } - - if ($definition->getOptions()) { - $this->writeText('Options:', $options); - $this->writeText("\n"); - foreach ($definition->getOptions() as $option) { - $this->describeInputOption($option, array_merge($options, array('name_width' => $nameWidth))); - $this->writeText("\n"); - } - } - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = array()) - { - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - - $this->writeText('Usage:', $options); - $this->writeText("\n"); - $this->writeText(' '.$command->getSynopsis(), $options); - $this->writeText("\n"); - - if (count($command->getAliases()) > 0) { - $this->writeText("\n"); - $this->writeText('Aliases: '.implode(', ', $command->getAliases()).'', $options); - } - - if ($definition = $command->getNativeDefinition()) { - $this->writeText("\n"); - $this->describeInputDefinition($definition, $options); - } - - $this->writeText("\n"); - - if ($help = $command->getProcessedHelp()) { - $this->writeText('Help:', $options); - $this->writeText("\n"); - $this->writeText(' '.str_replace("\n", "\n ", $help), $options); - $this->writeText("\n"); - } - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = array()) - { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; - $description = new ApplicationDescription($application, $describedNamespace); - - if (isset($options['raw_text']) && $options['raw_text']) { - $width = $this->getColumnWidth($description->getCommands()); - - foreach ($description->getCommands() as $command) { - $this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options); - $this->writeText("\n"); - } - } else { - $width = $this->getColumnWidth($description->getCommands()); - - $this->writeText($application->getHelp(), $options); - $this->writeText("\n\n"); - - if ($describedNamespace) { - $this->writeText(sprintf("Available commands for the \"%s\" namespace:", $describedNamespace), $options); - } else { - $this->writeText('Available commands:', $options); - } - - // add commands by namespace - foreach ($description->getNamespaces() as $namespace) { - if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { - $this->writeText("\n"); - $this->writeText(''.$namespace['id'].'', $options); - } - - foreach ($namespace['commands'] as $name) { - $this->writeText("\n"); - $this->writeText(sprintf(" %-${width}s %s", $name, $description->getCommand($name)->getDescription()), $options); - } - } - - $this->writeText("\n"); - } - } - - /** - * {@inheritdoc} - */ - private function writeText($content, array $options = array()) - { - $this->write( - isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, - isset($options['raw_output']) ? !$options['raw_output'] : true - ); - } - - /** - * Formats input option/argument default value. - * - * @param mixed $default - * - * @return string - */ - private function formatDefaultValue($default) - { - if (version_compare(PHP_VERSION, '5.4', '<')) { - return str_replace('\/', '/', json_encode($default)); - } - - return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); - } - - /** - * @param Command[] $commands - * - * @return int - */ - private function getColumnWidth(array $commands) - { - $width = 0; - foreach ($commands as $command) { - $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width; - } - - return $width + 2; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * XML descriptor. - * - * @author Jean-François Simon - */ -class XmlDescriptor extends Descriptor -{ - /** - * @param InputDefinition $definition - * - * @return \DOMDocument - */ - public function getInputDefinitionDocument(InputDefinition $definition) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($definitionXML = $dom->createElement('definition')); - - $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); - foreach ($definition->getArguments() as $argument) { - $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument)); - } - - $definitionXML->appendChild($optionsXML = $dom->createElement('options')); - foreach ($definition->getOptions() as $option) { - $this->appendDocument($optionsXML, $this->getInputOptionDocument($option)); - } - - return $dom; - } - - /** - * @param Command $command - * - * @return \DOMDocument - */ - public function getCommandDocument(Command $command) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($commandXML = $dom->createElement('command')); - - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - - $commandXML->setAttribute('id', $command->getName()); - $commandXML->setAttribute('name', $command->getName()); - - $commandXML->appendChild($usageXML = $dom->createElement('usage')); - $usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), ''))); - - $commandXML->appendChild($descriptionXML = $dom->createElement('description')); - $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); - - $commandXML->appendChild($helpXML = $dom->createElement('help')); - $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); - - $commandXML->appendChild($aliasesXML = $dom->createElement('aliases')); - foreach ($command->getAliases() as $alias) { - $aliasesXML->appendChild($aliasXML = $dom->createElement('alias')); - $aliasXML->appendChild($dom->createTextNode($alias)); - } - - $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition()); - $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); - - return $dom; - } - - /** - * @param Application $application - * @param string|null $namespace - * - * @return \DOMDocument - */ - public function getApplicationDocument(Application $application, $namespace = null) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($rootXml = $dom->createElement('symfony')); - - if ($application->getName() !== 'UNKNOWN') { - $rootXml->setAttribute('name', $application->getName()); - if ($application->getVersion() !== 'UNKNOWN') { - $rootXml->setAttribute('version', $application->getVersion()); - } - } - - $rootXml->appendChild($commandsXML = $dom->createElement('commands')); - - $description = new ApplicationDescription($application, $namespace); - - if ($namespace) { - $commandsXML->setAttribute('namespace', $namespace); - } - - foreach ($description->getCommands() as $command) { - $this->appendDocument($commandsXML, $this->getCommandDocument($command)); - } - - if (!$namespace) { - $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); - - foreach ($description->getNamespaces() as $namespaceDescription) { - $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); - $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']); - - foreach ($namespaceDescription['commands'] as $name) { - $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); - $commandXML->appendChild($dom->createTextNode($name)); - } - } - } - - return $dom; - } - - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) - { - $this->writeDocument($this->getInputArgumentDocument($argument)); - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = array()) - { - $this->writeDocument($this->getInputOptionDocument($option)); - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) - { - $this->writeDocument($this->getInputDefinitionDocument($definition)); - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = array()) - { - $this->writeDocument($this->getCommandDocument($command)); - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = array()) - { - $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null)); - } - - /** - * Appends document children to parent node. - * - * @param \DOMNode $parentNode - * @param \DOMNode $importedParent - */ - private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) - { - foreach ($importedParent->childNodes as $childNode) { - $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); - } - } - - /** - * Writes DOM document. - * - * @param \DOMDocument $dom - * - * @return \DOMDocument|string - */ - private function writeDocument(\DOMDocument $dom) - { - $dom->formatOutput = true; - $this->write($dom->saveXML()); - } - - /** - * @param InputArgument $argument - * - * @return \DOMDocument - */ - private function getInputArgumentDocument(InputArgument $argument) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - - $dom->appendChild($objectXML = $dom->createElement('argument')); - $objectXML->setAttribute('name', $argument->getName()); - $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); - $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); - $objectXML->appendChild($descriptionXML = $dom->createElement('description')); - $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); - - $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); - $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array())); - foreach ($defaults as $default) { - $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); - $defaultXML->appendChild($dom->createTextNode($default)); - } - - return $dom; - } - - /** - * @param InputOption $option - * - * @return \DOMDocument - */ - private function getInputOptionDocument(InputOption $option) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - - $dom->appendChild($objectXML = $dom->createElement('option')); - $objectXML->setAttribute('name', '--'.$option->getName()); - $pos = strpos($option->getShortcut(), '|'); - if (false !== $pos) { - $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); - $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut()))); - } else { - $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); - } - $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); - $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); - $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); - $objectXML->appendChild($descriptionXML = $dom->createElement('description')); - $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); - - if ($option->acceptValue()) { - $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array())); - $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); - - if (!empty($defaults)) { - foreach ($defaults as $default) { - $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); - $defaultXML->appendChild($dom->createTextNode($default)); - } - } - } - - return $dom; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; - -/** - * @author Jean-François Simon - */ -class ApplicationDescription -{ - const GLOBAL_NAMESPACE = '_global'; - - /** - * @var Application - */ - private $application; - - /** - * @var null|string - */ - private $namespace; - - /** - * @var array - */ - private $namespaces; - - /** - * @var Command[] - */ - private $commands; - - /** - * @var Command[] - */ - private $aliases; - - /** - * Constructor. - * - * @param Application $application - * @param string|null $namespace - */ - public function __construct(Application $application, $namespace = null) - { - $this->application = $application; - $this->namespace = $namespace; - } - - /** - * @return array - */ - public function getNamespaces() - { - if (null === $this->namespaces) { - $this->inspectApplication(); - } - - return $this->namespaces; - } - - /** - * @return Command[] - */ - public function getCommands() - { - if (null === $this->commands) { - $this->inspectApplication(); - } - - return $this->commands; - } - - /** - * @param string $name - * - * @return Command - * - * @throws \InvalidArgumentException - */ - public function getCommand($name) - { - if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { - throw new \InvalidArgumentException(sprintf('Command %s does not exist.', $name)); - } - - return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; - } - - private function inspectApplication() - { - $this->commands = array(); - $this->namespaces = array(); - - $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null); - foreach ($this->sortCommands($all) as $namespace => $commands) { - $names = array(); - - /** @var Command $command */ - foreach ($commands as $name => $command) { - if (!$command->getName()) { - continue; - } - - if ($command->getName() === $name) { - $this->commands[$name] = $command; - } else { - $this->aliases[$name] = $command; - } - - $names[] = $name; - } - - $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names); - } - } - - /** - * @param array $commands - * - * @return array - */ - private function sortCommands(array $commands) - { - $namespacedCommands = array(); - foreach ($commands as $name => $command) { - $key = $this->application->extractNamespace($name, 1); - if (!$key) { - $key = '_global'; - } - - $namespacedCommands[$key][$name] = $command; - } - ksort($namespacedCommands); - - foreach ($namespacedCommands as &$commands) { - ksort($commands); - } - - return $namespacedCommands; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * JSON descriptor. - * - * @author Jean-François Simon - */ -class JsonDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) - { - $this->writeData($this->getInputArgumentData($argument), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = array()) - { - $this->writeData($this->getInputOptionData($option), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) - { - $this->writeData($this->getInputDefinitionData($definition), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = array()) - { - $this->writeData($this->getCommandData($command), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = array()) - { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; - $description = new ApplicationDescription($application, $describedNamespace); - $commands = array(); - - foreach ($description->getCommands() as $command) { - $commands[] = $this->getCommandData($command); - } - - $data = $describedNamespace - ? array('commands' => $commands, 'namespace' => $describedNamespace) - : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces())); - - $this->writeData($data, $options); - } - - /** - * Writes data as json. - * - * @param array $data - * @param array $options - * - * @return array|string - */ - private function writeData(array $data, array $options) - { - $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0)); - } - - /** - * @param InputArgument $argument - * - * @return array - */ - private function getInputArgumentData(InputArgument $argument) - { - return array( - 'name' => $argument->getName(), - 'is_required' => $argument->isRequired(), - 'is_array' => $argument->isArray(), - 'description' => $argument->getDescription(), - 'default' => $argument->getDefault(), - ); - } - - /** - * @param InputOption $option - * - * @return array - */ - private function getInputOptionData(InputOption $option) - { - return array( - 'name' => '--'.$option->getName(), - 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '', - 'accept_value' => $option->acceptValue(), - 'is_value_required' => $option->isValueRequired(), - 'is_multiple' => $option->isArray(), - 'description' => $option->getDescription(), - 'default' => $option->getDefault(), - ); - } - - /** - * @param InputDefinition $definition - * - * @return array - */ - private function getInputDefinitionData(InputDefinition $definition) - { - $inputArguments = array(); - foreach ($definition->getArguments() as $name => $argument) { - $inputArguments[$name] = $this->getInputArgumentData($argument); - } - - $inputOptions = array(); - foreach ($definition->getOptions() as $name => $option) { - $inputOptions[$name] = $this->getInputOptionData($option); - } - - return array('arguments' => $inputArguments, 'options' => $inputOptions); - } - - /** - * @param Command $command - * - * @return array - */ - private function getCommandData(Command $command) - { - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - - return array( - 'name' => $command->getName(), - 'usage' => $command->getSynopsis(), - 'description' => $command->getDescription(), - 'help' => $command->getProcessedHelp(), - 'aliases' => $command->getAliases(), - 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()), - ); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * Markdown descriptor. - * - * @author Jean-François Simon - */ -class MarkdownDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) - { - $this->write( - '**'.$argument->getName().':**'."\n\n" - .'* Name: '.($argument->getName() ?: '')."\n" - .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" - .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" - .'* Description: '.($argument->getDescription() ?: '')."\n" - .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' - ); - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = array()) - { - $this->write( - '**'.$option->getName().':**'."\n\n" - .'* Name: `--'.$option->getName().'`'."\n" - .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '')."\n" - .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" - .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" - .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" - .'* Description: '.($option->getDescription() ?: '')."\n" - .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' - ); - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) - { - if ($showArguments = count($definition->getArguments()) > 0) { - $this->write('### Arguments:'); - foreach ($definition->getArguments() as $argument) { - $this->write("\n\n"); - $this->write($this->describeInputArgument($argument)); - } - } - - if (count($definition->getOptions()) > 0) { - if ($showArguments) { - $this->write("\n\n"); - } - - $this->write('### Options:'); - foreach ($definition->getOptions() as $option) { - $this->write("\n\n"); - $this->write($this->describeInputOption($option)); - } - } - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = array()) - { - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - - $this->write( - $command->getName()."\n" - .str_repeat('-', strlen($command->getName()))."\n\n" - .'* Description: '.($command->getDescription() ?: '')."\n" - .'* Usage: `'.$command->getSynopsis().'`'."\n" - .'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : '') - ); - - if ($help = $command->getProcessedHelp()) { - $this->write("\n\n"); - $this->write($help); - } - - if ($definition = $command->getNativeDefinition()) { - $this->write("\n\n"); - $this->describeInputDefinition($command->getNativeDefinition()); - } - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = array()) - { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; - $description = new ApplicationDescription($application, $describedNamespace); - - $this->write($application->getName()."\n".str_repeat('=', strlen($application->getName()))); - - foreach ($description->getNamespaces() as $namespace) { - if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { - $this->write("\n\n"); - $this->write('**'.$namespace['id'].':**'); - } - - $this->write("\n\n"); - $this->write(implode("\n", array_map(function ($commandName) { - return '* '.$commandName; - } , $namespace['commands']))); - } - - foreach ($description->getCommands() as $command) { - $this->write("\n\n"); - $this->write($this->describeCommand($command)); - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputAwareInterface; -use Symfony\Component\Console\Output\BufferedOutput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Command\HelpCommand; -use Symfony\Component\Console\Command\ListCommand; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Helper\FormatterHelper; -use Symfony\Component\Console\Helper\DialogHelper; -use Symfony\Component\Console\Helper\ProgressHelper; -use Symfony\Component\Console\Helper\TableHelper; -use Symfony\Component\Console\Event\ConsoleCommandEvent; -use Symfony\Component\Console\Event\ConsoleExceptionEvent; -use Symfony\Component\Console\Event\ConsoleTerminateEvent; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; - -/** - * An Application is the container for a collection of commands. - * - * It is the main entry point of a Console application. - * - * This class is optimized for a standard CLI environment. - * - * Usage: - * - * $app = new Application('myapp', '1.0 (stable)'); - * $app->add(new SimpleCommand()); - * $app->run(); - * - * @author Fabien Potencier - * - * @api - */ -class Application -{ - private $commands = array(); - private $wantHelps = false; - private $runningCommand; - private $name; - private $version; - private $catchExceptions = true; - private $autoExit = true; - private $definition; - private $helperSet; - private $dispatcher; - private $terminalDimensions; - - /** - * Constructor. - * - * @param string $name The name of the application - * @param string $version The version of the application - * - * @api - */ - public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') - { - $this->name = $name; - $this->version = $version; - $this->helperSet = $this->getDefaultHelperSet(); - $this->definition = $this->getDefaultInputDefinition(); - - foreach ($this->getDefaultCommands() as $command) { - $this->add($command); - } - } - - public function setDispatcher(EventDispatcherInterface $dispatcher) - { - $this->dispatcher = $dispatcher; - } - - /** - * Runs the current application. - * - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * - * @return integer 0 if everything went fine, or an error code - * - * @throws \Exception When doRun returns Exception - * - * @api - */ - public function run(InputInterface $input = null, OutputInterface $output = null) - { - if (null === $input) { - $input = new ArgvInput(); - } - - if (null === $output) { - $output = new ConsoleOutput(); - } - - $this->configureIO($input, $output); - - try { - $exitCode = $this->doRun($input, $output); - } catch (\Exception $e) { - if (!$this->catchExceptions) { - throw $e; - } - - if ($output instanceof ConsoleOutputInterface) { - $this->renderException($e, $output->getErrorOutput()); - } else { - $this->renderException($e, $output); - } - - $exitCode = $e->getCode(); - if (is_numeric($exitCode)) { - $exitCode = (int) $exitCode; - if (0 === $exitCode) { - $exitCode = 1; - } - } else { - $exitCode = 1; - } - } - - if ($this->autoExit) { - if ($exitCode > 255) { - $exitCode = 255; - } - // @codeCoverageIgnoreStart - exit($exitCode); - // @codeCoverageIgnoreEnd - } - - return $exitCode; - } - - /** - * Runs the current application. - * - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * - * @return integer 0 if everything went fine, or an error code - */ - public function doRun(InputInterface $input, OutputInterface $output) - { - if (true === $input->hasParameterOption(array('--version', '-V'))) { - $output->writeln($this->getLongVersion()); - - return 0; - } - - $name = $this->getCommandName($input); - if (true === $input->hasParameterOption(array('--help', '-h'))) { - if (!$name) { - $name = 'help'; - $input = new ArrayInput(array('command' => 'help')); - } else { - $this->wantHelps = true; - } - } - - if (!$name) { - $name = 'list'; - $input = new ArrayInput(array('command' => 'list')); - } - - // the command name MUST be the first element of the input - $command = $this->find($name); - - $this->runningCommand = $command; - $exitCode = $this->doRunCommand($command, $input, $output); - $this->runningCommand = null; - - return $exitCode; - } - - /** - * Set a helper set to be used with the command. - * - * @param HelperSet $helperSet The helper set - * - * @api - */ - public function setHelperSet(HelperSet $helperSet) - { - $this->helperSet = $helperSet; - } - - /** - * Get the helper set associated with the command. - * - * @return HelperSet The HelperSet instance associated with this command - * - * @api - */ - public function getHelperSet() - { - return $this->helperSet; - } - - /** - * Set an input definition set to be used with this application - * - * @param InputDefinition $definition The input definition - * - * @api - */ - public function setDefinition(InputDefinition $definition) - { - $this->definition = $definition; - } - - /** - * Gets the InputDefinition related to this Application. - * - * @return InputDefinition The InputDefinition instance - */ - public function getDefinition() - { - return $this->definition; - } - - /** - * Gets the help message. - * - * @return string A help message. - */ - public function getHelp() - { - $messages = array( - $this->getLongVersion(), - '', - 'Usage:', - ' [options] command [arguments]', - '', - 'Options:', - ); - - foreach ($this->getDefinition()->getOptions() as $option) { - $messages[] = sprintf(' %-29s %s %s', - '--'.$option->getName().'', - $option->getShortcut() ? '-'.$option->getShortcut().'' : ' ', - $option->getDescription() - ); - } - - return implode(PHP_EOL, $messages); - } - - /** - * Sets whether to catch exceptions or not during commands execution. - * - * @param Boolean $boolean Whether to catch exceptions or not during commands execution - * - * @api - */ - public function setCatchExceptions($boolean) - { - $this->catchExceptions = (Boolean) $boolean; - } - - /** - * Sets whether to automatically exit after a command execution or not. - * - * @param Boolean $boolean Whether to automatically exit after a command execution or not - * - * @api - */ - public function setAutoExit($boolean) - { - $this->autoExit = (Boolean) $boolean; - } - - /** - * Gets the name of the application. - * - * @return string The application name - * - * @api - */ - public function getName() - { - return $this->name; - } - - /** - * Sets the application name. - * - * @param string $name The application name - * - * @api - */ - public function setName($name) - { - $this->name = $name; - } - - /** - * Gets the application version. - * - * @return string The application version - * - * @api - */ - public function getVersion() - { - return $this->version; - } - - /** - * Sets the application version. - * - * @param string $version The application version - * - * @api - */ - public function setVersion($version) - { - $this->version = $version; - } - - /** - * Returns the long version of the application. - * - * @return string The long application version - * - * @api - */ - public function getLongVersion() - { - if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) { - return sprintf('%s version %s', $this->getName(), $this->getVersion()); - } - - return 'Console Tool'; - } - - /** - * Registers a new command. - * - * @param string $name The command name - * - * @return Command The newly created command - * - * @api - */ - public function register($name) - { - return $this->add(new Command($name)); - } - - /** - * Adds an array of command objects. - * - * @param Command[] $commands An array of commands - * - * @api - */ - public function addCommands(array $commands) - { - foreach ($commands as $command) { - $this->add($command); - } - } - - /** - * Adds a command object. - * - * If a command with the same name already exists, it will be overridden. - * - * @param Command $command A Command object - * - * @return Command The registered command - * - * @api - */ - public function add(Command $command) - { - $command->setApplication($this); - - if (!$command->isEnabled()) { - $command->setApplication(null); - - return; - } - - if (null === $command->getDefinition()) { - throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command))); - } - - $this->commands[$command->getName()] = $command; - - foreach ($command->getAliases() as $alias) { - $this->commands[$alias] = $command; - } - - return $command; - } - - /** - * Returns a registered command by name or alias. - * - * @param string $name The command name or alias - * - * @return Command A Command object - * - * @throws \InvalidArgumentException When command name given does not exist - * - * @api - */ - public function get($name) - { - if (!isset($this->commands[$name])) { - throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name)); - } - - $command = $this->commands[$name]; - - if ($this->wantHelps) { - $this->wantHelps = false; - - $helpCommand = $this->get('help'); - $helpCommand->setCommand($command); - - return $helpCommand; - } - - return $command; - } - - /** - * Returns true if the command exists, false otherwise. - * - * @param string $name The command name or alias - * - * @return Boolean true if the command exists, false otherwise - * - * @api - */ - public function has($name) - { - return isset($this->commands[$name]); - } - - /** - * Returns an array of all unique namespaces used by currently registered commands. - * - * It does not returns the global namespace which always exists. - * - * @return array An array of namespaces - */ - public function getNamespaces() - { - $namespaces = array(); - foreach ($this->commands as $command) { - $namespaces[] = $this->extractNamespace($command->getName()); - - foreach ($command->getAliases() as $alias) { - $namespaces[] = $this->extractNamespace($alias); - } - } - - return array_values(array_unique(array_filter($namespaces))); - } - - /** - * Finds a registered namespace by a name or an abbreviation. - * - * @param string $namespace A namespace or abbreviation to search for - * - * @return string A registered namespace - * - * @throws \InvalidArgumentException When namespace is incorrect or ambiguous - */ - public function findNamespace($namespace) - { - $allNamespaces = $this->getNamespaces(); - $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace); - $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces); - - if (empty($namespaces)) { - $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); - - if ($alternatives = $this->findAlternatives($namespace, $allNamespaces, array())) { - if (1 == count($alternatives)) { - $message .= "\n\nDid you mean this?\n "; - } else { - $message .= "\n\nDid you mean one of these?\n "; - } - - $message .= implode("\n ", $alternatives); - } - - throw new \InvalidArgumentException($message); - } - - $exact = in_array($namespace, $namespaces, true); - if (count($namespaces) > 1 && !$exact) { - throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces)))); - } - - return $exact ? $namespace : reset($namespaces); - } - - /** - * Finds a command by name or alias. - * - * Contrary to get, this command tries to find the best - * match if you give it an abbreviation of a name or alias. - * - * @param string $name A command name or a command alias - * - * @return Command A Command instance - * - * @throws \InvalidArgumentException When command name is incorrect or ambiguous - * - * @api - */ - public function find($name) - { - $allCommands = array_keys($this->commands); - $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); - $commands = preg_grep('{^'.$expr.'}', $allCommands); - - if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) { - if (false !== $pos = strrpos($name, ':')) { - // check if a namespace exists and contains commands - $this->findNamespace(substr($name, 0, $pos)); - } - - $message = sprintf('Command "%s" is not defined.', $name); - - if ($alternatives = $this->findAlternatives($name, $allCommands, array())) { - if (1 == count($alternatives)) { - $message .= "\n\nDid you mean this?\n "; - } else { - $message .= "\n\nDid you mean one of these?\n "; - } - $message .= implode("\n ", $alternatives); - } - - throw new \InvalidArgumentException($message); - } - - $exact = in_array($name, $commands, true); - if (count($commands) > 1 && !$exact) { - $suggestions = $this->getAbbreviationSuggestions(array_values($commands)); - - throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions)); - } - - return $this->get($exact ? $name : reset($commands)); - } - - /** - * Gets the commands (registered in the given namespace if provided). - * - * The array keys are the full names and the values the command instances. - * - * @param string $namespace A namespace name - * - * @return Command[] An array of Command instances - * - * @api - */ - public function all($namespace = null) - { - if (null === $namespace) { - return $this->commands; - } - - $commands = array(); - foreach ($this->commands as $name => $command) { - if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { - $commands[$name] = $command; - } - } - - return $commands; - } - - /** - * Returns an array of possible abbreviations given a set of names. - * - * @param array $names An array of names - * - * @return array An array of abbreviations - */ - public static function getAbbreviations($names) - { - $abbrevs = array(); - foreach ($names as $name) { - for ($len = strlen($name); $len > 0; --$len) { - $abbrev = substr($name, 0, $len); - $abbrevs[$abbrev][] = $name; - } - } - - return $abbrevs; - } - - /** - * Returns a text representation of the Application. - * - * @param string $namespace An optional namespace name - * @param boolean $raw Whether to return raw command list - * - * @return string A string representing the Application - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asText($namespace = null, $raw = false) - { - $descriptor = new TextDescriptor(); - $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw); - $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true)); - - return $output->fetch(); - } - - /** - * Returns an XML representation of the Application. - * - * @param string $namespace An optional namespace name - * @param Boolean $asDom Whether to return a DOM or an XML string - * - * @return string|\DOMDocument An XML string representing the Application - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asXml($namespace = null, $asDom = false) - { - $descriptor = new XmlDescriptor(); - - if ($asDom) { - return $descriptor->getApplicationDocument($this, $namespace); - } - - $output = new BufferedOutput(); - $descriptor->describe($output, $this, array('namespace' => $namespace)); - - return $output->fetch(); - } - - /** - * Renders a caught exception. - * - * @param \Exception $e An exception instance - * @param OutputInterface $output An OutputInterface instance - */ - public function renderException($e, $output) - { - $strlen = function ($string) { - if (!function_exists('mb_strlen')) { - return strlen($string); - } - - if (false === $encoding = mb_detect_encoding($string)) { - return strlen($string); - } - - return mb_strlen($string, $encoding); - }; - - do { - $title = sprintf(' [%s] ', get_class($e)); - $len = $strlen($title); - $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX; - $formatter = $output->getFormatter(); - $lines = array(); - foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) { - foreach (str_split($line, $width - 4) as $line) { - // pre-format lines to get the right string length - $lineLength = $strlen(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4; - $lines[] = array($line, $lineLength); - - $len = max($lineLength, $len); - } - } - - $messages = array('', ''); - $messages[] = $emptyLine = $formatter->format(sprintf('%s', str_repeat(' ', $len))); - $messages[] = $formatter->format(sprintf('%s%s', $title, str_repeat(' ', max(0, $len - $strlen($title))))); - foreach ($lines as $line) { - $messages[] = $formatter->format(sprintf(' %s %s', $line[0], str_repeat(' ', $len - $line[1]))); - } - $messages[] = $emptyLine; - $messages[] = ''; - $messages[] = ''; - - $output->writeln($messages, OutputInterface::OUTPUT_RAW); - - if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $output->writeln('Exception trace:'); - - // exception related properties - $trace = $e->getTrace(); - array_unshift($trace, array( - 'function' => '', - 'file' => $e->getFile() != null ? $e->getFile() : 'n/a', - 'line' => $e->getLine() != null ? $e->getLine() : 'n/a', - 'args' => array(), - )); - - for ($i = 0, $count = count($trace); $i < $count; $i++) { - $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; - $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; - $function = $trace[$i]['function']; - $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; - $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; - - $output->writeln(sprintf(' %s%s%s() at %s:%s', $class, $type, $function, $file, $line)); - } - - $output->writeln(""); - $output->writeln(""); - } - } while ($e = $e->getPrevious()); - - if (null !== $this->runningCommand) { - $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName()))); - $output->writeln(""); - $output->writeln(""); - } - } - - /** - * Tries to figure out the terminal width in which this application runs - * - * @return int|null - */ - protected function getTerminalWidth() - { - $dimensions = $this->getTerminalDimensions(); - - return $dimensions[0]; - } - - /** - * Tries to figure out the terminal height in which this application runs - * - * @return int|null - */ - protected function getTerminalHeight() - { - $dimensions = $this->getTerminalDimensions(); - - return $dimensions[1]; - } - - /** - * Tries to figure out the terminal dimensions based on the current environment - * - * @return array Array containing width and height - */ - public function getTerminalDimensions() - { - if ($this->terminalDimensions) { - return $this->terminalDimensions; - } - - if (defined('PHP_WINDOWS_VERSION_BUILD')) { - // extract [w, H] from "wxh (WxH)" - if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) { - return array((int) $matches[1], (int) $matches[2]); - } - // extract [w, h] from "wxh" - if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) { - return array((int) $matches[1], (int) $matches[2]); - } - } - - if ($sttyString = $this->getSttyColumns()) { - // extract [w, h] from "rows h; columns w;" - if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { - return array((int) $matches[2], (int) $matches[1]); - } - // extract [w, h] from "; h rows; w columns" - if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { - return array((int) $matches[2], (int) $matches[1]); - } - } - - return array(null, null); - } - - /** - * Sets terminal dimensions. - * - * Can be useful to force terminal dimensions for functional tests. - * - * @param integer $width The width - * @param integer $height The height - * - * @return Application The current application - */ - public function setTerminalDimensions($width, $height) - { - $this->terminalDimensions = array($width, $height); - - return $this; - } - - /** - * Configures the input and output instances based on the user arguments and options. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - */ - protected function configureIO(InputInterface $input, OutputInterface $output) - { - if (true === $input->hasParameterOption(array('--ansi'))) { - $output->setDecorated(true); - } elseif (true === $input->hasParameterOption(array('--no-ansi'))) { - $output->setDecorated(false); - } - - if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) { - $input->setInteractive(false); - } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('dialog')) { - $inputStream = $this->getHelperSet()->get('dialog')->getInputStream(); - if (!@posix_isatty($inputStream)) { - $input->setInteractive(false); - } - } - - if (true === $input->hasParameterOption(array('--quiet', '-q'))) { - $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); - } else { - if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) { - $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); - } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) { - $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); - } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) { - $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); - } - } - } - - /** - * Runs the current command. - * - * If an event dispatcher has been attached to the application, - * events are also dispatched during the life-cycle of the command. - * - * @param Command $command A Command instance - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * - * @return integer 0 if everything went fine, or an error code - */ - protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) - { - foreach ($command->getHelperSet() as $helper) { - if ($helper instanceof InputAwareInterface) { - $helper->setInput($input); - } - } - - if (null === $this->dispatcher) { - return $command->run($input, $output); - } - - $event = new ConsoleCommandEvent($command, $input, $output); - $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event); - - try { - $exitCode = $command->run($input, $output); - } catch (\Exception $e) { - $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode()); - $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); - - $event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode()); - $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); - - throw $event->getException(); - } - - $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); - $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); - - return $event->getExitCode(); - } - - /** - * Gets the name of the command based on input. - * - * @param InputInterface $input The input interface - * - * @return string The command name - */ - protected function getCommandName(InputInterface $input) - { - return $input->getFirstArgument(); - } - - /** - * Gets the default input definition. - * - * @return InputDefinition An InputDefinition instance - */ - protected function getDefaultInputDefinition() - { - return new InputDefinition(array( - new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), - - new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message.'), - new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message.'), - new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), - new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version.'), - new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output.'), - new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output.'), - new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question.'), - )); - } - - /** - * Gets the default commands that should always be available. - * - * @return Command[] An array of default Command instances - */ - protected function getDefaultCommands() - { - return array(new HelpCommand(), new ListCommand()); - } - - /** - * Gets the default helper set with the helpers that should always be available. - * - * @return HelperSet A HelperSet instance - */ - protected function getDefaultHelperSet() - { - return new HelperSet(array( - new FormatterHelper(), - new DialogHelper(), - new ProgressHelper(), - new TableHelper(), - )); - } - - /** - * Runs and parses stty -a if it's available, suppressing any error output - * - * @return string - */ - private function getSttyColumns() - { - if (!function_exists('proc_open')) { - return; - } - - $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); - $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); - if (is_resource($process)) { - $info = stream_get_contents($pipes[1]); - fclose($pipes[1]); - fclose($pipes[2]); - proc_close($process); - - return $info; - } - } - - /** - * Runs and parses mode CON if it's available, suppressing any error output - * - * @return string x or null if it could not be parsed - */ - private function getConsoleMode() - { - if (!function_exists('proc_open')) { - return; - } - - $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); - $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); - if (is_resource($process)) { - $info = stream_get_contents($pipes[1]); - fclose($pipes[1]); - fclose($pipes[2]); - proc_close($process); - - if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { - return $matches[2].'x'.$matches[1]; - } - } - } - - /** - * Returns abbreviated suggestions in string format. - * - * @param array $abbrevs Abbreviated suggestions to convert - * - * @return string A formatted string of abbreviated suggestions - */ - private function getAbbreviationSuggestions($abbrevs) - { - return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : ''); - } - - /** - * Returns the namespace part of the command name. - * - * This method is not part of public API and should not be used directly. - * - * @param string $name The full name of the command - * @param string $limit The maximum number of parts of the namespace - * - * @return string The namespace of the command - */ - public function extractNamespace($name, $limit = null) - { - $parts = explode(':', $name); - array_pop($parts); - - return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit)); - } - - /** - * Finds alternative of $name among $collection - * - * @param string $name The string - * @param array|Traversable $collection The collection - * - * @return array A sorted array of similar string - */ - private function findAlternatives($name, $collection) - { - $threshold = 1e3; - $alternatives = array(); - - $collectionParts = array(); - foreach ($collection as $item) { - $collectionParts[$item] = explode(':', $item); - } - - foreach (explode(':', $name) as $i => $subname) { - foreach ($collectionParts as $collectionName => $parts) { - $exists = isset($alternatives[$collectionName]); - if (!isset($parts[$i]) && $exists) { - $alternatives[$collectionName] += $threshold; - continue; - } elseif (!isset($parts[$i])) { - continue; - } - - $lev = levenshtein($subname, $parts[$i]); - if ($lev <= strlen($subname) / 3 || false !== strpos($parts[$i], $subname)) { - $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; - } elseif ($exists) { - $alternatives[$collectionName] += $threshold; - } - } - } - - foreach ($collection as $item) { - $lev = levenshtein($name, $item); - if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { - $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; - } - } - - $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2*$threshold; }); - asort($alternatives); - - return array_keys($alternatives); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -/** - * Contains all events dispatched by an Application. - * - * @author Francesco Levorato - */ -final class ConsoleEvents -{ - /** - * The COMMAND event allows you to attach listeners before any command is - * executed by the console. It also allows you to modify the command, input and output - * before they are handled to the command. - * - * The event listener method receives a Symfony\Component\Console\Event\ConsoleCommandEvent - * instance. - * - * @var string - */ - const COMMAND = 'console.command'; - - /** - * The TERMINATE event allows you to attach listeners after a command is - * executed by the console. - * - * The event listener method receives a Symfony\Component\Console\Event\ConsoleTerminateEvent - * instance. - * - * @var string - */ - const TERMINATE = 'console.terminate'; - - /** - * The EXCEPTION event occurs when an uncaught exception appears. - * - * This event allows you to deal with the exception or - * to modify the thrown exception. The event listener method receives - * a Symfony\Component\Console\Event\ConsoleExceptionEvent - * instance. - * - * @var string - */ - const EXCEPTION = 'console.exception'; -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -/** - * Helper is the base class for all helper classes. - * - * @author Fabien Potencier - */ -abstract class Helper implements HelperInterface -{ - protected $helperSet = null; - - /** - * Sets the helper set associated with this helper. - * - * @param HelperSet $helperSet A HelperSet instance - */ - public function setHelperSet(HelperSet $helperSet = null) - { - $this->helperSet = $helperSet; - } - - /** - * Gets the helper set associated with this helper. - * - * @return HelperSet A HelperSet instance - */ - public function getHelperSet() - { - return $this->helperSet; - } - - /** - * Returns the length of a string, using mb_strlen if it is available. - * - * @param string $string The string to check its length - * - * @return integer The length of the string - */ - protected function strlen($string) - { - if (!function_exists('mb_strlen')) { - return strlen($string); - } - - if (false === $encoding = mb_detect_encoding($string)) { - return strlen($string); - } - - return mb_strlen($string, $encoding); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Command\Command; - -/** - * HelperSet represents a set of helpers to be used with a command. - * - * @author Fabien Potencier - */ -class HelperSet implements \IteratorAggregate -{ - private $helpers = array(); - private $command; - - /** - * Constructor. - * - * @param Helper[] $helpers An array of helper. - */ - public function __construct(array $helpers = array()) - { - foreach ($helpers as $alias => $helper) { - $this->set($helper, is_int($alias) ? null : $alias); - } - } - - /** - * Sets a helper. - * - * @param HelperInterface $helper The helper instance - * @param string $alias An alias - */ - public function set(HelperInterface $helper, $alias = null) - { - $this->helpers[$helper->getName()] = $helper; - if (null !== $alias) { - $this->helpers[$alias] = $helper; - } - - $helper->setHelperSet($this); - } - - /** - * Returns true if the helper if defined. - * - * @param string $name The helper name - * - * @return Boolean true if the helper is defined, false otherwise - */ - public function has($name) - { - return isset($this->helpers[$name]); - } - - /** - * Gets a helper value. - * - * @param string $name The helper name - * - * @return HelperInterface The helper instance - * - * @throws \InvalidArgumentException if the helper is not defined - */ - public function get($name) - { - if (!$this->has($name)) { - throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); - } - - return $this->helpers[$name]; - } - - /** - * Sets the command associated with this helper set. - * - * @param Command $command A Command instance - */ - public function setCommand(Command $command = null) - { - $this->command = $command; - } - - /** - * Gets the command associated with this helper set. - * - * @return Command A Command instance - */ - public function getCommand() - { - return $this->command; - } - - public function getIterator() - { - return new \ArrayIterator($this->helpers); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputAwareInterface; - -/** - * An implementation of InputAwareInterface for Helpers. - * - * @author Wouter J - */ -abstract class InputAwareHelper extends Helper implements InputAwareInterface -{ - protected $input; - - /** - * {@inheritDoc} - */ - public function setInput(InputInterface $input) - { - $this->input = $input; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Output\OutputInterface; -use InvalidArgumentException; - -/** - * Provides helpers to display table output. - * - * @author Саша Стаменковић - */ -class TableHelper extends Helper -{ - const LAYOUT_DEFAULT = 0; - const LAYOUT_BORDERLESS = 1; - const LAYOUT_COMPACT = 2; - - /** - * Table headers. - * - * @var array - */ - private $headers = array(); - - /** - * Table rows. - * - * @var array - */ - private $rows = array(); - - // Rendering options - private $paddingChar; - private $horizontalBorderChar; - private $verticalBorderChar; - private $crossingChar; - private $cellHeaderFormat; - private $cellRowFormat; - private $cellRowContentFormat; - private $borderFormat; - private $padType; - - /** - * Column widths cache. - * - * @var array - */ - private $columnWidths = array(); - - /** - * Number of columns cache. - * - * @var array - */ - private $numberOfColumns; - - /** - * @var OutputInterface - */ - private $output; - - public function __construct() - { - $this->setLayout(self::LAYOUT_DEFAULT); - } - - /** - * Sets table layout type. - * - * @param int $layout self::LAYOUT_* - * - * @return TableHelper - */ - public function setLayout($layout) - { - switch ($layout) { - case self::LAYOUT_BORDERLESS: - $this - ->setPaddingChar(' ') - ->setHorizontalBorderChar('=') - ->setVerticalBorderChar(' ') - ->setCrossingChar(' ') - ->setCellHeaderFormat('%s') - ->setCellRowFormat('%s') - ->setCellRowContentFormat(' %s ') - ->setBorderFormat('%s') - ->setPadType(STR_PAD_RIGHT) - ; - break; - - case self::LAYOUT_COMPACT: - $this - ->setPaddingChar(' ') - ->setHorizontalBorderChar('') - ->setVerticalBorderChar(' ') - ->setCrossingChar('') - ->setCellHeaderFormat('%s') - ->setCellRowFormat('%s') - ->setCellRowContentFormat('%s') - ->setBorderFormat('%s') - ->setPadType(STR_PAD_RIGHT) - ; - break; - - case self::LAYOUT_DEFAULT: - $this - ->setPaddingChar(' ') - ->setHorizontalBorderChar('-') - ->setVerticalBorderChar('|') - ->setCrossingChar('+') - ->setCellHeaderFormat('%s') - ->setCellRowFormat('%s') - ->setCellRowContentFormat(' %s ') - ->setBorderFormat('%s') - ->setPadType(STR_PAD_RIGHT) - ; - break; - - default: - throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout)); - break; - }; - - return $this; - } - - public function setHeaders(array $headers) - { - $this->headers = array_values($headers); - - return $this; - } - - public function setRows(array $rows) - { - $this->rows = array(); - - return $this->addRows($rows); - } - - public function addRows(array $rows) - { - foreach ($rows as $row) { - $this->addRow($row); - } - - return $this; - } - - public function addRow(array $row) - { - $this->rows[] = array_values($row); - - return $this; - } - - public function setRow($column, array $row) - { - $this->rows[$column] = $row; - - return $this; - } - - /** - * Sets padding character, used for cell padding. - * - * @param string $paddingChar - * - * @return TableHelper - */ - public function setPaddingChar($paddingChar) - { - if (!$paddingChar) { - throw new \LogicException('The padding char must not be empty'); - } - - $this->paddingChar = $paddingChar; - - return $this; - } - - /** - * Sets horizontal border character. - * - * @param string $horizontalBorderChar - * - * @return TableHelper - */ - public function setHorizontalBorderChar($horizontalBorderChar) - { - $this->horizontalBorderChar = $horizontalBorderChar; - - return $this; - } - - /** - * Sets vertical border character. - * - * @param string $verticalBorderChar - * - * @return TableHelper - */ - public function setVerticalBorderChar($verticalBorderChar) - { - $this->verticalBorderChar = $verticalBorderChar; - - return $this; - } - - /** - * Sets crossing character. - * - * @param string $crossingChar - * - * @return TableHelper - */ - public function setCrossingChar($crossingChar) - { - $this->crossingChar = $crossingChar; - - return $this; - } - - /** - * Sets header cell format. - * - * @param string $cellHeaderFormat - * - * @return TableHelper - */ - public function setCellHeaderFormat($cellHeaderFormat) - { - $this->cellHeaderFormat = $cellHeaderFormat; - - return $this; - } - - /** - * Sets row cell format. - * - * @param string $cellRowFormat - * - * @return TableHelper - */ - public function setCellRowFormat($cellRowFormat) - { - $this->cellRowFormat = $cellRowFormat; - - return $this; - } - - /** - * Sets row cell content format. - * - * @param string $cellRowContentFormat - * - * @return TableHelper - */ - public function setCellRowContentFormat($cellRowContentFormat) - { - $this->cellRowContentFormat = $cellRowContentFormat; - - return $this; - } - - /** - * Sets table border format. - * - * @param string $borderFormat - * - * @return TableHelper - */ - public function setBorderFormat($borderFormat) - { - $this->borderFormat = $borderFormat; - - return $this; - } - - /** - * Sets cell padding type. - * - * @param integer $padType STR_PAD_* - * - * @return TableHelper - */ - public function setPadType($padType) - { - $this->padType = $padType; - - return $this; - } - - /** - * Renders table to output. - * - * Example: - * +---------------+-----------------------+------------------+ - * | ISBN | Title | Author | - * +---------------+-----------------------+------------------+ - * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | - * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | - * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | - * +---------------+-----------------------+------------------+ - * - * @param OutputInterface $output - */ - public function render(OutputInterface $output) - { - $this->output = $output; - - $this->renderRowSeparator(); - $this->renderRow($this->headers, $this->cellHeaderFormat); - if (!empty($this->headers)) { - $this->renderRowSeparator(); - } - foreach ($this->rows as $row) { - $this->renderRow($row, $this->cellRowFormat); - } - if (!empty($this->rows)) { - $this->renderRowSeparator(); - } - - $this->cleanup(); - } - - /** - * Renders horizontal header separator. - * - * Example: +-----+-----------+-------+ - */ - private function renderRowSeparator() - { - if (0 === $count = $this->getNumberOfColumns()) { - return; - } - - if (!$this->horizontalBorderChar && !$this->crossingChar) { - return; - } - - $markup = $this->crossingChar; - for ($column = 0; $column < $count; $column++) { - $markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column)).$this->crossingChar; - } - - $this->output->writeln(sprintf($this->borderFormat, $markup)); - } - - /** - * Renders vertical column separator. - */ - private function renderColumnSeparator() - { - $this->output->write(sprintf($this->borderFormat, $this->verticalBorderChar)); - } - - /** - * Renders table row. - * - * Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | - * - * @param array $row - * @param string $cellFormat - */ - private function renderRow(array $row, $cellFormat) - { - if (empty($row)) { - return; - } - - $this->renderColumnSeparator(); - for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) { - $this->renderCell($row, $column, $cellFormat); - $this->renderColumnSeparator(); - } - $this->output->writeln(''); - } - - /** - * Renders table cell with padding. - * - * @param array $row - * @param integer $column - * @param string $cellFormat - */ - private function renderCell(array $row, $column, $cellFormat) - { - $cell = isset($row[$column]) ? $row[$column] : ''; - $width = $this->getColumnWidth($column); - - // str_pad won't work properly with multi-byte strings, we need to fix the padding - if (function_exists('mb_strlen') && false !== $encoding = mb_detect_encoding($cell)) { - $width += strlen($cell) - mb_strlen($cell, $encoding); - } - - $content = sprintf($this->cellRowContentFormat, $cell); - - $this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->paddingChar, $this->padType))); - } - - /** - * Gets number of columns for this table. - * - * @return int - */ - private function getNumberOfColumns() - { - if (null !== $this->numberOfColumns) { - return $this->numberOfColumns; - } - - $columns = array(0); - $columns[] = count($this->headers); - foreach ($this->rows as $row) { - $columns[] = count($row); - } - - return $this->numberOfColumns = max($columns); - } - - /** - * Gets column width. - * - * @param integer $column - * - * @return int - */ - private function getColumnWidth($column) - { - if (isset($this->columnWidths[$column])) { - return $this->columnWidths[$column]; - } - - $lengths = array(0); - $lengths[] = $this->getCellWidth($this->headers, $column); - foreach ($this->rows as $row) { - $lengths[] = $this->getCellWidth($row, $column); - } - - return $this->columnWidths[$column] = max($lengths) + strlen($this->cellRowContentFormat) - 2; - } - - /** - * Gets cell width. - * - * @param array $row - * @param integer $column - * - * @return int - */ - private function getCellWidth(array $row, $column) - { - if ($column < 0) { - return 0; - } - - if (isset($row[$column])) { - return $this->strlen($row[$column]); - } - - return $this->getCellWidth($row, $column - 1); - } - - /** - * Called after rendering to cleanup cache data. - */ - private function cleanup() - { - $this->columnWidths = array(); - $this->numberOfColumns = null; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'table'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -/** - * HelperInterface is the interface all helpers must implement. - * - * @author Fabien Potencier - * - * @api - */ -interface HelperInterface -{ - /** - * Sets the helper set associated with this helper. - * - * @param HelperSet $helperSet A HelperSet instance - * - * @api - */ - public function setHelperSet(HelperSet $helperSet = null); - - /** - * Gets the helper set associated with this helper. - * - * @return HelperSet A HelperSet instance - * - * @api - */ - public function getHelperSet(); - - /** - * Returns the canonical name of this helper. - * - * @return string The canonical name - * - * @api - */ - public function getName(); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Output\OutputInterface; - -/** - * The Progress class provides helpers to display progress output. - * - * @author Chris Jones - * @author Fabien Potencier - */ -class ProgressHelper extends Helper -{ - const FORMAT_QUIET = ' %percent%%'; - const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%'; - const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%'; - const FORMAT_QUIET_NOMAX = ' %current%'; - const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]'; - const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%'; - - // options - private $barWidth = 28; - private $barChar = '='; - private $emptyBarChar = '-'; - private $progressChar = '>'; - private $format = null; - private $redrawFreq = 1; - - private $lastMessagesLength; - private $barCharOriginal; - - /** - * @var OutputInterface - */ - private $output; - - /** - * Current step - * - * @var integer - */ - private $current; - - /** - * Maximum number of steps - * - * @var integer - */ - private $max; - - /** - * Start time of the progress bar - * - * @var integer - */ - private $startTime; - - /** - * List of formatting variables - * - * @var array - */ - private $defaultFormatVars = array( - 'current', - 'max', - 'bar', - 'percent', - 'elapsed', - ); - - /** - * Available formatting variables - * - * @var array - */ - private $formatVars; - - /** - * Stored format part widths (used for padding) - * - * @var array - */ - private $widths = array( - 'current' => 4, - 'max' => 4, - 'percent' => 3, - 'elapsed' => 6, - ); - - /** - * Various time formats - * - * @var array - */ - private $timeFormats = array( - array(0, '???'), - array(2, '1 sec'), - array(59, 'secs', 1), - array(60, '1 min'), - array(3600, 'mins', 60), - array(5400, '1 hr'), - array(86400, 'hrs', 3600), - array(129600, '1 day'), - array(604800, 'days', 86400), - ); - - /** - * Sets the progress bar width. - * - * @param int $size The progress bar size - */ - public function setBarWidth($size) - { - $this->barWidth = (int) $size; - } - - /** - * Sets the bar character. - * - * @param string $char A character - */ - public function setBarCharacter($char) - { - $this->barChar = $char; - } - - /** - * Sets the empty bar character. - * - * @param string $char A character - */ - public function setEmptyBarCharacter($char) - { - $this->emptyBarChar = $char; - } - - /** - * Sets the progress bar character. - * - * @param string $char A character - */ - public function setProgressCharacter($char) - { - $this->progressChar = $char; - } - - /** - * Sets the progress bar format. - * - * @param string $format The format - */ - public function setFormat($format) - { - $this->format = $format; - } - - /** - * Sets the redraw frequency. - * - * @param int $freq The frequency in steps - */ - public function setRedrawFrequency($freq) - { - $this->redrawFreq = (int) $freq; - } - - /** - * Starts the progress output. - * - * @param OutputInterface $output An Output instance - * @param integer|null $max Maximum steps - */ - public function start(OutputInterface $output, $max = null) - { - $this->startTime = time(); - $this->current = 0; - $this->max = (int) $max; - $this->output = $output; - $this->lastMessagesLength = 0; - $this->barCharOriginal = ''; - - if (null === $this->format) { - switch ($output->getVerbosity()) { - case OutputInterface::VERBOSITY_QUIET: - $this->format = self::FORMAT_QUIET_NOMAX; - if ($this->max > 0) { - $this->format = self::FORMAT_QUIET; - } - break; - case OutputInterface::VERBOSITY_VERBOSE: - case OutputInterface::VERBOSITY_VERY_VERBOSE: - case OutputInterface::VERBOSITY_DEBUG: - $this->format = self::FORMAT_VERBOSE_NOMAX; - if ($this->max > 0) { - $this->format = self::FORMAT_VERBOSE; - } - break; - default: - $this->format = self::FORMAT_NORMAL_NOMAX; - if ($this->max > 0) { - $this->format = self::FORMAT_NORMAL; - } - break; - } - } - - $this->initialize(); - } - - /** - * Advances the progress output X steps. - * - * @param integer $step Number of steps to advance - * @param Boolean $redraw Whether to redraw or not - * - * @throws \LogicException - */ - public function advance($step = 1, $redraw = false) - { - $this->setCurrent($this->current + $step, $redraw); - } - - /** - * Sets the current progress. - * - * @param integer $current The current progress - * @param Boolean $redraw Whether to redraw or not - * - * @throws \LogicException - */ - public function setCurrent($current, $redraw = false) - { - if (null === $this->startTime) { - throw new \LogicException('You must start the progress bar before calling setCurrent().'); - } - - $current = (int) $current; - - if ($current < $this->current) { - throw new \LogicException('You can\'t regress the progress bar'); - } - - if (0 === $this->current) { - $redraw = true; - } - - $prevPeriod = intval($this->current / $this->redrawFreq); - - $this->current = $current; - - $currPeriod = intval($this->current / $this->redrawFreq); - if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) { - $this->display(); - } - } - - /** - * Outputs the current progress string. - * - * @param Boolean $finish Forces the end result - * - * @throws \LogicException - */ - public function display($finish = false) - { - if (null === $this->startTime) { - throw new \LogicException('You must start the progress bar before calling display().'); - } - - $message = $this->format; - foreach ($this->generate($finish) as $name => $value) { - $message = str_replace("%{$name}%", $value, $message); - } - $this->overwrite($this->output, $message); - } - - /** - * Removes the progress bar from the current line. - * - * This is useful if you wish to write some output - * while a progress bar is running. - * Call display() to show the progress bar again. - */ - public function clear() - { - $this->overwrite($this->output, ''); - } - - /** - * Finishes the progress output. - */ - public function finish() - { - if (null === $this->startTime) { - throw new \LogicException('You must start the progress bar before calling finish().'); - } - - if (null !== $this->startTime) { - if (!$this->max) { - $this->barChar = $this->barCharOriginal; - $this->display(true); - } - $this->startTime = null; - $this->output->writeln(''); - $this->output = null; - } - } - - /** - * Initializes the progress helper. - */ - private function initialize() - { - $this->formatVars = array(); - foreach ($this->defaultFormatVars as $var) { - if (false !== strpos($this->format, "%{$var}%")) { - $this->formatVars[$var] = true; - } - } - - if ($this->max > 0) { - $this->widths['max'] = $this->strlen($this->max); - $this->widths['current'] = $this->widths['max']; - } else { - $this->barCharOriginal = $this->barChar; - $this->barChar = $this->emptyBarChar; - } - } - - /** - * Generates the array map of format variables to values. - * - * @param Boolean $finish Forces the end result - * - * @return array Array of format vars and values - */ - private function generate($finish = false) - { - $vars = array(); - $percent = 0; - if ($this->max > 0) { - $percent = (double) $this->current / $this->max; - } - - if (isset($this->formatVars['bar'])) { - $completeBars = 0; - - if ($this->max > 0) { - $completeBars = floor($percent * $this->barWidth); - } else { - if (!$finish) { - $completeBars = floor($this->current % $this->barWidth); - } else { - $completeBars = $this->barWidth; - } - } - - $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar); - $bar = str_repeat($this->barChar, $completeBars); - if ($completeBars < $this->barWidth) { - $bar .= $this->progressChar; - $bar .= str_repeat($this->emptyBarChar, $emptyBars); - } - - $vars['bar'] = $bar; - } - - if (isset($this->formatVars['elapsed'])) { - $elapsed = time() - $this->startTime; - $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT); - } - - if (isset($this->formatVars['current'])) { - $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT); - } - - if (isset($this->formatVars['max'])) { - $vars['max'] = $this->max; - } - - if (isset($this->formatVars['percent'])) { - $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT); - } - - return $vars; - } - - /** - * Converts seconds into human-readable format. - * - * @param integer $secs Number of seconds - * - * @return string Time in readable format - */ - private function humaneTime($secs) - { - $text = ''; - foreach ($this->timeFormats as $format) { - if ($secs < $format[0]) { - if (count($format) == 2) { - $text = $format[1]; - break; - } else { - $text = ceil($secs / $format[2]).' '.$format[1]; - break; - } - } - } - - return $text; - } - - /** - * Overwrites a previous message to the output. - * - * @param OutputInterface $output An Output instance - * @param string $message The message - */ - private function overwrite(OutputInterface $output, $message) - { - $length = $this->strlen($message); - - // append whitespace to match the last line's length - if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) { - $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); - } - - // carriage return - $output->write("\x0D"); - $output->write($message); - - $this->lastMessagesLength = $this->strlen($message); - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'progress'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Descriptor\DescriptorInterface; -use Symfony\Component\Console\Descriptor\JsonDescriptor; -use Symfony\Component\Console\Descriptor\MarkdownDescriptor; -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * This class adds helper method to describe objects in various formats. - * - * @author Jean-François Simon - */ -class DescriptorHelper extends Helper -{ - /** - * @var DescriptorInterface[] - */ - private $descriptors = array(); - - /** - * Constructor. - */ - public function __construct() - { - $this - ->register('txt', new TextDescriptor()) - ->register('xml', new XmlDescriptor()) - ->register('json', new JsonDescriptor()) - ->register('md', new MarkdownDescriptor()) - ; - } - - /** - * Describes an object if supported. - * - * Available options are: - * * format: string, the output format name - * * raw_text: boolean, sets output type as raw - * - * @param OutputInterface $output - * @param object $object - * @param array $options - * - * @throws \InvalidArgumentException - */ - public function describe(OutputInterface $output, $object, array $options = array()) - { - $options = array_merge(array( - 'raw_text' => false, - 'format' => 'txt', - ), $options); - - if (!isset($this->descriptors[$options['format']])) { - throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); - } - - $descriptor = $this->descriptors[$options['format']]; - $descriptor->describe($output, $object, $options); - } - - /** - * Registers a descriptor. - * - * @param string $format - * @param DescriptorInterface $descriptor - * - * @return DescriptorHelper - */ - public function register($format, DescriptorInterface $descriptor) - { - $this->descriptors[$format] = $descriptor; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'descriptor'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; - -/** - * The Dialog class provides helpers to interact with the user. - * - * @author Fabien Potencier - */ -class DialogHelper extends InputAwareHelper -{ - private $inputStream; - private static $shell; - private static $stty; - - /** - * Asks the user to select a value. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param array $choices List of choices to pick from - * @param Boolean $default The default answer if the user enters nothing - * @param Boolean|integer $attempts Max number of times to ask before giving up (false by default, which means infinite) - * @param string $errorMessage Message which will be shown if invalid value from choice list would be picked - * @param Boolean $multiselect Select more than one value separated by comma - * - * @return integer|string|array The selected value or values (the key of the choices array) - * - * @throws \InvalidArgumentException - */ - public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false) - { - $width = max(array_map('strlen', array_keys($choices))); - - $messages = (array) $question; - foreach ($choices as $key => $value) { - $messages[] = sprintf(" [%-${width}s] %s", $key, $value); - } - - $output->writeln($messages); - - $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) { - // Collapse all spaces. - $selectedChoices = str_replace(" ", "", $picked); - - if ($multiselect) { - // Check for a separated comma values - if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) { - throw new \InvalidArgumentException(sprintf($errorMessage, $picked)); - } - $selectedChoices = explode(",", $selectedChoices); - } else { - $selectedChoices = array($picked); - } - - $multiselectChoices = array(); - - foreach ($selectedChoices as $value) { - if (empty($choices[$value])) { - throw new \InvalidArgumentException(sprintf($errorMessage, $value)); - } - array_push($multiselectChoices, $value); - } - - if ($multiselect) { - return $multiselectChoices; - } - - return $picked; - }, $attempts, $default); - - return $result; - } - - /** - * Asks a question to the user. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param string $default The default answer if none is given by the user - * @param array $autocomplete List of values to autocomplete - * - * @return string The user answer - * - * @throws \RuntimeException If there is no data to read in the input stream - */ - public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null) - { - if ($this->input && !$this->input->isInteractive()) { - return $default; - } - - $output->write($question); - - $inputStream = $this->inputStream ?: STDIN; - - if (null === $autocomplete || !$this->hasSttyAvailable()) { - $ret = fgets($inputStream, 4096); - if (false === $ret) { - throw new \RuntimeException('Aborted'); - } - $ret = trim($ret); - } else { - $ret = ''; - - $i = 0; - $ofs = -1; - $matches = $autocomplete; - $numMatches = count($matches); - - $sttyMode = shell_exec('stty -g'); - - // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) - shell_exec('stty -icanon -echo'); - - // Add highlighted text style - $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); - - // Read a keypress - while (!feof($inputStream)) { - $c = fread($inputStream, 1); - - // Backspace Character - if ("\177" === $c) { - if (0 === $numMatches && 0 !== $i) { - $i--; - // Move cursor backwards - $output->write("\033[1D"); - } - - if ($i === 0) { - $ofs = -1; - $matches = $autocomplete; - $numMatches = count($matches); - } else { - $numMatches = 0; - } - - // Pop the last character off the end of our string - $ret = substr($ret, 0, $i); - } elseif ("\033" === $c) { // Did we read an escape sequence? - $c .= fread($inputStream, 2); - - // A = Up Arrow. B = Down Arrow - if ('A' === $c[2] || 'B' === $c[2]) { - if ('A' === $c[2] && -1 === $ofs) { - $ofs = 0; - } - - if (0 === $numMatches) { - continue; - } - - $ofs += ('A' === $c[2]) ? -1 : 1; - $ofs = ($numMatches + $ofs) % $numMatches; - } - } elseif (ord($c) < 32) { - if ("\t" === $c || "\n" === $c) { - if ($numMatches > 0 && -1 !== $ofs) { - $ret = $matches[$ofs]; - // Echo out remaining chars for current match - $output->write(substr($ret, $i)); - $i = strlen($ret); - } - - if ("\n" === $c) { - $output->write($c); - break; - } - - $numMatches = 0; - } - - continue; - } else { - $output->write($c); - $ret .= $c; - $i++; - - $numMatches = 0; - $ofs = 0; - - foreach ($autocomplete as $value) { - // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) - if (0 === strpos($value, $ret) && $i !== strlen($value)) { - $matches[$numMatches++] = $value; - } - } - } - - // Erase characters from cursor to end of line - $output->write("\033[K"); - - if ($numMatches > 0 && -1 !== $ofs) { - // Save cursor position - $output->write("\0337"); - // Write highlighted text - $output->write(''.substr($matches[$ofs], $i).''); - // Restore cursor position - $output->write("\0338"); - } - } - - // Reset stty so it behaves normally again - shell_exec(sprintf('stty %s', $sttyMode)); - } - - return strlen($ret) > 0 ? $ret : $default; - } - - /** - * Asks a confirmation to the user. - * - * The question will be asked until the user answers by nothing, yes, or no. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param Boolean $default The default answer if the user enters nothing - * - * @return Boolean true if the user has confirmed, false otherwise - */ - public function askConfirmation(OutputInterface $output, $question, $default = true) - { - $answer = 'z'; - while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) { - $answer = $this->ask($output, $question); - } - - if (false === $default) { - return $answer && 'y' == strtolower($answer[0]); - } - - return !$answer || 'y' == strtolower($answer[0]); - } - - /** - * Asks a question to the user, the response is hidden - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question - * @param Boolean $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not - * - * @return string The answer - * - * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden - */ - public function askHiddenResponse(OutputInterface $output, $question, $fallback = true) - { - if (defined('PHP_WINDOWS_VERSION_BUILD')) { - $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; - - // handle code running from a phar - if ('phar:' === substr(__FILE__, 0, 5)) { - $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; - copy($exe, $tmpExe); - $exe = $tmpExe; - } - - $output->write($question); - $value = rtrim(shell_exec($exe)); - $output->writeln(''); - - if (isset($tmpExe)) { - unlink($tmpExe); - } - - return $value; - } - - if ($this->hasSttyAvailable()) { - $output->write($question); - - $sttyMode = shell_exec('stty -g'); - - shell_exec('stty -echo'); - $value = fgets($this->inputStream ?: STDIN, 4096); - shell_exec(sprintf('stty %s', $sttyMode)); - - if (false === $value) { - throw new \RuntimeException('Aborted'); - } - - $value = trim($value); - $output->writeln(''); - - return $value; - } - - if (false !== $shell = $this->getShell()) { - $output->write($question); - $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword'; - $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); - $value = rtrim(shell_exec($command)); - $output->writeln(''); - - return $value; - } - - if ($fallback) { - return $this->ask($output, $question); - } - - throw new \RuntimeException('Unable to hide the response'); - } - - /** - * Asks for a value and validates the response. - * - * The validator receives the data to validate. It must return the - * validated data when the data is valid and throw an exception - * otherwise. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param callable $validator A PHP callback - * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) - * @param string $default The default answer if none is given by the user - * @param array $autocomplete List of values to autocomplete - * - * @return mixed - * - * @throws \Exception When any of the validators return an error - */ - public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null) - { - $that = $this; - - $interviewer = function() use ($output, $question, $default, $autocomplete, $that) { - return $that->ask($output, $question, $default, $autocomplete); - }; - - return $this->validateAttempts($interviewer, $output, $validator, $attempts); - } - - /** - * Asks for a value, hide and validates the response. - * - * The validator receives the data to validate. It must return the - * validated data when the data is valid and throw an exception - * otherwise. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param callable $validator A PHP callback - * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) - * @param Boolean $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not - * - * @return string The response - * - * @throws \Exception When any of the validators return an error - * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden - * - */ - public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true) - { - $that = $this; - - $interviewer = function() use ($output, $question, $fallback, $that) { - return $that->askHiddenResponse($output, $question, $fallback); - }; - - return $this->validateAttempts($interviewer, $output, $validator, $attempts); - } - - /** - * Sets the input stream to read from when interacting with the user. - * - * This is mainly useful for testing purpose. - * - * @param resource $stream The input stream - */ - public function setInputStream($stream) - { - $this->inputStream = $stream; - } - - /** - * Returns the helper's input stream - * - * @return string - */ - public function getInputStream() - { - return $this->inputStream; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'dialog'; - } - - /** - * Return a valid unix shell - * - * @return string|Boolean The valid shell name, false in case no valid shell is found - */ - private function getShell() - { - if (null !== self::$shell) { - return self::$shell; - } - - self::$shell = false; - - if (file_exists('/usr/bin/env')) { - // handle other OSs with bash/zsh/ksh/csh if available to hide the answer - $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; - foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) { - if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { - self::$shell = $sh; - break; - } - } - } - - return self::$shell; - } - - private function hasSttyAvailable() - { - if (null !== self::$stty) { - return self::$stty; - } - - exec('stty 2>&1', $output, $exitcode); - - return self::$stty = $exitcode === 0; - } - - /** - * Validate an attempt - * - * @param callable $interviewer A callable that will ask for a question and return the result - * @param OutputInterface $output An Output instance - * @param callable $validator A PHP callback - * @param integer $attempts Max number of times to ask before giving up ; false will ask infinitely - * - * @return string The validated response - * - * @throws \Exception In case the max number of attempts has been reached and no valid response has been given - */ - private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts) - { - $error = null; - while (false === $attempts || $attempts--) { - if (null !== $error) { - $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error')); - } - - try { - return call_user_func($validator, $interviewer()); - } catch (\Exception $error) { - } - } - - throw $error; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Formatter\OutputFormatter; - -/** - * The Formatter class provides helpers to format messages. - * - * @author Fabien Potencier - */ -class FormatterHelper extends Helper -{ - /** - * Formats a message within a section. - * - * @param string $section The section name - * @param string $message The message - * @param string $style The style to apply to the section - * - * @return string The format section - */ - public function formatSection($section, $message, $style = 'info') - { - return sprintf('<%s>[%s] %s', $style, $section, $style, $message); - } - - /** - * Formats a message as a block of text. - * - * @param string|array $messages The message to write in the block - * @param string $style The style to apply to the whole block - * @param Boolean $large Whether to return a large block - * - * @return string The formatter message - */ - public function formatBlock($messages, $style, $large = false) - { - $messages = (array) $messages; - - $len = 0; - $lines = array(); - foreach ($messages as $message) { - $message = OutputFormatter::escape($message); - $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); - $len = max($this->strlen($message) + ($large ? 4 : 2), $len); - } - - $messages = $large ? array(str_repeat(' ', $len)) : array(); - foreach ($lines as $line) { - $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); - } - if ($large) { - $messages[] = str_repeat(' ', $len); - } - - foreach ($messages as &$message) { - $message = sprintf('<%s>%s', $style, $message, $style); - } - - return implode("\n", $messages); - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'formatter'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; -use Symfony\Component\Console\Output\ConsoleOutputInterface; - -/** - * ConsoleOutput is the default class for all CLI output. It uses STDOUT. - * - * This class is a convenient wrapper around `StreamOutput`. - * - * $output = new ConsoleOutput(); - * - * This is equivalent to: - * - * $output = new StreamOutput(fopen('php://stdout', 'w')); - * - * @author Fabien Potencier - * - * @api - */ -class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface -{ - private $stderr; - - /** - * Constructor. - * - * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) - * @param Boolean|null $decorated Whether to decorate messages (null for auto-guessing) - * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) - * - * @api - */ - public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) - { - $outputStream = 'php://stdout'; - if (!$this->hasStdoutSupport()) { - $outputStream = 'php://output'; - } - - parent::__construct(fopen($outputStream, 'w'), $verbosity, $decorated, $formatter); - - $this->stderr = new StreamOutput(fopen('php://stderr', 'w'), $verbosity, $decorated, $formatter); - } - - /** - * {@inheritdoc} - */ - public function setDecorated($decorated) - { - parent::setDecorated($decorated); - $this->stderr->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - parent::setFormatter($formatter); - $this->stderr->setFormatter($formatter); - } - - /** - * {@inheritdoc} - */ - public function setVerbosity($level) - { - parent::setVerbosity($level); - $this->stderr->setVerbosity($level); - } - - /** - * {@inheritdoc} - */ - public function getErrorOutput() - { - return $this->stderr; - } - - /** - * {@inheritdoc} - */ - public function setErrorOutput(OutputInterface $error) - { - $this->stderr = $error; - } - - /** - * Returns true if current environment supports writing console output to - * STDOUT. - * - * IBM iSeries (OS400) exhibits character-encoding issues when writing to - * STDOUT and doesn't properly convert ASCII to EBCDIC, resulting in garbage - * output. - * - * @return boolean - */ - protected function hasStdoutSupport() - { - return ('OS400' != php_uname('s')); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * StreamOutput writes the output to a given stream. - * - * Usage: - * - * $output = new StreamOutput(fopen('php://stdout', 'w')); - * - * As `StreamOutput` can use any stream, you can also use a file: - * - * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); - * - * @author Fabien Potencier - * - * @api - */ -class StreamOutput extends Output -{ - private $stream; - - /** - * Constructor. - * - * @param mixed $stream A stream resource - * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) - * @param Boolean|null $decorated Whether to decorate messages (null for auto-guessing) - * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) - * - * @throws \InvalidArgumentException When first argument is not a real stream - * - * @api - */ - public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) - { - if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) { - throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); - } - - $this->stream = $stream; - - if (null === $decorated) { - $decorated = $this->hasColorSupport(); - } - - parent::__construct($verbosity, $decorated, $formatter); - } - - /** - * Gets the stream attached to this StreamOutput instance. - * - * @return resource A stream resource - */ - public function getStream() - { - return $this->stream; - } - - /** - * {@inheritdoc} - */ - protected function doWrite($message, $newline) - { - if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) { - // @codeCoverageIgnoreStart - // should never happen - throw new \RuntimeException('Unable to write output.'); - // @codeCoverageIgnoreEnd - } - - fflush($this->stream); - } - - /** - * Returns true if the stream supports colorization. - * - * Colorization is disabled if not supported by the stream: - * - * - windows without ansicon and ConEmu - * - non tty consoles - * - * @return Boolean true if the stream supports colorization, false otherwise - */ - protected function hasColorSupport() - { - // @codeCoverageIgnoreStart - if (DIRECTORY_SEPARATOR == '\\') { - return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI'); - } - - return function_exists('posix_isatty') && @posix_isatty($this->stream); - // @codeCoverageIgnoreEnd - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -/** - * @author Jean-François Simon - */ -class BufferedOutput extends Output -{ - /** - * @var string - */ - private $buffer = ''; - - /** - * Empties buffer and returns its content. - * - * @return string - */ - public function fetch() - { - $content = $this->buffer; - $this->buffer = ''; - - return $content; - } - - /** - * {@inheritdoc} - */ - protected function doWrite($message, $newline) - { - $this->buffer .= $message; - - if ($newline) { - $this->buffer .= "\n"; - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Output\OutputInterface; - -/** - * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. - * This adds information about stderr output stream. - * - * @author Dariusz Górecki - */ -interface ConsoleOutputInterface extends OutputInterface -{ - /** - * Gets the OutputInterface for errors. - * - * @return OutputInterface - */ - public function getErrorOutput(); - - /** - * Sets the OutputInterface used for errors. - * - * @param OutputInterface $error - */ - public function setErrorOutput(OutputInterface $error); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * NullOutput suppresses all output. - * - * $output = new NullOutput(); - * - * @author Fabien Potencier - * @author Tobias Schultze - * - * @api - */ -class NullOutput implements OutputInterface -{ - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function getFormatter() - { - // to comply with the interface we must return a OutputFormatterInterface - return new OutputFormatter(); - } - - /** - * {@inheritdoc} - */ - public function setDecorated($decorated) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function isDecorated() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function setVerbosity($level) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function getVerbosity() - { - return self::VERBOSITY_QUIET; - } - - /** - * {@inheritdoc} - */ - public function writeln($messages, $type = self::OUTPUT_NORMAL) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) - { - // do nothing - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; -use Symfony\Component\Console\Formatter\OutputFormatter; - -/** - * Base class for output classes. - * - * There are five levels of verbosity: - * - * * normal: no option passed (normal output) - * * verbose: -v (more output) - * * very verbose: -vv (highly extended output) - * * debug: -vvv (all debug output) - * * quiet: -q (no output) - * - * @author Fabien Potencier - * - * @api - */ -abstract class Output implements OutputInterface -{ - private $verbosity; - private $formatter; - - /** - * Constructor. - * - * @param integer $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) - * @param Boolean $decorated Whether to decorate messages - * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) - * - * @api - */ - public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null) - { - $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; - $this->formatter = $formatter ?: new OutputFormatter(); - $this->formatter->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - $this->formatter = $formatter; - } - - /** - * {@inheritdoc} - */ - public function getFormatter() - { - return $this->formatter; - } - - /** - * {@inheritdoc} - */ - public function setDecorated($decorated) - { - $this->formatter->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function isDecorated() - { - return $this->formatter->isDecorated(); - } - - /** - * {@inheritdoc} - */ - public function setVerbosity($level) - { - $this->verbosity = (int) $level; - } - - /** - * {@inheritdoc} - */ - public function getVerbosity() - { - return $this->verbosity; - } - - public function isQuiet() - { - return self::VERBOSITY_QUIET === $this->verbosity; - } - - public function isVerbose() - { - return self::VERBOSITY_VERBOSE <= $this->verbosity; - } - - public function isVeryVerbose() - { - return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity; - } - - public function isDebug() - { - return self::VERBOSITY_DEBUG <= $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function writeln($messages, $type = self::OUTPUT_NORMAL) - { - $this->write($messages, true, $type); - } - - /** - * {@inheritdoc} - */ - public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) - { - if (self::VERBOSITY_QUIET === $this->verbosity) { - return; - } - - $messages = (array) $messages; - - foreach ($messages as $message) { - switch ($type) { - case OutputInterface::OUTPUT_NORMAL: - $message = $this->formatter->format($message); - break; - case OutputInterface::OUTPUT_RAW: - break; - case OutputInterface::OUTPUT_PLAIN: - $message = strip_tags($this->formatter->format($message)); - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type)); - } - - $this->doWrite($message, $newline); - } - } - - /** - * Writes a message to the output. - * - * @param string $message A message to write to the output - * @param Boolean $newline Whether to add a newline or not - */ - abstract protected function doWrite($message, $newline); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * OutputInterface is the interface implemented by all Output classes. - * - * @author Fabien Potencier - * - * @api - */ -interface OutputInterface -{ - const VERBOSITY_QUIET = 0; - const VERBOSITY_NORMAL = 1; - const VERBOSITY_VERBOSE = 2; - const VERBOSITY_VERY_VERBOSE = 3; - const VERBOSITY_DEBUG = 4; - - const OUTPUT_NORMAL = 0; - const OUTPUT_RAW = 1; - const OUTPUT_PLAIN = 2; - - /** - * Writes a message to the output. - * - * @param string|array $messages The message as an array of lines or a single string - * @param Boolean $newline Whether to add a newline - * @param integer $type The type of output (one of the OUTPUT constants) - * - * @throws \InvalidArgumentException When unknown output type is given - * - * @api - */ - public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL); - - /** - * Writes a message to the output and adds a newline at the end. - * - * @param string|array $messages The message as an array of lines of a single string - * @param integer $type The type of output (one of the OUTPUT constants) - * - * @throws \InvalidArgumentException When unknown output type is given - * - * @api - */ - public function writeln($messages, $type = self::OUTPUT_NORMAL); - - /** - * Sets the verbosity of the output. - * - * @param integer $level The level of verbosity (one of the VERBOSITY constants) - * - * @api - */ - public function setVerbosity($level); - - /** - * Gets the current verbosity of the output. - * - * @return integer The current level of verbosity (one of the VERBOSITY constants) - * - * @api - */ - public function getVerbosity(); - - /** - * Sets the decorated flag. - * - * @param Boolean $decorated Whether to decorate the messages - * - * @api - */ - public function setDecorated($decorated); - - /** - * Gets the decorated flag. - * - * @return Boolean true if the output will decorate messages, false otherwise - * - * @api - */ - public function isDecorated(); - - /** - * Sets output formatter. - * - * @param OutputFormatterInterface $formatter - * - * @api - */ - public function setFormatter(OutputFormatterInterface $formatter); - - /** - * Returns current output formatter instance. - * - * @return OutputFormatterInterface - * - * @api - */ - public function getFormatter(); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Input\StringInput; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Process\ProcessBuilder; -use Symfony\Component\Process\PhpExecutableFinder; - -/** - * A Shell wraps an Application to add shell capabilities to it. - * - * Support for history and completion only works with a PHP compiled - * with readline support (either --with-readline or --with-libedit) - * - * @author Fabien Potencier - * @author Martin Hasoň - */ -class Shell -{ - private $application; - private $history; - private $output; - private $hasReadline; - private $processIsolation = false; - - /** - * Constructor. - * - * If there is no readline support for the current PHP executable - * a \RuntimeException exception is thrown. - * - * @param Application $application An application instance - */ - public function __construct(Application $application) - { - $this->hasReadline = function_exists('readline'); - $this->application = $application; - $this->history = getenv('HOME').'/.history_'.$application->getName(); - $this->output = new ConsoleOutput(); - } - - /** - * Runs the shell. - */ - public function run() - { - $this->application->setAutoExit(false); - $this->application->setCatchExceptions(true); - - if ($this->hasReadline) { - readline_read_history($this->history); - readline_completion_function(array($this, 'autocompleter')); - } - - $this->output->writeln($this->getHeader()); - $php = null; - if ($this->processIsolation) { - $finder = new PhpExecutableFinder(); - $php = $finder->find(); - $this->output->writeln(<<Running with process isolation, you should consider this: - * each command is executed as separate process, - * commands don't support interactivity, all params must be passed explicitly, - * commands output is not colorized. - -EOF - ); - } - - while (true) { - $command = $this->readline(); - - if (false === $command) { - $this->output->writeln("\n"); - - break; - } - - if ($this->hasReadline) { - readline_add_history($command); - readline_write_history($this->history); - } - - if ($this->processIsolation) { - $pb = new ProcessBuilder(); - - $process = $pb - ->add($php) - ->add($_SERVER['argv'][0]) - ->add($command) - ->inheritEnvironmentVariables(true) - ->getProcess() - ; - - $output = $this->output; - $process->run(function($type, $data) use ($output) { - $output->writeln($data); - }); - - $ret = $process->getExitCode(); - } else { - $ret = $this->application->run(new StringInput($command), $this->output); - } - - if (0 !== $ret) { - $this->output->writeln(sprintf('The command terminated with an error status (%s)', $ret)); - } - } - } - - /** - * Returns the shell header. - * - * @return string The header string - */ - protected function getHeader() - { - return <<{$this->application->getName()} shell ({$this->application->getVersion()}). - -At the prompt, type help for some help, -or list to get a list of available commands. - -To exit the shell, type ^D. - -EOF; - } - - /** - * Renders a prompt. - * - * @return string The prompt - */ - protected function getPrompt() - { - // using the formatter here is required when using readline - return $this->output->getFormatter()->format($this->application->getName().' > '); - } - - protected function getOutput() - { - return $this->output; - } - - protected function getApplication() - { - return $this->application; - } - - /** - * Tries to return autocompletion for the current entered text. - * - * @param string $text The last segment of the entered text - * - * @return Boolean|array A list of guessed strings or true - */ - private function autocompleter($text) - { - $info = readline_info(); - $text = substr($info['line_buffer'], 0, $info['end']); - - if ($info['point'] !== $info['end']) { - return true; - } - - // task name? - if (false === strpos($text, ' ') || !$text) { - return array_keys($this->application->all()); - } - - // options and arguments? - try { - $command = $this->application->find(substr($text, 0, strpos($text, ' '))); - } catch (\Exception $e) { - return true; - } - - $list = array('--help'); - foreach ($command->getDefinition()->getOptions() as $option) { - $list[] = '--'.$option->getName(); - } - - return $list; - } - - /** - * Reads a single line from standard input. - * - * @return string The single line from standard input - */ - private function readline() - { - if ($this->hasReadline) { - $line = readline($this->getPrompt()); - } else { - $this->output->write($this->getPrompt()); - $line = fgets(STDIN, 1024); - $line = (!$line && strlen($line) == 0) ? false : rtrim($line); - } - - return $line; - } - - public function getProcessIsolation() - { - return $this->processIsolation; - } - - public function setProcessIsolation($processIsolation) - { - $this->processIsolation = (Boolean) $processIsolation; - - if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) { - throw new \RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.'); - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * ArgvInput represents an input coming from the CLI arguments. - * - * Usage: - * - * $input = new ArgvInput(); - * - * By default, the `$_SERVER['argv']` array is used for the input values. - * - * This can be overridden by explicitly passing the input values in the constructor: - * - * $input = new ArgvInput($_SERVER['argv']); - * - * If you pass it yourself, don't forget that the first element of the array - * is the name of the running application. - * - * When passing an argument to the constructor, be sure that it respects - * the same rules as the argv one. It's almost always better to use the - * `StringInput` when you want to provide your own input. - * - * @author Fabien Potencier - * - * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html - * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 - * - * @api - */ -class ArgvInput extends Input -{ - private $tokens; - private $parsed; - - /** - * Constructor. - * - * @param array $argv An array of parameters from the CLI (in the argv format) - * @param InputDefinition $definition A InputDefinition instance - * - * @api - */ - public function __construct(array $argv = null, InputDefinition $definition = null) - { - if (null === $argv) { - $argv = $_SERVER['argv']; - } - - // strip the application name - array_shift($argv); - - $this->tokens = $argv; - - parent::__construct($definition); - } - - protected function setTokens(array $tokens) - { - $this->tokens = $tokens; - } - - /** - * Processes command line arguments. - */ - protected function parse() - { - $parseOptions = true; - $this->parsed = $this->tokens; - while (null !== $token = array_shift($this->parsed)) { - if ($parseOptions && '' == $token) { - $this->parseArgument($token); - } elseif ($parseOptions && '--' == $token) { - $parseOptions = false; - } elseif ($parseOptions && 0 === strpos($token, '--')) { - $this->parseLongOption($token); - } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { - $this->parseShortOption($token); - } else { - $this->parseArgument($token); - } - } - } - - /** - * Parses a short option. - * - * @param string $token The current token. - */ - private function parseShortOption($token) - { - $name = substr($token, 1); - - if (strlen($name) > 1) { - if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { - // an option with a value (with no space) - $this->addShortOption($name[0], substr($name, 1)); - } else { - $this->parseShortOptionSet($name); - } - } else { - $this->addShortOption($name, null); - } - } - - /** - * Parses a short option set. - * - * @param string $name The current token - * - * @throws \RuntimeException When option given doesn't exist - */ - private function parseShortOptionSet($name) - { - $len = strlen($name); - for ($i = 0; $i < $len; $i++) { - if (!$this->definition->hasShortcut($name[$i])) { - throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i])); - } - - $option = $this->definition->getOptionForShortcut($name[$i]); - if ($option->acceptValue()) { - $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); - - break; - } else { - $this->addLongOption($option->getName(), null); - } - } - } - - /** - * Parses a long option. - * - * @param string $token The current token - */ - private function parseLongOption($token) - { - $name = substr($token, 2); - - if (false !== $pos = strpos($name, '=')) { - $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1)); - } else { - $this->addLongOption($name, null); - } - } - - /** - * Parses an argument. - * - * @param string $token The current token - * - * @throws \RuntimeException When too many arguments are given - */ - private function parseArgument($token) - { - $c = count($this->arguments); - - // if input is expecting another argument, add it - if ($this->definition->hasArgument($c)) { - $arg = $this->definition->getArgument($c); - $this->arguments[$arg->getName()] = $arg->isArray()? array($token) : $token; - - // if last argument isArray(), append token to last argument - } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { - $arg = $this->definition->getArgument($c - 1); - $this->arguments[$arg->getName()][] = $token; - - // unexpected argument - } else { - throw new \RuntimeException('Too many arguments.'); - } - } - - /** - * Adds a short option value. - * - * @param string $shortcut The short option key - * @param mixed $value The value for the option - * - * @throws \RuntimeException When option given doesn't exist - */ - private function addShortOption($shortcut, $value) - { - if (!$this->definition->hasShortcut($shortcut)) { - throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); - } - - $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); - } - - /** - * Adds a long option value. - * - * @param string $name The long option key - * @param mixed $value The value for the option - * - * @throws \RuntimeException When option given doesn't exist - */ - private function addLongOption($name, $value) - { - if (!$this->definition->hasOption($name)) { - throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name)); - } - - $option = $this->definition->getOption($name); - - // Convert false values (from a previous call to substr()) to null - if (false === $value) { - $value = null; - } - - if (null !== $value && !$option->acceptValue()) { - throw new \RuntimeException(sprintf('The "--%s" option does not accept a value.', $name, $value)); - } - - if (null === $value && $option->acceptValue() && count($this->parsed)) { - // if option accepts an optional or mandatory argument - // let's see if there is one provided - $next = array_shift($this->parsed); - if (isset($next[0]) && '-' !== $next[0]) { - $value = $next; - } elseif (empty($next)) { - $value = ''; - } else { - array_unshift($this->parsed, $next); - } - } - - if (null === $value) { - if ($option->isValueRequired()) { - throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name)); - } - - if (!$option->isArray()) { - $value = $option->isValueOptional() ? $option->getDefault() : true; - } - } - - if ($option->isArray()) { - $this->options[$name][] = $value; - } else { - $this->options[$name] = $value; - } - } - - /** - * Returns the first argument from the raw parameters (not parsed). - * - * @return string The value of the first argument or null otherwise - */ - public function getFirstArgument() - { - foreach ($this->tokens as $token) { - if ($token && '-' === $token[0]) { - continue; - } - - return $token; - } - } - - /** - * Returns true if the raw parameters (not parsed) contain a value. - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * - * @return Boolean true if the value is contained in the raw parameters - */ - public function hasParameterOption($values) - { - $values = (array) $values; - - foreach ($this->tokens as $token) { - foreach ($values as $value) { - if ($token === $value || 0 === strpos($token, $value.'=')) { - return true; - } - } - } - - return false; - } - - /** - * Returns the value of a raw option (not parsed). - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found - * - * @return mixed The option value - */ - public function getParameterOption($values, $default = false) - { - $values = (array) $values; - - $tokens = $this->tokens; - while ($token = array_shift($tokens)) { - foreach ($values as $value) { - if ($token === $value || 0 === strpos($token, $value.'=')) { - if (false !== $pos = strpos($token, '=')) { - return substr($token, $pos + 1); - } - - return array_shift($tokens); - } - } - } - - return $default; - } - - /** - * Returns a stringified representation of the args passed to the command - * - * @return string - */ - public function __toString() - { - $self = $this; - $tokens = array_map(function ($token) use ($self) { - if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { - return $match[1] . $self->escapeToken($match[2]); - } - - if ($token && $token[0] !== '-') { - return $self->escapeToken($token); - } - - return $token; - }, $this->tokens); - - return implode(' ', $tokens); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * StringInput represents an input provided as a string. - * - * Usage: - * - * $input = new StringInput('foo --bar="foobar"'); - * - * @author Fabien Potencier - * - * @api - */ -class StringInput extends ArgvInput -{ - const REGEX_STRING = '([^\s]+?)(?:\s|(?setTokens($this->tokenize($input)); - - if (null !== $definition) { - $this->bind($definition); - } - } - - /** - * Tokenizes a string. - * - * @param string $input The input to tokenize - * - * @return array An array of tokens - * - * @throws \InvalidArgumentException When unable to parse input (should never happen) - */ - private function tokenize($input) - { - $tokens = array(); - $length = strlen($input); - $cursor = 0; - while ($cursor < $length) { - if (preg_match('/\s+/A', $input, $match, null, $cursor)) { - } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) { - $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2))); - } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) { - $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2)); - } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) { - $tokens[] = stripcslashes($match[1]); - } else { - // should never happen - // @codeCoverageIgnoreStart - throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10))); - // @codeCoverageIgnoreEnd - } - - $cursor += strlen($match[0]); - } - - return $tokens; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * InputInterface is the interface implemented by all input classes. - * - * @author Fabien Potencier - */ -interface InputInterface -{ - /** - * Returns the first argument from the raw parameters (not parsed). - * - * @return string The value of the first argument or null otherwise - */ - public function getFirstArgument(); - - /** - * Returns true if the raw parameters (not parsed) contain a value. - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The values to look for in the raw parameters (can be an array) - * - * @return Boolean true if the value is contained in the raw parameters - */ - public function hasParameterOption($values); - - /** - * Returns the value of a raw option (not parsed). - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found - * - * @return mixed The option value - */ - public function getParameterOption($values, $default = false); - - /** - * Binds the current Input instance with the given arguments and options. - * - * @param InputDefinition $definition A InputDefinition instance - */ - public function bind(InputDefinition $definition); - - /** - * Validates if arguments given are correct. - * - * Throws an exception when not enough arguments are given. - * - * @throws \RuntimeException - */ - public function validate(); - - /** - * Returns all the given arguments merged with the default values. - * - * @return array - */ - public function getArguments(); - - /** - * Gets argument by name. - * - * @param string $name The name of the argument - * - * @return mixed - */ - public function getArgument($name); - - /** - * Sets an argument value by name. - * - * @param string $name The argument name - * @param string $value The argument value - * - * @throws \InvalidArgumentException When argument given doesn't exist - */ - public function setArgument($name, $value); - - /** - * Returns true if an InputArgument object exists by name or position. - * - * @param string|integer $name The InputArgument name or position - * - * @return Boolean true if the InputArgument object exists, false otherwise - */ - public function hasArgument($name); - - /** - * Returns all the given options merged with the default values. - * - * @return array - */ - public function getOptions(); - - /** - * Gets an option by name. - * - * @param string $name The name of the option - * - * @return mixed - */ - public function getOption($name); - - /** - * Sets an option value by name. - * - * @param string $name The option name - * @param string $value The option value - * - * @throws \InvalidArgumentException When option given doesn't exist - */ - public function setOption($name, $value); - - /** - * Returns true if an InputOption object exists by name. - * - * @param string $name The InputOption name - * - * @return Boolean true if the InputOption object exists, false otherwise - */ - public function hasOption($name); - - /** - * Is this input means interactive? - * - * @return Boolean - */ - public function isInteractive(); - - /** - * Sets the input interactivity. - * - * @param Boolean $interactive If the input should be interactive - */ - public function setInteractive($interactive); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * Represents a command line option. - * - * @author Fabien Potencier - * - * @api - */ -class InputOption -{ - const VALUE_NONE = 1; - const VALUE_REQUIRED = 2; - const VALUE_OPTIONAL = 4; - const VALUE_IS_ARRAY = 8; - - private $name; - private $shortcut; - private $mode; - private $default; - private $description; - - /** - * Constructor. - * - * @param string $name The option name - * @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts - * @param integer $mode The option mode: One of the VALUE_* constants - * @param string $description A description text - * @param mixed $default The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE) - * - * @throws \InvalidArgumentException If option mode is invalid or incompatible - * - * @api - */ - public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null) - { - if (0 === strpos($name, '--')) { - $name = substr($name, 2); - } - - if (empty($name)) { - throw new \InvalidArgumentException('An option name cannot be empty.'); - } - - if (empty($shortcut)) { - $shortcut = null; - } - - if (null !== $shortcut) { - if (is_array($shortcut)) { - $shortcut = implode('|', $shortcut); - } - $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); - $shortcuts = array_filter($shortcuts); - $shortcut = implode('|', $shortcuts); - - if (empty($shortcut)) { - throw new \InvalidArgumentException('An option shortcut cannot be empty.'); - } - } - - if (null === $mode) { - $mode = self::VALUE_NONE; - } elseif (!is_int($mode) || $mode > 15 || $mode < 1) { - throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); - } - - $this->name = $name; - $this->shortcut = $shortcut; - $this->mode = $mode; - $this->description = $description; - - if ($this->isArray() && !$this->acceptValue()) { - throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); - } - - $this->setDefault($default); - } - - /** - * Returns the option shortcut. - * - * @return string The shortcut - */ - public function getShortcut() - { - return $this->shortcut; - } - - /** - * Returns the option name. - * - * @return string The name - */ - public function getName() - { - return $this->name; - } - - /** - * Returns true if the option accepts a value. - * - * @return Boolean true if value mode is not self::VALUE_NONE, false otherwise - */ - public function acceptValue() - { - return $this->isValueRequired() || $this->isValueOptional(); - } - - /** - * Returns true if the option requires a value. - * - * @return Boolean true if value mode is self::VALUE_REQUIRED, false otherwise - */ - public function isValueRequired() - { - return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); - } - - /** - * Returns true if the option takes an optional value. - * - * @return Boolean true if value mode is self::VALUE_OPTIONAL, false otherwise - */ - public function isValueOptional() - { - return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); - } - - /** - * Returns true if the option can take multiple values. - * - * @return Boolean true if mode is self::VALUE_IS_ARRAY, false otherwise - */ - public function isArray() - { - return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); - } - - /** - * Sets the default value. - * - * @param mixed $default The default value - * - * @throws \LogicException When incorrect default value is given - */ - public function setDefault($default = null) - { - if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { - throw new \LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.'); - } - - if ($this->isArray()) { - if (null === $default) { - $default = array(); - } elseif (!is_array($default)) { - throw new \LogicException('A default value for an array option must be an array.'); - } - } - - $this->default = $this->acceptValue() ? $default : false; - } - - /** - * Returns the default value. - * - * @return mixed The default value - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns the description text. - * - * @return string The description text - */ - public function getDescription() - { - return $this->description; - } - - /** - * Checks whether the given option equals this one - * - * @param InputOption $option option to compare - * @return Boolean - */ - public function equals(InputOption $option) - { - return $option->getName() === $this->getName() - && $option->getShortcut() === $this->getShortcut() - && $option->getDefault() === $this->getDefault() - && $option->isArray() === $this->isArray() - && $option->isValueRequired() === $this->isValueRequired() - && $option->isValueOptional() === $this->isValueOptional() - ; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * Input is the base class for all concrete Input classes. - * - * Three concrete classes are provided by default: - * - * * `ArgvInput`: The input comes from the CLI arguments (argv) - * * `StringInput`: The input is provided as a string - * * `ArrayInput`: The input is provided as an array - * - * @author Fabien Potencier - */ -abstract class Input implements InputInterface -{ - /** - * @var InputDefinition - */ - protected $definition; - protected $options = array(); - protected $arguments = array(); - protected $interactive = true; - - /** - * Constructor. - * - * @param InputDefinition $definition A InputDefinition instance - */ - public function __construct(InputDefinition $definition = null) - { - if (null === $definition) { - $this->definition = new InputDefinition(); - } else { - $this->bind($definition); - $this->validate(); - } - } - - /** - * Binds the current Input instance with the given arguments and options. - * - * @param InputDefinition $definition A InputDefinition instance - */ - public function bind(InputDefinition $definition) - { - $this->arguments = array(); - $this->options = array(); - $this->definition = $definition; - - $this->parse(); - } - - /** - * Processes command line arguments. - */ - abstract protected function parse(); - - /** - * Validates the input. - * - * @throws \RuntimeException When not enough arguments are given - */ - public function validate() - { - if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) { - throw new \RuntimeException('Not enough arguments.'); - } - } - - /** - * Checks if the input is interactive. - * - * @return Boolean Returns true if the input is interactive - */ - public function isInteractive() - { - return $this->interactive; - } - - /** - * Sets the input interactivity. - * - * @param Boolean $interactive If the input should be interactive - */ - public function setInteractive($interactive) - { - $this->interactive = (Boolean) $interactive; - } - - /** - * Returns the argument values. - * - * @return array An array of argument values - */ - public function getArguments() - { - return array_merge($this->definition->getArgumentDefaults(), $this->arguments); - } - - /** - * Returns the argument value for a given argument name. - * - * @param string $name The argument name - * - * @return mixed The argument value - * - * @throws \InvalidArgumentException When argument given doesn't exist - */ - public function getArgument($name) - { - if (!$this->definition->hasArgument($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); - } - - return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault(); - } - - /** - * Sets an argument value by name. - * - * @param string $name The argument name - * @param string $value The argument value - * - * @throws \InvalidArgumentException When argument given doesn't exist - */ - public function setArgument($name, $value) - { - if (!$this->definition->hasArgument($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); - } - - $this->arguments[$name] = $value; - } - - /** - * Returns true if an InputArgument object exists by name or position. - * - * @param string|integer $name The InputArgument name or position - * - * @return Boolean true if the InputArgument object exists, false otherwise - */ - public function hasArgument($name) - { - return $this->definition->hasArgument($name); - } - - /** - * Returns the options values. - * - * @return array An array of option values - */ - public function getOptions() - { - return array_merge($this->definition->getOptionDefaults(), $this->options); - } - - /** - * Returns the option value for a given option name. - * - * @param string $name The option name - * - * @return mixed The option value - * - * @throws \InvalidArgumentException When option given doesn't exist - */ - public function getOption($name) - { - if (!$this->definition->hasOption($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); - } - - return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); - } - - /** - * Sets an option value by name. - * - * @param string $name The option name - * @param string $value The option value - * - * @throws \InvalidArgumentException When option given doesn't exist - */ - public function setOption($name, $value) - { - if (!$this->definition->hasOption($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); - } - - $this->options[$name] = $value; - } - - /** - * Returns true if an InputOption object exists by name. - * - * @param string $name The InputOption name - * - * @return Boolean true if the InputOption object exists, false otherwise - */ - public function hasOption($name) - { - return $this->definition->hasOption($name); - } - - /** - * Escapes a token through escapeshellarg if it contains unsafe chars - * - * @param string $token - * - * @return string - */ - public function escapeToken($token) - { - return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * Represents a command line argument. - * - * @author Fabien Potencier - * - * @api - */ -class InputArgument -{ - const REQUIRED = 1; - const OPTIONAL = 2; - const IS_ARRAY = 4; - - private $name; - private $mode; - private $default; - private $description; - - /** - * Constructor. - * - * @param string $name The argument name - * @param integer $mode The argument mode: self::REQUIRED or self::OPTIONAL - * @param string $description A description text - * @param mixed $default The default value (for self::OPTIONAL mode only) - * - * @throws \InvalidArgumentException When argument mode is not valid - * - * @api - */ - public function __construct($name, $mode = null, $description = '', $default = null) - { - if (null === $mode) { - $mode = self::OPTIONAL; - } elseif (!is_int($mode) || $mode > 7 || $mode < 1) { - throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); - } - - $this->name = $name; - $this->mode = $mode; - $this->description = $description; - - $this->setDefault($default); - } - - /** - * Returns the argument name. - * - * @return string The argument name - */ - public function getName() - { - return $this->name; - } - - /** - * Returns true if the argument is required. - * - * @return Boolean true if parameter mode is self::REQUIRED, false otherwise - */ - public function isRequired() - { - return self::REQUIRED === (self::REQUIRED & $this->mode); - } - - /** - * Returns true if the argument can take multiple values. - * - * @return Boolean true if mode is self::IS_ARRAY, false otherwise - */ - public function isArray() - { - return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); - } - - /** - * Sets the default value. - * - * @param mixed $default The default value - * - * @throws \LogicException When incorrect default value is given - */ - public function setDefault($default = null) - { - if (self::REQUIRED === $this->mode && null !== $default) { - throw new \LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.'); - } - - if ($this->isArray()) { - if (null === $default) { - $default = array(); - } elseif (!is_array($default)) { - throw new \LogicException('A default value for an array argument must be an array.'); - } - } - - $this->default = $default; - } - - /** - * Returns the default value. - * - * @return mixed The default value - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns the description text. - * - * @return string The description text - */ - public function getDescription() - { - return $this->description; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * ArrayInput represents an input provided as an array. - * - * Usage: - * - * $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar')); - * - * @author Fabien Potencier - * - * @api - */ -class ArrayInput extends Input -{ - private $parameters; - - /** - * Constructor. - * - * @param array $parameters An array of parameters - * @param InputDefinition $definition A InputDefinition instance - * - * @api - */ - public function __construct(array $parameters, InputDefinition $definition = null) - { - $this->parameters = $parameters; - - parent::__construct($definition); - } - - /** - * Returns the first argument from the raw parameters (not parsed). - * - * @return string The value of the first argument or null otherwise - */ - public function getFirstArgument() - { - foreach ($this->parameters as $key => $value) { - if ($key && '-' === $key[0]) { - continue; - } - - return $value; - } - } - - /** - * Returns true if the raw parameters (not parsed) contain a value. - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The values to look for in the raw parameters (can be an array) - * - * @return Boolean true if the value is contained in the raw parameters - */ - public function hasParameterOption($values) - { - $values = (array) $values; - - foreach ($this->parameters as $k => $v) { - if (!is_int($k)) { - $v = $k; - } - - if (in_array($v, $values)) { - return true; - } - } - - return false; - } - - /** - * Returns the value of a raw option (not parsed). - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found - * - * @return mixed The option value - */ - public function getParameterOption($values, $default = false) - { - $values = (array) $values; - - foreach ($this->parameters as $k => $v) { - if (is_int($k) && in_array($v, $values)) { - return true; - } elseif (in_array($k, $values)) { - return $v; - } - } - - return $default; - } - - /** - * Returns a stringified representation of the args passed to the command - * - * @return string - */ - public function __toString() - { - $params = array(); - foreach ($this->parameters as $param => $val) { - if ($param && '-' === $param[0]) { - $params[] = $param . ('' != $val ? '='.$this->escapeToken($val) : ''); - } else { - $params[] = $this->escapeToken($val); - } - } - - return implode(' ', $params); - } - - /** - * Processes command line arguments. - */ - protected function parse() - { - foreach ($this->parameters as $key => $value) { - if (0 === strpos($key, '--')) { - $this->addLongOption(substr($key, 2), $value); - } elseif ('-' === $key[0]) { - $this->addShortOption(substr($key, 1), $value); - } else { - $this->addArgument($key, $value); - } - } - } - - /** - * Adds a short option value. - * - * @param string $shortcut The short option key - * @param mixed $value The value for the option - * - * @throws \InvalidArgumentException When option given doesn't exist - */ - private function addShortOption($shortcut, $value) - { - if (!$this->definition->hasShortcut($shortcut)) { - throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); - } - - $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); - } - - /** - * Adds a long option value. - * - * @param string $name The long option key - * @param mixed $value The value for the option - * - * @throws \InvalidArgumentException When option given doesn't exist - * @throws \InvalidArgumentException When a required value is missing - */ - private function addLongOption($name, $value) - { - if (!$this->definition->hasOption($name)) { - throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); - } - - $option = $this->definition->getOption($name); - - if (null === $value) { - if ($option->isValueRequired()) { - throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name)); - } - - $value = $option->isValueOptional() ? $option->getDefault() : true; - } - - $this->options[$name] = $value; - } - - /** - * Adds an argument value. - * - * @param string $name The argument name - * @param mixed $value The value for the argument - * - * @throws \InvalidArgumentException When argument given doesn't exist - */ - private function addArgument($name, $value) - { - if (!$this->definition->hasArgument($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); - } - - $this->arguments[$name] = $value; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -if (!defined('JSON_UNESCAPED_UNICODE')) { - define('JSON_UNESCAPED_SLASHES', 64); - define('JSON_UNESCAPED_UNICODE', 256); -} - -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; -use Symfony\Component\Console\Output\BufferedOutput; - -/** - * A InputDefinition represents a set of valid command line arguments and options. - * - * Usage: - * - * $definition = new InputDefinition(array( - * new InputArgument('name', InputArgument::REQUIRED), - * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), - * )); - * - * @author Fabien Potencier - * - * @api - */ -class InputDefinition -{ - private $arguments; - private $requiredCount; - private $hasAnArrayArgument = false; - private $hasOptional; - private $options; - private $shortcuts; - - /** - * Constructor. - * - * @param array $definition An array of InputArgument and InputOption instance - * - * @api - */ - public function __construct(array $definition = array()) - { - $this->setDefinition($definition); - } - - /** - * Sets the definition of the input. - * - * @param array $definition The definition array - * - * @api - */ - public function setDefinition(array $definition) - { - $arguments = array(); - $options = array(); - foreach ($definition as $item) { - if ($item instanceof InputOption) { - $options[] = $item; - } else { - $arguments[] = $item; - } - } - - $this->setArguments($arguments); - $this->setOptions($options); - } - - /** - * Sets the InputArgument objects. - * - * @param InputArgument[] $arguments An array of InputArgument objects - * - * @api - */ - public function setArguments($arguments = array()) - { - $this->arguments = array(); - $this->requiredCount = 0; - $this->hasOptional = false; - $this->hasAnArrayArgument = false; - $this->addArguments($arguments); - } - - /** - * Adds an array of InputArgument objects. - * - * @param InputArgument[] $arguments An array of InputArgument objects - * - * @api - */ - public function addArguments($arguments = array()) - { - if (null !== $arguments) { - foreach ($arguments as $argument) { - $this->addArgument($argument); - } - } - } - - /** - * Adds an InputArgument object. - * - * @param InputArgument $argument An InputArgument object - * - * @throws \LogicException When incorrect argument is given - * - * @api - */ - public function addArgument(InputArgument $argument) - { - if (isset($this->arguments[$argument->getName()])) { - throw new \LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName())); - } - - if ($this->hasAnArrayArgument) { - throw new \LogicException('Cannot add an argument after an array argument.'); - } - - if ($argument->isRequired() && $this->hasOptional) { - throw new \LogicException('Cannot add a required argument after an optional one.'); - } - - if ($argument->isArray()) { - $this->hasAnArrayArgument = true; - } - - if ($argument->isRequired()) { - ++$this->requiredCount; - } else { - $this->hasOptional = true; - } - - $this->arguments[$argument->getName()] = $argument; - } - - /** - * Returns an InputArgument by name or by position. - * - * @param string|integer $name The InputArgument name or position - * - * @return InputArgument An InputArgument object - * - * @throws \InvalidArgumentException When argument given doesn't exist - * - * @api - */ - public function getArgument($name) - { - if (!$this->hasArgument($name)) { - throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); - } - - $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; - - return $arguments[$name]; - } - - /** - * Returns true if an InputArgument object exists by name or position. - * - * @param string|integer $name The InputArgument name or position - * - * @return Boolean true if the InputArgument object exists, false otherwise - * - * @api - */ - public function hasArgument($name) - { - $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; - - return isset($arguments[$name]); - } - - /** - * Gets the array of InputArgument objects. - * - * @return InputArgument[] An array of InputArgument objects - * - * @api - */ - public function getArguments() - { - return $this->arguments; - } - - /** - * Returns the number of InputArguments. - * - * @return integer The number of InputArguments - */ - public function getArgumentCount() - { - return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments); - } - - /** - * Returns the number of required InputArguments. - * - * @return integer The number of required InputArguments - */ - public function getArgumentRequiredCount() - { - return $this->requiredCount; - } - - /** - * Gets the default values. - * - * @return array An array of default values - */ - public function getArgumentDefaults() - { - $values = array(); - foreach ($this->arguments as $argument) { - $values[$argument->getName()] = $argument->getDefault(); - } - - return $values; - } - - /** - * Sets the InputOption objects. - * - * @param InputOption[] $options An array of InputOption objects - * - * @api - */ - public function setOptions($options = array()) - { - $this->options = array(); - $this->shortcuts = array(); - $this->addOptions($options); - } - - /** - * Adds an array of InputOption objects. - * - * @param InputOption[] $options An array of InputOption objects - * - * @api - */ - public function addOptions($options = array()) - { - foreach ($options as $option) { - $this->addOption($option); - } - } - - /** - * Adds an InputOption object. - * - * @param InputOption $option An InputOption object - * - * @throws \LogicException When option given already exist - * - * @api - */ - public function addOption(InputOption $option) - { - if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { - throw new \LogicException(sprintf('An option named "%s" already exists.', $option->getName())); - } - - if ($option->getShortcut()) { - foreach (explode('|', $option->getShortcut()) as $shortcut) { - if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) { - throw new \LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut)); - } - } - } - - $this->options[$option->getName()] = $option; - if ($option->getShortcut()) { - foreach (explode('|', $option->getShortcut()) as $shortcut) { - $this->shortcuts[$shortcut] = $option->getName(); - } - } - } - - /** - * Returns an InputOption by name. - * - * @param string $name The InputOption name - * - * @return InputOption A InputOption object - * - * @throws \InvalidArgumentException When option given doesn't exist - * - * @api - */ - public function getOption($name) - { - if (!$this->hasOption($name)) { - throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); - } - - return $this->options[$name]; - } - - /** - * Returns true if an InputOption object exists by name. - * - * @param string $name The InputOption name - * - * @return Boolean true if the InputOption object exists, false otherwise - * - * @api - */ - public function hasOption($name) - { - return isset($this->options[$name]); - } - - /** - * Gets the array of InputOption objects. - * - * @return InputOption[] An array of InputOption objects - * - * @api - */ - public function getOptions() - { - return $this->options; - } - - /** - * Returns true if an InputOption object exists by shortcut. - * - * @param string $name The InputOption shortcut - * - * @return Boolean true if the InputOption object exists, false otherwise - */ - public function hasShortcut($name) - { - return isset($this->shortcuts[$name]); - } - - /** - * Gets an InputOption by shortcut. - * - * @param string $shortcut the Shortcut name - * - * @return InputOption An InputOption object - */ - public function getOptionForShortcut($shortcut) - { - return $this->getOption($this->shortcutToName($shortcut)); - } - - /** - * Gets an array of default values. - * - * @return array An array of all default values - */ - public function getOptionDefaults() - { - $values = array(); - foreach ($this->options as $option) { - $values[$option->getName()] = $option->getDefault(); - } - - return $values; - } - - /** - * Returns the InputOption name given a shortcut. - * - * @param string $shortcut The shortcut - * - * @return string The InputOption name - * - * @throws \InvalidArgumentException When option given does not exist - */ - private function shortcutToName($shortcut) - { - if (!isset($this->shortcuts[$shortcut])) { - throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); - } - - return $this->shortcuts[$shortcut]; - } - - /** - * Gets the synopsis. - * - * @return string The synopsis - */ - public function getSynopsis() - { - $elements = array(); - foreach ($this->getOptions() as $option) { - $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; - $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName()); - } - - foreach ($this->getArguments() as $argument) { - $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : '')); - - if ($argument->isArray()) { - $elements[] = sprintf('... [%sN]', $argument->getName()); - } - } - - return implode(' ', $elements); - } - - /** - * Returns a textual representation of the InputDefinition. - * - * @return string A string representing the InputDefinition - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asText() - { - $descriptor = new TextDescriptor(); - $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); - $descriptor->describe($output, $this, array('raw_output' => true)); - - return $output->fetch(); - } - - /** - * Returns an XML representation of the InputDefinition. - * - * @param Boolean $asDom Whether to return a DOM or an XML string - * - * @return string|\DOMDocument An XML string representing the InputDefinition - * - * @deprecated Deprecated since version 2.3, to be removed in 3.0. - */ - public function asXml($asDom = false) - { - $descriptor = new XmlDescriptor(); - - if ($asDom) { - return $descriptor->getInputDefinitionDocument($this); - } - - $output = new BufferedOutput(); - $descriptor->describe($output, $this); - - return $output->fetch(); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * InputAwareInterface should be implemented by classes that depends on the - * Console Input. - * - * @author Wouter J - */ -interface InputAwareInterface -{ - /** - * Sets the Console Input. - * - * @param InputInterface - */ - public function setInput(InputInterface $input); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter interface for console output. - * - * @author Konstantin Kudryashov - * - * @api - */ -interface OutputFormatterInterface -{ - /** - * Sets the decorated flag. - * - * @param Boolean $decorated Whether to decorate the messages or not - * - * @api - */ - public function setDecorated($decorated); - - /** - * Gets the decorated flag. - * - * @return Boolean true if the output will decorate messages, false otherwise - * - * @api - */ - public function isDecorated(); - - /** - * Sets a new style. - * - * @param string $name The style name - * @param OutputFormatterStyleInterface $style The style instance - * - * @api - */ - public function setStyle($name, OutputFormatterStyleInterface $style); - - /** - * Checks if output formatter has style with specified name. - * - * @param string $name - * - * @return Boolean - * - * @api - */ - public function hasStyle($name); - - /** - * Gets style options from style with specified name. - * - * @param string $name - * - * @return OutputFormatterStyleInterface - * - * @api - */ - public function getStyle($name); - - /** - * Formats a message according to the given styles. - * - * @param string $message The message to style - * - * @return string The styled message - * - * @api - */ - public function format($message); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter class for console output. - * - * @author Konstantin Kudryashov - * - * @api - */ -class OutputFormatter implements OutputFormatterInterface -{ - /** - * The pattern to phrase the format. - */ - const FORMAT_PATTERN = '#(\\\\?)<(/?)([a-z][a-z0-9_=;-]*)?>((?: [^<\\\\]+ | (?!<(?:/?[a-z]|/>)). | .(?<=\\\\<) )*)#isx'; - - private $decorated; - private $styles = array(); - private $styleStack; - - /** - * Escapes "<" special char in given text. - * - * @param string $text Text to escape - * - * @return string Escaped text - */ - public static function escape($text) - { - return preg_replace('/([^\\\\]?) FormatterStyle" instances - * - * @api - */ - public function __construct($decorated = false, array $styles = array()) - { - $this->decorated = (Boolean) $decorated; - - $this->setStyle('error', new OutputFormatterStyle('white', 'red')); - $this->setStyle('info', new OutputFormatterStyle('green')); - $this->setStyle('comment', new OutputFormatterStyle('yellow')); - $this->setStyle('question', new OutputFormatterStyle('black', 'cyan')); - - foreach ($styles as $name => $style) { - $this->setStyle($name, $style); - } - - $this->styleStack = new OutputFormatterStyleStack(); - } - - /** - * Sets the decorated flag. - * - * @param Boolean $decorated Whether to decorate the messages or not - * - * @api - */ - public function setDecorated($decorated) - { - $this->decorated = (Boolean) $decorated; - } - - /** - * Gets the decorated flag. - * - * @return Boolean true if the output will decorate messages, false otherwise - * - * @api - */ - public function isDecorated() - { - return $this->decorated; - } - - /** - * Sets a new style. - * - * @param string $name The style name - * @param OutputFormatterStyleInterface $style The style instance - * - * @api - */ - public function setStyle($name, OutputFormatterStyleInterface $style) - { - $this->styles[strtolower($name)] = $style; - } - - /** - * Checks if output formatter has style with specified name. - * - * @param string $name - * - * @return Boolean - * - * @api - */ - public function hasStyle($name) - { - return isset($this->styles[strtolower($name)]); - } - - /** - * Gets style options from style with specified name. - * - * @param string $name - * - * @return OutputFormatterStyleInterface - * - * @throws \InvalidArgumentException When style isn't defined - * - * @api - */ - public function getStyle($name) - { - if (!$this->hasStyle($name)) { - throw new \InvalidArgumentException(sprintf('Undefined style: %s', $name)); - } - - return $this->styles[strtolower($name)]; - } - - /** - * Formats a message according to the given styles. - * - * @param string $message The message to style - * - * @return string The styled message - * - * @api - */ - public function format($message) - { - $message = preg_replace_callback(self::FORMAT_PATTERN, array($this, 'replaceStyle'), $message); - - return str_replace('\\<', '<', $message); - } - - /** - * @return OutputFormatterStyleStack - */ - public function getStyleStack() - { - return $this->styleStack; - } - - /** - * Replaces style of the output. - * - * All escaped tags and tags that reference unknown styles are kept as is. - * - * @param array $match - * - * @return string The replaced style - */ - private function replaceStyle($match) - { - // we got "\<" escaped char - if ('\\' === $match[1]) { - return $this->applyCurrentStyle($match[0]); - } - - if ('' === $match[3]) { - if ('/' === $match[2]) { - // we got "" tag - $this->styleStack->pop(); - - return $this->applyCurrentStyle($match[4]); - } - - // we got "<>" tag - return '<>'.$this->applyCurrentStyle($match[4]); - } - - if (isset($this->styles[strtolower($match[3])])) { - $style = $this->styles[strtolower($match[3])]; - } else { - $style = $this->createStyleFromString($match[3]); - - if (false === $style) { - return $this->applyCurrentStyle($match[0]); - } - } - - if ('/' === $match[2]) { - $this->styleStack->pop($style); - } else { - $this->styleStack->push($style); - } - - return $this->applyCurrentStyle($match[4]); - } - - /** - * Tries to create new style instance from string. - * - * @param string $string - * - * @return OutputFormatterStyle|Boolean false if string is not format string - */ - private function createStyleFromString($string) - { - if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) { - return false; - } - - $style = new OutputFormatterStyle(); - foreach ($matches as $match) { - array_shift($match); - - if ('fg' == $match[0]) { - $style->setForeground($match[1]); - } elseif ('bg' == $match[0]) { - $style->setBackground($match[1]); - } else { - $style->setOption($match[1]); - } - } - - return $style; - } - - /** - * Applies current style from stack to text, if must be applied. - * - * @param string $text Input text - * - * @return string Styled text - */ - private function applyCurrentStyle($text) - { - return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter style class for defining styles. - * - * @author Konstantin Kudryashov - * - * @api - */ -class OutputFormatterStyle implements OutputFormatterStyleInterface -{ - private static $availableForegroundColors = array( - 'black' => 30, - 'red' => 31, - 'green' => 32, - 'yellow' => 33, - 'blue' => 34, - 'magenta' => 35, - 'cyan' => 36, - 'white' => 37 - ); - private static $availableBackgroundColors = array( - 'black' => 40, - 'red' => 41, - 'green' => 42, - 'yellow' => 43, - 'blue' => 44, - 'magenta' => 45, - 'cyan' => 46, - 'white' => 47 - ); - private static $availableOptions = array( - 'bold' => 1, - 'underscore' => 4, - 'blink' => 5, - 'reverse' => 7, - 'conceal' => 8 - ); - - private $foreground; - private $background; - private $options = array(); - - /** - * Initializes output formatter style. - * - * @param string|null $foreground The style foreground color name - * @param string|null $background The style background color name - * @param array $options The style options - * - * @api - */ - public function __construct($foreground = null, $background = null, array $options = array()) - { - if (null !== $foreground) { - $this->setForeground($foreground); - } - if (null !== $background) { - $this->setBackground($background); - } - if (count($options)) { - $this->setOptions($options); - } - } - - /** - * Sets style foreground color. - * - * @param string|null $color The color name - * - * @throws \InvalidArgumentException When the color name isn't defined - * - * @api - */ - public function setForeground($color = null) - { - if (null === $color) { - $this->foreground = null; - - return; - } - - if (!isset(static::$availableForegroundColors[$color])) { - throw new \InvalidArgumentException(sprintf( - 'Invalid foreground color specified: "%s". Expected one of (%s)', - $color, - implode(', ', array_keys(static::$availableForegroundColors)) - )); - } - - $this->foreground = static::$availableForegroundColors[$color]; - } - - /** - * Sets style background color. - * - * @param string|null $color The color name - * - * @throws \InvalidArgumentException When the color name isn't defined - * - * @api - */ - public function setBackground($color = null) - { - if (null === $color) { - $this->background = null; - - return; - } - - if (!isset(static::$availableBackgroundColors[$color])) { - throw new \InvalidArgumentException(sprintf( - 'Invalid background color specified: "%s". Expected one of (%s)', - $color, - implode(', ', array_keys(static::$availableBackgroundColors)) - )); - } - - $this->background = static::$availableBackgroundColors[$color]; - } - - /** - * Sets some specific style option. - * - * @param string $option The option name - * - * @throws \InvalidArgumentException When the option name isn't defined - * - * @api - */ - public function setOption($option) - { - if (!isset(static::$availableOptions[$option])) { - throw new \InvalidArgumentException(sprintf( - 'Invalid option specified: "%s". Expected one of (%s)', - $option, - implode(', ', array_keys(static::$availableOptions)) - )); - } - - if (false === array_search(static::$availableOptions[$option], $this->options)) { - $this->options[] = static::$availableOptions[$option]; - } - } - - /** - * Unsets some specific style option. - * - * @param string $option The option name - * - * @throws \InvalidArgumentException When the option name isn't defined - * - */ - public function unsetOption($option) - { - if (!isset(static::$availableOptions[$option])) { - throw new \InvalidArgumentException(sprintf( - 'Invalid option specified: "%s". Expected one of (%s)', - $option, - implode(', ', array_keys(static::$availableOptions)) - )); - } - - $pos = array_search(static::$availableOptions[$option], $this->options); - if (false !== $pos) { - unset($this->options[$pos]); - } - } - - /** - * Sets multiple style options at once. - * - * @param array $options - */ - public function setOptions(array $options) - { - $this->options = array(); - - foreach ($options as $option) { - $this->setOption($option); - } - } - - /** - * Applies the style to a given text. - * - * @param string $text The text to style - * - * @return string - */ - public function apply($text) - { - $codes = array(); - - if (null !== $this->foreground) { - $codes[] = $this->foreground; - } - if (null !== $this->background) { - $codes[] = $this->background; - } - if (count($this->options)) { - $codes = array_merge($codes, $this->options); - } - - if (0 === count($codes)) { - return $text; - } - - return sprintf("\033[%sm%s\033[0m", implode(';', $codes), $text); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * @author Jean-François Simon - */ -class OutputFormatterStyleStack -{ - /** - * @var OutputFormatterStyleInterface[] - */ - private $styles; - - /** - * @var OutputFormatterStyleInterface - */ - private $emptyStyle; - - /** - * Constructor. - * - * @param OutputFormatterStyleInterface|null $emptyStyle - */ - public function __construct(OutputFormatterStyleInterface $emptyStyle = null) - { - $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle(); - $this->reset(); - } - - /** - * Resets stack (ie. empty internal arrays). - */ - public function reset() - { - $this->styles = array(); - } - - /** - * Pushes a style in the stack. - * - * @param OutputFormatterStyleInterface $style - */ - public function push(OutputFormatterStyleInterface $style) - { - $this->styles[] = $style; - } - - /** - * Pops a style from the stack. - * - * @param OutputFormatterStyleInterface|null $style - * - * @return OutputFormatterStyleInterface - * - * @throws \InvalidArgumentException When style tags incorrectly nested - */ - public function pop(OutputFormatterStyleInterface $style = null) - { - if (empty($this->styles)) { - return $this->emptyStyle; - } - - if (null === $style) { - return array_pop($this->styles); - } - - foreach (array_reverse($this->styles, true) as $index => $stackedStyle) { - if ($style->apply('') === $stackedStyle->apply('')) { - $this->styles = array_slice($this->styles, 0, $index); - - return $stackedStyle; - } - } - - throw new \InvalidArgumentException('Incorrectly nested style tag found.'); - } - - /** - * Computes current style with stacks top codes. - * - * @return OutputFormatterStyle - */ - public function getCurrent() - { - if (empty($this->styles)) { - return $this->emptyStyle; - } - - return $this->styles[count($this->styles)-1]; - } - - /** - * @param OutputFormatterStyleInterface $emptyStyle - * - * @return OutputFormatterStyleStack - */ - public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle) - { - $this->emptyStyle = $emptyStyle; - - return $this; - } - - /** - * @return OutputFormatterStyleInterface - */ - public function getEmptyStyle() - { - return $this->emptyStyle; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter style interface for defining styles. - * - * @author Konstantin Kudryashov - * - * @api - */ -interface OutputFormatterStyleInterface -{ - /** - * Sets style foreground color. - * - * @param string $color The color name - * - * @api - */ - public function setForeground($color = null); - - /** - * Sets style background color. - * - * @param string $color The color name - * - * @api - */ - public function setBackground($color = null); - - /** - * Sets some specific style option. - * - * @param string $option The option name - * - * @api - */ - public function setOption($option); - - /** - * Unsets some specific style option. - * - * @param string $option The option name - */ - public function unsetOption($option); - - /** - * Sets multiple style options at once. - * - * @param array $options - */ - public function setOptions(array $options); - - /** - * Applies the style to a given text. - * - * @param string $text The text to style - * - * @return string - */ - public function apply($text); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\EventDispatcher\Event; - -/** - * Allows to inspect input and output of a command. - * - * @author Francesco Levorato - */ -class ConsoleEvent extends Event -{ - protected $command; - - private $input; - private $output; - - public function __construct(Command $command, InputInterface $input, OutputInterface $output) - { - $this->command = $command; - $this->input = $input; - $this->output = $output; - } - - /** - * Gets the command that is executed. - * - * @return Command A Command instance - */ - public function getCommand() - { - return $this->command; - } - - /** - * Gets the input instance. - * - * @return InputInterface An InputInterface instance - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance. - * - * @return OutputInterface An OutputInterface instance - */ - public function getOutput() - { - return $this->output; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -/** - * Allows to do things before the command is executed. - * - * @author Fabien Potencier - */ -class ConsoleCommandEvent extends ConsoleEvent -{ -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Allows to manipulate the exit code of a command after its execution. - * - * @author Francesco Levorato - */ -class ConsoleTerminateEvent extends ConsoleEvent -{ - /** - * The exit code of the command. - * - * @var integer - */ - private $exitCode; - - public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode) - { - parent::__construct($command, $input, $output); - - $this->setExitCode($exitCode); - } - - /** - * Sets the exit code. - * - * @param integer $exitCode The command exit code - */ - public function setExitCode($exitCode) - { - $this->exitCode = (int) $exitCode; - } - - /** - * Gets the exit code. - * - * @return integer The command exit code - */ - public function getExitCode() - { - return $this->exitCode; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Allows to handle exception thrown in a command. - * - * @author Fabien Potencier - */ -class ConsoleExceptionEvent extends ConsoleEvent -{ - private $exception; - private $exitCode; - - public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode) - { - parent::__construct($command, $input, $output); - - $this->setException($exception); - $this->exitCode = (int) $exitCode; - } - - /** - * Returns the thrown exception. - * - * @return \Exception The thrown exception - */ - public function getException() - { - return $this->exception; - } - - /** - * Replaces the thrown exception. - * - * This exception will be thrown if no response is set in the event. - * - * @param \Exception $exception The thrown exception - */ - public function setException(\Exception $exception) - { - $this->exception = $exception; - } - - /** - * Gets the exit code. - * - * @return integer The command exit code - */ - public function getExitCode() - { - return $this->exitCode; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tester; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Output\StreamOutput; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Eases the testing of console commands. - * - * @author Fabien Potencier - */ -class CommandTester -{ - private $command; - private $input; - private $output; - private $statusCode; - - /** - * Constructor. - * - * @param Command $command A Command instance to test. - */ - public function __construct(Command $command) - { - $this->command = $command; - } - - /** - * Executes the command. - * - * Available options: - * - * * interactive: Sets the input interactive flag - * * decorated: Sets the output decorated flag - * * verbosity: Sets the output verbosity flag - * - * @param array $input An array of arguments and options - * @param array $options An array of options - * - * @return integer The command exit code - */ - public function execute(array $input, array $options = array()) - { - // set the command name automatically if the application requires - // this argument and no command name was passed - if (!isset($input['command']) - && (null !== $application = $this->command->getApplication()) - && $application->getDefinition()->hasArgument('command') - ) { - $input['command'] = $this->command->getName(); - } - - $this->input = new ArrayInput($input); - if (isset($options['interactive'])) { - $this->input->setInteractive($options['interactive']); - } - - $this->output = new StreamOutput(fopen('php://memory', 'w', false)); - if (isset($options['decorated'])) { - $this->output->setDecorated($options['decorated']); - } - if (isset($options['verbosity'])) { - $this->output->setVerbosity($options['verbosity']); - } - - return $this->statusCode = $this->command->run($this->input, $this->output); - } - - /** - * Gets the display returned by the last execution of the command. - * - * @param Boolean $normalize Whether to normalize end of lines to \n or not - * - * @return string The display - */ - public function getDisplay($normalize = false) - { - rewind($this->output->getStream()); - - $display = stream_get_contents($this->output->getStream()); - - if ($normalize) { - $display = str_replace(PHP_EOL, "\n", $display); - } - - return $display; - } - - /** - * Gets the input instance used by the last execution of the command. - * - * @return InputInterface The current input instance - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance used by the last execution of the command. - * - * @return OutputInterface The current output instance - */ - public function getOutput() - { - return $this->output; - } - - /** - * Gets the status code returned by the last execution of the application. - * - * @return integer The status code - */ - public function getStatusCode() - { - return $this->statusCode; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tester; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\StreamOutput; - -/** - * Eases the testing of console applications. - * - * When testing an application, don't forget to disable the auto exit flag: - * - * $application = new Application(); - * $application->setAutoExit(false); - * - * @author Fabien Potencier - */ -class ApplicationTester -{ - private $application; - private $input; - private $output; - private $statusCode; - - /** - * Constructor. - * - * @param Application $application An Application instance to test. - */ - public function __construct(Application $application) - { - $this->application = $application; - } - - /** - * Executes the application. - * - * Available options: - * - * * interactive: Sets the input interactive flag - * * decorated: Sets the output decorated flag - * * verbosity: Sets the output verbosity flag - * - * @param array $input An array of arguments and options - * @param array $options An array of options - * - * @return integer The command exit code - */ - public function run(array $input, $options = array()) - { - $this->input = new ArrayInput($input); - if (isset($options['interactive'])) { - $this->input->setInteractive($options['interactive']); - } - - $this->output = new StreamOutput(fopen('php://memory', 'w', false)); - if (isset($options['decorated'])) { - $this->output->setDecorated($options['decorated']); - } - if (isset($options['verbosity'])) { - $this->output->setVerbosity($options['verbosity']); - } - - return $this->statusCode = $this->application->run($this->input, $this->output); - } - - /** - * Gets the display returned by the last execution of the application. - * - * @param Boolean $normalize Whether to normalize end of lines to \n or not - * - * @return string The display - */ - public function getDisplay($normalize = false) - { - rewind($this->output->getStream()); - - $display = stream_get_contents($this->output->getStream()); - - if ($normalize) { - $display = str_replace(PHP_EOL, "\n", $display); - } - - return $display; - } - - /** - * Gets the input instance used by the last execution of the application. - * - * @return InputInterface The current input instance - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance used by the last execution of the application. - * - * @return OutputInterface The current output instance - */ - public function getOutput() - { - return $this->output; - } - - /** - * Gets the status code returned by the last execution of the application. - * - * @return integer The status code - */ - public function getStatusCode() - { - return $this->statusCode; - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package Git - * @author Sebastian Bergmann - * @copyright 2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://www.github.com/sebastianbergmann/git - */ - -namespace SebastianBergmann; - -/** - * @package Git - * @author Sebastian Bergmann - * @copyright 2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @link http://www.github.com/sebastianbergmann/git - */ -class Git -{ - /** - * @var string - */ - private $repositoryPath; - - /** - * @param string $repositoryPath - */ - public function __construct($repositoryPath) - { - $this->repositoryPath = realpath($repositoryPath); - } - - /** - * @param string $revision - */ - public function checkout($revision) - { - $this->execute('git checkout ' . $revision . ' 2>&1', $output, $return); - } - - /** - * @return string - */ - public function getCurrentBranch() - { - $this->execute('git status --short --branch', $output, $return); - - $tmp = explode(' ', $output[0]); - - return $tmp[1]; - } - - /** - * @param string $from - * @param string $to - * @return string - */ - public function getDiff($from, $to) - { - $this->execute( - 'git diff --no-ext-diff ' . $from . ' ' . $to, - $output, - $return - ); - - return join("\n", $output); - } - - /** - * @return array - */ - public function getRevisions() - { - $this->execute( - 'git log --no-merges --date-order --reverse', - $output, - $return - ); - - $numLines = count($output); - $revisions = array(); - - for ($i = 0; $i < $numLines; $i++) { - $tmp = explode(' ', $output[$i]); - - if (count($tmp) == 2 && $tmp[0] == 'commit') { - $sha1 = $tmp[1]; - } elseif (count($tmp) == 4 && $tmp[0] == 'Author:') { - $author = join(' ', array_slice($tmp, 1)); - } elseif (count($tmp) == 9 && $tmp[0] == 'Date:') { - - $revisions[] = array( - 'author' => $author, - 'date' => \DateTime::createFromFormat( - 'D M j H:i:s Y O', - join(' ', array_slice($tmp, 3)) - ), - 'sha1' => $sha1, - 'message' => isset($output[$i+2]) ? trim($output[$i+2]) : '' - ); - } - } - - return $revisions; - } - - /** - * @param string $command - * @param array $output - * @param integer $returnValue - */ - private function execute($command, &$output, &$returnValue) - { - $cwd = getcwd(); - chdir($this->repositoryPath); - exec($command, $output, $returnValue); - chdir($cwd); - } -} - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license BSD License - */ - -namespace TheSeer\fDOM { - - /** - * fDOMException - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMException extends \Exception { - - const LoadError = 1; - const ParseError = 2; - const SaveError = 3; - const QueryError = 4; - const RegistrationFailed = 5; - const NoDOMXPath = 6; - const UnboundPrefix = 7; - const SetFailedError = 8; - const NameInvalid = 9; - - /** - * List of libxml error objects - * - * @var array - */ - private $errorList; - - - /** - * Full Error message - * - * @var string - */ - private $fullMessage = null; - - - /** - * Short Error Message - * - * @var string - */ - private $shortMessage = null; - - - private static $fullMesageMode = true; - - /** - * Constructor - * - * @param string $message Exception message - * @param integer $code Exception code - * @param Exception $chain optional chained exception - * - */ - public function __construct($message, $code = 0, \Exception $chain = NULL) { - $this->shortMessage = $message; - $this->errorList = libxml_get_errors(); - libxml_clear_errors(); - parent :: __construct($message, $code, $chain); - - $this->fullMessage = $message."\n\n"; - - foreach ($this->errorList as $error) { - // hack, skip "attempt to load external pseudo error" - if ($error->code=='1543') { - continue; - } - - if (empty($error->file)) { - $this->fullMessage .= '[XML-STRING] '; - } else { - $this->fullMessage .= '['.$error->file.'] '; - } - - $this->fullMessage .= '[Line: '.$error->line.' - Column: '.$error->column.'] '; - - switch ($error->level) { - case LIBXML_ERR_WARNING: - $this->fullMessage .= "Warning $error->code: "; - break; - case LIBXML_ERR_ERROR: - $this->fullMessage .= "Error $error->code: "; - break; - case LIBXML_ERR_FATAL: - $this->fullMessage .= "Fatal Error $error->code: "; - break; - } - - $this->fullMessage .= str_replace("\n", '', $error->message)."\n"; - - if (self::$fullMesageMode) { - $this->message = $this->fullMessage; - } - - } - } - - /** - * Accessor to fullMessage - * - * @return string - */ - public function getFullMessage() { - return $this->fullMessage; - } - - /** - * Access to shortMessage - * - * @return string - */ - public function getShortMessage() { - return $this->shortMessage; - } - - /** - * Accessor to errorList objets - * - * @return array - */ - public function getErrorList() { - return $this->errorList; - } - - /** - * Toggle wehter getMessage() should return full or only exception message - * - * @param boolean $full Flag to enable or disable full message output - * - * @return void - */ - public function toggleFullMessage($full = true) { - $this->message = $full ? $this->fullMessage : $this->shortMessage; - } - - /** - * Magic method for string context - * - * @return string - */ - public function __toString() { - return $this->fullMessage; - } - - } // fDOMException - -} - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - class XPathQueryException extends \Exception { - const KeyNotFound = 1; - } - -} - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * fDOMDocument extension to PHP's DOMDocument. - * This class adds various convenience methods to simplify APIs - * It is set to final since further extending it would even more - * break the Object structure after use of registerNodeClass. - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMDocument extends \DOMDocument { - - /** - * XPath Object instance - * - * @var fDOMXPath - */ - private $xp = NULL; - - /** - * List of registered prefixes and their namespace uri - * @var Array - */ - private $prefixes = array(); - - /** - * Extended DOMDocument constructor - * - * @param string $version XML Version, should be 1.0 - * @param string $encoding Encoding, defaults to utf-8 - * @param array $streamOptions optional stream options array - * - * @return fDOMDocument - */ - public function __construct($version = '1.0', $encoding = 'utf-8', $streamOptions = NULL) { - if (!is_null($streamOptions)) { - $this->setStreamContext($streamOptions); - } - - libxml_use_internal_errors(TRUE); - $rc = parent::__construct($version, $encoding); - - $this->registerNodeClass('\DOMDocument', get_called_class()); - $this->registerNodeClass('\DOMNode', 'TheSeer\fDOM\fDOMNode'); - $this->registerNodeClass('\DOMElement', 'TheSeer\fDOM\fDOMElement'); - $this->registerNodeClass('\DOMDocumentFragment', 'TheSeer\fDOM\fDOMDocumentFragment'); - - return $rc; - } - - /** - * Reset XPath object so the clone gets a new instance when needed - */ - public function __clone() { - $this->xp = new fDOMXPath($this); - foreach($this->prefixes as $prefix => $uri) { - $this->xp->registerNamespace($prefix, $uri); - } - } - - public function __toString() { - return $this->C14N(); - } - - /** - * Set Stream context options - * - * @param Array $options Stream context options - * - * @return boolean true on success, false on failure - */ - public function setStreamContext(Array $options) { - if (!count($options)) { - return FALSE; - } - $context = stream_context_create($options); - libxml_set_streams_context($context); - return TRUE; - } - - /** - * Wrapper to DOMDocument load with exception handling - * Returns true on success to satisfy the compatibilty of the original DOM Api - * - * @param string $fname File to load - * @param int|null $options LibXML Flags to pass - * - * @throws fDOMException - * - * @return bool|mixed - */ - public function load($fname, $options = LIBXML_NONET) { - $this->xp = NULL; - $tmp = parent :: load($fname, $options); - if (!$tmp || libxml_get_last_error()) { - throw new fDOMException("loading file '$fname' failed.", fDOMException::LoadError); - } - return TRUE; - } - - /** - * Wrapper to DOMDocument loadXML with exception handling - * Returns true on success to satisfy the compatibilty of the original DOM Api - * - * @param string $source XML source code - * @param integer $options LibXML option flags - * - * @throws fDOMException - * - * @return boolean - */ - public function loadXML($source, $options = LIBXML_NONET) { - $this->xp = NULL; - $tmp = parent :: loadXML($source, $options); - if (!$tmp || libxml_get_last_error()) { - throw new fDOMException('parsing string failed', fDOMException::ParseError); - } - return TRUE; - } - - /** - * Wrapper to DOMDocument loadHTMLFile with exception handling. - * Returns true on success to satisfy the compatibilty of the original DOM Api - * - * @param string $fname html file to load - * @param integer $options Options bitmask (@see DOMDocument::loadHTMLFile) - * - * @throws fDOMException - * - * @return boolean - */ - public function loadHTMLFile($fname, $options = NULL) { - $this->xp = NULL; - if (version_compare(PHP_VERSION, '5.4.0', '<')) { - if ($options != NULL) { - throw new fDOMException('Passing options requires PHP 5.4.0+', fDOMException::LoadError); - } - $tmp = parent :: loadHTMLFile($fname); - } else { - $tmp = parent :: loadHTMLFile($fname, $options); - } - if (!$tmp || libxml_get_last_error()) { - throw new fDOMException("loading html file '$fname' failed", fDOMException::LoadError); - } - return TRUE; - } - - /** - * Wrapper to DOMDocument loadHTML with exception handling - * Returns true on success to satisfy the compatibilty of the original DOM Api - * - * @param string $source html source code - * @param integer $options Options bitmask (@see DOMDocument::loadHTML) - * - * @throws fDOMException - * - * @return boolean - */ - public function loadHTML($source, $options = NULL) { - $this->xp = NULL; - if (version_compare(PHP_VERSION, '5.4.0', '<')) { - if ($options != NULL) { - throw new fDOMException('Passing options requires PHP 5.4.0+', fDOMException::LoadError); - } - $tmp = parent :: loadHTML($source); - } else { - $tmp = parent :: loadHTML($source, $options); - } - if (!$tmp || libxml_get_last_error()) { - throw new fDOMException('parsing html string failed', fDOMException::ParseError); - } - return TRUE; - } - - /** - * Wrapper to DOMDocument::save with exception handling - * - * @param string $filename filename to save to - * @param integer $options Options bitmask (@see DOMDocument::save) - * - * @throws fDOMException - * - * @return integer bytes saved - */ - public function save($filename, $options = NULL) { - $tmp = parent::save($filename, $options); - if (!$tmp) { - throw new fDOMException('saving xml file failed', fDOMException::SaveError); - } - return $tmp; - } - - /** - * Wrapper to DOMDocument::saveHTML with exception handling - * - * @param DOMNode|null $node Context DOMNode (optional) - * - * @throws fDOMException - * @return string html content - */ - public function saveHTML(\DOMNode $node = NULL) { - if (version_compare(PHP_VERSION, '5.3.6', '<') && $node != NULL) { - throw new fDOMException('Passing a context node requires PHP 5.3.6+', fDOMException::SaveError); - } - $tmp = parent::saveHTML($node); - if (!$tmp) { - throw new fDOMException('serializing to HTML failed', fDOMException::SaveError); - } - return $tmp; - } - - /** - * Wrapper to DOMDocument::saveHTMLfile with exception handling - * - * @param string $filename filename to save to - * @param integer $options Options bitmask (@see DOMDocument::saveHTMLFile) - * - * @throws fDOMException - * - * @return integer bytes saved - */ - public function saveHTMLFile($filename, $options = NULL) { - $tmp = parent::saveHTMLFile($filename, $options); - if (!$tmp) { - throw new fDOMException('saving to HTML file failed', fDOMException::SaveError); - } - return $tmp; - } - - /** - * Wrapper to DOMDocument::saveXML with exception handling - * - * @param \DOMNode $node node to start serializing at - * @param integer $options options flags as bitmask - * - * @throws fDOMException - * - * @return string serialized XML - */ - public function saveXML(\DOMNode $node = NULL, $options = NULL) { - try { - $tmp = parent::saveXML($node, $options); - if (!$tmp) { - throw new fDOMException('serializing to XML failed', fDOMException::SaveError); - } - return $tmp; - } catch (\Exception $e) { - if (!$e instanceof fDOMException) { - throw new fDOMException($e->getMessage(), fDOMException::SaveError, $e); - } - throw $e; - } - } - - /** - * get Instance of DOMXPath Object for current DOM - * - * @throws fDOMException - * - * @return fDOMXPath - */ - public function getDOMXPath() { - if (is_null($this->xp)) { - $this->xp = new fDOMXPath($this); - } - if (!$this->xp) { - throw new fDOMException('creating DOMXPath object failed.', fDOMException::NoDOMXPath); - } - return $this->xp; - } - - /** - * Convert a given DOMNodeList into a DOMFragment - * - * @param \DOMNodeList $list The Nodelist to process - * @param boolean $move Signale if nodes are to be moved into fragment or not - * - * @return fDOMDocumentFragment - */ - public function nodeList2Fragment(\DOMNodeList $list, $move=FALSE) { - $frag = $this->createDocumentFragment(); - /** @var fDOMNode $node */ - foreach($list as $node) { - $frag->appendChild($move ? $node : $node->cloneNode(TRUE)); - } - return $frag; - } - - /** - * Perform an xpath query - * - * @param String $q query string containing xpath - * @param \DOMNode|null $ctx (optional) Context DOMNode - * @param boolean $registerNodeNS Register flag pass through - * - * @return \DOMNodeList - */ - public function query($q, \DOMNode $ctx = NULL, $registerNodeNS = TRUE) { - if (is_null($this->xp)) { - $this->getDOMXPath(); - } - return $this->xp->evaluate($q, $ctx, $registerNodeNS); - } - - /** - * Perform an xpath query and return only the 1st match - * - * @param String $q query string containing xpath - * @param \DOMNode $ctx (optional) Context DOMNode - * @param boolean $registerNodeNS Register flag pass thru - * - * @return fDOMNode - */ - public function queryOne($q, \DOMNode $ctx = NULL, $registerNodeNS = TRUE) { - if (is_null($this->xp)) { - $this->getDOMXPath(); - } - return $this->xp->queryOne($q, $ctx, $registerNodeNS); - } - - /** - * Forwarder to fDOMXPath's prepare method allowing for easy and secure - * placeholder replacement comparable to sql's prepared statements - * . - * @param string $xpath String containing xpath with :placeholder markup - * @param array $valueMap Array containing keys (:placeholder) and value pairs to be quoted - * - * @return string - */ - public function prepareQuery($xpath, array $valueMap) { - if (is_null($this->xp)) { - $this->getDOMXPath(); - } - return $this->xp->prepare($xpath, $valueMap); - } - - /** - * Forward to DOMXPath->registerNamespace() - * - * @param string $prefix The prefix to use - * @param string $uri The uri to assign to this prefix - * - * @throws fDOMException - * - * @return void - */ - public function registerNamespace($prefix, $uri) { - if (is_null($this->xp)) { - $this->getDOMXPath(); - } - if (!$this->xp->registerNamespace($prefix, $uri)) { - throw new fDOMException("Registering namespace '$uri' with prefix '$prefix' failed.", fDOMException::RegistrationFailed); - } - $this->prefixes[$prefix] = $uri; - } - - /** - * Forward to DOMXPath->registerPHPFunctions() - * - * @param mixed $restrict Array of function names or string with functionname to restrict callabilty to - * - * @throws fDOMException - * - * @return void - */ - public function registerPHPFunctions($restrict = NULL) { - if (is_null($this->xp)) { - $this->getDOMXPath(); - } - $this->xp->registerPHPFunctions($restrict); - if (libxml_get_last_error()) { - throw new fDOMException("Registering php functions failed.", fDOMException::RegistrationFailed); - } - } - - /** - * Create a new element in namespace defined by given prefix - * - * @param string $prefix Namespace prefix for node to create - * @param string $name Name of not element to create - * @param string $content Optional content to be set - * @param bool $asTextNode Create content as textNode rather then setting nodeValue - * - * @throws fDOMException - * - * @return fDOMElement Reference to created fDOMElement - */ - public function createElementPrefix($prefix, $name, $content = NULL, $asTextNode = FALSE) { - if (!isset($this->prefixes[$prefix])) { - throw new fDOMException("'$prefix' not bound", fDOMException::UnboundPrefix); - } - return $this->createElementNS($this->prefixes[$prefix], $prefix.':'.$name, $content, $asTextNode); - } - - /** - * Create a new fDOMElement and return it, optionally set content - * - * @param string $name Name of node to create - * @param null $content Content to set (optional) - * @param bool $asTextNode Create content as textNode rather then setting nodeValue - * - * @throws fDOMException - * - * @return fDOMElement Reference to created fDOMElement - */ - public function createElement($name, $content = NULL, $asTextnode = FALSE) { - try { - $node = parent::createElement($name); - if (!$node) { - throw new fDOMException("Creating element with name '$name' failed", fDOMException::NameInvalid); - } - if ($content !== NULL) { - if ($asTextnode) { - $node->appendChild($this->createTextnode($content)); - } else { - $node->nodeValue = $content; - } - if (libxml_get_errors()) { - throw new fDOMException("Setting content value failed", fDOMException::SetFailedError); - } - } - } catch (\DOMException $e) { - throw new fDOMException("Creating elemnt with name '$name' failed", 0, $e); - } - return $node; - } - - /** - * Create a new fDOMElement within given namespace and return it - * - * @param string $namespace Namespace URI for node to create - * @param string $name Name of node to create - * @param null $content Content to set (optional) - * @param bool $asTextNode Create content as textNode rather then setting nodeValue - * - * @throws fDOMException - * - * @return fDOMElement - */ - public function createElementNS($namespace, $name, $content = NULL, $asTextNode = FALSE) { - $node = parent::createElementNS($namespace, $name); - if (!$node) { - throw new fDOMException("Creating element with name '$name' failed", fDOMException::NameInvalid); - } - if ($content !== NULL) { - if ($asTextNode) { - $node->appendChild($this->createTextnode($content)); - } else { - $node->nodeValue = $content; - } - if (libxml_get_errors()) { - throw new fDOMException("Setting content value failed", fDOMException::SetFailedError); - } - } - return $node; - } - - /** - * Check if the given node is in the same document - * - * @param \DOMNode $node Node to compare with - * - * @return boolean true on match, false if they differ - * - */ - public function inSameDocument(\DOMNode $node) { - if ($node instanceof \DOMDocument) { - return $this->isSameNode($node); - } - return $this->isSameNode($node->ownerDocument); - } - - /** - * Create a new element and append it as documentElement - * - * @param $name Name of not element to create - * @param $content Optional content to be set - * - * @return fDOMElement Reference to created fDOMElement - */ - public function appendElement($name, $content = NULL, $asTextNode = FALSE) { - return $this->appendChild( - $this->createElement($name, $content, $asTextNode) - ); - } - - /** - * Create a new element in given namespace and append it as documentElement - * - * @param $ns Namespace of node to create - * @param $name Name of not element to create - * @param $content Optional content to be set - * - * @return fDOMElement Reference to created fDOMElement - */ - public function appendElementNS($ns, $name, $content = NULL, $asTextNode = FALSE) { - return $this->appendChild( - $this->createElementNS($ns, $name, $content, $asTextNode) - ); - } - - } // fDOMDocument - -} - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * fDOMDocumentFragment - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMDocumentFragment extends \DOMDocumentFragment { - - public function __toString() { - return $this->C14N(); - } - - /** - * Wrapper to standard method with exception support - * - * @param string $str Data string to parse and append - * - * @return boolean true on success - */ - public function appendXML($str) { - if (!parent::appendXML($str)) { - throw new fDOMException('Appending xml string failed', fDOMException::ParseError); - } - return true; - } - - /** - * Check if the given node is in the same document - * - * @param \DOMNode $node Node to compare with - * - * @return boolean true on match, false if they differ - * - */ - public function inSameDocument(\DOMNode $node) { - return $this->ownerDocument->inSameDocument($node); - } - - } // fDOMDocumentFragment - -} - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * fDomElement - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMElement extends \DOMElement { - - public function __toString() { - return $this->C14N(); - } - - /** - * Forward to fDomDocument->query() - * - * @param string $q XPath to use - * @param \DOMNode $ctx \DOMNode to overwrite context - * @param boolean $registerNodeNS Register flag pass thru - * - * @return \DomNodeList - */ - public function query($q, \DOMNode $ctx = null, $registerNodeNS = true) { - return $this->ownerDocument->query($q, $ctx ? $ctx : $this, $registerNodeNS); - } - - /** - * Forward to fDomDocument->queryOne() - * - * @param string $q XPath to use - * @param \DOMNode $ctx (optional) \DOMNode to overwrite context - * @param boolean $registerNodeNS Register flag pass thru - * - * @return mixed - */ - public function queryOne($q, \DOMNode $ctx = null, $registerNodeNS = true) { - return $this->ownerDocument->queryOne($q, $ctx ? $ctx : $this, $registerNodeNS); - } - - /** - * Parse and append XML String to node - * - * @param String $str string to process - * - * @return fDomDocumentFragment Reference to the created Fragment - */ - public function appendXML($str) { - $frag = $this->ownerDocument->createDocumentFragment(); - $frag->appendXML($str); - $this->appendChild($frag); - return $frag; - } - - /** - * Create a new element and append it - * - * @param string $name Name of not element to create - * @param string $content Optional content to be set - * - * @return fDOMElement Reference to created fDOMElement - */ - public function appendElement($name, $content = null) { - $node = $this->ownerDocument->createElement($name, $content); - $this->appendChild($node); - return $node; - } - - /** - * Create a new element in given namespace and append it - * - * @param string $ns Namespace of node to create - * @param string $name Name of not element to create - * @param string $content Optional content to be set - * - * @return fDOMElement Reference to created fDOMElement - */ - public function appendElementNS($ns, $name, $content = null) { - $node = $this->ownerDocument->createElementNS($ns, $name, $content); - $this->appendChild($node); - return $node; - } - - /** - * Create a new element in given namespace and append it - * - * @param string $prefix Namespace prefix for node to create - * @param string $name Name of not element to create - * @param string $content Optional content to be set - * - * @return fDOMElement Reference to created fDOMElement - */ - public function appendElementPrefix($prefix, $name, $content = null) { - $node = $this->ownerDocument->createElementPrefix($prefix, $name, $content); - $this->appendChild($node); - return $node; - } - - /** - * Create a new text node and append it - * - * @param string $content Text content to be added - * - * @return \DOMText - */ - public function appendTextNode($content) { - $text = $this->ownerDocument->createTextNode($content); - $this->appendChild($text); - return $text; - } - - /** - * Wrapper to DomElement->getAttribute with default value option - * - * Note: A set but emptry attribute does NOT trigger use of the default - * - * @param string $attr Attribute to access - * @param string $default Default value to use if the attribute is not set - * - * @return string - */ - public function getAttribute($attr, $default='') { - return $this->hasAttribute($attr) ? parent::getAttribute($attr) : $default; - } - - /** - * Wrapper to DomElement->getAttributeNS with default value option - * - * Note: A set but empty attribute does NOT trigger use of the default - * - * @param string $ns Namespace of attribute - * @param string $attr Attribute to access - * @param string $default Default value to use if the attribute is not set - * - * @return string - */ - public function getAttributeNS($ns, $attr, $default='') { - return $this->hasAttributeNS($ns, $attr) ? parent::getAttributeNS($ns, $attr) : $default; - } - - /** - * Wrapper to DOMElement::setAttribute with additional entities support - * - * @param string $attr Attribute name to set - * @param string $value Value to set attribute to - * @param bool $keepEntitites Flag to signale if entities should be kept - * - * @throws fDOMException - * - * @return DOMAttr - * - * @see DOMElement::setAttribute() - */ - public function setAttribute($attr, $value, $keepEntities=false) { - if ($keepEntities === true) { - $attrNode = $this->ownerDocument->createAttribute($attr); - if (!$attrNode) { - throw new fDOMException("Setting attribute '$attr' failed.", fDOMException::SetFailedError); - } - $attrNode->value = $value; - $this->appendChild($attrNode); - return $attrNode; - } - return parent::setAttribute($attr, $value); - } - - /** - * Wrapper to namespace aware DOMElement::setAttributeNS with additional entities support - * - * @param string $ns namespace attribute should be in - * @param string $attr Attribute name to set - * @param string $value Value to set attribute to - * @param boolean $keepEntitites Flag to signale if entities should be kept - * - * @return \DOMAttr - * - * @see DOMElement::setAttribute() - */ - public function setAttributeNS($ns, $attr, $value, $keepEntities=false) { - if ($keepEntities === true) { - $attrNode = $this->ownerDocument->createAttributeNS($ns, $attr); - if (!$attrNode) { - throw new fDOMException("Setting attribute '$attr' failed.", fDOMException::SetFailedError); - } - $attrNode->value = $value; - $this->appendChild($attrNode); - return $attrNode; - } - return parent::setAttributeNS($ns, $attr, $value); - } - - /** - * Helper to add multiple attributes to an element - * - * @param array $attr Attributes to add as key-value pair - * @param bool $keepEntities Flag wether to keep entities - * - * @return array List with references to created DOMAttr - */ - public function setAttributes(array $attr, $keepEntities=false) { - $attList = array(); - foreach($attr as $name => $value) { - $attList[] = $this->setAttribute($name, $value, $keepEntities); - } - return $attList; - } - - /** - * Helper to add multiple attributes with the given namespace and prefix - * - * @param string $ns Namespace of attribute - * @param string $prefix Namespace prefix for attribute to create - * @param array $attr Attributes to add - * @param bool $keepEntities Flag wether to keep entities - * - * @return void - */ - public function setAttributesNS($ns, $prefix, array $attr, $keepEntities=false) { - foreach($attr as $name => $value) { - $this->setAttributeNS($ns, $prefix.':'.$name, $value, $keepEntities); - } - } - - /** - * Helper method to get children by name - * - * @param string $tagName tagname to search for - * - * @return DomNodeList - */ - public function getChildrenByTagName($tagName) { - return $this->query("*[local-name()='$tagName']"); - } - - /** - * Helper method to get children by name and namespace - * - * @param string $ns namespace nodes have to be in - * @param string $tagName tagname to search for - * - * @return DomNodeList - */ - public function getChildrenByTagNameNS($ns, $tagName) { - return $this->query("*[local-name()='$tagName' and namespace-uri()='$ns']"); - } - - /** - * Check if the given node is in the same document - * - * @param \DomNode $node Node to compare with - * - * @return boolean true on match, false if they differ - * - */ - public function inSameDocument(\DomNode $node) { - return $this->ownerDocument->inSameDocument($node); - } - - } // fDOMElement - -} - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * fDomNode - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMNode extends \DOMNode { - - public function __toString() { - return $this->C14N(); - } - - /** - * Check if the given node is in the same document - * - * @param \DomNode $node Node to compare with - * - * @return boolean true on match, false if they differ - * - */ - public function inSameDocument(\DOMNode $node) { - return $this->ownerDocument->inSameDocument($node); - } - - } // fDOMNode - -} - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * Class XPathQuery - * - * @package TheSeer\fDOM - */ - class XPathQuery { - - /** - * @var string - */ - private $query; - - /** - * Key-value Map for bound values - * - * @var array - */ - private $values = array(); - - /** - * @param string $query - */ - public function __construct($query) { - $this->setQuery($query); - } - - /** - * @param string $query - */ - private function setQuery($query) { - $this->query = $query; - $res = preg_match_all('/(:(\w*))/', $query, $matches); - if ($res > 0) { - $this->values = array_fill_keys($matches[2], ''); - } - } - - public function getKeys() { - return array_keys($this->values); - } - - public function bind($key, $value) { - if (!array_key_exists($key, $this->values)) { - throw new XPathQueryException("'$key' not found in query'", XPathQueryException::KeyNotFound ); - } - $this->values[$key] = $value; - } - - public function generate(\DOMNode $ctx, array $values = NULL) { - return $this->buildQuery($this->getXPathObjectFor($ctx), $values); - } - - public function evaluate(\DOMNode $ctx, array $values = NULL, $registerNodeNS = TRUE) { - $xp = $this->getXPathObjectFor($ctx); - return $xp->evaluate($this->buildQuery($xp, $values), $ctx, $registerNodeNS); - } - - public function query(\DOMNode $ctx, array $values = NULL, $registerNodeNS = TRUE) { - $xp = $this->getXPathObjectFor($ctx); - return $xp->evaluate($this->buildQuery($xp, $values), $ctx, $registerNodeNS); - } - - public function queryOne(\DOMNode $ctx, array $values = NULL, $registerNodeNS = TRUE) { - $xp = $this->getXPathObjectFor($ctx); - return $xp->queryOne($this->buildQuery($xp, $values), $ctx, $registerNodeNS); - } - - private function getXPathObjectFor(\DOMNode $ctx) { - $dom = $ctx instanceof \DOMDocument ? $ctx : $ctx->ownerDocument; - if ($dom instanceOf fDOMDocument) { - return $dom->getDOMXPath(); - } - return new fDOMXPath($dom); - } - - private function buildQuery(fDOMXPath $xp, array $values = NULL) { - $backup = $this->values; - if (count($values) > 0) { - foreach($values as $k => $v) { - $this->bind($k, $v); - } - } - $query = $xp->prepare($this->query, $this->values); - $this->values = $backup; - return $query; - } - } - -} - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Arne Blankerts nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ORCONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @copyright Arne Blankerts , All rights reserved. - * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @link http://github.com/theseer/fdomdocument - * - */ - -namespace TheSeer\fDOM { - - /** - * fDOMXPath extension to PHP's DOMXPath. - * - * @category PHP - * @package TheSeer\fDOM - * @author Arne Blankerts - * @access public - * - */ - class fDOMXPath extends \DOMXPath { - - protected $doc; - - public function __construct(\DOMDocument $doc) { - parent::__construct($doc); - $this->doc = $doc; - } - - public function prepare($xpath, array $valueMap) { - if (count($valueMap)==0) { - return $xpath; - } - foreach($valueMap as $key => $value) { - $xpath = str_replace(':'.$key, $this->quote($value), $xpath); - } - return $xpath; - } - - public function query($q, \DOMNode $ctx = null, $registerNodeNS = true) { - libxml_clear_errors(); - if (version_compare(PHP_VERSION, '5.3.3', '<')) { - $rc = parent::query($q, ($ctx instanceof \DOMNode) ? $ctx : $this->doc->documentElement); - } else { - $rc = parent::query($q, ($ctx instanceof \DOMNode) ? $ctx : $this->doc->documentElement, $registerNodeNS); - } - - if (libxml_get_last_error()) { - throw new fDOMException('evaluating xpath expression failed.', fDOMException::QueryError); - } - return $rc; - } - - public function evaluate($q, \DOMNode $ctx = null, $registerNodeNS = true) { - libxml_clear_errors(); - if (version_compare(PHP_VERSION, '5.3.3', '<')) { - $rc = parent::evaluate($q, ($ctx instanceof \DOMNode) ? $ctx : $this->doc->documentElement); - } else { - $rc = parent::evaluate($q, ($ctx instanceof \DOMNode) ? $ctx : $this->doc->documentElement, $registerNodeNS); - } - if (libxml_get_last_error()) { - throw new fDOMException('evaluating xpath expression failed.', fDOMException::QueryError); - } - return $rc; - } - - public function queryOne($q, \DOMNode $ctx = null, $registerNodeNS = true) { - $rc = $this->evaluate($q, $ctx, $registerNodeNS); - if ($rc instanceof \DOMNodelist) { - return $rc->item(0); - } - return $rc; - } - - public function quote($str) { - if (strpos($str, '"') === false) { - return '"'.$str.'"'; - } - $parts = explode('"', $str); - return 'concat("' . join('",\'"\',"', $parts).'")'; - } - } -}. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package FinderFacade - * @author Sebastian Bergmann - * @copyright 2012-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.0.0 - */ - -namespace SebastianBergmann\FinderFacade -{ - use Symfony\Component\Finder\Finder; - - /** - * Convenience wrapper for Symfony's Finder component. - * - * @author Sebastian Bergmann - * @copyright 2012-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @version Release: @package_version@ - * @link http://github.com/sebastianbergmann/finder-facade/tree - * @since Class available since Release 1.0.0 - */ - class FinderFacade - { - /** - * @var array - */ - protected $items = array(); - - /** - * @var array - */ - protected $excludes = array(); - - /** - * @var array - */ - protected $names = array(); - - - /** - * @var array - */ - protected $notNames = array(); - - /** - * @param array $items - * @param array $excludes - * @param array $names - * @param array $notNames - */ - public function __construct(array $items = array(), array $excludes = array(), array $names = array(), array $notNames = array()) - { - $this->items = $items; - $this->excludes = $excludes; - $this->names = $names; - $this->notNames = $notNames; - } - - /** - * @return array - */ - public function findFiles() - { - $files = array(); - $finder = new Finder; - $iterate = FALSE; - - foreach ($this->items as $item) { - if (!is_file($item)) { - $finder->in($item); - $iterate = TRUE; - } - - else { - $files[] = realpath($item); - } - } - - foreach ($this->excludes as $exclude) { - $finder->exclude($exclude); - } - - foreach ($this->names as $name) { - $finder->name($name); - } - - foreach ($this->notNames as $notName) { - $finder->notName($notName); - } - - if ($iterate) { - foreach ($finder as $file) { - $files[] = $file->getRealpath(); - } - } - - return $files; - } - - /** - * @param string $file - */ - public function loadConfiguration($file) - { - $configuration = new Configuration($file); - $configuration = $configuration->parse(); - - $this->items = $configuration['items']; - $this->excludes = $configuration['excludes']; - $this->names = $configuration['names']; - $this->notNames = $configuration['notNames']; - } - } -} -. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of Sebastian Bergmann nor the names of his - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @package FinderFacade - * @author Sebastian Bergmann - * @copyright 2012-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @since File available since Release 1.0.0 - */ - -namespace SebastianBergmann\FinderFacade -{ - use TheSeer\fDOM\fDOMDocument; - - /** - * - * - * - * /path/to/directory - * /path/to/file - * - * /path/to/directory - * *.php - * - * - * - * @author Sebastian Bergmann - * @copyright 2012-2013 Sebastian Bergmann - * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License - * @version Release: @package_version@ - * @link http://github.com/sebastianbergmann/finder-facade/tree - * @since Class available since Release 1.0.0 - */ - class Configuration - { - /** - * @var string - */ - protected $basePath; - - /** - * @var fDOMDocument - */ - protected $xml; - - /** - * @param string $file - */ - public function __construct($file) - { - $this->basePath = dirname($file); - - $this->xml = new fDOMDocument; - $this->xml->load($file); - } - - /** - * @param string $xpath - * @return array - */ - public function parse($xpath = '') - { - $result = array( - 'items' => array(), 'excludes' => array(), 'names' => array(), 'notNames' => array() - ); - - foreach ($this->xml->getDOMXPath()->query($xpath . 'include/directory') as $item) { - $result['items'][] = $this->toAbsolutePath($item->nodeValue); - } - - foreach ($this->xml->getDOMXPath()->query($xpath . 'include/file') as $item) { - $result['items'][] = $this->toAbsolutePath($item->nodeValue); - } - - foreach ($this->xml->getDOMXPath()->query($xpath . 'exclude') as $exclude) { - $result['excludes'][] = $exclude->nodeValue; - } - - foreach ($this->xml->getDOMXPath()->query($xpath . 'name') as $name) { - $result['names'][] = $name->nodeValue; - } - - foreach ($this->xml->getDOMXPath()->query($xpath . 'notName') as $name) { - $result['notNames'][] = $name->nodeValue; - } - - return $result; - } - - /** - * @param string $path - * @return string - */ - protected function toAbsolutePath($path) - { - // Check whether the path is already absolute. - if ($path[0] === '/' || $path[0] === '\\' || - (strlen($path) > 3 && ctype_alpha($path[0]) && - $path[1] === ':' && ($path[2] === '\\' || $path[2] === '/'))) { - return $path; - } - - // Check whether a stream is used. - if (strpos($path, '://') !== FALSE) { - return $path; - } - - return $this->basePath . DIRECTORY_SEPARATOR . $path; - } - } -} -HQRM;)bG[gGBMB \ No newline at end of file diff --git a/puppet/modules/joindin/files/tests/phpmd b/puppet/modules/joindin/files/tests/phpmd deleted file mode 100644 index 5749391..0000000 Binary files a/puppet/modules/joindin/files/tests/phpmd and /dev/null differ diff --git a/puppet/modules/joindin/files/tests/phpunit b/puppet/modules/joindin/files/tests/phpunit deleted file mode 100755 index b8dfc88..0000000 --- a/puppet/modules/joindin/files/tests/phpunit +++ /dev/null @@ -1,67032 +0,0 @@ -#!/usr/bin/env php -')) { - fwrite( - STDERR, - 'This version of PHPUnit requires PHP 5.6; using the latest version of PHP is highly recommended.' . PHP_EOL - ); - - die(1); -} - -if (__FILE__ == realpath($GLOBALS['_SERVER']['SCRIPT_NAME'])) { - $execute = true; -} else { - $execute = false; -} - -define('__PHPUNIT_PHAR__', str_replace(DIRECTORY_SEPARATOR, '/', __FILE__)); -define('__PHPUNIT_PHAR_ROOT__', 'phar://phpunit-5.2.9.phar'); - -Phar::mapPhar('phpunit-5.2.9.phar'); - -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/DeepCopy.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Exception/CloneException.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Filter/Filter.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Filter/KeepFilter.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Filter/ReplaceFilter.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Filter/SetNullFilter.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Matcher/Matcher.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Matcher/PropertyMatcher.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Matcher/PropertyNameMatcher.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Matcher/PropertyTypeMatcher.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/Reflection/ReflectionHelper.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/TypeFilter/TypeFilter.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/TypeFilter/ReplaceFilter.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/TypeFilter/ShallowCopyFilter.php'; -require 'phar://phpunit-5.2.9.phar' . '/myclabs-deep-copy/DeepCopy/TypeMatcher/TypeMatcher.php'; -require 'phar://phpunit-5.2.9.phar' . '/doctrine-instantiator/Doctrine/Instantiator/Exception/ExceptionInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/doctrine-instantiator/Doctrine/Instantiator/Exception/InvalidArgumentException.php'; -require 'phar://phpunit-5.2.9.phar' . '/doctrine-instantiator/Doctrine/Instantiator/Exception/UnexpectedValueException.php'; -require 'phar://phpunit-5.2.9.phar' . '/doctrine-instantiator/Doctrine/Instantiator/InstantiatorInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/doctrine-instantiator/Doctrine/Instantiator/Instantiator.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-file-iterator/Iterator.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-file-iterator/Facade.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-file-iterator/Factory.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/ITester.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/AbstractTester.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/SelfDescribing.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Constraint/DataSetIsEqual.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Constraint/TableIsEqual.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Constraint/TableRowCount.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/IDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/AbstractDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/DataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/IDatabaseConnection.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/DefaultDatabaseConnection.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/FilteredDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/IMetaData.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/MetaData.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/MetaData/Dblib.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/MetaData/Firebird.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/MetaData/InformationSchema.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/MetaData/MySQL.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/MetaData/Oci.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/MetaData/PgSQL.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/MetaData/SqlSrv.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/MetaData/Sqlite.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/ITable.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/AbstractTable.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/ResultSetTable.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/Table.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/ITableIterator.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/TableIterator.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/ITableMetaData.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/AbstractTableMetaData.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/DefaultTableMetaData.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DB/TableMetaData.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/AbstractXmlDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/ArrayDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/CompositeDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/CsvDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/DataSetFilter.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/DefaultDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/DefaultTable.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/DefaultTableIterator.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/FlatXmlDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/IPersistable.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/ISpec.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/IYamlParser.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/MysqlXmlDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Persistors/Abstract.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Persistors/Factory.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Persistors/FlatXml.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Persistors/MysqlXml.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Persistors/Xml.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Persistors/Yaml.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/QueryDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/QueryTable.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/ReplacementDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/ReplacementTable.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/ReplacementTableIterator.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Specs/Csv.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/IDatabaseListConsumer.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Specs/DbQuery.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Specs/DbTable.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Specs/IFactory.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Specs/Factory.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Specs/FlatXml.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Specs/Xml.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/Specs/Yaml.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/SymfonyYamlParser.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/TableFilter.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/TableMetaDataFilter.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/XmlDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DataSet/YamlDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/DefaultTester.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/IDatabaseOperation.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/Composite.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/RowBased.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/Delete.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/DeleteAll.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/Factory.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/Insert.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/Null.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/Replace.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/Truncate.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/Operation/Update.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Test.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Assert.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/TestCase.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/TestCaseTrait.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/TestCase.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/UI/Command.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/UI/Context.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/UI/IMediumPrinter.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/UI/IMedium.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/UI/IMode.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/UI/IModeFactory.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/UI/InvalidModeException.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/UI/Mediums/Text.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/UI/ModeFactory.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/UI/Modes/ExportDataSet.php'; -require 'phar://phpunit-5.2.9.phar' . '/dbunit/Extensions/Database/UI/Modes/ExportDataSet/Arguments.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/TestSuite.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Extensions/GroupTestSuite.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Extensions/PhptTestCase.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Extensions/PhptTestSuite.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Extensions/TestDecorator.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Extensions/RepeatedTest.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/TestListener.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Extensions/TicketListener.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/AssertionFailedError.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/BaseTestListener.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/CodeCoverageException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/And.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/ArrayHasKey.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/ArraySubset.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/Composite.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/Attribute.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/Callback.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/ClassHasAttribute.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/ClassHasStaticAttribute.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/Count.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/ExceptionCode.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/ExceptionMessage.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/ExceptionMessageRegExp.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/FileExists.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/GreaterThan.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsAnything.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsEmpty.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsEqual.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsFalse.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsFinite.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsIdentical.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsInfinite.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsInstanceOf.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsJson.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsNan.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsNull.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsTrue.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/IsType.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/JsonMatches.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/JsonMatches/ErrorMessageProvider.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/LessThan.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/Not.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/ObjectHasAttribute.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/Or.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/PCREMatch.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/SameSize.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/StringContains.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/StringEndsWith.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/StringMatches.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/StringStartsWith.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/TraversableContains.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/TraversableContainsOnly.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Constraint/Xor.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/RiskyTest.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/RiskyTestError.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/PHPUnit_Framework_CoveredCodeNotExecutedException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Error.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Error/Deprecated.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Error/Notice.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Error/Warning.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/ExceptionWrapper.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/ExpectationFailedException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/IncompleteTest.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/IncompleteTestCase.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/IncompleteTestError.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/InvalidCoversTargetException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Exception/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Exception/BadMethodCallException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Builder/Identity.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Builder/Stub.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Builder/Match.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Builder/ParametersMatch.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Builder/MethodNameMatch.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Builder/InvocationMocker.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Builder/Namespace.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Generator.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Invocation.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Stub/MatcherCollection.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Verifiable.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Invokable.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/InvocationMocker.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Invocation/Static.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Invocation/Object.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/Invocation.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/InvokedRecorder.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/AnyInvokedCount.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/StatelessInvocation.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/AnyParameters.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/ConsecutiveParameters.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtIndex.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtLeastCount.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtLeastOnce.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtMostCount.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/InvokedCount.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/MethodName.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Matcher/Parameters.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/MockBuilder.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/MockObject.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Exception/RuntimeException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Stub.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Stub/ConsecutiveCalls.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Stub/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Stub/Return.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Stub/ReturnArgument.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Stub/ReturnCallback.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Stub/ReturnSelf.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit-mock-objects/Framework/MockObject/Stub/ReturnValueMap.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/OutputError.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/SkippedTest.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/SkippedTestCase.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/SkippedTestError.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/SkippedTestSuiteError.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/SyntheticError.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/TestFailure.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/TestResult.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/TestSuite/DataProvider.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/UnintentionallyCoveredCodeError.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/Warning.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Framework/WarningTestCase.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Runner/BaseTestRunner.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Runner/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Runner/Filter/Factory.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Runner/Filter/Group.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Runner/Filter/Group/Exclude.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Runner/Filter/Group/Include.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Runner/Filter/Test.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Runner/TestSuiteLoader.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Runner/StandardTestSuiteLoader.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Runner/Version.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/TextUI/Command.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Printer.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/TextUI/ResultPrinter.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/TextUI/TestRunner.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Blacklist.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Configuration.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/ErrorHandler.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Fileloader.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Filesystem.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Filter.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Getopt.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/GlobalState.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/InvalidArgumentHelper.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Log/JSON.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Log/JUnit.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Log/TAP.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Log/TeamCity.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/PHP.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/PHP/Default.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/PHP/Windows.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Regex.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/String.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Test.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/TestDox/NamePrettifier.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/TestDox/ResultPrinter.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/TestDox/ResultPrinter/HTML.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/TestDox/ResultPrinter/Text.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/TestSuiteIterator.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/Type.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpunit/Util/XML.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Exception/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Exception/RuntimeException.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Exception/CoveredCodeNotExecutedException.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Driver.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Driver/Xdebug.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Driver/HHVM.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Driver/PHPDBG.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Filter.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Exception/InvalidArgumentException.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Exception/MissingCoversAnnotationException.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/Clover.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/Crap4j.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/Factory.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/HTML.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/HTML/Renderer.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/HTML/Renderer/Dashboard.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/HTML/Renderer/Directory.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/HTML/Renderer/File.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/Node.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/Node/Directory.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/Node/File.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/Node/Iterator.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/PHP.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/Text.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/XML.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/XML/Node.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/XML/Directory.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/XML/File.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/XML/File/Coverage.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/XML/File/Method.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/XML/File/Report.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/XML/File/Unit.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/XML/Project.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/XML/Tests.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Report/XML/Totals.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Exception/UnintentionallyCoveredCodeException.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-code-coverage/CodeCoverage/Util.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-invoker/Invoker.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-invoker/TimeoutException.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-timer/Timer.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-token-stream/Token.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-token-stream/Token/Stream.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-token-stream/Token/Stream/CachingFactory.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/ArgumentsWildcard.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/TokenInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/AnyValueToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/AnyValuesToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ApproximateValueToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ArrayCountToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ArrayEntryToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ArrayEveryEntryToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/CallbackToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ExactValueToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/IdenticalValueToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/LogicalAndToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/LogicalNotToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/ObjectStateToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/StringContainsToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Argument/Token/TypeToken.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Call/Call.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Call/CallCenter.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/Comparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Comparator/ClosureComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/Factory.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Comparator/Factory.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/ArrayComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/ObjectComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Comparator/ProphecyComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/Doubler.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/CachedDoubler.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/ClassPatchInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/HhvmExceptionPatch.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/KeywordPatch.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/MagicCallPatch.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/ReflectionClassNewInstancePatch.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/SplFileInfoPatch.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/ClassPatch/TraversablePatch.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/DoubleInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/ClassCodeGenerator.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/ClassCreator.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/ClassMirror.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/Node/ArgumentNode.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/Node/ClassNode.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/Node/MethodNode.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/Generator/ReflectionInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/LazyDouble.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Doubler/NameGenerator.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Prophecy/ProphecyException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Prophecy/ObjectProphecyException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Call/UnexpectedCallException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/DoublerException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/ClassCreatorException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/ClassMirrorException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/DoubleException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/ClassNotFoundException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/InterfaceNotFoundException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/MethodNotExtendableException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/MethodNotFoundException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Doubler/ReturnByReferenceException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/InvalidArgumentException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/PredictionException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/AggregateException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/FailedPredictionException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Prophecy/MethodProphecyException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/NoCallsException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/UnexpectedCallsException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Exception/Prediction/UnexpectedCallsCountException.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prediction/PredictionInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prediction/CallPrediction.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prediction/CallTimesPrediction.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prediction/CallbackPrediction.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prediction/NoCallsPrediction.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Promise/PromiseInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Promise/CallbackPromise.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Promise/ReturnArgumentPromise.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Promise/ReturnPromise.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Promise/ThrowPromise.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prophecy/MethodProphecy.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prophecy/ProphecyInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prophecy/ObjectProphecy.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prophecy/ProphecySubjectInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prophecy/RevealerInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prophecy/Revealer.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Prophet.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Util/ExportUtil.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpspec-prophecy/Prophecy/Util/StringUtil.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-code-unit-reverse-lookup/Wizard.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/ComparisonFailure.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/DOMNodeComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/DateTimeComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/ScalarComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/NumericComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/DoubleComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/ExceptionComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/MockObjectComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/ResourceComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/SplObjectStorageComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-comparator/TypeComparator.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-diff/Chunk.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-diff/Diff.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-diff/Differ.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-diff/LCS/LongestCommonSubsequence.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-diff/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-diff/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-diff/Line.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-diff/Parser.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-environment/Console.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-environment/Runtime.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-exporter/Exporter.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-global-state/Blacklist.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-global-state/CodeExporter.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-global-state/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-global-state/Restorer.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-global-state/RuntimeException.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-global-state/Snapshot.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-recursion-context/Context.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-recursion-context/Exception.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-recursion-context/InvalidArgumentException.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-resource-operations/ResourceOperations.php'; -require 'phar://phpunit-5.2.9.phar' . '/sebastian-version/Version.php'; -require 'phar://phpunit-5.2.9.phar' . '/symfony/yaml/Dumper.php'; -require 'phar://phpunit-5.2.9.phar' . '/symfony/yaml/Escaper.php'; -require 'phar://phpunit-5.2.9.phar' . '/symfony/yaml/Exception/ExceptionInterface.php'; -require 'phar://phpunit-5.2.9.phar' . '/symfony/yaml/Exception/RuntimeException.php'; -require 'phar://phpunit-5.2.9.phar' . '/symfony/yaml/Exception/DumpException.php'; -require 'phar://phpunit-5.2.9.phar' . '/symfony/yaml/Exception/ParseException.php'; -require 'phar://phpunit-5.2.9.phar' . '/symfony/yaml/Inline.php'; -require 'phar://phpunit-5.2.9.phar' . '/symfony/yaml/Parser.php'; -require 'phar://phpunit-5.2.9.phar' . '/symfony/yaml/Unescaper.php'; -require 'phar://phpunit-5.2.9.phar' . '/symfony/yaml/Yaml.php'; -require 'phar://phpunit-5.2.9.phar' . '/php-text-template/Template.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Context.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Description.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Location.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Serializer.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/AuthorTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/SeeTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/CoversTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/VersionTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/DeprecatedTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/SourceTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/ExampleTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/LinkTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/ReturnTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/MethodTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/ParamTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/PropertyTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/PropertyReadTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/PropertyWriteTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/SinceTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/ThrowsTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/UsesTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/VarTag.php'; -require 'phar://phpunit-5.2.9.phar' . '/phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Type/Collection.php'; - -if ($execute) { - if (isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == '--manifest') { - print file_get_contents(__PHPUNIT_PHAR_ROOT__ . '/manifest.txt'); - exit; - } - - PHPUnit_TextUI_Command::main(); -} - -__HALT_COMPILER(); ?> -k#phpunit-5.2.9.phar$sebastian-global-state/Exception.php?V?#sebastian-global-state/Snapshot.php%V%ÖSݶsebastian-global-state/LICENSE -V - `#sebastian-global-state/Restorer.phpVӓ;\$sebastian-global-state/Blacklist.php[ V[ :+sebastian-global-state/RuntimeException.phpqVq~]!'sebastian-global-state/CodeExporter.phpV`(Cphp-text-template/LICENSE V S:php-text-template/Template.php V w4sebastian-diff/LICENSEVvEvö/sebastian-diff/LCS/LongestCommonSubsequence.phplVll1Lsebastian-diff/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php V _Jsebastian-diff/LCS/TimeEfficientLongestCommonSubsequenceImplementation.phpVf#5/sebastian-diff/Line.phpV:;sebastian-diff/Differ.phpV`sebastian-diff/Parser.php' V' ZKsebastian-diff/Diff.phpV˾sebastian-diff/Chunk.phpV-*myclabs-deep-copy/LICENSE5V5ʭ˄'myclabs-deep-copy/DeepCopy/DeepCopy.php"V"llLmyclabs-deep-copy/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.phpeVe+ֶGmyclabs-deep-copy/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.phpVxkж3myclabs-deep-copy/DeepCopy/Filter/ReplaceFilter.phpV̎|3myclabs-deep-copy/DeepCopy/Filter/SetNullFilter.phpVM䧶,myclabs-deep-copy/DeepCopy/Filter/Filter.phpSVSksk0myclabs-deep-copy/DeepCopy/Filter/KeepFilter.phpVߝ7myclabs-deep-copy/DeepCopy/Exception/CloneException.php`V`.ڝ6myclabs-deep-copy/DeepCopy/TypeMatcher/TypeMatcher.phpVʨ:myclabs-deep-copy/DeepCopy/Reflection/ReflectionHelper.phpV&ԋ.myclabs-deep-copy/DeepCopy/Matcher/Matcher.phpV((6myclabs-deep-copy/DeepCopy/Matcher/PropertyMatcher.phpVuօ:myclabs-deep-copy/DeepCopy/Matcher/PropertyNameMatcher.phpVy㻞:myclabs-deep-copy/DeepCopy/Matcher/PropertyTypeMatcher.phpVo4myclabs-deep-copy/DeepCopy/TypeFilter/TypeFilter.phpV947myclabs-deep-copy/DeepCopy/TypeFilter/ReplaceFilter.phpV;If;myclabs-deep-copy/DeepCopy/TypeFilter/ShallowCopyFilter.phpVتphp-timer/Timer.phpE VE *Ephp-timer/LICENSEVǨAEsebastian-comparator/LICENSE V :#sebastian-comparator/Comparator.phpPVP!P=3sebastian-comparator/SplObjectStorageComparator.php -V -MQ'sebastian-comparator/TypeComparator.phpVQ)sebastian-comparator/ObjectComparator.phpVw+sebastian-comparator/ResourceComparator.phpV&w(sebastian-comparator/ArrayComparator.phpVvx+sebastian-comparator/DateTimeComparator.php V ,sebastian-comparator/ExceptionComparator.phpVkf*sebastian-comparator/DOMNodeComparator.php V >%)sebastian-comparator/ScalarComparator.php>V>B(-sebastian-comparator/MockObjectComparator.phpVO*sebastian-comparator/NumericComparator.php~ -V~ -7 sebastian-comparator/Factory.phpd Vd ه1)sebastian-comparator/DoubleComparator.php7V7Stٶ*sebastian-comparator/ComparisonFailure.php V V-sebastian-code-unit-reverse-lookup/Wizard.phpe Ve *sebastian-code-unit-reverse-lookup/LICENSEVX?phpspec-prophecy/Prophecy/Doubler/Generator/Node/MethodNode.phpV'׶>phpspec-prophecy/Prophecy/Doubler/Generator/Node/ClassNode.phpIVI)Uݶ0phpspec-prophecy/Prophecy/Doubler/LazyDouble.phpF VF l=phpspec-prophecy/Prophecy/Doubler/ClassPatch/KeywordPatch.php V /@ȶEphpspec-prophecy/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php -V -ni?phpspec-prophecy/Prophecy/Doubler/ClassPatch/MagicCallPatch.phpV!KMAphpspec-prophecy/Prophecy/Doubler/ClassPatch/TraversablePatch.php V jNAphpspec-prophecy/Prophecy/Doubler/ClassPatch/SplFileInfoPatch.phpV!h^Hphpspec-prophecy/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.phpV:0`Cphpspec-prophecy/Prophecy/Doubler/ClassPatch/HhvmExceptionPatch.phpVx^Pphpspec-prophecy/Prophecy/Doubler/ClassPatch/ReflectionClassNewInstancePatch.phppVpxDphpspec-prophecy/Prophecy/Doubler/ClassPatch/ClassPatchInterface.phplVl)5:3phpspec-prophecy/Prophecy/Doubler/NameGenerator.phpV7<phpspec-prophecy/Prophecy/Prediction/CallTimesPrediction.php V X:phpspec-prophecy/Prophecy/Prediction/NoCallsPrediction.phpVL9%<phpspec-prophecy/Prophecy/Prediction/PredictionInterface.phpV`IE;phpspec-prophecy/Prophecy/Prediction/CallbackPrediction.phpVVb{ζ7phpspec-prophecy/Prophecy/Prediction/CallPrediction.phpQ VQ I'phpspec-prophecy/Prophecy/Call/Call.php V {:%-phpspec-prophecy/Prophecy/Call/CallCenter.phpV|2phpspec-prophecy/Prophecy/Promise/ThrowPromise.php` -V` -+,;phpspec-prophecy/Prophecy/Promise/ReturnArgumentPromise.php'V'(3phpspec-prophecy/Prophecy/Promise/ReturnPromise.phpV؏5phpspec-prophecy/Prophecy/Promise/CallbackPromise.phpV[6phpspec-prophecy/Prophecy/Promise/PromiseInterface.phpKVK8phpspec-prophecy/Prophecy/Argument/ArgumentsWildcard.php4 V4 A;K2:phpspec-prophecy/Prophecy/Argument/Token/AnyValueToken.phpVFhAphpspec-prophecy/Prophecy/Argument/Token/ArrayEveryEntryToken.phpVpb<phpspec-prophecy/Prophecy/Argument/Token/LogicalAndToken.phpV Nv;phpspec-prophecy/Prophecy/Argument/Token/TokenInterface.phpVٰ<phpspec-prophecy/Prophecy/Argument/Token/ArrayEntryToken.phpVJ:<phpspec-prophecy/Prophecy/Argument/Token/ArrayCountToken.phpV4̶;phpspec-prophecy/Prophecy/Argument/Token/AnyValuesToken.phpVbN/@phpspec-prophecy/Prophecy/Argument/Token/StringContainsToken.phpV>Bphpspec-prophecy/Prophecy/Argument/Token/ApproximateValueToken.phpV#I<phpspec-prophecy/Prophecy/Argument/Token/ExactValueToken.php V 3=phpspec-prophecy/Prophecy/Argument/Token/ObjectStateToken.php9 -V9 -_Jg:phpspec-prophecy/Prophecy/Argument/Token/CallbackToken.php,V,cR̶@phpspec-prophecy/Prophecy/Argument/Token/IdenticalValueToken.phpV<phpspec-prophecy/Prophecy/Argument/Token/LogicalNotToken.phpVr6phpspec-prophecy/Prophecy/Argument/Token/TypeToken.phpVn\-phpspec-prophecy/Prophecy/Util/ExportUtil.php2V2W-phpspec-prophecy/Prophecy/Util/StringUtil.php V %sebastian-exporter/LICENSEVAe)sebastian-exporter/Exporter.php["V["Tphp-file-iterator/LICENSE V sphp-file-iterator/Iterator.phpaVaphp-file-iterator/Facade.php V 0php-file-iterator/Factory.php V y manifest.txtVv7)sebastian-recursion-context/Exception.phpJVJ#sebastian-recursion-context/LICENSEV'sebastian-recursion-context/Context.phpVqP8sebastian-recursion-context/InvalidArgumentException.phpVmH%sebastian-resource-operations/LICENSE V I4sebastian-resource-operations/ResourceOperations.phpUVUhն'php-code-coverage/CodeCoverage/Util.php4V4JZ7php-code-coverage/CodeCoverage/Report/HTML/Renderer.php!V!p9DiAphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Dashboard.php&V&X<php-code-coverage/CodeCoverage/Report/HTML/Renderer/File.phpHJVHJU ĶPphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/dashboard.html.distV{Pphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/directory.html.disteVeǐSphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/coverage_bar.html.dist1V1itLPphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/js/bootstrap.min.jsoVo;Iphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/js/d3.min.jsUNVUN;1Nphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/js/respond.min.jsV{Pphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/js/html5shiv.min.jsL -VL -FMphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/js/holder.min.jsmVmJsѶLphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/js/nv.d3.min.js]V]']4Mphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/js/jquery.min.jsvVvePphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/file_item.html.distgVgV PRphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/method_item.html.distxVx*Uphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/directory_item.html.dist5V5Z]Kphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/file.html.dist -V -DJphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/css/style.css+V+Y`gNphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/css/nv.d3.min.cssX%VX%0,Rphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/css/bootstrap.min.css9V9ܛ2cphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.ttf\V\<ephp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.woff2lFVlFvadphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.woff[V[{cphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.eotNVNXDZcphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.svg¨V¨|ɶAphp-code-coverage/CodeCoverage/Report/HTML/Renderer/Directory.phpr Vr E2L0php-code-coverage/CodeCoverage/Report/Crap4j.php)V)3php-code-coverage/CodeCoverage/Report/XML/Tests.phpV^*2php-code-coverage/CodeCoverage/Report/XML/File.php0V0ڶ2php-code-coverage/CodeCoverage/Report/XML/Node.php^V^N5php-code-coverage/CodeCoverage/Report/XML/Project.php]V]h>4php-code-coverage/CodeCoverage/Report/XML/Totals.phpVoF7php-code-coverage/CodeCoverage/Report/XML/Directory.phpVZ9php-code-coverage/CodeCoverage/Report/XML/File/Method.phpuVuʶ9php-code-coverage/CodeCoverage/Report/XML/File/Report.phpCVCY{ȶ;php-code-coverage/CodeCoverage/Report/XML/File/Coverage.php<V<`ö7php-code-coverage/CodeCoverage/Report/XML/File/Unit.phpB -VB - kr.php-code-coverage/CodeCoverage/Report/Node.phpVΑ7php-code-coverage/CodeCoverage/Report/Node/Iterator.phpVMq3php-code-coverage/CodeCoverage/Report/Node/File.phpIVIъ8php-code-coverage/CodeCoverage/Report/Node/Directory.php_(V_(I\0php-code-coverage/CodeCoverage/Report/Clover.php)V)d.php-code-coverage/CodeCoverage/Report/HTML.phpRVR@*1php-code-coverage/CodeCoverage/Report/Factory.phpfVfW}n-php-code-coverage/CodeCoverage/Report/XML.phpV&}-php-code-coverage/CodeCoverage/Report/PHP.phpVo.php-code-coverage/CodeCoverage/Report/Text.php_!V_!teTLphp-code-coverage/CodeCoverage/Exception/CoveredCodeNotExecutedException.phpVN[6php-code-coverage/CodeCoverage/Exception/Exception.phpVIPphp-code-coverage/CodeCoverage/Exception/UnintentionallyCoveredCodeException.phpV׶Mphp-code-coverage/CodeCoverage/Exception/MissingCoversAnnotationException.phpVXe.=php-code-coverage/CodeCoverage/Exception/RuntimeException.phpVc"\Ephp-code-coverage/CodeCoverage/Exception/InvalidArgumentException.phpV+G)php-code-coverage/CodeCoverage/Driver.phpV0)php-code-coverage/CodeCoverage/Filter.php}V}]Z.php-code-coverage/CodeCoverage/Driver/HHVM.php^V^7b0php-code-coverage/CodeCoverage/Driver/PHPDBG.php V J=0php-code-coverage/CodeCoverage/Driver/Xdebug.phpd Vd _?Kphp-code-coverage/LICENSEVЉxZ"php-code-coverage/CodeCoverage.phpuVuqsymfony/LICENSE)V)symfony/yaml/Inline.phpPVPSsymfony/yaml/Unescaper.phpUVUőUsymfony/yaml/Yaml.php V H)symfony/yaml/Exception/ParseException.php] V] A(symfony/yaml/Exception/DumpException.phpV+symfony/yaml/Exception/RuntimeException.phpV_q-symfony/yaml/Exception/ExceptionInterface.phpV^KAsymfony/yaml/Parser.phptVtD^symfony/yaml/Dumper.php V lDsymfony/yaml/Escaper.php V +oöca.pemVbydoctrine-instantiator/LICENSE$V$ -͂Edoctrine-instantiator/Doctrine/Instantiator/InstantiatorInterface.php~V~:Ldoctrine-instantiator/Doctrine/Instantiator/Exception/ExceptionInterface.phpV.öRdoctrine-instantiator/Doctrine/Instantiator/Exception/InvalidArgumentException.phpVh7IRdoctrine-instantiator/Doctrine/Instantiator/Exception/UnexpectedValueException.php -V -" <doctrine-instantiator/Doctrine/Instantiator/Instantiator.php V &php-token-stream/LICENSEV-& 0php-token-stream/Token/Stream/CachingFactory.phpV_!php-token-stream/Token/Stream.php@V@ܜphp-token-stream/Token.php:bV:b#0!,dbunit/Extensions/Database/TestCaseTrait.php6!V6!X#K(dbunit/Extensions/Database/Exception.phpVm-`0dbunit/Extensions/Database/UI/IMediumPrinter.phpV}0)dbunit/Extensions/Database/UI/Command.phpIVIT.dbunit/Extensions/Database/UI/Mediums/Text.php V o4a6dbunit/Extensions/Database/UI/InvalidModeException.phpV*,'dbunit/Extensions/Database/UI/IMode.phpVd)dbunit/Extensions/Database/UI/Context.phpVG?dbunit/Extensions/Database/UI/Modes/ExportDataSet/Arguments.php -V -:Y5dbunit/Extensions/Database/UI/Modes/ExportDataSet.php V Xq)dbunit/Extensions/Database/UI/IMedium.phpPVPԚ-dbunit/Extensions/Database/UI/ModeFactory.php= -V= -t=.dbunit/Extensions/Database/UI/IModeFactory.php -V -4dbunit/Extensions/Database/IDatabaseListConsumer.php;V;4o2dbunit/Extensions/Database/Operation/Exception.php/V/J0dbunit/Extensions/Database/Operation/Replace.php`V`d綶/dbunit/Extensions/Database/Operation/Insert.phpV td/dbunit/Extensions/Database/Operation/Delete.phpVZ>0;dbunit/Extensions/Database/Operation/IDatabaseOperation.phpV"-dbunit/Extensions/Database/Operation/Null.phpV0Ӷ2dbunit/Extensions/Database/Operation/DeleteAll.phpV}^ /dbunit/Extensions/Database/Operation/Update.phpVW":˶1dbunit/Extensions/Database/Operation/RowBased.php+V+cX0dbunit/Extensions/Database/Operation/Factory.php V p{U2dbunit/Extensions/Database/Operation/Composite.phpVM1dbunit/Extensions/Database/Operation/Truncate.php V ;i'dbunit/Extensions/Database/TestCase.phpV[i-dbunit/Extensions/Database/AbstractTester.phpVCY1dbunit/Extensions/Database/DB/MetaData/Sqlite.php -V -0dbunit/Extensions/Database/DB/MetaData/Dblib.php -V -#j*-0dbunit/Extensions/Database/DB/MetaData/MySQL.phpV <dbunit/Extensions/Database/DB/MetaData/InformationSchema.phpAVA4C"3dbunit/Extensions/Database/DB/MetaData/Firebird.phpV]Y.dbunit/Extensions/Database/DB/MetaData/Oci.phpIVIUWK0dbunit/Extensions/Database/DB/MetaData/PgSQL.phpVA.1dbunit/Extensions/Database/DB/MetaData/SqlSrv.php V yD'dbunit/Extensions/Database/DB/Table.phpV8k8o1dbunit/Extensions/Database/DB/FilteredDataSet.phpFVF (e5dbunit/Extensions/Database/DB/IDatabaseConnection.php V dʶ/dbunit/Extensions/Database/DB/TableMetaData.phpV;Е*dbunit/Extensions/Database/DB/MetaData.phpVPp;dbunit/Extensions/Database/DB/DefaultDatabaseConnection.php}V}+dbunit/Extensions/Database/DB/IMetaData.php3V3@G/dbunit/Extensions/Database/DB/TableIterator.php} -V} -0W6)dbunit/Extensions/Database/DB/DataSet.phpCVCԍ0dbunit/Extensions/Database/DB/ResultSetTable.phpVO&,dbunit/Extensions/Database/DefaultTester.phpVX`6dbunit/Extensions/Database/Constraint/TableIsEqual.phpV7 -8dbunit/Extensions/Database/Constraint/DataSetIsEqual.phpVM7dbunit/Extensions/Database/Constraint/TableRowCount.phpVIXӶ&dbunit/Extensions/Database/ITester.phpV#6dbunit/Extensions/Database/DataSet/MysqlXmlDataSet.phpVƱ¶3dbunit/Extensions/Database/DataSet/QueryDataSet.php V '7u2dbunit/Extensions/Database/DataSet/YamlDataSet.php|V|IK6dbunit/Extensions/Database/DataSet/AbstractDataSet.phpV^,dbunit/Extensions/Database/DataSet/ISpec.phpV݂2dbunit/Extensions/Database/DataSet/TableFilter.php V )Ŷ<dbunit/Extensions/Database/DataSet/AbstractTableMetaData.phpV;c7dbunit/Extensions/Database/DataSet/CompositeDataSet.php5 -V5 -4O;dbunit/Extensions/Database/DataSet/DefaultTableIterator.php V 44dbunit/Extensions/Database/DataSet/DataSetFilter.phpGVG12dbunit/Extensions/Database/DataSet/IYamlParser.phpV@ۈ[1dbunit/Extensions/Database/DataSet/XmlDataSet.phptVtD5dbunit/Extensions/Database/DataSet/DefaultDataSet.phpVw8dbunit/Extensions/Database/DataSet/SymfonyYamlParser.phpOVOPW/dbunit/Extensions/Database/DataSet/IDataSet.phpVZ߶5dbunit/Extensions/Database/DataSet/ITableMetaData.php1V1,+;:dbunit/Extensions/Database/DataSet/Persistors/Abstract.php -V -D:5dbunit/Extensions/Database/DataSet/Persistors/Xml.php5 V5 .9dbunit/Extensions/Database/DataSet/Persistors/FlatXml.php V TZ,6dbunit/Extensions/Database/DataSet/Persistors/Yaml.phpV*勇:dbunit/Extensions/Database/DataSet/Persistors/MysqlXml.php V OӶ9dbunit/Extensions/Database/DataSet/Persistors/Factory.phpV(1dbunit/Extensions/Database/DataSet/CsvDataSet.php V l?dbunit/Extensions/Database/DataSet/ReplacementTableIterator.php V Ns9dbunit/Extensions/Database/DataSet/ReplacementDataSet.php -V -O3dbunit/Extensions/Database/DataSet/ArrayDataSet.phpoVo||3dbunit/Extensions/Database/DataSet/DefaultTable.phptVt϶5dbunit/Extensions/Database/DataSet/ITableIterator.phpV !-5dbunit/Extensions/Database/DataSet/FlatXmlDataSet.php@V@耀3dbunit/Extensions/Database/DataSet/IPersistable.phpV9dbunit/Extensions/Database/DataSet/AbstractXmlDataSet.php V F!:dbunit/Extensions/Database/DataSet/TableMetaDataFilter.php9 V9 52P7dbunit/Extensions/Database/DataSet/ReplacementTable.phphVh/w4dbunit/Extensions/Database/DataSet/Specs/DbQuery.phpVĶ0dbunit/Extensions/Database/DataSet/Specs/Xml.phpVTZ4dbunit/Extensions/Database/DataSet/Specs/FlatXml.phpV߆1dbunit/Extensions/Database/DataSet/Specs/Yaml.phpV{;>5dbunit/Extensions/Database/DataSet/Specs/IFactory.phplVl՗+0dbunit/Extensions/Database/DataSet/Specs/Csv.php -V -:d=4dbunit/Extensions/Database/DataSet/Specs/DbTable.phpVv4dbunit/Extensions/Database/DataSet/Specs/Factory.phpVA̶1dbunit/Extensions/Database/DataSet/QueryTable.phpVVVlN4dbunit/Extensions/Database/DataSet/AbstractTable.phpSVSXlٶ-dbunit/Extensions/Database/DataSet/ITable.phpVȃN;dbunit/Extensions/Database/DataSet/DefaultTableMetaData.phpV.Fphp-invoker/Invoker.phpV w php-invoker/TimeoutException.phppVp~phpunit-mock-objects/LICENSEVC>5phpunit-mock-objects/Framework/MockObject/Matcher.php V mSG8phpunit-mock-objects/Framework/MockObject/Verifiable.phpV'L7phpunit-mock-objects/Framework/MockObject/Invokable.php9V9~9phpunit-mock-objects/Framework/MockObject/MockBuilder.phpVJѶAphpunit-mock-objects/Framework/MockObject/Exception/Exception.phpV]TNphpunit-mock-objects/Framework/MockObject/Exception/BadMethodCallException.phpV).Hphpunit-mock-objects/Framework/MockObject/Exception/RuntimeException.phpVYn48phpunit-mock-objects/Framework/MockObject/Invocation.phpV9T8phpunit-mock-objects/Framework/MockObject/MockObject.phpV0Ҭ>phpunit-mock-objects/Framework/MockObject/InvocationMocker.phpQVQ=@phpunit-mock-objects/Framework/MockObject/Matcher/MethodName.php V vHphpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtLeastOnce.phpVcICphpunit-mock-objects/Framework/MockObject/Matcher/AnyParameters.phpCVC@phpunit-mock-objects/Framework/MockObject/Matcher/Parameters.phpV-EYEphpunit-mock-objects/Framework/MockObject/Matcher/AnyInvokedCount.phpVDs$Iphpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtLeastCount.phpV R@phpunit-mock-objects/Framework/MockObject/Matcher/Invocation.phpVKbKphpunit-mock-objects/Framework/MockObject/Matcher/ConsecutiveParameters.phpV0^zDphpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtIndex.php V YBphpunit-mock-objects/Framework/MockObject/Matcher/InvokedCount.php V SGHphpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtMostCount.phpVEphpunit-mock-objects/Framework/MockObject/Matcher/InvokedRecorder.php[V[ڭ\Iphpunit-mock-objects/Framework/MockObject/Matcher/StatelessInvocation.phpkVk϶7phpunit-mock-objects/Framework/MockObject/Generator.php}V}SʼnHphpunit-mock-objects/Framework/MockObject/Generator/wsdl_method.tpl.dist<V<iKphpunit-mock-objects/Framework/MockObject/Generator/unmocked_clone.tpl.distV8W}ضIphpunit-mock-objects/Framework/MockObject/Generator/mocked_class.tpl.dist^V^!Iphpunit-mock-objects/Framework/MockObject/Generator/mocked_clone.tpl.distVaTKphpunit-mock-objects/Framework/MockObject/Generator/proxied_method.tpl.distV Gphpunit-mock-objects/Framework/MockObject/Generator/wsdl_class.tpl.distVw&SHphpunit-mock-objects/Framework/MockObject/Generator/trait_class.tpl.dist7V7[$~Jphpunit-mock-objects/Framework/MockObject/Generator/mocked_method.tpl.distVZ ߶Pphpunit-mock-objects/Framework/MockObject/Generator/mocked_class_method.tpl.distV4޶Qphpunit-mock-objects/Framework/MockObject/Generator/mocked_static_method.tpl.distVϪ^b;phpunit-mock-objects/Framework/MockObject/Builder/Match.phpWVWEA>phpunit-mock-objects/Framework/MockObject/Builder/Identity.phpV(4Fphpunit-mock-objects/Framework/MockObject/Builder/InvocationMocker.php\V\w,Ephpunit-mock-objects/Framework/MockObject/Builder/ParametersMatch.phpVsґζ?phpunit-mock-objects/Framework/MockObject/Builder/Namespace.phpVM쉔Ephpunit-mock-objects/Framework/MockObject/Builder/MethodNameMatch.php)V)s:phpunit-mock-objects/Framework/MockObject/Builder/Stub.phpoVohr?phpunit-mock-objects/Framework/MockObject/Invocation/Object.phpV?phpunit-mock-objects/Framework/MockObject/Invocation/Static.phpFVF~럶2phpunit-mock-objects/Framework/MockObject/Stub.php\V\f+Fж<phpunit-mock-objects/Framework/MockObject/Stub/Exception.phpV0׶9phpunit-mock-objects/Framework/MockObject/Stub/Return.phpVLf+=phpunit-mock-objects/Framework/MockObject/Stub/ReturnSelf.phpVIAphpunit-mock-objects/Framework/MockObject/Stub/ReturnValueMap.php|V|uB Cphpunit-mock-objects/Framework/MockObject/Stub/ConsecutiveCalls.phpV2 Dphpunit-mock-objects/Framework/MockObject/Stub/MatcherCollection.php:V:YAphpunit-mock-objects/Framework/MockObject/Stub/ReturnCallback.phpVg`Aphpunit-mock-objects/Framework/MockObject/Stub/ReturnArgument.phpV9)`phpunit/Exception.phpsVsy:۶phpunit/Framework/Test.phpV%phpunit/Framework/Exception.php V ~b!phpunit/Framework/OutputError.phpVj̶phpunit/Framework/Assert.phpWXVWXp[+phpunit/Framework/CodeCoverageException.phpqVqEphpunit/Framework/TestSuite.phpGsVGsphpunit/Framework/RiskyTest.phpV\$phpunit/Framework/SelfDescribing.phpV:|&phpunit/Framework/Assert/Functions.phpV4-$phpunit/Framework/SyntheticError.php V K$phpunit/Framework/RiskyTestError.phpV?v%phpunit/Framework/WarningTestCase.phpV7"phpunit/Framework/TestListener.phpa Va ]&phpunit/Framework/ExceptionWrapper.phpV!phpunit/Framework/SkippedTest.phpV_ $2phpunit/Framework/InvalidCoversTargetException.phpV%Mphpunit/Framework/TestCase.php -V -f0phpunit/Framework/ExpectationFailedException.phpV_S;phpunit/Framework/Error.php$V$X%yW phpunit/Framework/Constraint.php:V:5L*phpunit/Framework/AssertionFailedError.php{V{+(phpunit/Framework/IncompleteTestCase.php5V5.S,phpunit/Framework/TestSuite/DataProvider.phpVg+phpunit/Framework/Constraint/IsAnything.phppVpV&phpunit/Framework/Constraint/Count.php V u$phpunit/Framework/Constraint/And.php, V, s&phpunit/Framework/BaseTestListener.phpV_03&phpunit/Framework/SkippedTestError.php V T5phpunit/Framework/UnintentionallyCoveredCodeError.phpV摢phpunit/Framework/Warning.phppVptd%phpunit/Extensions/GroupTestSuite.phpV0$phpunit/Extensions/PhptTestSuite.phpV ܶ#phpunit/Extensions/RepeatedTest.phpV%phpunit/Extensions/TicketListener.php&V&HC$phpunit/Extensions/TestDecorator.php@ V@ 9#phpunit/Extensions/PhptTestCase.phpV Rphpunit/TextUI/Command.php\V\ַAphpunit/TextUI/TestRunner.phpVq:] phpunit/TextUI/ResultPrinter.php6LV6L\ phpunit/Util/Test.phpV_|kphpunit/Util/Filesystem.phpV8phpunit/Util/Getopt.phpVphpunit/Util/ErrorHandler.php} V} *zphpunit/Util/String.phpVd&phpunit/Util/InvalidArgumentHelper.phpSVS(Qϩphpunit/Util/Printer.phpWVW1phpunit/Util/Configuration.phpzVz8c$pphpunit/Util/GlobalState.php%V% ޫphpunit/Util/Log/JSON.phpVM9fphpunit/Util/Log/TeamCity.phpl+Vl+öphpunit/Util/Log/TAP.phpVKlphpunit/Util/Log/JUnit.php3V3蒶phpunit/Util/Blacklist.php V DԶ"phpunit/Util/TestSuiteIterator.phpV⍘phpunit/Util/Filter.php V +phpunit/Util/TestDox/ResultPrinter/HTML.php V +phpunit/Util/TestDox/ResultPrinter/Text.phpwVw ;&phpunit/Util/TestDox/ResultPrinter.phpi"Vi"q৶'phpunit/Util/TestDox/NamePrettifier.phpL VL phpunit/Util/Regex.phpVPdphpunit/Util/Type.php3V3Nphpunit/Util/PHP/Default.phpVy1phpunit/Util/PHP/Template/TestCaseMethod.tpl.dist V phpunit/Util/PHP/Windows.php V H6phpunit/Util/PHP/eval-stdin.php6V6Gphpunit/Util/Fileloader.phpVphpunit/Util/XML.phpV0۹Bphpunit/Util/PHP.php!V!nphpunit/Runner/Exception.phptVtdphpunit/Runner/Filter/Test.php V a'phpunit/Runner/Filter/Group/Exclude.phpVPF'phpunit/Runner/Filter/Group/Include.phpVVe!phpunit/Runner/Filter/Factory.phpVἕphpunit/Runner/Filter/Group.phpVkm1"phpunit/Runner/TestSuiteLoader.phpV!phpunit/Runner/BaseTestRunner.php{V{DJ{*phpunit/Runner/StandardTestSuiteLoader.php V phpunit/Runner/Version.phpVܑsebastian-environment/LICENSE -V -߶!sebastian-environment/Runtime.php@V@Ҏ!˶!sebastian-environment/Console.phpVhh϶)phpdocumentor-reflection-docblock/LICENSE8V8ʶGphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock.phpc6Vc6qPphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Location.phpqVqu/Tphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/SinceTag.php|V|tRRphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/SeeTag.phpVi?$Vphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/VersionTag.phpx -Vx -EƶWphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/PropertyTag.phpOVO#mUphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/ReturnTag.phpVpSYphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/DeprecatedTag.phpVK Uphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/ThrowsTag.phpLVL"Uphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/CoversTag.phpIVI9{Uphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/SourceTag.php V n*Sphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/UsesTag.phpEVE.˶Uphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/MethodTag.php~V~!kͶ[phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/PropertyReadTag.php[V[< =Uphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/AuthorTag.phpM VM 1Rphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/VarTag.phpEVEͶSphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/LinkTag.phpLVLFVphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/ExampleTag.phpV -Tphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/ParamTag.phpH VH  \phpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag/PropertyWriteTag.php]V]RpRphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Serializer.phpVrжOphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Context.php5V5l.%Wphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Type/Collection.phpV+=4Kphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Tag.php(V(E6 Sphpdocumentor-reflection-docblock/phpDocumentor/Reflection/DocBlock/Description.phpVԲضsebastian-version/LICENSEVnsebastian-version/Version.phpVN\Ƕ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\GlobalState; - -/** - */ -interface Exception -{ -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\GlobalState; - -use ReflectionClass; -use Serializable; - -/** - * A snapshot of global state. - */ -class Snapshot -{ - /** - * @var Blacklist - */ - private $blacklist; - - /** - * @var array - */ - private $globalVariables = array(); - - /** - * @var array - */ - private $superGlobalArrays = array(); - - /** - * @var array - */ - private $superGlobalVariables = array(); - - /** - * @var array - */ - private $staticAttributes = array(); - - /** - * @var array - */ - private $iniSettings = array(); - - /** - * @var array - */ - private $includedFiles = array(); - - /** - * @var array - */ - private $constants = array(); - - /** - * @var array - */ - private $functions = array(); - - /** - * @var array - */ - private $interfaces = array(); - - /** - * @var array - */ - private $classes = array(); - - /** - * @var array - */ - private $traits = array(); - - /** - * Creates a snapshot of the current global state. - * - * @param Blacklist $blacklist - * @param bool $includeGlobalVariables - * @param bool $includeStaticAttributes - * @param bool $includeConstants - * @param bool $includeFunctions - * @param bool $includeClasses - * @param bool $includeInterfaces - * @param bool $includeTraits - * @param bool $includeIniSettings - * @param bool $includeIncludedFiles - */ - public function __construct(Blacklist $blacklist = null, $includeGlobalVariables = true, $includeStaticAttributes = true, $includeConstants = true, $includeFunctions = true, $includeClasses = true, $includeInterfaces = true, $includeTraits = true, $includeIniSettings = true, $includeIncludedFiles = true) - { - if ($blacklist === null) { - $blacklist = new Blacklist; - } - - $this->blacklist = $blacklist; - - if ($includeConstants) { - $this->snapshotConstants(); - } - - if ($includeFunctions) { - $this->snapshotFunctions(); - } - - if ($includeClasses || $includeStaticAttributes) { - $this->snapshotClasses(); - } - - if ($includeInterfaces) { - $this->snapshotInterfaces(); - } - - if ($includeGlobalVariables) { - $this->setupSuperGlobalArrays(); - $this->snapshotGlobals(); - } - - if ($includeStaticAttributes) { - $this->snapshotStaticAttributes(); - } - - if ($includeIniSettings) { - $this->iniSettings = ini_get_all(null, false); - } - - if ($includeIncludedFiles) { - $this->includedFiles = get_included_files(); - } - - if (function_exists('get_declared_traits')) { - $this->traits = get_declared_traits(); - } - } - - /** - * @return Blacklist - */ - public function blacklist() - { - return $this->blacklist; - } - - /** - * @return array - */ - public function globalVariables() - { - return $this->globalVariables; - } - - /** - * @return array - */ - public function superGlobalVariables() - { - return $this->superGlobalVariables; - } - - /** - * Returns a list of all super-global variable arrays. - * - * @return array - */ - public function superGlobalArrays() - { - return $this->superGlobalArrays; - } - - /** - * @return array - */ - public function staticAttributes() - { - return $this->staticAttributes; - } - - /** - * @return array - */ - public function iniSettings() - { - return $this->iniSettings; - } - - /** - * @return array - */ - public function includedFiles() - { - return $this->includedFiles; - } - - /** - * @return array - */ - public function constants() - { - return $this->constants; - } - - /** - * @return array - */ - public function functions() - { - return $this->functions; - } - - /** - * @return array - */ - public function interfaces() - { - return $this->interfaces; - } - - /** - * @return array - */ - public function classes() - { - return $this->classes; - } - - /** - * @return array - */ - public function traits() - { - return $this->traits; - } - - /** - * Creates a snapshot user-defined constants. - */ - private function snapshotConstants() - { - $constants = get_defined_constants(true); - - if (isset($constants['user'])) { - $this->constants = $constants['user']; - } - } - - /** - * Creates a snapshot user-defined functions. - */ - private function snapshotFunctions() - { - $functions = get_defined_functions(); - - $this->functions = $functions['user']; - } - - /** - * Creates a snapshot user-defined classes. - */ - private function snapshotClasses() - { - foreach (array_reverse(get_declared_classes()) as $className) { - $class = new ReflectionClass($className); - - if (!$class->isUserDefined()) { - break; - } - - $this->classes[] = $className; - } - - $this->classes = array_reverse($this->classes); - } - - /** - * Creates a snapshot user-defined interfaces. - */ - private function snapshotInterfaces() - { - foreach (array_reverse(get_declared_interfaces()) as $interfaceName) { - $class = new ReflectionClass($interfaceName); - - if (!$class->isUserDefined()) { - break; - } - - $this->interfaces[] = $interfaceName; - } - - $this->interfaces = array_reverse($this->interfaces); - } - - /** - * Creates a snapshot of all global and super-global variables. - */ - private function snapshotGlobals() - { - $superGlobalArrays = $this->superGlobalArrays(); - - foreach ($superGlobalArrays as $superGlobalArray) { - $this->snapshotSuperGlobalArray($superGlobalArray); - } - - foreach (array_keys($GLOBALS) as $key) { - if ($key != 'GLOBALS' && - !in_array($key, $superGlobalArrays) && - $this->canBeSerialized($GLOBALS[$key]) && - !$this->blacklist->isGlobalVariableBlacklisted($key)) { - $this->globalVariables[$key] = unserialize(serialize($GLOBALS[$key])); - } - } - } - - /** - * Creates a snapshot a super-global variable array. - * - * @param $superGlobalArray - */ - private function snapshotSuperGlobalArray($superGlobalArray) - { - $this->superGlobalVariables[$superGlobalArray] = array(); - - if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) { - foreach ($GLOBALS[$superGlobalArray] as $key => $value) { - $this->superGlobalVariables[$superGlobalArray][$key] = unserialize(serialize($value)); - } - } - } - - /** - * Creates a snapshot of all static attributes in user-defined classes. - */ - private function snapshotStaticAttributes() - { - foreach ($this->classes as $className) { - $class = new ReflectionClass($className); - $snapshot = array(); - - foreach ($class->getProperties() as $attribute) { - if ($attribute->isStatic()) { - $name = $attribute->getName(); - - if ($this->blacklist->isStaticAttributeBlacklisted($className, $name)) { - continue; - } - - $attribute->setAccessible(true); - $value = $attribute->getValue(); - - if ($this->canBeSerialized($value)) { - $snapshot[$name] = unserialize(serialize($value)); - } - } - } - - if (!empty($snapshot)) { - $this->staticAttributes[$className] = $snapshot; - } - } - } - - /** - * Returns a list of all super-global variable arrays. - * - * @return array - */ - private function setupSuperGlobalArrays() - { - $this->superGlobalArrays = array( - '_ENV', - '_POST', - '_GET', - '_COOKIE', - '_SERVER', - '_FILES', - '_REQUEST' - ); - - if (ini_get('register_long_arrays') == '1') { - $this->superGlobalArrays = array_merge( - $this->superGlobalArrays, - array( - 'HTTP_ENV_VARS', - 'HTTP_POST_VARS', - 'HTTP_GET_VARS', - 'HTTP_COOKIE_VARS', - 'HTTP_SERVER_VARS', - 'HTTP_POST_FILES' - ) - ); - } - } - - /** - * @param mixed $variable - * @return bool - * @todo Implement this properly - */ - private function canBeSerialized($variable) - { - if (!is_object($variable)) { - return !is_resource($variable); - } - - if ($variable instanceof \stdClass) { - return true; - } - - $class = new ReflectionClass($variable); - - do { - if ($class->isInternal()) { - return $variable instanceof Serializable; - } - } while ($class = $class->getParentClass()); - - return true; - } -} -GlobalState - -Copyright (c) 2001-2015, Sebastian Bergmann . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Sebastian Bergmann nor the names of his - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\GlobalState; - -use ReflectionProperty; - -/** - * Restorer of snapshots of global state. - */ -class Restorer -{ - /** - * Deletes function definitions that are not defined in a snapshot. - * - * @param Snapshot $snapshot - * @throws RuntimeException when the uopz_delete() function is not available - * @see https://github.com/krakjoe/uopz - */ - public function restoreFunctions(Snapshot $snapshot) - { - if (!function_exists('uopz_delete')) { - throw new RuntimeException('The uopz_delete() function is required for this operation'); - } - - $functions = get_defined_functions(); - - foreach (array_diff($functions['user'], $snapshot->functions()) as $function) { - uopz_delete($function); - } - } - - /** - * Restores all global and super-global variables from a snapshot. - * - * @param Snapshot $snapshot - */ - public function restoreGlobalVariables(Snapshot $snapshot) - { - $superGlobalArrays = $snapshot->superGlobalArrays(); - - foreach ($superGlobalArrays as $superGlobalArray) { - $this->restoreSuperGlobalArray($snapshot, $superGlobalArray); - } - - $globalVariables = $snapshot->globalVariables(); - - foreach (array_keys($GLOBALS) as $key) { - if ($key != 'GLOBALS' && - !in_array($key, $superGlobalArrays) && - !$snapshot->blacklist()->isGlobalVariableBlacklisted($key)) { - if (isset($globalVariables[$key])) { - $GLOBALS[$key] = $globalVariables[$key]; - } else { - unset($GLOBALS[$key]); - } - } - } - } - - /** - * Restores all static attributes in user-defined classes from this snapshot. - * - * @param Snapshot $snapshot - */ - public function restoreStaticAttributes(Snapshot $snapshot) - { - $current = new Snapshot($snapshot->blacklist(), false, false, false, false, true, false, false, false, false); - $newClasses = array_diff($current->classes(), $snapshot->classes()); - unset($current); - - foreach ($snapshot->staticAttributes() as $className => $staticAttributes) { - foreach ($staticAttributes as $name => $value) { - $reflector = new ReflectionProperty($className, $name); - $reflector->setAccessible(true); - $reflector->setValue($value); - } - } - - foreach ($newClasses as $className) { - $class = new \ReflectionClass($className); - $defaults = $class->getDefaultProperties(); - - foreach ($class->getProperties() as $attribute) { - if (!$attribute->isStatic()) { - continue; - } - - $name = $attribute->getName(); - - if ($snapshot->blacklist()->isStaticAttributeBlacklisted($className, $name)) { - continue; - } - - if (!isset($defaults[$name])) { - continue; - } - - $attribute->setAccessible(true); - $attribute->setValue($defaults[$name]); - } - } - } - - /** - * Restores a super-global variable array from this snapshot. - * - * @param Snapshot $snapshot - * @param $superGlobalArray - */ - private function restoreSuperGlobalArray(Snapshot $snapshot, $superGlobalArray) - { - $superGlobalVariables = $snapshot->superGlobalVariables(); - - if (isset($GLOBALS[$superGlobalArray]) && - is_array($GLOBALS[$superGlobalArray]) && - isset($superGlobalVariables[$superGlobalArray])) { - $keys = array_keys( - array_merge( - $GLOBALS[$superGlobalArray], - $superGlobalVariables[$superGlobalArray] - ) - ); - - foreach ($keys as $key) { - if (isset($superGlobalVariables[$superGlobalArray][$key])) { - $GLOBALS[$superGlobalArray][$key] = $superGlobalVariables[$superGlobalArray][$key]; - } else { - unset($GLOBALS[$superGlobalArray][$key]); - } - } - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\GlobalState; - -use ReflectionClass; - -/** - * A blacklist for global state elements that should not be snapshotted. - */ -class Blacklist -{ - /** - * @var array - */ - private $globalVariables = array(); - - /** - * @var array - */ - private $classes = array(); - - /** - * @var array - */ - private $classNamePrefixes = array(); - - /** - * @var array - */ - private $parentClasses = array(); - - /** - * @var array - */ - private $interfaces = array(); - - /** - * @var array - */ - private $staticAttributes = array(); - - /** - * @param string $variableName - */ - public function addGlobalVariable($variableName) - { - $this->globalVariables[$variableName] = true; - } - - /** - * @param string $className - */ - public function addClass($className) - { - $this->classes[] = $className; - } - - /** - * @param string $className - */ - public function addSubclassesOf($className) - { - $this->parentClasses[] = $className; - } - - /** - * @param string $interfaceName - */ - public function addImplementorsOf($interfaceName) - { - $this->interfaces[] = $interfaceName; - } - - /** - * @param string $classNamePrefix - */ - public function addClassNamePrefix($classNamePrefix) - { - $this->classNamePrefixes[] = $classNamePrefix; - } - - /** - * @param string $className - * @param string $attributeName - */ - public function addStaticAttribute($className, $attributeName) - { - if (!isset($this->staticAttributes[$className])) { - $this->staticAttributes[$className] = array(); - } - - $this->staticAttributes[$className][$attributeName] = true; - } - - /** - * @param string $variableName - * @return bool - */ - public function isGlobalVariableBlacklisted($variableName) - { - return isset($this->globalVariables[$variableName]); - } - - /** - * @param string $className - * @param string $attributeName - * @return bool - */ - public function isStaticAttributeBlacklisted($className, $attributeName) - { - if (in_array($className, $this->classes)) { - return true; - } - - foreach ($this->classNamePrefixes as $prefix) { - if (strpos($className, $prefix) === 0) { - return true; - } - } - - $class = new ReflectionClass($className); - - foreach ($this->parentClasses as $type) { - if ($class->isSubclassOf($type)) { - return true; - } - } - - foreach ($this->interfaces as $type) { - if ($class->implementsInterface($type)) { - return true; - } - } - - if (isset($this->staticAttributes[$className][$attributeName])) { - return true; - } - - return false; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\GlobalState; - -/** - */ -class RuntimeException extends \RuntimeException implements Exception -{ -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\GlobalState; - -/** - * Exports parts of a Snapshot as PHP code. - */ -class CodeExporter -{ - /** - * @param Snapshot $snapshot - * @return string - */ - public function constants(Snapshot $snapshot) - { - $result = ''; - - foreach ($snapshot->constants() as $name => $value) { - $result .= sprintf( - 'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n", - $name, - $name, - $this->exportVariable($value) - ); - } - - return $result; - } - - /** - * @param Snapshot $snapshot - * @return string - */ - public function iniSettings(Snapshot $snapshot) - { - $result = ''; - - foreach ($snapshot->iniSettings() as $key => $value) { - $result .= sprintf( - '@ini_set(%s, %s);' . "\n", - $this->exportVariable($key), - $this->exportVariable($value) - ); - } - - return $result; - } - - /** - * @param mixed $variable - * @return string - */ - private function exportVariable($variable) - { - if (is_scalar($variable) || is_null($variable) || - (is_array($variable) && $this->arrayOnlyContainsScalars($variable))) { - return var_export($variable, true); - } - - return 'unserialize(' . var_export(serialize($variable), true) . ')'; - } - - /** - * @param array $array - * @return bool - */ - private function arrayOnlyContainsScalars(array $array) - { - $result = true; - - foreach ($array as $element) { - if (is_array($element)) { - $result = self::arrayOnlyContainsScalars($element); - } elseif (!is_scalar($element) && !is_null($element)) { - $result = false; - } - - if ($result === false) { - break; - } - } - - return $result; - } -} -Text_Template - -Copyright (c) 2009-2015, Sebastian Bergmann . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Sebastian Bergmann nor the names of his - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * A simple template engine. - * - * @since Class available since Release 1.0.0 - */ -class Text_Template -{ - /** - * @var string - */ - protected $template = ''; - - /** - * @var string - */ - protected $openDelimiter = '{'; - - /** - * @var string - */ - protected $closeDelimiter = '}'; - - /** - * @var array - */ - protected $values = array(); - - /** - * Constructor. - * - * @param string $file - * @throws InvalidArgumentException - */ - public function __construct($file = '', $openDelimiter = '{', $closeDelimiter = '}') - { - $this->setFile($file); - $this->openDelimiter = $openDelimiter; - $this->closeDelimiter = $closeDelimiter; - } - - /** - * Sets the template file. - * - * @param string $file - * @throws InvalidArgumentException - */ - public function setFile($file) - { - $distFile = $file . '.dist'; - - if (file_exists($file)) { - $this->template = file_get_contents($file); - } - - else if (file_exists($distFile)) { - $this->template = file_get_contents($distFile); - } - - else { - throw new InvalidArgumentException( - 'Template file could not be loaded.' - ); - } - } - - /** - * Sets one or more template variables. - * - * @param array $values - * @param bool $merge - */ - public function setVar(array $values, $merge = TRUE) - { - if (!$merge || empty($this->values)) { - $this->values = $values; - } else { - $this->values = array_merge($this->values, $values); - } - } - - /** - * Renders the template and returns the result. - * - * @return string - */ - public function render() - { - $keys = array(); - - foreach ($this->values as $key => $value) { - $keys[] = $this->openDelimiter . $key . $this->closeDelimiter; - } - - return str_replace($keys, $this->values, $this->template); - } - - /** - * Renders the template and writes the result to a file. - * - * @param string $target - */ - public function renderTo($target) - { - $fp = @fopen($target, 'wt'); - - if ($fp) { - fwrite($fp, $this->render()); - fclose($fp); - } else { - $error = error_get_last(); - - throw new RuntimeException( - sprintf( - 'Could not write to %s: %s', - $target, - substr( - $error['message'], - strpos($error['message'], ':') + 2 - ) - ) - ); - } - } -} - -Diff - -Copyright (c) 2002-2015, Sebastian Bergmann . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Sebastian Bergmann nor the names of his - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Diff\LCS; - -/** - * Interface for implementations of longest common subsequence calculation. - */ -interface LongestCommonSubsequence -{ - /** - * Calculates the longest common subsequence of two arrays. - * - * @param array $from - * @param array $to - * - * @return array - */ - public function calculate(array $from, array $to); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Diff\LCS; - -/** - * Memory-efficient implementation of longest common subsequence calculation. - */ -class MemoryEfficientImplementation implements LongestCommonSubsequence -{ - /** - * Calculates the longest common subsequence of two arrays. - * - * @param array $from - * @param array $to - * - * @return array - */ - public function calculate(array $from, array $to) - { - $cFrom = count($from); - $cTo = count($to); - - if ($cFrom == 0) { - return array(); - } elseif ($cFrom == 1) { - if (in_array($from[0], $to)) { - return array($from[0]); - } else { - return array(); - } - } else { - $i = intval($cFrom / 2); - $fromStart = array_slice($from, 0, $i); - $fromEnd = array_slice($from, $i); - $llB = $this->length($fromStart, $to); - $llE = $this->length(array_reverse($fromEnd), array_reverse($to)); - $jMax = 0; - $max = 0; - - for ($j = 0; $j <= $cTo; $j++) { - $m = $llB[$j] + $llE[$cTo - $j]; - - if ($m >= $max) { - $max = $m; - $jMax = $j; - } - } - - $toStart = array_slice($to, 0, $jMax); - $toEnd = array_slice($to, $jMax); - - return array_merge( - $this->calculate($fromStart, $toStart), - $this->calculate($fromEnd, $toEnd) - ); - } - } - - /** - * @param array $from - * @param array $to - * - * @return array - */ - private function length(array $from, array $to) - { - $current = array_fill(0, count($to) + 1, 0); - $cFrom = count($from); - $cTo = count($to); - - for ($i = 0; $i < $cFrom; $i++) { - $prev = $current; - - for ($j = 0; $j < $cTo; $j++) { - if ($from[$i] == $to[$j]) { - $current[$j + 1] = $prev[$j] + 1; - } else { - $current[$j + 1] = max($current[$j], $prev[$j + 1]); - } - } - } - - return $current; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Diff\LCS; - -/** - * Time-efficient implementation of longest common subsequence calculation. - */ -class TimeEfficientImplementation implements LongestCommonSubsequence -{ - /** - * Calculates the longest common subsequence of two arrays. - * - * @param array $from - * @param array $to - * - * @return array - */ - public function calculate(array $from, array $to) - { - $common = array(); - $fromLength = count($from); - $toLength = count($to); - $width = $fromLength + 1; - $matrix = new \SplFixedArray($width * ($toLength + 1)); - - for ($i = 0; $i <= $fromLength; ++$i) { - $matrix[$i] = 0; - } - - for ($j = 0; $j <= $toLength; ++$j) { - $matrix[$j * $width] = 0; - } - - for ($i = 1; $i <= $fromLength; ++$i) { - for ($j = 1; $j <= $toLength; ++$j) { - $o = ($j * $width) + $i; - $matrix[$o] = max( - $matrix[$o - 1], - $matrix[$o - $width], - $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0 - ); - } - } - - $i = $fromLength; - $j = $toLength; - - while ($i > 0 && $j > 0) { - if ($from[$i-1] === $to[$j-1]) { - $common[] = $from[$i-1]; - --$i; - --$j; - } else { - $o = ($j * $width) + $i; - if ($matrix[$o - $width] > $matrix[$o - 1]) { - --$j; - } else { - --$i; - } - } - } - - return array_reverse($common); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Diff; - -/** - */ -class Line -{ - const ADDED = 1; - const REMOVED = 2; - const UNCHANGED = 3; - - /** - * @var int - */ - private $type; - - /** - * @var string - */ - private $content; - - /** - * @param int $type - * @param string $content - */ - public function __construct($type = self::UNCHANGED, $content = '') - { - $this->type = $type; - $this->content = $content; - } - - /** - * @return string - */ - public function getContent() - { - return $this->content; - } - - /** - * @return int - */ - public function getType() - { - return $this->type; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Diff; - -use SebastianBergmann\Diff\LCS\LongestCommonSubsequence; -use SebastianBergmann\Diff\LCS\TimeEfficientImplementation; -use SebastianBergmann\Diff\LCS\MemoryEfficientImplementation; - -/** - * Diff implementation. - */ -class Differ -{ - /** - * @var string - */ - private $header; - - /** - * @var bool - */ - private $showNonDiffLines; - - /** - * @param string $header - */ - public function __construct($header = "--- Original\n+++ New\n", $showNonDiffLines = true) - { - $this->header = $header; - $this->showNonDiffLines = $showNonDiffLines; - } - - /** - * Returns the diff between two arrays or strings as string. - * - * @param array|string $from - * @param array|string $to - * @param LongestCommonSubsequence $lcs - * - * @return string - */ - public function diff($from, $to, LongestCommonSubsequence $lcs = null) - { - if (!is_array($from) && !is_string($from)) { - $from = (string) $from; - } - - if (!is_array($to) && !is_string($to)) { - $to = (string) $to; - } - - $buffer = $this->header; - $diff = $this->diffToArray($from, $to, $lcs); - - $inOld = false; - $i = 0; - $old = array(); - - foreach ($diff as $line) { - if ($line[1] === 0 /* OLD */) { - if ($inOld === false) { - $inOld = $i; - } - } elseif ($inOld !== false) { - if (($i - $inOld) > 5) { - $old[$inOld] = $i - 1; - } - - $inOld = false; - } - - ++$i; - } - - $start = isset($old[0]) ? $old[0] : 0; - $end = count($diff); - - if ($tmp = array_search($end, $old)) { - $end = $tmp; - } - - $newChunk = true; - - for ($i = $start; $i < $end; $i++) { - if (isset($old[$i])) { - $buffer .= "\n"; - $newChunk = true; - $i = $old[$i]; - } - - if ($newChunk) { - if ($this->showNonDiffLines === true) { - $buffer .= "@@ @@\n"; - } - $newChunk = false; - } - - if ($diff[$i][1] === 1 /* ADDED */) { - $buffer .= '+' . $diff[$i][0] . "\n"; - } elseif ($diff[$i][1] === 2 /* REMOVED */) { - $buffer .= '-' . $diff[$i][0] . "\n"; - } elseif ($this->showNonDiffLines === true) { - $buffer .= ' ' . $diff[$i][0] . "\n"; - } - } - - return $buffer; - } - - /** - * Returns the diff between two arrays or strings as array. - * - * Each array element contains two elements: - * - [0] => string $token - * - [1] => 2|1|0 - * - * - 2: REMOVED: $token was removed from $from - * - 1: ADDED: $token was added to $from - * - 0: OLD: $token is not changed in $to - * - * @param array|string $from - * @param array|string $to - * @param LongestCommonSubsequence $lcs - * - * @return array - */ - public function diffToArray($from, $to, LongestCommonSubsequence $lcs = null) - { - preg_match_all('(\r\n|\r|\n)', $from, $fromMatches); - preg_match_all('(\r\n|\r|\n)', $to, $toMatches); - - if (is_string($from)) { - $from = preg_split('(\r\n|\r|\n)', $from); - } - - if (is_string($to)) { - $to = preg_split('(\r\n|\r|\n)', $to); - } - - $start = array(); - $end = array(); - $fromLength = count($from); - $toLength = count($to); - $length = min($fromLength, $toLength); - - for ($i = 0; $i < $length; ++$i) { - if ($from[$i] === $to[$i]) { - $start[] = $from[$i]; - unset($from[$i], $to[$i]); - } else { - break; - } - } - - $length -= $i; - - for ($i = 1; $i < $length; ++$i) { - if ($from[$fromLength - $i] === $to[$toLength - $i]) { - array_unshift($end, $from[$fromLength - $i]); - unset($from[$fromLength - $i], $to[$toLength - $i]); - } else { - break; - } - } - - if ($lcs === null) { - $lcs = $this->selectLcsImplementation($from, $to); - } - - $common = $lcs->calculate(array_values($from), array_values($to)); - $diff = array(); - - if (isset($fromMatches[0]) && $toMatches[0] && - count($fromMatches[0]) === count($toMatches[0]) && - $fromMatches[0] !== $toMatches[0]) { - $diff[] = array( - '#Warning: Strings contain different line endings!', 0 - ); - } - - foreach ($start as $token) { - $diff[] = array($token, 0 /* OLD */); - } - - reset($from); - reset($to); - - foreach ($common as $token) { - while ((($fromToken = reset($from)) !== $token)) { - $diff[] = array(array_shift($from), 2 /* REMOVED */); - } - - while ((($toToken = reset($to)) !== $token)) { - $diff[] = array(array_shift($to), 1 /* ADDED */); - } - - $diff[] = array($token, 0 /* OLD */); - - array_shift($from); - array_shift($to); - } - - while (($token = array_shift($from)) !== null) { - $diff[] = array($token, 2 /* REMOVED */); - } - - while (($token = array_shift($to)) !== null) { - $diff[] = array($token, 1 /* ADDED */); - } - - foreach ($end as $token) { - $diff[] = array($token, 0 /* OLD */); - } - - return $diff; - } - - /** - * @param array $from - * @param array $to - * - * @return LongestCommonSubsequence - */ - private function selectLcsImplementation(array $from, array $to) - { - // We do not want to use the time-efficient implementation if its memory - // footprint will probably exceed this value. Note that the footprint - // calculation is only an estimation for the matrix and the LCS method - // will typically allocate a bit more memory than this. - $memoryLimit = 100 * 1024 * 1024; - - if ($this->calculateEstimatedFootprint($from, $to) > $memoryLimit) { - return new MemoryEfficientImplementation; - } - - return new TimeEfficientImplementation; - } - - /** - * Calculates the estimated memory footprint for the DP-based method. - * - * @param array $from - * @param array $to - * - * @return int - */ - private function calculateEstimatedFootprint(array $from, array $to) - { - $itemSize = PHP_INT_SIZE == 4 ? 76 : 144; - - return $itemSize * pow(min(count($from), count($to)), 2); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Diff; - -/** - * Unified diff parser. - */ -class Parser -{ - /** - * @param string $string - * - * @return Diff[] - */ - public function parse($string) - { - $lines = preg_split('(\r\n|\r|\n)', $string); - $lineCount = count($lines); - $diffs = array(); - $diff = null; - $collected = array(); - - for ($i = 0; $i < $lineCount; ++$i) { - if (preg_match('(^---\\s+(?P\\S+))', $lines[$i], $fromMatch) && - preg_match('(^\\+\\+\\+\\s+(?P\\S+))', $lines[$i + 1], $toMatch)) { - if ($diff !== null) { - $this->parseFileDiff($diff, $collected); - $diffs[] = $diff; - $collected = array(); - } - - $diff = new Diff($fromMatch['file'], $toMatch['file']); - ++$i; - } else { - if (preg_match('/^(?:diff --git |index [\da-f\.]+|[+-]{3} [ab])/', $lines[$i])) { - continue; - } - $collected[] = $lines[$i]; - } - } - - if (count($collected) && ($diff !== null)) { - $this->parseFileDiff($diff, $collected); - $diffs[] = $diff; - } - - return $diffs; - } - - /** - * @param Diff $diff - * @param array $lines - */ - private function parseFileDiff(Diff $diff, array $lines) - { - $chunks = array(); - - foreach ($lines as $line) { - if (preg_match('/^@@\s+-(?P\d+)(?:,\s*(?P\d+))?\s+\+(?P\d+)(?:,\s*(?P\d+))?\s+@@/', $line, $match)) { - $chunk = new Chunk( - $match['start'], - isset($match['startrange']) ? max(1, $match['startrange']) : 1, - $match['end'], - isset($match['endrange']) ? max(1, $match['endrange']) : 1 - ); - - $chunks[] = $chunk; - $diffLines = array(); - continue; - } - - if (preg_match('/^(?P[+ -])?(?P.*)/', $line, $match)) { - $type = Line::UNCHANGED; - - if ($match['type'] == '+') { - $type = Line::ADDED; - } elseif ($match['type'] == '-') { - $type = Line::REMOVED; - } - - $diffLines[] = new Line($type, $match['line']); - - if (isset($chunk)) { - $chunk->setLines($diffLines); - } - } - } - - $diff->setChunks($chunks); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Diff; - -/** - */ -class Diff -{ - /** - * @var string - */ - private $from; - - /** - * @var string - */ - private $to; - - /** - * @var Chunk[] - */ - private $chunks; - - /** - * @param string $from - * @param string $to - * @param Chunk[] $chunks - */ - public function __construct($from, $to, array $chunks = array()) - { - $this->from = $from; - $this->to = $to; - $this->chunks = $chunks; - } - - /** - * @return string - */ - public function getFrom() - { - return $this->from; - } - - /** - * @return string - */ - public function getTo() - { - return $this->to; - } - - /** - * @return Chunk[] - */ - public function getChunks() - { - return $this->chunks; - } - - /** - * @param Chunk[] $chunks - */ - public function setChunks(array $chunks) - { - $this->chunks = $chunks; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Diff; - -/** - */ -class Chunk -{ - /** - * @var int - */ - private $start; - - /** - * @var int - */ - private $startRange; - - /** - * @var int - */ - private $end; - /** - * @var int - */ - private $endRange; - - /** - * @var array - */ - private $lines; - - /** - * @param int $start - * @param int $startRange - * @param int $end - * @param int $endRange - * @param array $lines - */ - public function __construct($start = 0, $startRange = 1, $end = 0, $endRange = 1, array $lines = array()) - { - $this->start = (int) $start; - $this->startRange = (int) $startRange; - $this->end = (int) $end; - $this->endRange = (int) $endRange; - $this->lines = $lines; - } - - /** - * @return int - */ - public function getStart() - { - return $this->start; - } - - /** - * @return int - */ - public function getStartRange() - { - return $this->startRange; - } - - /** - * @return int - */ - public function getEnd() - { - return $this->end; - } - - /** - * @return int - */ - public function getEndRange() - { - return $this->endRange; - } - - /** - * @return array - */ - public function getLines() - { - return $this->lines; - } - - /** - * @param array $lines - */ - public function setLines(array $lines) - { - $this->lines = $lines; - } -} -The MIT License (MIT) - -Copyright (c) 2013 My C-Sense - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -skipUncloneable = $skipUncloneable; - return $this; - } - - /** - * Perform a deep copy of the object. - * @param mixed $object - * @return mixed - */ - public function copy($object) - { - $this->hashMap = []; - - return $this->recursiveCopy($object); - } - - public function addFilter(Filter $filter, Matcher $matcher) - { - $this->filters[] = [ - 'matcher' => $matcher, - 'filter' => $filter, - ]; - } - - public function addTypeFilter(TypeFilter $filter, TypeMatcher $matcher) - { - $this->typeFilters[] = [ - 'matcher' => $matcher, - 'filter' => $filter, - ]; - } - - - private function recursiveCopy($var) - { - // Matches Type Filter - if ($filter = $this->getFirstMatchedTypeFilter($this->typeFilters, $var)) { - return $filter->apply($var); - } - - // Resource - if (is_resource($var)) { - return $var; - } - // Array - if (is_array($var)) { - return $this->copyArray($var); - } - // Scalar - if (! is_object($var)) { - return $var; - } - // Object - return $this->copyObject($var); - } - - /** - * Copy an array - * @param array $array - * @return array - */ - private function copyArray(array $array) - { - $copier = function($item) { - return $this->recursiveCopy($item); - }; - - return array_map($copier, $array); - } - - /** - * Copy an object - * @param object $object - * @return object - */ - private function copyObject($object) - { - $objectHash = spl_object_hash($object); - - if (isset($this->hashMap[$objectHash])) { - return $this->hashMap[$objectHash]; - } - - $reflectedObject = new \ReflectionObject($object); - - if (false === $isCloneable = $reflectedObject->isCloneable() and $this->skipUncloneable) { - $this->hashMap[$objectHash] = $object; - return $object; - } - - if (false === $isCloneable) { - throw new CloneException(sprintf( - 'Class "%s" is not cloneable.', - $object->getName() - )); - } - - $newObject = clone $object; - $this->hashMap[$objectHash] = $newObject; - - foreach (ReflectionHelper::getProperties($reflectedObject) as $property) { - $this->copyObjectProperty($newObject, $property); - } - - return $newObject; - } - - private function copyObjectProperty($object, ReflectionProperty $property) - { - // Ignore static properties - if ($property->isStatic()) { - return; - } - - // Apply the filters - foreach ($this->filters as $item) { - /** @var Matcher $matcher */ - $matcher = $item['matcher']; - /** @var Filter $filter */ - $filter = $item['filter']; - - if ($matcher->matches($object, $property->getName())) { - $filter->apply( - $object, - $property->getName(), - function ($object) { - return $this->recursiveCopy($object); - } - ); - // If a filter matches, we stop processing this property - return; - } - } - - $property->setAccessible(true); - $propertyValue = $property->getValue($object); - - // Copy the property - $property->setValue($object, $this->recursiveCopy($propertyValue)); - } - - /** - * Returns first filter that matches variable, NULL if no such filter found. - * @param array $filterRecords Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and - * 'matcher' with value of type {@see TypeMatcher} - * @param mixed $var - * @return TypeFilter|null - */ - private function getFirstMatchedTypeFilter(array $filterRecords, $var) - { - $matched = $this->first( - $filterRecords, - function (array $record) use ($var) { - /* @var TypeMatcher $matcher */ - $matcher = $record['matcher']; - - return $matcher->matches($var); - } - ); - - return isset($matched) ? $matched['filter'] : null; - } - - /** - * Returns first element that matches predicate, NULL if no such element found. - * @param array $elements - * @param callable $predicate Predicate arguments are: element. - * @return mixed|null - */ - private function first(array $elements, callable $predicate) - { - foreach ($elements as $element) { - if (call_user_func($predicate, $element)) { - return $element; - } - } - - return null; - } -} -setAccessible(true); - - $reflectionProperty->setValue($object, new ArrayCollection()); - } -} setAccessible(true); - $oldCollection = $reflectionProperty->getValue($object); - - $newCollection = $oldCollection->map( - function ($item) use ($objectCopier) { - return $objectCopier($item); - } - ); - - $reflectionProperty->setValue($object, $newCollection); - } -} -callback = $callable; - } - - /** - * {@inheritdoc} - */ - public function apply($object, $property, $objectCopier) - { - $reflectionProperty = new \ReflectionProperty($object, $property); - $reflectionProperty->setAccessible(true); - - $value = call_user_func($this->callback, $reflectionProperty->getValue($object)); - - $reflectionProperty->setValue($object, $value); - } -} -setAccessible(true); - $reflectionProperty->setValue($object, null); - } -} -type = $type; - } - - /** - * @param $element - * @return boolean - */ - public function matches($element) - { - return is_object($element) ? is_a($element, $this->type) : gettype($element) === $this->type; - } -} -getProperties() does not return private properties from ancestor classes. - * - * @author muratyaman@gmail.com - * @see http://php.net/manual/en/reflectionclass.getproperties.php - * - * @param \ReflectionClass $ref - * @return \ReflectionProperty[] - */ - public static function getProperties(\ReflectionClass $ref) - { - $props = $ref->getProperties(); - $propsArr = array(); - - foreach ($props as $prop) { - $f = $prop->getName(); - $propsArr[$f] = $prop; - } - - if ($parentClass = $ref->getParentClass()) { - $parentPropsArr = self::getProperties($parentClass); - if (count($parentPropsArr) > 0) { - $propsArr = array_merge($parentPropsArr, $propsArr); - } - } - return $propsArr; - } -} -class = $class; - $this->property = $property; - } - - /** - * {@inheritdoc} - */ - public function matches($object, $property) - { - return ($object instanceof $this->class) && ($property == $this->property); - } -} -property = $property; - } - - /** - * {@inheritdoc} - */ - public function matches($object, $property) - { - return $property == $this->property; - } -} -propertyType = $propertyType; - } - - /** - * {@inheritdoc} - */ - public function matches($object, $property) - { - $reflectionProperty = new ReflectionProperty($object, $property); - $reflectionProperty->setAccessible(true); - - return $reflectionProperty->getValue($object) instanceof $this->propertyType; - } -} -callback = $callable; - } - - /** - * {@inheritdoc} - */ - public function apply($element) - { - return call_user_func($this->callback, $element); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Utility class for timing. - * - * @since Class available since Release 1.0.0 - */ -class PHP_Timer -{ - /** - * @var array - */ - private static $times = array( - 'hour' => 3600000, - 'minute' => 60000, - 'second' => 1000 - ); - - /** - * @var array - */ - private static $startTimes = array(); - - /** - * @var float - */ - public static $requestTime; - - /** - * Starts the timer. - */ - public static function start() - { - array_push(self::$startTimes, microtime(true)); - } - - /** - * Stops the timer and returns the elapsed time. - * - * @return float - */ - public static function stop() - { - return microtime(true) - array_pop(self::$startTimes); - } - - /** - * Formats the elapsed time as a string. - * - * @param float $time - * @return string - */ - public static function secondsToTimeString($time) - { - $ms = round($time * 1000); - - foreach (self::$times as $unit => $value) { - if ($ms >= $value) { - $time = floor($ms / $value * 100.0) / 100.0; - - return $time . ' ' . ($time == 1 ? $unit : $unit . 's'); - } - } - - return $ms . ' ms'; - } - - /** - * Formats the elapsed time since the start of the request as a string. - * - * @return string - */ - public static function timeSinceStartOfRequest() - { - return self::secondsToTimeString(microtime(true) - self::$requestTime); - } - - /** - * Returns the resources (time, memory) of the request as a string. - * - * @return string - */ - public static function resourceUsage() - { - return sprintf( - 'Time: %s, Memory: %4.2fMb', - self::timeSinceStartOfRequest(), - memory_get_peak_usage(true) / 1048576 - ); - } -} - -if (isset($_SERVER['REQUEST_TIME_FLOAT'])) { - PHP_Timer::$requestTime = $_SERVER['REQUEST_TIME_FLOAT']; -} elseif (isset($_SERVER['REQUEST_TIME'])) { - PHP_Timer::$requestTime = $_SERVER['REQUEST_TIME']; -} else { - PHP_Timer::$requestTime = microtime(true); -} -PHP_Timer - -Copyright (c) 2010-2015, Sebastian Bergmann . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Sebastian Bergmann nor the names of his - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -Comparator - -Copyright (c) 2002-2015, Sebastian Bergmann . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Sebastian Bergmann nor the names of his - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -use SebastianBergmann\Exporter\Exporter; - -/** - * Abstract base class for comparators which compare values for equality. - */ -abstract class Comparator -{ - /** - * @var Factory - */ - protected $factory; - - /** - * @var Exporter - */ - protected $exporter; - - public function __construct() - { - $this->exporter = new Exporter; - } - - /** - * @param Factory $factory - */ - public function setFactory(Factory $factory) - { - $this->factory = $factory; - } - - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - abstract public function accepts($expected, $actual); - - /** - * Asserts that two values are equal. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @param float $delta The allowed numerical distance between two values to - * consider them equal - * @param bool $canonicalize If set to TRUE, arrays are sorted before - * comparison - * @param bool $ignoreCase If set to TRUE, upper- and lowercasing is - * ignored when comparing string values - * @throws ComparisonFailure Thrown when the comparison - * fails. Contains information about the - * specific errors that lead to the failure. - */ - abstract public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false); -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Compares \SplObjectStorage instances for equality. - */ -class SplObjectStorageComparator extends Comparator -{ - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - public function accepts($expected, $actual) - { - return $expected instanceof \SplObjectStorage && $actual instanceof \SplObjectStorage; - } - - /** - * Asserts that two values are equal. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @param float $delta The allowed numerical distance between two values to - * consider them equal - * @param bool $canonicalize If set to TRUE, arrays are sorted before - * comparison - * @param bool $ignoreCase If set to TRUE, upper- and lowercasing is - * ignored when comparing string values - * @throws ComparisonFailure Thrown when the comparison - * fails. Contains information about the - * specific errors that lead to the failure. - */ - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) - { - foreach ($actual as $object) { - if (!$expected->contains($object)) { - throw new ComparisonFailure( - $expected, - $actual, - $this->exporter->export($expected), - $this->exporter->export($actual), - false, - 'Failed asserting that two objects are equal.' - ); - } - } - - foreach ($expected as $object) { - if (!$actual->contains($object)) { - throw new ComparisonFailure( - $expected, - $actual, - $this->exporter->export($expected), - $this->exporter->export($actual), - false, - 'Failed asserting that two objects are equal.' - ); - } - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Compares values for type equality. - */ -class TypeComparator extends Comparator -{ - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - public function accepts($expected, $actual) - { - return true; - } - - /** - * Asserts that two values are equal. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @param float $delta The allowed numerical distance between two values to - * consider them equal - * @param bool $canonicalize If set to TRUE, arrays are sorted before - * comparison - * @param bool $ignoreCase If set to TRUE, upper- and lowercasing is - * ignored when comparing string values - * @throws ComparisonFailure Thrown when the comparison - * fails. Contains information about the - * specific errors that lead to the failure. - */ - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) - { - if (gettype($expected) != gettype($actual)) { - throw new ComparisonFailure( - $expected, - $actual, - // we don't need a diff - '', - '', - false, - sprintf( - '%s does not match expected type "%s".', - $this->exporter->shortenedExport($actual), - gettype($expected) - ) - ); - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Compares objects for equality. - */ -class ObjectComparator extends ArrayComparator -{ - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - public function accepts($expected, $actual) - { - return is_object($expected) && is_object($actual); - } - - /** - * Asserts that two values are equal. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @param float $delta The allowed numerical distance between two values to - * consider them equal - * @param bool $canonicalize If set to TRUE, arrays are sorted before - * comparison - * @param bool $ignoreCase If set to TRUE, upper- and lowercasing is - * ignored when comparing string values - * @param array $processed - * @throws ComparisonFailure Thrown when the comparison - * fails. Contains information about the - * specific errors that lead to the failure. - */ - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = array()) - { - if (get_class($actual) !== get_class($expected)) { - throw new ComparisonFailure( - $expected, - $actual, - $this->exporter->export($expected), - $this->exporter->export($actual), - false, - sprintf( - '%s is not instance of expected class "%s".', - $this->exporter->export($actual), - get_class($expected) - ) - ); - } - - // don't compare twice to allow for cyclic dependencies - if (in_array(array($actual, $expected), $processed, true) || - in_array(array($expected, $actual), $processed, true)) { - return; - } - - $processed[] = array($actual, $expected); - - // don't compare objects if they are identical - // this helps to avoid the error "maximum function nesting level reached" - // CAUTION: this conditional clause is not tested - if ($actual !== $expected) { - try { - parent::assertEquals( - $this->toArray($expected), - $this->toArray($actual), - $delta, - $canonicalize, - $ignoreCase, - $processed - ); - } catch (ComparisonFailure $e) { - throw new ComparisonFailure( - $expected, - $actual, - // replace "Array" with "MyClass object" - substr_replace($e->getExpectedAsString(), get_class($expected) . ' Object', 0, 5), - substr_replace($e->getActualAsString(), get_class($actual) . ' Object', 0, 5), - false, - 'Failed asserting that two objects are equal.' - ); - } - } - } - - /** - * Converts an object to an array containing all of its private, protected - * and public properties. - * - * @param object $object - * @return array - */ - protected function toArray($object) - { - return $this->exporter->toArray($object); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Compares resources for equality. - */ -class ResourceComparator extends Comparator -{ - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - public function accepts($expected, $actual) - { - return is_resource($expected) && is_resource($actual); - } - - /** - * Asserts that two values are equal. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @param float $delta The allowed numerical distance between two values to - * consider them equal - * @param bool $canonicalize If set to TRUE, arrays are sorted before - * comparison - * @param bool $ignoreCase If set to TRUE, upper- and lowercasing is - * ignored when comparing string values - * @throws ComparisonFailure Thrown when the comparison - * fails. Contains information about the - * specific errors that lead to the failure. - */ - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) - { - if ($actual != $expected) { - throw new ComparisonFailure( - $expected, - $actual, - $this->exporter->export($expected), - $this->exporter->export($actual) - ); - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Compares arrays for equality. - */ -class ArrayComparator extends Comparator -{ - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - public function accepts($expected, $actual) - { - return is_array($expected) && is_array($actual); - } - - /** - * Asserts that two values are equal. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @param float $delta The allowed numerical distance between two values to - * consider them equal - * @param bool $canonicalize If set to TRUE, arrays are sorted before - * comparison - * @param bool $ignoreCase If set to TRUE, upper- and lowercasing is - * ignored when comparing string values - * @param array $processed - * @throws ComparisonFailure Thrown when the comparison - * fails. Contains information about the - * specific errors that lead to the failure. - */ - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = array()) - { - if ($canonicalize) { - sort($expected); - sort($actual); - } - - $remaining = $actual; - $expString = $actString = "Array (\n"; - $equal = true; - - foreach ($expected as $key => $value) { - unset($remaining[$key]); - - if (!array_key_exists($key, $actual)) { - $expString .= sprintf( - " %s => %s\n", - $this->exporter->export($key), - $this->exporter->shortenedExport($value) - ); - - $equal = false; - - continue; - } - - try { - $comparator = $this->factory->getComparatorFor($value, $actual[$key]); - $comparator->assertEquals($value, $actual[$key], $delta, $canonicalize, $ignoreCase, $processed); - - $expString .= sprintf( - " %s => %s\n", - $this->exporter->export($key), - $this->exporter->shortenedExport($value) - ); - $actString .= sprintf( - " %s => %s\n", - $this->exporter->export($key), - $this->exporter->shortenedExport($actual[$key]) - ); - } catch (ComparisonFailure $e) { - $expString .= sprintf( - " %s => %s\n", - $this->exporter->export($key), - $e->getExpectedAsString() - ? $this->indent($e->getExpectedAsString()) - : $this->exporter->shortenedExport($e->getExpected()) - ); - - $actString .= sprintf( - " %s => %s\n", - $this->exporter->export($key), - $e->getActualAsString() - ? $this->indent($e->getActualAsString()) - : $this->exporter->shortenedExport($e->getActual()) - ); - - $equal = false; - } - } - - foreach ($remaining as $key => $value) { - $actString .= sprintf( - " %s => %s\n", - $this->exporter->export($key), - $this->exporter->shortenedExport($value) - ); - - $equal = false; - } - - $expString .= ')'; - $actString .= ')'; - - if (!$equal) { - throw new ComparisonFailure( - $expected, - $actual, - $expString, - $actString, - false, - 'Failed asserting that two arrays are equal.' - ); - } - } - - protected function indent($lines) - { - return trim(str_replace("\n", "\n ", $lines)); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Compares DateTimeInterface instances for equality. - */ -class DateTimeComparator extends ObjectComparator -{ - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - public function accepts($expected, $actual) - { - return ($expected instanceof \DateTime || $expected instanceof \DateTimeInterface) && - ($actual instanceof \DateTime || $actual instanceof \DateTimeInterface); - } - - /** - * Asserts that two values are equal. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @param float $delta The allowed numerical distance between two values to - * consider them equal - * @param bool $canonicalize If set to TRUE, arrays are sorted before - * comparison - * @param bool $ignoreCase If set to TRUE, upper- and lowercasing is - * ignored when comparing string values - * @throws ComparisonFailure Thrown when the comparison - * fails. Contains information about the - * specific errors that lead to the failure. - */ - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) - { - $delta = new \DateInterval(sprintf('PT%sS', abs($delta))); - - $expectedLower = clone $expected; - $expectedUpper = clone $expected; - - if ($actual < $expectedLower->sub($delta) || - $actual > $expectedUpper->add($delta)) { - throw new ComparisonFailure( - $expected, - $actual, - $this->dateTimeToString($expected), - $this->dateTimeToString($actual), - false, - 'Failed asserting that two DateTime objects are equal.' - ); - } - } - - /** - * Returns an ISO 8601 formatted string representation of a datetime or - * 'Invalid DateTimeInterface object' if the provided DateTimeInterface was not properly - * initialized. - * - * @param \DateTimeInterface $datetime - * @return string - */ - protected function dateTimeToString($datetime) - { - $string = $datetime->format(\DateTime::ISO8601); - - return $string ? $string : 'Invalid DateTimeInterface object'; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Compares Exception instances for equality. - */ -class ExceptionComparator extends ObjectComparator -{ - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - public function accepts($expected, $actual) - { - return $expected instanceof \Exception && $actual instanceof \Exception; - } - - /** - * Converts an object to an array containing all of its private, protected - * and public properties. - * - * @param object $object - * @return array - */ - protected function toArray($object) - { - $array = parent::toArray($object); - - unset( - $array['file'], - $array['line'], - $array['trace'], - $array['string'], - $array['xdebug_message'] - ); - - return $array; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -use DOMDocument; -use DOMNode; - -/** - * Compares DOMNode instances for equality. - */ -class DOMNodeComparator extends ObjectComparator -{ - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - public function accepts($expected, $actual) - { - return $expected instanceof DOMNode && $actual instanceof DOMNode; - } - - /** - * Asserts that two values are equal. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @param float $delta The allowed numerical distance between two values to - * consider them equal - * @param bool $canonicalize If set to TRUE, arrays are sorted before - * comparison - * @param bool $ignoreCase If set to TRUE, upper- and lowercasing is - * ignored when comparing string values - * @throws ComparisonFailure Thrown when the comparison - * fails. Contains information about the - * specific errors that lead to the failure. - */ - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) - { - $expectedAsString = $this->nodeToText($expected, true, $ignoreCase); - $actualAsString = $this->nodeToText($actual, true, $ignoreCase); - - if ($expectedAsString !== $actualAsString) { - if ($expected instanceof DOMDocument) { - $type = 'documents'; - } else { - $type = 'nodes'; - } - - throw new ComparisonFailure( - $expected, - $actual, - $expectedAsString, - $actualAsString, - false, - sprintf("Failed asserting that two DOM %s are equal.\n", $type) - ); - } - } - - /** - * Returns the normalized, whitespace-cleaned, and indented textual - * representation of a DOMNode. - * - * @param DOMNode $node - * @param bool $canonicalize - * @param bool $ignoreCase - * @return string - */ - private function nodeToText(DOMNode $node, $canonicalize, $ignoreCase) - { - if ($canonicalize) { - $document = new DOMDocument; - $document->loadXML($node->C14N()); - - $node = $document; - } - - if ($node instanceof DOMDocument) { - $document = $node; - } else { - $document = $node->ownerDocument; - } - - $document->formatOutput = true; - $document->normalizeDocument(); - - if ($node instanceof DOMDocument) { - $text = $node->saveXML(); - } else { - $text = $document->saveXML($node); - } - - if ($ignoreCase) { - $text = strtolower($text); - } - - return $text; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Compares scalar or NULL values for equality. - */ -class ScalarComparator extends Comparator -{ - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - * @since Method available since Release 3.6.0 - */ - public function accepts($expected, $actual) - { - return ((is_scalar($expected) xor null === $expected) && - (is_scalar($actual) xor null === $actual)) - // allow comparison between strings and objects featuring __toString() - || (is_string($expected) && is_object($actual) && method_exists($actual, '__toString')) - || (is_object($expected) && method_exists($expected, '__toString') && is_string($actual)); - } - - /** - * Asserts that two values are equal. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @param float $delta The allowed numerical distance between two values to - * consider them equal - * @param bool $canonicalize If set to TRUE, arrays are sorted before - * comparison - * @param bool $ignoreCase If set to TRUE, upper- and lowercasing is - * ignored when comparing string values - * @throws ComparisonFailure Thrown when the comparison - * fails. Contains information about the - * specific errors that lead to the failure. - */ - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) - { - $expectedToCompare = $expected; - $actualToCompare = $actual; - - // always compare as strings to avoid strange behaviour - // otherwise 0 == 'Foobar' - if (is_string($expected) || is_string($actual)) { - $expectedToCompare = (string) $expectedToCompare; - $actualToCompare = (string) $actualToCompare; - - if ($ignoreCase) { - $expectedToCompare = strtolower($expectedToCompare); - $actualToCompare = strtolower($actualToCompare); - } - } - - if ($expectedToCompare != $actualToCompare) { - if (is_string($expected) && is_string($actual)) { - throw new ComparisonFailure( - $expected, - $actual, - $this->exporter->export($expected), - $this->exporter->export($actual), - false, - 'Failed asserting that two strings are equal.' - ); - } - - throw new ComparisonFailure( - $expected, - $actual, - // no diff is required - '', - '', - false, - sprintf( - 'Failed asserting that %s matches expected %s.', - $this->exporter->export($actual), - $this->exporter->export($expected) - ) - ); - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Compares PHPUnit_Framework_MockObject_MockObject instances for equality. - */ -class MockObjectComparator extends ObjectComparator -{ - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - public function accepts($expected, $actual) - { - return $expected instanceof \PHPUnit_Framework_MockObject_MockObject && $actual instanceof \PHPUnit_Framework_MockObject_MockObject; - } - - /** - * Converts an object to an array containing all of its private, protected - * and public properties. - * - * @param object $object - * @return array - */ - protected function toArray($object) - { - $array = parent::toArray($object); - - unset($array['__phpunit_invocationMocker']); - - return $array; - } -} - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Compares numerical values for equality. - */ -class NumericComparator extends ScalarComparator -{ - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - public function accepts($expected, $actual) - { - // all numerical values, but not if one of them is a double - // or both of them are strings - return is_numeric($expected) && is_numeric($actual) && - !(is_double($expected) || is_double($actual)) && - !(is_string($expected) && is_string($actual)); - } - - /** - * Asserts that two values are equal. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @param float $delta The allowed numerical distance between two values to - * consider them equal - * @param bool $canonicalize If set to TRUE, arrays are sorted before - * comparison - * @param bool $ignoreCase If set to TRUE, upper- and lowercasing is - * ignored when comparing string values - * @throws ComparisonFailure Thrown when the comparison - * fails. Contains information about the - * specific errors that lead to the failure. - */ - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) - { - if (is_infinite($actual) && is_infinite($expected)) { - return; - } - - if ((is_infinite($actual) xor is_infinite($expected)) || - (is_nan($actual) or is_nan($expected)) || - abs($actual - $expected) > $delta) { - throw new ComparisonFailure( - $expected, - $actual, - '', - '', - false, - sprintf( - 'Failed asserting that %s matches expected %s.', - $this->exporter->export($actual), - $this->exporter->export($expected) - ) - ); - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Factory for comparators which compare values for equality. - */ -class Factory -{ - /** - * @var Comparator[] - */ - private $comparators = array(); - - /** - * @var Factory - */ - private static $instance; - - /** - * Constructs a new factory. - */ - public function __construct() - { - $this->register(new TypeComparator); - $this->register(new ScalarComparator); - $this->register(new NumericComparator); - $this->register(new DoubleComparator); - $this->register(new ArrayComparator); - $this->register(new ResourceComparator); - $this->register(new ObjectComparator); - $this->register(new ExceptionComparator); - $this->register(new SplObjectStorageComparator); - $this->register(new DOMNodeComparator); - $this->register(new MockObjectComparator); - $this->register(new DateTimeComparator); - } - - /** - * @return Factory - */ - public static function getInstance() - { - if (self::$instance === null) { - self::$instance = new self; - } - - return self::$instance; - } - - /** - * Returns the correct comparator for comparing two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return Comparator - */ - public function getComparatorFor($expected, $actual) - { - foreach ($this->comparators as $comparator) { - if ($comparator->accepts($expected, $actual)) { - return $comparator; - } - } - } - - /** - * Registers a new comparator. - * - * This comparator will be returned by getInstance() if its accept() method - * returns TRUE for the compared values. It has higher priority than the - * existing comparators, meaning that its accept() method will be tested - * before those of the other comparators. - * - * @param Comparator $comparator The registered comparator - */ - public function register(Comparator $comparator) - { - array_unshift($this->comparators, $comparator); - - $comparator->setFactory($this); - } - - /** - * Unregisters a comparator. - * - * This comparator will no longer be returned by getInstance(). - * - * @param Comparator $comparator The unregistered comparator - */ - public function unregister(Comparator $comparator) - { - foreach ($this->comparators as $key => $_comparator) { - if ($comparator === $_comparator) { - unset($this->comparators[$key]); - } - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -/** - * Compares doubles for equality. - */ -class DoubleComparator extends NumericComparator -{ - /** - * Smallest value available in PHP. - * - * @var float - */ - const EPSILON = 0.0000000001; - - /** - * Returns whether the comparator can compare two values. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @return bool - */ - public function accepts($expected, $actual) - { - return (is_double($expected) || is_double($actual)) && is_numeric($expected) && is_numeric($actual); - } - - /** - * Asserts that two values are equal. - * - * @param mixed $expected The first value to compare - * @param mixed $actual The second value to compare - * @param float $delta The allowed numerical distance between two values to - * consider them equal - * @param bool $canonicalize If set to TRUE, arrays are sorted before - * comparison - * @param bool $ignoreCase If set to TRUE, upper- and lowercasing is - * ignored when comparing string values - * @throws ComparisonFailure Thrown when the comparison - * fails. Contains information about the - * specific errors that lead to the failure. - */ - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) - { - if ($delta == 0) { - $delta = self::EPSILON; - } - - parent::assertEquals($expected, $actual, $delta, $canonicalize, $ignoreCase); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Comparator; - -use SebastianBergmann\Diff\Differ; - -/** - * Thrown when an assertion for string equality failed. - */ -class ComparisonFailure extends \RuntimeException -{ - /** - * Expected value of the retrieval which does not match $actual. - * @var mixed - */ - protected $expected; - - /** - * Actually retrieved value which does not match $expected. - * @var mixed - */ - protected $actual; - - /** - * The string representation of the expected value - * @var string - */ - protected $expectedAsString; - - /** - * The string representation of the actual value - * @var string - */ - protected $actualAsString; - - /** - * @var bool - */ - protected $identical; - - /** - * Optional message which is placed in front of the first line - * returned by toString(). - * @var string - */ - protected $message; - - /** - * Initialises with the expected value and the actual value. - * - * @param mixed $expected Expected value retrieved. - * @param mixed $actual Actual value retrieved. - * @param string $expectedAsString - * @param string $actualAsString - * @param bool $identical - * @param string $message A string which is prefixed on all returned lines - * in the difference output. - */ - public function __construct($expected, $actual, $expectedAsString, $actualAsString, $identical = false, $message = '') - { - $this->expected = $expected; - $this->actual = $actual; - $this->expectedAsString = $expectedAsString; - $this->actualAsString = $actualAsString; - $this->message = $message; - } - - /** - * @return mixed - */ - public function getActual() - { - return $this->actual; - } - - /** - * @return mixed - */ - public function getExpected() - { - return $this->expected; - } - - /** - * @return string - */ - public function getActualAsString() - { - return $this->actualAsString; - } - - /** - * @return string - */ - public function getExpectedAsString() - { - return $this->expectedAsString; - } - - /** - * @return string - */ - public function getDiff() - { - if (!$this->actualAsString && !$this->expectedAsString) { - return ''; - } - - $differ = new Differ("\n--- Expected\n+++ Actual\n"); - - return $differ->diff($this->expectedAsString, $this->actualAsString); - } - - /** - * @return string - */ - public function toString() - { - return $this->message . $this->getDiff(); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\CodeUnitReverseLookup; - -/** - * @since Class available since Release 1.0.0 - */ -class Wizard -{ - /** - * @var array - */ - private $lookupTable = []; - - /** - * @var array - */ - private $processedClasses = []; - - /** - * @var array - */ - private $processedFunctions = []; - - /** - * @param string $filename - * @param int $lineNumber - * - * @return string - */ - public function lookup($filename, $lineNumber) - { - if (!isset($this->lookupTable[$filename][$lineNumber])) { - $this->updateLookupTable(); - } - - if (isset($this->lookupTable[$filename][$lineNumber])) { - return $this->lookupTable[$filename][$lineNumber]; - } else { - return $filename . ':' . $lineNumber; - } - } - - private function updateLookupTable() - { - $this->processClassesAndTraits(); - $this->processFunctions(); - } - - private function processClassesAndTraits() - { - foreach (array_merge(get_declared_classes(), get_declared_traits()) as $classOrTrait) { - if (isset($this->processedClasses[$classOrTrait])) { - continue; - } - - $reflector = new \ReflectionClass($classOrTrait); - - foreach ($reflector->getMethods() as $method) { - $this->processFunctionOrMethod($method); - } - - $this->processedClasses[$classOrTrait] = true; - } - } - - private function processFunctions() - { - foreach (get_defined_functions()['user'] as $function) { - if (isset($this->processedFunctions[$function])) { - continue; - } - - $this->processFunctionOrMethod(new \ReflectionFunction($function)); - - $this->processedFunctions[$function] = true; - } - } - - /** - * @param \ReflectionFunctionAbstract $functionOrMethod - */ - private function processFunctionOrMethod(\ReflectionFunctionAbstract $functionOrMethod) - { - if ($functionOrMethod->isInternal()) { - return; - } - - $name = $functionOrMethod->getName(); - - if ($functionOrMethod instanceof \ReflectionMethod) { - $name = $functionOrMethod->getDeclaringClass()->getName() . '::' . $name; - } - - if (!isset($this->lookupTable[$functionOrMethod->getFileName()])) { - $this->lookupTable[$functionOrMethod->getFileName()] = []; - } - - foreach (range($functionOrMethod->getStartLine(), $functionOrMethod->getEndLine()) as $line) { - $this->lookupTable[$functionOrMethod->getFileName()][$line] = $name; - } - } -} -code-unit-reverse-lookup - -Copyright (c) 2016, Sebastian Bergmann . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Sebastian Bergmann nor the names of his - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -Copyright (c) 2013 Konstantin Kudryashov - Marcello Duarte - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Prophecy; - -/** - * Prophecies revealer interface. - * - * @author Konstantin Kudryashov - */ -interface RevealerInterface -{ - /** - * Unwraps value(s). - * - * @param mixed $value - * - * @return mixed - */ - public function reveal($value); -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Prophecy; - -/** - * Controllable doubles interface. - * - * @author Konstantin Kudryashov - */ -interface ProphecySubjectInterface -{ - /** - * Sets subject prophecy. - * - * @param ProphecyInterface $prophecy - */ - public function setProphecy(ProphecyInterface $prophecy); - - /** - * Returns subject prophecy. - * - * @return ProphecyInterface - */ - public function getProphecy(); -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Prophecy; - -/** - * Basic prophecies revealer. - * - * @author Konstantin Kudryashov - */ -class Revealer implements RevealerInterface -{ - /** - * Unwraps value(s). - * - * @param mixed $value - * - * @return mixed - */ - public function reveal($value) - { - if (is_array($value)) { - return array_map(array($this, __FUNCTION__), $value); - } - - if (!is_object($value)) { - return $value; - } - - if ($value instanceof ProphecyInterface) { - $value = $value->reveal(); - } - - return $value; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Prophecy; - -/** - * Core Prophecy interface. - * - * @author Konstantin Kudryashov - */ -interface ProphecyInterface -{ - /** - * Reveals prophecy object (double) . - * - * @return object - */ - public function reveal(); -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Prophecy; - -use SebastianBergmann\Comparator\ComparisonFailure; -use Prophecy\Comparator\Factory as ComparatorFactory; -use Prophecy\Call\Call; -use Prophecy\Doubler\LazyDouble; -use Prophecy\Argument\ArgumentsWildcard; -use Prophecy\Call\CallCenter; -use Prophecy\Exception\Prophecy\ObjectProphecyException; -use Prophecy\Exception\Prophecy\MethodProphecyException; -use Prophecy\Exception\Prediction\AggregateException; -use Prophecy\Exception\Prediction\PredictionException; - -/** - * Object prophecy. - * - * @author Konstantin Kudryashov - */ -class ObjectProphecy implements ProphecyInterface -{ - private $lazyDouble; - private $callCenter; - private $revealer; - private $comparatorFactory; - - /** - * @var MethodProphecy[][] - */ - private $methodProphecies = array(); - - /** - * Initializes object prophecy. - * - * @param LazyDouble $lazyDouble - * @param CallCenter $callCenter - * @param RevealerInterface $revealer - * @param ComparatorFactory $comparatorFactory - */ - public function __construct( - LazyDouble $lazyDouble, - CallCenter $callCenter = null, - RevealerInterface $revealer = null, - ComparatorFactory $comparatorFactory = null - ) { - $this->lazyDouble = $lazyDouble; - $this->callCenter = $callCenter ?: new CallCenter; - $this->revealer = $revealer ?: new Revealer; - - $this->comparatorFactory = $comparatorFactory ?: ComparatorFactory::getInstance(); - } - - /** - * Forces double to extend specific class. - * - * @param string $class - * - * @return $this - */ - public function willExtend($class) - { - $this->lazyDouble->setParentClass($class); - - return $this; - } - - /** - * Forces double to implement specific interface. - * - * @param string $interface - * - * @return $this - */ - public function willImplement($interface) - { - $this->lazyDouble->addInterface($interface); - - return $this; - } - - /** - * Sets constructor arguments. - * - * @param array $arguments - * - * @return $this - */ - public function willBeConstructedWith(array $arguments = null) - { - $this->lazyDouble->setArguments($arguments); - - return $this; - } - - /** - * Reveals double. - * - * @return object - * - * @throws \Prophecy\Exception\Prophecy\ObjectProphecyException If double doesn't implement needed interface - */ - public function reveal() - { - $double = $this->lazyDouble->getInstance(); - - if (null === $double || !$double instanceof ProphecySubjectInterface) { - throw new ObjectProphecyException( - "Generated double must implement ProphecySubjectInterface, but it does not.\n". - 'It seems you have wrongly configured doubler without required ClassPatch.', - $this - ); - } - - $double->setProphecy($this); - - return $double; - } - - /** - * Adds method prophecy to object prophecy. - * - * @param MethodProphecy $methodProphecy - * - * @throws \Prophecy\Exception\Prophecy\MethodProphecyException If method prophecy doesn't - * have arguments wildcard - */ - public function addMethodProphecy(MethodProphecy $methodProphecy) - { - $argumentsWildcard = $methodProphecy->getArgumentsWildcard(); - if (null === $argumentsWildcard) { - throw new MethodProphecyException(sprintf( - "Can not add prophecy for a method `%s::%s()`\n". - "as you did not specify arguments wildcard for it.", - get_class($this->reveal()), - $methodProphecy->getMethodName() - ), $methodProphecy); - } - - $methodName = $methodProphecy->getMethodName(); - - if (!isset($this->methodProphecies[$methodName])) { - $this->methodProphecies[$methodName] = array(); - } - - $this->methodProphecies[$methodName][] = $methodProphecy; - } - - /** - * Returns either all or related to single method prophecies. - * - * @param null|string $methodName - * - * @return MethodProphecy[] - */ - public function getMethodProphecies($methodName = null) - { - if (null === $methodName) { - return $this->methodProphecies; - } - - if (!isset($this->methodProphecies[$methodName])) { - return array(); - } - - return $this->methodProphecies[$methodName]; - } - - /** - * Makes specific method call. - * - * @param string $methodName - * @param array $arguments - * - * @return mixed - */ - public function makeProphecyMethodCall($methodName, array $arguments) - { - $arguments = $this->revealer->reveal($arguments); - $return = $this->callCenter->makeCall($this, $methodName, $arguments); - - return $this->revealer->reveal($return); - } - - /** - * Finds calls by method name & arguments wildcard. - * - * @param string $methodName - * @param ArgumentsWildcard $wildcard - * - * @return Call[] - */ - public function findProphecyMethodCalls($methodName, ArgumentsWildcard $wildcard) - { - return $this->callCenter->findCalls($methodName, $wildcard); - } - - /** - * Checks that registered method predictions do not fail. - * - * @throws \Prophecy\Exception\Prediction\AggregateException If any of registered predictions fail - */ - public function checkProphecyMethodsPredictions() - { - $exception = new AggregateException(sprintf("%s:\n", get_class($this->reveal()))); - $exception->setObjectProphecy($this); - - foreach ($this->methodProphecies as $prophecies) { - foreach ($prophecies as $prophecy) { - try { - $prophecy->checkPrediction(); - } catch (PredictionException $e) { - $exception->append($e); - } - } - } - - if (count($exception->getExceptions())) { - throw $exception; - } - } - - /** - * Creates new method prophecy using specified method name and arguments. - * - * @param string $methodName - * @param array $arguments - * - * @return MethodProphecy - */ - public function __call($methodName, array $arguments) - { - $arguments = new ArgumentsWildcard($this->revealer->reveal($arguments)); - - foreach ($this->getMethodProphecies($methodName) as $prophecy) { - $argumentsWildcard = $prophecy->getArgumentsWildcard(); - $comparator = $this->comparatorFactory->getComparatorFor( - $argumentsWildcard, $arguments - ); - - try { - $comparator->assertEquals($argumentsWildcard, $arguments); - return $prophecy; - } catch (ComparisonFailure $failure) {} - } - - return new MethodProphecy($this, $methodName, $arguments); - } - - /** - * Tries to get property value from double. - * - * @param string $name - * - * @return mixed - */ - public function __get($name) - { - return $this->reveal()->$name; - } - - /** - * Tries to set property value to double. - * - * @param string $name - * @param mixed $value - */ - public function __set($name, $value) - { - $this->reveal()->$name = $this->revealer->reveal($value); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Prophecy; - -use Prophecy\Argument; -use Prophecy\Prophet; -use Prophecy\Promise; -use Prophecy\Prediction; -use Prophecy\Exception\Doubler\MethodNotFoundException; -use Prophecy\Exception\InvalidArgumentException; -use Prophecy\Exception\Prophecy\MethodProphecyException; - -/** - * Method prophecy. - * - * @author Konstantin Kudryashov - */ -class MethodProphecy -{ - private $objectProphecy; - private $methodName; - private $argumentsWildcard; - private $promise; - private $prediction; - private $checkedPredictions = array(); - private $bound = false; - - /** - * Initializes method prophecy. - * - * @param ObjectProphecy $objectProphecy - * @param string $methodName - * @param null|Argument\ArgumentsWildcard|array $arguments - * - * @throws \Prophecy\Exception\Doubler\MethodNotFoundException If method not found - */ - public function __construct(ObjectProphecy $objectProphecy, $methodName, $arguments = null) - { - $double = $objectProphecy->reveal(); - if (!method_exists($double, $methodName)) { - throw new MethodNotFoundException(sprintf( - 'Method `%s::%s()` is not defined.', get_class($double), $methodName - ), get_class($double), $methodName, $arguments); - } - - $this->objectProphecy = $objectProphecy; - $this->methodName = $methodName; - - $reflectedMethod = new \ReflectionMethod($double, $methodName); - if ($reflectedMethod->isFinal()) { - throw new MethodProphecyException(sprintf( - "Can not add prophecy for a method `%s::%s()`\n". - "as it is a final method.", - get_class($double), - $methodName - ), $this); - } - - if (null !== $arguments) { - $this->withArguments($arguments); - } - - if (version_compare(PHP_VERSION, '7.0', '>=') && true === $reflectedMethod->hasReturnType()) { - $type = (string) $reflectedMethod->getReturnType(); - $this->will(function () use ($type) { - switch ($type) { - case 'string': return ''; - case 'float': return 0.0; - case 'int': return 0; - case 'bool': return false; - case 'array': return array(); - - case 'callable': - case 'Closure': - return function () {}; - - case 'Traversable': - case 'Generator': - // Remove eval() when minimum version >=5.5 - $generator = eval('return function () { yield; };'); - return $generator(); - - default: - $prophet = new Prophet; - return $prophet->prophesize($type)->reveal(); - } - }); - } - } - - /** - * Sets argument wildcard. - * - * @param array|Argument\ArgumentsWildcard $arguments - * - * @return $this - * - * @throws \Prophecy\Exception\InvalidArgumentException - */ - public function withArguments($arguments) - { - if (is_array($arguments)) { - $arguments = new Argument\ArgumentsWildcard($arguments); - } - - if (!$arguments instanceof Argument\ArgumentsWildcard) { - throw new InvalidArgumentException(sprintf( - "Either an array or an instance of ArgumentsWildcard expected as\n". - 'a `MethodProphecy::withArguments()` argument, but got %s.', - gettype($arguments) - )); - } - - $this->argumentsWildcard = $arguments; - - return $this; - } - - /** - * Sets custom promise to the prophecy. - * - * @param callable|Promise\PromiseInterface $promise - * - * @return $this - * - * @throws \Prophecy\Exception\InvalidArgumentException - */ - public function will($promise) - { - if (is_callable($promise)) { - $promise = new Promise\CallbackPromise($promise); - } - - if (!$promise instanceof Promise\PromiseInterface) { - throw new InvalidArgumentException(sprintf( - 'Expected callable or instance of PromiseInterface, but got %s.', - gettype($promise) - )); - } - - $this->bindToObjectProphecy(); - $this->promise = $promise; - - return $this; - } - - /** - * Sets return promise to the prophecy. - * - * @see Prophecy\Promise\ReturnPromise - * - * @return $this - */ - public function willReturn() - { - return $this->will(new Promise\ReturnPromise(func_get_args())); - } - - /** - * Sets return argument promise to the prophecy. - * - * @param int $index The zero-indexed number of the argument to return - * - * @see Prophecy\Promise\ReturnArgumentPromise - * - * @return $this - */ - public function willReturnArgument($index = 0) - { - return $this->will(new Promise\ReturnArgumentPromise($index)); - } - - /** - * Sets throw promise to the prophecy. - * - * @see Prophecy\Promise\ThrowPromise - * - * @param string|\Exception $exception Exception class or instance - * - * @return $this - */ - public function willThrow($exception) - { - return $this->will(new Promise\ThrowPromise($exception)); - } - - /** - * Sets custom prediction to the prophecy. - * - * @param callable|Prediction\PredictionInterface $prediction - * - * @return $this - * - * @throws \Prophecy\Exception\InvalidArgumentException - */ - public function should($prediction) - { - if (is_callable($prediction)) { - $prediction = new Prediction\CallbackPrediction($prediction); - } - - if (!$prediction instanceof Prediction\PredictionInterface) { - throw new InvalidArgumentException(sprintf( - 'Expected callable or instance of PredictionInterface, but got %s.', - gettype($prediction) - )); - } - - $this->bindToObjectProphecy(); - $this->prediction = $prediction; - - return $this; - } - - /** - * Sets call prediction to the prophecy. - * - * @see Prophecy\Prediction\CallPrediction - * - * @return $this - */ - public function shouldBeCalled() - { - return $this->should(new Prediction\CallPrediction); - } - - /** - * Sets no calls prediction to the prophecy. - * - * @see Prophecy\Prediction\NoCallsPrediction - * - * @return $this - */ - public function shouldNotBeCalled() - { - return $this->should(new Prediction\NoCallsPrediction); - } - - /** - * Sets call times prediction to the prophecy. - * - * @see Prophecy\Prediction\CallTimesPrediction - * - * @param $count - * - * @return $this - */ - public function shouldBeCalledTimes($count) - { - return $this->should(new Prediction\CallTimesPrediction($count)); - } - - /** - * Checks provided prediction immediately. - * - * @param callable|Prediction\PredictionInterface $prediction - * - * @return $this - * - * @throws \Prophecy\Exception\InvalidArgumentException - */ - public function shouldHave($prediction) - { - if (is_callable($prediction)) { - $prediction = new Prediction\CallbackPrediction($prediction); - } - - if (!$prediction instanceof Prediction\PredictionInterface) { - throw new InvalidArgumentException(sprintf( - 'Expected callable or instance of PredictionInterface, but got %s.', - gettype($prediction) - )); - } - - if (null === $this->promise) { - $this->willReturn(); - } - - $calls = $this->getObjectProphecy()->findProphecyMethodCalls( - $this->getMethodName(), - $this->getArgumentsWildcard() - ); - - try { - $prediction->check($calls, $this->getObjectProphecy(), $this); - $this->checkedPredictions[] = $prediction; - } catch (\Exception $e) { - $this->checkedPredictions[] = $prediction; - - throw $e; - } - - return $this; - } - - /** - * Checks call prediction. - * - * @see Prophecy\Prediction\CallPrediction - * - * @return $this - */ - public function shouldHaveBeenCalled() - { - return $this->shouldHave(new Prediction\CallPrediction); - } - - /** - * Checks no calls prediction. - * - * @see Prophecy\Prediction\NoCallsPrediction - * - * @return $this - */ - public function shouldNotHaveBeenCalled() - { - return $this->shouldHave(new Prediction\NoCallsPrediction); - } - - /** - * Checks no calls prediction. - * - * @see Prophecy\Prediction\NoCallsPrediction - * @deprecated - * - * @return $this - */ - public function shouldNotBeenCalled() - { - return $this->shouldNotHaveBeenCalled(); - } - - /** - * Checks call times prediction. - * - * @see Prophecy\Prediction\CallTimesPrediction - * - * @param int $count - * - * @return $this - */ - public function shouldHaveBeenCalledTimes($count) - { - return $this->shouldHave(new Prediction\CallTimesPrediction($count)); - } - - /** - * Checks currently registered [with should(...)] prediction. - */ - public function checkPrediction() - { - if (null === $this->prediction) { - return; - } - - $this->shouldHave($this->prediction); - } - - /** - * Returns currently registered promise. - * - * @return null|Promise\PromiseInterface - */ - public function getPromise() - { - return $this->promise; - } - - /** - * Returns currently registered prediction. - * - * @return null|Prediction\PredictionInterface - */ - public function getPrediction() - { - return $this->prediction; - } - - /** - * Returns predictions that were checked on this object. - * - * @return Prediction\PredictionInterface[] - */ - public function getCheckedPredictions() - { - return $this->checkedPredictions; - } - - /** - * Returns object prophecy this method prophecy is tied to. - * - * @return ObjectProphecy - */ - public function getObjectProphecy() - { - return $this->objectProphecy; - } - - /** - * Returns method name. - * - * @return string - */ - public function getMethodName() - { - return $this->methodName; - } - - /** - * Returns arguments wildcard. - * - * @return Argument\ArgumentsWildcard - */ - public function getArgumentsWildcard() - { - return $this->argumentsWildcard; - } - - private function bindToObjectProphecy() - { - if ($this->bound) { - return; - } - - $this->getObjectProphecy()->addMethodProphecy($this); - $this->bound = true; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Comparator; - -use Prophecy\Prophecy\ProphecyInterface; -use SebastianBergmann\Comparator\ObjectComparator; - -class ProphecyComparator extends ObjectComparator -{ - public function accepts($expected, $actual) - { - return is_object($expected) && is_object($actual) && $actual instanceof ProphecyInterface; - } - - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = array()) - { - parent::assertEquals($expected, $actual->reveal(), $delta, $canonicalize, $ignoreCase, $processed); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Comparator; - -use SebastianBergmann\Comparator\Comparator; -use SebastianBergmann\Comparator\ComparisonFailure; - -/** - * Closure comparator. - * - * @author Konstantin Kudryashov - */ -final class ClosureComparator extends Comparator -{ - public function accepts($expected, $actual) - { - return is_object($expected) && $expected instanceof \Closure - && is_object($actual) && $actual instanceof \Closure; - } - - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) - { - throw new ComparisonFailure( - $expected, - $actual, - // we don't need a diff - '', - '', - false, - 'all closures are born different' - ); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Comparator; - -use SebastianBergmann\Comparator\Factory as BaseFactory; - -/** - * Prophecy comparator factory. - * - * @author Konstantin Kudryashov - */ -final class Factory extends BaseFactory -{ - /** - * @var Factory - */ - private static $instance; - - public function __construct() - { - parent::__construct(); - - $this->register(new ClosureComparator()); - $this->register(new ProphecyComparator()); - } - - /** - * @return Factory - */ - public static function getInstance() - { - if (self::$instance === null) { - self::$instance = new Factory; - } - - return self::$instance; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy; - -use Prophecy\Argument\Token; - -/** - * Argument tokens shortcuts. - * - * @author Konstantin Kudryashov - */ -class Argument -{ - /** - * Checks that argument is exact value or object. - * - * @param mixed $value - * - * @return Token\ExactValueToken - */ - public static function exact($value) - { - return new Token\ExactValueToken($value); - } - - /** - * Checks that argument is of specific type or instance of specific class. - * - * @param string $type Type name (`integer`, `string`) or full class name - * - * @return Token\TypeToken - */ - public static function type($type) - { - return new Token\TypeToken($type); - } - - /** - * Checks that argument object has specific state. - * - * @param string $methodName - * @param mixed $value - * - * @return Token\ObjectStateToken - */ - public static function which($methodName, $value) - { - return new Token\ObjectStateToken($methodName, $value); - } - - /** - * Checks that argument matches provided callback. - * - * @param callable $callback - * - * @return Token\CallbackToken - */ - public static function that($callback) - { - return new Token\CallbackToken($callback); - } - - /** - * Matches any single value. - * - * @return Token\AnyValueToken - */ - public static function any() - { - return new Token\AnyValueToken; - } - - /** - * Matches all values to the rest of the signature. - * - * @return Token\AnyValuesToken - */ - public static function cetera() - { - return new Token\AnyValuesToken; - } - - /** - * Checks that argument matches all tokens - * - * @param mixed ... a list of tokens - * - * @return Token\LogicalAndToken - */ - public static function allOf() - { - return new Token\LogicalAndToken(func_get_args()); - } - - /** - * Checks that argument array or countable object has exact number of elements. - * - * @param integer $value array elements count - * - * @return Token\ArrayCountToken - */ - public static function size($value) - { - return new Token\ArrayCountToken($value); - } - - /** - * Checks that argument array contains (key, value) pair - * - * @param mixed $key exact value or token - * @param mixed $value exact value or token - * - * @return Token\ArrayEntryToken - */ - public static function withEntry($key, $value) - { - return new Token\ArrayEntryToken($key, $value); - } - - /** - * Checks that arguments array entries all match value - * - * @param mixed $value - * - * @return Token\ArrayEveryEntryToken - */ - public static function withEveryEntry($value) - { - return new Token\ArrayEveryEntryToken($value); - } - - /** - * Checks that argument array contains value - * - * @param mixed $value - * - * @return Token\ArrayEntryToken - */ - public static function containing($value) - { - return new Token\ArrayEntryToken(self::any(), $value); - } - - /** - * Checks that argument array has key - * - * @param mixed $key exact value or token - * - * @return Token\ArrayEntryToken - */ - public static function withKey($key) - { - return new Token\ArrayEntryToken($key, self::any()); - } - - /** - * Checks that argument does not match the value|token. - * - * @param mixed $value either exact value or argument token - * - * @return Token\LogicalNotToken - */ - public static function not($value) - { - return new Token\LogicalNotToken($value); - } - - /** - * @param string $value - * - * @return Token\StringContainsToken - */ - public static function containingString($value) - { - return new Token\StringContainsToken($value); - } - - /** - * Checks that argument is identical value. - * - * @param mixed $value - * - * @return Token\IdenticalValueToken - */ - public static function is($value) - { - return new Token\IdenticalValueToken($value); - } - - /** - * Check that argument is same value when rounding to the - * given precision. - * - * @param float $value - * @param float $precision - * - * @return Token\ApproximateValueToken - */ - public static function approximate($value, $precision = 0) - { - return new Token\ApproximateValueToken($value, $precision); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy; - -use Prophecy\Doubler\Doubler; -use Prophecy\Doubler\LazyDouble; -use Prophecy\Doubler\ClassPatch; -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophecy\RevealerInterface; -use Prophecy\Prophecy\Revealer; -use Prophecy\Call\CallCenter; -use Prophecy\Util\StringUtil; -use Prophecy\Exception\Prediction\PredictionException; -use Prophecy\Exception\Prediction\AggregateException; - -/** - * Prophet creates prophecies. - * - * @author Konstantin Kudryashov - */ -class Prophet -{ - private $doubler; - private $revealer; - private $util; - - /** - * @var ObjectProphecy[] - */ - private $prophecies = array(); - - /** - * Initializes Prophet. - * - * @param null|Doubler $doubler - * @param null|RevealerInterface $revealer - * @param null|StringUtil $util - */ - public function __construct(Doubler $doubler = null, RevealerInterface $revealer = null, - StringUtil $util = null) - { - if (null === $doubler) { - $doubler = new Doubler; - $doubler->registerClassPatch(new ClassPatch\SplFileInfoPatch); - $doubler->registerClassPatch(new ClassPatch\TraversablePatch); - $doubler->registerClassPatch(new ClassPatch\DisableConstructorPatch); - $doubler->registerClassPatch(new ClassPatch\ProphecySubjectPatch); - $doubler->registerClassPatch(new ClassPatch\ReflectionClassNewInstancePatch); - $doubler->registerClassPatch(new ClassPatch\HhvmExceptionPatch()); - $doubler->registerClassPatch(new ClassPatch\MagicCallPatch); - $doubler->registerClassPatch(new ClassPatch\KeywordPatch); - } - - $this->doubler = $doubler; - $this->revealer = $revealer ?: new Revealer; - $this->util = $util ?: new StringUtil; - } - - /** - * Creates new object prophecy. - * - * @param null|string $classOrInterface Class or interface name - * - * @return ObjectProphecy - */ - public function prophesize($classOrInterface = null) - { - $this->prophecies[] = $prophecy = new ObjectProphecy( - new LazyDouble($this->doubler), - new CallCenter($this->util), - $this->revealer - ); - - if ($classOrInterface && class_exists($classOrInterface)) { - return $prophecy->willExtend($classOrInterface); - } - - if ($classOrInterface && interface_exists($classOrInterface)) { - return $prophecy->willImplement($classOrInterface); - } - - return $prophecy; - } - - /** - * Returns all created object prophecies. - * - * @return ObjectProphecy[] - */ - public function getProphecies() - { - return $this->prophecies; - } - - /** - * Returns Doubler instance assigned to this Prophet. - * - * @return Doubler - */ - public function getDoubler() - { - return $this->doubler; - } - - /** - * Checks all predictions defined by prophecies of this Prophet. - * - * @throws Exception\Prediction\AggregateException If any prediction fails - */ - public function checkPredictions() - { - $exception = new AggregateException("Some predictions failed:\n"); - foreach ($this->prophecies as $prophecy) { - try { - $prophecy->checkProphecyMethodsPredictions(); - } catch (PredictionException $e) { - $exception->append($e); - } - } - - if (count($exception->getExceptions())) { - throw $exception; - } - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception; - -/** - * Core Prophecy exception interface. - * All Prophecy exceptions implement it. - * - * @author Konstantin Kudryashov - */ -interface Exception -{ - /** - * @return string - */ - public function getMessage(); -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Prophecy; - -use Prophecy\Prophecy\ObjectProphecy; - -class ObjectProphecyException extends \RuntimeException implements ProphecyException -{ - private $objectProphecy; - - public function __construct($message, ObjectProphecy $objectProphecy) - { - parent::__construct($message); - - $this->objectProphecy = $objectProphecy; - } - - /** - * @return ObjectProphecy - */ - public function getObjectProphecy() - { - return $this->objectProphecy; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Prophecy; - -use Prophecy\Exception\Exception; - -interface ProphecyException extends Exception -{ -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Prophecy; - -use Prophecy\Prophecy\MethodProphecy; - -class MethodProphecyException extends ObjectProphecyException -{ - private $methodProphecy; - - public function __construct($message, MethodProphecy $methodProphecy) - { - parent::__construct($message, $methodProphecy->getObjectProphecy()); - - $this->methodProphecy = $methodProphecy; - } - - /** - * @return MethodProphecy - */ - public function getMethodProphecy() - { - return $this->methodProphecy; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Doubler; - -class InterfaceNotFoundException extends ClassNotFoundException -{ - public function getInterfaceName() - { - return $this->getClassname(); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Doubler; - -use ReflectionClass; - -class ClassMirrorException extends \RuntimeException implements DoublerException -{ - private $class; - - public function __construct($message, ReflectionClass $class) - { - parent::__construct($message); - - $this->class = $class; - } - - public function getReflectedClass() - { - return $this->class; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Doubler; - -use RuntimeException; - -class DoubleException extends RuntimeException implements DoublerException -{ -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Doubler; - -use Prophecy\Exception\Exception; - -interface DoublerException extends Exception -{ -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Doubler; - -class MethodNotFoundException extends DoubleException -{ - /** - * @var string - */ - private $classname; - - /** - * @var string - */ - private $methodName; - - /** - * @var array - */ - private $arguments; - - /** - * @param string $message - * @param string $classname - * @param string $methodName - * @param null|Argument\ArgumentsWildcard|array $arguments - */ - public function __construct($message, $classname, $methodName, $arguments = null) - { - parent::__construct($message); - - $this->classname = $classname; - $this->methodName = $methodName; - $this->arguments = $arguments; - } - - public function getClassname() - { - return $this->classname; - } - - public function getMethodName() - { - return $this->methodName; - } - - public function getArguments() - { - return $this->arguments; - } -} -methodName = $methodName; - $this->className = $className; - } - - - /** - * @return string - */ - public function getMethodName() - { - return $this->methodName; - } - - /** - * @return string - */ - public function getClassName() - { - return $this->className; - } - - } - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Doubler; - -class ReturnByReferenceException extends DoubleException -{ - private $classname; - private $methodName; - - /** - * @param string $message - * @param string $classname - * @param string $methodName - */ - public function __construct($message, $classname, $methodName) - { - parent::__construct($message); - - $this->classname = $classname; - $this->methodName = $methodName; - } - - public function getClassname() - { - return $this->classname; - } - - public function getMethodName() - { - return $this->methodName; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Doubler; - -use Prophecy\Doubler\Generator\Node\ClassNode; - -class ClassCreatorException extends \RuntimeException implements DoublerException -{ - private $node; - - public function __construct($message, ClassNode $node) - { - parent::__construct($message); - - $this->node = $node; - } - - public function getClassNode() - { - return $this->node; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Doubler; - -class ClassNotFoundException extends DoubleException -{ - private $classname; - - /** - * @param string $message - * @param string $classname - */ - public function __construct($message, $classname) - { - parent::__construct($message); - - $this->classname = $classname; - } - - public function getClassname() - { - return $this->classname; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Prediction; - -use Prophecy\Prophecy\MethodProphecy; -use Prophecy\Exception\Prophecy\MethodProphecyException; - -class UnexpectedCallsException extends MethodProphecyException implements PredictionException -{ - private $calls = array(); - - public function __construct($message, MethodProphecy $methodProphecy, array $calls) - { - parent::__construct($message, $methodProphecy); - - $this->calls = $calls; - } - - public function getCalls() - { - return $this->calls; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Prediction; - -use Prophecy\Exception\Exception; - -interface PredictionException extends Exception -{ -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Prediction; - -use RuntimeException; - -/** - * Basic failed prediction exception. - * Use it for custom prediction failures. - * - * @author Konstantin Kudryashov - */ -class FailedPredictionException extends RuntimeException implements PredictionException -{ -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Prediction; - -use Prophecy\Exception\Prophecy\MethodProphecyException; - -class NoCallsException extends MethodProphecyException implements PredictionException -{ -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Prediction; - -use Prophecy\Prophecy\ObjectProphecy; - -class AggregateException extends \RuntimeException implements PredictionException -{ - private $exceptions = array(); - private $objectProphecy; - - public function append(PredictionException $exception) - { - $message = $exception->getMessage(); - $message = ' '.strtr($message, array("\n" => "\n "))."\n"; - - $this->message = rtrim($this->message.$message); - $this->exceptions[] = $exception; - } - - /** - * @return PredictionException[] - */ - public function getExceptions() - { - return $this->exceptions; - } - - public function setObjectProphecy(ObjectProphecy $objectProphecy) - { - $this->objectProphecy = $objectProphecy; - } - - /** - * @return ObjectProphecy - */ - public function getObjectProphecy() - { - return $this->objectProphecy; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Prediction; - -use Prophecy\Prophecy\MethodProphecy; - -class UnexpectedCallsCountException extends UnexpectedCallsException -{ - private $expectedCount; - - public function __construct($message, MethodProphecy $methodProphecy, $count, array $calls) - { - parent::__construct($message, $methodProphecy, $calls); - - $this->expectedCount = intval($count); - } - - public function getExpectedCount() - { - return $this->expectedCount; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception\Call; - -use Prophecy\Exception\Prophecy\ObjectProphecyException; -use Prophecy\Prophecy\ObjectProphecy; - -class UnexpectedCallException extends ObjectProphecyException -{ - private $methodName; - private $arguments; - - public function __construct($message, ObjectProphecy $objectProphecy, - $methodName, array $arguments) - { - parent::__construct($message, $objectProphecy); - - $this->methodName = $methodName; - $this->arguments = $arguments; - } - - public function getMethodName() - { - return $this->methodName; - } - - public function getArguments() - { - return $this->arguments; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Exception; - -class InvalidArgumentException extends \InvalidArgumentException implements Exception -{ -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler; - -use ReflectionClass; - -/** - * Cached class doubler. - * Prevents mirroring/creation of the same structure twice. - * - * @author Konstantin Kudryashov - */ -class CachedDoubler extends Doubler -{ - private $classes = array(); - - /** - * {@inheritdoc} - */ - public function registerClassPatch(ClassPatch\ClassPatchInterface $patch) - { - $this->classes[] = array(); - - parent::registerClassPatch($patch); - } - - /** - * {@inheritdoc} - */ - protected function createDoubleClass(ReflectionClass $class = null, array $interfaces) - { - $classId = $this->generateClassId($class, $interfaces); - if (isset($this->classes[$classId])) { - return $this->classes[$classId]; - } - - return $this->classes[$classId] = parent::createDoubleClass($class, $interfaces); - } - - /** - * @param ReflectionClass $class - * @param ReflectionClass[] $interfaces - * - * @return string - */ - private function generateClassId(ReflectionClass $class = null, array $interfaces) - { - $parts = array(); - if (null !== $class) { - $parts[] = $class->getName(); - } - foreach ($interfaces as $interface) { - $parts[] = $interface->getName(); - } - sort($parts); - - return md5(implode('', $parts)); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler; - -/** - * Core double interface. - * All doubled classes will implement this one. - * - * @author Konstantin Kudryashov - */ -interface DoubleInterface -{ -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler; - -use Doctrine\Instantiator\Instantiator; -use Prophecy\Doubler\ClassPatch\ClassPatchInterface; -use Prophecy\Doubler\Generator\ClassMirror; -use Prophecy\Doubler\Generator\ClassCreator; -use Prophecy\Exception\InvalidArgumentException; -use ReflectionClass; - -/** - * Cached class doubler. - * Prevents mirroring/creation of the same structure twice. - * - * @author Konstantin Kudryashov - */ -class Doubler -{ - private $mirror; - private $creator; - private $namer; - - /** - * @var ClassPatchInterface[] - */ - private $patches = array(); - - /** - * @var \Doctrine\Instantiator\Instantiator - */ - private $instantiator; - - /** - * Initializes doubler. - * - * @param ClassMirror $mirror - * @param ClassCreator $creator - * @param NameGenerator $namer - */ - public function __construct(ClassMirror $mirror = null, ClassCreator $creator = null, - NameGenerator $namer = null) - { - $this->mirror = $mirror ?: new ClassMirror; - $this->creator = $creator ?: new ClassCreator; - $this->namer = $namer ?: new NameGenerator; - } - - /** - * Returns list of registered class patches. - * - * @return ClassPatchInterface[] - */ - public function getClassPatches() - { - return $this->patches; - } - - /** - * Registers new class patch. - * - * @param ClassPatchInterface $patch - */ - public function registerClassPatch(ClassPatchInterface $patch) - { - $this->patches[] = $patch; - - @usort($this->patches, function (ClassPatchInterface $patch1, ClassPatchInterface $patch2) { - return $patch2->getPriority() - $patch1->getPriority(); - }); - } - - /** - * Creates double from specific class or/and list of interfaces. - * - * @param ReflectionClass $class - * @param ReflectionClass[] $interfaces Array of ReflectionClass instances - * @param array $args Constructor arguments - * - * @return DoubleInterface - * - * @throws \Prophecy\Exception\InvalidArgumentException - */ - public function double(ReflectionClass $class = null, array $interfaces, array $args = null) - { - foreach ($interfaces as $interface) { - if (!$interface instanceof ReflectionClass) { - throw new InvalidArgumentException(sprintf( - "[ReflectionClass \$interface1 [, ReflectionClass \$interface2]] array expected as\n". - "a second argument to `Doubler::double(...)`, but got %s.", - is_object($interface) ? get_class($interface).' class' : gettype($interface) - )); - } - } - - $classname = $this->createDoubleClass($class, $interfaces); - $reflection = new ReflectionClass($classname); - - if (null !== $args) { - return $reflection->newInstanceArgs($args); - } - if ((null === $constructor = $reflection->getConstructor()) - || ($constructor->isPublic() && !$constructor->isFinal())) { - return $reflection->newInstance(); - } - - if (!$this->instantiator) { - $this->instantiator = new Instantiator(); - } - - return $this->instantiator->instantiate($classname); - } - - /** - * Creates double class and returns its FQN. - * - * @param ReflectionClass $class - * @param ReflectionClass[] $interfaces - * - * @return string - */ - protected function createDoubleClass(ReflectionClass $class = null, array $interfaces) - { - $name = $this->namer->name($class, $interfaces); - $node = $this->mirror->reflect($class, $interfaces); - - foreach ($this->patches as $patch) { - if ($patch->supports($node)) { - $patch->apply($node); - } - } - - $this->creator->create($name, $node); - - return $name; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\Generator; - -/** - * Class code creator. - * Generates PHP code for specific class node tree. - * - * @author Konstantin Kudryashov - */ -class ClassCodeGenerator -{ - /** - * Generates PHP code for class node. - * - * @param string $classname - * @param Node\ClassNode $class - * - * @return string - */ - public function generate($classname, Node\ClassNode $class) - { - $parts = explode('\\', $classname); - $classname = array_pop($parts); - $namespace = implode('\\', $parts); - - $code = sprintf("class %s extends \%s implements %s {\n", - $classname, $class->getParentClass(), implode(', ', - array_map(function ($interface) {return '\\'.$interface;}, $class->getInterfaces()) - ) - ); - - foreach ($class->getProperties() as $name => $visibility) { - $code .= sprintf("%s \$%s;\n", $visibility, $name); - } - $code .= "\n"; - - foreach ($class->getMethods() as $method) { - $code .= $this->generateMethod($method)."\n"; - } - $code .= "\n}"; - - return sprintf("namespace %s {\n%s\n}", $namespace, $code); - } - - private function generateMethod(Node\MethodNode $method) - { - $php = sprintf("%s %s function %s%s(%s)%s {\n", - $method->getVisibility(), - $method->isStatic() ? 'static' : '', - $method->returnsReference() ? '&':'', - $method->getName(), - implode(', ', $this->generateArguments($method->getArguments())), - version_compare(PHP_VERSION, '7.0', '>=') && $method->hasReturnType() - ? sprintf(': %s', $method->getReturnType()) - : '' - ); - $php .= $method->getCode()."\n"; - - return $php.'}'; - } - - private function generateArguments(array $arguments) - { - return array_map(function (Node\ArgumentNode $argument) { - $php = ''; - - if ($hint = $argument->getTypeHint()) { - switch ($hint) { - case 'array': - case 'callable': - $php .= $hint; - break; - - case 'string': - case 'int': - case 'float': - case 'bool': - if (version_compare(PHP_VERSION, '7.0', '>=')) { - $php .= $hint; - break; - } - // Fall-through to default case for PHP 5.x - - default: - $php .= '\\'.$hint; - } - } - - $php .= ' '.($argument->isPassedByReference() ? '&' : ''); - - $php .= $argument->isVariadic() ? '...' : ''; - - $php .= '$'.$argument->getName(); - - if ($argument->isOptional() && !$argument->isVariadic()) { - $php .= ' = '.var_export($argument->getDefault(), true); - } - - return $php; - }, $arguments); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\Generator; - -use Prophecy\Exception\Doubler\ClassCreatorException; - -/** - * Class creator. - * Creates specific class in current environment. - * - * @author Konstantin Kudryashov - */ -class ClassCreator -{ - private $generator; - - /** - * Initializes creator. - * - * @param ClassCodeGenerator $generator - */ - public function __construct(ClassCodeGenerator $generator = null) - { - $this->generator = $generator ?: new ClassCodeGenerator; - } - - /** - * Creates class. - * - * @param string $classname - * @param Node\ClassNode $class - * - * @return mixed - * - * @throws \Prophecy\Exception\Doubler\ClassCreatorException - */ - public function create($classname, Node\ClassNode $class) - { - $code = $this->generator->generate($classname, $class); - $return = eval($code); - - if (!class_exists($classname, false)) { - if (count($class->getInterfaces())) { - throw new ClassCreatorException(sprintf( - 'Could not double `%s` and implement interfaces: [%s].', - $class->getParentClass(), implode(', ', $class->getInterfaces()) - ), $class); - } - - throw new ClassCreatorException( - sprintf('Could not double `%s`.', $class->getParentClass()), - $class - ); - } - - return $return; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\Generator; - -/** - * Reflection interface. - * All reflected classes implement this interface. - * - * @author Konstantin Kudryashov - */ -interface ReflectionInterface -{ -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\Generator; - -use Prophecy\Exception\InvalidArgumentException; -use Prophecy\Exception\Doubler\ClassMirrorException; -use ReflectionClass; -use ReflectionMethod; -use ReflectionParameter; - -/** - * Class mirror. - * Core doubler class. Mirrors specific class and/or interfaces into class node tree. - * - * @author Konstantin Kudryashov - */ -class ClassMirror -{ - private static $reflectableMethods = array( - '__construct', - '__destruct', - '__sleep', - '__wakeup', - '__toString', - '__call', - '__invoke' - ); - - /** - * Reflects provided arguments into class node. - * - * @param ReflectionClass $class - * @param ReflectionClass[] $interfaces - * - * @return Node\ClassNode - * - * @throws \Prophecy\Exception\InvalidArgumentException - */ - public function reflect(ReflectionClass $class = null, array $interfaces) - { - $node = new Node\ClassNode; - - if (null !== $class) { - if (true === $class->isInterface()) { - throw new InvalidArgumentException(sprintf( - "Could not reflect %s as a class, because it\n". - "is interface - use the second argument instead.", - $class->getName() - )); - } - - $this->reflectClassToNode($class, $node); - } - - foreach ($interfaces as $interface) { - if (!$interface instanceof ReflectionClass) { - throw new InvalidArgumentException(sprintf( - "[ReflectionClass \$interface1 [, ReflectionClass \$interface2]] array expected as\n". - "a second argument to `ClassMirror::reflect(...)`, but got %s.", - is_object($interface) ? get_class($interface).' class' : gettype($interface) - )); - } - if (false === $interface->isInterface()) { - throw new InvalidArgumentException(sprintf( - "Could not reflect %s as an interface, because it\n". - "is class - use the first argument instead.", - $interface->getName() - )); - } - - $this->reflectInterfaceToNode($interface, $node); - } - - $node->addInterface('Prophecy\Doubler\Generator\ReflectionInterface'); - - return $node; - } - - private function reflectClassToNode(ReflectionClass $class, Node\ClassNode $node) - { - if (true === $class->isFinal()) { - throw new ClassMirrorException(sprintf( - 'Could not reflect class %s as it is marked final.', $class->getName() - ), $class); - } - - $node->setParentClass($class->getName()); - - foreach ($class->getMethods(ReflectionMethod::IS_ABSTRACT) as $method) { - if (false === $method->isProtected()) { - continue; - } - - $this->reflectMethodToNode($method, $node); - } - - foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { - if (0 === strpos($method->getName(), '_') - && !in_array($method->getName(), self::$reflectableMethods)) { - continue; - } - - if (true === $method->isFinal()) { - $node->addUnextendableMethod($method->getName()); - continue; - } - - $this->reflectMethodToNode($method, $node); - } - } - - private function reflectInterfaceToNode(ReflectionClass $interface, Node\ClassNode $node) - { - $node->addInterface($interface->getName()); - - foreach ($interface->getMethods() as $method) { - $this->reflectMethodToNode($method, $node); - } - } - - private function reflectMethodToNode(ReflectionMethod $method, Node\ClassNode $classNode) - { - $node = new Node\MethodNode($method->getName()); - - if (true === $method->isProtected()) { - $node->setVisibility('protected'); - } - - if (true === $method->isStatic()) { - $node->setStatic(); - } - - if (true === $method->returnsReference()) { - $node->setReturnsReference(); - } - - if (version_compare(PHP_VERSION, '7.0', '>=') && true === $method->hasReturnType()) { - $returnType = (string) $method->getReturnType(); - $returnTypeLower = strtolower($returnType); - - if ('self' === $returnTypeLower) { - $returnType = $method->getDeclaringClass()->getName(); - } - if ('parent' === $returnTypeLower) { - $returnType = $method->getDeclaringClass()->getParentClass()->getName(); - } - - $node->setReturnType($returnType); - } - - if (is_array($params = $method->getParameters()) && count($params)) { - foreach ($params as $param) { - $this->reflectArgumentToNode($param, $node); - } - } - - $classNode->addMethod($node); - } - - private function reflectArgumentToNode(ReflectionParameter $parameter, Node\MethodNode $methodNode) - { - $name = $parameter->getName() == '...' ? '__dot_dot_dot__' : $parameter->getName(); - $node = new Node\ArgumentNode($name); - - $node->setTypeHint($this->getTypeHint($parameter)); - - if ($this->isVariadic($parameter)) { - $node->setAsVariadic(); - } - - if ($this->hasDefaultValue($parameter)) { - $node->setDefault($this->getDefaultValue($parameter)); - } - - if ($parameter->isPassedByReference()) { - $node->setAsPassedByReference(); - } - - $methodNode->addArgument($node); - } - - private function hasDefaultValue(ReflectionParameter $parameter) - { - if ($this->isVariadic($parameter)) { - return false; - } - - if ($parameter->isDefaultValueAvailable()) { - return true; - } - - return $parameter->isOptional() || $this->isNullable($parameter); - } - - private function getDefaultValue(ReflectionParameter $parameter) - { - if (!$parameter->isDefaultValueAvailable()) { - return null; - } - - return $parameter->getDefaultValue(); - } - - private function getTypeHint(ReflectionParameter $parameter) - { - if (null !== $className = $this->getParameterClassName($parameter)) { - return $className; - } - - if (true === $parameter->isArray()) { - return 'array'; - } - - if (version_compare(PHP_VERSION, '5.4', '>=') && true === $parameter->isCallable()) { - return 'callable'; - } - - if (version_compare(PHP_VERSION, '7.0', '>=') && true === $parameter->hasType()) { - return (string) $parameter->getType(); - } - - return null; - } - - private function isVariadic(ReflectionParameter $parameter) - { - return PHP_VERSION_ID >= 50600 && $parameter->isVariadic(); - } - - private function isNullable(ReflectionParameter $parameter) - { - return $parameter->allowsNull() && null !== $this->getTypeHint($parameter); - } - - private function getParameterClassName(ReflectionParameter $parameter) - { - try { - return $parameter->getClass() ? $parameter->getClass()->getName() : null; - } catch (\ReflectionException $e) { - preg_match('/\[\s\<\w+?>\s([\w,\\\]+)/s', $parameter, $matches); - - return isset($matches[1]) ? $matches[1] : null; - } - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\Generator\Node; - -/** - * Argument node. - * - * @author Konstantin Kudryashov - */ -class ArgumentNode -{ - private $name; - private $typeHint; - private $default; - private $optional = false; - private $byReference = false; - private $isVariadic = false; - - /** - * @param string $name - */ - public function __construct($name) - { - $this->name = $name; - } - - public function getName() - { - return $this->name; - } - - public function getTypeHint() - { - return $this->typeHint; - } - - public function setTypeHint($typeHint = null) - { - $this->typeHint = $typeHint; - } - - public function hasDefault() - { - return $this->isOptional() && !$this->isVariadic(); - } - - public function getDefault() - { - return $this->default; - } - - public function setDefault($default = null) - { - $this->optional = true; - $this->default = $default; - } - - public function isOptional() - { - return $this->optional; - } - - public function setAsPassedByReference($byReference = true) - { - $this->byReference = $byReference; - } - - public function isPassedByReference() - { - return $this->byReference; - } - - public function setAsVariadic($isVariadic = true) - { - $this->isVariadic = $isVariadic; - } - - public function isVariadic() - { - return $this->isVariadic; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\Generator\Node; - -use Prophecy\Exception\InvalidArgumentException; - -/** - * Method node. - * - * @author Konstantin Kudryashov - */ -class MethodNode -{ - private $name; - private $code; - private $visibility = 'public'; - private $static = false; - private $returnsReference = false; - private $returnType; - - /** - * @var ArgumentNode[] - */ - private $arguments = array(); - - /** - * @param string $name - * @param string $code - */ - public function __construct($name, $code = null) - { - $this->name = $name; - $this->code = $code; - } - - public function getVisibility() - { - return $this->visibility; - } - - /** - * @param string $visibility - */ - public function setVisibility($visibility) - { - $visibility = strtolower($visibility); - - if (!in_array($visibility, array('public', 'private', 'protected'))) { - throw new InvalidArgumentException(sprintf( - '`%s` method visibility is not supported.', $visibility - )); - } - - $this->visibility = $visibility; - } - - public function isStatic() - { - return $this->static; - } - - public function setStatic($static = true) - { - $this->static = (bool) $static; - } - - public function returnsReference() - { - return $this->returnsReference; - } - - public function setReturnsReference() - { - $this->returnsReference = true; - } - - public function getName() - { - return $this->name; - } - - public function addArgument(ArgumentNode $argument) - { - $this->arguments[] = $argument; - } - - /** - * @return ArgumentNode[] - */ - public function getArguments() - { - return $this->arguments; - } - - public function hasReturnType() - { - return null !== $this->returnType; - } - - /** - * @param string $type - */ - public function setReturnType($type = null) - { - switch ($type) { - case '': - $this->returnType = null; - break; - - case 'string'; - case 'float': - case 'int': - case 'bool': - case 'array': - case 'callable': - $this->returnType = $type; - break; - - case 'double': - case 'real': - $this->returnType = 'float'; - break; - - case 'boolean': - $this->returnType = 'bool'; - break; - - case 'integer': - $this->returnType = 'int'; - break; - - default: - $this->returnType = '\\' . ltrim($type, '\\'); - } - } - - public function getReturnType() - { - return $this->returnType; - } - - /** - * @param string $code - */ - public function setCode($code) - { - $this->code = $code; - } - - public function getCode() - { - if ($this->returnsReference) - { - return "throw new \Prophecy\Exception\Doubler\ReturnByReferenceException('Returning by reference not supported', get_class(\$this), '{$this->name}');"; - } - - return (string) $this->code; - } - - public function useParentCode() - { - $this->code = sprintf( - 'return parent::%s(%s);', $this->getName(), implode(', ', - array_map(array($this, 'generateArgument'), $this->arguments) - ) - ); - } - - private function generateArgument(ArgumentNode $arg) - { - $argument = '$'.$arg->getName(); - - if ($arg->isVariadic()) { - $argument = '...'.$argument; - } - - return $argument; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\Generator\Node; - -use Prophecy\Exception\Doubler\MethodNotExtendableException; -use Prophecy\Exception\InvalidArgumentException; - -/** - * Class node. - * - * @author Konstantin Kudryashov - */ -class ClassNode -{ - private $parentClass = 'stdClass'; - private $interfaces = array(); - private $properties = array(); - private $unextendableMethods = array(); - - /** - * @var MethodNode[] - */ - private $methods = array(); - - public function getParentClass() - { - return $this->parentClass; - } - - /** - * @param string $class - */ - public function setParentClass($class) - { - $this->parentClass = $class ?: 'stdClass'; - } - - /** - * @return string[] - */ - public function getInterfaces() - { - return $this->interfaces; - } - - /** - * @param string $interface - */ - public function addInterface($interface) - { - if ($this->hasInterface($interface)) { - return; - } - - array_unshift($this->interfaces, $interface); - } - - /** - * @param string $interface - * - * @return bool - */ - public function hasInterface($interface) - { - return in_array($interface, $this->interfaces); - } - - public function getProperties() - { - return $this->properties; - } - - public function addProperty($name, $visibility = 'public') - { - $visibility = strtolower($visibility); - - if (!in_array($visibility, array('public', 'private', 'protected'))) { - throw new InvalidArgumentException(sprintf( - '`%s` property visibility is not supported.', $visibility - )); - } - - $this->properties[$name] = $visibility; - } - - /** - * @return MethodNode[] - */ - public function getMethods() - { - return $this->methods; - } - - public function addMethod(MethodNode $method) - { - if (!$this->isExtendable($method->getName())){ - $message = sprintf( - 'Method `%s` is not extendable, so can not be added.', $method->getName() - ); - throw new MethodNotExtendableException($message, $this->getParentClass(), $method->getName()); - } - $this->methods[$method->getName()] = $method; - } - - public function removeMethod($name) - { - unset($this->methods[$name]); - } - - /** - * @param string $name - * - * @return MethodNode|null - */ - public function getMethod($name) - { - return $this->hasMethod($name) ? $this->methods[$name] : null; - } - - /** - * @param string $name - * - * @return bool - */ - public function hasMethod($name) - { - return isset($this->methods[$name]); - } - - /** - * @return string[] - */ - public function getUnextendableMethods() - { - return $this->unextendableMethods; - } - - /** - * @param string $unextendableMethod - */ - public function addUnextendableMethod($unextendableMethod) - { - if (!$this->isExtendable($unextendableMethod)){ - return; - } - $this->unextendableMethods[] = $unextendableMethod; - } - - /** - * @param string $method - * @return bool - */ - public function isExtendable($method) - { - return !in_array($method, $this->unextendableMethods); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler; - -use Prophecy\Exception\Doubler\DoubleException; -use Prophecy\Exception\Doubler\ClassNotFoundException; -use Prophecy\Exception\Doubler\InterfaceNotFoundException; -use ReflectionClass; - -/** - * Lazy double. - * Gives simple interface to describe double before creating it. - * - * @author Konstantin Kudryashov - */ -class LazyDouble -{ - private $doubler; - private $class; - private $interfaces = array(); - private $arguments = null; - private $double; - - /** - * Initializes lazy double. - * - * @param Doubler $doubler - */ - public function __construct(Doubler $doubler) - { - $this->doubler = $doubler; - } - - /** - * Tells doubler to use specific class as parent one for double. - * - * @param string|ReflectionClass $class - * - * @throws \Prophecy\Exception\Doubler\ClassNotFoundException - * @throws \Prophecy\Exception\Doubler\DoubleException - */ - public function setParentClass($class) - { - if (null !== $this->double) { - throw new DoubleException('Can not extend class with already instantiated double.'); - } - - if (!$class instanceof ReflectionClass) { - if (!class_exists($class)) { - throw new ClassNotFoundException(sprintf('Class %s not found.', $class), $class); - } - - $class = new ReflectionClass($class); - } - - $this->class = $class; - } - - /** - * Tells doubler to implement specific interface with double. - * - * @param string|ReflectionClass $interface - * - * @throws \Prophecy\Exception\Doubler\InterfaceNotFoundException - * @throws \Prophecy\Exception\Doubler\DoubleException - */ - public function addInterface($interface) - { - if (null !== $this->double) { - throw new DoubleException( - 'Can not implement interface with already instantiated double.' - ); - } - - if (!$interface instanceof ReflectionClass) { - if (!interface_exists($interface)) { - throw new InterfaceNotFoundException( - sprintf('Interface %s not found.', $interface), - $interface - ); - } - - $interface = new ReflectionClass($interface); - } - - $this->interfaces[] = $interface; - } - - /** - * Sets constructor arguments. - * - * @param array $arguments - */ - public function setArguments(array $arguments = null) - { - $this->arguments = $arguments; - } - - /** - * Creates double instance or returns already created one. - * - * @return DoubleInterface - */ - public function getInstance() - { - if (null === $this->double) { - if (null !== $this->arguments) { - return $this->double = $this->doubler->double( - $this->class, $this->interfaces, $this->arguments - ); - } - - $this->double = $this->doubler->double($this->class, $this->interfaces); - } - - return $this->double; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\ClassPatch; - -use Prophecy\Doubler\Generator\Node\ClassNode; - -/** - * Remove method functionality from the double which will clash with php keywords. - * - * @author Milan Magudia - */ -class KeywordPatch implements ClassPatchInterface -{ - /** - * Support any class - * - * @param ClassNode $node - * - * @return boolean - */ - public function supports(ClassNode $node) - { - return true; - } - - /** - * Remove methods that clash with php keywords - * - * @param ClassNode $node - */ - public function apply(ClassNode $node) - { - $methodNames = array_keys($node->getMethods()); - $methodsToRemove = array_intersect($methodNames, $this->getKeywords()); - foreach ($methodsToRemove as $methodName) { - $node->removeMethod($methodName); - } - } - - /** - * Returns patch priority, which determines when patch will be applied. - * - * @return int Priority number (higher - earlier) - */ - public function getPriority() { - return 49; - } - - /** - * Returns array of php keywords. - * - * @return array - */ - private function getKeywords() { - - return array( - '__halt_compiler', - 'abstract', - 'and', - 'array', - 'as', - 'break', - 'callable', - 'case', - 'catch', - 'class', - 'clone', - 'const', - 'continue', - 'declare', - 'default', - 'die', - 'do', - 'echo', - 'else', - 'elseif', - 'empty', - 'enddeclare', - 'endfor', - 'endforeach', - 'endif', - 'endswitch', - 'endwhile', - 'eval', - 'exit', - 'extends', - 'final', - 'finally', - 'for', - 'foreach', - 'function', - 'global', - 'goto', - 'if', - 'implements', - 'include', - 'include_once', - 'instanceof', - 'insteadof', - 'interface', - 'isset', - 'list', - 'namespace', - 'new', - 'or', - 'print', - 'private', - 'protected', - 'public', - 'require', - 'require_once', - 'return', - 'static', - 'switch', - 'throw', - 'trait', - 'try', - 'unset', - 'use', - 'var', - 'while', - 'xor', - 'yield', - ); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\ClassPatch; - -use Prophecy\Doubler\Generator\Node\ClassNode; -use Prophecy\Doubler\Generator\Node\MethodNode; -use Prophecy\Doubler\Generator\Node\ArgumentNode; - -/** - * Add Prophecy functionality to the double. - * This is a core class patch for Prophecy. - * - * @author Konstantin Kudryashov - */ -class ProphecySubjectPatch implements ClassPatchInterface -{ - /** - * Always returns true. - * - * @param ClassNode $node - * - * @return bool - */ - public function supports(ClassNode $node) - { - return true; - } - - /** - * Apply Prophecy functionality to class node. - * - * @param ClassNode $node - */ - public function apply(ClassNode $node) - { - $node->addInterface('Prophecy\Prophecy\ProphecySubjectInterface'); - $node->addProperty('objectProphecy', 'private'); - - foreach ($node->getMethods() as $name => $method) { - if ('__construct' === strtolower($name)) { - continue; - } - - $method->setCode( - 'return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());' - ); - } - - $prophecySetter = new MethodNode('setProphecy'); - $prophecyArgument = new ArgumentNode('prophecy'); - $prophecyArgument->setTypeHint('Prophecy\Prophecy\ProphecyInterface'); - $prophecySetter->addArgument($prophecyArgument); - $prophecySetter->setCode('$this->objectProphecy = $prophecy;'); - - $prophecyGetter = new MethodNode('getProphecy'); - $prophecyGetter->setCode('return $this->objectProphecy;'); - - if ($node->hasMethod('__call')) { - $__call = $node->getMethod('__call'); - } else { - $__call = new MethodNode('__call'); - $__call->addArgument(new ArgumentNode('name')); - $__call->addArgument(new ArgumentNode('arguments')); - - $node->addMethod($__call); - } - - $__call->setCode(<<getProphecy(), func_get_arg(0) -); -PHP - ); - - $node->addMethod($prophecySetter); - $node->addMethod($prophecyGetter); - } - - /** - * Returns patch priority, which determines when patch will be applied. - * - * @return int Priority number (higher - earlier) - */ - public function getPriority() - { - return 0; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\ClassPatch; - -use phpDocumentor\Reflection\DocBlock; -use Prophecy\Doubler\Generator\Node\ClassNode; -use Prophecy\Doubler\Generator\Node\MethodNode; - -/** - * Discover Magical API using "@method" PHPDoc format. - * - * @author Thomas Tourlourat - */ -class MagicCallPatch implements ClassPatchInterface -{ - /** - * Support any class - * - * @param ClassNode $node - * - * @return boolean - */ - public function supports(ClassNode $node) - { - return true; - } - - /** - * Discover Magical API - * - * @param ClassNode $node - */ - public function apply(ClassNode $node) - { - $parentClass = $node->getParentClass(); - $reflectionClass = new \ReflectionClass($parentClass); - - $phpdoc = new DocBlock($reflectionClass->getDocComment()); - - $tagList = $phpdoc->getTagsByName('method'); - - $interfaces = $reflectionClass->getInterfaces(); - foreach($interfaces as $interface) { - $phpdoc = new DocBlock($interface); - $tagList = array_merge($tagList, $phpdoc->getTagsByName('method')); - } - - foreach($tagList as $tag) { - $methodName = $tag->getMethodName(); - - if (!$reflectionClass->hasMethod($methodName)) { - $methodNode = new MethodNode($tag->getMethodName()); - $methodNode->setStatic($tag->isStatic()); - - $node->addMethod($methodNode); - } - } - } - - /** - * Returns patch priority, which determines when patch will be applied. - * - * @return integer Priority number (higher - earlier) - */ - public function getPriority() - { - return 50; - } -} - - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\ClassPatch; - -use Prophecy\Doubler\Generator\Node\ClassNode; -use Prophecy\Doubler\Generator\Node\MethodNode; - -/** - * Traversable interface patch. - * Forces classes that implement interfaces, that extend Traversable to also implement Iterator. - * - * @author Konstantin Kudryashov - */ -class TraversablePatch implements ClassPatchInterface -{ - /** - * Supports nodetree, that implement Traversable, but not Iterator or IteratorAggregate. - * - * @param ClassNode $node - * - * @return bool - */ - public function supports(ClassNode $node) - { - if (in_array('Iterator', $node->getInterfaces())) { - return false; - } - if (in_array('IteratorAggregate', $node->getInterfaces())) { - return false; - } - - foreach ($node->getInterfaces() as $interface) { - if ('Traversable' !== $interface && !is_subclass_of($interface, 'Traversable')) { - continue; - } - if ('Iterator' === $interface || is_subclass_of($interface, 'Iterator')) { - continue; - } - if ('IteratorAggregate' === $interface || is_subclass_of($interface, 'IteratorAggregate')) { - continue; - } - - return true; - } - - return false; - } - - /** - * Forces class to implement Iterator interface. - * - * @param ClassNode $node - */ - public function apply(ClassNode $node) - { - $node->addInterface('Iterator'); - - $node->addMethod(new MethodNode('current')); - $node->addMethod(new MethodNode('key')); - $node->addMethod(new MethodNode('next')); - $node->addMethod(new MethodNode('rewind')); - $node->addMethod(new MethodNode('valid')); - } - - /** - * Returns patch priority, which determines when patch will be applied. - * - * @return int Priority number (higher - earlier) - */ - public function getPriority() - { - return 100; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\ClassPatch; - -use Prophecy\Doubler\Generator\Node\ClassNode; -use Prophecy\Doubler\Generator\Node\MethodNode; - -/** - * SplFileInfo patch. - * Makes SplFileInfo and derivative classes usable with Prophecy. - * - * @author Konstantin Kudryashov - */ -class SplFileInfoPatch implements ClassPatchInterface -{ - /** - * Supports everything that extends SplFileInfo. - * - * @param ClassNode $node - * - * @return bool - */ - public function supports(ClassNode $node) - { - if (null === $node->getParentClass()) { - return false; - } - - return 'SplFileInfo' === $node->getParentClass() - || is_subclass_of($node->getParentClass(), 'SplFileInfo') - ; - } - - /** - * Updated constructor code to call parent one with dummy file argument. - * - * @param ClassNode $node - */ - public function apply(ClassNode $node) - { - if ($node->hasMethod('__construct')) { - $constructor = $node->getMethod('__construct'); - } else { - $constructor = new MethodNode('__construct'); - $node->addMethod($constructor); - } - - if ($this->nodeIsDirectoryIterator($node)) { - $constructor->setCode('return parent::__construct("' . __DIR__ . '");'); - return; - } - - $constructor->useParentCode(); - } - - /** - * Returns patch priority, which determines when patch will be applied. - * - * @return int Priority number (higher - earlier) - */ - public function getPriority() - { - return 50; - } - - /** - * @param ClassNode $node - * @return boolean - */ - private function nodeIsDirectoryIterator(ClassNode $node) - { - $parent = $node->getParentClass(); - return 'DirectoryIterator' === $parent - || is_subclass_of($parent, 'DirectoryIterator'); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\ClassPatch; - -use Prophecy\Doubler\Generator\Node\ClassNode; -use Prophecy\Doubler\Generator\Node\MethodNode; - -/** - * Disable constructor. - * Makes all constructor arguments optional. - * - * @author Konstantin Kudryashov - */ -class DisableConstructorPatch implements ClassPatchInterface -{ - /** - * Checks if class has `__construct` method. - * - * @param ClassNode $node - * - * @return bool - */ - public function supports(ClassNode $node) - { - return true; - } - - /** - * Makes all class constructor arguments optional. - * - * @param ClassNode $node - */ - public function apply(ClassNode $node) - { - if (!$node->hasMethod('__construct')) { - $node->addMethod(new MethodNode('__construct', '')); - - return; - } - - $constructor = $node->getMethod('__construct'); - foreach ($constructor->getArguments() as $argument) { - $argument->setDefault(null); - } - - $constructor->setCode(<< - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\ClassPatch; - -use Prophecy\Doubler\Generator\Node\ClassNode; - -/** - * Exception patch for HHVM to remove the stubs from special methods - * - * @author Christophe Coevoet - */ -class HhvmExceptionPatch implements ClassPatchInterface -{ - /** - * Supports exceptions on HHVM. - * - * @param ClassNode $node - * - * @return bool - */ - public function supports(ClassNode $node) - { - if (!defined('HHVM_VERSION')) { - return false; - } - - return 'Exception' === $node->getParentClass() || is_subclass_of($node->getParentClass(), 'Exception'); - } - - /** - * Removes special exception static methods from the doubled methods. - * - * @param ClassNode $node - * - * @return void - */ - public function apply(ClassNode $node) - { - if ($node->hasMethod('setTraceOptions')) { - $node->getMethod('setTraceOptions')->useParentCode(); - } - if ($node->hasMethod('getTraceOptions')) { - $node->getMethod('getTraceOptions')->useParentCode(); - } - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - return -50; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\ClassPatch; - -use Prophecy\Doubler\Generator\Node\ClassNode; - -/** - * ReflectionClass::newInstance patch. - * Makes first argument of newInstance optional, since it works but signature is misleading - * - * @author Florian Klein - */ -class ReflectionClassNewInstancePatch implements ClassPatchInterface -{ - /** - * Supports ReflectionClass - * - * @param ClassNode $node - * - * @return bool - */ - public function supports(ClassNode $node) - { - return 'ReflectionClass' === $node->getParentClass(); - } - - /** - * Updates newInstance's first argument to make it optional - * - * @param ClassNode $node - */ - public function apply(ClassNode $node) - { - foreach ($node->getMethod('newInstance')->getArguments() as $argument) { - $argument->setDefault(null); - } - } - - /** - * Returns patch priority, which determines when patch will be applied. - * - * @return int Priority number (higher = earlier) - */ - public function getPriority() - { - return 50; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler\ClassPatch; - -use Prophecy\Doubler\Generator\Node\ClassNode; - -/** - * Class patch interface. - * Class patches extend doubles functionality or help - * Prophecy to avoid some internal PHP bugs. - * - * @author Konstantin Kudryashov - */ -interface ClassPatchInterface -{ - /** - * Checks if patch supports specific class node. - * - * @param ClassNode $node - * - * @return bool - */ - public function supports(ClassNode $node); - - /** - * Applies patch to the specific class node. - * - * @param ClassNode $node - * @return void - */ - public function apply(ClassNode $node); - - /** - * Returns patch priority, which determines when patch will be applied. - * - * @return int Priority number (higher - earlier) - */ - public function getPriority(); -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Doubler; - -use ReflectionClass; - -/** - * Name generator. - * Generates classname for double. - * - * @author Konstantin Kudryashov - */ -class NameGenerator -{ - private static $counter = 1; - - /** - * Generates name. - * - * @param ReflectionClass $class - * @param ReflectionClass[] $interfaces - * - * @return string - */ - public function name(ReflectionClass $class = null, array $interfaces) - { - $parts = array(); - - if (null !== $class) { - $parts[] = $class->getName(); - } else { - foreach ($interfaces as $interface) { - $parts[] = $interface->getShortName(); - } - } - - if (!count($parts)) { - $parts[] = 'stdClass'; - } - - return sprintf('Double\%s\P%d', implode('\\', $parts), self::$counter++); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Prediction; - -use Prophecy\Call\Call; -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophecy\MethodProphecy; -use Prophecy\Argument\ArgumentsWildcard; -use Prophecy\Argument\Token\AnyValuesToken; -use Prophecy\Util\StringUtil; -use Prophecy\Exception\Prediction\UnexpectedCallsCountException; - -/** - * Prediction interface. - * Predictions are logical test blocks, tied to `should...` keyword. - * - * @author Konstantin Kudryashov - */ -class CallTimesPrediction implements PredictionInterface -{ - private $times; - private $util; - - /** - * Initializes prediction. - * - * @param int $times - * @param StringUtil $util - */ - public function __construct($times, StringUtil $util = null) - { - $this->times = intval($times); - $this->util = $util ?: new StringUtil; - } - - /** - * Tests that there was exact amount of calls made. - * - * @param Call[] $calls - * @param ObjectProphecy $object - * @param MethodProphecy $method - * - * @throws \Prophecy\Exception\Prediction\UnexpectedCallsCountException - */ - public function check(array $calls, ObjectProphecy $object, MethodProphecy $method) - { - if ($this->times == count($calls)) { - return; - } - - $methodCalls = $object->findProphecyMethodCalls( - $method->getMethodName(), - new ArgumentsWildcard(array(new AnyValuesToken)) - ); - - if (count($calls)) { - $message = sprintf( - "Expected exactly %d calls that match:\n". - " %s->%s(%s)\n". - "but %d were made:\n%s", - - $this->times, - get_class($object->reveal()), - $method->getMethodName(), - $method->getArgumentsWildcard(), - count($calls), - $this->util->stringifyCalls($calls) - ); - } elseif (count($methodCalls)) { - $message = sprintf( - "Expected exactly %d calls that match:\n". - " %s->%s(%s)\n". - "but none were made.\n". - "Recorded `%s(...)` calls:\n%s", - - $this->times, - get_class($object->reveal()), - $method->getMethodName(), - $method->getArgumentsWildcard(), - $method->getMethodName(), - $this->util->stringifyCalls($methodCalls) - ); - } else { - $message = sprintf( - "Expected exactly %d calls that match:\n". - " %s->%s(%s)\n". - "but none were made.", - - $this->times, - get_class($object->reveal()), - $method->getMethodName(), - $method->getArgumentsWildcard() - ); - } - - throw new UnexpectedCallsCountException($message, $method, $this->times, $calls); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Prediction; - -use Prophecy\Call\Call; -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophecy\MethodProphecy; -use Prophecy\Util\StringUtil; -use Prophecy\Exception\Prediction\UnexpectedCallsException; - -/** - * No calls prediction. - * - * @author Konstantin Kudryashov - */ -class NoCallsPrediction implements PredictionInterface -{ - private $util; - - /** - * Initializes prediction. - * - * @param null|StringUtil $util - */ - public function __construct(StringUtil $util = null) - { - $this->util = $util ?: new StringUtil; - } - - /** - * Tests that there were no calls made. - * - * @param Call[] $calls - * @param ObjectProphecy $object - * @param MethodProphecy $method - * - * @throws \Prophecy\Exception\Prediction\UnexpectedCallsException - */ - public function check(array $calls, ObjectProphecy $object, MethodProphecy $method) - { - if (!count($calls)) { - return; - } - - $verb = count($calls) === 1 ? 'was' : 'were'; - - throw new UnexpectedCallsException(sprintf( - "No calls expected that match:\n". - " %s->%s(%s)\n". - "but %d %s made:\n%s", - get_class($object->reveal()), - $method->getMethodName(), - $method->getArgumentsWildcard(), - count($calls), - $verb, - $this->util->stringifyCalls($calls) - ), $method, $calls); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Prediction; - -use Prophecy\Call\Call; -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophecy\MethodProphecy; - -/** - * Prediction interface. - * Predictions are logical test blocks, tied to `should...` keyword. - * - * @author Konstantin Kudryashov - */ -interface PredictionInterface -{ - /** - * Tests that double fulfilled prediction. - * - * @param Call[] $calls - * @param ObjectProphecy $object - * @param MethodProphecy $method - * - * @throws object - * @return void - */ - public function check(array $calls, ObjectProphecy $object, MethodProphecy $method); -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Prediction; - -use Prophecy\Call\Call; -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophecy\MethodProphecy; -use Prophecy\Exception\InvalidArgumentException; -use Closure; - -/** - * Callback prediction. - * - * @author Konstantin Kudryashov - */ -class CallbackPrediction implements PredictionInterface -{ - private $callback; - - /** - * Initializes callback prediction. - * - * @param callable $callback Custom callback - * - * @throws \Prophecy\Exception\InvalidArgumentException - */ - public function __construct($callback) - { - if (!is_callable($callback)) { - throw new InvalidArgumentException(sprintf( - 'Callable expected as an argument to CallbackPrediction, but got %s.', - gettype($callback) - )); - } - - $this->callback = $callback; - } - - /** - * Executes preset callback. - * - * @param Call[] $calls - * @param ObjectProphecy $object - * @param MethodProphecy $method - */ - public function check(array $calls, ObjectProphecy $object, MethodProphecy $method) - { - $callback = $this->callback; - - if ($callback instanceof Closure && method_exists('Closure', 'bind')) { - $callback = Closure::bind($callback, $object); - } - - call_user_func($callback, $calls, $object, $method); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Prediction; - -use Prophecy\Call\Call; -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophecy\MethodProphecy; -use Prophecy\Argument\ArgumentsWildcard; -use Prophecy\Argument\Token\AnyValuesToken; -use Prophecy\Util\StringUtil; -use Prophecy\Exception\Prediction\NoCallsException; - -/** - * Call prediction. - * - * @author Konstantin Kudryashov - */ -class CallPrediction implements PredictionInterface -{ - private $util; - - /** - * Initializes prediction. - * - * @param StringUtil $util - */ - public function __construct(StringUtil $util = null) - { - $this->util = $util ?: new StringUtil; - } - - /** - * Tests that there was at least one call. - * - * @param Call[] $calls - * @param ObjectProphecy $object - * @param MethodProphecy $method - * - * @throws \Prophecy\Exception\Prediction\NoCallsException - */ - public function check(array $calls, ObjectProphecy $object, MethodProphecy $method) - { - if (count($calls)) { - return; - } - - $methodCalls = $object->findProphecyMethodCalls( - $method->getMethodName(), - new ArgumentsWildcard(array(new AnyValuesToken)) - ); - - if (count($methodCalls)) { - throw new NoCallsException(sprintf( - "No calls have been made that match:\n". - " %s->%s(%s)\n". - "but expected at least one.\n". - "Recorded `%s(...)` calls:\n%s", - - get_class($object->reveal()), - $method->getMethodName(), - $method->getArgumentsWildcard(), - $method->getMethodName(), - $this->util->stringifyCalls($methodCalls) - ), $method); - } - - throw new NoCallsException(sprintf( - "No calls have been made that match:\n". - " %s->%s(%s)\n". - "but expected at least one.", - - get_class($object->reveal()), - $method->getMethodName(), - $method->getArgumentsWildcard() - ), $method); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Call; - -use Exception; - -/** - * Call object. - * - * @author Konstantin Kudryashov - */ -class Call -{ - private $methodName; - private $arguments; - private $returnValue; - private $exception; - private $file; - private $line; - - /** - * Initializes call. - * - * @param string $methodName - * @param array $arguments - * @param mixed $returnValue - * @param Exception $exception - * @param null|string $file - * @param null|int $line - */ - public function __construct($methodName, array $arguments, $returnValue, - Exception $exception = null, $file, $line) - { - $this->methodName = $methodName; - $this->arguments = $arguments; - $this->returnValue = $returnValue; - $this->exception = $exception; - - if ($file) { - $this->file = $file; - $this->line = intval($line); - } - } - - /** - * Returns called method name. - * - * @return string - */ - public function getMethodName() - { - return $this->methodName; - } - - /** - * Returns called method arguments. - * - * @return array - */ - public function getArguments() - { - return $this->arguments; - } - - /** - * Returns called method return value. - * - * @return null|mixed - */ - public function getReturnValue() - { - return $this->returnValue; - } - - /** - * Returns exception that call thrown. - * - * @return null|Exception - */ - public function getException() - { - return $this->exception; - } - - /** - * Returns callee filename. - * - * @return string - */ - public function getFile() - { - return $this->file; - } - - /** - * Returns callee line number. - * - * @return int - */ - public function getLine() - { - return $this->line; - } - - /** - * Returns short notation for callee place. - * - * @return string - */ - public function getCallPlace() - { - if (null === $this->file) { - return 'unknown'; - } - - return sprintf('%s:%d', $this->file, $this->line); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Call; - -use Prophecy\Prophecy\MethodProphecy; -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Argument\ArgumentsWildcard; -use Prophecy\Util\StringUtil; -use Prophecy\Exception\Call\UnexpectedCallException; - -/** - * Calls receiver & manager. - * - * @author Konstantin Kudryashov - */ -class CallCenter -{ - private $util; - - /** - * @var Call[] - */ - private $recordedCalls = array(); - - /** - * Initializes call center. - * - * @param StringUtil $util - */ - public function __construct(StringUtil $util = null) - { - $this->util = $util ?: new StringUtil; - } - - /** - * Makes and records specific method call for object prophecy. - * - * @param ObjectProphecy $prophecy - * @param string $methodName - * @param array $arguments - * - * @return mixed Returns null if no promise for prophecy found or promise return value. - * - * @throws \Prophecy\Exception\Call\UnexpectedCallException If no appropriate method prophecy found - */ - public function makeCall(ObjectProphecy $prophecy, $methodName, array $arguments) - { - // For efficiency exclude 'args' from the generated backtrace - if (PHP_VERSION_ID >= 50400) { - // Limit backtrace to last 3 calls as we don't use the rest - // Limit argument was introduced in PHP 5.4.0 - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3); - } elseif (defined('DEBUG_BACKTRACE_IGNORE_ARGS')) { - // DEBUG_BACKTRACE_IGNORE_ARGS was introduced in PHP 5.3.6 - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); - } else { - $backtrace = debug_backtrace(); - } - - $file = $line = null; - if (isset($backtrace[2]) && isset($backtrace[2]['file'])) { - $file = $backtrace[2]['file']; - $line = $backtrace[2]['line']; - } - - // If no method prophecies defined, then it's a dummy, so we'll just return null - if ('__destruct' === $methodName || 0 == count($prophecy->getMethodProphecies())) { - $this->recordedCalls[] = new Call($methodName, $arguments, null, null, $file, $line); - - return null; - } - - // There are method prophecies, so it's a fake/stub. Searching prophecy for this call - $matches = array(); - foreach ($prophecy->getMethodProphecies($methodName) as $methodProphecy) { - if (0 < $score = $methodProphecy->getArgumentsWildcard()->scoreArguments($arguments)) { - $matches[] = array($score, $methodProphecy); - } - } - - // If fake/stub doesn't have method prophecy for this call - throw exception - if (!count($matches)) { - throw $this->createUnexpectedCallException($prophecy, $methodName, $arguments); - } - - // Sort matches by their score value - @usort($matches, function ($match1, $match2) { return $match2[0] - $match1[0]; }); - - // If Highest rated method prophecy has a promise - execute it or return null instead - $returnValue = null; - $exception = null; - if ($promise = $matches[0][1]->getPromise()) { - try { - $returnValue = $promise->execute($arguments, $prophecy, $matches[0][1]); - } catch (\Exception $e) { - $exception = $e; - } - } - - $this->recordedCalls[] = new Call( - $methodName, $arguments, $returnValue, $exception, $file, $line - ); - - if (null !== $exception) { - throw $exception; - } - - return $returnValue; - } - - /** - * Searches for calls by method name & arguments wildcard. - * - * @param string $methodName - * @param ArgumentsWildcard $wildcard - * - * @return Call[] - */ - public function findCalls($methodName, ArgumentsWildcard $wildcard) - { - return array_values( - array_filter($this->recordedCalls, function (Call $call) use ($methodName, $wildcard) { - return $methodName === $call->getMethodName() - && 0 < $wildcard->scoreArguments($call->getArguments()) - ; - }) - ); - } - - private function createUnexpectedCallException(ObjectProphecy $prophecy, $methodName, - array $arguments) - { - $classname = get_class($prophecy->reveal()); - $argstring = implode(', ', array_map(array($this->util, 'stringify'), $arguments)); - $expected = implode("\n", array_map(function (MethodProphecy $methodProphecy) { - return sprintf(' - %s(%s)', - $methodProphecy->getMethodName(), - $methodProphecy->getArgumentsWildcard() - ); - }, call_user_func_array('array_merge', $prophecy->getMethodProphecies()))); - - return new UnexpectedCallException( - sprintf( - "Method call:\n". - " - %s(%s)\n". - "on %s was not expected, expected calls were:\n%s", - - $methodName, $argstring, $classname, $expected - ), - $prophecy, $methodName, $arguments - ); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Promise; - -use Doctrine\Instantiator\Instantiator; -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophecy\MethodProphecy; -use Prophecy\Exception\InvalidArgumentException; -use ReflectionClass; - -/** - * Throw promise. - * - * @author Konstantin Kudryashov - */ -class ThrowPromise implements PromiseInterface -{ - private $exception; - - /** - * @var \Doctrine\Instantiator\Instantiator - */ - private $instantiator; - - /** - * Initializes promise. - * - * @param string|\Exception $exception Exception class name or instance - * - * @throws \Prophecy\Exception\InvalidArgumentException - */ - public function __construct($exception) - { - if (is_string($exception)) { - if (!class_exists($exception) - && 'Exception' !== $exception - && !is_subclass_of($exception, 'Exception')) { - throw new InvalidArgumentException(sprintf( - 'Exception class or instance expected as argument to ThrowPromise, but got %s.', - $exception - )); - } - } elseif (!$exception instanceof \Exception) { - throw new InvalidArgumentException(sprintf( - 'Exception class or instance expected as argument to ThrowPromise, but got %s.', - is_object($exception) ? get_class($exception) : gettype($exception) - )); - } - - $this->exception = $exception; - } - - /** - * Throws predefined exception. - * - * @param array $args - * @param ObjectProphecy $object - * @param MethodProphecy $method - * - * @throws object - */ - public function execute(array $args, ObjectProphecy $object, MethodProphecy $method) - { - if (is_string($this->exception)) { - $classname = $this->exception; - $reflection = new ReflectionClass($classname); - $constructor = $reflection->getConstructor(); - - if ($constructor->isPublic() && 0 == $constructor->getNumberOfRequiredParameters()) { - throw $reflection->newInstance(); - } - - if (!$this->instantiator) { - $this->instantiator = new Instantiator(); - } - - throw $this->instantiator->instantiate($classname); - } - - throw $this->exception; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Promise; - -use Prophecy\Exception\InvalidArgumentException; -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophecy\MethodProphecy; - -/** - * Return argument promise. - * - * @author Konstantin Kudryashov - */ -class ReturnArgumentPromise implements PromiseInterface -{ - /** - * @var int - */ - private $index; - - /** - * Initializes callback promise. - * - * @param int $index The zero-indexed number of the argument to return - * - * @throws \Prophecy\Exception\InvalidArgumentException - */ - public function __construct($index = 0) - { - if (!is_int($index) || $index < 0) { - throw new InvalidArgumentException(sprintf( - 'Zero-based index expected as argument to ReturnArgumentPromise, but got %s.', - $index - )); - } - $this->index = $index; - } - - /** - * Returns nth argument if has one, null otherwise. - * - * @param array $args - * @param ObjectProphecy $object - * @param MethodProphecy $method - * - * @return null|mixed - */ - public function execute(array $args, ObjectProphecy $object, MethodProphecy $method) - { - return count($args) > $this->index ? $args[$this->index] : null; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Promise; - -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophecy\MethodProphecy; - -/** - * Return promise. - * - * @author Konstantin Kudryashov - */ -class ReturnPromise implements PromiseInterface -{ - private $returnValues = array(); - - /** - * Initializes promise. - * - * @param array $returnValues Array of values - */ - public function __construct(array $returnValues) - { - $this->returnValues = $returnValues; - } - - /** - * Returns saved values one by one until last one, then continuously returns last value. - * - * @param array $args - * @param ObjectProphecy $object - * @param MethodProphecy $method - * - * @return mixed - */ - public function execute(array $args, ObjectProphecy $object, MethodProphecy $method) - { - $value = array_shift($this->returnValues); - - if (!count($this->returnValues)) { - $this->returnValues[] = $value; - } - - return $value; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Promise; - -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophecy\MethodProphecy; -use Prophecy\Exception\InvalidArgumentException; -use Closure; - -/** - * Callback promise. - * - * @author Konstantin Kudryashov - */ -class CallbackPromise implements PromiseInterface -{ - private $callback; - - /** - * Initializes callback promise. - * - * @param callable $callback Custom callback - * - * @throws \Prophecy\Exception\InvalidArgumentException - */ - public function __construct($callback) - { - if (!is_callable($callback)) { - throw new InvalidArgumentException(sprintf( - 'Callable expected as an argument to CallbackPromise, but got %s.', - gettype($callback) - )); - } - - $this->callback = $callback; - } - - /** - * Evaluates promise callback. - * - * @param array $args - * @param ObjectProphecy $object - * @param MethodProphecy $method - * - * @return mixed - */ - public function execute(array $args, ObjectProphecy $object, MethodProphecy $method) - { - $callback = $this->callback; - - if ($callback instanceof Closure && method_exists('Closure', 'bind')) { - $callback = Closure::bind($callback, $object); - } - - return call_user_func($callback, $args, $object, $method); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Promise; - -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophecy\MethodProphecy; - -/** - * Promise interface. - * Promises are logical blocks, tied to `will...` keyword. - * - * @author Konstantin Kudryashov - */ -interface PromiseInterface -{ - /** - * Evaluates promise. - * - * @param array $args - * @param ObjectProphecy $object - * @param MethodProphecy $method - * - * @return mixed - */ - public function execute(array $args, ObjectProphecy $object, MethodProphecy $method); -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument; - -/** - * Arguments wildcarding. - * - * @author Konstantin Kudryashov - */ -class ArgumentsWildcard -{ - /** - * @var Token\TokenInterface[] - */ - private $tokens = array(); - private $string; - - /** - * Initializes wildcard. - * - * @param array $arguments Array of argument tokens or values - */ - public function __construct(array $arguments) - { - foreach ($arguments as $argument) { - if (!$argument instanceof Token\TokenInterface) { - $argument = new Token\ExactValueToken($argument); - } - - $this->tokens[] = $argument; - } - } - - /** - * Calculates wildcard match score for provided arguments. - * - * @param array $arguments - * - * @return false|int False OR integer score (higher - better) - */ - public function scoreArguments(array $arguments) - { - if (0 == count($arguments) && 0 == count($this->tokens)) { - return 1; - } - - $arguments = array_values($arguments); - $totalScore = 0; - foreach ($this->tokens as $i => $token) { - $argument = isset($arguments[$i]) ? $arguments[$i] : null; - if (1 >= $score = $token->scoreArgument($argument)) { - return false; - } - - $totalScore += $score; - - if (true === $token->isLast()) { - return $totalScore; - } - } - - if (count($arguments) > count($this->tokens)) { - return false; - } - - return $totalScore; - } - - /** - * Returns string representation for wildcard. - * - * @return string - */ - public function __toString() - { - if (null === $this->string) { - $this->string = implode(', ', array_map(function ($token) { - return (string) $token; - }, $this->tokens)); - } - - return $this->string; - } - - /** - * @return array - */ - public function getTokens() - { - return $this->tokens; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -/** - * Any single value token. - * - * @author Konstantin Kudryashov - */ -class AnyValueToken implements TokenInterface -{ - /** - * Always scores 3 for any argument. - * - * @param $argument - * - * @return int - */ - public function scoreArgument($argument) - { - return 3; - } - - /** - * Returns false. - * - * @return bool - */ - public function isLast() - { - return false; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - return '*'; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -/** - * Array every entry token. - * - * @author Adrien Brault - */ -class ArrayEveryEntryToken implements TokenInterface -{ - /** - * @var TokenInterface - */ - private $value; - - /** - * @param mixed $value exact value or token - */ - public function __construct($value) - { - if (!$value instanceof TokenInterface) { - $value = new ExactValueToken($value); - } - - $this->value = $value; - } - - /** - * {@inheritdoc} - */ - public function scoreArgument($argument) - { - if (!$argument instanceof \Traversable && !is_array($argument)) { - return false; - } - - $scores = array(); - foreach ($argument as $key => $argumentEntry) { - $scores[] = $this->value->scoreArgument($argumentEntry); - } - - if (empty($scores) || in_array(false, $scores, true)) { - return false; - } - - return array_sum($scores) / count($scores); - } - - /** - * {@inheritdoc} - */ - public function isLast() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function __toString() - { - return sprintf('[%s, ..., %s]', $this->value, $this->value); - } - - /** - * @return TokenInterface - */ - public function getValue() - { - return $this->value; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -/** - * Logical AND token. - * - * @author Boris Mikhaylov - */ -class LogicalAndToken implements TokenInterface -{ - private $tokens = array(); - - /** - * @param array $arguments exact values or tokens - */ - public function __construct(array $arguments) - { - foreach ($arguments as $argument) { - if (!$argument instanceof TokenInterface) { - $argument = new ExactValueToken($argument); - } - $this->tokens[] = $argument; - } - } - - /** - * Scores maximum score from scores returned by tokens for this argument if all of them score. - * - * @param $argument - * - * @return bool|int - */ - public function scoreArgument($argument) - { - if (0 === count($this->tokens)) { - return false; - } - - $maxScore = 0; - foreach ($this->tokens as $token) { - $score = $token->scoreArgument($argument); - if (false === $score) { - return false; - } - $maxScore = max($score, $maxScore); - } - - return $maxScore; - } - - /** - * Returns false. - * - * @return boolean - */ - public function isLast() - { - return false; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - return sprintf('bool(%s)', implode(' AND ', $this->tokens)); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -/** - * Argument token interface. - * - * @author Konstantin Kudryashov - */ -interface TokenInterface -{ - /** - * Calculates token match score for provided argument. - * - * @param $argument - * - * @return bool|int - */ - public function scoreArgument($argument); - - /** - * Returns true if this token prevents check of other tokens (is last one). - * - * @return bool|int - */ - public function isLast(); - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString(); -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -use Prophecy\Exception\InvalidArgumentException; - -/** - * Array entry token. - * - * @author Boris Mikhaylov - */ -class ArrayEntryToken implements TokenInterface -{ - /** @var \Prophecy\Argument\Token\TokenInterface */ - private $key; - /** @var \Prophecy\Argument\Token\TokenInterface */ - private $value; - - /** - * @param mixed $key exact value or token - * @param mixed $value exact value or token - */ - public function __construct($key, $value) - { - $this->key = $this->wrapIntoExactValueToken($key); - $this->value = $this->wrapIntoExactValueToken($value); - } - - /** - * Scores half of combined scores from key and value tokens for same entry. Capped at 8. - * If argument implements \ArrayAccess without \Traversable, then key token is restricted to ExactValueToken. - * - * @param array|\ArrayAccess|\Traversable $argument - * - * @throws \Prophecy\Exception\InvalidArgumentException - * @return bool|int - */ - public function scoreArgument($argument) - { - if ($argument instanceof \Traversable) { - $argument = iterator_to_array($argument); - } - - if ($argument instanceof \ArrayAccess) { - $argument = $this->convertArrayAccessToEntry($argument); - } - - if (!is_array($argument) || empty($argument)) { - return false; - } - - $keyScores = array_map(array($this->key,'scoreArgument'), array_keys($argument)); - $valueScores = array_map(array($this->value,'scoreArgument'), $argument); - $scoreEntry = function ($value, $key) { - return $value && $key ? min(8, ($key + $value) / 2) : false; - }; - - return max(array_map($scoreEntry, $valueScores, $keyScores)); - } - - /** - * Returns false. - * - * @return boolean - */ - public function isLast() - { - return false; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - return sprintf('[..., %s => %s, ...]', $this->key, $this->value); - } - - /** - * Returns key - * - * @return TokenInterface - */ - public function getKey() - { - return $this->key; - } - - /** - * Returns value - * - * @return TokenInterface - */ - public function getValue() - { - return $this->value; - } - - /** - * Wraps non token $value into ExactValueToken - * - * @param $value - * @return TokenInterface - */ - private function wrapIntoExactValueToken($value) - { - return $value instanceof TokenInterface ? $value : new ExactValueToken($value); - } - - /** - * Converts instance of \ArrayAccess to key => value array entry - * - * @param \ArrayAccess $object - * - * @return array|null - * @throws \Prophecy\Exception\InvalidArgumentException - */ - private function convertArrayAccessToEntry(\ArrayAccess $object) - { - if (!$this->key instanceof ExactValueToken) { - throw new InvalidArgumentException(sprintf( - 'You can only use exact value tokens to match key of ArrayAccess object'.PHP_EOL. - 'But you used `%s`.', - $this->key - )); - } - - $key = $this->key->getValue(); - - return $object->offsetExists($key) ? array($key => $object[$key]) : array(); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -/** - * Array elements count token. - * - * @author Boris Mikhaylov - */ - -class ArrayCountToken implements TokenInterface -{ - private $count; - - /** - * @param integer $value - */ - public function __construct($value) - { - $this->count = $value; - } - - /** - * Scores 6 when argument has preset number of elements. - * - * @param $argument - * - * @return bool|int - */ - public function scoreArgument($argument) - { - return $this->isCountable($argument) && $this->hasProperCount($argument) ? 6 : false; - } - - /** - * Returns false. - * - * @return boolean - */ - public function isLast() - { - return false; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - return sprintf('count(%s)', $this->count); - } - - /** - * Returns true if object is either array or instance of \Countable - * - * @param $argument - * @return bool - */ - private function isCountable($argument) - { - return (is_array($argument) || $argument instanceof \Countable); - } - - /** - * Returns true if $argument has expected number of elements - * - * @param array|\Countable $argument - * - * @return bool - */ - private function hasProperCount($argument) - { - return $this->count === count($argument); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -/** - * Any values token. - * - * @author Konstantin Kudryashov - */ -class AnyValuesToken implements TokenInterface -{ - /** - * Always scores 2 for any argument. - * - * @param $argument - * - * @return int - */ - public function scoreArgument($argument) - { - return 2; - } - - /** - * Returns true to stop wildcard from processing other tokens. - * - * @return bool - */ - public function isLast() - { - return true; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - return '* [, ...]'; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -/** - * String contains token. - * - * @author Peter Mitchell - */ -class StringContainsToken implements TokenInterface -{ - private $value; - - /** - * Initializes token. - * - * @param string $value - */ - public function __construct($value) - { - $this->value = $value; - } - - public function scoreArgument($argument) - { - return strpos($argument, $this->value) !== false ? 6 : false; - } - - /** - * Returns preset value against which token checks arguments. - * - * @return mixed - */ - public function getValue() - { - return $this->value; - } - - /** - * Returns false. - * - * @return bool - */ - public function isLast() - { - return false; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - return sprintf('contains("%s")', $this->value); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -/** - * Approximate value token - * - * @author Daniel Leech - */ -class ApproximateValueToken implements TokenInterface -{ - private $value; - private $precision; - - public function __construct($value, $precision = 0) - { - $this->value = $value; - $this->precision = $precision; - } - - /** - * {@inheritdoc} - */ - public function scoreArgument($argument) - { - return round($argument, $this->precision) === round($this->value, $this->precision) ? 10 : false; - } - - /** - * {@inheritdoc} - */ - public function isLast() - { - return false; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - return sprintf('≅%s', round($this->value, $this->precision)); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -use SebastianBergmann\Comparator\ComparisonFailure; -use Prophecy\Comparator\Factory as ComparatorFactory; -use Prophecy\Util\StringUtil; - -/** - * Exact value token. - * - * @author Konstantin Kudryashov - */ -class ExactValueToken implements TokenInterface -{ - private $value; - private $string; - private $util; - private $comparatorFactory; - - /** - * Initializes token. - * - * @param mixed $value - * @param StringUtil $util - * @param ComparatorFactory $comparatorFactory - */ - public function __construct($value, StringUtil $util = null, ComparatorFactory $comparatorFactory = null) - { - $this->value = $value; - $this->util = $util ?: new StringUtil(); - - $this->comparatorFactory = $comparatorFactory ?: ComparatorFactory::getInstance(); - } - - /** - * Scores 10 if argument matches preset value. - * - * @param $argument - * - * @return bool|int - */ - public function scoreArgument($argument) - { - if (is_object($argument) && is_object($this->value)) { - $comparator = $this->comparatorFactory->getComparatorFor( - $argument, $this->value - ); - - try { - $comparator->assertEquals($argument, $this->value); - return 10; - } catch (ComparisonFailure $failure) {} - } - - // If either one is an object it should be castable to a string - if (is_object($argument) xor is_object($this->value)) { - if (is_object($argument) && !method_exists($argument, '__toString')) { - return false; - } - - if (is_object($this->value) && !method_exists($this->value, '__toString')) { - return false; - } - } elseif (is_numeric($argument) && is_numeric($this->value)) { - // noop - } elseif (gettype($argument) !== gettype($this->value)) { - return false; - } - - return $argument == $this->value ? 10 : false; - } - - /** - * Returns preset value against which token checks arguments. - * - * @return mixed - */ - public function getValue() - { - return $this->value; - } - - /** - * Returns false. - * - * @return bool - */ - public function isLast() - { - return false; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - if (null === $this->string) { - $this->string = sprintf('exact(%s)', $this->util->stringify($this->value)); - } - - return $this->string; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -use SebastianBergmann\Comparator\ComparisonFailure; -use Prophecy\Comparator\Factory as ComparatorFactory; -use Prophecy\Util\StringUtil; - -/** - * Object state-checker token. - * - * @author Konstantin Kudryashov - */ -class ObjectStateToken implements TokenInterface -{ - private $name; - private $value; - private $util; - private $comparatorFactory; - - /** - * Initializes token. - * - * @param string $methodName - * @param mixed $value Expected return value - * @param null|StringUtil $util - * @param ComparatorFactory $comparatorFactory - */ - public function __construct( - $methodName, - $value, - StringUtil $util = null, - ComparatorFactory $comparatorFactory = null - ) { - $this->name = $methodName; - $this->value = $value; - $this->util = $util ?: new StringUtil; - - $this->comparatorFactory = $comparatorFactory ?: ComparatorFactory::getInstance(); - } - - /** - * Scores 8 if argument is an object, which method returns expected value. - * - * @param mixed $argument - * - * @return bool|int - */ - public function scoreArgument($argument) - { - if (is_object($argument) && method_exists($argument, $this->name)) { - $actual = call_user_func(array($argument, $this->name)); - - $comparator = $this->comparatorFactory->getComparatorFor( - $actual, $this->value - ); - - try { - $comparator->assertEquals($actual, $this->value); - return 8; - } catch (ComparisonFailure $failure) { - return false; - } - } - - if (is_object($argument) && property_exists($argument, $this->name)) { - return $argument->{$this->name} === $this->value ? 8 : false; - } - - return false; - } - - /** - * Returns false. - * - * @return bool - */ - public function isLast() - { - return false; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - return sprintf('state(%s(), %s)', - $this->name, - $this->util->stringify($this->value) - ); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -use Prophecy\Exception\InvalidArgumentException; - -/** - * Callback-verified token. - * - * @author Konstantin Kudryashov - */ -class CallbackToken implements TokenInterface -{ - private $callback; - - /** - * Initializes token. - * - * @param callable $callback - * - * @throws \Prophecy\Exception\InvalidArgumentException - */ - public function __construct($callback) - { - if (!is_callable($callback)) { - throw new InvalidArgumentException(sprintf( - 'Callable expected as an argument to CallbackToken, but got %s.', - gettype($callback) - )); - } - - $this->callback = $callback; - } - - /** - * Scores 7 if callback returns true, false otherwise. - * - * @param $argument - * - * @return bool|int - */ - public function scoreArgument($argument) - { - return call_user_func($this->callback, $argument) ? 7 : false; - } - - /** - * Returns false. - * - * @return bool - */ - public function isLast() - { - return false; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - return 'callback()'; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -use Prophecy\Util\StringUtil; - -/** - * Identical value token. - * - * @author Florian Voutzinos - */ -class IdenticalValueToken implements TokenInterface -{ - private $value; - private $string; - private $util; - - /** - * Initializes token. - * - * @param mixed $value - * @param StringUtil $util - */ - public function __construct($value, StringUtil $util = null) - { - $this->value = $value; - $this->util = $util ?: new StringUtil(); - } - - /** - * Scores 11 if argument matches preset value. - * - * @param $argument - * - * @return bool|int - */ - public function scoreArgument($argument) - { - return $argument === $this->value ? 11 : false; - } - - /** - * Returns false. - * - * @return bool - */ - public function isLast() - { - return false; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - if (null === $this->string) { - $this->string = sprintf('identical(%s)', $this->util->stringify($this->value)); - } - - return $this->string; - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -/** - * Logical NOT token. - * - * @author Boris Mikhaylov - */ -class LogicalNotToken implements TokenInterface -{ - /** @var \Prophecy\Argument\Token\TokenInterface */ - private $token; - - /** - * @param mixed $value exact value or token - */ - public function __construct($value) - { - $this->token = $value instanceof TokenInterface? $value : new ExactValueToken($value); - } - - /** - * Scores 4 when preset token does not match the argument. - * - * @param $argument - * - * @return bool|int - */ - public function scoreArgument($argument) - { - return false === $this->token->scoreArgument($argument) ? 4 : false; - } - - /** - * Returns true if preset token is last. - * - * @return bool|int - */ - public function isLast() - { - return $this->token->isLast(); - } - - /** - * Returns originating token. - * - * @return TokenInterface - */ - public function getOriginatingToken() - { - return $this->token; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - return sprintf('not(%s)', $this->token); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Argument\Token; - -use Prophecy\Exception\InvalidArgumentException; - -/** - * Value type token. - * - * @author Konstantin Kudryashov - */ -class TypeToken implements TokenInterface -{ - private $type; - - /** - * @param string $type - */ - public function __construct($type) - { - $checker = "is_{$type}"; - if (!function_exists($checker) && !interface_exists($type) && !class_exists($type)) { - throw new InvalidArgumentException(sprintf( - 'Type or class name expected as an argument to TypeToken, but got %s.', $type - )); - } - - $this->type = $type; - } - - /** - * Scores 5 if argument has the same type this token was constructed with. - * - * @param $argument - * - * @return bool|int - */ - public function scoreArgument($argument) - { - $checker = "is_{$this->type}"; - if (function_exists($checker)) { - return call_user_func($checker, $argument) ? 5 : false; - } - - return $argument instanceof $this->type ? 5 : false; - } - - /** - * Returns false. - * - * @return bool - */ - public function isLast() - { - return false; - } - - /** - * Returns string representation for token. - * - * @return string - */ - public function __toString() - { - return sprintf('type(%s)', $this->type); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * This class is a modification from sebastianbergmann/exporter - * @see https://github.com/sebastianbergmann/exporter - */ -class ExportUtil -{ - /** - * Exports a value as a string - * - * The output of this method is similar to the output of print_r(), but - * improved in various aspects: - * - * - NULL is rendered as "null" (instead of "") - * - TRUE is rendered as "true" (instead of "1") - * - FALSE is rendered as "false" (instead of "") - * - Strings are always quoted with single quotes - * - Carriage returns and newlines are normalized to \n - * - Recursion and repeated rendering is treated properly - * - * @param mixed $value - * @param int $indentation The indentation level of the 2nd+ line - * @return string - */ - public static function export($value, $indentation = 0) - { - return self::recursiveExport($value, $indentation); - } - - /** - * Converts an object to an array containing all of its private, protected - * and public properties. - * - * @param mixed $value - * @return array - */ - public static function toArray($value) - { - if (!is_object($value)) { - return (array) $value; - } - - $array = array(); - - foreach ((array) $value as $key => $val) { - // properties are transformed to keys in the following way: - // private $property => "\0Classname\0property" - // protected $property => "\0*\0property" - // public $property => "property" - if (preg_match('/^\0.+\0(.+)$/', $key, $matches)) { - $key = $matches[1]; - } - - // See https://github.com/php/php-src/commit/5721132 - if ($key === "\0gcdata") { - continue; - } - - $array[$key] = $val; - } - - // Some internal classes like SplObjectStorage don't work with the - // above (fast) mechanism nor with reflection in Zend. - // Format the output similarly to print_r() in this case - if ($value instanceof \SplObjectStorage) { - // However, the fast method does work in HHVM, and exposes the - // internal implementation. Hide it again. - if (property_exists('\SplObjectStorage', '__storage')) { - unset($array['__storage']); - } elseif (property_exists('\SplObjectStorage', 'storage')) { - unset($array['storage']); - } - - if (property_exists('\SplObjectStorage', '__key')) { - unset($array['__key']); - } - - foreach ($value as $key => $val) { - $array[spl_object_hash($val)] = array( - 'obj' => $val, - 'inf' => $value->getInfo(), - ); - } - } - - return $array; - } - - /** - * Recursive implementation of export - * - * @param mixed $value The value to export - * @param int $indentation The indentation level of the 2nd+ line - * @param \SebastianBergmann\RecursionContext\Context $processed Previously processed objects - * @return string - * @see SebastianBergmann\Exporter\Exporter::export - */ - protected static function recursiveExport(&$value, $indentation, $processed = null) - { - if ($value === null) { - return 'null'; - } - - if ($value === true) { - return 'true'; - } - - if ($value === false) { - return 'false'; - } - - if (is_float($value) && floatval(intval($value)) === $value) { - return "$value.0"; - } - - if (is_resource($value)) { - return sprintf( - 'resource(%d) of type (%s)', - $value, - get_resource_type($value) - ); - } - - if (is_string($value)) { - // Match for most non printable chars somewhat taking multibyte chars into account - if (preg_match('/[^\x09-\x0d\x20-\xff]/', $value)) { - return 'Binary String: 0x' . bin2hex($value); - } - - return "'" . - str_replace(array("\r\n", "\n\r", "\r"), array("\n", "\n", "\n"), $value) . - "'"; - } - - $whitespace = str_repeat(' ', 4 * $indentation); - - if (!$processed) { - $processed = new Context; - } - - if (is_array($value)) { - if (($key = $processed->contains($value)) !== false) { - return 'Array &' . $key; - } - - $key = $processed->add($value); - $values = ''; - - if (count($value) > 0) { - foreach ($value as $k => $v) { - $values .= sprintf( - '%s %s => %s' . "\n", - $whitespace, - self::recursiveExport($k, $indentation), - self::recursiveExport($value[$k], $indentation + 1, $processed) - ); - } - - $values = "\n" . $values . $whitespace; - } - - return sprintf('Array &%s (%s)', $key, $values); - } - - if (is_object($value)) { - $class = get_class($value); - - if ($value instanceof ProphecyInterface) { - return sprintf('%s Object (*Prophecy*)', $class); - } elseif ($hash = $processed->contains($value)) { - return sprintf('%s:%s Object', $class, $hash); - } - - $hash = $processed->add($value); - $values = ''; - $array = self::toArray($value); - - if (count($array) > 0) { - foreach ($array as $k => $v) { - $values .= sprintf( - '%s %s => %s' . "\n", - $whitespace, - self::recursiveExport($k, $indentation), - self::recursiveExport($v, $indentation + 1, $processed) - ); - } - - $values = "\n" . $values . $whitespace; - } - - return sprintf('%s:%s Object (%s)', $class, $hash, $values); - } - - return var_export($value, true); - } -} - - * Marcello Duarte - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Prophecy\Util; - -use Prophecy\Call\Call; - -/** - * String utility. - * - * @author Konstantin Kudryashov - */ -class StringUtil -{ - /** - * Stringifies any provided value. - * - * @param mixed $value - * @param boolean $exportObject - * - * @return string - */ - public function stringify($value, $exportObject = true) - { - if (is_array($value)) { - if (range(0, count($value) - 1) === array_keys($value)) { - return '['.implode(', ', array_map(array($this, __FUNCTION__), $value)).']'; - } - - $stringify = array($this, __FUNCTION__); - - return '['.implode(', ', array_map(function ($item, $key) use ($stringify) { - return (is_integer($key) ? $key : '"'.$key.'"'). - ' => '.call_user_func($stringify, $item); - }, $value, array_keys($value))).']'; - } - if (is_resource($value)) { - return get_resource_type($value).':'.$value; - } - if (is_object($value)) { - return $exportObject ? ExportUtil::export($value) : sprintf('%s:%s', get_class($value), spl_object_hash($value)); - } - if (true === $value || false === $value) { - return $value ? 'true' : 'false'; - } - if (is_string($value)) { - $str = sprintf('"%s"', str_replace("\n", '\\n', $value)); - - if (50 <= strlen($str)) { - return substr($str, 0, 50).'"...'; - } - - return $str; - } - if (null === $value) { - return 'null'; - } - - return (string) $value; - } - - /** - * Stringifies provided array of calls. - * - * @param Call[] $calls Array of Call instances - * - * @return string - */ - public function stringifyCalls(array $calls) - { - $self = $this; - - return implode(PHP_EOL, array_map(function (Call $call) use ($self) { - return sprintf(' - %s(%s) @ %s', - $call->getMethodName(), - implode(', ', array_map(array($self, 'stringify'), $call->getArguments())), - str_replace(GETCWD().DIRECTORY_SEPARATOR, '', $call->getCallPlace()) - ); - }, $calls)); - } -} -Exporter - -Copyright (c) 2002-2015, Sebastian Bergmann . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Sebastian Bergmann nor the names of his - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\Exporter; - -use SebastianBergmann\RecursionContext\Context; - -/** - * A nifty utility for visualizing PHP variables. - * - * - * export(new Exception); - * - */ -class Exporter -{ - /** - * Exports a value as a string - * - * The output of this method is similar to the output of print_r(), but - * improved in various aspects: - * - * - NULL is rendered as "null" (instead of "") - * - TRUE is rendered as "true" (instead of "1") - * - FALSE is rendered as "false" (instead of "") - * - Strings are always quoted with single quotes - * - Carriage returns and newlines are normalized to \n - * - Recursion and repeated rendering is treated properly - * - * @param mixed $value - * @param int $indentation The indentation level of the 2nd+ line - * @return string - */ - public function export($value, $indentation = 0) - { - return $this->recursiveExport($value, $indentation); - } - - /** - * @param mixed $data - * @param Context $context - * @return string - */ - public function shortenedRecursiveExport(&$data, Context $context = null) - { - $result = array(); - $exporter = new self(); - - if (!$context) { - $context = new Context; - } - - $context->add($data); - - foreach ($data as $key => $value) { - if (is_array($value)) { - if ($context->contains($data[$key]) !== false) { - $result[] = '*RECURSION*'; - } - - else { - $result[] = sprintf( - 'array(%s)', - $this->shortenedRecursiveExport($data[$key], $context) - ); - } - } - - else { - $result[] = $exporter->shortenedExport($value); - } - } - - return implode(', ', $result); - } - - /** - * Exports a value into a single-line string - * - * The output of this method is similar to the output of - * SebastianBergmann\Exporter\Exporter::export. This method guarantees - * thought that the result contains now newlines. - * - * Newlines are replaced by the visible string '\n'. Contents of arrays - * and objects (if any) are replaced by '...'. - * - * @param mixed $value - * @return string - * @see SebastianBergmann\Exporter\Exporter::export - */ - public function shortenedExport($value) - { - if (is_string($value)) { - $string = $this->export($value); - - if (strlen($string) > 40) { - $string = substr($string, 0, 30) . '...' . substr($string, -7); - } - - return str_replace("\n", '\n', $string); - } - - if (is_object($value)) { - return sprintf( - '%s Object (%s)', - get_class($value), - count($this->toArray($value)) > 0 ? '...' : '' - ); - } - - if (is_array($value)) { - return sprintf( - 'Array (%s)', - count($value) > 0 ? '...' : '' - ); - } - - return $this->export($value); - } - - /** - * Converts an object to an array containing all of its private, protected - * and public properties. - * - * @param mixed $value - * @return array - */ - public function toArray($value) - { - if (!is_object($value)) { - return (array) $value; - } - - $array = array(); - - foreach ((array) $value as $key => $val) { - // properties are transformed to keys in the following way: - // private $property => "\0Classname\0property" - // protected $property => "\0*\0property" - // public $property => "property" - if (preg_match('/^\0.+\0(.+)$/', $key, $matches)) { - $key = $matches[1]; - } - - // See https://github.com/php/php-src/commit/5721132 - if ($key === "\0gcdata") { - continue; - } - - $array[$key] = $val; - } - - // Some internal classes like SplObjectStorage don't work with the - // above (fast) mechanism nor with reflection in Zend. - // Format the output similarly to print_r() in this case - if ($value instanceof \SplObjectStorage) { - // However, the fast method does work in HHVM, and exposes the - // internal implementation. Hide it again. - if (property_exists('\SplObjectStorage', '__storage')) { - unset($array['__storage']); - } elseif (property_exists('\SplObjectStorage', 'storage')) { - unset($array['storage']); - } - - if (property_exists('\SplObjectStorage', '__key')) { - unset($array['__key']); - } - - foreach ($value as $key => $val) { - $array[spl_object_hash($val)] = array( - 'obj' => $val, - 'inf' => $value->getInfo(), - ); - } - } - - return $array; - } - - /** - * Recursive implementation of export - * - * @param mixed $value The value to export - * @param int $indentation The indentation level of the 2nd+ line - * @param \SebastianBergmann\RecursionContext\Context $processed Previously processed objects - * @return string - * @see SebastianBergmann\Exporter\Exporter::export - */ - protected function recursiveExport(&$value, $indentation, $processed = null) - { - if ($value === null) { - return 'null'; - } - - if ($value === true) { - return 'true'; - } - - if ($value === false) { - return 'false'; - } - - if (is_float($value) && floatval(intval($value)) === $value) { - return "$value.0"; - } - - if (is_resource($value)) { - return sprintf( - 'resource(%d) of type (%s)', - $value, - get_resource_type($value) - ); - } - - if (is_string($value)) { - // Match for most non printable chars somewhat taking multibyte chars into account - if (preg_match('/[^\x09-\x0d\x20-\xff]/', $value)) { - return 'Binary String: 0x' . bin2hex($value); - } - - return "'" . - str_replace(array("\r\n", "\n\r", "\r"), array("\n", "\n", "\n"), $value) . - "'"; - } - - $whitespace = str_repeat(' ', 4 * $indentation); - - if (!$processed) { - $processed = new Context; - } - - if (is_array($value)) { - if (($key = $processed->contains($value)) !== false) { - return 'Array &' . $key; - } - - $key = $processed->add($value); - $values = ''; - - if (count($value) > 0) { - foreach ($value as $k => $v) { - $values .= sprintf( - '%s %s => %s' . "\n", - $whitespace, - $this->recursiveExport($k, $indentation), - $this->recursiveExport($value[$k], $indentation + 1, $processed) - ); - } - - $values = "\n" . $values . $whitespace; - } - - return sprintf('Array &%s (%s)', $key, $values); - } - - if (is_object($value)) { - $class = get_class($value); - - if ($hash = $processed->contains($value)) { - return sprintf('%s Object &%s', $class, $hash); - } - - $hash = $processed->add($value); - $values = ''; - $array = $this->toArray($value); - - if (count($array) > 0) { - foreach ($array as $k => $v) { - $values .= sprintf( - '%s %s => %s' . "\n", - $whitespace, - $this->recursiveExport($k, $indentation), - $this->recursiveExport($v, $indentation + 1, $processed) - ); - } - - $values = "\n" . $values . $whitespace; - } - - return sprintf('%s Object &%s (%s)', $class, $hash, $values); - } - - return var_export($value, true); - } -} -File_Iterator - -Copyright (c) 2009-2015, Sebastian Bergmann . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Sebastian Bergmann nor the names of his - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * FilterIterator implementation that filters files based on prefix(es) and/or - * suffix(es). Hidden files and files from hidden directories are also filtered. - * - * @since Class available since Release 1.0.0 - */ -class File_Iterator extends FilterIterator -{ - const PREFIX = 0; - const SUFFIX = 1; - - /** - * @var array - */ - protected $suffixes = array(); - - /** - * @var array - */ - protected $prefixes = array(); - - /** - * @var array - */ - protected $exclude = array(); - - /** - * @var string - */ - protected $basepath; - - /** - * @param Iterator $iterator - * @param array $suffixes - * @param array $prefixes - * @param array $exclude - * @param string $basepath - */ - public function __construct(Iterator $iterator, array $suffixes = array(), array $prefixes = array(), array $exclude = array(), $basepath = NULL) - { - $exclude = array_filter(array_map('realpath', $exclude)); - - if ($basepath !== NULL) { - $basepath = realpath($basepath); - } - - if ($basepath === FALSE) { - $basepath = NULL; - } else { - foreach ($exclude as &$_exclude) { - $_exclude = str_replace($basepath, '', $_exclude); - } - } - - $this->prefixes = $prefixes; - $this->suffixes = $suffixes; - $this->exclude = $exclude; - $this->basepath = $basepath; - - parent::__construct($iterator); - } - - /** - * @return bool - */ - public function accept() - { - $current = $this->getInnerIterator()->current(); - $filename = $current->getFilename(); - $realpath = $current->getRealPath(); - - if ($this->basepath !== NULL) { - $realpath = str_replace($this->basepath, '', $realpath); - } - - // Filter files in hidden directories. - if (preg_match('=/\.[^/]*/=', $realpath)) { - return FALSE; - } - - return $this->acceptPath($realpath) && - $this->acceptPrefix($filename) && - $this->acceptSuffix($filename); - } - - /** - * @param string $path - * @return bool - * @since Method available since Release 1.1.0 - */ - protected function acceptPath($path) - { - foreach ($this->exclude as $exclude) { - if (strpos($path, $exclude) === 0) { - return FALSE; - } - } - - return TRUE; - } - - /** - * @param string $filename - * @return bool - * @since Method available since Release 1.1.0 - */ - protected function acceptPrefix($filename) - { - return $this->acceptSubString($filename, $this->prefixes, self::PREFIX); - } - - /** - * @param string $filename - * @return bool - * @since Method available since Release 1.1.0 - */ - protected function acceptSuffix($filename) - { - return $this->acceptSubString($filename, $this->suffixes, self::SUFFIX); - } - - /** - * @param string $filename - * @param array $subString - * @param int $type - * @return bool - * @since Method available since Release 1.1.0 - */ - protected function acceptSubString($filename, array $subStrings, $type) - { - if (empty($subStrings)) { - return TRUE; - } - - $matched = FALSE; - - foreach ($subStrings as $string) { - if (($type == self::PREFIX && strpos($filename, $string) === 0) || - ($type == self::SUFFIX && - substr($filename, -1 * strlen($string)) == $string)) { - $matched = TRUE; - break; - } - } - - return $matched; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Façade implementation that uses File_Iterator_Factory to create a - * File_Iterator that operates on an AppendIterator that contains an - * RecursiveDirectoryIterator for each given path. The list of unique - * files is returned as an array. - * - * @since Class available since Release 1.3.0 - */ -class File_Iterator_Facade -{ - /** - * @param array|string $paths - * @param array|string $suffixes - * @param array|string $prefixes - * @param array $exclude - * @param bool $commonPath - * @return array - */ - public function getFilesAsArray($paths, $suffixes = '', $prefixes = '', array $exclude = array(), $commonPath = FALSE) - { - if (is_string($paths)) { - $paths = array($paths); - } - - $factory = new File_Iterator_Factory; - $iterator = $factory->getFileIterator( - $paths, $suffixes, $prefixes, $exclude - ); - - $files = array(); - - foreach ($iterator as $file) { - $file = $file->getRealPath(); - - if ($file) { - $files[] = $file; - } - } - - foreach ($paths as $path) { - if (is_file($path)) { - $files[] = realpath($path); - } - } - - $files = array_unique($files); - sort($files); - - if ($commonPath) { - return array( - 'commonPath' => $this->getCommonPath($files), - 'files' => $files - ); - } else { - return $files; - } - } - - /** - * Returns the common path of a set of files. - * - * @param array $files - * @return string - */ - protected function getCommonPath(array $files) - { - $count = count($files); - - if ($count == 0) { - return ''; - } - - if ($count == 1) { - return dirname($files[0]) . DIRECTORY_SEPARATOR; - } - - $_files = array(); - - foreach ($files as $file) { - $_files[] = $_fileParts = explode(DIRECTORY_SEPARATOR, $file); - - if (empty($_fileParts[0])) { - $_fileParts[0] = DIRECTORY_SEPARATOR; - } - } - - $common = ''; - $done = FALSE; - $j = 0; - $count--; - - while (!$done) { - for ($i = 0; $i < $count; $i++) { - if ($_files[$i][$j] != $_files[$i+1][$j]) { - $done = TRUE; - break; - } - } - - if (!$done) { - $common .= $_files[0][$j]; - - if ($j > 0) { - $common .= DIRECTORY_SEPARATOR; - } - } - - $j++; - } - - return DIRECTORY_SEPARATOR . $common; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Factory Method implementation that creates a File_Iterator that operates on - * an AppendIterator that contains an RecursiveDirectoryIterator for each given - * path. - * - * @since Class available since Release 1.1.0 - */ -class File_Iterator_Factory -{ - /** - * @param array|string $paths - * @param array|string $suffixes - * @param array|string $prefixes - * @param array $exclude - * @return AppendIterator - */ - public function getFileIterator($paths, $suffixes = '', $prefixes = '', array $exclude = array()) - { - if (is_string($paths)) { - $paths = array($paths); - } - - $paths = $this->getPathsAfterResolvingWildcards($paths); - $exclude = $this->getPathsAfterResolvingWildcards($exclude); - - if (is_string($prefixes)) { - if ($prefixes != '') { - $prefixes = array($prefixes); - } else { - $prefixes = array(); - } - } - - if (is_string($suffixes)) { - if ($suffixes != '') { - $suffixes = array($suffixes); - } else { - $suffixes = array(); - } - } - - $iterator = new AppendIterator; - - foreach ($paths as $path) { - if (is_dir($path)) { - $iterator->append( - new File_Iterator( - new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::FOLLOW_SYMLINKS) - ), - $suffixes, - $prefixes, - $exclude, - $path - ) - ); - } - } - - return $iterator; - } - - /** - * @param array $paths - * @return array - */ - protected function getPathsAfterResolvingWildcards(array $paths) - { - $_paths = array(); - - foreach ($paths as $path) { - if ($locals = glob($path, GLOB_ONLYDIR)) { - $_paths = array_merge($_paths, $locals); - } else { - $_paths[] = $path; - } - } - - return $_paths; - } -} -phpunit/phpunit: 5.2.9 -doctrine/instantiator: 1.0.5 -myclabs/deep-copy: 1.5.0 -phpdocumentor/reflection-docblock: 2.0.4 -phpspec/prophecy: v1.6.0 -phpunit/dbunit: 2.0.2 -phpunit/php-code-coverage: 3.2.1 -phpunit/php-file-iterator: 1.4.1 -phpunit/php-invoker: 1.1.4 -phpunit/php-text-template: 1.2.1 -phpunit/php-timer: 1.0.7 -phpunit/php-token-stream: 1.4.8 -phpunit/phpunit-mock-objects: 3.0.6 -sebastian/code-unit-reverse-lookup: 1.0.0 -sebastian/comparator: 1.2.0 -sebastian/diff: 1.4.1 -sebastian/environment: 1.3.3 -sebastian/exporter: 1.2.1 -sebastian/global-state: 1.1.1 -sebastian/recursion-context: 1.0.2 -sebastian/resource-operations: 1.0.0 -sebastian/version: 2.0.0 -symfony/yaml: v3.0.2 - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\RecursionContext; - -/** - */ -interface Exception -{ -} -Recursion Context - -Copyright (c) 2002-2015, Sebastian Bergmann . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Sebastian Bergmann nor the names of his - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\RecursionContext; - -/** - * A context containing previously processed arrays and objects - * when recursively processing a value. - */ -final class Context -{ - /** - * @var array[] - */ - private $arrays; - - /** - * @var \SplObjectStorage - */ - private $objects; - - /** - * Initialises the context - */ - public function __construct() - { - $this->arrays = array(); - $this->objects = new \SplObjectStorage; - } - - /** - * Adds a value to the context. - * - * @param array|object $value The value to add. - * @return int|string The ID of the stored value, either as - * a string or integer. - * @throws InvalidArgumentException Thrown if $value is not an array or - * object - */ - public function add(&$value) - { - if (is_array($value)) { - return $this->addArray($value); - } - - else if (is_object($value)) { - return $this->addObject($value); - } - - throw new InvalidArgumentException( - 'Only arrays and objects are supported' - ); - } - - /** - * Checks if the given value exists within the context. - * - * @param array|object $value The value to check. - * @return int|string|false The string or integer ID of the stored - * value if it has already been seen, or - * false if the value is not stored. - * @throws InvalidArgumentException Thrown if $value is not an array or - * object - */ - public function contains(&$value) - { - if (is_array($value)) { - return $this->containsArray($value); - } - - else if (is_object($value)) { - return $this->containsObject($value); - } - - throw new InvalidArgumentException( - 'Only arrays and objects are supported' - ); - } - - /** - * @param array $array - * @return bool|int - */ - private function addArray(array &$array) - { - $key = $this->containsArray($array); - - if ($key !== false) { - return $key; - } - - $this->arrays[] = &$array; - - return count($this->arrays) - 1; - } - - /** - * @param object $object - * @return string - */ - private function addObject($object) - { - if (!$this->objects->contains($object)) { - $this->objects->attach($object); - } - - return spl_object_hash($object); - } - - /** - * @param array $array - * @return int|false - */ - private function containsArray(array &$array) - { - $keys = array_keys($this->arrays, $array, true); - $hash = '_Key_' . microtime(true); - - foreach ($keys as $key) { - $this->arrays[$key][$hash] = $hash; - - if (isset($array[$hash]) && $array[$hash] === $hash) { - unset($this->arrays[$key][$hash]); - - return $key; - } - - unset($this->arrays[$key][$hash]); - } - - return false; - } - - /** - * @param object $value - * @return string|false - */ - private function containsObject($value) - { - if ($this->objects->contains($value)) { - return spl_object_hash($value); - } - - return false; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\RecursionContext; - -/** - */ -final class InvalidArgumentException extends \InvalidArgumentException implements Exception -{ -} -Resource Operations - -Copyright (c) 2015, Sebastian Bergmann . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Sebastian Bergmann nor the names of his - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace SebastianBergmann\ResourceOperations; - -class ResourceOperations -{ - /** - * @return string[] - */ - public static function getFunctions() - { - return [ - 'Directory::close', - 'Directory::read', - 'Directory::rewind', - 'HttpResponse::getRequestBodyStream', - 'HttpResponse::getStream', - 'MongoGridFSCursor::__construct', - 'MongoGridFSFile::getResource', - 'MysqlndUhConnection::stmtInit', - 'MysqlndUhConnection::storeResult', - 'MysqlndUhConnection::useResult', - 'PDF_new', - 'PDO::pgsqlLOBOpen', - 'RarEntry::getStream', - 'SQLite3::openBlob', - 'XMLWriter::openMemory', - 'XMLWriter::openURI', - 'ZipArchive::getStream', - 'bbcode_create', - 'bzopen', - 'crack_opendict', - 'cubrid_connect', - 'cubrid_connect_with_url', - 'cubrid_get_query_timeout', - 'cubrid_lob2_bind', - 'cubrid_lob2_close', - 'cubrid_lob2_export', - 'cubrid_lob2_import', - 'cubrid_lob2_new', - 'cubrid_lob2_read', - 'cubrid_lob2_seek', - 'cubrid_lob2_seek64', - 'cubrid_lob2_size', - 'cubrid_lob2_size64', - 'cubrid_lob2_tell', - 'cubrid_lob2_tell64', - 'cubrid_lob2_write', - 'cubrid_pconnect', - 'cubrid_pconnect_with_url', - 'cubrid_prepare', - 'cubrid_query', - 'cubrid_set_query_timeout', - 'cubrid_unbuffered_query', - 'curl_copy_handle', - 'curl_getinfo', - 'curl_init', - 'curl_multi_add_handle', - 'curl_multi_close', - 'curl_multi_exec', - 'curl_multi_getcontent', - 'curl_multi_info_read', - 'curl_multi_init', - 'curl_multi_remove_handle', - 'curl_multi_select', - 'curl_multi_setopt', - 'curl_pause', - 'curl_reset', - 'curl_setopt', - 'curl_setopt_array', - 'curl_share_close', - 'curl_share_init', - 'curl_share_setopt', - 'curl_unescape', - 'cyrus_connect', - 'db2_column_privileges', - 'db2_columns', - 'db2_connect', - 'db2_exec', - 'db2_foreign_keys', - 'db2_next_result', - 'db2_pconnect', - 'db2_prepare', - 'db2_primary_keys', - 'db2_procedure_columns', - 'db2_procedures', - 'db2_special_columns', - 'db2_statistics', - 'db2_table_privileges', - 'db2_tables', - 'dba_fetch', - 'dba_fetch 1', - 'dba_open', - 'dba_popen', - 'dbplus_aql', - 'dbplus_open', - 'dbplus_rcreate', - 'dbplus_ropen', - 'dbplus_rquery', - 'dbplus_sql', - 'deflate_init', - 'dio_open', - 'eio_busy', - 'eio_cancel', - 'eio_chmod', - 'eio_chown', - 'eio_close', - 'eio_custom', - 'eio_dup2', - 'eio_fallocate', - 'eio_fchmod', - 'eio_fchown', - 'eio_fdatasync', - 'eio_fstat', - 'eio_fstatvfs', - 'eio_fsync', - 'eio_ftruncate', - 'eio_futime', - 'eio_get_last_error', - 'eio_grp', - 'eio_grp_add', - 'eio_grp_cancel', - 'eio_grp_limit', - 'eio_link', - 'eio_lstat', - 'eio_mkdir', - 'eio_mknod', - 'eio_nop', - 'eio_open', - 'eio_read', - 'eio_readahead', - 'eio_readdir', - 'eio_readlink', - 'eio_realpath', - 'eio_rename', - 'eio_rmdir', - 'eio_seek', - 'eio_sendfile', - 'eio_stat', - 'eio_statvfs', - 'eio_symlink', - 'eio_sync', - 'eio_sync_file_range', - 'eio_syncfs', - 'eio_truncate', - 'eio_unlink', - 'eio_utime', - 'eio_write', - 'enchant_broker_free_dict', - 'enchant_broker_init', - 'enchant_broker_request_dict', - 'enchant_broker_request_pwl_dict', - 'event_base_new', - 'event_base_reinit', - 'event_buffer_new', - 'event_new', - 'event_priority_set', - 'event_timer_set', - 'expect_popen', - 'fam_monitor_collection', - 'fam_monitor_directory', - 'fam_monitor_file', - 'fam_open', - 'fann_cascadetrain_on_data', - 'fann_cascadetrain_on_file', - 'fann_clear_scaling_params', - 'fann_copy', - 'fann_create_from_file', - 'fann_create_shortcut_array', - 'fann_create_standard', - 'fann_create_standard_array', - 'fann_create_train', - 'fann_create_train_from_callback', - 'fann_descale_input', - 'fann_descale_output', - 'fann_descale_train', - 'fann_destroy', - 'fann_destroy_train', - 'fann_duplicate_train_data', - 'fann_get_MSE', - 'fann_get_activation_function', - 'fann_get_activation_steepness', - 'fann_get_bias_array', - 'fann_get_bit_fail', - 'fann_get_bit_fail_limit', - 'fann_get_cascade_activation_functions', - 'fann_get_cascade_activation_functions_count', - 'fann_get_cascade_activation_steepnesses', - 'fann_get_cascade_activation_steepnesses_count', - 'fann_get_cascade_candidate_change_fraction', - 'fann_get_cascade_candidate_limit', - 'fann_get_cascade_candidate_stagnation_epochs', - 'fann_get_cascade_max_cand_epochs', - 'fann_get_cascade_max_out_epochs', - 'fann_get_cascade_min_cand_epochs', - 'fann_get_cascade_min_out_epochs', - 'fann_get_cascade_num_candidate_groups', - 'fann_get_cascade_num_candidates', - 'fann_get_cascade_output_change_fraction', - 'fann_get_cascade_output_stagnation_epochs', - 'fann_get_cascade_weight_multiplier', - 'fann_get_connection_array', - 'fann_get_connection_rate', - 'fann_get_errno', - 'fann_get_errstr', - 'fann_get_layer_array', - 'fann_get_learning_momentum', - 'fann_get_learning_rate', - 'fann_get_network_type', - 'fann_get_num_input', - 'fann_get_num_layers', - 'fann_get_num_output', - 'fann_get_quickprop_decay', - 'fann_get_quickprop_mu', - 'fann_get_rprop_decrease_factor', - 'fann_get_rprop_delta_max', - 'fann_get_rprop_delta_min', - 'fann_get_rprop_delta_zero', - 'fann_get_rprop_increase_factor', - 'fann_get_sarprop_step_error_shift', - 'fann_get_sarprop_step_error_threshold_factor', - 'fann_get_sarprop_temperature', - 'fann_get_sarprop_weight_decay_shift', - 'fann_get_total_connections', - 'fann_get_total_neurons', - 'fann_get_train_error_function', - 'fann_get_train_stop_function', - 'fann_get_training_algorithm', - 'fann_init_weights', - 'fann_length_train_data', - 'fann_merge_train_data', - 'fann_num_input_train_data', - 'fann_num_output_train_data', - 'fann_randomize_weights', - 'fann_read_train_from_file', - 'fann_reset_errno', - 'fann_reset_errstr', - 'fann_run', - 'fann_save', - 'fann_save_train', - 'fann_scale_input', - 'fann_scale_input_train_data', - 'fann_scale_output', - 'fann_scale_output_train_data', - 'fann_scale_train', - 'fann_scale_train_data', - 'fann_set_activation_function', - 'fann_set_activation_function_hidden', - 'fann_set_activation_function_layer', - 'fann_set_activation_function_output', - 'fann_set_activation_steepness', - 'fann_set_activation_steepness_hidden', - 'fann_set_activation_steepness_layer', - 'fann_set_activation_steepness_output', - 'fann_set_bit_fail_limit', - 'fann_set_callback', - 'fann_set_cascade_activation_functions', - 'fann_set_cascade_activation_steepnesses', - 'fann_set_cascade_candidate_change_fraction', - 'fann_set_cascade_candidate_limit', - 'fann_set_cascade_candidate_stagnation_epochs', - 'fann_set_cascade_max_cand_epochs', - 'fann_set_cascade_max_out_epochs', - 'fann_set_cascade_min_cand_epochs', - 'fann_set_cascade_min_out_epochs', - 'fann_set_cascade_num_candidate_groups', - 'fann_set_cascade_output_change_fraction', - 'fann_set_cascade_output_stagnation_epochs', - 'fann_set_cascade_weight_multiplier', - 'fann_set_error_log', - 'fann_set_input_scaling_params', - 'fann_set_learning_momentum', - 'fann_set_learning_rate', - 'fann_set_output_scaling_params', - 'fann_set_quickprop_decay', - 'fann_set_quickprop_mu', - 'fann_set_rprop_decrease_factor', - 'fann_set_rprop_delta_max', - 'fann_set_rprop_delta_min', - 'fann_set_rprop_delta_zero', - 'fann_set_rprop_increase_factor', - 'fann_set_sarprop_step_error_shift', - 'fann_set_sarprop_step_error_threshold_factor', - 'fann_set_sarprop_temperature', - 'fann_set_sarprop_weight_decay_shift', - 'fann_set_scaling_params', - 'fann_set_train_error_function', - 'fann_set_train_stop_function', - 'fann_set_training_algorithm', - 'fann_set_weight', - 'fann_set_weight_array', - 'fann_shuffle_train_data', - 'fann_subset_train_data', - 'fann_test', - 'fann_test_data', - 'fann_train', - 'fann_train_epoch', - 'fann_train_on_data', - 'fann_train_on_file', - 'fbsql_connect', - 'fbsql_db_query', - 'fbsql_list_dbs', - 'fbsql_list_fields', - 'fbsql_list_tables', - 'fbsql_pconnect', - 'fbsql_query', - 'fdf_create', - 'fdf_open', - 'fdf_open_string', - 'finfo::buffer', - 'finfo_buffer', - 'finfo_close', - 'finfo_file', - 'finfo_open', - 'finfo_set_flags', - 'fopen', - 'fsockopen', - 'ftp_alloc', - 'ftp_cdup', - 'ftp_chdir', - 'ftp_chmod', - 'ftp_close', - 'ftp_connect', - 'ftp_delete', - 'ftp_exec', - 'ftp_fget', - 'ftp_fput', - 'ftp_get', - 'ftp_get_option', - 'ftp_login', - 'ftp_mdtm', - 'ftp_mkdir', - 'ftp_nb_continue', - 'ftp_nb_fget', - 'ftp_nb_fput', - 'ftp_nb_get', - 'ftp_nb_put', - 'ftp_nlist', - 'ftp_pasv', - 'ftp_put', - 'ftp_pwd', - 'ftp_raw', - 'ftp_rawlist', - 'ftp_rename', - 'ftp_rmdir', - 'ftp_set_option', - 'ftp_site', - 'ftp_size', - 'ftp_ssl_connect', - 'ftp_systype', - 'gnupg_init', - 'gupnp_context_new', - 'gupnp_control_point_new', - 'gupnp_device_info_get_service', - 'gupnp_root_device_new', - 'gzopen', - 'hash_copy', - 'hash_final', - 'hash_init', - 'hash_update', - 'hash_update_file', - 'hash_update_stream', - 'http_get_request_body_stream', - 'ibase_blob_create', - 'ibase_blob_open', - 'ibase_blob_open 1', - 'ibase_connect', - 'ibase_pconnect', - 'ibase_prepare', - 'ibase_service_attach', - 'ibase_set_event_handler', - 'ibase_set_event_handler 1', - 'ibase_trans', - 'ifx_connect', - 'ifx_pconnect', - 'ifx_prepare', - 'ifx_query', - 'imageaffine', - 'imageconvolution', - 'imagecreate', - 'imagecreatefromgd', - 'imagecreatefromgd2', - 'imagecreatefromgd2part', - 'imagecreatefromgif', - 'imagecreatefromjpeg', - 'imagecreatefrompng', - 'imagecreatefromstring', - 'imagecreatefromwbmp', - 'imagecreatefromwebp', - 'imagecreatefromxbm', - 'imagecreatefromxpm', - 'imagecreatetruecolor', - 'imagegrabscreen', - 'imagegrabwindow', - 'imagepalettetotruecolor', - 'imagepsloadfont', - 'imagerotate', - 'imagescale', - 'imap_open', - 'inflate_init', - 'ingres_connect', - 'ingres_pconnect', - 'inotify_init', - 'kadm5_init_with_password', - 'ldap_connect', - 'ldap_first_entry', - 'ldap_first_reference', - 'ldap_list', - 'ldap_next_entry', - 'ldap_next_reference', - 'ldap_read', - 'ldap_search', - 'm_initconn', - 'mailparse_msg_create', - 'mailparse_msg_get_part', - 'mailparse_msg_parse_file', - 'maxdb::use_result', - 'maxdb_connect', - 'maxdb_embedded_connect', - 'maxdb_init', - 'maxdb_stmt::result_metadata', - 'maxdb_stmt_result_metadata', - 'maxdb_use_result', - 'mcrypt_module_open', - 'msg_get_queue', - 'msql_connect', - 'msql_db_query', - 'msql_list_dbs', - 'msql_list_fields', - 'msql_list_tables', - 'msql_pconnect', - 'msql_query', - 'mssql_connect', - 'mssql_init', - 'mssql_pconnect', - 'mysql_connect', - 'mysql_db_query', - 'mysql_list_dbs', - 'mysql_list_fields', - 'mysql_list_processes', - 'mysql_list_tables', - 'mysql_pconnect', - 'mysql_query', - 'mysql_unbuffered_query', - 'mysqlnd_uh_convert_to_mysqlnd', - 'ncurses_new_panel', - 'ncurses_newpad', - 'ncurses_newwin', - 'ncurses_panel_above', - 'ncurses_panel_below', - 'ncurses_panel_window', - 'newt_button', - 'newt_button_bar', - 'newt_checkbox', - 'newt_checkbox_tree', - 'newt_checkbox_tree_multi', - 'newt_compact_button', - 'newt_create_grid', - 'newt_entry', - 'newt_form', - 'newt_form_get_current', - 'newt_grid_basic_window', - 'newt_grid_h_close_stacked', - 'newt_grid_h_stacked', - 'newt_grid_simple_window', - 'newt_grid_v_close_stacked', - 'newt_grid_v_stacked', - 'newt_label', - 'newt_listbox', - 'newt_listitem', - 'newt_radio_get_current', - 'newt_radiobutton', - 'newt_run_form', - 'newt_scale', - 'newt_textbox', - 'newt_textbox_reflowed', - 'newt_vertical_scrollbar', - 'oci_connect', - 'oci_get_implicit_resultset', - 'oci_new_connect', - 'oci_new_cursor', - 'oci_parse', - 'oci_pconnect', - 'odbc_columnprivileges', - 'odbc_columns', - 'odbc_connect', - 'odbc_exec', - 'odbc_foreignkeys', - 'odbc_gettypeinfo', - 'odbc_pconnect', - 'odbc_prepare', - 'odbc_primarykeys', - 'odbc_procedurecolumns', - 'odbc_procedures', - 'odbc_specialcolumns', - 'odbc_statistics', - 'odbc_tableprivileges', - 'odbc_tables', - 'openal_buffer_create', - 'openal_context_create', - 'openal_device_open', - 'openal_source_create', - 'openal_stream', - 'openssl_csr_new', - 'openssl_csr_sign', - 'openssl_pkey_get_private', - 'openssl_pkey_get_public', - 'openssl_pkey_new', - 'openssl_x509_read', - 'pfsockopen', - 'pg_cancel_query', - 'pg_client_encoding', - 'pg_close', - 'pg_connect', - 'pg_connect_poll', - 'pg_connection_busy', - 'pg_connection_reset', - 'pg_connection_status', - 'pg_consume_input', - 'pg_copy_from', - 'pg_copy_to', - 'pg_dbname', - 'pg_end_copy', - 'pg_escape_bytea', - 'pg_escape_identifier', - 'pg_escape_identifier 1', - 'pg_escape_literal', - 'pg_escape_string', - 'pg_execute', - 'pg_execute 1', - 'pg_flush', - 'pg_free_result', - 'pg_get_notify', - 'pg_get_pid', - 'pg_get_result', - 'pg_host', - 'pg_last_error', - 'pg_last_notice', - 'pg_lo_create', - 'pg_lo_export', - 'pg_lo_import', - 'pg_lo_open', - 'pg_lo_unlink', - 'pg_options', - 'pg_parameter_status', - 'pg_pconnect', - 'pg_ping', - 'pg_port', - 'pg_prepare', - 'pg_prepare 1', - 'pg_put_line', - 'pg_query', - 'pg_query 1', - 'pg_query_params', - 'pg_query_params 1', - 'pg_send_execute', - 'pg_send_prepare', - 'pg_send_query', - 'pg_send_query_params', - 'pg_set_client_encoding', - 'pg_set_client_encoding 1', - 'pg_set_error_verbosity', - 'pg_socket', - 'pg_trace', - 'pg_transaction_status', - 'pg_tty', - 'pg_untrace', - 'pg_version', - 'php_user_filter::filter', - 'popen', - 'proc_open', - 'ps_new', - 'px_new', - 'radius_acct_open', - 'radius_auth_open', - 'radius_salt_encrypt_attr', - 'rpm_open', - 'sem_get', - 'shm_attach', - 'socket_accept', - 'socket_create', - 'socket_create_listen', - 'socket_recvmsg', - 'socket_sendmsg', - 'sqlite_open', - 'sqlite_popen', - 'sqlsrv_begin_transaction', - 'sqlsrv_cancel', - 'sqlsrv_client_info', - 'sqlsrv_close', - 'sqlsrv_commit', - 'sqlsrv_connect', - 'sqlsrv_execute', - 'sqlsrv_fetch', - 'sqlsrv_fetch_array', - 'sqlsrv_fetch_object', - 'sqlsrv_field_metadata', - 'sqlsrv_free_stmt', - 'sqlsrv_get_field', - 'sqlsrv_has_rows', - 'sqlsrv_next_result', - 'sqlsrv_num_fields', - 'sqlsrv_num_rows', - 'sqlsrv_prepare', - 'sqlsrv_query', - 'sqlsrv_rollback', - 'sqlsrv_rows_affected', - 'sqlsrv_send_stream_data', - 'sqlsrv_server_info', - 'ssh2_auth_agent', - 'ssh2_connect', - 'ssh2_exec', - 'ssh2_fetch_stream', - 'ssh2_publickey_init', - 'ssh2_sftp', - 'ssh2_sftp_chmod', - 'ssh2_shell', - 'ssh2_tunnel', - 'stomp_connect', - 'streamWrapper::stream_cast', - 'stream_bucket_new', - 'stream_context_create', - 'stream_context_get_default', - 'stream_context_set_default', - 'stream_filter_append', - 'stream_filter_prepend', - 'stream_socket_accept', - 'stream_socket_client', - 'stream_socket_server', - 'svn_fs_apply_text', - 'svn_fs_begin_txn2', - 'svn_fs_file_contents', - 'svn_fs_revision_root', - 'svn_fs_txn_root', - 'svn_repos_create', - 'svn_repos_fs', - 'svn_repos_fs_begin_txn_for_commit', - 'svn_repos_open', - 'sybase_connect', - 'sybase_pconnect', - 'sybase_unbuffered_query', - 'tmpfile', - 'udm_alloc_agent', - 'udm_alloc_agent_array', - 'udm_find', - 'unlink', - 'w32api_init_dtype', - 'wddx_packet_start', - 'xml_parser_create', - 'xml_parser_create_ns', - 'xml_parser_free', - 'xml_parser_get_option', - 'xml_parser_set_option', - 'xmlrpc_server_create', - 'xmlwriter_open_memory', - 'xmlwriter_open_uri', - 'xslt_create', - 'zip_open', - 'zip_read', - ]; - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Utility methods. - * - * @since Class available since Release 1.0.0 - */ -class PHP_CodeCoverage_Util -{ - /** - * @param float $a - * @param float $b - * @param bool $asString - * @param bool $fixedWidth - * @return float|int|string - */ - public static function percent($a, $b, $asString = false, $fixedWidth = false) - { - if ($asString && $b == 0) { - return ''; - } - - if ($b > 0) { - $percent = ($a / $b) * 100; - } else { - $percent = 100; - } - - if ($asString) { - if ($fixedWidth) { - return sprintf('%6.2F%%', $percent); - } - - return sprintf('%01.2F%%', $percent); - } else { - return $percent; - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use SebastianBergmann\Environment\Runtime; - -/** - * Base class for PHP_CodeCoverage_Report_Node renderers. - * - * @since Class available since Release 1.1.0 - */ -abstract class PHP_CodeCoverage_Report_HTML_Renderer -{ - /** - * @var string - */ - protected $templatePath; - - /** - * @var string - */ - protected $generator; - - /** - * @var string - */ - protected $date; - - /** - * @var int - */ - protected $lowUpperBound; - - /** - * @var int - */ - protected $highLowerBound; - - /** - * @var string - */ - protected $version; - - /** - * Constructor. - * - * @param string $templatePath - * @param string $generator - * @param string $date - * @param int $lowUpperBound - * @param int $highLowerBound - */ - public function __construct($templatePath, $generator, $date, $lowUpperBound, $highLowerBound) - { - $version = new SebastianBergmann\Version('3.2.1', dirname(dirname(dirname(dirname(__DIR__))))); - - $this->templatePath = $templatePath; - $this->generator = $generator; - $this->date = $date; - $this->lowUpperBound = $lowUpperBound; - $this->highLowerBound = $highLowerBound; - $this->version = $version->getVersion(); - } - - /** - * @param Text_Template $template - * @param array $data - * @return string - */ - protected function renderItemTemplate(Text_Template $template, array $data) - { - $numSeparator = ' / '; - - if (isset($data['numClasses']) && $data['numClasses'] > 0) { - $classesLevel = $this->getColorLevel($data['testedClassesPercent']); - - $classesNumber = $data['numTestedClasses'] . $numSeparator . - $data['numClasses']; - - $classesBar = $this->getCoverageBar( - $data['testedClassesPercent'] - ); - } else { - $classesLevel = 'success'; - $classesNumber = '0' . $numSeparator . '0'; - $classesBar = $this->getCoverageBar(100); - } - - if ($data['numMethods'] > 0) { - $methodsLevel = $this->getColorLevel($data['testedMethodsPercent']); - - $methodsNumber = $data['numTestedMethods'] . $numSeparator . - $data['numMethods']; - - $methodsBar = $this->getCoverageBar( - $data['testedMethodsPercent'] - ); - } else { - $methodsLevel = 'success'; - $methodsNumber = '0' . $numSeparator . '0'; - $methodsBar = $this->getCoverageBar(100); - $data['testedMethodsPercentAsString'] = '100.00%'; - } - - if ($data['numExecutableLines'] > 0) { - $linesLevel = $this->getColorLevel($data['linesExecutedPercent']); - - $linesNumber = $data['numExecutedLines'] . $numSeparator . - $data['numExecutableLines']; - - $linesBar = $this->getCoverageBar( - $data['linesExecutedPercent'] - ); - } else { - $linesLevel = 'success'; - $linesNumber = '0' . $numSeparator . '0'; - $linesBar = $this->getCoverageBar(100); - $data['linesExecutedPercentAsString'] = '100.00%'; - } - - $template->setVar( - [ - 'icon' => isset($data['icon']) ? $data['icon'] : '', - 'crap' => isset($data['crap']) ? $data['crap'] : '', - 'name' => $data['name'], - 'lines_bar' => $linesBar, - 'lines_executed_percent' => $data['linesExecutedPercentAsString'], - 'lines_level' => $linesLevel, - 'lines_number' => $linesNumber, - 'methods_bar' => $methodsBar, - 'methods_tested_percent' => $data['testedMethodsPercentAsString'], - 'methods_level' => $methodsLevel, - 'methods_number' => $methodsNumber, - 'classes_bar' => $classesBar, - 'classes_tested_percent' => isset($data['testedClassesPercentAsString']) ? $data['testedClassesPercentAsString'] : '', - 'classes_level' => $classesLevel, - 'classes_number' => $classesNumber - ] - ); - - return $template->render(); - } - - /** - * @param Text_Template $template - * @param PHP_CodeCoverage_Report_Node $node - */ - protected function setCommonTemplateVariables(Text_Template $template, PHP_CodeCoverage_Report_Node $node) - { - $runtime = new Runtime; - - $template->setVar( - [ - 'id' => $node->getId(), - 'full_path' => $node->getPath(), - 'path_to_root' => $this->getPathToRoot($node), - 'breadcrumbs' => $this->getBreadcrumbs($node), - 'date' => $this->date, - 'version' => $this->version, - 'runtime_name' => $runtime->getName(), - 'runtime_version' => $runtime->getVersion(), - 'runtime_link' => $runtime->getVendorUrl(), - 'generator' => $this->generator, - 'low_upper_bound' => $this->lowUpperBound, - 'high_lower_bound' => $this->highLowerBound - ] - ); - } - - protected function getBreadcrumbs(PHP_CodeCoverage_Report_Node $node) - { - $breadcrumbs = ''; - $path = $node->getPathAsArray(); - $pathToRoot = []; - $max = count($path); - - if ($node instanceof PHP_CodeCoverage_Report_Node_File) { - $max--; - } - - for ($i = 0; $i < $max; $i++) { - $pathToRoot[] = str_repeat('../', $i); - } - - foreach ($path as $step) { - if ($step !== $node) { - $breadcrumbs .= $this->getInactiveBreadcrumb( - $step, - array_pop($pathToRoot) - ); - } else { - $breadcrumbs .= $this->getActiveBreadcrumb($step); - } - } - - return $breadcrumbs; - } - - protected function getActiveBreadcrumb(PHP_CodeCoverage_Report_Node $node) - { - $buffer = sprintf( - '
  • %s
  • ' . "\n", - $node->getName() - ); - - if ($node instanceof PHP_CodeCoverage_Report_Node_Directory) { - $buffer .= '
  • (Dashboard)
  • ' . "\n"; - } - - return $buffer; - } - - protected function getInactiveBreadcrumb(PHP_CodeCoverage_Report_Node $node, $pathToRoot) - { - return sprintf( - '
  • %s
  • ' . "\n", - $pathToRoot, - $node->getName() - ); - } - - protected function getPathToRoot(PHP_CodeCoverage_Report_Node $node) - { - $id = $node->getId(); - $depth = substr_count($id, '/'); - - if ($id != 'index' && - $node instanceof PHP_CodeCoverage_Report_Node_Directory) { - $depth++; - } - - return str_repeat('../', $depth); - } - - protected function getCoverageBar($percent) - { - $level = $this->getColorLevel($percent); - - $template = new Text_Template( - $this->templatePath . 'coverage_bar.html', - '{{', - '}}' - ); - - $template->setVar(['level' => $level, 'percent' => sprintf('%.2F', $percent)]); - - return $template->render(); - } - - /** - * @param int $percent - * @return string - */ - protected function getColorLevel($percent) - { - if ($percent <= $this->lowUpperBound) { - return 'danger'; - } elseif ($percent > $this->lowUpperBound && - $percent < $this->highLowerBound) { - return 'warning'; - } else { - return 'success'; - } - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Renders the dashboard for a PHP_CodeCoverage_Report_Node_Directory node. - * - * @since Class available since Release 1.1.0 - */ -class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_Report_HTML_Renderer -{ - /** - * @param PHP_CodeCoverage_Report_Node_Directory $node - * @param string $file - */ - public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file) - { - $classes = $node->getClassesAndTraits(); - $template = new Text_Template( - $this->templatePath . 'dashboard.html', - '{{', - '}}' - ); - - $this->setCommonTemplateVariables($template, $node); - - $baseLink = $node->getId() . '/'; - $complexity = $this->complexity($classes, $baseLink); - $coverageDistribution = $this->coverageDistribution($classes); - $insufficientCoverage = $this->insufficientCoverage($classes, $baseLink); - $projectRisks = $this->projectRisks($classes, $baseLink); - - $template->setVar( - [ - 'insufficient_coverage_classes' => $insufficientCoverage['class'], - 'insufficient_coverage_methods' => $insufficientCoverage['method'], - 'project_risks_classes' => $projectRisks['class'], - 'project_risks_methods' => $projectRisks['method'], - 'complexity_class' => $complexity['class'], - 'complexity_method' => $complexity['method'], - 'class_coverage_distribution' => $coverageDistribution['class'], - 'method_coverage_distribution' => $coverageDistribution['method'] - ] - ); - - $template->renderTo($file); - } - - /** - * Returns the data for the Class/Method Complexity charts. - * - * @param array $classes - * @param string $baseLink - * @return array - */ - protected function complexity(array $classes, $baseLink) - { - $result = ['class' => [], 'method' => []]; - - foreach ($classes as $className => $class) { - foreach ($class['methods'] as $methodName => $method) { - if ($className != '*') { - $methodName = $className . '::' . $methodName; - } - - $result['method'][] = [ - $method['coverage'], - $method['ccn'], - sprintf( - '%s', - str_replace($baseLink, '', $method['link']), - $methodName - ) - ]; - } - - $result['class'][] = [ - $class['coverage'], - $class['ccn'], - sprintf( - '%s', - str_replace($baseLink, '', $class['link']), - $className - ) - ]; - } - - return [ - 'class' => json_encode($result['class']), - 'method' => json_encode($result['method']) - ]; - } - - /** - * Returns the data for the Class / Method Coverage Distribution chart. - * - * @param array $classes - * @return array - */ - protected function coverageDistribution(array $classes) - { - $result = [ - 'class' => [ - '0%' => 0, - '0-10%' => 0, - '10-20%' => 0, - '20-30%' => 0, - '30-40%' => 0, - '40-50%' => 0, - '50-60%' => 0, - '60-70%' => 0, - '70-80%' => 0, - '80-90%' => 0, - '90-100%' => 0, - '100%' => 0 - ], - 'method' => [ - '0%' => 0, - '0-10%' => 0, - '10-20%' => 0, - '20-30%' => 0, - '30-40%' => 0, - '40-50%' => 0, - '50-60%' => 0, - '60-70%' => 0, - '70-80%' => 0, - '80-90%' => 0, - '90-100%' => 0, - '100%' => 0 - ] - ]; - - foreach ($classes as $class) { - foreach ($class['methods'] as $methodName => $method) { - if ($method['coverage'] == 0) { - $result['method']['0%']++; - } elseif ($method['coverage'] == 100) { - $result['method']['100%']++; - } else { - $key = floor($method['coverage'] / 10) * 10; - $key = $key . '-' . ($key + 10) . '%'; - $result['method'][$key]++; - } - } - - if ($class['coverage'] == 0) { - $result['class']['0%']++; - } elseif ($class['coverage'] == 100) { - $result['class']['100%']++; - } else { - $key = floor($class['coverage'] / 10) * 10; - $key = $key . '-' . ($key + 10) . '%'; - $result['class'][$key]++; - } - } - - return [ - 'class' => json_encode(array_values($result['class'])), - 'method' => json_encode(array_values($result['method'])) - ]; - } - - /** - * Returns the classes / methods with insufficient coverage. - * - * @param array $classes - * @param string $baseLink - * @return array - */ - protected function insufficientCoverage(array $classes, $baseLink) - { - $leastTestedClasses = []; - $leastTestedMethods = []; - $result = ['class' => '', 'method' => '']; - - foreach ($classes as $className => $class) { - foreach ($class['methods'] as $methodName => $method) { - if ($method['coverage'] < $this->highLowerBound) { - if ($className != '*') { - $key = $className . '::' . $methodName; - } else { - $key = $methodName; - } - - $leastTestedMethods[$key] = $method['coverage']; - } - } - - if ($class['coverage'] < $this->highLowerBound) { - $leastTestedClasses[$className] = $class['coverage']; - } - } - - asort($leastTestedClasses); - asort($leastTestedMethods); - - foreach ($leastTestedClasses as $className => $coverage) { - $result['class'] .= sprintf( - ' %s%d%%' . "\n", - str_replace($baseLink, '', $classes[$className]['link']), - $className, - $coverage - ); - } - - foreach ($leastTestedMethods as $methodName => $coverage) { - list($class, $method) = explode('::', $methodName); - - $result['method'] .= sprintf( - ' %s%d%%' . "\n", - str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), - $methodName, - $method, - $coverage - ); - } - - return $result; - } - - /** - * Returns the project risks according to the CRAP index. - * - * @param array $classes - * @param string $baseLink - * @return array - */ - protected function projectRisks(array $classes, $baseLink) - { - $classRisks = []; - $methodRisks = []; - $result = ['class' => '', 'method' => '']; - - foreach ($classes as $className => $class) { - foreach ($class['methods'] as $methodName => $method) { - if ($method['coverage'] < $this->highLowerBound && - $method['ccn'] > 1) { - if ($className != '*') { - $key = $className . '::' . $methodName; - } else { - $key = $methodName; - } - - $methodRisks[$key] = $method['crap']; - } - } - - if ($class['coverage'] < $this->highLowerBound && - $class['ccn'] > count($class['methods'])) { - $classRisks[$className] = $class['crap']; - } - } - - arsort($classRisks); - arsort($methodRisks); - - foreach ($classRisks as $className => $crap) { - $result['class'] .= sprintf( - ' %s%d' . "\n", - str_replace($baseLink, '', $classes[$className]['link']), - $className, - $crap - ); - } - - foreach ($methodRisks as $methodName => $crap) { - list($class, $method) = explode('::', $methodName); - - $result['method'] .= sprintf( - ' %s%d' . "\n", - str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), - $methodName, - $method, - $crap - ); - } - - return $result; - } - - protected function getActiveBreadcrumb(PHP_CodeCoverage_Report_Node $node) - { - return sprintf( - '
  • %s
  • ' . "\n" . - '
  • (Dashboard)
  • ' . "\n", - $node->getName() - ); - } -} - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Renders a PHP_CodeCoverage_Report_Node_File node. - * - * @since Class available since Release 1.1.0 - */ -class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report_HTML_Renderer -{ - /** - * @var int - */ - private $htmlspecialcharsFlags; - - /** - * Constructor. - * - * @param string $templatePath - * @param string $generator - * @param string $date - * @param int $lowUpperBound - * @param int $highLowerBound - */ - public function __construct($templatePath, $generator, $date, $lowUpperBound, $highLowerBound) - { - parent::__construct( - $templatePath, - $generator, - $date, - $lowUpperBound, - $highLowerBound - ); - - $this->htmlspecialcharsFlags = ENT_COMPAT; - - $this->htmlspecialcharsFlags = $this->htmlspecialcharsFlags | ENT_HTML401 | ENT_SUBSTITUTE; - } - - /** - * @param PHP_CodeCoverage_Report_Node_File $node - * @param string $file - */ - public function render(PHP_CodeCoverage_Report_Node_File $node, $file) - { - $template = new Text_Template($this->templatePath . 'file.html', '{{', '}}'); - - $template->setVar( - [ - 'items' => $this->renderItems($node), - 'lines' => $this->renderSource($node) - ] - ); - - $this->setCommonTemplateVariables($template, $node); - - $template->renderTo($file); - } - - /** - * @param PHP_CodeCoverage_Report_Node_File $node - * @return string - */ - protected function renderItems(PHP_CodeCoverage_Report_Node_File $node) - { - $template = new Text_Template($this->templatePath . 'file_item.html', '{{', '}}'); - - $methodItemTemplate = new Text_Template( - $this->templatePath . 'method_item.html', - '{{', - '}}' - ); - - $items = $this->renderItemTemplate( - $template, - [ - 'name' => 'Total', - 'numClasses' => $node->getNumClassesAndTraits(), - 'numTestedClasses' => $node->getNumTestedClassesAndTraits(), - 'numMethods' => $node->getNumMethods(), - 'numTestedMethods' => $node->getNumTestedMethods(), - 'linesExecutedPercent' => $node->getLineExecutedPercent(false), - 'linesExecutedPercentAsString' => $node->getLineExecutedPercent(), - 'numExecutedLines' => $node->getNumExecutedLines(), - 'numExecutableLines' => $node->getNumExecutableLines(), - 'testedMethodsPercent' => $node->getTestedMethodsPercent(false), - 'testedMethodsPercentAsString' => $node->getTestedMethodsPercent(), - 'testedClassesPercent' => $node->getTestedClassesAndTraitsPercent(false), - 'testedClassesPercentAsString' => $node->getTestedClassesAndTraitsPercent(), - 'crap' => 'CRAP' - ] - ); - - $items .= $this->renderFunctionItems( - $node->getFunctions(), - $methodItemTemplate - ); - - $items .= $this->renderTraitOrClassItems( - $node->getTraits(), - $template, - $methodItemTemplate - ); - - $items .= $this->renderTraitOrClassItems( - $node->getClasses(), - $template, - $methodItemTemplate - ); - - return $items; - } - - /** - * @param array $items - * @param Text_Template $template - * @param Text_Template $methodItemTemplate - * @return string - */ - protected function renderTraitOrClassItems(array $items, Text_Template $template, Text_Template $methodItemTemplate) - { - if (empty($items)) { - return ''; - } - - $buffer = ''; - - foreach ($items as $name => $item) { - $numMethods = count($item['methods']); - $numTestedMethods = 0; - - foreach ($item['methods'] as $method) { - if ($method['executedLines'] == $method['executableLines']) { - $numTestedMethods++; - } - } - - $buffer .= $this->renderItemTemplate( - $template, - [ - 'name' => $name, - 'numClasses' => 1, - 'numTestedClasses' => $numTestedMethods == $numMethods ? 1 : 0, - 'numMethods' => $numMethods, - 'numTestedMethods' => $numTestedMethods, - 'linesExecutedPercent' => PHP_CodeCoverage_Util::percent( - $item['executedLines'], - $item['executableLines'], - false - ), - 'linesExecutedPercentAsString' => PHP_CodeCoverage_Util::percent( - $item['executedLines'], - $item['executableLines'], - true - ), - 'numExecutedLines' => $item['executedLines'], - 'numExecutableLines' => $item['executableLines'], - 'testedMethodsPercent' => PHP_CodeCoverage_Util::percent( - $numTestedMethods, - $numMethods, - false - ), - 'testedMethodsPercentAsString' => PHP_CodeCoverage_Util::percent( - $numTestedMethods, - $numMethods, - true - ), - 'testedClassesPercent' => PHP_CodeCoverage_Util::percent( - $numTestedMethods == $numMethods ? 1 : 0, - 1, - false - ), - 'testedClassesPercentAsString' => PHP_CodeCoverage_Util::percent( - $numTestedMethods == $numMethods ? 1 : 0, - 1, - true - ), - 'crap' => $item['crap'] - ] - ); - - foreach ($item['methods'] as $method) { - $buffer .= $this->renderFunctionOrMethodItem( - $methodItemTemplate, - $method, - ' ' - ); - } - } - - return $buffer; - } - - /** - * @param array $functions - * @param Text_Template $template - * @return string - */ - protected function renderFunctionItems(array $functions, Text_Template $template) - { - if (empty($functions)) { - return ''; - } - - $buffer = ''; - - foreach ($functions as $function) { - $buffer .= $this->renderFunctionOrMethodItem( - $template, - $function - ); - } - - return $buffer; - } - - /** - * @param Text_Template $template - * @return string - */ - protected function renderFunctionOrMethodItem(Text_Template $template, array $item, $indent = '') - { - $numTestedItems = $item['executedLines'] == $item['executableLines'] ? 1 : 0; - - return $this->renderItemTemplate( - $template, - [ - 'name' => sprintf( - '%s%s', - $indent, - $item['startLine'], - htmlspecialchars($item['signature']), - isset($item['functionName']) ? $item['functionName'] : $item['methodName'] - ), - 'numMethods' => 1, - 'numTestedMethods' => $numTestedItems, - 'linesExecutedPercent' => PHP_CodeCoverage_Util::percent( - $item['executedLines'], - $item['executableLines'], - false - ), - 'linesExecutedPercentAsString' => PHP_CodeCoverage_Util::percent( - $item['executedLines'], - $item['executableLines'], - true - ), - 'numExecutedLines' => $item['executedLines'], - 'numExecutableLines' => $item['executableLines'], - 'testedMethodsPercent' => PHP_CodeCoverage_Util::percent( - $numTestedItems, - 1, - false - ), - 'testedMethodsPercentAsString' => PHP_CodeCoverage_Util::percent( - $numTestedItems, - 1, - true - ), - 'crap' => $item['crap'] - ] - ); - } - - /** - * @param PHP_CodeCoverage_Report_Node_File $node - * @return string - */ - protected function renderSource(PHP_CodeCoverage_Report_Node_File $node) - { - $coverageData = $node->getCoverageData(); - $testData = $node->getTestData(); - $codeLines = $this->loadFile($node->getPath()); - $lines = ''; - $i = 1; - - foreach ($codeLines as $line) { - $trClass = ''; - $popoverContent = ''; - $popoverTitle = ''; - - if (array_key_exists($i, $coverageData)) { - $numTests = count($coverageData[$i]); - - if ($coverageData[$i] === null) { - $trClass = ' class="warning"'; - } elseif ($numTests == 0) { - $trClass = ' class="danger"'; - } else { - $lineCss = 'covered-by-large-tests'; - $popoverContent = '
      '; - - if ($numTests > 1) { - $popoverTitle = $numTests . ' tests cover line ' . $i; - } else { - $popoverTitle = '1 test covers line ' . $i; - } - - foreach ($coverageData[$i] as $test) { - if ($lineCss == 'covered-by-large-tests' && $testData[$test]['size'] == 'medium') { - $lineCss = 'covered-by-medium-tests'; - } elseif ($testData[$test]['size'] == 'small') { - $lineCss = 'covered-by-small-tests'; - } - - switch ($testData[$test]['status']) { - case 0: - switch ($testData[$test]['size']) { - case 'small': - $testCSS = ' class="covered-by-small-tests"'; - break; - - case 'medium': - $testCSS = ' class="covered-by-medium-tests"'; - break; - - default: - $testCSS = ' class="covered-by-large-tests"'; - break; - } - break; - - case 1: - case 2: - $testCSS = ' class="warning"'; - break; - - case 3: - $testCSS = ' class="danger"'; - break; - - case 4: - $testCSS = ' class="danger"'; - break; - - default: - $testCSS = ''; - } - - $popoverContent .= sprintf( - '%s', - $testCSS, - htmlspecialchars($test) - ); - } - - $popoverContent .= '
    '; - $trClass = ' class="' . $lineCss . ' popin"'; - } - } - - if (!empty($popoverTitle)) { - $popover = sprintf( - ' data-title="%s" data-content="%s" data-placement="bottom" data-html="true"', - $popoverTitle, - htmlspecialchars($popoverContent) - ); - } else { - $popover = ''; - } - - $lines .= sprintf( - ' %s' . "\n", - $trClass, - $popover, - $i, - $i, - $i, - $line - ); - - $i++; - } - - return $lines; - } - - /** - * @param string $file - * @return array - */ - protected function loadFile($file) - { - $buffer = file_get_contents($file); - $tokens = token_get_all($buffer); - $result = ['']; - $i = 0; - $stringFlag = false; - $fileEndsWithNewLine = substr($buffer, -1) == "\n"; - - unset($buffer); - - foreach ($tokens as $j => $token) { - if (is_string($token)) { - if ($token === '"' && $tokens[$j - 1] !== '\\') { - $result[$i] .= sprintf( - '%s', - htmlspecialchars($token) - ); - - $stringFlag = !$stringFlag; - } else { - $result[$i] .= sprintf( - '%s', - htmlspecialchars($token) - ); - } - - continue; - } - - list($token, $value) = $token; - - $value = str_replace( - ["\t", ' '], - ['    ', ' '], - htmlspecialchars($value, $this->htmlspecialcharsFlags) - ); - - if ($value === "\n") { - $result[++$i] = ''; - } else { - $lines = explode("\n", $value); - - foreach ($lines as $jj => $line) { - $line = trim($line); - - if ($line !== '') { - if ($stringFlag) { - $colour = 'string'; - } else { - switch ($token) { - case T_INLINE_HTML: - $colour = 'html'; - break; - - case T_COMMENT: - case T_DOC_COMMENT: - $colour = 'comment'; - break; - - case T_ABSTRACT: - case T_ARRAY: - case T_AS: - case T_BREAK: - case T_CALLABLE: - case T_CASE: - case T_CATCH: - case T_CLASS: - case T_CLONE: - case T_CONTINUE: - case T_DEFAULT: - case T_ECHO: - case T_ELSE: - case T_ELSEIF: - case T_EMPTY: - case T_ENDDECLARE: - case T_ENDFOR: - case T_ENDFOREACH: - case T_ENDIF: - case T_ENDSWITCH: - case T_ENDWHILE: - case T_EXIT: - case T_EXTENDS: - case T_FINAL: - case T_FINALLY: - case T_FOREACH: - case T_FUNCTION: - case T_GLOBAL: - case T_IF: - case T_IMPLEMENTS: - case T_INCLUDE: - case T_INCLUDE_ONCE: - case T_INSTANCEOF: - case T_INSTEADOF: - case T_INTERFACE: - case T_ISSET: - case T_LOGICAL_AND: - case T_LOGICAL_OR: - case T_LOGICAL_XOR: - case T_NAMESPACE: - case T_NEW: - case T_PRIVATE: - case T_PROTECTED: - case T_PUBLIC: - case T_REQUIRE: - case T_REQUIRE_ONCE: - case T_RETURN: - case T_STATIC: - case T_THROW: - case T_TRAIT: - case T_TRY: - case T_UNSET: - case T_USE: - case T_VAR: - case T_WHILE: - case T_YIELD: - $colour = 'keyword'; - break; - - default: - $colour = 'default'; - } - } - - $result[$i] .= sprintf( - '%s', - $colour, - $line - ); - } - - if (isset($lines[$jj + 1])) { - $result[++$i] = ''; - } - } - } - } - - if ($fileEndsWithNewLine) { - unset($result[count($result)-1]); - } - - return $result; - } -} - - - - - Dashboard for {{full_path}} - - - - - - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -

    Classes

    -
    -
    -
    -
    -

    Coverage Distribution

    -
    - -
    -
    -
    -

    Complexity

    -
    - -
    -
    -
    -
    -
    -

    Insufficient Coverage

    -
    - - - - - - - - -{{insufficient_coverage_classes}} - -
    ClassCoverage
    -
    -
    -
    -

    Project Risks

    -
    - - - - - - - - -{{project_risks_classes}} - -
    ClassCRAP
    -
    -
    -
    -
    -
    -

    Methods

    -
    -
    -
    -
    -

    Coverage Distribution

    -
    - -
    -
    -
    -

    Complexity

    -
    - -
    -
    -
    -
    -
    -

    Insufficient Coverage

    -
    - - - - - - - - -{{insufficient_coverage_methods}} - -
    MethodCoverage
    -
    -
    -
    -

    Project Risks

    -
    - - - - - - - - -{{project_risks_methods}} - -
    MethodCRAP
    -
    -
    -
    - -
    - - - - - - - - - - - - - Code Coverage for {{full_path}} - - - - - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    - - - - - - - - - - - - - - -{{items}} - -
     
    Code Coverage
     
    Lines
    Functions and Methods
    Classes and Traits
    - -
    - - - - - -
    -
    - {{percent}}% covered ({{level}}) -
    -
    -/*! - * Bootstrap v3.3.4 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.4",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.4",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.4",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.4",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.4",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport),this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c&&c.$tip&&c.$tip.is(":visible")?void(c.hoverState="in"):(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.options.container?a(this.options.container):this.$element.parent(),p=this.getPosition(o);h="bottom"==h&&k.bottom+m>p.bottom?"top":"top"==h&&k.top-mp.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type)})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.4",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.4",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.4",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=a(document.body).height();"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);!function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:0/0}function r(n){return null===n?0/0:+n}function u(n){return!isNaN(n)}function i(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function c(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function l(){this._=Object.create(null)}function s(n){return(n+="")===pa||n[0]===va?va+n:n}function f(n){return(n+="")[0]===va?n.slice(1):n}function h(n){return s(n)in this._}function g(n){return(n=s(n))in this._&&delete this._[n]}function p(){var n=[];for(var t in this._)n.push(f(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function m(){this._=Object.create(null)}function y(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=da.length;r>e;++e){var u=da[e]+t;if(u in n)return u}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,u=-1,i=r.length;++ue;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function Z(n){return ya(n,Sa),n}function V(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t0&&(n=n.slice(0,a));var l=ka.get(n);return l&&(n=l,c=B),a?t?u:r:t?b:i}function $(n,t){return function(e){var r=ta.event;ta.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ta.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Aa,u="click"+r,i=ta.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ea&&(Ea="onselectstart"in e?!1:x(e.style,"userSelect")),Ea){var o=n(e).style,a=o[Ea];o[Ea]="none"}return function(n){if(i.on(r,null),Ea&&(o[Ea]=a),n){var t=function(){i.on(u,null)};i.on(u,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var u=r.createSVGPoint();if(0>Na){var i=t(n);if(i.scrollX||i.scrollY){r=ta.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Na=!(o.f||o.e),r.remove()}}return Na?(u.x=e.pageX,u.y=e.pageY):(u.x=e.clientX,u.y=e.clientY),u=u.matrixTransform(n.getScreenCTM().inverse()),[u.x,u.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ta.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nt(n){return n>1?0:-1>n?qa:Math.acos(n)}function tt(n){return n>1?Ra:-1>n?-Ra:Math.asin(n)}function et(n){return((n=Math.exp(n))-1/n)/2}function rt(n){return((n=Math.exp(n))+1/n)/2}function ut(n){return((n=Math.exp(2*n))-1)/(n+1)}function it(n){return(n=Math.sin(n/2))*n}function ot(){}function at(n,t,e){return this instanceof at?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof at?new at(n.h,n.s,n.l):bt(""+n,_t,at):new at(n,t,e)}function ct(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,new mt(u(n+120),u(n),u(n-120))}function lt(n,t,e){return this instanceof lt?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof lt?new lt(n.h,n.c,n.l):n instanceof ft?gt(n.l,n.a,n.b):gt((n=wt((n=ta.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new lt(n,t,e)}function st(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new ft(e,Math.cos(n*=Da)*t,Math.sin(n)*t)}function ft(n,t,e){return this instanceof ft?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof ft?new ft(n.l,n.a,n.b):n instanceof lt?st(n.h,n.c,n.l):wt((n=mt(n)).r,n.g,n.b):new ft(n,t,e)}function ht(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=pt(u)*Xa,r=pt(r)*$a,i=pt(i)*Ba,new mt(dt(3.2404542*u-1.5371385*r-.4985314*i),dt(-.969266*u+1.8760108*r+.041556*i),dt(.0556434*u-.2040259*r+1.0572252*i))}function gt(n,t,e){return n>0?new lt(Math.atan2(e,t)*Pa,Math.sqrt(t*t+e*e),n):new lt(0/0,0/0,n)}function pt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function vt(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function dt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mt(n,t,e){return this instanceof mt?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mt?new mt(n.r,n.g,n.b):bt(""+n,mt,ct):new mt(n,t,e)}function yt(n){return new mt(n>>16,n>>8&255,255&n)}function Mt(n){return yt(n)+""}function xt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function bt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(kt(u[0]),kt(u[1]),kt(u[2]))}return(i=Ga.get(n.toLowerCase()))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&i)>>4,o=o>>4|o,a=240&i,a=a>>4|a,c=15&i,c=c<<4|c):7===n.length&&(o=(16711680&i)>>16,a=(65280&i)>>8,c=255&i)),t(o,a,c))}function _t(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),new at(r,u,c)}function wt(n,t,e){n=St(n),t=St(t),e=St(e);var r=vt((.4124564*n+.3575761*t+.1804375*e)/Xa),u=vt((.2126729*n+.7151522*t+.072175*e)/$a),i=vt((.0193339*n+.119192*t+.9503041*e)/Ba);return ft(116*u-16,500*(r-u),200*(u-i))}function St(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function kt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function Et(n){return"function"==typeof n?n:function(){return n}}function At(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Nt(t,e,n,r)}}function Nt(n,t,e,r){function u(){var n,t=c.status;if(!t&&zt(c)||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return void o.error.call(i,r)}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=ta.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,l=null;return!this.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=ta.event;ta.event=n;try{o.progress.call(i,c)}finally{ta.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(l=n,i):l},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(ra(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var s in a)c.setRequestHeader(s,a[s]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=l&&(c.responseType=l),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},ta.rebind(i,o,"on"),null==r?i:i.get(Ct(r))}function Ct(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function zt(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qt(){var n=Lt(),t=Tt()-n;t>24?(isFinite(t)&&(clearTimeout(tc),tc=setTimeout(qt,t)),nc=0):(nc=1,rc(qt))}function Lt(){var n=Date.now();for(ec=Ka;ec;)n>=ec.t&&(ec.f=ec.c(n-ec.t)),ec=ec.n;return n}function Tt(){for(var n,t=Ka,e=1/0;t;)t.f?t=n?n.n=t.n:Ka=t.n:(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Pt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r&&e?function(n,t){for(var u=n.length,i=[],o=0,a=r[0],c=0;u>0&&a>0&&(c+a+1>t&&(a=Math.max(1,t-c)),i.push(n.substring(u-=a,u+a)),!((c+=a+1)>t));)a=r[o=(o+1)%r.length];return i.reverse().join(e)}:y;return function(n){var e=ic.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",c=e[4]||"",l=e[5],s=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1,y=!0;switch(h&&(h=+h.substring(1)),(l||"0"===r&&"="===o)&&(l=r="0",o="="),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":y=!1;case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=oc.get(g)||Ut;var M=l&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>p){var c=ta.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=y?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!l&&f&&(x=i(x,1/0));var S=v.length+x.length+b.length+(M?0:u.length),k=s>S?new Array(S=s-S+1).join(r):"";return M&&(x=i(k+x,k.length?s-b.length:1/0)),u+=v,n=x+b,("<"===o?u+n+k:">"===o?k+u+n:"^"===o?k.substring(0,S>>=1)+u+n+k.substring(S):u+(M?n:k+n))+e}}}function Ut(n){return n+""}function jt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ft(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new cc(e-1)),1),e}function i(n,e){return t(n=new cc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{cc=jt;var r=new jt;return r._=n,o(r,t,e)}finally{cc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Ht(n);return c.floor=c,c.round=Ht(r),c.ceil=Ht(u),c.offset=Ht(i),c.range=a,n}function Ht(n){return function(t,e){try{cc=jt;var r=new jt;return r._=t,n(r,e)._}finally{cc=Date}}}function Ot(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++aa;){if(r>=l)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=C[o in sc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.slice(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,N.c.toString(),t,r)}function c(n,t,r){return e(n,N.x.toString(),t,r)}function l(n,t,r){return e(n,N.X.toString(),t,r)}function s(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{cc=jt;var t=new cc;return t._=n,r(t)}finally{cc=Date}}var r=t(n);return e.parse=function(n){try{cc=jt;var t=r.parse(n);return t&&t._}finally{cc=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ae;var M=ta.map(),x=Yt(v),b=Zt(v),_=Yt(d),w=Zt(d),S=Yt(m),k=Zt(m),E=Yt(y),A=Zt(y);p.forEach(function(n,t){M.set(n.toLowerCase(),t)});var N={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return It(n.getDate(),t,2)},e:function(n,t){return It(n.getDate(),t,2)},H:function(n,t){return It(n.getHours(),t,2)},I:function(n,t){return It(n.getHours()%12||12,t,2)},j:function(n,t){return It(1+ac.dayOfYear(n),t,3)},L:function(n,t){return It(n.getMilliseconds(),t,3)},m:function(n,t){return It(n.getMonth()+1,t,2)},M:function(n,t){return It(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return It(n.getSeconds(),t,2)},U:function(n,t){return It(ac.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return It(ac.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return It(n.getFullYear()%100,t,2)},Y:function(n,t){return It(n.getFullYear()%1e4,t,4)},Z:ie,"%":function(){return"%"}},C={a:r,A:u,b:i,B:o,c:a,d:Qt,e:Qt,H:te,I:te,j:ne,L:ue,m:Kt,M:ee,p:s,S:re,U:Xt,w:Vt,W:$t,x:c,X:l,y:Wt,Y:Bt,Z:Jt,"%":oe};return t}function It(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Yt(n){return new RegExp("^(?:"+n.map(ta.requote).join("|")+")","i")}function Zt(n){for(var t=new l,e=-1,r=n.length;++e68?1900:2e3)}function Kt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Qt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function ne(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function te(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function ee(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function re(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ue(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ie(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=ga(t)/60|0,u=ga(t)%60;return e+It(r,"0",2)+It(u,"0",2)}function oe(n,t,e){hc.lastIndex=0;var r=hc.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ae(n){for(var t=n.length,e=-1;++e=0?1:-1,a=o*e,c=Math.cos(t),l=Math.sin(t),s=i*l,f=u*c+s*Math.cos(a),h=s*o*Math.sin(a);yc.add(Math.atan2(h,f)),r=n,u=c,i=l}var t,e,r,u,i;Mc.point=function(o,a){Mc.point=n,r=(t=o)*Da,u=Math.cos(a=(e=a)*Da/2+qa/4),i=Math.sin(a)},Mc.lineEnd=function(){n(t,e)}}function pe(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function ve(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function de(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function me(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ye(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function Me(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function xe(n){return[Math.atan2(n[1],n[0]),tt(n[2])]}function be(n,t){return ga(n[0]-t[0])a;++a)u.point((e=n[a])[0],e[1]);return void u.lineEnd()}var c=new qe(e,n,null,!0),l=new qe(e,null,c,!1);c.o=l,i.push(c),o.push(l),c=new qe(r,n,null,!1),l=new qe(r,null,c,!0),c.o=l,i.push(c),o.push(l)}}),o.sort(t),ze(i),ze(o),i.length){for(var a=0,c=e,l=o.length;l>a;++a)o[a].e=c=!c;for(var s,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;s=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,l=s.length;l>a;++a)u.point((f=s[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){s=g.p.z;for(var a=s.length-1;a>=0;--a)u.point((f=s[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,s=g.z,p=!p}while(!g.v);u.lineEnd()}}}function ze(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r0){for(b||(i.polygonStart(),b=!0),i.lineStart();++o1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Te))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:l,polygonStart:function(){y.point=s,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=l,g=ta.merge(g);var n=Fe(m,p);g.length?(b||(i.polygonStart(),b=!0),Ce(g,De,n,e,i)):n&&(b||(i.polygonStart(),b=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),b&&(i.polygonEnd(),b=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},M=Re(),x=t(M),b=!1;return y}}function Te(n){return n.length>1}function Re(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function De(n,t){return((n=n.x)[0]<0?n[1]-Ra-Ca:Ra-n[1])-((t=t.x)[0]<0?t[1]-Ra-Ca:Ra-t[1])}function Pe(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?qa:-qa,c=ga(i-e);ga(c-qa)0?Ra:-Ra),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=qa&&(ga(e-u)Ca?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function je(n,t,e,r){var u;if(null==n)u=e*Ra,r.point(-qa,u),r.point(0,u),r.point(qa,u),r.point(qa,0),r.point(qa,-u),r.point(0,-u),r.point(-qa,-u),r.point(-qa,0),r.point(-qa,u);else if(ga(n[0]-t[0])>Ca){var i=n[0]a;++a){var l=t[a],s=l.length;if(s)for(var f=l[0],h=f[0],g=f[1]/2+qa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===s&&(d=0),n=l[d];var m=n[0],y=n[1]/2+qa/4,M=Math.sin(y),x=Math.cos(y),b=m-h,_=b>=0?1:-1,w=_*b,S=w>qa,k=p*M;if(yc.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),i+=S?b+_*La:b,S^h>=e^m>=e){var E=de(pe(f),pe(n));Me(E);var A=de(u,E);Me(A);var N=(S^b>=0?-1:1)*tt(A[2]);(r>N||r===N&&(E[0]||E[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=m,p=M,v=x,f=n}}return(-Ca>i||Ca>i&&0>yc)^1&o}function He(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,l,s;return{lineStart:function(){l=c=!1,s=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?qa:-qa),h):0;if(!e&&(l=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(be(e,g)||be(p,g))&&(p[0]+=Ca,p[1]+=Ca,v=t(p[0],p[1]))),v!==c)s=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(s=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&be(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return s|(l&&c)<<1}}}function r(n,t,e){var r=pe(n),u=pe(t),o=[1,0,0],a=de(r,u),c=ve(a,a),l=a[0],s=c-l*l;if(!s)return!e&&n;var f=i*c/s,h=-i*l/s,g=de(o,a),p=ye(o,f),v=ye(a,h);me(p,v);var d=g,m=ve(p,d),y=ve(d,d),M=m*m-y*(ve(p,p)-1);if(!(0>M)){var x=Math.sqrt(M),b=ye(d,(-m-x)/y);if(me(b,p),b=xe(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(_=w,w=S,S=_);var A=S-w,N=ga(A-qa)A;if(!N&&k>E&&(_=k,k=E,E=_),C?N?k+E>0^b[1]<(ga(b[0]-w)qa^(w<=b[0]&&b[0]<=S)){var z=ye(d,(-m+x)/y);return me(z,p),[b,xe(z)]}}}function u(t,e){var r=o?n:qa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=ga(i)>Ca,c=gr(n,6*Da);return Le(t,e,c,o?[0,-n]:[-qa,n-qa])}function Oe(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,l=o.y,s=a.x,f=a.y,h=0,g=1,p=s-c,v=f-l;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-l,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-l,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:l+h*v}),1>g&&(u.b={x:c+g*p,y:l+g*v}),u}}}}}}function Ie(n,t,e,r){function u(r,u){return ga(r[0]-n)0?0:3:ga(r[0]-e)0?2:1:ga(r[1]-t)0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,l=a[0];c>o;++o)i=a[o],l[1]<=r?i[1]>r&&Q(l,i,n)>0&&++t:i[1]<=r&&Q(l,i,n)<0&&--t,l=i;return 0!==t}function l(i,a,c,l){var s=0,f=0;if(null==i||(s=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do l.point(0===s||3===s?n:e,s>1?r:t);while((s=(s+c+4)%4)!==f)}else l.point(a[0],a[1])}function s(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){s(n,t)&&a.point(n,t)}function h(){C.point=p,d&&d.push(m=[]),S=!0,w=!1,b=_=0/0}function g(){v&&(p(y,M),x&&w&&A.rejoin(),v.push(A.buffer())),C.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Tc,Math.min(Tc,n)),t=Math.max(-Tc,Math.min(Tc,t));var e=s(n,t);if(d&&m.push([n,t]),S)y=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};N(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,m,y,M,x,b,_,w,S,k,E=a,A=Re(),N=Oe(n,t,e,r),C={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=ta.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),l(null,null,1,a),a.lineEnd()),u&&Ce(v,i,t,l,a),a.polygonEnd()),v=d=m=null}};return C}}function Ye(n){var t=0,e=qa/3,r=ir(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*qa/180,e=n[1]*qa/180):[t/qa*180,e/qa*180]},u}function Ze(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,tt((i-(n*n+e*e)*u*u)/(2*u))]},e}function Ve(){function n(n,t){Dc+=u*n-r*t,r=n,u=t}var t,e,r,u;Hc.point=function(i,o){Hc.point=n,t=r=i,e=u=o},Hc.lineEnd=function(){n(t,e)}}function Xe(n,t){Pc>n&&(Pc=n),n>jc&&(jc=n),Uc>t&&(Uc=t),t>Fc&&(Fc=t)}function $e(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Be(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Be(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Be(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function We(n,t){_c+=n,wc+=t,++Sc}function Je(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);kc+=o*(t+n)/2,Ec+=o*(e+r)/2,Ac+=o,We(t=n,e=r)}var t,e;Ic.point=function(r,u){Ic.point=n,We(t=r,e=u)}}function Ge(){Ic.point=We}function Ke(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);kc+=o*(r+n)/2,Ec+=o*(u+t)/2,Ac+=o,o=u*n-r*t,Nc+=o*(r+n),Cc+=o*(u+t),zc+=3*o,We(r=n,u=t)}var t,e,r,u;Ic.point=function(i,o){Ic.point=n,We(t=r=i,e=u=o)},Ic.lineEnd=function(){n(t,e)}}function Qe(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,La)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function nr(n){function t(n){return(a?r:e)(n)}function e(t){return rr(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=0/0,S.point=i,t.lineStart()}function i(e,r){var i=pe([e,r]),o=n(e,r);u(M,x,y,b,_,w,M=o[0],x=o[1],y=e,b=i[0],_=i[1],w=i[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=l,S.lineEnd=s}function l(n,t){i(f=n,h=t),g=M,p=x,v=b,d=_,m=w,S.point=i}function s(){u(M,x,y,b,_,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c -},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,l,s,f,h,g,p,v,d,m){var y=s-t,M=f-e,x=y*y+M*M;if(x>4*i&&d--){var b=a+g,_=c+p,w=l+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),E=ga(ga(w)-1)i||ga((y*z+M*q)/x-.5)>.3||o>a*g+c*p+l*v)&&(u(t,e,r,a,c,l,N,C,E,b/=S,_/=S,w,d,m),m.point(N,C),u(N,C,E,b,_,w,s,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Da),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function tr(n){var t=nr(function(t,e){return n([t*Pa,e*Pa])});return function(n){return or(t(n))}}function er(n){this.stream=n}function rr(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function ur(n){return ir(function(){return n})()}function ir(n){function t(n){return n=a(n[0]*Da,n[1]*Da),[n[0]*h+c,l-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(l-n[1])/h),n&&[n[0]*Pa,n[1]*Pa]}function r(){a=Ae(o=lr(m,M,x),i);var n=i(v,d);return c=g-n[0]*h,l=p+n[1]*h,u()}function u(){return s&&(s.valid=!1,s=null),t}var i,o,a,c,l,s,f=nr(function(n,t){return n=i(n,t),[n[0]*h+c,l-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,M=0,x=0,b=Lc,_=y,w=null,S=null;return t.stream=function(n){return s&&(s.valid=!1),s=or(b(o,f(_(n)))),s.valid=!0,s},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Lc):He((w=+n)*Da),u()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Ie(n[0][0],n[0][1],n[1][0],n[1][1]):y,u()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Da,d=n[1]%360*Da,r()):[v*Pa,d*Pa]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Da,M=n[1]%360*Da,x=n.length>2?n[2]%360*Da:0,r()):[m*Pa,M*Pa,x*Pa]},ta.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function or(n){return rr(n,function(t,e){n.point(t*Da,e*Da)})}function ar(n,t){return[n,t]}function cr(n,t){return[n>qa?n-La:-qa>n?n+La:n,t]}function lr(n,t,e){return n?t||e?Ae(fr(n),hr(t,e)):fr(n):t||e?hr(t,e):cr}function sr(n){return function(t,e){return t+=n,[t>qa?t-La:-qa>t?t+La:t,e]}}function fr(n){var t=sr(n);return t.invert=sr(-n),t}function hr(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*r+a*u;return[Math.atan2(c*i-s*o,a*r-l*u),tt(s*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*i-c*o;return[Math.atan2(c*i+l*o,a*r+s*u),tt(s*r-a*u)]},e}function gr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=pr(e,u),i=pr(e,i),(o>0?i>u:u>i)&&(u+=o*La)):(u=n+o*La,i=n-.5*c);for(var l,s=u;o>0?s>i:i>s;s-=c)a.point((l=xe([e,-r*Math.cos(s),-r*Math.sin(s)]))[0],l[1])}}function pr(n,t){var e=pe(t);e[0]-=n,Me(e);var r=nt(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Ca)%(2*Math.PI)}function vr(n,t,e){var r=ta.range(n,t-Ca,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function dr(n,t,e){var r=ta.range(n,t-Ca,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function mr(n){return n.source}function yr(n){return n.target}function Mr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),l=u*Math.sin(n),s=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(it(r-t)+u*o*it(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*s,u=e*l+t*f,o=e*i+t*a;return[Math.atan2(u,r)*Pa,Math.atan2(o,Math.sqrt(r*r+u*u))*Pa]}:function(){return[n*Pa,t*Pa]};return p.distance=h,p}function xr(){function n(n,u){var i=Math.sin(u*=Da),o=Math.cos(u),a=ga((n*=Da)-t),c=Math.cos(a);Yc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;Zc.point=function(u,i){t=u*Da,e=Math.sin(i*=Da),r=Math.cos(i),Zc.point=n},Zc.lineEnd=function(){Zc.point=Zc.lineEnd=b}}function br(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function _r(n,t){function e(n,t){o>0?-Ra+Ca>t&&(t=-Ra+Ca):t>Ra-Ca&&(t=Ra-Ca);var e=o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(qa/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=K(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Ra]},e):Sr}function wr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return ga(u)u;u++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function zr(n,t){return n[0]-t[0]||n[1]-t[1]}function qr(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Lr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],l=e[1],s=t[1]-c,f=r[1]-l,h=(a*(c-l)-f*(u-i))/(f*o-a*s);return[u+h*o,c+h*s]}function Tr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Rr(){tu(this),this.edge=this.site=this.circle=null}function Dr(n){var t=el.pop()||new Rr;return t.site=n,t}function Pr(n){Xr(n),Qc.remove(n),el.push(n),tu(n)}function Ur(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Pr(n);for(var c=i;c.circle&&ga(e-c.circle.x)s;++s)l=a[s],c=a[s-1],Kr(l.edge,c.site,l.site,u);c=a[0],l=a[f-1],l.edge=Jr(c.site,l.site,null,u),Vr(c),Vr(l)}function jr(n){for(var t,e,r,u,i=n.x,o=n.y,a=Qc._;a;)if(r=Fr(a,o)-i,r>Ca)a=a.L;else{if(u=i-Hr(a,o),!(u>Ca)){r>-Ca?(t=a.P,e=a):u>-Ca?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Dr(n);if(Qc.insert(t,c),t||e){if(t===e)return Xr(t),e=Dr(t.site),Qc.insert(c,e),c.edge=e.edge=Jr(t.site,c.site),Vr(t),void Vr(e);if(!e)return void(c.edge=Jr(t.site,c.site));Xr(t),Xr(e);var l=t.site,s=l.x,f=l.y,h=n.x-s,g=n.y-f,p=e.site,v=p.x-s,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,M=v*v+d*d,x={x:(d*y-g*M)/m+s,y:(h*M-v*y)/m+f};Kr(e.edge,l,p,x),c.edge=Jr(l,n,null,x),e.edge=Jr(n,p,null,x),Vr(t),Vr(e)}}function Fr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,l=c-t;if(!l)return a;var s=a-r,f=1/i-1/l,h=s/l;return f?(-h+Math.sqrt(h*h-2*f*(s*s/(-2*l)-c+l/2+u-i/2)))/f+r:(r+a)/2}function Hr(n,t){var e=n.N;if(e)return Fr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Or(n){this.site=n,this.edges=[]}function Ir(n){for(var t,e,r,u,i,o,a,c,l,s,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Kc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)s=a[o].end(),r=s.x,u=s.y,l=a[++o%c].start(),t=l.x,e=l.y,(ga(r-t)>Ca||ga(u-e)>Ca)&&(a.splice(o,0,new Qr(Gr(i.site,s,ga(r-f)Ca?{x:f,y:ga(t-f)Ca?{x:ga(e-p)Ca?{x:h,y:ga(t-h)Ca?{x:ga(e-g)=-za)){var g=c*c+l*l,p=s*s+f*f,v=(f*g-l*p)/h,d=(c*p-s*g)/h,f=d+a,m=rl.pop()||new Zr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,M=tl._;M;)if(m.yd||d>=a)return;if(h>p){if(i){if(i.y>=l)return}else i={x:d,y:c};e={x:d,y:l}}else{if(i){if(i.yr||r>1)if(h>p){if(i){if(i.y>=l)return}else i={x:(c-u)/r,y:c};e={x:(l-u)/r,y:l}}else{if(i){if(i.yg){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.xi||f>o||r>h||u>g)){if(p=n.point){var p,v=t-n.x,d=e-n.y,m=v*v+d*d;if(c>m){var y=Math.sqrt(c=m);r=t-y,u=e-y,i=t+y,o=e+y,a=p}}for(var M=n.nodes,x=.5*(s+h),b=.5*(f+g),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:l(n,s,f,x,b);break;case 1:l(n,x,f,h,b);break;case 2:l(n,s,b,x,g);break;case 3:l(n,x,b,h,g)}}}(n,r,u,i,o),a}function gu(n,t){n=ta.rgb(n),t=ta.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+xt(Math.round(e+i*n))+xt(Math.round(r+o*n))+xt(Math.round(u+a*n))}}function pu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=mu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function vu(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function du(n,t){var e,r,u,i=il.lastIndex=ol.lastIndex=0,o=-1,a=[],c=[];for(n+="",t+="";(e=il.exec(n))&&(r=ol.exec(t));)(u=r.index)>i&&(u=t.slice(i,u),a[o]?a[o]+=u:a[++o]=u),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,c.push({i:o,x:vu(e,r)})),i=ol.lastIndex;return ir;++r)a[(e=c[r]).i]=e.x(n);return a.join("")})}function mu(n,t){for(var e,r=ta.interpolators.length;--r>=0&&!(e=ta.interpolators[r](n,t)););return e}function yu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(mu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function Mu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function xu(n){return function(t){return 1-n(1-t)}}function bu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function _u(n){return n*n}function wu(n){return n*n*n}function Su(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function ku(n){return function(t){return Math.pow(t,n)}}function Eu(n){return 1-Math.cos(n*Ra)}function Au(n){return Math.pow(2,10*(n-1))}function Nu(n){return 1-Math.sqrt(1-n*n)}function Cu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/La*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*La/t)}}function zu(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function qu(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Lu(n,t){n=ta.hcl(n),t=ta.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return st(e+i*n,r+o*n,u+a*n)+""}}function Tu(n,t){n=ta.hsl(n),t=ta.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ct(e+i*n,r+o*n,u+a*n)+""}}function Ru(n,t){n=ta.lab(n),t=ta.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ht(e+i*n,r+o*n,u+a*n)+""}}function Du(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Pu(n){var t=[n.a,n.b],e=[n.c,n.d],r=ju(t),u=Uu(t,e),i=ju(Fu(e,t,-u))||0;t[0]*e[1]180?s+=360:s-l>180&&(l+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:vu(l,s)})):s&&r.push(r.pop()+"rotate("+s+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:vu(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:vu(g[0],p[0])},{i:e-2,x:vu(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i=0;)e.push(u[r])}function Qu(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,o=-1;++oe;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function si(n){return n.reduce(fi,0)}function fi(n,t){return n+t[1]}function hi(n,t){return gi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function gi(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function pi(n){return[ta.min(n),ta.max(n)]}function vi(n,t){return n.value-t.value}function di(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function mi(n,t){n._pack_next=t,t._pack_prev=n}function yi(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function Mi(n){function t(n){s=Math.min(n.x-n.r,s),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(l=e.length)){var e,r,u,i,o,a,c,l,s=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(xi),r=e[0],r.x=-r.r,r.y=0,t(r),l>1&&(u=e[1],u.x=u.r,u.y=0,t(u),l>2))for(i=e[2],wi(r,u,i),t(i),di(r,i),r._pack_prev=i,di(i,u),u=r._pack_next,o=3;l>o;o++){wi(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(yi(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!yi(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.ro;o++)i=e[o],i.x-=m,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=M,e.forEach(bi)}}function xi(n){n._pack_next=n._pack_prev=n}function bi(n){delete n._pack_next,delete n._pack_prev}function _i(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Ci(n,t,e){return n.a.parent===t.parent?n.a:e}function zi(n){return 1+ta.max(n,function(n){return n.y})}function qi(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Li(n){var t=n.children;return t&&t.length?Li(t[0]):n}function Ti(n){var t,e=n.children;return e&&(t=e.length)?Ti(e[t-1]):n}function Ri(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Di(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Pi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ui(n){return n.rangeExtent?n.rangeExtent():Pi(n.range())}function ji(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Fi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Hi(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ml}function Oi(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?Oi:ji,c=r?Iu:Ou;return o=u(n,t,c,e),a=u(t,n,c,mu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Du)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Xi(n,t)},i.tickFormat=function(t,e){return $i(n,t,e)},i.nice=function(t){return Zi(n,t),u()},i.copy=function(){return Ii(n,t,e,r)},u()}function Yi(n,t){return ta.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Zi(n,t){return Fi(n,Hi(Vi(n,t)[2]))}function Vi(n,t){null==t&&(t=10);var e=Pi(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Xi(n,t){return ta.range.apply(ta,Vi(n,t))}function $i(n,t,e){var r=Vi(n,t);if(e){var u=ic.exec(e);if(u.shift(),"s"===u[8]){var i=ta.formatPrefix(Math.max(ga(r[0]),ga(r[1])));return u[7]||(u[7]="."+Bi(i.scale(r[2]))),u[8]="f",e=ta.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+Wi(u[8],r)),e=u.join("")}else e=",."+Bi(r[2])+"f";return ta.format(e)}function Bi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Wi(n,t){var e=Bi(t[2]);return n in yl?Math.abs(e-Bi(Math.max(ga(t[0]),ga(t[1]))))+ +("e"!==n):e-2*("%"===n)}function Ji(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Fi(r.map(u),e?Math:xl);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Pi(r),o=[],a=n[0],c=n[1],l=Math.floor(u(a)),s=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(s-l)){if(e){for(;s>l;l++)for(var h=1;f>h;h++)o.push(i(l)*h);o.push(i(l))}else for(o.push(i(l));l++0;h--)o.push(i(l)*h);for(l=0;o[l]c;s--);o=o.slice(l,s)}return o},o.tickFormat=function(n,t){if(!arguments.length)return Ml;arguments.length<2?t=Ml:"function"!=typeof t&&(t=ta.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return Ji(n.copy(),t,e,r)},Yi(o,n)}function Gi(n,t,e){function r(t){return n(u(t))}var u=Ki(t),i=Ki(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Xi(e,n)},r.tickFormat=function(n,t){return $i(e,n,t)},r.nice=function(n){return r.domain(Zi(e,n))},r.exponent=function(o){return arguments.length?(u=Ki(t=o),i=Ki(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Gi(n.copy(),t,e)},Yi(r,n)}function Ki(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Qi(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):0/0))-1)%i.length]}function r(t,e){return ta.range(n.length).map(function(n){return t+e*n})}var u,i,o;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new l;for(var i,o=-1,a=r.length;++oe?[0/0,0/0]:[e>0?a[e-1]:n[0],et?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return to(n,t,e)},u()}function eo(n,t){function e(e){return e>=e?t[ta.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return eo(n,t)},e}function ro(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Xi(n,t)},t.tickFormat=function(t,e){return $i(n,t,e)},t.copy=function(){return ro(n)},t}function uo(){return 0}function io(n){return n.innerRadius}function oo(n){return n.outerRadius}function ao(n){return n.startAngle}function co(n){return n.endAngle}function lo(n){return n&&n.padAngle}function so(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function fo(n,t,e,r,u){var i=n[0]-t[0],o=n[1]-t[1],a=(u?r:-r)/Math.sqrt(i*i+o*o),c=a*o,l=-a*i,s=n[0]+c,f=n[1]+l,h=t[0]+c,g=t[1]+l,p=(s+h)/2,v=(f+g)/2,d=h-s,m=g-f,y=d*d+m*m,M=e-r,x=s*g-h*f,b=(0>m?-1:1)*Math.sqrt(M*M*y-x*x),_=(x*m-d*b)/y,w=(-x*d-m*b)/y,S=(x*m+d*b)/y,k=(-x*d+m*b)/y,E=_-p,A=w-v,N=S-p,C=k-v;return E*E+A*A>N*N+C*C&&(_=S,w=k),[[_-c,w-l],[_*e/M,w*e/M]]}function ho(n){function t(t){function o(){l.push("M",i(n(s),a))}for(var c,l=[],s=[],f=-1,h=t.length,g=Et(e),p=Et(r);++f1&&u.push("H",r[0]),u.join("")}function mo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var l=2;l9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function To(n){return n.length<3?go(n):n[0]+_o(n,Lo(n))}function Ro(n){for(var t,e,r,u=-1,i=n.length;++ur)return s();var u=i[i.active];u&&(--i.count,delete i[i.active],u.event&&u.event.interrupt.call(n,n.__data__,u.index)),i.active=r,o.event&&o.event.start.call(n,n.__data__,t),o.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&v.push(r)}),h=o.ease,f=o.duration,ta.timer(function(){return p.c=l(e||1)?Ne:l,1},0,a)}function l(e){if(i.active!==r)return 1;for(var u=e/f,a=h(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,n.__data__,t),s()):void 0}function s(){return--i.count?delete i[r]:delete n[e],1}var f,h,g=o.delay,p=ec,v=[];return p.t=g+a,u>=g?c(u-g):void(p.c=c)},0,a)}}function Bo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function Wo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function Jo(n){return n.toISOString()}function Go(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=ta.bisect(Vl,u);return i==Vl.length?[t.year,Vi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Vl[i-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=Ko(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Ko(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Pi(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Ko(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Go(n.copy(),t,e)},Yi(r,n)}function Ko(n){return new Date(n)}function Qo(n){return JSON.parse(n.responseText)}function na(n){var t=ua.createRange();return t.selectNode(ua.body),t.createContextualFragment(n.responseText)}var ta={version:"3.5.5"},ea=[].slice,ra=function(n){return ea.call(n)},ua=this.document;if(ua)try{ra(ua.documentElement.childNodes)[0].nodeType}catch(ia){ra=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),ua)try{ua.createElement("DIV").style.setProperty("opacity",0,"")}catch(oa){var aa=this.Element.prototype,ca=aa.setAttribute,la=aa.setAttributeNS,sa=this.CSSStyleDeclaration.prototype,fa=sa.setProperty;aa.setAttribute=function(n,t){ca.call(this,n,t+"")},aa.setAttributeNS=function(n,t,e){la.call(this,n,t,e+"")},sa.setProperty=function(n,t,e){fa.call(this,n,t+"",e)}}ta.ascending=e,ta.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},ta.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=r){e=r;break}for(;++ur&&(e=r)}else{for(;++u=r){e=r;break}for(;++ur&&(e=r)}return e},ta.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=r){e=r;break}for(;++ue&&(e=r)}else{for(;++u=r){e=r;break}for(;++ue&&(e=r)}return e},ta.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i=r){e=u=r;break}for(;++ir&&(e=r),r>u&&(u=r))}else{for(;++i=r){e=u=r;break}for(;++ir&&(e=r),r>u&&(u=r))}return[e,u]},ta.sum=function(n,t){var e,r=0,i=n.length,o=-1;if(1===arguments.length)for(;++o1?c/(s-1):void 0},ta.deviation=function(){var n=ta.variance.apply(this,arguments);return n?Math.sqrt(n):n};var ha=i(e);ta.bisectLeft=ha.left,ta.bisect=ta.bisectRight=ha.right,ta.bisector=function(n){return i(1===n.length?function(t,r){return e(n(t),r)}:n)},ta.shuffle=function(n,t,e){(i=arguments.length)<3&&(e=n.length,2>i&&(t=0));for(var r,u,i=e-t;i;)u=Math.random()*i--|0,r=n[i+t],n[i+t]=n[u+t],n[u+t]=r;return n},ta.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ta.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},ta.zip=function(){if(!(r=arguments.length))return[];for(var n=-1,t=ta.min(arguments,o),e=new Array(t);++n=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var ga=Math.abs;ta.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,u=[],i=a(ga(e)),o=-1;if(n*=i,t*=i,e*=i,0>e)for(;(r=n+e*++o)>t;)u.push(r/i);else for(;(r=n+e*++o)=i.length)return r?r.call(u,o):e?o.sort(e):o;for(var c,s,f,h,g=-1,p=o.length,v=i[a++],d=new l;++g=i.length)return n;var r=[],u=o[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],o=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(ta.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return o[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},ta.set=function(n){var t=new m;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},c(m,{has:h,add:function(n){return this._[s(n+="")]=!0,n},remove:g,values:p,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,f(t))}}),ta.behavior={},ta.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ta.event=null,ta.requote=function(n){return n.replace(ma,"\\$&")};var ma=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ya={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},Ma=function(n,t){return t.querySelector(n)},xa=function(n,t){return t.querySelectorAll(n)},ba=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(ba=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(Ma=function(n,t){return Sizzle(n,t)[0]||null},xa=Sizzle,ba=Sizzle.matchesSelector),ta.selection=function(){return ta.select(ua.documentElement)};var _a=ta.selection.prototype=[];_a.select=function(n){var t,e,r,u,i=[];n=N(n);for(var o=-1,a=this.length;++o=0&&(e=n.slice(0,t),n=n.slice(t+1)),wa.hasOwnProperty(e)?{space:wa[e],local:n}:n}},_a.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ta.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},_a.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,u=-1;if(t=e.classList){for(;++uu){if("string"!=typeof n){2>u&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>u){var i=this.node();return t(i).getComputedStyle(i,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},_a.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},_a.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},_a.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},_a.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},_a.insert=function(n,t){return n=j(n),t=N(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},_a.remove=function(){return this.each(F)},_a.data=function(n,t){function e(n,e){var r,u,i,o=n.length,f=e.length,h=Math.min(o,f),g=new Array(f),p=new Array(f),v=new Array(o);if(t){var d,m=new l,y=new Array(o);for(r=-1;++rr;++r)p[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,a.push(p),c.push(g),s.push(v)}var r,u,i=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++ii;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return A(u)},_a.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},_a.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},_a.size=function(){var n=0;return Y(this,function(){++n}),n};var Sa=[];ta.selection.enter=Z,ta.selection.enter.prototype=Sa,Sa.append=_a.append,Sa.empty=_a.empty,Sa.node=_a.node,Sa.call=_a.call,Sa.size=_a.size,Sa.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var ka=ta.map({mouseenter:"mouseover",mouseleave:"mouseout"});ua&&ka.forEach(function(n){"on"+n in ua&&ka.remove(n)});var Ea,Aa=0;ta.mouse=function(n){return J(n,k())};var Na=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ta.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,u=0,i=t.length;i>u;++u)if((r=t[u]).identifier===e)return J(n,r)},ta.behavior.drag=function(){function n(){this.on("mousedown.drag",i).on("touchstart.drag",o)}function e(n,t,e,i,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],p|=n|e,M=r,g({type:"drag",x:r[0]+l[0],y:r[1]+l[1],dx:n,dy:e}))}function c(){t(h,v)&&(m.on(i+d,null).on(o+d,null),y(p&&ta.event.target===f),g({type:"dragend"}))}var l,s=this,f=ta.event.target,h=s.parentNode,g=r.of(s,arguments),p=0,v=n(),d=".drag"+(null==v?"":"-"+v),m=ta.select(e(f)).on(i+d,a).on(o+d,c),y=W(f),M=t(h,v);u?(l=u.apply(s,arguments),l=[l.x-M[0],l.y-M[1]]):l=[0,0],g({type:"dragstart"})}}var r=E(n,"drag","dragstart","dragend"),u=null,i=e(b,ta.mouse,t,"mousemove","mouseup"),o=e(G,ta.touch,y,"touchmove","touchend");return n.origin=function(t){return arguments.length?(u=t,n):u},ta.rebind(n,r,"on")},ta.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?ra(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Ca=1e-6,za=Ca*Ca,qa=Math.PI,La=2*qa,Ta=La-Ca,Ra=qa/2,Da=qa/180,Pa=180/qa,Ua=Math.SQRT2,ja=2,Fa=4;ta.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=rt(v),o=i/(ja*h)*(e*ut(Ua*t+v)-et(v));return[r+o*l,u+o*s,i*e/rt(Ua*t+v)]}return[r+n*l,u+n*s,i*Math.exp(Ua*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],l=o-r,s=a-u,f=l*l+s*s,h=Math.sqrt(f),g=(c*c-i*i+Fa*f)/(2*i*ja*h),p=(c*c-i*i-Fa*f)/(2*c*ja*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Ua;return e.duration=1e3*y,e},ta.behavior.zoom=function(){function n(n){n.on(q,f).on(Oa+".zoom",g).on("dblclick.zoom",p).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function u(n){k.k=Math.max(N[0],Math.min(N[1],n))}function i(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function o(t,e,r,o){t.__chart__={x:k.x,y:k.y,k:k.k},u(Math.pow(2,o)),i(d=e,r),t=ta.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function a(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function c(n){z++||n({type:"zoomstart"})}function l(n){a(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function s(n){--z||n({type:"zoomend"}),d=null}function f(){function n(){f=1,i(ta.mouse(u),g),l(a)}function r(){h.on(L,null).on(T,null),p(f&&ta.event.target===o),s(a)}var u=this,o=ta.event.target,a=D.of(u,arguments),f=0,h=ta.select(t(u)).on(L,n).on(T,r),g=e(ta.mouse(u)),p=W(u);Dl.call(u),c(a)}function h(){function n(){var n=ta.touches(p);return g=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=ta.event.target;ta.select(t).on(x,r).on(b,a),_.push(t);for(var e=ta.event.changedTouches,u=0,i=e.length;i>u;++u)d[e[u].identifier]=null;var c=n(),l=Date.now();if(1===c.length){if(500>l-M){var s=c[0];o(p,s,d[s.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=l}else if(c.length>1){var s=c[0],f=c[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function r(){var n,t,e,r,o=ta.touches(p);Dl.call(p);for(var a=0,c=o.length;c>a;++a,r=null)if(e=o[a],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var s=(s=e[0]-n[0])*s+(s=e[1]-n[1])*s,f=m&&Math.sqrt(s/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],u(f*g)}M=null,i(n,t),l(v)}function a(){if(ta.event.touches.length){for(var t=ta.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var u in d)return void n()}ta.selectAll(_).on(y,null),w.on(q,f).on(R,h),E(),s(v)}var g,p=this,v=D.of(p,arguments),d={},m=0,y=".zoom-"+ta.event.changedTouches[0].identifier,x="touchmove"+y,b="touchend"+y,_=[],w=ta.select(p),E=W(p);t(),c(v),w.on(q,null).on(R,t)}function g(){var n=D.of(this,arguments);y?clearTimeout(y):(v=e(d=m||ta.mouse(this)),Dl.call(this),c(n)),y=setTimeout(function(){y=null,s(n)},50),S(),u(Math.pow(2,.002*Ha())*k.k),i(d,v),l(n)}function p(){var n=ta.mouse(this),t=Math.log(k.k)/Math.LN2;o(this,n,e(n),ta.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,m,y,M,x,b,_,w,k={x:0,y:0,k:1},A=[960,500],N=Ia,C=250,z=0,q="mousedown.zoom",L="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=E(n,"zoomstart","zoom","zoomend");return Oa||(Oa="onwheel"in ua?(Ha=function(){return-ta.event.deltaY*(ta.event.deltaMode?120:1)},"wheel"):"onmousewheel"in ua?(Ha=function(){return ta.event.wheelDelta},"mousewheel"):(Ha=function(){return-ta.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Tl?ta.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},c(n)}).tween("zoom:zoom",function(){var e=A[0],r=A[1],u=d?d[0]:e/2,i=d?d[1]:r/2,o=ta.interpolateZoom([(u-k.x)/k.k,(i-k.y)/k.k,e/k.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:u-r[0]*a,y:i-r[1]*a,k:a},l(n)}}).each("interrupt.zoom",function(){s(n)}).each("end.zoom",function(){s(n)}):(this.__chart__=k,c(n),l(n),s(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},a(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:+t},a(),n):k.k},n.scaleExtent=function(t){return arguments.length?(N=null==t?Ia:[+t[0],+t[1]],n):N},n.center=function(t){return arguments.length?(m=t&&[+t[0],+t[1]],n):m},n.size=function(t){return arguments.length?(A=t&&[+t[0],+t[1]],n):A},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},ta.rebind(n,D,"on")};var Ha,Oa,Ia=[0,1/0];ta.color=ot,ot.prototype.toString=function(){return this.rgb()+""},ta.hsl=at;var Ya=at.prototype=new ot;Ya.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new at(this.h,this.s,this.l/n)},Ya.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new at(this.h,this.s,n*this.l)},Ya.rgb=function(){return ct(this.h,this.s,this.l)},ta.hcl=lt;var Za=lt.prototype=new ot;Za.brighter=function(n){return new lt(this.h,this.c,Math.min(100,this.l+Va*(arguments.length?n:1)))},Za.darker=function(n){return new lt(this.h,this.c,Math.max(0,this.l-Va*(arguments.length?n:1)))},Za.rgb=function(){return st(this.h,this.c,this.l).rgb()},ta.lab=ft;var Va=18,Xa=.95047,$a=1,Ba=1.08883,Wa=ft.prototype=new ot;Wa.brighter=function(n){return new ft(Math.min(100,this.l+Va*(arguments.length?n:1)),this.a,this.b)},Wa.darker=function(n){return new ft(Math.max(0,this.l-Va*(arguments.length?n:1)),this.a,this.b)},Wa.rgb=function(){return ht(this.l,this.a,this.b)},ta.rgb=mt;var Ja=mt.prototype=new ot;Ja.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),new mt(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new mt(u,u,u)},Ja.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new mt(n*this.r,n*this.g,n*this.b)},Ja.hsl=function(){return _t(this.r,this.g,this.b)},Ja.toString=function(){return"#"+xt(this.r)+xt(this.g)+xt(this.b)};var Ga=ta.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Ga.forEach(function(n,t){Ga.set(n,yt(t))}),ta.functor=Et,ta.xhr=At(y),ta.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=Nt(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(s>=l)return o;if(u)return u=!1,i;var t=s;if(34===n.charCodeAt(t)){for(var e=t;e++s;){var r=n.charCodeAt(s++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(s)&&(++s,++a);else if(r!==c)continue;return n.slice(t,s-a)}return n.slice(t)}for(var r,u,i={},o={},a=[],l=n.length,s=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,f++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new m,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},ta.csv=ta.dsv(",","text/csv"),ta.tsv=ta.dsv(" ","text/tab-separated-values");var Ka,Qa,nc,tc,ec,rc=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ta.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};Qa?Qa.n=i:Ka=i,Qa=i,nc||(tc=clearTimeout(tc),nc=1,rc(qt))},ta.timer.flush=function(){Lt(),Tt()},ta.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var uc=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Dt);ta.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=ta.round(n,Rt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),uc[8+e/3]};var ic=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,oc=ta.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ta.round(n,Rt(n,t))).toFixed(Math.max(0,Math.min(20,Rt(n*(1+1e-15),t))))}}),ac=ta.time={},cc=Date;jt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){lc.setUTCDate.apply(this._,arguments)},setDay:function(){lc.setUTCDay.apply(this._,arguments)},setFullYear:function(){lc.setUTCFullYear.apply(this._,arguments)},setHours:function(){lc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){lc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){lc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){lc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){lc.setUTCSeconds.apply(this._,arguments)},setTime:function(){lc.setTime.apply(this._,arguments)}};var lc=Date.prototype;ac.year=Ft(function(n){return n=ac.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ac.years=ac.year.range,ac.years.utc=ac.year.utc.range,ac.day=Ft(function(n){var t=new cc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ac.days=ac.day.range,ac.days.utc=ac.day.utc.range,ac.dayOfYear=function(n){var t=ac.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ac[n]=Ft(function(n){return(n=ac.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ac.year(n).getDay();return Math.floor((ac.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ac[n+"s"]=e.range,ac[n+"s"].utc=e.utc.range,ac[n+"OfYear"]=function(n){var e=ac.year(n).getDay();return Math.floor((ac.dayOfYear(n)+(e+t)%7)/7)}}),ac.week=ac.sunday,ac.weeks=ac.sunday.range,ac.weeks.utc=ac.sunday.utc.range,ac.weekOfYear=ac.sundayOfYear;var sc={"-":"",_:" ",0:"0"},fc=/^\s*\d+/,hc=/^%/;ta.locale=function(n){return{numberFormat:Pt(n),timeFormat:Ot(n)}};var gc=ta.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ta.format=gc.numberFormat,ta.geo={},ce.prototype={s:0,t:0,add:function(n){le(n,this.t,pc),le(pc.s,this.s,this),this.s?this.t+=pc.t:this.s=pc.t -},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var pc=new ce;ta.geo.stream=function(n,t){n&&vc.hasOwnProperty(n.type)?vc[n.type](n,t):se(n,t)};var vc={Feature:function(n,t){se(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++rn?4*qa+n:n,Mc.lineStart=Mc.lineEnd=Mc.point=b}};ta.geo.bounds=function(){function n(n,t){M.push(x=[s=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=pe([t*Da,e*Da]);if(m){var u=de(m,r),i=[u[1],-u[0],0],o=de(i,u);Me(o),o=xe(o);var c=t-p,l=c>0?1:-1,v=o[0]*Pa*l,d=ga(c)>180;if(d^(v>l*p&&l*t>v)){var y=o[1]*Pa;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>l*p&&l*t>v)){var y=-o[1]*Pa;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t):h>=s?(s>t&&(s=t),t>h&&(h=t)):t>p?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t)}else n(t,e);m=r,p=t}function e(){b.point=t}function r(){x[0]=s,x[1]=h,b.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=ga(r)>180?r+(r>0?360:-360):r}else v=n,d=e;Mc.point(n,e),t(n,e)}function i(){Mc.lineStart()}function o(){u(v,d),Mc.lineEnd(),ga(y)>Ca&&(s=-(h=180)),x[0]=s,x[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function l(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nyc?(s=-(h=180),f=-(g=90)):y>Ca?g=90:-Ca>y&&(f=-90),x[0]=s,x[1]=h}};return function(n){g=h=-(s=f=1/0),M=[],ta.geo.stream(n,b);var t=M.length;if(t){M.sort(c);for(var e,r=1,u=M[0],i=[u];t>r;++r)e=M[r],l(e[0],u)||l(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,s=e[0],h=u[1])}return M=x=null,1/0===s||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[s,f],[h,g]]}}(),ta.geo.centroid=function(n){xc=bc=_c=wc=Sc=kc=Ec=Ac=Nc=Cc=zc=0,ta.geo.stream(n,qc);var t=Nc,e=Cc,r=zc,u=t*t+e*e+r*r;return za>u&&(t=kc,e=Ec,r=Ac,Ca>bc&&(t=_c,e=wc,r=Sc),u=t*t+e*e+r*r,za>u)?[0/0,0/0]:[Math.atan2(e,t)*Pa,tt(r/Math.sqrt(u))*Pa]};var xc,bc,_c,wc,Sc,kc,Ec,Ac,Nc,Cc,zc,qc={sphere:b,point:_e,lineStart:Se,lineEnd:ke,polygonStart:function(){qc.lineStart=Ee},polygonEnd:function(){qc.lineStart=Se}},Lc=Le(Ne,Pe,je,[-qa,-qa/2]),Tc=1e9;ta.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Ie(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ta.geo.conicEqualArea=function(){return Ye(Ze)}).raw=Ze,ta.geo.albers=function(){return ta.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ta.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=ta.geo.albers(),o=ta.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ta.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var l=i.scale(),s=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[s-.455*l,f-.238*l],[s+.455*l,f+.238*l]]).stream(c).point,r=o.translate([s-.307*l,f+.201*l]).clipExtent([[s-.425*l+Ca,f+.12*l+Ca],[s-.214*l-Ca,f+.234*l-Ca]]).stream(c).point,u=a.translate([s-.205*l,f+.212*l]).clipExtent([[s-.214*l+Ca,f+.166*l+Ca],[s-.115*l-Ca,f+.234*l-Ca]]).stream(c).point,n},n.scale(1070)};var Rc,Dc,Pc,Uc,jc,Fc,Hc={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Dc=0,Hc.lineStart=Ve},polygonEnd:function(){Hc.lineStart=Hc.lineEnd=Hc.point=b,Rc+=ga(Dc/2)}},Oc={point:Xe,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Ic={point:We,lineStart:Je,lineEnd:Ge,polygonStart:function(){Ic.lineStart=Ke},polygonEnd:function(){Ic.point=We,Ic.lineStart=Je,Ic.lineEnd=Ge}};ta.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),ta.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Rc=0,ta.geo.stream(n,u(Hc)),Rc},n.centroid=function(n){return _c=wc=Sc=kc=Ec=Ac=Nc=Cc=zc=0,ta.geo.stream(n,u(Ic)),zc?[Nc/zc,Cc/zc]:Ac?[kc/Ac,Ec/Ac]:Sc?[_c/Sc,wc/Sc]:[0/0,0/0]},n.bounds=function(n){return jc=Fc=-(Pc=Uc=1/0),ta.geo.stream(n,u(Oc)),[[Pc,Uc],[jc,Fc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||tr(n):y,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new $e:new Qe(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(ta.geo.albersUsa()).context(null)},ta.geo.transform=function(n){return{stream:function(t){var e=new er(t);for(var r in n)e[r]=n[r];return e}}},er.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ta.geo.projection=ur,ta.geo.projectionMutator=ir,(ta.geo.equirectangular=function(){return ur(ar)}).raw=ar.invert=ar,ta.geo.rotation=function(n){function t(t){return t=n(t[0]*Da,t[1]*Da),t[0]*=Pa,t[1]*=Pa,t}return n=lr(n[0]%360*Da,n[1]*Da,n.length>2?n[2]*Da:0),t.invert=function(t){return t=n.invert(t[0]*Da,t[1]*Da),t[0]*=Pa,t[1]*=Pa,t},t},cr.invert=ar,ta.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=lr(-n[0]*Da,-n[1]*Da,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Pa,n[1]*=Pa}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=gr((t=+r)*Da,u*Da),n):t},n.precision=function(r){return arguments.length?(e=gr(t*Da,(u=+r)*Da),n):u},n.angle(90)},ta.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Da,u=n[1]*Da,i=t[1]*Da,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),l=Math.cos(u),s=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=l*s-c*f*a)*e),c*s+l*f*a)},ta.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ta.range(Math.ceil(i/d)*d,u,d).map(h).concat(ta.range(Math.ceil(l/m)*m,c,m).map(g)).concat(ta.range(Math.ceil(r/p)*p,e,p).filter(function(n){return ga(n%d)>Ca}).map(s)).concat(ta.range(Math.ceil(a/v)*v,o,v).filter(function(n){return ga(n%m)>Ca}).map(f))}var e,r,u,i,o,a,c,l,s,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(l).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],l=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),l>c&&(t=l,l=c,c=t),n.precision(y)):[[i,l],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,s=vr(a,o,90),f=dr(r,e,y),h=vr(l,c,90),g=dr(i,u,y),n):y},n.majorExtent([[-180,-90+Ca],[180,90-Ca]]).minorExtent([[-180,-80-Ca],[180,80+Ca]])},ta.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=mr,u=yr;return n.distance=function(){return ta.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},ta.geo.interpolate=function(n,t){return Mr(n[0]*Da,n[1]*Da,t[0]*Da,t[1]*Da)},ta.geo.length=function(n){return Yc=0,ta.geo.stream(n,Zc),Yc};var Yc,Zc={sphere:b,point:b,lineStart:xr,lineEnd:b,polygonStart:b,polygonEnd:b},Vc=br(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ta.geo.azimuthalEqualArea=function(){return ur(Vc)}).raw=Vc;var Xc=br(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},y);(ta.geo.azimuthalEquidistant=function(){return ur(Xc)}).raw=Xc,(ta.geo.conicConformal=function(){return Ye(_r)}).raw=_r,(ta.geo.conicEquidistant=function(){return Ye(wr)}).raw=wr;var $c=br(function(n){return 1/n},Math.atan);(ta.geo.gnomonic=function(){return ur($c)}).raw=$c,Sr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ra]},(ta.geo.mercator=function(){return kr(Sr)}).raw=Sr;var Bc=br(function(){return 1},Math.asin);(ta.geo.orthographic=function(){return ur(Bc)}).raw=Bc;var Wc=br(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ta.geo.stereographic=function(){return ur(Wc)}).raw=Wc,Er.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ra]},(ta.geo.transverseMercator=function(){var n=kr(Er),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Er,ta.geom={},ta.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=Et(e),i=Et(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(zr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var l=Cr(a),s=Cr(c),f=s[0]===l[0],h=s[s.length-1]===l[l.length-1],g=[];for(t=l.length-1;t>=0;--t)g.push(n[a[l[t]][2]]);for(t=+f;t=r&&l.x<=i&&l.y>=u&&l.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];s.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Ca)*Ca,y:Math.round(o(n,t)/Ca)*Ca,i:t}})}var r=Ar,u=Nr,i=r,o=u,a=ul;return n?t(n):(t.links=function(n){return iu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return iu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(Yr),c=-1,l=a.length,s=a[l-1].edge,f=s.l===o?s.r:s.l;++c=l,h=r>=s,g=h<<1|f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=su()),f?u=l:a=l,h?o=s:c=s,i(n,t,e,r,u,o,a,c)}var s,f,h,g,p,v,d,m,y,M=Et(a),x=Et(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)s=n[g],s.xm&&(m=s.x),s.y>y&&(y=s.y),f.push(s.x),h.push(s.y);else for(g=0;p>g;++g){var b=+M(s=n[g],g),_=+x(s,g);v>b&&(v=b),d>_&&(d=_),b>m&&(m=b),_>y&&(y=_),f.push(b),h.push(_)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=su();if(k.add=function(n){i(k,n,+M(n,++g),+x(n,g),v,d,m,y)},k.visit=function(n){fu(n,k,v,d,m,y)},k.find=function(n){return hu(k,n[0],n[1],v,d,m,y)},g=-1,null==t){for(;++g=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=cl.get(e)||al,r=ll.get(r)||y,Mu(r(e.apply(null,ea.call(arguments,1))))},ta.interpolateHcl=Lu,ta.interpolateHsl=Tu,ta.interpolateLab=Ru,ta.interpolateRound=Du,ta.transform=function(n){var t=ua.createElementNS(ta.ns.prefix.svg,"g");return(ta.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Pu(e?e.matrix:sl)})(n)},Pu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var sl={a:1,b:0,c:0,d:1,e:0,f:0};ta.interpolateTransform=Hu,ta.layout={},ta.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++ea*a/d){if(p>c){var l=t.charge/c;n.px-=i*l,n.py-=o*l}return!0}if(t.point&&c&&p>c){var l=t.pointCharge/c;n.px-=i*l,n.py-=o*l}}return!t.charge}}function t(n){n.px=ta.event.x,n.py=ta.event.y,a.resume()}var e,r,u,i,o,a={},c=ta.dispatch("start","tick","end"),l=[1,1],s=.9,f=fl,h=hl,g=-30,p=gl,v=.1,d=.64,m=[],M=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,y,x,b=m.length,_=M.length;for(e=0;_>e;++e)a=M[e],f=a.source,h=a.target,y=h.x-f.x,x=h.y-f.y,(p=y*y+x*x)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,y*=p,x*=p,h.x-=y*(d=f.weight/(h.weight+f.weight)),h.y-=x*d,f.x+=y*(d=1-d),f.y+=x*d);if((d=r*v)&&(y=l[0]/2,x=l[1]/2,e=-1,d))for(;++e0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),ta.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=M[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,l=o.length;++at;++t)(r=m[t]).index=t,r.weight=0;for(t=0;s>t;++t)r=M[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;s>t;++t)u[t]=+f.call(this,M[t],t);else for(t=0;s>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;s>t;++t)i[t]=+h.call(this,M[t],t);else for(t=0;s>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=ta.behavior.drag().origin(y).on("dragstart.force",Xu).on("drag.force",t).on("dragend.force",$u)),arguments.length?void this.on("mouseover.force",Bu).on("mouseout.force",Wu).call(e):e},ta.rebind(a,c,"on")};var fl=20,hl=1,gl=1/0;ta.layout.hierarchy=function(){function n(u){var i,o=[u],a=[];for(u.depth=0;null!=(i=o.pop());)if(a.push(i),(l=e.call(n,i,i.depth))&&(c=l.length)){for(var c,l,s;--c>=0;)o.push(s=l[c]),s.parent=i,s.depth=i.depth+1;r&&(i.value=0),i.children=l}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return Qu(u,function(n){var e,u;t&&(e=n.children)&&e.sort(t),r&&(u=n.parent)&&(u.value+=n.value)}),a}var t=ei,e=ni,r=ti;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(Ku(t,function(n){n.children&&(n.value=0)}),Qu(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ta.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,l=-1;for(r=t.value?r/t.value:0;++lf?-1:1),p=(f-c*g)/ta.sum(l),v=ta.range(c),d=[];return null!=e&&v.sort(e===pl?function(n,t){return l[t]-l[n]}:function(n,t){return e(o[n],o[t])}),v.forEach(function(n){d[n]={data:o[n],value:a=l[n],startAngle:s,endAngle:s+=a*p+g,padAngle:h}}),d}var t=Number,e=pl,r=0,u=La,i=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n.padAngle=function(t){return arguments.length?(i=t,n):i},n};var pl={};ta.layout.stack=function(){function n(a,c){if(!(h=a.length))return a;var l=a.map(function(e,r){return t.call(n,e,r)}),s=l.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,s,c);l=ta.permute(l,f),s=ta.permute(s,f);var h,g,p,v,d=r.call(n,s,c),m=l[0].length;for(p=0;m>p;++p)for(u.call(n,l[0][p],v=d[p],s[0][p][1]),g=1;h>g;++g)u.call(n,l[g][p],v+=s[g-1][p][1],s[g][p][1]);return a}var t=y,e=ai,r=ci,u=oi,i=ui,o=ii;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:vl.get(t)||ai,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:dl.get(t)||ci,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var vl=ta.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(li),i=n.map(si),o=ta.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,l=[],s=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],l.push(e)):(c+=i[e],s.push(e));return s.reverse().concat(l)},reverse:function(n){return ta.range(n.length).reverse()},"default":ai}),dl=ta.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,l,s=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=l=0,e=1;h>e;++e){for(t=0,u=0;s>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];s>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,l>c&&(l=c)}for(e=0;h>e;++e)g[e]-=l;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ci});ta.layout.histogram=function(){function n(n,i){for(var o,a,c=[],l=n.map(e,this),s=r.call(this,l,i),f=u.call(this,s,l,i),i=-1,h=l.length,g=f.length-1,p=t?1:1/h;++i0)for(i=-1;++i=s[0]&&a<=s[1]&&(o=c[ta.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=pi,u=hi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=Et(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return gi(n,t)}:Et(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ta.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],l=u[1],s=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,Qu(a,function(n){n.r=+s(n.value)}),Qu(a,Mi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/l))/2;Qu(a,function(n){n.r+=f}),Qu(a,Mi),Qu(a,function(n){n.r-=f})}return _i(a,c/2,l/2,t?1:1/Math.max(2*a.r/c,2*a.r/l)),o}var t,e=ta.layout.hierarchy().sort(vi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Gu(n,e)},ta.layout.tree=function(){function n(n,u){var s=o.call(this,n,u),f=s[0],h=t(f);if(Qu(h,e),h.parent.m=-h.z,Ku(h,r),l)Ku(f,i);else{var g=f,p=f,v=f;Ku(f,function(n){n.xp.x&&(p=n),n.depth>v.depth&&(v=n)});var d=a(g,p)/2-g.x,m=c[0]/(p.x+a(p,g)/2+d),y=c[1]/(v.depth||1);Ku(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return s}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,o=0,a=i.length;a>o;++o)r.push((i[o]=u={_:i[o],parent:t,children:(u=i[o].children)&&u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Ni(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-i):n.z=i}else r&&(n.z=r.z+a(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,o=t,c=u.parent.children[0],l=u.m,s=i.m,f=o.m,h=c.m;o=Ei(o),u=ki(u),o&&u;)c=ki(c),i=Ei(i),i.a=n,r=o.z+f-u.z-l+a(o._,u._),r>0&&(Ai(Ci(o,n,e),n,r),l+=r,s+=r),f+=o.m,l+=u.m,h+=c.m,s+=i.m;o&&!Ei(i)&&(i.t=o,i.m+=f-s),u&&!ki(c)&&(c.t=u,c.m+=l-h,e=n)}return e}function i(n){n.x*=c[0],n.y=n.depth*c[1]}var o=ta.layout.hierarchy().sort(null).value(null),a=Si,c=[1,1],l=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(l=null==(c=t)?i:null,n):l?null:c},n.nodeSize=function(t){return arguments.length?(l=null==(c=t)?null:i,n):l?c:null},Gu(n,o)},ta.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],l=0;Qu(c,function(n){var t=n.children;t&&t.length?(n.x=qi(t),n.y=zi(t)):(n.x=o?l+=e(n,o):0,n.y=0,o=n)});var s=Li(c),f=Ti(c),h=s.x-e(s,f)/2,g=f.x+e(f,s)/2;return Qu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=ta.layout.hierarchy().sort(null).value(null),e=Si,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Gu(n,t)},ta.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++ut?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,l=f(e),s=[],h=i.slice(),p=1/0,v="slice"===g?l.dx:"dice"===g?l.dy:"slice-dice"===g?1&e.depth?l.dy:l.dx:Math.min(l.dx,l.dy);for(n(h,l.dx*l.dy/e.value),s.area=0;(c=h.length)>0;)s.push(o=h[c-1]),s.area+=o.area,"squarify"!==g||(a=r(s,v))<=p?(h.pop(),p=a):(s.area-=s.pop().area,u(s,v,l,!1),v=Math.min(l.dx,l.dy),s.length=s.area=0,p=1/0);s.length&&(u(s,v,l,!0),s.length=s.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++oe&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,l=e.y,s=t?c(n.area/t):0;if(t==e.dx){for((r||s>e.dy)&&(s=e.dy);++ie.dx)&&(s=e.dx);++ie&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=ta.random.normal.apply(ta,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ta.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ta.scale={};var ml={floor:y,ceil:y};ta.scale.linear=function(){return Ii([0,1],[0,1],mu,!1)};var yl={s:1,g:1,p:1,r:1,e:1};ta.scale.log=function(){return Ji(ta.scale.linear().domain([0,1]),10,!0,[1,10])};var Ml=ta.format(".0e"),xl={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ta.scale.pow=function(){return Gi(ta.scale.linear(),1,[0,1])},ta.scale.sqrt=function(){return ta.scale.pow().exponent(.5)},ta.scale.ordinal=function(){return Qi([],{t:"range",a:[[]]})},ta.scale.category10=function(){return ta.scale.ordinal().range(bl)},ta.scale.category20=function(){return ta.scale.ordinal().range(_l)},ta.scale.category20b=function(){return ta.scale.ordinal().range(wl)},ta.scale.category20c=function(){return ta.scale.ordinal().range(Sl)};var bl=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(Mt),_l=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(Mt),wl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(Mt),Sl=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(Mt);ta.scale.quantile=function(){return no([],[])},ta.scale.quantize=function(){return to(0,1,[0,1])},ta.scale.threshold=function(){return eo([.5],[0,1])},ta.scale.identity=function(){return ro([0,1])},ta.svg={},ta.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),l=Math.max(0,+r.apply(this,arguments)),s=o.apply(this,arguments)-Ra,f=a.apply(this,arguments)-Ra,h=Math.abs(f-s),g=s>f?0:1;if(n>l&&(p=l,l=n,n=p),h>=Ta)return t(l,g)+(n?t(n,1-g):"")+"Z";var p,v,d,m,y,M,x,b,_,w,S,k,E=0,A=0,N=[];if((m=(+c.apply(this,arguments)||0)/2)&&(d=i===kl?Math.sqrt(n*n+l*l):+i.apply(this,arguments),g||(A*=-1),l&&(A=tt(d/l*Math.sin(m))),n&&(E=tt(d/n*Math.sin(m)))),l){y=l*Math.cos(s+A),M=l*Math.sin(s+A),x=l*Math.cos(f-A),b=l*Math.sin(f-A);var C=Math.abs(f-s-2*A)<=qa?0:1;if(A&&so(y,M,x,b)===g^C){var z=(s+f)/2;y=l*Math.cos(z),M=l*Math.sin(z),x=b=null}}else y=M=0;if(n){_=n*Math.cos(f-E),w=n*Math.sin(f-E),S=n*Math.cos(s+E),k=n*Math.sin(s+E);var q=Math.abs(s-f+2*E)<=qa?0:1;if(E&&so(_,w,S,k)===1-g^q){var L=(s+f)/2;_=n*Math.cos(L),w=n*Math.sin(L),S=k=null}}else _=w=0;if((p=Math.min(Math.abs(l-n)/2,+u.apply(this,arguments)))>.001){v=l>n^g?0:1;var T=null==S?[_,w]:null==x?[y,M]:Lr([y,M],[S,k],[x,b],[_,w]),R=y-T[0],D=M-T[1],P=x-T[0],U=b-T[1],j=1/Math.sin(Math.acos((R*P+D*U)/(Math.sqrt(R*R+D*D)*Math.sqrt(P*P+U*U)))/2),F=Math.sqrt(T[0]*T[0]+T[1]*T[1]);if(null!=x){var H=Math.min(p,(l-F)/(j+1)),O=fo(null==S?[_,w]:[S,k],[y,M],l,H,g),I=fo([x,b],[_,w],l,H,g);p===H?N.push("M",O[0],"A",H,",",H," 0 0,",v," ",O[1],"A",l,",",l," 0 ",1-g^so(O[1][0],O[1][1],I[1][0],I[1][1]),",",g," ",I[1],"A",H,",",H," 0 0,",v," ",I[0]):N.push("M",O[0],"A",H,",",H," 0 1,",v," ",I[0])}else N.push("M",y,",",M);if(null!=S){var Y=Math.min(p,(n-F)/(j-1)),Z=fo([y,M],[S,k],n,-Y,g),V=fo([_,w],null==x?[y,M]:[x,b],n,-Y,g);p===Y?N.push("L",V[0],"A",Y,",",Y," 0 0,",v," ",V[1],"A",n,",",n," 0 ",g^so(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-g," ",Z[1],"A",Y,",",Y," 0 0,",v," ",Z[0]):N.push("L",V[0],"A",Y,",",Y," 0 0,",v," ",Z[0])}else N.push("L",_,",",w)}else N.push("M",y,",",M),null!=x&&N.push("A",l,",",l," 0 ",C,",",g," ",x,",",b),N.push("L",_,",",w),null!=S&&N.push("A",n,",",n," 0 ",q,",",1-g," ",S,",",k);return N.push("Z"),N.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=io,r=oo,u=uo,i=kl,o=ao,a=co,c=lo;return n.innerRadius=function(t){return arguments.length?(e=Et(t),n):e},n.outerRadius=function(t){return arguments.length?(r=Et(t),n):r},n.cornerRadius=function(t){return arguments.length?(u=Et(t),n):u},n.padRadius=function(t){return arguments.length?(i=t==kl?kl:Et(t),n):i},n.startAngle=function(t){return arguments.length?(o=Et(t),n):o},n.endAngle=function(t){return arguments.length?(a=Et(t),n):a},n.padAngle=function(t){return arguments.length?(c=Et(t),n):c},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-Ra;return[Math.cos(t)*n,Math.sin(t)*n]},n};var kl="auto";ta.svg.line=function(){return ho(y)};var El=ta.map({linear:go,"linear-closed":po,step:vo,"step-before":mo,"step-after":yo,basis:So,"basis-open":ko,"basis-closed":Eo,bundle:Ao,cardinal:bo,"cardinal-open":Mo,"cardinal-closed":xo,monotone:To});El.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Al=[0,2/3,1/3,0],Nl=[0,1/3,2/3,0],Cl=[0,1/6,2/3,1/6];ta.svg.line.radial=function(){var n=ho(Ro);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},mo.reverse=yo,yo.reverse=mo,ta.svg.area=function(){return Do(y)},ta.svg.area.radial=function(){var n=Do(Ro);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ta.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),l=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,l)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,l.r,l.p0)+r(l.r,l.p1,l.a1-l.a0)+u(l.r,l.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)-Ra,s=l.call(n,u,r)-Ra;return{r:i,a0:o,a1:s,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(s),i*Math.sin(s)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>qa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=mr,o=yr,a=Po,c=ao,l=co;return n.radius=function(t){return arguments.length?(a=Et(t),n):a},n.source=function(t){return arguments.length?(i=Et(t),n):i},n.target=function(t){return arguments.length?(o=Et(t),n):o},n.startAngle=function(t){return arguments.length?(c=Et(t),n):c},n.endAngle=function(t){return arguments.length?(l=Et(t),n):l},n},ta.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=mr,e=yr,r=Uo;return n.source=function(e){return arguments.length?(t=Et(e),n):t},n.target=function(t){return arguments.length?(e=Et(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ta.svg.diagonal.radial=function(){var n=ta.svg.diagonal(),t=Uo,e=n.projection;return n.projection=function(n){return arguments.length?e(jo(t=n)):t},n},ta.svg.symbol=function(){function n(n,r){return(zl.get(t.call(this,n,r))||Oo)(e.call(this,n,r))}var t=Ho,e=Fo;return n.type=function(e){return arguments.length?(t=Et(e),n):t},n.size=function(t){return arguments.length?(e=Et(t),n):e},n};var zl=ta.map({circle:Oo,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Ll)),e=t*Ll;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/ql),e=t*ql/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/ql),e=t*ql/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ta.svg.symbolTypes=zl.keys();var ql=Math.sqrt(3),Ll=Math.tan(30*Da);_a.transition=function(n){for(var t,e,r=Tl||++Ul,u=Xo(n),i=[],o=Rl||{time:Date.now(),ease:Su,delay:0,duration:250},a=-1,c=this.length;++ai;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Yo(u,this.namespace,this.id)},Pl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(u){u[r][e].tween.set(n,t)})},Pl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Hu:mu,a=ta.ns.qualify(n);return Zo(this,"attr."+n,t,a.local?i:u)},Pl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=ta.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Pl.style=function(n,e,r){function u(){this.style.removeProperty(n)}function i(e){return null==e?u:(e+="",function(){var u,i=t(this).getComputedStyle(this,null).getPropertyValue(n);return i!==e&&(u=mu(i,e),function(t){this.style.setProperty(n,u(t),r)})})}var o=arguments.length;if(3>o){if("string"!=typeof n){2>o&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Zo(this,"style."+n,e,i)},Pl.styleTween=function(n,e,r){function u(u,i){var o=e.call(this,u,i,t(this).getComputedStyle(this,null).getPropertyValue(n));return o&&function(t){this.style.setProperty(n,o(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,u)},Pl.text=function(n){return Zo(this,"text",n,Vo)},Pl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Pl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ta.ease.apply(ta,arguments)),Y(this,function(r){r[e][t].ease=n}))},Pl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,u,i){r[e][t].delay=+n.call(r,r.__data__,u,i)}:(n=+n,function(r){r[e][t].delay=n}))},Pl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,u,i){r[e][t].duration=Math.max(1,n.call(r,r.__data__,u,i))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Pl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var u=Rl,i=Tl;try{Tl=e,Y(this,function(t,u,i){Rl=t[r][e],n.call(t,t.__data__,u,i)})}finally{Rl=u,Tl=i}}else Y(this,function(u){var i=u[r][e];(i.event||(i.event=ta.dispatch("start","end","interrupt"))).on(n,t)});return this},Pl.transition=function(){for(var n,t,e,r,u=this.id,i=++Ul,o=this.namespace,a=[],c=0,l=this.length;l>c;c++){a.push(n=[]);for(var t=this[c],s=0,f=t.length;f>s;s++)(e=t[s])&&(r=e[o][u],$o(e,s,o,i,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Yo(a,o,i)},ta.svg.axis=function(){function n(n){n.each(function(){var n,l=ta.select(this),s=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):y:t,p=l.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Ca),d=ta.transition(p.exit()).style("opacity",Ca).remove(),m=ta.transition(p.order()).style("opacity",1),M=Math.max(u,0)+o,x=Ui(f),b=l.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),ta.transition(b));v.append("line"),v.append("text");var w,S,k,E,A=v.select("line"),N=m.select("line"),C=p.select("text").text(g),z=v.select("text"),q=m.select("text"),L="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=Bo,w="x",k="y",S="x2",E="y2",C.attr("dy",0>L?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+L*i+"V0H"+x[1]+"V"+L*i)):(n=Wo,w="y",k="x",S="y2",E="x2",C.attr("dy",".32em").style("text-anchor",0>L?"end":"start"),_.attr("d","M"+L*i+","+x[0]+"H0V"+x[1]+"H"+L*i)),A.attr(E,L*u),z.attr(k,L*M),N.attr(S,0).attr(E,L*u),q.attr(w,0).attr(k,L*M),f.rangeBand){var T=f,R=T.rangeBand()/2;s=f=function(n){return T(n)+R}}else s.rangeBand?s=f:d.call(n,f,s);v.call(n,s,f),m.call(n,f,f)})}var t,e=ta.scale.linear(),r=jl,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Fl?t+"":jl,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var jl="bottom",Fl={top:1,right:1,bottom:1,left:1};ta.svg.brush=function(){function n(t){t.each(function(){var t=ta.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",i).on("touchstart.brush",i),o=t.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=t.selectAll(".resize").data(v,y);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Hl[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var c,f=ta.transition(t),h=ta.transition(o);l&&(c=Ui(l),h.attr("x",c[0]).attr("width",c[1]-c[0]),r(f)),s&&(c=Ui(s),h.attr("y",c[0]).attr("height",c[1]-c[0]),u(f)),e(f)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+f[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",f[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",f[1]-f[0])}function u(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function i(){function i(){32==ta.event.keyCode&&(C||(M=null,q[0]-=f[1],q[1]-=h[1],C=2),S())}function v(){32==ta.event.keyCode&&2==C&&(q[0]+=f[1],q[1]+=h[1],C=0,S())}function d(){var n=ta.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(ta.event.altKey?(M||(M=[(f[0]+f[1])/2,(h[0]+h[1])/2]),q[0]=f[+(n[0]s?(u=r,r=s):u=s),v[0]!=r||v[1]!=u?(e?a=null:o=null,v[0]=r,v[1]=u,!0):void 0}function y(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ta.select("body").style("cursor",null),L.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=ta.select(ta.event.target),w=c.of(b,arguments),k=ta.select(b),E=_.datum(),A=!/^(n|s)$/.test(E)&&l,N=!/^(e|w)$/.test(E)&&s,C=_.classed("extent"),z=W(b),q=ta.mouse(b),L=ta.select(t(b)).on("keydown.brush",i).on("keyup.brush",v);if(ta.event.changedTouches?L.on("touchmove.brush",d).on("touchend.brush",y):L.on("mousemove.brush",d).on("mouseup.brush",y),k.interrupt().selectAll("*").interrupt(),C)q[0]=f[0]-q[0],q[1]=h[0]-q[1];else if(E){var T=+/w$/.test(E),R=+/^n/.test(E);x=[f[1-T]-q[0],h[1-R]-q[1]],q[0]=f[T],q[1]=h[R]}else ta.event.altKey&&(M=q.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),ta.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var o,a,c=E(n,"brushstart","brush","brushend"),l=null,s=null,f=[0,0],h=[0,0],g=!0,p=!0,v=Ol[0];return n.event=function(n){n.each(function(){var n=c.of(this,arguments),t={x:f,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Tl?ta.select(this).transition().each("start.brush",function(){o=e.i,a=e.j,f=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=yu(f,t.x),r=yu(h,t.y);return o=a=null,function(u){f=t.x=e(u),h=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){o=t.i,a=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(l=t,v=Ol[!l<<1|!s],n):l},n.y=function(t){return arguments.length?(s=t,v=Ol[!l<<1|!s],n):s},n.clamp=function(t){return arguments.length?(l&&s?(g=!!t[0],p=!!t[1]):l?g=!!t:s&&(p=!!t),n):l&&s?[g,p]:l?g:s?p:null},n.extent=function(t){var e,r,u,i,c;return arguments.length?(l&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),o=[e,r],l.invert&&(e=l(e),r=l(r)),e>r&&(c=e,e=r,r=c),(e!=f[0]||r!=f[1])&&(f=[e,r])),s&&(u=t[0],i=t[1],l&&(u=u[1],i=i[1]),a=[u,i],s.invert&&(u=s(u),i=s(i)),u>i&&(c=u,u=i,i=c),(u!=h[0]||i!=h[1])&&(h=[u,i])),n):(l&&(o?(e=o[0],r=o[1]):(e=f[0],r=f[1],l.invert&&(e=l.invert(e),r=l.invert(r)),e>r&&(c=e,e=r,r=c))),s&&(a?(u=a[0],i=a[1]):(u=h[0],i=h[1],s.invert&&(u=s.invert(u),i=s.invert(i)),u>i&&(c=u,u=i,i=c))),l&&s?[[e,u],[r,i]]:l?[e,r]:s&&[u,i])},n.clear=function(){return n.empty()||(f=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!l&&f[0]==f[1]||!!s&&h[0]==h[1]},ta.rebind(n,c,"on")};var Hl={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Ol=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Il=ac.format=gc.timeFormat,Yl=Il.utc,Zl=Yl("%Y-%m-%dT%H:%M:%S.%LZ");Il.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Jo:Zl,Jo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Jo.toString=Zl.toString,ac.second=Ft(function(n){return new cc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ac.seconds=ac.second.range,ac.seconds.utc=ac.second.utc.range,ac.minute=Ft(function(n){return new cc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ac.minutes=ac.minute.range,ac.minutes.utc=ac.minute.utc.range,ac.hour=Ft(function(n){var t=n.getTimezoneOffset()/60;return new cc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ac.hours=ac.hour.range,ac.hours.utc=ac.hour.utc.range,ac.month=Ft(function(n){return n=ac.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ac.months=ac.month.range,ac.months.utc=ac.month.utc.range;var Vl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Xl=[[ac.second,1],[ac.second,5],[ac.second,15],[ac.second,30],[ac.minute,1],[ac.minute,5],[ac.minute,15],[ac.minute,30],[ac.hour,1],[ac.hour,3],[ac.hour,6],[ac.hour,12],[ac.day,1],[ac.day,2],[ac.week,1],[ac.month,1],[ac.month,3],[ac.year,1]],$l=Il.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",Ne]]),Bl={range:function(n,t,e){return ta.range(Math.ceil(n/e)*e,+t,e).map(Ko)},floor:y,ceil:y};Xl.year=ac.year,ac.scale=function(){return Go(ta.scale.linear(),Xl,$l)};var Wl=Xl.map(function(n){return[n[0].utc,n[1]]}),Jl=Yl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",Ne]]);Wl.year=ac.year.utc,ac.scale.utc=function(){return Go(ta.scale.linear(),Wl,Jl)},ta.text=At(function(n){return n.responseText}),ta.json=function(n,t){return Nt(n,"application/json",Qo,t)},ta.html=function(n,t){return Nt(n,"text/html",na,t)},ta.xml=At(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(ta):"object"==typeof module&&module.exports&&(module.exports=ta),this.d3=ta}();/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl - * Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT - * */ - -!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document);/*! - -Holder - client side image placeholders -Version 2.7.1+6hydf -© 2015 Ivan Malopinsky - http://imsky.co - -Site: http://holderjs.com -Issues: https://github.com/imsky/holder/issues -License: http://opensource.org/licenses/MIT - -*/ -!function(a){if(a.document){var b=a.document;b.querySelectorAll||(b.querySelectorAll=function(c){var d,e=b.createElement("style"),f=[];for(b.documentElement.firstChild.appendChild(e),b._qsa=[],e.styleSheet.cssText=c+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",a.scrollBy(0,0),e.parentNode.removeChild(e);b._qsa.length;)d=b._qsa.shift(),d.style.removeAttribute("x-qsa"),f.push(d);return b._qsa=null,f}),b.querySelector||(b.querySelector=function(a){var c=b.querySelectorAll(a);return c.length?c[0]:null}),b.getElementsByClassName||(b.getElementsByClassName=function(a){return a=String(a).replace(/^|\s+/g,"."),b.querySelectorAll(a)}),Object.keys||(Object.keys=function(a){if(a!==Object(a))throw TypeError("Object.keys called on non-object");var b,c=[];for(b in a)Object.prototype.hasOwnProperty.call(a,b)&&c.push(b);return c}),function(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";a.atob=a.atob||function(a){a=String(a);var c,d=0,e=[],f=0,g=0;if(a=a.replace(/\s/g,""),a.length%4===0&&(a=a.replace(/=+$/,"")),a.length%4===1)throw Error("InvalidCharacterError");if(/[^+/0-9A-Za-z]/.test(a))throw Error("InvalidCharacterError");for(;d>16&255)),e.push(String.fromCharCode(f>>8&255)),e.push(String.fromCharCode(255&f)),g=0,f=0),d+=1;return 12===g?(f>>=4,e.push(String.fromCharCode(255&f))):18===g&&(f>>=2,e.push(String.fromCharCode(f>>8&255)),e.push(String.fromCharCode(255&f))),e.join("")},a.btoa=a.btoa||function(a){a=String(a);var c,d,e,f,g,h,i,j=0,k=[];if(/[^\x00-\xFF]/.test(a))throw Error("InvalidCharacterError");for(;j>2,g=(3&c)<<4|d>>4,h=(15&d)<<2|e>>6,i=63&e,j===a.length+2?(h=64,i=64):j===a.length+1&&(i=64),k.push(b.charAt(f),b.charAt(g),b.charAt(h),b.charAt(i));return k.join("")}}(a),Object.prototype.hasOwnProperty||(Object.prototype.hasOwnProperty=function(a){var b=this.__proto__||this.constructor.prototype;return a in this&&(!(a in b)||b[a]!==this[a])}),function(){if("performance"in a==!1&&(a.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in a.performance==!1){var b=Date.now();performance.timing&&performance.timing.navigationStart&&(b=performance.timing.navigationStart),a.performance.now=function(){return Date.now()-b}}}(),a.requestAnimationFrame||(a.webkitRequestAnimationFrame?!function(a){a.requestAnimationFrame=function(b){return webkitRequestAnimationFrame(function(){b(a.performance.now())})},a.cancelAnimationFrame=webkitCancelAnimationFrame}(a):a.mozRequestAnimationFrame?!function(a){a.requestAnimationFrame=function(b){return mozRequestAnimationFrame(function(){b(a.performance.now())})},a.cancelAnimationFrame=mozCancelAnimationFrame}(a):!function(a){a.requestAnimationFrame=function(b){return a.setTimeout(b,1e3/60)},a.cancelAnimationFrame=a.clearTimeout}(a))}}(this),function(a,b){"object"==typeof exports&&"object"==typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):"object"==typeof exports?exports.Holder=b():a.Holder=b()}(this,function(){return function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p="",b(0)}([function(a,b,c){(function(b){function d(a,b,c,d){var f=e(c.substr(c.lastIndexOf(a.domain)),a);f&&h({mode:null,el:d,flags:f,engineSettings:b})}function e(a,b){var c={theme:B(J.settings.themes.gray,null),stylesheets:b.stylesheets,instanceOptions:b};return a.match(/([\d]+p?)x([\d]+p?)(?:\?|$)/)?f(a,c):g(a,c)}function f(a,b){var c=a.split("?"),d=c[0].split("/");b.holderURL=a;var e=d[1],f=e.match(/([\d]+p?)x([\d]+p?)/);if(!f)return!1;if(b.fluid=-1!==e.indexOf("p"),b.dimensions={width:f[1].replace("p","%"),height:f[2].replace("p","%")},2===c.length){var g=A.parse(c[1]);if(g.bg&&(b.theme.background=(-1===g.bg.indexOf("#")?"#":"")+g.bg),g.fg&&(b.theme.foreground=(-1===g.fg.indexOf("#")?"#":"")+g.fg),g.theme&&b.instanceOptions.themes.hasOwnProperty(g.theme)&&(b.theme=B(b.instanceOptions.themes[g.theme],null)),g.text&&(b.text=g.text),g.textmode&&(b.textmode=g.textmode),g.size&&(b.size=g.size),g.font&&(b.font=g.font),g.align&&(b.align=g.align),b.nowrap=z.truthy(g.nowrap),b.auto=z.truthy(g.auto),z.truthy(g.random)){J.vars.cache.themeKeys=J.vars.cache.themeKeys||Object.keys(b.instanceOptions.themes);var h=J.vars.cache.themeKeys[0|Math.random()*J.vars.cache.themeKeys.length];b.theme=B(b.instanceOptions.themes[h],null)}}return b}function g(a,b){var c=!1,d=String.fromCharCode(11),e=a.replace(/([^\\])\//g,"$1"+d).split(d),f=/%[0-9a-f]{2}/gi,g=b.instanceOptions;b.holderURL=[];for(var h=e.length,i=0;h>i;i++){var j=e[i];if(j.match(f))try{j=decodeURIComponent(j)}catch(k){j=e[i]}var l=!1;if(J.flags.dimensions.match(j))c=!0,b.dimensions=J.flags.dimensions.output(j),l=!0;else if(J.flags.fluid.match(j))c=!0,b.dimensions=J.flags.fluid.output(j),b.fluid=!0,l=!0;else if(J.flags.textmode.match(j))b.textmode=J.flags.textmode.output(j),l=!0;else if(J.flags.colors.match(j)){var m=J.flags.colors.output(j);b.theme=B(b.theme,m),l=!0}else if(g.themes[j])g.themes.hasOwnProperty(j)&&(b.theme=B(g.themes[j],null)),l=!0;else if(J.flags.font.match(j))b.font=J.flags.font.output(j),l=!0;else if(J.flags.auto.match(j))b.auto=!0,l=!0;else if(J.flags.text.match(j))b.text=J.flags.text.output(j),l=!0;else if(J.flags.size.match(j))b.size=J.flags.size.output(j),l=!0;else if(J.flags.random.match(j)){null==J.vars.cache.themeKeys&&(J.vars.cache.themeKeys=Object.keys(g.themes));var n=J.vars.cache.themeKeys[0|Math.random()*J.vars.cache.themeKeys.length];b.theme=B(g.themes[n],null),l=!0}l&&b.holderURL.push(j)}return b.holderURL.unshift(g.domain),b.holderURL=b.holderURL.join("/"),c?b:!1}function h(a){var b=a.mode,c=a.el,d=a.flags,e=a.engineSettings,f=d.dimensions,g=d.theme,h=f.width+"x"+f.height;if(b=null==b?d.fluid?"fluid":"image":b,null!=d.text&&(g.text=d.text,"object"===c.nodeName.toLowerCase())){for(var j=g.text.split("\\n"),k=0;k1){var n,o=0,p=0,q=0;j=new e.Group("line"+q),("left"===a.align||"right"===a.align)&&(m=a.width*(1-2*(1-J.setup.lineWrapRatio)));for(var r=0;r=m||t===!0)&&(b(g,j,o,g.properties.leading),g.add(j),o=0,p+=g.properties.leading,q+=1,j=new e.Group("line"+q),j.y=p),t!==!0&&(i.moveTo(o,0),o+=h.spaceWidth+s.width,j.add(i))}if(b(g,j,o,g.properties.leading),g.add(j),"left"===a.align)g.moveTo(a.width-l,null,null);else if("right"===a.align){for(n in g.children)j=g.children[n],j.moveTo(a.width-j.width,null,null);g.moveTo(0-(a.width-l),null,null)}else{for(n in g.children)j=g.children[n],j.moveTo((g.width-j.width)/2,null,null);g.moveTo((a.width-g.width)/2,null,null)}g.moveTo(null,(a.height-g.height)/2,null),(a.height-g.height)/2<0&&g.moveTo(null,0,null)}else i=new e.Text(a.text),j=new e.Group("line0"),j.add(i),g.add(j),"left"===a.align?g.moveTo(a.width-l,null,null):"right"===a.align?g.moveTo(0-(a.width-l),null,null):g.moveTo((a.width-h.boundingBox.width)/2,null,null),g.moveTo(null,(a.height-h.boundingBox.height)/2,null);return d}function k(a,b,c){var d=parseInt(a,10),e=parseInt(b,10),f=Math.max(d,e),g=Math.min(d,e),h=.8*Math.min(g,f*J.defaults.scale);return Math.round(Math.max(c,h))}function l(a){var b;b=null==a||null==a.nodeType?J.vars.resizableImages:[a];for(var c=0,d=b.length;d>c;c++){var e=b[c];if(e.holderData){var f=e.holderData.flags,g=D(e);if(g){if(!e.holderData.resizeUpdate)continue;if(f.fluid&&f.auto){var h=e.holderData.fluidConfig;switch(h.mode){case"width":g.height=g.width/h.ratio;break;case"height":g.width=g.height*h.ratio}}var j={mode:"image",holderSettings:{dimensions:g,theme:f.theme,flags:f},el:e,engineSettings:e.holderData.engineSettings};"exact"==f.textmode&&(f.exactDimensions=g,j.holderSettings.dimensions=f.dimensions),i(j)}else p(e)}}}function m(a){if(a.holderData){var b=D(a);if(b){var c=a.holderData.flags,d={fluidHeight:"%"==c.dimensions.height.slice(-1),fluidWidth:"%"==c.dimensions.width.slice(-1),mode:null,initialDimensions:b};d.fluidWidth&&!d.fluidHeight?(d.mode="width",d.ratio=d.initialDimensions.width/parseFloat(c.dimensions.height)):!d.fluidWidth&&d.fluidHeight&&(d.mode="height",d.ratio=parseFloat(c.dimensions.width)/d.initialDimensions.height),a.holderData.fluidConfig=d}else p(a)}}function n(){for(var a,c=[],d=Object.keys(J.vars.invisibleImages),e=0,f=d.length;f>e;e++)a=J.vars.invisibleImages[d[e]],D(a)&&"img"==a.nodeName.toLowerCase()&&(c.push(a),delete J.vars.invisibleImages[d[e]]);c.length&&I.run({images:c}),b.requestAnimationFrame(n)}function o(){J.vars.visibilityCheckStarted||(b.requestAnimationFrame(n),J.vars.visibilityCheckStarted=!0)}function p(a){a.holderData.invisibleId||(J.vars.invisibleId+=1,J.vars.invisibleImages["i"+J.vars.invisibleId]=a,a.holderData.invisibleId=J.vars.invisibleId)}function q(a,b){return null==b?document.createElement(a):document.createElementNS(b,a)}function r(a,b){for(var c in b)a.setAttribute(c,b[c])}function s(a,b,c){var d,e;null==a?(a=q("svg",E),d=q("defs",E),e=q("style",E),r(e,{type:"text/css"}),d.appendChild(e),a.appendChild(d)):e=a.querySelector("style"),a.webkitMatchesSelector&&a.setAttribute("xmlns",E);for(var f=0;f=0;h--){var i=g.createProcessingInstruction("xml-stylesheet",'href="'+f[h]+'" rel="stylesheet"');g.insertBefore(i,g.firstChild)}g.removeChild(g.documentElement),e=d.serializeToString(g)}var j=d.serializeToString(a);return j=j.replace(/\&(\#[0-9]{2,}\;)/g,"&$1"),e+j}}function u(){return b.DOMParser?(new DOMParser).parseFromString("","application/xml"):void 0}function v(a){J.vars.debounceTimer||a.call(this),J.vars.debounceTimer&&b.clearTimeout(J.vars.debounceTimer),J.vars.debounceTimer=b.setTimeout(function(){J.vars.debounceTimer=null,a.call(this)},J.setup.debounce)}function w(){v(function(){l(null)})}var x=c(1),y=c(2),z=c(3),A=c(4),B=z.extend,C=z.getNodeArray,D=z.dimensionCheck,E="http://www.w3.org/2000/svg",F=8,G="2.7.1",H="\nCreated with Holder.js "+G+".\nLearn more at http://holderjs.com\n(c) 2012-2015 Ivan Malopinsky - http://imsky.co\n",I={version:G,addTheme:function(a,b){return null!=a&&null!=b&&(J.settings.themes[a]=b),delete J.vars.cache.themeKeys,this},addImage:function(a,b){var c=document.querySelectorAll(b);if(c.length)for(var d=0,e=c.length;e>d;d++){var f=q("img"),g={};g[J.vars.dataAttr]=a,r(f,g),c[d].appendChild(f)}return this},setResizeUpdate:function(a,b){a.holderData&&(a.holderData.resizeUpdate=!!b,a.holderData.resizeUpdate&&l(a))},run:function(a){a=a||{};var c={},f=B(J.settings,a);J.vars.preempted=!0,J.vars.dataAttr=f.dataAttr||J.vars.dataAttr,c.renderer=f.renderer?f.renderer:J.setup.renderer,-1===J.setup.renderers.join(",").indexOf(c.renderer)&&(c.renderer=J.setup.supportsSVG?"svg":J.setup.supportsCanvas?"canvas":"html");var g=C(f.images),i=C(f.bgnodes),j=C(f.stylenodes),k=C(f.objects);c.stylesheets=[],c.svgXMLStylesheet=!0,c.noFontFallback=f.noFontFallback?f.noFontFallback:!1;for(var l=0;l1){c.nodeValue="";for(var u=0;u=0?b:1)}function f(a){v?e(a):w.push(a)}null==document.readyState&&document.addEventListener&&(document.addEventListener("DOMContentLoaded",function y(){document.removeEventListener("DOMContentLoaded",y,!1),document.readyState="complete"},!1),document.readyState="loading");var g=a.document,h=g.documentElement,i="load",j=!1,k="on"+i,l="complete",m="readyState",n="attachEvent",o="detachEvent",p="addEventListener",q="DOMContentLoaded",r="onreadystatechange",s="removeEventListener",t=p in g,u=j,v=j,w=[];if(g[m]===l)e(b);else if(t)g[p](q,c,j),a[p](i,c,j);else{g[n](r,c),a[n](k,c);try{u=null==a.frameElement&&h}catch(x){}u&&u.doScroll&&!function z(){if(!v){try{u.doScroll("left")}catch(a){return e(z,50)}d(),b()}}()}return f.version="1.4.0",f.isReady=function(){return v},f}a.exports="undefined"!=typeof window&&b(window)},function(a,b,c){var d=c(5),e=function(a){function b(a,b){for(var c in b)a[c]=b[c];return a}var c=1,e=d.defclass({constructor:function(a){c++,this.parent=null,this.children={},this.id=c,this.name="n"+c,null!=a&&(this.name=a),this.x=0,this.y=0,this.z=0,this.width=0,this.height=0},resize:function(a,b){null!=a&&(this.width=a),null!=b&&(this.height=b)},moveTo:function(a,b,c){this.x=null!=a?a:this.x,this.y=null!=b?b:this.y,this.z=null!=c?c:this.z},add:function(a){var b=a.name;if(null!=this.children[b])throw"SceneGraph: child with that name already exists: "+b;this.children[b]=a,a.parent=this}}),f=d(e,function(b){this.constructor=function(){b.constructor.call(this,"root"),this.properties=a}}),g=d(e,function(a){function c(c,d){if(a.constructor.call(this,c),this.properties={fill:"#000"},null!=d)b(this.properties,d);else if(null!=c&&"string"!=typeof c)throw"SceneGraph: invalid node name"}this.Group=d.extend(this,{constructor:c,type:"group"}),this.Rect=d.extend(this,{constructor:c,type:"rect"}),this.Text=d.extend(this,{constructor:function(a){c.call(this),this.properties.text=a},type:"text"})}),h=new f;return this.Shape=g,this.root=h,this};a.exports=e},function(a,b){(function(a){b.extend=function(a,b){var c={};for(var d in a)a.hasOwnProperty(d)&&(c[d]=a[d]);if(null!=b)for(var e in b)b.hasOwnProperty(e)&&(c[e]=b[e]);return c},b.cssProps=function(a){var b=[];for(var c in a)a.hasOwnProperty(c)&&b.push(c+":"+a[c]);return b.join(";")},b.encodeHtmlEntity=function(a){for(var b=[],c=0,d=a.length-1;d>=0;d--)c=a.charCodeAt(d),b.unshift(c>128?["&#",c,";"].join(""):a[d]);return b.join("")},b.getNodeArray=function(b){var c=null;return"string"==typeof b?c=document.querySelectorAll(b):a.NodeList&&b instanceof a.NodeList?c=b:a.Node&&b instanceof a.Node?c=[b]:a.HTMLCollection&&b instanceof a.HTMLCollection?c=b:b instanceof Array?c=b:null===b&&(c=[]),c},b.imageExists=function(a,b){var c=new Image;c.onerror=function(){b.call(this,!1)},c.onload=function(){b.call(this,!0)},c.src=a},b.decodeHtmlEntity=function(a){return a.replace(/&#(\d+);/g,function(a,b){return String.fromCharCode(b)})},b.dimensionCheck=function(a){var b={height:a.clientHeight,width:a.clientWidth};return b.height&&b.width?b:!1},b.truthy=function(a){return"string"==typeof a?"true"===a||"yes"===a||"1"===a||"on"===a||"✓"===a:!!a}}).call(b,function(){return this}())},function(a,b,c){var d=encodeURIComponent,e=decodeURIComponent,f=c(6),g=c(7),h=/(\w+)\[(\d+)\]/,i=/\w+\.\w+/;b.parse=function(a){if("string"!=typeof a)return{};if(a=f(a),""===a)return{};"?"===a.charAt(0)&&(a=a.slice(1));for(var b={},c=a.split("&"),d=0;df&&(e=a.render.queue[f]);f++)d=e.generate(),typeof e.callback==typeof Function&&e.callback(d);a.render.queue.splice(0,f),a.render.queue.length?setTimeout(c):(a.dispatch.render_end(),a.render.active=!1)};setTimeout(c)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},"undefined"!=typeof module&&"undefined"!=typeof exports&&(module.exports=a),"undefined"!=typeof window&&(window.nv=a),a.dom.write=function(a){return void 0!==window.fastdom?fastdom.write(a):a()},a.dom.read=function(a){return void 0!==window.fastdom?fastdom.read(a):a()},a.interactiveGuideline=function(){"use strict";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],i=!0,j=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,"svg"!==d3.event.target.tagName&&(i=!1),d3.event.target.className.baseVal.match("nv-legend")&&(j=!0)),i&&(d-=f.left,e-=f.top),0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||j){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&(void 0===d3.event.relatedTarget.className||d3.event.relatedTarget.className.match(c.nvPointerEventsClass)))return;return h.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void c.hidden(!0)}c.hidden(!1);var l=g.invert(d);h.elementMousemove({mouseX:d,mouseY:e,pointXValue:l}),"dblclick"===d3.event.type&&h.elementDblclick({mouseX:d,mouseY:e,pointXValue:l}),"click"===d3.event.type&&h.elementClick({mouseX:d,mouseY:e,pointXValue:l})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([l]),r=q.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");r.append("g").attr("class","nv-interactiveGuideLine"),j&&(j.on("touchmove",m).on("mousemove",m,!0).on("mouseout",m,!0).on("dblclick",m).on("click",m),b.guideLine=null,b.renderGuideLine=function(c){i&&(b.guideLine&&b.guideLine.attr("x1")===c||a.dom.write(function(){var b=q.select(".nv-interactiveGuideLine").selectAll("line").data(null!=c?[a.utils.NaNtoZero(c)]:[],String);b.enter().append("line").attr("class","nv-guideline").attr("x1",function(a){return a}).attr("x2",function(a){return a}).attr("y1",p).attr("y2",0),b.exit().remove()}))})})}var c=a.models.tooltip();c.duration(0).hideDelay(0)._isInteractiveLayer(!0).hidden(!1);var d=null,e=null,f={left:0,top:0},g=d3.scale.linear(),h=d3.dispatch("elementMousemove","elementMouseout","elementClick","elementDblclick"),i=!0,j=null,k="ActiveXObject"in window;return b.dispatch=h,b.tooltip=c,b.margin=function(a){return arguments.length?(f.top="undefined"!=typeof a.top?a.top:f.top,f.left="undefined"!=typeof a.left?a.left:f.left,b):f},b.width=function(a){return arguments.length?(d=a,b):d},b.height=function(a){return arguments.length?(e=a,b):e},b.xScale=function(a){return arguments.length?(g=a,b):g},b.showGuideLine=function(a){return arguments.length?(i=a,b):i},b.svgContainer=function(a){return arguments.length?(j=a,b):j},b},a.interactiveBisect=function(a,b,c){"use strict";if(!(a instanceof Array))return null;var d;d="function"!=typeof c?function(a){return a.x}:c;var e=function(a,b){return d(a)-b},f=d3.bisector(e).left,g=d3.max([0,f(a,b)-1]),h=d(a[g]);if("undefined"==typeof h&&(h=g),h===b)return g;var i=d3.min([g+1,a.length-1]),j=d(a[i]);return"undefined"==typeof j&&(j=i),Math.abs(j-b)>=Math.abs(h-b)?g:i},a.nearestValueIndex=function(a,b,c){"use strict";var d=1/0,e=null;return a.forEach(function(a,f){var g=Math.abs(b-a);null!=a&&d>=g&&c>g&&(d=g,e=f)}),e},function(){"use strict";a.models.tooltip=function(){function b(){if(k){var a=d3.select(k);"svg"!==a.node().tagName&&(a=a.select("svg"));var b=a.node()?a.attr("viewBox"):null;if(b){b=b.split(" ");var c=parseInt(a.style("width"),10)/b[2];p.left=p.left*c,p.top=p.top*c}}}function c(){if(!n){var a;a=k?k:document.body,n=d3.select(a).append("div").attr("class","nvtooltip "+(j?j:"xy-tooltip")).attr("id",v),n.style("top",0).style("left",0),n.style("opacity",0),n.selectAll("div, table, td, tr").classed(w,!0),n.classed(w,!0),o=n.node()}}function d(){if(r&&B(e)){b();var f=p.left,g=null!==i?i:p.top;return a.dom.write(function(){c();var b=A(e);b&&(o.innerHTML=b),k&&u?a.dom.read(function(){var a=k.getElementsByTagName("svg")[0],b={left:0,top:0};if(a){var c=a.getBoundingClientRect(),d=k.getBoundingClientRect(),e=c.top;if(0>e){var i=k.getBoundingClientRect();e=Math.abs(e)>i.height?0:e}b.top=Math.abs(e-d.top),b.left=Math.abs(c.left-d.left)}f+=k.offsetLeft+b.left-2*k.scrollLeft,g+=k.offsetTop+b.top-2*k.scrollTop,h&&h>0&&(g=Math.floor(g/h)*h),C([f,g])}):C([f,g])}),d}}var e=null,f="w",g=25,h=0,i=null,j=null,k=null,l=!0,m=400,n=null,o=null,p={left:null,top:null},q={left:0,top:0},r=!0,s=100,t=!0,u=!1,v="nvtooltip-"+Math.floor(1e5*Math.random()),w="nv-pointer-events-none",x=function(a){return a},y=function(a){return a},z=function(a){return a},A=function(a){if(null===a)return"";var b=d3.select(document.createElement("table"));if(t){var c=b.selectAll("thead").data([a]).enter().append("thead");c.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(y(a.value))}var d=b.selectAll("tbody").data([a]).enter().append("tbody"),e=d.selectAll("tr").data(function(a){return a.series}).enter().append("tr").classed("highlight",function(a){return a.highlight});e.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(a){return a.color}),e.append("td").classed("key",!0).html(function(a,b){return z(a.key,b)}),e.append("td").classed("value",!0).html(function(a,b){return x(a.value,b)}),e.selectAll("td").each(function(a){if(a.highlight){var b=d3.scale.linear().domain([0,1]).range(["#fff",a.color]),c=.6;d3.select(this).style("border-bottom-color",b(c)).style("border-top-color",b(c))}});var f=b.node().outerHTML;return void 0!==a.footer&&(f+=""),f},B=function(a){if(a&&a.series){if(a.series instanceof Array)return!!a.series.length;if(a.series instanceof Object)return a.series=[a.series],!0}return!1},C=function(b){o&&a.dom.read(function(){var c,d,e=parseInt(o.offsetHeight,10),h=parseInt(o.offsetWidth,10),i=a.utils.windowSize().width,j=a.utils.windowSize().height,k=window.pageYOffset,p=window.pageXOffset;j=window.innerWidth>=document.body.scrollWidth?j:j-16,i=window.innerHeight>=document.body.scrollHeight?i:i-16;var r,t,u=function(a){var b=d;do isNaN(a.offsetTop)||(b+=a.offsetTop),a=a.offsetParent;while(a);return b},v=function(a){var b=c;do isNaN(a.offsetLeft)||(b+=a.offsetLeft),a=a.offsetParent;while(a);return b};switch(f){case"e":c=b[0]-h-g,d=b[1]-e/2,r=v(o),t=u(o),p>r&&(c=b[0]+g>p?b[0]+g:p-r+c),k>t&&(d=k-t+d),t+e>k+j&&(d=k+j-t+d-e);break;case"w":c=b[0]+g,d=b[1]-e/2,r=v(o),t=u(o),r+h>i&&(c=b[0]-h-g),k>t&&(d=k+5),t+e>k+j&&(d=k+j-t+d-e);break;case"n":c=b[0]-h/2-5,d=b[1]+g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),t+e>k+j&&(d=k+j-t+d-e);break;case"s":c=b[0]-h/2,d=b[1]-e-g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),k>t&&(d=k);break;case"none":c=b[0],d=b[1]-g,r=v(o),t=u(o)}c-=q.left,d-=q.top;var w=o.getBoundingClientRect(),k=window.pageYOffset||document.documentElement.scrollTop,p=window.pageXOffset||document.documentElement.scrollLeft,x="translate("+(w.left+p)+"px, "+(w.top+k)+"px)",y="translate("+c+"px, "+d+"px)",z=d3.interpolateString(x,y),A=n.style("opacity")<.1;l?n.transition().delay(m).duration(0).style("opacity",0):n.interrupt().transition().duration(A?0:s).styleTween("transform",function(){return z},"important").style("-webkit-transform",y).style("opacity",1)})};return d.nvPointerEventsClass=w,d.options=a.utils.optionsFunc.bind(d),d._options=Object.create({},{duration:{get:function(){return s},set:function(a){s=a}},gravity:{get:function(){return f},set:function(a){f=a}},distance:{get:function(){return g},set:function(a){g=a}},snapDistance:{get:function(){return h},set:function(a){h=a}},classes:{get:function(){return j},set:function(a){j=a}},chartContainer:{get:function(){return k},set:function(a){k=a}},fixedTop:{get:function(){return i},set:function(a){i=a}},enabled:{get:function(){return r},set:function(a){r=a}},hideDelay:{get:function(){return m},set:function(a){m=a}},contentGenerator:{get:function(){return A},set:function(a){A=a}},valueFormatter:{get:function(){return x},set:function(a){x=a}},headerFormatter:{get:function(){return y},set:function(a){y=a}},keyFormatter:{get:function(){return z},set:function(a){z=a}},headerEnabled:{get:function(){return t},set:function(a){t=a}},_isInteractiveLayer:{get:function(){return u},set:function(a){u=!!a}},position:{get:function(){return p},set:function(a){p.left=void 0!==a.left?a.left:p.left,p.top=void 0!==a.top?a.top:p.top}},offset:{get:function(){return q},set:function(a){q.left=void 0!==a.left?a.left:q.left,q.top=void 0!==a.top?a.top:q.top}},hidden:{get:function(){return l},set:function(a){l!=a&&(l=!!a,d())}},data:{get:function(){return e},set:function(a){a.point&&(a.value=a.point.x,a.series=a.series||{},a.series.value=a.point.y,a.series.color=a.point.color||a.series.color),e=a}},tooltipElem:{get:function(){return o},set:function(){}},id:{get:function(){return v},set:function(){}}}),a.utils.initOptions(d),d}}(),a.utils.windowSize=function(){var a={width:640,height:480};return window.innerWidth&&window.innerHeight?(a.width=window.innerWidth,a.height=window.innerHeight,a):"CSS1Compat"==document.compatMode&&document.documentElement&&document.documentElement.offsetWidth?(a.width=document.documentElement.offsetWidth,a.height=document.documentElement.offsetHeight,a):document.body&&document.body.offsetWidth?(a.width=document.body.offsetWidth,a.height=document.body.offsetHeight,a):a},a.utils.windowResize=function(b){return window.addEventListener?window.addEventListener("resize",b):a.log("ERROR: Failed to bind to window.resize with: ",b),{callback:b,clear:function(){window.removeEventListener("resize",b)}}},a.utils.getColor=function(b){if(void 0===b)return a.utils.defaultColor();if(Array.isArray(b)){var c=d3.scale.ordinal().range(b);return function(a,b){var d=void 0===b?a:b;return a.color||c(d)}}return b},a.utils.defaultColor=function(){return a.utils.getColor(d3.scale.category20().range())},a.utils.customTheme=function(a,b,c){b=b||function(a){return a.key},c=c||d3.scale.category20().range();var d=c.length;return function(e){var f=b(e);return"function"==typeof a[f]?a[f]():void 0!==a[f]?a[f]:(d||(d=c.length),d-=1,c[d])}},a.utils.pjax=function(b,c){var d=function(d){d3.html(d,function(d){var e=d3.select(c).node();e.parentNode.replaceChild(d3.select(d).select(c).node(),e),a.utils.pjax(b,c)})};d3.selectAll(b).on("click",function(){history.pushState(this.href,this.textContent,this.href),d(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&d(d3.event.state)})},a.utils.calcApproxTextWidth=function(a){if("function"==typeof a.style&&"function"==typeof a.text){var b=parseInt(a.style("font-size").replace("px",""),10),c=a.text().length;return c*b*.5}return 0},a.utils.NaNtoZero=function(a){return"number"!=typeof a||isNaN(a)||null===a||1/0===a||a===-1/0?0:a},d3.selection.prototype.watchTransition=function(a){var b=[this].concat([].slice.call(arguments,1));return a.transition.apply(a,b)},a.utils.renderWatch=function(b,c){if(!(this instanceof a.utils.renderWatch))return new a.utils.renderWatch(b,c);var d=void 0!==c?c:250,e=[],f=this;this.models=function(a){return a=[].slice.call(arguments,0),a.forEach(function(a){a.__rendered=!1,function(a){a.dispatch.on("renderEnd",function(){a.__rendered=!0,f.renderEnd("model")})}(a),e.indexOf(a)<0&&e.push(a)}),this},this.reset=function(a){void 0!==a&&(d=a),e=[]},this.transition=function(a,b,c){if(b=arguments.length>1?[].slice.call(arguments,1):[],c=b.length>1?b.pop():void 0!==d?d:250,a.__rendered=!1,e.indexOf(a)<0&&e.push(a),0===c)return a.__rendered=!0,a.delay=function(){return this},a.duration=function(){return this},a;a.__rendered=0===a.length?!0:a.every(function(a){return!a.length})?!0:!1;var g=0;return a.transition().duration(c).each(function(){++g}).each("end",function(){0===--g&&(a.__rendered=!0,f.renderEnd.apply(this,b))})},this.renderEnd=function(){e.every(function(a){return a.__rendered})&&(e.forEach(function(a){a.__rendered=!1}),b.renderEnd.apply(this,arguments))}},a.utils.deepExtend=function(b){var c=arguments.length>1?[].slice.call(arguments,1):[];c.forEach(function(c){for(var d in c){var e=b[d]instanceof Array,f="object"==typeof b[d],g="object"==typeof c[d];f&&!e&&g?a.utils.deepExtend(b[d],c[d]):b[d]=c[d]}})},a.utils.state=function(){if(!(this instanceof a.utils.state))return new a.utils.state;var b={},c=function(){},d=function(){return{}},e=null,f=null;this.dispatch=d3.dispatch("change","set"),this.dispatch.on("set",function(a){c(a,!0)}),this.getter=function(a){return d=a,this},this.setter=function(a,b){return b||(b=function(){}),c=function(c,d){a(c),d&&b()},this},this.init=function(b){e=e||{},a.utils.deepExtend(e,b)};var g=function(){var a=d();if(JSON.stringify(a)===JSON.stringify(b))return!1;for(var c in a)void 0===b[c]&&(b[c]={}),b[c]=a[c],f=!0;return!0};this.update=function(){e&&(c(e,!1),e=null),g.call(this)&&this.dispatch.change(b)}},a.utils.optionsFunc=function(a){return a&&d3.map(a).forEach(function(a,b){"function"==typeof this[a]&&this[a](b)}.bind(this)),this},a.utils.calcTicksX=function(b,c){var d=1,e=0;for(e;ed?f:d}return a.log("Requested number of ticks: ",b),a.log("Calculated max values to be: ",d),b=b>d?b=d-1:b,b=1>b?1:b,b=Math.floor(b),a.log("Calculating tick count as: ",b),b},a.utils.calcTicksY=function(b,c){return a.utils.calcTicksX(b,c)},a.utils.initOption=function(a,b){a._calls&&a._calls[b]?a[b]=a._calls[b]:(a[b]=function(c){return arguments.length?(a._overrides[b]=!0,a._options[b]=c,a):a._options[b]},a["_"+b]=function(c){return arguments.length?(a._overrides[b]||(a._options[b]=c),a):a._options[b]})},a.utils.initOptions=function(b){b._overrides=b._overrides||{};var c=Object.getOwnPropertyNames(b._options||{}),d=Object.getOwnPropertyNames(b._calls||{});c=c.concat(d);for(var e in c)a.utils.initOption(b,c[e])},a.utils.inheritOptionsD3=function(a,b,c){a._d3options=c.concat(a._d3options||[]),c.unshift(b),c.unshift(a),d3.rebind.apply(this,c)},a.utils.arrayUnique=function(a){return a.sort().filter(function(b,c){return!c||b!=a[c-1]})},a.utils.symbolMap=d3.map(),a.utils.symbol=function(){function b(b,e){var f=c.call(this,b,e),g=d.call(this,b,e);return-1!==d3.svg.symbolTypes.indexOf(f)?d3.svg.symbol().type(f).size(g)():a.utils.symbolMap.get(f)(g)}var c,d=64;return b.type=function(a){return arguments.length?(c=d3.functor(a),b):c},b.size=function(a){return arguments.length?(d=d3.functor(a),b):d},b},a.utils.inheritOptions=function(b,c){var d=Object.getOwnPropertyNames(c._options||{}),e=Object.getOwnPropertyNames(c._calls||{}),f=c._inherited||[],g=c._d3options||[],h=d.concat(e).concat(f).concat(g);h.unshift(c),h.unshift(b),d3.rebind.apply(this,h),b._inherited=a.utils.arrayUnique(d.concat(e).concat(f).concat(d).concat(b._inherited||[])),b._d3options=a.utils.arrayUnique(g.concat(b._d3options||[]))},a.utils.initSVG=function(a){a.classed({"nvd3-svg":!0})},a.utils.sanitizeHeight=function(a,b){return a||parseInt(b.style("height"),10)||400},a.utils.sanitizeWidth=function(a,b){return a||parseInt(b.style("width"),10)||960},a.utils.availableHeight=function(b,c,d){return a.utils.sanitizeHeight(b,c)-d.top-d.bottom},a.utils.availableWidth=function(b,c,d){return a.utils.sanitizeWidth(b,c)-d.left-d.right},a.utils.noData=function(b,c){var d=b.options(),e=d.margin(),f=d.noData(),g=null==f?["No Data Available."]:[f],h=a.utils.availableHeight(d.height(),c,e),i=a.utils.availableWidth(d.width(),c,e),j=e.left+i/2,k=e.top+h/2;c.selectAll("g").remove();var l=c.selectAll(".nv-noData").data(g);l.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),l.attr("x",j).attr("y",k).text(function(a){return a})},a.models.axis=function(){"use strict";function b(g){return s.reset(),g.each(function(b){var g=d3.select(this);a.utils.initSVG(g);var p=g.selectAll("g.nv-wrap.nv-axis").data([b]),q=p.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),t=(q.append("g"),p.select("g"));null!==n?c.ticks(n):("top"==c.orient()||"bottom"==c.orient())&&c.ticks(Math.abs(d.range()[1]-d.range()[0])/100),t.watchTransition(s,"axis").call(c),r=r||c.scale();var u=c.tickFormat();null==u&&(u=r.tickFormat());var v=t.selectAll("text.nv-axislabel").data([h||null]);v.exit().remove();var w,x,y;switch(c.orient()){case"top":v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",0).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b))+",0)"}).select("text").attr("dy","-0.5em").attr("y",-c.tickPadding()).attr("text-anchor","middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max top").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d.range()[c])+",0)"}));break;case"bottom":w=o+36;var z=30,A=0,B=t.selectAll("g").select("text"),C="";if(j%360){B.each(function(){var a=this.getBoundingClientRect(),b=a.width;A=a.height,b>z&&(z=b)}),C="rotate("+j+" 0,"+(A/2+c.tickPadding())+")";var D=Math.abs(Math.sin(j*Math.PI/180));w=(D?D*z:z)+30,B.attr("transform",C).style("text-anchor",j%360>0?"start":"end")}v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",w).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data([d.domain()[0],d.domain()[d.domain().length-1]]),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",c.tickPadding()).attr("transform",C).style("text-anchor",j?j%360>0?"start":"end":"middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max bottom").attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"})),l&&B.attr("transform",function(a,b){return"translate(0,"+(b%2==0?"0":"12")+")"});break;case"right":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"begin").attr("transform",k?"rotate(90)":"").attr("y",k?-Math.max(e.right,f)+12:-10).attr("x",k?d3.max(d.range())/2:c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(d(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",c.tickPadding()).style("text-anchor","start").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1));break;case"left":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"end").attr("transform",k?"rotate(-90)":"").attr("y",k?-Math.max(e.left,f)+25-(o||0):-10).attr("x",k?-d3.max(d.range())/2:-c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(r(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-c.tickPadding()).attr("text-anchor","end").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1))}if(v.text(function(a){return a}),!i||"left"!==c.orient()&&"right"!==c.orient()||(t.selectAll("g").each(function(a){d3.select(this).select("text").attr("opacity",1),(d(a)d.range()[0]-10)&&((a>1e-10||-1e-10>a)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0))}),d.domain()[0]==d.domain()[1]&&0==d.domain()[0]&&p.selectAll("g.nv-axisMaxMin").style("opacity",function(a,b){return b?0:1})),i&&("top"===c.orient()||"bottom"===c.orient())){var E=[];p.selectAll("g.nv-axisMaxMin").each(function(a,b){try{E.push(b?d(a)-this.getBoundingClientRect().width-4:d(a)+this.getBoundingClientRect().width+4)}catch(c){E.push(b?d(a)-4:d(a)+4)}}),t.selectAll("g").each(function(a){(d(a)E[1])&&(a>1e-10||-1e-10>a?d3.select(this).remove():d3.select(this).select("text").remove())})}t.selectAll(".tick").filter(function(a){return!parseFloat(Math.round(1e5*a)/1e6)&&void 0!==a}).classed("zero",!0),r=d.copy()}),s.renderEnd("axis immediate"),b}var c=d3.svg.axis(),d=d3.scale.linear(),e={top:0,right:0,bottom:0,left:0},f=75,g=60,h=null,i=!0,j=0,k=!0,l=!1,m=!1,n=null,o=0,p=250,q=d3.dispatch("renderEnd");c.scale(d).orient("bottom").tickFormat(function(a){return a});var r,s=a.utils.renderWatch(q,p);return b.axis=c,b.dispatch=q,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{axisLabelDistance:{get:function(){return o},set:function(a){o=a}},staggerLabels:{get:function(){return l},set:function(a){l=a}},rotateLabels:{get:function(){return j},set:function(a){j=a}},rotateYLabel:{get:function(){return k},set:function(a){k=a}},showMaxMin:{get:function(){return i},set:function(a){i=a}},axisLabel:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return g},set:function(a){g=a}},ticks:{get:function(){return n},set:function(a){n=a}},width:{get:function(){return f},set:function(a){f=a}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},duration:{get:function(){return p},set:function(a){p=a,s.reset(p)}},scale:{get:function(){return d},set:function(e){d=e,c.scale(d),m="function"==typeof d.rangeBands,a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"])}}}),a.utils.initOptions(b),a.utils.inheritOptionsD3(b,c,["orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"]),a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"]),b},a.models.boxPlot=function(){"use strict";function b(l){return v.reset(),l.each(function(b){var l=j-i.left-i.right,p=k-i.top-i.bottom;r=d3.select(this),a.utils.initSVG(r),m.domain(c||b.map(function(a,b){return o(a,b)})).rangeBands(e||[0,l],.1);var w=[];if(!d){var x=d3.min(b.map(function(a){var b=[];return b.push(a.values.Q1),a.values.hasOwnProperty("whisker_low")&&null!==a.values.whisker_low&&b.push(a.values.whisker_low),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.min(b)})),y=d3.max(b.map(function(a){var b=[];return b.push(a.values.Q3),a.values.hasOwnProperty("whisker_high")&&null!==a.values.whisker_high&&b.push(a.values.whisker_high),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.max(b)}));w=[x,y]}n.domain(d||w),n.range(f||[p,0]),g=g||m,h=h||n.copy().range([n(0),n(0)]);{var z=r.selectAll("g.nv-wrap").data([b]);z.enter().append("g").attr("class","nvd3 nv-wrap")}z.attr("transform","translate("+i.left+","+i.top+")");var A=z.selectAll(".nv-boxplot").data(function(a){return a}),B=A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);A.attr("class","nv-boxplot").attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}).classed("hover",function(a){return a.hover}),A.watchTransition(v,"nv-boxplot: boxplots").style("stroke-opacity",1).style("fill-opacity",.75).delay(function(a,c){return c*t/b.length}).attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}),A.exit().remove(),B.each(function(a,b){var c=d3.select(this);["low","high"].forEach(function(d){a.values.hasOwnProperty("whisker_"+d)&&null!==a.values["whisker_"+d]&&(c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-whisker nv-boxplot-"+d),c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-tick nv-boxplot-"+d))})});var C=A.selectAll(".nv-boxplot-outlier").data(function(a){return a.values.hasOwnProperty("outliers")&&null!==a.values.outliers?a.values.outliers:[]});C.enter().append("circle").style("fill",function(a,b,c){return q(a,c)}).style("stroke",function(a,b,c){return q(a,c)}).on("mouseover",function(a,b,c){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:a,color:q(a,c)},e:d3.event})}).on("mouseout",function(a,b,c){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:a,color:q(a,c)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),C.attr("class","nv-boxplot-outlier"),C.watchTransition(v,"nv-boxplot: nv-boxplot-outlier").attr("cx",.45*m.rangeBand()).attr("cy",function(a){return n(a)}).attr("r","3"),C.exit().remove();var D=function(){return null===u?.9*m.rangeBand():Math.min(75,.9*m.rangeBand())},E=function(){return.45*m.rangeBand()-D()/2},F=function(){return.45*m.rangeBand()+D()/2};["low","high"].forEach(function(a){var b="low"===a?"Q1":"Q3";A.select("line.nv-boxplot-whisker.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",.45*m.rangeBand()).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",.45*m.rangeBand()).attr("y2",function(a){return n(a.values[b])}),A.select("line.nv-boxplot-tick.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",E).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",F).attr("y2",function(b){return n(b.values["whisker_"+a])})}),["low","high"].forEach(function(a){B.selectAll(".nv-boxplot-"+a).on("mouseover",function(b,c,d){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mouseout",function(b,c,d){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})})}),B.append("rect").attr("class","nv-boxplot-box").on("mouseover",function(a,b){d3.select(this).classed("hover",!0),s.elementMouseover({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),s.elementMouseout({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),A.select("rect.nv-boxplot-box").watchTransition(v,"nv-boxplot: boxes").attr("y",function(a){return n(a.values.Q3)}).attr("width",D).attr("x",E).attr("height",function(a){return Math.abs(n(a.values.Q3)-n(a.values.Q1))||1}).style("fill",function(a,b){return a.color||q(a,b)}).style("stroke",function(a,b){return a.color||q(a,b)}),B.append("line").attr("class","nv-boxplot-median"),A.select("line.nv-boxplot-median").watchTransition(v,"nv-boxplot: boxplots line").attr("x1",E).attr("y1",function(a){return n(a.values.Q2)}).attr("x2",F).attr("y2",function(a){return n(a.values.Q2)}),g=m.copy(),h=n.copy()}),v.renderEnd("nv-boxplot immediate"),b}var c,d,e,f,g,h,i={top:0,right:0,bottom:0,left:0},j=960,k=500,l=Math.floor(1e4*Math.random()),m=d3.scale.ordinal(),n=d3.scale.linear(),o=function(a){return a.x},p=function(a){return a.y},q=a.utils.defaultColor(),r=null,s=d3.dispatch("elementMouseover","elementMouseout","elementMousemove","renderEnd"),t=250,u=null,v=a.utils.renderWatch(s,t);return b.dispatch=s,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},maxBoxWidth:{get:function(){return u},set:function(a){u=a}},x:{get:function(){return o},set:function(a){o=a}},y:{get:function(){return p},set:function(a){p=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return l},set:function(a){l=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}},duration:{get:function(){return t},set:function(a){t=a,v.reset(t)}}}),a.utils.initOptions(b),b},a.models.boxPlotChart=function(){"use strict";function b(k){return t.reset(),t.models(e),l&&t.models(f),m&&t.models(g),k.each(function(k){var p=d3.select(this);a.utils.initSVG(p);var t=(i||parseInt(p.style("width"))||960)-h.left-h.right,u=(j||parseInt(p.style("height"))||400)-h.top-h.bottom;if(b.update=function(){r.beforeUpdate(),p.transition().duration(s).call(b)},b.container=this,!(k&&k.length&&k.filter(function(a){return a.values.hasOwnProperty("Q1")&&a.values.hasOwnProperty("Q2")&&a.values.hasOwnProperty("Q3")}).length)){var v=p.selectAll(".nv-noData").data([q]);return v.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),v.attr("x",h.left+t/2).attr("y",h.top+u/2).text(function(a){return a}),b}p.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var w=p.selectAll("g.nv-wrap.nv-boxPlotWithAxes").data([k]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-boxPlotWithAxes").append("g"),y=x.append("defs"),z=w.select("g"); -x.append("g").attr("class","nv-x nv-axis"),x.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),x.append("g").attr("class","nv-barsWrap"),z.attr("transform","translate("+h.left+","+h.top+")"),n&&z.select(".nv-y.nv-axis").attr("transform","translate("+t+",0)"),e.width(t).height(u);var A=z.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));if(A.transition().call(e),y.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),z.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(o?2:1)).attr("height",16).attr("x",-c.rangeBand()/(o?1:2)),l){f.scale(c).ticks(a.utils.calcTicksX(t/100,k)).tickSize(-u,0),z.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),z.select(".nv-x.nv-axis").call(f);var B=z.select(".nv-x.nv-axis").selectAll("g");o&&B.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}m&&(g.scale(d).ticks(Math.floor(u/36)).tickSize(-t,0),z.select(".nv-y.nv-axis").call(g)),z.select(".nv-zeroLine line").attr("x1",0).attr("x2",t).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("nv-boxplot chart immediate"),b}var c,d,e=a.models.boxPlot(),f=a.models.axis(),g=a.models.axis(),h={top:15,right:10,bottom:50,left:60},i=null,j=null,k=a.utils.getColor(),l=!0,m=!0,n=!1,o=!1,p=a.models.tooltip(),q="No Data Available.",r=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(n?"right":"left").tickFormat(d3.format(",.1f")),p.duration(0);var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){p.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){p.data(a).hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){p.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.boxplot=e,b.xAxis=f,b.yAxis=g,b.tooltip=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},staggerLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return l},set:function(a){l=a}},showYAxis:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return tooltips},set:function(a){tooltips=a}},tooltipContent:{get:function(){return p},set:function(a){p=a}},noData:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!==a.top?a.top:h.top,h.right=void 0!==a.right?a.right:h.right,h.bottom=void 0!==a.bottom?a.bottom:h.bottom,h.left=void 0!==a.left?a.left:h.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}},rightAlignYAxis:{get:function(){return n},set:function(a){n=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.bullet=function(){"use strict";function b(d){return d.each(function(b,d){var p=m-c.left-c.right,s=n-c.top-c.bottom;o=d3.select(this),a.utils.initSVG(o);{var t=f.call(this,b,d).slice().sort(d3.descending),u=g.call(this,b,d).slice().sort(d3.descending),v=h.call(this,b,d).slice().sort(d3.descending),w=i.call(this,b,d).slice(),x=j.call(this,b,d).slice(),y=k.call(this,b,d).slice(),z=d3.scale.linear().domain(d3.extent(d3.merge([l,t]))).range(e?[p,0]:[0,p]);this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range())}this.__chart__=z;var A=d3.min(t),B=d3.max(t),C=t[1],D=o.selectAll("g.nv-wrap.nv-bullet").data([b]),E=D.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),F=E.append("g"),G=D.select("g");F.append("rect").attr("class","nv-range nv-rangeMax"),F.append("rect").attr("class","nv-range nv-rangeAvg"),F.append("rect").attr("class","nv-range nv-rangeMin"),F.append("rect").attr("class","nv-measure"),D.attr("transform","translate("+c.left+","+c.top+")");var H=function(a){return Math.abs(z(a)-z(0))},I=function(a){return z(0>a?a:0)};G.select("rect.nv-rangeMax").attr("height",s).attr("width",H(B>0?B:A)).attr("x",I(B>0?B:A)).datum(B>0?B:A),G.select("rect.nv-rangeAvg").attr("height",s).attr("width",H(C)).attr("x",I(C)).datum(C),G.select("rect.nv-rangeMin").attr("height",s).attr("width",H(B)).attr("x",I(B)).attr("width",H(B>0?A:B)).attr("x",I(B>0?A:B)).datum(B>0?A:B),G.select("rect.nv-measure").style("fill",q).attr("height",s/3).attr("y",s/3).attr("width",0>v?z(0)-z(v[0]):z(v[0])-z(0)).attr("x",I(v)).on("mouseover",function(){r.elementMouseover({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mouseout",function(){r.elementMouseout({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})});var J=s/6,K=u.map(function(a,b){return{value:a,label:x[b]}});F.selectAll("path.nv-markerTriangle").data(K).enter().append("path").attr("class","nv-markerTriangle").attr("transform",function(a){return"translate("+z(a.value)+","+s/2+")"}).attr("d","M0,"+J+"L"+J+","+-J+" "+-J+","+-J+"Z").on("mouseover",function(a){r.elementMouseover({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill"),pos:[z(a.value),s/2]})}).on("mousemove",function(a){r.elementMousemove({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a){r.elementMouseout({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}),D.selectAll(".nv-range").on("mouseover",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseover({value:a,label:c,color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseout({value:a,label:c,color:d3.select(this).style("fill")})})}),b}var c={top:0,right:0,bottom:0,left:0},d="left",e=!1,f=function(a){return a.ranges},g=function(a){return a.markers?a.markers:[0]},h=function(a){return a.measures},i=function(a){return a.rangeLabels?a.rangeLabels:[]},j=function(a){return a.markerLabels?a.markerLabels:[]},k=function(a){return a.measureLabels?a.measureLabels:[]},l=[0],m=380,n=30,o=null,p=null,q=a.utils.getColor(["#1f77b4"]),r=d3.dispatch("elementMouseover","elementMouseout","elementMousemove");return b.dispatch=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return f},set:function(a){f=a}},markers:{get:function(){return g},set:function(a){g=a}},measures:{get:function(){return h},set:function(a){h=a}},forceX:{get:function(){return l},set:function(a){l=a}},width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},tickFormat:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},orient:{get:function(){return d},set:function(a){d=a,e="right"==d||"bottom"==d}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.bulletChart=function(){"use strict";function b(d){return d.each(function(e,o){var p=d3.select(this);a.utils.initSVG(p);var q=a.utils.availableWidth(k,p,g),r=l-g.top-g.bottom;if(b.update=function(){b(d)},b.container=this,!e||!h.call(this,e,o))return a.utils.noData(b,p),b;p.selectAll(".nv-noData").remove();var s=h.call(this,e,o).slice().sort(d3.descending),t=i.call(this,e,o).slice().sort(d3.descending),u=j.call(this,e,o).slice().sort(d3.descending),v=p.selectAll("g.nv-wrap.nv-bulletChart").data([e]),w=v.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),x=w.append("g"),y=v.select("g");x.append("g").attr("class","nv-bulletWrap"),x.append("g").attr("class","nv-titles"),v.attr("transform","translate("+g.left+","+g.top+")");var z=d3.scale.linear().domain([0,Math.max(s[0],t[0],u[0])]).range(f?[q,0]:[0,q]),A=this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range());this.__chart__=z;var B=x.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(l-g.top-g.bottom)/2+")");B.append("text").attr("class","nv-title").text(function(a){return a.title}),B.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(a){return a.subtitle}),c.width(q).height(r);var C=y.select(".nv-bulletWrap");d3.transition(C).call(c);var D=m||z.tickFormat(q/100),E=y.selectAll("g.nv-tick").data(z.ticks(n?n:q/50),function(a){return this.textContent||D(a)}),F=E.enter().append("g").attr("class","nv-tick").attr("transform",function(a){return"translate("+A(a)+",0)"}).style("opacity",1e-6);F.append("line").attr("y1",r).attr("y2",7*r/6),F.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",7*r/6).text(D);var G=d3.transition(E).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1);G.select("line").attr("y1",r).attr("y2",7*r/6),G.select("text").attr("y",7*r/6),d3.transition(E.exit()).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1e-6).remove()}),d3.timer.flush(),b}var c=a.models.bullet(),d=a.models.tooltip(),e="left",f=!1,g={top:5,right:40,bottom:20,left:120},h=function(a){return a.ranges},i=function(a){return a.markers?a.markers:[0]},j=function(a){return a.measures},k=null,l=55,m=null,n=null,o=null,p=d3.dispatch("tooltipShow","tooltipHide");return d.duration(0).headerEnabled(!1),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.label,value:a.value,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.bullet=c,b.dispatch=p,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return h},set:function(a){h=a}},markers:{get:function(){return i},set:function(a){i=a}},measures:{get:function(){return j},set:function(a){j=a}},width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},tickFormat:{get:function(){return m},set:function(a){m=a}},ticks:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return o},set:function(a){o=a}},tooltips:{get:function(){return d.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),d.enabled(!!b)}},tooltipContent:{get:function(){return d.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),d.contentGenerator(b)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},orient:{get:function(){return e},set:function(a){e=a,f="right"==e||"bottom"==e}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.candlestickBar=function(){"use strict";function b(x){return x.each(function(b){c=d3.select(this);var x=a.utils.availableWidth(i,c,h),y=a.utils.availableHeight(j,c,h);a.utils.initSVG(c);var A=x/b[0].values.length*.45;l.domain(d||d3.extent(b[0].values.map(n).concat(t))),l.range(v?f||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:f||[5+A/2,x-A/2-5]),m.domain(e||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(g||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var B=d3.select(this).selectAll("g.nv-wrap.nv-candlestickBar").data([b[0].values]),C=B.enter().append("g").attr("class","nvd3 nv-wrap nv-candlestickBar"),D=C.append("defs"),E=C.append("g"),F=B.select("g");E.append("g").attr("class","nv-ticks"),B.attr("transform","translate("+h.left+","+h.top+")"),c.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:k})}),D.append("clipPath").attr("id","nv-chart-clip-path-"+k).append("rect"),B.select("#nv-chart-clip-path-"+k+" rect").attr("width",x).attr("height",y),F.attr("clip-path",w?"url(#nv-chart-clip-path-"+k+")":"");var G=B.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});G.exit().remove();{var H=G.enter().append("g").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b});H.append("line").attr("class","nv-candlestick-lines").attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),H.append("rect").attr("class","nv-candlestick-rects nv-bars").attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}c.selectAll(".nv-candlestick-lines").transition().attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),c.selectAll(".nv-candlestick-rects").transition().attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}),b}var c,d,e,f,g,h={top:0,right:0,bottom:0,left:0},i=null,j=null,k=Math.floor(1e4*Math.random()),l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,d){b.clearHighlights(),c.select(".nv-candlestickBar .nv-tick-0-"+a).classed("hover",d)},b.clearHighlights=function(){c.select(".nv-candlestickBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return k},set:function(a){k=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!=a.top?a.top:h.top,h.right=void 0!=a.right?a.right:h.right,h.bottom=void 0!=a.bottom?a.bottom:h.bottom,h.left=void 0!=a.left?a.left:h.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){"use strict";function b(l){return H.reset(),H.models(f),r&&H.models(g),s&&H.models(h),l.each(function(l){function A(){d3.select(b.container).style("cursor","ew-resize")}function E(){G.x=d3.event.x,G.i=Math.round(F.invert(G.x)),K()}function H(){d3.select(b.container).style("cursor","auto"),y.index=G.i,C.stateChange(y)}function K(){bb.data([G]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var L=d3.select(this);a.utils.initSVG(L),L.classed("nv-chart-"+x,!0);var M=this,N=a.utils.availableWidth(o,L,m),O=a.utils.availableHeight(p,L,m);if(b.update=function(){0===D?L.call(b):L.transition().duration(D).call(b)},b.container=this,y.setter(J(l),b.update).getter(I(l)).update(),y.disabled=l.map(function(a){return!!a.disabled}),!z){var P;z={};for(P in y)z[P]=y[P]instanceof Array?y[P].slice(0):y[P]}var Q=d3.behavior.drag().on("dragstart",A).on("drag",E).on("dragend",H);if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length))return a.utils.noData(b,L),b;if(L.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale(),w)f.yDomain(null);else{var R=l.filter(function(a){return!a.disabled}).map(function(a){var b=d3.extent(a.values,f.y());return b[0]<-.95&&(b[0]=-.95),[(b[0]-b[1])/(1+b[1]),(b[1]-b[0])/(1+b[0])]}),S=[d3.min(R,function(a){return a[0]}),d3.max(R,function(a){return a[1]})];f.yDomain(S)}F.domain([0,l[0].values.length-1]).range([0,N]).clamp(!0);var l=c(G.i,l),T=v?"none":"all",U=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([l]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),W=U.select("g");if(V.append("g").attr("class","nv-interactive"),V.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),V.append("g").attr("class","nv-y nv-axis"),V.append("g").attr("class","nv-background"),V.append("g").attr("class","nv-linesWrap").style("pointer-events",T),V.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),V.append("g").attr("class","nv-legendWrap"),V.append("g").attr("class","nv-controlsWrap"),q&&(i.width(N),W.select(".nv-legendWrap").datum(l).call(i),m.top!=i.height()&&(m.top=i.height(),O=a.utils.availableHeight(p,L,m)),W.select(".nv-legendWrap").attr("transform","translate(0,"+-m.top+")")),u){var X=[{key:"Re-scale y-axis",disabled:!w}];j.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),W.select(".nv-controlsWrap").datum(X).attr("transform","translate(0,"+-m.top+")").call(j)}U.attr("transform","translate("+m.left+","+m.top+")"),t&&W.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)");var Y=l.filter(function(a){return a.tempDisabled});U.select(".tempDisabled").remove(),Y.length&&U.append("text").attr("class","tempDisabled").attr("x",N/2).attr("y","-.71em").style("text-anchor","end").text(Y.map(function(a){return a.key}).join(", ")+" values cannot be calculated for this time period."),v&&(k.width(N).height(O).margin({left:m.left,top:m.top}).svgContainer(L).xScale(d),U.select(".nv-interactive").call(k)),V.select(".nv-background").append("rect"),W.select(".nv-background rect").attr("width",N).attr("height",O),f.y(function(a){return a.display.y}).width(N).height(O).color(l.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!l[b].disabled&&!l[b].tempDisabled}));var Z=W.select(".nv-linesWrap").datum(l.filter(function(a){return!a.disabled&&!a.tempDisabled}));Z.call(f),l.forEach(function(a,b){a.seriesIndex=b});var $=l.filter(function(a){return!a.disabled&&!!B(a)}),_=W.select(".nv-avgLinesWrap").selectAll("line").data($,function(a){return a.key}),ab=function(a){var b=e(B(a));return 0>b?0:b>O?O:b};_.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(a){return f.color()(a,a.seriesIndex)}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.style("stroke-opacity",function(a){var b=e(B(a));return 0>b||b>O?0:1}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.exit().remove();var bb=Z.selectAll(".nv-indexLine").data([G]);bb.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(Q),bb.attr("transform",function(a){return"translate("+F(a.i)+",0)"}).attr("height",O),r&&(g.scale(d)._ticks(a.utils.calcTicksX(N/70,l)).tickSize(-O,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),W.select(".nv-x.nv-axis").call(g)),s&&(h.scale(e)._ticks(a.utils.calcTicksY(O/36,l)).tickSize(-N,0),W.select(".nv-y.nv-axis").call(h)),W.select(".nv-background rect").on("click",function(){G.x=d3.mouse(this)[0],G.i=Math.round(F.invert(G.x)),y.index=G.i,C.stateChange(y),K()}),f.dispatch.on("elementClick",function(a){G.i=a.pointIndex,G.x=F(G.i),y.index=G.i,C.stateChange(y),K()}),j.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,w=!a.disabled,y.rescaleY=w,C.stateChange(y),b.update()}),i.dispatch.on("stateChange",function(a){for(var c in a)y[c]=a[c];C.stateChange(y),b.update()}),k.dispatch.on("elementMousemove",function(c){f.clearHighlights();var d,e,i,j=[];if(l.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];"undefined"!=typeof k&&("undefined"==typeof d&&(d=k),"undefined"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:n(g,g.seriesIndex)}))}),j.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(j.map(function(a){return a.value}),o,q);null!==r&&(j[r].highlight=!0)}var s=g.tickFormat()(b.x()(d,e),e);k.tooltip.position({left:i+m.left,top:c.mouseY+m.top}).chartContainer(M.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:s,series:j})(),k.renderGuideLine(i)}),k.dispatch.on("elementMouseout",function(){f.clearHighlights()}),C.on("changeState",function(a){"undefined"!=typeof a.disabled&&(l.forEach(function(b,c){b.disabled=a.disabled[c]}),y.disabled=a.disabled),"undefined"!=typeof a.index&&(G.i=a.index,G.x=F(G.i),y.index=a.index,bb.data([G])),"undefined"!=typeof a.rescaleY&&(w=a.rescaleY),b.update()})}),H.renderEnd("cumulativeLineChart immediate"),b}function c(a,b){return K||(K=f.y()),b.map(function(b){if(!b.values)return b;var c=b.values[a];if(null==c)return b;var d=K(c,a);return-.95>d&&!E?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(K(a,b)-d)/(1+d)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l=a.models.tooltip(),m={top:30,right:30,bottom:50,left:60},n=a.utils.defaultColor(),o=null,p=null,q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=!0,x=f.id(),y=a.utils.state(),z=null,A=null,B=function(a){return a.average},C=d3.dispatch("stateChange","changeState","renderEnd"),D=250,E=!1;y.index=0,y.rescaleY=w,g.orient("bottom").tickPadding(7),h.orient(t?"right":"left"),l.valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)}),j.updateState(!1);var F=d3.scale.linear(),G={i:0,x:0},H=a.utils.renderWatch(C,D),I=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:G.i,rescaleY:w}}},J=function(a){return function(b){void 0!==b.index&&(G.i=b.index),void 0!==b.rescaleY&&(w=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on("elementMouseover.tooltip",function(a){var c={x:b.x()(a.point),y:b.y()(a.point),color:a.point.color};a.point=c,l.data(a).position(a.pos).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){l.hidden(!0)});var K=null;return b.dispatch=C,b.lines=f,b.legend=i,b.controls=j,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=y,b.tooltip=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},rescaleY:{get:function(){return w},set:function(a){w=a}},showControls:{get:function(){return u},set:function(a){u=a}},showLegend:{get:function(){return q},set:function(a){q=a}},average:{get:function(){return B},set:function(a){B=a}},defaultState:{get:function(){return z},set:function(a){z=a}},noData:{get:function(){return A},set:function(a){A=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},noErrorCheck:{get:function(){return E},set:function(a){E=a}},tooltips:{get:function(){return l.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),l.enabled(!!b)}},tooltipContent:{get:function(){return l.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),l.contentGenerator(b)}},margin:{get:function(){return m},set:function(a){m.top=void 0!==a.top?a.top:m.top,m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),i.color(n)}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,h.orient(a?"right":"left")}},duration:{get:function(){return D},set:function(a){D=a,f.duration(D),g.duration(D),h.duration(D),H.reset(D)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){"use strict";function b(m){return y.reset(),m.each(function(b){var m=k-j.left-j.right,x=l-j.top-j.bottom;c=d3.select(this),a.utils.initSVG(c),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0}})});n.domain(d||d3.merge(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(r))),o.range(t?g||[x-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]:g||[x,0]),h=h||n,i=i||o.copy().range([o(0),o(0)]);{var A=c.selectAll("g.nv-wrap.nv-discretebar").data([b]),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),C=B.append("g");A.select("g")}C.append("g").attr("class","nv-groups"),A.attr("transform","translate("+j.left+","+j.top+")");var D=A.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().watchTransition(y,"discreteBar: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),D.watchTransition(y,"discreteBar: groups").style("stroke-opacity",1).style("fill-opacity",.75);var E=D.selectAll("g.nv-bar").data(function(a){return a.values});E.exit().remove();var F=E.enter().append("g").attr("transform",function(a,b){return"translate("+(n(p(a,b))+.05*n.rangeBand())+", "+o(0)+")"}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),v.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),v.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){v.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){v.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()});F.append("rect").attr("height",0).attr("width",.9*n.rangeBand()/b.length),t?(F.append("text").attr("text-anchor","middle"),E.select("text").text(function(a,b){return u(q(a,b))}).watchTransition(y,"discreteBar: bars text").attr("x",.9*n.rangeBand()/2).attr("y",function(a,b){return q(a,b)<0?o(q(a,b))-o(0)+12:-4})):E.selectAll("text").remove(),E.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(a,b){return a.color||s(a,b)}).style("stroke",function(a,b){return a.color||s(a,b)}).select("rect").attr("class",w).watchTransition(y,"discreteBar: bars rect").attr("width",.9*n.rangeBand()/b.length),E.watchTransition(y,"discreteBar: bars").attr("transform",function(a,b){var c=n(p(a,b))+.05*n.rangeBand(),d=q(a,b)<0?o(0):o(0)-o(q(a,b))<1?o(0)-1:o(q(a,b));return"translate("+c+", "+d+")"}).select("rect").attr("height",function(a,b){return Math.max(Math.abs(o(q(a,b))-o(e&&e[0]||0))||1)}),h=n.copy(),i=o.copy()}),y.renderEnd("discreteBar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=d3.scale.ordinal(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=[0],s=a.utils.defaultColor(),t=!1,u=d3.format(",.2f"),v=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),w="discreteBar",x=250,y=a.utils.renderWatch(v,x);return b.dispatch=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},forceY:{get:function(){return r},set:function(a){r=a}},showValues:{get:function(){return t},set:function(a){t=a}},x:{get:function(){return p},set:function(a){p=a}},y:{get:function(){return q},set:function(a){q=a}},xScale:{get:function(){return n},set:function(a){n=a}},yScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},valueFormat:{get:function(){return u},set:function(a){u=a}},id:{get:function(){return m},set:function(a){m=a}},rectClass:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b)}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x)}}}),a.utils.initOptions(b),b},a.models.discreteBarChart=function(){"use strict";function b(h){return t.reset(),t.models(e),m&&t.models(f),n&&t.models(g),h.each(function(h){var l=d3.select(this);a.utils.initSVG(l);var q=a.utils.availableWidth(j,l,i),t=a.utils.availableHeight(k,l,i);if(b.update=function(){r.beforeUpdate(),l.transition().duration(s).call(b)},b.container=this,!(h&&h.length&&h.filter(function(a){return a.values.length}).length))return a.utils.noData(b,l),b;l.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var u=l.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([h]),v=u.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),w=v.append("defs"),x=u.select("g");v.append("g").attr("class","nv-x nv-axis"),v.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),v.append("g").attr("class","nv-barsWrap"),x.attr("transform","translate("+i.left+","+i.top+")"),o&&x.select(".nv-y.nv-axis").attr("transform","translate("+q+",0)"),e.width(q).height(t);var y=x.select(".nv-barsWrap").datum(h.filter(function(a){return!a.disabled}));if(y.transition().call(e),w.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),x.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(p?2:1)).attr("height",16).attr("x",-c.rangeBand()/(p?1:2)),m){f.scale(c)._ticks(a.utils.calcTicksX(q/100,h)).tickSize(-t,0),x.select(".nv-x.nv-axis").attr("transform","translate(0,"+(d.range()[0]+(e.showValues()&&d.domain()[0]<0?16:0))+")"),x.select(".nv-x.nv-axis").call(f); -var z=x.select(".nv-x.nv-axis").selectAll("g");p&&z.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}n&&(g.scale(d)._ticks(a.utils.calcTicksY(t/36,h)).tickSize(-q,0),x.select(".nv-y.nv-axis").call(g)),x.select(".nv-zeroLine line").attr("x1",0).attr("x2",q).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("discreteBar chart immediate"),b}var c,d,e=a.models.discreteBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.tooltip(),i={top:15,right:10,bottom:50,left:60},j=null,k=null,l=a.utils.getColor(),m=!0,n=!0,o=!1,p=!1,q=null,r=d3.dispatch("beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(o?"right":"left").tickFormat(d3.format(",.1f")),h.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).keyFormatter(function(a,b){return f.tickFormat()(a,b)});var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},h.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){h.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){h.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.discretebar=e,b.xAxis=f,b.yAxis=g,b.tooltip=h,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},staggerLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return m},set:function(a){m=a}},showYAxis:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return q},set:function(a){q=a}},tooltips:{get:function(){return h.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),h.enabled(!!b)}},tooltipContent:{get:function(){return h.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),h.contentGenerator(b)}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),e.color(l)}},rightAlignYAxis:{get:function(){return o},set:function(a){o=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.distribution=function(){"use strict";function b(k){return m.reset(),k.each(function(b){var k=(e-("x"===g?d.left+d.right:d.top+d.bottom),"x"==g?"y":"x"),l=d3.select(this);a.utils.initSVG(l),c=c||j;var n=l.selectAll("g.nv-distribution").data([b]),o=n.enter().append("g").attr("class","nvd3 nv-distribution"),p=(o.append("g"),n.select("g"));n.attr("transform","translate("+d.left+","+d.top+")");var q=p.selectAll("g.nv-dist").data(function(a){return a},function(a){return a.key});q.enter().append("g"),q.attr("class",function(a,b){return"nv-dist nv-series-"+b}).style("stroke",function(a,b){return i(a,b)});var r=q.selectAll("line.nv-dist"+g).data(function(a){return a.values});r.enter().append("line").attr(g+"1",function(a,b){return c(h(a,b))}).attr(g+"2",function(a,b){return c(h(a,b))}),m.transition(q.exit().selectAll("line.nv-dist"+g),"dist exit").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}).style("stroke-opacity",0).remove(),r.attr("class",function(a,b){return"nv-dist"+g+" nv-dist"+g+"-"+b}).attr(k+"1",0).attr(k+"2",f),m.transition(r,"dist").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}),c=j.copy()}),m.renderEnd("distribution immediate"),b}var c,d={top:0,right:0,bottom:0,left:0},e=400,f=8,g="x",h=function(a){return a[g]},i=a.utils.defaultColor(),j=d3.scale.linear(),k=250,l=d3.dispatch("renderEnd"),m=a.utils.renderWatch(l,k);return b.options=a.utils.optionsFunc.bind(b),b.dispatch=l,b.margin=function(a){return arguments.length?(d.top="undefined"!=typeof a.top?a.top:d.top,d.right="undefined"!=typeof a.right?a.right:d.right,d.bottom="undefined"!=typeof a.bottom?a.bottom:d.bottom,d.left="undefined"!=typeof a.left?a.left:d.left,b):d},b.width=function(a){return arguments.length?(e=a,b):e},b.axis=function(a){return arguments.length?(g=a,b):g},b.size=function(a){return arguments.length?(f=a,b):f},b.getData=function(a){return arguments.length?(h=d3.functor(a),b):h},b.scale=function(a){return arguments.length?(j=a,b):j},b.color=function(c){return arguments.length?(i=a.utils.getColor(c),b):i},b.duration=function(a){return arguments.length?(k=a,m.reset(k),b):k},b},a.models.furiousLegend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?g(a,b):"#fff":m?void 0:a.disabled?g(a,b):"#fff"}function r(a,b){return m&&"furious"==o?a.disengaged?"#fff":g(a,b):a.disabled?"#fff":g(a,b)}return p.each(function(b){var p=d-c.left-c.right,s=d3.select(this);a.utils.initSVG(s);var t=s.selectAll("g.nv-legend").data([b]),u=(t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),t.select("g"));t.attr("transform","translate("+c.left+","+c.top+")");var v,w=u.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),x=w.enter().append("g").attr("class","nv-series");if("classic"==o)x.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),v=w.select("circle");else if("furious"==o){x.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),v=w.select("rect"),x.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var y=w.select(".nv-check-box");y.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}x.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var z=w.select("text.nv-legend-text");w.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=w.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=w.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),w.classed("nv-disabled",function(a){return a.userDisabled}),w.exit().remove(),z.attr("fill",q).text(f);var A;switch(o){case"furious":A=23;break;case"classic":A=20}if(h){var B=[];w.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}B.push(b+i)});for(var C=0,D=0,E=[];p>D&&Cp&&C>1;){E=[],C--;for(var F=0;F(E[F%C]||0)&&(E[F%C]=B[F]);D=E.reduce(function(a,b){return a+b})}for(var G=[],H=0,I=0;C>H;H++)G[H]=I,I+=E[H];w.attr("transform",function(a,b){return"translate("+G[b%C]+","+(5+Math.floor(b/C)*A)+")"}),j?u.attr("transform","translate("+(d-c.right-D)+","+c.top+")"):u.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(B.length/C)*A}else{var J,K=5,L=5,M=0;w.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return J=L,dM&&(M=L),"translate("+J+","+K+")"}),u.attr("transform","translate("+(d-c.right-M)+","+c.top+")"),e=c.top+c.bottom+K+15}"furious"==o&&v.attr("width",function(a,b){return z[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),v.style("fill",r).style("stroke",function(a,b){return a.color||g(a,b)})}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=28,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBar=function(){"use strict";function b(x){return x.each(function(b){w.reset(),k=d3.select(this);var x=a.utils.availableWidth(h,k,g),y=a.utils.availableHeight(i,k,g);a.utils.initSVG(k),l.domain(c||d3.extent(b[0].values.map(n).concat(p))),l.range(r?e||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:e||[0,x]),m.domain(d||d3.extent(b[0].values.map(o).concat(q))).range(f||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var z=k.selectAll("g.nv-wrap.nv-historicalBar-"+j).data([b[0].values]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+j),B=A.append("defs"),C=A.append("g"),D=z.select("g");C.append("g").attr("class","nv-bars"),z.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){u.chartClick({data:a,index:b,pos:d3.event,id:j})}),B.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),z.select("#nv-chart-clip-path-"+j+" rect").attr("width",x).attr("height",y),D.attr("clip-path",s?"url(#nv-chart-clip-path-"+j+")":"");var E=z.select(".nv-bars").selectAll(".nv-bar").data(function(a){return a},function(a,b){return n(a,b)});E.exit().remove(),E.enter().append("rect").attr("x",0).attr("y",function(b,c){return a.utils.NaNtoZero(m(Math.max(0,o(b,c))))}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.abs(m(o(b,c))-m(0)))}).attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).on("mouseover",function(a,b){v&&(d3.select(this).classed("hover",!0),u.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mouseout",function(a,b){v&&(d3.select(this).classed("hover",!1),u.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mousemove",function(a,b){v&&u.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v&&(u.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}).on("dblclick",function(a,b){v&&(u.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}),E.attr("fill",function(a,b){return t(a,b)}).attr("class",function(a,b,c){return(o(a,b)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+c+"-"+b}).watchTransition(w,"bars").attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).attr("width",x/b[0].values.length*.9),E.watchTransition(w,"bars").attr("y",function(b,c){var d=o(b,c)<0?m(0):m(0)-m(o(b,c))<1?m(0)-1:m(o(b,c));return a.utils.NaNtoZero(d)}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.max(Math.abs(m(o(b,c))-m(0)),1))})}),w.renderEnd("historicalBar immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=[],q=[0],r=!1,s=!0,t=a.utils.defaultColor(),u=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),v=!0,w=a.utils.renderWatch(u,0);return b.highlightPoint=function(a,b){k.select(".nv-bars .nv-bar-0-"+a).classed("hover",b)},b.clearHighlights=function(){k.select(".nv-bars .nv-bar.hover").classed("hover",!1)},b.dispatch=u,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},forceX:{get:function(){return p},set:function(a){p=a}},forceY:{get:function(){return q},set:function(a){q=a}},padData:{get:function(){return r},set:function(a){r=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},clipEdge:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return t},set:function(b){t=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBarChart=function(b){"use strict";function c(b){return b.each(function(k){z.reset(),z.models(f),q&&z.models(g),r&&z.models(h);var w=d3.select(this),A=this;a.utils.initSVG(w);var B=a.utils.availableWidth(n,w,l),C=a.utils.availableHeight(o,w,l);if(c.update=function(){w.transition().duration(y).call(c)},c.container=this,u.disabled=k.map(function(a){return!!a.disabled}),!v){var D;v={};for(D in u)v[D]=u[D]instanceof Array?u[D].slice(0):u[D]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(c,w),c;w.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale();var E=w.selectAll("g.nv-wrap.nv-historicalBarChart").data([k]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),G=E.select("g");F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-barsWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),p&&(i.width(B),G.select(".nv-legendWrap").datum(k).call(i),l.top!=i.height()&&(l.top=i.height(),C=a.utils.availableHeight(o,w,l)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")")),E.attr("transform","translate("+l.left+","+l.top+")"),s&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),t&&(j.width(B).height(C).margin({left:l.left,top:l.top}).svgContainer(w).xScale(d),E.select(".nv-interactive").call(j)),f.width(B).height(C).color(k.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!k[b].disabled}));var H=G.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));H.transition().call(f),q&&(g.scale(d)._ticks(a.utils.calcTicksX(B/100,k)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),G.select(".nv-x.nv-axis").transition().call(g)),r&&(h.scale(e)._ticks(a.utils.calcTicksY(C/36,k)).tickSize(-B,0),G.select(".nv-y.nv-axis").transition().call(h)),j.dispatch.on("elementMousemove",function(b){f.clearHighlights();var d,e,i,n=[];k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g){e=a.interactiveBisect(g.values,b.pointXValue,c.x()),f.highlightPoint(e,!0);var h=g.values[e];void 0!==h&&(void 0===d&&(d=h),void 0===i&&(i=c.xScale()(c.x()(h,e))),n.push({key:g.key,value:c.y()(h,e),color:m(g,g.seriesIndex),data:g.values[e]}))});var o=g.tickFormat()(c.x()(d,e));j.tooltip.position({left:i+l.left,top:b.mouseY+l.top}).chartContainer(A.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:o,index:e,series:n})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(){x.tooltipHide(),f.clearHighlights()}),i.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,k.filter(function(a){return!a.disabled}).length||k.map(function(a){return a.disabled=!1,E.selectAll(".nv-series").classed("disabled",!1),a}),u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),b.transition().call(c)}),i.dispatch.on("legendDblclick",function(a){k.forEach(function(a){a.disabled=!0}),a.disabled=!1,u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),c.update()}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),c.update()})}),z.renderEnd("historicalBarChart immediate"),c}var d,e,f=b||a.models.historicalBar(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:90,bottom:50,left:90},m=a.utils.defaultColor(),n=null,o=null,p=!1,q=!0,r=!0,s=!1,t=!1,u={},v=null,w=null,x=d3.dispatch("tooltipHide","stateChange","changeState","renderEnd"),y=250;g.orient("bottom").tickPadding(7),h.orient(s?"right":"left"),k.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)});var z=a.utils.renderWatch(x,0);return f.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:c.x()(a.data),value:c.y()(a.data),color:a.color},k.data(a).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),f.dispatch.on("elementMousemove.tooltip",function(){k.position({top:d3.event.pageY,left:d3.event.pageX})()}),c.dispatch=x,c.bars=f,c.legend=i,c.xAxis=g,c.yAxis=h,c.interactiveLayer=j,c.tooltip=k,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{width:{get:function(){return n},set:function(a){n=a}},height:{get:function(){return o},set:function(a){o=a}},showLegend:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b),i.color(m),f.color(m)}},duration:{get:function(){return y},set:function(a){y=a,z.reset(y),h.duration(y),g.duration(y)}},rightAlignYAxis:{get:function(){return s},set:function(a){s=a,h.orient(a?"right":"left")}},useInteractiveGuideline:{get:function(){return t},set:function(a){t=a,a===!0&&c.interactive(!1)}}}),a.utils.inheritOptions(c,f),a.utils.initOptions(c),c},a.models.ohlcBarChart=function(){var b=a.models.historicalBarChart(a.models.ohlcBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
    open:"+b.yAxis.tickFormat()(c.open)+"
    close:"+b.yAxis.tickFormat()(c.close)+"
    high"+b.yAxis.tickFormat()(c.high)+"
    low:"+b.yAxis.tickFormat()(c.low)+"
    "}),b},a.models.candlestickBarChart=function(){var b=a.models.historicalBarChart(a.models.candlestickBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
    open:"+b.yAxis.tickFormat()(c.open)+"
    close:"+b.yAxis.tickFormat()(c.close)+"
    high"+b.yAxis.tickFormat()(c.high)+"
    low:"+b.yAxis.tickFormat()(c.low)+"
    "}),b},a.models.legend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?"#000":"#fff":m?void 0:(a.color||(a.color=g(a,b)),a.disabled?a.color:"#fff")}function r(a,b){return m&&"furious"==o&&a.disengaged?"#eee":a.color||g(a,b)}function s(a){return m&&"furious"==o?1:a.disabled?0:1}return p.each(function(b){var g=d-c.left-c.right,p=d3.select(this);a.utils.initSVG(p);var t=p.selectAll("g.nv-legend").data([b]),u=t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),v=t.select("g");t.attr("transform","translate("+c.left+","+c.top+")");var w,x,y=v.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),z=y.enter().append("g").attr("class","nv-series");switch(o){case"furious":x=23;break;case"classic":x=20}if("classic"==o)z.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),w=y.select("circle");else if("furious"==o){z.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),w=y.select(".nv-legend-symbol"),z.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var A=y.select(".nv-check-box");A.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}z.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var B=y.select("text.nv-legend-text");y.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=y.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=y.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),y.classed("nv-disabled",function(a){return a.userDisabled}),y.exit().remove(),B.attr("fill",q).text(f);var C=0;if(h){var D=[];y.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}D.push(b+i)});var E=0,F=[];for(C=0;g>C&&Eg&&E>1;){F=[],E--;for(var G=0;G(F[G%E]||0)&&(F[G%E]=D[G]);C=F.reduce(function(a,b){return a+b})}for(var H=[],I=0,J=0;E>I;I++)H[I]=J,J+=F[I];y.attr("transform",function(a,b){return"translate("+H[b%E]+","+(5+Math.floor(b/E)*x)+")"}),j?v.attr("transform","translate("+(d-c.right-C)+","+c.top+")"):v.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(D.length/E)*x}else{var K,L=5,M=5,N=0;y.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return K=M,dN&&(N=M),K+N>C&&(C=K+N),"translate("+K+","+L+")"}),v.attr("transform","translate("+(d-c.right-N)+","+c.top+")"),e=c.top+c.bottom+L+15}if("furious"==o){w.attr("width",function(a,b){return B[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),u.insert("rect",":first-child").attr("class","nv-legend-bg").attr("fill","#eee").attr("opacity",0);var O=v.select(".nv-legend-bg");O.transition().duration(300).attr("x",-x).attr("width",C+x-12).attr("height",e+10).attr("y",-c.top-10).attr("opacity",m?1:0)}w.style("fill",r).style("fill-opacity",s).style("stroke",r)}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=32,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.line=function(){"use strict";function b(r){return v.reset(),v.models(e),r.each(function(b){i=d3.select(this);var r=a.utils.availableWidth(g,i,f),s=a.utils.availableHeight(h,i,f);a.utils.initSVG(i),c=e.xScale(),d=e.yScale(),t=t||c,u=u||d;var w=i.selectAll("g.nv-wrap.nv-line").data([b]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),y=x.append("defs"),z=x.append("g"),A=w.select("g");z.append("g").attr("class","nv-groups"),z.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+f.left+","+f.top+")"),e.width(r).height(s);var B=w.select(".nv-scatterWrap");B.call(e),y.append("clipPath").attr("id","nv-edge-clip-"+e.id()).append("rect"),w.select("#nv-edge-clip-"+e.id()+" rect").attr("width",r).attr("height",s>0?s:0),A.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":""),B.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":"");var C=w.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});C.enter().append("g").style("stroke-opacity",1e-6).style("stroke-width",function(a){return a.strokeWidth||j}).style("fill-opacity",1e-6),C.exit().remove(),C.attr("class",function(a,b){return(a.classed||"")+" nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return k(a,b)}).style("stroke",function(a,b){return k(a,b)}),C.watchTransition(v,"line: groups").style("stroke-opacity",1).style("fill-opacity",function(a){return a.fillOpacity||.5});var D=C.selectAll("path.nv-area").data(function(a){return o(a)?[a]:[]});D.enter().append("path").attr("class","nv-area").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y0(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))}).y1(function(){return u(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])}),C.exit().selectAll("path.nv-area").remove(),D.watchTransition(v,"line: areaPaths").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y0(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))}).y1(function(){return d(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])});var E=C.selectAll("path.nv-line").data(function(a){return[a.values]});E.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))})),E.watchTransition(v,"line: linePaths").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))})),t=c.copy(),u=d.copy()}),v.renderEnd("line immediate"),b}var c,d,e=a.models.scatter(),f={top:0,right:0,bottom:0,left:0},g=960,h=500,i=null,j=1.5,k=a.utils.defaultColor(),l=function(a){return a.x},m=function(a){return a.y},n=function(a,b){return!isNaN(m(a,b))&&null!==m(a,b)},o=function(a){return a.area},p=!1,q="linear",r=250,s=d3.dispatch("elementClick","elementMouseover","elementMouseout","renderEnd");e.pointSize(16).pointDomain([16,256]);var t,u,v=a.utils.renderWatch(s,r);return b.dispatch=s,b.scatter=e,e.dispatch.on("elementClick",function(){s.elementClick.apply(this,arguments)}),e.dispatch.on("elementMouseover",function(){s.elementMouseover.apply(this,arguments)}),e.dispatch.on("elementMouseout",function(){s.elementMouseout.apply(this,arguments)}),b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},defined:{get:function(){return n},set:function(a){n=a}},interpolate:{get:function(){return q},set:function(a){q=a}},clipEdge:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},duration:{get:function(){return r},set:function(a){r=a,v.reset(r),e.duration(r)}},isArea:{get:function(){return o},set:function(a){o=d3.functor(a)}},x:{get:function(){return l},set:function(a){l=a,e.x(a)}},y:{get:function(){return m},set:function(a){m=a,e.y(a)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineChart=function(){"use strict";function b(j){return y.reset(),y.models(e),p&&y.models(f),q&&y.models(g),j.each(function(j){var v=d3.select(this),y=this;a.utils.initSVG(v);var B=a.utils.availableWidth(m,v,k),C=a.utils.availableHeight(n,v,k);if(b.update=function(){0===x?v.call(b):v.transition().duration(x).call(b)},b.container=this,t.setter(A(j),b.update).getter(z(j)).update(),t.disabled=j.map(function(a){return!!a.disabled}),!u){var D;u={};for(D in t)u[D]=t[D]instanceof Array?t[D].slice(0):t[D] -}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,v),b;v.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var E=v.selectAll("g.nv-wrap.nv-lineChart").data([j]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),G=E.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-linesWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),G.select("rect").attr("width",B).attr("height",C>0?C:0),o&&(h.width(B),G.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),C=a.utils.availableHeight(n,v,k)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-k.top+")")),E.attr("transform","translate("+k.left+","+k.top+")"),r&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),s&&(i.width(B).height(C).margin({left:k.left,top:k.top}).svgContainer(v).xScale(c),E.select(".nv-interactive").call(i)),e.width(B).height(C).color(j.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!j[b].disabled}));var H=G.select(".nv-linesWrap").datum(j.filter(function(a){return!a.disabled}));H.call(e),p&&(f.scale(c)._ticks(a.utils.calcTicksX(B/100,j)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),G.select(".nv-x.nv-axis").call(f)),q&&(g.scale(d)._ticks(a.utils.calcTicksY(C/36,j)).tickSize(-B,0),G.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)t[c]=a[c];w.stateChange(t),b.update()}),i.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,h,m,n=[];if(j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=a.interactiveBisect(f.values,c.pointXValue,b.x());var i=f.values[h],j=b.y()(i,h);null!=j&&e.highlightPoint(g,h,!0),void 0!==i&&(void 0===d&&(d=i),void 0===m&&(m=b.xScale()(b.x()(i,h))),n.push({key:f.key,value:j,color:l(f,f.seriesIndex)}))}),n.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(n.map(function(a){return a.value}),o,q);null!==r&&(n[r].highlight=!0)}var s=f.tickFormat()(b.x()(d,h));i.tooltip.position({left:c.mouseX+k.left,top:c.mouseY+k.top}).chartContainer(y.parentNode).valueFormatter(function(a){return null==a?"N/A":g.tickFormat()(a)}).data({value:s,index:h,series:n})(),i.renderGuideLine(m)}),i.dispatch.on("elementClick",function(c){var d,f=[];j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if("undefined"!=typeof h){"undefined"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on("elementMouseout",function(){e.clearHighlights()}),w.on("changeState",function(a){"undefined"!=typeof a.disabled&&j.length===a.disabled.length&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),t.disabled=a.disabled),b.update()})}),y.renderEnd("lineChart immediate"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=a.utils.defaultColor(),m=null,n=null,o=!0,p=!0,q=!0,r=!1,s=!1,t=a.utils.state(),u=null,v=null,w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),x=250;f.orient("bottom").tickPadding(7),g.orient(r?"right":"left"),j.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)});var y=a.utils.renderWatch(w,x),z=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},A=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){j.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),b.dispatch=w,b.lines=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.interactiveLayer=i,b.tooltip=j,b.dispatch=w,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return p},set:function(a){p=a}},showYAxis:{get:function(){return q},set:function(a){q=a}},defaultState:{get:function(){return u},set:function(a){u=a}},noData:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x),e.duration(x),f.duration(x),g.duration(x)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),h.color(l),e.color(l)}},rightAlignYAxis:{get:function(){return r},set:function(a){r=a,g.orient(r?"right":"left")}},useInteractiveGuideline:{get:function(){return s},set:function(a){s=a,s&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.linePlusBarChart=function(){"use strict";function b(v){return v.each(function(v){function J(a){var b=+("e"==a),c=b?1:-1,d=X/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function S(){u.empty()||u.extent(I),kb.data([u.empty()?e.domain():I]).each(function(a){var b=e(a[0])-e.range()[0],c=e.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>c?0:c)})}function T(){I=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),K.brush({extent:c,brush:u}),S(),l.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),j.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var b=db.select(".nv-focus .nv-barsWrap").datum(Z.length?Z.map(function(a){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=db.select(".nv-focus .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$.map(function(a){return{area:a.area,fillOpacity:a.fillOpacity,key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=Z.length?l.xScale():j.xScale(),n.scale(d)._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-W,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),db.select(".nv-x.nv-axis").transition().duration(L).call(n),b.transition().duration(L).call(l),h.transition().duration(L).call(j),db.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),p.scale(f)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(-V,0),q.scale(g)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(Z.length?0:-V,0),db.select(".nv-focus .nv-y1.nv-axis").style("opacity",Z.length?1:0),db.select(".nv-focus .nv-y2.nv-axis").style("opacity",$.length&&!$[0].disabled?1:0).attr("transform","translate("+d.range()[1]+",0)"),db.select(".nv-focus .nv-y1.nv-axis").transition().duration(L).call(p),db.select(".nv-focus .nv-y2.nv-axis").transition().duration(L).call(q)}var U=d3.select(this);a.utils.initSVG(U);var V=a.utils.availableWidth(y,U,w),W=a.utils.availableHeight(z,U,w)-(E?H:0),X=H-x.top-x.bottom;if(b.update=function(){U.transition().duration(L).call(b)},b.container=this,M.setter(R(v),b.update).getter(Q(v)).update(),M.disabled=v.map(function(a){return!!a.disabled}),!N){var Y;N={};for(Y in M)N[Y]=M[Y]instanceof Array?M[Y].slice(0):M[Y]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length))return a.utils.noData(b,U),b;U.selectAll(".nv-noData").remove();var Z=v.filter(function(a){return!a.disabled&&a.bar}),$=v.filter(function(a){return!a.bar});d=l.xScale(),e=o.scale(),f=l.yScale(),g=j.yScale(),h=m.yScale(),i=k.yScale();var _=v.filter(function(a){return!a.disabled&&a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})}),ab=v.filter(function(a){return!a.disabled&&!a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})});d.range([0,V]),e.domain(d3.extent(d3.merge(_.concat(ab)),function(a){return a.x})).range([0,V]);var bb=U.selectAll("g.nv-wrap.nv-linePlusBar").data([v]),cb=bb.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),db=bb.select("g");cb.append("g").attr("class","nv-legendWrap");var eb=cb.append("g").attr("class","nv-focus");eb.append("g").attr("class","nv-x nv-axis"),eb.append("g").attr("class","nv-y1 nv-axis"),eb.append("g").attr("class","nv-y2 nv-axis"),eb.append("g").attr("class","nv-barsWrap"),eb.append("g").attr("class","nv-linesWrap");var fb=cb.append("g").attr("class","nv-context");if(fb.append("g").attr("class","nv-x nv-axis"),fb.append("g").attr("class","nv-y1 nv-axis"),fb.append("g").attr("class","nv-y2 nv-axis"),fb.append("g").attr("class","nv-barsWrap"),fb.append("g").attr("class","nv-linesWrap"),fb.append("g").attr("class","nv-brushBackground"),fb.append("g").attr("class","nv-x nv-brush"),D){var gb=t.align()?V/2:V,hb=t.align()?gb:0;t.width(gb),db.select(".nv-legendWrap").datum(v.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(a.bar?O:P),a})).call(t),w.top!=t.height()&&(w.top=t.height(),W=a.utils.availableHeight(z,U,w)-H),db.select(".nv-legendWrap").attr("transform","translate("+hb+","+-w.top+")")}bb.attr("transform","translate("+w.left+","+w.top+")"),db.select(".nv-context").style("display",E?"initial":"none"),m.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),k.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var ib=db.select(".nv-context .nv-barsWrap").datum(Z.length?Z:[{values:[]}]),jb=db.select(".nv-context .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$);db.select(".nv-context").attr("transform","translate(0,"+(W+w.bottom+x.top)+")"),ib.transition().call(m),jb.transition().call(k),G&&(o._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-X,0),db.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+h.range()[0]+")"),db.select(".nv-context .nv-x.nv-axis").transition().call(o)),F&&(r.scale(h)._ticks(X/36).tickSize(-V,0),s.scale(i)._ticks(X/36).tickSize(Z.length?0:-V,0),db.select(".nv-context .nv-y3.nv-axis").style("opacity",Z.length?1:0).attr("transform","translate(0,"+e.range()[0]+")"),db.select(".nv-context .nv-y2.nv-axis").style("opacity",$.length?1:0).attr("transform","translate("+e.range()[1]+",0)"),db.select(".nv-context .nv-y1.nv-axis").transition().call(r),db.select(".nv-context .nv-y2.nv-axis").transition().call(s)),u.x(e).on("brush",T),I&&u.extent(I);var kb=db.select(".nv-brushBackground").selectAll("g").data([I||u.extent()]),lb=kb.enter().append("g");lb.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",X),lb.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",X);var mb=db.select(".nv-x.nv-brush").call(u);mb.selectAll("rect").attr("height",X),mb.selectAll(".resize").append("path").attr("d",J),t.dispatch.on("stateChange",function(a){for(var c in a)M[c]=a[c];K.stateChange(M),b.update()}),K.on("changeState",function(a){"undefined"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),M.disabled=a.disabled),b.update()}),T()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v=a.models.tooltip(),w={top:30,right:30,bottom:30,left:60},x={top:0,right:30,bottom:20,left:60},y=null,z=null,A=function(a){return a.x},B=function(a){return a.y},C=a.utils.defaultColor(),D=!0,E=!0,F=!1,G=!0,H=50,I=null,J=null,K=d3.dispatch("brush","stateChange","changeState"),L=0,M=a.utils.state(),N=null,O=" (left axis)",P=" (right axis)";j.clipEdge(!0),k.interactive(!1),k.pointActive(function(){return!1}),n.orient("bottom").tickPadding(5),p.orient("left"),q.orient("right"),o.orient("bottom").tickPadding(5),r.orient("left"),s.orient("right"),v.headerEnabled(!0).headerFormatter(function(a,b){return n.tickFormat()(a,b)});var Q=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},R=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return j.dispatch.on("elementMouseover.tooltip",function(a){v.duration(100).valueFormatter(function(a,b){return q.tickFormat()(a,b)}).data(a).position(a.pos).hidden(!1)}),j.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={value:b.y()(a.data),color:a.color},v.duration(0).valueFormatter(function(a,b){return p.tickFormat()(a,b)}).data(a).hidden(!1)}),l.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMousemove.tooltip",function(){v.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=K,b.legend=t,b.lines=j,b.lines2=k,b.bars=l,b.bars2=m,b.xAxis=n,b.x2Axis=o,b.y1Axis=p,b.y2Axis=q,b.y3Axis=r,b.y4Axis=s,b.tooltip=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return y},set:function(a){y=a}},height:{get:function(){return z},set:function(a){z=a}},showLegend:{get:function(){return D},set:function(a){D=a}},brushExtent:{get:function(){return I},set:function(a){I=a}},noData:{get:function(){return J},set:function(a){J=a}},focusEnable:{get:function(){return E},set:function(a){E=a}},focusHeight:{get:function(){return H},set:function(a){H=a}},focusShowAxisX:{get:function(){return G},set:function(a){G=a}},focusShowAxisY:{get:function(){return F},set:function(a){F=a}},legendLeftAxisHint:{get:function(){return O},set:function(a){O=a}},legendRightAxisHint:{get:function(){return P},set:function(a){P=a}},tooltips:{get:function(){return v.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),v.enabled(!!b)}},tooltipContent:{get:function(){return v.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),v.contentGenerator(b)}},margin:{get:function(){return w},set:function(a){w.top=void 0!==a.top?a.top:w.top,w.right=void 0!==a.right?a.right:w.right,w.bottom=void 0!==a.bottom?a.bottom:w.bottom,w.left=void 0!==a.left?a.left:w.left}},focusMargin:{get:function(){return x},set:function(a){x.top=void 0!==a.top?a.top:x.top,x.right=void 0!==a.right?a.right:x.right,x.bottom=void 0!==a.bottom?a.bottom:x.bottom,x.left=void 0!==a.left?a.left:x.left}},duration:{get:function(){return L},set:function(a){L=a}},color:{get:function(){return C},set:function(b){C=a.utils.getColor(b),t.color(C)}},x:{get:function(){return A},set:function(a){A=a,j.x(a),k.x(a),l.x(a),m.x(a)}},y:{get:function(){return B},set:function(a){B=a,j.y(a),k.y(a),l.y(a),m.y(a)}}}),a.utils.inheritOptions(b,j),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){"use strict";function b(o){return o.each(function(o){function z(a){var b=+("e"==a),c=b?1:-1,d=M/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function G(){n.empty()||n.extent(y),U.data([n.empty()?e.domain():y]).each(function(a){var b=e(a[0])-c.range()[0],d=K-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>d?0:d)})}function H(){y=n.empty()?null:n.extent();var a=n.empty()?e.domain():n.extent();if(!(Math.abs(a[0]-a[1])<=1)){A.brush({extent:a,brush:n}),G();var b=Q.select(".nv-focus .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}).map(function(b){return{key:b.key,area:b.area,values:b.values.filter(function(b,c){return g.x()(b,c)>=a[0]&&g.x()(b,c)<=a[1]})}}));b.transition().duration(B).call(g),Q.select(".nv-focus .nv-x.nv-axis").transition().duration(B).call(i),Q.select(".nv-focus .nv-y.nv-axis").transition().duration(B).call(j)}}var I=d3.select(this),J=this;a.utils.initSVG(I);var K=a.utils.availableWidth(t,I,q),L=a.utils.availableHeight(u,I,q)-v,M=v-r.top-r.bottom;if(b.update=function(){I.transition().duration(B).call(b)},b.container=this,C.setter(F(o),b.update).getter(E(o)).update(),C.disabled=o.map(function(a){return!!a.disabled}),!D){var N;D={};for(N in C)D[N]=C[N]instanceof Array?C[N].slice(0):C[N]}if(!(o&&o.length&&o.filter(function(a){return a.values.length}).length))return a.utils.noData(b,I),b;I.selectAll(".nv-noData").remove(),c=g.xScale(),d=g.yScale(),e=h.xScale(),f=h.yScale();var O=I.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([o]),P=O.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),Q=O.select("g");P.append("g").attr("class","nv-legendWrap");var R=P.append("g").attr("class","nv-focus");R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-linesWrap"),R.append("g").attr("class","nv-interactive");var S=P.append("g").attr("class","nv-context");S.append("g").attr("class","nv-x nv-axis"),S.append("g").attr("class","nv-y nv-axis"),S.append("g").attr("class","nv-linesWrap"),S.append("g").attr("class","nv-brushBackground"),S.append("g").attr("class","nv-x nv-brush"),x&&(m.width(K),Q.select(".nv-legendWrap").datum(o).call(m),q.top!=m.height()&&(q.top=m.height(),L=a.utils.availableHeight(u,I,q)-v),Q.select(".nv-legendWrap").attr("transform","translate(0,"+-q.top+")")),O.attr("transform","translate("+q.left+","+q.top+")"),w&&(p.width(K).height(L).margin({left:q.left,top:q.top}).svgContainer(I).xScale(c),O.select(".nv-interactive").call(p)),g.width(K).height(L).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),h.defined(g.defined()).width(K).height(M).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),Q.select(".nv-context").attr("transform","translate(0,"+(L+q.bottom+r.top)+")");var T=Q.select(".nv-context .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}));d3.transition(T).call(h),i.scale(c)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-L,0),j.scale(d)._ticks(a.utils.calcTicksY(L/36,o)).tickSize(-K,0),Q.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L+")"),n.x(e).on("brush",function(){H()}),y&&n.extent(y);var U=Q.select(".nv-brushBackground").selectAll("g").data([y||n.extent()]),V=U.enter().append("g");V.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",M),V.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",M);var W=Q.select(".nv-x.nv-brush").call(n);W.selectAll("rect").attr("height",M),W.selectAll(".resize").append("path").attr("d",z),H(),k.scale(e)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-M,0),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),d3.transition(Q.select(".nv-context .nv-x.nv-axis")).call(k),l.scale(f)._ticks(a.utils.calcTicksY(M/36,o)).tickSize(-K,0),d3.transition(Q.select(".nv-context .nv-y.nv-axis")).call(l),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),m.dispatch.on("stateChange",function(a){for(var c in a)C[c]=a[c];A.stateChange(C),b.update()}),p.dispatch.on("elementMousemove",function(c){g.clearHighlights();var d,f,h,k=[];if(o.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(i,j){var l=n.empty()?e.domain():n.extent(),m=i.values.filter(function(a,b){return g.x()(a,b)>=l[0]&&g.x()(a,b)<=l[1]});f=a.interactiveBisect(m,c.pointXValue,g.x());var o=m[f],p=b.y()(o,f);null!=p&&g.highlightPoint(j,f,!0),void 0!==o&&(void 0===d&&(d=o),void 0===h&&(h=b.xScale()(b.x()(o,f))),k.push({key:i.key,value:b.y()(o,f),color:s(i,i.seriesIndex)}))}),k.length>2){var l=b.yScale().invert(c.mouseY),m=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),r=.03*m,t=a.nearestValueIndex(k.map(function(a){return a.value}),l,r);null!==t&&(k[t].highlight=!0)}var u=i.tickFormat()(b.x()(d,f));p.tooltip.position({left:c.mouseX+q.left,top:c.mouseY+q.top}).chartContainer(J.parentNode).valueFormatter(function(a){return null==a?"N/A":j.tickFormat()(a)}).data({value:u,index:f,series:k})(),p.renderGuideLine(h)}),p.dispatch.on("elementMouseout",function(){g.clearHighlights()}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&o.forEach(function(b,c){b.disabled=a.disabled[c]}),b.update()})}),b}var c,d,e,f,g=a.models.line(),h=a.models.line(),i=a.models.axis(),j=a.models.axis(),k=a.models.axis(),l=a.models.axis(),m=a.models.legend(),n=d3.svg.brush(),o=a.models.tooltip(),p=a.interactiveGuideline(),q={top:30,right:30,bottom:30,left:60},r={top:0,right:30,bottom:20,left:60},s=a.utils.defaultColor(),t=null,u=null,v=50,w=!1,x=!0,y=null,z=null,A=d3.dispatch("brush","stateChange","changeState"),B=250,C=a.utils.state(),D=null;g.clipEdge(!0).duration(0),h.interactive(!1),h.pointActive(function(){return!1}),i.orient("bottom").tickPadding(5),j.orient("left"),k.orient("bottom").tickPadding(5),l.orient("left"),o.valueFormatter(function(a,b){return j.tickFormat()(a,b)}).headerFormatter(function(a,b){return i.tickFormat()(a,b)});var E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return g.dispatch.on("elementMouseover.tooltip",function(a){o.data(a).position(a.pos).hidden(!1)}),g.dispatch.on("elementMouseout.tooltip",function(){o.hidden(!0)}),b.dispatch=A,b.legend=m,b.lines=g,b.lines2=h,b.xAxis=i,b.yAxis=j,b.x2Axis=k,b.y2Axis=l,b.interactiveLayer=p,b.tooltip=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return t},set:function(a){t=a}},height:{get:function(){return u},set:function(a){u=a}},focusHeight:{get:function(){return v},set:function(a){v=a}},showLegend:{get:function(){return x},set:function(a){x=a}},brushExtent:{get:function(){return y},set:function(a){y=a}},defaultState:{get:function(){return D},set:function(a){D=a}},noData:{get:function(){return z},set:function(a){z=a}},tooltips:{get:function(){return o.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),o.enabled(!!b)}},tooltipContent:{get:function(){return o.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),o.contentGenerator(b)}},margin:{get:function(){return q},set:function(a){q.top=void 0!==a.top?a.top:q.top,q.right=void 0!==a.right?a.right:q.right,q.bottom=void 0!==a.bottom?a.bottom:q.bottom,q.left=void 0!==a.left?a.left:q.left}},focusMargin:{get:function(){return r},set:function(a){r.top=void 0!==a.top?a.top:r.top,r.right=void 0!==a.right?a.right:r.right,r.bottom=void 0!==a.bottom?a.bottom:r.bottom,r.left=void 0!==a.left?a.left:r.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b),m.color(s)}},interpolate:{get:function(){return g.interpolate()},set:function(a){g.interpolate(a),h.interpolate(a)}},xTickFormat:{get:function(){return i.tickFormat()},set:function(a){i.tickFormat(a),k.tickFormat(a)}},yTickFormat:{get:function(){return j.tickFormat()},set:function(a){j.tickFormat(a),l.tickFormat(a)}},duration:{get:function(){return B},set:function(a){B=a,j.duration(B),l.duration(B),i.duration(B),k.duration(B)}},x:{get:function(){return g.x()},set:function(a){g.x(a),h.x(a)}},y:{get:function(){return g.y()},set:function(a){g.y(a),h.y(a)}},useInteractiveGuideline:{get:function(){return w},set:function(a){w=a,w&&(g.interactive(!1),g.useVoronoi(!1))}}}),a.utils.inheritOptions(b,g),a.utils.initOptions(b),b},a.models.multiBar=function(){"use strict";function b(G){return E.reset(),G.each(function(b){var G=k-j.left-j.right,H=l-j.top-j.bottom;p=d3.select(this),a.utils.initSVG(p);var I=0;if(z&&b.length&&(z=[{values:b[0].values.map(function(a){return{x:a.x,y:0,series:a.series,size:.01}})}]),v){var J=d3.layout.stack().offset(w).values(function(a){return a.values}).y(r)(!b.length&&z?z:b);J.forEach(function(a,c){a.nonStackable?(b[c].nonStackableSeries=I++,J[c]=b[c]):c>0&&J[c-1].nonStackable&&J[c].values.map(function(a,b){a.y0-=J[c-1].values[b].y,a.y1=a.y0+a.y})}),b=J}b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),v&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a,f){if(!b[f].nonStackable){var g=a.values[c];g.size=Math.abs(g.y),g.y<0?(g.y1=e,e-=g.size):(g.y1=g.size+d,d+=g.size)}})});var K=d&&e?[]:b.map(function(a,b){return a.values.map(function(a,c){return{x:q(a,c),y:r(a,c),y0:a.y0,y1:a.y1,idx:b,yErr:s(a,c)}})});m.domain(d||d3.merge(K).map(function(a){return a.x})).rangeBands(f||[0,G],C),n.domain(e||d3.extent(d3.merge(d3.merge(K).map(function(a){var c=a.y;v&&!b[a.idx].nonStackable&&(c=a.y>0?a.y1:a.y1+a.y);var d=a.yErr;return d?d.length?[c+d[0],c+d[1]]:(d=Math.abs(d),[c-d,c+d]):[c]})).concat(t))).range(g||[H,0]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]+.01*n.domain()[0],n.domain()[1]-.01*n.domain()[1]]:[-1,1]),h=h||m,i=i||n;var L=p.selectAll("g.nv-wrap.nv-multibar").data([b]),M=L.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),N=M.append("defs"),O=M.append("g"),P=L.select("g");O.append("g").attr("class","nv-groups"),L.attr("transform","translate("+j.left+","+j.top+")"),N.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),L.select("#nv-edge-clip-"+o+" rect").attr("width",G).attr("height",H),P.attr("clip-path",u?"url(#nv-edge-clip-"+o+")":"");var Q=L.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});Q.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);var R=E.transition(Q.exit().selectAll("g.nv-bar"),"multibarExit",Math.min(100,B)).attr("y",function(a){var c=i(0)||0;return v&&b[a.series]&&!b[a.series].nonStackable&&(c=i(a.y0)),c}).attr("height",0).remove();R.delay&&R.delay(function(a,b){var c=b*(B/(F+1))-b;return c}),Q.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return x(a,b)}).style("stroke",function(a,b){return x(a,b)}),Q.style("stroke-opacity",1).style("fill-opacity",.75);var S=Q.selectAll("g.nv-bar").data(function(a){return z&&!b.length?z.values:a.values});S.exit().remove();var T=S.enter().append("g").attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(a,c,d){var e=v&&!b[d].nonStackable?0:d*m.rangeBand()/b.length,f=i(v&&!b[d].nonStackable?a.y0:0)||0;return"translate("+e+","+f+")"});T.append("rect").attr("height",0).attr("width",function(a,c,d){return m.rangeBand()/(v&&!b[d].nonStackable?1:b.length)}).style("fill",function(a,b,c){return x(a,c,b)}).style("stroke",function(a,b,c){return x(a,c,b)}),S.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),D.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){D.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){D.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){D.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),s(b[0].values[0],0)&&(T.append("polyline"),S.select("polyline").attr("fill","none").attr("stroke",function(a,b,c){return y(a,c,b)}).attr("points",function(a,c){var d=s(a,c),e=.8*m.rangeBand()/(2*(v?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return n(a)-n(0)});var f=[[-e,d[0]],[e,d[0]],[0,d[0]],[0,d[1]],[-e,d[1]],[e,d[1]]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=m.rangeBand()/(2*(v?1:b.length)),e=r(a,c)<0?n(r(a,c))-n(0):0;return"translate("+d+", "+e+")"})),S.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}),A&&(c||(c=b.map(function(){return!0})),S.select("rect").style("fill",function(a,b,d){return d3.rgb(A(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(A(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}));var U=S.watchTransition(E,"multibar",Math.min(250,B)).delay(function(a,c){return c*B/b[0].values.length});v?U.attr("transform",function(a,c,d){var e=0;e=b[d].nonStackable?r(a,c)<0?n(0):n(0)-n(r(a,c))<-1?n(0)-1:n(r(a,c))||0:n(a.y1);var f=0;b[d].nonStackable&&(f=a.series*m.rangeBand()/b.length,b.length!==I&&(f=b[d].nonStackableSeries*m.rangeBand()/(2*I)));var g=f+m(q(a,c));return"translate("+g+","+e+")"}).select("rect").attr("height",function(a,c,d){return b[d].nonStackable?Math.max(Math.abs(n(r(a,c))-n(0)),1)||0:Math.max(Math.abs(n(a.y+a.y0)-n(a.y0)),1)}).attr("width",function(a,c,d){if(b[d].nonStackable){var e=m.rangeBand()/I;return b.length!==I&&(e=m.rangeBand()/(2*I)),e}return m.rangeBand()}):U.attr("transform",function(a,c){var d=a.series*m.rangeBand()/b.length+m(q(a,c)),e=r(a,c)<0?n(0):n(0)-n(r(a,c))<1?n(0)-1:n(r(a,c))||0;return"translate("+d+","+e+")"}).select("rect").attr("width",m.rangeBand()/b.length).attr("height",function(a,b){return Math.max(Math.abs(n(r(a,b))-n(0)),1)||0}),h=m.copy(),i=n.copy(),b[0]&&b[0].values&&(F=b[0].values.length)}),E.renderEnd("multibar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=d3.scale.ordinal(),n=d3.scale.linear(),o=Math.floor(1e4*Math.random()),p=null,q=function(a){return a.x},r=function(a){return a.y},s=function(a){return a.yErr},t=[0],u=!0,v=!1,w="zero",x=a.utils.defaultColor(),y=a.utils.defaultColor(),z=!1,A=null,B=500,C=.1,D=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),E=a.utils.renderWatch(D,B),F=0;return b.dispatch=D,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},yErr:{get:function(){return s},set:function(a){s=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return t},set:function(a){t=a}},stacked:{get:function(){return v},set:function(a){v=a}},stackOffset:{get:function(){return w},set:function(a){w=a}},clipEdge:{get:function(){return u},set:function(a){u=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return o},set:function(a){o=a}},hideable:{get:function(){return z -},set:function(a){z=a}},groupSpacing:{get:function(){return C},set:function(a){C=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return B},set:function(a){B=a,E.reset(B)}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}},barColor:{get:function(){return A},set:function(b){A=b?a.utils.getColor(b):null}},errorBarColor:{get:function(){return y},set:function(b){y=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarChart=function(){"use strict";function b(j){return D.reset(),D.models(e),r&&D.models(f),s&&D.models(g),j.each(function(j){var z=d3.select(this);a.utils.initSVG(z);var D=a.utils.availableWidth(l,z,k),H=a.utils.availableHeight(m,z,k);if(b.update=function(){0===C?z.call(b):z.transition().duration(C).call(b)},b.container=this,x.setter(G(j),b.update).getter(F(j)).update(),x.disabled=j.map(function(a){return!!a.disabled}),!y){var I;y={};for(I in x)y[I]=x[I]instanceof Array?x[I].slice(0):x[I]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,z),b;z.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var J=z.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([j]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),L=J.select("g");if(K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-legendWrap"),K.append("g").attr("class","nv-controlsWrap"),q&&(h.width(D-B()),L.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),H=a.utils.availableHeight(m,z,k)),L.select(".nv-legendWrap").attr("transform","translate("+B()+","+-k.top+")")),o){var M=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(B()).color(["#444","#444","#444"]),L.select(".nv-controlsWrap").datum(M).attr("transform","translate(0,"+-k.top+")").call(i)}J.attr("transform","translate("+k.left+","+k.top+")"),t&&L.select(".nv-y.nv-axis").attr("transform","translate("+D+",0)"),e.disabled(j.map(function(a){return a.disabled})).width(D).height(H).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var N=L.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(N.call(e),r){f.scale(c)._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-H,0),L.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),L.select(".nv-x.nv-axis").call(f);var O=L.select(".nv-x.nv-axis > g").selectAll("g");if(O.selectAll("line, text").style("opacity",1),v){var P=function(a,b){return"translate("+a+","+b+")"},Q=5,R=17;O.selectAll("text").attr("transform",function(a,b,c){return P(0,c%2==0?Q:R)});var S=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;L.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(a,b){return P(0,0===b||S%2!==0?R:Q)})}u&&O.filter(function(a,b){return b%Math.ceil(j[0].values.length/(D/100))!==0}).selectAll("text, line").style("opacity",0),w&&O.selectAll(".tick text").attr("transform","rotate("+w+" 0,0)").style("text-anchor",w>0?"start":"end"),L.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}s&&(g.scale(d)._ticks(a.utils.calcTicksY(H/36,j)).tickSize(-D,0),L.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)x[c]=a[c];A.stateChange(x),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(M=M.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":case p.grouped:e.stacked(!1);break;case"Stacked":case p.stacked:e.stacked(!0)}x.stacked=e.stacked(),A.stateChange(x),b.update()}}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),x.stacked=a.stacked,E=a.stacked),b.update()})}),D.renderEnd("multibarchart immediate"),b}var c,d,e=a.models.multiBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=0,x=a.utils.state(),y=null,z=null,A=d3.dispatch("stateChange","changeState","renderEnd"),B=function(){return o?180:0},C=250;x.stacked=!1,e.stacked(!1),f.orient("bottom").tickPadding(7).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(t?"right":"left").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var D=a.utils.renderWatch(A),E=!1,F=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:E}}},G=function(a){return function(b){void 0!==b.stacked&&(E=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=A,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=x,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},reduceXTicks:{get:function(){return u},set:function(a){u=a}},rotateLabels:{get:function(){return w},set:function(a){w=a}},staggerLabels:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return C},set:function(a){C=a,e.duration(C),f.duration(C),g.duration(C),D.reset(C)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiBarHorizontal=function(){"use strict";function b(m){return F.reset(),m.each(function(b){var m=k-j.left-j.right,D=l-j.top-j.bottom;n=d3.select(this),a.utils.initSVG(n),x&&(b=d3.layout.stack().offset("zero").values(function(a){return a.values}).y(r)(b)),b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),x&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a){var b=a.values[c];b.size=Math.abs(b.y),b.y<0?(b.y1=e-b.size,e-=b.size):(b.y1=d,d+=b.size)})});var G=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:q(a,b),y:r(a,b),y0:a.y0,y1:a.y1,yErr:s(a,b)}})});o.domain(d||d3.merge(G).map(function(a){return a.x})).rangeBands(f||[0,D],B),p.domain(e||d3.extent(d3.merge(d3.merge(G).map(function(a){var b=a.y;x&&(b=a.y>0?a.y1+a.y:a.y1);var c=a.yErr;return c?c.length?[b+c[0],b+c[1]]:(c=Math.abs(c),[b-c,b+c]):[b]})).concat(t))),p.range(y&&!x?g||[p.domain()[0]<0?A:0,m-(p.domain()[1]>0?A:0)]:g||[0,m]),h=h||o,i=i||d3.scale.linear().domain(p.domain()).range([p(0),p(0)]);{var H=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([b]),I=H.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),J=(I.append("defs"),I.append("g"));H.select("g")}J.append("g").attr("class","nv-groups"),H.attr("transform","translate("+j.left+","+j.top+")");var K=H.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});K.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),K.exit().watchTransition(F,"multibarhorizontal: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),K.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return u(a,b)}).style("stroke",function(a,b){return u(a,b)}),K.watchTransition(F,"multibarhorizontal: groups").style("stroke-opacity",1).style("fill-opacity",.75);var L=K.selectAll("g.nv-bar").data(function(a){return a.values});L.exit().remove();var M=L.enter().append("g").attr("transform",function(a,c,d){return"translate("+i(x?a.y0:0)+","+(x?0:d*o.rangeBand()/b.length+o(q(a,c)))+")"});M.append("rect").attr("width",0).attr("height",o.rangeBand()/(x?1:b.length)),L.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),E.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),E.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){E.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){E.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){E.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){E.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),s(b[0].values[0],0)&&(M.append("polyline"),L.select("polyline").attr("fill","none").attr("stroke",function(a,b,c){return w(a,c,b)}).attr("points",function(a,c){var d=s(a,c),e=.8*o.rangeBand()/(2*(x?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return p(a)-p(0)});var f=[[d[0],-e],[d[0],e],[d[0],0],[d[1],0],[d[1],-e],[d[1],e]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=o.rangeBand()/(2*(x?1:b.length));return"translate("+(r(a,c)<0?0:p(r(a,c))-p(0))+", "+d+")"})),M.append("text"),y&&!x?(L.select("text").attr("text-anchor",function(a,b){return r(a,b)<0?"end":"start"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){var c=C(r(a,b)),d=s(a,b);return void 0===d?c:d.length?c+"+"+C(Math.abs(d[1]))+"-"+C(Math.abs(d[0])):c+"±"+C(Math.abs(d))}),L.watchTransition(F,"multibarhorizontal: bars").select("text").attr("x",function(a,b){return r(a,b)<0?-4:p(r(a,b))-p(0)+4})):L.selectAll("text").text(""),z&&!x?(M.append("text").classed("nv-bar-label",!0),L.select("text.nv-bar-label").attr("text-anchor",function(a,b){return r(a,b)<0?"start":"end"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){return q(a,b)}),L.watchTransition(F,"multibarhorizontal: bars").select("text.nv-bar-label").attr("x",function(a,b){return r(a,b)<0?p(0)-p(r(a,b))+4:-4})):L.selectAll("text.nv-bar-label").text(""),L.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}),v&&(c||(c=b.map(function(){return!0})),L.style("fill",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()})),x?L.watchTransition(F,"multibarhorizontal: bars").attr("transform",function(a,b){return"translate("+p(a.y1)+","+o(q(a,b))+")"}).select("rect").attr("width",function(a,b){return Math.abs(p(r(a,b)+a.y0)-p(a.y0))}).attr("height",o.rangeBand()):L.watchTransition(F,"multibarhorizontal: bars").attr("transform",function(a,c){return"translate("+p(r(a,c)<0?r(a,c):0)+","+(a.series*o.rangeBand()/b.length+o(q(a,c)))+")"}).select("rect").attr("height",o.rangeBand()/b.length).attr("width",function(a,b){return Math.max(Math.abs(p(r(a,b))-p(0)),1)}),h=o.copy(),i=p.copy()}),F.renderEnd("multibarHorizontal immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=null,o=d3.scale.ordinal(),p=d3.scale.linear(),q=function(a){return a.x},r=function(a){return a.y},s=function(a){return a.yErr},t=[0],u=a.utils.defaultColor(),v=null,w=a.utils.defaultColor(),x=!1,y=!1,z=!1,A=60,B=.1,C=d3.format(",.2f"),D=250,E=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),F=a.utils.renderWatch(E,D);return b.dispatch=E,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},yErr:{get:function(){return s},set:function(a){s=a}},xScale:{get:function(){return o},set:function(a){o=a}},yScale:{get:function(){return p},set:function(a){p=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return t},set:function(a){t=a}},stacked:{get:function(){return x},set:function(a){x=a}},showValues:{get:function(){return y},set:function(a){y=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return m},set:function(a){m=a}},valueFormat:{get:function(){return C},set:function(a){C=a}},valuePadding:{get:function(){return A},set:function(a){A=a}},groupSpacing:{get:function(){return B},set:function(a){B=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return D},set:function(a){D=a,F.reset(D)}},color:{get:function(){return u},set:function(b){u=a.utils.getColor(b)}},barColor:{get:function(){return v},set:function(b){v=b?a.utils.getColor(b):null}},errorBarColor:{get:function(){return w},set:function(b){w=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarHorizontalChart=function(){"use strict";function b(j){return C.reset(),C.models(e),r&&C.models(f),s&&C.models(g),j.each(function(j){var w=d3.select(this);a.utils.initSVG(w);var C=a.utils.availableWidth(l,w,k),D=a.utils.availableHeight(m,w,k);if(b.update=function(){w.transition().duration(z).call(b)},b.container=this,t=e.stacked(),u.setter(B(j),b.update).getter(A(j)).update(),u.disabled=j.map(function(a){return!!a.disabled}),!v){var E;v={};for(E in u)v[E]=u[E]instanceof Array?u[E].slice(0):u[E]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,w),b;w.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var F=w.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([j]),G=F.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),H=F.select("g");if(G.append("g").attr("class","nv-x nv-axis"),G.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),G.append("g").attr("class","nv-barsWrap"),G.append("g").attr("class","nv-legendWrap"),G.append("g").attr("class","nv-controlsWrap"),q&&(h.width(C-y()),H.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),D=a.utils.availableHeight(m,w,k)),H.select(".nv-legendWrap").attr("transform","translate("+y()+","+-k.top+")")),o){var I=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(y()).color(["#444","#444","#444"]),H.select(".nv-controlsWrap").datum(I).attr("transform","translate(0,"+-k.top+")").call(i)}F.attr("transform","translate("+k.left+","+k.top+")"),e.disabled(j.map(function(a){return a.disabled})).width(C).height(D).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var J=H.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(J.transition().call(e),r){f.scale(c)._ticks(a.utils.calcTicksY(D/24,j)).tickSize(-C,0),H.select(".nv-x.nv-axis").call(f);var K=H.select(".nv-x.nv-axis").selectAll("g");K.selectAll("line, text")}s&&(g.scale(d)._ticks(a.utils.calcTicksX(C/100,j)).tickSize(-D,0),H.select(".nv-y.nv-axis").attr("transform","translate(0,"+D+")"),H.select(".nv-y.nv-axis").call(g)),H.select(".nv-zeroLine line").attr("x1",d(0)).attr("x2",d(0)).attr("y1",0).attr("y2",-D),h.dispatch.on("stateChange",function(a){for(var c in a)u[c]=a[c];x.stateChange(u),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(I=I.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}u.stacked=e.stacked(),x.stateChange(u),t=e.stacked(),b.update()}}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),u.stacked=a.stacked,t=a.stacked),b.update()})}),C.renderEnd("multibar horizontal chart immediate"),b}var c,d,e=a.models.multiBarHorizontal(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend().height(30),i=a.models.legend().height(30),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=a.utils.state(),v=null,w=null,x=d3.dispatch("stateChange","changeState","renderEnd"),y=function(){return o?180:0},z=250;u.stacked=!1,e.stacked(t),f.orient("left").tickPadding(5).showMaxMin(!1).tickFormat(function(a){return a}),g.orient("bottom").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var A=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:t}}},B=function(a){return function(b){void 0!==b.stacked&&(t=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},C=a.utils.renderWatch(x,z);return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=x,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=u,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z),e.duration(z),f.duration(z),g.duration(z)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiChart=function(){"use strict";function b(j){return j.each(function(j){function k(a){var b=2===j[a.seriesIndex].yAxis?B:A;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color},D.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function l(a){var b=2===j[a.seriesIndex].yAxis?B:A;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color},D.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function n(a){var b=2===j[a.seriesIndex].yAxis?B:A;a.point.x=x.x()(a.point),a.point.y=x.y()(a.point),D.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function E(a){var b=2===j[a.data.series].yAxis?B:A;a.value=v.x()(a.data),a.series={value:v.y()(a.data),color:a.color},D.duration(0).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}var F=d3.select(this);a.utils.initSVG(F),b.update=function(){F.transition().call(b)},b.container=this;var G=a.utils.availableWidth(g,F,e),H=a.utils.availableHeight(h,F,e),I=j.filter(function(a){return"line"==a.type&&1==a.yAxis}),J=j.filter(function(a){return"line"==a.type&&2==a.yAxis}),K=j.filter(function(a){return"scatter"==a.type&&1==a.yAxis}),L=j.filter(function(a){return"scatter"==a.type&&2==a.yAxis}),M=j.filter(function(a){return"bar"==a.type&&1==a.yAxis}),N=j.filter(function(a){return"bar"==a.type&&2==a.yAxis}),O=j.filter(function(a){return"area"==a.type&&1==a.yAxis}),P=j.filter(function(a){return"area"==a.type&&2==a.yAxis});if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,F),b;F.selectAll(".nv-noData").remove();var Q=j.filter(function(a){return!a.disabled&&1==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})}),R=j.filter(function(a){return!a.disabled&&2==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})});o.domain(d3.extent(d3.merge(Q.concat(R)),function(a){return a.x})).range([0,G]);var S=F.selectAll("g.wrap.multiChart").data([j]),T=S.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");T.append("g").attr("class","nv-x nv-axis"),T.append("g").attr("class","nv-y1 nv-axis"),T.append("g").attr("class","nv-y2 nv-axis"),T.append("g").attr("class","lines1Wrap"),T.append("g").attr("class","lines2Wrap"),T.append("g").attr("class","scatters1Wrap"),T.append("g").attr("class","scatters2Wrap"),T.append("g").attr("class","bars1Wrap"),T.append("g").attr("class","bars2Wrap"),T.append("g").attr("class","stack1Wrap"),T.append("g").attr("class","stack2Wrap"),T.append("g").attr("class","legendWrap");var U=S.select("g"),V=j.map(function(a,b){return j[b].color||f(a,b)});if(i){var W=C.align()?G/2:G,X=C.align()?W:0;C.width(W),C.color(V),U.select(".legendWrap").datum(j.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(1==a.yAxis?"":" (right axis)"),a})).call(C),e.top!=C.height()&&(e.top=C.height(),H=a.utils.availableHeight(h,F,e)),U.select(".legendWrap").attr("transform","translate("+X+","+-e.top+")")}r.width(G).height(H).interpolate(m).color(V.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"line"==j[b].type})),s.width(G).height(H).interpolate(m).color(V.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"line"==j[b].type})),t.width(G).height(H).color(V.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"scatter"==j[b].type})),u.width(G).height(H).color(V.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"scatter"==j[b].type})),v.width(G).height(H).color(V.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"bar"==j[b].type})),w.width(G).height(H).color(V.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"bar"==j[b].type})),x.width(G).height(H).color(V.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"area"==j[b].type})),y.width(G).height(H).color(V.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"area"==j[b].type})),U.attr("transform","translate("+e.left+","+e.top+")");var Y=U.select(".lines1Wrap").datum(I.filter(function(a){return!a.disabled})),Z=U.select(".scatters1Wrap").datum(K.filter(function(a){return!a.disabled})),$=U.select(".bars1Wrap").datum(M.filter(function(a){return!a.disabled})),_=U.select(".stack1Wrap").datum(O.filter(function(a){return!a.disabled})),ab=U.select(".lines2Wrap").datum(J.filter(function(a){return!a.disabled})),bb=U.select(".scatters2Wrap").datum(L.filter(function(a){return!a.disabled})),cb=U.select(".bars2Wrap").datum(N.filter(function(a){return!a.disabled})),db=U.select(".stack2Wrap").datum(P.filter(function(a){return!a.disabled})),eb=O.length?O.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[],fb=P.length?P.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[];p.domain(c||d3.extent(d3.merge(Q).concat(eb),function(a){return a.y})).range([0,H]),q.domain(d||d3.extent(d3.merge(R).concat(fb),function(a){return a.y})).range([0,H]),r.yDomain(p.domain()),t.yDomain(p.domain()),v.yDomain(p.domain()),x.yDomain(p.domain()),s.yDomain(q.domain()),u.yDomain(q.domain()),w.yDomain(q.domain()),y.yDomain(q.domain()),O.length&&d3.transition(_).call(x),P.length&&d3.transition(db).call(y),M.length&&d3.transition($).call(v),N.length&&d3.transition(cb).call(w),I.length&&d3.transition(Y).call(r),J.length&&d3.transition(ab).call(s),K.length&&d3.transition(Z).call(t),L.length&&d3.transition(bb).call(u),z._ticks(a.utils.calcTicksX(G/100,j)).tickSize(-H,0),U.select(".nv-x.nv-axis").attr("transform","translate(0,"+H+")"),d3.transition(U.select(".nv-x.nv-axis")).call(z),A._ticks(a.utils.calcTicksY(H/36,j)).tickSize(-G,0),d3.transition(U.select(".nv-y1.nv-axis")).call(A),B._ticks(a.utils.calcTicksY(H/36,j)).tickSize(-G,0),d3.transition(U.select(".nv-y2.nv-axis")).call(B),U.select(".nv-y1.nv-axis").classed("nv-disabled",Q.length?!1:!0).attr("transform","translate("+o.range()[0]+",0)"),U.select(".nv-y2.nv-axis").classed("nv-disabled",R.length?!1:!0).attr("transform","translate("+o.range()[1]+",0)"),C.dispatch.on("stateChange",function(){b.update()}),r.dispatch.on("elementMouseover.tooltip",k),s.dispatch.on("elementMouseover.tooltip",k),r.dispatch.on("elementMouseout.tooltip",function(){D.hidden(!0)}),s.dispatch.on("elementMouseout.tooltip",function(){D.hidden(!0)}),t.dispatch.on("elementMouseover.tooltip",l),u.dispatch.on("elementMouseover.tooltip",l),t.dispatch.on("elementMouseout.tooltip",function(){D.hidden(!0)}),u.dispatch.on("elementMouseout.tooltip",function(){D.hidden(!0)}),x.dispatch.on("elementMouseover.tooltip",n),y.dispatch.on("elementMouseover.tooltip",n),x.dispatch.on("elementMouseout.tooltip",function(){D.hidden(!0)}),y.dispatch.on("elementMouseout.tooltip",function(){D.hidden(!0)}),v.dispatch.on("elementMouseover.tooltip",E),w.dispatch.on("elementMouseover.tooltip",E),v.dispatch.on("elementMouseout.tooltip",function(){D.hidden(!0)}),w.dispatch.on("elementMouseout.tooltip",function(){D.hidden(!0)}),v.dispatch.on("elementMousemove.tooltip",function(){D.position({top:d3.event.pageY,left:d3.event.pageX})()}),w.dispatch.on("elementMousemove.tooltip",function(){D.position({top:d3.event.pageY,left:d3.event.pageX})()})}),b}var c,d,e={top:30,right:20,bottom:50,left:60},f=a.utils.defaultColor(),g=null,h=null,i=!0,j=null,k=function(a){return a.x},l=function(a){return a.y},m="monotone",n=!0,o=d3.scale.linear(),p=d3.scale.linear(),q=d3.scale.linear(),r=a.models.line().yScale(p),s=a.models.line().yScale(q),t=a.models.scatter().yScale(p),u=a.models.scatter().yScale(q),v=a.models.multiBar().stacked(!1).yScale(p),w=a.models.multiBar().stacked(!1).yScale(q),x=a.models.stackedArea().yScale(p),y=a.models.stackedArea().yScale(q),z=a.models.axis().scale(o).orient("bottom").tickPadding(5),A=a.models.axis().scale(p).orient("left"),B=a.models.axis().scale(q).orient("right"),C=a.models.legend().height(30),D=a.models.tooltip(),E=d3.dispatch();return b.dispatch=E,b.lines1=r,b.lines2=s,b.scatters1=t,b.scatters2=u,b.bars1=v,b.bars2=w,b.stack1=x,b.stack2=y,b.xAxis=z,b.yAxis1=A,b.yAxis2=B,b.tooltip=D,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},showLegend:{get:function(){return i},set:function(a){i=a}},yDomain1:{get:function(){return c},set:function(a){c=a}},yDomain2:{get:function(){return d},set:function(a){d=a}},noData:{get:function(){return j},set:function(a){j=a}},interpolate:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return D.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),D.enabled(!!b)}},tooltipContent:{get:function(){return D.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),D.contentGenerator(b)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return f},set:function(b){f=a.utils.getColor(b)}},x:{get:function(){return k},set:function(a){k=a,r.x(a),s.x(a),t.x(a),u.x(a),v.x(a),w.x(a),x.x(a),y.x(a)}},y:{get:function(){return l},set:function(a){l=a,r.y(a),s.y(a),t.y(a),u.y(a),x.y(a),y.y(a),v.y(a),w.y(a)}},useVoronoi:{get:function(){return n},set:function(a){n=a,r.useVoronoi(a),s.useVoronoi(a),x.useVoronoi(a),y.useVoronoi(a)}}}),a.utils.initOptions(b),b},a.models.ohlcBar=function(){"use strict";function b(y){return y.each(function(b){k=d3.select(this);var y=a.utils.availableWidth(h,k,g),A=a.utils.availableHeight(i,k,g);a.utils.initSVG(k);var B=y/b[0].values.length*.9;l.domain(c||d3.extent(b[0].values.map(n).concat(t))),l.range(v?e||[.5*y/b[0].values.length,y*(b[0].values.length-.5)/b[0].values.length]:e||[5+B/2,y-B/2-5]),m.domain(d||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(f||[A,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var C=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([b[0].values]),D=C.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),E=D.append("defs"),F=D.append("g"),G=C.select("g");F.append("g").attr("class","nv-ticks"),C.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:j})}),E.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),C.select("#nv-chart-clip-path-"+j+" rect").attr("width",y).attr("height",A),G.attr("clip-path",w?"url(#nv-chart-clip-path-"+j+")":"");var H=C.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});H.exit().remove(),H.enter().append("path").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b -}).attr("d",function(a,b){return"m0,0l0,"+(m(p(a,b))-m(r(a,b)))+"l"+-B/2+",0l"+B/2+",0l0,"+(m(s(a,b))-m(p(a,b)))+"l0,"+(m(q(a,b))-m(s(a,b)))+"l"+B/2+",0l"+-B/2+",0z"}).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("fill",function(){return x[0]}).attr("stroke",function(){return x[0]}).attr("x",0).attr("y",function(a,b){return m(Math.max(0,o(a,b)))}).attr("height",function(a,b){return Math.abs(m(o(a,b))-m(0))}),H.attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}),d3.transition(H).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("d",function(a,c){var d=y/b[0].values.length*.9;return"m0,0l0,"+(m(p(a,c))-m(r(a,c)))+"l"+-d/2+",0l"+d/2+",0l0,"+(m(s(a,c))-m(p(a,c)))+"l0,"+(m(q(a,c))-m(s(a,c)))+"l"+d/2+",0l"+-d/2+",0z"})}),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,c){b.clearHighlights(),k.select(".nv-ohlcBar .nv-tick-0-"+a).classed("hover",c)},b.clearHighlights=function(){k.select(".nv-ohlcBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!=a.top?a.top:g.top,g.right=void 0!=a.right?a.right:g.right,g.bottom=void 0!=a.bottom?a.bottom:g.bottom,g.left=void 0!=a.left?a.left:g.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinates=function(){"use strict";function b(p){return p.each(function(b){function p(a){return F(h.map(function(b){if(isNaN(a[b])||isNaN(parseFloat(a[b]))){var c=g[b].domain(),d=g[b].range(),e=c[0]-(c[1]-c[0])/9;if(J.indexOf(b)<0){var h=d3.scale.linear().domain([e,c[1]]).range([x-12,d[1]]);g[b].brush.y(h),J.push(b)}return[f(b),g[b](e)]}return J.length>0?(D.style("display","inline"),E.style("display","inline")):(D.style("display","none"),E.style("display","none")),[f(b),g[b](a[b])]}))}function q(){var a=h.filter(function(a){return!g[a].brush.empty()}),b=a.map(function(a){return g[a].brush.extent()});k=[],a.forEach(function(a,c){k[c]={dimension:a,extent:b[c]}}),l=[],M.style("display",function(c){var d=a.every(function(a,d){return isNaN(c[a])&&b[d][0]==g[a].brush.y().domain()[0]?!0:b[d][0]<=c[a]&&c[a]<=b[d][1]});return d&&l.push(c),d?null:"none"}),o.brush({filters:k,active:l})}function r(a){m[a]=this.parentNode.__origin__=f(a),L.attr("visibility","hidden")}function s(a){m[a]=Math.min(w,Math.max(0,this.parentNode.__origin__+=d3.event.x)),M.attr("d",p),h.sort(function(a,b){return u(a)-u(b)}),f.domain(h),N.attr("transform",function(a){return"translate("+u(a)+")"})}function t(a){delete this.parentNode.__origin__,delete m[a],d3.select(this.parentNode).attr("transform","translate("+f(a)+")"),M.attr("d",p),L.attr("d",p).attr("visibility",null)}function u(a){var b=m[a];return null==b?f(a):b}var v=d3.select(this),w=a.utils.availableWidth(d,v,c),x=a.utils.availableHeight(e,v,c);a.utils.initSVG(v),l=b,f.rangePoints([0,w],1).domain(h);var y={};h.forEach(function(a){var c=d3.extent(b,function(b){return+b[a]});return y[a]=!1,void 0===c[0]&&(y[a]=!0,c[0]=0,c[1]=0),c[0]===c[1]&&(c[0]=c[0]-1,c[1]=c[1]+1),g[a]=d3.scale.linear().domain(c).range([.9*(x-12),0]),g[a].brush=d3.svg.brush().y(g[a]).on("brush",q),"name"!=a});var z=v.selectAll("g.nv-wrap.nv-parallelCoordinates").data([b]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-parallelCoordinates"),B=A.append("g"),C=z.select("g");B.append("g").attr("class","nv-parallelCoordinates background"),B.append("g").attr("class","nv-parallelCoordinates foreground"),B.append("g").attr("class","nv-parallelCoordinates missingValuesline"),z.attr("transform","translate("+c.left+","+c.top+")");var D,E,F=d3.svg.line().interpolate("cardinal").tension(n),G=d3.svg.axis().orient("left"),H=d3.behavior.drag().on("dragstart",r).on("drag",s).on("dragend",t),I=f.range()[1]-f.range()[0],J=[],K=[0+I/2,x-12,w-I/2,x-12];D=z.select(".missingValuesline").selectAll("line").data([K]),D.enter().append("line"),D.exit().remove(),D.attr("x1",function(a){return a[0]}).attr("y1",function(a){return a[1]}).attr("x2",function(a){return a[2]}).attr("y2",function(a){return a[3]}),E=z.select(".missingValuesline").selectAll("text").data(["undefined values"]),E.append("text").data(["undefined values"]),E.enter().append("text"),E.exit().remove(),E.attr("y",x).attr("x",w-92-I/2).text(function(a){return a});var L=z.select(".background").selectAll("path").data(b);L.enter().append("path"),L.exit().remove(),L.attr("d",p);var M=z.select(".foreground").selectAll("path").data(b);M.enter().append("path"),M.exit().remove(),M.attr("d",p).attr("stroke",j),M.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),o.elementMouseover({label:a.name,data:a.data,index:b,pos:[d3.mouse(this.parentNode)[0],d3.mouse(this.parentNode)[1]]})}),M.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),o.elementMouseout({label:a.name,data:a.data,index:b})});var N=C.selectAll(".dimension").data(h),O=N.enter().append("g").attr("class","nv-parallelCoordinates dimension");O.append("g").attr("class","nv-parallelCoordinates nv-axis"),O.append("g").attr("class","nv-parallelCoordinates-brush"),O.append("text").attr("class","nv-parallelCoordinates nv-label"),N.attr("transform",function(a){return"translate("+f(a)+",0)"}),N.exit().remove(),N.select(".nv-label").style("cursor","move").attr("dy","-1em").attr("text-anchor","middle").text(String).on("mouseover",function(a){o.elementMouseover({dim:a,pos:[d3.mouse(this.parentNode.parentNode)[0],d3.mouse(this.parentNode.parentNode)[1]]})}).on("mouseout",function(a){o.elementMouseout({dim:a})}).call(H),N.select(".nv-axis").each(function(a,b){d3.select(this).call(G.scale(g[a]).tickFormat(d3.format(i[b])))}),N.select(".nv-parallelCoordinates-brush").each(function(a){d3.select(this).call(g[a].brush)}).selectAll("rect").attr("x",-8).attr("width",16)}),b}var c={top:30,right:0,bottom:10,left:0},d=null,e=null,f=d3.scale.ordinal(),g={},h=[],i=[],j=a.utils.defaultColor(),k=[],l=[],m=[],n=1,o=d3.dispatch("brush","elementMouseover","elementMouseout");return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},dimensionNames:{get:function(){return h},set:function(a){h=a}},dimensionFormats:{get:function(){return i},set:function(a){i=a}},lineTension:{get:function(){return n},set:function(a){n=a}},dimensions:{get:function(){return h},set:function(b){a.deprecated("dimensions","use dimensionNames instead"),h=b}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.pie=function(){"use strict";function b(E){return D.reset(),E.each(function(b){function E(a,b){a.endAngle=isNaN(a.endAngle)?0:a.endAngle,a.startAngle=isNaN(a.startAngle)?0:a.startAngle,p||(a.innerRadius=0);var c=d3.interpolate(this._current,a);return this._current=c(0),function(a){return B[b](c(a))}}var F=d-c.left-c.right,G=e-c.top-c.bottom,H=Math.min(F,G)/2,I=[],J=[];if(i=d3.select(this),0===z.length)for(var K=H-H/5,L=y*H,M=0;Mc)return"";if("function"==typeof n)d=n(a,b,{key:f(a.data),value:g(a.data),percent:k(c)});else switch(n){case"key":d=f(a.data);break;case"value":d=k(g(a.data));break;case"percent":d=d3.format("%")(c)}return d})}}),D.renderEnd("pie immediate"),b}var c={top:0,right:0,bottom:0,left:0},d=500,e=500,f=function(a){return a.x},g=function(a){return a.y},h=Math.floor(1e4*Math.random()),i=null,j=a.utils.defaultColor(),k=d3.format(",.2f"),l=!0,m=!1,n="key",o=.02,p=!1,q=!1,r=!0,s=0,t=!1,u=!1,v=!1,w=!1,x=0,y=.5,z=[],A=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),B=[],C=[],D=a.utils.renderWatch(A);return b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{arcsRadius:{get:function(){return z},set:function(a){z=a}},width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},showLabels:{get:function(){return l},set:function(a){l=a}},title:{get:function(){return q},set:function(a){q=a}},titleOffset:{get:function(){return s},set:function(a){s=a}},labelThreshold:{get:function(){return o},set:function(a){o=a}},valueFormat:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return h},set:function(a){h=a}},endAngle:{get:function(){return w},set:function(a){w=a}},startAngle:{get:function(){return u},set:function(a){u=a}},padAngle:{get:function(){return v},set:function(a){v=a}},cornerRadius:{get:function(){return x},set:function(a){x=a}},donutRatio:{get:function(){return y},set:function(a){y=a}},labelsOutside:{get:function(){return m},set:function(a){m=a}},labelSunbeamLayout:{get:function(){return t},set:function(a){t=a}},donut:{get:function(){return p},set:function(a){p=a}},growOnHover:{get:function(){return r},set:function(a){r=a}},pieLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("pieLabelsOutside","use labelsOutside instead")}},donutLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("donutLabelsOutside","use labelsOutside instead")}},labelFormat:{get:function(){return k},set:function(b){k=b,a.deprecated("labelFormat","use valueFormat instead")}},margin:{get:function(){return c},set:function(a){c.top="undefined"!=typeof a.top?a.top:c.top,c.right="undefined"!=typeof a.right?a.right:c.right,c.bottom="undefined"!=typeof a.bottom?a.bottom:c.bottom,c.left="undefined"!=typeof a.left?a.left:c.left}},y:{get:function(){return g},set:function(a){g=d3.functor(a)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},labelType:{get:function(){return n},set:function(a){n=a||"key"}}}),a.utils.initOptions(b),b},a.models.pieChart=function(){"use strict";function b(e){return q.reset(),q.models(c),e.each(function(e){var k=d3.select(this);a.utils.initSVG(k);var n=a.utils.availableWidth(g,k,f),o=a.utils.availableHeight(h,k,f);if(b.update=function(){k.transition().call(b)},b.container=this,l.setter(s(e),b.update).getter(r(e)).update(),l.disabled=e.map(function(a){return!!a.disabled}),!m){var q;m={};for(q in l)m[q]=l[q]instanceof Array?l[q].slice(0):l[q]}if(!e||!e.length)return a.utils.noData(b,k),b;k.selectAll(".nv-noData").remove();var t=k.selectAll("g.nv-wrap.nv-pieChart").data([e]),u=t.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),v=t.select("g");if(u.append("g").attr("class","nv-pieWrap"),u.append("g").attr("class","nv-legendWrap"),i)if("top"===j)d.width(n).key(c.x()),t.select(".nv-legendWrap").datum(e).call(d),f.top!=d.height()&&(f.top=d.height(),o=a.utils.availableHeight(h,k,f)),t.select(".nv-legendWrap").attr("transform","translate(0,"+-f.top+")");else if("right"===j){var w=a.models.legend().width();w>n/2&&(w=n/2),d.height(o).key(c.x()),d.width(w),n-=d.width(),t.select(".nv-legendWrap").datum(e).call(d).attr("transform","translate("+n+",0)")}t.attr("transform","translate("+f.left+","+f.top+")"),c.width(n).height(o);var x=v.select(".nv-pieWrap").datum([e]);d3.transition(x).call(c),d.dispatch.on("stateChange",function(a){for(var c in a)l[c]=a[c];p.stateChange(l),b.update()}),p.on("changeState",function(a){"undefined"!=typeof a.disabled&&(e.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),q.renderEnd("pieChart immediate"),b}var c=a.models.pie(),d=a.models.legend(),e=a.models.tooltip(),f={top:30,right:20,bottom:20,left:20},g=null,h=null,i=!0,j="top",k=a.utils.defaultColor(),l=a.utils.state(),m=null,n=null,o=250,p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd");e.headerEnabled(!1).duration(0).valueFormatter(function(a,b){return c.valueFormat()(a,b)});var q=a.utils.renderWatch(p),r=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},s=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},e.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){e.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){e.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.legend=d,b.dispatch=p,b.pie=c,b.tooltip=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return i},set:function(a){i=a}},legendPosition:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return e.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),e.enabled(!!b)}},tooltipContent:{get:function(){return e.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),e.contentGenerator(b)}},color:{get:function(){return k},set:function(a){k=a,d.color(k),c.color(k)}},duration:{get:function(){return o},set:function(a){o=a,q.reset(o)}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.scatter=function(){"use strict";function b(N){return P.reset(),N.each(function(b){function N(){if(O=!1,!w)return!1;if(M===!0){var a=d3.merge(b.map(function(a,b){return a.values.map(function(a,c){var d=p(a,c),e=q(a,c);return[m(d)+1e-4*Math.random(),n(e)+1e-4*Math.random(),b,c,a]}).filter(function(a,b){return x(a[4],b)})}));if(0==a.length)return!1;a.length<3&&(a.push([m.range()[0]-20,n.range()[0]-20,null,null]),a.push([m.range()[1]+20,n.range()[1]+20,null,null]),a.push([m.range()[0]-20,n.range()[0]+20,null,null]),a.push([m.range()[1]+20,n.range()[1]-20,null,null]));var c=d3.geom.polygon([[-10,-10],[-10,i+10],[h+10,i+10],[h+10,-10]]),d=d3.geom.voronoi(a).map(function(b,d){return{data:c.clip(b),series:a[d][2],point:a[d][3]}});U.select(".nv-point-paths").selectAll("path").remove();var e=U.select(".nv-point-paths").selectAll("path").data(d),f=e.enter().append("svg:path").attr("d",function(a){return a&&a.data&&0!==a.data.length?"M"+a.data.join(",")+"Z":"M 0 0"}).attr("id",function(a,b){return"nv-path-"+b}).attr("clip-path",function(a,b){return"url(#nv-clip-"+k+"-"+b+")"});C&&f.style("fill",d3.rgb(230,230,230)).style("fill-opacity",.4).style("stroke-opacity",1).style("stroke",d3.rgb(200,200,200)),B&&(U.select(".nv-point-clips").selectAll("clipPath").remove(),U.select(".nv-point-clips").selectAll("clipPath").data(a).enter().append("svg:clipPath").attr("id",function(a,b){return"nv-clip-"+k+"-"+b}).append("svg:circle").attr("cx",function(a){return a[0]}).attr("cy",function(a){return a[1]}).attr("r",D));var o=function(a,c){if(O)return 0;var d=b[a.series];if(void 0!==d){var e=d.values[a.point];e.color=j(d,a.series),e.x=p(e),e.y=q(e);var f=l.node().getBoundingClientRect(),h=window.pageYOffset||document.documentElement.scrollTop,i=window.pageXOffset||document.documentElement.scrollLeft,k={left:m(p(e,a.point))+f.left+i+g.left+10,top:n(q(e,a.point))+f.top+h+g.top+10};c({point:e,series:d,pos:k,seriesIndex:a.series,pointIndex:a.point})}};e.on("click",function(a){o(a,L.elementClick)}).on("dblclick",function(a){o(a,L.elementDblClick)}).on("mouseover",function(a){o(a,L.elementMouseover)}).on("mouseout",function(a){o(a,L.elementMouseout)})}else U.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("dblclick",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementDblClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("mouseover",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseover({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c,color:j(a,c)})}).on("mouseout",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseout({point:e,series:d,seriesIndex:a.series,pointIndex:c,color:j(a,c)})})}l=d3.select(this);var R=a.utils.availableWidth(h,l,g),S=a.utils.availableHeight(i,l,g);a.utils.initSVG(l),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var T=E&&F&&I?[]:d3.merge(b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),size:r(a,b)}})}));m.domain(E||d3.extent(T.map(function(a){return a.x}).concat(t))),m.range(y&&b[0]?G||[(R*z+R)/(2*b[0].values.length),R-R*(1+z)/(2*b[0].values.length)]:G||[0,R]),n.domain(F||d3.extent(T.map(function(a){return a.y}).concat(u))).range(H||[S,0]),o.domain(I||d3.extent(T.map(function(a){return a.size}).concat(v))).range(J||Q),K=m.domain()[0]===m.domain()[1]||n.domain()[0]===n.domain()[1],m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]-.01*n.domain()[0],n.domain()[1]+.01*n.domain()[1]]:[-1,1]),isNaN(m.domain()[0])&&m.domain([-1,1]),isNaN(n.domain()[0])&&n.domain([-1,1]),c=c||m,d=d||n,e=e||o;var U=l.selectAll("g.nv-wrap.nv-scatter").data([b]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+k),W=V.append("defs"),X=V.append("g"),Y=U.select("g");U.classed("nv-single-point",K),X.append("g").attr("class","nv-groups"),X.append("g").attr("class","nv-point-paths"),V.append("g").attr("class","nv-point-clips"),U.attr("transform","translate("+g.left+","+g.top+")"),W.append("clipPath").attr("id","nv-edge-clip-"+k).append("rect"),U.select("#nv-edge-clip-"+k+" rect").attr("width",R).attr("height",S>0?S:0),Y.attr("clip-path",A?"url(#nv-edge-clip-"+k+")":""),O=!0;var Z=U.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});Z.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),Z.exit().remove(),Z.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),Z.watchTransition(P,"scatter: groups").style("fill",function(a,b){return j(a,b)}).style("stroke",function(a,b){return j(a,b)}).style("stroke-opacity",1).style("fill-opacity",.5);var $=Z.selectAll("path.nv-point").data(function(a){return a.values.map(function(a,b){return[a,b]}).filter(function(a,b){return x(a[0],b)})});$.enter().append("path").style("fill",function(a){return a.color}).style("stroke",function(a){return a.color}).attr("transform",function(a){return"translate("+c(p(a[0],a[1]))+","+d(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),$.exit().remove(),Z.exit().selectAll("path.nv-point").watchTransition(P,"scatter exit").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).remove(),$.each(function(a){d3.select(this).classed("nv-point",!0).classed("nv-point-"+a[1],!0).classed("nv-noninteractive",!w).classed("hover",!1)}),$.watchTransition(P,"scatter points").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),clearTimeout(f),f=setTimeout(N,300),c=m.copy(),d=n.copy(),e=o.copy()}),P.renderEnd("scatter immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=a.utils.defaultColor(),k=Math.floor(1e5*Math.random()),l=null,m=d3.scale.linear(),n=d3.scale.linear(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=function(a){return a.size||1},s=function(a){return a.shape||"circle"},t=[],u=[],v=[],w=!0,x=function(a){return!a.notActive},y=!1,z=.1,A=!1,B=!0,C=!1,D=function(){return 25},E=null,F=null,G=null,H=null,I=null,J=null,K=!1,L=d3.dispatch("elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),M=!0,N=250,O=!1,P=a.utils.renderWatch(L,N),Q=[16,256];return b.dispatch=L,b.options=a.utils.optionsFunc.bind(b),b._calls=new function(){this.clearHighlights=function(){return a.dom.write(function(){l.selectAll(".nv-point.hover").classed("hover",!1)}),null},this.highlightPoint=function(b,c,d){a.dom.write(function(){l.select(" .nv-series-"+b+" .nv-point-"+c).classed("hover",d)})}},L.on("elementMouseover.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!0)}),L.on("elementMouseout.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!1)}),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},pointScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return E},set:function(a){E=a}},yDomain:{get:function(){return F},set:function(a){F=a}},pointDomain:{get:function(){return I},set:function(a){I=a}},xRange:{get:function(){return G},set:function(a){G=a}},yRange:{get:function(){return H},set:function(a){H=a}},pointRange:{get:function(){return J},set:function(a){J=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},forcePoint:{get:function(){return v},set:function(a){v=a}},interactive:{get:function(){return w},set:function(a){w=a}},pointActive:{get:function(){return x},set:function(a){x=a}},padDataOuter:{get:function(){return z},set:function(a){z=a}},padData:{get:function(){return y},set:function(a){y=a}},clipEdge:{get:function(){return A},set:function(a){A=a}},clipVoronoi:{get:function(){return B},set:function(a){B=a}},clipRadius:{get:function(){return D},set:function(a){D=a}},showVoronoi:{get:function(){return C},set:function(a){C=a}},id:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return p},set:function(a){p=d3.functor(a)}},y:{get:function(){return q},set:function(a){q=d3.functor(a)}},pointSize:{get:function(){return r},set:function(a){r=d3.functor(a)}},pointShape:{get:function(){return s},set:function(a){s=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},duration:{get:function(){return N},set:function(a){N=a,P.reset(N)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},useVoronoi:{get:function(){return M},set:function(a){M=a,M===!1&&(B=!1)}}}),a.utils.initOptions(b),b},a.models.scatterChart=function(){"use strict";function b(z){return D.reset(),D.models(c),t&&D.models(d),u&&D.models(e),q&&D.models(g),r&&D.models(h),z.each(function(z){m=d3.select(this),a.utils.initSVG(m);var G=a.utils.availableWidth(k,m,j),H=a.utils.availableHeight(l,m,j);if(b.update=function(){0===A?m.call(b):m.transition().duration(A).call(b)},b.container=this,w.setter(F(z),b.update).getter(E(z)).update(),w.disabled=z.map(function(a){return!!a.disabled}),!x){var I;x={};for(I in w)x[I]=w[I]instanceof Array?w[I].slice(0):w[I]}if(!(z&&z.length&&z.filter(function(a){return a.values.length}).length))return a.utils.noData(b,m),D.renderEnd("scatter immediate"),b;m.selectAll(".nv-noData").remove(),o=c.xScale(),p=c.yScale();var J=m.selectAll("g.nv-wrap.nv-scatterChart").data([z]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+c.id()),L=K.append("g"),M=J.select("g");if(L.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis"),L.append("g").attr("class","nv-scatterWrap"),L.append("g").attr("class","nv-regressionLinesWrap"),L.append("g").attr("class","nv-distWrap"),L.append("g").attr("class","nv-legendWrap"),v&&M.select(".nv-y.nv-axis").attr("transform","translate("+G+",0)"),s){var N=G;f.width(N),J.select(".nv-legendWrap").datum(z).call(f),j.top!=f.height()&&(j.top=f.height(),H=a.utils.availableHeight(l,m,j)),J.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")}J.attr("transform","translate("+j.left+","+j.top+")"),c.width(G).height(H).color(z.map(function(a,b){return a.color=a.color||n(a,b),a.color}).filter(function(a,b){return!z[b].disabled})),J.select(".nv-scatterWrap").datum(z.filter(function(a){return!a.disabled})).call(c),J.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+c.id()+")");var O=J.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(a){return a});O.enter().append("g").attr("class","nv-regLines");var P=O.selectAll(".nv-regLine").data(function(a){return[a]});P.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0),P.filter(function(a){return a.intercept&&a.slope}).watchTransition(D,"scatterPlusLineChart: regline").attr("x1",o.range()[0]).attr("x2",o.range()[1]).attr("y1",function(a){return p(o.domain()[0]*a.slope+a.intercept)}).attr("y2",function(a){return p(o.domain()[1]*a.slope+a.intercept)}).style("stroke",function(a,b,c){return n(a,c)}).style("stroke-opacity",function(a){return a.disabled||"undefined"==typeof a.slope||"undefined"==typeof a.intercept?0:1}),t&&(d.scale(o)._ticks(a.utils.calcTicksX(G/100,z)).tickSize(-H,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(d)),u&&(e.scale(p)._ticks(a.utils.calcTicksY(H/36,z)).tickSize(-G,0),M.select(".nv-y.nv-axis").call(e)),q&&(g.getData(c.x()).scale(o).width(G).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),M.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(z.filter(function(a){return!a.disabled})).call(g)),r&&(h.getData(c.y()).scale(p).width(H).color(z.map(function(a,b){return a.color||n(a,b) -}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),M.select(".nv-distributionY").attr("transform","translate("+(v?G:-h.size())+",0)").datum(z.filter(function(a){return!a.disabled})).call(h)),f.dispatch.on("stateChange",function(a){for(var c in a)w[c]=a[c];y.stateChange(w),b.update()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(z.forEach(function(b,c){b.disabled=a.disabled[c]}),w.disabled=a.disabled),b.update()}),c.dispatch.on("elementMouseout.tooltip",function(a){i.hidden(!0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",h.size())}),c.dispatch.on("elementMouseover.tooltip",function(a){m.select(".nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.pos.top-H-j.top),m.select(".nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.pos.left+g.size()-j.left),i.position(a.pos).data(a).hidden(!1)}),B=o.copy(),C=p.copy()}),D.renderEnd("scatter with line immediate"),b}var c=a.models.scatter(),d=a.models.axis(),e=a.models.axis(),f=a.models.legend(),g=a.models.distribution(),h=a.models.distribution(),i=a.models.tooltip(),j={top:30,right:20,bottom:50,left:75},k=null,l=null,m=null,n=a.utils.defaultColor(),o=c.xScale(),p=c.yScale(),q=!1,r=!1,s=!0,t=!0,u=!0,v=!1,w=a.utils.state(),x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=null,A=250;c.xScale(o).yScale(p),d.orient("bottom").tickPadding(10),e.orient(v?"right":"left").tickPadding(10),g.axis("x"),h.axis("y"),i.headerFormatter(function(a,b){return d.tickFormat()(a,b)}).valueFormatter(function(a,b){return e.tickFormat()(a,b)});var B,C,D=a.utils.renderWatch(y,A),E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return b.dispatch=y,b.scatter=c,b.legend=f,b.xAxis=d,b.yAxis=e,b.distX=g,b.distY=h,b.tooltip=i,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},container:{get:function(){return m},set:function(a){m=a}},showDistX:{get:function(){return q},set:function(a){q=a}},showDistY:{get:function(){return r},set:function(a){r=a}},showLegend:{get:function(){return s},set:function(a){s=a}},showXAxis:{get:function(){return t},set:function(a){t=a}},showYAxis:{get:function(){return u},set:function(a){u=a}},defaultState:{get:function(){return x},set:function(a){x=a}},noData:{get:function(){return z},set:function(a){z=a}},duration:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return i.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),i.enabled(!!b)}},tooltipContent:{get:function(){return i.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),i.contentGenerator(b)}},tooltipXContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},tooltipYContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},rightAlignYAxis:{get:function(){return v},set:function(a){v=a,e.orient(a?"right":"left")}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),f.color(n),g.color(n),h.color(n)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.sparkline=function(){"use strict";function b(k){return k.each(function(b){var k=h-g.left-g.right,q=i-g.top-g.bottom;j=d3.select(this),a.utils.initSVG(j),l.domain(c||d3.extent(b,n)).range(e||[0,k]),m.domain(d||d3.extent(b,o)).range(f||[q,0]);{var r=j.selectAll("g.nv-wrap.nv-sparkline").data([b]),s=r.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline");s.append("g"),r.select("g")}r.attr("transform","translate("+g.left+","+g.top+")");var t=r.selectAll("path").data(function(a){return[a]});t.enter().append("path"),t.exit().remove(),t.style("stroke",function(a,b){return a.color||p(a,b)}).attr("d",d3.svg.line().x(function(a,b){return l(n(a,b))}).y(function(a,b){return m(o(a,b))}));var u=r.selectAll("circle.nv-point").data(function(a){function b(b){if(-1!=b){var c=a[b];return c.pointIndex=b,c}return null}var c=a.map(function(a,b){return o(a,b)}),d=b(c.lastIndexOf(m.domain()[1])),e=b(c.indexOf(m.domain()[0])),f=b(c.length-1);return[e,d,f].filter(function(a){return null!=a})});u.enter().append("circle"),u.exit().remove(),u.attr("cx",function(a){return l(n(a,a.pointIndex))}).attr("cy",function(a){return m(o(a,a.pointIndex))}).attr("r",2).attr("class",function(a){return n(a,a.pointIndex)==l.domain()[1]?"nv-point nv-currentValue":o(a,a.pointIndex)==m.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),b}var c,d,e,f,g={top:2,right:0,bottom:2,left:0},h=400,i=32,j=null,k=!0,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=a.utils.getColor(["#000"]);return b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},animate:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return n},set:function(a){n=d3.functor(a)}},y:{get:function(){return o},set:function(a){o=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return p},set:function(b){p=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sparklinePlus=function(){"use strict";function b(p){return p.each(function(p){function q(){if(!j){var a=z.selectAll(".nv-hoverValue").data(i),b=a.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);a.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),a.attr("transform",function(a){return"translate("+c(e.x()(p[a],a))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1),i.length&&(b.append("line").attr("x1",0).attr("y1",-f.top).attr("x2",0).attr("y2",u),b.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-f.top).attr("text-anchor","end").attr("dy",".9em"),z.select(".nv-hoverValue .nv-xValue").text(k(e.x()(p[i[0]],i[0]))),b.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-f.top).attr("text-anchor","start").attr("dy",".9em"),z.select(".nv-hoverValue .nv-yValue").text(l(e.y()(p[i[0]],i[0]))))}}function r(){function a(a,b){for(var c=Math.abs(e.x()(a[0],0)-b),d=0,f=0;fc;++c){for(b=0,d=0;bb;b++)a[b][c][1]/=d;else for(b=0;e>b;b++)a[b][c][1]=0}for(c=0;f>c;++c)g[c]=0;return g}}),u.renderEnd("stackedArea immediate"),b}var c,d,e={top:0,right:0,bottom:0,left:0},f=960,g=500,h=a.utils.defaultColor(),i=Math.floor(1e5*Math.random()),j=null,k=function(a){return a.x},l=function(a){return a.y},m="stack",n="zero",o="default",p="linear",q=!1,r=a.models.scatter(),s=250,t=d3.dispatch("areaClick","areaMouseover","areaMouseout","renderEnd","elementClick","elementMouseover","elementMouseout");r.pointSize(2.2).pointDomain([2.2,2.2]);var u=a.utils.renderWatch(t,s);return b.dispatch=t,b.scatter=r,r.dispatch.on("elementClick",function(){t.elementClick.apply(this,arguments)}),r.dispatch.on("elementMouseover",function(){t.elementMouseover.apply(this,arguments)}),r.dispatch.on("elementMouseout",function(){t.elementMouseout.apply(this,arguments)}),b.interpolate=function(a){return arguments.length?(p=a,b):p},b.duration=function(a){return arguments.length?(s=a,u.reset(s),r.duration(s),b):s},b.dispatch=t,b.scatter=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return f},set:function(a){f=a}},height:{get:function(){return g},set:function(a){g=a}},clipEdge:{get:function(){return q},set:function(a){q=a}},offset:{get:function(){return n},set:function(a){n=a}},order:{get:function(){return o},set:function(a){o=a}},interpolate:{get:function(){return p},set:function(a){p=a}},x:{get:function(){return k},set:function(a){k=d3.functor(a)}},y:{get:function(){return l},set:function(a){l=d3.functor(a)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}},style:{get:function(){return m},set:function(a){switch(m=a){case"stack":b.offset("zero"),b.order("default");break;case"stream":b.offset("wiggle"),b.order("inside-out");break;case"stream-center":b.offset("silhouette"),b.order("inside-out");break;case"expand":b.offset("expand"),b.order("default");break;case"stack_percent":b.offset(b.d3_stackedOffset_stackPercent),b.order("default")}}},duration:{get:function(){return s},set:function(a){s=a,u.reset(s),r.duration(s)}}}),a.utils.inheritOptions(b,r),a.utils.initOptions(b),b},a.models.stackedAreaChart=function(){"use strict";function b(k){return F.reset(),F.models(e),r&&F.models(f),s&&F.models(g),k.each(function(k){var x=d3.select(this),F=this;a.utils.initSVG(x);var K=a.utils.availableWidth(m,x,l),L=a.utils.availableHeight(n,x,l);if(b.update=function(){x.transition().duration(C).call(b)},b.container=this,v.setter(I(k),b.update).getter(H(k)).update(),v.disabled=k.map(function(a){return!!a.disabled}),!w){var M;w={};for(M in v)w[M]=v[M]instanceof Array?v[M].slice(0):v[M]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(b,x),b;x.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var N=x.selectAll("g.nv-wrap.nv-stackedAreaChart").data([k]),O=N.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),P=N.select("g");if(O.append("rect").style("opacity",0),O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-stackedWrap"),O.append("g").attr("class","nv-legendWrap"),O.append("g").attr("class","nv-controlsWrap"),O.append("g").attr("class","nv-interactive"),P.select("rect").attr("width",K).attr("height",L),q){var Q=p?K-z:K;h.width(Q),P.select(".nv-legendWrap").datum(k).call(h),l.top!=h.height()&&(l.top=h.height(),L=a.utils.availableHeight(n,x,l)),P.select(".nv-legendWrap").attr("transform","translate("+(K-Q)+","+-l.top+")")}if(p){var R=[{key:B.stacked||"Stacked",metaKey:"Stacked",disabled:"stack"!=e.style(),style:"stack"},{key:B.stream||"Stream",metaKey:"Stream",disabled:"stream"!=e.style(),style:"stream"},{key:B.expanded||"Expanded",metaKey:"Expanded",disabled:"expand"!=e.style(),style:"expand"},{key:B.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:"stack_percent"!=e.style(),style:"stack_percent"}];z=A.length/3*260,R=R.filter(function(a){return-1!==A.indexOf(a.metaKey)}),i.width(z).color(["#444","#444","#444"]),P.select(".nv-controlsWrap").datum(R).call(i),l.top!=Math.max(i.height(),h.height())&&(l.top=Math.max(i.height(),h.height()),L=a.utils.availableHeight(n,x,l)),P.select(".nv-controlsWrap").attr("transform","translate(0,"+-l.top+")")}N.attr("transform","translate("+l.left+","+l.top+")"),t&&P.select(".nv-y.nv-axis").attr("transform","translate("+K+",0)"),u&&(j.width(K).height(L).margin({left:l.left,top:l.top}).svgContainer(x).xScale(c),N.select(".nv-interactive").call(j)),e.width(K).height(L);var S=P.select(".nv-stackedWrap").datum(k);if(S.transition().call(e),r&&(f.scale(c)._ticks(a.utils.calcTicksX(K/100,k)).tickSize(-L,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+L+")"),P.select(".nv-x.nv-axis").transition().duration(0).call(f)),s){var T;if(T="wiggle"===e.offset()?0:a.utils.calcTicksY(L/36,k),g.scale(d)._ticks(T).tickSize(-K,0),"expand"===e.style()||"stack_percent"===e.style()){var U=g.tickFormat();D&&U===J||(D=U),g.tickFormat(J)}else D&&(g.tickFormat(D),D=null);P.select(".nv-y.nv-axis").transition().duration(0).call(g)}e.dispatch.on("areaClick.toggle",function(a){k.forEach(1===k.filter(function(a){return!a.disabled}).length?function(a){a.disabled=!1}:function(b,c){b.disabled=c!=a.seriesIndex}),v.disabled=k.map(function(a){return!!a.disabled}),y.stateChange(v),b.update()}),h.dispatch.on("stateChange",function(a){for(var c in a)v[c]=a[c];y.stateChange(v),b.update()}),i.dispatch.on("legendClick",function(a){a.disabled&&(R=R.map(function(a){return a.disabled=!0,a}),a.disabled=!1,e.style(a.style),v.style=e.style(),y.stateChange(v),b.update())}),j.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,g,h,i=[];if(k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,j){g=a.interactiveBisect(f.values,c.pointXValue,b.x());var k=f.values[g],l=b.y()(k,g);if(null!=l&&e.highlightPoint(j,g,!0),"undefined"!=typeof k){"undefined"==typeof d&&(d=k),"undefined"==typeof h&&(h=b.xScale()(b.x()(k,g)));var m="expand"==e.style()?k.display.y:b.y()(k,g);i.push({key:f.key,value:m,color:o(f,f.seriesIndex),stackedValue:k.display})}}),i.reverse(),i.length>2){var m=b.yScale().invert(c.mouseY),n=null;i.forEach(function(a,b){m=Math.abs(m);var c=Math.abs(a.stackedValue.y0),d=Math.abs(a.stackedValue.y);return m>=c&&d+c>=m?void(n=b):void 0}),null!=n&&(i[n].highlight=!0)}var p=f.tickFormat()(b.x()(d,g)),q=j.tooltip.valueFormatter();"expand"===e.style()||"stack_percent"===e.style()?(E||(E=q),q=d3.format(".1%")):E&&(q=E,E=null),j.tooltip.position({left:h+l.left,top:c.mouseY+l.top}).chartContainer(F.parentNode).valueFormatter(q).data({value:p,series:i})(),j.renderGuideLine(h)}),j.dispatch.on("elementMouseout",function(){e.clearHighlights()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&k.length===a.disabled.length&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),v.disabled=a.disabled),"undefined"!=typeof a.style&&(e.style(a.style),G=a.style),b.update()})}),F.renderEnd("stacked Area chart immediate"),b}var c,d,e=a.models.stackedArea(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:25,bottom:50,left:60},m=null,n=null,o=a.utils.defaultColor(),p=!0,q=!0,r=!0,s=!0,t=!1,u=!1,v=a.utils.state(),w=null,x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=250,A=["Stacked","Stream","Expanded"],B={},C=250;v.style=e.style(),f.orient("bottom").tickPadding(7),g.orient(t?"right":"left"),k.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)}),j.tooltip.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)});var D=null,E=null;i.updateState(!1);var F=a.utils.renderWatch(y),G=e.style(),H=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),style:e.style()}}},I=function(a){return function(b){void 0!==b.style&&(G=b.style),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},J=d3.format("%");return e.dispatch.on("elementMouseover.tooltip",function(a){a.point.x=e.x()(a.point),a.point.y=e.y()(a.point),k.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),b.dispatch=y,b.stacked=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.interactiveLayer=j,b.tooltip=k,b.dispatch=y,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return w},set:function(a){w=a}},noData:{get:function(){return x},set:function(a){x=a}},showControls:{get:function(){return p},set:function(a){p=a}},controlLabels:{get:function(){return B},set:function(a){B=a}},controlOptions:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return C},set:function(a){C=a,F.reset(C),e.duration(C),f.duration(C),g.duration(C)}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),h.color(o),e.color(o)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},useInteractiveGuideline:{get:function(){return u},set:function(a){u=!!a,b.interactive(!a),b.useVoronoi(!a),e.scatter.interactive(!a)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.sunburst=function(){"use strict";function b(u){return t.reset(),u.each(function(b){function t(a){a.x0=a.x,a.dx0=a.dx}function u(a){var b=d3.interpolate(p.domain(),[a.x,a.x+a.dx]),c=d3.interpolate(q.domain(),[a.y,1]),d=d3.interpolate(q.range(),[a.y?20:0,y]);return function(a,e){return e?function(){return s(a)}:function(e){return p.domain(b(e)),q.domain(c(e)).range(d(e)),s(a)}}}l=d3.select(this);var v,w=a.utils.availableWidth(g,l,f),x=a.utils.availableHeight(h,l,f),y=Math.min(w,x)/2;a.utils.initSVG(l);var z=l.selectAll(".nv-wrap.nv-sunburst").data(b),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburst nv-chart-"+k),B=A.selectAll("nv-sunburst");z.attr("transform","translate("+w/2+","+x/2+")"),l.on("click",function(a,b){o.chartClick({data:a,index:b,pos:d3.event,id:k})}),q.range([0,y]),c=c||b,e=b[0],r.value(j[i]||j.count),v=B.data(r.nodes).enter().append("path").attr("d",s).style("fill",function(a){return m((a.children?a:a.parent).name)}).style("stroke","#FFF").on("click",function(a){d!==c&&c!==a&&(d=c),c=a,v.transition().duration(n).attrTween("d",u(a))}).each(t).on("dblclick",function(a){d.parent==a&&v.transition().duration(n).attrTween("d",u(e))}).each(t).on("mouseover",function(a){d3.select(this).classed("hover",!0).style("opacity",.8),o.elementMouseover({data:a,color:d3.select(this).style("fill")})}).on("mouseout",function(a){d3.select(this).classed("hover",!1).style("opacity",1),o.elementMouseout({data:a})}).on("mousemove",function(a){o.elementMousemove({data:a})})}),t.renderEnd("sunburst immediate"),b}var c,d,e,f={top:0,right:0,bottom:0,left:0},g=null,h=null,i="count",j={count:function(){return 1},size:function(a){return a.size}},k=Math.floor(1e4*Math.random()),l=null,m=a.utils.defaultColor(),n=500,o=d3.dispatch("chartClick","elementClick","elementDblClick","elementMousemove","elementMouseover","elementMouseout","renderEnd"),p=d3.scale.linear().range([0,2*Math.PI]),q=d3.scale.sqrt(),r=d3.layout.partition().sort(null).value(function(){return 1}),s=d3.svg.arc().startAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x)))}).endAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x+a.dx)))}).innerRadius(function(a){return Math.max(0,q(a.y))}).outerRadius(function(a){return Math.max(0,q(a.y+a.dy))}),t=a.utils.renderWatch(o);return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},mode:{get:function(){return i},set:function(a){i=a}},id:{get:function(){return k},set:function(a){k=a}},duration:{get:function(){return n},set:function(a){n=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!=a.top?a.top:f.top,f.right=void 0!=a.right?a.right:f.right,f.bottom=void 0!=a.bottom?a.bottom:f.bottom,f.left=void 0!=a.left?a.left:f.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sunburstChart=function(){"use strict";function b(d){return m.reset(),m.models(c),d.each(function(d){var h=d3.select(this);a.utils.initSVG(h);var i=a.utils.availableWidth(f,h,e),j=a.utils.availableHeight(g,h,e);if(b.update=function(){0===k?h.call(b):h.transition().duration(k).call(b)},b.container=this,!d||!d.length)return a.utils.noData(b,h),b;h.selectAll(".nv-noData").remove();var l=h.selectAll("g.nv-wrap.nv-sunburstChart").data(d),m=l.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburstChart").append("g"),n=l.select("g");m.append("g").attr("class","nv-sunburstWrap"),l.attr("transform","translate("+e.left+","+e.top+")"),c.width(i).height(j);var o=n.select(".nv-sunburstWrap").datum(d);d3.transition(o).call(c)}),m.renderEnd("sunburstChart immediate"),b}var c=a.models.sunburst(),d=a.models.tooltip(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=a.utils.defaultColor(),i=(Math.round(1e5*Math.random()),null),j=null,k=250,l=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),m=a.utils.renderWatch(l);return d.headerEnabled(!1).duration(0).valueFormatter(function(a){return a}),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.data.name,value:a.data.size,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=l,b.sunburst=c,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return i},set:function(a){i=a}},color:{get:function(){return h},set:function(a){h=a,c.color(h)}},duration:{get:function(){return k},set:function(a){k=a,m.reset(k),c.duration(k)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.version="1.8.1"}();/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; - -return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
    a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/\s*$/g,ra={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:k.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("