From ab868a4c1357e1840be054ae49a94331d5d403a7 Mon Sep 17 00:00:00 2001 From: Jelle Kok Date: Thu, 14 Aug 2014 20:49:29 +0200 Subject: [PATCH 01/63] Fix: error 500 When you have already set index.php as default, you get a error 500. So first you need to remove it then add it again. This is solving the error 500. --- web.config | 1 + 1 file changed, 1 insertion(+) diff --git a/web.config b/web.config index 8083c163f4..72a041f631 100755 --- a/web.config +++ b/web.config @@ -3,6 +3,7 @@ + From 7612cee9d61f95b0e54d7e0267a5d1b4b609039a Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 15 Aug 2014 14:17:14 +0300 Subject: [PATCH 02/63] Make images progressive by default --- system/config/media.yaml | 9 +++++++++ system/src/Grav/Common/Page/Media.php | 3 +++ 2 files changed, 12 insertions(+) diff --git a/system/config/media.yaml b/system/config/media.yaml index 0e8b592fa6..40385268ee 100644 --- a/system/config/media.yaml +++ b/system/config/media.yaml @@ -1,3 +1,12 @@ +defaults: + type: file + thumb: media/thumb.png + mime: application/octet-stream + image: + filters: + default: + - enableProgressive + jpg: type: image thumb: media/thumb-jpg.png diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index cf210a389d..4dcddc78f0 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -85,6 +85,9 @@ public function get($filename, $create = false) } $filePath = $this->path . '/' . $filename; + + // Add default settings for undefined variables. + $params += $config->get('media.defaults'); $params += array( 'type' => 'file', 'thumb' => 'media/thumb.png', From fee951813442c8d2c21b10021e5e268d5cd7e383 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 15 Aug 2014 14:37:44 +0300 Subject: [PATCH 03/63] Update system default settings to be more suitable for production --- system/config/system.yaml | 17 +++++++++-------- system/src/Grav/Common/Grav.php | 6 +++++- user/config/system.yaml | 1 + 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/system/config/system.yaml b/system/config/system.yaml index 67ca278f41..ac6e23c54c 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -26,14 +26,15 @@ cache: prefix: 'g' # Cache prefix string (prevents cache conflicts) twig: - cache: false # Set to true to enable twig caching - debug: true # Enable Twig debug - auto_reload: true # Refresh cache on changes - autoescape: false # Autoescape Twig vars + cache: true # Set to true to enable twig caching + debug: false # Enable Twig debug + auto_reload: true # Refresh cache on changes + autoescape: false # Autoescape Twig vars debugger: - enabled: true # Enable Grav debugger - max_depth: 10 # How many nested levels to display for objects or arrays + enabled: false # Enable Grav debugger and following settings + strict: false # Throw fatal error also on PHP warnings and notices + max_depth: 10 # How many nested levels to display for objects or arrays log: - enabled: true # Enable logging - timing: false # Enable timing logging + enabled: true # Enable logging + timing: false # Enable timing logging diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index f224cf7ae9..454e5fb986 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -12,7 +12,7 @@ * @author Andy Miller * @link http://www.rockettheme.com * @license http://opensource.org/licenses/MIT - * @version 0.1 + * @version 0.8.0 * * Originally based on Pico by Gilbert Pellegrom - http://pico.dev7studios.com * Influeced by Pico, Stacey, Kirby, PieCrust and other great platforms... @@ -84,6 +84,10 @@ public function process() // Switch debugger into development mode if configured if ($this->config->get('system.debugger.enabled')) { + if ($this->config->get('system.debugger.strict')) { + Debugger::$strictMode = true; + } + if (function_exists('ini_set')) { ini_set('display_errors', true); } diff --git a/user/config/system.yaml b/user/config/system.yaml index e05c34ba05..d2fe4567dc 100644 --- a/user/config/system.yaml +++ b/user/config/system.yaml @@ -25,6 +25,7 @@ twig: debugger: enabled: true + strict: false max_depth: 10 log: enabled: false From 0c0cc03394d2b900b17ee4df64371afa769a7a30 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 15 Aug 2014 14:47:10 +0300 Subject: [PATCH 04/63] Exit instead of throwing exception when PHP < 5.4.0 --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index df77bbadc3..02a6a352a8 100644 --- a/index.php +++ b/index.php @@ -2,7 +2,7 @@ namespace Grav\Common; if (version_compare($ver = PHP_VERSION, $req = '5.4.0', '<')) { - throw new \RuntimeException(sprintf('You are running PHP %s, but Grav needs at least PHP %s to run.', $ver, $req)); + exit(sprintf('You are running PHP %s, but Grav needs at least PHP %s to run.', $ver, $req)); } use Tracy\Debugger; From ec8c3d9e602a669ff128f4e68045a7fe56537d3f Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 15 Aug 2014 14:47:48 +0300 Subject: [PATCH 05/63] Better error message when template file isn't found --- system/src/Grav/Common/Twig.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Twig.php b/system/src/Grav/Common/Twig.php index d694ca1607..f0c88bf5c2 100644 --- a/system/src/Grav/Common/Twig.php +++ b/system/src/Grav/Common/Twig.php @@ -233,7 +233,12 @@ public function processSite($format = null) // Get Twig template layout $template = $this->template($page->template() . $ext); - $output = $this->twig->render($template, $twig_vars); + + try { + $output = $this->twig->render($template, $twig_vars); + } catch (\Twig_Error_Loader $e) { + throw new \RuntimeException('Resource not found.', 404, $e); + } return $output; } From 9ed16512fe39b88e0311b239662488c809e7ce98 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 15 Aug 2014 15:07:48 +0300 Subject: [PATCH 06/63] Fix PHP warning on locking without file handle --- system/src/Grav/Common/Filesystem/File/General.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Filesystem/File/General.php b/system/src/Grav/Common/Filesystem/File/General.php index 91fbb66c7b..838c5e54de 100644 --- a/system/src/Grav/Common/Filesystem/File/General.php +++ b/system/src/Grav/Common/Filesystem/File/General.php @@ -149,7 +149,7 @@ public function lock($block = true) $this->handle = fopen($this->filename, 'wb+'); } $lock = $block ? LOCK_EX : LOCK_EX | LOCK_NB; - return $this->locked = flock($this->handle, $lock); + return $this->locked = $this->handle ? flock($this->handle, $lock) : false; } /** From ae2b6e1f74de53e735ec738c25c4bcac014decc8 Mon Sep 17 00:00:00 2001 From: Djamil Legato Date: Fri, 15 Aug 2014 13:26:02 -0700 Subject: [PATCH 07/63] Added Contributing section --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index a6dbf236ef..1b60079eb8 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,19 @@ You can download a **ready-built** package from the [Downloads page on http://ge Check out the [install procedures](http://learn.getgrav.org/basics/installation) for more information. +# Contributing +We appreciate any contribution to Grav, whether it is related to bugs, grammar, or simply a suggestion or improvement. +However, we ask that any contribution follow our simple guidelines in order to be properly received. + +All our projects follow the [GitFlow branching model][gitflow-model], from development to release. If you aren't familiar with it, there are several guides and tutorials to make you understand what it is about. + +You will probably want to get started by installing [this very good collection of git extensions][gitflow-extensions]. + +What you mainly want to know is that: + +- All the main activity happens in the `develop` branch. Any pull-request should be addressed only to that branch. We won't consider pull-requests made to the `master`. +- It's very well appreciated, and highly suggested, to start a new feature whenever you want to make changes or add functionalities. It will make it much easier for us to just checkout your feature branch and test it, before merging it into `develop` + # Getting Started * [What is Grav?](http://learn.getgrav.org/basics/what-is-grav) @@ -51,3 +64,7 @@ Check out the [install procedures](http://learn.getgrav.org/basics/installation) # License See [LICENSE](LICENSE) + + +[gitflow-model]: http://nvie.com/posts/a-successful-git-branching-model/ +[gitflow-extensions]: https://github.com/nvie/gitflow \ No newline at end of file From 69ca8bc93443824b905e34ba9e979ce77fd0ed3e Mon Sep 17 00:00:00 2001 From: Ryan Matthew Pierson Date: Fri, 15 Aug 2014 15:31:49 -0500 Subject: [PATCH 08/63] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1b60079eb8..5aceb95485 100644 --- a/README.md +++ b/README.md @@ -38,13 +38,13 @@ Check out the [install procedures](http://learn.getgrav.org/basics/installation) We appreciate any contribution to Grav, whether it is related to bugs, grammar, or simply a suggestion or improvement. However, we ask that any contribution follow our simple guidelines in order to be properly received. -All our projects follow the [GitFlow branching model][gitflow-model], from development to release. If you aren't familiar with it, there are several guides and tutorials to make you understand what it is about. +All our projects follow the [GitFlow branching model][gitflow-model], from development to release. If you are not familiar with it, there are several guides and tutorials to make you understand what it is about. You will probably want to get started by installing [this very good collection of git extensions][gitflow-extensions]. What you mainly want to know is that: -- All the main activity happens in the `develop` branch. Any pull-request should be addressed only to that branch. We won't consider pull-requests made to the `master`. +- All the main activity happens in the `develop` branch. Any pull request should be addressed only to that branch. We will not consider pull requests made to the `master`. - It's very well appreciated, and highly suggested, to start a new feature whenever you want to make changes or add functionalities. It will make it much easier for us to just checkout your feature branch and test it, before merging it into `develop` # Getting Started @@ -67,4 +67,4 @@ See [LICENSE](LICENSE) [gitflow-model]: http://nvie.com/posts/a-successful-git-branching-model/ -[gitflow-extensions]: https://github.com/nvie/gitflow \ No newline at end of file +[gitflow-extensions]: https://github.com/nvie/gitflow From 0e9417ab1b983c0aa340f3f4df0b26b03028269c Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Fri, 15 Aug 2014 22:05:22 -0600 Subject: [PATCH 09/63] initial commit of new asset pipeline work + user agent handling --- .gitignore | 2 + composer.json | 4 +- index.php | 1 + system/config/system.yaml | 7 + system/defines.php | 1 + system/src/Grav/Common/Assets.php | 682 ++++++ system/src/Grav/Common/Grav.php | 13 + system/src/Grav/Common/Twig.php | 12 +- system/src/Grav/Console/CleanCommand.php | 20 + system/src/Grav/Console/ClearCacheCommand.php | 3 +- user/config/system.yaml | 7 + vendor/autoload.php | 2 +- vendor/composer/autoload_classmap.php | 50 + vendor/composer/autoload_files.php | 4 +- vendor/composer/autoload_real.php | 10 +- vendor/composer/installed.json | 335 ++- vendor/erusev/parsedown/Parsedown.php | 2 +- vendor/mrclay/minify/HISTORY.txt | 141 ++ vendor/mrclay/minify/LICENSE.txt | 26 + vendor/mrclay/minify/MIN.txt | 181 ++ vendor/mrclay/minify/README.txt | 68 + vendor/mrclay/minify/UPGRADING.txt | 28 + vendor/mrclay/minify/min/lib/CSSmin.php | 775 ++++++ .../mrclay/minify/min/lib/DooDigestAuth.php | 121 + vendor/mrclay/minify/min/lib/FirePHP.php | 1370 +++++++++++ .../minify/min/lib/HTTP/ConditionalGet.php | 366 +++ vendor/mrclay/minify/min/lib/HTTP/Encoder.php | 335 +++ vendor/mrclay/minify/min/lib/JSMin.php | 449 ++++ vendor/mrclay/minify/min/lib/JSMinPlus.php | 2086 +++++++++++++++++ vendor/mrclay/minify/min/lib/Minify.php | 608 +++++ vendor/mrclay/minify/min/lib/Minify/Build.php | 101 + vendor/mrclay/minify/min/lib/Minify/CSS.php | 99 + .../minify/min/lib/Minify/CSS/Compressor.php | 249 ++ .../minify/min/lib/Minify/CSS/UriRewriter.php | 307 +++ .../mrclay/minify/min/lib/Minify/CSSmin.php | 85 + .../minify/min/lib/Minify/Cache/APC.php | 133 ++ .../minify/min/lib/Minify/Cache/File.php | 197 ++ .../minify/min/lib/Minify/Cache/Memcache.php | 140 ++ .../minify/min/lib/Minify/Cache/XCache.php | 126 + .../min/lib/Minify/Cache/ZendPlatform.php | 142 ++ .../minify/min/lib/Minify/ClosureCompiler.php | 139 ++ .../min/lib/Minify/CommentPreserver.php | 89 + .../minify/min/lib/Minify/Controller/Base.php | 222 ++ .../min/lib/Minify/Controller/Files.php | 76 + .../min/lib/Minify/Controller/Groups.php | 91 + .../min/lib/Minify/Controller/MinApp.php | 238 ++ .../minify/min/lib/Minify/Controller/Page.php | 68 + .../min/lib/Minify/Controller/Version1.php | 119 + .../minify/min/lib/Minify/DebugDetector.php | 26 + vendor/mrclay/minify/min/lib/Minify/HTML.php | 255 ++ .../minify/min/lib/Minify/HTML/Helper.php | 225 ++ .../minify/min/lib/Minify/ImportProcessor.php | 216 ++ .../min/lib/Minify/JS/ClosureCompiler.php | 230 ++ vendor/mrclay/minify/min/lib/Minify/Lines.php | 143 ++ .../mrclay/minify/min/lib/Minify/Loader.php | 28 + .../mrclay/minify/min/lib/Minify/Logger.php | 47 + .../mrclay/minify/min/lib/Minify/Packer.php | 37 + .../mrclay/minify/min/lib/Minify/Source.php | 187 ++ .../min/lib/Minify/YUI/CssCompressor.java | 382 +++ .../min/lib/Minify/YUI/CssCompressor.php | 171 ++ .../minify/min/lib/Minify/YUICompressor.php | 156 ++ vendor/mrclay/minify/min/lib/MrClay/Cli.php | 384 +++ .../mrclay/minify/min/lib/MrClay/Cli/Arg.php | 183 ++ vendor/ornicar/php-user-agent/CHANGELOG.md | 13 + vendor/ornicar/php-user-agent/LICENSE | 21 + vendor/ornicar/php-user-agent/README.md | 92 + .../php-user-agent/lib/phpUserAgent.php | 194 ++ .../lib/phpUserAgentStringParser.php | 321 +++ .../Console/Formatter/OutputFormatter.php | 6 +- vendor/tracy/tracy/src/Tracy/Debugger.php | 39 +- 70 files changed, 13537 insertions(+), 149 deletions(-) create mode 100644 system/src/Grav/Common/Assets.php create mode 100644 vendor/mrclay/minify/HISTORY.txt create mode 100644 vendor/mrclay/minify/LICENSE.txt create mode 100644 vendor/mrclay/minify/MIN.txt create mode 100644 vendor/mrclay/minify/README.txt create mode 100644 vendor/mrclay/minify/UPGRADING.txt create mode 100644 vendor/mrclay/minify/min/lib/CSSmin.php create mode 100644 vendor/mrclay/minify/min/lib/DooDigestAuth.php create mode 100644 vendor/mrclay/minify/min/lib/FirePHP.php create mode 100644 vendor/mrclay/minify/min/lib/HTTP/ConditionalGet.php create mode 100644 vendor/mrclay/minify/min/lib/HTTP/Encoder.php create mode 100644 vendor/mrclay/minify/min/lib/JSMin.php create mode 100644 vendor/mrclay/minify/min/lib/JSMinPlus.php create mode 100644 vendor/mrclay/minify/min/lib/Minify.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Build.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/CSS.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/CSS/Compressor.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/CSS/UriRewriter.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/CSSmin.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Cache/APC.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Cache/File.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Cache/Memcache.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Cache/XCache.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Cache/ZendPlatform.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/ClosureCompiler.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/CommentPreserver.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Controller/Base.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Controller/Files.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Controller/Groups.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Controller/MinApp.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Controller/Page.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Controller/Version1.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/DebugDetector.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/HTML.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/HTML/Helper.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/ImportProcessor.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/JS/ClosureCompiler.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Lines.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Loader.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Logger.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Packer.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/Source.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/YUI/CssCompressor.java create mode 100644 vendor/mrclay/minify/min/lib/Minify/YUI/CssCompressor.php create mode 100644 vendor/mrclay/minify/min/lib/Minify/YUICompressor.php create mode 100644 vendor/mrclay/minify/min/lib/MrClay/Cli.php create mode 100644 vendor/mrclay/minify/min/lib/MrClay/Cli/Arg.php create mode 100644 vendor/ornicar/php-user-agent/CHANGELOG.md create mode 100644 vendor/ornicar/php-user-agent/LICENSE create mode 100644 vendor/ornicar/php-user-agent/README.md create mode 100644 vendor/ornicar/php-user-agent/lib/phpUserAgent.php create mode 100644 vendor/ornicar/php-user-agent/lib/phpUserAgentStringParser.php diff --git a/.gitignore b/.gitignore index 9fb5cb23b6..d5d22b7a68 100755 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ composer.lock # Grav Specific cache/* !cache/.* +assets/* +!assets/.* logs/* !logs/.* images/* diff --git a/composer.json b/composer.json index c937e27a81..7522dd726f 100644 --- a/composer.json +++ b/composer.json @@ -20,6 +20,8 @@ "doctrine/cache": "1.4.*@dev", "tracy/tracy": "dev-master", "gregwar/image": "dev-master", - "ircmaxell/password-compat": "1.0.*" + "ircmaxell/password-compat": "1.0.*", + "mrclay/minify": "dev-master", + "ornicar/php-user-agent": "1.0.*@dev" } } diff --git a/index.php b/index.php index df77bbadc3..5712865959 100644 --- a/index.php +++ b/index.php @@ -35,6 +35,7 @@ $registry->store('Twig', new Twig); $registry->store('Pages', new Page\Pages); $registry->store('Taxonomy', new Taxonomy); + $registry->store('Assets', new Assets); $grav->process(); diff --git a/system/config/system.yaml b/system/config/system.yaml index 67ca278f41..e6bb00fe98 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -31,6 +31,13 @@ twig: auto_reload: true # Refresh cache on changes autoescape: false # Autoescape Twig vars +assets: # Configuration for Assets Manager (JS, CSS) + css_pipeline: false # The CSS pipeline is the unification of multiple CSS resources into one file + css_minify: true # Minify the CSS during pipelining + css_rewrite: true # Rewrite any CSS relative URLs during pipelining + js_pipeline: false # The JS pipeline is the unification of multiple JS resources into one file + js_minify: true # Minify the JS during pipelining + debugger: enabled: true # Enable Grav debugger max_depth: 10 # How many nested levels to display for objects or arrays diff --git a/system/defines.php b/system/defines.php index b7d1a3526e..d04de5495b 100644 --- a/system/defines.php +++ b/system/defines.php @@ -12,6 +12,7 @@ define('USER_PATH', 'user/'); define('USER_DIR', ROOT_DIR . USER_PATH); define('SYSTEM_DIR', ROOT_DIR .'system/'); +define('ASSETS_DIR', ROOT_DIR . 'assets/'); define('CACHE_DIR', ROOT_DIR .'cache/'); define('IMAGES_DIR', ROOT_DIR . 'images/'); define('LOG_DIR', ROOT_DIR .'logs/'); diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php new file mode 100644 index 0000000000..6cfc42e917 --- /dev/null +++ b/system/src/Grav/Common/Assets.php @@ -0,0 +1,682 @@ +config($options); + } + + public function init() + { + // $this->config = $config; + + $this->config = Registry::get('Config'); + $base_url = $this->config->get('system.base_url_relative'); + $theme = $this->config->get('system.pages.theme'); + $asset_config = (array)$this->config->get('system.assets'); + + $this->config($asset_config); + $this->base_url = $base_url; + $this->theme_url = $base_url .'/'. USER_PATH . basename(THEMES_DIR) .'/'. $theme; + + } + + /** + * Set up configuration options. + * + * All the class properties except 'js' and 'css' are accepted here. + * Also, an extra option 'autoload' may be passed containing an array of + * assets and/or collections that will be automatically added on startup. + * + * @param array $options Configurable options. + * @return Manager + * @throws Exception + */ + public function config(array $config) + { + // Set pipeline modes + if(isset($config['css_pipeline'])) + $this->css_pipeline = $config['css_pipeline']; + + if(isset($config['js_pipeline'])) + $this->js_pipeline = $config['js_pipeline']; + + // Pipeline requires public dir + if(($this->js_pipeline || $this->css_pipeline) && ! is_dir(ASSETS_DIR)) + throw new Exception('Assets: Public dir not found'); + + // Set custom pipeline fetch command + if(isset($config['fetch_command']) and ($config['fetch_command'] instanceof Closure)) + $this->fetch_command = $config['fetch_command']; + + // Set CSS Minify state + if(isset($config['css_minify'])) + $this->css_minify = $config['css_minify']; + + if(isset($config['css_rewrite'])) + $this->css_rewrite = $config['css_rewrite']; + + // Set JS Minify state + if(isset($config['js_minify'])) + $this->js_minify = $config['js_minify']; + + // Set collections + if(isset($config['collections']) and is_array($config['collections'])) + $this->collections = $config['collections']; + + // Autoload assets + if(isset($config['autoload']) and is_array($config['autoload'])) + { + foreach($config['autoload'] as $asset) + { + $this->add($asset); + } + } + + return $this; + } + + /** + * Add an asset or a collection of assets. + * + * It automatically detects the asset type (JavaScript, CSS or collection). + * You may add more than one asset passing an array as argument. + * + * @param mixed $asset + * @param int $priority the priority, bigger comes first + * @param bool $pipeline false if this should not be pipelined + * @return Manager + */ + public function add($asset, $priority = 10, $pipeline = true) + { + // More than one asset + if(is_array($asset)) + { + foreach($asset as $a) + $this->add($a, $priority, $pipeline); + } + // Collection + elseif(isset($this->collections[$asset])) + { + $this->add($this->collections[$asset], $priority, $pipeline); + } + else + { + // JavaScript or CSS + $info = pathinfo($asset); + if(isset($info['extension'])) + { + $ext = strtolower($info['extension']); + if($ext === 'css') + $this->addCss($asset, $priority, $pipeline); + elseif($ext === 'js') + $this->addJs($asset, $priority, $pipeline); + } + } + + return $this; + } + + /** + * Add a CSS asset. + * + * It checks for duplicates. + * You may add more than one asset passing an array as argument. + * + * @param mixed $asset + * @param int $priority the priority, bigger comes first + * @param bool $pipeline false if this should not be pipelined + * @return Manager + */ + public function addCss($asset, $priority = 10, $pipeline = true) + { + if(is_array($asset)) + { + foreach($asset as $a) + $this->addCss($a, $priority, $pipeline); + + return $this; + } + + if( ! $this->isRemoteLink($asset)) + $asset = $this->buildLocalLink($asset); + + if( ! in_array($asset, $this->css)) + $this->css[] = ['asset'=>$asset, 'priority'=>$priority, 'pipeline'=>$pipeline]; + + return $this; + } + + /** + * Add a JavaScript asset. + * + * It checks for duplicates. + * You may add more than one asset passing an array as argument. + * + * @param mixed $asset + * @param int $priority the priority, bigger comes first + * @param bool $pipeline false if this should not be pipelined + * @return Manager + */ + public function addJs($asset, $priority = 10, $pipeline = true) + { + if(is_array($asset)) + { + foreach($asset as $a) + $this->addJs($a, $priority, $pipeline); + + return $this; + } + + if( ! $this->isRemoteLink($asset)) + $asset = $this->buildLocalLink($asset); + + if( ! in_array($asset, $this->js)) + $this->js[] = ['asset'=>$asset, 'priority'=>$priority, 'pipeline'=>$pipeline]; + + return $this; + } + + /** + * Build the CSS link tags. + * + * @return string + */ + public function css() + { + if( ! $this->css) + return null; + + // Sort array by priorities (larger priority first) + usort($this->css, function ($a, $b) {return $a['priority'] - $b['priority'];}); + $this->css = array_reverse($this->css); + + + + $output = ''; + if($this->css_pipeline) { + $output .= ''."\n"; + + foreach ($this->css_no_pipeline as $file) { + $output .= ''."\n"; + } + return $output; + } + + + foreach($this->css as $file) + $output .= ''."\n"; + + return $output; + } + + /** + * Build the JavaScript script tags. + * + * @return string + */ + public function js() + { + if( ! $this->js) + return null; + + // Sort array by priorities (larger priority first) + usort($this->js, function ($a, $b) {return $a['priority'] - $b['priority'];}); + $this->js = array_reverse($this->js); + + $output = ''; + if($this->js_pipeline) { + $output .= ''."\n"; + foreach ($this->js_no_pipeline as $file) { + $output .= ''."\n"; + } + return $output; + } + + + foreach($this->js as $file) + $output .= ''."\n"; + + return $output; + } + + /** + * Add/replace collection. + * + * @param string $collectionName + * @param array $assets + * @return Manager + */ + public function registerCollection($collectionName, Array $assets) + { + $this->collections[$collectionName] = $assets; + + return $this; + } + + /** + * Reset all assets. + * + * @return Manager + */ + public function reset() + { + return $this->resetCss()->resetJs(); + } + + /** + * Reset CSS assets. + * + * @return Manager + */ + public function resetCss() + { + $this->css = array(); + + return $this; + } + + /** + * Reset JavaScript assets. + * + * @return Manager + */ + public function resetJs() + { + $this->js = array(); + + return $this; + } + + /** + * Minifiy and concatenate CSS / JS files. + * + * @return string + */ + protected function pipeline($css = true) + { + $cache = Registry::get('Cache'); + $key = '?'.$cache->getKey(); + + if ($css) { + $file = md5(json_encode($this->css) . $this->js_minify . $this->css_minify . $this->css_rewrite) . '.css'; + foreach ($this->css as $id => $asset) { + if (!$asset['pipeline']) { + $this->css_no_pipeline[] = $asset; + unset($this->css[$id]); + } + } + } else { + $file = md5(json_encode($this->js) . $this->js_minify . $this->css_minify . $this->css_rewrite) . '.js'; + foreach ($this->js as $id => $asset) { + if (!$asset['pipeline']) { + $this->js_no_pipeline[] = $asset; + unset($this->js[$id]); + } + } + } + + $relative_path = "{$this->base_url}/".basename(ASSETS_DIR)."/{$file}"; + $absolute_path = ASSETS_DIR.$file; + + + // If pipeline exist return it + if(file_exists($absolute_path)) + return $relative_path . $key; + + // Concatenate files + if ($css) { + $buffer = $this->gatherLinks($this->css, CSS_ASSET); + if ($this->css_minify) { + $min = new \CSSmin(); + $buffer = $min->run($buffer); + } + } else { + $buffer = $this->gatherLinks($this->js, JS_ASSET); + if ($this->js_minify) { + $buffer = \JSMin::minify($buffer); + } + } + + // Write file + file_put_contents($absolute_path, $buffer); + + return $relative_path . $key; + } + + /** + * Download and concatenate the content of several links. + * + * @param array $links + * @return string + */ + protected function gatherLinks(array $links, $css = true) + { + $buffer = ''; + $local = true; + + foreach($links as $asset) + { + $link = $asset['asset']; + + if($this->isRemoteLink($link)) { + $local = false; + if('//' === substr($link, 0, 2)) + $link = 'http:' . $link; + } else { + $relative_path = str_replace($this->base_url.'/', '', $link); + $relative_dir = dirname ($relative_path); + $link = ROOT_DIR . $relative_path; + } + + $file = ($this->fetch_command instanceof Closure) ? $this->fetch_command->__invoke($link) : file_get_contents($link); + $buffer .= $file; + } + + // If this is CSS + the file is local + rewrite enabled + if ($css && $local && $this->css_rewrite) { + $buffer = $this->cssRewrite($buffer, $relative_dir); + } + + // Pull out @imports and move to top + if ($css) { + $buffer = $this->moveImports($buffer); + } + + return $buffer; + } + + protected function moveImports($file) + { + $this->imports = array(); + + $file = preg_replace_callback('{@import(.*);}', + function($matches) { + $this->imports[] = $matches[0]; + return ''; + }, + $file + ); + + return implode("\n", $this->imports) . "\n\n" . $file; + } + + /** + * Finds relative CSS urls() and rewrites the URL with an absolute one + * @param string $file the css source file + * @param string $relative_path relative path to the css file + * @return [type] [description] + */ + protected function cssRewrite($file, $relative_path) + { + + // Strip any sourcemap comments + $file = preg_replace(self::CSS_SOURCEMAP_REGEX, '', $file); + + // Find any css url() elements, grab the URLs and calculate an absolute path + // Then replace the old url with the new one + $file = preg_replace_callback(self::CSS_URL_REGEX, + function($matches) use ($relative_path) { + + $old_url = $matches[1]; + $newpath = array(); + $paths = explode('/', $old_url); + + foreach ($paths as $path) { + if ($path == '..') { + $relative_path = dirname($relative_path); + } else { + $newpath[] = $path; + } + } + + $new_url = $this->base_url . '/' . $relative_path . '/' . implode('/', $newpath); + + return str_replace($old_url, $new_url, $matches[0]); + }, + $file + ); + + return $file; + } + + protected function buildLocalLink($asset) + { + + $matches = $this->assetIsGravPackage($asset); + $base_url = $this->config->get('system.base_url_relative'); + + if($matches === false) + return $base_url . '/' . $asset; + + if($matches[1] == 'theme') { + return $this->theme_url . '/' . $matches[2] . '/' . $matches[3]; + } elseif ($matches[1] == 'plugin') { + return $base_url . '/user/plugins/' . $matches[2] . '/' . $matches[3]; + } else { + return $base_url . '/' . $asset; + } + + } + + protected function assetIsGravPackage($asset) + { + if(preg_match('{^@([a-z]+)/(.*?):(.*)$}', $asset, $matches)) + return $matches; + return false; + } + + + + /** + * Determine whether a link is local or remote. + * + * Undestands both "http://" and "https://" as well as protocol agnostic links "//" + * + * @param string $link + * @return bool + */ + protected function isRemoteLink($link) + { + return ('http://' === substr($link, 0, 7) or 'https://' === substr($link, 0, 8) or '//' === substr($link, 0, 2)); + } + + /** + * Get all CSS assets already added. + * + * @return array + */ + public function getCss() + { + return $this->css; + } + + /** + * Get all JavaScript assets already added. + * + * @return array + */ + public function getJs() + { + return $this->js; + } + + /** + * Add all assets matching $pattern within $directory. + * + * @param string $directory Relative to $this->public_dir + * @param string $pattern (regex) + * @return Manager + * @throws Exception + */ + public function addDir($directory, $pattern = self::DEFAULT_REGEX) + { + // Check if public_dir exists + if( ! is_dir(ASSETS_DIR)) + throw new Exception('Assets: Public dir not found'); + + // Get files + $files = $this->rglob(ASSETS_DIR . DIRECTORY_SEPARATOR . $directory, $pattern, ASSETS_DIR); + + // No luck? Nothing to do + if( ! $files) + return $this; + + // Add CSS files + if($pattern === self::CSS_REGEX) + { + $this->css = array_unique(array_merge($this->css, $files)); + return $this; + } + + // Add JavaScript files + if($pattern === self::JS_REGEX) + { + $this->js = array_unique(array_merge($this->js, $files)); + return $this; + } + + // Unknown pattern. We must poll to know the extension :( + foreach($files as $asset) + { + $info = pathinfo($asset); + if(isset($info['extension'])) + { + $ext = strtolower($info['extension']); + if($ext === 'css' and ! in_array($asset, $this->css)) + $this->css[] = $asset; + elseif($ext === 'js' and ! in_array($asset, $this->js)) + $this->js[] = $asset; + } + } + + return $this; + } + + /** + * Add all CSS assets within $directory (relative to public dir). + * + * @param string $directory Relative to $this->public_dir + * @return Manager + */ + public function addDirCss($directory) + { + return $this->addDir($directory, self::CSS_REGEX); + } + + /** + * Add all JavaScript assets within $directory. + * + * @param string $directory Relative to $this->public_dir + * @return Manager + */ + public function addDirJs($directory) + { + return $this->addDir($directory, self::JS_REGEX); + } + + /** + * Recursively get files matching $pattern within $directory. + * + * @param string $directory + * @param string $pattern (regex) + * @param string $ltrim Will be trimed from the left of the file path + * @return array + */ + protected function rglob($directory, $pattern, $ltrim = null) + { + $iterator = new RegexIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory, FilesystemIterator::SKIP_DOTS)), $pattern); + $offset = strlen($ltrim); + $files = array(); + + foreach($iterator as $file) + $files[] = substr($file->getPathname(), $offset); + + return $files; + } + + /** + * @var Config + */ + protected function priorityCompare($a, $b) + { + return $a ['priority'] - $b ['priority']; + } + + public function __toString() { + return ''; + } + +} diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index f224cf7ae9..381c6b4c16 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -66,6 +66,11 @@ class Grav extends Getters */ protected $twig; + /** + * @var Assets + */ + protected $assets; + /** * @var Taxonomy */ @@ -79,6 +84,9 @@ public function process() // Get the Configuration settings and caching $this->config = Registry::get('Config'); + // Get User Agent + $this->user_agent = new \phpUserAgent(); + Debugger::$logDirectory = $this->config->get('system.debugger.log.enabled') ? LOG_DIR : null; Debugger::$maxDepth = $this->config->get('system.debugger.max_depth'); @@ -103,6 +111,11 @@ public function process() $themes = new Themes(); $this->plugins['Theme'] = $themes->load(); + // Get assets and fire event to hook onto + $this->assets = Registry::get('Assets'); + $this->assets->init(); + $this->fireEvent('onAfterGetAssets'); + // Get twig object $this->twig = Registry::get('Twig'); $this->twig->init(); diff --git a/system/src/Grav/Common/Twig.php b/system/src/Grav/Common/Twig.php index d694ca1607..cc68b52fbd 100644 --- a/system/src/Grav/Common/Twig.php +++ b/system/src/Grav/Common/Twig.php @@ -28,6 +28,11 @@ class Twig */ protected $config; + /** + * @var Useragent + */ + protected $user_agent; + /** * @var Uri */ @@ -69,9 +74,10 @@ public function init() // get Grav and Config $this->grav = Registry::get('Grav'); $this->config = $this->grav->config; + $this->user_agent = $this->grav->user_agent; $this->uri = Registry::get('Uri'); $this->taxonomy = Registry::get('Taxonomy'); - + $this->assets = Registry::get('Assets'); $this->twig_paths = array(THEMES_DIR . $this->config->get('system.pages.theme') . '/templates'); $this->grav->fireEvent('onAfterTwigTemplatesPaths'); @@ -114,9 +120,9 @@ public function init() 'theme_dir' => THEMES_DIR . $theme, 'theme_url' => $themeUrl, 'site' => $this->config->get('site'), - 'stylesheets' => array(), - 'scripts' => array(), + 'assets' => $this->assets, 'taxonomy' => $this->taxonomy, + 'user_agent' => $this->user_agent, ); } diff --git a/system/src/Grav/Console/CleanCommand.php b/system/src/Grav/Console/CleanCommand.php index cb61ed15a1..63f6aacebc 100644 --- a/system/src/Grav/Console/CleanCommand.php +++ b/system/src/Grav/Console/CleanCommand.php @@ -57,6 +57,26 @@ class CleanCommand extends Command { 'vendor/ircmaxell/password-compat/version-test.php', 'vendor/ircmaxell/password-compat/.travis.yml', 'vendor/ircmaxell/password-compat/test', + 'vendor/mrclay/minify/.editorconfig', + 'vendor/mrclay/minify/.git', + 'vendor/mrclay/minify/.gitignore', + 'vendor/mrclay/minify/composer.json', + 'vendor/mrclay/minify/min_extras', + 'vendor/mrclay/minify/min_unit_tests', + 'vendor/mrclay/minify/min/.htaccess', + 'vendor/mrclay/minify/min/builder', + 'vendor/mrclay/minify/min/config-test.php', + 'vendor/mrclay/minify/min/config.php', + 'vendor/mrclay/minify/min/groupsConfig.php', + 'vendor/mrclay/minify/min/index.php', + 'vendor/mrclay/minify/min/quick-test.css', + 'vendor/mrclay/minify/min/quick-test.js', + 'vendor/mrclay/minify/min/utils.php', + 'vendor/ornicar/php-user-agent/.git', + 'vendor/ornicar/php-user-agent/.gitignore', + 'vendor/ornicar/php-user-agent/composer.json', + 'vendor/ornicar/php-user-agent/prove.php', + 'vendor/ornicar/php-user-agent/test', 'vendor/symfony/console/Symfony/Component/Console/composer.json', 'vendor/symfony/console/Symfony/Component/Console/phpunit.xml.dist', 'vendor/symfony/console/Symfony/Component/Console/.gitignore', diff --git a/system/src/Grav/Console/ClearCacheCommand.php b/system/src/Grav/Console/ClearCacheCommand.php index f2eab71cc5..29340c2181 100644 --- a/system/src/Grav/Console/ClearCacheCommand.php +++ b/system/src/Grav/Console/ClearCacheCommand.php @@ -13,7 +13,8 @@ class ClearCacheCommand extends Command { protected $paths_to_remove = [ 'cache', - 'images' + 'images', + 'assets' ]; protected function configure() { diff --git a/user/config/system.yaml b/user/config/system.yaml index e05c34ba05..7aea37da14 100644 --- a/user/config/system.yaml +++ b/user/config/system.yaml @@ -23,6 +23,13 @@ twig: auto_reload: true autoescape: false +assets: + css_pipeline: false + css_minify: true + css_rewrite: true + js_pipeline: false + js_minify: true + debugger: enabled: true max_depth: 10 diff --git a/vendor/autoload.php b/vendor/autoload.php index ee668a0889..2ce276c067 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit59d31b9205a8126f2a856995d42bb492::getLoader(); +return ComposerAutoloaderInit70d1fc134524e0edbf7795cd92686187::getLoader(); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 6c5a474946..77d51d4810 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -6,6 +6,56 @@ $baseDir = dirname($vendorDir); return array( + 'CSSmin' => $vendorDir . '/mrclay/minify/min/lib/CSSmin.php', + 'DooDigestAuth' => $vendorDir . '/mrclay/minify/min/lib/DooDigestAuth.php', + 'FirePHP' => $vendorDir . '/mrclay/minify/min/lib/FirePHP.php', + 'HTTP_ConditionalGet' => $vendorDir . '/mrclay/minify/min/lib/HTTP/ConditionalGet.php', + 'HTTP_Encoder' => $vendorDir . '/mrclay/minify/min/lib/HTTP/Encoder.php', + 'JSCompilerContext' => $vendorDir . '/mrclay/minify/min/lib/JSMinPlus.php', + 'JSMin' => $vendorDir . '/mrclay/minify/min/lib/JSMin.php', + 'JSMinPlus' => $vendorDir . '/mrclay/minify/min/lib/JSMinPlus.php', + 'JSMin_UnterminatedCommentException' => $vendorDir . '/mrclay/minify/min/lib/JSMin.php', + 'JSMin_UnterminatedRegExpException' => $vendorDir . '/mrclay/minify/min/lib/JSMin.php', + 'JSMin_UnterminatedStringException' => $vendorDir . '/mrclay/minify/min/lib/JSMin.php', + 'JSNode' => $vendorDir . '/mrclay/minify/min/lib/JSMinPlus.php', + 'JSParser' => $vendorDir . '/mrclay/minify/min/lib/JSMinPlus.php', + 'JSToken' => $vendorDir . '/mrclay/minify/min/lib/JSMinPlus.php', + 'JSTokenizer' => $vendorDir . '/mrclay/minify/min/lib/JSMinPlus.php', + 'Minify' => $vendorDir . '/mrclay/minify/min/lib/Minify.php', + 'Minify_Build' => $vendorDir . '/mrclay/minify/min/lib/Minify/Build.php', + 'Minify_CSS' => $vendorDir . '/mrclay/minify/min/lib/Minify/CSS.php', + 'Minify_CSS_Compressor' => $vendorDir . '/mrclay/minify/min/lib/Minify/CSS/Compressor.php', + 'Minify_CSS_UriRewriter' => $vendorDir . '/mrclay/minify/min/lib/Minify/CSS/UriRewriter.php', + 'Minify_CSSmin' => $vendorDir . '/mrclay/minify/min/lib/Minify/CSSmin.php', + 'Minify_Cache_APC' => $vendorDir . '/mrclay/minify/min/lib/Minify/Cache/APC.php', + 'Minify_Cache_File' => $vendorDir . '/mrclay/minify/min/lib/Minify/Cache/File.php', + 'Minify_Cache_Memcache' => $vendorDir . '/mrclay/minify/min/lib/Minify/Cache/Memcache.php', + 'Minify_Cache_XCache' => $vendorDir . '/mrclay/minify/min/lib/Minify/Cache/XCache.php', + 'Minify_Cache_ZendPlatform' => $vendorDir . '/mrclay/minify/min/lib/Minify/Cache/ZendPlatform.php', + 'Minify_ClosureCompiler' => $vendorDir . '/mrclay/minify/min/lib/Minify/ClosureCompiler.php', + 'Minify_ClosureCompiler_Exception' => $vendorDir . '/mrclay/minify/min/lib/Minify/ClosureCompiler.php', + 'Minify_CommentPreserver' => $vendorDir . '/mrclay/minify/min/lib/Minify/CommentPreserver.php', + 'Minify_Controller_Base' => $vendorDir . '/mrclay/minify/min/lib/Minify/Controller/Base.php', + 'Minify_Controller_Files' => $vendorDir . '/mrclay/minify/min/lib/Minify/Controller/Files.php', + 'Minify_Controller_Groups' => $vendorDir . '/mrclay/minify/min/lib/Minify/Controller/Groups.php', + 'Minify_Controller_MinApp' => $vendorDir . '/mrclay/minify/min/lib/Minify/Controller/MinApp.php', + 'Minify_Controller_Page' => $vendorDir . '/mrclay/minify/min/lib/Minify/Controller/Page.php', + 'Minify_Controller_Version1' => $vendorDir . '/mrclay/minify/min/lib/Minify/Controller/Version1.php', + 'Minify_DebugDetector' => $vendorDir . '/mrclay/minify/min/lib/Minify/DebugDetector.php', + 'Minify_HTML' => $vendorDir . '/mrclay/minify/min/lib/Minify/HTML.php', + 'Minify_HTML_Helper' => $vendorDir . '/mrclay/minify/min/lib/Minify/HTML/Helper.php', + 'Minify_ImportProcessor' => $vendorDir . '/mrclay/minify/min/lib/Minify/ImportProcessor.php', + 'Minify_JS_ClosureCompiler' => $vendorDir . '/mrclay/minify/min/lib/Minify/JS/ClosureCompiler.php', + 'Minify_JS_ClosureCompiler_Exception' => $vendorDir . '/mrclay/minify/min/lib/Minify/JS/ClosureCompiler.php', + 'Minify_Lines' => $vendorDir . '/mrclay/minify/min/lib/Minify/Lines.php', + 'Minify_Loader' => $vendorDir . '/mrclay/minify/min/lib/Minify/Loader.php', + 'Minify_Logger' => $vendorDir . '/mrclay/minify/min/lib/Minify/Logger.php', + 'Minify_Packer' => $vendorDir . '/mrclay/minify/min/lib/Minify/Packer.php', + 'Minify_Source' => $vendorDir . '/mrclay/minify/min/lib/Minify/Source.php', + 'Minify_YUICompressor' => $vendorDir . '/mrclay/minify/min/lib/Minify/YUICompressor.php', + 'Minify_YUI_CssCompressor' => $vendorDir . '/mrclay/minify/min/lib/Minify/YUI/CssCompressor.php', + 'MrClay\\Cli' => $vendorDir . '/mrclay/minify/min/lib/MrClay/Cli.php', + 'MrClay\\Cli\\Arg' => $vendorDir . '/mrclay/minify/min/lib/MrClay/Cli/Arg.php', 'Tracy\\Bar' => $vendorDir . '/tracy/tracy/src/Tracy/Bar.php', 'Tracy\\BlueScreen' => $vendorDir . '/tracy/tracy/src/Tracy/BlueScreen.php', 'Tracy\\Debugger' => $vendorDir . '/tracy/tracy/src/Tracy/Debugger.php', diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index 7ce7f52418..dc9dacbf59 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -6,6 +6,8 @@ $baseDir = dirname($vendorDir); return array( - $vendorDir . '/tracy/tracy/src/shortcuts.php', $vendorDir . '/ircmaxell/password-compat/lib/password.php', + $vendorDir . '/tracy/tracy/src/shortcuts.php', + $vendorDir . '/ornicar/php-user-agent/lib/phpUserAgent.php', + $vendorDir . '/ornicar/php-user-agent/lib/phpUserAgentStringParser.php', ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 70b9d34283..3ce4be5b34 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit59d31b9205a8126f2a856995d42bb492 +class ComposerAutoloaderInit70d1fc134524e0edbf7795cd92686187 { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit59d31b9205a8126f2a856995d42bb492', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit70d1fc134524e0edbf7795cd92686187', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit59d31b9205a8126f2a856995d42bb492', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit70d1fc134524e0edbf7795cd92686187', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ public static function getLoader() $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequire59d31b9205a8126f2a856995d42bb492($file); + composerRequire70d1fc134524e0edbf7795cd92686187($file); } return $loader; } } -function composerRequire59d31b9205a8126f2a856995d42bb492($file) +function composerRequire70d1fc134524e0edbf7795cd92686187($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 0e25e4c58d..e68921e1c7 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,45 +1,4 @@ [ - { - "name": "erusev/parsedown", - "version": "dev-master", - "version_normalized": "9999999-dev", - "source": { - "type": "git", - "url": "https://github.com/erusev/parsedown.git", - "reference": "e33ac1c56ea591f21b9cf2fa74356ef708d4e130" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/e33ac1c56ea591f21b9cf2fa74356ef708d4e130", - "reference": "e33ac1c56ea591f21b9cf2fa74356ef708d4e130", - "shasum": "" - }, - "time": "2014-06-18 09:27:25", - "type": "library", - "installation-source": "source", - "autoload": { - "psr-0": { - "Parsedown": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Emanuil Rusev", - "email": "hello@erusev.com", - "homepage": "http://erusev.com" - } - ], - "description": "Parser for Markdown.", - "homepage": "http://parsedown.org", - "keywords": [ - "markdown", - "parser" - ] - }, { "name": "doctrine/cache", "version": "dev-master", @@ -111,67 +70,6 @@ "caching" ] }, - { - "name": "tracy/tracy", - "version": "dev-master", - "version_normalized": "9999999-dev", - "source": { - "type": "git", - "url": "https://github.com/nette/tracy.git", - "reference": "1250ac4907947b28ec66d6e00a337dadaddaad4c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/tracy/zipball/1250ac4907947b28ec66d6e00a337dadaddaad4c", - "reference": "1250ac4907947b28ec66d6e00a337dadaddaad4c", - "shasum": "" - }, - "require": { - "php": ">=5.3.1" - }, - "require-dev": { - "nette/tester": "~1.0" - }, - "time": "2014-08-07 17:19:48", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "installation-source": "source", - "autoload": { - "classmap": [ - "src/Tracy" - ], - "files": [ - "src/shortcuts.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "http://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "http://nette.org/contributors" - } - ], - "description": "Tracy: useful PHP debugger", - "homepage": "http://tracy.nette.org", - "keywords": [ - "debug", - "debugger", - "nette" - ] - }, { "name": "gregwar/cache", "version": "v1.0.9", @@ -373,6 +271,149 @@ "description": "Symfony Yaml Component", "homepage": "http://symfony.com" }, + { + "name": "ircmaxell/password-compat", + "version": "1.0.3", + "version_normalized": "1.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/ircmaxell/password_compat.git", + "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/1fc1521b5e9794ea77e4eca30717be9635f1d4f4", + "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4", + "shasum": "" + }, + "time": "2013-04-30 19:58:08", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "lib/password.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anthony Ferrara", + "email": "ircmaxell@ircmaxell.com", + "homepage": "http://blog.ircmaxell.com" + } + ], + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "homepage": "https://github.com/ircmaxell/password_compat", + "keywords": [ + "hashing", + "password" + ] + }, + { + "name": "erusev/parsedown", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/erusev/parsedown.git", + "reference": "9437766539f6f88e748e7b6183ea31f78e154df5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/9437766539f6f88e748e7b6183ea31f78e154df5", + "reference": "9437766539f6f88e748e7b6183ea31f78e154df5", + "shasum": "" + }, + "time": "2014-08-13 22:27:48", + "type": "library", + "installation-source": "source", + "autoload": { + "psr-0": { + "Parsedown": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "Parser for Markdown.", + "homepage": "http://parsedown.org", + "keywords": [ + "markdown", + "parser" + ] + }, + { + "name": "tracy/tracy", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/nette/tracy.git", + "reference": "e432452e0a68b2e5adfba2061eba412f51dbab4c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/tracy/zipball/e432452e0a68b2e5adfba2061eba412f51dbab4c", + "reference": "e432452e0a68b2e5adfba2061eba412f51dbab4c", + "shasum": "" + }, + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "nette/tester": "~1.0" + }, + "time": "2014-08-14 17:58:22", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "installation-source": "source", + "autoload": { + "classmap": [ + "src/Tracy" + ], + "files": [ + "src/shortcuts.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "http://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "http://nette.org/contributors" + } + ], + "description": "Tracy: useful PHP debugger", + "homepage": "http://tracy.nette.org", + "keywords": [ + "debug", + "debugger", + "nette" + ] + }, { "name": "symfony/console", "version": "2.5.x-dev", @@ -381,12 +422,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "cd2d1e4bac2206b337326b0140ff475fe9ad5f63" + "reference": "748beed2a1e73179c3f5154d33fe6ae100c1aeb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/cd2d1e4bac2206b337326b0140ff475fe9ad5f63", - "reference": "cd2d1e4bac2206b337326b0140ff475fe9ad5f63", + "url": "https://api.github.com/repos/symfony/Console/zipball/748beed2a1e73179c3f5154d33fe6ae100c1aeb1", + "reference": "748beed2a1e73179c3f5154d33fe6ae100c1aeb1", "shasum": "" }, "require": { @@ -400,7 +441,7 @@ "psr/log": "For using the console logger", "symfony/event-dispatcher": "" }, - "time": "2014-08-05 09:00:40", + "time": "2014-08-14 16:10:54", "type": "library", "extra": { "branch-alias": { @@ -431,26 +472,77 @@ "homepage": "http://symfony.com" }, { - "name": "ircmaxell/password-compat", - "version": "1.0.3", - "version_normalized": "1.0.3.0", + "name": "mrclay/minify", + "version": "dev-master", + "version_normalized": "9999999-dev", "source": { "type": "git", - "url": "https://github.com/ircmaxell/password_compat.git", - "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4" + "url": "https://github.com/mrclay/minify.git", + "reference": "fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/1fc1521b5e9794ea77e4eca30717be9635f1d4f4", - "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4", + "url": "https://api.github.com/repos/mrclay/minify/zipball/fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9", + "reference": "fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9", "shasum": "" }, - "time": "2013-04-30 19:58:08", + "require": { + "ext-pcre": "*", + "php": ">=5.2.1" + }, + "time": "2014-04-03 23:53:48", "type": "library", - "installation-source": "dist", + "installation-source": "source", + "autoload": { + "classmap": [ + "min/lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Steve Clay", + "email": "steve@mrclay.org", + "homepage": "http://www.mrclay.org/", + "role": "Developer" + } + ], + "description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers", + "homepage": "http://code.google.com/p/minify/" + }, + { + "name": "ornicar/php-user-agent", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/ornicar/php-user-agent.git", + "reference": "91f648fc5080ac1e8a8b51bcd90867b6ddeaf633" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ornicar/php-user-agent/zipball/91f648fc5080ac1e8a8b51bcd90867b6ddeaf633", + "reference": "91f648fc5080ac1e8a8b51bcd90867b6ddeaf633", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2013-07-09 13:04:43", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "source", "autoload": { "files": [ - "lib/password.php" + "lib/phpUserAgent.php", + "lib/phpUserAgentStringParser.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -459,16 +551,13 @@ ], "authors": [ { - "name": "Anthony Ferrara", - "email": "ircmaxell@ircmaxell.com", - "homepage": "http://blog.ircmaxell.com" + "name": "Thibault Duplessis", + "email": "thibault.duplessis@gmail.com", + "homepage": "http://ornicar.github.com" } ], - "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", - "homepage": "https://github.com/ircmaxell/password_compat", "keywords": [ - "hashing", - "password" + "user-agent" ] } ] diff --git a/vendor/erusev/parsedown/Parsedown.php b/vendor/erusev/parsedown/Parsedown.php index f877c4871e..a109451604 100755 --- a/vendor/erusev/parsedown/Parsedown.php +++ b/vendor/erusev/parsedown/Parsedown.php @@ -619,7 +619,7 @@ protected function identifySetext($Line, array $Block = null) protected function identifyMarkup($Line) { - if (preg_match('/^<(\w[\w\d]*)(?:[ ][^>\/]*)?(\/?)[ ]*>/', $Line['text'], $matches)) + if (preg_match('/^<(\w[\w\d]*)(?:[ ][^>]*)?(\/?)[ ]*>/', $Line['text'], $matches)) { if (in_array($matches[1], $this->textLevelElements)) { diff --git a/vendor/mrclay/minify/HISTORY.txt b/vendor/mrclay/minify/HISTORY.txt new file mode 100644 index 0000000000..9c44d164cd --- /dev/null +++ b/vendor/mrclay/minify/HISTORY.txt @@ -0,0 +1,141 @@ +Minify Release History + +(master) + * Builder styled with Bootstrap (thanks to help from acidvertigo) + +Version 2.2.0 + * Fix handling of RegEx in certain situations in JSMin + * Thanks to Vovan-VE for reporting this + * Update composer.json with support info + * Add ability to set ClosureCompiler URL + * Thanks Elan Ruusamäe for the pull request + * Better report of temp directory errors + * Also thanks to Elan Ruusamäe for anatoher pull request + * Updated CSSmin and added Minify_CSSmin wrapper + * Fix windows issue associated with long cache filenames + * Fix issue with web-based tool + * Fix bug in JSMin exceptions + * Fix "about:blank" bug in CSS_UriRewriter + * Cite is no longer a block element in HTML minification + * Allow for definition of custom config locations outside of the min directory + * Thanks Sam Bauers for the pull request + * Allow option for overriding the maximum byte size POST limit for ClosureCompiler and other additions + * Thanks Joscha Feth for the code + * Fixes to file-relative URL identification in UriRewriter + * Allow far-future expiration and file versioning with the "v" querystirng parameter in addition to existing method + * Lots of general code tidy ups + +Version 2.1.7 + * Fixes arbitrary file inclusion vulnerability on some systems + * Thanks to Matt Mecham for reporting this + +Version 2.1.6 + * JSMin fixes + * Prevents some Closure Compiler API failures + * Uses autoloading for all class loading + * Multiple group support in HTML Helper + * Cache adaptor for XCache + * Allow setting stack-size in YUI Compressor wrapper + * Adds jsCleanComments option to HTML minifier + * Upgrades CSSmin + * CLI script more portable + * Adds composer.json + +Version 2.1.5 + * Removed XSS vulnerability + * Disabled builder bby default + * command line tools to minify and rewrite URIs in CSS + * upgrade (optional) JSMin+ library + * more efficient JS minification when using CC/YUIC + * Closure Compiler uses cURL when allow_url_fopen is off + * Missing file notices when using groups + +Version 2.1.4 + * Option to minify JS with Closure Compiler API w/ JSMin failover + * Cookie/bookmarklet-based debug mode. No HTML editing! + * Allows 1 file to be missing w/o complete failure + * Combine multiple groups and files in single URI + * More useful HTML helpers for writing versioned URIs + * More detailed error logging, including minifier exceptions + * Builder offers more helpful messages/PHP environment warnings + * Bypass minification based on filename pattern. e.g. foo.min.js / foo-min.css + * JSMin won't choke on common Closure compiler syntaxes (i+ ++j) + * Better caching in IE6 + * Cache ids are influenced by group/file names + * Debug mode for Javascript doesn't break on common XPath strings (Prototype 1.6) + * Removed annoying maxFiles limit + * mbstring.func_overload usage is safer + +Version 2.1.3 + * HTTP fixes + * ETag generation now valid (different when gzipped) + * Vary header always sent when Accept-Encoding is sniffed + * Cache-Control no longer has "must-revalidate" due to webkit bug + See: http://mrclay.org/index.php/2009/02/24/safari-4-beta-cache-controlmust-revalidate-bug/ + * Dropped deflate encoding. Browser and proxy support could be buggy. + See: http://stackoverflow.com/questions/883841/ + * File cache now works w/o setting $min_cachePath + * Allow setting contentType in Minify_Source objects + * No more 5.3 deprecation warnings: split() removed + +Version 2.1.2 + * Javascript fixes + * Debug mode no longer confused by "*/*" in strings/RegExps (jQuery) + * quote characters inside RegExp literals no longer cause exception + * files ending in single-line comments no longer cause code loss + * CSS: data: URLs no longer mangled + * Optional error logging to Firefox's FirePHP extension + * Unit tests to check for common DOCUMENT_ROOT problems + * DOCUMENT_ROOT no longer overwritten on IIS servers + * Builder app doesn't fail on systems without gzdeflate() + * APC caching class included + +Version 2.1.1 + * Bug fix release + * Detection and workarounds for zlib.output_compression and non-PHP encoding modules + * Zlib not required (mod_rewrite, et.al., can still be used for encoding) + * HTML : More IE conditional comments preserved + * Minify_groupUri() utility fixed + +Version 2.1.0 + * "min" default application for quick deployment + * Minify URI Builder app & bookmarklet for quickly creating minify URIs + * Relative URIs in CSS file are fixed automatically by default + * "debug" mode for revealing original line #s in combined files + * Better IIS support + * Improved minifier classes: + * JS: preserves IE conditional comments + * CSS: smaller output, preserves more hacks and valid CSS syntax, + shorter line lengths, other bug fixes + * HTML: smaller output, shorter line lengths, other bug fixes + * Default Cache-Control: max-age of 30 minutes + * Conditional GETs supported even when max-age sent + * Experimental memcache cache class (default is files) + * Minify_Cache_File has flock()s (by default) + * Workaround for Windows mtime reporting bug + +Version 2.0.2 beta (2008-06-24) + * Fast new cache system. Cached files served almost 3x as fast. + * Dropped support of compress encoding (though HTTP_Encoder still supports it) + +Version 2.0.1 (2008-05-31) + * E_STRICT compliance (Cache_Lite_File). + +Version 2.0.0 (2008-05-22) + * Complete code overhaul. Minify is now a PEAR-style class and toolkit + for building customized minifying file servers. + * Content-Encoding: deflate/gzip/compress, based on request headers + * Expanded CSS and HTML minifiers with test cases + * Easily plug-in 3rd-party minifiers (like Packer) + * Plug-able front end controller allows changing the way files are chosen + * Compression & encoding modules lazy-loaded as needed (304 responses use + use minimal code) + * Separate utility classes for HTTP encoding and cache control + +Version 1.0.1 (2007-05-05) + * Fixed various problems resolving pathnames when hosted on an NFS mount. + * Fixed 'undefined constant' notice. + * Replaced old JSMin library with a much faster custom implementation. + +Version 1.0.0 (2007-05-02) + * First release. diff --git a/vendor/mrclay/minify/LICENSE.txt b/vendor/mrclay/minify/LICENSE.txt new file mode 100644 index 0000000000..8f008adb56 --- /dev/null +++ b/vendor/mrclay/minify/LICENSE.txt @@ -0,0 +1,26 @@ +Copyright (c) 2008 Ryan Grove +Copyright (c) 2008 Steve Clay +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 this project nor the names of its 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. diff --git a/vendor/mrclay/minify/MIN.txt b/vendor/mrclay/minify/MIN.txt new file mode 100644 index 0000000000..5aaf0fb8cd --- /dev/null +++ b/vendor/mrclay/minify/MIN.txt @@ -0,0 +1,181 @@ +The files in the /min/ directory represent the default Minify setup designed to ease +integration with your site. This app will combine and minify your Javascript or +CSS files and serve them with HTTP compression and cache headers. + + +RECOMMENDED + +It's recommended to edit /min/config.php to set $min_cachePath to a writeable +(by PHP) directory on your system. This will improve performance. + + +GETTING STARTED + +The quickest way to get started is to use the Minify URI Builder application +on your website: http://example.com/min/builder/ + + +MINIFYING A SINGLE FILE + +Let's say you want to serve this file: + http://example.com/wp-content/themes/default/default.css + +Here's the "Minify URL" for this file: + http://example.com/min/?f=wp-content/themes/default/default.css + +In other words, the "f" argument is set to the file path from root without the +initial "/". As CSS files may contain relative URIs, Minify will automatically +"fix" these by rewriting them as root relative. + + +COMBINING MULTIPLE FILES IN ONE DOWNLOAD + +Separate the paths given to "f" with commas. + +Let's say you have CSS files at these URLs: + http://example.com/scripts/jquery-1.2.6.js + http://example.com/scripts/site.js + +You can combine these files through Minify by requesting this URL: + http://example.com/min/?f=scripts/jquery-1.2.6.js,scripts/site.js + + +SIMPLIFYING URLS WITH A BASE PATH + +If you're combining files that share the same ancestor directory, you can use +the "b" argument to set the base directory for the "f" argument. Do not include +the leading or trailing "/" characters. + +E.g., the following URLs will serve the exact same content: + http://example.com/min/?f=scripts/jquery-1.2.6.js,scripts/site.js,scripts/home.js + http://example.com/min/?b=scripts&f=jquery-1.2.6.js,site.js,home.js + + +MINIFY URLS IN HTML + +In HTML files, don't forget to replace any "&" characters with "&". + + +SPECIFYING ALLOWED DIRECTORIES + +By default, Minify will serve any *.css/*.js files within the DOCUMENT_ROOT. If +you'd prefer to limit Minify's access to certain directories, set the +$min_serveOptions['minApp']['allowDirs'] array in config.php. E.g. to limit +to the /js and /themes/default directories, use: + +$min_serveOptions['minApp']['allowDirs'] = array('//js', '//themes/default'); + + +GROUPS: NICER URLS + +For nicer URLs, edit groupsConfig.php to pre-specify groups of files +to be combined under preset keys. E.g., here's an example configuration in +groupsConfig.php: + +return array( + 'js' => array('//js/Class.js', '//js/email.js') +); + +This pre-selects the following files to be combined under the key "js": + http://example.com/js/Class.js + http://example.com/js/email.js + +You can now serve these files with this simple URL: + http://example.com/min/?g=js + + +GROUPS: SPECIFYING FILES OUTSIDE THE DOC_ROOT + +In the groupsConfig.php array, the "//" in the file paths is a shortcut for +the DOCUMENT_ROOT, but you can also specify paths from the root of the filesystem +or relative to the DOC_ROOT: + +return array( + 'js' => array( + '//js/file.js' // file within DOC_ROOT + ,'//../file.js' // file in parent directory of DOC_ROOT + ,'C:/Users/Steve/file.js' // file anywhere on filesystem + ) +); + + +COMBINE MULTIPLE GROUPS AND FILES IN ONE URL + +E.g.: http://example.com/min/?g=js&f=more/scripts.js + +Separate group keys with commas: + http://example.com/min/?g=baseCss,css1&f=moreStyles.css + + +FAR-FUTURE EXPIRES HEADERS + +Minify can send far-future (one year) Expires headers. To enable this you must +add a number or the parameter "v" to the querystring (e.g. /min/?g=js&1234 or +/min/?g=js&v=1234) and alter it whenever a source file is changed. If you have a +build process you can use a build/source control revision number. + +You can alternately use the utility function Minify_getUri() to get a "versioned" +Minify URI for use in your HTML. E.g.: + +"; + +$cssUri = Minify_getUri(array( + '//css/styles1.css' + ,'//css/styles2.css' +)); // a list of files +echo ""; + + +STORING CONFIG FILES OUTSIDE THE MINIFY DIRECTORY + +It is possible to store config files (min/config.php, min/config-test.php, +min/groupsConfig.php) in a custom directory outside the Minify directory. This is +useful if you wish to include Minify as an external dependency inside another +project via SVN external or Git submodule inclusion. + +For example, let's assume you have a Minify directory "min" in your site root. Then +you could create a new directory called "min-configs" in the site root. Copy any +config files you wish to modify to "min-configs", and modify as desired. + +Then create a new file, for example "min.php" in your site root. The contents of +this file could look like this: + + $customConfigDirectory . '/config.php', + 'test' => $customConfigDirectory . '/config-test.php', + 'groups' => $customConfigDirectory . '/groupsConfig.php' +); + +include_once 'min/index.php'; + +You would then reference min.php in your JS and CSS links instead of min/index.php. + +This method will affect those using the Minify_getUri() function. You will need +to add options to calls to that function, e.g.: + + '/min.php')); +echo ""; + + +DEBUG MODE + +In debug mode, instead of compressing files, Minify sends combined files with +comments prepended to each line to show the line number in the original source +file. To enable this, set $min_allowDebugFlag to true in config.php and append +"&debug=1" to your URIs. E.g. /min/?f=script1.js,script2.js&debug=1 + +Known issue: files with comment-like strings/regexps can cause problems in this mode. + + +QUESTIONS? + +http://groups.google.com/group/minify diff --git a/vendor/mrclay/minify/README.txt b/vendor/mrclay/minify/README.txt new file mode 100644 index 0000000000..54b0690f83 --- /dev/null +++ b/vendor/mrclay/minify/README.txt @@ -0,0 +1,68 @@ +WELCOME TO MINIFY! + +Minify is an HTTP content server. It compresses sources of content +(usually files), combines the result and serves it with appropriate +HTTP headers. These headers can allow clients to perform conditional +GETs (serving content only when clients do not have a valid cache) +and tell clients to cache the file for a period of time. +More info: http://code.google.com/p/minify/ + + +WORDPRESS USER? + +These WP plugins integrate Minify into WordPress's style and script hooks to +get you set up faster. + http://wordpress.org/extend/plugins/bwp-minify/ + http://wordpress.org/extend/plugins/w3-total-cache/ + + +INSTALLATION + +Place the /min/ directory as a child of your DOCUMENT_ROOT +directory: i.e. you will have: /home/example/www/min + +You can see verify that it is working by visiting these two URLs: + http://example.org/min/?f=min/quick-test.js + http://example.org/min/?f=min/quick-test.css + +If your server supports mod_rewrite, this URL should also work: + http://example.org/min/f=min/quick-test.js + +CONFIGURATION & USAGE + +See the MIN.txt file and http://code.google.com/p/minify/wiki/UserGuide + +Minify also comes with a URI Builder application that can help you write URLs +for use with Minify or configure groups of files. See here for details: + http://code.google.com/p/minify/wiki/BuilderApp + +The cookbook also provides some more advanced options for minification: + http://code.google.com/p/minify/wiki/CookBook + +UPGRADING + +See UPGRADING.txt for instructions. + + +UNIT TESTING: + +1. Place the /min_unit_tests/ directory as a child of your DOCUMENT_ROOT +directory: i.e. you will have: /home/example/www/min_unit_tests + +2. To run unit tests, access: http://example.org/min_unit_tests/test_all.php + +(If you wish, the other test_*.php files can be run to test individual +components with more verbose output.) + +3. Remove /min_unit_tests/ from your DOCUMENT_ROOT when you are done. + + +FILE ENCODINGS + +Minify *should* work fine with files encoded in UTF-8 or other 8-bit +encodings like ISO 8859/Windows-1252. By default Minify appends +";charset=utf-8" to the Content-Type headers it sends. + +Leading UTF-8 BOMs are stripped from all sources to prevent +duplication in output files, and files are converted to Unix newlines. + diff --git a/vendor/mrclay/minify/UPGRADING.txt b/vendor/mrclay/minify/UPGRADING.txt new file mode 100644 index 0000000000..647b9cc31f --- /dev/null +++ b/vendor/mrclay/minify/UPGRADING.txt @@ -0,0 +1,28 @@ +Minify Upgrade Guide + +UPGRADING FROM 2.1.* + +1. Rename the following files: + + /min/config.php --> /min/old_config.php + /min/groupsConfig.php --> /min/old_groupsConfig.php + +2. Overwrite all files in /min (and /min_unit_tests) with those from this zip. + +3. Delete /min/groupsConfig.php + +4. Rename /min/old_groupsConfig.php --> /min/groupsConfig.php + +5. Merge your settings in old_config.php into config.php. + +6. (optional) Delete /min/old_config.php. + + +INSTALLING FRESH + +See README.txt for instructions on installing this app for the first time. + + +SUPPORT + +Send a message to http://groups.google.com/group/minify \ No newline at end of file diff --git a/vendor/mrclay/minify/min/lib/CSSmin.php b/vendor/mrclay/minify/min/lib/CSSmin.php new file mode 100644 index 0000000000..e85f23eb5e --- /dev/null +++ b/vendor/mrclay/minify/min/lib/CSSmin.php @@ -0,0 +1,775 @@ +memory_limit = 128 * 1048576; // 128MB in bytes + $this->max_execution_time = 60; // 1 min + $this->pcre_backtrack_limit = 1000 * 1000; + $this->pcre_recursion_limit = 500 * 1000; + + $this->raise_php_limits = (bool) $raise_php_limits; + } + + /** + * Minify a string of CSS + * @param string $css + * @param int|bool $linebreak_pos + * @return string + */ + public function run($css = '', $linebreak_pos = FALSE) + { + if (empty($css)) { + return ''; + } + + if ($this->raise_php_limits) { + $this->do_raise_php_limits(); + } + + $this->comments = array(); + $this->preserved_tokens = array(); + + $start_index = 0; + $length = strlen($css); + + $css = $this->extract_data_urls($css); + + // collect all comment blocks... + while (($start_index = $this->index_of($css, '/*', $start_index)) >= 0) { + $end_index = $this->index_of($css, '*/', $start_index + 2); + if ($end_index < 0) { + $end_index = $length; + } + $comment_found = $this->str_slice($css, $start_index + 2, $end_index); + $this->comments[] = $comment_found; + $comment_preserve_string = self::COMMENT . (count($this->comments) - 1) . '___'; + $css = $this->str_slice($css, 0, $start_index + 2) . $comment_preserve_string . $this->str_slice($css, $end_index); + // Set correct start_index: Fixes issue #2528130 + $start_index = $end_index + 2 + strlen($comment_preserve_string) - strlen($comment_found); + } + + // preserve strings so their content doesn't get accidentally minified + $css = preg_replace_callback('/(?:"(?:[^\\\\"]|\\\\.|\\\\)*")|'."(?:'(?:[^\\\\']|\\\\.|\\\\)*')/S", array($this, 'replace_string'), $css); + + // Let's divide css code in chunks of 5.000 chars aprox. + // Reason: PHP's PCRE functions like preg_replace have a "backtrack limit" + // of 100.000 chars by default (php < 5.3.7) so if we're dealing with really + // long strings and a (sub)pattern matches a number of chars greater than + // the backtrack limit number (i.e. /(.*)/s) PCRE functions may fail silently + // returning NULL and $css would be empty. + $charset = ''; + $charset_regexp = '/(@charset)( [^;]+;)/i'; + $css_chunks = array(); + $css_chunk_length = 5000; // aprox size, not exact + $start_index = 0; + $i = $css_chunk_length; // save initial iterations + $l = strlen($css); + + + // if the number of characters is 25000 or less, do not chunk + if ($l <= $css_chunk_length) { + $css_chunks[] = $css; + } else { + // chunk css code securely + while ($i < $l) { + $i += 50; // save iterations + if ($l - $start_index <= $css_chunk_length || $i >= $l) { + $css_chunks[] = $this->str_slice($css, $start_index); + break; + } + if ($css[$i - 1] === '}' && $i - $start_index > $css_chunk_length) { + // If there are two ending curly braces }} separated or not by spaces, + // join them in the same chunk (i.e. @media blocks) + $next_chunk = substr($css, $i); + if (preg_match('/^\s*\}/', $next_chunk)) { + $i = $i + $this->index_of($next_chunk, '}') + 1; + } + + $css_chunks[] = $this->str_slice($css, $start_index, $i); + $start_index = $i; + } + } + } + + // Minify each chunk + for ($i = 0, $n = count($css_chunks); $i < $n; $i++) { + $css_chunks[$i] = $this->minify($css_chunks[$i], $linebreak_pos); + // Keep the first @charset at-rule found + if (empty($charset) && preg_match($charset_regexp, $css_chunks[$i], $matches)) { + $charset = strtolower($matches[1]) . $matches[2]; + } + // Delete all @charset at-rules + $css_chunks[$i] = preg_replace($charset_regexp, '', $css_chunks[$i]); + } + + // Update the first chunk and push the charset to the top of the file. + $css_chunks[0] = $charset . $css_chunks[0]; + + return implode('', $css_chunks); + } + + /** + * Sets the memory limit for this script + * @param int|string $limit + */ + public function set_memory_limit($limit) + { + $this->memory_limit = $this->normalize_int($limit); + } + + /** + * Sets the maximum execution time for this script + * @param int|string $seconds + */ + public function set_max_execution_time($seconds) + { + $this->max_execution_time = (int) $seconds; + } + + /** + * Sets the PCRE backtrack limit for this script + * @param int $limit + */ + public function set_pcre_backtrack_limit($limit) + { + $this->pcre_backtrack_limit = (int) $limit; + } + + /** + * Sets the PCRE recursion limit for this script + * @param int $limit + */ + public function set_pcre_recursion_limit($limit) + { + $this->pcre_recursion_limit = (int) $limit; + } + + /** + * Try to configure PHP to use at least the suggested minimum settings + */ + private function do_raise_php_limits() + { + $php_limits = array( + 'memory_limit' => $this->memory_limit, + 'max_execution_time' => $this->max_execution_time, + 'pcre.backtrack_limit' => $this->pcre_backtrack_limit, + 'pcre.recursion_limit' => $this->pcre_recursion_limit + ); + + // If current settings are higher respect them. + foreach ($php_limits as $name => $suggested) { + $current = $this->normalize_int(ini_get($name)); + // memory_limit exception: allow -1 for "no memory limit". + if ($current > -1 && ($suggested == -1 || $current < $suggested)) { + ini_set($name, $suggested); + } + } + } + + /** + * Does bulk of the minification + * @param string $css + * @param int|bool $linebreak_pos + * @return string + */ + private function minify($css, $linebreak_pos) + { + // strings are safe, now wrestle the comments + for ($i = 0, $max = count($this->comments); $i < $max; $i++) { + + $token = $this->comments[$i]; + $placeholder = '/' . self::COMMENT . $i . '___/'; + + // ! in the first position of the comment means preserve + // so push to the preserved tokens keeping the ! + if (substr($token, 0, 1) === '!') { + $this->preserved_tokens[] = $token; + $token_tring = self::TOKEN . (count($this->preserved_tokens) - 1) . '___'; + $css = preg_replace($placeholder, $token_tring, $css, 1); + // Preserve new lines for /*! important comments + $css = preg_replace('/\s*[\n\r\f]+\s*(\/\*'. $token_tring .')/S', self::NL.'$1', $css); + $css = preg_replace('/('. $token_tring .'\*\/)\s*[\n\r\f]+\s*/', '$1'.self::NL, $css); + continue; + } + + // \ in the last position looks like hack for Mac/IE5 + // shorten that to /*\*/ and the next one to /**/ + if (substr($token, (strlen($token) - 1), 1) === '\\') { + $this->preserved_tokens[] = '\\'; + $css = preg_replace($placeholder, self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1); + $i = $i + 1; // attn: advancing the loop + $this->preserved_tokens[] = ''; + $css = preg_replace('/' . self::COMMENT . $i . '___/', self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1); + continue; + } + + // keep empty comments after child selectors (IE7 hack) + // e.g. html >/**/ body + if (strlen($token) === 0) { + $start_index = $this->index_of($css, $this->str_slice($placeholder, 1, -1)); + if ($start_index > 2) { + if (substr($css, $start_index - 3, 1) === '>') { + $this->preserved_tokens[] = ''; + $css = preg_replace($placeholder, self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1); + } + } + } + + // in all other cases kill the comment + $css = preg_replace('/\/\*' . $this->str_slice($placeholder, 1, -1) . '\*\//', '', $css, 1); + } + + + // Normalize all whitespace strings to single spaces. Easier to work with that way. + $css = preg_replace('/\s+/', ' ', $css); + + // Fix IE7 issue on matrix filters which browser accept whitespaces between Matrix parameters + $css = preg_replace_callback('/\s*filter\:\s*progid:DXImageTransform\.Microsoft\.Matrix\(([^\)]+)\)/', array($this, 'preserve_old_IE_specific_matrix_definition'), $css); + + // Shorten & preserve calculations calc(...) since spaces are important + $css = preg_replace_callback('/calc(\(((?:[^\(\)]+|(?1))*)\))/i', array($this, 'replace_calc'), $css); + + // Replace positive sign from numbers preceded by : or a white-space before the leading space is removed + // +1.2em to 1.2em, +.8px to .8px, +2% to 2% + $css = preg_replace('/((? -9.0 to -9 + $css = preg_replace('/((?\+\(\)\]\~\=,])/', '$1', $css); + + // Restore spaces for !important + $css = preg_replace('/\!important/i', ' !important', $css); + + // bring back the colon + $css = preg_replace('/' . self::CLASSCOLON . '/', ':', $css); + + // retain space for special IE6 cases + $css = preg_replace_callback('/\:first\-(line|letter)(\{|,)/i', array($this, 'lowercase_pseudo_first'), $css); + + // no space after the end of a preserved comment + $css = preg_replace('/\*\/ /', '*/', $css); + + // lowercase some popular @directives + $css = preg_replace_callback('/@(font-face|import|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?keyframe|media|page|namespace)/i', array($this, 'lowercase_directives'), $css); + + // lowercase some more common pseudo-elements + $css = preg_replace_callback('/:(active|after|before|checked|disabled|empty|enabled|first-(?:child|of-type)|focus|hover|last-(?:child|of-type)|link|only-(?:child|of-type)|root|:selection|target|visited)/i', array($this, 'lowercase_pseudo_elements'), $css); + + // lowercase some more common functions + $css = preg_replace_callback('/:(lang|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|(?:-(?:moz|webkit)-)?any)\(/i', array($this, 'lowercase_common_functions'), $css); + + // lower case some common function that can be values + // NOTE: rgb() isn't useful as we replace with #hex later, as well as and() is already done for us + $css = preg_replace_callback('/([:,\( ]\s*)(attr|color-stop|from|rgba|to|url|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|max|min|(?:repeating-)?(?:linear|radial)-gradient)|-webkit-gradient)/iS', array($this, 'lowercase_common_functions_values'), $css); + + // Put the space back in some cases, to support stuff like + // @media screen and (-webkit-min-device-pixel-ratio:0){ + $css = preg_replace('/\band\(/i', 'and (', $css); + + // Remove the spaces after the things that should not have spaces after them. + $css = preg_replace('/([\!\{\}\:;\>\+\(\[\~\=,])\s+/S', '$1', $css); + + // remove unnecessary semicolons + $css = preg_replace('/;+\}/', '}', $css); + + // Fix for issue: #2528146 + // Restore semicolon if the last property is prefixed with a `*` (lte IE7 hack) + // to avoid issues on Symbian S60 3.x browsers. + $css = preg_replace('/(\*[a-z0-9\-]+\s*\:[^;\}]+)(\})/', '$1;$2', $css); + + // Replace 0 length units 0(px,em,%) with 0. + $css = preg_replace('/(^|[^0-9])(?:0?\.)?0(?:em|ex|ch|rem|vw|vh|vm|vmin|cm|mm|in|px|pt|pc|%|deg|g?rad|m?s|k?hz)/iS', '${1}0', $css); + + // 0% step in a keyframe? restore the % unit + $css = preg_replace_callback('/(@[a-z\-]*?keyframes[^\{]*?\{)(.*?\}\s*\})/iS', array($this, 'replace_keyframe_zero'), $css); + + // Replace 0 0; or 0 0 0; or 0 0 0 0; with 0. + $css = preg_replace('/\:0(?: 0){1,3}(;|\}| \!)/', ':0$1', $css); + + // Fix for issue: #2528142 + // Replace text-shadow:0; with text-shadow:0 0 0; + $css = preg_replace('/(text-shadow\:0)(;|\}| \!)/i', '$1 0 0$2', $css); + + // Replace background-position:0; with background-position:0 0; + // same for transform-origin + // Changing -webkit-mask-position: 0 0 to just a single 0 will result in the second parameter defaulting to 50% (center) + $css = preg_replace('/(background\-position|webkit-mask-position|(?:webkit|moz|o|ms|)\-?transform\-origin)\:0(;|\}| \!)/iS', '$1:0 0$2', $css); + + // Shorten colors from rgb(51,102,153) to #336699, rgb(100%,0%,0%) to #ff0000 (sRGB color space) + // Shorten colors from hsl(0, 100%, 50%) to #ff0000 (sRGB color space) + // This makes it more likely that it'll get further compressed in the next step. + $css = preg_replace_callback('/rgb\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'rgb_to_hex'), $css); + $css = preg_replace_callback('/hsl\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'hsl_to_hex'), $css); + + // Shorten colors from #AABBCC to #ABC or short color name. + $css = $this->compress_hex_colors($css); + + // border: none to border:0, outline: none to outline:0 + $css = preg_replace('/(border\-?(?:top|right|bottom|left|)|outline)\:none(;|\}| \!)/iS', '$1:0$2', $css); + + // shorter opacity IE filter + $css = preg_replace('/progid\:DXImageTransform\.Microsoft\.Alpha\(Opacity\=/i', 'alpha(opacity=', $css); + + // Find a fraction that is used for Opera's -o-device-pixel-ratio query + // Add token to add the "\" back in later + $css = preg_replace('/\(([a-z\-]+):([0-9]+)\/([0-9]+)\)/i', '($1:$2'. self::QUERY_FRACTION .'$3)', $css); + + // Remove empty rules. + $css = preg_replace('/[^\};\{\/]+\{\}/S', '', $css); + + // Add "/" back to fix Opera -o-device-pixel-ratio query + $css = preg_replace('/'. self::QUERY_FRACTION .'/', '/', $css); + + // Replace multiple semi-colons in a row by a single one + // See SF bug #1980989 + $css = preg_replace('/;;+/', ';', $css); + + // Restore new lines for /*! important comments + $css = preg_replace('/'. self::NL .'/', "\n", $css); + + // Lowercase all uppercase properties + $css = preg_replace_callback('/(\{|\;)([A-Z\-]+)(\:)/', array($this, 'lowercase_properties'), $css); + + // Some source control tools don't like it when files containing lines longer + // than, say 8000 characters, are checked in. The linebreak option is used in + // that case to split long lines after a specific column. + if ($linebreak_pos !== FALSE && (int) $linebreak_pos >= 0) { + $linebreak_pos = (int) $linebreak_pos; + $start_index = $i = 0; + while ($i < strlen($css)) { + $i++; + if ($css[$i - 1] === '}' && $i - $start_index > $linebreak_pos) { + $css = $this->str_slice($css, 0, $i) . "\n" . $this->str_slice($css, $i); + $start_index = $i; + } + } + } + + // restore preserved comments and strings in reverse order + for ($i = count($this->preserved_tokens) - 1; $i >= 0; $i--) { + $css = preg_replace('/' . self::TOKEN . $i . '___/', $this->preserved_tokens[$i], $css, 1); + } + + // Trim the final string (for any leading or trailing white spaces) + return trim($css); + } + + /** + * Utility method to replace all data urls with tokens before we start + * compressing, to avoid performance issues running some of the subsequent + * regexes against large strings chunks. + * + * @param string $css + * @return string + */ + private function extract_data_urls($css) + { + // Leave data urls alone to increase parse performance. + $max_index = strlen($css) - 1; + $append_index = $index = $last_index = $offset = 0; + $sb = array(); + $pattern = '/url\(\s*(["\']?)data\:/i'; + + // Since we need to account for non-base64 data urls, we need to handle + // ' and ) being part of the data string. Hence switching to indexOf, + // to determine whether or not we have matching string terminators and + // handling sb appends directly, instead of using matcher.append* methods. + + while (preg_match($pattern, $css, $m, 0, $offset)) { + $index = $this->index_of($css, $m[0], $offset); + $last_index = $index + strlen($m[0]); + $start_index = $index + 4; // "url(".length() + $end_index = $last_index - 1; + $terminator = $m[1]; // ', " or empty (not quoted) + $found_terminator = FALSE; + + if (strlen($terminator) === 0) { + $terminator = ')'; + } + + while ($found_terminator === FALSE && $end_index+1 <= $max_index) { + $end_index = $this->index_of($css, $terminator, $end_index + 1); + + // endIndex == 0 doesn't really apply here + if ($end_index > 0 && substr($css, $end_index - 1, 1) !== '\\') { + $found_terminator = TRUE; + if (')' != $terminator) { + $end_index = $this->index_of($css, ')', $end_index); + } + } + } + + // Enough searching, start moving stuff over to the buffer + $sb[] = $this->str_slice($css, $append_index, $index); + + if ($found_terminator) { + $token = $this->str_slice($css, $start_index, $end_index); + $token = preg_replace('/\s+/', '', $token); + $this->preserved_tokens[] = $token; + + $preserver = 'url(' . self::TOKEN . (count($this->preserved_tokens) - 1) . '___)'; + $sb[] = $preserver; + + $append_index = $end_index + 1; + } else { + // No end terminator found, re-add the whole match. Should we throw/warn here? + $sb[] = $this->str_slice($css, $index, $last_index); + $append_index = $last_index; + } + + $offset = $last_index; + } + + $sb[] = $this->str_slice($css, $append_index); + + return implode('', $sb); + } + + /** + * Utility method to compress hex color values of the form #AABBCC to #ABC or short color name. + * + * DOES NOT compress CSS ID selectors which match the above pattern (which would break things). + * e.g. #AddressForm { ... } + * + * DOES NOT compress IE filters, which have hex color values (which would break things). + * e.g. filter: chroma(color="#FFFFFF"); + * + * DOES NOT compress invalid hex values. + * e.g. background-color: #aabbccdd + * + * @param string $css + * @return string + */ + private function compress_hex_colors($css) + { + // Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters) + $pattern = '/(\=\s*?["\']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/iS'; + $_index = $index = $last_index = $offset = 0; + $sb = array(); + // See: http://ajaxmin.codeplex.com/wikipage?title=CSS%20Colors + $short_safe = array( + '#808080' => 'gray', + '#008000' => 'green', + '#800000' => 'maroon', + '#000080' => 'navy', + '#808000' => 'olive', + '#ffa500' => 'orange', + '#800080' => 'purple', + '#c0c0c0' => 'silver', + '#008080' => 'teal', + '#f00' => 'red' + ); + + while (preg_match($pattern, $css, $m, 0, $offset)) { + $index = $this->index_of($css, $m[0], $offset); + $last_index = $index + strlen($m[0]); + $is_filter = $m[1] !== null && $m[1] !== ''; + + $sb[] = $this->str_slice($css, $_index, $index); + + if ($is_filter) { + // Restore, maintain case, otherwise filter will break + $sb[] = $m[1] . '#' . $m[2] . $m[3] . $m[4] . $m[5] . $m[6] . $m[7]; + } else { + if (strtolower($m[2]) == strtolower($m[3]) && + strtolower($m[4]) == strtolower($m[5]) && + strtolower($m[6]) == strtolower($m[7])) { + // Compress. + $hex = '#' . strtolower($m[3] . $m[5] . $m[7]); + } else { + // Non compressible color, restore but lower case. + $hex = '#' . strtolower($m[2] . $m[3] . $m[4] . $m[5] . $m[6] . $m[7]); + } + // replace Hex colors to short safe color names + $sb[] = array_key_exists($hex, $short_safe) ? $short_safe[$hex] : $hex; + } + + $_index = $offset = $last_index - strlen($m[8]); + } + + $sb[] = $this->str_slice($css, $_index); + + return implode('', $sb); + } + + /* CALLBACKS + * --------------------------------------------------------------------------------------------- + */ + + private function replace_string($matches) + { + $match = $matches[0]; + $quote = substr($match, 0, 1); + // Must use addcslashes in PHP to avoid parsing of backslashes + $match = addcslashes($this->str_slice($match, 1, -1), '\\'); + + // maybe the string contains a comment-like substring? + // one, maybe more? put'em back then + if (($pos = $this->index_of($match, self::COMMENT)) >= 0) { + for ($i = 0, $max = count($this->comments); $i < $max; $i++) { + $match = preg_replace('/' . self::COMMENT . $i . '___/', $this->comments[$i], $match, 1); + } + } + + // minify alpha opacity in filter strings + $match = preg_replace('/progid\:DXImageTransform\.Microsoft\.Alpha\(Opacity\=/i', 'alpha(opacity=', $match); + + $this->preserved_tokens[] = $match; + return $quote . self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . $quote; + } + + private function replace_colon($matches) + { + return preg_replace('/\:/', self::CLASSCOLON, $matches[0]); + } + + private function replace_calc($matches) + { + $this->preserved_tokens[] = trim(preg_replace('/\s*([\*\/\(\),])\s*/', '$1', $matches[2])); + return 'calc('. self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . ')'; + } + + private function preserve_old_IE_specific_matrix_definition($matches) + { + $this->preserved_tokens[] = $matches[1]; + return 'filter:progid:DXImageTransform.Microsoft.Matrix(' . self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . ')'; + } + + private function replace_keyframe_zero($matches) + { + return $matches[1] . preg_replace('/0\s*,/', '0%,', preg_replace('/\s*0\s*\{/', '0%{', $matches[2])); + } + + private function rgb_to_hex($matches) + { + // Support for percentage values rgb(100%, 0%, 45%); + if ($this->index_of($matches[1], '%') >= 0){ + $rgbcolors = explode(',', str_replace('%', '', $matches[1])); + for ($i = 0; $i < count($rgbcolors); $i++) { + $rgbcolors[$i] = $this->round_number(floatval($rgbcolors[$i]) * 2.55); + } + } else { + $rgbcolors = explode(',', $matches[1]); + } + + // Values outside the sRGB color space should be clipped (0-255) + for ($i = 0; $i < count($rgbcolors); $i++) { + $rgbcolors[$i] = $this->clamp_number(intval($rgbcolors[$i], 10), 0, 255); + $rgbcolors[$i] = sprintf("%02x", $rgbcolors[$i]); + } + + // Fix for issue #2528093 + if (!preg_match('/[\s\,\);\}]/', $matches[2])){ + $matches[2] = ' ' . $matches[2]; + } + + return '#' . implode('', $rgbcolors) . $matches[2]; + } + + private function hsl_to_hex($matches) + { + $values = explode(',', str_replace('%', '', $matches[1])); + $h = floatval($values[0]); + $s = floatval($values[1]); + $l = floatval($values[2]); + + // Wrap and clamp, then fraction! + $h = ((($h % 360) + 360) % 360) / 360; + $s = $this->clamp_number($s, 0, 100) / 100; + $l = $this->clamp_number($l, 0, 100) / 100; + + if ($s == 0) { + $r = $g = $b = $this->round_number(255 * $l); + } else { + $v2 = $l < 0.5 ? $l * (1 + $s) : ($l + $s) - ($s * $l); + $v1 = (2 * $l) - $v2; + $r = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h + (1/3))); + $g = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h)); + $b = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h - (1/3))); + } + + return $this->rgb_to_hex(array('', $r.','.$g.','.$b, $matches[2])); + } + + private function lowercase_pseudo_first($matches) + { + return ':first-'. strtolower($matches[1]) .' '. $matches[2]; + } + + private function lowercase_directives($matches) + { + return '@'. strtolower($matches[1]); + } + + private function lowercase_pseudo_elements($matches) + { + return ':'. strtolower($matches[1]); + } + + private function lowercase_common_functions($matches) + { + return ':'. strtolower($matches[1]) .'('; + } + + private function lowercase_common_functions_values($matches) + { + return $matches[1] . strtolower($matches[2]); + } + + private function lowercase_properties($matches) + { + return $matches[1].strtolower($matches[2]).$matches[3]; + } + + /* HELPERS + * --------------------------------------------------------------------------------------------- + */ + + private function hue_to_rgb($v1, $v2, $vh) + { + $vh = $vh < 0 ? $vh + 1 : ($vh > 1 ? $vh - 1 : $vh); + if ($vh * 6 < 1) return $v1 + ($v2 - $v1) * 6 * $vh; + if ($vh * 2 < 1) return $v2; + if ($vh * 3 < 2) return $v1 + ($v2 - $v1) * ((2/3) - $vh) * 6; + return $v1; + } + + private function round_number($n) + { + return intval(floor(floatval($n) + 0.5), 10); + } + + private function clamp_number($n, $min, $max) + { + return min(max($n, $min), $max); + } + + /** + * PHP port of Javascript's "indexOf" function for strings only + * Author: Tubal Martin http://blog.margenn.com + * + * @param string $haystack + * @param string $needle + * @param int $offset index (optional) + * @return int + */ + private function index_of($haystack, $needle, $offset = 0) + { + $index = strpos($haystack, $needle, $offset); + + return ($index !== FALSE) ? $index : -1; + } + + /** + * PHP port of Javascript's "slice" function for strings only + * Author: Tubal Martin http://blog.margenn.com + * Tests: http://margenn.com/tubal/str_slice/ + * + * @param string $str + * @param int $start index + * @param int|bool $end index (optional) + * @return string + */ + private function str_slice($str, $start = 0, $end = FALSE) + { + if ($end !== FALSE && ($start < 0 || $end <= 0)) { + $max = strlen($str); + + if ($start < 0) { + if (($start = $max + $start) < 0) { + return ''; + } + } + + if ($end < 0) { + if (($end = $max + $end) < 0) { + return ''; + } + } + + if ($end <= $start) { + return ''; + } + } + + $slice = ($end === FALSE) ? substr($str, $start) : substr($str, $start, $end - $start); + return ($slice === FALSE) ? '' : $slice; + } + + /** + * Convert strings like "64M" or "30" to int values + * @param mixed $size + * @return int + */ + private function normalize_int($size) + { + if (is_string($size)) { + switch (substr($size, -1)) { + case 'M': case 'm': return $size * 1048576; + case 'K': case 'k': return $size * 1024; + case 'G': case 'g': return $size * 1073741824; + } + } + + return (int) $size; + } +} \ No newline at end of file diff --git a/vendor/mrclay/minify/min/lib/DooDigestAuth.php b/vendor/mrclay/minify/min/lib/DooDigestAuth.php new file mode 100644 index 0000000000..69bc4ed4db --- /dev/null +++ b/vendor/mrclay/minify/min/lib/DooDigestAuth.php @@ -0,0 +1,121 @@ + + * @link http://www.doophp.com/ + * @copyright Copyright © 2009 Leng Sheng Hong + * @license http://www.doophp.com/license + */ + +/** + * Handles HTTP digest authentication + * + *

HTTP digest authentication can be used with the URI router. + * HTTP digest is much more recommended over the use of HTTP Basic auth which doesn't provide any encryption. + * If you are running PHP on Apache in CGI/FastCGI mode, you would need to + * add the following line to your .htaccess for digest auth to work correctly.

+ * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] + * + *

This class is tested under Apache 2.2 and Cherokee web server. It should work in both mod_php and cgi mode.

+ * + * @author Leng Sheng Hong + * @version $Id: DooDigestAuth.php 1000 2009-07-7 18:27:22 + * @package doo.auth + * @since 1.0 + */ +class DooDigestAuth{ + + /** + * Authenticate against a list of username and passwords. + * + *

HTTP Digest Authentication doesn't work with PHP in CGI mode, + * you have to add this into your .htaccess RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]

+ * + * @param string $realm Name of the authentication session + * @param array $users An assoc array of username and password: array('uname1'=>'pwd1', 'uname2'=>'pwd2') + * @param string $fail_msg Message to be displayed if the User cancel the login + * @param string $fail_url URL to be redirect if the User cancel the login + * @return string The username if login success. + */ + public static function http_auth($realm, $users, $fail_msg=NULL, $fail_url=NULL){ + $realm = "Restricted area - $realm"; + + //user => password + //$users = array('admin' => '1234', 'guest' => 'guest'); + if(!empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && strpos($_SERVER['REDIRECT_HTTP_AUTHORIZATION'], 'Digest')===0){ + $_SERVER['PHP_AUTH_DIGEST'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; + } + + if (empty($_SERVER['PHP_AUTH_DIGEST'])) { + header('WWW-Authenticate: Digest realm="'.$realm. + '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); + header('HTTP/1.1 401 Unauthorized'); + if($fail_msg!=NULL) + die($fail_msg); + if($fail_url!=NULL) + die(""); + exit; + } + + // analyze the PHP_AUTH_DIGEST variable + if (!($data = self::http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) || !isset($users[$data['username']])){ + header('WWW-Authenticate: Digest realm="'.$realm. + '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); + header('HTTP/1.1 401 Unauthorized'); + if($fail_msg!=NULL) + die($fail_msg); + if($fail_url!=NULL) + die(""); + exit; + } + + // generate the valid response + $A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]); + $A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']); + $valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2); + + if ($data['response'] != $valid_response){ + header('HTTP/1.1 401 Unauthorized'); + header('WWW-Authenticate: Digest realm="'.$realm. + '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); + if($fail_msg!=NULL) + die($fail_msg); + if($fail_url!=NULL) + die(""); + exit; + } + + // ok, valid username & password + return $data['username']; + } + + /** + * Method to parse the http auth header, works with IE. + * + * Internet Explorer returns a qop="xxxxxxxxxxx" in the header instead of qop=xxxxxxxxxxx as most browsers do. + * + * @param string $txt header string to parse + * @return array An assoc array of the digest auth session + */ + private static function http_digest_parse($txt) + { + $res = preg_match("/username=\"([^\"]+)\"/i", $txt, $match); + $data['username'] = (isset($match[1]))?$match[1]:null; + $res = preg_match('/nonce=\"([^\"]+)\"/i', $txt, $match); + $data['nonce'] = $match[1]; + $res = preg_match('/nc=([0-9]+)/i', $txt, $match); + $data['nc'] = $match[1]; + $res = preg_match('/cnonce=\"([^\"]+)\"/i', $txt, $match); + $data['cnonce'] = $match[1]; + $res = preg_match('/qop=([^,]+)/i', $txt, $match); + $data['qop'] = str_replace('"','',$match[1]); + $res = preg_match('/uri=\"([^\"]+)\"/i', $txt, $match); + $data['uri'] = $match[1]; + $res = preg_match('/response=\"([^\"]+)\"/i', $txt, $match); + $data['response'] = $match[1]; + return $data; + } + + +} diff --git a/vendor/mrclay/minify/min/lib/FirePHP.php b/vendor/mrclay/minify/min/lib/FirePHP.php new file mode 100644 index 0000000000..d301a641ab --- /dev/null +++ b/vendor/mrclay/minify/min/lib/FirePHP.php @@ -0,0 +1,1370 @@ + + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHP + */ + + +/** + * Sends the given data to the FirePHP Firefox Extension. + * The data can be displayed in the Firebug Console or in the + * "Server" request tab. + * + * For more information see: http://www.firephp.org/ + * + * @copyright Copyright (C) 2007-2008 Christoph Dorn + * @author Christoph Dorn + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHP + */ +class FirePHP { + + /** + * FirePHP version + * + * @var string + */ + const VERSION = '0.2.0'; + + /** + * Firebug LOG level + * + * Logs a message to firebug console. + * + * @var string + */ + const LOG = 'LOG'; + + /** + * Firebug INFO level + * + * Logs a message to firebug console and displays an info icon before the message. + * + * @var string + */ + const INFO = 'INFO'; + + /** + * Firebug WARN level + * + * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise. + * + * @var string + */ + const WARN = 'WARN'; + + /** + * Firebug ERROR level + * + * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count. + * + * @var string + */ + const ERROR = 'ERROR'; + + /** + * Dumps a variable to firebug's server panel + * + * @var string + */ + const DUMP = 'DUMP'; + + /** + * Displays a stack trace in firebug console + * + * @var string + */ + const TRACE = 'TRACE'; + + /** + * Displays an exception in firebug console + * + * Increments the firebug error count. + * + * @var string + */ + const EXCEPTION = 'EXCEPTION'; + + /** + * Displays an table in firebug console + * + * @var string + */ + const TABLE = 'TABLE'; + + /** + * Starts a group in firebug console + * + * @var string + */ + const GROUP_START = 'GROUP_START'; + + /** + * Ends a group in firebug console + * + * @var string + */ + const GROUP_END = 'GROUP_END'; + + /** + * Singleton instance of FirePHP + * + * @var FirePHP + */ + protected static $instance = null; + + /** + * Wildfire protocol message index + * + * @var int + */ + protected $messageIndex = 1; + + /** + * Options for the library + * + * @var array + */ + protected $options = array(); + + /** + * Filters used to exclude object members when encoding + * + * @var array + */ + protected $objectFilters = array(); + + /** + * A stack of objects used to detect recursion during object encoding + * + * @var object + */ + protected $objectStack = array(); + + /** + * Flag to enable/disable logging + * + * @var boolean + */ + protected $enabled = true; + + /** + * The object constructor + */ + function __construct() { + $this->options['maxObjectDepth'] = 10; + $this->options['maxArrayDepth'] = 20; + $this->options['useNativeJsonEncode'] = true; + $this->options['includeLineNumbers'] = true; + } + + /** + * When the object gets serialized only include specific object members. + * + * @return array + */ + public function __sleep() { + return array('options','objectFilters','enabled'); + } + + /** + * Gets singleton instance of FirePHP + * + * @param boolean $AutoCreate + * @return FirePHP + */ + public static function getInstance($AutoCreate=false) { + if($AutoCreate===true && !self::$instance) { + self::init(); + } + return self::$instance; + } + + /** + * Creates FirePHP object and stores it for singleton access + * + * @return FirePHP + */ + public static function init() { + return self::$instance = new self(); + } + + /** + * Enable and disable logging to Firebug + * + * @param boolean $Enabled TRUE to enable, FALSE to disable + * @return void + */ + public function setEnabled($Enabled) { + $this->enabled = $Enabled; + } + + /** + * Check if logging is enabled + * + * @return boolean TRUE if enabled + */ + public function getEnabled() { + return $this->enabled; + } + + /** + * Specify a filter to be used when encoding an object + * + * Filters are used to exclude object members. + * + * @param string $Class The class name of the object + * @param array $Filter An array or members to exclude + * @return void + */ + public function setObjectFilter($Class, $Filter) { + $this->objectFilters[$Class] = $Filter; + } + + /** + * Set some options for the library + * + * Options: + * - maxObjectDepth: The maximum depth to traverse objects (default: 10) + * - maxArrayDepth: The maximum depth to traverse arrays (default: 20) + * - useNativeJsonEncode: If true will use json_encode() (default: true) + * - includeLineNumbers: If true will include line numbers and filenames (default: true) + * + * @param array $Options The options to be set + * @return void + */ + public function setOptions($Options) { + $this->options = array_merge($this->options,$Options); + } + + /** + * Register FirePHP as your error handler + * + * Will throw exceptions for each php error. + */ + public function registerErrorHandler() + { + //NOTE: The following errors will not be caught by this error handler: + // E_ERROR, E_PARSE, E_CORE_ERROR, + // E_CORE_WARNING, E_COMPILE_ERROR, + // E_COMPILE_WARNING, E_STRICT + + set_error_handler(array($this,'errorHandler')); + } + + /** + * FirePHP's error handler + * + * Throws exception for each php error that will occur. + * + * @param int $errno + * @param string $errstr + * @param string $errfile + * @param int $errline + * @param array $errcontext + */ + public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) + { + // Don't throw exception if error reporting is switched off + if (error_reporting() == 0) { + return; + } + // Only throw exceptions for errors we are asking for + if (error_reporting() & $errno) { + throw new ErrorException($errstr, 0, $errno, $errfile, $errline); + } + } + + /** + * Register FirePHP as your exception handler + */ + public function registerExceptionHandler() + { + set_exception_handler(array($this,'exceptionHandler')); + } + + /** + * FirePHP's exception handler + * + * Logs all exceptions to your firebug console and then stops the script. + * + * @param Exception $Exception + * @throws Exception + */ + function exceptionHandler($Exception) { + $this->fb($Exception); + } + + /** + * Set custom processor url for FirePHP + * + * @param string $URL + */ + public function setProcessorUrl($URL) + { + $this->setHeader('X-FirePHP-ProcessorURL', $URL); + } + + /** + * Set custom renderer url for FirePHP + * + * @param string $URL + */ + public function setRendererUrl($URL) + { + $this->setHeader('X-FirePHP-RendererURL', $URL); + } + + /** + * Start a group for following messages + * + * @param string $Name + * @return true + * @throws Exception + */ + public function group($Name) { + return $this->fb(null, $Name, FirePHP::GROUP_START); + } + + /** + * Ends a group you have started before + * + * @return true + * @throws Exception + */ + public function groupEnd() { + return $this->fb(null, null, FirePHP::GROUP_END); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::LOG + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function log($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::LOG); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::INFO + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function info($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::INFO); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::WARN + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function warn($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::WARN); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::ERROR + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function error($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::ERROR); + } + + /** + * Dumps key and variable to firebug server panel + * + * @see FirePHP::DUMP + * @param string $Key + * @param mixed $Variable + * @return true + * @throws Exception + */ + public function dump($Key, $Variable) { + return $this->fb($Variable, $Key, FirePHP::DUMP); + } + + /** + * Log a trace in the firebug console + * + * @see FirePHP::TRACE + * @param string $Label + * @return true + * @throws Exception + */ + public function trace($Label) { + return $this->fb($Label, FirePHP::TRACE); + } + + /** + * Log a table in the firebug console + * + * @see FirePHP::TABLE + * @param string $Label + * @param string $Table + * @return true + * @throws Exception + */ + public function table($Label, $Table) { + return $this->fb($Table, $Label, FirePHP::TABLE); + } + + /** + * Check if FirePHP is installed on client + * + * @return boolean + */ + public function detectClientExtension() { + /* Check if FirePHP is installed on client */ + if(!@preg_match_all('/\sFirePHP\/([\.|\d]*)\s?/si',$this->getUserAgent(),$m) || + !version_compare($m[1][0],'0.0.6','>=')) { + return false; + } + return true; + } + + /** + * Log varible to Firebug + * + * @see http://www.firephp.org/Wiki/Reference/Fb + * @param mixed $Object The variable to be logged + * @return true Return TRUE if message was added to headers, FALSE otherwise + * @throws Exception + */ + public function fb($Object) { + + if(!$this->enabled) { + return false; + } + + if (headers_sent($filename, $linenum)) { + throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.'); + } + + $Type = null; + $Label = null; + + if(func_num_args()==1) { + } else + if(func_num_args()==2) { + switch(func_get_arg(1)) { + case self::LOG: + case self::INFO: + case self::WARN: + case self::ERROR: + case self::DUMP: + case self::TRACE: + case self::EXCEPTION: + case self::TABLE: + case self::GROUP_START: + case self::GROUP_END: + $Type = func_get_arg(1); + break; + default: + $Label = func_get_arg(1); + break; + } + } else + if(func_num_args()==3) { + $Type = func_get_arg(2); + $Label = func_get_arg(1); + } else { + throw $this->newException('Wrong number of arguments to fb() function!'); + } + + + if(!$this->detectClientExtension()) { + return false; + } + + $meta = array(); + $skipFinalObjectEncode = false; + + if($Object instanceof Exception) { + + $meta['file'] = $this->_escapeTraceFile($Object->getFile()); + $meta['line'] = $Object->getLine(); + + $trace = $Object->getTrace(); + if($Object instanceof ErrorException + && isset($trace[0]['function']) + && $trace[0]['function']=='errorHandler' + && isset($trace[0]['class']) + && $trace[0]['class']=='FirePHP') { + + $severity = false; + switch($Object->getSeverity()) { + case E_WARNING: $severity = 'E_WARNING'; break; + case E_NOTICE: $severity = 'E_NOTICE'; break; + case E_USER_ERROR: $severity = 'E_USER_ERROR'; break; + case E_USER_WARNING: $severity = 'E_USER_WARNING'; break; + case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break; + case E_STRICT: $severity = 'E_STRICT'; break; + case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break; + case E_DEPRECATED: $severity = 'E_DEPRECATED'; break; + case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break; + } + + $Object = array('Class'=>get_class($Object), + 'Message'=>$severity.': '.$Object->getMessage(), + 'File'=>$this->_escapeTraceFile($Object->getFile()), + 'Line'=>$Object->getLine(), + 'Type'=>'trigger', + 'Trace'=>$this->_escapeTrace(array_splice($trace,2))); + $skipFinalObjectEncode = true; + } else { + $Object = array('Class'=>get_class($Object), + 'Message'=>$Object->getMessage(), + 'File'=>$this->_escapeTraceFile($Object->getFile()), + 'Line'=>$Object->getLine(), + 'Type'=>'throw', + 'Trace'=>$this->_escapeTrace($trace)); + $skipFinalObjectEncode = true; + } + $Type = self::EXCEPTION; + + } else + if($Type==self::TRACE) { + + $trace = debug_backtrace(); + if(!$trace) return false; + for( $i=0 ; $i_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' + || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { + /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ + } else + if(isset($trace[$i]['class']) + && isset($trace[$i+1]['file']) + && $trace[$i]['class']=='FirePHP' + && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip fb() */ + } else + if($trace[$i]['function']=='fb' + || $trace[$i]['function']=='trace' + || $trace[$i]['function']=='send') { + $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'', + 'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'', + 'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'', + 'Message'=>$trace[$i]['args'][0], + 'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'', + 'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'', + 'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'', + 'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1))); + + $skipFinalObjectEncode = true; + $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; + $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; + break; + } + } + + } else + if($Type==self::TABLE) { + + if(isset($Object[0]) && is_string($Object[0])) { + $Object[1] = $this->encodeTable($Object[1]); + } else { + $Object = $this->encodeTable($Object); + } + + $skipFinalObjectEncode = true; + + } else { + if($Type===null) { + $Type = self::LOG; + } + } + + if($this->options['includeLineNumbers']) { + if(!isset($meta['file']) || !isset($meta['line'])) { + + $trace = debug_backtrace(); + for( $i=0 ; $trace && $i_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' + || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { + /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ + } else + if(isset($trace[$i]['class']) + && isset($trace[$i+1]['file']) + && $trace[$i]['class']=='FirePHP' + && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip fb() */ + } else + if(isset($trace[$i]['file']) + && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip FB::fb() */ + } else { + $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; + $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; + break; + } + } + + } + } else { + unset($meta['file']); + unset($meta['line']); + } + + $this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2'); + $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION); + + $structure_index = 1; + if($Type==self::DUMP) { + $structure_index = 2; + $this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1'); + } else { + $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'); + } + + if($Type==self::DUMP) { + $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}'; + } else { + $msg_meta = array('Type'=>$Type); + if($Label!==null) { + $msg_meta['Label'] = $Label; + } + if(isset($meta['file'])) { + $msg_meta['File'] = $meta['file']; + } + if(isset($meta['line'])) { + $msg_meta['Line'] = $meta['line']; + } + $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']'; + } + + $parts = explode("\n",chunk_split($msg, 5000, "\n")); + + for( $i=0 ; $i2) { + // Message needs to be split into multiple parts + $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, + (($i==0)?strlen($msg):'') + . '|' . $part . '|' + . (($isetHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, + strlen($part) . '|' . $part . '|'); + } + + $this->messageIndex++; + + if ($this->messageIndex > 99999) { + throw new Exception('Maximum number (99,999) of messages reached!'); + } + } + } + + $this->setHeader('X-Wf-1-Index',$this->messageIndex-1); + + return true; + } + + /** + * Standardizes path for windows systems. + * + * @param string $Path + * @return string + */ + protected function _standardizePath($Path) { + return preg_replace('/\\\\+/','/',$Path); + } + + /** + * Escape trace path for windows systems + * + * @param array $Trace + * @return array + */ + protected function _escapeTrace($Trace) { + if(!$Trace) return $Trace; + for( $i=0 ; $i_escapeTraceFile($Trace[$i]['file']); + } + if(isset($Trace[$i]['args'])) { + $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']); + } + } + return $Trace; + } + + /** + * Escape file information of trace for windows systems + * + * @param string $File + * @return string + */ + protected function _escapeTraceFile($File) { + /* Check if we have a windows filepath */ + if(strpos($File,'\\')) { + /* First strip down to single \ */ + + $file = preg_replace('/\\\\+/','\\',$File); + + return $file; + } + return $File; + } + + /** + * Send header + * + * @param string $Name + * @param string_type $Value + */ + protected function setHeader($Name, $Value) { + return header($Name.': '.$Value); + } + + /** + * Get user agent + * + * @return string|false + */ + protected function getUserAgent() { + if(!isset($_SERVER['HTTP_USER_AGENT'])) return false; + return $_SERVER['HTTP_USER_AGENT']; + } + + /** + * Returns a new exception + * + * @param string $Message + * @return Exception + */ + protected function newException($Message) { + return new Exception($Message); + } + + /** + * Encode an object into a JSON string + * + * Uses PHP's jeson_encode() if available + * + * @param object $Object The object to be encoded + * @return string The JSON string + */ + protected function jsonEncode($Object, $skipObjectEncode=false) + { + if(!$skipObjectEncode) { + $Object = $this->encodeObject($Object); + } + + if(function_exists('json_encode') + && $this->options['useNativeJsonEncode']!=false) { + + return json_encode($Object); + } else { + return $this->json_encode($Object); + } + } + + /** + * Encodes a table by encoding each row and column with encodeObject() + * + * @param array $Table The table to be encoded + * @return array + */ + protected function encodeTable($Table) { + if(!$Table) return $Table; + for( $i=0 ; $iencodeObject($Table[$i][$j]); + } + } + } + return $Table; + } + + /** + * Encodes an object including members with + * protected and private visibility + * + * @param Object $Object The object to be encoded + * @param int $Depth The current traversal depth + * @return array All members of the object + */ + protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1) + { + $return = array(); + + if (is_object($Object)) { + + if ($ObjectDepth > $this->options['maxObjectDepth']) { + return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **'; + } + + foreach ($this->objectStack as $refVal) { + if ($refVal === $Object) { + return '** Recursion ('.get_class($Object).') **'; + } + } + array_push($this->objectStack, $Object); + + $return['__className'] = $class = get_class($Object); + + $reflectionClass = new ReflectionClass($class); + $properties = array(); + foreach( $reflectionClass->getProperties() as $property) { + $properties[$property->getName()] = $property; + } + + $members = (array)$Object; + + foreach( $properties as $raw_name => $property ) { + + $name = $raw_name; + if($property->isStatic()) { + $name = 'static:'.$name; + } + if($property->isPublic()) { + $name = 'public:'.$name; + } else + if($property->isPrivate()) { + $name = 'private:'.$name; + $raw_name = "\0".$class."\0".$raw_name; + } else + if($property->isProtected()) { + $name = 'protected:'.$name; + $raw_name = "\0".'*'."\0".$raw_name; + } + + if(!(isset($this->objectFilters[$class]) + && is_array($this->objectFilters[$class]) + && in_array($raw_name,$this->objectFilters[$class]))) { + + if(array_key_exists($raw_name,$members) + && !$property->isStatic()) { + + $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1); + + } else { + if(method_exists($property,'setAccessible')) { + $property->setAccessible(true); + $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1); + } else + if($property->isPublic()) { + $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1); + } else { + $return[$name] = '** Need PHP 5.3 to get value **'; + } + } + } else { + $return[$name] = '** Excluded by Filter **'; + } + } + + // Include all members that are not defined in the class + // but exist in the object + foreach( $members as $raw_name => $value ) { + + $name = $raw_name; + + if ($name{0} == "\0") { + $parts = explode("\0", $name); + $name = $parts[2]; + } + + if(!isset($properties[$name])) { + $name = 'undeclared:'.$name; + + if(!(isset($this->objectFilters[$class]) + && is_array($this->objectFilters[$class]) + && in_array($raw_name,$this->objectFilters[$class]))) { + + $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1); + } else { + $return[$name] = '** Excluded by Filter **'; + } + } + } + + array_pop($this->objectStack); + + } elseif (is_array($Object)) { + + if ($ArrayDepth > $this->options['maxArrayDepth']) { + return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **'; + } + + foreach ($Object as $key => $val) { + + // Encoding the $GLOBALS PHP array causes an infinite loop + // if the recursion is not reset here as it contains + // a reference to itself. This is the only way I have come up + // with to stop infinite recursion in this case. + if($key=='GLOBALS' + && is_array($val) + && array_key_exists('GLOBALS',$val)) { + $val['GLOBALS'] = '** Recursion (GLOBALS) **'; + } + + $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1); + } + } else { + if(self::is_utf8($Object)) { + return $Object; + } else { + return utf8_encode($Object); + } + } + return $return; + } + + /** + * Returns true if $string is valid UTF-8 and false otherwise. + * + * @param mixed $str String to be tested + * @return boolean + */ + protected static function is_utf8($str) { + $c=0; $b=0; + $bits=0; + $len=strlen($str); + for($i=0; $i<$len; $i++){ + $c=ord($str[$i]); + if($c > 128){ + if(($c >= 254)) return false; + elseif($c >= 252) $bits=6; + elseif($c >= 248) $bits=5; + elseif($c >= 240) $bits=4; + elseif($c >= 224) $bits=3; + elseif($c >= 192) $bits=2; + else return false; + if(($i+$bits) > $len) return false; + while($bits > 1){ + $i++; + $b=ord($str[$i]); + if($b < 128 || $b > 191) return false; + $bits--; + } + } + } + return true; + } + + /** + * Converts to and from JSON format. + * + * JSON (JavaScript Object Notation) is a lightweight data-interchange + * format. It is easy for humans to read and write. It is easy for machines + * to parse and generate. It is based on a subset of the JavaScript + * Programming Language, Standard ECMA-262 3rd Edition - December 1999. + * This feature can also be found in Python. JSON is a text format that is + * completely language independent but uses conventions that are familiar + * to programmers of the C-family of languages, including C, C++, C#, Java, + * JavaScript, Perl, TCL, and many others. These properties make JSON an + * ideal data-interchange language. + * + * This package provides a simple encoder and decoder for JSON notation. It + * is intended for use with client-side Javascript applications that make + * use of HTTPRequest to perform server communication functions - data can + * be encoded into JSON notation for use in a client-side javascript, or + * decoded from incoming Javascript requests. JSON format is native to + * Javascript, and can be directly eval()'ed with no further parsing + * overhead + * + * All strings should be in ASCII or UTF-8 format! + * + * LICENSE: 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. + * + * THIS SOFTWARE IS PROVIDED ``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 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. + * + * @category + * @package Services_JSON + * @author Michal Migurski + * @author Matt Knapp + * @author Brett Stimmerman + * @author Christoph Dorn + * @copyright 2005 Michal Migurski + * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $ + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 + */ + + + /** + * Keep a list of objects as we descend into the array so we can detect recursion. + */ + private $json_objectStack = array(); + + + /** + * convert a string from one UTF-8 char to one UTF-16 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf8 UTF-8 character + * @return string UTF-16 character + * @access private + */ + private function json_utf82utf16($utf8) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) { + return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); + } + + switch(strlen($utf8)) { + case 1: + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return $utf8; + + case 2: + // return a UTF-16 character from a 2-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x07 & (ord($utf8{0}) >> 2)) + . chr((0xC0 & (ord($utf8{0}) << 6)) + | (0x3F & ord($utf8{1}))); + + case 3: + // return a UTF-16 character from a 3-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr((0xF0 & (ord($utf8{0}) << 4)) + | (0x0F & (ord($utf8{1}) >> 2))) + . chr((0xC0 & (ord($utf8{1}) << 6)) + | (0x7F & ord($utf8{2}))); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * encodes an arbitrary variable into JSON format + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return mixed JSON string representation of input var or an error if a problem occurs + * @access public + */ + private function json_encode($var) + { + + if(is_object($var)) { + if(in_array($var,$this->json_objectStack)) { + return '"** Recursion **"'; + } + } + + switch (gettype($var)) { + case 'boolean': + return $var ? 'true' : 'false'; + + case 'NULL': + return 'null'; + + case 'integer': + return (int) $var; + + case 'double': + case 'float': + return (float) $var; + + case 'string': + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT + $ascii = ''; + $strlen_var = strlen($var); + + /* + * Iterate over every character in the string, + * escaping with a slash or encoding to UTF-8 where necessary + */ + for ($c = 0; $c < $strlen_var; ++$c) { + + $ord_var_c = ord($var{$c}); + + switch (true) { + case $ord_var_c == 0x08: + $ascii .= '\b'; + break; + case $ord_var_c == 0x09: + $ascii .= '\t'; + break; + case $ord_var_c == 0x0A: + $ascii .= '\n'; + break; + case $ord_var_c == 0x0C: + $ascii .= '\f'; + break; + case $ord_var_c == 0x0D: + $ascii .= '\r'; + break; + + case $ord_var_c == 0x22: + case $ord_var_c == 0x2F: + case $ord_var_c == 0x5C: + // double quote, slash, slosh + $ascii .= '\\'.$var{$c}; + break; + + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): + // characters U-00000000 - U-0000007F (same as ASCII) + $ascii .= $var{$c}; + break; + + case (($ord_var_c & 0xE0) == 0xC0): + // characters U-00000080 - U-000007FF, mask 110XXXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($var{$c + 1})); + $c += 1; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF0) == 0xE0): + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2})); + $c += 2; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF8) == 0xF0): + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3})); + $c += 3; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFC) == 0xF8): + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4})); + $c += 4; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFE) == 0xFC): + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4}), + ord($var{$c + 5})); + $c += 5; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + } + } + + return '"'.$ascii.'"'; + + case 'array': + /* + * As per JSON spec if any array key is not an integer + * we must treat the the whole array as an object. We + * also try to catch a sparsely populated associative + * array with numeric keys here because some JS engines + * will create an array with empty indexes up to + * max_index which can cause memory issues and because + * the keys, which may be relevant, will be remapped + * otherwise. + * + * As per the ECMA and JSON specification an object may + * have any string as a property. Unfortunately due to + * a hole in the ECMA specification if the key is a + * ECMA reserved word or starts with a digit the + * parameter is only accessible using ECMAScript's + * bracket notation. + */ + + // treat as a JSON object + if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { + + $this->json_objectStack[] = $var; + + $properties = array_map(array($this, 'json_name_value'), + array_keys($var), + array_values($var)); + + array_pop($this->json_objectStack); + + foreach($properties as $property) { + if($property instanceof Exception) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + } + + $this->json_objectStack[] = $var; + + // treat it like a regular array + $elements = array_map(array($this, 'json_encode'), $var); + + array_pop($this->json_objectStack); + + foreach($elements as $element) { + if($element instanceof Exception) { + return $element; + } + } + + return '[' . join(',', $elements) . ']'; + + case 'object': + $vars = self::encodeObject($var); + + $this->json_objectStack[] = $var; + + $properties = array_map(array($this, 'json_name_value'), + array_keys($vars), + array_values($vars)); + + array_pop($this->json_objectStack); + + foreach($properties as $property) { + if($property instanceof Exception) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + + default: + return null; + } + } + + /** + * array-walking function for use in generating JSON-formatted name-value pairs + * + * @param string $name name of key to use + * @param mixed $value reference to an array element to be encoded + * + * @return string JSON-formatted name-value pair, like '"name":value' + * @access private + */ + private function json_name_value($name, $value) + { + // Encoding the $GLOBALS PHP array causes an infinite loop + // if the recursion is not reset here as it contains + // a reference to itself. This is the only way I have come up + // with to stop infinite recursion in this case. + if($name=='GLOBALS' + && is_array($value) + && array_key_exists('GLOBALS',$value)) { + $value['GLOBALS'] = '** Recursion **'; + } + + $encoded_value = $this->json_encode($value); + + if($encoded_value instanceof Exception) { + return $encoded_value; + } + + return $this->json_encode(strval($name)) . ':' . $encoded_value; + } +} diff --git a/vendor/mrclay/minify/min/lib/HTTP/ConditionalGet.php b/vendor/mrclay/minify/min/lib/HTTP/ConditionalGet.php new file mode 100644 index 0000000000..93b7e75d8e --- /dev/null +++ b/vendor/mrclay/minify/min/lib/HTTP/ConditionalGet.php @@ -0,0 +1,366 @@ + + * list($updateTime, $content) = getDbUpdateAndContent(); + * $cg = new HTTP_ConditionalGet(array( + * 'lastModifiedTime' => $updateTime + * ,'isPublic' => true + * )); + * $cg->sendHeaders(); + * if ($cg->cacheIsValid) { + * exit(); + * } + * echo $content; + * + * + * E.g. Shortcut for the above + * + * HTTP_ConditionalGet::check($updateTime, true); // exits if client has cache + * echo $content; + * + * + * E.g. Content from DB with no update time: + * + * $content = getContentFromDB(); + * $cg = new HTTP_ConditionalGet(array( + * 'contentHash' => md5($content) + * )); + * $cg->sendHeaders(); + * if ($cg->cacheIsValid) { + * exit(); + * } + * echo $content; + * + * + * E.g. Static content with some static includes: + * + * // before content + * $cg = new HTTP_ConditionalGet(array( + * 'lastUpdateTime' => max( + * filemtime(__FILE__) + * ,filemtime('/path/to/header.inc') + * ,filemtime('/path/to/footer.inc') + * ) + * )); + * $cg->sendHeaders(); + * if ($cg->cacheIsValid) { + * exit(); + * } + * + * @package Minify + * @subpackage HTTP + * @author Stephen Clay + */ +class HTTP_ConditionalGet { + + /** + * Does the client have a valid copy of the requested resource? + * + * You'll want to check this after instantiating the object. If true, do + * not send content, just call sendHeaders() if you haven't already. + * + * @var bool + */ + public $cacheIsValid = null; + + /** + * @param array $spec options + * + * 'isPublic': (bool) if false, the Cache-Control header will contain + * "private", allowing only browser caching. (default false) + * + * 'lastModifiedTime': (int) if given, both ETag AND Last-Modified headers + * will be sent with content. This is recommended. + * + * 'encoding': (string) if set, the header "Vary: Accept-Encoding" will + * always be sent and a truncated version of the encoding will be appended + * to the ETag. E.g. "pub123456;gz". This will also trigger a more lenient + * checking of the client's If-None-Match header, as the encoding portion of + * the ETag will be stripped before comparison. + * + * 'contentHash': (string) if given, only the ETag header can be sent with + * content (only HTTP1.1 clients can conditionally GET). The given string + * should be short with no quote characters and always change when the + * resource changes (recommend md5()). This is not needed/used if + * lastModifiedTime is given. + * + * 'eTag': (string) if given, this will be used as the ETag header rather + * than values based on lastModifiedTime or contentHash. Also the encoding + * string will not be appended to the given value as described above. + * + * 'invalidate': (bool) if true, the client cache will be considered invalid + * without testing. Effectively this disables conditional GET. + * (default false) + * + * 'maxAge': (int) if given, this will set the Cache-Control max-age in + * seconds, and also set the Expires header to the equivalent GMT date. + * After the max-age period has passed, the browser will again send a + * conditional GET to revalidate its cache. + */ + public function __construct($spec) + { + $scope = (isset($spec['isPublic']) && $spec['isPublic']) + ? 'public' + : 'private'; + $maxAge = 0; + // backwards compatibility (can be removed later) + if (isset($spec['setExpires']) + && is_numeric($spec['setExpires']) + && ! isset($spec['maxAge'])) { + $spec['maxAge'] = $spec['setExpires'] - $_SERVER['REQUEST_TIME']; + } + if (isset($spec['maxAge'])) { + $maxAge = $spec['maxAge']; + $this->_headers['Expires'] = self::gmtDate( + $_SERVER['REQUEST_TIME'] + $spec['maxAge'] + ); + } + $etagAppend = ''; + if (isset($spec['encoding'])) { + $this->_stripEtag = true; + $this->_headers['Vary'] = 'Accept-Encoding'; + if ('' !== $spec['encoding']) { + if (0 === strpos($spec['encoding'], 'x-')) { + $spec['encoding'] = substr($spec['encoding'], 2); + } + $etagAppend = ';' . substr($spec['encoding'], 0, 2); + } + } + if (isset($spec['lastModifiedTime'])) { + $this->_setLastModified($spec['lastModifiedTime']); + if (isset($spec['eTag'])) { // Use it + $this->_setEtag($spec['eTag'], $scope); + } else { // base both headers on time + $this->_setEtag($spec['lastModifiedTime'] . $etagAppend, $scope); + } + } elseif (isset($spec['eTag'])) { // Use it + $this->_setEtag($spec['eTag'], $scope); + } elseif (isset($spec['contentHash'])) { // Use the hash as the ETag + $this->_setEtag($spec['contentHash'] . $etagAppend, $scope); + } + $privacy = ($scope === 'private') + ? ', private' + : ''; + $this->_headers['Cache-Control'] = "max-age={$maxAge}{$privacy}"; + // invalidate cache if disabled, otherwise check + $this->cacheIsValid = (isset($spec['invalidate']) && $spec['invalidate']) + ? false + : $this->_isCacheValid(); + } + + /** + * Get array of output headers to be sent + * + * In the case of 304 responses, this array will only contain the response + * code header: array('_responseCode' => 'HTTP/1.0 304 Not Modified') + * + * Otherwise something like: + * + * array( + * 'Cache-Control' => 'max-age=0, public' + * ,'ETag' => '"foobar"' + * ) + * + * + * @return array + */ + public function getHeaders() + { + return $this->_headers; + } + + /** + * Set the Content-Length header in bytes + * + * With most PHP configs, as long as you don't flush() output, this method + * is not needed and PHP will buffer all output and set Content-Length for + * you. Otherwise you'll want to call this to let the client know up front. + * + * @param int $bytes + * + * @return int copy of input $bytes + */ + public function setContentLength($bytes) + { + return $this->_headers['Content-Length'] = $bytes; + } + + /** + * Send headers + * + * @see getHeaders() + * + * Note this doesn't "clear" the headers. Calling sendHeaders() will + * call header() again (but probably have not effect) and getHeaders() will + * still return the headers. + * + * @return null + */ + public function sendHeaders() + { + $headers = $this->_headers; + if (array_key_exists('_responseCode', $headers)) { + // FastCGI environments require 3rd arg to header() to be set + list(, $code) = explode(' ', $headers['_responseCode'], 3); + header($headers['_responseCode'], true, $code); + unset($headers['_responseCode']); + } + foreach ($headers as $name => $val) { + header($name . ': ' . $val); + } + } + + /** + * Exit if the client's cache is valid for this resource + * + * This is a convenience method for common use of the class + * + * @param int $lastModifiedTime if given, both ETag AND Last-Modified headers + * will be sent with content. This is recommended. + * + * @param bool $isPublic (default false) if true, the Cache-Control header + * will contain "public", allowing proxies to cache the content. Otherwise + * "private" will be sent, allowing only browser caching. + * + * @param array $options (default empty) additional options for constructor + */ + public static function check($lastModifiedTime = null, $isPublic = false, $options = array()) + { + if (null !== $lastModifiedTime) { + $options['lastModifiedTime'] = (int)$lastModifiedTime; + } + $options['isPublic'] = (bool)$isPublic; + $cg = new HTTP_ConditionalGet($options); + $cg->sendHeaders(); + if ($cg->cacheIsValid) { + exit(); + } + } + + + /** + * Get a GMT formatted date for use in HTTP headers + * + * + * header('Expires: ' . HTTP_ConditionalGet::gmtdate($time)); + * + * + * @param int $time unix timestamp + * + * @return string + */ + public static function gmtDate($time) + { + return gmdate('D, d M Y H:i:s \G\M\T', $time); + } + + protected $_headers = array(); + protected $_lmTime = null; + protected $_etag = null; + protected $_stripEtag = false; + + /** + * @param string $hash + * + * @param string $scope + */ + protected function _setEtag($hash, $scope) + { + $this->_etag = '"' . substr($scope, 0, 3) . $hash . '"'; + $this->_headers['ETag'] = $this->_etag; + } + + /** + * @param int $time + */ + protected function _setLastModified($time) + { + $this->_lmTime = (int)$time; + $this->_headers['Last-Modified'] = self::gmtDate($time); + } + + /** + * Determine validity of client cache and queue 304 header if valid + * + * @return bool + */ + protected function _isCacheValid() + { + if (null === $this->_etag) { + // lmTime is copied to ETag, so this condition implies that the + // server sent neither ETag nor Last-Modified, so the client can't + // possibly has a valid cache. + return false; + } + $isValid = ($this->resourceMatchedEtag() || $this->resourceNotModified()); + if ($isValid) { + $this->_headers['_responseCode'] = 'HTTP/1.0 304 Not Modified'; + } + return $isValid; + } + + /** + * @return bool + */ + protected function resourceMatchedEtag() + { + if (!isset($_SERVER['HTTP_IF_NONE_MATCH'])) { + return false; + } + $clientEtagList = get_magic_quotes_gpc() + ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) + : $_SERVER['HTTP_IF_NONE_MATCH']; + $clientEtags = explode(',', $clientEtagList); + + $compareTo = $this->normalizeEtag($this->_etag); + foreach ($clientEtags as $clientEtag) { + if ($this->normalizeEtag($clientEtag) === $compareTo) { + // respond with the client's matched ETag, even if it's not what + // we would've sent by default + $this->_headers['ETag'] = trim($clientEtag); + return true; + } + } + return false; + } + + /** + * @param string $etag + * + * @return string + */ + protected function normalizeEtag($etag) { + $etag = trim($etag); + return $this->_stripEtag + ? preg_replace('/;\\w\\w"$/', '"', $etag) + : $etag; + } + + /** + * @return bool + */ + protected function resourceNotModified() + { + if (!isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { + return false; + } + // strip off IE's extra data (semicolon) + list($ifModifiedSince) = explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE'], 2); + if (strtotime($ifModifiedSince) >= $this->_lmTime) { + // Apache 2.2's behavior. If there was no ETag match, send the + // non-encoded version of the ETag value. + $this->_headers['ETag'] = $this->normalizeEtag($this->_etag); + return true; + } + return false; + } +} diff --git a/vendor/mrclay/minify/min/lib/HTTP/Encoder.php b/vendor/mrclay/minify/min/lib/HTTP/Encoder.php new file mode 100644 index 0000000000..8f347793cf --- /dev/null +++ b/vendor/mrclay/minify/min/lib/HTTP/Encoder.php @@ -0,0 +1,335 @@ + + * // Send a CSS file, compressed if possible + * $he = new HTTP_Encoder(array( + * 'content' => file_get_contents($cssFile) + * ,'type' => 'text/css' + * )); + * $he->encode(); + * $he->sendAll(); + * + * + * + * // Shortcut to encoding output + * header('Content-Type: text/css'); // needed if not HTML + * HTTP_Encoder::output($css); + * + * + * + * // Just sniff for the accepted encoding + * $encoding = HTTP_Encoder::getAcceptedEncoding(); + * + * + * For more control over headers, use getHeaders() and getData() and send your + * own output. + * + * Note: If you don't need header mgmt, use PHP's native gzencode, gzdeflate, + * and gzcompress functions for gzip, deflate, and compress-encoding + * respectively. + * + * @package Minify + * @subpackage HTTP + * @author Stephen Clay + */ +class HTTP_Encoder { + + /** + * Should the encoder allow HTTP encoding to IE6? + * + * If you have many IE6 users and the bandwidth savings is worth troubling + * some of them, set this to true. + * + * By default, encoding is only offered to IE7+. When this is true, + * getAcceptedEncoding() will return an encoding for IE6 if its user agent + * string contains "SV1". This has been documented in many places as "safe", + * but there seem to be remaining, intermittent encoding bugs in patched + * IE6 on the wild web. + * + * @var bool + */ + public static $encodeToIe6 = true; + + + /** + * Default compression level for zlib operations + * + * This level is used if encode() is not given a $compressionLevel + * + * @var int + */ + public static $compressionLevel = 6; + + + /** + * Get an HTTP Encoder object + * + * @param array $spec options + * + * 'content': (string required) content to be encoded + * + * 'type': (string) if set, the Content-Type header will have this value. + * + * 'method: (string) only set this if you are forcing a particular encoding + * method. If not set, the best method will be chosen by getAcceptedEncoding() + * The available methods are 'gzip', 'deflate', 'compress', and '' (no + * encoding) + */ + public function __construct($spec) + { + $this->_useMbStrlen = (function_exists('mb_strlen') + && (ini_get('mbstring.func_overload') !== '') + && ((int)ini_get('mbstring.func_overload') & 2)); + $this->_content = $spec['content']; + $this->_headers['Content-Length'] = $this->_useMbStrlen + ? (string)mb_strlen($this->_content, '8bit') + : (string)strlen($this->_content); + if (isset($spec['type'])) { + $this->_headers['Content-Type'] = $spec['type']; + } + if (isset($spec['method']) + && in_array($spec['method'], array('gzip', 'deflate', 'compress', ''))) + { + $this->_encodeMethod = array($spec['method'], $spec['method']); + } else { + $this->_encodeMethod = self::getAcceptedEncoding(); + } + } + + /** + * Get content in current form + * + * Call after encode() for encoded content. + * + * @return string + */ + public function getContent() + { + return $this->_content; + } + + /** + * Get array of output headers to be sent + * + * E.g. + * + * array( + * 'Content-Length' => '615' + * ,'Content-Encoding' => 'x-gzip' + * ,'Vary' => 'Accept-Encoding' + * ) + * + * + * @return array + */ + public function getHeaders() + { + return $this->_headers; + } + + /** + * Send output headers + * + * You must call this before headers are sent and it probably cannot be + * used in conjunction with zlib output buffering / mod_gzip. Errors are + * not handled purposefully. + * + * @see getHeaders() + */ + public function sendHeaders() + { + foreach ($this->_headers as $name => $val) { + header($name . ': ' . $val); + } + } + + /** + * Send output headers and content + * + * A shortcut for sendHeaders() and echo getContent() + * + * You must call this before headers are sent and it probably cannot be + * used in conjunction with zlib output buffering / mod_gzip. Errors are + * not handled purposefully. + */ + public function sendAll() + { + $this->sendHeaders(); + echo $this->_content; + } + + /** + * Determine the client's best encoding method from the HTTP Accept-Encoding + * header. + * + * If no Accept-Encoding header is set, or the browser is IE before v6 SP2, + * this will return ('', ''), the "identity" encoding. + * + * A syntax-aware scan is done of the Accept-Encoding, so the method must + * be non 0. The methods are favored in order of gzip, deflate, then + * compress. Deflate is always smallest and generally faster, but is + * rarely sent by servers, so client support could be buggier. + * + * @param bool $allowCompress allow the older compress encoding + * + * @param bool $allowDeflate allow the more recent deflate encoding + * + * @return array two values, 1st is the actual encoding method, 2nd is the + * alias of that method to use in the Content-Encoding header (some browsers + * call gzip "x-gzip" etc.) + */ + public static function getAcceptedEncoding($allowCompress = true, $allowDeflate = true) + { + // @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html + + if (! isset($_SERVER['HTTP_ACCEPT_ENCODING']) + || self::isBuggyIe()) + { + return array('', ''); + } + $ae = $_SERVER['HTTP_ACCEPT_ENCODING']; + // gzip checks (quick) + if (0 === strpos($ae, 'gzip,') // most browsers + || 0 === strpos($ae, 'deflate, gzip,') // opera + ) { + return array('gzip', 'gzip'); + } + // gzip checks (slow) + if (preg_match( + '@(?:^|,)\\s*((?:x-)?gzip)\\s*(?:$|,|;\\s*q=(?:0\\.|1))@' + ,$ae + ,$m)) { + return array('gzip', $m[1]); + } + if ($allowDeflate) { + // deflate checks + $aeRev = strrev($ae); + if (0 === strpos($aeRev, 'etalfed ,') // ie, webkit + || 0 === strpos($aeRev, 'etalfed,') // gecko + || 0 === strpos($ae, 'deflate,') // opera + // slow parsing + || preg_match( + '@(?:^|,)\\s*deflate\\s*(?:$|,|;\\s*q=(?:0\\.|1))@', $ae)) { + return array('deflate', 'deflate'); + } + } + if ($allowCompress && preg_match( + '@(?:^|,)\\s*((?:x-)?compress)\\s*(?:$|,|;\\s*q=(?:0\\.|1))@' + ,$ae + ,$m)) { + return array('compress', $m[1]); + } + return array('', ''); + } + + /** + * Encode (compress) the content + * + * If the encode method is '' (none) or compression level is 0, or the 'zlib' + * extension isn't loaded, we return false. + * + * Then the appropriate gz_* function is called to compress the content. If + * this fails, false is returned. + * + * The header "Vary: Accept-Encoding" is added. If encoding is successful, + * the Content-Length header is updated, and Content-Encoding is also added. + * + * @param int $compressionLevel given to zlib functions. If not given, the + * class default will be used. + * + * @return bool success true if the content was actually compressed + */ + public function encode($compressionLevel = null) + { + if (! self::isBuggyIe()) { + $this->_headers['Vary'] = 'Accept-Encoding'; + } + if (null === $compressionLevel) { + $compressionLevel = self::$compressionLevel; + } + if ('' === $this->_encodeMethod[0] + || ($compressionLevel == 0) + || !extension_loaded('zlib')) + { + return false; + } + if ($this->_encodeMethod[0] === 'deflate') { + $encoded = gzdeflate($this->_content, $compressionLevel); + } elseif ($this->_encodeMethod[0] === 'gzip') { + $encoded = gzencode($this->_content, $compressionLevel); + } else { + $encoded = gzcompress($this->_content, $compressionLevel); + } + if (false === $encoded) { + return false; + } + $this->_headers['Content-Length'] = $this->_useMbStrlen + ? (string)mb_strlen($encoded, '8bit') + : (string)strlen($encoded); + $this->_headers['Content-Encoding'] = $this->_encodeMethod[1]; + $this->_content = $encoded; + return true; + } + + /** + * Encode and send appropriate headers and content + * + * This is a convenience method for common use of the class + * + * @param string $content + * + * @param int $compressionLevel given to zlib functions. If not given, the + * class default will be used. + * + * @return bool success true if the content was actually compressed + */ + public static function output($content, $compressionLevel = null) + { + if (null === $compressionLevel) { + $compressionLevel = self::$compressionLevel; + } + $he = new HTTP_Encoder(array('content' => $content)); + $ret = $he->encode($compressionLevel); + $he->sendAll(); + return $ret; + } + + /** + * Is the browser an IE version earlier than 6 SP2? + * + * @return bool + */ + public static function isBuggyIe() + { + if (empty($_SERVER['HTTP_USER_AGENT'])) { + return false; + } + $ua = $_SERVER['HTTP_USER_AGENT']; + // quick escape for non-IEs + if (0 !== strpos($ua, 'Mozilla/4.0 (compatible; MSIE ') + || false !== strpos($ua, 'Opera')) { + return false; + } + // no regex = faaast + $version = (float)substr($ua, 30); + return self::$encodeToIe6 + ? ($version < 6 || ($version == 6 && false === strpos($ua, 'SV1'))) + : ($version < 7); + } + + protected $_content = ''; + protected $_headers = array(); + protected $_encodeMethod = array('', ''); + protected $_useMbStrlen = false; +} diff --git a/vendor/mrclay/minify/min/lib/JSMin.php b/vendor/mrclay/minify/min/lib/JSMin.php new file mode 100644 index 0000000000..9840d8b33d --- /dev/null +++ b/vendor/mrclay/minify/min/lib/JSMin.php @@ -0,0 +1,449 @@ + + * $minifiedJs = JSMin::minify($js); + * + * + * This is a modified port of jsmin.c. Improvements: + * + * Does not choke on some regexp literals containing quote characters. E.g. /'/ + * + * Spaces are preserved after some add/sub operators, so they are not mistakenly + * converted to post-inc/dec. E.g. a + ++b -> a+ ++b + * + * Preserves multi-line comments that begin with /*! + * + * PHP 5 or higher is required. + * + * Permission is hereby granted to use this version of the library under the + * same terms as jsmin.c, which has the following license: + * + * -- + * Copyright (c) 2002 Douglas Crockford (www.crockford.com) + * + * 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 shall be used for Good, not Evil. + * + * 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. + * -- + * + * @package JSMin + * @author Ryan Grove (PHP port) + * @author Steve Clay (modifications + cleanup) + * @author Andrea Giammarchi (spaceBeforeRegExp) + * @copyright 2002 Douglas Crockford (jsmin.c) + * @copyright 2008 Ryan Grove (PHP port) + * @license http://opensource.org/licenses/mit-license.php MIT License + * @link http://code.google.com/p/jsmin-php/ + */ + +class JSMin { + const ORD_LF = 10; + const ORD_SPACE = 32; + const ACTION_KEEP_A = 1; + const ACTION_DELETE_A = 2; + const ACTION_DELETE_A_B = 3; + + protected $a = "\n"; + protected $b = ''; + protected $input = ''; + protected $inputIndex = 0; + protected $inputLength = 0; + protected $lookAhead = null; + protected $output = ''; + protected $lastByteOut = ''; + protected $keptComment = ''; + + /** + * Minify Javascript. + * + * @param string $js Javascript to be minified + * + * @return string + */ + public static function minify($js) + { + $jsmin = new JSMin($js); + return $jsmin->min(); + } + + /** + * @param string $input + */ + public function __construct($input) + { + $this->input = $input; + } + + /** + * Perform minification, return result + * + * @return string + */ + public function min() + { + if ($this->output !== '') { // min already run + return $this->output; + } + + $mbIntEnc = null; + if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) { + $mbIntEnc = mb_internal_encoding(); + mb_internal_encoding('8bit'); + } + $this->input = str_replace("\r\n", "\n", $this->input); + $this->inputLength = strlen($this->input); + + $this->action(self::ACTION_DELETE_A_B); + + while ($this->a !== null) { + // determine next command + $command = self::ACTION_KEEP_A; // default + if ($this->a === ' ') { + if (($this->lastByteOut === '+' || $this->lastByteOut === '-') + && ($this->b === $this->lastByteOut)) { + // Don't delete this space. If we do, the addition/subtraction + // could be parsed as a post-increment + } elseif (! $this->isAlphaNum($this->b)) { + $command = self::ACTION_DELETE_A; + } + } elseif ($this->a === "\n") { + if ($this->b === ' ') { + $command = self::ACTION_DELETE_A_B; + + // in case of mbstring.func_overload & 2, must check for null b, + // otherwise mb_strpos will give WARNING + } elseif ($this->b === null + || (false === strpos('{[(+-!~', $this->b) + && ! $this->isAlphaNum($this->b))) { + $command = self::ACTION_DELETE_A; + } + } elseif (! $this->isAlphaNum($this->a)) { + if ($this->b === ' ' + || ($this->b === "\n" + && (false === strpos('}])+-"\'', $this->a)))) { + $command = self::ACTION_DELETE_A_B; + } + } + $this->action($command); + } + $this->output = trim($this->output); + + if ($mbIntEnc !== null) { + mb_internal_encoding($mbIntEnc); + } + return $this->output; + } + + /** + * ACTION_KEEP_A = Output A. Copy B to A. Get the next B. + * ACTION_DELETE_A = Copy B to A. Get the next B. + * ACTION_DELETE_A_B = Get the next B. + * + * @param int $command + * @throws JSMin_UnterminatedRegExpException|JSMin_UnterminatedStringException + */ + protected function action($command) + { + // make sure we don't compress "a + ++b" to "a+++b", etc. + if ($command === self::ACTION_DELETE_A_B + && $this->b === ' ' + && ($this->a === '+' || $this->a === '-')) { + // Note: we're at an addition/substraction operator; the inputIndex + // will certainly be a valid index + if ($this->input[$this->inputIndex] === $this->a) { + // This is "+ +" or "- -". Don't delete the space. + $command = self::ACTION_KEEP_A; + } + } + + switch ($command) { + case self::ACTION_KEEP_A: // 1 + $this->output .= $this->a; + + if ($this->keptComment) { + $this->output = rtrim($this->output, "\n"); + $this->output .= $this->keptComment; + $this->keptComment = ''; + } + + $this->lastByteOut = $this->a; + + // fallthrough intentional + case self::ACTION_DELETE_A: // 2 + $this->a = $this->b; + if ($this->a === "'" || $this->a === '"') { // string literal + $str = $this->a; // in case needed for exception + for(;;) { + $this->output .= $this->a; + $this->lastByteOut = $this->a; + + $this->a = $this->get(); + if ($this->a === $this->b) { // end quote + break; + } + if ($this->isEOF($this->a)) { + $byte = $this->inputIndex - 1; + throw new JSMin_UnterminatedStringException( + "JSMin: Unterminated String at byte {$byte}: {$str}"); + } + $str .= $this->a; + if ($this->a === '\\') { + $this->output .= $this->a; + $this->lastByteOut = $this->a; + + $this->a = $this->get(); + $str .= $this->a; + } + } + } + + // fallthrough intentional + case self::ACTION_DELETE_A_B: // 3 + $this->b = $this->next(); + if ($this->b === '/' && $this->isRegexpLiteral()) { + $this->output .= $this->a . $this->b; + $pattern = '/'; // keep entire pattern in case we need to report it in the exception + for(;;) { + $this->a = $this->get(); + $pattern .= $this->a; + if ($this->a === '[') { + for(;;) { + $this->output .= $this->a; + $this->a = $this->get(); + $pattern .= $this->a; + if ($this->a === ']') { + break; + } + if ($this->a === '\\') { + $this->output .= $this->a; + $this->a = $this->get(); + $pattern .= $this->a; + } + if ($this->isEOF($this->a)) { + throw new JSMin_UnterminatedRegExpException( + "JSMin: Unterminated set in RegExp at byte " + . $this->inputIndex .": {$pattern}"); + } + } + } + + if ($this->a === '/') { // end pattern + break; // while (true) + } elseif ($this->a === '\\') { + $this->output .= $this->a; + $this->a = $this->get(); + $pattern .= $this->a; + } elseif ($this->isEOF($this->a)) { + $byte = $this->inputIndex - 1; + throw new JSMin_UnterminatedRegExpException( + "JSMin: Unterminated RegExp at byte {$byte}: {$pattern}"); + } + $this->output .= $this->a; + $this->lastByteOut = $this->a; + } + $this->b = $this->next(); + } + // end case ACTION_DELETE_A_B + } + } + + /** + * @return bool + */ + protected function isRegexpLiteral() + { + if (false !== strpos("(,=:[!&|?+-~*{;", $this->a)) { + // we obviously aren't dividing + return true; + } + + // we have to check for a preceding keyword, and we don't need to pattern + // match over the whole output. + $recentOutput = substr($this->output, -10); + + // check if return/typeof directly precede a pattern without a space + foreach (array('return', 'typeof') as $keyword) { + if ($this->a !== substr($keyword, -1)) { + // certainly wasn't keyword + continue; + } + if (preg_match("~(^|[\\s\\S])" . substr($keyword, 0, -1) . "$~", $recentOutput, $m)) { + if ($m[1] === '' || !$this->isAlphaNum($m[1])) { + return true; + } + } + } + + // check all keywords + if ($this->a === ' ' || $this->a === "\n") { + if (preg_match('~(^|[\\s\\S])(?:case|else|in|return|typeof)$~', $recentOutput, $m)) { + if ($m[1] === '' || !$this->isAlphaNum($m[1])) { + return true; + } + } + } + + return false; + } + + /** + * Return the next character from stdin. Watch out for lookahead. If the character is a control character, + * translate it to a space or linefeed. + * + * @return string + */ + protected function get() + { + $c = $this->lookAhead; + $this->lookAhead = null; + if ($c === null) { + // getc(stdin) + if ($this->inputIndex < $this->inputLength) { + $c = $this->input[$this->inputIndex]; + $this->inputIndex += 1; + } else { + $c = null; + } + } + if (ord($c) >= self::ORD_SPACE || $c === "\n" || $c === null) { + return $c; + } + if ($c === "\r") { + return "\n"; + } + return ' '; + } + + /** + * Does $a indicate end of input? + * + * @param string $a + * @return bool + */ + protected function isEOF($a) + { + return ord($a) <= self::ORD_LF; + } + + /** + * Get next char (without getting it). If is ctrl character, translate to a space or newline. + * + * @return string + */ + protected function peek() + { + $this->lookAhead = $this->get(); + return $this->lookAhead; + } + + /** + * Return true if the character is a letter, digit, underscore, dollar sign, or non-ASCII character. + * + * @param string $c + * + * @return bool + */ + protected function isAlphaNum($c) + { + return (preg_match('/^[a-z0-9A-Z_\\$\\\\]$/', $c) || ord($c) > 126); + } + + /** + * Consume a single line comment from input (possibly retaining it) + */ + protected function consumeSingleLineComment() + { + $comment = ''; + while (true) { + $get = $this->get(); + $comment .= $get; + if (ord($get) <= self::ORD_LF) { // end of line reached + // if IE conditional comment + if (preg_match('/^\\/@(?:cc_on|if|elif|else|end)\\b/', $comment)) { + $this->keptComment .= "/{$comment}"; + } + return; + } + } + } + + /** + * Consume a multiple line comment from input (possibly retaining it) + * + * @throws JSMin_UnterminatedCommentException + */ + protected function consumeMultipleLineComment() + { + $this->get(); + $comment = ''; + for(;;) { + $get = $this->get(); + if ($get === '*') { + if ($this->peek() === '/') { // end of comment reached + $this->get(); + if (0 === strpos($comment, '!')) { + // preserved by YUI Compressor + if (!$this->keptComment) { + // don't prepend a newline if two comments right after one another + $this->keptComment = "\n"; + } + $this->keptComment .= "/*!" . substr($comment, 1) . "*/\n"; + } else if (preg_match('/^@(?:cc_on|if|elif|else|end)\\b/', $comment)) { + // IE conditional + $this->keptComment .= "/*{$comment}*/"; + } + return; + } + } elseif ($get === null) { + throw new JSMin_UnterminatedCommentException( + "JSMin: Unterminated comment at byte {$this->inputIndex}: /*{$comment}"); + } + $comment .= $get; + } + } + + /** + * Get the next character, skipping over comments. Some comments may be preserved. + * + * @return string + */ + protected function next() + { + $get = $this->get(); + if ($get === '/') { + switch ($this->peek()) { + case '/': + $this->consumeSingleLineComment(); + $get = "\n"; + break; + case '*': + $this->consumeMultipleLineComment(); + $get = ' '; + break; + } + } + return $get; + } +} + +class JSMin_UnterminatedStringException extends Exception {} +class JSMin_UnterminatedCommentException extends Exception {} +class JSMin_UnterminatedRegExpException extends Exception {} diff --git a/vendor/mrclay/minify/min/lib/JSMinPlus.php b/vendor/mrclay/minify/min/lib/JSMinPlus.php new file mode 100644 index 0000000000..5a3c5bdff4 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/JSMinPlus.php @@ -0,0 +1,2086 @@ + + * + * Usage: $minified = JSMinPlus::minify($script [, $filename]) + * + * Versionlog (see also changelog.txt): + * 23-07-2011 - remove dynamic creation of OP_* and KEYWORD_* defines and declare them on top + * reduce memory footprint by minifying by block-scope + * some small byte-saving and performance improvements + * 12-05-2009 - fixed hook:colon precedence, fixed empty body in loop and if-constructs + * 18-04-2009 - fixed crashbug in PHP 5.2.9 and several other bugfixes + * 12-04-2009 - some small bugfixes and performance improvements + * 09-04-2009 - initial open sourced version 1.0 + * + * Latest version of this script: http://files.tweakers.net/jsminplus/jsminplus.zip + * + */ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Narcissus JavaScript engine. + * + * The Initial Developer of the Original Code is + * Brendan Eich . + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): Tino Zijdel + * PHP port, modifications and minifier routine are (C) 2009-2011 + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +define('TOKEN_END', 1); +define('TOKEN_NUMBER', 2); +define('TOKEN_IDENTIFIER', 3); +define('TOKEN_STRING', 4); +define('TOKEN_REGEXP', 5); +define('TOKEN_NEWLINE', 6); +define('TOKEN_CONDCOMMENT_START', 7); +define('TOKEN_CONDCOMMENT_END', 8); + +define('JS_SCRIPT', 100); +define('JS_BLOCK', 101); +define('JS_LABEL', 102); +define('JS_FOR_IN', 103); +define('JS_CALL', 104); +define('JS_NEW_WITH_ARGS', 105); +define('JS_INDEX', 106); +define('JS_ARRAY_INIT', 107); +define('JS_OBJECT_INIT', 108); +define('JS_PROPERTY_INIT', 109); +define('JS_GETTER', 110); +define('JS_SETTER', 111); +define('JS_GROUP', 112); +define('JS_LIST', 113); + +define('JS_MINIFIED', 999); + +define('DECLARED_FORM', 0); +define('EXPRESSED_FORM', 1); +define('STATEMENT_FORM', 2); + +/* Operators */ +define('OP_SEMICOLON', ';'); +define('OP_COMMA', ','); +define('OP_HOOK', '?'); +define('OP_COLON', ':'); +define('OP_OR', '||'); +define('OP_AND', '&&'); +define('OP_BITWISE_OR', '|'); +define('OP_BITWISE_XOR', '^'); +define('OP_BITWISE_AND', '&'); +define('OP_STRICT_EQ', '==='); +define('OP_EQ', '=='); +define('OP_ASSIGN', '='); +define('OP_STRICT_NE', '!=='); +define('OP_NE', '!='); +define('OP_LSH', '<<'); +define('OP_LE', '<='); +define('OP_LT', '<'); +define('OP_URSH', '>>>'); +define('OP_RSH', '>>'); +define('OP_GE', '>='); +define('OP_GT', '>'); +define('OP_INCREMENT', '++'); +define('OP_DECREMENT', '--'); +define('OP_PLUS', '+'); +define('OP_MINUS', '-'); +define('OP_MUL', '*'); +define('OP_DIV', '/'); +define('OP_MOD', '%'); +define('OP_NOT', '!'); +define('OP_BITWISE_NOT', '~'); +define('OP_DOT', '.'); +define('OP_LEFT_BRACKET', '['); +define('OP_RIGHT_BRACKET', ']'); +define('OP_LEFT_CURLY', '{'); +define('OP_RIGHT_CURLY', '}'); +define('OP_LEFT_PAREN', '('); +define('OP_RIGHT_PAREN', ')'); +define('OP_CONDCOMMENT_END', '@*/'); + +define('OP_UNARY_PLUS', 'U+'); +define('OP_UNARY_MINUS', 'U-'); + +/* Keywords */ +define('KEYWORD_BREAK', 'break'); +define('KEYWORD_CASE', 'case'); +define('KEYWORD_CATCH', 'catch'); +define('KEYWORD_CONST', 'const'); +define('KEYWORD_CONTINUE', 'continue'); +define('KEYWORD_DEBUGGER', 'debugger'); +define('KEYWORD_DEFAULT', 'default'); +define('KEYWORD_DELETE', 'delete'); +define('KEYWORD_DO', 'do'); +define('KEYWORD_ELSE', 'else'); +define('KEYWORD_ENUM', 'enum'); +define('KEYWORD_FALSE', 'false'); +define('KEYWORD_FINALLY', 'finally'); +define('KEYWORD_FOR', 'for'); +define('KEYWORD_FUNCTION', 'function'); +define('KEYWORD_IF', 'if'); +define('KEYWORD_IN', 'in'); +define('KEYWORD_INSTANCEOF', 'instanceof'); +define('KEYWORD_NEW', 'new'); +define('KEYWORD_NULL', 'null'); +define('KEYWORD_RETURN', 'return'); +define('KEYWORD_SWITCH', 'switch'); +define('KEYWORD_THIS', 'this'); +define('KEYWORD_THROW', 'throw'); +define('KEYWORD_TRUE', 'true'); +define('KEYWORD_TRY', 'try'); +define('KEYWORD_TYPEOF', 'typeof'); +define('KEYWORD_VAR', 'var'); +define('KEYWORD_VOID', 'void'); +define('KEYWORD_WHILE', 'while'); +define('KEYWORD_WITH', 'with'); + + +class JSMinPlus +{ + private $parser; + private $reserved = array( + 'break', 'case', 'catch', 'continue', 'default', 'delete', 'do', + 'else', 'finally', 'for', 'function', 'if', 'in', 'instanceof', + 'new', 'return', 'switch', 'this', 'throw', 'try', 'typeof', 'var', + 'void', 'while', 'with', + // Words reserved for future use + 'abstract', 'boolean', 'byte', 'char', 'class', 'const', 'debugger', + 'double', 'enum', 'export', 'extends', 'final', 'float', 'goto', + 'implements', 'import', 'int', 'interface', 'long', 'native', + 'package', 'private', 'protected', 'public', 'short', 'static', + 'super', 'synchronized', 'throws', 'transient', 'volatile', + // These are not reserved, but should be taken into account + // in isValidIdentifier (See jslint source code) + 'arguments', 'eval', 'true', 'false', 'Infinity', 'NaN', 'null', 'undefined' + ); + + private function __construct() + { + $this->parser = new JSParser($this); + } + + public static function minify($js, $filename='') + { + static $instance; + + // this is a singleton + if(!$instance) + $instance = new JSMinPlus(); + + return $instance->min($js, $filename); + } + + private function min($js, $filename) + { + try + { + $n = $this->parser->parse($js, $filename, 1); + return $this->parseTree($n); + } + catch(Exception $e) + { + echo $e->getMessage() . "\n"; + } + + return false; + } + + public function parseTree($n, $noBlockGrouping = false) + { + $s = ''; + + switch ($n->type) + { + case JS_MINIFIED: + $s = $n->value; + break; + + case JS_SCRIPT: + // we do nothing yet with funDecls or varDecls + $noBlockGrouping = true; + // FALL THROUGH + + case JS_BLOCK: + $childs = $n->treeNodes; + $lastType = 0; + for ($c = 0, $i = 0, $j = count($childs); $i < $j; $i++) + { + $type = $childs[$i]->type; + $t = $this->parseTree($childs[$i]); + if (strlen($t)) + { + if ($c) + { + $s = rtrim($s, ';'); + + if ($type == KEYWORD_FUNCTION && $childs[$i]->functionForm == DECLARED_FORM) + { + // put declared functions on a new line + $s .= "\n"; + } + elseif ($type == KEYWORD_VAR && $type == $lastType) + { + // mutiple var-statements can go into one + $t = ',' . substr($t, 4); + } + else + { + // add terminator + $s .= ';'; + } + } + + $s .= $t; + + $c++; + $lastType = $type; + } + } + + if ($c > 1 && !$noBlockGrouping) + { + $s = '{' . $s . '}'; + } + break; + + case KEYWORD_FUNCTION: + $s .= 'function' . ($n->name ? ' ' . $n->name : '') . '('; + $params = $n->params; + for ($i = 0, $j = count($params); $i < $j; $i++) + $s .= ($i ? ',' : '') . $params[$i]; + $s .= '){' . $this->parseTree($n->body, true) . '}'; + break; + + case KEYWORD_IF: + $s = 'if(' . $this->parseTree($n->condition) . ')'; + $thenPart = $this->parseTree($n->thenPart); + $elsePart = $n->elsePart ? $this->parseTree($n->elsePart) : null; + + // empty if-statement + if ($thenPart == '') + $thenPart = ';'; + + if ($elsePart) + { + // be carefull and always make a block out of the thenPart; could be more optimized but is a lot of trouble + if ($thenPart != ';' && $thenPart[0] != '{') + $thenPart = '{' . $thenPart . '}'; + + $s .= $thenPart . 'else'; + + // we could check for more, but that hardly ever applies so go for performance + if ($elsePart[0] != '{') + $s .= ' '; + + $s .= $elsePart; + } + else + { + $s .= $thenPart; + } + break; + + case KEYWORD_SWITCH: + $s = 'switch(' . $this->parseTree($n->discriminant) . '){'; + $cases = $n->cases; + for ($i = 0, $j = count($cases); $i < $j; $i++) + { + $case = $cases[$i]; + if ($case->type == KEYWORD_CASE) + $s .= 'case' . ($case->caseLabel->type != TOKEN_STRING ? ' ' : '') . $this->parseTree($case->caseLabel) . ':'; + else + $s .= 'default:'; + + $statement = $this->parseTree($case->statements, true); + if ($statement) + { + $s .= $statement; + // no terminator for last statement + if ($i + 1 < $j) + $s .= ';'; + } + } + $s .= '}'; + break; + + case KEYWORD_FOR: + $s = 'for(' . ($n->setup ? $this->parseTree($n->setup) : '') + . ';' . ($n->condition ? $this->parseTree($n->condition) : '') + . ';' . ($n->update ? $this->parseTree($n->update) : '') . ')'; + + $body = $this->parseTree($n->body); + if ($body == '') + $body = ';'; + + $s .= $body; + break; + + case KEYWORD_WHILE: + $s = 'while(' . $this->parseTree($n->condition) . ')'; + + $body = $this->parseTree($n->body); + if ($body == '') + $body = ';'; + + $s .= $body; + break; + + case JS_FOR_IN: + $s = 'for(' . ($n->varDecl ? $this->parseTree($n->varDecl) : $this->parseTree($n->iterator)) . ' in ' . $this->parseTree($n->object) . ')'; + + $body = $this->parseTree($n->body); + if ($body == '') + $body = ';'; + + $s .= $body; + break; + + case KEYWORD_DO: + $s = 'do{' . $this->parseTree($n->body, true) . '}while(' . $this->parseTree($n->condition) . ')'; + break; + + case KEYWORD_BREAK: + case KEYWORD_CONTINUE: + $s = $n->value . ($n->label ? ' ' . $n->label : ''); + break; + + case KEYWORD_TRY: + $s = 'try{' . $this->parseTree($n->tryBlock, true) . '}'; + $catchClauses = $n->catchClauses; + for ($i = 0, $j = count($catchClauses); $i < $j; $i++) + { + $t = $catchClauses[$i]; + $s .= 'catch(' . $t->varName . ($t->guard ? ' if ' . $this->parseTree($t->guard) : '') . '){' . $this->parseTree($t->block, true) . '}'; + } + if ($n->finallyBlock) + $s .= 'finally{' . $this->parseTree($n->finallyBlock, true) . '}'; + break; + + case KEYWORD_THROW: + case KEYWORD_RETURN: + $s = $n->type; + if ($n->value) + { + $t = $this->parseTree($n->value); + if (strlen($t)) + { + if ($this->isWordChar($t[0]) || $t[0] == '\\') + $s .= ' '; + + $s .= $t; + } + } + break; + + case KEYWORD_WITH: + $s = 'with(' . $this->parseTree($n->object) . ')' . $this->parseTree($n->body); + break; + + case KEYWORD_VAR: + case KEYWORD_CONST: + $s = $n->value . ' '; + $childs = $n->treeNodes; + for ($i = 0, $j = count($childs); $i < $j; $i++) + { + $t = $childs[$i]; + $s .= ($i ? ',' : '') . $t->name; + $u = $t->initializer; + if ($u) + $s .= '=' . $this->parseTree($u); + } + break; + + case KEYWORD_IN: + case KEYWORD_INSTANCEOF: + $left = $this->parseTree($n->treeNodes[0]); + $right = $this->parseTree($n->treeNodes[1]); + + $s = $left; + + if ($this->isWordChar(substr($left, -1))) + $s .= ' '; + + $s .= $n->type; + + if ($this->isWordChar($right[0]) || $right[0] == '\\') + $s .= ' '; + + $s .= $right; + break; + + case KEYWORD_DELETE: + case KEYWORD_TYPEOF: + $right = $this->parseTree($n->treeNodes[0]); + + $s = $n->type; + + if ($this->isWordChar($right[0]) || $right[0] == '\\') + $s .= ' '; + + $s .= $right; + break; + + case KEYWORD_VOID: + $s = 'void(' . $this->parseTree($n->treeNodes[0]) . ')'; + break; + + case KEYWORD_DEBUGGER: + throw new Exception('NOT IMPLEMENTED: DEBUGGER'); + break; + + case TOKEN_CONDCOMMENT_START: + case TOKEN_CONDCOMMENT_END: + $s = $n->value . ($n->type == TOKEN_CONDCOMMENT_START ? ' ' : ''); + $childs = $n->treeNodes; + for ($i = 0, $j = count($childs); $i < $j; $i++) + $s .= $this->parseTree($childs[$i]); + break; + + case OP_SEMICOLON: + if ($expression = $n->expression) + $s = $this->parseTree($expression); + break; + + case JS_LABEL: + $s = $n->label . ':' . $this->parseTree($n->statement); + break; + + case OP_COMMA: + $childs = $n->treeNodes; + for ($i = 0, $j = count($childs); $i < $j; $i++) + $s .= ($i ? ',' : '') . $this->parseTree($childs[$i]); + break; + + case OP_ASSIGN: + $s = $this->parseTree($n->treeNodes[0]) . $n->value . $this->parseTree($n->treeNodes[1]); + break; + + case OP_HOOK: + $s = $this->parseTree($n->treeNodes[0]) . '?' . $this->parseTree($n->treeNodes[1]) . ':' . $this->parseTree($n->treeNodes[2]); + break; + + case OP_OR: case OP_AND: + case OP_BITWISE_OR: case OP_BITWISE_XOR: case OP_BITWISE_AND: + case OP_EQ: case OP_NE: case OP_STRICT_EQ: case OP_STRICT_NE: + case OP_LT: case OP_LE: case OP_GE: case OP_GT: + case OP_LSH: case OP_RSH: case OP_URSH: + case OP_MUL: case OP_DIV: case OP_MOD: + $s = $this->parseTree($n->treeNodes[0]) . $n->type . $this->parseTree($n->treeNodes[1]); + break; + + case OP_PLUS: + case OP_MINUS: + $left = $this->parseTree($n->treeNodes[0]); + $right = $this->parseTree($n->treeNodes[1]); + + switch ($n->treeNodes[1]->type) + { + case OP_PLUS: + case OP_MINUS: + case OP_INCREMENT: + case OP_DECREMENT: + case OP_UNARY_PLUS: + case OP_UNARY_MINUS: + $s = $left . $n->type . ' ' . $right; + break; + + case TOKEN_STRING: + //combine concatted strings with same quotestyle + if ($n->type == OP_PLUS && substr($left, -1) == $right[0]) + { + $s = substr($left, 0, -1) . substr($right, 1); + break; + } + // FALL THROUGH + + default: + $s = $left . $n->type . $right; + } + break; + + case OP_NOT: + case OP_BITWISE_NOT: + case OP_UNARY_PLUS: + case OP_UNARY_MINUS: + $s = $n->value . $this->parseTree($n->treeNodes[0]); + break; + + case OP_INCREMENT: + case OP_DECREMENT: + if ($n->postfix) + $s = $this->parseTree($n->treeNodes[0]) . $n->value; + else + $s = $n->value . $this->parseTree($n->treeNodes[0]); + break; + + case OP_DOT: + $s = $this->parseTree($n->treeNodes[0]) . '.' . $this->parseTree($n->treeNodes[1]); + break; + + case JS_INDEX: + $s = $this->parseTree($n->treeNodes[0]); + // See if we can replace named index with a dot saving 3 bytes + if ( $n->treeNodes[0]->type == TOKEN_IDENTIFIER && + $n->treeNodes[1]->type == TOKEN_STRING && + $this->isValidIdentifier(substr($n->treeNodes[1]->value, 1, -1)) + ) + $s .= '.' . substr($n->treeNodes[1]->value, 1, -1); + else + $s .= '[' . $this->parseTree($n->treeNodes[1]) . ']'; + break; + + case JS_LIST: + $childs = $n->treeNodes; + for ($i = 0, $j = count($childs); $i < $j; $i++) + $s .= ($i ? ',' : '') . $this->parseTree($childs[$i]); + break; + + case JS_CALL: + $s = $this->parseTree($n->treeNodes[0]) . '(' . $this->parseTree($n->treeNodes[1]) . ')'; + break; + + case KEYWORD_NEW: + case JS_NEW_WITH_ARGS: + $s = 'new ' . $this->parseTree($n->treeNodes[0]) . '(' . ($n->type == JS_NEW_WITH_ARGS ? $this->parseTree($n->treeNodes[1]) : '') . ')'; + break; + + case JS_ARRAY_INIT: + $s = '['; + $childs = $n->treeNodes; + for ($i = 0, $j = count($childs); $i < $j; $i++) + { + $s .= ($i ? ',' : '') . $this->parseTree($childs[$i]); + } + $s .= ']'; + break; + + case JS_OBJECT_INIT: + $s = '{'; + $childs = $n->treeNodes; + for ($i = 0, $j = count($childs); $i < $j; $i++) + { + $t = $childs[$i]; + if ($i) + $s .= ','; + if ($t->type == JS_PROPERTY_INIT) + { + // Ditch the quotes when the index is a valid identifier + if ( $t->treeNodes[0]->type == TOKEN_STRING && + $this->isValidIdentifier(substr($t->treeNodes[0]->value, 1, -1)) + ) + $s .= substr($t->treeNodes[0]->value, 1, -1); + else + $s .= $t->treeNodes[0]->value; + + $s .= ':' . $this->parseTree($t->treeNodes[1]); + } + else + { + $s .= $t->type == JS_GETTER ? 'get' : 'set'; + $s .= ' ' . $t->name . '('; + $params = $t->params; + for ($i = 0, $j = count($params); $i < $j; $i++) + $s .= ($i ? ',' : '') . $params[$i]; + $s .= '){' . $this->parseTree($t->body, true) . '}'; + } + } + $s .= '}'; + break; + + case TOKEN_NUMBER: + $s = $n->value; + if (preg_match('/^([1-9]+)(0{3,})$/', $s, $m)) + $s = $m[1] . 'e' . strlen($m[2]); + break; + + case KEYWORD_NULL: case KEYWORD_THIS: case KEYWORD_TRUE: case KEYWORD_FALSE: + case TOKEN_IDENTIFIER: case TOKEN_STRING: case TOKEN_REGEXP: + $s = $n->value; + break; + + case JS_GROUP: + if (in_array( + $n->treeNodes[0]->type, + array( + JS_ARRAY_INIT, JS_OBJECT_INIT, JS_GROUP, + TOKEN_NUMBER, TOKEN_STRING, TOKEN_REGEXP, TOKEN_IDENTIFIER, + KEYWORD_NULL, KEYWORD_THIS, KEYWORD_TRUE, KEYWORD_FALSE + ) + )) + { + $s = $this->parseTree($n->treeNodes[0]); + } + else + { + $s = '(' . $this->parseTree($n->treeNodes[0]) . ')'; + } + break; + + default: + throw new Exception('UNKNOWN TOKEN TYPE: ' . $n->type); + } + + return $s; + } + + private function isValidIdentifier($string) + { + return preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $string) && !in_array($string, $this->reserved); + } + + private function isWordChar($char) + { + return $char == '_' || $char == '$' || ctype_alnum($char); + } +} + +class JSParser +{ + private $t; + private $minifier; + + private $opPrecedence = array( + ';' => 0, + ',' => 1, + '=' => 2, '?' => 2, ':' => 2, + // The above all have to have the same precedence, see bug 330975 + '||' => 4, + '&&' => 5, + '|' => 6, + '^' => 7, + '&' => 8, + '==' => 9, '!=' => 9, '===' => 9, '!==' => 9, + '<' => 10, '<=' => 10, '>=' => 10, '>' => 10, 'in' => 10, 'instanceof' => 10, + '<<' => 11, '>>' => 11, '>>>' => 11, + '+' => 12, '-' => 12, + '*' => 13, '/' => 13, '%' => 13, + 'delete' => 14, 'void' => 14, 'typeof' => 14, + '!' => 14, '~' => 14, 'U+' => 14, 'U-' => 14, + '++' => 15, '--' => 15, + 'new' => 16, + '.' => 17, + JS_NEW_WITH_ARGS => 0, JS_INDEX => 0, JS_CALL => 0, + JS_ARRAY_INIT => 0, JS_OBJECT_INIT => 0, JS_GROUP => 0 + ); + + private $opArity = array( + ',' => -2, + '=' => 2, + '?' => 3, + '||' => 2, + '&&' => 2, + '|' => 2, + '^' => 2, + '&' => 2, + '==' => 2, '!=' => 2, '===' => 2, '!==' => 2, + '<' => 2, '<=' => 2, '>=' => 2, '>' => 2, 'in' => 2, 'instanceof' => 2, + '<<' => 2, '>>' => 2, '>>>' => 2, + '+' => 2, '-' => 2, + '*' => 2, '/' => 2, '%' => 2, + 'delete' => 1, 'void' => 1, 'typeof' => 1, + '!' => 1, '~' => 1, 'U+' => 1, 'U-' => 1, + '++' => 1, '--' => 1, + 'new' => 1, + '.' => 2, + JS_NEW_WITH_ARGS => 2, JS_INDEX => 2, JS_CALL => 2, + JS_ARRAY_INIT => 1, JS_OBJECT_INIT => 1, JS_GROUP => 1, + TOKEN_CONDCOMMENT_START => 1, TOKEN_CONDCOMMENT_END => 1 + ); + + public function __construct($minifier=null) + { + $this->minifier = $minifier; + $this->t = new JSTokenizer(); + } + + public function parse($s, $f, $l) + { + // initialize tokenizer + $this->t->init($s, $f, $l); + + $x = new JSCompilerContext(false); + $n = $this->Script($x); + if (!$this->t->isDone()) + throw $this->t->newSyntaxError('Syntax error'); + + return $n; + } + + private function Script($x) + { + $n = $this->Statements($x); + $n->type = JS_SCRIPT; + $n->funDecls = $x->funDecls; + $n->varDecls = $x->varDecls; + + // minify by scope + if ($this->minifier) + { + $n->value = $this->minifier->parseTree($n); + + // clear tree from node to save memory + $n->treeNodes = null; + $n->funDecls = null; + $n->varDecls = null; + + $n->type = JS_MINIFIED; + } + + return $n; + } + + private function Statements($x) + { + $n = new JSNode($this->t, JS_BLOCK); + array_push($x->stmtStack, $n); + + while (!$this->t->isDone() && $this->t->peek() != OP_RIGHT_CURLY) + $n->addNode($this->Statement($x)); + + array_pop($x->stmtStack); + + return $n; + } + + private function Block($x) + { + $this->t->mustMatch(OP_LEFT_CURLY); + $n = $this->Statements($x); + $this->t->mustMatch(OP_RIGHT_CURLY); + + return $n; + } + + private function Statement($x) + { + $tt = $this->t->get(); + $n2 = null; + + // Cases for statements ending in a right curly return early, avoiding the + // common semicolon insertion magic after this switch. + switch ($tt) + { + case KEYWORD_FUNCTION: + return $this->FunctionDefinition( + $x, + true, + count($x->stmtStack) > 1 ? STATEMENT_FORM : DECLARED_FORM + ); + break; + + case OP_LEFT_CURLY: + $n = $this->Statements($x); + $this->t->mustMatch(OP_RIGHT_CURLY); + return $n; + + case KEYWORD_IF: + $n = new JSNode($this->t); + $n->condition = $this->ParenExpression($x); + array_push($x->stmtStack, $n); + $n->thenPart = $this->Statement($x); + $n->elsePart = $this->t->match(KEYWORD_ELSE) ? $this->Statement($x) : null; + array_pop($x->stmtStack); + return $n; + + case KEYWORD_SWITCH: + $n = new JSNode($this->t); + $this->t->mustMatch(OP_LEFT_PAREN); + $n->discriminant = $this->Expression($x); + $this->t->mustMatch(OP_RIGHT_PAREN); + $n->cases = array(); + $n->defaultIndex = -1; + + array_push($x->stmtStack, $n); + + $this->t->mustMatch(OP_LEFT_CURLY); + + while (($tt = $this->t->get()) != OP_RIGHT_CURLY) + { + switch ($tt) + { + case KEYWORD_DEFAULT: + if ($n->defaultIndex >= 0) + throw $this->t->newSyntaxError('More than one switch default'); + // FALL THROUGH + case KEYWORD_CASE: + $n2 = new JSNode($this->t); + if ($tt == KEYWORD_DEFAULT) + $n->defaultIndex = count($n->cases); + else + $n2->caseLabel = $this->Expression($x, OP_COLON); + break; + default: + throw $this->t->newSyntaxError('Invalid switch case'); + } + + $this->t->mustMatch(OP_COLON); + $n2->statements = new JSNode($this->t, JS_BLOCK); + while (($tt = $this->t->peek()) != KEYWORD_CASE && $tt != KEYWORD_DEFAULT && $tt != OP_RIGHT_CURLY) + $n2->statements->addNode($this->Statement($x)); + + array_push($n->cases, $n2); + } + + array_pop($x->stmtStack); + return $n; + + case KEYWORD_FOR: + $n = new JSNode($this->t); + $n->isLoop = true; + $this->t->mustMatch(OP_LEFT_PAREN); + + if (($tt = $this->t->peek()) != OP_SEMICOLON) + { + $x->inForLoopInit = true; + if ($tt == KEYWORD_VAR || $tt == KEYWORD_CONST) + { + $this->t->get(); + $n2 = $this->Variables($x); + } + else + { + $n2 = $this->Expression($x); + } + $x->inForLoopInit = false; + } + + if ($n2 && $this->t->match(KEYWORD_IN)) + { + $n->type = JS_FOR_IN; + if ($n2->type == KEYWORD_VAR) + { + if (count($n2->treeNodes) != 1) + { + throw $this->t->SyntaxError( + 'Invalid for..in left-hand side', + $this->t->filename, + $n2->lineno + ); + } + + // NB: n2[0].type == IDENTIFIER and n2[0].value == n2[0].name. + $n->iterator = $n2->treeNodes[0]; + $n->varDecl = $n2; + } + else + { + $n->iterator = $n2; + $n->varDecl = null; + } + + $n->object = $this->Expression($x); + } + else + { + $n->setup = $n2 ? $n2 : null; + $this->t->mustMatch(OP_SEMICOLON); + $n->condition = $this->t->peek() == OP_SEMICOLON ? null : $this->Expression($x); + $this->t->mustMatch(OP_SEMICOLON); + $n->update = $this->t->peek() == OP_RIGHT_PAREN ? null : $this->Expression($x); + } + + $this->t->mustMatch(OP_RIGHT_PAREN); + $n->body = $this->nest($x, $n); + return $n; + + case KEYWORD_WHILE: + $n = new JSNode($this->t); + $n->isLoop = true; + $n->condition = $this->ParenExpression($x); + $n->body = $this->nest($x, $n); + return $n; + + case KEYWORD_DO: + $n = new JSNode($this->t); + $n->isLoop = true; + $n->body = $this->nest($x, $n, KEYWORD_WHILE); + $n->condition = $this->ParenExpression($x); + if (!$x->ecmaStrictMode) + { + // "; + * $link = ""; + * + * // in min.php + * Minify::serve('Groups', array( + * 'groups' => $groupSources + * ,'setExpires' => (time() + 86400 * 365) + * )); + * + * + * @package Minify + * @author Stephen Clay + */ +class Minify_Build { + + /** + * Last modification time of all files in the build + * + * @var int + */ + public $lastModified = 0; + + /** + * String to use as ampersand in uri(). Set this to '&' if + * you are not HTML-escaping URIs. + * + * @var string + */ + public static $ampersand = '&'; + + /** + * Get a time-stamped URI + * + * + * echo $b->uri('/site.js'); + * // outputs "/site.js?1678242" + * + * echo $b->uri('/scriptaculous.js?load=effects'); + * // outputs "/scriptaculous.js?load=effects&1678242" + * + * + * @param string $uri + * @param boolean $forceAmpersand (default = false) Force the use of ampersand to + * append the timestamp to the URI. + * @return string + */ + public function uri($uri, $forceAmpersand = false) { + $sep = ($forceAmpersand || strpos($uri, '?') !== false) + ? self::$ampersand + : '?'; + return "{$uri}{$sep}{$this->lastModified}"; + } + + /** + * Create a build object + * + * @param array $sources array of Minify_Source objects and/or file paths + * + * @return null + */ + public function __construct($sources) + { + $max = 0; + foreach ((array)$sources as $source) { + if ($source instanceof Minify_Source) { + $max = max($max, $source->lastModified); + } elseif (is_string($source)) { + if (0 === strpos($source, '//')) { + $source = $_SERVER['DOCUMENT_ROOT'] . substr($source, 1); + } + if (is_file($source)) { + $max = max($max, filemtime($source)); + } + } + } + $this->lastModified = $max; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/CSS.php b/vendor/mrclay/minify/min/lib/Minify/CSS.php new file mode 100644 index 0000000000..32414551d9 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/CSS.php @@ -0,0 +1,99 @@ + + * @author http://code.google.com/u/1stvamp/ (Issue 64 patch) + */ +class Minify_CSS { + + /** + * Minify a CSS string + * + * @param string $css + * + * @param array $options available options: + * + * 'preserveComments': (default true) multi-line comments that begin + * with "/*!" will be preserved with newlines before and after to + * enhance readability. + * + * 'removeCharsets': (default true) remove all @charset at-rules + * + * 'prependRelativePath': (default null) if given, this string will be + * prepended to all relative URIs in import/url declarations + * + * 'currentDir': (default null) if given, this is assumed to be the + * directory of the current CSS file. Using this, minify will rewrite + * all relative URIs in import/url declarations to correctly point to + * the desired files. For this to work, the files *must* exist and be + * visible by the PHP process. + * + * 'symlinks': (default = array()) If the CSS file is stored in + * a symlink-ed directory, provide an array of link paths to + * target paths, where the link paths are within the document root. Because + * paths need to be normalized for this to work, use "//" to substitute + * the doc root in the link paths (the array keys). E.g.: + * + * array('//symlink' => '/real/target/path') // unix + * array('//static' => 'D:\\staticStorage') // Windows + * + * + * 'docRoot': (default = $_SERVER['DOCUMENT_ROOT']) + * see Minify_CSS_UriRewriter::rewrite + * + * @return string + */ + public static function minify($css, $options = array()) + { + $options = array_merge(array( + 'compress' => true, + 'removeCharsets' => true, + 'preserveComments' => true, + 'currentDir' => null, + 'docRoot' => $_SERVER['DOCUMENT_ROOT'], + 'prependRelativePath' => null, + 'symlinks' => array(), + ), $options); + + if ($options['removeCharsets']) { + $css = preg_replace('/@charset[^;]+;\\s*/', '', $css); + } + if ($options['compress']) { + if (! $options['preserveComments']) { + $css = Minify_CSS_Compressor::process($css, $options); + } else { + $css = Minify_CommentPreserver::process( + $css + ,array('Minify_CSS_Compressor', 'process') + ,array($options) + ); + } + } + if (! $options['currentDir'] && ! $options['prependRelativePath']) { + return $css; + } + if ($options['currentDir']) { + return Minify_CSS_UriRewriter::rewrite( + $css + ,$options['currentDir'] + ,$options['docRoot'] + ,$options['symlinks'] + ); + } else { + return Minify_CSS_UriRewriter::prepend( + $css + ,$options['prependRelativePath'] + ); + } + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/CSS/Compressor.php b/vendor/mrclay/minify/min/lib/Minify/CSS/Compressor.php new file mode 100644 index 0000000000..c6cdd8b7a6 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/CSS/Compressor.php @@ -0,0 +1,249 @@ + + * @author http://code.google.com/u/1stvamp/ (Issue 64 patch) + */ +class Minify_CSS_Compressor { + + /** + * Minify a CSS string + * + * @param string $css + * + * @param array $options (currently ignored) + * + * @return string + */ + public static function process($css, $options = array()) + { + $obj = new Minify_CSS_Compressor($options); + return $obj->_process($css); + } + + /** + * @var array + */ + protected $_options = null; + + /** + * Are we "in" a hack? I.e. are some browsers targetted until the next comment? + * + * @var bool + */ + protected $_inHack = false; + + + /** + * Constructor + * + * @param array $options (currently ignored) + */ + private function __construct($options) { + $this->_options = $options; + } + + /** + * Minify a CSS string + * + * @param string $css + * + * @return string + */ + protected function _process($css) + { + $css = str_replace("\r\n", "\n", $css); + + // preserve empty comment after '>' + // http://www.webdevout.net/css-hacks#in_css-selectors + $css = preg_replace('@>/\\*\\s*\\*/@', '>/*keep*/', $css); + + // preserve empty comment between property and value + // http://css-discuss.incutio.com/?page=BoxModelHack + $css = preg_replace('@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css); + $css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css); + + // apply callback to all valid comments (and strip out surrounding ws + $css = preg_replace_callback('@\\s*/\\*([\\s\\S]*?)\\*/\\s*@' + ,array($this, '_commentCB'), $css); + + // remove ws around { } and last semicolon in declaration block + $css = preg_replace('/\\s*{\\s*/', '{', $css); + $css = preg_replace('/;?\\s*}\\s*/', '}', $css); + + // remove ws surrounding semicolons + $css = preg_replace('/\\s*;\\s*/', ';', $css); + + // remove ws around urls + $css = preg_replace('/ + url\\( # url( + \\s* + ([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis) + \\s* + \\) # ) + /x', 'url($1)', $css); + + // remove ws between rules and colons + $css = preg_replace('/ + \\s* + ([{;]) # 1 = beginning of block or rule separator + \\s* + ([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter) + \\s* + : + \\s* + (\\b|[#\'"-]) # 3 = first character of a value + /x', '$1$2:$3', $css); + + // remove ws in selectors + $css = preg_replace_callback('/ + (?: # non-capture + \\s* + [^~>+,\\s]+ # selector part + \\s* + [,>+~] # combinators + )+ + \\s* + [^~>+,\\s]+ # selector part + { # open declaration block + /x' + ,array($this, '_selectorsCB'), $css); + + // minimize hex colors + $css = preg_replace('/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i' + , '$1#$2$3$4$5', $css); + + // remove spaces between font families + $css = preg_replace_callback('/font-family:([^;}]+)([;}])/' + ,array($this, '_fontFamilyCB'), $css); + + $css = preg_replace('/@import\\s+url/', '@import url', $css); + + // replace any ws involving newlines with a single newline + $css = preg_replace('/[ \\t]*\\n+\\s*/', "\n", $css); + + // separate common descendent selectors w/ newlines (to limit line lengths) + $css = preg_replace('/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/', "$1\n$2{", $css); + + // Use newline after 1st numeric value (to limit line lengths). + $css = preg_replace('/ + ((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value + \\s+ + /x' + ,"$1\n", $css); + + // prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/ + $css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css); + + return trim($css); + } + + /** + * Replace what looks like a set of selectors + * + * @param array $m regex matches + * + * @return string + */ + protected function _selectorsCB($m) + { + // remove ws around the combinators + return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]); + } + + /** + * Process a comment and return a replacement + * + * @param array $m regex matches + * + * @return string + */ + protected function _commentCB($m) + { + $hasSurroundingWs = (trim($m[0]) !== $m[1]); + $m = $m[1]; + // $m is the comment content w/o the surrounding tokens, + // but the return value will replace the entire comment. + if ($m === 'keep') { + return '/**/'; + } + if ($m === '" "') { + // component of http://tantek.com/CSS/Examples/midpass.html + return '/*" "*/'; + } + if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) { + // component of http://tantek.com/CSS/Examples/midpass.html + return '/*";}}/* */'; + } + if ($this->_inHack) { + // inversion: feeding only to one browser + if (preg_match('@ + ^/ # comment started like /*/ + \\s* + (\\S[\\s\\S]+?) # has at least some non-ws content + \\s* + /\\* # ends like /*/ or /**/ + @x', $m, $n)) { + // end hack mode after this comment, but preserve the hack and comment content + $this->_inHack = false; + return "/*/{$n[1]}/**/"; + } + } + if (substr($m, -1) === '\\') { // comment ends like \*/ + // begin hack mode and preserve hack + $this->_inHack = true; + return '/*\\*/'; + } + if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */ + // begin hack mode and preserve hack + $this->_inHack = true; + return '/*/*/'; + } + if ($this->_inHack) { + // a regular comment ends hack mode but should be preserved + $this->_inHack = false; + return '/**/'; + } + // Issue 107: if there's any surrounding whitespace, it may be important, so + // replace the comment with a single space + return $hasSurroundingWs // remove all other comments + ? ' ' + : ''; + } + + /** + * Process a font-family listing and return a replacement + * + * @param array $m regex matches + * + * @return string + */ + protected function _fontFamilyCB($m) + { + // Issue 210: must not eliminate WS between words in unquoted families + $pieces = preg_split('/(\'[^\']+\'|"[^"]+")/', $m[1], null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + $out = 'font-family:'; + while (null !== ($piece = array_shift($pieces))) { + if ($piece[0] !== '"' && $piece[0] !== "'") { + $piece = preg_replace('/\\s+/', ' ', $piece); + $piece = preg_replace('/\\s?,\\s?/', ',', $piece); + } + $out .= $piece; + } + return $out . $m[2]; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/CSS/UriRewriter.php b/vendor/mrclay/minify/min/lib/Minify/CSS/UriRewriter.php new file mode 100644 index 0000000000..43cc2548b0 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/CSS/UriRewriter.php @@ -0,0 +1,307 @@ + + */ +class Minify_CSS_UriRewriter { + + /** + * rewrite() and rewriteRelative() append debugging information here + * + * @var string + */ + public static $debugText = ''; + + /** + * In CSS content, rewrite file relative URIs as root relative + * + * @param string $css + * + * @param string $currentDir The directory of the current CSS file. + * + * @param string $docRoot The document root of the web site in which + * the CSS file resides (default = $_SERVER['DOCUMENT_ROOT']). + * + * @param array $symlinks (default = array()) If the CSS file is stored in + * a symlink-ed directory, provide an array of link paths to + * target paths, where the link paths are within the document root. Because + * paths need to be normalized for this to work, use "//" to substitute + * the doc root in the link paths (the array keys). E.g.: + * + * array('//symlink' => '/real/target/path') // unix + * array('//static' => 'D:\\staticStorage') // Windows + * + * + * @return string + */ + public static function rewrite($css, $currentDir, $docRoot = null, $symlinks = array()) + { + self::$_docRoot = self::_realpath( + $docRoot ? $docRoot : $_SERVER['DOCUMENT_ROOT'] + ); + self::$_currentDir = self::_realpath($currentDir); + self::$_symlinks = array(); + + // normalize symlinks + foreach ($symlinks as $link => $target) { + $link = ($link === '//') + ? self::$_docRoot + : str_replace('//', self::$_docRoot . '/', $link); + $link = strtr($link, '/', DIRECTORY_SEPARATOR); + self::$_symlinks[$link] = self::_realpath($target); + } + + self::$debugText .= "docRoot : " . self::$_docRoot . "\n" + . "currentDir : " . self::$_currentDir . "\n"; + if (self::$_symlinks) { + self::$debugText .= "symlinks : " . var_export(self::$_symlinks, 1) . "\n"; + } + self::$debugText .= "\n"; + + $css = self::_trimUrls($css); + + // rewrite + $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/' + ,array(self::$className, '_processUriCB'), $css); + $css = preg_replace_callback('/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/' + ,array(self::$className, '_processUriCB'), $css); + + return $css; + } + + /** + * In CSS content, prepend a path to relative URIs + * + * @param string $css + * + * @param string $path The path to prepend. + * + * @return string + */ + public static function prepend($css, $path) + { + self::$_prependPath = $path; + + $css = self::_trimUrls($css); + + // append + $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/' + ,array(self::$className, '_processUriCB'), $css); + $css = preg_replace_callback('/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/' + ,array(self::$className, '_processUriCB'), $css); + + self::$_prependPath = null; + return $css; + } + + /** + * Get a root relative URI from a file relative URI + * + * + * Minify_CSS_UriRewriter::rewriteRelative( + * '../img/hello.gif' + * , '/home/user/www/css' // path of CSS file + * , '/home/user/www' // doc root + * ); + * // returns '/img/hello.gif' + * + * // example where static files are stored in a symlinked directory + * Minify_CSS_UriRewriter::rewriteRelative( + * 'hello.gif' + * , '/var/staticFiles/theme' + * , '/home/user/www' + * , array('/home/user/www/static' => '/var/staticFiles') + * ); + * // returns '/static/theme/hello.gif' + * + * + * @param string $uri file relative URI + * + * @param string $realCurrentDir realpath of the current file's directory. + * + * @param string $realDocRoot realpath of the site document root. + * + * @param array $symlinks (default = array()) If the file is stored in + * a symlink-ed directory, provide an array of link paths to + * real target paths, where the link paths "appear" to be within the document + * root. E.g.: + * + * array('/home/foo/www/not/real/path' => '/real/target/path') // unix + * array('C:\\htdocs\\not\\real' => 'D:\\real\\target\\path') // Windows + * + * + * @return string + */ + public static function rewriteRelative($uri, $realCurrentDir, $realDocRoot, $symlinks = array()) + { + // prepend path with current dir separator (OS-independent) + $path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR) + . DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR); + + self::$debugText .= "file-relative URI : {$uri}\n" + . "path prepended : {$path}\n"; + + // "unresolve" a symlink back to doc root + foreach ($symlinks as $link => $target) { + if (0 === strpos($path, $target)) { + // replace $target with $link + $path = $link . substr($path, strlen($target)); + + self::$debugText .= "symlink unresolved : {$path}\n"; + + break; + } + } + // strip doc root + $path = substr($path, strlen($realDocRoot)); + + self::$debugText .= "docroot stripped : {$path}\n"; + + // fix to root-relative URI + $uri = strtr($path, '/\\', '//'); + $uri = self::removeDots($uri); + + self::$debugText .= "traversals removed : {$uri}\n\n"; + + return $uri; + } + + /** + * Remove instances of "./" and "../" where possible from a root-relative URI + * + * @param string $uri + * + * @return string + */ + public static function removeDots($uri) + { + $uri = str_replace('/./', '/', $uri); + // inspired by patch from Oleg Cherniy + do { + $uri = preg_replace('@/[^/]+/\\.\\./@', '/', $uri, 1, $changed); + } while ($changed); + return $uri; + } + + /** + * Defines which class to call as part of callbacks, change this + * if you extend Minify_CSS_UriRewriter + * + * @var string + */ + protected static $className = 'Minify_CSS_UriRewriter'; + + /** + * Get realpath with any trailing slash removed. If realpath() fails, + * just remove the trailing slash. + * + * @param string $path + * + * @return mixed path with no trailing slash + */ + protected static function _realpath($path) + { + $realPath = realpath($path); + if ($realPath !== false) { + $path = $realPath; + } + return rtrim($path, '/\\'); + } + + /** + * Directory of this stylesheet + * + * @var string + */ + private static $_currentDir = ''; + + /** + * DOC_ROOT + * + * @var string + */ + private static $_docRoot = ''; + + /** + * directory replacements to map symlink targets back to their + * source (within the document root) E.g. '/var/www/symlink' => '/var/realpath' + * + * @var array + */ + private static $_symlinks = array(); + + /** + * Path to prepend + * + * @var string + */ + private static $_prependPath = null; + + /** + * @param string $css + * + * @return string + */ + private static function _trimUrls($css) + { + return preg_replace('/ + url\\( # url( + \\s* + ([^\\)]+?) # 1 = URI (assuming does not contain ")") + \\s* + \\) # ) + /x', 'url($1)', $css); + } + + /** + * @param array $m + * + * @return string + */ + private static function _processUriCB($m) + { + // $m matched either '/@import\\s+([\'"])(.*?)[\'"]/' or '/url\\(\\s*([^\\)\\s]+)\\s*\\)/' + $isImport = ($m[0][0] === '@'); + // determine URI and the quote character (if any) + if ($isImport) { + $quoteChar = $m[1]; + $uri = $m[2]; + } else { + // $m[1] is either quoted or not + $quoteChar = ($m[1][0] === "'" || $m[1][0] === '"') + ? $m[1][0] + : ''; + $uri = ($quoteChar === '') + ? $m[1] + : substr($m[1], 1, strlen($m[1]) - 2); + } + // if not root/scheme relative and not starts with scheme + if (!preg_match('~^(/|[a-z]+\:)~', $uri)) { + // URI is file-relative: rewrite depending on options + if (self::$_prependPath === null) { + $uri = self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks); + } else { + $uri = self::$_prependPath . $uri; + if ($uri[0] === '/') { + $root = ''; + $rootRelative = $uri; + $uri = $root . self::removeDots($rootRelative); + } elseif (preg_match('@^((https?\:)?//([^/]+))/@', $uri, $m) && (false !== strpos($m[3], '.'))) { + $root = $m[1]; + $rootRelative = substr($uri, strlen($root)); + $uri = $root . self::removeDots($rootRelative); + } + } + } + return $isImport + ? "@import {$quoteChar}{$uri}{$quoteChar}" + : "url({$quoteChar}{$uri}{$quoteChar})"; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/CSSmin.php b/vendor/mrclay/minify/min/lib/Minify/CSSmin.php new file mode 100644 index 0000000000..4403383872 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/CSSmin.php @@ -0,0 +1,85 @@ + + */ +class Minify_CSSmin { + + /** + * Minify a CSS string + * + * @param string $css + * + * @param array $options available options: + * + * 'removeCharsets': (default true) remove all @charset at-rules + * + * 'prependRelativePath': (default null) if given, this string will be + * prepended to all relative URIs in import/url declarations + * + * 'currentDir': (default null) if given, this is assumed to be the + * directory of the current CSS file. Using this, minify will rewrite + * all relative URIs in import/url declarations to correctly point to + * the desired files. For this to work, the files *must* exist and be + * visible by the PHP process. + * + * 'symlinks': (default = array()) If the CSS file is stored in + * a symlink-ed directory, provide an array of link paths to + * target paths, where the link paths are within the document root. Because + * paths need to be normalized for this to work, use "//" to substitute + * the doc root in the link paths (the array keys). E.g.: + * + * array('//symlink' => '/real/target/path') // unix + * array('//static' => 'D:\\staticStorage') // Windows + * + * + * 'docRoot': (default = $_SERVER['DOCUMENT_ROOT']) + * see Minify_CSS_UriRewriter::rewrite + * + * @return string + */ + public static function minify($css, $options = array()) + { + $options = array_merge(array( + 'compress' => true, + 'removeCharsets' => true, + 'currentDir' => null, + 'docRoot' => $_SERVER['DOCUMENT_ROOT'], + 'prependRelativePath' => null, + 'symlinks' => array(), + ), $options); + + if ($options['removeCharsets']) { + $css = preg_replace('/@charset[^;]+;\\s*/', '', $css); + } + if ($options['compress']) { + $obj = new CSSmin(); + $css = $obj->run($css); + } + if (! $options['currentDir'] && ! $options['prependRelativePath']) { + return $css; + } + if ($options['currentDir']) { + return Minify_CSS_UriRewriter::rewrite( + $css + ,$options['currentDir'] + ,$options['docRoot'] + ,$options['symlinks'] + ); + } else { + return Minify_CSS_UriRewriter::prepend( + $css + ,$options['prependRelativePath'] + ); + } + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Cache/APC.php b/vendor/mrclay/minify/min/lib/Minify/Cache/APC.php new file mode 100644 index 0000000000..24ab046205 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Cache/APC.php @@ -0,0 +1,133 @@ + + * Minify::setCache(new Minify_Cache_APC()); + * + * + * @package Minify + * @author Chris Edwards + **/ +class Minify_Cache_APC { + + /** + * Create a Minify_Cache_APC object, to be passed to + * Minify::setCache(). + * + * + * @param int $expire seconds until expiration (default = 0 + * meaning the item will not get an expiration date) + * + * @return null + */ + public function __construct($expire = 0) + { + $this->_exp = $expire; + } + + /** + * Write data to cache. + * + * @param string $id cache id + * + * @param string $data + * + * @return bool success + */ + public function store($id, $data) + { + return apc_store($id, "{$_SERVER['REQUEST_TIME']}|{$data}", $this->_exp); + } + + /** + * Get the size of a cache entry + * + * @param string $id cache id + * + * @return int size in bytes + */ + public function getSize($id) + { + if (! $this->_fetch($id)) { + return false; + } + return (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) + ? mb_strlen($this->_data, '8bit') + : strlen($this->_data); + } + + /** + * Does a valid cache entry exist? + * + * @param string $id cache id + * + * @param int $srcMtime mtime of the original source file(s) + * + * @return bool exists + */ + public function isValid($id, $srcMtime) + { + return ($this->_fetch($id) && ($this->_lm >= $srcMtime)); + } + + /** + * Send the cached content to output + * + * @param string $id cache id + */ + public function display($id) + { + echo $this->_fetch($id) + ? $this->_data + : ''; + } + + /** + * Fetch the cached content + * + * @param string $id cache id + * + * @return string + */ + public function fetch($id) + { + return $this->_fetch($id) + ? $this->_data + : ''; + } + + private $_exp = null; + + // cache of most recently fetched id + private $_lm = null; + private $_data = null; + private $_id = null; + + /** + * Fetch data and timestamp from apc, store in instance + * + * @param string $id + * + * @return bool success + */ + private function _fetch($id) + { + if ($this->_id === $id) { + return true; + } + $ret = apc_fetch($id); + if (false === $ret) { + $this->_id = null; + return false; + } + list($this->_lm, $this->_data) = explode('|', $ret, 2); + $this->_id = $id; + return true; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Cache/File.php b/vendor/mrclay/minify/min/lib/Minify/Cache/File.php new file mode 100644 index 0000000000..c228eb2b2f --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Cache/File.php @@ -0,0 +1,197 @@ +_locking = $fileLocking; + $this->_path = $path; + } + + /** + * Write data to cache. + * + * @param string $id cache id (e.g. a filename) + * + * @param string $data + * + * @return bool success + */ + public function store($id, $data) + { + $flag = $this->_locking + ? LOCK_EX + : null; + $file = $this->_path . '/' . $id; + if (! @file_put_contents($file, $data, $flag)) { + $this->_log("Minify_Cache_File: Write failed to '$file'"); + } + // write control + if ($data !== $this->fetch($id)) { + @unlink($file); + $this->_log("Minify_Cache_File: Post-write read failed for '$file'"); + return false; + } + return true; + } + + /** + * Get the size of a cache entry + * + * @param string $id cache id (e.g. a filename) + * + * @return int size in bytes + */ + public function getSize($id) + { + return filesize($this->_path . '/' . $id); + } + + /** + * Does a valid cache entry exist? + * + * @param string $id cache id (e.g. a filename) + * + * @param int $srcMtime mtime of the original source file(s) + * + * @return bool exists + */ + public function isValid($id, $srcMtime) + { + $file = $this->_path . '/' . $id; + return (is_file($file) && (filemtime($file) >= $srcMtime)); + } + + /** + * Send the cached content to output + * + * @param string $id cache id (e.g. a filename) + */ + public function display($id) + { + if ($this->_locking) { + $fp = fopen($this->_path . '/' . $id, 'rb'); + flock($fp, LOCK_SH); + fpassthru($fp); + flock($fp, LOCK_UN); + fclose($fp); + } else { + readfile($this->_path . '/' . $id); + } + } + + /** + * Fetch the cached content + * + * @param string $id cache id (e.g. a filename) + * + * @return string + */ + public function fetch($id) + { + if ($this->_locking) { + $fp = fopen($this->_path . '/' . $id, 'rb'); + if (!$fp) { + return false; + } + flock($fp, LOCK_SH); + $ret = stream_get_contents($fp); + flock($fp, LOCK_UN); + fclose($fp); + return $ret; + } else { + return file_get_contents($this->_path . '/' . $id); + } + } + + /** + * Fetch the cache path used + * + * @return string + */ + public function getPath() + { + return $this->_path; + } + + /** + * Get a usable temp directory + * + * Adapted from Solar/Dir.php + * @author Paul M. Jones + * @license http://opensource.org/licenses/bsd-license.php BSD + * @link http://solarphp.com/trac/core/browser/trunk/Solar/Dir.php + * + * @return string + */ + public static function tmp() + { + static $tmp = null; + if (! $tmp) { + $tmp = function_exists('sys_get_temp_dir') + ? sys_get_temp_dir() + : self::_tmp(); + $tmp = rtrim($tmp, DIRECTORY_SEPARATOR); + } + return $tmp; + } + + /** + * Returns the OS-specific directory for temporary files + * + * @author Paul M. Jones + * @license http://opensource.org/licenses/bsd-license.php BSD + * @link http://solarphp.com/trac/core/browser/trunk/Solar/Dir.php + * + * @return string + */ + protected static function _tmp() + { + // non-Windows system? + if (strtolower(substr(PHP_OS, 0, 3)) != 'win') { + $tmp = empty($_ENV['TMPDIR']) ? getenv('TMPDIR') : $_ENV['TMPDIR']; + if ($tmp) { + return $tmp; + } else { + return '/tmp'; + } + } + // Windows 'TEMP' + $tmp = empty($_ENV['TEMP']) ? getenv('TEMP') : $_ENV['TEMP']; + if ($tmp) { + return $tmp; + } + // Windows 'TMP' + $tmp = empty($_ENV['TMP']) ? getenv('TMP') : $_ENV['TMP']; + if ($tmp) { + return $tmp; + } + // Windows 'windir' + $tmp = empty($_ENV['windir']) ? getenv('windir') : $_ENV['windir']; + if ($tmp) { + return $tmp; + } + // final fallback for Windows + return getenv('SystemRoot') . '\\temp'; + } + + /** + * Send message to the Minify logger + * @param string $msg + * @return null + */ + protected function _log($msg) + { + Minify_Logger::log($msg); + } + + private $_path = null; + private $_locking = null; +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Cache/Memcache.php b/vendor/mrclay/minify/min/lib/Minify/Cache/Memcache.php new file mode 100644 index 0000000000..72bf454b93 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Cache/Memcache.php @@ -0,0 +1,140 @@ + + * // fall back to disk caching if memcache can't connect + * $memcache = new Memcache; + * if ($memcache->connect('localhost', 11211)) { + * Minify::setCache(new Minify_Cache_Memcache($memcache)); + * } else { + * Minify::setCache(); + * } + * + **/ +class Minify_Cache_Memcache { + + /** + * Create a Minify_Cache_Memcache object, to be passed to + * Minify::setCache(). + * + * @param Memcache $memcache already-connected instance + * + * @param int $expire seconds until expiration (default = 0 + * meaning the item will not get an expiration date) + * + * @return null + */ + public function __construct($memcache, $expire = 0) + { + $this->_mc = $memcache; + $this->_exp = $expire; + } + + /** + * Write data to cache. + * + * @param string $id cache id + * + * @param string $data + * + * @return bool success + */ + public function store($id, $data) + { + return $this->_mc->set($id, "{$_SERVER['REQUEST_TIME']}|{$data}", 0, $this->_exp); + } + + + /** + * Get the size of a cache entry + * + * @param string $id cache id + * + * @return int size in bytes + */ + public function getSize($id) + { + if (! $this->_fetch($id)) { + return false; + } + return (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) + ? mb_strlen($this->_data, '8bit') + : strlen($this->_data); + } + + /** + * Does a valid cache entry exist? + * + * @param string $id cache id + * + * @param int $srcMtime mtime of the original source file(s) + * + * @return bool exists + */ + public function isValid($id, $srcMtime) + { + return ($this->_fetch($id) && ($this->_lm >= $srcMtime)); + } + + /** + * Send the cached content to output + * + * @param string $id cache id + */ + public function display($id) + { + echo $this->_fetch($id) + ? $this->_data + : ''; + } + + /** + * Fetch the cached content + * + * @param string $id cache id + * + * @return string + */ + public function fetch($id) + { + return $this->_fetch($id) + ? $this->_data + : ''; + } + + private $_mc = null; + private $_exp = null; + + // cache of most recently fetched id + private $_lm = null; + private $_data = null; + private $_id = null; + + /** + * Fetch data and timestamp from memcache, store in instance + * + * @param string $id + * + * @return bool success + */ + private function _fetch($id) + { + if ($this->_id === $id) { + return true; + } + $ret = $this->_mc->get($id); + if (false === $ret) { + $this->_id = null; + return false; + } + list($this->_lm, $this->_data) = explode('|', $ret, 2); + $this->_id = $id; + return true; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Cache/XCache.php b/vendor/mrclay/minify/min/lib/Minify/Cache/XCache.php new file mode 100644 index 0000000000..3039deddcb --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Cache/XCache.php @@ -0,0 +1,126 @@ + + * Minify::setCache(new Minify_Cache_XCache()); + * + * + * @package Minify + * @author Elan Ruusamäe + **/ +class Minify_Cache_XCache { + + /** + * Create a Minify_Cache_XCache object, to be passed to + * Minify::setCache(). + * + * @param int $expire seconds until expiration (default = 0 + * meaning the item will not get an expiration date) + */ + public function __construct($expire = 0) + { + $this->_exp = $expire; + } + + /** + * Write data to cache. + * + * @param string $id cache id + * @param string $data + * @return bool success + */ + public function store($id, $data) + { + return xcache_set($id, "{$_SERVER['REQUEST_TIME']}|{$data}", $this->_exp); + } + + /** + * Get the size of a cache entry + * + * @param string $id cache id + * @return int size in bytes + */ + public function getSize($id) + { + if (! $this->_fetch($id)) { + return false; + } + return (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) + ? mb_strlen($this->_data, '8bit') + : strlen($this->_data); + } + + /** + * Does a valid cache entry exist? + * + * @param string $id cache id + * @param int $srcMtime mtime of the original source file(s) + * @return bool exists + */ + public function isValid($id, $srcMtime) + { + return ($this->_fetch($id) && ($this->_lm >= $srcMtime)); + } + + /** + * Send the cached content to output + * + * @param string $id cache id + */ + public function display($id) + { + echo $this->_fetch($id) + ? $this->_data + : ''; + } + + /** + * Fetch the cached content + * + * @param string $id cache id + * @return string + */ + public function fetch($id) + { + return $this->_fetch($id) + ? $this->_data + : ''; + } + + private $_exp = null; + + // cache of most recently fetched id + private $_lm = null; + private $_data = null; + private $_id = null; + + /** + * Fetch data and timestamp from xcache, store in instance + * + * @param string $id + * @return bool success + */ + private function _fetch($id) + { + if ($this->_id === $id) { + return true; + } + $ret = xcache_get($id); + if (false === $ret) { + $this->_id = null; + return false; + } + list($this->_lm, $this->_data) = explode('|', $ret, 2); + $this->_id = $id; + return true; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Cache/ZendPlatform.php b/vendor/mrclay/minify/min/lib/Minify/Cache/ZendPlatform.php new file mode 100644 index 0000000000..3130d69a7b --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Cache/ZendPlatform.php @@ -0,0 +1,142 @@ + + * Minify::setCache(new Minify_Cache_ZendPlatform()); + * + * + * @package Minify + * @author Patrick van Dissel + */ +class Minify_Cache_ZendPlatform { + + + /** + * Create a Minify_Cache_ZendPlatform object, to be passed to + * Minify::setCache(). + * + * @param int $expire seconds until expiration (default = 0 + * meaning the item will not get an expiration date) + * + * @return null + */ + public function __construct($expire = 0) + { + $this->_exp = $expire; + } + + + /** + * Write data to cache. + * + * @param string $id cache id + * + * @param string $data + * + * @return bool success + */ + public function store($id, $data) + { + return output_cache_put($id, "{$_SERVER['REQUEST_TIME']}|{$data}"); + } + + + /** + * Get the size of a cache entry + * + * @param string $id cache id + * + * @return int size in bytes + */ + public function getSize($id) + { + return $this->_fetch($id) + ? strlen($this->_data) + : false; + } + + + /** + * Does a valid cache entry exist? + * + * @param string $id cache id + * + * @param int $srcMtime mtime of the original source file(s) + * + * @return bool exists + */ + public function isValid($id, $srcMtime) + { + $ret = ($this->_fetch($id) && ($this->_lm >= $srcMtime)); + return $ret; + } + + + /** + * Send the cached content to output + * + * @param string $id cache id + */ + public function display($id) + { + echo $this->_fetch($id) + ? $this->_data + : ''; + } + + + /** + * Fetch the cached content + * + * @param string $id cache id + * + * @return string + */ + public function fetch($id) + { + return $this->_fetch($id) + ? $this->_data + : ''; + } + + + private $_exp = null; + + + // cache of most recently fetched id + private $_lm = null; + private $_data = null; + private $_id = null; + + + /** + * Fetch data and timestamp from ZendPlatform, store in instance + * + * @param string $id + * + * @return bool success + */ + private function _fetch($id) + { + if ($this->_id === $id) { + return true; + } + $ret = output_cache_get($id, $this->_exp); + if (false === $ret) { + $this->_id = null; + return false; + } + list($this->_lm, $this->_data) = explode('|', $ret, 2); + $this->_id = $id; + return true; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/ClosureCompiler.php b/vendor/mrclay/minify/min/lib/Minify/ClosureCompiler.php new file mode 100644 index 0000000000..53983a52aa --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/ClosureCompiler.php @@ -0,0 +1,139 @@ + + * Minify_ClosureCompiler::$jarFile = '/path/to/closure-compiler-20120123.jar'; + * Minify_ClosureCompiler::$tempDir = '/tmp'; + * $code = Minify_ClosureCompiler::minify( + * $code, + * array('compilation_level' => 'SIMPLE_OPTIMIZATIONS') + * ); + * + * --compilation_level WHITESPACE_ONLY, SIMPLE_OPTIMIZATIONS, ADVANCED_OPTIMIZATIONS + * + * + * + * @todo unit tests, $options docs + * @todo more options support (or should just passthru them all?) + * + * @package Minify + * @author Stephen Clay + * @author Elan Ruusamäe + */ +class Minify_ClosureCompiler { + + const OPTION_CHARSET = 'charset'; + const OPTION_COMPILATION_LEVEL = 'compilation_level'; + + public static $isDebug = false; + + /** + * Filepath of the Closure Compiler jar file. This must be set before + * calling minifyJs(). + * + * @var string + */ + public static $jarFile = null; + + /** + * Writable temp directory. This must be set before calling minifyJs(). + * + * @var string + */ + public static $tempDir = null; + + /** + * Filepath of "java" executable (may be needed if not in shell's PATH) + * + * @var string + */ + public static $javaExecutable = 'java'; + + /** + * Minify a Javascript string + * + * @param string $js + * + * @param array $options (verbose is ignored) + * + * @see https://code.google.com/p/closure-compiler/source/browse/trunk/README + * + * @return string + * + * @throws Minify_ClosureCompiler_Exception + */ + public static function minify($js, $options = array()) + { + self::_prepare(); + if (! ($tmpFile = tempnam(self::$tempDir, 'cc_'))) { + throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : could not create temp file in "'.self::$tempDir.'".'); + } + file_put_contents($tmpFile, $js); + $cmd = self::_getCmd($options, $tmpFile); + exec($cmd, $output, $result_code); + unlink($tmpFile); + if ($result_code != 0) { + $message = 'Minify_ClosureCompiler : Closure Compiler execution failed.'; + if (self::$isDebug) { + exec($cmd . ' 2>&1', $error); + if ($error) { + $message .= "\nReason:\n" . join("\n", $error); + } + } + throw new Minify_ClosureCompiler_Exception($message); + } + return implode("\n", $output); + } + + private static function _getCmd($userOptions, $tmpFile) + { + $o = array_merge( + array( + self::OPTION_CHARSET => 'utf-8', + self::OPTION_COMPILATION_LEVEL => 'SIMPLE_OPTIMIZATIONS', + ), + $userOptions + ); + $charsetOption = $o[self::OPTION_CHARSET]; + $cmd = self::$javaExecutable . ' -jar ' . escapeshellarg(self::$jarFile) + . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $charsetOption) + ? " --charset {$charsetOption}" + : ''); + + foreach (array(self::OPTION_COMPILATION_LEVEL) as $opt) { + if ($o[$opt]) { + $cmd .= " --{$opt} ". escapeshellarg($o[$opt]); + } + } + return $cmd . ' ' . escapeshellarg($tmpFile); + } + + private static function _prepare() + { + if (! is_file(self::$jarFile)) { + throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $jarFile('.self::$jarFile.') is not a valid file.'); + } + if (! is_readable(self::$jarFile)) { + throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $jarFile('.self::$jarFile.') is not readable.'); + } + if (! is_dir(self::$tempDir)) { + throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $tempDir('.self::$tempDir.') is not a valid direcotry.'); + } + if (! is_writable(self::$tempDir)) { + throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $tempDir('.self::$tempDir.') is not writable.'); + } + } +} + +class Minify_ClosureCompiler_Exception extends Exception {} diff --git a/vendor/mrclay/minify/min/lib/Minify/CommentPreserver.php b/vendor/mrclay/minify/min/lib/Minify/CommentPreserver.php new file mode 100644 index 0000000000..7a359bf9bb --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/CommentPreserver.php @@ -0,0 +1,89 @@ + + */ +class Minify_CommentPreserver { + + /** + * String to be prepended to each preserved comment + * + * @var string + */ + public static $prepend = "\n"; + + /** + * String to be appended to each preserved comment + * + * @var string + */ + public static $append = "\n"; + + /** + * Process a string outside of C-style comments that begin with "/*!" + * + * On each non-empty string outside these comments, the given processor + * function will be called. The comments will be surrounded by + * Minify_CommentPreserver::$preprend and Minify_CommentPreserver::$append. + * + * @param string $content + * @param callback $processor function + * @param array $args array of extra arguments to pass to the processor + * function (default = array()) + * @return string + */ + public static function process($content, $processor, $args = array()) + { + $ret = ''; + while (true) { + list($beforeComment, $comment, $afterComment) = self::_nextComment($content); + if ('' !== $beforeComment) { + $callArgs = $args; + array_unshift($callArgs, $beforeComment); + $ret .= call_user_func_array($processor, $callArgs); + } + if (false === $comment) { + break; + } + $ret .= $comment; + $content = $afterComment; + } + return $ret; + } + + /** + * Extract comments that YUI Compressor preserves. + * + * @param string $in input + * + * @return array 3 elements are returned. If a YUI comment is found, the + * 2nd element is the comment and the 1st and 3rd are the surrounding + * strings. If no comment is found, the entire string is returned as the + * 1st element and the other two are false. + */ + private static function _nextComment($in) + { + if ( + false === ($start = strpos($in, '/*!')) + || false === ($end = strpos($in, '*/', $start + 3)) + ) { + return array($in, false, false); + } + $ret = array( + substr($in, 0, $start) + ,self::$prepend . '/*!' . substr($in, $start + 3, $end - $start - 1) . self::$append + ); + $endChars = (strlen($in) - $end - 2); + $ret[] = (0 === $endChars) + ? '' + : substr($in, -$endChars); + return $ret; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Controller/Base.php b/vendor/mrclay/minify/min/lib/Minify/Controller/Base.php new file mode 100644 index 0000000000..5a86329033 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Controller/Base.php @@ -0,0 +1,222 @@ + + */ +abstract class Minify_Controller_Base { + + /** + * Setup controller sources and set an needed options for Minify::source + * + * You must override this method in your subclass controller to set + * $this->sources. If the request is NOT valid, make sure $this->sources + * is left an empty array. Then strip any controller-specific options from + * $options and return it. To serve files, $this->sources must be an array of + * Minify_Source objects. + * + * @param array $options controller and Minify options + * + * @return array $options Minify::serve options + */ + abstract public function setupSources($options); + + /** + * Get default Minify options for this controller. + * + * Override in subclass to change defaults + * + * @return array options for Minify + */ + public function getDefaultMinifyOptions() { + return array( + 'isPublic' => true + ,'encodeOutput' => function_exists('gzdeflate') + ,'encodeMethod' => null // determine later + ,'encodeLevel' => 9 + ,'minifierOptions' => array() // no minifier options + ,'contentTypeCharset' => 'utf-8' + ,'maxAge' => 1800 // 30 minutes + ,'rewriteCssUris' => true + ,'bubbleCssImports' => false + ,'quiet' => false // serve() will send headers and output + ,'debug' => false + + // if you override these, the response codes MUST be directly after + // the first space. + ,'badRequestHeader' => 'HTTP/1.0 400 Bad Request' + ,'errorHeader' => 'HTTP/1.0 500 Internal Server Error' + + // callback function to see/modify content of all sources + ,'postprocessor' => null + // file to require to load preprocessor + ,'postprocessorRequire' => null + ); + } + + /** + * Get default minifiers for this controller. + * + * Override in subclass to change defaults + * + * @return array minifier callbacks for common types + */ + public function getDefaultMinifers() { + $ret[Minify::TYPE_JS] = array('JSMin', 'minify'); + $ret[Minify::TYPE_CSS] = array('Minify_CSS', 'minify'); + $ret[Minify::TYPE_HTML] = array('Minify_HTML', 'minify'); + return $ret; + } + + /** + * Is a user-given file within an allowable directory, existing, + * and having an extension js/css/html/txt ? + * + * This is a convenience function for controllers that have to accept + * user-given paths + * + * @param string $file full file path (already processed by realpath()) + * + * @param array $safeDirs directories where files are safe to serve. Files can also + * be in subdirectories of these directories. + * + * @return bool file is safe + * + * @deprecated use checkAllowDirs, checkNotHidden instead + */ + public static function _fileIsSafe($file, $safeDirs) + { + $pathOk = false; + foreach ((array)$safeDirs as $safeDir) { + if (strpos($file, $safeDir) === 0) { + $pathOk = true; + break; + } + } + $base = basename($file); + if (! $pathOk || ! is_file($file) || $base[0] === '.') { + return false; + } + list($revExt) = explode('.', strrev($base)); + return in_array(strrev($revExt), array('js', 'css', 'html', 'txt')); + } + + /** + * @param string $file + * @param array $allowDirs + * @param string $uri + * @return bool + * @throws Exception + */ + public static function checkAllowDirs($file, $allowDirs, $uri) + { + foreach ((array)$allowDirs as $allowDir) { + if (strpos($file, $allowDir) === 0) { + return true; + } + } + throw new Exception("File '$file' is outside \$allowDirs. If the path is" + . " resolved via an alias/symlink, look into the \$min_symlinks option." + . " E.g. \$min_symlinks['/" . dirname($uri) . "'] = '" . dirname($file) . "';"); + } + + /** + * @param string $file + * @throws Exception + */ + public static function checkNotHidden($file) + { + $b = basename($file); + if (0 === strpos($b, '.')) { + throw new Exception("Filename '$b' starts with period (may be hidden)"); + } + } + + /** + * instances of Minify_Source, which provide content and any individual minification needs. + * + * @var array + * + * @see Minify_Source + */ + public $sources = array(); + + /** + * Short name to place inside cache id + * + * The setupSources() method may choose to set this, making it easier to + * recognize a particular set of sources/settings in the cache folder. It + * will be filtered and truncated to make the final cache id <= 250 bytes. + * + * @var string + */ + public $selectionId = ''; + + /** + * Mix in default controller options with user-given options + * + * @param array $options user options + * + * @return array mixed options + */ + public final function mixInDefaultOptions($options) + { + $ret = array_merge( + $this->getDefaultMinifyOptions(), $options + ); + if (! isset($options['minifiers'])) { + $options['minifiers'] = array(); + } + $ret['minifiers'] = array_merge( + $this->getDefaultMinifers(), $options['minifiers'] + ); + return $ret; + } + + /** + * Analyze sources (if there are any) and set $options 'contentType' + * and 'lastModifiedTime' if they already aren't. + * + * @param array $options options for Minify + * + * @return array options for Minify + */ + public final function analyzeSources($options = array()) + { + if ($this->sources) { + if (! isset($options['contentType'])) { + $options['contentType'] = Minify_Source::getContentType($this->sources); + } + // last modified is needed for caching, even if setExpires is set + if (! isset($options['lastModifiedTime'])) { + $max = 0; + foreach ($this->sources as $source) { + $max = max($source->lastModified, $max); + } + $options['lastModifiedTime'] = $max; + } + } + return $options; + } + + /** + * Send message to the Minify logger + * + * @param string $msg + * + * @return null + */ + public function log($msg) { + Minify_Logger::log($msg); + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Controller/Files.php b/vendor/mrclay/minify/min/lib/Minify/Controller/Files.php new file mode 100644 index 0000000000..f084cd07eb --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Controller/Files.php @@ -0,0 +1,76 @@ + + * Minify::serve('Files', array( + * 'files' => array( + * '//js/jquery.js' + * ,'//js/plugins.js' + * ,'/home/username/file.js' + * ) + * )); + * + * + * As a shortcut, the controller will replace "//" at the beginning + * of a filename with $_SERVER['DOCUMENT_ROOT'] . '/'. + * + * @package Minify + * @author Stephen Clay + */ +class Minify_Controller_Files extends Minify_Controller_Base { + + /** + * Set up file sources + * + * @param array $options controller and Minify options + * @return array Minify options + * + * Controller options: + * + * 'files': (required) array of complete file paths, or a single path + */ + public function setupSources($options) { + // strip controller options + + $files = $options['files']; + // if $files is a single object, casting will break it + if (is_object($files)) { + $files = array($files); + } elseif (! is_array($files)) { + $files = (array)$files; + } + unset($options['files']); + + $sources = array(); + foreach ($files as $file) { + if ($file instanceof Minify_Source) { + $sources[] = $file; + continue; + } + if (0 === strpos($file, '//')) { + $file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1); + } + $realPath = realpath($file); + if (is_file($realPath)) { + $sources[] = new Minify_Source(array( + 'filepath' => $realPath + )); + } else { + $this->log("The path \"{$file}\" could not be found (or was not a file)"); + return $options; + } + } + if ($sources) { + $this->sources = $sources; + } + return $options; + } +} + diff --git a/vendor/mrclay/minify/min/lib/Minify/Controller/Groups.php b/vendor/mrclay/minify/min/lib/Minify/Controller/Groups.php new file mode 100644 index 0000000000..c4c25db120 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Controller/Groups.php @@ -0,0 +1,91 @@ + + * Minify::serve('Groups', array( + * 'groups' => array( + * 'css' => array('//css/type.css', '//css/layout.css') + * ,'js' => array('//js/jquery.js', '//js/site.js') + * ) + * )); + * + * + * If the above code were placed in /serve.php, it would enable the URLs + * /serve.php/js and /serve.php/css + * + * As a shortcut, the controller will replace "//" at the beginning + * of a filename with $_SERVER['DOCUMENT_ROOT'] . '/'. + * + * @package Minify + * @author Stephen Clay + */ +class Minify_Controller_Groups extends Minify_Controller_Base { + + /** + * Set up groups of files as sources + * + * @param array $options controller and Minify options + * + * 'groups': (required) array mapping PATH_INFO strings to arrays + * of complete file paths. @see Minify_Controller_Groups + * + * @return array Minify options + */ + public function setupSources($options) { + // strip controller options + $groups = $options['groups']; + unset($options['groups']); + + // mod_fcgid places PATH_INFO in ORIG_PATH_INFO + $pi = isset($_SERVER['ORIG_PATH_INFO']) + ? substr($_SERVER['ORIG_PATH_INFO'], 1) + : (isset($_SERVER['PATH_INFO']) + ? substr($_SERVER['PATH_INFO'], 1) + : false + ); + if (false === $pi || ! isset($groups[$pi])) { + // no PATH_INFO or not a valid group + $this->log("Missing PATH_INFO or no group set for \"$pi\""); + return $options; + } + $sources = array(); + + $files = $groups[$pi]; + // if $files is a single object, casting will break it + if (is_object($files)) { + $files = array($files); + } elseif (! is_array($files)) { + $files = (array)$files; + } + foreach ($files as $file) { + if ($file instanceof Minify_Source) { + $sources[] = $file; + continue; + } + if (0 === strpos($file, '//')) { + $file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1); + } + $realPath = realpath($file); + if (is_file($realPath)) { + $sources[] = new Minify_Source(array( + 'filepath' => $realPath + )); + } else { + $this->log("The path \"{$file}\" could not be found (or was not a file)"); + return $options; + } + } + if ($sources) { + $this->sources = $sources; + } + return $options; + } +} + diff --git a/vendor/mrclay/minify/min/lib/Minify/Controller/MinApp.php b/vendor/mrclay/minify/min/lib/Minify/Controller/MinApp.php new file mode 100644 index 0000000000..6943ee6bf8 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Controller/MinApp.php @@ -0,0 +1,238 @@ + + */ +class Minify_Controller_MinApp extends Minify_Controller_Base { + + /** + * Set up groups of files as sources + * + * @param array $options controller and Minify options + * + * @return array Minify options + */ + public function setupSources($options) { + // PHP insecure by default: realpath() and other FS functions can't handle null bytes. + foreach (array('g', 'b', 'f') as $key) { + if (isset($_GET[$key])) { + $_GET[$key] = str_replace("\x00", '', (string)$_GET[$key]); + } + } + + // filter controller options + $cOptions = array_merge( + array( + 'allowDirs' => '//' + ,'groupsOnly' => false + ,'groups' => array() + ,'noMinPattern' => '@[-\\.]min\\.(?:js|css)$@i' // matched against basename + ) + ,(isset($options['minApp']) ? $options['minApp'] : array()) + ); + unset($options['minApp']); + $sources = array(); + $this->selectionId = ''; + $firstMissingResource = null; + if (isset($_GET['g'])) { + // add group(s) + $this->selectionId .= 'g=' . $_GET['g']; + $keys = explode(',', $_GET['g']); + if ($keys != array_unique($keys)) { + $this->log("Duplicate group key found."); + return $options; + } + $keys = explode(',', $_GET['g']); + foreach ($keys as $key) { + if (! isset($cOptions['groups'][$key])) { + $this->log("A group configuration for \"{$key}\" was not found"); + return $options; + } + $files = $cOptions['groups'][$key]; + // if $files is a single object, casting will break it + if (is_object($files)) { + $files = array($files); + } elseif (! is_array($files)) { + $files = (array)$files; + } + foreach ($files as $file) { + if ($file instanceof Minify_Source) { + $sources[] = $file; + continue; + } + if (0 === strpos($file, '//')) { + $file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1); + } + $realpath = realpath($file); + if ($realpath && is_file($realpath)) { + $sources[] = $this->_getFileSource($realpath, $cOptions); + } else { + $this->log("The path \"{$file}\" (realpath \"{$realpath}\") could not be found (or was not a file)"); + if (null === $firstMissingResource) { + $firstMissingResource = basename($file); + continue; + } else { + $secondMissingResource = basename($file); + $this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource'"); + return $options; + } + } + } + if ($sources) { + try { + $this->checkType($sources[0]); + } catch (Exception $e) { + $this->log($e->getMessage()); + return $options; + } + } + } + } + if (! $cOptions['groupsOnly'] && isset($_GET['f'])) { + // try user files + // The following restrictions are to limit the URLs that minify will + // respond to. + if (// verify at least one file, files are single comma separated, + // and are all same extension + ! preg_match('/^[^,]+\\.(css|js)(?:,[^,]+\\.\\1)*$/', $_GET['f'], $m) + // no "//" + || strpos($_GET['f'], '//') !== false + // no "\" + || strpos($_GET['f'], '\\') !== false + ) { + $this->log("GET param 'f' was invalid"); + return $options; + } + $ext = ".{$m[1]}"; + try { + $this->checkType($m[1]); + } catch (Exception $e) { + $this->log($e->getMessage()); + return $options; + } + $files = explode(',', $_GET['f']); + if ($files != array_unique($files)) { + $this->log("Duplicate files were specified"); + return $options; + } + if (isset($_GET['b'])) { + // check for validity + if (preg_match('@^[^/]+(?:/[^/]+)*$@', $_GET['b']) + && false === strpos($_GET['b'], '..') + && $_GET['b'] !== '.') { + // valid base + $base = "/{$_GET['b']}/"; + } else { + $this->log("GET param 'b' was invalid"); + return $options; + } + } else { + $base = '/'; + } + $allowDirs = array(); + foreach ((array)$cOptions['allowDirs'] as $allowDir) { + $allowDirs[] = realpath(str_replace('//', $_SERVER['DOCUMENT_ROOT'] . '/', $allowDir)); + } + $basenames = array(); // just for cache id + foreach ($files as $file) { + $uri = $base . $file; + $path = $_SERVER['DOCUMENT_ROOT'] . $uri; + $realpath = realpath($path); + if (false === $realpath || ! is_file($realpath)) { + $this->log("The path \"{$path}\" (realpath \"{$realpath}\") could not be found (or was not a file)"); + if (null === $firstMissingResource) { + $firstMissingResource = $uri; + continue; + } else { + $secondMissingResource = $uri; + $this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource`'"); + return $options; + } + } + try { + parent::checkNotHidden($realpath); + parent::checkAllowDirs($realpath, $allowDirs, $uri); + } catch (Exception $e) { + $this->log($e->getMessage()); + return $options; + } + $sources[] = $this->_getFileSource($realpath, $cOptions); + $basenames[] = basename($realpath, $ext); + } + if ($this->selectionId) { + $this->selectionId .= '_f='; + } + $this->selectionId .= implode(',', $basenames) . $ext; + } + if ($sources) { + if (null !== $firstMissingResource) { + array_unshift($sources, new Minify_Source(array( + 'id' => 'missingFile' + // should not cause cache invalidation + ,'lastModified' => 0 + // due to caching, filename is unreliable. + ,'content' => "/* Minify: at least one missing file. See " . Minify::URL_DEBUG . " */\n" + ,'minifier' => '' + ))); + } + $this->sources = $sources; + } else { + $this->log("No sources to serve"); + } + return $options; + } + + /** + * @param string $file + * + * @param array $cOptions + * + * @return Minify_Source + */ + protected function _getFileSource($file, $cOptions) + { + $spec['filepath'] = $file; + if ($cOptions['noMinPattern'] && preg_match($cOptions['noMinPattern'], basename($file))) { + if (preg_match('~\.css$~i', $file)) { + $spec['minifyOptions']['compress'] = false; + } else { + $spec['minifier'] = ''; + } + } + return new Minify_Source($spec); + } + + protected $_type = null; + + /** + * Make sure that only source files of a single type are registered + * + * @param string $sourceOrExt + * + * @throws Exception + */ + public function checkType($sourceOrExt) + { + if ($sourceOrExt === 'js') { + $type = Minify::TYPE_JS; + } elseif ($sourceOrExt === 'css') { + $type = Minify::TYPE_CSS; + } elseif ($sourceOrExt->contentType !== null) { + $type = $sourceOrExt->contentType; + } else { + return; + } + if ($this->_type === null) { + $this->_type = $type; + } elseif ($this->_type !== $type) { + throw new Exception('Content-Type mismatch'); + } + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Controller/Page.php b/vendor/mrclay/minify/min/lib/Minify/Controller/Page.php new file mode 100644 index 0000000000..1095fb46fe --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Controller/Page.php @@ -0,0 +1,68 @@ + + */ +class Minify_Controller_Page extends Minify_Controller_Base { + + /** + * Set up source of HTML content + * + * @param array $options controller and Minify options + * @return array Minify options + * + * Controller options: + * + * 'content': (required) HTML markup + * + * 'id': (required) id of page (string for use in server-side caching) + * + * 'lastModifiedTime': timestamp of when this content changed. This + * is recommended to allow both server and client-side caching. + * + * 'minifyAll': should all CSS and Javascript blocks be individually + * minified? (default false) + * + * @todo Add 'file' option to read HTML file. + */ + public function setupSources($options) { + if (isset($options['file'])) { + $sourceSpec = array( + 'filepath' => $options['file'] + ); + $f = $options['file']; + } else { + // strip controller options + $sourceSpec = array( + 'content' => $options['content'] + ,'id' => $options['id'] + ); + $f = $options['id']; + unset($options['content'], $options['id']); + } + // something like "builder,index.php" or "directory,file.html" + $this->selectionId = strtr(substr($f, 1 + strlen(dirname(dirname($f)))), '/\\', ',,'); + + if (isset($options['minifyAll'])) { + // this will be the 2nd argument passed to Minify_HTML::minify() + $sourceSpec['minifyOptions'] = array( + 'cssMinifier' => array('Minify_CSS', 'minify') + ,'jsMinifier' => array('JSMin', 'minify') + ); + unset($options['minifyAll']); + } + $this->sources[] = new Minify_Source($sourceSpec); + + $options['contentType'] = Minify::TYPE_HTML; + return $options; + } +} + diff --git a/vendor/mrclay/minify/min/lib/Minify/Controller/Version1.php b/vendor/mrclay/minify/min/lib/Minify/Controller/Version1.php new file mode 100644 index 0000000000..91fcf61448 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Controller/Version1.php @@ -0,0 +1,119 @@ + + * Minify::serve('Version1'); + * + * + * @package Minify + * @author Stephen Clay + */ +class Minify_Controller_Version1 extends Minify_Controller_Base { + + /** + * Set up groups of files as sources + * + * @param array $options controller and Minify options + * @return array Minify options + * + */ + public function setupSources($options) { + // PHP insecure by default: realpath() and other FS functions can't handle null bytes. + if (isset($_GET['files'])) { + $_GET['files'] = str_replace("\x00", '', (string)$_GET['files']); + } + + self::_setupDefines(); + if (MINIFY_USE_CACHE) { + $cacheDir = defined('MINIFY_CACHE_DIR') + ? MINIFY_CACHE_DIR + : ''; + Minify::setCache($cacheDir); + } + $options['badRequestHeader'] = 'HTTP/1.0 404 Not Found'; + $options['contentTypeCharset'] = MINIFY_ENCODING; + + // The following restrictions are to limit the URLs that minify will + // respond to. Ideally there should be only one way to reference a file. + if (! isset($_GET['files']) + // verify at least one file, files are single comma separated, + // and are all same extension + || ! preg_match('/^[^,]+\\.(css|js)(,[^,]+\\.\\1)*$/', $_GET['files'], $m) + // no "//" (makes URL rewriting easier) + || strpos($_GET['files'], '//') !== false + // no "\" + || strpos($_GET['files'], '\\') !== false + // no "./" + || preg_match('/(?:^|[^\\.])\\.\\//', $_GET['files']) + ) { + return $options; + } + + $files = explode(',', $_GET['files']); + if (count($files) > MINIFY_MAX_FILES) { + return $options; + } + + // strings for prepending to relative/absolute paths + $prependRelPaths = dirname($_SERVER['SCRIPT_FILENAME']) + . DIRECTORY_SEPARATOR; + $prependAbsPaths = $_SERVER['DOCUMENT_ROOT']; + + $goodFiles = array(); + $hasBadSource = false; + + $allowDirs = isset($options['allowDirs']) + ? $options['allowDirs'] + : MINIFY_BASE_DIR; + + foreach ($files as $file) { + // prepend appropriate string for abs/rel paths + $file = ($file[0] === '/' ? $prependAbsPaths : $prependRelPaths) . $file; + // make sure a real file! + $file = realpath($file); + // don't allow unsafe or duplicate files + if (parent::_fileIsSafe($file, $allowDirs) + && !in_array($file, $goodFiles)) + { + $goodFiles[] = $file; + $srcOptions = array( + 'filepath' => $file + ); + $this->sources[] = new Minify_Source($srcOptions); + } else { + $hasBadSource = true; + break; + } + } + if ($hasBadSource) { + $this->sources = array(); + } + if (! MINIFY_REWRITE_CSS_URLS) { + $options['rewriteCssUris'] = false; + } + return $options; + } + + private static function _setupDefines() + { + $defaults = array( + 'MINIFY_BASE_DIR' => realpath($_SERVER['DOCUMENT_ROOT']) + ,'MINIFY_ENCODING' => 'utf-8' + ,'MINIFY_MAX_FILES' => 16 + ,'MINIFY_REWRITE_CSS_URLS' => true + ,'MINIFY_USE_CACHE' => true + ); + foreach ($defaults as $const => $val) { + if (! defined($const)) { + define($const, $val); + } + } + } +} + diff --git a/vendor/mrclay/minify/min/lib/Minify/DebugDetector.php b/vendor/mrclay/minify/min/lib/Minify/DebugDetector.php new file mode 100644 index 0000000000..1def97484f --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/DebugDetector.php @@ -0,0 +1,26 @@ + + */ +class Minify_DebugDetector { + public static function shouldDebugRequest($cookie, $get, $requestUri) + { + if (isset($get['debug'])) { + return true; + } + if (! empty($cookie['minifyDebug'])) { + foreach (preg_split('/\\s+/', $cookie['minifyDebug']) as $debugUri) { + $pattern = '@' . preg_quote($debugUri, '@') . '@i'; + $pattern = str_replace(array('\\*', '\\?'), array('.*', '.'), $pattern); + if (preg_match($pattern, $requestUri)) { + return true; + } + } + } + return false; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/HTML.php b/vendor/mrclay/minify/min/lib/Minify/HTML.php new file mode 100644 index 0000000000..40f7307610 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/HTML.php @@ -0,0 +1,255 @@ + + */ +class Minify_HTML { + /** + * @var boolean + */ + protected $_jsCleanComments = true; + + /** + * "Minify" an HTML page + * + * @param string $html + * + * @param array $options + * + * 'cssMinifier' : (optional) callback function to process content of STYLE + * elements. + * + * 'jsMinifier' : (optional) callback function to process content of SCRIPT + * elements. Note: the type attribute is ignored. + * + * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If + * unset, minify will sniff for an XHTML doctype. + * + * @return string + */ + public static function minify($html, $options = array()) { + $min = new self($html, $options); + return $min->process(); + } + + + /** + * Create a minifier object + * + * @param string $html + * + * @param array $options + * + * 'cssMinifier' : (optional) callback function to process content of STYLE + * elements. + * + * 'jsMinifier' : (optional) callback function to process content of SCRIPT + * elements. Note: the type attribute is ignored. + * + * 'jsCleanComments' : (optional) whether to remove HTML comments beginning and end of script block + * + * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If + * unset, minify will sniff for an XHTML doctype. + */ + public function __construct($html, $options = array()) + { + $this->_html = str_replace("\r\n", "\n", trim($html)); + if (isset($options['xhtml'])) { + $this->_isXhtml = (bool)$options['xhtml']; + } + if (isset($options['cssMinifier'])) { + $this->_cssMinifier = $options['cssMinifier']; + } + if (isset($options['jsMinifier'])) { + $this->_jsMinifier = $options['jsMinifier']; + } + if (isset($options['jsCleanComments'])) { + $this->_jsCleanComments = (bool)$options['jsCleanComments']; + } + } + + + /** + * Minify the markeup given in the constructor + * + * @return string + */ + public function process() + { + if ($this->_isXhtml === null) { + $this->_isXhtml = (false !== strpos($this->_html, '_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']); + $this->_placeholders = array(); + + // replace SCRIPTs (and minify) with placeholders + $this->_html = preg_replace_callback( + '/(\\s*)]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i' + ,array($this, '_removeScriptCB') + ,$this->_html); + + // replace STYLEs (and minify) with placeholders + $this->_html = preg_replace_callback( + '/\\s*]*>)([\\s\\S]*?)<\\/style>\\s*/i' + ,array($this, '_removeStyleCB') + ,$this->_html); + + // remove HTML comments (not containing IE conditional comments). + $this->_html = preg_replace_callback( + '//' + ,array($this, '_commentCB') + ,$this->_html); + + // replace PREs with placeholders + $this->_html = preg_replace_callback('/\\s*]*?>[\\s\\S]*?<\\/pre>)\\s*/i' + ,array($this, '_removePreCB') + ,$this->_html); + + // replace TEXTAREAs with placeholders + $this->_html = preg_replace_callback( + '/\\s*]*?>[\\s\\S]*?<\\/textarea>)\\s*/i' + ,array($this, '_removeTextareaCB') + ,$this->_html); + + // trim each line. + // @todo take into account attribute values that span multiple lines. + $this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html); + + // remove ws around block/undisplayed elements + $this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body' + .'|caption|center|col(?:group)?|dd|dir|div|dl|dt|fieldset|form' + .'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta' + .'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)' + .'|ul)\\b[^>]*>)/i', '$1', $this->_html); + + // remove ws outside of all elements + $this->_html = preg_replace( + '/>(\\s(?:\\s*))?([^<]+)(\\s(?:\s*))?$1$2$3<' + ,$this->_html); + + // use newlines before 1st attribute in open tags (to limit line lengths) + $this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html); + + // fill placeholders + $this->_html = str_replace( + array_keys($this->_placeholders) + ,array_values($this->_placeholders) + ,$this->_html + ); + // issue 229: multi-pass to catch scripts that didn't get replaced in textareas + $this->_html = str_replace( + array_keys($this->_placeholders) + ,array_values($this->_placeholders) + ,$this->_html + ); + return $this->_html; + } + + protected function _commentCB($m) + { + return (0 === strpos($m[1], '[') || false !== strpos($m[1], '_replacementHash . count($this->_placeholders) . '%'; + $this->_placeholders[$placeholder] = $content; + return $placeholder; + } + + protected $_isXhtml = null; + protected $_replacementHash = null; + protected $_placeholders = array(); + protected $_cssMinifier = null; + protected $_jsMinifier = null; + + protected function _removePreCB($m) + { + return $this->_reservePlace("_reservePlace("\\s*$)/', '', $css); + + // remove CDATA section markers + $css = $this->_removeCdata($css); + + // minify + $minifier = $this->_cssMinifier + ? $this->_cssMinifier + : 'trim'; + $css = call_user_func($minifier, $css); + + return $this->_reservePlace($this->_needsCdata($css) + ? "{$openStyle}/**/" + : "{$openStyle}{$css}" + ); + } + + protected function _removeScriptCB($m) + { + $openScript = "_jsCleanComments) { + $js = preg_replace('/(?:^\\s*\\s*$)/', '', $js); + } + + // remove CDATA section markers + $js = $this->_removeCdata($js); + + // minify + $minifier = $this->_jsMinifier + ? $this->_jsMinifier + : 'trim'; + $js = call_user_func($minifier, $js); + + return $this->_reservePlace($this->_needsCdata($js) + ? "{$ws1}{$openScript}/**/{$ws2}" + : "{$ws1}{$openScript}{$js}{$ws2}" + ); + } + + protected function _removeCdata($str) + { + return (false !== strpos($str, ''), '', $str) + : $str; + } + + protected function _needsCdata($str) + { + return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str)); + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/HTML/Helper.php b/vendor/mrclay/minify/min/lib/Minify/HTML/Helper.php new file mode 100644 index 0000000000..f92ab854c1 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/HTML/Helper.php @@ -0,0 +1,225 @@ + + */ +class Minify_HTML_Helper { + public $rewriteWorks = true; + public $minAppUri = '/min'; + public $groupsConfigFile = ''; + + /** + * Get an HTML-escaped Minify URI for a group or set of files + * + * @param string|array $keyOrFiles a group key or array of filepaths/URIs + * @param array $opts options: + * 'farExpires' : (default true) append a modified timestamp for cache revving + * 'debug' : (default false) append debug flag + * 'charset' : (default 'UTF-8') for htmlspecialchars + * 'minAppUri' : (default '/min') URI of min directory + * 'rewriteWorks' : (default true) does mod_rewrite work in min app? + * 'groupsConfigFile' : specify if different + * @return string + */ + public static function getUri($keyOrFiles, $opts = array()) + { + $opts = array_merge(array( // default options + 'farExpires' => true + ,'debug' => false + ,'charset' => 'UTF-8' + ,'minAppUri' => '/min' + ,'rewriteWorks' => true + ,'groupsConfigFile' => '' + ), $opts); + $h = new self; + $h->minAppUri = $opts['minAppUri']; + $h->rewriteWorks = $opts['rewriteWorks']; + $h->groupsConfigFile = $opts['groupsConfigFile']; + if (is_array($keyOrFiles)) { + $h->setFiles($keyOrFiles, $opts['farExpires']); + } else { + $h->setGroup($keyOrFiles, $opts['farExpires']); + } + $uri = $h->getRawUri($opts['farExpires'], $opts['debug']); + return htmlspecialchars($uri, ENT_QUOTES, $opts['charset']); + } + + /** + * Get non-HTML-escaped URI to minify the specified files + * + * @param bool $farExpires + * @param bool $debug + * @return string + */ + public function getRawUri($farExpires = true, $debug = false) + { + $path = rtrim($this->minAppUri, '/') . '/'; + if (! $this->rewriteWorks) { + $path .= '?'; + } + if (null === $this->_groupKey) { + // @todo: implement shortest uri + $path = self::_getShortestUri($this->_filePaths, $path); + } else { + $path .= "g=" . $this->_groupKey; + } + if ($debug) { + $path .= "&debug"; + } elseif ($farExpires && $this->_lastModified) { + $path .= "&" . $this->_lastModified; + } + return $path; + } + + /** + * Set the files that will comprise the URI we're building + * + * @param array $files + * @param bool $checkLastModified + */ + public function setFiles($files, $checkLastModified = true) + { + $this->_groupKey = null; + if ($checkLastModified) { + $this->_lastModified = self::getLastModified($files); + } + // normalize paths like in /min/f= + foreach ($files as $k => $file) { + if (0 === strpos($file, '//')) { + $file = substr($file, 2); + } elseif (0 === strpos($file, '/') + || 1 === strpos($file, ':\\')) { + $file = substr($file, strlen($_SERVER['DOCUMENT_ROOT']) + 1); + } + $file = strtr($file, '\\', '/'); + $files[$k] = $file; + } + $this->_filePaths = $files; + } + + /** + * Set the group of files that will comprise the URI we're building + * + * @param string $key + * @param bool $checkLastModified + */ + public function setGroup($key, $checkLastModified = true) + { + $this->_groupKey = $key; + if ($checkLastModified) { + if (! $this->groupsConfigFile) { + $this->groupsConfigFile = dirname(dirname(dirname(dirname(__FILE__)))) . '/groupsConfig.php'; + } + if (is_file($this->groupsConfigFile)) { + $gc = (require $this->groupsConfigFile); + $keys = explode(',', $key); + foreach ($keys as $key) { + if (isset($gc[$key])) { + $this->_lastModified = self::getLastModified($gc[$key], $this->_lastModified); + } + } + } + } + } + + /** + * Get the max(lastModified) of all files + * + * @param array|string $sources + * @param int $lastModified + * @return int + */ + public static function getLastModified($sources, $lastModified = 0) + { + $max = $lastModified; + foreach ((array)$sources as $source) { + if (is_object($source) && isset($source->lastModified)) { + $max = max($max, $source->lastModified); + } elseif (is_string($source)) { + if (0 === strpos($source, '//')) { + $source = $_SERVER['DOCUMENT_ROOT'] . substr($source, 1); + } + if (is_file($source)) { + $max = max($max, filemtime($source)); + } + } + } + return $max; + } + + protected $_groupKey = null; // if present, URI will be like g=... + protected $_filePaths = array(); + protected $_lastModified = null; + + + /** + * In a given array of strings, find the character they all have at + * a particular index + * + * @param array $arr array of strings + * @param int $pos index to check + * @return mixed a common char or '' if any do not match + */ + protected static function _getCommonCharAtPos($arr, $pos) { + if (!isset($arr[0][$pos])) { + return ''; + } + $c = $arr[0][$pos]; + $l = count($arr); + if ($l === 1) { + return $c; + } + for ($i = 1; $i < $l; ++$i) { + if ($arr[$i][$pos] !== $c) { + return ''; + } + } + return $c; + } + + /** + * Get the shortest URI to minify the set of source files + * + * @param array $paths root-relative URIs of files + * @param string $minRoot root-relative URI of the "min" application + * @return string + */ + protected static function _getShortestUri($paths, $minRoot = '/min/') { + $pos = 0; + $base = ''; + while (true) { + $c = self::_getCommonCharAtPos($paths, $pos); + if ($c === '') { + break; + } else { + $base .= $c; + } + ++$pos; + } + $base = preg_replace('@[^/]+$@', '', $base); + $uri = $minRoot . 'f=' . implode(',', $paths); + + if (substr($base, -1) === '/') { + // we have a base dir! + $basedPaths = $paths; + $l = count($paths); + for ($i = 0; $i < $l; ++$i) { + $basedPaths[$i] = substr($paths[$i], strlen($base)); + } + $base = substr($base, 0, strlen($base) - 1); + $bUri = $minRoot . 'b=' . $base . '&f=' . implode(',', $basedPaths); + + $uri = strlen($uri) < strlen($bUri) + ? $uri + : $bUri; + } + return $uri; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/ImportProcessor.php b/vendor/mrclay/minify/min/lib/Minify/ImportProcessor.php new file mode 100644 index 0000000000..bdfae547d7 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/ImportProcessor.php @@ -0,0 +1,216 @@ + + * @author Simon Schick + */ +class Minify_ImportProcessor { + + public static $filesIncluded = array(); + + public static function process($file) + { + self::$filesIncluded = array(); + self::$_isCss = (strtolower(substr($file, -4)) === '.css'); + $obj = new Minify_ImportProcessor(dirname($file)); + return $obj->_getContent($file); + } + + // allows callback funcs to know the current directory + private $_currentDir = null; + + // allows callback funcs to know the directory of the file that inherits this one + private $_previewsDir = null; + + // allows _importCB to write the fetched content back to the obj + private $_importedContent = ''; + + private static $_isCss = null; + + /** + * @param String $currentDir + * @param String $previewsDir Is only used internally + */ + private function __construct($currentDir, $previewsDir = "") + { + $this->_currentDir = $currentDir; + $this->_previewsDir = $previewsDir; + } + + private function _getContent($file, $is_imported = false) + { + $file = realpath($file); + if (! $file + || in_array($file, self::$filesIncluded) + || false === ($content = @file_get_contents($file)) + ) { + // file missing, already included, or failed read + return ''; + } + self::$filesIncluded[] = realpath($file); + $this->_currentDir = dirname($file); + + // remove UTF-8 BOM if present + if (pack("CCC",0xef,0xbb,0xbf) === substr($content, 0, 3)) { + $content = substr($content, 3); + } + // ensure uniform EOLs + $content = str_replace("\r\n", "\n", $content); + + // process @imports + $content = preg_replace_callback( + '/ + @import\\s+ + (?:url\\(\\s*)? # maybe url( + [\'"]? # maybe quote + (.*?) # 1 = URI + [\'"]? # maybe end quote + (?:\\s*\\))? # maybe ) + ([a-zA-Z,\\s]*)? # 2 = media list + ; # end token + /x' + ,array($this, '_importCB') + ,$content + ); + + // You only need to rework the import-path if the script is imported + if (self::$_isCss && $is_imported) { + // rewrite remaining relative URIs + $content = preg_replace_callback( + '/url\\(\\s*([^\\)\\s]+)\\s*\\)/' + ,array($this, '_urlCB') + ,$content + ); + } + + return $this->_importedContent . $content; + } + + private function _importCB($m) + { + $url = $m[1]; + $mediaList = preg_replace('/\\s+/', '', $m[2]); + + if (strpos($url, '://') > 0) { + // protocol, leave in place for CSS, comment for JS + return self::$_isCss + ? $m[0] + : "/* Minify_ImportProcessor will not include remote content */"; + } + if ('/' === $url[0]) { + // protocol-relative or root path + $url = ltrim($url, '/'); + $file = realpath($_SERVER['DOCUMENT_ROOT']) . DIRECTORY_SEPARATOR + . strtr($url, '/', DIRECTORY_SEPARATOR); + } else { + // relative to current path + $file = $this->_currentDir . DIRECTORY_SEPARATOR + . strtr($url, '/', DIRECTORY_SEPARATOR); + } + $obj = new Minify_ImportProcessor(dirname($file), $this->_currentDir); + $content = $obj->_getContent($file, true); + if ('' === $content) { + // failed. leave in place for CSS, comment for JS + return self::$_isCss + ? $m[0] + : "/* Minify_ImportProcessor could not fetch '{$file}' */"; + } + return (!self::$_isCss || preg_match('@(?:^$|\\ball\\b)@', $mediaList)) + ? $content + : "@media {$mediaList} {\n{$content}\n}\n"; + } + + private function _urlCB($m) + { + // $m[1] is either quoted or not + $quote = ($m[1][0] === "'" || $m[1][0] === '"') + ? $m[1][0] + : ''; + $url = ($quote === '') + ? $m[1] + : substr($m[1], 1, strlen($m[1]) - 2); + if ('/' !== $url[0]) { + if (strpos($url, '//') > 0) { + // probably starts with protocol, do not alter + } else { + // prepend path with current dir separator (OS-independent) + $path = $this->_currentDir + . DIRECTORY_SEPARATOR . strtr($url, '/', DIRECTORY_SEPARATOR); + // update the relative path by the directory of the file that imported this one + $url = self::getPathDiff(realpath($this->_previewsDir), $path); + } + } + return "url({$quote}{$url}{$quote})"; + } + + /** + * @param string $from + * @param string $to + * @param string $ps + * @return string + */ + private function getPathDiff($from, $to, $ps = DIRECTORY_SEPARATOR) + { + $realFrom = $this->truepath($from); + $realTo = $this->truepath($to); + + $arFrom = explode($ps, rtrim($realFrom, $ps)); + $arTo = explode($ps, rtrim($realTo, $ps)); + while (count($arFrom) && count($arTo) && ($arFrom[0] == $arTo[0])) + { + array_shift($arFrom); + array_shift($arTo); + } + return str_pad("", count($arFrom) * 3, '..' . $ps) . implode($ps, $arTo); + } + + /** + * This function is to replace PHP's extremely buggy realpath(). + * @param string $path The original path, can be relative etc. + * @return string The resolved path, it might not exist. + * @see http://stackoverflow.com/questions/4049856/replace-phps-realpath + */ + function truepath($path) + { + // whether $path is unix or not + $unipath = strlen($path) == 0 || $path{0} != '/'; + // attempts to detect if path is relative in which case, add cwd + if (strpos($path, ':') === false && $unipath) + $path = $this->_currentDir . DIRECTORY_SEPARATOR . $path; + + // resolve path parts (single dot, double dot and double delimiters) + $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path); + $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen'); + $absolutes = array(); + foreach ($parts as $part) { + if ('.' == $part) + continue; + if ('..' == $part) { + array_pop($absolutes); + } else { + $absolutes[] = $part; + } + } + $path = implode(DIRECTORY_SEPARATOR, $absolutes); + // resolve any symlinks + if (file_exists($path) && linkinfo($path) > 0) + $path = readlink($path); + // put initial separator that could have been lost + $path = !$unipath ? '/' . $path : $path; + return $path; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/JS/ClosureCompiler.php b/vendor/mrclay/minify/min/lib/Minify/JS/ClosureCompiler.php new file mode 100644 index 0000000000..e067d7c85e --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/JS/ClosureCompiler.php @@ -0,0 +1,230 @@ + + * + * @todo can use a stream wrapper to unit test this? + */ +class Minify_JS_ClosureCompiler { + + /** + * @var string The option key for the maximum POST byte size + */ + const OPTION_MAX_BYTES = 'maxBytes'; + + /** + * @var string The option key for additional params. @see __construct + */ + const OPTION_ADDITIONAL_OPTIONS = 'additionalParams'; + + /** + * @var string The option key for the fallback Minifier + */ + const OPTION_FALLBACK_FUNCTION = 'fallbackFunc'; + + /** + * @var string The option key for the service URL + */ + const OPTION_COMPILER_URL = 'compilerUrl'; + + /** + * @var int The default maximum POST byte size according to https://developers.google.com/closure/compiler/docs/api-ref + */ + const DEFAULT_MAX_BYTES = 200000; + + /** + * @var string[] $DEFAULT_OPTIONS The default options to pass to the compiler service + * + * @note This would be a constant if PHP allowed it + */ + private static $DEFAULT_OPTIONS = array( + 'output_format' => 'text', + 'compilation_level' => 'SIMPLE_OPTIMIZATIONS' + ); + + /** + * @var string $url URL of compiler server. defaults to Google's + */ + protected $serviceUrl = 'http://closure-compiler.appspot.com/compile'; + + /** + * @var int $maxBytes The maximum JS size that can be sent to the compiler server in bytes + */ + protected $maxBytes = self::DEFAULT_MAX_BYTES; + + /** + * @var string[] $additionalOptions Additional options to pass to the compiler service + */ + protected $additionalOptions = array(); + + /** + * @var callable Function to minify JS if service fails. Default is JSMin + */ + protected $fallbackMinifier = array('JSMin', 'minify'); + + /** + * Minify JavaScript code via HTTP request to a Closure Compiler API + * + * @param string $js input code + * @param array $options Options passed to __construct(). @see __construct + * + * @return string + */ + public static function minify($js, array $options = array()) + { + $obj = new self($options); + return $obj->min($js); + } + + /** + * @param array $options Options with keys available below: + * + * fallbackFunc : (callable) function to minify if service unavailable. Default is JSMin. + * + * compilerUrl : (string) URL to closure compiler server + * + * maxBytes : (int) The maximum amount of bytes to be sent as js_code in the POST request. + * Defaults to 200000. + * + * additionalParams : (string[]) Additional parameters to pass to the compiler server. Can be anything named + * in https://developers.google.com/closure/compiler/docs/api-ref except for js_code and + * output_info + */ + public function __construct(array $options = array()) + { + if (isset($options[self::OPTION_FALLBACK_FUNCTION])) { + $this->fallbackMinifier = $options[self::OPTION_FALLBACK_FUNCTION]; + } + if (isset($options[self::OPTION_COMPILER_URL])) { + $this->serviceUrl = $options[self::OPTION_COMPILER_URL]; + } + if (isset($options[self::OPTION_ADDITIONAL_OPTIONS]) && is_array($options[self::OPTION_ADDITIONAL_OPTIONS])) { + $this->additionalOptions = $options[self::OPTION_ADDITIONAL_OPTIONS]; + } + if (isset($options[self::OPTION_MAX_BYTES])) { + $this->maxBytes = (int) $options[self::OPTION_MAX_BYTES]; + } + } + + /** + * Call the service to perform the minification + * + * @param string $js JavaScript code + * @return string + * @throws Minify_JS_ClosureCompiler_Exception + */ + public function min($js) + { + $postBody = $this->buildPostBody($js); + + if ($this->maxBytes > 0) { + $bytes = (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) + ? mb_strlen($postBody, '8bit') + : strlen($postBody); + if ($bytes > $this->maxBytes) { + throw new Minify_JS_ClosureCompiler_Exception( + 'POST content larger than ' . $this->maxBytes . ' bytes' + ); + } + } + + $response = $this->getResponse($postBody); + + if (preg_match('/^Error\(\d\d?\):/', $response)) { + if (is_callable($this->fallbackMinifier)) { + // use fallback + $response = "/* Received errors from Closure Compiler API:\n$response" + . "\n(Using fallback minifier)\n*/\n"; + $response .= call_user_func($this->fallbackMinifier, $js); + } else { + throw new Minify_JS_ClosureCompiler_Exception($response); + } + } + + if ($response === '') { + $errors = $this->getResponse($this->buildPostBody($js, true)); + throw new Minify_JS_ClosureCompiler_Exception($errors); + } + + return $response; + } + + /** + * Get the response for a given POST body + * + * @param string $postBody + * @return string + * @throws Minify_JS_ClosureCompiler_Exception + */ + protected function getResponse($postBody) + { + $allowUrlFopen = preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen')); + + if ($allowUrlFopen) { + $contents = file_get_contents($this->serviceUrl, false, stream_context_create(array( + 'http' => array( + 'method' => 'POST', + 'header' => "Content-type: application/x-www-form-urlencoded\r\nConnection: close\r\n", + 'content' => $postBody, + 'max_redirects' => 0, + 'timeout' => 15, + ) + ))); + } elseif (defined('CURLOPT_POST')) { + $ch = curl_init($this->serviceUrl); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded')); + curl_setopt($ch, CURLOPT_POSTFIELDS, $postBody); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15); + $contents = curl_exec($ch); + curl_close($ch); + } else { + throw new Minify_JS_ClosureCompiler_Exception( + "Could not make HTTP request: allow_url_open is false and cURL not available" + ); + } + + if (false === $contents) { + throw new Minify_JS_ClosureCompiler_Exception( + "No HTTP response from server" + ); + } + + return trim($contents); + } + + /** + * Build a POST request body + * + * @param string $js JavaScript code + * @param bool $returnErrors + * @return string + */ + protected function buildPostBody($js, $returnErrors = false) + { + return http_build_query( + array_merge( + self::$DEFAULT_OPTIONS, + $this->additionalOptions, + array( + 'js_code' => $js, + 'output_info' => ($returnErrors ? 'errors' : 'compiled_code') + ) + ), + null, + '&' + ); + } +} + +class Minify_JS_ClosureCompiler_Exception extends Exception {} diff --git a/vendor/mrclay/minify/min/lib/Minify/Lines.php b/vendor/mrclay/minify/min/lib/Minify/Lines.php new file mode 100644 index 0000000000..e999a6c2b5 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Lines.php @@ -0,0 +1,143 @@ + + * @author Adam Pedersen (Issue 55 fix) + */ +class Minify_Lines { + + /** + * Add line numbers in C-style comments + * + * This uses a very basic parser easily fooled by comment tokens inside + * strings or regexes, but, otherwise, generally clean code will not be + * mangled. URI rewriting can also be performed. + * + * @param string $content + * + * @param array $options available options: + * + * 'id': (optional) string to identify file. E.g. file name/path + * + * 'currentDir': (default null) if given, this is assumed to be the + * directory of the current CSS file. Using this, minify will rewrite + * all relative URIs in import/url declarations to correctly point to + * the desired files, and prepend a comment with debugging information about + * this process. + * + * @return string + */ + public static function minify($content, $options = array()) + { + $id = (isset($options['id']) && $options['id']) + ? $options['id'] + : ''; + $content = str_replace("\r\n", "\n", $content); + + // Hackily rewrite strings with XPath expressions that are + // likely to throw off our dumb parser (for Prototype 1.6.1). + $content = str_replace('"/*"', '"/"+"*"', $content); + $content = preg_replace('@([\'"])(\\.?//?)\\*@', '$1$2$1+$1*', $content); + + $lines = explode("\n", $content); + $numLines = count($lines); + // determine left padding + $padTo = strlen((string) $numLines); // e.g. 103 lines = 3 digits + $inComment = false; + $i = 0; + $newLines = array(); + while (null !== ($line = array_shift($lines))) { + if (('' !== $id) && (0 == $i % 50)) { + if ($inComment) { + array_push($newLines, '', "/* {$id} *|", ''); + } else { + array_push($newLines, '', "/* {$id} */", ''); + } + } + ++$i; + $newLines[] = self::_addNote($line, $i, $inComment, $padTo); + $inComment = self::_eolInComment($line, $inComment); + } + $content = implode("\n", $newLines) . "\n"; + + // check for desired URI rewriting + if (isset($options['currentDir'])) { + Minify_CSS_UriRewriter::$debugText = ''; + $content = Minify_CSS_UriRewriter::rewrite( + $content + ,$options['currentDir'] + ,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT'] + ,isset($options['symlinks']) ? $options['symlinks'] : array() + ); + $content = "/* Minify_CSS_UriRewriter::\$debugText\n\n" + . Minify_CSS_UriRewriter::$debugText . "*/\n" + . $content; + } + + return $content; + } + + /** + * Is the parser within a C-style comment at the end of this line? + * + * @param string $line current line of code + * + * @param bool $inComment was the parser in a comment at the + * beginning of the line? + * + * @return bool + */ + private static function _eolInComment($line, $inComment) + { + // crude way to avoid things like // */ + $line = preg_replace('~//.*?(\\*/|/\\*).*~', '', $line); + + while (strlen($line)) { + $search = $inComment + ? '*/' + : '/*'; + $pos = strpos($line, $search); + if (false === $pos) { + return $inComment; + } else { + if ($pos == 0 + || ($inComment + ? substr($line, $pos, 3) + : substr($line, $pos-1, 3)) != '*/*') + { + $inComment = ! $inComment; + } + $line = substr($line, $pos + 2); + } + } + return $inComment; + } + + /** + * Prepend a comment (or note) to the given line + * + * @param string $line current line of code + * + * @param string $note content of note/comment + * + * @param bool $inComment was the parser in a comment at the + * beginning of the line? + * + * @param int $padTo minimum width of comment + * + * @return string + */ + private static function _addNote($line, $note, $inComment, $padTo) + { + return $inComment + ? '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' *| ' . $line + : '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' */ ' . $line; + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Loader.php b/vendor/mrclay/minify/min/lib/Minify/Loader.php new file mode 100644 index 0000000000..0a225c056c --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Loader.php @@ -0,0 +1,28 @@ + + */ +class Minify_Loader { + public function loadClass($class) + { + $file = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR; + $file .= strtr($class, "\\_", DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR) . '.php'; + if (is_readable($file)) { + require $file; + } + } + + static public function register() + { + $inst = new self(); + spl_autoload_register(array($inst, 'loadClass')); + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Logger.php b/vendor/mrclay/minify/min/lib/Minify/Logger.php new file mode 100644 index 0000000000..8eb72f4528 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Logger.php @@ -0,0 +1,47 @@ + + * + * @todo lose this singleton! pass log object in Minify::serve and distribute to others + */ +class Minify_Logger { + + /** + * Set logger object. + * + * The object should have a method "log" that accepts a value as 1st argument and + * an optional string label as the 2nd. + * + * @param mixed $obj or a "falsey" value to disable + * @return null + */ + public static function setLogger($obj = null) { + self::$_logger = $obj + ? $obj + : null; + } + + /** + * Pass a message to the logger (if set) + * + * @param string $msg message to log + * @return null + */ + public static function log($msg, $label = 'Minify') { + if (! self::$_logger) return; + self::$_logger->log($msg, $label); + } + + /** + * @var mixed logger object (like FirePHP) or null (i.e. no logger available) + */ + private static $_logger = null; +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Packer.php b/vendor/mrclay/minify/min/lib/Minify/Packer.php new file mode 100644 index 0000000000..949c3eef04 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Packer.php @@ -0,0 +1,37 @@ +pack()); + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/Source.php b/vendor/mrclay/minify/min/lib/Minify/Source.php new file mode 100644 index 0000000000..5a85d10d0d --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/Source.php @@ -0,0 +1,187 @@ + + */ +class Minify_Source { + + /** + * @var int time of last modification + */ + public $lastModified = null; + + /** + * @var callback minifier function specifically for this source. + */ + public $minifier = null; + + /** + * @var array minification options specific to this source. + */ + public $minifyOptions = null; + + /** + * @var string full path of file + */ + public $filepath = null; + + /** + * @var string HTTP Content Type (Minify requires one of the constants Minify::TYPE_*) + */ + public $contentType = null; + + /** + * Create a Minify_Source + * + * In the $spec array(), you can either provide a 'filepath' to an existing + * file (existence will not be checked!) or give 'id' (unique string for + * the content), 'content' (the string content) and 'lastModified' + * (unixtime of last update). + * + * As a shortcut, the controller will replace "//" at the beginning + * of a filepath with $_SERVER['DOCUMENT_ROOT'] . '/'. + * + * @param array $spec options + */ + public function __construct($spec) + { + if (isset($spec['filepath'])) { + if (0 === strpos($spec['filepath'], '//')) { + $spec['filepath'] = $_SERVER['DOCUMENT_ROOT'] . substr($spec['filepath'], 1); + } + $segments = explode('.', $spec['filepath']); + $ext = strtolower(array_pop($segments)); + switch ($ext) { + case 'js' : $this->contentType = 'application/x-javascript'; + break; + case 'css' : $this->contentType = 'text/css'; + break; + case 'htm' : // fallthrough + case 'html' : $this->contentType = 'text/html'; + break; + } + $this->filepath = $spec['filepath']; + $this->_id = $spec['filepath']; + $this->lastModified = filemtime($spec['filepath']) + // offset for Windows uploaders with out of sync clocks + + round(Minify::$uploaderHoursBehind * 3600); + } elseif (isset($spec['id'])) { + $this->_id = 'id::' . $spec['id']; + if (isset($spec['content'])) { + $this->_content = $spec['content']; + } else { + $this->_getContentFunc = $spec['getContentFunc']; + } + $this->lastModified = isset($spec['lastModified']) + ? $spec['lastModified'] + : time(); + } + if (isset($spec['contentType'])) { + $this->contentType = $spec['contentType']; + } + if (isset($spec['minifier'])) { + $this->minifier = $spec['minifier']; + } + if (isset($spec['minifyOptions'])) { + $this->minifyOptions = $spec['minifyOptions']; + } + } + + /** + * Get content + * + * @return string + */ + public function getContent() + { + $content = (null !== $this->filepath) + ? file_get_contents($this->filepath) + : ((null !== $this->_content) + ? $this->_content + : call_user_func($this->_getContentFunc, $this->_id) + ); + // remove UTF-8 BOM if present + return (pack("CCC",0xef,0xbb,0xbf) === substr($content, 0, 3)) + ? substr($content, 3) + : $content; + } + + /** + * Get id + * + * @return string + */ + public function getId() + { + return $this->_id; + } + + /** + * Verifies a single minification call can handle all sources + * + * @param array $sources Minify_Source instances + * + * @return bool true iff there no sources with specific minifier preferences. + */ + public static function haveNoMinifyPrefs($sources) + { + foreach ($sources as $source) { + if (null !== $source->minifier + || null !== $source->minifyOptions) { + return false; + } + } + return true; + } + + /** + * Get unique string for a set of sources + * + * @param array $sources Minify_Source instances + * + * @return string + */ + public static function getDigest($sources) + { + foreach ($sources as $source) { + $info[] = array( + $source->_id, $source->minifier, $source->minifyOptions + ); + } + return md5(serialize($info)); + } + + /** + * Get content type from a group of sources + * + * This is called if the user doesn't pass in a 'contentType' options + * + * @param array $sources Minify_Source instances + * + * @return string content type. e.g. 'text/css' + */ + public static function getContentType($sources) + { + foreach ($sources as $source) { + if ($source->contentType !== null) { + return $source->contentType; + } + } + return 'text/plain'; + } + + protected $_content = null; + protected $_getContentFunc = null; + protected $_id = null; +} + diff --git a/vendor/mrclay/minify/min/lib/Minify/YUI/CssCompressor.java b/vendor/mrclay/minify/min/lib/Minify/YUI/CssCompressor.java new file mode 100644 index 0000000000..3fb497a969 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/YUI/CssCompressor.java @@ -0,0 +1,382 @@ +/* + * YUI Compressor + * http://developer.yahoo.com/yui/compressor/ + * Author: Julien Lecomte - http://www.julienlecomte.net/ + * Author: Isaac Schlueter - http://foohack.com/ + * Author: Stoyan Stefanov - http://phpied.com/ + * Copyright (c) 2011 Yahoo! Inc. All rights reserved. + * The copyrights embodied in the content of this file are licensed + * by Yahoo! Inc. under the BSD (revised) open source license. + */ +package com.yahoo.platform.yui.compressor; + +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.regex.Pattern; +import java.util.regex.Matcher; +import java.util.ArrayList; + +public class CssCompressor { + + private StringBuffer srcsb = new StringBuffer(); + + public CssCompressor(Reader in) throws IOException { + // Read the stream... + int c; + while ((c = in.read()) != -1) { + srcsb.append((char) c); + } + } + + // Leave data urls alone to increase parse performance. + protected String extractDataUrls(String css, ArrayList preservedTokens) { + + int maxIndex = css.length() - 1; + int appendIndex = 0; + + StringBuffer sb = new StringBuffer(); + + Pattern p = Pattern.compile("url\\(\\s*([\"']?)data\\:"); + Matcher m = p.matcher(css); + + /* + * Since we need to account for non-base64 data urls, we need to handle + * ' and ) being part of the data string. Hence switching to indexOf, + * to determine whether or not we have matching string terminators and + * handling sb appends directly, instead of using matcher.append* methods. + */ + + while (m.find()) { + + int startIndex = m.start() + 4; // "url(".length() + String terminator = m.group(1); // ', " or empty (not quoted) + + if (terminator.length() == 0) { + terminator = ")"; + } + + boolean foundTerminator = false; + + int endIndex = m.end() - 1; + while(foundTerminator == false && endIndex+1 <= maxIndex) { + endIndex = css.indexOf(terminator, endIndex+1); + + if ((endIndex > 0) && (css.charAt(endIndex-1) != '\\')) { + foundTerminator = true; + if (!")".equals(terminator)) { + endIndex = css.indexOf(")", endIndex); + } + } + } + + // Enough searching, start moving stuff over to the buffer + sb.append(css.substring(appendIndex, m.start())); + + if (foundTerminator) { + String token = css.substring(startIndex, endIndex); + token = token.replaceAll("\\s+", ""); + preservedTokens.add(token); + + String preserver = "url(___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___)"; + sb.append(preserver); + + appendIndex = endIndex + 1; + } else { + // No end terminator found, re-add the whole match. Should we throw/warn here? + sb.append(css.substring(m.start(), m.end())); + appendIndex = m.end(); + } + } + + sb.append(css.substring(appendIndex)); + + return sb.toString(); + } + + public void compress(Writer out, int linebreakpos) + throws IOException { + + Pattern p; + Matcher m; + String css = srcsb.toString(); + + int startIndex = 0; + int endIndex = 0; + int i = 0; + int max = 0; + ArrayList preservedTokens = new ArrayList(0); + ArrayList comments = new ArrayList(0); + String token; + int totallen = css.length(); + String placeholder; + + css = this.extractDataUrls(css, preservedTokens); + + StringBuffer sb = new StringBuffer(css); + + // collect all comment blocks... + while ((startIndex = sb.indexOf("/*", startIndex)) >= 0) { + endIndex = sb.indexOf("*/", startIndex + 2); + if (endIndex < 0) { + endIndex = totallen; + } + + token = sb.substring(startIndex + 2, endIndex); + comments.add(token); + sb.replace(startIndex + 2, endIndex, "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + (comments.size() - 1) + "___"); + startIndex += 2; + } + css = sb.toString(); + + // preserve strings so their content doesn't get accidentally minified + sb = new StringBuffer(); + p = Pattern.compile("(\"([^\\\\\"]|\\\\.|\\\\)*\")|(\'([^\\\\\']|\\\\.|\\\\)*\')"); + m = p.matcher(css); + while (m.find()) { + token = m.group(); + char quote = token.charAt(0); + token = token.substring(1, token.length() - 1); + + // maybe the string contains a comment-like substring? + // one, maybe more? put'em back then + if (token.indexOf("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_") >= 0) { + for (i = 0, max = comments.size(); i < max; i += 1) { + token = token.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", comments.get(i).toString()); + } + } + + // minify alpha opacity in filter strings + token = token.replaceAll("(?i)progid:DXImageTransform.Microsoft.Alpha\\(Opacity=", "alpha(opacity="); + + preservedTokens.add(token); + String preserver = quote + "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___" + quote; + m.appendReplacement(sb, preserver); + } + m.appendTail(sb); + css = sb.toString(); + + + // strings are safe, now wrestle the comments + for (i = 0, max = comments.size(); i < max; i += 1) { + + token = comments.get(i).toString(); + placeholder = "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___"; + + // ! in the first position of the comment means preserve + // so push to the preserved tokens while stripping the ! + if (token.startsWith("!")) { + preservedTokens.add(token); + css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___"); + continue; + } + + // \ in the last position looks like hack for Mac/IE5 + // shorten that to /*\*/ and the next one to /**/ + if (token.endsWith("\\")) { + preservedTokens.add("\\"); + css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___"); + i = i + 1; // attn: advancing the loop + preservedTokens.add(""); + css = css.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___"); + continue; + } + + // keep empty comments after child selectors (IE7 hack) + // e.g. html >/**/ body + if (token.length() == 0) { + startIndex = css.indexOf(placeholder); + if (startIndex > 2) { + if (css.charAt(startIndex - 3) == '>') { + preservedTokens.add(""); + css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___"); + } + } + } + + // in all other cases kill the comment + css = css.replace("/*" + placeholder + "*/", ""); + } + + + // Normalize all whitespace strings to single spaces. Easier to work with that way. + css = css.replaceAll("\\s+", " "); + + // Remove the spaces before the things that should not have spaces before them. + // But, be careful not to turn "p :link {...}" into "p:link{...}" + // Swap out any pseudo-class colons with the token, and then swap back. + sb = new StringBuffer(); + p = Pattern.compile("(^|\\})(([^\\{:])+:)+([^\\{]*\\{)"); + m = p.matcher(css); + while (m.find()) { + String s = m.group(); + s = s.replaceAll(":", "___YUICSSMIN_PSEUDOCLASSCOLON___"); + s = s.replaceAll( "\\\\", "\\\\\\\\" ).replaceAll( "\\$", "\\\\\\$" ); + m.appendReplacement(sb, s); + } + m.appendTail(sb); + css = sb.toString(); + // Remove spaces before the things that should not have spaces before them. + css = css.replaceAll("\\s+([!{};:>+\\(\\)\\],])", "$1"); + // bring back the colon + css = css.replaceAll("___YUICSSMIN_PSEUDOCLASSCOLON___", ":"); + + // retain space for special IE6 cases + css = css.replaceAll(":first\\-(line|letter)(\\{|,)", ":first-$1 $2"); + + // no space after the end of a preserved comment + css = css.replaceAll("\\*/ ", "*/"); + + // If there is a @charset, then only allow one, and push to the top of the file. + css = css.replaceAll("^(.*)(@charset \"[^\"]*\";)", "$2$1"); + css = css.replaceAll("^(\\s*@charset [^;]+;\\s*)+", "$1"); + + // Put the space back in some cases, to support stuff like + // @media screen and (-webkit-min-device-pixel-ratio:0){ + css = css.replaceAll("\\band\\(", "and ("); + + // Remove the spaces after the things that should not have spaces after them. + css = css.replaceAll("([!{}:;>+\\(\\[,])\\s+", "$1"); + + // remove unnecessary semicolons + css = css.replaceAll(";+}", "}"); + + // Replace 0(px,em,%) with 0. + css = css.replaceAll("([\\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)", "$1$2"); + + // Replace 0 0 0 0; with 0. + css = css.replaceAll(":0 0 0 0(;|})", ":0$1"); + css = css.replaceAll(":0 0 0(;|})", ":0$1"); + css = css.replaceAll(":0 0(;|})", ":0$1"); + + + // Replace background-position:0; with background-position:0 0; + // same for transform-origin + sb = new StringBuffer(); + p = Pattern.compile("(?i)(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|})"); + m = p.matcher(css); + while (m.find()) { + m.appendReplacement(sb, m.group(1).toLowerCase() + ":0 0" + m.group(2)); + } + m.appendTail(sb); + css = sb.toString(); + + // Replace 0.6 to .6, but only when preceded by : or a white-space + css = css.replaceAll("(:|\\s)0+\\.(\\d+)", "$1.$2"); + + // Shorten colors from rgb(51,102,153) to #336699 + // This makes it more likely that it'll get further compressed in the next step. + p = Pattern.compile("rgb\\s*\\(\\s*([0-9,\\s]+)\\s*\\)"); + m = p.matcher(css); + sb = new StringBuffer(); + while (m.find()) { + String[] rgbcolors = m.group(1).split(","); + StringBuffer hexcolor = new StringBuffer("#"); + for (i = 0; i < rgbcolors.length; i++) { + int val = Integer.parseInt(rgbcolors[i]); + if (val < 16) { + hexcolor.append("0"); + } + hexcolor.append(Integer.toHexString(val)); + } + m.appendReplacement(sb, hexcolor.toString()); + } + m.appendTail(sb); + css = sb.toString(); + + // Shorten colors from #AABBCC to #ABC. Note that we want to make sure + // the color is not preceded by either ", " or =. Indeed, the property + // filter: chroma(color="#FFFFFF"); + // would become + // filter: chroma(color="#FFF"); + // which makes the filter break in IE. + // We also want to make sure we're only compressing #AABBCC patterns inside { }, not id selectors ( #FAABAC {} ) + // We also want to avoid compressing invalid values (e.g. #AABBCCD to #ABCD) + p = Pattern.compile("(\\=\\s*?[\"']?)?" + "#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])" + "(:?\\}|[^0-9a-fA-F{][^{]*?\\})"); + + m = p.matcher(css); + sb = new StringBuffer(); + int index = 0; + + while (m.find(index)) { + + sb.append(css.substring(index, m.start())); + + boolean isFilter = (m.group(1) != null && !"".equals(m.group(1))); + + if (isFilter) { + // Restore, as is. Compression will break filters + sb.append(m.group(1) + "#" + m.group(2) + m.group(3) + m.group(4) + m.group(5) + m.group(6) + m.group(7)); + } else { + if( m.group(2).equalsIgnoreCase(m.group(3)) && + m.group(4).equalsIgnoreCase(m.group(5)) && + m.group(6).equalsIgnoreCase(m.group(7))) { + + // #AABBCC pattern + sb.append("#" + (m.group(3) + m.group(5) + m.group(7)).toLowerCase()); + + } else { + + // Non-compressible color, restore, but lower case. + sb.append("#" + (m.group(2) + m.group(3) + m.group(4) + m.group(5) + m.group(6) + m.group(7)).toLowerCase()); + } + } + + index = m.end(7); + } + + sb.append(css.substring(index)); + css = sb.toString(); + + // border: none -> border:0 + sb = new StringBuffer(); + p = Pattern.compile("(?i)(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|})"); + m = p.matcher(css); + while (m.find()) { + m.appendReplacement(sb, m.group(1).toLowerCase() + ":0" + m.group(2)); + } + m.appendTail(sb); + css = sb.toString(); + + // shorter opacity IE filter + css = css.replaceAll("(?i)progid:DXImageTransform.Microsoft.Alpha\\(Opacity=", "alpha(opacity="); + + // Remove empty rules. + css = css.replaceAll("[^\\}\\{/;]+\\{\\}", ""); + + // TODO: Should this be after we re-insert tokens. These could alter the break points. However then + // we'd need to make sure we don't break in the middle of a string etc. + if (linebreakpos >= 0) { + // Some source control tools don't like it when files containing lines longer + // than, say 8000 characters, are checked in. The linebreak option is used in + // that case to split long lines after a specific column. + i = 0; + int linestartpos = 0; + sb = new StringBuffer(css); + while (i < sb.length()) { + char c = sb.charAt(i++); + if (c == '}' && i - linestartpos > linebreakpos) { + sb.insert(i, '\n'); + linestartpos = i; + } + } + + css = sb.toString(); + } + + // Replace multiple semi-colons in a row by a single one + // See SF bug #1980989 + css = css.replaceAll(";;+", ";"); + + // restore preserved comments and strings + for(i = 0, max = preservedTokens.size(); i < max; i++) { + css = css.replace("___YUICSSMIN_PRESERVED_TOKEN_" + i + "___", preservedTokens.get(i).toString()); + } + + // Trim the final string (for any leading or trailing white spaces) + css = css.trim(); + + // Write the output... + out.write(css); + } +} diff --git a/vendor/mrclay/minify/min/lib/Minify/YUI/CssCompressor.php b/vendor/mrclay/minify/min/lib/Minify/YUI/CssCompressor.php new file mode 100644 index 0000000000..ae3443d445 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/YUI/CssCompressor.php @@ -0,0 +1,171 @@ ++\\(\\)\\],])@", "$1", $css); + $css = str_replace("___PSEUDOCLASSCOLON___", ":", $css); + + // Remove the spaces after the things that should not have spaces after them. + $css = preg_replace("@([!{}:;>+\\(\\[,])\\s+@", "$1", $css); + + // Add the semicolon where it's missing. + $css = preg_replace("@([^;\\}])}@", "$1;}", $css); + + // Replace 0(px,em,%) with 0. + $css = preg_replace("@([\\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)@", "$1$2", $css); + + // Replace 0 0 0 0; with 0. + $css = str_replace(":0 0 0 0;", ":0;", $css); + $css = str_replace(":0 0 0;", ":0;", $css); + $css = str_replace(":0 0;", ":0;", $css); + + // Replace background-position:0; with background-position:0 0; + $css = str_replace("background-position:0;", "background-position:0 0;", $css); + + // Replace 0.6 to .6, but only when preceded by : or a white-space + $css = preg_replace("@(:|\\s)0+\\.(\\d+)@", "$1.$2", $css); + + // Shorten colors from rgb(51,102,153) to #336699 + // This makes it more likely that it'll get further compressed in the next step. + $css = preg_replace_callback("@rgb\\s*\\(\\s*([0-9,\\s]+)\\s*\\)@", array($this, '_shortenRgbCB'), $css); + + // Shorten colors from #AABBCC to #ABC. Note that we want to make sure + // the color is not preceded by either ", " or =. Indeed, the property + // filter: chroma(color="#FFFFFF"); + // would become + // filter: chroma(color="#FFF"); + // which makes the filter break in IE. + $css = preg_replace_callback("@([^\"'=\\s])(\\s*)#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])@", array($this, '_shortenHexCB'), $css); + + // Remove empty rules. + $css = preg_replace("@[^\\}]+\\{;\\}@", "", $css); + + $linebreakpos = isset($this->_options['linebreakpos']) + ? $this->_options['linebreakpos'] + : 0; + + if ($linebreakpos > 0) { + // Some source control tools don't like it when files containing lines longer + // than, say 8000 characters, are checked in. The linebreak option is used in + // that case to split long lines after a specific column. + $i = 0; + $linestartpos = 0; + $sb = $css; + + // make sure strlen returns byte count + $mbIntEnc = null; + if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) { + $mbIntEnc = mb_internal_encoding(); + mb_internal_encoding('8bit'); + } + $sbLength = strlen($css); + while ($i < $sbLength) { + $c = $sb[$i++]; + if ($c === '}' && $i - $linestartpos > $linebreakpos) { + $sb = substr_replace($sb, "\n", $i, 0); + $sbLength++; + $linestartpos = $i; + } + } + $css = $sb; + + // undo potential mb_encoding change + if ($mbIntEnc !== null) { + mb_internal_encoding($mbIntEnc); + } + } + + // Replace the pseudo class for the Box Model Hack + $css = str_replace("___PSEUDOCLASSBMH___", "\"\\\\\"}\\\\\"\"", $css); + + // Replace multiple semi-colons in a row by a single one + // See SF bug #1980989 + $css = preg_replace("@;;+@", ";", $css); + + // prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/ + $css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css); + + // Trim the final string (for any leading or trailing white spaces) + $css = trim($css); + + return $css; + } + + protected function _removeSpacesCB($m) + { + return str_replace(':', '___PSEUDOCLASSCOLON___', $m[0]); + } + + protected function _shortenRgbCB($m) + { + $rgbcolors = explode(',', $m[1]); + $hexcolor = '#'; + for ($i = 0; $i < count($rgbcolors); $i++) { + $val = round($rgbcolors[$i]); + if ($val < 16) { + $hexcolor .= '0'; + } + $hexcolor .= dechex($val); + } + return $hexcolor; + } + + protected function _shortenHexCB($m) + { + // Test for AABBCC pattern + if ((strtolower($m[3])===strtolower($m[4])) && + (strtolower($m[5])===strtolower($m[6])) && + (strtolower($m[7])===strtolower($m[8]))) { + return $m[1] . $m[2] . "#" . $m[3] . $m[5] . $m[7]; + } else { + return $m[0]; + } + } +} \ No newline at end of file diff --git a/vendor/mrclay/minify/min/lib/Minify/YUICompressor.php b/vendor/mrclay/minify/min/lib/Minify/YUICompressor.php new file mode 100644 index 0000000000..5762e890c6 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/Minify/YUICompressor.php @@ -0,0 +1,156 @@ + + * Minify_YUICompressor::$jarFile = '/path/to/yuicompressor-2.4.6.jar'; + * Minify_YUICompressor::$tempDir = '/tmp'; + * $code = Minify_YUICompressor::minifyJs( + * $code + * ,array('nomunge' => true, 'line-break' => 1000) + * ); + * + * + * Note: In case you run out stack (default is 512k), you may increase stack size in $options: + * array('stack-size' => '2048k') + * + * @todo unit tests, $options docs + * + * @package Minify + * @author Stephen Clay + */ +class Minify_YUICompressor { + + /** + * Filepath of the YUI Compressor jar file. This must be set before + * calling minifyJs() or minifyCss(). + * + * @var string + */ + public static $jarFile = null; + + /** + * Writable temp directory. This must be set before calling minifyJs() + * or minifyCss(). + * + * @var string + */ + public static $tempDir = null; + + /** + * Filepath of "java" executable (may be needed if not in shell's PATH) + * + * @var string + */ + public static $javaExecutable = 'java'; + + /** + * Minify a Javascript string + * + * @param string $js + * + * @param array $options (verbose is ignored) + * + * @see http://www.julienlecomte.net/yuicompressor/README + * + * @return string + */ + public static function minifyJs($js, $options = array()) + { + return self::_minify('js', $js, $options); + } + + /** + * Minify a CSS string + * + * @param string $css + * + * @param array $options (verbose is ignored) + * + * @see http://www.julienlecomte.net/yuicompressor/README + * + * @return string + */ + public static function minifyCss($css, $options = array()) + { + return self::_minify('css', $css, $options); + } + + private static function _minify($type, $content, $options) + { + self::_prepare(); + if (! ($tmpFile = tempnam(self::$tempDir, 'yuic_'))) { + throw new Exception('Minify_YUICompressor : could not create temp file in "'.self::$tempDir.'".'); + } + file_put_contents($tmpFile, $content); + exec(self::_getCmd($options, $type, $tmpFile), $output, $result_code); + unlink($tmpFile); + if ($result_code != 0) { + throw new Exception('Minify_YUICompressor : YUI compressor execution failed.'); + } + return implode("\n", $output); + } + + private static function _getCmd($userOptions, $type, $tmpFile) + { + $o = array_merge( + array( + 'charset' => '' + ,'line-break' => 5000 + ,'type' => $type + ,'nomunge' => false + ,'preserve-semi' => false + ,'disable-optimizations' => false + ,'stack-size' => '' + ) + ,$userOptions + ); + $cmd = self::$javaExecutable + . (!empty($o['stack-size']) + ? ' -Xss' . $o['stack-size'] + : '') + . ' -jar ' . escapeshellarg(self::$jarFile) + . " --type {$type}" + . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset']) + ? " --charset {$o['charset']}" + : '') + . (is_numeric($o['line-break']) && $o['line-break'] >= 0 + ? ' --line-break ' . (int)$o['line-break'] + : ''); + if ($type === 'js') { + foreach (array('nomunge', 'preserve-semi', 'disable-optimizations') as $opt) { + $cmd .= $o[$opt] + ? " --{$opt}" + : ''; + } + } + return $cmd . ' ' . escapeshellarg($tmpFile); + } + + private static function _prepare() + { + if (! is_file(self::$jarFile)) { + throw new Exception('Minify_YUICompressor : $jarFile('.self::$jarFile.') is not a valid file.'); + } + if (! is_readable(self::$jarFile)) { + throw new Exception('Minify_YUICompressor : $jarFile('.self::$jarFile.') is not readable.'); + } + if (! is_dir(self::$tempDir)) { + throw new Exception('Minify_YUICompressor : $tempDir('.self::$tempDir.') is not a valid direcotry.'); + } + if (! is_writable(self::$tempDir)) { + throw new Exception('Minify_YUICompressor : $tempDir('.self::$tempDir.') is not writable.'); + } + } +} + diff --git a/vendor/mrclay/minify/min/lib/MrClay/Cli.php b/vendor/mrclay/minify/min/lib/MrClay/Cli.php new file mode 100644 index 0000000000..9aa8e06f29 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/MrClay/Cli.php @@ -0,0 +1,384 @@ +values. + * + * You may also specify that some arguments be used to provide input/output. By communicating + * solely through the file pointers provided by openInput()/openOutput(), you can make your + * app more flexible to end users. + * + * @author Steve Clay + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +class Cli { + + /** + * @var array validation errors + */ + public $errors = array(); + + /** + * @var array option values available after validation. + * + * E.g. array( + * 'a' => false // option was missing + * ,'b' => true // option was present + * ,'c' => "Hello" // option had value + * ,'f' => "/home/user/file" // file path from root + * ,'f.raw' => "~/file" // file path as given to option + * ) + */ + public $values = array(); + + /** + * @var array + */ + public $moreArgs = array(); + + /** + * @var array + */ + public $debug = array(); + + /** + * @var bool The user wants help info + */ + public $isHelpRequest = false; + + /** + * @var Arg[] + */ + protected $_args = array(); + + /** + * @var resource + */ + protected $_stdin = null; + + /** + * @var resource + */ + protected $_stdout = null; + + /** + * @param bool $exitIfNoStdin (default true) Exit() if STDIN is not defined + */ + public function __construct($exitIfNoStdin = true) + { + if ($exitIfNoStdin && ! defined('STDIN')) { + exit('This script is for command-line use only.'); + } + if (isset($GLOBALS['argv'][1]) + && ($GLOBALS['argv'][1] === '-?' || $GLOBALS['argv'][1] === '--help')) { + $this->isHelpRequest = true; + } + } + + /** + * @param Arg|string $letter + * @return Arg + */ + public function addOptionalArg($letter) + { + return $this->addArgument($letter, false); + } + + /** + * @param Arg|string $letter + * @return Arg + */ + public function addRequiredArg($letter) + { + return $this->addArgument($letter, true); + } + + /** + * @param string $letter + * @param bool $required + * @param Arg|null $arg + * @return Arg + * @throws InvalidArgumentException + */ + public function addArgument($letter, $required, Arg $arg = null) + { + if (! preg_match('/^[a-zA-Z]$/', $letter)) { + throw new InvalidArgumentException('$letter must be in [a-zA-Z]'); + } + if (! $arg) { + $arg = new Arg($required); + } + $this->_args[$letter] = $arg; + return $arg; + } + + /** + * @param string $letter + * @return Arg|null + */ + public function getArgument($letter) + { + return isset($this->_args[$letter]) ? $this->_args[$letter] : null; + } + + /* + * Read and validate options + * + * @return bool true if all options are valid + */ + public function validate() + { + $options = ''; + $this->errors = array(); + $this->values = array(); + $this->_stdin = null; + + if ($this->isHelpRequest) { + return false; + } + + $lettersUsed = ''; + foreach ($this->_args as $letter => $arg) { + /* @var Arg $arg */ + $options .= $letter; + $lettersUsed .= $letter; + + if ($arg->mayHaveValue || $arg->mustHaveValue) { + $options .= ($arg->mustHaveValue ? ':' : '::'); + } + } + + $this->debug['argv'] = $GLOBALS['argv']; + $argvCopy = array_slice($GLOBALS['argv'], 1); + $o = getopt($options); + $this->debug['getopt_options'] = $options; + $this->debug['getopt_return'] = $o; + + foreach ($this->_args as $letter => $arg) { + /* @var Arg $arg */ + $this->values[$letter] = false; + if (isset($o[$letter])) { + if (is_bool($o[$letter])) { + + // remove from argv copy + $k = array_search("-$letter", $argvCopy); + if ($k !== false) { + array_splice($argvCopy, $k, 1); + } + + if ($arg->mustHaveValue) { + $this->addError($letter, "Missing value"); + } else { + $this->values[$letter] = true; + } + } else { + // string + $this->values[$letter] = $o[$letter]; + $v =& $this->values[$letter]; + + // remove from argv copy + // first look for -ovalue or -o=value + $pattern = "/^-{$letter}=?" . preg_quote($v, '/') . "$/"; + $foundInArgv = false; + foreach ($argvCopy as $k => $argV) { + if (preg_match($pattern, $argV)) { + array_splice($argvCopy, $k, 1); + $foundInArgv = true; + break; + } + } + if (! $foundInArgv) { + // space separated + $k = array_search("-$letter", $argvCopy); + if ($k !== false) { + array_splice($argvCopy, $k, 2); + } + } + + // check that value isn't really another option + if (strlen($lettersUsed) > 1) { + $pattern = "/^-[" . str_replace($letter, '', $lettersUsed) . "]/i"; + if (preg_match($pattern, $v)) { + $this->addError($letter, "Value was read as another option: %s", $v); + return false; + } + } + if ($arg->assertFile || $arg->assertDir) { + if ($v[0] !== '/' && $v[0] !== '~') { + $this->values["$letter.raw"] = $v; + $v = getcwd() . "/$v"; + } + } + if ($arg->assertFile) { + if ($arg->useAsInfile) { + $this->_stdin = $v; + } elseif ($arg->useAsOutfile) { + $this->_stdout = $v; + } + if ($arg->assertReadable && ! is_readable($v)) { + $this->addError($letter, "File not readable: %s", $v); + continue; + } + if ($arg->assertWritable) { + if (is_file($v)) { + if (! is_writable($v)) { + $this->addError($letter, "File not writable: %s", $v); + } + } else { + if (! is_writable(dirname($v))) { + $this->addError($letter, "Directory not writable: %s", dirname($v)); + } + } + } + } elseif ($arg->assertDir && $arg->assertWritable && ! is_writable($v)) { + $this->addError($letter, "Directory not readable: %s", $v); + } + } + } else { + if ($arg->isRequired()) { + $this->addError($letter, "Missing"); + } + } + } + $this->moreArgs = $argvCopy; + reset($this->moreArgs); + return empty($this->errors); + } + + /** + * Get the full paths of file(s) passed in as unspecified arguments + * + * @return array + */ + public function getPathArgs() + { + $r = $this->moreArgs; + foreach ($r as $k => $v) { + if ($v[0] !== '/' && $v[0] !== '~') { + $v = getcwd() . "/$v"; + $v = str_replace('/./', '/', $v); + do { + $v = preg_replace('@/[^/]+/\\.\\./@', '/', $v, 1, $changed); + } while ($changed); + $r[$k] = $v; + } + } + return $r; + } + + /** + * Get a short list of errors with options + * + * @return string + */ + public function getErrorReport() + { + if (empty($this->errors)) { + return ''; + } + $r = "Some arguments did not pass validation:\n"; + foreach ($this->errors as $letter => $arr) { + $r .= " $letter : " . implode(', ', $arr) . "\n"; + } + $r .= "\n"; + return $r; + } + + /** + * @return string + */ + public function getArgumentsListing() + { + $r = "\n"; + foreach ($this->_args as $letter => $arg) { + /* @var Arg $arg */ + $desc = $arg->getDescription(); + $flag = " -$letter "; + if ($arg->mayHaveValue) { + $flag .= "[VAL]"; + } elseif ($arg->mustHaveValue) { + $flag .= "VAL"; + } + if ($arg->assertFile) { + $flag = str_replace('VAL', 'FILE', $flag); + } elseif ($arg->assertDir) { + $flag = str_replace('VAL', 'DIR', $flag); + } + if ($arg->isRequired()) { + $desc = "(required) $desc"; + } + $flag = str_pad($flag, 12, " ", STR_PAD_RIGHT); + $desc = wordwrap($desc, 70); + $r .= $flag . str_replace("\n", "\n ", $desc) . "\n\n"; + } + return $r; + } + + /** + * Get resource of open input stream. May be STDIN or a file pointer + * to the file specified by an option with 'STDIN'. + * + * @return resource + */ + public function openInput() + { + if (null === $this->_stdin) { + return STDIN; + } else { + $this->_stdin = fopen($this->_stdin, 'rb'); + return $this->_stdin; + } + } + + public function closeInput() + { + if (null !== $this->_stdin) { + fclose($this->_stdin); + } + } + + /** + * Get resource of open output stream. May be STDOUT or a file pointer + * to the file specified by an option with 'STDOUT'. The file will be + * truncated to 0 bytes on opening. + * + * @return resource + */ + public function openOutput() + { + if (null === $this->_stdout) { + return STDOUT; + } else { + $this->_stdout = fopen($this->_stdout, 'wb'); + return $this->_stdout; + } + } + + public function closeOutput() + { + if (null !== $this->_stdout) { + fclose($this->_stdout); + } + } + + /** + * @param string $letter + * @param string $msg + * @param string $value + */ + protected function addError($letter, $msg, $value = null) + { + if ($value !== null) { + $value = var_export($value, 1); + } + $this->errors[$letter][] = sprintf($msg, $value); + } +} + diff --git a/vendor/mrclay/minify/min/lib/MrClay/Cli/Arg.php b/vendor/mrclay/minify/min/lib/MrClay/Cli/Arg.php new file mode 100644 index 0000000000..5fa5932734 --- /dev/null +++ b/vendor/mrclay/minify/min/lib/MrClay/Cli/Arg.php @@ -0,0 +1,183 @@ +values['f.raw'] + * + * Use assertReadable()/assertWritable() to cause the validator to test the file/dir for + * read/write permissions respectively. + * + * @method \MrClay\Cli\Arg mayHaveValue() Assert that the argument, if present, may receive a string value + * @method \MrClay\Cli\Arg mustHaveValue() Assert that the argument, if present, must receive a string value + * @method \MrClay\Cli\Arg assertFile() Assert that the argument's value must specify a file + * @method \MrClay\Cli\Arg assertDir() Assert that the argument's value must specify a directory + * @method \MrClay\Cli\Arg assertReadable() Assert that the specified file/dir must be readable + * @method \MrClay\Cli\Arg assertWritable() Assert that the specified file/dir must be writable + * + * @property-read bool mayHaveValue + * @property-read bool mustHaveValue + * @property-read bool assertFile + * @property-read bool assertDir + * @property-read bool assertReadable + * @property-read bool assertWritable + * @property-read bool useAsInfile + * @property-read bool useAsOutfile + * + * @author Steve Clay + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ +class Arg { + /** + * @return array + */ + public function getDefaultSpec() + { + return array( + 'mayHaveValue' => false, + 'mustHaveValue' => false, + 'assertFile' => false, + 'assertDir' => false, + 'assertReadable' => false, + 'assertWritable' => false, + 'useAsInfile' => false, + 'useAsOutfile' => false, + ); + } + + /** + * @var array + */ + protected $spec = array(); + + /** + * @var bool + */ + protected $required = false; + + /** + * @var string + */ + protected $description = ''; + + /** + * @param bool $isRequired + */ + public function __construct($isRequired = false) + { + $this->spec = $this->getDefaultSpec(); + $this->required = (bool) $isRequired; + if ($isRequired) { + $this->spec['mustHaveValue'] = true; + } + } + + /** + * Assert that the argument's value points to a writable file. When + * Cli::openOutput() is called, a write pointer to this file will + * be provided. + * @return Arg + */ + public function useAsOutfile() + { + $this->spec['useAsOutfile'] = true; + return $this->assertFile()->assertWritable(); + } + + /** + * Assert that the argument's value points to a readable file. When + * Cli::openInput() is called, a read pointer to this file will + * be provided. + * @return Arg + */ + public function useAsInfile() + { + $this->spec['useAsInfile'] = true; + return $this->assertFile()->assertReadable(); + } + + /** + * @return array + */ + public function getSpec() + { + return $this->spec; + } + + /** + * @param string $desc + * @return Arg + */ + public function setDescription($desc) + { + $this->description = $desc; + return $this; + } + + /** + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * @return bool + */ + public function isRequired() + { + return $this->required; + } + + /** + * Note: magic methods declared in class PHPDOC + * + * @param string $name + * @param array $args + * @return Arg + * @throws BadMethodCallException + */ + public function __call($name, array $args = array()) + { + if (array_key_exists($name, $this->spec)) { + $this->spec[$name] = true; + if ($name === 'assertFile' || $name === 'assertDir') { + $this->spec['mustHaveValue'] = true; + } + } else { + throw new BadMethodCallException('Method does not exist'); + } + return $this; + } + + /** + * Note: magic properties declared in class PHPDOC + * + * @param string $name + * @return bool|null + */ + public function __get($name) + { + if (array_key_exists($name, $this->spec)) { + return $this->spec[$name]; + } + return null; + } +} diff --git a/vendor/ornicar/php-user-agent/CHANGELOG.md b/vendor/ornicar/php-user-agent/CHANGELOG.md new file mode 100644 index 0000000000..2d4aa7a13a --- /dev/null +++ b/vendor/ornicar/php-user-agent/CHANGELOG.md @@ -0,0 +1,13 @@ +# CHANGELOG + +### 1.0.1 (????-??-??) + + * f1b82e5 - [Composer] Add branch alias support + +### 1.0.0 (2013-08-09) + + * Add a version following semver spec. + +### v1.0 (2010-04-13) + + * Create initial 1.0 version \ No newline at end of file diff --git a/vendor/ornicar/php-user-agent/LICENSE b/vendor/ornicar/php-user-agent/LICENSE new file mode 100644 index 0000000000..dd2630b84b --- /dev/null +++ b/vendor/ornicar/php-user-agent/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2010 Thibault Duplessis + +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. diff --git a/vendor/ornicar/php-user-agent/README.md b/vendor/ornicar/php-user-agent/README.md new file mode 100644 index 0000000000..63813a2414 --- /dev/null +++ b/vendor/ornicar/php-user-agent/README.md @@ -0,0 +1,92 @@ +# PHP User Agent + +Browser detection in PHP5. +Uses a simple and fast algorithm to recognize major browsers. + +## Overview + +``` php +$userAgent = new phpUserAgent(); + +$userAgent->getBrowserName() // firefox +$userAgent->getBrowserVersion() // 3.6 +$userAgent->getOperatingSystem() // linux +$userAgent->getEngine() // gecko +``` + +### Why you should use it + +PHP provides a native function to detect user browser: [get_browser()](http://us2.php.net/manual/en/function.get-browser.php). +get_browser() requires the "browscap.ini" file which is 300KB+. +Loading and processing this file impact script performance. +And sometimes, the production server just doesn't provide browscap.ini. + +Although get_browser() surely provides excellent detection results, in most +cases a much simpler method can be just as effective. +php-user-agent has the advantage of being compact and easy to extend. +It is performant as well, since it doesn't do any iteration or recursion. + +## Usage + +``` php +// include classes or rely on Composer autoloader +require_once '/path/to/php-user-agent/phpUserAgent.php'; +require_once '/path/to/php-user-agent/phpUserAgentStringParser.php'; + +// Create a user agent +$userAgent = new phpUserAgent(); + +// Interrogate the user agent +$userAgent->getBrowserName() // firefox +$userAgent->getBrowserVersion() // 3.6 +$userAgent->getOperatingSystem() // linux +$userAgent->getEngine() // gecko +``` + +## Advanced + +### Custom user agent string + +When you create a phpUserAgent object, the current user agent string is used. +You can specify another user agent string: + +``` php +// use another user agent string +$userAgent = new phpUserAgent('msnbot/2.0b (+http://search.msn.com/msnbot.htm)'); +$userAgent->getBrowserName() // msnbot + +// use current user agent string +$userAgent = new phpUserAgent($_SERVER['HTTP_USER_AGENT'); +// this is equivalent to: +$userAgent = new phpUserAgent(); +``` + +### Custom parser class + +By default, phpUserAgentStringParser is used to analyse the user agent string. +You can replace the parser instance and customize it to match your needs: + +``` php +// create a custom user agent string parser +class myUserAgentStringParser extends phpUserAgentStringParser +{ + // override methods +} + +// inject the custom parser when creating a user agent: +$userAgent = new phpUserAgent(null, new myUserAgentStringParser()); +``` + +## Run tests + +You can run the unit tests on your server: + +``` bash +$ php prove.php +``` + +## Contribute + +If you found a browser of operating system this library fails to recognize, +feel free to submit an issue. Please provide the user agent string. +And well, if you also want to provide the patch, it's even better. diff --git a/vendor/ornicar/php-user-agent/lib/phpUserAgent.php b/vendor/ornicar/php-user-agent/lib/phpUserAgent.php new file mode 100644 index 0000000000..2e29b0d728 --- /dev/null +++ b/vendor/ornicar/php-user-agent/lib/phpUserAgent.php @@ -0,0 +1,194 @@ + + * @license MIT License + * + * Documentation: http://github.com/ornicar/php-user-agent/blob/master/README.markdown + * Tickets: http://github.com/ornicar/php-user-agent/issues + */ + +class phpUserAgent +{ + protected $userAgentString; + protected $browserName; + protected $browserVersion; + protected $operatingSystem; + protected $engine; + + public function __construct($userAgentString = null, phpUserAgentStringParser $userAgentStringParser = null) + { + $this->configureFromUserAgentString($userAgentString, $userAgentStringParser); + } + + /** + * Get the browser name + * + * @return string the browser name + */ + public function getBrowserName() + { + return $this->browserName; + } + + /** + * Set the browser name + * + * @param string $name the browser name + */ + public function setBrowserName($name) + { + $this->browserName = $name; + } + + /** + * Get the browser version + * + * @return string the browser version + */ + public function getBrowserVersion() + { + return $this->browserVersion; + } + + /** + * Set the browser version + * + * @param string $version the browser version + */ + public function setBrowserVersion($version) + { + $this->browserVersion = $version; + } + + /** + * Get the operating system name + * + * @return string the operating system name + */ + public function getOperatingSystem() + { + return $this->operatingSystem; + } + + /** + * Set the operating system name + * + * @param string $operatingSystem the operating system name + */ + public function setOperatingSystem($operatingSystem) + { + $this->operatingSystem = $operatingSystem; + } + + /** + * Get the engine name + * + * @return string the engine name + */ + public function getEngine() + { + return $this->engine; + } + + /** + * Set the engine name + * + * @param string $operatingSystem the engine name + */ + public function setEngine($engine) + { + $this->engine = $engine; + } + + /** + * Get the user agent string + * + * @return string the user agent string + */ + public function getUserAgentString() + { + return $this->userAgentString; + } + + /** + * Set the user agent string + * + * @param string $userAgentString the user agent string + */ + public function setUserAgentString($userAgentString) + { + $this->userAgentString = $userAgentString; + } + + /** + * Tell whether this user agent is unknown or not + * + * @return boolean true if this user agent is unknown, false otherwise + */ + public function isUnknown() + { + return empty($this->browserName); + } + + /** + * @return string combined browser name and version + */ + public function getFullName() + { + return $this->getBrowserName().' '.$this->getBrowserVersion(); + } + + public function __toString() + { + return $this->getFullName(); + } + + /** + * Configure the user agent from a user agent string + * @param string $userAgentString the user agent string + * @param phpUserAgentStringParser $userAgentStringParser the parser used to parse the string + */ + public function configureFromUserAgentString($userAgentString, phpUserAgentStringParser $userAgentStringParser = null) + { + if(null === $userAgentStringParser) + { + $userAgentStringParser = new phpUserAgentStringParser(); + } + + $this->setUserAgentString($userAgentString); + + $this->fromArray($userAgentStringParser->parse($userAgentString)); + } + + /** + * Convert the user agent to a data array + * + * @return array data + */ + public function toArray() + { + return array( + 'browser_name' => $this->getBrowserName(), + 'browser_version' => $this->getBrowserVersion(), + 'operating_system' => $this->getOperatingSystem() + ); + } + + /** + * Configure the user agent from a data array + * + * @param array $data + */ + public function fromArray(array $data) + { + $this->setBrowserName($data['browser_name']); + $this->setBrowserVersion($data['browser_version']); + $this->setOperatingSystem($data['operating_system']); + $this->setEngine($data['engine']); + } +} diff --git a/vendor/ornicar/php-user-agent/lib/phpUserAgentStringParser.php b/vendor/ornicar/php-user-agent/lib/phpUserAgentStringParser.php new file mode 100644 index 0000000000..e33548e23e --- /dev/null +++ b/vendor/ornicar/php-user-agent/lib/phpUserAgentStringParser.php @@ -0,0 +1,321 @@ + 'firefox', + * 'browser_version' => '3.6', + * 'operating_system' => 'linux' + * ) + */ + public function parse($userAgentString = null) + { + // use current user agent string as default + if(!$userAgentString) + { + $userAgentString = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null; + } + + // parse quickly (with medium accuracy) + $informations = $this->doParse($userAgentString); + + + // run some filters to increase accuracy + foreach($this->getFilters() as $filter) + { + $this->$filter($informations); + } + + return $informations; + } + + /** + * Detect quickly informations from the user agent string + * + * @param string $userAgentString user agent string + * @return array user agent informations array + */ + protected function doParse($userAgentString) + { + $userAgent = array( + 'string' => $this->cleanUserAgentString($userAgentString), + 'browser_name' => null, + 'browser_version' => null, + 'operating_system' => null, + 'engine' => null + ); + + if(empty($userAgent['string'])) + { + return $userAgent; + } + + // build regex that matches phrases for known browsers + // (e.g. "Firefox/2.0" or "MSIE 6.0" (This only matches the major and minor + // version numbers. E.g. "2.0.0.6" is parsed as simply "2.0" + $pattern = '#('.join('|', $this->getKnownBrowsers()).')[/ ]+([0-9]+(?:\.[0-9]+)?)#'; + + // Find all phrases (or return empty array if none found) + if (preg_match_all($pattern, $userAgent['string'], $matches)) + { + // Since some UAs have more than one phrase (e.g Firefox has a Gecko phrase, + // Opera 7,8 have a MSIE phrase), use the last one found (the right-most one + // in the UA). That's usually the most correct. + $i = count($matches[1])-1; + + if (isset($matches[1][$i])) + { + $userAgent['browser_name'] = $matches[1][$i]; + } + if (isset($matches[2][$i])) + { + $userAgent['browser_version'] = $matches[2][$i]; + } + } + + // Find operating system + $pattern = '#'.join('|', $this->getKnownOperatingSystems()).'#'; + + if (preg_match($pattern, $userAgent['string'], $match)) + { + if (isset($match[0])) + { + $userAgent['operating_system'] = $match[0]; + } + } + + // Find engine + $pattern = '#'.join('|', $this->getKnownEngines()).'#'; + + if (preg_match($pattern, $userAgent['string'], $match)) + { + if (isset($match[0])) + { + $userAgent['engine'] = $match[0]; + } + } + + return $userAgent; + } + + /** + * Make user agent string lowercase, and replace browser aliases + * + * @param string $userAgentString the dirty user agent string + * @return string the clean user agent string + */ + public function cleanUserAgentString($userAgentString) + { + // clean up the string + $userAgentString = trim(strtolower($userAgentString)); + + // replace browser names with their aliases + $userAgentString = strtr($userAgentString, $this->getKnownBrowserAliases()); + + // replace operating system names with their aliases + $userAgentString = strtr($userAgentString, $this->getKnownOperatingSystemAliases()); + + // replace engine names with their aliases + $userAgentString = strtr($userAgentString, $this->getKnownEngineAliases()); + + return $userAgentString; + } + + /** + * Get the list of filters that get called when parsing a user agent + * + * @return array list of valid callables + */ + public function getFilters() + { + return array( + 'filterAndroid', + 'filterGoogleChrome', + 'filterSafariVersion', + 'filterOperaVersion', + 'filterYahoo', + 'filterMsie', + ); + } + + /** + * Add a filter to be called when parsing a user agent + * + * @param string $filter name of the filter method + */ + public function addFilter($filter) + { + $this->filters += $filter; + } + + /** + * Get known browsers + * + * @return array the browsers + */ + protected function getKnownBrowsers() + { + return array( + 'msie', + 'firefox', + 'safari', + 'webkit', + 'opera', + 'netscape', + 'konqueror', + 'gecko', + 'chrome', + 'googlebot', + 'iphone', + 'msnbot', + 'applewebkit' + ); + } + + /** + * Get known browser aliases + * + * @return array the browser aliases + */ + protected function getKnownBrowserAliases() + { + return array( + 'shiretoko' => 'firefox', + 'namoroka' => 'firefox', + 'shredder' => 'firefox', + 'minefield' => 'firefox', + 'granparadiso' => 'firefox' + ); + } + + /** + * Get known operating system + * + * @return array the operating systems + */ + protected function getKnownOperatingSystems() + { + return array( + 'windows', + 'macintosh', + 'linux', + 'freebsd', + 'unix', + 'iphone' + ); + } + + /** + * Get known operating system aliases + * + * @return array the operating system aliases + */ + protected function getKnownOperatingSystemAliases() + { + return array(); + } + + /** + * Get known engines + * + * @return array the engines + */ + protected function getKnownEngines() + { + return array( + 'gecko', + 'webkit', + 'trident', + 'presto' + ); + } + + /** + * Get known engines aliases + * + * @return array the engines aliases + */ + protected function getKnownEngineAliases() + { + return array(); + } + + /** + * Filters + */ + + /** + * Google chrome has a safari like signature + */ + protected function filterGoogleChrome(array &$userAgent) + { + if ('safari' === $userAgent['browser_name'] && strpos($userAgent['string'], 'chrome/')) + { + $userAgent['browser_name'] = 'chrome'; + $userAgent['browser_version'] = preg_replace('|.+chrome/([0-9]+(?:\.[0-9]+)?).+|', '$1', $userAgent['string']); + } + } + + /** + * Safari version is not encoded "normally" + */ + protected function filterSafariVersion(array &$userAgent) + { + if ('safari' === $userAgent['browser_name'] && strpos($userAgent['string'], ' version/')) + { + $userAgent['browser_version'] = preg_replace('|.+\sversion/([0-9]+(?:\.[0-9]+)?).+|', '$1', $userAgent['string']); + } + } + + /** + * Opera 10.00 (and higher) version number is located at the end + */ + protected function filterOperaVersion(array &$userAgent) + { + if('opera' === $userAgent['browser_name'] && strpos($userAgent['string'], ' version/')) + { + $userAgent['browser_version'] = preg_replace('|.+\sversion/([0-9]+\.[0-9]+)\s*.*|', '$1', $userAgent['string']); + } + } + + /** + * Yahoo bot has a special user agent string + */ + protected function filterYahoo(array &$userAgent) + { + if (null === $userAgent['browser_name'] && strpos($userAgent['string'], 'yahoo! slurp')) + { + $userAgent['browser_name'] = 'yahoobot'; + } + } + + /** + * MSIE does not always declare its engine + */ + protected function filterMsie(array &$userAgent) + { + if ('msie' === $userAgent['browser_name'] && empty($userAgent['engine'])) + { + $userAgent['engine'] = 'trident'; + } + } + + /** + * Android has a safari like signature + */ + protected function filterAndroid(array &$userAgent) { + if ('safari' === $userAgent['browser_name'] && strpos($userAgent['string'], 'android ')) { + $userAgent['browser_name'] = 'android'; + $userAgent['operating_system'] = 'android'; + $userAgent['browser_version'] = preg_replace('|.+android ([0-9]+(?:\.[0-9]+)+).+|', '$1', $userAgent['string']); + } + } +} diff --git a/vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php b/vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php index ca5f28731e..3813b542d4 100644 --- a/vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -215,7 +215,11 @@ private function createStyleFromString($string) } elseif ('bg' == $match[0]) { $style->setBackground($match[1]); } else { - $style->setOption($match[1]); + try { + $style->setOption($match[1]); + } catch (\InvalidArgumentException $e) { + return false; + } } } diff --git a/vendor/tracy/tracy/src/Tracy/Debugger.php b/vendor/tracy/tracy/src/Tracy/Debugger.php index 551d7f47a8..76a65442aa 100644 --- a/vendor/tracy/tracy/src/Tracy/Debugger.php +++ b/vendor/tracy/tracy/src/Tracy/Debugger.php @@ -23,6 +23,8 @@ class Debugger PRODUCTION = TRUE, DETECT = NULL; + const COOKIE_SECRET = 'tracy-debug'; + /** @var string */ public static $version = '2.3-dev'; @@ -126,18 +128,7 @@ public static function enable($mode = NULL, $logDirectory = NULL, $email = NULL) self::$time = isset($_SERVER['REQUEST_TIME_FLOAT']) ? $_SERVER['REQUEST_TIME_FLOAT'] : microtime(TRUE); error_reporting(E_ALL | E_STRICT); - // production/development mode detection - if (is_bool($mode)) { - self::$productionMode = $mode; - - } elseif ($mode !== self::DETECT || self::$productionMode === NULL) { // IP addresses or computer names whitelist detection - $list = is_string($mode) ? preg_split('#[,\s]+#', $mode) : (array) $mode; - if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { - $list[] = '127.0.0.1'; - $list[] = '::1'; - } - self::$productionMode = !in_array(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : php_uname('n'), $list, TRUE); - } + self::$productionMode = is_bool($mode) ? $mode : !self::detectDebugMode($mode); // logging configuration if ($email !== NULL) { @@ -518,4 +509,28 @@ public static function fireLog($message) } } + + /** + * Detects debug mode by IP address. + * @param string|array IP addresses or computer names whitelist detection + * @return bool + */ + public static function detectDebugMode($list = NULL) + { + $addr = isset($_SERVER['REMOTE_ADDR']) + ? $_SERVER['REMOTE_ADDR'] + : php_uname('n'); + $secret = isset($_COOKIE[self::COOKIE_SECRET]) && is_string($_COOKIE[self::COOKIE_SECRET]) + ? $_COOKIE[self::COOKIE_SECRET] + : NULL; + $list = is_string($list) + ? preg_split('#[,\s]+#', $list) + : (array) $list; + if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { + $list[] = '127.0.0.1'; + $list[] = '::1'; + } + return in_array($addr, $list, TRUE) || in_array("$secret@$addr", $list, TRUE); + } + } From 41aadf25ed045cce3e2928e9dd39cf1b39014342 Mon Sep 17 00:00:00 2001 From: Pascal Borreli Date: Sun, 17 Aug 2014 20:29:40 +0100 Subject: [PATCH 10/63] Fixed typos/CS --- system/src/Grav/Common/Filesystem/File/Config.php | 2 +- system/src/Grav/Common/Getters.php | 2 +- system/src/Grav/Common/Grav.php | 2 +- system/src/Grav/Common/Page/Pages.php | 2 +- system/src/Grav/Common/Session/Session.php | 2 +- system/src/Grav/Common/Themes.php | 4 ++-- system/src/Grav/Common/User/Authentication.php | 4 ++-- system/src/Grav/Common/Utils.php | 8 ++++---- system/src/Grav/Console/SetupCommand.php | 1 - 9 files changed, 13 insertions(+), 14 deletions(-) diff --git a/system/src/Grav/Common/Filesystem/File/Config.php b/system/src/Grav/Common/Filesystem/File/Config.php index d697b1f655..c54f76c73b 100644 --- a/system/src/Grav/Common/Filesystem/File/Config.php +++ b/system/src/Grav/Common/Filesystem/File/Config.php @@ -85,7 +85,7 @@ protected function encode($var) } $vars = implode("\n", $vars); - return "offsetGet($offset); + return $this->offsetGet($offset); } /** diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 454e5fb986..80c7b19d3e 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -15,7 +15,7 @@ * @version 0.8.0 * * Originally based on Pico by Gilbert Pellegrom - http://pico.dev7studios.com - * Influeced by Pico, Stacey, Kirby, PieCrust and other great platforms... + * Influenced by Pico, Stacey, Kirby, PieCrust and other great platforms... * * @property Plugins $plugins * @property Config $config diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index 2de1561673..eaca62eb83 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -489,7 +489,7 @@ protected function buildSort($path, array $pages, $order_by = 'default', $manual $child = isset($this->instances[$key]) ? $this->instances[$key] : null; if (!$child) { - throw new \RuntimeException("Page does not exist: {$key}"); + throw new \RuntimeException("Page does not exist: {$key}"); } switch ($order_by) { diff --git a/system/src/Grav/Common/Session/Session.php b/system/src/Grav/Common/Session/Session.php index 0fe34d7f9e..2f6596cbb6 100644 --- a/system/src/Grav/Common/Session/Session.php +++ b/system/src/Grav/Common/Session/Session.php @@ -79,7 +79,7 @@ public function start() $this->started = true; return $this; - } + } /** * Get session ID diff --git a/system/src/Grav/Common/Themes.php b/system/src/Grav/Common/Themes.php index f21e8faac9..72835e4a34 100644 --- a/system/src/Grav/Common/Themes.php +++ b/system/src/Grav/Common/Themes.php @@ -16,7 +16,7 @@ class Themes * * @return array|Data\Data[] */ - static public function all() + public static function all() { $list = array(); $iterator = new \DirectoryIterator(THEMES_DIR); @@ -43,7 +43,7 @@ static public function all() * @return Data\Data * @throws \RuntimeException */ - static public function get($type) + public static function get($type) { if (!$type) { throw new \RuntimeException('Theme name not provided.'); diff --git a/system/src/Grav/Common/User/Authentication.php b/system/src/Grav/Common/User/Authentication.php index 3a7af6d8f2..265cac8fc9 100644 --- a/system/src/Grav/Common/User/Authentication.php +++ b/system/src/Grav/Common/User/Authentication.php @@ -15,7 +15,7 @@ abstract class Authentication * @param string $password Plaintext password. * @return string|bool */ - static public function create($password) + public static function create($password) { return password_hash($password, PASSWORD_DEFAULT); } @@ -27,7 +27,7 @@ static public function create($password) * @param string $hash Hash to verify against. * @return int Returns 0 if the check fails, 1 if password matches, 2 if hash needs to be updated. */ - static public function verify($password, $hash) + public static function verify($password, $hash) { // Always accept plaintext passwords (needs an update). // FIXME: not safe to do this... diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index 09e564ebdb..068c6b20e7 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -72,7 +72,7 @@ public static function truncateHtml($text, $length = 100, $ending = '...', $exac // delete tag from $open_tags list $pos = array_search($tag_matchings[1], $open_tags); if ($pos !== false) { - unset($open_tags[$pos]); + unset($open_tags[$pos]); } // if tag is an opening tag } else if (preg_match('/^<\s*([^\s>!]+).*?>$/s', $line_matchings[1], $tag_matchings)) { @@ -102,14 +102,14 @@ public static function truncateHtml($text, $length = 100, $ending = '...', $exac } } $truncate .= substr($line_matchings[2], 0, $left+$entities_length); - // maximum lenght is reached, so get off the loop + // maximum length is reached, so get off the loop break; } else { $truncate .= $line_matchings[2]; $total_length += $content_length; } // if the maximum length is reached, get off the loop - if($total_length>= $length) { + if ($total_length >= $length) { break; } } @@ -131,7 +131,7 @@ public static function truncateHtml($text, $length = 100, $ending = '...', $exac } // add the defined ending to the text $truncate .= $ending; - if($considerHtml) { + if ($considerHtml) { // close all unclosed html-tags foreach ($open_tags as $tag) { $truncate .= ''; diff --git a/system/src/Grav/Console/SetupCommand.php b/system/src/Grav/Console/SetupCommand.php index 41ba7c17ea..4ad1c3516f 100644 --- a/system/src/Grav/Console/SetupCommand.php +++ b/system/src/Grav/Console/SetupCommand.php @@ -86,7 +86,6 @@ protected function execute(InputInterface $input, OutputInterface $output) // Copy the Core STuff } else { - $options = true; // Create Some core stuff if it doesn't exist $this->createDirectories($output); From 215c8da54225e0c612be0b343359de8a3da2d2ff Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 17 Aug 2014 15:49:38 -0600 Subject: [PATCH 11/63] clean up codebase a little --- system/src/Grav/Common/Assets.php | 74 ++++++++++++++++++------ system/src/Grav/Common/Page/Pages.php | 3 + system/src/Grav/Common/TwigExtension.php | 6 ++ system/src/Grav/Common/Uri.php | 6 ++ system/src/Grav/Console/SetupCommand.php | 5 -- 5 files changed, 71 insertions(+), 23 deletions(-) diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php index 6cfc42e917..8154c61420 100644 --- a/system/src/Grav/Common/Assets.php +++ b/system/src/Grav/Common/Assets.php @@ -13,10 +13,9 @@ define('JS_ASSET', false); /** - * The Wrapper object for handling JS, CSS assets - * - * Based on stolz/assets package modified for use with Grav + * Handles Asset management (CSS & JS) and also pipelining (combining into a single file for each asset) * + * Based on stolz/assets (https://github.com/Stolz/Assets) package modified for use with Grav * * @author RocketTheme * @license MIT @@ -24,6 +23,9 @@ class Assets { + /** @const Regex to match grav asset shortcodes */ + const GRAV_ASSET_REGEX = '/@(plugin|theme)\/(.*?):(.*)/i'; + /** @const Regex to match CSS and JavaScript files */ const DEFAULT_REGEX = '/.\.(css|js)$/i'; @@ -34,11 +36,15 @@ class Assets const JS_REGEX = '/.\.js$/i'; /** @const Regex to match CSS urls */ - const CSS_URL_REGEX = '{url\([\'\"]((?!http|//).*?)[\'\"]\)}'; + const CSS_URL_REGEX = '{url\([\'\"]?((?!http|//).*?)[\'\"]?\)}'; /** @const Regex to match CSS sourcemap comments */ const CSS_SOURCEMAP_REGEX = '{\/\*# (.*) \*\/}'; + /** @const Regex to match CSS import content */ + const CSS_IMPORT_REGEX = '{@import(.*);}'; + + /** * Closure used by the pipeline to fetch assets. * @@ -52,21 +58,26 @@ class Assets */ protected $fetch_command; + // Configuration toggles to enable/disable the pipelining feature protected $css_pipeline = false; protected $js_pipeline = false; + // The asset holding arrays protected $collections = array(); protected $css = array(); protected $js = array(); + // Some configuration variables protected $config; protected $theme_url; protected $base_url; + // Default values for pipeline settings protected $css_minify = true; protected $css_rewrite = true; protected $js_minify = true; + // Arrays to hold assets that should NOT be pipelined protected $css_no_pipeline = array(); protected $js_no_pipeline = array(); @@ -75,17 +86,21 @@ public function __construct(array $options = array()) { // Forward config options if($options) - $this->config($options); + $this->config((array)$options); } + /** + * Initialization called in the Grav lifecycle to initialize the Assets with appropriate configuration + * + * @return [type] [description] + */ public function init() { - // $this->config = $config; - $this->config = Registry::get('Config'); - $base_url = $this->config->get('system.base_url_relative'); - $theme = $this->config->get('system.pages.theme'); - $asset_config = (array)$this->config->get('system.assets'); + $config = Registry::get('Config'); + $base_url = $config->get('system.base_url_relative'); + $theme = $config->get('system.pages.theme'); + $asset_config = (array)$config->get('system.assets'); $this->config($asset_config); $this->base_url = $base_url; @@ -442,12 +457,13 @@ protected function gatherLinks(array $links, $css = true) } $file = ($this->fetch_command instanceof Closure) ? $this->fetch_command->__invoke($link) : file_get_contents($link); - $buffer .= $file; - } - // If this is CSS + the file is local + rewrite enabled - if ($css && $local && $this->css_rewrite) { - $buffer = $this->cssRewrite($buffer, $relative_dir); + // If this is CSS + the file is local + rewrite enabled + if ($css && $local && $this->css_rewrite) { + $file = $this->cssRewrite($file, $relative_dir); + } + + $buffer .= $file; } // Pull out @imports and move to top @@ -458,11 +474,17 @@ protected function gatherLinks(array $links, $css = true) return $buffer; } + /** + * Moves @import statements to the top of the file per the CSS specification + * + * @param string $file the file containing the combined CSS files + * @return string the modified file with any @imports at the top of the file + */ protected function moveImports($file) { $this->imports = array(); - $file = preg_replace_callback('{@import(.*);}', + $file = preg_replace_callback(self::CSS_IMPORT_REGEX, function($matches) { $this->imports[] = $matches[0]; return ''; @@ -481,6 +503,7 @@ function($matches) { */ protected function cssRewrite($file, $relative_path) { + xdebug_break(); // Strip any sourcemap comments $file = preg_replace(self::CSS_SOURCEMAP_REGEX, '', $file); @@ -512,11 +535,17 @@ function($matches) use ($relative_path) { return $file; } + /** + * Build local links including grav asset shortcodes + * + * @param string $asset the asset string reference + * @return string the final link url to the asset + */ protected function buildLocalLink($asset) { $matches = $this->assetIsGravPackage($asset); - $base_url = $this->config->get('system.base_url_relative'); + $base_url = $this->base_url; if($matches === false) return $base_url . '/' . $asset; @@ -531,9 +560,18 @@ protected function buildLocalLink($asset) } + /** + * Determines if an asset contains a valid grav asset shortcode + * Currently supported formats are: + * @plugin/plugin_name/directories:assetname.js|css + * @theme/directories:assetname.js|css + * + * @param string $asset the asset string reference + * @return matches|false if there are matches, those regex matches are returned, else return false + */ protected function assetIsGravPackage($asset) { - if(preg_match('{^@([a-z]+)/(.*?):(.*)$}', $asset, $matches)) + if(preg_match(self::GRAV_ASSET_REGEX, $asset, $matches)) return $matches; return false; } diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index 2de1561673..a7366ba0b8 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -12,6 +12,9 @@ /** * GravPages is the class that is the entry point into the hierarchy of pages + * + * @author RocketTheme + * @license MIT */ class Pages { diff --git a/system/src/Grav/Common/TwigExtension.php b/system/src/Grav/Common/TwigExtension.php index 6ef8779b61..4c5a45d9cc 100644 --- a/system/src/Grav/Common/TwigExtension.php +++ b/system/src/Grav/Common/TwigExtension.php @@ -1,6 +1,12 @@ Date: Sun, 17 Aug 2014 15:55:56 -0600 Subject: [PATCH 12/63] Added empty assets folder --- assets/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/.gitkeep diff --git a/assets/.gitkeep b/assets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 From b716ca3270c66f1430125dd6b74ddc44605455ff Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 17 Aug 2014 16:01:19 -0600 Subject: [PATCH 13/63] removed left over debug :( --- system/src/Grav/Common/Assets.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php index 8154c61420..1fb48a0656 100644 --- a/system/src/Grav/Common/Assets.php +++ b/system/src/Grav/Common/Assets.php @@ -503,8 +503,6 @@ function($matches) { */ protected function cssRewrite($file, $relative_path) { - xdebug_break(); - // Strip any sourcemap comments $file = preg_replace(self::CSS_SOURCEMAP_REGEX, '', $file); From 5f8b37507e57d039a252af065516a8cb7112fa2d Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 17 Aug 2014 17:16:54 -0600 Subject: [PATCH 14/63] fixes for pipeline assets at root / rather than /subdir --- system/src/Grav/Common/Assets.php | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php index 1fb48a0656..489f43fadd 100644 --- a/system/src/Grav/Common/Assets.php +++ b/system/src/Grav/Common/Assets.php @@ -98,13 +98,13 @@ public function init() { $config = Registry::get('Config'); - $base_url = $config->get('system.base_url_relative'); + $base_url = trim($config->get('system.base_url_relative')); $theme = $config->get('system.pages.theme'); $asset_config = (array)$config->get('system.assets'); $this->config($asset_config); - $this->base_url = $base_url; - $this->theme_url = $base_url .'/'. USER_PATH . basename(THEMES_DIR) .'/'. $theme; + $this->base_url = $base_url . '/'; + $this->theme_url = $base_url . '/' . USER_PATH . basename(THEMES_DIR) .'/'. $theme; } @@ -403,10 +403,9 @@ protected function pipeline($css = true) } } - $relative_path = "{$this->base_url}/".basename(ASSETS_DIR)."/{$file}"; + $relative_path = "{$this->base_url}".basename(ASSETS_DIR)."/{$file}"; $absolute_path = ASSETS_DIR.$file; - // If pipeline exist return it if(file_exists($absolute_path)) return $relative_path . $key; @@ -439,19 +438,26 @@ protected function pipeline($css = true) */ protected function gatherLinks(array $links, $css = true) { + + $buffer = ''; $local = true; foreach($links as $asset) { $link = $asset['asset']; + $relative_path = $link; if($this->isRemoteLink($link)) { $local = false; if('//' === substr($link, 0, 2)) $link = 'http:' . $link; } else { - $relative_path = str_replace($this->base_url.'/', '', $link); + // Fix to remove relative dir if grav is in one + if (($this->base_url != '/') && (strpos($this->base_url, $link) == 0)) { + $relative_path = str_replace($this->base_url, '/', $link); + } + $relative_dir = dirname ($relative_path); $link = ROOT_DIR . $relative_path; } @@ -523,7 +529,7 @@ function($matches) use ($relative_path) { } } - $new_url = $this->base_url . '/' . $relative_path . '/' . implode('/', $newpath); + $new_url = rtrim($this->base_url,'/') . $relative_path . '/' . implode('/', $newpath); return str_replace($old_url, $new_url, $matches[0]); }, @@ -545,17 +551,19 @@ protected function buildLocalLink($asset) $matches = $this->assetIsGravPackage($asset); $base_url = $this->base_url; + if($matches === false) - return $base_url . '/' . $asset; + return $base_url . $asset; if($matches[1] == 'theme') { return $this->theme_url . '/' . $matches[2] . '/' . $matches[3]; } elseif ($matches[1] == 'plugin') { - return $base_url . '/user/plugins/' . $matches[2] . '/' . $matches[3]; + return $base_url . 'user/plugins/' . $matches[2] . '/' . $matches[3]; } else { - return $base_url . '/' . $asset; + return $base_url . $asset; } + } /** From 54de6f2ce5b321980af2c00eb55bdde36611fc51 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 17 Aug 2014 17:31:05 -0600 Subject: [PATCH 15/63] set tracy debugger to production mode by default, set to development by enabling in the configuration --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 59152e7bc7..8242845cbc 100644 --- a/index.php +++ b/index.php @@ -20,7 +20,7 @@ // Start the timer and enable debugger in production mode as we do not have system configuration yet. // Debugger catches all errors and logs them, for example if the script doesn't have write permissions. Debugger::timer(); -Debugger::enable(Debugger::DEVELOPMENT, is_dir(LOG_DIR) ? LOG_DIR : null); +Debugger::enable(Debugger::PRODUCTION, is_dir(LOG_DIR) ? LOG_DIR : null); $grav = new Grav; From 419bceb47a81f98d0d772f9705cdaacb68dc4209 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 17 Aug 2014 17:46:22 -0600 Subject: [PATCH 16/63] GRAV_VERSION available in twig for use in templates --- system/src/Grav/Common/Twig.php | 1 + 1 file changed, 1 insertion(+) diff --git a/system/src/Grav/Common/Twig.php b/system/src/Grav/Common/Twig.php index b8f8104a81..bfad83e8a1 100644 --- a/system/src/Grav/Common/Twig.php +++ b/system/src/Grav/Common/Twig.php @@ -112,6 +112,7 @@ public function init() // Set some standard variables for twig $this->twig_vars = array( + 'grav_version' => GRAV_VERSION, 'config' => $this->config, 'uri' => $this->uri, 'base_dir' => rtrim(ROOT_DIR, '/'), From 8374d03a3616926ea20faf68923f9bf412e0a72f Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 17 Aug 2014 18:20:23 -0600 Subject: [PATCH 17/63] Added some additional input filtering on query and param options --- system/src/Grav/Common/Uri.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php index bb395d751c..1db8c1ac5e 100644 --- a/system/src/Grav/Common/Uri.php +++ b/system/src/Grav/Common/Uri.php @@ -63,7 +63,7 @@ public function init() if (strpos($bit, ':') !== false) { $param = explode(':', $bit); if (count($param) == 2) { - $this->params[$param[0]] = str_replace('%7C', '/', $param[1]); + $this->params[$param[0]] = str_replace('%7C', '/', filter_var($param[1], FILTER_SANITIZE_STRING)); } } else { $path[] = $bit; @@ -134,7 +134,7 @@ public function route($absolute = false, $domain = false) public function query($id = null) { if (isset($id)) { - return $this->query[$id]; + return filter_var($this->query[$id], FILTER_SANITIZE_STRING) ; } else { return http_build_query($this->query); } From 9f2236dea357e5b7588d5a5196a873f2654d3cc0 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 17 Aug 2014 18:54:10 -0600 Subject: [PATCH 18/63] Added support for Markdown Extra - optional and default is GFM style markdown --- composer.json | 2 +- system/config/system.yaml | 1 + system/src/Grav/Common/Page/Page.php | 6 +- system/src/Grav/Console/CleanCommand.php | 2 + user/config/system.yaml | 1 + vendor/autoload.php | 2 +- vendor/composer/autoload_files.php | 2 +- vendor/composer/autoload_namespaces.php | 1 + vendor/composer/autoload_real.php | 10 +- vendor/composer/installed.json | 376 +++++++++------- vendor/erusev/parsedown-extra/LICENSE.txt | 20 + .../erusev/parsedown-extra/ParsedownExtra.php | 415 ++++++++++++++++++ vendor/erusev/parsedown-extra/README.md | 17 + vendor/erusev/parsedown/Parsedown.php | 2 +- vendor/erusev/parsedown/README.md | 1 - vendor/tracy/tracy/src/Tracy/Debugger.php | 4 +- 16 files changed, 685 insertions(+), 177 deletions(-) create mode 100644 vendor/erusev/parsedown-extra/LICENSE.txt create mode 100644 vendor/erusev/parsedown-extra/ParsedownExtra.php create mode 100644 vendor/erusev/parsedown-extra/README.md diff --git a/composer.json b/composer.json index 7522dd726f..4df896cc30 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "require": { "php": ">=5.3.10", "twig/twig": "1.16.*@dev", - "erusev/parsedown": "dev-master", + "erusev/parsedown-extra": "dev-master", "symfony/yaml": "2.5.*@dev", "symfony/console": "2.5.*@dev", "doctrine/cache": "1.4.*@dev", diff --git a/system/config/system.yaml b/system/config/system.yaml index 358d2699ca..65a7ce1936 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -3,6 +3,7 @@ home: pages: theme: antimatter # Default theme (defaults to "antimatter" theme) + markdown_extra: false # Enable support for Markdown Extra support (GFM by default) order: by: defaults # Order pages by "default", "alpha" or "date" dir: asc # Default ordering direction, "asc" or "desc" diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 310ade904c..0950960a59 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -1506,7 +1506,11 @@ protected function rawContent($content) */ protected function parseMarkdownContent($content) { - $parsedown = new \Parsedown(); + if (Registry::get('Config')->get('system.pages.markdown_extra')) { + $parsedown = new \ParsedownExtra(); + } else { + $parsedown = new \Parsedown(); + } $content = $parsedown->parse($content); return $content; } diff --git a/system/src/Grav/Console/CleanCommand.php b/system/src/Grav/Console/CleanCommand.php index 63f6aacebc..5c48a70b4b 100644 --- a/system/src/Grav/Console/CleanCommand.php +++ b/system/src/Grav/Console/CleanCommand.php @@ -40,6 +40,8 @@ class CleanCommand extends Command { 'vendor/erusev/parsedown/.travis.yml', 'vendor/erusev/parsedown/.git', 'vendor/erusev/parsedown/test', + 'vendor/erusev/parsedown-extra/composer.json', + 'vendor/erusev/parsedown-extra/.git', 'vendor/gregwar/image/Gregwar/Image/composer.json', 'vendor/gregwar/image/Gregwar/Image/phpunit.xml', 'vendor/gregwar/image/Gregwar/Image/.gitignore', diff --git a/user/config/system.yaml b/user/config/system.yaml index aaf3d9f30e..8f3cb5decc 100644 --- a/user/config/system.yaml +++ b/user/config/system.yaml @@ -3,6 +3,7 @@ home: pages: theme: antimatter + markdown_extra: true process: markdown: true twig: false diff --git a/vendor/autoload.php b/vendor/autoload.php index 2ce276c067..7d02b46698 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit70d1fc134524e0edbf7795cd92686187::getLoader(); +return ComposerAutoloaderInit0ecdddcbf5a967ed661815e7747f4510::getLoader(); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index dc9dacbf59..6f66c7e75b 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -6,8 +6,8 @@ $baseDir = dirname($vendorDir); return array( - $vendorDir . '/ircmaxell/password-compat/lib/password.php', $vendorDir . '/tracy/tracy/src/shortcuts.php', + $vendorDir . '/ircmaxell/password-compat/lib/password.php', $vendorDir . '/ornicar/php-user-agent/lib/phpUserAgent.php', $vendorDir . '/ornicar/php-user-agent/lib/phpUserAgentStringParser.php', ); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index d55f7e8a47..9a7291c070 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -9,6 +9,7 @@ 'Twig_' => array($vendorDir . '/twig/twig/lib'), 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), + 'ParsedownExtra' => array($vendorDir . '/erusev/parsedown-extra'), 'Parsedown' => array($vendorDir . '/erusev/parsedown'), 'Gregwar\\Image' => array($vendorDir . '/gregwar/image'), 'Gregwar\\Cache' => array($vendorDir . '/gregwar/cache'), diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 3ce4be5b34..c11cbb8859 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit70d1fc134524e0edbf7795cd92686187 +class ComposerAutoloaderInit0ecdddcbf5a967ed661815e7747f4510 { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit70d1fc134524e0edbf7795cd92686187', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit0ecdddcbf5a967ed661815e7747f4510', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit70d1fc134524e0edbf7795cd92686187', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit0ecdddcbf5a967ed661815e7747f4510', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ public static function getLoader() $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequire70d1fc134524e0edbf7795cd92686187($file); + composerRequire0ecdddcbf5a967ed661815e7747f4510($file); } return $loader; } } -function composerRequire70d1fc134524e0edbf7795cd92686187($file) +function composerRequire0ecdddcbf5a967ed661815e7747f4510($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index e68921e1c7..66954f4c3e 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,4 +1,91 @@ [ + { + "name": "erusev/parsedown", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/erusev/parsedown.git", + "reference": "d24439ada0704948deef0d3eda2ea20fd8db1747" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/d24439ada0704948deef0d3eda2ea20fd8db1747", + "reference": "d24439ada0704948deef0d3eda2ea20fd8db1747", + "shasum": "" + }, + "time": "2014-05-21 20:20:46", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Parsedown": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "Parser for Markdown.", + "homepage": "http://parsedown.org", + "keywords": [ + "markdown", + "parser" + ] + }, + { + "name": "erusev/parsedown-extra", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/erusev/parsedown-extra.git", + "reference": "7578fe28ce42e7a1fff4ba2aada3807c4c03d04b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/erusev/parsedown-extra/zipball/7578fe28ce42e7a1fff4ba2aada3807c4c03d04b", + "reference": "7578fe28ce42e7a1fff4ba2aada3807c4c03d04b", + "shasum": "" + }, + "require": { + "erusev/parsedown": "~1.0" + }, + "time": "2014-08-16 11:20:35", + "type": "library", + "installation-source": "source", + "autoload": { + "psr-0": { + "ParsedownExtra": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "An extension of Parsedown that adds support for Markdown Extra.", + "homepage": "https://github.com/erusev/parsedown-extra", + "keywords": [ + "markdown", + "markdown extra", + "parsedown", + "parser" + ] + }, { "name": "doctrine/cache", "version": "dev-master", @@ -70,6 +157,67 @@ "caching" ] }, + { + "name": "tracy/tracy", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/nette/tracy.git", + "reference": "5b62cb55e904ba1a1325803686a9f90959c99585" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/tracy/zipball/5b62cb55e904ba1a1325803686a9f90959c99585", + "reference": "5b62cb55e904ba1a1325803686a9f90959c99585", + "shasum": "" + }, + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "nette/tester": "~1.0" + }, + "time": "2014-08-17 22:39:47", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "installation-source": "source", + "autoload": { + "classmap": [ + "src/Tracy" + ], + "files": [ + "src/shortcuts.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "http://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "http://nette.org/contributors" + } + ], + "description": "Tracy: useful PHP debugger", + "homepage": "http://tracy.nette.org", + "keywords": [ + "debug", + "debugger", + "nette" + ] + }, { "name": "gregwar/cache", "version": "v1.0.9", @@ -163,6 +311,48 @@ "image" ] }, + { + "name": "mrclay/minify", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/mrclay/minify.git", + "reference": "fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mrclay/minify/zipball/fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9", + "reference": "fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "php": ">=5.2.1" + }, + "time": "2014-04-03 23:53:48", + "type": "library", + "installation-source": "source", + "autoload": { + "classmap": [ + "min/lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Steve Clay", + "email": "steve@mrclay.org", + "homepage": "http://www.mrclay.org/", + "role": "Developer" + } + ], + "description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers", + "homepage": "http://code.google.com/p/minify/" + }, { "name": "twig/twig", "version": "dev-master", @@ -271,149 +461,6 @@ "description": "Symfony Yaml Component", "homepage": "http://symfony.com" }, - { - "name": "ircmaxell/password-compat", - "version": "1.0.3", - "version_normalized": "1.0.3.0", - "source": { - "type": "git", - "url": "https://github.com/ircmaxell/password_compat.git", - "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/1fc1521b5e9794ea77e4eca30717be9635f1d4f4", - "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4", - "shasum": "" - }, - "time": "2013-04-30 19:58:08", - "type": "library", - "installation-source": "dist", - "autoload": { - "files": [ - "lib/password.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Anthony Ferrara", - "email": "ircmaxell@ircmaxell.com", - "homepage": "http://blog.ircmaxell.com" - } - ], - "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", - "homepage": "https://github.com/ircmaxell/password_compat", - "keywords": [ - "hashing", - "password" - ] - }, - { - "name": "erusev/parsedown", - "version": "dev-master", - "version_normalized": "9999999-dev", - "source": { - "type": "git", - "url": "https://github.com/erusev/parsedown.git", - "reference": "9437766539f6f88e748e7b6183ea31f78e154df5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/9437766539f6f88e748e7b6183ea31f78e154df5", - "reference": "9437766539f6f88e748e7b6183ea31f78e154df5", - "shasum": "" - }, - "time": "2014-08-13 22:27:48", - "type": "library", - "installation-source": "source", - "autoload": { - "psr-0": { - "Parsedown": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Emanuil Rusev", - "email": "hello@erusev.com", - "homepage": "http://erusev.com" - } - ], - "description": "Parser for Markdown.", - "homepage": "http://parsedown.org", - "keywords": [ - "markdown", - "parser" - ] - }, - { - "name": "tracy/tracy", - "version": "dev-master", - "version_normalized": "9999999-dev", - "source": { - "type": "git", - "url": "https://github.com/nette/tracy.git", - "reference": "e432452e0a68b2e5adfba2061eba412f51dbab4c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/tracy/zipball/e432452e0a68b2e5adfba2061eba412f51dbab4c", - "reference": "e432452e0a68b2e5adfba2061eba412f51dbab4c", - "shasum": "" - }, - "require": { - "php": ">=5.3.1" - }, - "require-dev": { - "nette/tester": "~1.0" - }, - "time": "2014-08-14 17:58:22", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "installation-source": "source", - "autoload": { - "classmap": [ - "src/Tracy" - ], - "files": [ - "src/shortcuts.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "http://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "http://nette.org/contributors" - } - ], - "description": "Tracy: useful PHP debugger", - "homepage": "http://tracy.nette.org", - "keywords": [ - "debug", - "debugger", - "nette" - ] - }, { "name": "symfony/console", "version": "2.5.x-dev", @@ -472,46 +519,45 @@ "homepage": "http://symfony.com" }, { - "name": "mrclay/minify", - "version": "dev-master", - "version_normalized": "9999999-dev", + "name": "ircmaxell/password-compat", + "version": "1.0.3", + "version_normalized": "1.0.3.0", "source": { "type": "git", - "url": "https://github.com/mrclay/minify.git", - "reference": "fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9" + "url": "https://github.com/ircmaxell/password_compat.git", + "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mrclay/minify/zipball/fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9", - "reference": "fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/1fc1521b5e9794ea77e4eca30717be9635f1d4f4", + "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4", "shasum": "" }, - "require": { - "ext-pcre": "*", - "php": ">=5.2.1" - }, - "time": "2014-04-03 23:53:48", + "time": "2013-04-30 19:58:08", "type": "library", - "installation-source": "source", + "installation-source": "dist", "autoload": { - "classmap": [ - "min/lib/" + "files": [ + "lib/password.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Steve Clay", - "email": "steve@mrclay.org", - "homepage": "http://www.mrclay.org/", - "role": "Developer" + "name": "Anthony Ferrara", + "email": "ircmaxell@ircmaxell.com", + "homepage": "http://blog.ircmaxell.com" } ], - "description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers", - "homepage": "http://code.google.com/p/minify/" + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "homepage": "https://github.com/ircmaxell/password_compat", + "keywords": [ + "hashing", + "password" + ] }, { "name": "ornicar/php-user-agent", diff --git a/vendor/erusev/parsedown-extra/LICENSE.txt b/vendor/erusev/parsedown-extra/LICENSE.txt new file mode 100644 index 0000000000..baca86f5b8 --- /dev/null +++ b/vendor/erusev/parsedown-extra/LICENSE.txt @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Emanuil Rusev, erusev.com + +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. \ No newline at end of file diff --git a/vendor/erusev/parsedown-extra/ParsedownExtra.php b/vendor/erusev/parsedown-extra/ParsedownExtra.php new file mode 100644 index 0000000000..b6ac978dc1 --- /dev/null +++ b/vendor/erusev/parsedown-extra/ParsedownExtra.php @@ -0,0 +1,415 @@ +BlockTypes[':'] []= 'DefinitionList'; + + $this->DefinitionTypes['*'] []= 'Abbreviation'; + + # identify footnote definitions before reference definitions + array_unshift($this->DefinitionTypes['['], 'Footnote'); + + # identify footnote markers before before links + array_unshift($this->SpanTypes['['], 'FootnoteMarker'); + } + + # + # ~ + + function text($text) + { + $markup = parent::text($text); + + # merge consecutive dl elements + + $markup = preg_replace('/<\/dl>\s+
\s+/', '', $markup); + + # add footnotes + + if (isset($this->Definitions['Footnote'])) + { + $Element = $this->buildFootnoteElement(); + + $markup .= "\n" . $this->element($Element); + } + + return $markup; + } + + # + # Blocks + # + + # + # Atx + + protected function identifyAtx($Line) + { + $Block = parent::identifyAtx($Line); + + if (preg_match('/[ ]*'.$this->attributesPattern.'[ ]*$/', $Block['element']['text'], $matches, PREG_OFFSET_CAPTURE)) + { + $attributeString = $matches[1][0]; + + $Block['element']['attributes'] = $this->parseAttributes($attributeString); + + $Block['element']['text'] = substr($Block['element']['text'], 0, $matches[0][1]); + } + + return $Block; + } + + # + # Definition List + + protected function identifyDefinitionList($Line, $Block) + { + if (isset($Block['type'])) + { + return; + } + + $Element = array( + 'name' => 'dl', + 'handler' => 'elements', + 'text' => array(), + ); + + $terms = explode("\n", $Block['element']['text']); + + foreach ($terms as $term) + { + $Element['text'] []= array( + 'name' => 'dt', + 'handler' => 'line', + 'text' => $term, + ); + } + + $Element['text'] []= array( + 'name' => 'dd', + 'handler' => 'line', + 'text' => ltrim($Line['text'], ' :'), + ); + + $Block['element'] = $Element; + + return $Block; + } + + protected function addToDefinitionList($Line, array $Block) + { + if ($Line['text'][0] === ':') + { + $Block['element']['text'] []= array( + 'name' => 'dd', + 'handler' => 'line', + 'text' => ltrim($Line['text'], ' :'), + ); + + return $Block; + } + + if ( ! isset($Block['interrupted'])) + { + $Element = array_pop($Block['element']['text']); + + $Element['text'] .= "\n" . chop($Line['text']); + + $Block['element']['text'] []= $Element; + + return $Block; + } + } + + # + # Setext + + protected function identifySetext($Line, array $Block = null) + { + $Block = parent::identifySetext($Line, $Block); + + if (preg_match('/[ ]*'.$this->attributesPattern.'[ ]*$/', $Block['element']['text'], $matches, PREG_OFFSET_CAPTURE)) + { + $attributeString = $matches[1][0]; + + $Block['element']['attributes'] = $this->parseAttributes($attributeString); + + $Block['element']['text'] = substr($Block['element']['text'], 0, $matches[0][1]); + } + + return $Block; + } + + # + # Markup + + protected function completeMarkup($Block) + { + $DOMDocument = new DOMDocument; + + $DOMDocument->loadXML($Block['element']); + + $result = $DOMDocument->documentElement->getAttribute('markdown'); + + if ($result !== '1') + { + return $Block; + } + + $DOMDocument->documentElement->removeAttribute('markdown'); + + $index = 0; + $texts = array(); + + foreach ($DOMDocument->documentElement->childNodes as $Node) + { + if ($Node instanceof DOMText) + { + $texts [] = $this->text($Node->nodeValue); + + # replaces the text of the node with a placeholder + $Node->nodeValue = '\x1A'.$index ++; + } + } + + $markup = $DOMDocument->saveXML($DOMDocument->documentElement); + + foreach ($texts as $index => $text) + { + $markup = str_replace('\x1A'.$index, $text, $markup); + } + + $Block['element'] = $markup; + + return $Block; + } + + # + # Definitions + # + + # + # Abbreviation + + protected function identifyAbbreviation($Line) + { + if (preg_match('/^\*\[(.+?)\]:[ ]*(.+?)[ ]*$/', $Line['text'], $matches)) + { + $Abbreviation = array( + 'id' => $matches[1], + 'data' => $matches[2], + ); + + return $Abbreviation; + } + } + + # + # Footnote + + protected function identifyFootnote($Line) + { + if (preg_match('/^\[\^(.+?)\]:[ ]?(.+)$/', $Line['text'], $matches)) + { + $Footnote = array( + 'id' => $matches[1], + 'data' => array( + 'text' => $matches[2], + 'count' => null, + 'number' => null, + ), + ); + + return $Footnote; + } + } + + # + # Spans + # + + # + # Footnote Marker + + protected function identifyFootnoteMarker($Excerpt) + { + if (preg_match('/^\[\^(.+?)\]/', $Excerpt['text'], $matches)) + { + $name = $matches[1]; + + if ( ! isset($this->Definitions['Footnote'][$name])) + { + return; + } + + $this->Definitions['Footnote'][$name]['count'] ++; + + if ( ! isset($this->Definitions['Footnote'][$name]['number'])) + { + $this->Definitions['Footnote'][$name]['number'] = ++ $this->footnoteCount; # » & + } + + $Element = array( + 'name' => 'sup', + 'attributes' => array('id' => 'fnref'.$this->Definitions['Footnote'][$name]['count'].':'.$name), + 'handler' => 'element', + 'text' => array( + 'name' => 'a', + 'attributes' => array('href' => '#fn:'.$name, 'class' => 'footnote-ref'), + 'text' => $this->Definitions['Footnote'][$name]['number'], + ), + ); + + return array( + 'extent' => strlen($matches[0]), + 'element' => $Element, + ); + } + } + + private $footnoteCount = 0; + + # + # Link + + protected function identifyLink($Excerpt) + { + $Span = parent::identifyLink($Excerpt); + + $remainder = substr($Excerpt['text'], $Span['extent']); + + if (preg_match('/^[ ]*'.$this->attributesPattern.'/', $remainder, $matches)) + { + $Span['element']['attributes'] += $this->parseAttributes($matches[1]); + + $Span['extent'] += strlen($matches[0]); + } + + return $Span; + } + + # + # ~ + + protected function readPlainText($text) + { + $text = parent::readPlainText($text); + + if (isset($this->Definitions['Abbreviation'])) + { + foreach ($this->Definitions['Abbreviation'] as $abbreviation => $phrase) + { + $text = str_replace($abbreviation, ''.$abbreviation.'', $text); + } + } + + return $text; + } + + # + # ~ + # + + protected function buildFootnoteElement() + { + $Element = array( + 'name' => 'div', + 'attributes' => array('class' => 'footnotes'), + 'handler' => 'elements', + 'text' => array( + array( + 'name' => 'hr', + ), + array( + 'name' => 'ol', + 'handler' => 'elements', + 'text' => array(), + ), + ), + ); + + usort($this->Definitions['Footnote'], function($A, $B) { + return $A['number'] - $B['number']; + }); + + foreach ($this->Definitions['Footnote'] as $name => $Data) + { + if ( ! isset($Data['number'])) + { + continue; + } + + $text = $Data['text']; + + foreach (range(1, $Data['count']) as $number) + { + $text .= ' '; + } + + $Element['text'][1]['text'] []= array( + 'name' => 'li', + 'attributes' => array('id' => 'fn:'.$name), + 'handler' => 'elements', + 'text' => array( + array( + 'name' => 'p', + 'text' => $text, + ), + ), + ); + } + + return $Element; + } + + # + # Private + # + + private function parseAttributes($attributeString) + { + $Data = array(); + + $attributes = preg_split('/[ ]+/', $attributeString, - 1, PREG_SPLIT_NO_EMPTY); + + foreach ($attributes as $attribute) + { + if ($attribute[0] === '#') + { + $Data['id'] = substr($attribute, 1); + } + else # "." + { + $classes []= substr($attribute, 1); + } + } + + if (isset($classes)) + { + $Data['class'] = implode(' ', $classes); + } + + return $Data; + } + + private $attributesPattern = '{((?:[#.][-\w]+[ ]*)+)}'; +} diff --git a/vendor/erusev/parsedown-extra/README.md b/vendor/erusev/parsedown-extra/README.md new file mode 100644 index 0000000000..931ea2f9c8 --- /dev/null +++ b/vendor/erusev/parsedown-extra/README.md @@ -0,0 +1,17 @@ +## Parsedown Extra + +An extension of [Parsedown](http://parsedown.org) that adds support for [Markdown Extra](http://en.wikipedia.org/wiki/Markdown_Extra). + +[[ demo ]](http://parsedown.org/demo?extra=1) + +### Installation + +Include both `Parsedown.php` and `ParsedownExtra.php` or install [the composer package](https://packagist.org/packages/erusev/parsedown-extra). + +### Example + +``` php +$Instance = new ParsedownExtra(); + +echo $Instance->text('Hello _Parsedown Extra_!'); # prints:

Hello Parsedown Extra!

+``` diff --git a/vendor/erusev/parsedown/Parsedown.php b/vendor/erusev/parsedown/Parsedown.php index a109451604..f877c4871e 100755 --- a/vendor/erusev/parsedown/Parsedown.php +++ b/vendor/erusev/parsedown/Parsedown.php @@ -619,7 +619,7 @@ protected function identifySetext($Line, array $Block = null) protected function identifyMarkup($Line) { - if (preg_match('/^<(\w[\w\d]*)(?:[ ][^>]*)?(\/?)[ ]*>/', $Line['text'], $matches)) + if (preg_match('/^<(\w[\w\d]*)(?:[ ][^>\/]*)?(\/?)[ ]*>/', $Line['text'], $matches)) { if (in_array($matches[1], $this->textLevelElements)) { diff --git a/vendor/erusev/parsedown/README.md b/vendor/erusev/parsedown/README.md index f1676f4d23..a67b3ec9e4 100644 --- a/vendor/erusev/parsedown/README.md +++ b/vendor/erusev/parsedown/README.md @@ -13,7 +13,6 @@ Better [Markdown](http://en.wikipedia.org/wiki/Markdown) parser for PHP. * [Tested](https://travis-ci.org/erusev/parsedown) in PHP 5.2, 5.3, 5.4, 5.5, 5.6 and [hhvm](http://www.hhvm.com/) * Extensible * [Markdown Extra extension](https://github.com/erusev/parsedown-extra) new -* [JavaScript port](https://github.com/hkdobrev/parsedown.js) under development new ### Installation diff --git a/vendor/tracy/tracy/src/Tracy/Debugger.php b/vendor/tracy/tracy/src/Tracy/Debugger.php index 76a65442aa..0c66cd99a9 100644 --- a/vendor/tracy/tracy/src/Tracy/Debugger.php +++ b/vendor/tracy/tracy/src/Tracy/Debugger.php @@ -128,7 +128,9 @@ public static function enable($mode = NULL, $logDirectory = NULL, $email = NULL) self::$time = isset($_SERVER['REQUEST_TIME_FLOAT']) ? $_SERVER['REQUEST_TIME_FLOAT'] : microtime(TRUE); error_reporting(E_ALL | E_STRICT); - self::$productionMode = is_bool($mode) ? $mode : !self::detectDebugMode($mode); + if ($mode !== NULL || self::$productionMode === NULL) { + self::$productionMode = is_bool($mode) ? $mode : !self::detectDebugMode($mode); + } // logging configuration if ($email !== NULL) { From e91b9c84bfe2ed9177ea87cadf3545934d096e6d Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 18 Aug 2014 14:13:51 +0300 Subject: [PATCH 19/63] Implement DI container --- composer.json | 5 +- index.php | 31 +-- system/defines.php | 2 +- system/src/Grav/Common/Cache.php | 25 ++- system/src/Grav/Common/Config.php | 13 +- system/src/Grav/Common/Data/Blueprint.php | 1 - system/src/Grav/Common/Debugger.php | 52 +++++ system/src/Grav/Common/Grav.php | 195 ++++++++---------- system/src/Grav/Common/Page/Collection.php | 5 +- system/src/Grav/Common/Page/Media.php | 7 +- system/src/Grav/Common/Page/Medium.php | 10 +- system/src/Grav/Common/Page/Page.php | 48 ++--- system/src/Grav/Common/Page/Pages.php | 71 ++++--- system/src/Grav/Common/Plugins.php | 21 +- system/src/Grav/Common/Registry.php | 41 ++-- system/src/Grav/Common/Taxonomy.php | 7 +- system/src/Grav/Common/Themes.php | 17 +- system/src/Grav/Common/Twig.php | 126 +++++------ system/src/Grav/Common/Utils.php | 2 +- system/src/Grav/Component/DI/Container.php | 6 + .../Component/DI/ServiceProviderInterface.php | 6 + user/config/system.yaml | 2 +- 22 files changed, 381 insertions(+), 312 deletions(-) create mode 100644 system/src/Grav/Common/Debugger.php create mode 100644 system/src/Grav/Component/DI/Container.php create mode 100644 system/src/Grav/Component/DI/ServiceProviderInterface.php diff --git a/composer.json b/composer.json index c937e27a81..e506e7ecfc 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ } ], "require": { - "php": ">=5.3.10", + "php": ">=5.4.0", "twig/twig": "1.16.*@dev", "erusev/parsedown": "dev-master", "symfony/yaml": "2.5.*@dev", @@ -20,6 +20,7 @@ "doctrine/cache": "1.4.*@dev", "tracy/tracy": "dev-master", "gregwar/image": "dev-master", - "ircmaxell/password-compat": "1.0.*" + "ircmaxell/password-compat": "1.0.*", + "pimple/pimple": "~3.0" } } diff --git a/index.php b/index.php index 02a6a352a8..f35aa9b984 100644 --- a/index.php +++ b/index.php @@ -1,11 +1,12 @@ PHP %s to run.', $ver, $req)); } -use Tracy\Debugger; +use Grav\Common\Grav; +use Grav\Common\Debugger; // Register system libraries to the auto-loader. $loader = require_once __DIR__ . '/system/autoload.php'; @@ -14,28 +15,18 @@ date_default_timezone_set('UTC'); } +$grav = Grav::instance( + [ + 'Loader' => $loader, + 'Debugger' => new Debugger + ] +); + // Use output buffering to prevent headers from being sent too early. ob_start(); -// Start the timer and enable debugger in production mode as we do not have system configuration yet. -// Debugger catches all errors and logs them, for example if the script doesn't have write permissions. -Debugger::timer(); -Debugger::enable(Debugger::DEVELOPMENT, is_dir(LOG_DIR) ? LOG_DIR : null); - -$grav = new Grav; - try { - // Register all the Grav bits into registry. - $registry = Registry::instance(); - $registry->store('autoloader', $loader); - $registry->store('Grav', $grav); - $registry->store('Uri', new Uri); - $registry->store('Config', Config::instance(CACHE_DIR . 'config.php')); - $registry->store('Cache', new Cache); - $registry->store('Twig', new Twig); - $registry->store('Pages', new Page\Pages); - $registry->store('Taxonomy', new Taxonomy); - + $grav['Debugger']->init(); $grav->process(); } catch (\Exception $e) { diff --git a/system/defines.php b/system/defines.php index b7d1a3526e..1000f058b3 100644 --- a/system/defines.php +++ b/system/defines.php @@ -2,7 +2,7 @@ // Some standard defines define('GRAV', true); -define('GRAV_VERSION', '0.8.0'); +define('GRAV_VERSION', '0.8.1'); define('DS', '/'); // Directories and Paths diff --git a/system/src/Grav/Common/Cache.php b/system/src/Grav/Common/Cache.php index a032e554d2..27eb942ec6 100644 --- a/system/src/Grav/Common/Cache.php +++ b/system/src/Grav/Common/Cache.php @@ -1,6 +1,8 @@ init($c); + } + /** * Initialization that sets a base key and the driver based on configuration settings * + * @param Grav $c * @return void */ - public function init() + public function init(Grav $c) { /** @var Config $config */ - $config = Registry::get('Config'); - $prefix = $config->get('system.cache.prefix'); + $config = $c['Config']; + /** @var Uri $uri */ - $uri = Registry::get('Uri'); + $uri = $c['Uri']; + + $prefix = $config->get('system.cache.prefix'); $this->enabled = (bool) $config->get('system.cache.enabled'); diff --git a/system/src/Grav/Common/Config.php b/system/src/Grav/Common/Config.php index 68865b6dff..9b96db61fa 100644 --- a/system/src/Grav/Common/Config.php +++ b/system/src/Grav/Common/Config.php @@ -101,16 +101,17 @@ public function save() } /** - * Gets configuration instance. + * Load configuration. * - * @param string $filename + * @param Grav $grav * @return \Grav\Common\Config */ - public static function instance($filename) + public static function instance(Grav $grav) { + $filename = $grav['config_path']; + // Load cached version if available.. if (file_exists($filename)) { - clearstatcache(true, $filename); require_once $filename; if (class_exists('\Grav\Config')) { @@ -131,11 +132,11 @@ public static function instance($filename) // If not set, add manually current base url. if (empty($instance->items['system']['base_url_absolute'])) { - $instance->items['system']['base_url_absolute'] = Registry::get('Uri')->rootUrl(true); + $instance->items['system']['base_url_absolute'] = $grav['Uri']->rootUrl(true); } if (empty($instance->items['system']['base_url_relative'])) { - $instance->items['system']['base_url_relative'] = Registry::get('Uri')->rootUrl(false); + $instance->items['system']['base_url_relative'] = $grav['Uri']->rootUrl(false); } return $instance; diff --git a/system/src/Grav/Common/Data/Blueprint.php b/system/src/Grav/Common/Data/Blueprint.php index 6339f873a6..362a999cf5 100644 --- a/system/src/Grav/Common/Data/Blueprint.php +++ b/system/src/Grav/Common/Data/Blueprint.php @@ -1,7 +1,6 @@ get('system.debugger.log.enabled') ? LOG_DIR : null; + TracyDebugger::$maxDepth = $config->get('system.debugger.max_depth'); + + // Switch debugger into development mode if configured + if ($config->get('system.debugger.enabled')) { + if ($config->get('system.debugger.strict')) { + TracyDebugger::$strictMode = true; + } + + if (function_exists('ini_set')) { + ini_set('display_errors', true); + } + TracyDebugger::$productionMode = TracyDebugger::DEVELOPMENT; + } + } + + /** + * Log a message. + * + * @param string $message + */ + public function log($message) + { + if (TracyDebugger::$logDirectory) { + TracyDebugger::log(sprintf($message, TracyDebugger::timer() * 1000)); + } + } +} diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 454e5fb986..ac0ebc726b 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -1,10 +1,7 @@ $value) { + $instance->offsetSet($key, $value); + } + } - /** - * @var Twig - */ - protected $twig; + return self::$instance; + } - /** - * @var Taxonomy - */ - protected $taxonomy; + protected static function load(array $values) + { + $container = new static($values); + + $container['config_path'] = CACHE_DIR . 'config.php'; + + $container['Grav'] = $container; + + $container['Uri'] = function ($c) { + return new Uri($c); + }; + $container['Config'] = function ($c) { + return Config::instance($c); + }; + $container['Cache'] = function ($c) { + return new Cache($c); + }; + $container['Plugins'] = function ($c) { + return new Plugins($c); + }; + $container['Themes'] = function ($c) { + return new Themes($c); + }; + $container['Twig'] = function ($c) { + return new Twig($c); + }; + $container['Taxonomy'] = function ($c) { + return new Taxonomy($c); + }; + $container['Pages'] = function ($c) { + return new Page\Pages($c); + }; + $container['Page'] = function ($c) { + return $c['Pages']->dispatch($c['Uri']->route()); + }; + + return $container; + } public function process() { - // Get the URI and URL (needed for configuration) - $this->uri = Registry::get('Uri'); - - // Get the Configuration settings and caching - $this->config = Registry::get('Config'); - - Debugger::$logDirectory = $this->config->get('system.debugger.log.enabled') ? LOG_DIR : null; - Debugger::$maxDepth = $this->config->get('system.debugger.max_depth'); - - // Switch debugger into development mode if configured - if ($this->config->get('system.debugger.enabled')) { - if ($this->config->get('system.debugger.strict')) { - Debugger::$strictMode = true; - } + $this['Plugins']->init(); - if (function_exists('ini_set')) { - ini_set('display_errors', true); - } - Debugger::$productionMode = Debugger::DEVELOPMENT; - } - - // Get the Caching setup - $this->cache = Registry::get('Cache'); - $this->cache->init(); - - // Get Plugins - $plugins = new Plugins(); - $this->plugins = $plugins->load(); $this->fireEvent('onAfterInitPlugins'); - // Get current theme and hook it into plugins. - $themes = new Themes(); - $this->plugins['Theme'] = $themes->load(); - - // Get twig object - $this->twig = Registry::get('Twig'); - $this->twig->init(); + $this['Twig']->init(); + $this['Pages']->init(); - // Get all the Pages that Grav knows about - $this->pages = Registry::get('Pages'); - $this->pages->init(); $this->fireEvent('onAfterGetPages'); - // Get the taxonomy and set it on the grav object - $this->taxonomy = Registry::get('Taxonomy'); - - // Get current page - $this->page = $this->pages->dispatch($this->uri->route()); $this->fireEvent('onAfterGetPage'); // If there's no page, throw exception - if (!$this->page) { + if (!$this['Page']) { throw new \RuntimeException('Page Not Found', 404); } // Process whole page as required - $this->output = $this->twig->processSite($this->uri->extension()); + $this->output = $this['Twig']->processSite($this['Uri']->extension()); + $this->fireEvent('onAfterGetOutput'); // Set the header type @@ -146,7 +123,9 @@ public function process() */ public function redirect($route, $code = 303) { - header("Location: " . rtrim($this->uri->rootUrl(), '/') .'/'. trim($route, '/'), true, $code); + /** @var Uri $uri */ + $uri = $this['Uri']; + header("Location: " . rtrim($uri->rootUrl(), '/') .'/'. trim($route, '/'), true, $code); exit(); } @@ -178,19 +157,9 @@ public function mime($format) */ public function header() { - header('Content-type: ' . $this->mime($this->uri->extension())); - } - - /** - * Log a message. - * - * @param string $message - */ - protected static function log($message) - { - if (Debugger::$logDirectory) { - Debugger::log(sprintf($message, Debugger::timer() * 1000)); - } + /** @var Uri $uri */ + $uri = $this['Uri']; + header('Content-type: ' . $this->mime($uri->extension())); } /** @@ -202,16 +171,26 @@ public function fireEvent() $hook_id = array_shift($args); $no_timing_hooks = array('onAfterPageProcessed','onAfterFolderProcessed', 'onAfterCollectionProcessed'); - if (!empty($this->plugins)) { - foreach ($this->plugins as $plugin) { + /** @var Plugins $plugins */ + $plugins = $this['Plugins']; + + if (!empty($plugins)) { + foreach ($plugins as $plugin) { if (is_callable(array($plugin, $hook_id))) { call_user_func_array(array($plugin, $hook_id), $args); } } } - if ($this->config && $this->config->get('system.debugger.log.timing') && !in_array($hook_id, $no_timing_hooks)) { - static::log($hook_id.': %f ms'); + if (isset($this['Debugger'])) { + /** @var Config $config */ + $config = $this['Config']; + + if ($config && $config->get('system.debugger.log.timing') && !in_array($hook_id, $no_timing_hooks)) { + /** @var Debugger $debugger */ + $debugger = $this['Debugger']; + $debugger->log($hook_id.': %f ms'); + } } } } diff --git a/system/src/Grav/Common/Page/Collection.php b/system/src/Grav/Common/Page/Collection.php index 857675af60..2d5bf47662 100644 --- a/system/src/Grav/Common/Page/Collection.php +++ b/system/src/Grav/Common/Page/Collection.php @@ -1,7 +1,8 @@ params = $params; - $this->pages = $pages ? $pages : Registry::get('Pages'); + $this->pages = $pages ? $pages : Grav::instance()['Pages']; } public function params() diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index 4dcddc78f0..fbfc47365c 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -2,9 +2,8 @@ namespace Grav\Common\Page; use Grav\Common\Getters; -use Grav\Common\Registry; -use Grav\Config; -use Symfony\Component\Yaml\Yaml; +use Grav\Common\Grav; +use Grav\Common\Config; /** * Media is a holder object that contains references to the media of page. This object is created and @@ -76,7 +75,7 @@ public function get($filename, $create = false) $basename = implode('.', $parts); /** @var Config $config */ - $config = Registry::get('Config'); + $config = Grav::instance()['Config']; // Check if medium type has been configured. $params = $config->get("media.{$ext}"); diff --git a/system/src/Grav/Common/Page/Medium.php b/system/src/Grav/Common/Page/Medium.php index f966af9801..cefb90906a 100644 --- a/system/src/Grav/Common/Page/Medium.php +++ b/system/src/Grav/Common/Page/Medium.php @@ -1,11 +1,11 @@ image) { $output = $this->image->cacheFile($this->type, $this->quality); @@ -172,7 +173,8 @@ public function html($title = null, $class = null, $type = null, $quality = 80) } if ($this->linkTarget) { - $config = Registry::get('Config'); + /** @var Config $config */ + $config = Grav::instance()['Config']; $output = 'linkAttributes. ' class="'. $class . '">' . $output . ''; diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 310ade904c..ca9a7033bb 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -84,7 +84,7 @@ class Page public function __construct($array = array()) { /** @var Config $config */ - $config = Registry::get('Config'); + $config = Grav::instance()['Config']; $this->routable = true; $this->taxonomy = array(); @@ -231,7 +231,7 @@ public function summary($size = null) // Return calculated summary based on setting in site config file /** @var Config $config */ - $config = Registry::get('Config'); + $config = Grav::instance()['Config']; if (!$size && $config->get('site.summary.size')) { $size = $config->get('site.summary.size'); } @@ -271,7 +271,7 @@ public function content($var = null) // Load cached content /** @var Cache $cache */ - $cache = Registry::get('Cache'); + $cache = Grav::instance()['Cache']; $cache_id = md5('page'.$this->id()); $content = $cache->fetch($cache_id); @@ -297,7 +297,7 @@ public function content($var = null) // Do we need to process twig this time? if ($update_cache || $process_twig) { /** @var Twig $twig */ - $twig = Registry::get('Twig'); + $twig = Grav::instance()['Twig']; $content = $twig->processPage($this, $content); } } @@ -465,7 +465,7 @@ public function copy($parent) public function blueprints() { /** @var Pages $pages */ - $pages = Registry::get('Pages'); + $pages = Grav::instance()['Pages']; return $pages->blueprints($this->template()); } @@ -544,7 +544,7 @@ public function toJson() public function media($var = null) { /** @var Cache $cache */ - $cache = Registry::get('Cache'); + $cache = Grav::instance()['Cache']; if ($var) { $this->media = $var; @@ -762,7 +762,7 @@ public function link($include_host = false) public function url($include_host = false) { /** @var Uri $uri */ - $uri = Registry::get('Uri'); + $uri = Grav::instance()['Uri']; $rootUrl = $uri->rootUrl($include_host); $url = $rootUrl.'/'.trim($this->route(), '/'); @@ -958,7 +958,7 @@ public function maxCount($var = null) } if (empty($this->max_count)) { /** @var Config $config */ - $config = Registry::get('Config'); + $config = Grav::instance()['Config']; $this->max_count = (int) $config->get('system.pages.list.count'); } return $this->max_count; @@ -1029,11 +1029,13 @@ public function shouldProcess($process) */ public function parent(Page $var = null) { - if ($var !== null) { - $this->parent = $var ? $var->path() : ''; + if ($var) { + $this->parent = $var->path(); + return $var; } + /** @var Pages $pages */ - $pages = Registry::get('Pages'); + $pages = Grav::instance()['Pages']; return $pages->get($this->parent); } @@ -1046,7 +1048,7 @@ public function parent(Page $var = null) public function children() { /** @var Pages $pages */ - $pages = Registry::get('Pages'); + $pages = Grav::instance()['Pages']; return $pages->children($this->path()); } @@ -1126,7 +1128,7 @@ public function nth($key) public function isFirst() { /** @var Pages $pages */ - $pages = Registry::get('Pages'); + $pages = Grav::instance()['Pages']; $parent = $pages->get($this->parent); if ($this->path() == array_values($parent->items)[0]) { @@ -1144,7 +1146,7 @@ public function isFirst() public function isLast() { /** @var Pages $pages */ - $pages = Registry::get('Pages'); + $pages = Grav::instance()['Pages']; $parent = $pages->get($this->parent); if ($this->path() == array_values($parent->items)[count($parent->items)-1]) { @@ -1183,7 +1185,7 @@ public function nextSibling() public function adjacentSibling($direction = 1) { /** @var Pages $pages */ - $pages = Registry::get('Pages'); + $pages = Grav::instance()['Pages']; $parent = $pages->get($this->parent); $current = $this->slug(); @@ -1202,7 +1204,7 @@ public function adjacentSibling($direction = 1) public function active() { /** @var Uri $uri */ - $uri = Registry::get('Uri'); + $uri = Grav::instance()['Uri']; if ($this->url() == $uri->url()) { return true; } @@ -1217,7 +1219,7 @@ public function active() */ public function activeChild() { - $uri = Registry::get('Uri'); + $uri = Grav::instance()['Uri']; if (!$this->home() && (strpos($uri->url(), $this->url()) !== false)) { return true; } @@ -1258,7 +1260,7 @@ public function root() public function find($url) { /** @var Pages $pages */ - $pages = Registry::get('Pages'); + $pages = Grav::instance()['Pages']; return $pages->dispatch($url); } @@ -1289,9 +1291,9 @@ public function collection($params = 'content') // TODO: MOVE THIS INTO SOMEWHERE ELSE? /** @var Uri $uri */ - $uri = Registry::get('Uri'); + $uri = Grav::instance()['Uri']; /** @var Config $config */ - $config = Registry::get('Config'); + $config = Grav::instance()['Config']; foreach ((array) $config->get('site.taxonomies') as $taxonomy) { if ($uri->param($taxonomy)) { @@ -1323,7 +1325,7 @@ public function collection($params = 'content') } /** @var Grav $grav */ - $grav = Registry::get('Grav'); + $grav = Grav::instance()['Grav']; // New Custom event to handle things like pagination. $grav->fireEvent('onAfterCollectionProcessed', $collection); @@ -1391,7 +1393,7 @@ protected function evaluate($value) // @taxonomy: { category: [ blog, featured ], level: 1 } /** @var Taxonomy $taxonomy_map */ - $taxonomy_map = Registry::get('Taxonomy'); + $taxonomy_map = Grav::instance()['Taxonomy']; if (!empty($parts)) { $params = [implode('.', $parts) => $params]; @@ -1540,7 +1542,7 @@ protected function doRelocation($reorder) // Do reordering. if ($reorder && $this->order() != $this->_original->order()) { /** @var Pages $pages */ - $pages = Registry::get('Pages'); + $pages = Grav::instance()['Pages']; $parent = $this->parent(); diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index 2de1561673..19932d0aa6 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -5,7 +5,6 @@ use \Grav\Common\Grav; use \Grav\Common\Config; use \Grav\Common\Data; -use \Grav\Common\Registry; use \Grav\Common\Utils; use \Grav\Common\Cache; use \Grav\Common\Taxonomy; @@ -20,11 +19,6 @@ class Pages */ protected $grav; - /** - * @var Config - */ - protected $config; - /** * @var array|Page[] */ @@ -55,14 +49,21 @@ class Pages */ protected $last_modified; + /** + * Constructor + * + * @params Grav $c + */ + public function __construct(Grav $c) + { + $this->grav = $c; + } + /** * Class initialization. Must be called before using this class. */ public function init() { - $this->grav = Registry::get('Grav'); - $this->config = Registry::get('Config'); - $this->buildPages(); } @@ -221,7 +222,10 @@ public function dispatch($url, $all = false) // If the page cannot be reached, look into site wide routes. if (!$all && (!$page || !$page->routable())) { - $route = $this->config->get("site.routes.{$url}"); + /** @var Config $config */ + $config = $this->grav['Config']; + + $route = $config->get("site.routes.{$url}"); if ($route) { $page = $this->dispatch($route, $all); } @@ -249,7 +253,10 @@ public function root() public function blueprints($type) { if (!isset($this->blueprints)) { - $this->blueprints = new Data\Blueprints(THEMES_DIR . $this->config->get('system.pages.theme') . '/blueprints/'); + /** @var Config $config */ + $config = $this->grav['Config']; + + $this->blueprints = new Data\Blueprints(THEMES_DIR . $config->get('system.pages.theme') . '/blueprints/'); } try { @@ -259,9 +266,7 @@ public function blueprints($type) } if (!$blueprint->initialized) { - /** @var Grav $grav */ - $grav = Registry::get('Grav'); - $grav->fireEvent('onCreateBlueprint', $blueprint); + $this->grav->fireEvent('onCreateBlueprint', $blueprint); $blueprint->initialized = true; } @@ -306,7 +311,8 @@ public function getList(Page $current = null, $level = 0) static public function types() { /** @var Config $config */ - $config = Registry::get('Config'); + $config = Grav::instance()['Config']; + $blueprints = new Data\Blueprints(THEMES_DIR . $config->get('system.pages.theme') . '/blueprints/'); return $blueprints->types(); @@ -320,7 +326,7 @@ static public function types() static public function parents() { /** @var Pages $pages */ - $pages = Registry::get('Pages'); + $pages = Grav::instance()['Pages']; return $pages->getList(); } @@ -332,12 +338,16 @@ static public function parents() protected function buildPages() { $this->sort = array(); - if ($this->config->get('system.cache.enabled')) { + + /** @var Config $config */ + $config = $this->grav['Config']; + + if ($config->get('system.cache.enabled')) { /** @var Cache $cache */ - $cache = Registry::get('Cache'); + $cache = $this->grav['Cache']; /** @var Taxonomy $taxonomy */ - $taxonomy = Registry::get('Taxonomy'); - $last_modified = $this->config->get('system.cache.check.pages', true) + $taxonomy = $this->grav['Taxonomy']; + $last_modified = $config->get('system.cache.check.pages', true) ? Folder::lastModified(PAGES_DIR) : 0; $page_cache_id = md5(USER_DIR.$last_modified); @@ -370,16 +380,18 @@ protected function buildPages() * @throws \RuntimeException * @internal */ - protected function recurse($directory = PAGES_DIR, &$parent = null) + protected function recurse($directory = PAGES_DIR, Page &$parent = null) { $directory = rtrim($directory, DS); $iterator = new \DirectoryIterator($directory); $page = new Page; + $config = $this->grav['Config']; $page->path($directory); - $page->parent($parent); - $page->orderDir($this->config->get('system.pages.order.dir')); - $page->orderBy($this->config->get('system.pages.order.by')); + if ($parent) $page->parent($parent); + + $page->orderDir($config->get('system.pages.order.dir')); + $page->orderBy($config->get('system.pages.order.by')); // Add into instances if (!isset($this->instances[$page->path()])) { @@ -399,7 +411,7 @@ protected function recurse($directory = PAGES_DIR, &$parent = null) $page->init($file); - if ($this->config->get('system.pages.events.page')) { + if ($config->get('system.pages.events.page')) { $this->grav->fireEvent('onAfterPageProcessed', $page); } @@ -426,7 +438,7 @@ protected function recurse($directory = PAGES_DIR, &$parent = null) // set the last modified time on pages $this->lastModified($file->getMTime()); - if ($this->config->get('system.pages.events.page')) { + if ($config->get('system.pages.events.page')) { $this->grav->fireEvent('onAfterFolderProcessed', $page); } } @@ -444,7 +456,7 @@ protected function recurse($directory = PAGES_DIR, &$parent = null) protected function buildRoutes() { /** @var $taxonomy Taxonomy */ - $taxonomy = Registry::get('Taxonomy'); + $taxonomy = $this->grav['Taxonomy']; // Build routes and taxonomy map. /** @var $page Page */ @@ -465,8 +477,11 @@ protected function buildRoutes() } } + /** @var Config $config */ + $config = $this->grav['Config']; + // Alias and set default route to home page. - $home = trim($this->config->get('system.home.alias'), '/'); + $home = trim($config->get('system.home.alias'), '/'); if ($home && isset($this->routes['/' . $home])) { $this->routes['/'] = $this->routes['/' . $home]; $this->get($this->routes['/' . $home])->route('/'); diff --git a/system/src/Grav/Common/Plugins.php b/system/src/Grav/Common/Plugins.php index 1be3f9e7ae..c275c72e26 100644 --- a/system/src/Grav/Common/Plugins.php +++ b/system/src/Grav/Common/Plugins.php @@ -10,13 +10,13 @@ * @author RocketTheme * @license MIT */ -class Plugins +class Plugins extends Iterator { - /** - * @var array|Plugin[] - */ - protected $plugins; + protected $grav; + public function __construct(Grav $grav) { + $this->grav = $grav; + } /** * Recurses through the plugins directory creating Plugin objects for each plugin it finds. @@ -24,12 +24,13 @@ class Plugins * @return array|Plugin[] array of Plugin objects * @throws \RuntimeException */ - public function load() + public function init() { /** @var Config $config */ - $config = Registry::get('Config'); + $config = $this->grav['Config']; $plugins = (array) $config->get('plugins'); + $instances = ['Theme' => $this->grav['Themes']->load()]; foreach ($plugins as $plugin => $data) { if (empty($data['enabled'])) { // Only load enabled plugins. @@ -50,16 +51,16 @@ public function load() throw new \RuntimeException(sprintf("Plugin '%s' class not found!", $plugin)); } - $this->plugins[$pluginClass] = new $pluginClass($config); + $instances[$pluginClass] = new $pluginClass($config); } - return $this->plugins; + return $instances; } public function add($plugin) { if (is_object($plugin)) { - $this->plugins[get_class($plugin)] = $plugin; + $this->items[get_class($plugin)] = $plugin; } } diff --git a/system/src/Grav/Common/Registry.php b/system/src/Grav/Common/Registry.php index 59fbe5d7a1..97e8ce6866 100644 --- a/system/src/Grav/Common/Registry.php +++ b/system/src/Grav/Common/Registry.php @@ -7,18 +7,10 @@ * * @author RocketTheme * @license MIT + * @deprecated */ class Registry { - /** - * @var array - */ - private $registry = array(); - - /** - * @var Registry - */ - private static $instance = null; /** * Return global instance. @@ -27,11 +19,8 @@ class Registry */ public static function instance() { - if (self::$instance === null) { - self::$instance = new Registry(); - } - - return self::$instance; + user_error(__METHOD__ . '()', E_USER_DEPRECATED); + return new Registry; } /** @@ -43,11 +32,9 @@ public static function instance() */ public static function get($key) { - if (!isset(self::$instance->registry[$key])) { - throw new \Exception("There is no entry for key " . $key); - } - - return self::$instance->registry[$key]; + user_error(__METHOD__ . '()', E_USER_DEPRECATED); + $instance = Grav::instance(); + return $instance[$key]; } /** @@ -73,11 +60,9 @@ private function __clone() */ public function store($key, $value) { - if (isset($this->registry[$key])) { - throw new \Exception("There is already an entry for key " . $key); - } - - $this->registry[$key] = $value; + user_error(__CLASS__ . '::' . __METHOD__ . '()', E_USER_DEPRECATED); + $instance = Grav::instance(); + $instance[$key] = $value; } /** @@ -89,10 +74,8 @@ public function store($key, $value) */ public function retrieve($key) { - if (!isset($this->registry[$key])) { - throw new \Exception("There is no entry for key " . $key); - } - - return $this->registry[$key]; + user_error(__CLASS__ . '::' . __METHOD__ . '()', E_USER_DEPRECATED); + $instance = Grav::instance(); + return $instance[$key]; } } diff --git a/system/src/Grav/Common/Taxonomy.php b/system/src/Grav/Common/Taxonomy.php index 3143e2d4e0..93e1eca62c 100644 --- a/system/src/Grav/Common/Taxonomy.php +++ b/system/src/Grav/Common/Taxonomy.php @@ -26,13 +26,15 @@ class Taxonomy { protected $taxonomy_map; + protected $grav; /** * Constructor that resets the map */ - public function __construct() + public function __construct(Grav $grav) { $this->taxonomy_map = array(); + $this->grav = $grav; } /** @@ -48,7 +50,8 @@ public function addTaxonomy(Page\Page $page, $page_taxonomy = null) $page_taxonomy = $page->taxonomy(); } - $config = Registry::get('Config'); + /** @var Config $config */ + $config = $this->grav['Config']; if ($config->get('site.taxonomies') && count($page_taxonomy) > 0) { foreach ((array) $config->get('site.taxonomies') as $taxonomy) { if (isset($page_taxonomy[$taxonomy])) { diff --git a/system/src/Grav/Common/Themes.php b/system/src/Grav/Common/Themes.php index f21e8faac9..fcc8ed6fcb 100644 --- a/system/src/Grav/Common/Themes.php +++ b/system/src/Grav/Common/Themes.php @@ -11,12 +11,22 @@ */ class Themes { + /** + * @var Grav + */ + protected $grav; + + public function __construct(Grav $grav) + { + $this->grav = $grav; + } + /** * Return list of all theme data with their blueprints. * * @return array|Data\Data[] */ - static public function all() + public function all() { $list = array(); $iterator = new \DirectoryIterator(THEMES_DIR); @@ -43,7 +53,7 @@ static public function all() * @return Data\Data * @throws \RuntimeException */ - static public function get($type) + public function get($type) { if (!$type) { throw new \RuntimeException('Theme name not provided.'); @@ -77,7 +87,8 @@ static public function get($type) public function load($name = null) { if (!$name) { - $config = Registry::get('Config'); + /** @var Config $config */ + $config = $this->grav['Config']; $name = $config->get('system.pages.theme'); } diff --git a/system/src/Grav/Common/Twig.php b/system/src/Grav/Common/Twig.php index f0c88bf5c2..9dc8bb3409 100644 --- a/system/src/Grav/Common/Twig.php +++ b/system/src/Grav/Common/Twig.php @@ -43,6 +43,11 @@ class Twig */ public $twig_vars; + /** + * @var array + */ + public $twig_paths; + /** * @var string */ @@ -58,68 +63,70 @@ class Twig */ protected $loaderArray; + /** + * Constructor + */ + public function __construct(Grav $grav) + { + $this->grav = $grav; + } + /** * Twig initialization that sets the twig loader chain, then the environment, then extensions * and also the base set of twig vars */ public function init() { - if (!isset($this->twig)) { - - // get Grav and Config - $this->grav = Registry::get('Grav'); - $this->config = $this->grav->config; - $this->uri = Registry::get('Uri'); - $this->taxonomy = Registry::get('Taxonomy'); - - - $this->twig_paths = array(THEMES_DIR . $this->config->get('system.pages.theme') . '/templates'); - $this->grav->fireEvent('onAfterTwigTemplatesPaths'); - - $this->loader = new \Twig_Loader_Filesystem($this->twig_paths); - $this->loaderArray = new \Twig_Loader_Array(array()); - $loader_chain = new \Twig_Loader_Chain(array($this->loaderArray, $this->loader)); - - $params = $this->config->get('system.twig'); - if (!empty($params['cache'])) { - $params['cache'] = CACHE_DIR; - } - - $this->twig = new \Twig_Environment($loader_chain, $params); - $this->grav->fireEvent('onAfterTwigInit'); - - // set default date format if set in config - if ($this->config->get('system.pages.dateformat.long')) { - $this->twig->getExtension('core')->setDateFormat($this->config->get('system.pages.dateformat.long')); - } - // enable the debug extension if required - if ($this->config->get('system.twig.debug')) { - $this->twig->addExtension(new \Twig_Extension_Debug()); - } - $this->twig->addExtension(new TwigExtension()); - $this->grav->fireEvent('onAfterTwigExtensions'); - - $baseUrlAbsolute = $this->config->get('system.base_url_absolute'); - $baseUrlRelative = $this->config->get('system.base_url_relative'); - $theme = $this->config->get('system.pages.theme'); - $themeUrl = $baseUrlRelative .'/'. USER_PATH . basename(THEMES_DIR) .'/'. $theme; - - // Set some standard variables for twig - $this->twig_vars = array( - 'config' => $this->config, - 'uri' => $this->uri, - 'base_dir' => rtrim(ROOT_DIR, '/'), - 'base_url_absolute' => $baseUrlAbsolute, - 'base_url_relative' => $baseUrlRelative, - 'theme_dir' => THEMES_DIR . $theme, - 'theme_url' => $themeUrl, - 'site' => $this->config->get('site'), - 'stylesheets' => array(), - 'scripts' => array(), - 'taxonomy' => $this->taxonomy, - ); + // get Grav and Config + $this->config = $this->grav['Config']; + $this->uri = $this->grav['Uri']; + $this->taxonomy = $this->grav['Taxonomy']; + $this->twig_paths = array(THEMES_DIR . $this->config->get('system.pages.theme') . '/templates'); + $this->grav->fireEvent('onAfterTwigTemplatesPaths'); + + $this->loader = new \Twig_Loader_Filesystem($this->twig_paths); + $this->loaderArray = new \Twig_Loader_Array(array()); + $loader_chain = new \Twig_Loader_Chain(array($this->loaderArray, $this->loader)); + + $params = $this->config->get('system.twig'); + if (!empty($params['cache'])) { + $params['cache'] = CACHE_DIR; + } + + $this->twig = new \Twig_Environment($loader_chain, $params); + $this->grav->fireEvent('onAfterTwigInit'); + + // set default date format if set in config + if ($this->config->get('system.pages.dateformat.long')) { + $this->twig->getExtension('core')->setDateFormat($this->config->get('system.pages.dateformat.long')); } + // enable the debug extension if required + if ($this->config->get('system.twig.debug')) { + $this->twig->addExtension(new \Twig_Extension_Debug()); + } + $this->twig->addExtension(new TwigExtension()); + $this->grav->fireEvent('onAfterTwigExtensions'); + + $baseUrlAbsolute = $this->config->get('system.base_url_absolute'); + $baseUrlRelative = $this->config->get('system.base_url_relative'); + $theme = $this->config->get('system.pages.theme'); + $themeUrl = $baseUrlRelative .'/'. USER_PATH . basename(THEMES_DIR) .'/'. $theme; + + // Set some standard variables for twig + $this->twig_vars = array( + 'config' => $this->config, + 'uri' => $this->uri, + 'base_dir' => rtrim(ROOT_DIR, '/'), + 'base_url_absolute' => $baseUrlAbsolute, + 'base_url_relative' => $baseUrlRelative, + 'theme_dir' => THEMES_DIR . $theme, + 'theme_url' => $themeUrl, + 'site' => $this->config->get('site'), + 'stylesheets' => array(), + 'scripts' => array(), + 'taxonomy' => $this->taxonomy, + ); } /** @@ -161,7 +168,6 @@ public function setTemplate($name, $template) */ public function processPage(Page $item, $content = null) { - $this->init(); $content = $content !== null ? $content : $item->content(); // override the twig header vars for local resolution @@ -194,8 +200,6 @@ public function processPage(Page $item, $content = null) */ public function processString($string, array $vars = array()) { - $this->init(); - // override the twig header vars for local resolution $this->grav->fireEvent('onAfterTwigVars'); $vars += $this->twig_vars; @@ -213,17 +217,15 @@ public function processString($string, array $vars = array()) * * @param string $format Output format (defaults to HTML). * @return string the rendered output - * @throws \Twig_Error_Loader + * @throws \RuntimeException */ public function processSite($format = null) { - $this->init(); - // set the page now its been processed $this->grav->fireEvent('onAfterTwigSiteVars'); $twig_vars = $this->twig_vars; - $pages = $this->grav->pages; - $page = $this->grav->page; + $pages = $this->grav['Pages']; + $page = $this->grav['Page']; $twig_vars['pages'] = $pages->root(); $twig_vars['page'] = $page; diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index 09e564ebdb..977128b883 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -51,6 +51,7 @@ public static function mergeObjects($obj1, $obj2) * @return string */ public static function truncateHtml($text, $length = 100, $ending = '...', $exact = false, $considerHtml = true) { + $open_tags = array(); if ($considerHtml) { // if the plain text is shorter than the maximum length, return the whole text if (strlen(preg_replace('/<.*?>/', '', $text)) <= $length) { @@ -59,7 +60,6 @@ public static function truncateHtml($text, $length = 100, $ending = '...', $exac // splits all html-tags to scanable lines preg_match_all('/(<.+?>)?([^<>]*)/s', $text, $lines, PREG_SET_ORDER); $total_length = strlen($ending); - $open_tags = array(); $truncate = ''; foreach ($lines as $line_matchings) { // if there is any html-tag in this line, handle it and add it (uncounted) to the output diff --git a/system/src/Grav/Component/DI/Container.php b/system/src/Grav/Component/DI/Container.php new file mode 100644 index 0000000000..59fafe882e --- /dev/null +++ b/system/src/Grav/Component/DI/Container.php @@ -0,0 +1,6 @@ + Date: Mon, 18 Aug 2014 14:41:06 +0300 Subject: [PATCH 20/63] Add missing vendor dependencies --- vendor/autoload.php | 2 +- vendor/composer/ClassLoader.php | 4 - vendor/composer/autoload_namespaces.php | 1 + vendor/composer/autoload_real.php | 10 +- vendor/composer/installed.json | 48 + vendor/pimple/pimple/.gitignore | 3 + vendor/pimple/pimple/.travis.yml | 32 + vendor/pimple/pimple/CHANGELOG | 25 + vendor/pimple/pimple/LICENSE | 19 + vendor/pimple/pimple/README.rst | 200 ++++ vendor/pimple/pimple/composer.json | 25 + vendor/pimple/pimple/ext/pimple/.gitignore | 30 + vendor/pimple/pimple/ext/pimple/README.md | 12 + vendor/pimple/pimple/ext/pimple/config.m4 | 63 ++ vendor/pimple/pimple/ext/pimple/config.w32 | 13 + vendor/pimple/pimple/ext/pimple/php_pimple.h | 122 +++ vendor/pimple/pimple/ext/pimple/pimple.c | 940 ++++++++++++++++++ .../pimple/pimple/ext/pimple/pimple_compat.h | 81 ++ .../pimple/pimple/ext/pimple/tests/001.phpt | 45 + .../pimple/pimple/ext/pimple/tests/002.phpt | 15 + .../pimple/pimple/ext/pimple/tests/003.phpt | 16 + .../pimple/pimple/ext/pimple/tests/004.phpt | 30 + .../pimple/pimple/ext/pimple/tests/005.phpt | 27 + .../pimple/pimple/ext/pimple/tests/006.phpt | 51 + .../pimple/pimple/ext/pimple/tests/007.phpt | 22 + .../pimple/pimple/ext/pimple/tests/008.phpt | 29 + .../pimple/pimple/ext/pimple/tests/009.phpt | 13 + .../pimple/pimple/ext/pimple/tests/010.phpt | 45 + .../pimple/pimple/ext/pimple/tests/011.phpt | 19 + .../pimple/pimple/ext/pimple/tests/012.phpt | 28 + .../pimple/pimple/ext/pimple/tests/013.phpt | 33 + .../pimple/pimple/ext/pimple/tests/014.phpt | 30 + .../pimple/pimple/ext/pimple/tests/015.phpt | 17 + .../pimple/pimple/ext/pimple/tests/016.phpt | 24 + .../pimple/pimple/ext/pimple/tests/017.phpt | 17 + .../pimple/pimple/ext/pimple/tests/017_1.phpt | 17 + .../pimple/pimple/ext/pimple/tests/018.phpt | 23 + .../pimple/pimple/ext/pimple/tests/bench.phpb | 51 + .../pimple/ext/pimple/tests/bench_shared.phpb | 25 + vendor/pimple/pimple/phpunit.xml.dist | 14 + vendor/pimple/pimple/src/Pimple/Container.php | 281 ++++++ .../src/Pimple/ServiceProviderInterface.php | 46 + .../src/Pimple/Tests/Fixtures/Invokable.php | 38 + .../Pimple/Tests/Fixtures/NonInvokable.php | 34 + .../Tests/Fixtures/PimpleServiceProvider.php | 54 + .../src/Pimple/Tests/Fixtures/Service.php | 35 + .../PimpleServiceProviderInterfaceTest.php | 76 ++ .../pimple/src/Pimple/Tests/PimpleTest.php | 434 ++++++++ 48 files changed, 3209 insertions(+), 10 deletions(-) create mode 100644 vendor/pimple/pimple/.gitignore create mode 100644 vendor/pimple/pimple/.travis.yml create mode 100644 vendor/pimple/pimple/CHANGELOG create mode 100644 vendor/pimple/pimple/LICENSE create mode 100644 vendor/pimple/pimple/README.rst create mode 100644 vendor/pimple/pimple/composer.json create mode 100644 vendor/pimple/pimple/ext/pimple/.gitignore create mode 100644 vendor/pimple/pimple/ext/pimple/README.md create mode 100644 vendor/pimple/pimple/ext/pimple/config.m4 create mode 100644 vendor/pimple/pimple/ext/pimple/config.w32 create mode 100644 vendor/pimple/pimple/ext/pimple/php_pimple.h create mode 100644 vendor/pimple/pimple/ext/pimple/pimple.c create mode 100644 vendor/pimple/pimple/ext/pimple/pimple_compat.h create mode 100644 vendor/pimple/pimple/ext/pimple/tests/001.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/002.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/003.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/004.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/005.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/006.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/007.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/008.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/009.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/010.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/011.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/012.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/013.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/014.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/015.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/016.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/017.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/017_1.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/018.phpt create mode 100644 vendor/pimple/pimple/ext/pimple/tests/bench.phpb create mode 100644 vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb create mode 100644 vendor/pimple/pimple/phpunit.xml.dist create mode 100644 vendor/pimple/pimple/src/Pimple/Container.php create mode 100644 vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php create mode 100644 vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php diff --git a/vendor/autoload.php b/vendor/autoload.php index 7d02b46698..d8611fcf84 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit0ecdddcbf5a967ed661815e7747f4510::getLoader(); +return ComposerAutoloaderInitaeb322692412910c492cb020797b4f37::getLoader(); diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index 443364959a..88684c5265 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -143,8 +143,6 @@ public function add($prefix, $paths, $prepend = false) * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-0 base directories * @param bool $prepend Whether to prepend the directories - * - * @throws \InvalidArgumentException */ public function addPsr4($prefix, $paths, $prepend = false) { @@ -206,8 +204,6 @@ public function set($prefix, $paths) * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-4 base directories - * - * @throws \InvalidArgumentException */ public function setPsr4($prefix, $paths) { diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index 9a7291c070..9b0ddcafb4 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -9,6 +9,7 @@ 'Twig_' => array($vendorDir . '/twig/twig/lib'), 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), + 'Pimple' => array($vendorDir . '/pimple/pimple/src'), 'ParsedownExtra' => array($vendorDir . '/erusev/parsedown-extra'), 'Parsedown' => array($vendorDir . '/erusev/parsedown'), 'Gregwar\\Image' => array($vendorDir . '/gregwar/image'), diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index c11cbb8859..28fb5ec075 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit0ecdddcbf5a967ed661815e7747f4510 +class ComposerAutoloaderInitaeb322692412910c492cb020797b4f37 { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit0ecdddcbf5a967ed661815e7747f4510', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInitaeb322692412910c492cb020797b4f37', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit0ecdddcbf5a967ed661815e7747f4510', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInitaeb322692412910c492cb020797b4f37', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ public static function getLoader() $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequire0ecdddcbf5a967ed661815e7747f4510($file); + composerRequireaeb322692412910c492cb020797b4f37($file); } return $loader; } } -function composerRequire0ecdddcbf5a967ed661815e7747f4510($file) +function composerRequireaeb322692412910c492cb020797b4f37($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 66954f4c3e..0bee9bd062 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -605,5 +605,53 @@ "keywords": [ "user-agent" ] + }, + { + "name": "pimple/pimple", + "version": "v3.0.0", + "version_normalized": "3.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/fabpot/Pimple.git", + "reference": "876bf0899d01feacd2a2e83f04641e51350099ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fabpot/Pimple/zipball/876bf0899d01feacd2a2e83f04641e51350099ef", + "reference": "876bf0899d01feacd2a2e83f04641e51350099ef", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2014-07-24 09:48:15", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", + "homepage": "http://pimple.sensiolabs.org", + "keywords": [ + "container", + "dependency injection" + ] } ] diff --git a/vendor/pimple/pimple/.gitignore b/vendor/pimple/pimple/.gitignore new file mode 100644 index 0000000000..c089b09520 --- /dev/null +++ b/vendor/pimple/pimple/.gitignore @@ -0,0 +1,3 @@ +phpunit.xml +composer.lock +/vendor/ diff --git a/vendor/pimple/pimple/.travis.yml b/vendor/pimple/pimple/.travis.yml new file mode 100644 index 0000000000..5f8bb7c9f3 --- /dev/null +++ b/vendor/pimple/pimple/.travis.yml @@ -0,0 +1,32 @@ +language: php + +env: + matrix: + - PIMPLE_EXT=no + - PIMPLE_EXT=yes + global: + - REPORT_EXIT_STATUS=1 + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - hhvm + +before_script: + - composer self-update + - COMPOSER_ROOT_VERSION=dev-master composer dump-autoload + - if [ "$PIMPLE_EXT" == "yes" ]; then sh -c "cd ext/pimple && phpize && ./configure && make && sudo make install"; fi + - if [ "$PIMPLE_EXT" == "yes" ]; then echo "extension=pimple.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi + +script: + - cd ext/pimple + - if [ "$PIMPLE_EXT" == "yes" ]; then yes n | make test | tee output ; grep -E 'Tests failed +. +0' output; fi + - cd ../.. + - phpunit + +matrix: + exclude: + - php: hhvm + env: PIMPLE_EXT=yes diff --git a/vendor/pimple/pimple/CHANGELOG b/vendor/pimple/pimple/CHANGELOG new file mode 100644 index 0000000000..776a9153e9 --- /dev/null +++ b/vendor/pimple/pimple/CHANGELOG @@ -0,0 +1,25 @@ +* 3.0.0 (2014-07-24) + + * removed the Pimple class alias (use Pimple\Container instead) + +* 2.1.1 (2014-07-24) + + * fixed compiler warnings for the C extension + * fixed code when dealing with circular references + +* 2.1.0 (2014-06-24) + + * moved the Pimple to Pimple\Container (with a BC layer -- Pimple is now a + deprecated alias which will be removed in Pimple 3.0) + * added Pimple\ServiceProviderInterface (and Pimple::register()) + +* 2.0.0 (2014-02-10) + + * changed extend to automatically re-assign the extended service and keep it as shared or factory + (to keep BC, extend still returns the extended service) + * changed services to be shared by default (use factory() for factory + services) + +* 1.0.0 + + * initial version diff --git a/vendor/pimple/pimple/LICENSE b/vendor/pimple/pimple/LICENSE new file mode 100644 index 0000000000..86b4721be4 --- /dev/null +++ b/vendor/pimple/pimple/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2009-2014 Fabien Potencier + +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. diff --git a/vendor/pimple/pimple/README.rst b/vendor/pimple/pimple/README.rst new file mode 100644 index 0000000000..c345b6a114 --- /dev/null +++ b/vendor/pimple/pimple/README.rst @@ -0,0 +1,200 @@ +Pimple +====== + +.. caution:: + + This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read + the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good + way to learn more about how to create a simple Dependency Injection + Container (recent versions of Pimple are more focused on performance). + +Pimple is a small Dependency Injection Container for PHP. + +Installation +------------ + +Before using Pimple in your project, add it to your ``composer.json`` file: + +.. code-block:: bash + + $ ./composer.phar require pimple/pimple ~3.0 + +Alternatively, Pimple is also available as a PHP C extension: + +.. code-block:: bash + + $ cd ext/pimple + $ phpize + $ ./configure + $ make + $ make install + +Usage +----- + +Creating a container is a matter of creating a ``Container`` instance: + +.. code-block:: php + + use Pimple\Container; + + $container = new Container(); + +As many other dependency injection containers, Pimple manages two different +kind of data: **services** and **parameters**. + +Defining Services +~~~~~~~~~~~~~~~~~ + +A service is an object that does something as part of a larger system. Examples +of services: a database connection, a templating engine, or a mailer. Almost +any **global** object can be a service. + +Services are defined by **anonymous functions** that return an instance of an +object: + +.. code-block:: php + + // define some services + $container['session_storage'] = function ($c) { + return new SessionStorage('SESSION_ID'); + }; + + $container['session'] = function ($c) { + return new Session($c['session_storage']); + }; + +Notice that the anonymous function has access to the current container +instance, allowing references to other services or parameters. + +As objects are only created when you get them, the order of the definitions +does not matter. + +Using the defined services is also very easy: + +.. code-block:: php + + // get the session object + $session = $container['session']; + + // the above call is roughly equivalent to the following code: + // $storage = new SessionStorage('SESSION_ID'); + // $session = new Session($storage); + +Defining Factory Services +~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, each time you get a service, Pimple returns the **same instance** +of it. If you want a different instance to be returned for all calls, wrap your +anonymous function with the ``factory()`` method + +.. code-block:: php + + $container['session'] = $container->factory(function ($c) { + return new Session($c['session_storage']); + }); + +Now, each call to ``$container['session']`` returns a new instance of the +session. + +Defining Parameters +~~~~~~~~~~~~~~~~~~~ + +Defining a parameter allows to ease the configuration of your container from +the outside and to store global values: + +.. code-block:: php + + // define some parameters + $container['cookie_name'] = 'SESSION_ID'; + $container['session_storage_class'] = 'SessionStorage'; + +If you change the ``session_storage`` service definition like below: + +.. code-block:: php + + $container['session_storage'] = function ($c) { + return new $c['session_storage_class']($c['cookie_name']); + }; + +You can now easily change the cookie name by overriding the +``session_storage_class`` parameter instead of redefining the service +definition. + +Protecting Parameters +~~~~~~~~~~~~~~~~~~~~~ + +Because Pimple sees anonymous functions as service definitions, you need to +wrap anonymous functions with the ``protect()`` method to store them as +parameters: + +.. code-block:: php + + $container['random_func'] = $container->protect(function () { + return rand(); + }); + +Modifying Services after Definition +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In some cases you may want to modify a service definition after it has been +defined. You can use the ``extend()`` method to define additional code to be +run on your service just after it is created: + +.. code-block:: php + + $container['session_storage'] = function ($c) { + return new $c['session_storage_class']($c['cookie_name']); + }; + + $container->extend('session_storage', function ($storage, $c) { + $storage->...(); + + return $storage; + }; + +The first argument is the name of the service to extend, the second a function +that gets access to the object instance and the container. + +Extending a Container +~~~~~~~~~~~~~~~~~~~~~ + +If you use the same libraries over and over, you might want to reuse some +services from one project to the next one; package your services into a +**provider** by implementing ``Pimple\ServiceProviderInterface``: + +.. code-block:: php + + use Pimple\Container; + + class FooProvider implements Pimple\ServiceProviderInterface + { + public function register(Container $pimple) + { + // register some services and parameters + // on $pimple + } + } + +Then, register the provider on a Container: + +.. code-block:: php + + $pimple->register(new FooProvider()); + +Fetching the Service Creation Function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When you access an object, Pimple automatically calls the anonymous function +that you defined, which creates the service object for you. If you want to get +raw access to this function, you can use the ``raw()`` method: + +.. code-block:: php + + $container['session'] = function ($c) { + return new Session($c['session_storage']); + }; + + $sessionFunction = $container->raw('session'); + +.. _Pimple 1.x documentation: https://github.com/fabpot/Pimple/tree/1.1 diff --git a/vendor/pimple/pimple/composer.json b/vendor/pimple/pimple/composer.json new file mode 100644 index 0000000000..3474eb8389 --- /dev/null +++ b/vendor/pimple/pimple/composer.json @@ -0,0 +1,25 @@ +{ + "name": "pimple/pimple", + "type": "library", + "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", + "keywords": ["dependency injection", "container"], + "homepage": "http://pimple.sensiolabs.org", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-0": { "Pimple": "src/" } + }, + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + } +} diff --git a/vendor/pimple/pimple/ext/pimple/.gitignore b/vendor/pimple/pimple/ext/pimple/.gitignore new file mode 100644 index 0000000000..1861088ac1 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/.gitignore @@ -0,0 +1,30 @@ +*.sw* +.deps +Makefile +Makefile.fragments +Makefile.global +Makefile.objects +acinclude.m4 +aclocal.m4 +build/ +config.cache +config.guess +config.h +config.h.in +config.log +config.nice +config.status +config.sub +configure +configure.in +install-sh +libtool +ltmain.sh +missing +mkinstalldirs +run-tests.php +*.loT +.libs/ +modules/ +*.la +*.lo diff --git a/vendor/pimple/pimple/ext/pimple/README.md b/vendor/pimple/pimple/ext/pimple/README.md new file mode 100644 index 0000000000..7b39eb2929 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/README.md @@ -0,0 +1,12 @@ +This is Pimple 2 implemented in C + +* PHP >= 5.3 +* Not tested under Windows, might work + +Install +======= + + > phpize + > ./configure + > make + > make install diff --git a/vendor/pimple/pimple/ext/pimple/config.m4 b/vendor/pimple/pimple/ext/pimple/config.m4 new file mode 100644 index 0000000000..c9ba17ddbd --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/config.m4 @@ -0,0 +1,63 @@ +dnl $Id$ +dnl config.m4 for extension pimple + +dnl Comments in this file start with the string 'dnl'. +dnl Remove where necessary. This file will not work +dnl without editing. + +dnl If your extension references something external, use with: + +dnl PHP_ARG_WITH(pimple, for pimple support, +dnl Make sure that the comment is aligned: +dnl [ --with-pimple Include pimple support]) + +dnl Otherwise use enable: + +PHP_ARG_ENABLE(pimple, whether to enable pimple support, +dnl Make sure that the comment is aligned: +[ --enable-pimple Enable pimple support]) + +if test "$PHP_PIMPLE" != "no"; then + dnl Write more examples of tests here... + + dnl # --with-pimple -> check with-path + dnl SEARCH_PATH="/usr/local /usr" # you might want to change this + dnl SEARCH_FOR="/include/pimple.h" # you most likely want to change this + dnl if test -r $PHP_PIMPLE/$SEARCH_FOR; then # path given as parameter + dnl PIMPLE_DIR=$PHP_PIMPLE + dnl else # search default path list + dnl AC_MSG_CHECKING([for pimple files in default path]) + dnl for i in $SEARCH_PATH ; do + dnl if test -r $i/$SEARCH_FOR; then + dnl PIMPLE_DIR=$i + dnl AC_MSG_RESULT(found in $i) + dnl fi + dnl done + dnl fi + dnl + dnl if test -z "$PIMPLE_DIR"; then + dnl AC_MSG_RESULT([not found]) + dnl AC_MSG_ERROR([Please reinstall the pimple distribution]) + dnl fi + + dnl # --with-pimple -> add include path + dnl PHP_ADD_INCLUDE($PIMPLE_DIR/include) + + dnl # --with-pimple -> check for lib and symbol presence + dnl LIBNAME=pimple # you may want to change this + dnl LIBSYMBOL=pimple # you most likely want to change this + + dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, + dnl [ + dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $PIMPLE_DIR/lib, PIMPLE_SHARED_LIBADD) + dnl AC_DEFINE(HAVE_PIMPLELIB,1,[ ]) + dnl ],[ + dnl AC_MSG_ERROR([wrong pimple lib version or lib not found]) + dnl ],[ + dnl -L$PIMPLE_DIR/lib -lm + dnl ]) + dnl + dnl PHP_SUBST(PIMPLE_SHARED_LIBADD) + + PHP_NEW_EXTENSION(pimple, pimple.c, $ext_shared) +fi diff --git a/vendor/pimple/pimple/ext/pimple/config.w32 b/vendor/pimple/pimple/ext/pimple/config.w32 new file mode 100644 index 0000000000..39857b3254 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/config.w32 @@ -0,0 +1,13 @@ +// $Id$ +// vim:ft=javascript + +// If your extension references something external, use ARG_WITH +// ARG_WITH("pimple", "for pimple support", "no"); + +// Otherwise, use ARG_ENABLE +// ARG_ENABLE("pimple", "enable pimple support", "no"); + +if (PHP_PIMPLE != "no") { + EXTENSION("pimple", "pimple.c"); +} + diff --git a/vendor/pimple/pimple/ext/pimple/php_pimple.h b/vendor/pimple/pimple/ext/pimple/php_pimple.h new file mode 100644 index 0000000000..359f7132cf --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/php_pimple.h @@ -0,0 +1,122 @@ + +/* + * This file is part of Pimple. + * + * Copyright (c) 2014 Fabien Potencier + * + * 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. + */ + +#ifndef PHP_PIMPLE_H +#define PHP_PIMPLE_H + +extern zend_module_entry pimple_module_entry; +#define phpext_pimple_ptr &pimple_module_entry + +#ifdef PHP_WIN32 +# define PHP_PIMPLE_API __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define PHP_PIMPLE_API __attribute__ ((visibility("default"))) +#else +# define PHP_PIMPLE_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +#define PIMPLE_VERSION "3.0.0" +#define PIMPLE_NS "Pimple" + +#define PIMPLE_DEFAULT_ZVAL_CACHE_NUM 5 +#define PIMPLE_DEFAULT_ZVAL_VALUES_NUM 10 + +PHP_MINIT_FUNCTION(pimple); +PHP_MSHUTDOWN_FUNCTION(pimple); +PHP_RINIT_FUNCTION(pimple); +PHP_RSHUTDOWN_FUNCTION(pimple); +PHP_MINFO_FUNCTION(pimple); + +PHP_METHOD(Pimple, __construct); +PHP_METHOD(Pimple, factory); +PHP_METHOD(Pimple, protect); +PHP_METHOD(Pimple, raw); +PHP_METHOD(Pimple, extend); +PHP_METHOD(Pimple, keys); +PHP_METHOD(Pimple, register); +PHP_METHOD(Pimple, offsetSet); +PHP_METHOD(Pimple, offsetUnset); +PHP_METHOD(Pimple, offsetGet); +PHP_METHOD(Pimple, offsetExists); + +PHP_METHOD(PimpleClosure, __invoke); + +typedef struct _pimple_bucket_value { + zval *value; /* Must be the first element */ + zval *raw; + zend_fcall_info_cache *fcc; + zend_object_handle handle_num; + enum { + PIMPLE_IS_PARAM = 0, + PIMPLE_IS_SERVICE = 2 + } type; + zend_bool initialized; +} pimple_bucket_value; + +typedef struct _pimple_object { + zend_object zobj; + HashTable values; + HashTable factories; + HashTable protected; +} pimple_object; + +typedef struct _pimple_closure_object { + zend_object zobj; + zval *callable; + zval *factory; +} pimple_closure_object; + +static const char sensiolabs_logo[] = ""; + +static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC); +static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC); + +static void pimple_init_bucket(pimple_bucket_value *bucket); +static void pimple_bucket_dtor(pimple_bucket_value *bucket); +static void pimple_free_bucket(pimple_bucket_value *bucket); + +static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC); +static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC); +static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC); +static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC); +static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC); +static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC); + +static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC); +static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC); +static zend_function *pimple_closure_get_constructor(zval * TSRMLS_DC); + +#ifdef ZTS +#define PIMPLE_G(v) TSRMG(pimple_globals_id, zend_pimple_globals *, v) +#else +#define PIMPLE_G(v) (pimple_globals.v) +#endif + +#endif /* PHP_PIMPLE_H */ + diff --git a/vendor/pimple/pimple/ext/pimple/pimple.c b/vendor/pimple/pimple/ext/pimple/pimple.c new file mode 100644 index 0000000000..44eb8da784 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/pimple.c @@ -0,0 +1,940 @@ + +/* + * This file is part of Pimple. + * + * Copyright (c) 2014 Fabien Potencier + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_pimple.h" +#include "pimple_compat.h" +#include "zend_interfaces.h" +#include "zend.h" +#include "ext/spl/spl_exceptions.h" +#include "Zend/zend_exceptions.h" +#include "main/php_output.h" +#include "SAPI.h" + +static zend_class_entry *pimple_ce; +static zend_object_handlers pimple_object_handlers; +static zend_class_entry *pimple_closure_ce; +static zend_class_entry *pimple_serviceprovider_ce; +static zend_object_handlers pimple_closure_object_handlers; + +#define FETCH_DIM_HANDLERS_VARS pimple_object *pimple_obj = NULL; \ + ulong index; \ + pimple_obj = (pimple_object *)zend_object_store_get_object(object TSRMLS_CC); \ + +#define PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS do { \ + if (ce != pimple_ce) { \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetget"), (void **)&function); \ + if (function->common.scope != ce) { /* if the function is not defined in this actual class */ \ + pimple_object_handlers.read_dimension = pimple_object_read_dimension; /* then overwrite the handler to use custom one */ \ + } \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetset"), (void **)&function); \ + if (function->common.scope != ce) { \ + pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ + } \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetexists"), (void **)&function); \ + if (function->common.scope != ce) { \ + pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ + } \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetunset"), (void **)&function); \ + if (function->common.scope != ce) { \ + pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ + } \ + } else { \ + pimple_object_handlers.read_dimension = pimple_object_read_dimension; \ + pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ + pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ + pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ + }\ + } while(0); + +#define PIMPLE_CALL_CB do { \ + zend_fcall_info_argn(&fci TSRMLS_CC, 1, &object); \ + fci.size = sizeof(fci); \ + fci.object_ptr = retval->fcc->object_ptr; \ + fci.function_name = retval->value; \ + fci.no_separation = 1; \ + fci.retval_ptr_ptr = &retval_ptr_ptr; \ +\ + zend_call_function(&fci, retval->fcc TSRMLS_CC); \ + efree(fci.params); \ + if (EG(exception)) { \ + return EG(uninitialized_zval_ptr); \ + } \ + } while(0); + +ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) +ZEND_ARG_ARRAY_INFO(0, value, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetset, 0, 0, 2) +ZEND_ARG_INFO(0, offset) +ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetget, 0, 0, 1) +ZEND_ARG_INFO(0, offset) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetexists, 0, 0, 1) +ZEND_ARG_INFO(0, offset) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetunset, 0, 0, 1) +ZEND_ARG_INFO(0, offset) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_factory, 0, 0, 1) +ZEND_ARG_INFO(0, callable) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_protect, 0, 0, 1) +ZEND_ARG_INFO(0, callable) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_raw, 0, 0, 1) +ZEND_ARG_INFO(0, id) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_extend, 0, 0, 2) +ZEND_ARG_INFO(0, id) +ZEND_ARG_INFO(0, callable) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_keys, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_register, 0, 0, 1) +ZEND_ARG_OBJ_INFO(0, provider, Pimple\\ServiceProviderInterface, 0) +ZEND_ARG_ARRAY_INFO(0, values, 1) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_pimpleclosure___invoke, 0, 0, 1) +ZEND_ARG_INFO(0, callarg) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_serviceprovider_register, 0, 0, 1) +ZEND_ARG_OBJ_INFO(0, pimple, Pimple\\Container, 0) +ZEND_END_ARG_INFO() + +static const zend_function_entry pimple_ce_functions[] = { + PHP_ME(Pimple, __construct, arginfo___construct, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, factory, arginfo_factory, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, protect, arginfo_protect, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, raw, arginfo_raw, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, extend, arginfo_extend, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, keys, arginfo_keys, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, register, arginfo_register, ZEND_ACC_PUBLIC) + + PHP_ME(Pimple, offsetSet, arginfo_offsetset, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, offsetGet, arginfo_offsetget, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, offsetExists, arginfo_offsetexists, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, offsetUnset, arginfo_offsetunset, ZEND_ACC_PUBLIC) + PHP_FE_END +}; + +static const zend_function_entry pimple_closure_ce_functions[] = { + PHP_ME(PimpleClosure, __invoke, arginfo_pimpleclosure___invoke, ZEND_ACC_PRIVATE) + PHP_FE_END +}; + +static const zend_function_entry pimple_serviceprovider_iface_ce_functions[] = { + PHP_ABSTRACT_ME(ServiceProviderInterface, register, arginfo_serviceprovider_register) + PHP_FE_END +}; + +static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC) +{ + zend_object_std_dtor(&obj->zobj TSRMLS_CC); + if (obj->factory) { + zval_ptr_dtor(&obj->factory); + } + if (obj->callable) { + zval_ptr_dtor(&obj->callable); + } + efree(obj); +} + +static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC) +{ + zend_hash_destroy(&obj->factories); + zend_hash_destroy(&obj->protected); + zend_hash_destroy(&obj->values); + zend_object_std_dtor(&obj->zobj TSRMLS_CC); + efree(obj); +} + +static void pimple_free_bucket(pimple_bucket_value *bucket) +{ + if (bucket->fcc) { + efree(bucket->fcc); + bucket->fcc = NULL; + } + if (bucket->raw) { + zval_ptr_dtor(&bucket->raw); + } +} + +static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + pimple_closure_object *pimple_closure_obj = NULL; + + pimple_closure_obj = ecalloc(1, sizeof(pimple_closure_object)); + ZEND_OBJ_INIT(&pimple_closure_obj->zobj, ce); + + pimple_closure_object_handlers.get_constructor = pimple_closure_get_constructor; + retval.handlers = &pimple_closure_object_handlers; + retval.handle = zend_objects_store_put(pimple_closure_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_closure_free_object_storage, NULL TSRMLS_CC); + + return retval; +} + +static zend_function *pimple_closure_get_constructor(zval *obj TSRMLS_DC) +{ + zend_error(E_ERROR, "Pimple\\ContainerClosure is an internal class and cannot be instantiated"); + + return NULL; +} + +static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + pimple_object *pimple_obj = NULL; + zend_function *function = NULL; + + pimple_obj = emalloc(sizeof(pimple_object)); + ZEND_OBJ_INIT(&pimple_obj->zobj, ce); + + PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS + + retval.handlers = &pimple_object_handlers; + retval.handle = zend_objects_store_put(pimple_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_free_object_storage, NULL TSRMLS_CC); + + zend_hash_init(&pimple_obj->factories, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); + zend_hash_init(&pimple_obj->protected, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); + zend_hash_init(&pimple_obj->values, PIMPLE_DEFAULT_ZVAL_VALUES_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); + + return retval; +} + +static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + pimple_bucket_value pimple_value = {0}, *found_value = NULL; + ulong hash; + + pimple_init_bucket(&pimple_value); + pimple_zval_to_pimpleval(value, &pimple_value TSRMLS_CC); + + if (!offset) {/* $p[] = 'foo' when not overloaded */ + zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); + Z_ADDREF_P(value); + return; + } + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + hash = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + zend_hash_quick_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void **)&found_value); + if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { + pimple_free_bucket(&pimple_value); + zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%s\".", Z_STRVAL_P(offset)); + return; + } + if (zend_hash_quick_update(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { + pimple_free_bucket(&pimple_value); + return; + } + Z_ADDREF_P(value); + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + zend_hash_index_find(&pimple_obj->values, index, (void **)&found_value); + if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { + pimple_free_bucket(&pimple_value); + zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%ld\".", index); + return; + } + if (zend_hash_index_update(&pimple_obj->values, index, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { + pimple_free_bucket(&pimple_value); + return; + } + Z_ADDREF_P(value); + break; + case IS_NULL: /* $p[] = 'foo' when overloaded */ + zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); + Z_ADDREF_P(value); + break; + default: + pimple_free_bucket(&pimple_value); + zend_error(E_WARNING, "Unsupported offset type"); + } +} + +static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + zend_symtable_del(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + zend_symtable_del(&pimple_obj->factories, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + zend_symtable_del(&pimple_obj->protected, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + zend_hash_index_del(&pimple_obj->values, index); + zend_hash_index_del(&pimple_obj->factories, index); + zend_hash_index_del(&pimple_obj->protected, index); + break; + default: + zend_error(E_WARNING, "Unsupported offset type"); + } +} + +static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + pimple_bucket_value *retval = NULL; + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == SUCCESS) { + switch (check_empty) { + case 0: /* isset */ + return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;) */ + case 1: /* empty */ + default: + return zend_is_true(retval->value); + } + } + return 0; + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == SUCCESS) { + switch (check_empty) { + case 0: /* isset */ + return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;)*/ + case 1: /* empty */ + default: + return zend_is_true(retval->value); + } + } + return 0; + break; + default: + zend_error(E_WARNING, "Unsupported offset type"); + return 0; + } +} + +static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + pimple_bucket_value *retval = NULL; + zend_fcall_info fci = {0}; + zval *retval_ptr_ptr = NULL; + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); + return EG(uninitialized_zval_ptr); + } + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == FAILURE) { + return EG(uninitialized_zval_ptr); + } + break; + case IS_NULL: /* $p[][3] = 'foo' first dim access */ + return EG(uninitialized_zval_ptr); + break; + default: + zend_error(E_WARNING, "Unsupported offset type"); + return EG(uninitialized_zval_ptr); + } + + if(retval->type == PIMPLE_IS_PARAM) { + return retval->value; + } + + if (zend_hash_index_exists(&pimple_obj->protected, retval->handle_num)) { + /* Service is protected, return the value every time */ + return retval->value; + } + + if (zend_hash_index_exists(&pimple_obj->factories, retval->handle_num)) { + /* Service is a factory, call it everytime and never cache its result */ + PIMPLE_CALL_CB + Z_DELREF_P(retval_ptr_ptr); /* fetch dim addr will increment refcount */ + return retval_ptr_ptr; + } + + if (retval->initialized == 1) { + /* Service has already been called, return its cached value */ + return retval->value; + } + + ALLOC_INIT_ZVAL(retval->raw); + MAKE_COPY_ZVAL(&retval->value, retval->raw); + + PIMPLE_CALL_CB + + retval->initialized = 1; + zval_ptr_dtor(&retval->value); + retval->value = retval_ptr_ptr; + + return retval->value; +} + +static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) +{ + if (Z_TYPE_P(_zval) != IS_OBJECT) { + return FAILURE; + } + + if (_pimple_bucket_value->fcc->called_scope) { + return SUCCESS; + } + + if (Z_OBJ_HANDLER_P(_zval, get_closure) && Z_OBJ_HANDLER_P(_zval, get_closure)(_zval, &_pimple_bucket_value->fcc->calling_scope, &_pimple_bucket_value->fcc->function_handler, &_pimple_bucket_value->fcc->object_ptr TSRMLS_CC) == SUCCESS) { + _pimple_bucket_value->fcc->called_scope = _pimple_bucket_value->fcc->calling_scope; + return SUCCESS; + } else { + return FAILURE; + } +} + +static void pimple_init_bucket(pimple_bucket_value *bucket) +{ + memset(bucket, 0, sizeof(pimple_bucket_value)); + bucket->fcc = ecalloc(1, sizeof(zend_fcall_info_cache)); +} + +static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) +{ + _pimple_bucket_value->value = _zval; + + if (Z_TYPE_P(_zval) != IS_OBJECT) { + return PIMPLE_IS_PARAM; + } + + if (pimple_zval_is_valid_callback(_zval, _pimple_bucket_value TSRMLS_CC) == SUCCESS) { + _pimple_bucket_value->type = PIMPLE_IS_SERVICE; + _pimple_bucket_value->handle_num = Z_OBJ_HANDLE_P(_zval); + } + + return PIMPLE_IS_SERVICE; +} + +static void pimple_bucket_dtor(pimple_bucket_value *bucket) +{ + zval_ptr_dtor(&bucket->value); + pimple_free_bucket(bucket); +} + +PHP_METHOD(Pimple, protect) +{ + zval *protected = NULL; + pimple_object *pobj = NULL; + pimple_bucket_value bucket = {0}; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &protected) == FAILURE) { + return; + } + + pimple_init_bucket(&bucket); + + if (pimple_zval_is_valid_callback(protected, &bucket TSRMLS_CC) == FAILURE) { + pimple_free_bucket(&bucket); + zend_throw_exception(spl_ce_InvalidArgumentException, "Callable is not a Closure or invokable object.", 0 TSRMLS_CC); + return; + } + + pimple_zval_to_pimpleval(protected, &bucket TSRMLS_CC); + pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); + + if (zend_hash_index_update(&pobj->protected, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { + RETURN_ZVAL(protected, 1 , 0); + } else { + pimple_free_bucket(&bucket); + } + RETURN_FALSE; +} + +PHP_METHOD(Pimple, raw) +{ + zval *offset = NULL; + pimple_object *pobj = NULL; + pimple_bucket_value *value = NULL; + ulong index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + pobj = zend_object_store_get_object(getThis() TSRMLS_CC); + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); + RETURN_NULL(); + } + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { + RETURN_NULL(); + } + break; + case IS_NULL: + default: + zend_error(E_WARNING, "Unsupported offset type"); + } + + if (value->raw) { + RETVAL_ZVAL(value->raw, 1, 0); + } else { + RETVAL_ZVAL(value->value, 1, 0); + } +} + +PHP_METHOD(Pimple, extend) +{ + zval *offset = NULL, *callable = NULL, *pimple_closure_obj = NULL; + pimple_bucket_value bucket = {0}, *value = NULL; + pimple_object *pobj = NULL; + pimple_closure_object *pcobj = NULL; + ulong index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &callable) == FAILURE) { + return; + } + + pobj = zend_object_store_get_object(getThis() TSRMLS_CC); + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); + RETURN_NULL(); + } + if (value->type != PIMPLE_IS_SERVICE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" does not contain an object definition.", Z_STRVAL_P(offset)); + RETURN_NULL(); + } + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" is not defined.", index); + RETURN_NULL(); + } + if (value->type != PIMPLE_IS_SERVICE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" does not contain an object definition.", index); + RETURN_NULL(); + } + break; + case IS_NULL: + default: + zend_error(E_WARNING, "Unsupported offset type"); + } + + pimple_init_bucket(&bucket); + + if (pimple_zval_is_valid_callback(callable, &bucket TSRMLS_CC) == FAILURE) { + pimple_free_bucket(&bucket); + zend_throw_exception(spl_ce_InvalidArgumentException, "Extension service definition is not a Closure or invokable object.", 0 TSRMLS_CC); + RETURN_NULL(); + } + pimple_free_bucket(&bucket); + + ALLOC_INIT_ZVAL(pimple_closure_obj); + object_init_ex(pimple_closure_obj, pimple_closure_ce); + + pcobj = zend_object_store_get_object(pimple_closure_obj TSRMLS_CC); + pcobj->callable = callable; + pcobj->factory = value->value; + Z_ADDREF_P(callable); + Z_ADDREF_P(value->value); + + if (zend_hash_index_exists(&pobj->factories, value->handle_num)) { + pimple_init_bucket(&bucket); + pimple_zval_to_pimpleval(pimple_closure_obj, &bucket TSRMLS_CC); + zend_hash_index_del(&pobj->factories, value->handle_num); + zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL); + Z_ADDREF_P(pimple_closure_obj); + } + + pimple_object_write_dimension(getThis(), offset, pimple_closure_obj TSRMLS_CC); + + RETVAL_ZVAL(pimple_closure_obj, 1, 1); +} + +PHP_METHOD(Pimple, keys) +{ + HashPosition pos; + pimple_object *pobj = NULL; + zval **value = NULL; + zval *endval = NULL; + char *str_index = NULL; + int str_len; + ulong num_index; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + pobj = zend_object_store_get_object(getThis() TSRMLS_CC); + array_init_size(return_value, zend_hash_num_elements(&pobj->values)); + + zend_hash_internal_pointer_reset_ex(&pobj->values, &pos); + + while(zend_hash_get_current_data_ex(&pobj->values, (void **)&value, &pos) == SUCCESS) { + MAKE_STD_ZVAL(endval); + switch (zend_hash_get_current_key_ex(&pobj->values, &str_index, (uint *)&str_len, &num_index, 0, &pos)) { + case HASH_KEY_IS_STRING: + ZVAL_STRINGL(endval, str_index, str_len - 1, 1); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); + break; + case HASH_KEY_IS_LONG: + ZVAL_LONG(endval, num_index); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); + break; + } + zend_hash_move_forward_ex(&pobj->values, &pos); + } +} + +PHP_METHOD(Pimple, factory) +{ + zval *factory = NULL; + pimple_object *pobj = NULL; + pimple_bucket_value bucket = {0}; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &factory) == FAILURE) { + return; + } + + pimple_init_bucket(&bucket); + + if (pimple_zval_is_valid_callback(factory, &bucket TSRMLS_CC) == FAILURE) { + pimple_free_bucket(&bucket); + zend_throw_exception(spl_ce_InvalidArgumentException, "Service definition is not a Closure or invokable object.", 0 TSRMLS_CC); + return; + } + + pimple_zval_to_pimpleval(factory, &bucket TSRMLS_CC); + pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); + + if (zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { + Z_ADDREF_P(factory); + RETURN_ZVAL(factory, 1 , 0); + } else { + pimple_free_bucket(&bucket); + } + + RETURN_FALSE; +} + +PHP_METHOD(Pimple, offsetSet) +{ + zval *offset = NULL, *value = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &value) == FAILURE) { + return; + } + + pimple_object_write_dimension(getThis(), offset, value TSRMLS_CC); +} + +PHP_METHOD(Pimple, offsetGet) +{ + zval *offset = NULL, *retval = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + retval = pimple_object_read_dimension(getThis(), offset, 0 TSRMLS_CC); + + RETVAL_ZVAL(retval, 1, 0); +} + +PHP_METHOD(Pimple, offsetUnset) +{ + zval *offset = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + pimple_object_unset_dimension(getThis(), offset TSRMLS_CC); +} + +PHP_METHOD(Pimple, offsetExists) +{ + zval *offset = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + RETVAL_BOOL(pimple_object_has_dimension(getThis(), offset, 1 TSRMLS_CC)); +} + +PHP_METHOD(Pimple, register) +{ + zval *provider; + zval **data; + zval *retval = NULL; + zval key; + + HashTable *array = NULL; + HashPosition pos; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|h", &provider, pimple_serviceprovider_ce, &array) == FAILURE) { + return; + } + + zend_call_method_with_1_params(&provider, Z_OBJCE_P(provider), NULL, "register", &retval, getThis()); + + if (retval) { + zval_ptr_dtor(&retval); + } + + if (!array) { + return; + } + + zend_hash_internal_pointer_reset_ex(array, &pos); + + while(zend_hash_get_current_data_ex(array, (void **)&data, &pos) == SUCCESS) { + zend_hash_get_current_key_zval_ex(array, &key, &pos); + pimple_object_write_dimension(getThis(), &key, *data TSRMLS_CC); + zend_hash_move_forward_ex(array, &pos); + } + + RETVAL_ZVAL(getThis(), 1, 0); +} + +PHP_METHOD(Pimple, __construct) +{ + zval *values = NULL, **pData = NULL, offset = {0}; + HashPosition pos; + char *str_index = NULL; + zend_uint str_length; + ulong num_index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &values) == FAILURE || !values) { + return; + } + + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos); + while (zend_hash_has_more_elements_ex(Z_ARRVAL_P(values), &pos) == SUCCESS) { + zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&pData, &pos); + zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &str_index, &str_length, &num_index, 0, &pos); + if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(values), &pos) == HASH_KEY_IS_LONG) { + ZVAL_LONG(&offset, num_index); + } else { + ZVAL_STRINGL(&offset, str_index, (str_length - 1), 0); + } + pimple_object_write_dimension(getThis(), &offset, *pData TSRMLS_CC); + zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos); + } +} + +/* + * This is PHP code snippet handling extend()s calls : + + $extended = function ($c) use ($callable, $factory) { + return $callable($factory($c), $c); + }; + + */ +PHP_METHOD(PimpleClosure, __invoke) +{ + pimple_closure_object *pcobj = NULL; + zval *arg = NULL, *retval = NULL, *newretval = NULL; + zend_fcall_info fci = {0}; + zval **args[2]; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { + return; + } + + pcobj = zend_object_store_get_object(getThis() TSRMLS_CC); + + fci.function_name = pcobj->factory; + args[0] = &arg; + zend_fcall_info_argp(&fci TSRMLS_CC, 1, args); + fci.retval_ptr_ptr = &retval; + fci.size = sizeof(fci); + + if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { + efree(fci.params); + return; /* Should here return default zval */ + } + + efree(fci.params); + memset(&fci, 0, sizeof(fci)); + fci.size = sizeof(fci); + + fci.function_name = pcobj->callable; + args[0] = &retval; + args[1] = &arg; + zend_fcall_info_argp(&fci TSRMLS_CC, 2, args); + fci.retval_ptr_ptr = &newretval; + + if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { + efree(fci.params); + zval_ptr_dtor(&retval); + return; + } + + efree(fci.params); + zval_ptr_dtor(&retval); + RETVAL_ZVAL(newretval, 1 ,1); +} + +PHP_MINIT_FUNCTION(pimple) +{ + zend_class_entry tmp_pimple_ce, tmp_pimple_closure_ce, tmp_pimple_serviceprovider_iface_ce; + INIT_NS_CLASS_ENTRY(tmp_pimple_ce, PIMPLE_NS, "Container", pimple_ce_functions); + INIT_NS_CLASS_ENTRY(tmp_pimple_closure_ce, PIMPLE_NS, "ContainerClosure", pimple_closure_ce_functions); + INIT_NS_CLASS_ENTRY(tmp_pimple_serviceprovider_iface_ce, PIMPLE_NS, "ServiceProviderInterface", pimple_serviceprovider_iface_ce_functions); + + tmp_pimple_ce.create_object = pimple_object_create; + tmp_pimple_closure_ce.create_object = pimple_closure_object_create; + + pimple_ce = zend_register_internal_class(&tmp_pimple_ce TSRMLS_CC); + zend_class_implements(pimple_ce TSRMLS_CC, 1, zend_ce_arrayaccess); + + pimple_closure_ce = zend_register_internal_class(&tmp_pimple_closure_ce TSRMLS_CC); + pimple_closure_ce->ce_flags |= ZEND_ACC_FINAL_CLASS; + + pimple_serviceprovider_ce = zend_register_internal_interface(&tmp_pimple_serviceprovider_iface_ce TSRMLS_CC); + + pimple_closure_object_handlers = std_object_handlers; + pimple_object_handlers = std_object_handlers; + + return SUCCESS; +} + +PHP_MSHUTDOWN_FUNCTION(pimple) +{ + return SUCCESS; +} + +PHP_RINIT_FUNCTION(pimple) +{ + return SUCCESS; +} + +PHP_RSHUTDOWN_FUNCTION(pimple) +{ + return SUCCESS; +} + +PHP_MINFO_FUNCTION(pimple) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "SensioLabs Pimple C support", "enabled"); + php_info_print_table_row(2, "Pimple supported version", PIMPLE_VERSION); + php_info_print_table_end(); + + php_info_print_box_start(0); + php_write((void *)ZEND_STRL("SensioLabs Pimple C support developed by Julien Pauli") TSRMLS_CC); + if (!sapi_module.phpinfo_as_text) { + php_write((void *)ZEND_STRL(sensiolabs_logo) TSRMLS_CC); + } + php_info_print_box_end(); +} + +zend_module_entry pimple_module_entry = { + STANDARD_MODULE_HEADER, + "pimple", + NULL, + PHP_MINIT(pimple), + PHP_MSHUTDOWN(pimple), + PHP_RINIT(pimple), + PHP_RSHUTDOWN(pimple), + PHP_MINFO(pimple), + PIMPLE_VERSION, + STANDARD_MODULE_PROPERTIES +}; + +#ifdef COMPILE_DL_PIMPLE +ZEND_GET_MODULE(pimple) +#endif diff --git a/vendor/pimple/pimple/ext/pimple/pimple_compat.h b/vendor/pimple/pimple/ext/pimple/pimple_compat.h new file mode 100644 index 0000000000..d234e174d0 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/pimple_compat.h @@ -0,0 +1,81 @@ + +/* + * This file is part of Pimple. + * + * Copyright (c) 2014 Fabien Potencier + * + * 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. + */ + +#ifndef PIMPLE_COMPAT_H_ +#define PIMPLE_COMPAT_H_ + +#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */ + +#define PHP_5_0_X_API_NO 220040412 +#define PHP_5_1_X_API_NO 220051025 +#define PHP_5_2_X_API_NO 220060519 +#define PHP_5_3_X_API_NO 220090626 +#define PHP_5_4_X_API_NO 220100525 +#define PHP_5_5_X_API_NO 220121212 +#define PHP_5_6_X_API_NO 220131226 + +#define IS_PHP_56 ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO +#define IS_AT_LEAST_PHP_56 ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO + +#define IS_PHP_55 ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO +#define IS_AT_LEAST_PHP_55 ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO + +#define IS_PHP_54 ZEND_EXTENSION_API_NO == PHP_5_4_X_API_NO +#define IS_AT_LEAST_PHP_54 ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO + +#define IS_PHP_53 ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO +#define IS_AT_LEAST_PHP_53 ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + +#if IS_PHP_53 +#define object_properties_init(obj, ce) do { \ + zend_hash_copy(obj->properties, &ce->default_properties, zval_copy_property_ctor(ce), NULL, sizeof(zval *)); \ + } while (0); +#endif + +#define ZEND_OBJ_INIT(obj, ce) do { \ + zend_object_std_init(obj, ce TSRMLS_CC); \ + object_properties_init((obj), (ce)); \ + } while(0); + +#if IS_PHP_53 || IS_PHP_54 +static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) { + Bucket *p; + + p = pos ? (*pos) : ht->pInternalPointer; + + if (!p) { + Z_TYPE_P(key) = IS_NULL; + } else if (p->nKeyLength) { + Z_TYPE_P(key) = IS_STRING; + Z_STRVAL_P(key) = estrndup(p->arKey, p->nKeyLength - 1); + Z_STRLEN_P(key) = p->nKeyLength - 1; + } else { + Z_TYPE_P(key) = IS_LONG; + Z_LVAL_P(key) = p->h; + } +} +#endif + +#endif /* PIMPLE_COMPAT_H_ */ diff --git a/vendor/pimple/pimple/ext/pimple/tests/001.phpt b/vendor/pimple/pimple/ext/pimple/tests/001.phpt new file mode 100644 index 0000000000..0809ea232b --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/001.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test for read_dim/write_dim handlers +--SKIPIF-- + +--FILE-- + + +--EXPECTF-- +foo +42 +foo2 +foo99 +baz +strstr \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/002.phpt b/vendor/pimple/pimple/ext/pimple/tests/002.phpt new file mode 100644 index 0000000000..7b56d2c1fe --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/002.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test for constructor +--SKIPIF-- + +--FILE-- +'foo')); +var_dump($p[42]); +?> +--EXPECT-- +NULL +string(3) "foo" diff --git a/vendor/pimple/pimple/ext/pimple/tests/003.phpt b/vendor/pimple/pimple/ext/pimple/tests/003.phpt new file mode 100644 index 0000000000..a22cfa352e --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/003.phpt @@ -0,0 +1,16 @@ +--TEST-- +Test empty dimensions +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(42) +string(3) "bar" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/004.phpt b/vendor/pimple/pimple/ext/pimple/tests/004.phpt new file mode 100644 index 0000000000..1e1d251367 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/004.phpt @@ -0,0 +1,30 @@ +--TEST-- +Test has/unset dim handlers +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(42) +NULL +bool(true) +bool(false) +bool(true) +bool(true) \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/005.phpt b/vendor/pimple/pimple/ext/pimple/tests/005.phpt new file mode 100644 index 0000000000..0479ee055d --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/005.phpt @@ -0,0 +1,27 @@ +--TEST-- +Test simple class inheritance +--SKIPIF-- + +--FILE-- +someAttr; +?> +--EXPECT-- +string(3) "hit" +foo +fooAttr \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/006.phpt b/vendor/pimple/pimple/ext/pimple/tests/006.phpt new file mode 100644 index 0000000000..cfe8a119e6 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/006.phpt @@ -0,0 +1,51 @@ +--TEST-- +Test complex class inheritance +--SKIPIF-- + +--FILE-- + 'bar', 88 => 'baz'); + +$p = new TestPimple($defaultValues); +$p[42] = 'foo'; +var_dump($p[42]); +var_dump($p[0]); +?> +--EXPECT-- +string(13) "hit offsetset" +string(27) "hit offsetget in TestPimple" +string(25) "hit offsetget in MyPimple" +string(3) "foo" +string(27) "hit offsetget in TestPimple" +string(25) "hit offsetget in MyPimple" +string(3) "baz" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/007.phpt b/vendor/pimple/pimple/ext/pimple/tests/007.phpt new file mode 100644 index 0000000000..5aac683806 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/007.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test for read_dim/write_dim handlers +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +foo +42 \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/008.phpt b/vendor/pimple/pimple/ext/pimple/tests/008.phpt new file mode 100644 index 0000000000..db7eeec4a1 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/008.phpt @@ -0,0 +1,29 @@ +--TEST-- +Test frozen services +--SKIPIF-- + +--FILE-- + +--EXPECTF-- diff --git a/vendor/pimple/pimple/ext/pimple/tests/009.phpt b/vendor/pimple/pimple/ext/pimple/tests/009.phpt new file mode 100644 index 0000000000..bb05ea2964 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/009.phpt @@ -0,0 +1,13 @@ +--TEST-- +Test service is called as callback, and only once +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +bool(true) \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/010.phpt b/vendor/pimple/pimple/ext/pimple/tests/010.phpt new file mode 100644 index 0000000000..badce0146a --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/010.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test service is called as callback for every callback type +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +callme +called +Foo::bar +array(2) { + [0]=> + string(3) "Foo" + [1]=> + string(3) "bar" +} \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/011.phpt b/vendor/pimple/pimple/ext/pimple/tests/011.phpt new file mode 100644 index 0000000000..6682ab8ebd --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/011.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test service callback throwing an exception +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +all right! \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/012.phpt b/vendor/pimple/pimple/ext/pimple/tests/012.phpt new file mode 100644 index 0000000000..4c6ac486dc --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/012.phpt @@ -0,0 +1,28 @@ +--TEST-- +Test service factory +--SKIPIF-- + +--FILE-- +factory($f = function() { var_dump('called-1'); return 'ret-1';}); + +$p[] = $f; + +$p[] = function () { var_dump('called-2'); return 'ret-2'; }; + +var_dump($p[0]); +var_dump($p[0]); +var_dump($p[1]); +var_dump($p[1]); +?> +--EXPECTF-- +string(8) "called-1" +string(5) "ret-1" +string(8) "called-1" +string(5) "ret-1" +string(8) "called-2" +string(5) "ret-2" +string(5) "ret-2" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/013.phpt b/vendor/pimple/pimple/ext/pimple/tests/013.phpt new file mode 100644 index 0000000000..f419958c5f --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/013.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test keys() +--SKIPIF-- + +--FILE-- +keys()); + +$p['foo'] = 'bar'; +$p[] = 'foo'; + +var_dump($p->keys()); + +unset($p['foo']); + +var_dump($p->keys()); +?> +--EXPECTF-- +array(0) { +} +array(2) { + [0]=> + string(3) "foo" + [1]=> + int(0) +} +array(1) { + [0]=> + int(0) +} \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/014.phpt b/vendor/pimple/pimple/ext/pimple/tests/014.phpt new file mode 100644 index 0000000000..ac937213ac --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/014.phpt @@ -0,0 +1,30 @@ +--TEST-- +Test raw() +--SKIPIF-- + +--FILE-- +raw('foo')); +var_dump($p[42]); + +unset($p['foo']); + +try { + $p->raw('foo'); + echo "expected exception"; +} catch (InvalidArgumentException $e) { } +--EXPECTF-- +string(8) "called-2" +string(5) "ret-2" +object(Closure)#%i (0) { +} +string(8) "called-2" +string(5) "ret-2" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/015.phpt b/vendor/pimple/pimple/ext/pimple/tests/015.phpt new file mode 100644 index 0000000000..314f008ac1 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/015.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test protect() +--SKIPIF-- + +--FILE-- +protect($f); + +var_dump($p['foo']); +--EXPECTF-- +object(Closure)#%i (0) { +} \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/016.phpt b/vendor/pimple/pimple/ext/pimple/tests/016.phpt new file mode 100644 index 0000000000..e55edb0a7a --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/016.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test extend() +--SKIPIF-- + +--FILE-- +extend(12, function ($w) { var_dump($w); return 'bar'; }); /* $callable in code above */ + +var_dump($c('param')); +--EXPECTF-- +string(5) "param" +string(3) "foo" +string(3) "bar" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/017.phpt b/vendor/pimple/pimple/ext/pimple/tests/017.phpt new file mode 100644 index 0000000000..bac23ce09a --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/017.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test extend() with exception in service extension +--SKIPIF-- + +--FILE-- +extend(12, function ($w) { throw new BadMethodCallException; }); + +try { + $p[12]; + echo "Exception expected"; +} catch (BadMethodCallException $e) { } +--EXPECTF-- diff --git a/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt b/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt new file mode 100644 index 0000000000..8f881d6ebf --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test extend() with exception in service factory +--SKIPIF-- + +--FILE-- +extend(12, function ($w) { return 'foobar'; }); + +try { + $p[12]; + echo "Exception expected"; +} catch (BadMethodCallException $e) { } +--EXPECTF-- diff --git a/vendor/pimple/pimple/ext/pimple/tests/018.phpt b/vendor/pimple/pimple/ext/pimple/tests/018.phpt new file mode 100644 index 0000000000..27c12a14e7 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/018.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test register() +--SKIPIF-- + +--FILE-- +register(new Foo, array(42 => 'bar')); + +var_dump($p[42]); +--EXPECTF-- +object(Pimple\Container)#1 (0) { +} +string(3) "bar" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/bench.phpb b/vendor/pimple/pimple/ext/pimple/tests/bench.phpb new file mode 100644 index 0000000000..8ddd6e3b9a --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/bench.phpb @@ -0,0 +1,51 @@ +factory($factory); + +$p['factory'] = $factory; + +echo $p['factory']; +echo $p['factory']; +echo $p['factory']; + +} + +echo microtime(true) - $time; diff --git a/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb b/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb new file mode 100644 index 0000000000..0fbc8391e0 --- /dev/null +++ b/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb @@ -0,0 +1,25 @@ + diff --git a/vendor/pimple/pimple/phpunit.xml.dist b/vendor/pimple/pimple/phpunit.xml.dist new file mode 100644 index 0000000000..5c8d487fea --- /dev/null +++ b/vendor/pimple/pimple/phpunit.xml.dist @@ -0,0 +1,14 @@ + + + + + + ./src/Pimple/Tests + + + diff --git a/vendor/pimple/pimple/src/Pimple/Container.php b/vendor/pimple/pimple/src/Pimple/Container.php new file mode 100644 index 0000000000..26edefc9d8 --- /dev/null +++ b/vendor/pimple/pimple/src/Pimple/Container.php @@ -0,0 +1,281 @@ +factories = new \SplObjectStorage(); + $this->protected = new \SplObjectStorage(); + + foreach ($values as $key => $value) { + $this->offsetSet($key, $value); + } + } + + /** + * Sets a parameter or an object. + * + * Objects must be defined as Closures. + * + * Allowing any PHP callable leads to difficult to debug problems + * as function names (strings) are callable (creating a function with + * the same name as an existing parameter would break your container). + * + * @param string $id The unique identifier for the parameter or object + * @param mixed $value The value of the parameter or a closure to define an object + * @throws \RuntimeException Prevent override of a frozen service + */ + public function offsetSet($id, $value) + { + if (isset($this->frozen[$id])) { + throw new \RuntimeException(sprintf('Cannot override frozen service "%s".', $id)); + } + + $this->values[$id] = $value; + $this->keys[$id] = true; + } + + /** + * Gets a parameter or an object. + * + * @param string $id The unique identifier for the parameter or object + * + * @return mixed The value of the parameter or an object + * + * @throws \InvalidArgumentException if the identifier is not defined + */ + public function offsetGet($id) + { + if (!isset($this->keys[$id])) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); + } + + if ( + isset($this->raw[$id]) + || !is_object($this->values[$id]) + || isset($this->protected[$this->values[$id]]) + || !method_exists($this->values[$id], '__invoke') + ) { + return $this->values[$id]; + } + + if (isset($this->factories[$this->values[$id]])) { + return $this->values[$id]($this); + } + + $raw = $this->values[$id]; + $val = $this->values[$id] = $raw($this); + $this->raw[$id] = $raw; + + $this->frozen[$id] = true; + + return $val; + } + + /** + * Checks if a parameter or an object is set. + * + * @param string $id The unique identifier for the parameter or object + * + * @return bool + */ + public function offsetExists($id) + { + return isset($this->keys[$id]); + } + + /** + * Unsets a parameter or an object. + * + * @param string $id The unique identifier for the parameter or object + */ + public function offsetUnset($id) + { + if (isset($this->keys[$id])) { + if (is_object($this->values[$id])) { + unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]); + } + + unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]); + } + } + + /** + * Marks a callable as being a factory service. + * + * @param callable $callable A service definition to be used as a factory + * + * @return callable The passed callable + * + * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object + */ + public function factory($callable) + { + if (!is_object($callable) || !method_exists($callable, '__invoke')) { + throw new \InvalidArgumentException('Service definition is not a Closure or invokable object.'); + } + + $this->factories->attach($callable); + + return $callable; + } + + /** + * Protects a callable from being interpreted as a service. + * + * This is useful when you want to store a callable as a parameter. + * + * @param callable $callable A callable to protect from being evaluated + * + * @return callable The passed callable + * + * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object + */ + public function protect($callable) + { + if (!is_object($callable) || !method_exists($callable, '__invoke')) { + throw new \InvalidArgumentException('Callable is not a Closure or invokable object.'); + } + + $this->protected->attach($callable); + + return $callable; + } + + /** + * Gets a parameter or the closure defining an object. + * + * @param string $id The unique identifier for the parameter or object + * + * @return mixed The value of the parameter or the closure defining an object + * + * @throws \InvalidArgumentException if the identifier is not defined + */ + public function raw($id) + { + if (!isset($this->keys[$id])) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); + } + + if (isset($this->raw[$id])) { + return $this->raw[$id]; + } + + return $this->values[$id]; + } + + /** + * Extends an object definition. + * + * Useful when you want to extend an existing object definition, + * without necessarily loading that object. + * + * @param string $id The unique identifier for the object + * @param callable $callable A service definition to extend the original + * + * @return callable The wrapped callable + * + * @throws \InvalidArgumentException if the identifier is not defined or not a service definition + */ + public function extend($id, $callable) + { + if (!isset($this->keys[$id])) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); + } + + if (!is_object($this->values[$id]) || !method_exists($this->values[$id], '__invoke')) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" does not contain an object definition.', $id)); + } + + if (!is_object($callable) || !method_exists($callable, '__invoke')) { + throw new \InvalidArgumentException('Extension service definition is not a Closure or invokable object.'); + } + + $factory = $this->values[$id]; + + $extended = function ($c) use ($callable, $factory) { + return $callable($factory($c), $c); + }; + + if (isset($this->factories[$factory])) { + $this->factories->detach($factory); + $this->factories->attach($extended); + } + + return $this[$id] = $extended; + } + + /** + * Returns all defined value names. + * + * @return array An array of value names + */ + public function keys() + { + return array_keys($this->values); + } + + /** + * Registers a service provider. + * + * @param ServiceProviderInterface $provider A ServiceProviderInterface instance + * @param array $values An array of values that customizes the provider + * + * @return static + */ + public function register(ServiceProviderInterface $provider, array $values = array()) + { + $provider->register($this); + + foreach ($values as $key => $value) { + $this[$key] = $value; + } + + return $this; + } +} diff --git a/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php b/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php new file mode 100644 index 0000000000..9b122bd434 --- /dev/null +++ b/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php @@ -0,0 +1,46 @@ +value = $value; + + return $service; + } +} diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php new file mode 100644 index 0000000000..33cd4e5486 --- /dev/null +++ b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php @@ -0,0 +1,34 @@ +factory(function () { + return new Service(); + }); + } +} diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php new file mode 100644 index 0000000000..d71b184ddf --- /dev/null +++ b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php @@ -0,0 +1,35 @@ + + */ +class Service +{ + public $value; +} diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php new file mode 100644 index 0000000000..69f76f8435 --- /dev/null +++ b/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php @@ -0,0 +1,76 @@ + + */ +class PimpleServiceProviderInterfaceTest extends \PHPUnit_Framework_TestCase +{ + public function testProvider() + { + $pimple = new Container(); + + $pimpleServiceProvider = new Fixtures\PimpleServiceProvider(); + $pimpleServiceProvider->register($pimple); + + $this->assertEquals('value', $pimple['param']); + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + + $serviceOne = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } + + public function testProviderWithRegisterMethod() + { + $pimple = new Container(); + + $pimple->register(new Fixtures\PimpleServiceProvider(), array( + 'anotherParameter' => 'anotherValue' + )); + + $this->assertEquals('value', $pimple['param']); + $this->assertEquals('anotherValue', $pimple['anotherParameter']); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + + $serviceOne = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } +} diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php new file mode 100644 index 0000000000..30ca391255 --- /dev/null +++ b/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php @@ -0,0 +1,434 @@ + + */ +class PimpleTest extends \PHPUnit_Framework_TestCase +{ + public function testWithString() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + + $this->assertEquals('value', $pimple['param']); + } + + public function testWithClosure() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + } + + public function testServicesShouldBeDifferent() + { + $pimple = new Container(); + $pimple['service'] = $pimple->factory(function () { + return new Fixtures\Service(); + }); + + $serviceOne = $pimple['service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } + + public function testShouldPassContainerAsParameter() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + $pimple['container'] = function ($container) { + return $container; + }; + + $this->assertNotSame($pimple, $pimple['service']); + $this->assertSame($pimple, $pimple['container']); + } + + public function testIsset() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + $pimple['null'] = null; + + $this->assertTrue(isset($pimple['param'])); + $this->assertTrue(isset($pimple['service'])); + $this->assertTrue(isset($pimple['null'])); + $this->assertFalse(isset($pimple['non_existent'])); + } + + public function testConstructorInjection() + { + $params = array("param" => "value"); + $pimple = new Container($params); + + $this->assertSame($params['param'], $pimple['param']); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" is not defined. + */ + public function testOffsetGetValidatesKeyIsPresent() + { + $pimple = new Container(); + echo $pimple['foo']; + } + + public function testOffsetGetHonorsNullValues() + { + $pimple = new Container(); + $pimple['foo'] = null; + $this->assertNull($pimple['foo']); + } + + public function testUnset() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + unset($pimple['param'], $pimple['service']); + $this->assertFalse(isset($pimple['param'])); + $this->assertFalse(isset($pimple['service'])); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testShare($service) + { + $pimple = new Container(); + $pimple['shared_service'] = $service; + + $serviceOne = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertSame($serviceOne, $serviceTwo); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testProtect($service) + { + $pimple = new Container(); + $pimple['protected'] = $pimple->protect($service); + + $this->assertSame($service, $pimple['protected']); + } + + public function testGlobalFunctionNameAsParameterValue() + { + $pimple = new Container(); + $pimple['global_function'] = 'strlen'; + $this->assertSame('strlen', $pimple['global_function']); + } + + public function testRaw() + { + $pimple = new Container(); + $pimple['service'] = $definition = $pimple->factory(function () { return 'foo'; }); + $this->assertSame($definition, $pimple->raw('service')); + } + + public function testRawHonorsNullValues() + { + $pimple = new Container(); + $pimple['foo'] = null; + $this->assertNull($pimple->raw('foo')); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" is not defined. + */ + public function testRawValidatesKeyIsPresent() + { + $pimple = new Container(); + $pimple->raw('foo'); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testExtend($service) + { + $pimple = new Container(); + $pimple['shared_service'] = function () { + return new Fixtures\Service(); + }; + $pimple['factory_service'] = $pimple->factory(function () { + return new Fixtures\Service(); + }); + + $pimple->extend('shared_service', $service); + $serviceOne = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + $serviceTwo = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + $this->assertSame($serviceOne, $serviceTwo); + $this->assertSame($serviceOne->value, $serviceTwo->value); + + $pimple->extend('factory_service', $service); + $serviceOne = $pimple['factory_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + $serviceTwo = $pimple['factory_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + $this->assertNotSame($serviceOne, $serviceTwo); + $this->assertNotSame($serviceOne->value, $serviceTwo->value); + } + + public function testExtendDoesNotLeakWithFactories() + { + if (extension_loaded('pimple')) { + $this->markTestSkipped('Pimple extension does not support this test'); + } + $pimple = new Container(); + + $pimple['foo'] = $pimple->factory(function () { return; }); + $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) { return; }); + unset($pimple['foo']); + + $p = new \ReflectionProperty($pimple, 'values'); + $p->setAccessible(true); + $this->assertEmpty($p->getValue($pimple)); + + $p = new \ReflectionProperty($pimple, 'factories'); + $p->setAccessible(true); + $this->assertCount(0, $p->getValue($pimple)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" is not defined. + */ + public function testExtendValidatesKeyIsPresent() + { + $pimple = new Container(); + $pimple->extend('foo', function () {}); + } + + public function testKeys() + { + $pimple = new Container(); + $pimple['foo'] = 123; + $pimple['bar'] = 123; + + $this->assertEquals(array('foo', 'bar'), $pimple->keys()); + } + + /** @test */ + public function settingAnInvokableObjectShouldTreatItAsFactory() + { + $pimple = new Container(); + $pimple['invokable'] = new Fixtures\Invokable(); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['invokable']); + } + + /** @test */ + public function settingNonInvokableObjectShouldTreatItAsParameter() + { + $pimple = new Container(); + $pimple['non_invokable'] = new Fixtures\NonInvokable(); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\NonInvokable', $pimple['non_invokable']); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Service definition is not a Closure or invokable object. + */ + public function testFactoryFailsForInvalidServiceDefinitions($service) + { + $pimple = new Container(); + $pimple->factory($service); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Callable is not a Closure or invokable object. + */ + public function testProtectFailsForInvalidServiceDefinitions($service) + { + $pimple = new Container(); + $pimple->protect($service); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" does not contain an object definition. + */ + public function testExtendFailsForKeysNotContainingServiceDefinitions($service) + { + $pimple = new Container(); + $pimple['foo'] = $service; + $pimple->extend('foo', function () {}); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Extension service definition is not a Closure or invokable object. + */ + public function testExtendFailsForInvalidServiceDefinitions($service) + { + $pimple = new Container(); + $pimple['foo'] = function () {}; + $pimple->extend('foo', $service); + } + + /** + * Provider for invalid service definitions + */ + public function badServiceDefinitionProvider() + { + return array( + array(123), + array(new Fixtures\NonInvokable()) + ); + } + + /** + * Provider for service definitions + */ + public function serviceDefinitionProvider() + { + return array( + array(function ($value) { + $service = new Fixtures\Service(); + $service->value = $value; + + return $service; + }), + array(new Fixtures\Invokable()) + ); + } + + public function testDefiningNewServiceAfterFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + $pimple['bar'] = function () { + return 'bar'; + }; + $this->assertSame('bar', $pimple['bar']); + } + + /** + * @expectedException RuntimeException + * @expectedExceptionMessage Cannot override frozen service "foo". + */ + public function testOverridingServiceAfterFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + $pimple['foo'] = function () { + return 'bar'; + }; + } + + public function testRemovingServiceAfterFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + unset($pimple['foo']); + $pimple['foo'] = function () { + return 'bar'; + }; + $this->assertSame('bar', $pimple['foo']); + } + + public function testExtendingService() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { + return "$foo.bar"; + }); + $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { + return "$foo.baz"; + }); + $this->assertSame('foo.bar.baz', $pimple['foo']); + } + + public function testExtendingServiceAfterOtherServiceFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $pimple['bar'] = function () { + return 'bar'; + }; + $foo = $pimple['foo']; + + $pimple['bar'] = $pimple->extend('bar', function ($bar, $app) { + return "$bar.baz"; + }); + $this->assertSame('bar.baz', $pimple['bar']); + } +} From 846c836cb870d5eb7dc4697e1b58216b7bb8a14d Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 18 Aug 2014 14:45:42 +0300 Subject: [PATCH 21/63] Add DEV/PROD parameter to debugger constructor --- index.php | 2 +- system/src/Grav/Common/Debugger.php | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index f35aa9b984..26fe3baea1 100644 --- a/index.php +++ b/index.php @@ -18,7 +18,7 @@ $grav = Grav::instance( [ 'Loader' => $loader, - 'Debugger' => new Debugger + 'Debugger' => new Debugger(Debugger::PRODUCTION) ] ); diff --git a/system/src/Grav/Common/Debugger.php b/system/src/Grav/Common/Debugger.php index 50f3678561..a6e2c56d82 100644 --- a/system/src/Grav/Common/Debugger.php +++ b/system/src/Grav/Common/Debugger.php @@ -9,12 +9,15 @@ */ class Debugger { - public function __construct() + const PRODUCTION = TracyDebugger::PRODUCTION; + const DEVELOPMENT = TracyDebugger::DEVELOPMENT; + + public function __construct($mode = self::PRODUCTION) { // Start the timer and enable debugger in production mode as we do not have system configuration yet. // Debugger catches all errors and logs them, for example if the script doesn't have write permissions. TracyDebugger::timer(); - TracyDebugger::enable(TracyDebugger::DEVELOPMENT, is_dir(LOG_DIR) ? LOG_DIR : null); + TracyDebugger::enable($mode, is_dir(LOG_DIR) ? LOG_DIR : null); } public function init() From b0bf847208bbcadee3e343bdfeb98f7db87140a0 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 18 Aug 2014 15:23:53 +0300 Subject: [PATCH 22/63] Convert DI variables to lower case --- index.php | 6 +- system/src/Grav/Common/Assets.php | 4 +- system/src/Grav/Common/Cache.php | 4 +- system/src/Grav/Common/Config.php | 4 +- system/src/Grav/Common/Debugger.php | 2 +- system/src/Grav/Common/Grav.php | 68 ++++++++++------------ system/src/Grav/Common/Page/Collection.php | 2 +- system/src/Grav/Common/Page/Media.php | 2 +- system/src/Grav/Common/Page/Medium.php | 4 +- system/src/Grav/Common/Page/Page.php | 44 +++++++------- system/src/Grav/Common/Page/Pages.php | 20 +++---- system/src/Grav/Common/Plugins.php | 4 +- system/src/Grav/Common/Registry.php | 6 +- system/src/Grav/Common/Taxonomy.php | 2 +- system/src/Grav/Common/Themes.php | 2 +- system/src/Grav/Common/Twig.php | 14 ++--- 16 files changed, 91 insertions(+), 97 deletions(-) diff --git a/index.php b/index.php index 26fe3baea1..cf7025a4c2 100644 --- a/index.php +++ b/index.php @@ -17,8 +17,8 @@ $grav = Grav::instance( [ - 'Loader' => $loader, - 'Debugger' => new Debugger(Debugger::PRODUCTION) + 'loader' => $loader, + 'debugger' => new Debugger(Debugger::PRODUCTION) ] ); @@ -26,7 +26,7 @@ ob_start(); try { - $grav['Debugger']->init(); + $grav['debugger']->init(); $grav->process(); } catch (\Exception $e) { diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php index cf9af020b8..f4fe9f14d6 100644 --- a/system/src/Grav/Common/Assets.php +++ b/system/src/Grav/Common/Assets.php @@ -97,7 +97,7 @@ public function __construct(array $options = array()) public function init() { /** @var Config $config */ - $config = Grav::instance()['Config']; + $config = Grav::instance()['config']; $base_url = trim($config->get('system.base_url_relative')); $theme = $config->get('system.pages.theme'); $asset_config = (array)$config->get('system.assets'); @@ -383,7 +383,7 @@ public function resetJs() protected function pipeline($css = true) { /** @var Cache $cache */ - $cache = Grav::instance()['Cache']; + $cache = Grav::instance()['cache']; $key = '?'.$cache->getKey(); if ($css) { diff --git a/system/src/Grav/Common/Cache.php b/system/src/Grav/Common/Cache.php index 27eb942ec6..3b92b28499 100644 --- a/system/src/Grav/Common/Cache.php +++ b/system/src/Grav/Common/Cache.php @@ -53,10 +53,10 @@ public function __construct(Grav $c) public function init(Grav $c) { /** @var Config $config */ - $config = $c['Config']; + $config = $c['config']; /** @var Uri $uri */ - $uri = $c['Uri']; + $uri = $c['uri']; $prefix = $config->get('system.cache.prefix'); diff --git a/system/src/Grav/Common/Config.php b/system/src/Grav/Common/Config.php index 9b96db61fa..df25af8704 100644 --- a/system/src/Grav/Common/Config.php +++ b/system/src/Grav/Common/Config.php @@ -132,11 +132,11 @@ public static function instance(Grav $grav) // If not set, add manually current base url. if (empty($instance->items['system']['base_url_absolute'])) { - $instance->items['system']['base_url_absolute'] = $grav['Uri']->rootUrl(true); + $instance->items['system']['base_url_absolute'] = $grav['uri']->rootUrl(true); } if (empty($instance->items['system']['base_url_relative'])) { - $instance->items['system']['base_url_relative'] = $grav['Uri']->rootUrl(false); + $instance->items['system']['base_url_relative'] = $grav['uri']->rootUrl(false); } return $instance; diff --git a/system/src/Grav/Common/Debugger.php b/system/src/Grav/Common/Debugger.php index a6e2c56d82..4c54144b99 100644 --- a/system/src/Grav/Common/Debugger.php +++ b/system/src/Grav/Common/Debugger.php @@ -23,7 +23,7 @@ public function __construct($mode = self::PRODUCTION) public function init() { /** @var Config $config */ - $config = Grav::instance()['Config']; + $config = Grav::instance()['config']; TracyDebugger::$logDirectory = $config->get('system.debugger.log.enabled') ? LOG_DIR : null; TracyDebugger::$maxDepth = $config->get('system.debugger.max_depth'); diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 550427129e..8499d10225 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -13,15 +13,6 @@ * * Originally based on Pico by Gilbert Pellegrom - http://pico.dev7studios.com * Influenced by Pico, Stacey, Kirby, PieCrust and other great platforms... - * - * @property Uri $uri - * @property Config $config - * @property Plugins $plugins - * @property Cache $cache - * @property Page\Pages $pages - * @property Page\Page $page - * @property Assets $assets - * @property Taxonomy $taxonomy */ class Grav extends Container { @@ -55,39 +46,42 @@ protected static function load(array $values) $container['config_path'] = CACHE_DIR . 'config.php'; - $container['Grav'] = $container; + $container['grav'] = $container; - $container['Uri'] = function ($c) { + $container['uri'] = function ($c) { return new Uri($c); }; - $container['Config'] = function ($c) { + $container['config'] = function ($c) { return Config::instance($c); }; - $container['Cache'] = function ($c) { + $container['cache'] = function ($c) { return new Cache($c); }; - $container['Plugins'] = function ($c) { + $container['plugins'] = function ($c) { return new Plugins($c); }; - $container['Themes'] = function ($c) { + $container['themes'] = function ($c) { return new Themes($c); }; - $container['Twig'] = function ($c) { + $container['twig'] = function ($c) { return new Twig($c); }; - $container['Taxonomy'] = function ($c) { + $container['taxonomy'] = function ($c) { return new Taxonomy($c); }; - $container['Pages'] = function ($c) { + $container['pages'] = function ($c) { return new Page\Pages($c); }; - $container['Assets'] = function ($c) { + $container['assets'] = function ($c) { return new Assets(); }; - $container['Page'] = function ($c) { - return $c['Pages']->dispatch($c['Uri']->route()); + $container['page'] = function ($c) { + return $c['pages']->dispatch($c['uri']->route()); + }; + $container['output'] = function ($c) { + return $c['twig']->processSite($c['uri']->extension()); }; - $container['UserAgent'] = function ($c) { + $container['user_agent'] = function ($c) { return new \phpUserAgent(); }; @@ -96,28 +90,28 @@ protected static function load(array $values) public function process() { - $this['Plugins']->init(); + $this['plugins']->init(); $this->fireEvent('onAfterInitPlugins'); - $this['Assets']->init(); + $this['assets']->init(); $this->fireEvent('onAfterGetAssets'); - $this['Twig']->init(); - $this['Pages']->init(); + $this['twig']->init(); + $this['pages']->init(); $this->fireEvent('onAfterGetPages'); $this->fireEvent('onAfterGetPage'); // If there's no page, throw exception - if (!$this['Page']) { + if (!$this['page']) { throw new \RuntimeException('Page Not Found', 404); } // Process whole page as required - $this->output = $this['Twig']->processSite($this['Uri']->extension()); + $this->output = $this['output']; $this->fireEvent('onAfterGetOutput'); @@ -136,7 +130,7 @@ public function process() public function redirect($route, $code = 303) { /** @var Uri $uri */ - $uri = $this['Uri']; + $uri = $this['uri']; header("Location: " . rtrim($uri->rootUrl(), '/') .'/'. trim($route, '/'), true, $code); exit(); } @@ -170,7 +164,7 @@ public function mime($format) public function header() { /** @var Uri $uri */ - $uri = $this['Uri']; + $uri = $this['uri']; header('Content-type: ' . $this->mime($uri->extension())); } @@ -184,7 +178,7 @@ public function fireEvent() $no_timing_hooks = array('onAfterPageProcessed','onAfterFolderProcessed', 'onAfterCollectionProcessed'); /** @var Plugins $plugins */ - $plugins = $this['Plugins']; + $plugins = $this['plugins']; if (!empty($plugins)) { foreach ($plugins as $plugin) { @@ -194,13 +188,13 @@ public function fireEvent() } } - if (isset($this['Debugger'])) { - /** @var Config $config */ - $config = $this['Config']; + /** @var Config $config */ + $config = $this['config']; - if ($config && $config->get('system.debugger.log.timing') && !in_array($hook_id, $no_timing_hooks)) { - /** @var Debugger $debugger */ - $debugger = $this['Debugger']; + if ($config && $config->get('system.debugger.log.timing') && !in_array($hook_id, $no_timing_hooks)) { + /** @var Debugger $debugger */ + $debugger = isset($this['debugger']) ? $this['debugger'] : null; + if ($debugger) { $debugger->log($hook_id.': %f ms'); } } diff --git a/system/src/Grav/Common/Page/Collection.php b/system/src/Grav/Common/Page/Collection.php index 2d5bf47662..3eb091ea04 100644 --- a/system/src/Grav/Common/Page/Collection.php +++ b/system/src/Grav/Common/Page/Collection.php @@ -26,7 +26,7 @@ public function __construct($items = array(), array $params = array(), Pages $pa parent::__construct($items); $this->params = $params; - $this->pages = $pages ? $pages : Grav::instance()['Pages']; + $this->pages = $pages ? $pages : Grav::instance()['pages']; } public function params() diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index fbfc47365c..3760f14c91 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -75,7 +75,7 @@ public function get($filename, $create = false) $basename = implode('.', $parts); /** @var Config $config */ - $config = Grav::instance()['Config']; + $config = Grav::instance()['config']; // Check if medium type has been configured. $params = $config->get("media.{$ext}"); diff --git a/system/src/Grav/Common/Page/Medium.php b/system/src/Grav/Common/Page/Medium.php index cefb90906a..6164728682 100644 --- a/system/src/Grav/Common/Page/Medium.php +++ b/system/src/Grav/Common/Page/Medium.php @@ -97,7 +97,7 @@ public function __toString() public function url() { /** @var Config $config */ - $config = Grav::instance()['Config']; + $config = Grav::instance()['config']; if ($this->image) { $output = $this->image->cacheFile($this->type, $this->quality); @@ -174,7 +174,7 @@ public function html($title = null, $class = null, $type = null, $quality = 80) if ($this->linkTarget) { /** @var Config $config */ - $config = Grav::instance()['Config']; + $config = Grav::instance()['config']; $output = 'linkAttributes. ' class="'. $class . '">' . $output . ''; diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index f72bcee2d8..44fd908f4b 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -83,7 +83,7 @@ class Page public function __construct($array = array()) { /** @var Config $config */ - $config = Grav::instance()['Config']; + $config = Grav::instance()['config']; $this->routable = true; $this->taxonomy = array(); @@ -230,7 +230,7 @@ public function summary($size = null) // Return calculated summary based on setting in site config file /** @var Config $config */ - $config = Grav::instance()['Config']; + $config = Grav::instance()['config']; if (!$size && $config->get('site.summary.size')) { $size = $config->get('site.summary.size'); } @@ -270,7 +270,7 @@ public function content($var = null) // Load cached content /** @var Cache $cache */ - $cache = Grav::instance()['Cache']; + $cache = Grav::instance()['cache']; $cache_id = md5('page'.$this->id()); $content = $cache->fetch($cache_id); @@ -296,7 +296,7 @@ public function content($var = null) // Do we need to process twig this time? if ($update_cache || $process_twig) { /** @var Twig $twig */ - $twig = Grav::instance()['Twig']; + $twig = Grav::instance()['twig']; $content = $twig->processPage($this, $content); } } @@ -464,7 +464,7 @@ public function copy($parent) public function blueprints() { /** @var Pages $pages */ - $pages = Grav::instance()['Pages']; + $pages = Grav::instance()['pages']; return $pages->blueprints($this->template()); } @@ -543,7 +543,7 @@ public function toJson() public function media($var = null) { /** @var Cache $cache */ - $cache = Grav::instance()['Cache']; + $cache = Grav::instance()['cache']; if ($var) { $this->media = $var; @@ -761,7 +761,7 @@ public function link($include_host = false) public function url($include_host = false) { /** @var Uri $uri */ - $uri = Grav::instance()['Uri']; + $uri = Grav::instance()['uri']; $rootUrl = $uri->rootUrl($include_host); $url = $rootUrl.'/'.trim($this->route(), '/'); @@ -957,7 +957,7 @@ public function maxCount($var = null) } if (empty($this->max_count)) { /** @var Config $config */ - $config = Grav::instance()['Config']; + $config = Grav::instance()['config']; $this->max_count = (int) $config->get('system.pages.list.count'); } return $this->max_count; @@ -1034,7 +1034,7 @@ public function parent(Page $var = null) } /** @var Pages $pages */ - $pages = Grav::instance()['Pages']; + $pages = Grav::instance()['pages']; return $pages->get($this->parent); } @@ -1047,7 +1047,7 @@ public function parent(Page $var = null) public function children() { /** @var Pages $pages */ - $pages = Grav::instance()['Pages']; + $pages = Grav::instance()['pages']; return $pages->children($this->path()); } @@ -1127,7 +1127,7 @@ public function nth($key) public function isFirst() { /** @var Pages $pages */ - $pages = Grav::instance()['Pages']; + $pages = Grav::instance()['pages']; $parent = $pages->get($this->parent); if ($this->path() == array_values($parent->items)[0]) { @@ -1145,7 +1145,7 @@ public function isFirst() public function isLast() { /** @var Pages $pages */ - $pages = Grav::instance()['Pages']; + $pages = Grav::instance()['pages']; $parent = $pages->get($this->parent); if ($this->path() == array_values($parent->items)[count($parent->items)-1]) { @@ -1184,7 +1184,7 @@ public function nextSibling() public function adjacentSibling($direction = 1) { /** @var Pages $pages */ - $pages = Grav::instance()['Pages']; + $pages = Grav::instance()['pages']; $parent = $pages->get($this->parent); $current = $this->slug(); @@ -1203,7 +1203,7 @@ public function adjacentSibling($direction = 1) public function active() { /** @var Uri $uri */ - $uri = Grav::instance()['Uri']; + $uri = Grav::instance()['uri']; if ($this->url() == $uri->url()) { return true; } @@ -1218,7 +1218,7 @@ public function active() */ public function activeChild() { - $uri = Grav::instance()['Uri']; + $uri = Grav::instance()['uri']; if (!$this->home() && (strpos($uri->url(), $this->url()) !== false)) { return true; } @@ -1259,7 +1259,7 @@ public function root() public function find($url) { /** @var Pages $pages */ - $pages = Grav::instance()['Pages']; + $pages = Grav::instance()['pages']; return $pages->dispatch($url); } @@ -1290,9 +1290,9 @@ public function collection($params = 'content') // TODO: MOVE THIS INTO SOMEWHERE ELSE? /** @var Uri $uri */ - $uri = Grav::instance()['Uri']; + $uri = Grav::instance()['uri']; /** @var Config $config */ - $config = Grav::instance()['Config']; + $config = Grav::instance()['config']; foreach ((array) $config->get('site.taxonomies') as $taxonomy) { if ($uri->param($taxonomy)) { @@ -1324,7 +1324,7 @@ public function collection($params = 'content') } /** @var Grav $grav */ - $grav = Grav::instance()['Grav']; + $grav = Grav::instance()['grav']; // New Custom event to handle things like pagination. $grav->fireEvent('onAfterCollectionProcessed', $collection); @@ -1392,7 +1392,7 @@ protected function evaluate($value) // @taxonomy: { category: [ blog, featured ], level: 1 } /** @var Taxonomy $taxonomy_map */ - $taxonomy_map = Grav::instance()['Taxonomy']; + $taxonomy_map = Grav::instance()['taxonomy']; if (!empty($parts)) { $params = [implode('.', $parts) => $params]; @@ -1508,7 +1508,7 @@ protected function rawContent($content) protected function parseMarkdownContent($content) { /** @var Config $config */ - $config = Grav::instance()['Config']; + $config = Grav::instance()['config']; if ($config->get('system.pages.markdown_extra')) { $parsedown = new \ParsedownExtra(); } else { @@ -1547,7 +1547,7 @@ protected function doRelocation($reorder) // Do reordering. if ($reorder && $this->order() != $this->_original->order()) { /** @var Pages $pages */ - $pages = Grav::instance()['Pages']; + $pages = Grav::instance()['pages']; $parent = $this->parent(); diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index b6cdecca4e..ef406cca16 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -226,7 +226,7 @@ public function dispatch($url, $all = false) // If the page cannot be reached, look into site wide routes. if (!$all && (!$page || !$page->routable())) { /** @var Config $config */ - $config = $this->grav['Config']; + $config = $this->grav['config']; $route = $config->get("site.routes.{$url}"); if ($route) { @@ -257,7 +257,7 @@ public function blueprints($type) { if (!isset($this->blueprints)) { /** @var Config $config */ - $config = $this->grav['Config']; + $config = $this->grav['config']; $this->blueprints = new Data\Blueprints(THEMES_DIR . $config->get('system.pages.theme') . '/blueprints/'); } @@ -314,7 +314,7 @@ public function getList(Page $current = null, $level = 0) static public function types() { /** @var Config $config */ - $config = Grav::instance()['Config']; + $config = Grav::instance()['config']; $blueprints = new Data\Blueprints(THEMES_DIR . $config->get('system.pages.theme') . '/blueprints/'); @@ -329,7 +329,7 @@ static public function types() static public function parents() { /** @var Pages $pages */ - $pages = Grav::instance()['Pages']; + $pages = Grav::instance()['pages']; return $pages->getList(); } @@ -343,13 +343,13 @@ protected function buildPages() $this->sort = array(); /** @var Config $config */ - $config = $this->grav['Config']; + $config = $this->grav['config']; if ($config->get('system.cache.enabled')) { /** @var Cache $cache */ - $cache = $this->grav['Cache']; + $cache = $this->grav['cache']; /** @var Taxonomy $taxonomy */ - $taxonomy = $this->grav['Taxonomy']; + $taxonomy = $this->grav['taxonomy']; $last_modified = $config->get('system.cache.check.pages', true) ? Folder::lastModified(PAGES_DIR) : 0; $page_cache_id = md5(USER_DIR.$last_modified); @@ -388,7 +388,7 @@ protected function recurse($directory = PAGES_DIR, Page &$parent = null) $directory = rtrim($directory, DS); $iterator = new \DirectoryIterator($directory); $page = new Page; - $config = $this->grav['Config']; + $config = $this->grav['config']; $page->path($directory); if ($parent) $page->parent($parent); @@ -459,7 +459,7 @@ protected function recurse($directory = PAGES_DIR, Page &$parent = null) protected function buildRoutes() { /** @var $taxonomy Taxonomy */ - $taxonomy = $this->grav['Taxonomy']; + $taxonomy = $this->grav['taxonomy']; // Build routes and taxonomy map. /** @var $page Page */ @@ -481,7 +481,7 @@ protected function buildRoutes() } /** @var Config $config */ - $config = $this->grav['Config']; + $config = $this->grav['config']; // Alias and set default route to home page. $home = trim($config->get('system.home.alias'), '/'); diff --git a/system/src/Grav/Common/Plugins.php b/system/src/Grav/Common/Plugins.php index c275c72e26..92db564610 100644 --- a/system/src/Grav/Common/Plugins.php +++ b/system/src/Grav/Common/Plugins.php @@ -27,10 +27,10 @@ public function __construct(Grav $grav) { public function init() { /** @var Config $config */ - $config = $this->grav['Config']; + $config = $this->grav['config']; $plugins = (array) $config->get('plugins'); - $instances = ['Theme' => $this->grav['Themes']->load()]; + $instances = ['theme' => $this->grav['themes']->load()]; foreach ($plugins as $plugin => $data) { if (empty($data['enabled'])) { // Only load enabled plugins. diff --git a/system/src/Grav/Common/Registry.php b/system/src/Grav/Common/Registry.php index 97e8ce6866..0f7b8d6066 100644 --- a/system/src/Grav/Common/Registry.php +++ b/system/src/Grav/Common/Registry.php @@ -34,7 +34,7 @@ public static function get($key) { user_error(__METHOD__ . '()', E_USER_DEPRECATED); $instance = Grav::instance(); - return $instance[$key]; + return $instance[strtolower($key)]; } /** @@ -62,7 +62,7 @@ public function store($key, $value) { user_error(__CLASS__ . '::' . __METHOD__ . '()', E_USER_DEPRECATED); $instance = Grav::instance(); - $instance[$key] = $value; + $instance[strtolower($key)] = $value; } /** @@ -76,6 +76,6 @@ public function retrieve($key) { user_error(__CLASS__ . '::' . __METHOD__ . '()', E_USER_DEPRECATED); $instance = Grav::instance(); - return $instance[$key]; + return $instance[strtolower($key)]; } } diff --git a/system/src/Grav/Common/Taxonomy.php b/system/src/Grav/Common/Taxonomy.php index 93e1eca62c..dadf42b7f6 100644 --- a/system/src/Grav/Common/Taxonomy.php +++ b/system/src/Grav/Common/Taxonomy.php @@ -51,7 +51,7 @@ public function addTaxonomy(Page\Page $page, $page_taxonomy = null) } /** @var Config $config */ - $config = $this->grav['Config']; + $config = $this->grav['config']; if ($config->get('site.taxonomies') && count($page_taxonomy) > 0) { foreach ((array) $config->get('site.taxonomies') as $taxonomy) { if (isset($page_taxonomy[$taxonomy])) { diff --git a/system/src/Grav/Common/Themes.php b/system/src/Grav/Common/Themes.php index fcc8ed6fcb..4d359c24e6 100644 --- a/system/src/Grav/Common/Themes.php +++ b/system/src/Grav/Common/Themes.php @@ -88,7 +88,7 @@ public function load($name = null) { if (!$name) { /** @var Config $config */ - $config = $this->grav['Config']; + $config = $this->grav['config']; $name = $config->get('system.pages.theme'); } diff --git a/system/src/Grav/Common/Twig.php b/system/src/Grav/Common/Twig.php index f128ffa83b..38eec6c214 100644 --- a/system/src/Grav/Common/Twig.php +++ b/system/src/Grav/Common/Twig.php @@ -64,7 +64,7 @@ public function init() { if (!isset($this->twig)) { /** @var Config $config */ - $config = $this->grav['Config']; + $config = $this->grav['config']; $this->twig_paths = array(THEMES_DIR . $config->get('system.pages.theme') . '/templates'); $this->grav->fireEvent('onAfterTwigTemplatesPaths'); @@ -101,16 +101,16 @@ public function init() $this->twig_vars = array( 'grav_version' => GRAV_VERSION, 'config' => $config, - 'uri' => $this->grav['Uri'], + 'uri' => $this->grav['uri'], 'base_dir' => rtrim(ROOT_DIR, '/'), 'base_url_absolute' => $baseUrlAbsolute, 'base_url_relative' => $baseUrlRelative, 'theme_dir' => THEMES_DIR . $theme, 'theme_url' => $themeUrl, 'site' => $config->get('site'), - 'assets' => $this->grav['Assets'], - 'taxonomy' => $this->grav['Taxonomy'], - 'user_agent' => $this->grav['UserAgent'], + 'assets' => $this->grav['assets'], + 'taxonomy' => $this->grav['taxonomy'], + 'user_agent' => $this->grav['user_agent'], ); } @@ -211,8 +211,8 @@ public function processSite($format = null) // set the page now its been processed $this->grav->fireEvent('onAfterTwigSiteVars'); $twig_vars = $this->twig_vars; - $pages = $this->grav['Pages']; - $page = $this->grav['Page']; + $pages = $this->grav['pages']; + $page = $this->grav['page']; $twig_vars['pages'] = $pages->root(); $twig_vars['page'] = $page; From 285874caf54cf988c90d60a3c462aee4481764ad Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 18 Aug 2014 17:22:44 +0300 Subject: [PATCH 23/63] Fix exception using wrong namespace in Assets --- system/src/Grav/Common/Assets.php | 34 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php index f4fe9f14d6..114ace12c2 100644 --- a/system/src/Grav/Common/Assets.php +++ b/system/src/Grav/Common/Assets.php @@ -91,8 +91,6 @@ public function __construct(array $options = array()) /** * Initialization called in the Grav lifecycle to initialize the Assets with appropriate configuration - * - * @return [type] [description] */ public function init() { @@ -116,8 +114,8 @@ public function init() * assets and/or collections that will be automatically added on startup. * * @param array $options Configurable options. - * @return Manager - * @throws Exception + * @return $this + * @throws \Exception */ public function config(array $config) { @@ -130,7 +128,7 @@ public function config(array $config) // Pipeline requires public dir if(($this->js_pipeline || $this->css_pipeline) && ! is_dir(ASSETS_DIR)) - throw new Exception('Assets: Public dir not found'); + throw new \Exception('Assets: Public dir not found'); // Set custom pipeline fetch command if(isset($config['fetch_command']) and ($config['fetch_command'] instanceof Closure)) @@ -172,7 +170,7 @@ public function config(array $config) * @param mixed $asset * @param int $priority the priority, bigger comes first * @param bool $pipeline false if this should not be pipelined - * @return Manager + * @return $this */ public function add($asset, $priority = 10, $pipeline = true) { @@ -213,7 +211,7 @@ public function add($asset, $priority = 10, $pipeline = true) * @param mixed $asset * @param int $priority the priority, bigger comes first * @param bool $pipeline false if this should not be pipelined - * @return Manager + * @return $this */ public function addCss($asset, $priority = 10, $pipeline = true) { @@ -243,7 +241,7 @@ public function addCss($asset, $priority = 10, $pipeline = true) * @param mixed $asset * @param int $priority the priority, bigger comes first * @param bool $pipeline false if this should not be pipelined - * @return Manager + * @return $this */ public function addJs($asset, $priority = 10, $pipeline = true) { @@ -332,7 +330,7 @@ public function js() * * @param string $collectionName * @param array $assets - * @return Manager + * @return $this */ public function registerCollection($collectionName, Array $assets) { @@ -344,7 +342,7 @@ public function registerCollection($collectionName, Array $assets) /** * Reset all assets. * - * @return Manager + * @return $this */ public function reset() { @@ -354,7 +352,7 @@ public function reset() /** * Reset CSS assets. * - * @return Manager + * @return $this */ public function resetCss() { @@ -366,7 +364,7 @@ public function resetCss() /** * Reset JavaScript assets. * - * @return Manager + * @return $this */ public function resetJs() { @@ -574,7 +572,7 @@ protected function buildLocalLink($asset) * @theme/directories:assetname.js|css * * @param string $asset the asset string reference - * @return matches|false if there are matches, those regex matches are returned, else return false + * @return array|bool if there are matches, those regex matches are returned, else return false */ protected function assetIsGravPackage($asset) { @@ -623,7 +621,7 @@ public function getJs() * * @param string $directory Relative to $this->public_dir * @param string $pattern (regex) - * @return Manager + * @return $this * @throws Exception */ public function addDir($directory, $pattern = self::DEFAULT_REGEX) @@ -674,7 +672,7 @@ public function addDir($directory, $pattern = self::DEFAULT_REGEX) * Add all CSS assets within $directory (relative to public dir). * * @param string $directory Relative to $this->public_dir - * @return Manager + * @return $this */ public function addDirCss($directory) { @@ -685,7 +683,7 @@ public function addDirCss($directory) * Add all JavaScript assets within $directory. * * @param string $directory Relative to $this->public_dir - * @return Manager + * @return $this */ public function addDirJs($directory) { @@ -713,7 +711,9 @@ protected function rglob($directory, $pattern, $ltrim = null) } /** - * @var Config + * @param $a + * @param $b + * @return mixed */ protected function priorityCompare($a, $b) { From e3da09076879641a96960c961375b93e4a3c2b5f Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 18 Aug 2014 19:05:20 +0300 Subject: [PATCH 24/63] Use similar way to get Grav context across the classes --- index.php | 2 +- system/src/Grav/Common/Assets.php | 6 ++- system/src/Grav/Common/Debugger.php | 4 +- system/src/Grav/Common/Grav.php | 3 ++ system/src/Grav/Common/GravTrait.php | 26 ++++++++++++ system/src/Grav/Common/Page/Collection.php | 37 ++++++++++------- system/src/Grav/Common/Page/Media.php | 5 ++- system/src/Grav/Common/Page/Medium.php | 7 +++- system/src/Grav/Common/Page/Page.php | 47 ++++++++++++---------- system/src/Grav/Common/Page/Pages.php | 9 ++++- 10 files changed, 100 insertions(+), 46 deletions(-) create mode 100644 system/src/Grav/Common/GravTrait.php diff --git a/index.php b/index.php index cf7025a4c2..3d4857ce3f 100644 --- a/index.php +++ b/index.php @@ -18,7 +18,7 @@ $grav = Grav::instance( [ 'loader' => $loader, - 'debugger' => new Debugger(Debugger::PRODUCTION) + 'debugger' => new Debugger(Debugger::DEVELOPMENT) ] ); diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php index 114ace12c2..28a6359baa 100644 --- a/system/src/Grav/Common/Assets.php +++ b/system/src/Grav/Common/Assets.php @@ -23,6 +23,8 @@ class Assets { + use GravTrait; + /** @const Regex to match grav asset shortcodes */ const GRAV_ASSET_REGEX = '/@(plugin|theme)\/(.*?):(.*)/i'; @@ -95,7 +97,7 @@ public function __construct(array $options = array()) public function init() { /** @var Config $config */ - $config = Grav::instance()['config']; + $config = self::$grav['config']; $base_url = trim($config->get('system.base_url_relative')); $theme = $config->get('system.pages.theme'); $asset_config = (array)$config->get('system.assets'); @@ -381,7 +383,7 @@ public function resetJs() protected function pipeline($css = true) { /** @var Cache $cache */ - $cache = Grav::instance()['cache']; + $cache = self::$grav['cache']; $key = '?'.$cache->getKey(); if ($css) { diff --git a/system/src/Grav/Common/Debugger.php b/system/src/Grav/Common/Debugger.php index 4c54144b99..2aff55e97a 100644 --- a/system/src/Grav/Common/Debugger.php +++ b/system/src/Grav/Common/Debugger.php @@ -22,8 +22,10 @@ public function __construct($mode = self::PRODUCTION) public function init() { + $grav = Grav::instance(); + /** @var Config $config */ - $config = Grav::instance()['config']; + $config = $grav['config']; TracyDebugger::$logDirectory = $config->get('system.debugger.log.enabled') ? LOG_DIR : null; TracyDebugger::$maxDepth = $config->get('system.debugger.max_depth'); diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 8499d10225..2f9c30fe83 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -30,6 +30,9 @@ public static function instance(array $values = array()) { if (!self::$instance) { self::$instance = static::load($values); + + GravTrait::setGrav(self::$instance); + } elseif ($values) { $instance = self::$instance; foreach ($values as $key => $value) { diff --git a/system/src/Grav/Common/GravTrait.php b/system/src/Grav/Common/GravTrait.php new file mode 100644 index 0000000000..b182583234 --- /dev/null +++ b/system/src/Grav/Common/GravTrait.php @@ -0,0 +1,26 @@ +params = $params; - $this->pages = $pages ? $pages : Grav::instance()['pages']; + $this->pages = $pages ? $pages : Grav::instance()->offsetGet('pages'); } public function params() @@ -115,9 +115,10 @@ public function order($by, $dir = 'asc', $manual = null) } /** - * Check to see if this item is the first in the collection + * Check to see if this item is the first in the collection. + * * @param string $path - * @return boolean True if item is first + * @return boolean True if item is first. */ public function isFirst($path) { @@ -129,9 +130,10 @@ public function isFirst($path) } /** - * Check to see if this item is the last in the collection + * Check to see if this item is the last in the collection. + * * @param string $path - * @return boolean True if item is last + * @return boolean True if item is last. */ public function isLast($path) { @@ -143,9 +145,10 @@ public function isLast($path) } /** - * Gets the previous sibling based on current position + * Gets the previous sibling based on current position. * - * @return Object the previous item + * @param string $path + * @return Page The previous item. */ public function prevSibling($path) { @@ -153,9 +156,10 @@ public function prevSibling($path) } /** - * Gets the next sibling based on current position + * Gets the next sibling based on current position. * - * @return Object the next item + * @param string $path + * @return Page The next item. */ public function nextSibling($path) { @@ -163,9 +167,11 @@ public function nextSibling($path) } /** - * Returns the adjacent sibling based on a direction + * Returns the adjacent sibling based on a direction. + * + * @param string $path * @param integer $direction either -1 or +1 - * @return Object the sibling item + * @return Page The sibling item. */ public function adjacentSibling($path, $direction = 1) { @@ -178,11 +184,12 @@ public function adjacentSibling($path, $direction = 1) } /** - * Returns the item in the current position - * @param String $path the path the item - * @return Object item in the array the the current position + * Returns the item in the current position. + * + * @param string $path the path the item + * @return Page Item in the array the the current position. */ public function currentPosition($path) { - return array_search($path,array_keys($this->items)); + return array_search($path, array_keys($this->items)); } } diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index 3760f14c91..801055a51d 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -4,6 +4,7 @@ use Grav\Common\Getters; use Grav\Common\Grav; use Grav\Common\Config; +use Grav\Common\GravTrait; /** * Media is a holder object that contains references to the media of page. This object is created and @@ -14,6 +15,8 @@ */ class Media extends Getters { + use GravTrait; + protected $gettersVariable = 'instances'; protected $path; @@ -75,7 +78,7 @@ public function get($filename, $create = false) $basename = implode('.', $parts); /** @var Config $config */ - $config = Grav::instance()['config']; + $config = self::$grav['config']; // Check if medium type has been configured. $params = $config->get("media.{$ext}"); diff --git a/system/src/Grav/Common/Page/Medium.php b/system/src/Grav/Common/Page/Medium.php index 6164728682..7cd97ccb6d 100644 --- a/system/src/Grav/Common/Page/Medium.php +++ b/system/src/Grav/Common/Page/Medium.php @@ -6,6 +6,7 @@ use Grav\Common\Data\Data; use Grav\Common\Filesystem\File\Yaml; use Grav\Common\Grav; +use Grav\Common\GravTrait; use Gregwar\Image\Image as ImageFile; /** @@ -34,6 +35,8 @@ */ class Medium extends Data { + use GravTrait; + /** * @var string */ @@ -97,7 +100,7 @@ public function __toString() public function url() { /** @var Config $config */ - $config = Grav::instance()['config']; + $config = self::$grav['config']; if ($this->image) { $output = $this->image->cacheFile($this->type, $this->quality); @@ -174,7 +177,7 @@ public function html($title = null, $class = null, $type = null, $quality = 80) if ($this->linkTarget) { /** @var Config $config */ - $config = Grav::instance()['config']; + $config = self::$grav['config']; $output = 'linkAttributes. ' class="'. $class . '">' . $output . ''; diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 44fd908f4b..9685bdd462 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -2,6 +2,7 @@ namespace Grav\Common\Page; use \Grav\Common\Config; +use Grav\Common\GravTrait; use \Grav\Common\Utils; use \Grav\Common\Cache; use \Grav\Common\Twig; @@ -24,6 +25,8 @@ */ class Page { + use GravTrait; + /** * @var string Filename. Leave as null if page is folder. */ @@ -83,7 +86,7 @@ class Page public function __construct($array = array()) { /** @var Config $config */ - $config = Grav::instance()['config']; + $config = self::$grav['config']; $this->routable = true; $this->taxonomy = array(); @@ -230,7 +233,7 @@ public function summary($size = null) // Return calculated summary based on setting in site config file /** @var Config $config */ - $config = Grav::instance()['config']; + $config = self::$grav['config']; if (!$size && $config->get('site.summary.size')) { $size = $config->get('site.summary.size'); } @@ -270,7 +273,7 @@ public function content($var = null) // Load cached content /** @var Cache $cache */ - $cache = Grav::instance()['cache']; + $cache = self::$grav['cache']; $cache_id = md5('page'.$this->id()); $content = $cache->fetch($cache_id); @@ -296,7 +299,7 @@ public function content($var = null) // Do we need to process twig this time? if ($update_cache || $process_twig) { /** @var Twig $twig */ - $twig = Grav::instance()['twig']; + $twig = self::$grav['twig']; $content = $twig->processPage($this, $content); } } @@ -464,7 +467,7 @@ public function copy($parent) public function blueprints() { /** @var Pages $pages */ - $pages = Grav::instance()['pages']; + $pages = self::$grav['pages']; return $pages->blueprints($this->template()); } @@ -543,7 +546,7 @@ public function toJson() public function media($var = null) { /** @var Cache $cache */ - $cache = Grav::instance()['cache']; + $cache = self::$grav['cache']; if ($var) { $this->media = $var; @@ -761,7 +764,7 @@ public function link($include_host = false) public function url($include_host = false) { /** @var Uri $uri */ - $uri = Grav::instance()['uri']; + $uri = self::$grav['uri']; $rootUrl = $uri->rootUrl($include_host); $url = $rootUrl.'/'.trim($this->route(), '/'); @@ -957,7 +960,7 @@ public function maxCount($var = null) } if (empty($this->max_count)) { /** @var Config $config */ - $config = Grav::instance()['config']; + $config = self::$grav['config']; $this->max_count = (int) $config->get('system.pages.list.count'); } return $this->max_count; @@ -1034,7 +1037,7 @@ public function parent(Page $var = null) } /** @var Pages $pages */ - $pages = Grav::instance()['pages']; + $pages = self::$grav['pages']; return $pages->get($this->parent); } @@ -1047,7 +1050,7 @@ public function parent(Page $var = null) public function children() { /** @var Pages $pages */ - $pages = Grav::instance()['pages']; + $pages = self::$grav['pages']; return $pages->children($this->path()); } @@ -1127,7 +1130,7 @@ public function nth($key) public function isFirst() { /** @var Pages $pages */ - $pages = Grav::instance()['pages']; + $pages = self::$grav['pages']; $parent = $pages->get($this->parent); if ($this->path() == array_values($parent->items)[0]) { @@ -1145,7 +1148,7 @@ public function isFirst() public function isLast() { /** @var Pages $pages */ - $pages = Grav::instance()['pages']; + $pages = self::$grav['pages']; $parent = $pages->get($this->parent); if ($this->path() == array_values($parent->items)[count($parent->items)-1]) { @@ -1184,7 +1187,7 @@ public function nextSibling() public function adjacentSibling($direction = 1) { /** @var Pages $pages */ - $pages = Grav::instance()['pages']; + $pages = self::$grav['pages']; $parent = $pages->get($this->parent); $current = $this->slug(); @@ -1203,7 +1206,7 @@ public function adjacentSibling($direction = 1) public function active() { /** @var Uri $uri */ - $uri = Grav::instance()['uri']; + $uri = self::$grav['uri']; if ($this->url() == $uri->url()) { return true; } @@ -1218,7 +1221,7 @@ public function active() */ public function activeChild() { - $uri = Grav::instance()['uri']; + $uri = self::$grav['uri']; if (!$this->home() && (strpos($uri->url(), $this->url()) !== false)) { return true; } @@ -1259,7 +1262,7 @@ public function root() public function find($url) { /** @var Pages $pages */ - $pages = Grav::instance()['pages']; + $pages = self::$grav['pages']; return $pages->dispatch($url); } @@ -1290,9 +1293,9 @@ public function collection($params = 'content') // TODO: MOVE THIS INTO SOMEWHERE ELSE? /** @var Uri $uri */ - $uri = Grav::instance()['uri']; + $uri = self::$grav['uri']; /** @var Config $config */ - $config = Grav::instance()['config']; + $config = self::$grav['config']; foreach ((array) $config->get('site.taxonomies') as $taxonomy) { if ($uri->param($taxonomy)) { @@ -1324,7 +1327,7 @@ public function collection($params = 'content') } /** @var Grav $grav */ - $grav = Grav::instance()['grav']; + $grav = self::$grav['grav']; // New Custom event to handle things like pagination. $grav->fireEvent('onAfterCollectionProcessed', $collection); @@ -1392,7 +1395,7 @@ protected function evaluate($value) // @taxonomy: { category: [ blog, featured ], level: 1 } /** @var Taxonomy $taxonomy_map */ - $taxonomy_map = Grav::instance()['taxonomy']; + $taxonomy_map = self::$grav['taxonomy']; if (!empty($parts)) { $params = [implode('.', $parts) => $params]; @@ -1508,7 +1511,7 @@ protected function rawContent($content) protected function parseMarkdownContent($content) { /** @var Config $config */ - $config = Grav::instance()['config']; + $config = self::$grav['config']; if ($config->get('system.pages.markdown_extra')) { $parsedown = new \ParsedownExtra(); } else { @@ -1547,7 +1550,7 @@ protected function doRelocation($reorder) // Do reordering. if ($reorder && $this->order() != $this->_original->order()) { /** @var Pages $pages */ - $pages = Grav::instance()['pages']; + $pages = self::$grav['pages']; $parent = $this->parent(); diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index ef406cca16..a3e29e23f5 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -313,8 +313,10 @@ public function getList(Page $current = null, $level = 0) */ static public function types() { + $grav = Grav::instance(); + /** @var Config $config */ - $config = Grav::instance()['config']; + $config = $grav['config']; $blueprints = new Data\Blueprints(THEMES_DIR . $config->get('system.pages.theme') . '/blueprints/'); @@ -328,8 +330,11 @@ static public function types() */ static public function parents() { + $grav = Grav::instance(); + /** @var Pages $pages */ - $pages = Grav::instance()['pages']; + $pages = $grav['pages']; + return $pages->getList(); } From 53cec9b62082ff90e5fc345510b6704540d5ab3d Mon Sep 17 00:00:00 2001 From: Djamil Legato Date: Mon, 18 Aug 2014 09:56:26 -0700 Subject: [PATCH 25/63] Fixed setup command in combination of symlink not linking properly directories. --- system/src/Grav/Console/SetupCommand.php | 26 ++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/system/src/Grav/Console/SetupCommand.php b/system/src/Grav/Console/SetupCommand.php index 9ca38dc47c..7e7ab3a51e 100644 --- a/system/src/Grav/Console/SetupCommand.php +++ b/system/src/Grav/Console/SetupCommand.php @@ -150,8 +150,13 @@ private function symlink($output) $to = $this->destination . $target; $output->writeln(' ' . $source . ' -> ' . $to); - @unlink ($to); - symlink ($from, $to); + + if (is_dir($to)) { + $this->rmdir($to); + } else { + @unlink($to); + } + symlink($from, $to); } } @@ -271,4 +276,21 @@ private function rcopy($src, $dest){ } } } + + private function rmdir($dir) { + $files = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::CHILD_FIRST + ); + + foreach ($files as $fileinfo) { + if ($fileinfo->isDir()) { + if (false === rmdir($fileinfo->getRealPath())) return false; + } else { + if (false === unlink($fileinfo->getRealPath())) return false; + } + } + + return rmdir($dir); + } } From a42144c3f77bb55df186888aad009eec6c99fcee Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 18 Aug 2014 21:24:32 +0300 Subject: [PATCH 26/63] Implement stream wrappers --- system/config/streams.yaml | 6 + system/src/Grav/Common/Grav.php | 7 + system/src/Grav/Common/Plugins.php | 11 +- .../Common/Service/StreamsServiceProvider.php | 61 +++++ .../Component/Filesystem/ResourceLocator.php | 109 ++++++++ .../StreamWrapper/ReadOnlyStream.php | 71 +++++ .../Filesystem/StreamWrapper/Stream.php | 232 ++++++++++++++++ .../StreamWrapper/StreamInterface.php | 251 ++++++++++++++++++ 8 files changed, 742 insertions(+), 6 deletions(-) create mode 100644 system/config/streams.yaml create mode 100644 system/src/Grav/Common/Service/StreamsServiceProvider.php create mode 100644 system/src/Grav/Component/Filesystem/ResourceLocator.php create mode 100644 system/src/Grav/Component/Filesystem/StreamWrapper/ReadOnlyStream.php create mode 100644 system/src/Grav/Component/Filesystem/StreamWrapper/Stream.php create mode 100644 system/src/Grav/Component/Filesystem/StreamWrapper/StreamInterface.php diff --git a/system/config/streams.yaml b/system/config/streams.yaml new file mode 100644 index 0000000000..8c4f239d3b --- /dev/null +++ b/system/config/streams.yaml @@ -0,0 +1,6 @@ +schemes: + plugin: + type: ReadOnlyStream + paths: + - user/plugins + - system/plugins diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 2f9c30fe83..1de34b00eb 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -1,7 +1,9 @@ register(new StreamsServiceProvider); + return $container; } public function process() { + // Initialize stream wrappers. + $this['locator']; + $this['plugins']->init(); $this->fireEvent('onAfterInitPlugins'); diff --git a/system/src/Grav/Common/Plugins.php b/system/src/Grav/Common/Plugins.php index 92db564610..50278e10b7 100644 --- a/system/src/Grav/Common/Plugins.php +++ b/system/src/Grav/Common/Plugins.php @@ -37,8 +37,7 @@ public function init() continue; } - $folder = PLUGINS_DIR . $plugin; - $filePath = $folder . DS . $plugin . PLUGIN_EXT; + $filePath = 'plugin://' . $plugin . DS . $plugin . PLUGIN_EXT; if (!is_file($filePath)) { throw new \RuntimeException(sprintf("Plugin '%s' enabled but not found!", $filePath, $plugin)); } @@ -72,7 +71,7 @@ public function add($plugin) static public function all() { $list = array(); - $iterator = new \DirectoryIterator(PLUGINS_DIR); + $iterator = new \DirectoryIterator('plugin://'); /** @var \DirectoryIterator $directory */ foreach ($iterator as $directory) { @@ -91,16 +90,16 @@ static public function all() static public function get($type) { - $blueprints = new Data\Blueprints(PLUGINS_DIR . $type); + $blueprints = new Data\Blueprints('plugin://' . $type); $blueprint = $blueprints->get('blueprints'); $blueprint->name = $type; // Load default configuration. - $file = File\Yaml::instance(PLUGINS_DIR . "{$type}/{$type}" . YAML_EXT); + $file = File\Yaml::instance('plugin://' . "{$type}/{$type}" . YAML_EXT); $obj = new Data\Data($file->content(), $blueprint); // Override with user configuration. - $file = File\Yaml::instance(USER_DIR . "config/plugins/{$type}" . YAML_EXT); + $file = File\Yaml::instance('plugin://' . "config/plugins/{$type}" . YAML_EXT); $obj->merge($file->content()); // Save configuration always to user/config. diff --git a/system/src/Grav/Common/Service/StreamsServiceProvider.php b/system/src/Grav/Common/Service/StreamsServiceProvider.php new file mode 100644 index 0000000000..f29ba2a30d --- /dev/null +++ b/system/src/Grav/Common/Service/StreamsServiceProvider.php @@ -0,0 +1,61 @@ +init($c, $locator); + + return $locator; + }; + } + + protected function init(Container $container, ResourceLocator $locator) + { + $schemes = $container['config']->get('streams.schemes'); + + if (!$schemes) { + return; + } + + // Set locator to both streams. + Stream::setLocator($locator); + ReadOnlyStream::setLocator($locator); + + $registered = stream_get_wrappers(); + + foreach ($schemes as $scheme => $config) { + if (isset($config['paths'])) { + $locator->addPath($scheme, '', $config['paths']); + } + if (isset($config['prefixes'])) { + foreach ($config['prefixes'] as $prefix => $paths) { + $locator->addPath($scheme, $prefix, $paths); + } + } + + if (in_array($scheme, $registered)) { + stream_wrapper_unregister($scheme); + } + $type = !empty($config['type']) ? $config['type'] : 'ReadOnlyStream'; + if ($type[0] != '\\') { + $type = '\\Grav\\Component\\Filesystem\\StreamWrapper\\' . $type; + } + + if (!stream_wrapper_register($scheme, $type)) { + throw new \InvalidArgumentException("Stream '{$type}' could not be initialized."); + } + } + } +} diff --git a/system/src/Grav/Component/Filesystem/ResourceLocator.php b/system/src/Grav/Component/Filesystem/ResourceLocator.php new file mode 100644 index 0000000000..95c202cf34 --- /dev/null +++ b/system/src/Grav/Component/Filesystem/ResourceLocator.php @@ -0,0 +1,109 @@ +schemes[$scheme][$prefix])) { + $list = array_merge($list, $this->schemes[$scheme][$prefix]); + } + + $this->schemes[$scheme][$prefix] = $list; + + // Sort in reverse order to get longer prefixes to be matched first. + krsort($this->schemes[$scheme]); + } + + /** + * @param $uri + * @return string|bool + */ + public function __invoke($uri) + { + return $this->find($uri, false); + } + + /** + * @param string $uri + * @return string|bool + */ + public function findResource($uri) + { + return $this->find($uri, false); + } + + /** + * @param string $uri + * @return array + */ + public function findResources($uri) + { + return $this->find($uri, true); + } + + /** + * @param string $uri + * @param bool $array + * @throws \InvalidArgumentException + * @return array|string|bool + */ + protected function find($uri, $array) + { + $segments = explode('://', $uri, 2); + $file = array_pop($segments); + $scheme = array_pop($segments); + + if (!$scheme) { + $scheme = 'file'; + } + + if (!$file || $uri[0] == ':') { + throw new \InvalidArgumentException('Invalid resource URI'); + } + if (!isset($this->schemes[$scheme])) { + throw new \InvalidArgumentException("Invalid resource {$scheme}://"); + } + + $paths = $array ? [] : false; + foreach ($this->schemes[$scheme] as $prefix => $paths) { + if ($prefix && strpos($file, $prefix) !== 0) { + continue; + } + + foreach ($paths as $path) { + $filename = ROOT_DIR . '/' . $path . '/' . ltrim(substr($file, strlen($prefix)), '\/'); + + if (file_exists($filename)) { + if (!$array) { + return $filename; + } + $paths[] = $filename; + } + } + } + + return $paths; + } +} diff --git a/system/src/Grav/Component/Filesystem/StreamWrapper/ReadOnlyStream.php b/system/src/Grav/Component/Filesystem/StreamWrapper/ReadOnlyStream.php new file mode 100644 index 0000000000..dc1e88c656 --- /dev/null +++ b/system/src/Grav/Component/Filesystem/StreamWrapper/ReadOnlyStream.php @@ -0,0 +1,71 @@ +getPath($uri); + + if (!$path) { + return false; + } + + $this->handle = ($options & STREAM_REPORT_ERRORS) ? fopen($path, $mode) : @fopen($path, $mode); + + return (bool) $this->handle; + } + + public function stream_lock($operation) + { + // Disallow exclusive lock or non-blocking lock requests + if (!in_array($operation, [LOCK_SH, LOCK_UN, LOCK_SH | LOCK_NB])) { + trigger_error( + 'stream_lock() exclusive lock operations not supported for read-only stream wrappers', + E_USER_WARNING + ); + return false; + } + + return flock($this->handle, $operation); + } + + public function stream_write($data) + { + throw new \BadMethodCallException('stream_write() not supported for read-only stream wrappers'); + } + + public function unlink($uri) + { + throw new \BadMethodCallException('unlink() not supported for read-only stream wrappers'); + } + + public function rename($from_uri, $to_uri) + { + throw new \BadMethodCallException('rename() not supported for read-only stream wrappers'); + } + + public function mkdir($uri, $mode, $options) + { + throw new \BadMethodCallException('mkdir() not supported for read-only stream wrappers'); + } + + public function rmdir($uri, $options) + { + throw new \BadMethodCallException('rmdir() not supported for read-only stream wrappers'); + } +} diff --git a/system/src/Grav/Component/Filesystem/StreamWrapper/Stream.php b/system/src/Grav/Component/Filesystem/StreamWrapper/Stream.php new file mode 100644 index 0000000000..a1307bf4f5 --- /dev/null +++ b/system/src/Grav/Component/Filesystem/StreamWrapper/Stream.php @@ -0,0 +1,232 @@ +getPath($uri, $mode); + + if (!$path) { + return false; + } + + $this->handle = ($options & STREAM_REPORT_ERRORS) ? fopen($path, $mode) : @fopen($path, $mode); + + return (bool) $this->handle; + } + + public function stream_close() + { + return fclose($this->handle); + } + + public function stream_lock($operation) + { + if (in_array($operation, [LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB])) { + return flock($this->handle, $operation); + } + + return false; + } + + public function stream_metadata($uri, $option, $value) + { + switch ($option) { + case STREAM_META_TOUCH: + list ($time, $atime) = $value; + return touch($uri, $time, $atime); + + case STREAM_META_OWNER_NAME: + case STREAM_META_OWNER: + return chown($uri, $value); + + case STREAM_META_GROUP_NAME: + case STREAM_META_GROUP: + return chgrp($uri, $value); + + case STREAM_META_ACCESS: + return chmod($uri, $value); + } + + return false; + } + + public function stream_read($count) + { + return fread($this->handle, $count); + } + + public function stream_write($data) + { + return fwrite($this->handle, $data); + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_seek($offset, $whence) + { + // fseek returns 0 on success and -1 on a failure. + return !fseek($this->handle, $offset, $whence); + } + + public function stream_flush() + { + return fflush($this->handle); + } + + public function stream_tell() + { + return ftell($this->handle); + } + + public function stream_stat() + { + return fstat($this->handle); + } + + public function unlink($uri) + { + $path = $this->getPath($uri); + + if (!$path) { + return false; + } + + return unlink($path); + } + + public function rename($fromUri, $toUri) + { + $fromPath = $this->getPath($fromUri); + $toPath = $this->getPath($toUri); + + if (!($fromPath && $toPath)) { + return false; + } + + return rename($fromPath, $toPath); + } + + public function mkdir($uri, $mode, $options) + { + $recursive = (bool) ($options & STREAM_MKDIR_RECURSIVE); + $path = $this->getPath($uri, $recursive ? $mode : null); + + if (!$path) { + return false; + } + + return ($options & STREAM_REPORT_ERRORS) ? mkdir($path, $mode, $recursive) : @mkdir($path, $mode, $recursive); + } + + public function rmdir($uri, $options) + { + $path = $this->getPath($uri); + + if (!$path) { + return false; + } + + return ($options & STREAM_REPORT_ERRORS) ? rmdir($path) : @rmdir($path); + } + + public function url_stat($uri, $flags) + { + $path = $this->getPath($uri); + + if (!$path) { + return false; + } + + // Suppress warnings if requested or if the file or directory does not + // exist. This is consistent with PHP's plain filesystem stream wrapper. + return ($flags & STREAM_URL_STAT_QUIET || !file_exists($path)) ? @stat($path) : stat($path); + } + + public function dir_opendir($uri, $options) + { + $path = $this->getPath($uri); + + if (!$path) { + return false; + } + + $this->handle = opendir($path); + + return (bool) $this->handle; + } + + public function dir_readdir() + { + return readdir($this->handle); + } + + public function dir_rewinddir() + { + rewinddir($this->handle); + + return true; + } + + public function dir_closedir() + { + closedir($this->handle); + + return true; + } + + protected function getPath($uri, $mode = null) + { + $path = $this->findPath($uri); + + if ($mode == null || !$path || file_exists($path)) { + return $path; + } + + if ($mode[0] == 'r') { + return false; + } + + // We are either opening a file or creating directory. + list($scheme, $target) = explode('://', $uri, 2); + + $path = $this->findPath($scheme . '://' . dirname($target)); + + if (!$path) { + return false; + } + + return $path . '/' . basename($uri); + } + + protected function findPath($uri) + { + return static::$locator ? static::$locator->findResource($uri) : false; + } +} diff --git a/system/src/Grav/Component/Filesystem/StreamWrapper/StreamInterface.php b/system/src/Grav/Component/Filesystem/StreamWrapper/StreamInterface.php new file mode 100644 index 0000000000..01b9bff298 --- /dev/null +++ b/system/src/Grav/Component/Filesystem/StreamWrapper/StreamInterface.php @@ -0,0 +1,251 @@ + Date: Mon, 18 Aug 2014 22:27:27 +0300 Subject: [PATCH 27/63] Add a few stream wrappers --- index.php | 2 +- system/config/streams.yaml | 30 ++++++++++++++++++++++++++++++ system/defines.php | 1 - 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index 3d4857ce3f..cf7025a4c2 100644 --- a/index.php +++ b/index.php @@ -18,7 +18,7 @@ $grav = Grav::instance( [ 'loader' => $loader, - 'debugger' => new Debugger(Debugger::DEVELOPMENT) + 'debugger' => new Debugger(Debugger::PRODUCTION) ] ); diff --git a/system/config/streams.yaml b/system/config/streams.yaml index 8c4f239d3b..1ea6f2acda 100644 --- a/system/config/streams.yaml +++ b/system/config/streams.yaml @@ -4,3 +4,33 @@ schemes: paths: - user/plugins - system/plugins + +# asset: +# type: ReadOnlyStream +# paths: +# - assets + +# cache: +# type: ReadOnlyStream +# paths: +# - cache + +# log: +# type: ReadOnlyStream +# paths: +# - logs + + page: + type: ReadOnlyStream + paths: + - user/pages + + account: + type: ReadOnlyStream + paths: + - user/accounts + + data: + type: ReadOnlyStream + paths: + - user/data diff --git a/system/defines.php b/system/defines.php index 84f62770d0..58cd757c7f 100644 --- a/system/defines.php +++ b/system/defines.php @@ -21,7 +21,6 @@ define('ACCOUNTS_DIR', USER_DIR .'accounts/'); define('DATA_DIR', USER_DIR .'data/'); define('PAGES_DIR', USER_DIR .'pages/'); -define('BLOCKS_DIR', USER_DIR .'blocks/'); define('PLUGINS_DIR', USER_DIR .'plugins/'); define('THEMES_DIR', USER_DIR .'themes/'); From 620c204128fa072d0df159a9d8c941edea17831f Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Mon, 18 Aug 2014 17:09:13 -0600 Subject: [PATCH 28/63] extra Tracy use in Assets --- system/src/Grav/Common/Assets.php | 1 - 1 file changed, 1 deletion(-) diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php index 28a6359baa..4b0d00f235 100644 --- a/system/src/Grav/Common/Assets.php +++ b/system/src/Grav/Common/Assets.php @@ -1,7 +1,6 @@ Date: Mon, 18 Aug 2014 17:12:32 -0600 Subject: [PATCH 29/63] #15 Workaround for apache style userdir (~username) routing --- system/src/Grav/Common/Uri.php | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php index 1db8c1ac5e..af7cad26ae 100644 --- a/system/src/Grav/Common/Uri.php +++ b/system/src/Grav/Common/Uri.php @@ -26,21 +26,29 @@ class Uri */ public function __construct() { + $base = 'http://'; - $uri = $_SERVER["REQUEST_URI"]; + $uri = $_SERVER['REQUEST_URI']; + $root_path = rtrim(substr($_SERVER['PHP_SELF'], 0, strpos($_SERVER['PHP_SELF'], 'index.php')), '/'); + - if (isset($_SERVER["HTTPS"])) { - $base = (@$_SERVER["HTTPS"] == "on") ? "https://" : "http://"; + if (isset($_SERVER['HTTPS'])) { + $base = (@$_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://'; } - $base .= $_SERVER["SERVER_NAME"]; + $base .= $_SERVER['SERVER_NAME']; + + if ($_SERVER['SERVER_PORT'] != '80' && $_SERVER['SERVER_PORT'] != '443') { + $base .= ":".$_SERVER['SERVER_PORT']; + } - if ($_SERVER["SERVER_PORT"] != "80" && $_SERVER["SERVER_PORT"] != "443") { - $base .= ":".$_SERVER["SERVER_PORT"]; + // check if userdir in the path and workaround PHP bug with PHP_SELF + if (strpos($_SERVER['REQUEST_URI'], '/~') !== false && strpos($_SERVER['PHP_SELF'], '/~') === false) { + $root_path = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '/', 1)) . $root_path; } $this->base = $base; - $this->root = $base . rtrim(substr($_SERVER['PHP_SELF'], 0, strpos($_SERVER['PHP_SELF'], 'index.php')), '/'); + $this->root = $base . $root_path; $this->url = $base . $uri; $this->init(); From 19b23746dc9d1885c35a7590de2db439911a9f2e Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Mon, 18 Aug 2014 17:12:47 -0600 Subject: [PATCH 30/63] minor trim fix --- system/src/Grav/Common/Assets.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php index 4b0d00f235..b6266ed75a 100644 --- a/system/src/Grav/Common/Assets.php +++ b/system/src/Grav/Common/Assets.php @@ -98,7 +98,7 @@ public function init() /** @var Config $config */ $config = self::$grav['config']; $base_url = trim($config->get('system.base_url_relative')); - $theme = $config->get('system.pages.theme'); + $theme = trim($config->get('system.pages.theme')); $asset_config = (array)$config->get('system.assets'); $this->config($asset_config); From dcc4335f8e5042be4427dca2270cc8af8578a1de Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 19 Aug 2014 09:56:18 +0300 Subject: [PATCH 31/63] Fix regression: plugins not firing --- system/src/Grav/Common/Plugins.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/src/Grav/Common/Plugins.php b/system/src/Grav/Common/Plugins.php index 92db564610..cf44693b44 100644 --- a/system/src/Grav/Common/Plugins.php +++ b/system/src/Grav/Common/Plugins.php @@ -51,10 +51,10 @@ public function init() throw new \RuntimeException(sprintf("Plugin '%s' class not found!", $plugin)); } - $instances[$pluginClass] = new $pluginClass($config); + $this->add(new $pluginClass($config)); } - return $instances; + return $this->items; } public function add($plugin) From a85c2638e48f9d4d4da83ab57895c9fad456cf30 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 19 Aug 2014 18:45:42 +0300 Subject: [PATCH 32/63] Fix #17: Use Symfony EventDispatcher --- composer.json | 1 + index.php | 2 +- system/src/Grav/Common/Grav.php | 59 ++++++++----------- system/src/Grav/Common/Page/Page.php | 25 ++++---- system/src/Grav/Common/Page/Pages.php | 21 +++---- system/src/Grav/Common/Plugin.php | 55 ++++++++++++++++- system/src/Grav/Common/Plugins.php | 16 ++++- system/src/Grav/Common/Theme.php | 2 +- system/src/Grav/Common/Themes.php | 9 +-- .../Component/ArrayTraits/ArrayAccess.php | 46 +++++++++++++++ .../Component/ArrayTraits/Constructor.php | 21 +++++++ .../Grav/Component/ArrayTraits/Countable.php | 19 ++++++ .../Grav/Component/ArrayTraits/Getters.php | 50 ++++++++++++++++ .../Grav/Component/EventDispatcher/Event.php | 15 +++++ .../EventDispatcher/EventDispatcher.php | 16 +++++ .../EventSubscriberInterface.php | 6 ++ 16 files changed, 297 insertions(+), 66 deletions(-) create mode 100644 system/src/Grav/Component/ArrayTraits/ArrayAccess.php create mode 100644 system/src/Grav/Component/ArrayTraits/Constructor.php create mode 100644 system/src/Grav/Component/ArrayTraits/Countable.php create mode 100644 system/src/Grav/Component/ArrayTraits/Getters.php create mode 100644 system/src/Grav/Component/EventDispatcher/Event.php create mode 100644 system/src/Grav/Component/EventDispatcher/EventDispatcher.php create mode 100644 system/src/Grav/Component/EventDispatcher/EventSubscriberInterface.php diff --git a/composer.json b/composer.json index 3e9f784617..5b29130064 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "erusev/parsedown-extra": "dev-master", "symfony/yaml": "2.5.*@dev", "symfony/console": "2.5.*@dev", + "symfony/event-dispatcher": "2.5.*@dev", "doctrine/cache": "1.4.*@dev", "tracy/tracy": "dev-master", "gregwar/image": "dev-master", diff --git a/index.php b/index.php index 3d4857ce3f..861749219b 100644 --- a/index.php +++ b/index.php @@ -30,7 +30,7 @@ $grav->process(); } catch (\Exception $e) { - $grav->fireEvent('onFatalException', $e); + $grav->fireEvent('onFatalException'); throw $e; } diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 2f9c30fe83..6ac395e810 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -2,6 +2,8 @@ namespace Grav\Common; use Grav\Component\DI\Container; +use Grav\Component\EventDispatcher\Event; +use Grav\Component\EventDispatcher\EventDispatcher; /** * Grav @@ -51,6 +53,9 @@ protected static function load(array $values) $container['grav'] = $container; + $container['events'] = function ($c) { + return new EventDispatcher; + }; $container['uri'] = function ($c) { return new Uri($c); }; @@ -79,7 +84,18 @@ protected static function load(array $values) return new Assets(); }; $container['page'] = function ($c) { - return $c['pages']->dispatch($c['uri']->route()); + $page = $c['pages']->dispatch($c['uri']->route()); + + if (!$page || !$page->routable()) { + $event = $c->fireEvent('onPageNotFound'); + + if (isset($event->page)) { + $page = $event->page; + } else { + throw new \RuntimeException('Page Not Found', 404); + } + } + return $page; }; $container['output'] = function ($c) { return $c['twig']->processSite($c['uri']->extension()); @@ -108,11 +124,6 @@ public function process() $this->fireEvent('onAfterGetPage'); - // If there's no page, throw exception - if (!$this['page']) { - throw new \RuntimeException('Page Not Found', 404); - } - // Process whole page as required $this->output = $this['output']; @@ -172,34 +183,16 @@ public function header() } /** - * Processes any hooks and runs them. + * Fires an event with optional parameters. + * + * @param string $eventName + * @param Event $event + * @return Event */ - public function fireEvent() + public function fireEvent($eventName, Event $event = null) { - $args = func_get_args(); - $hook_id = array_shift($args); - $no_timing_hooks = array('onAfterPageProcessed','onAfterFolderProcessed', 'onAfterCollectionProcessed'); - - /** @var Plugins $plugins */ - $plugins = $this['plugins']; - - if (!empty($plugins)) { - foreach ($plugins as $plugin) { - if (is_callable(array($plugin, $hook_id))) { - call_user_func_array(array($plugin, $hook_id), $args); - } - } - } - - /** @var Config $config */ - $config = $this['config']; - - if ($config && $config->get('system.debugger.log.timing') && !in_array($hook_id, $no_timing_hooks)) { - /** @var Debugger $debugger */ - $debugger = isset($this['debugger']) ? $this['debugger'] : null; - if ($debugger) { - $debugger->log($hook_id.': %f ms'); - } - } + /** @var EventDispatcher $events */ + $events = $this['events']; + return $events->dispatch($eventName, $event); } } diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 9685bdd462..dfced9a75a 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -1,18 +1,19 @@ fireEvent('onAfterCollectionProcessed', $collection); + $grav->fireEvent('onAfterCollectionProcessed', new Event(['collection' => $collection])); $params = $collection->params(); diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index a3e29e23f5..f853b97ff3 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -1,13 +1,14 @@ initialized) { - $this->grav->fireEvent('onCreateBlueprint', $blueprint); + $this->grav->fireEvent('onCreateBlueprint', new Event(['blueprint' => $blueprint])); $blueprint->initialized = true; } @@ -420,7 +421,7 @@ protected function recurse($directory = PAGES_DIR, Page &$parent = null) $page->init($file); if ($config->get('system.pages.events.page')) { - $this->grav->fireEvent('onAfterPageProcessed', $page); + $this->grav->fireEvent('onAfterPageProcessed', new Event(['page' => $page])); } } elseif ($file->isDir() && !$file->isDot()) { @@ -447,7 +448,7 @@ protected function recurse($directory = PAGES_DIR, Page &$parent = null) $this->lastModified($file->getMTime()); if ($config->get('system.pages.events.page')) { - $this->grav->fireEvent('onAfterFolderProcessed', $page); + $this->grav->fireEvent('onAfterFolderProcessed', new Event(['page' => $page])); } } } diff --git a/system/src/Grav/Common/Plugin.php b/system/src/Grav/Common/Plugin.php index fb25dccdbf..0371cd41ac 100644 --- a/system/src/Grav/Common/Plugin.php +++ b/system/src/Grav/Common/Plugin.php @@ -1,26 +1,75 @@ grav = $grav; $this->config = $config; } + + /** + * @param array $events + */ + protected function enable(array $events) + { + /** @var EventDispatcher $dispatcher */ + $dispatcher = $this->grav['events']; + + foreach ($events as $eventName => $params) { + if (is_string($params)) { + $dispatcher->addListener($eventName, array($this, $params)); + } elseif (is_string($params[0])) { + $dispatcher->addListener($eventName, array($this, $params[0]), isset($params[1]) ? $params[1] : 0); + } else { + foreach ($params as $listener) { + $dispatcher->addListener($eventName, array($this, $listener[0]), isset($listener[1]) ? $listener[1] : 0); + } + } + } + } } diff --git a/system/src/Grav/Common/Plugins.php b/system/src/Grav/Common/Plugins.php index cf44693b44..11ce584359 100644 --- a/system/src/Grav/Common/Plugins.php +++ b/system/src/Grav/Common/Plugins.php @@ -2,6 +2,8 @@ namespace Grav\Common; use Grav\Common\Filesystem\File; +use Grav\Component\EventDispatcher\EventDispatcher; +use Grav\Component\EventDispatcher\EventSubscriberInterface; /** * The Plugins object holds an array of all the plugin objects that @@ -30,7 +32,9 @@ public function init() $config = $this->grav['config']; $plugins = (array) $config->get('plugins'); - $instances = ['theme' => $this->grav['themes']->load()]; + /** @var EventDispatcher $events */ + $events = $this->grav['events']; + foreach ($plugins as $plugin => $data) { if (empty($data['enabled'])) { // Only load enabled plugins. @@ -51,7 +55,15 @@ public function init() throw new \RuntimeException(sprintf("Plugin '%s' class not found!", $plugin)); } - $this->add(new $pluginClass($config)); + $instance = new $pluginClass($this->grav, $config); + if ($instance instanceof EventSubscriberInterface) { + $events->addSubscriber($instance); + } + } + + $instance = $this->grav['themes']->load(); + if ($instance instanceof EventSubscriberInterface) { + $events->addSubscriber($instance); } return $this->items; diff --git a/system/src/Grav/Common/Theme.php b/system/src/Grav/Common/Theme.php index 31e5cf4778..0b3e170172 100644 --- a/system/src/Grav/Common/Theme.php +++ b/system/src/Grav/Common/Theme.php @@ -1,6 +1,6 @@ grav['config']; + if (!$name) { - /** @var Config $config */ - $config = $this->grav['config']; $name = $config->get('system.pages.theme'); } @@ -100,13 +101,13 @@ public function load($name = null) $className = '\\Grav\\Theme\\' . ucfirst($name); if (class_exists($className)) { - $class = new $className; + $class = new $className($this->grav, $config); } } } if (empty($class)) { - $class = new Theme; + $class = new Theme($this->grav, $config); } return $class; diff --git a/system/src/Grav/Component/ArrayTraits/ArrayAccess.php b/system/src/Grav/Component/ArrayTraits/ArrayAccess.php new file mode 100644 index 0000000000..aacd1c01f9 --- /dev/null +++ b/system/src/Grav/Component/ArrayTraits/ArrayAccess.php @@ -0,0 +1,46 @@ +items[$offset]); + } + + /** + * @param mixed $offset + * @return mixed + */ + public function offsetGet($offset) + { + return isset($this->items[$offset]) ? $this->items[$offset] : null; + } + + /** + * @param mixed $offset + * @param mixed $value + */ + public function offsetSet($offset, $value) + { + $this->items[$offset] = $value; + } + + /** + * @param mixed $offset + */ + public function offsetUnset($offset) + { + unset($this->items[$offset]); + } +} diff --git a/system/src/Grav/Component/ArrayTraits/Constructor.php b/system/src/Grav/Component/ArrayTraits/Constructor.php new file mode 100644 index 0000000000..80779c2fc0 --- /dev/null +++ b/system/src/Grav/Component/ArrayTraits/Constructor.php @@ -0,0 +1,21 @@ +items = $items; + } +} diff --git a/system/src/Grav/Component/ArrayTraits/Countable.php b/system/src/Grav/Component/ArrayTraits/Countable.php new file mode 100644 index 0000000000..10e51410c4 --- /dev/null +++ b/system/src/Grav/Component/ArrayTraits/Countable.php @@ -0,0 +1,19 @@ +items); + } +} diff --git a/system/src/Grav/Component/ArrayTraits/Getters.php b/system/src/Grav/Component/ArrayTraits/Getters.php new file mode 100644 index 0000000000..90da77a248 --- /dev/null +++ b/system/src/Grav/Component/ArrayTraits/Getters.php @@ -0,0 +1,50 @@ +offsetSet($offset, $value); + } + + /** + * Magic getter method + * + * @param mixed $offset Asset name value + * @return mixed Asset value + */ + public function __get($offset) + { + return $this->offsetGet($offset); + } + + /** + * Magic method to determine if the attribute is set + * + * @param mixed $offset Asset name value + * @return boolean True if the value is set + */ + public function __isset($offset) + { + return $this->offsetExists($offset); + } + + /** + * Magic method to unset the attribute + * + * @param mixed $offset The name value to unset + */ + public function __unset($offset) + { + $this->offsetUnset($offset); + } +} diff --git a/system/src/Grav/Component/EventDispatcher/Event.php b/system/src/Grav/Component/EventDispatcher/Event.php new file mode 100644 index 0000000000..ba2ad90752 --- /dev/null +++ b/system/src/Grav/Component/EventDispatcher/Event.php @@ -0,0 +1,15 @@ + Date: Tue, 19 Aug 2014 14:58:47 -0600 Subject: [PATCH 33/63] vendor updates --- system/src/Grav/Console/CleanCommand.php | 11 + vendor/autoload.php | 2 +- vendor/composer/ClassLoader.php | 4 + vendor/composer/autoload_namespaces.php | 1 + vendor/composer/autoload_real.php | 10 +- vendor/composer/installed.json | 155 ++- vendor/pimple/pimple/.gitignore | 3 - vendor/pimple/pimple/.travis.yml | 32 - vendor/pimple/pimple/composer.json | 25 - vendor/pimple/pimple/ext/pimple/.gitignore | 30 - vendor/pimple/pimple/ext/pimple/README.md | 12 - vendor/pimple/pimple/ext/pimple/config.m4 | 63 -- vendor/pimple/pimple/ext/pimple/config.w32 | 13 - vendor/pimple/pimple/ext/pimple/php_pimple.h | 122 --- vendor/pimple/pimple/ext/pimple/pimple.c | 940 ------------------ .../pimple/pimple/ext/pimple/pimple_compat.h | 81 -- .../pimple/pimple/ext/pimple/tests/001.phpt | 45 - .../pimple/pimple/ext/pimple/tests/002.phpt | 15 - .../pimple/pimple/ext/pimple/tests/003.phpt | 16 - .../pimple/pimple/ext/pimple/tests/004.phpt | 30 - .../pimple/pimple/ext/pimple/tests/005.phpt | 27 - .../pimple/pimple/ext/pimple/tests/006.phpt | 51 - .../pimple/pimple/ext/pimple/tests/007.phpt | 22 - .../pimple/pimple/ext/pimple/tests/008.phpt | 29 - .../pimple/pimple/ext/pimple/tests/009.phpt | 13 - .../pimple/pimple/ext/pimple/tests/010.phpt | 45 - .../pimple/pimple/ext/pimple/tests/011.phpt | 19 - .../pimple/pimple/ext/pimple/tests/012.phpt | 28 - .../pimple/pimple/ext/pimple/tests/013.phpt | 33 - .../pimple/pimple/ext/pimple/tests/014.phpt | 30 - .../pimple/pimple/ext/pimple/tests/015.phpt | 17 - .../pimple/pimple/ext/pimple/tests/016.phpt | 24 - .../pimple/pimple/ext/pimple/tests/017.phpt | 17 - .../pimple/pimple/ext/pimple/tests/017_1.phpt | 17 - .../pimple/pimple/ext/pimple/tests/018.phpt | 23 - .../pimple/pimple/ext/pimple/tests/bench.phpb | 51 - .../pimple/ext/pimple/tests/bench_shared.phpb | 25 - vendor/pimple/pimple/phpunit.xml.dist | 14 - .../src/Pimple/Tests/Fixtures/Invokable.php | 38 - .../Pimple/Tests/Fixtures/NonInvokable.php | 34 - .../Tests/Fixtures/PimpleServiceProvider.php | 54 - .../src/Pimple/Tests/Fixtures/Service.php | 35 - .../PimpleServiceProviderInterfaceTest.php | 76 -- .../pimple/src/Pimple/Tests/PimpleTest.php | 434 -------- .../Component/EventDispatcher/CHANGELOG.md | 23 + .../ContainerAwareEventDispatcher.php | 202 ++++ .../Debug/TraceableEventDispatcher.php | 317 ++++++ .../TraceableEventDispatcherInterface.php | 34 + .../EventDispatcher/Debug/WrappedListener.php | 69 ++ .../RegisterListenersPass.php | 106 ++ .../Component/EventDispatcher/Event.php | 129 +++ .../EventDispatcher/EventDispatcher.php | 185 ++++ .../EventDispatcherInterface.php | 96 ++ .../EventSubscriberInterface.php | 50 + .../EventDispatcher/GenericEvent.php | 186 ++++ .../ImmutableEventDispatcher.php | 92 ++ .../Symfony/Component/EventDispatcher/LICENSE | 19 + .../Component/EventDispatcher/README.md | 25 + 58 files changed, 1662 insertions(+), 2637 deletions(-) delete mode 100644 vendor/pimple/pimple/.gitignore delete mode 100644 vendor/pimple/pimple/.travis.yml delete mode 100644 vendor/pimple/pimple/composer.json delete mode 100644 vendor/pimple/pimple/ext/pimple/.gitignore delete mode 100644 vendor/pimple/pimple/ext/pimple/README.md delete mode 100644 vendor/pimple/pimple/ext/pimple/config.m4 delete mode 100644 vendor/pimple/pimple/ext/pimple/config.w32 delete mode 100644 vendor/pimple/pimple/ext/pimple/php_pimple.h delete mode 100644 vendor/pimple/pimple/ext/pimple/pimple.c delete mode 100644 vendor/pimple/pimple/ext/pimple/pimple_compat.h delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/001.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/002.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/003.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/004.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/005.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/006.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/007.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/008.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/009.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/010.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/011.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/012.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/013.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/014.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/015.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/016.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/017.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/017_1.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/018.phpt delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/bench.phpb delete mode 100644 vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb delete mode 100644 vendor/pimple/pimple/phpunit.xml.dist delete mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php delete mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php delete mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php delete mode 100644 vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php delete mode 100644 vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php delete mode 100644 vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/CHANGELOG.md create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/WrappedListener.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Event.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcherInterface.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventSubscriberInterface.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/GenericEvent.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/LICENSE create mode 100644 vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/README.md diff --git a/system/src/Grav/Console/CleanCommand.php b/system/src/Grav/Console/CleanCommand.php index 5c48a70b4b..8fa7fde5df 100644 --- a/system/src/Grav/Console/CleanCommand.php +++ b/system/src/Grav/Console/CleanCommand.php @@ -79,11 +79,22 @@ class CleanCommand extends Command { 'vendor/ornicar/php-user-agent/composer.json', 'vendor/ornicar/php-user-agent/prove.php', 'vendor/ornicar/php-user-agent/test', + 'vendor/pimple/pimple/.gitignore', + 'vendor/pimple/pimple/.travis.yml', + 'vendor/pimple/pimple/composer.json', + 'vendor/pimple/pimple/ext', + 'vendor/pimple/pimple/phpunit.xml.dist', + 'vendor/pimple/pimple/src/Pimple/Tests', 'vendor/symfony/console/Symfony/Component/Console/composer.json', 'vendor/symfony/console/Symfony/Component/Console/phpunit.xml.dist', 'vendor/symfony/console/Symfony/Component/Console/.gitignore', 'vendor/symfony/console/Symfony/Component/Console/.git', 'vendor/symfony/console/Symfony/Component/Console/Tests', + 'vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/.git', + 'vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/.gitignore', + 'vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/composer.json', + 'vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/phpunit.xml.dist', + 'vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests', 'vendor/symfony/yaml/Symfony/Component/Yaml/composer.json', 'vendor/symfony/yaml/Symfony/Component/Yaml/phpunit.xml.dist', 'vendor/symfony/yaml/Symfony/Component/Yaml/.gitignore', diff --git a/vendor/autoload.php b/vendor/autoload.php index d8611fcf84..3f854dda0c 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInitaeb322692412910c492cb020797b4f37::getLoader(); +return ComposerAutoloaderInit010a27b310c3146ba53b52651441075a::getLoader(); diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index 88684c5265..443364959a 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -143,6 +143,8 @@ public function add($prefix, $paths, $prepend = false) * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-0 base directories * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException */ public function addPsr4($prefix, $paths, $prepend = false) { @@ -204,6 +206,8 @@ public function set($prefix, $paths) * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException */ public function setPsr4($prefix, $paths) { diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index 9b0ddcafb4..2c705bd2a5 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -8,6 +8,7 @@ return array( 'Twig_' => array($vendorDir . '/twig/twig/lib'), 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), + 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), 'Pimple' => array($vendorDir . '/pimple/pimple/src'), 'ParsedownExtra' => array($vendorDir . '/erusev/parsedown-extra'), diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 28fb5ec075..499efe4998 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInitaeb322692412910c492cb020797b4f37 +class ComposerAutoloaderInit010a27b310c3146ba53b52651441075a { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInitaeb322692412910c492cb020797b4f37', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit010a27b310c3146ba53b52651441075a', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInitaeb322692412910c492cb020797b4f37', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit010a27b310c3146ba53b52651441075a', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ public static function getLoader() $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequireaeb322692412910c492cb020797b4f37($file); + composerRequire010a27b310c3146ba53b52651441075a($file); } return $loader; } } -function composerRequireaeb322692412910c492cb020797b4f37($file) +function composerRequire010a27b310c3146ba53b52651441075a($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 0bee9bd062..3b92750048 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -353,6 +353,54 @@ "description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers", "homepage": "http://code.google.com/p/minify/" }, + { + "name": "pimple/pimple", + "version": "v3.0.0", + "version_normalized": "3.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/fabpot/Pimple.git", + "reference": "876bf0899d01feacd2a2e83f04641e51350099ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fabpot/Pimple/zipball/876bf0899d01feacd2a2e83f04641e51350099ef", + "reference": "876bf0899d01feacd2a2e83f04641e51350099ef", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2014-07-24 09:48:15", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", + "homepage": "http://pimple.sensiolabs.org", + "keywords": [ + "container", + "dependency injection" + ] + }, { "name": "twig/twig", "version": "dev-master", @@ -518,6 +566,65 @@ "description": "Symfony Console Component", "homepage": "http://symfony.com" }, + { + "name": "symfony/event-dispatcher", + "version": "2.5.x-dev", + "version_normalized": "2.5.9999999.9999999-dev", + "target-dir": "Symfony/Component/EventDispatcher", + "source": { + "type": "git", + "url": "https://github.com/symfony/EventDispatcher.git", + "reference": "8faf5cc7e80fde74a650a36e60d32ce3c3e0457b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/8faf5cc7e80fde74a650a36e60d32ce3c3e0457b", + "reference": "8faf5cc7e80fde74a650a36e60d32ce3c3e0457b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.0", + "symfony/dependency-injection": "~2.0", + "symfony/stopwatch": "~2.2" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "time": "2014-07-28 13:20:46", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "installation-source": "source", + "autoload": { + "psr-0": { + "Symfony\\Component\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "http://symfony.com" + }, { "name": "ircmaxell/password-compat", "version": "1.0.3", @@ -605,53 +712,5 @@ "keywords": [ "user-agent" ] - }, - { - "name": "pimple/pimple", - "version": "v3.0.0", - "version_normalized": "3.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/fabpot/Pimple.git", - "reference": "876bf0899d01feacd2a2e83f04641e51350099ef" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fabpot/Pimple/zipball/876bf0899d01feacd2a2e83f04641e51350099ef", - "reference": "876bf0899d01feacd2a2e83f04641e51350099ef", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2014-07-24 09:48:15", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Pimple": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", - "homepage": "http://pimple.sensiolabs.org", - "keywords": [ - "container", - "dependency injection" - ] } ] diff --git a/vendor/pimple/pimple/.gitignore b/vendor/pimple/pimple/.gitignore deleted file mode 100644 index c089b09520..0000000000 --- a/vendor/pimple/pimple/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -phpunit.xml -composer.lock -/vendor/ diff --git a/vendor/pimple/pimple/.travis.yml b/vendor/pimple/pimple/.travis.yml deleted file mode 100644 index 5f8bb7c9f3..0000000000 --- a/vendor/pimple/pimple/.travis.yml +++ /dev/null @@ -1,32 +0,0 @@ -language: php - -env: - matrix: - - PIMPLE_EXT=no - - PIMPLE_EXT=yes - global: - - REPORT_EXIT_STATUS=1 - -php: - - 5.3 - - 5.4 - - 5.5 - - 5.6 - - hhvm - -before_script: - - composer self-update - - COMPOSER_ROOT_VERSION=dev-master composer dump-autoload - - if [ "$PIMPLE_EXT" == "yes" ]; then sh -c "cd ext/pimple && phpize && ./configure && make && sudo make install"; fi - - if [ "$PIMPLE_EXT" == "yes" ]; then echo "extension=pimple.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi - -script: - - cd ext/pimple - - if [ "$PIMPLE_EXT" == "yes" ]; then yes n | make test | tee output ; grep -E 'Tests failed +. +0' output; fi - - cd ../.. - - phpunit - -matrix: - exclude: - - php: hhvm - env: PIMPLE_EXT=yes diff --git a/vendor/pimple/pimple/composer.json b/vendor/pimple/pimple/composer.json deleted file mode 100644 index 3474eb8389..0000000000 --- a/vendor/pimple/pimple/composer.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "pimple/pimple", - "type": "library", - "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", - "keywords": ["dependency injection", "container"], - "homepage": "http://pimple.sensiolabs.org", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "require": { - "php": ">=5.3.0" - }, - "autoload": { - "psr-0": { "Pimple": "src/" } - }, - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - } -} diff --git a/vendor/pimple/pimple/ext/pimple/.gitignore b/vendor/pimple/pimple/ext/pimple/.gitignore deleted file mode 100644 index 1861088ac1..0000000000 --- a/vendor/pimple/pimple/ext/pimple/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -*.sw* -.deps -Makefile -Makefile.fragments -Makefile.global -Makefile.objects -acinclude.m4 -aclocal.m4 -build/ -config.cache -config.guess -config.h -config.h.in -config.log -config.nice -config.status -config.sub -configure -configure.in -install-sh -libtool -ltmain.sh -missing -mkinstalldirs -run-tests.php -*.loT -.libs/ -modules/ -*.la -*.lo diff --git a/vendor/pimple/pimple/ext/pimple/README.md b/vendor/pimple/pimple/ext/pimple/README.md deleted file mode 100644 index 7b39eb2929..0000000000 --- a/vendor/pimple/pimple/ext/pimple/README.md +++ /dev/null @@ -1,12 +0,0 @@ -This is Pimple 2 implemented in C - -* PHP >= 5.3 -* Not tested under Windows, might work - -Install -======= - - > phpize - > ./configure - > make - > make install diff --git a/vendor/pimple/pimple/ext/pimple/config.m4 b/vendor/pimple/pimple/ext/pimple/config.m4 deleted file mode 100644 index c9ba17ddbd..0000000000 --- a/vendor/pimple/pimple/ext/pimple/config.m4 +++ /dev/null @@ -1,63 +0,0 @@ -dnl $Id$ -dnl config.m4 for extension pimple - -dnl Comments in this file start with the string 'dnl'. -dnl Remove where necessary. This file will not work -dnl without editing. - -dnl If your extension references something external, use with: - -dnl PHP_ARG_WITH(pimple, for pimple support, -dnl Make sure that the comment is aligned: -dnl [ --with-pimple Include pimple support]) - -dnl Otherwise use enable: - -PHP_ARG_ENABLE(pimple, whether to enable pimple support, -dnl Make sure that the comment is aligned: -[ --enable-pimple Enable pimple support]) - -if test "$PHP_PIMPLE" != "no"; then - dnl Write more examples of tests here... - - dnl # --with-pimple -> check with-path - dnl SEARCH_PATH="/usr/local /usr" # you might want to change this - dnl SEARCH_FOR="/include/pimple.h" # you most likely want to change this - dnl if test -r $PHP_PIMPLE/$SEARCH_FOR; then # path given as parameter - dnl PIMPLE_DIR=$PHP_PIMPLE - dnl else # search default path list - dnl AC_MSG_CHECKING([for pimple files in default path]) - dnl for i in $SEARCH_PATH ; do - dnl if test -r $i/$SEARCH_FOR; then - dnl PIMPLE_DIR=$i - dnl AC_MSG_RESULT(found in $i) - dnl fi - dnl done - dnl fi - dnl - dnl if test -z "$PIMPLE_DIR"; then - dnl AC_MSG_RESULT([not found]) - dnl AC_MSG_ERROR([Please reinstall the pimple distribution]) - dnl fi - - dnl # --with-pimple -> add include path - dnl PHP_ADD_INCLUDE($PIMPLE_DIR/include) - - dnl # --with-pimple -> check for lib and symbol presence - dnl LIBNAME=pimple # you may want to change this - dnl LIBSYMBOL=pimple # you most likely want to change this - - dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, - dnl [ - dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $PIMPLE_DIR/lib, PIMPLE_SHARED_LIBADD) - dnl AC_DEFINE(HAVE_PIMPLELIB,1,[ ]) - dnl ],[ - dnl AC_MSG_ERROR([wrong pimple lib version or lib not found]) - dnl ],[ - dnl -L$PIMPLE_DIR/lib -lm - dnl ]) - dnl - dnl PHP_SUBST(PIMPLE_SHARED_LIBADD) - - PHP_NEW_EXTENSION(pimple, pimple.c, $ext_shared) -fi diff --git a/vendor/pimple/pimple/ext/pimple/config.w32 b/vendor/pimple/pimple/ext/pimple/config.w32 deleted file mode 100644 index 39857b3254..0000000000 --- a/vendor/pimple/pimple/ext/pimple/config.w32 +++ /dev/null @@ -1,13 +0,0 @@ -// $Id$ -// vim:ft=javascript - -// If your extension references something external, use ARG_WITH -// ARG_WITH("pimple", "for pimple support", "no"); - -// Otherwise, use ARG_ENABLE -// ARG_ENABLE("pimple", "enable pimple support", "no"); - -if (PHP_PIMPLE != "no") { - EXTENSION("pimple", "pimple.c"); -} - diff --git a/vendor/pimple/pimple/ext/pimple/php_pimple.h b/vendor/pimple/pimple/ext/pimple/php_pimple.h deleted file mode 100644 index 359f7132cf..0000000000 --- a/vendor/pimple/pimple/ext/pimple/php_pimple.h +++ /dev/null @@ -1,122 +0,0 @@ - -/* - * This file is part of Pimple. - * - * Copyright (c) 2014 Fabien Potencier - * - * 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. - */ - -#ifndef PHP_PIMPLE_H -#define PHP_PIMPLE_H - -extern zend_module_entry pimple_module_entry; -#define phpext_pimple_ptr &pimple_module_entry - -#ifdef PHP_WIN32 -# define PHP_PIMPLE_API __declspec(dllexport) -#elif defined(__GNUC__) && __GNUC__ >= 4 -# define PHP_PIMPLE_API __attribute__ ((visibility("default"))) -#else -# define PHP_PIMPLE_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -#define PIMPLE_VERSION "3.0.0" -#define PIMPLE_NS "Pimple" - -#define PIMPLE_DEFAULT_ZVAL_CACHE_NUM 5 -#define PIMPLE_DEFAULT_ZVAL_VALUES_NUM 10 - -PHP_MINIT_FUNCTION(pimple); -PHP_MSHUTDOWN_FUNCTION(pimple); -PHP_RINIT_FUNCTION(pimple); -PHP_RSHUTDOWN_FUNCTION(pimple); -PHP_MINFO_FUNCTION(pimple); - -PHP_METHOD(Pimple, __construct); -PHP_METHOD(Pimple, factory); -PHP_METHOD(Pimple, protect); -PHP_METHOD(Pimple, raw); -PHP_METHOD(Pimple, extend); -PHP_METHOD(Pimple, keys); -PHP_METHOD(Pimple, register); -PHP_METHOD(Pimple, offsetSet); -PHP_METHOD(Pimple, offsetUnset); -PHP_METHOD(Pimple, offsetGet); -PHP_METHOD(Pimple, offsetExists); - -PHP_METHOD(PimpleClosure, __invoke); - -typedef struct _pimple_bucket_value { - zval *value; /* Must be the first element */ - zval *raw; - zend_fcall_info_cache *fcc; - zend_object_handle handle_num; - enum { - PIMPLE_IS_PARAM = 0, - PIMPLE_IS_SERVICE = 2 - } type; - zend_bool initialized; -} pimple_bucket_value; - -typedef struct _pimple_object { - zend_object zobj; - HashTable values; - HashTable factories; - HashTable protected; -} pimple_object; - -typedef struct _pimple_closure_object { - zend_object zobj; - zval *callable; - zval *factory; -} pimple_closure_object; - -static const char sensiolabs_logo[] = ""; - -static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC); -static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC); - -static void pimple_init_bucket(pimple_bucket_value *bucket); -static void pimple_bucket_dtor(pimple_bucket_value *bucket); -static void pimple_free_bucket(pimple_bucket_value *bucket); - -static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC); -static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC); -static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC); -static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC); -static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC); -static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC); - -static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC); -static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC); -static zend_function *pimple_closure_get_constructor(zval * TSRMLS_DC); - -#ifdef ZTS -#define PIMPLE_G(v) TSRMG(pimple_globals_id, zend_pimple_globals *, v) -#else -#define PIMPLE_G(v) (pimple_globals.v) -#endif - -#endif /* PHP_PIMPLE_H */ - diff --git a/vendor/pimple/pimple/ext/pimple/pimple.c b/vendor/pimple/pimple/ext/pimple/pimple.c deleted file mode 100644 index 44eb8da784..0000000000 --- a/vendor/pimple/pimple/ext/pimple/pimple.c +++ /dev/null @@ -1,940 +0,0 @@ - -/* - * This file is part of Pimple. - * - * Copyright (c) 2014 Fabien Potencier - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "php_pimple.h" -#include "pimple_compat.h" -#include "zend_interfaces.h" -#include "zend.h" -#include "ext/spl/spl_exceptions.h" -#include "Zend/zend_exceptions.h" -#include "main/php_output.h" -#include "SAPI.h" - -static zend_class_entry *pimple_ce; -static zend_object_handlers pimple_object_handlers; -static zend_class_entry *pimple_closure_ce; -static zend_class_entry *pimple_serviceprovider_ce; -static zend_object_handlers pimple_closure_object_handlers; - -#define FETCH_DIM_HANDLERS_VARS pimple_object *pimple_obj = NULL; \ - ulong index; \ - pimple_obj = (pimple_object *)zend_object_store_get_object(object TSRMLS_CC); \ - -#define PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS do { \ - if (ce != pimple_ce) { \ - zend_hash_find(&ce->function_table, ZEND_STRS("offsetget"), (void **)&function); \ - if (function->common.scope != ce) { /* if the function is not defined in this actual class */ \ - pimple_object_handlers.read_dimension = pimple_object_read_dimension; /* then overwrite the handler to use custom one */ \ - } \ - zend_hash_find(&ce->function_table, ZEND_STRS("offsetset"), (void **)&function); \ - if (function->common.scope != ce) { \ - pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ - } \ - zend_hash_find(&ce->function_table, ZEND_STRS("offsetexists"), (void **)&function); \ - if (function->common.scope != ce) { \ - pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ - } \ - zend_hash_find(&ce->function_table, ZEND_STRS("offsetunset"), (void **)&function); \ - if (function->common.scope != ce) { \ - pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ - } \ - } else { \ - pimple_object_handlers.read_dimension = pimple_object_read_dimension; \ - pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ - pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ - pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ - }\ - } while(0); - -#define PIMPLE_CALL_CB do { \ - zend_fcall_info_argn(&fci TSRMLS_CC, 1, &object); \ - fci.size = sizeof(fci); \ - fci.object_ptr = retval->fcc->object_ptr; \ - fci.function_name = retval->value; \ - fci.no_separation = 1; \ - fci.retval_ptr_ptr = &retval_ptr_ptr; \ -\ - zend_call_function(&fci, retval->fcc TSRMLS_CC); \ - efree(fci.params); \ - if (EG(exception)) { \ - return EG(uninitialized_zval_ptr); \ - } \ - } while(0); - -ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) -ZEND_ARG_ARRAY_INFO(0, value, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetset, 0, 0, 2) -ZEND_ARG_INFO(0, offset) -ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetget, 0, 0, 1) -ZEND_ARG_INFO(0, offset) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetexists, 0, 0, 1) -ZEND_ARG_INFO(0, offset) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetunset, 0, 0, 1) -ZEND_ARG_INFO(0, offset) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_factory, 0, 0, 1) -ZEND_ARG_INFO(0, callable) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_protect, 0, 0, 1) -ZEND_ARG_INFO(0, callable) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_raw, 0, 0, 1) -ZEND_ARG_INFO(0, id) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_extend, 0, 0, 2) -ZEND_ARG_INFO(0, id) -ZEND_ARG_INFO(0, callable) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_keys, 0, 0, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_register, 0, 0, 1) -ZEND_ARG_OBJ_INFO(0, provider, Pimple\\ServiceProviderInterface, 0) -ZEND_ARG_ARRAY_INFO(0, values, 1) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_pimpleclosure___invoke, 0, 0, 1) -ZEND_ARG_INFO(0, callarg) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_serviceprovider_register, 0, 0, 1) -ZEND_ARG_OBJ_INFO(0, pimple, Pimple\\Container, 0) -ZEND_END_ARG_INFO() - -static const zend_function_entry pimple_ce_functions[] = { - PHP_ME(Pimple, __construct, arginfo___construct, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, factory, arginfo_factory, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, protect, arginfo_protect, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, raw, arginfo_raw, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, extend, arginfo_extend, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, keys, arginfo_keys, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, register, arginfo_register, ZEND_ACC_PUBLIC) - - PHP_ME(Pimple, offsetSet, arginfo_offsetset, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, offsetGet, arginfo_offsetget, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, offsetExists, arginfo_offsetexists, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, offsetUnset, arginfo_offsetunset, ZEND_ACC_PUBLIC) - PHP_FE_END -}; - -static const zend_function_entry pimple_closure_ce_functions[] = { - PHP_ME(PimpleClosure, __invoke, arginfo_pimpleclosure___invoke, ZEND_ACC_PRIVATE) - PHP_FE_END -}; - -static const zend_function_entry pimple_serviceprovider_iface_ce_functions[] = { - PHP_ABSTRACT_ME(ServiceProviderInterface, register, arginfo_serviceprovider_register) - PHP_FE_END -}; - -static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC) -{ - zend_object_std_dtor(&obj->zobj TSRMLS_CC); - if (obj->factory) { - zval_ptr_dtor(&obj->factory); - } - if (obj->callable) { - zval_ptr_dtor(&obj->callable); - } - efree(obj); -} - -static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC) -{ - zend_hash_destroy(&obj->factories); - zend_hash_destroy(&obj->protected); - zend_hash_destroy(&obj->values); - zend_object_std_dtor(&obj->zobj TSRMLS_CC); - efree(obj); -} - -static void pimple_free_bucket(pimple_bucket_value *bucket) -{ - if (bucket->fcc) { - efree(bucket->fcc); - bucket->fcc = NULL; - } - if (bucket->raw) { - zval_ptr_dtor(&bucket->raw); - } -} - -static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC) -{ - zend_object_value retval; - pimple_closure_object *pimple_closure_obj = NULL; - - pimple_closure_obj = ecalloc(1, sizeof(pimple_closure_object)); - ZEND_OBJ_INIT(&pimple_closure_obj->zobj, ce); - - pimple_closure_object_handlers.get_constructor = pimple_closure_get_constructor; - retval.handlers = &pimple_closure_object_handlers; - retval.handle = zend_objects_store_put(pimple_closure_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_closure_free_object_storage, NULL TSRMLS_CC); - - return retval; -} - -static zend_function *pimple_closure_get_constructor(zval *obj TSRMLS_DC) -{ - zend_error(E_ERROR, "Pimple\\ContainerClosure is an internal class and cannot be instantiated"); - - return NULL; -} - -static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC) -{ - zend_object_value retval; - pimple_object *pimple_obj = NULL; - zend_function *function = NULL; - - pimple_obj = emalloc(sizeof(pimple_object)); - ZEND_OBJ_INIT(&pimple_obj->zobj, ce); - - PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS - - retval.handlers = &pimple_object_handlers; - retval.handle = zend_objects_store_put(pimple_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_free_object_storage, NULL TSRMLS_CC); - - zend_hash_init(&pimple_obj->factories, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); - zend_hash_init(&pimple_obj->protected, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); - zend_hash_init(&pimple_obj->values, PIMPLE_DEFAULT_ZVAL_VALUES_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); - - return retval; -} - -static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) -{ - FETCH_DIM_HANDLERS_VARS - - pimple_bucket_value pimple_value = {0}, *found_value = NULL; - ulong hash; - - pimple_init_bucket(&pimple_value); - pimple_zval_to_pimpleval(value, &pimple_value TSRMLS_CC); - - if (!offset) {/* $p[] = 'foo' when not overloaded */ - zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); - Z_ADDREF_P(value); - return; - } - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - hash = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); - zend_hash_quick_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void **)&found_value); - if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { - pimple_free_bucket(&pimple_value); - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%s\".", Z_STRVAL_P(offset)); - return; - } - if (zend_hash_quick_update(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { - pimple_free_bucket(&pimple_value); - return; - } - Z_ADDREF_P(value); - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - zend_hash_index_find(&pimple_obj->values, index, (void **)&found_value); - if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { - pimple_free_bucket(&pimple_value); - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%ld\".", index); - return; - } - if (zend_hash_index_update(&pimple_obj->values, index, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { - pimple_free_bucket(&pimple_value); - return; - } - Z_ADDREF_P(value); - break; - case IS_NULL: /* $p[] = 'foo' when overloaded */ - zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); - Z_ADDREF_P(value); - break; - default: - pimple_free_bucket(&pimple_value); - zend_error(E_WARNING, "Unsupported offset type"); - } -} - -static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC) -{ - FETCH_DIM_HANDLERS_VARS - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - zend_symtable_del(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); - zend_symtable_del(&pimple_obj->factories, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); - zend_symtable_del(&pimple_obj->protected, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - zend_hash_index_del(&pimple_obj->values, index); - zend_hash_index_del(&pimple_obj->factories, index); - zend_hash_index_del(&pimple_obj->protected, index); - break; - default: - zend_error(E_WARNING, "Unsupported offset type"); - } -} - -static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) -{ - FETCH_DIM_HANDLERS_VARS - - pimple_bucket_value *retval = NULL; - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == SUCCESS) { - switch (check_empty) { - case 0: /* isset */ - return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;) */ - case 1: /* empty */ - default: - return zend_is_true(retval->value); - } - } - return 0; - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == SUCCESS) { - switch (check_empty) { - case 0: /* isset */ - return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;)*/ - case 1: /* empty */ - default: - return zend_is_true(retval->value); - } - } - return 0; - break; - default: - zend_error(E_WARNING, "Unsupported offset type"); - return 0; - } -} - -static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) -{ - FETCH_DIM_HANDLERS_VARS - - pimple_bucket_value *retval = NULL; - zend_fcall_info fci = {0}; - zval *retval_ptr_ptr = NULL; - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == FAILURE) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); - return EG(uninitialized_zval_ptr); - } - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == FAILURE) { - return EG(uninitialized_zval_ptr); - } - break; - case IS_NULL: /* $p[][3] = 'foo' first dim access */ - return EG(uninitialized_zval_ptr); - break; - default: - zend_error(E_WARNING, "Unsupported offset type"); - return EG(uninitialized_zval_ptr); - } - - if(retval->type == PIMPLE_IS_PARAM) { - return retval->value; - } - - if (zend_hash_index_exists(&pimple_obj->protected, retval->handle_num)) { - /* Service is protected, return the value every time */ - return retval->value; - } - - if (zend_hash_index_exists(&pimple_obj->factories, retval->handle_num)) { - /* Service is a factory, call it everytime and never cache its result */ - PIMPLE_CALL_CB - Z_DELREF_P(retval_ptr_ptr); /* fetch dim addr will increment refcount */ - return retval_ptr_ptr; - } - - if (retval->initialized == 1) { - /* Service has already been called, return its cached value */ - return retval->value; - } - - ALLOC_INIT_ZVAL(retval->raw); - MAKE_COPY_ZVAL(&retval->value, retval->raw); - - PIMPLE_CALL_CB - - retval->initialized = 1; - zval_ptr_dtor(&retval->value); - retval->value = retval_ptr_ptr; - - return retval->value; -} - -static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) -{ - if (Z_TYPE_P(_zval) != IS_OBJECT) { - return FAILURE; - } - - if (_pimple_bucket_value->fcc->called_scope) { - return SUCCESS; - } - - if (Z_OBJ_HANDLER_P(_zval, get_closure) && Z_OBJ_HANDLER_P(_zval, get_closure)(_zval, &_pimple_bucket_value->fcc->calling_scope, &_pimple_bucket_value->fcc->function_handler, &_pimple_bucket_value->fcc->object_ptr TSRMLS_CC) == SUCCESS) { - _pimple_bucket_value->fcc->called_scope = _pimple_bucket_value->fcc->calling_scope; - return SUCCESS; - } else { - return FAILURE; - } -} - -static void pimple_init_bucket(pimple_bucket_value *bucket) -{ - memset(bucket, 0, sizeof(pimple_bucket_value)); - bucket->fcc = ecalloc(1, sizeof(zend_fcall_info_cache)); -} - -static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) -{ - _pimple_bucket_value->value = _zval; - - if (Z_TYPE_P(_zval) != IS_OBJECT) { - return PIMPLE_IS_PARAM; - } - - if (pimple_zval_is_valid_callback(_zval, _pimple_bucket_value TSRMLS_CC) == SUCCESS) { - _pimple_bucket_value->type = PIMPLE_IS_SERVICE; - _pimple_bucket_value->handle_num = Z_OBJ_HANDLE_P(_zval); - } - - return PIMPLE_IS_SERVICE; -} - -static void pimple_bucket_dtor(pimple_bucket_value *bucket) -{ - zval_ptr_dtor(&bucket->value); - pimple_free_bucket(bucket); -} - -PHP_METHOD(Pimple, protect) -{ - zval *protected = NULL; - pimple_object *pobj = NULL; - pimple_bucket_value bucket = {0}; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &protected) == FAILURE) { - return; - } - - pimple_init_bucket(&bucket); - - if (pimple_zval_is_valid_callback(protected, &bucket TSRMLS_CC) == FAILURE) { - pimple_free_bucket(&bucket); - zend_throw_exception(spl_ce_InvalidArgumentException, "Callable is not a Closure or invokable object.", 0 TSRMLS_CC); - return; - } - - pimple_zval_to_pimpleval(protected, &bucket TSRMLS_CC); - pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); - - if (zend_hash_index_update(&pobj->protected, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { - RETURN_ZVAL(protected, 1 , 0); - } else { - pimple_free_bucket(&bucket); - } - RETURN_FALSE; -} - -PHP_METHOD(Pimple, raw) -{ - zval *offset = NULL; - pimple_object *pobj = NULL; - pimple_bucket_value *value = NULL; - ulong index; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { - return; - } - - pobj = zend_object_store_get_object(getThis() TSRMLS_CC); - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); - RETURN_NULL(); - } - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { - RETURN_NULL(); - } - break; - case IS_NULL: - default: - zend_error(E_WARNING, "Unsupported offset type"); - } - - if (value->raw) { - RETVAL_ZVAL(value->raw, 1, 0); - } else { - RETVAL_ZVAL(value->value, 1, 0); - } -} - -PHP_METHOD(Pimple, extend) -{ - zval *offset = NULL, *callable = NULL, *pimple_closure_obj = NULL; - pimple_bucket_value bucket = {0}, *value = NULL; - pimple_object *pobj = NULL; - pimple_closure_object *pcobj = NULL; - ulong index; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &callable) == FAILURE) { - return; - } - - pobj = zend_object_store_get_object(getThis() TSRMLS_CC); - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); - RETURN_NULL(); - } - if (value->type != PIMPLE_IS_SERVICE) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" does not contain an object definition.", Z_STRVAL_P(offset)); - RETURN_NULL(); - } - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" is not defined.", index); - RETURN_NULL(); - } - if (value->type != PIMPLE_IS_SERVICE) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" does not contain an object definition.", index); - RETURN_NULL(); - } - break; - case IS_NULL: - default: - zend_error(E_WARNING, "Unsupported offset type"); - } - - pimple_init_bucket(&bucket); - - if (pimple_zval_is_valid_callback(callable, &bucket TSRMLS_CC) == FAILURE) { - pimple_free_bucket(&bucket); - zend_throw_exception(spl_ce_InvalidArgumentException, "Extension service definition is not a Closure or invokable object.", 0 TSRMLS_CC); - RETURN_NULL(); - } - pimple_free_bucket(&bucket); - - ALLOC_INIT_ZVAL(pimple_closure_obj); - object_init_ex(pimple_closure_obj, pimple_closure_ce); - - pcobj = zend_object_store_get_object(pimple_closure_obj TSRMLS_CC); - pcobj->callable = callable; - pcobj->factory = value->value; - Z_ADDREF_P(callable); - Z_ADDREF_P(value->value); - - if (zend_hash_index_exists(&pobj->factories, value->handle_num)) { - pimple_init_bucket(&bucket); - pimple_zval_to_pimpleval(pimple_closure_obj, &bucket TSRMLS_CC); - zend_hash_index_del(&pobj->factories, value->handle_num); - zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL); - Z_ADDREF_P(pimple_closure_obj); - } - - pimple_object_write_dimension(getThis(), offset, pimple_closure_obj TSRMLS_CC); - - RETVAL_ZVAL(pimple_closure_obj, 1, 1); -} - -PHP_METHOD(Pimple, keys) -{ - HashPosition pos; - pimple_object *pobj = NULL; - zval **value = NULL; - zval *endval = NULL; - char *str_index = NULL; - int str_len; - ulong num_index; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - pobj = zend_object_store_get_object(getThis() TSRMLS_CC); - array_init_size(return_value, zend_hash_num_elements(&pobj->values)); - - zend_hash_internal_pointer_reset_ex(&pobj->values, &pos); - - while(zend_hash_get_current_data_ex(&pobj->values, (void **)&value, &pos) == SUCCESS) { - MAKE_STD_ZVAL(endval); - switch (zend_hash_get_current_key_ex(&pobj->values, &str_index, (uint *)&str_len, &num_index, 0, &pos)) { - case HASH_KEY_IS_STRING: - ZVAL_STRINGL(endval, str_index, str_len - 1, 1); - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); - break; - case HASH_KEY_IS_LONG: - ZVAL_LONG(endval, num_index); - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); - break; - } - zend_hash_move_forward_ex(&pobj->values, &pos); - } -} - -PHP_METHOD(Pimple, factory) -{ - zval *factory = NULL; - pimple_object *pobj = NULL; - pimple_bucket_value bucket = {0}; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &factory) == FAILURE) { - return; - } - - pimple_init_bucket(&bucket); - - if (pimple_zval_is_valid_callback(factory, &bucket TSRMLS_CC) == FAILURE) { - pimple_free_bucket(&bucket); - zend_throw_exception(spl_ce_InvalidArgumentException, "Service definition is not a Closure or invokable object.", 0 TSRMLS_CC); - return; - } - - pimple_zval_to_pimpleval(factory, &bucket TSRMLS_CC); - pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); - - if (zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { - Z_ADDREF_P(factory); - RETURN_ZVAL(factory, 1 , 0); - } else { - pimple_free_bucket(&bucket); - } - - RETURN_FALSE; -} - -PHP_METHOD(Pimple, offsetSet) -{ - zval *offset = NULL, *value = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &value) == FAILURE) { - return; - } - - pimple_object_write_dimension(getThis(), offset, value TSRMLS_CC); -} - -PHP_METHOD(Pimple, offsetGet) -{ - zval *offset = NULL, *retval = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { - return; - } - - retval = pimple_object_read_dimension(getThis(), offset, 0 TSRMLS_CC); - - RETVAL_ZVAL(retval, 1, 0); -} - -PHP_METHOD(Pimple, offsetUnset) -{ - zval *offset = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { - return; - } - - pimple_object_unset_dimension(getThis(), offset TSRMLS_CC); -} - -PHP_METHOD(Pimple, offsetExists) -{ - zval *offset = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { - return; - } - - RETVAL_BOOL(pimple_object_has_dimension(getThis(), offset, 1 TSRMLS_CC)); -} - -PHP_METHOD(Pimple, register) -{ - zval *provider; - zval **data; - zval *retval = NULL; - zval key; - - HashTable *array = NULL; - HashPosition pos; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|h", &provider, pimple_serviceprovider_ce, &array) == FAILURE) { - return; - } - - zend_call_method_with_1_params(&provider, Z_OBJCE_P(provider), NULL, "register", &retval, getThis()); - - if (retval) { - zval_ptr_dtor(&retval); - } - - if (!array) { - return; - } - - zend_hash_internal_pointer_reset_ex(array, &pos); - - while(zend_hash_get_current_data_ex(array, (void **)&data, &pos) == SUCCESS) { - zend_hash_get_current_key_zval_ex(array, &key, &pos); - pimple_object_write_dimension(getThis(), &key, *data TSRMLS_CC); - zend_hash_move_forward_ex(array, &pos); - } - - RETVAL_ZVAL(getThis(), 1, 0); -} - -PHP_METHOD(Pimple, __construct) -{ - zval *values = NULL, **pData = NULL, offset = {0}; - HashPosition pos; - char *str_index = NULL; - zend_uint str_length; - ulong num_index; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &values) == FAILURE || !values) { - return; - } - - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos); - while (zend_hash_has_more_elements_ex(Z_ARRVAL_P(values), &pos) == SUCCESS) { - zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&pData, &pos); - zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &str_index, &str_length, &num_index, 0, &pos); - if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(values), &pos) == HASH_KEY_IS_LONG) { - ZVAL_LONG(&offset, num_index); - } else { - ZVAL_STRINGL(&offset, str_index, (str_length - 1), 0); - } - pimple_object_write_dimension(getThis(), &offset, *pData TSRMLS_CC); - zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos); - } -} - -/* - * This is PHP code snippet handling extend()s calls : - - $extended = function ($c) use ($callable, $factory) { - return $callable($factory($c), $c); - }; - - */ -PHP_METHOD(PimpleClosure, __invoke) -{ - pimple_closure_object *pcobj = NULL; - zval *arg = NULL, *retval = NULL, *newretval = NULL; - zend_fcall_info fci = {0}; - zval **args[2]; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { - return; - } - - pcobj = zend_object_store_get_object(getThis() TSRMLS_CC); - - fci.function_name = pcobj->factory; - args[0] = &arg; - zend_fcall_info_argp(&fci TSRMLS_CC, 1, args); - fci.retval_ptr_ptr = &retval; - fci.size = sizeof(fci); - - if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { - efree(fci.params); - return; /* Should here return default zval */ - } - - efree(fci.params); - memset(&fci, 0, sizeof(fci)); - fci.size = sizeof(fci); - - fci.function_name = pcobj->callable; - args[0] = &retval; - args[1] = &arg; - zend_fcall_info_argp(&fci TSRMLS_CC, 2, args); - fci.retval_ptr_ptr = &newretval; - - if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { - efree(fci.params); - zval_ptr_dtor(&retval); - return; - } - - efree(fci.params); - zval_ptr_dtor(&retval); - RETVAL_ZVAL(newretval, 1 ,1); -} - -PHP_MINIT_FUNCTION(pimple) -{ - zend_class_entry tmp_pimple_ce, tmp_pimple_closure_ce, tmp_pimple_serviceprovider_iface_ce; - INIT_NS_CLASS_ENTRY(tmp_pimple_ce, PIMPLE_NS, "Container", pimple_ce_functions); - INIT_NS_CLASS_ENTRY(tmp_pimple_closure_ce, PIMPLE_NS, "ContainerClosure", pimple_closure_ce_functions); - INIT_NS_CLASS_ENTRY(tmp_pimple_serviceprovider_iface_ce, PIMPLE_NS, "ServiceProviderInterface", pimple_serviceprovider_iface_ce_functions); - - tmp_pimple_ce.create_object = pimple_object_create; - tmp_pimple_closure_ce.create_object = pimple_closure_object_create; - - pimple_ce = zend_register_internal_class(&tmp_pimple_ce TSRMLS_CC); - zend_class_implements(pimple_ce TSRMLS_CC, 1, zend_ce_arrayaccess); - - pimple_closure_ce = zend_register_internal_class(&tmp_pimple_closure_ce TSRMLS_CC); - pimple_closure_ce->ce_flags |= ZEND_ACC_FINAL_CLASS; - - pimple_serviceprovider_ce = zend_register_internal_interface(&tmp_pimple_serviceprovider_iface_ce TSRMLS_CC); - - pimple_closure_object_handlers = std_object_handlers; - pimple_object_handlers = std_object_handlers; - - return SUCCESS; -} - -PHP_MSHUTDOWN_FUNCTION(pimple) -{ - return SUCCESS; -} - -PHP_RINIT_FUNCTION(pimple) -{ - return SUCCESS; -} - -PHP_RSHUTDOWN_FUNCTION(pimple) -{ - return SUCCESS; -} - -PHP_MINFO_FUNCTION(pimple) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "SensioLabs Pimple C support", "enabled"); - php_info_print_table_row(2, "Pimple supported version", PIMPLE_VERSION); - php_info_print_table_end(); - - php_info_print_box_start(0); - php_write((void *)ZEND_STRL("SensioLabs Pimple C support developed by Julien Pauli") TSRMLS_CC); - if (!sapi_module.phpinfo_as_text) { - php_write((void *)ZEND_STRL(sensiolabs_logo) TSRMLS_CC); - } - php_info_print_box_end(); -} - -zend_module_entry pimple_module_entry = { - STANDARD_MODULE_HEADER, - "pimple", - NULL, - PHP_MINIT(pimple), - PHP_MSHUTDOWN(pimple), - PHP_RINIT(pimple), - PHP_RSHUTDOWN(pimple), - PHP_MINFO(pimple), - PIMPLE_VERSION, - STANDARD_MODULE_PROPERTIES -}; - -#ifdef COMPILE_DL_PIMPLE -ZEND_GET_MODULE(pimple) -#endif diff --git a/vendor/pimple/pimple/ext/pimple/pimple_compat.h b/vendor/pimple/pimple/ext/pimple/pimple_compat.h deleted file mode 100644 index d234e174d0..0000000000 --- a/vendor/pimple/pimple/ext/pimple/pimple_compat.h +++ /dev/null @@ -1,81 +0,0 @@ - -/* - * This file is part of Pimple. - * - * Copyright (c) 2014 Fabien Potencier - * - * 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. - */ - -#ifndef PIMPLE_COMPAT_H_ -#define PIMPLE_COMPAT_H_ - -#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */ - -#define PHP_5_0_X_API_NO 220040412 -#define PHP_5_1_X_API_NO 220051025 -#define PHP_5_2_X_API_NO 220060519 -#define PHP_5_3_X_API_NO 220090626 -#define PHP_5_4_X_API_NO 220100525 -#define PHP_5_5_X_API_NO 220121212 -#define PHP_5_6_X_API_NO 220131226 - -#define IS_PHP_56 ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO -#define IS_AT_LEAST_PHP_56 ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO - -#define IS_PHP_55 ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO -#define IS_AT_LEAST_PHP_55 ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO - -#define IS_PHP_54 ZEND_EXTENSION_API_NO == PHP_5_4_X_API_NO -#define IS_AT_LEAST_PHP_54 ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO - -#define IS_PHP_53 ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO -#define IS_AT_LEAST_PHP_53 ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO - -#if IS_PHP_53 -#define object_properties_init(obj, ce) do { \ - zend_hash_copy(obj->properties, &ce->default_properties, zval_copy_property_ctor(ce), NULL, sizeof(zval *)); \ - } while (0); -#endif - -#define ZEND_OBJ_INIT(obj, ce) do { \ - zend_object_std_init(obj, ce TSRMLS_CC); \ - object_properties_init((obj), (ce)); \ - } while(0); - -#if IS_PHP_53 || IS_PHP_54 -static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) { - Bucket *p; - - p = pos ? (*pos) : ht->pInternalPointer; - - if (!p) { - Z_TYPE_P(key) = IS_NULL; - } else if (p->nKeyLength) { - Z_TYPE_P(key) = IS_STRING; - Z_STRVAL_P(key) = estrndup(p->arKey, p->nKeyLength - 1); - Z_STRLEN_P(key) = p->nKeyLength - 1; - } else { - Z_TYPE_P(key) = IS_LONG; - Z_LVAL_P(key) = p->h; - } -} -#endif - -#endif /* PIMPLE_COMPAT_H_ */ diff --git a/vendor/pimple/pimple/ext/pimple/tests/001.phpt b/vendor/pimple/pimple/ext/pimple/tests/001.phpt deleted file mode 100644 index 0809ea232b..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/001.phpt +++ /dev/null @@ -1,45 +0,0 @@ ---TEST-- -Test for read_dim/write_dim handlers ---SKIPIF-- - ---FILE-- - - ---EXPECTF-- -foo -42 -foo2 -foo99 -baz -strstr \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/002.phpt b/vendor/pimple/pimple/ext/pimple/tests/002.phpt deleted file mode 100644 index 7b56d2c1fe..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/002.phpt +++ /dev/null @@ -1,15 +0,0 @@ ---TEST-- -Test for constructor ---SKIPIF-- - ---FILE-- -'foo')); -var_dump($p[42]); -?> ---EXPECT-- -NULL -string(3) "foo" diff --git a/vendor/pimple/pimple/ext/pimple/tests/003.phpt b/vendor/pimple/pimple/ext/pimple/tests/003.phpt deleted file mode 100644 index a22cfa352e..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/003.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -Test empty dimensions ---SKIPIF-- - ---FILE-- - ---EXPECT-- -int(42) -string(3) "bar" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/004.phpt b/vendor/pimple/pimple/ext/pimple/tests/004.phpt deleted file mode 100644 index 1e1d251367..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/004.phpt +++ /dev/null @@ -1,30 +0,0 @@ ---TEST-- -Test has/unset dim handlers ---SKIPIF-- - ---FILE-- - ---EXPECT-- -int(42) -NULL -bool(true) -bool(false) -bool(true) -bool(true) \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/005.phpt b/vendor/pimple/pimple/ext/pimple/tests/005.phpt deleted file mode 100644 index 0479ee055d..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/005.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Test simple class inheritance ---SKIPIF-- - ---FILE-- -someAttr; -?> ---EXPECT-- -string(3) "hit" -foo -fooAttr \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/006.phpt b/vendor/pimple/pimple/ext/pimple/tests/006.phpt deleted file mode 100644 index cfe8a119e6..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/006.phpt +++ /dev/null @@ -1,51 +0,0 @@ ---TEST-- -Test complex class inheritance ---SKIPIF-- - ---FILE-- - 'bar', 88 => 'baz'); - -$p = new TestPimple($defaultValues); -$p[42] = 'foo'; -var_dump($p[42]); -var_dump($p[0]); -?> ---EXPECT-- -string(13) "hit offsetset" -string(27) "hit offsetget in TestPimple" -string(25) "hit offsetget in MyPimple" -string(3) "foo" -string(27) "hit offsetget in TestPimple" -string(25) "hit offsetget in MyPimple" -string(3) "baz" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/007.phpt b/vendor/pimple/pimple/ext/pimple/tests/007.phpt deleted file mode 100644 index 5aac683806..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/007.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Test for read_dim/write_dim handlers ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -foo -42 \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/008.phpt b/vendor/pimple/pimple/ext/pimple/tests/008.phpt deleted file mode 100644 index db7eeec4a1..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/008.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -Test frozen services ---SKIPIF-- - ---FILE-- - ---EXPECTF-- diff --git a/vendor/pimple/pimple/ext/pimple/tests/009.phpt b/vendor/pimple/pimple/ext/pimple/tests/009.phpt deleted file mode 100644 index bb05ea2964..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/009.phpt +++ /dev/null @@ -1,13 +0,0 @@ ---TEST-- -Test service is called as callback, and only once ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -bool(true) \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/010.phpt b/vendor/pimple/pimple/ext/pimple/tests/010.phpt deleted file mode 100644 index badce0146a..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/010.phpt +++ /dev/null @@ -1,45 +0,0 @@ ---TEST-- -Test service is called as callback for every callback type ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -callme -called -Foo::bar -array(2) { - [0]=> - string(3) "Foo" - [1]=> - string(3) "bar" -} \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/011.phpt b/vendor/pimple/pimple/ext/pimple/tests/011.phpt deleted file mode 100644 index 6682ab8ebd..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/011.phpt +++ /dev/null @@ -1,19 +0,0 @@ ---TEST-- -Test service callback throwing an exception ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -all right! \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/012.phpt b/vendor/pimple/pimple/ext/pimple/tests/012.phpt deleted file mode 100644 index 4c6ac486dc..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/012.phpt +++ /dev/null @@ -1,28 +0,0 @@ ---TEST-- -Test service factory ---SKIPIF-- - ---FILE-- -factory($f = function() { var_dump('called-1'); return 'ret-1';}); - -$p[] = $f; - -$p[] = function () { var_dump('called-2'); return 'ret-2'; }; - -var_dump($p[0]); -var_dump($p[0]); -var_dump($p[1]); -var_dump($p[1]); -?> ---EXPECTF-- -string(8) "called-1" -string(5) "ret-1" -string(8) "called-1" -string(5) "ret-1" -string(8) "called-2" -string(5) "ret-2" -string(5) "ret-2" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/013.phpt b/vendor/pimple/pimple/ext/pimple/tests/013.phpt deleted file mode 100644 index f419958c5f..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/013.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -Test keys() ---SKIPIF-- - ---FILE-- -keys()); - -$p['foo'] = 'bar'; -$p[] = 'foo'; - -var_dump($p->keys()); - -unset($p['foo']); - -var_dump($p->keys()); -?> ---EXPECTF-- -array(0) { -} -array(2) { - [0]=> - string(3) "foo" - [1]=> - int(0) -} -array(1) { - [0]=> - int(0) -} \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/014.phpt b/vendor/pimple/pimple/ext/pimple/tests/014.phpt deleted file mode 100644 index ac937213ac..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/014.phpt +++ /dev/null @@ -1,30 +0,0 @@ ---TEST-- -Test raw() ---SKIPIF-- - ---FILE-- -raw('foo')); -var_dump($p[42]); - -unset($p['foo']); - -try { - $p->raw('foo'); - echo "expected exception"; -} catch (InvalidArgumentException $e) { } ---EXPECTF-- -string(8) "called-2" -string(5) "ret-2" -object(Closure)#%i (0) { -} -string(8) "called-2" -string(5) "ret-2" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/015.phpt b/vendor/pimple/pimple/ext/pimple/tests/015.phpt deleted file mode 100644 index 314f008ac1..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/015.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Test protect() ---SKIPIF-- - ---FILE-- -protect($f); - -var_dump($p['foo']); ---EXPECTF-- -object(Closure)#%i (0) { -} \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/016.phpt b/vendor/pimple/pimple/ext/pimple/tests/016.phpt deleted file mode 100644 index e55edb0a7a..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/016.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -Test extend() ---SKIPIF-- - ---FILE-- -extend(12, function ($w) { var_dump($w); return 'bar'; }); /* $callable in code above */ - -var_dump($c('param')); ---EXPECTF-- -string(5) "param" -string(3) "foo" -string(3) "bar" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/017.phpt b/vendor/pimple/pimple/ext/pimple/tests/017.phpt deleted file mode 100644 index bac23ce09a..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/017.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Test extend() with exception in service extension ---SKIPIF-- - ---FILE-- -extend(12, function ($w) { throw new BadMethodCallException; }); - -try { - $p[12]; - echo "Exception expected"; -} catch (BadMethodCallException $e) { } ---EXPECTF-- diff --git a/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt b/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt deleted file mode 100644 index 8f881d6ebf..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Test extend() with exception in service factory ---SKIPIF-- - ---FILE-- -extend(12, function ($w) { return 'foobar'; }); - -try { - $p[12]; - echo "Exception expected"; -} catch (BadMethodCallException $e) { } ---EXPECTF-- diff --git a/vendor/pimple/pimple/ext/pimple/tests/018.phpt b/vendor/pimple/pimple/ext/pimple/tests/018.phpt deleted file mode 100644 index 27c12a14e7..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/018.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---TEST-- -Test register() ---SKIPIF-- - ---FILE-- -register(new Foo, array(42 => 'bar')); - -var_dump($p[42]); ---EXPECTF-- -object(Pimple\Container)#1 (0) { -} -string(3) "bar" \ No newline at end of file diff --git a/vendor/pimple/pimple/ext/pimple/tests/bench.phpb b/vendor/pimple/pimple/ext/pimple/tests/bench.phpb deleted file mode 100644 index 8ddd6e3b9a..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/bench.phpb +++ /dev/null @@ -1,51 +0,0 @@ -factory($factory); - -$p['factory'] = $factory; - -echo $p['factory']; -echo $p['factory']; -echo $p['factory']; - -} - -echo microtime(true) - $time; diff --git a/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb b/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb deleted file mode 100644 index 0fbc8391e0..0000000000 --- a/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb +++ /dev/null @@ -1,25 +0,0 @@ - diff --git a/vendor/pimple/pimple/phpunit.xml.dist b/vendor/pimple/pimple/phpunit.xml.dist deleted file mode 100644 index 5c8d487fea..0000000000 --- a/vendor/pimple/pimple/phpunit.xml.dist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - ./src/Pimple/Tests - - - diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php deleted file mode 100644 index aba453bfc6..0000000000 --- a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php +++ /dev/null @@ -1,38 +0,0 @@ -value = $value; - - return $service; - } -} diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php deleted file mode 100644 index 33cd4e5486..0000000000 --- a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php +++ /dev/null @@ -1,34 +0,0 @@ -factory(function () { - return new Service(); - }); - } -} diff --git a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php b/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php deleted file mode 100644 index d71b184ddf..0000000000 --- a/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php +++ /dev/null @@ -1,35 +0,0 @@ - - */ -class Service -{ - public $value; -} diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php deleted file mode 100644 index 69f76f8435..0000000000 --- a/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php +++ /dev/null @@ -1,76 +0,0 @@ - - */ -class PimpleServiceProviderInterfaceTest extends \PHPUnit_Framework_TestCase -{ - public function testProvider() - { - $pimple = new Container(); - - $pimpleServiceProvider = new Fixtures\PimpleServiceProvider(); - $pimpleServiceProvider->register($pimple); - - $this->assertEquals('value', $pimple['param']); - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); - - $serviceOne = $pimple['factory']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - - $serviceTwo = $pimple['factory']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - - $this->assertNotSame($serviceOne, $serviceTwo); - } - - public function testProviderWithRegisterMethod() - { - $pimple = new Container(); - - $pimple->register(new Fixtures\PimpleServiceProvider(), array( - 'anotherParameter' => 'anotherValue' - )); - - $this->assertEquals('value', $pimple['param']); - $this->assertEquals('anotherValue', $pimple['anotherParameter']); - - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); - - $serviceOne = $pimple['factory']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - - $serviceTwo = $pimple['factory']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - - $this->assertNotSame($serviceOne, $serviceTwo); - } -} diff --git a/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php b/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php deleted file mode 100644 index 30ca391255..0000000000 --- a/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php +++ /dev/null @@ -1,434 +0,0 @@ - - */ -class PimpleTest extends \PHPUnit_Framework_TestCase -{ - public function testWithString() - { - $pimple = new Container(); - $pimple['param'] = 'value'; - - $this->assertEquals('value', $pimple['param']); - } - - public function testWithClosure() - { - $pimple = new Container(); - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); - } - - public function testServicesShouldBeDifferent() - { - $pimple = new Container(); - $pimple['service'] = $pimple->factory(function () { - return new Fixtures\Service(); - }); - - $serviceOne = $pimple['service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - - $serviceTwo = $pimple['service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - - $this->assertNotSame($serviceOne, $serviceTwo); - } - - public function testShouldPassContainerAsParameter() - { - $pimple = new Container(); - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - $pimple['container'] = function ($container) { - return $container; - }; - - $this->assertNotSame($pimple, $pimple['service']); - $this->assertSame($pimple, $pimple['container']); - } - - public function testIsset() - { - $pimple = new Container(); - $pimple['param'] = 'value'; - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - - $pimple['null'] = null; - - $this->assertTrue(isset($pimple['param'])); - $this->assertTrue(isset($pimple['service'])); - $this->assertTrue(isset($pimple['null'])); - $this->assertFalse(isset($pimple['non_existent'])); - } - - public function testConstructorInjection() - { - $params = array("param" => "value"); - $pimple = new Container($params); - - $this->assertSame($params['param'], $pimple['param']); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Identifier "foo" is not defined. - */ - public function testOffsetGetValidatesKeyIsPresent() - { - $pimple = new Container(); - echo $pimple['foo']; - } - - public function testOffsetGetHonorsNullValues() - { - $pimple = new Container(); - $pimple['foo'] = null; - $this->assertNull($pimple['foo']); - } - - public function testUnset() - { - $pimple = new Container(); - $pimple['param'] = 'value'; - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - - unset($pimple['param'], $pimple['service']); - $this->assertFalse(isset($pimple['param'])); - $this->assertFalse(isset($pimple['service'])); - } - - /** - * @dataProvider serviceDefinitionProvider - */ - public function testShare($service) - { - $pimple = new Container(); - $pimple['shared_service'] = $service; - - $serviceOne = $pimple['shared_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - - $serviceTwo = $pimple['shared_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - - $this->assertSame($serviceOne, $serviceTwo); - } - - /** - * @dataProvider serviceDefinitionProvider - */ - public function testProtect($service) - { - $pimple = new Container(); - $pimple['protected'] = $pimple->protect($service); - - $this->assertSame($service, $pimple['protected']); - } - - public function testGlobalFunctionNameAsParameterValue() - { - $pimple = new Container(); - $pimple['global_function'] = 'strlen'; - $this->assertSame('strlen', $pimple['global_function']); - } - - public function testRaw() - { - $pimple = new Container(); - $pimple['service'] = $definition = $pimple->factory(function () { return 'foo'; }); - $this->assertSame($definition, $pimple->raw('service')); - } - - public function testRawHonorsNullValues() - { - $pimple = new Container(); - $pimple['foo'] = null; - $this->assertNull($pimple->raw('foo')); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Identifier "foo" is not defined. - */ - public function testRawValidatesKeyIsPresent() - { - $pimple = new Container(); - $pimple->raw('foo'); - } - - /** - * @dataProvider serviceDefinitionProvider - */ - public function testExtend($service) - { - $pimple = new Container(); - $pimple['shared_service'] = function () { - return new Fixtures\Service(); - }; - $pimple['factory_service'] = $pimple->factory(function () { - return new Fixtures\Service(); - }); - - $pimple->extend('shared_service', $service); - $serviceOne = $pimple['shared_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - $serviceTwo = $pimple['shared_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - $this->assertSame($serviceOne, $serviceTwo); - $this->assertSame($serviceOne->value, $serviceTwo->value); - - $pimple->extend('factory_service', $service); - $serviceOne = $pimple['factory_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - $serviceTwo = $pimple['factory_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - $this->assertNotSame($serviceOne, $serviceTwo); - $this->assertNotSame($serviceOne->value, $serviceTwo->value); - } - - public function testExtendDoesNotLeakWithFactories() - { - if (extension_loaded('pimple')) { - $this->markTestSkipped('Pimple extension does not support this test'); - } - $pimple = new Container(); - - $pimple['foo'] = $pimple->factory(function () { return; }); - $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) { return; }); - unset($pimple['foo']); - - $p = new \ReflectionProperty($pimple, 'values'); - $p->setAccessible(true); - $this->assertEmpty($p->getValue($pimple)); - - $p = new \ReflectionProperty($pimple, 'factories'); - $p->setAccessible(true); - $this->assertCount(0, $p->getValue($pimple)); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Identifier "foo" is not defined. - */ - public function testExtendValidatesKeyIsPresent() - { - $pimple = new Container(); - $pimple->extend('foo', function () {}); - } - - public function testKeys() - { - $pimple = new Container(); - $pimple['foo'] = 123; - $pimple['bar'] = 123; - - $this->assertEquals(array('foo', 'bar'), $pimple->keys()); - } - - /** @test */ - public function settingAnInvokableObjectShouldTreatItAsFactory() - { - $pimple = new Container(); - $pimple['invokable'] = new Fixtures\Invokable(); - - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['invokable']); - } - - /** @test */ - public function settingNonInvokableObjectShouldTreatItAsParameter() - { - $pimple = new Container(); - $pimple['non_invokable'] = new Fixtures\NonInvokable(); - - $this->assertInstanceOf('Pimple\Tests\Fixtures\NonInvokable', $pimple['non_invokable']); - } - - /** - * @dataProvider badServiceDefinitionProvider - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Service definition is not a Closure or invokable object. - */ - public function testFactoryFailsForInvalidServiceDefinitions($service) - { - $pimple = new Container(); - $pimple->factory($service); - } - - /** - * @dataProvider badServiceDefinitionProvider - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Callable is not a Closure or invokable object. - */ - public function testProtectFailsForInvalidServiceDefinitions($service) - { - $pimple = new Container(); - $pimple->protect($service); - } - - /** - * @dataProvider badServiceDefinitionProvider - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Identifier "foo" does not contain an object definition. - */ - public function testExtendFailsForKeysNotContainingServiceDefinitions($service) - { - $pimple = new Container(); - $pimple['foo'] = $service; - $pimple->extend('foo', function () {}); - } - - /** - * @dataProvider badServiceDefinitionProvider - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Extension service definition is not a Closure or invokable object. - */ - public function testExtendFailsForInvalidServiceDefinitions($service) - { - $pimple = new Container(); - $pimple['foo'] = function () {}; - $pimple->extend('foo', $service); - } - - /** - * Provider for invalid service definitions - */ - public function badServiceDefinitionProvider() - { - return array( - array(123), - array(new Fixtures\NonInvokable()) - ); - } - - /** - * Provider for service definitions - */ - public function serviceDefinitionProvider() - { - return array( - array(function ($value) { - $service = new Fixtures\Service(); - $service->value = $value; - - return $service; - }), - array(new Fixtures\Invokable()) - ); - } - - public function testDefiningNewServiceAfterFreeze() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return 'foo'; - }; - $foo = $pimple['foo']; - - $pimple['bar'] = function () { - return 'bar'; - }; - $this->assertSame('bar', $pimple['bar']); - } - - /** - * @expectedException RuntimeException - * @expectedExceptionMessage Cannot override frozen service "foo". - */ - public function testOverridingServiceAfterFreeze() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return 'foo'; - }; - $foo = $pimple['foo']; - - $pimple['foo'] = function () { - return 'bar'; - }; - } - - public function testRemovingServiceAfterFreeze() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return 'foo'; - }; - $foo = $pimple['foo']; - - unset($pimple['foo']); - $pimple['foo'] = function () { - return 'bar'; - }; - $this->assertSame('bar', $pimple['foo']); - } - - public function testExtendingService() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return 'foo'; - }; - $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { - return "$foo.bar"; - }); - $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { - return "$foo.baz"; - }); - $this->assertSame('foo.bar.baz', $pimple['foo']); - } - - public function testExtendingServiceAfterOtherServiceFreeze() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return 'foo'; - }; - $pimple['bar'] = function () { - return 'bar'; - }; - $foo = $pimple['foo']; - - $pimple['bar'] = $pimple->extend('bar', function ($bar, $app) { - return "$bar.baz"; - }); - $this->assertSame('bar.baz', $pimple['bar']); - } -} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/CHANGELOG.md b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/CHANGELOG.md new file mode 100644 index 0000000000..bb42ee19c0 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/CHANGELOG.md @@ -0,0 +1,23 @@ +CHANGELOG +========= + +2.5.0 +----- + + * added Debug\TraceableEventDispatcher (originally in HttpKernel) + * changed Debug\TraceableEventDispatcherInterface to extend EventDispatcherInterface + * added RegisterListenersPass (originally in HttpKernel) + +2.1.0 +----- + + * added TraceableEventDispatcherInterface + * added ContainerAwareEventDispatcher + * added a reference to the EventDispatcher on the Event + * added a reference to the Event name on the event + * added fluid interface to the dispatch() method which now returns the Event + object + * added GenericEvent event class + * added the possibility for subscribers to subscribe several times for the + same event + * added ImmutableEventDispatcher diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php new file mode 100644 index 0000000000..e97d427ea1 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -0,0 +1,202 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Lazily loads listeners and subscribers from the dependency injection + * container + * + * @author Fabien Potencier + * @author Bernhard Schussek + * @author Jordan Alliot + */ +class ContainerAwareEventDispatcher extends EventDispatcher +{ + /** + * The container from where services are loaded + * @var ContainerInterface + */ + private $container; + + /** + * The service IDs of the event listeners and subscribers + * @var array + */ + private $listenerIds = array(); + + /** + * The services registered as listeners + * @var array + */ + private $listeners = array(); + + /** + * Constructor. + * + * @param ContainerInterface $container A ContainerInterface instance + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * Adds a service as event listener + * + * @param string $eventName Event for which the listener is added + * @param array $callback The service ID of the listener service & the method + * name that has to be called + * @param int $priority The higher this value, the earlier an event listener + * will be triggered in the chain. + * Defaults to 0. + * + * @throws \InvalidArgumentException + */ + public function addListenerService($eventName, $callback, $priority = 0) + { + if (!is_array($callback) || 2 !== count($callback)) { + throw new \InvalidArgumentException('Expected an array("service", "method") argument'); + } + + $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority); + } + + public function removeListener($eventName, $listener) + { + $this->lazyLoad($eventName); + + if (isset($this->listeners[$eventName])) { + foreach ($this->listeners[$eventName] as $key => $l) { + foreach ($this->listenerIds[$eventName] as $i => $args) { + list($serviceId, $method, $priority) = $args; + if ($key === $serviceId.'.'.$method) { + if ($listener === array($l, $method)) { + unset($this->listeners[$eventName][$key]); + if (empty($this->listeners[$eventName])) { + unset($this->listeners[$eventName]); + } + unset($this->listenerIds[$eventName][$i]); + if (empty($this->listenerIds[$eventName])) { + unset($this->listenerIds[$eventName]); + } + } + } + } + } + } + + parent::removeListener($eventName, $listener); + } + + /** + * @see EventDispatcherInterface::hasListeners + */ + public function hasListeners($eventName = null) + { + if (null === $eventName) { + return (bool) count($this->listenerIds) || (bool) count($this->listeners); + } + + if (isset($this->listenerIds[$eventName])) { + return true; + } + + return parent::hasListeners($eventName); + } + + /** + * @see EventDispatcherInterface::getListeners + */ + public function getListeners($eventName = null) + { + if (null === $eventName) { + foreach (array_keys($this->listenerIds) as $serviceEventName) { + $this->lazyLoad($serviceEventName); + } + } else { + $this->lazyLoad($eventName); + } + + return parent::getListeners($eventName); + } + + /** + * Adds a service as event subscriber + * + * @param string $serviceId The service ID of the subscriber service + * @param string $class The service's class name (which must implement EventSubscriberInterface) + */ + public function addSubscriberService($serviceId, $class) + { + foreach ($class::getSubscribedEvents() as $eventName => $params) { + if (is_string($params)) { + $this->listenerIds[$eventName][] = array($serviceId, $params, 0); + } elseif (is_string($params[0])) { + $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0); + } else { + foreach ($params as $listener) { + $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0); + } + } + } + } + + /** + * {@inheritdoc} + * + * Lazily loads listeners for this event from the dependency injection + * container. + * + * @throws \InvalidArgumentException if the service is not defined + */ + public function dispatch($eventName, Event $event = null) + { + $this->lazyLoad($eventName); + + return parent::dispatch($eventName, $event); + } + + public function getContainer() + { + return $this->container; + } + + /** + * Lazily loads listeners for this event from the dependency injection + * container. + * + * @param string $eventName The name of the event to dispatch. The name of + * the event is the name of the method that is + * invoked on listeners. + */ + protected function lazyLoad($eventName) + { + if (isset($this->listenerIds[$eventName])) { + foreach ($this->listenerIds[$eventName] as $args) { + list($serviceId, $method, $priority) = $args; + $listener = $this->container->get($serviceId); + + $key = $serviceId.'.'.$method; + if (!isset($this->listeners[$eventName][$key])) { + $this->addListener($eventName, array($listener, $method), $priority); + } elseif ($listener !== $this->listeners[$eventName][$key]) { + parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method)); + $this->addListener($eventName, array($listener, $method), $priority); + } + + $this->listeners[$eventName][$key] = $listener; + } + } + } +} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php new file mode 100644 index 0000000000..410226bb36 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php @@ -0,0 +1,317 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Debug; + +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\Stopwatch\Stopwatch; +use Psr\Log\LoggerInterface; + +/** + * Collects some data about event listeners. + * + * This event dispatcher delegates the dispatching to another one. + * + * @author Fabien Potencier + */ +class TraceableEventDispatcher implements TraceableEventDispatcherInterface +{ + protected $logger; + protected $stopwatch; + + private $called; + private $dispatcher; + + /** + * Constructor. + * + * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance + * @param Stopwatch $stopwatch A Stopwatch instance + * @param LoggerInterface $logger A LoggerInterface instance + */ + public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null) + { + $this->dispatcher = $dispatcher; + $this->stopwatch = $stopwatch; + $this->logger = $logger; + $this->called = array(); + } + + /** + * {@inheritdoc} + */ + public function addListener($eventName, $listener, $priority = 0) + { + $this->dispatcher->addListener($eventName, $listener, $priority); + } + + /** + * {@inheritdoc} + */ + public function addSubscriber(EventSubscriberInterface $subscriber) + { + $this->dispatcher->addSubscriber($subscriber); + } + + /** + * {@inheritdoc} + */ + public function removeListener($eventName, $listener) + { + return $this->dispatcher->removeListener($eventName, $listener); + } + + /** + * {@inheritdoc} + */ + public function removeSubscriber(EventSubscriberInterface $subscriber) + { + return $this->dispatcher->removeSubscriber($subscriber); + } + + /** + * {@inheritdoc} + */ + public function getListeners($eventName = null) + { + return $this->dispatcher->getListeners($eventName); + } + + /** + * {@inheritdoc} + */ + public function hasListeners($eventName = null) + { + return $this->dispatcher->hasListeners($eventName); + } + + /** + * {@inheritdoc} + */ + public function dispatch($eventName, Event $event = null) + { + if (null === $event) { + $event = new Event(); + } + + $this->preProcess($eventName); + $this->preDispatch($eventName, $event); + + $e = $this->stopwatch->start($eventName, 'section'); + + $this->dispatcher->dispatch($eventName, $event); + + if ($e->isStarted()) { + $e->stop(); + } + + $this->postDispatch($eventName, $event); + $this->postProcess($eventName); + + return $event; + } + + /** + * {@inheritdoc} + */ + public function getCalledListeners() + { + $called = array(); + foreach ($this->called as $eventName => $listeners) { + foreach ($listeners as $listener) { + $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName); + $called[$eventName.'.'.$info['pretty']] = $info; + } + } + + return $called; + } + + /** + * {@inheritdoc} + */ + public function getNotCalledListeners() + { + try { + $allListeners = $this->getListeners(); + } catch (\Exception $e) { + if (null !== $this->logger) { + $this->logger->info(sprintf('An exception was thrown while getting the uncalled listeners (%s)', $e->getMessage()), array('exception' => $e)); + } + + // unable to retrieve the uncalled listeners + return array(); + } + + $notCalled = array(); + foreach ($allListeners as $eventName => $listeners) { + foreach ($listeners as $listener) { + $called = false; + if (isset($this->called[$eventName])) { + foreach ($this->called[$eventName] as $l) { + if ($l->getWrappedListener() === $listener) { + $called = true; + + break; + } + } + } + + if (!$called) { + $info = $this->getListenerInfo($listener, $eventName); + $notCalled[$eventName.'.'.$info['pretty']] = $info; + } + } + } + + return $notCalled; + } + + /** + * Proxies all method calls to the original event dispatcher. + * + * @param string $method The method name + * @param array $arguments The method arguments + * + * @return mixed + */ + public function __call($method, $arguments) + { + return call_user_func_array(array($this->dispatcher, $method), $arguments); + } + + /** + * Called before dispatching the event. + * + * @param string $eventName The event name + * @param Event $event The event + */ + protected function preDispatch($eventName, Event $event) + { + } + + /** + * Called after dispatching the event. + * + * @param string $eventName The event name + * @param Event $event The event + */ + protected function postDispatch($eventName, Event $event) + { + } + + private function preProcess($eventName) + { + foreach ($this->dispatcher->getListeners($eventName) as $listener) { + $this->dispatcher->removeListener($eventName, $listener); + $info = $this->getListenerInfo($listener, $eventName); + $name = isset($info['class']) ? $info['class'] : $info['type']; + $this->dispatcher->addListener($eventName, new WrappedListener($listener, $name, $this->stopwatch)); + } + } + + private function postProcess($eventName) + { + $skipped = false; + foreach ($this->dispatcher->getListeners($eventName) as $listener) { + // Unwrap listener + $this->dispatcher->removeListener($eventName, $listener); + $this->dispatcher->addListener($eventName, $listener->getWrappedListener()); + + $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName); + if ($listener->wasCalled()) { + if (null !== $this->logger) { + $this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty'])); + } + + if (!isset($this->called[$eventName])) { + $this->called[$eventName] = new \SplObjectStorage(); + } + + $this->called[$eventName]->attach($listener); + } + + if (null !== $this->logger && $skipped) { + $this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName)); + } + + if ($listener->stoppedPropagation()) { + if (null !== $this->logger) { + $this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName)); + } + + $skipped = true; + } + } + } + + /** + * Returns information about the listener + * + * @param object $listener The listener + * @param string $eventName The event name + * + * @return array Information about the listener + */ + private function getListenerInfo($listener, $eventName) + { + $info = array( + 'event' => $eventName, + ); + if ($listener instanceof \Closure) { + $info += array( + 'type' => 'Closure', + 'pretty' => 'closure' + ); + } elseif (is_string($listener)) { + try { + $r = new \ReflectionFunction($listener); + $file = $r->getFileName(); + $line = $r->getStartLine(); + } catch (\ReflectionException $e) { + $file = null; + $line = null; + } + $info += array( + 'type' => 'Function', + 'function' => $listener, + 'file' => $file, + 'line' => $line, + 'pretty' => $listener, + ); + } elseif (is_array($listener) || (is_object($listener) && is_callable($listener))) { + if (!is_array($listener)) { + $listener = array($listener, '__invoke'); + } + $class = is_object($listener[0]) ? get_class($listener[0]) : $listener[0]; + try { + $r = new \ReflectionMethod($class, $listener[1]); + $file = $r->getFileName(); + $line = $r->getStartLine(); + } catch (\ReflectionException $e) { + $file = null; + $line = null; + } + $info += array( + 'type' => 'Method', + 'class' => $class, + 'method' => $listener[1], + 'file' => $file, + 'line' => $line, + 'pretty' => $class.'::'.$listener[1], + ); + } + + return $info; + } +} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php new file mode 100644 index 0000000000..5483e81506 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Debug; + +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * @author Fabien Potencier + */ +interface TraceableEventDispatcherInterface extends EventDispatcherInterface +{ + /** + * Gets the called listeners. + * + * @return array An array of called listeners + */ + public function getCalledListeners(); + + /** + * Gets the not called listeners. + * + * @return array An array of not called listeners + */ + public function getNotCalledListeners(); +} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/WrappedListener.php b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/WrappedListener.php new file mode 100644 index 0000000000..c501662b07 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/WrappedListener.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Debug; + +use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * @author Fabien Potencier + */ +class WrappedListener +{ + private $listener; + private $name; + private $called; + private $stoppedPropagation; + private $stopwatch; + + public function __construct($listener, $name, Stopwatch $stopwatch) + { + $this->listener = $listener; + $this->name = $name; + $this->stopwatch = $stopwatch; + $this->called = false; + $this->stoppedPropagation = false; + } + + public function getWrappedListener() + { + return $this->listener; + } + + public function wasCalled() + { + return $this->called; + } + + public function stoppedPropagation() + { + return $this->stoppedPropagation; + } + + public function __invoke(Event $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->called = true; + + $e = $this->stopwatch->start($this->name, 'event_listener'); + + call_user_func($this->listener, $event, $eventName, $dispatcher); + + if ($e->isStarted()) { + $e->stop(); + } + + if ($event->isPropagationStopped()) { + $this->stoppedPropagation = true; + } + } +} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php new file mode 100644 index 0000000000..afe3ecd182 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; + +/** + * Compiler pass to register tagged services for an event dispatcher. + */ +class RegisterListenersPass implements CompilerPassInterface +{ + /** + * @var string + */ + protected $dispatcherService; + + /** + * @var string + */ + protected $listenerTag; + + /** + * @var string + */ + protected $subscriberTag; + + /** + * Constructor. + * + * @param string $dispatcherService Service name of the event dispatcher in processed container + * @param string $listenerTag Tag name used for listener + * @param string $subscriberTag Tag name used for subscribers + */ + public function __construct($dispatcherService = 'event_dispatcher', $listenerTag = 'kernel.event_listener', $subscriberTag = 'kernel.event_subscriber') + { + $this->dispatcherService = $dispatcherService; + $this->listenerTag = $listenerTag; + $this->subscriberTag = $subscriberTag; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) { + return; + } + + $definition = $container->findDefinition($this->dispatcherService); + + foreach ($container->findTaggedServiceIds($this->listenerTag) as $id => $events) { + $def = $container->getDefinition($id); + if (!$def->isPublic()) { + throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event listeners are lazy-loaded.', $id)); + } + + if ($def->isAbstract()) { + throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event listeners are lazy-loaded.', $id)); + } + + foreach ($events as $event) { + $priority = isset($event['priority']) ? $event['priority'] : 0; + + if (!isset($event['event'])) { + throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); + } + + if (!isset($event['method'])) { + $event['method'] = 'on'.preg_replace_callback(array( + '/(?<=\b)[a-z]/i', + '/[^a-z0-9]/i', + ), function ($matches) { return strtoupper($matches[0]); }, $event['event']); + $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); + } + + $definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority)); + } + } + + foreach ($container->findTaggedServiceIds($this->subscriberTag) as $id => $attributes) { + $def = $container->getDefinition($id); + if (!$def->isPublic()) { + throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id)); + } + + // We must assume that the class value has been correctly filled, even if the service is created by a factory + $class = $def->getClass(); + + $refClass = new \ReflectionClass($class); + $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; + if (!$refClass->implementsInterface($interface)) { + throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); + } + + $definition->addMethodCall('addSubscriberService', array($id, $class)); + } + } +} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Event.php b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Event.php new file mode 100644 index 0000000000..bf792a2579 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Event.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +/** + * Event is the base class for classes containing event data. + * + * This class contains no event data. It is used by events that do not pass + * state information to an event handler when an event is raised. + * + * You can call the method stopPropagation() to abort the execution of + * further listeners in your event listener. + * + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Bernhard Schussek + * + * @api + */ +class Event +{ + /** + * @var bool Whether no further event listeners should be triggered + */ + private $propagationStopped = false; + + /** + * @var EventDispatcher Dispatcher that dispatched this event + */ + private $dispatcher; + + /** + * @var string This event's name + */ + private $name; + + /** + * Returns whether further event listeners should be triggered. + * + * @see Event::stopPropagation + * @return bool Whether propagation was already stopped for this event. + * + * @api + */ + public function isPropagationStopped() + { + return $this->propagationStopped; + } + + /** + * Stops the propagation of the event to further event listeners. + * + * If multiple event listeners are connected to the same event, no + * further event listener will be triggered once any trigger calls + * stopPropagation(). + * + * @api + */ + public function stopPropagation() + { + $this->propagationStopped = true; + } + + /** + * Stores the EventDispatcher that dispatches this Event + * + * @param EventDispatcherInterface $dispatcher + * + * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call. + * + * @api + */ + public function setDispatcher(EventDispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + } + + /** + * Returns the EventDispatcher that dispatches this Event + * + * @return EventDispatcherInterface + * + * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call. + * + * @api + */ + public function getDispatcher() + { + return $this->dispatcher; + } + + /** + * Gets the event's name. + * + * @return string + * + * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call. + * + * @api + */ + public function getName() + { + return $this->name; + } + + /** + * Sets the event's name property. + * + * @param string $name The event name. + * + * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call. + * + * @api + */ + public function setName($name) + { + $this->name = $name; + } +} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php new file mode 100644 index 0000000000..222a937141 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php @@ -0,0 +1,185 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +/** + * The EventDispatcherInterface is the central point of Symfony's event listener system. + * + * Listeners are registered on the manager and events are dispatched through the + * manager. + * + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Bernhard Schussek + * @author Fabien Potencier + * @author Jordi Boggiano + * @author Jordan Alliot + * + * @api + */ +class EventDispatcher implements EventDispatcherInterface +{ + private $listeners = array(); + private $sorted = array(); + + /** + * @see EventDispatcherInterface::dispatch + * + * @api + */ + public function dispatch($eventName, Event $event = null) + { + if (null === $event) { + $event = new Event(); + } + + $event->setDispatcher($this); + $event->setName($eventName); + + if (!isset($this->listeners[$eventName])) { + return $event; + } + + $this->doDispatch($this->getListeners($eventName), $eventName, $event); + + return $event; + } + + /** + * @see EventDispatcherInterface::getListeners + */ + public function getListeners($eventName = null) + { + if (null !== $eventName) { + if (!isset($this->sorted[$eventName])) { + $this->sortListeners($eventName); + } + + return $this->sorted[$eventName]; + } + + foreach (array_keys($this->listeners) as $eventName) { + if (!isset($this->sorted[$eventName])) { + $this->sortListeners($eventName); + } + } + + return array_filter($this->sorted); + } + + /** + * @see EventDispatcherInterface::hasListeners + */ + public function hasListeners($eventName = null) + { + return (bool) count($this->getListeners($eventName)); + } + + /** + * @see EventDispatcherInterface::addListener + * + * @api + */ + public function addListener($eventName, $listener, $priority = 0) + { + $this->listeners[$eventName][$priority][] = $listener; + unset($this->sorted[$eventName]); + } + + /** + * @see EventDispatcherInterface::removeListener + */ + public function removeListener($eventName, $listener) + { + if (!isset($this->listeners[$eventName])) { + return; + } + + foreach ($this->listeners[$eventName] as $priority => $listeners) { + if (false !== ($key = array_search($listener, $listeners, true))) { + unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]); + } + } + } + + /** + * @see EventDispatcherInterface::addSubscriber + * + * @api + */ + public function addSubscriber(EventSubscriberInterface $subscriber) + { + foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { + if (is_string($params)) { + $this->addListener($eventName, array($subscriber, $params)); + } elseif (is_string($params[0])) { + $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0); + } else { + foreach ($params as $listener) { + $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0); + } + } + } + } + + /** + * @see EventDispatcherInterface::removeSubscriber + */ + public function removeSubscriber(EventSubscriberInterface $subscriber) + { + foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { + if (is_array($params) && is_array($params[0])) { + foreach ($params as $listener) { + $this->removeListener($eventName, array($subscriber, $listener[0])); + } + } else { + $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0])); + } + } + } + + /** + * Triggers the listeners of an event. + * + * This method can be overridden to add functionality that is executed + * for each listener. + * + * @param callable[] $listeners The event listeners. + * @param string $eventName The name of the event to dispatch. + * @param Event $event The event object to pass to the event handlers/listeners. + */ + protected function doDispatch($listeners, $eventName, Event $event) + { + foreach ($listeners as $listener) { + call_user_func($listener, $event, $eventName, $this); + if ($event->isPropagationStopped()) { + break; + } + } + } + + /** + * Sorts the internal list of listeners for the given event by priority. + * + * @param string $eventName The name of the event. + */ + private function sortListeners($eventName) + { + $this->sorted[$eventName] = array(); + + if (isset($this->listeners[$eventName])) { + krsort($this->listeners[$eventName]); + $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); + } + } +} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcherInterface.php new file mode 100644 index 0000000000..3fdbfd8822 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcherInterface.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +/** + * The EventDispatcherInterface is the central point of Symfony's event listener system. + * Listeners are registered on the manager and events are dispatched through the + * manager. + * + * @author Bernhard Schussek + * + * @api + */ +interface EventDispatcherInterface +{ + /** + * Dispatches an event to all registered listeners. + * + * @param string $eventName The name of the event to dispatch. The name of + * the event is the name of the method that is + * invoked on listeners. + * @param Event $event The event to pass to the event handlers/listeners. + * If not supplied, an empty Event instance is created. + * + * @return Event + * + * @api + */ + public function dispatch($eventName, Event $event = null); + + /** + * Adds an event listener that listens on the specified events. + * + * @param string $eventName The event to listen on + * @param callable $listener The listener + * @param int $priority The higher this value, the earlier an event + * listener will be triggered in the chain (defaults to 0) + * + * @api + */ + public function addListener($eventName, $listener, $priority = 0); + + /** + * Adds an event subscriber. + * + * The subscriber is asked for all the events he is + * interested in and added as a listener for these events. + * + * @param EventSubscriberInterface $subscriber The subscriber. + * + * @api + */ + public function addSubscriber(EventSubscriberInterface $subscriber); + + /** + * Removes an event listener from the specified events. + * + * @param string|array $eventName The event(s) to remove a listener from + * @param callable $listener The listener to remove + */ + public function removeListener($eventName, $listener); + + /** + * Removes an event subscriber. + * + * @param EventSubscriberInterface $subscriber The subscriber + */ + public function removeSubscriber(EventSubscriberInterface $subscriber); + + /** + * Gets the listeners of a specific event or all listeners. + * + * @param string $eventName The name of the event + * + * @return array The event listeners for the specified event, or all event listeners by event name + */ + public function getListeners($eventName = null); + + /** + * Checks whether an event has any registered listeners. + * + * @param string $eventName The name of the event + * + * @return bool true if the specified event has any listeners, false otherwise + */ + public function hasListeners($eventName = null); +} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventSubscriberInterface.php b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventSubscriberInterface.php new file mode 100644 index 0000000000..080f892fdf --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventSubscriberInterface.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +/** + * An EventSubscriber knows himself what events he is interested in. + * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes + * {@link getSubscribedEvents} and registers the subscriber as a listener for all + * returned events. + * + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Bernhard Schussek + * + * @api + */ +interface EventSubscriberInterface +{ + /** + * Returns an array of event names this subscriber wants to listen to. + * + * The array keys are event names and the value can be: + * + * * The method name to call (priority defaults to 0) + * * An array composed of the method name to call and the priority + * * An array of arrays composed of the method names to call and respective + * priorities, or 0 if unset + * + * For instance: + * + * * array('eventName' => 'methodName') + * * array('eventName' => array('methodName', $priority)) + * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) + * + * @return array The event names to listen to + * + * @api + */ + public static function getSubscribedEvents(); +} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/GenericEvent.php b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/GenericEvent.php new file mode 100644 index 0000000000..1e8c44a678 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/GenericEvent.php @@ -0,0 +1,186 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +/** + * Event encapsulation class. + * + * Encapsulates events thus decoupling the observer from the subject they encapsulate. + * + * @author Drak + */ +class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate +{ + /** + * Event subject. + * + * @var mixed usually object or callable + */ + protected $subject; + + /** + * Array of arguments. + * + * @var array + */ + protected $arguments; + + /** + * Encapsulate an event with $subject and $args. + * + * @param mixed $subject The subject of the event, usually an object. + * @param array $arguments Arguments to store in the event. + */ + public function __construct($subject = null, array $arguments = array()) + { + $this->subject = $subject; + $this->arguments = $arguments; + } + + /** + * Getter for subject property. + * + * @return mixed $subject The observer subject. + */ + public function getSubject() + { + return $this->subject; + } + + /** + * Get argument by key. + * + * @param string $key Key. + * + * @throws \InvalidArgumentException If key is not found. + * + * @return mixed Contents of array key. + */ + public function getArgument($key) + { + if ($this->hasArgument($key)) { + return $this->arguments[$key]; + } + + throw new \InvalidArgumentException(sprintf('%s not found in %s', $key, $this->getName())); + } + + /** + * Add argument to event. + * + * @param string $key Argument name. + * @param mixed $value Value. + * + * @return GenericEvent + */ + public function setArgument($key, $value) + { + $this->arguments[$key] = $value; + + return $this; + } + + /** + * Getter for all arguments. + * + * @return array + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Set args property. + * + * @param array $args Arguments. + * + * @return GenericEvent + */ + public function setArguments(array $args = array()) + { + $this->arguments = $args; + + return $this; + } + + /** + * Has argument. + * + * @param string $key Key of arguments array. + * + * @return bool + */ + public function hasArgument($key) + { + return array_key_exists($key, $this->arguments); + } + + /** + * ArrayAccess for argument getter. + * + * @param string $key Array key. + * + * @throws \InvalidArgumentException If key does not exist in $this->args. + * + * @return mixed + */ + public function offsetGet($key) + { + return $this->getArgument($key); + } + + /** + * ArrayAccess for argument setter. + * + * @param string $key Array key to set. + * @param mixed $value Value. + */ + public function offsetSet($key, $value) + { + $this->setArgument($key, $value); + } + + /** + * ArrayAccess for unset argument. + * + * @param string $key Array key. + */ + public function offsetUnset($key) + { + if ($this->hasArgument($key)) { + unset($this->arguments[$key]); + } + } + + /** + * ArrayAccess has argument. + * + * @param string $key Array key. + * + * @return bool + */ + public function offsetExists($key) + { + return $this->hasArgument($key); + } + + /** + * IteratorAggregate for iterating over the object like an array + * + * @return \ArrayIterator + */ + public function getIterator() + { + return new \ArrayIterator($this->arguments); + } +} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php new file mode 100644 index 0000000000..b70b81a8b2 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +/** + * A read-only proxy for an event dispatcher. + * + * @author Bernhard Schussek + */ +class ImmutableEventDispatcher implements EventDispatcherInterface +{ + /** + * The proxied dispatcher. + * @var EventDispatcherInterface + */ + private $dispatcher; + + /** + * Creates an unmodifiable proxy for an event dispatcher. + * + * @param EventDispatcherInterface $dispatcher The proxied event dispatcher. + */ + public function __construct(EventDispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + } + + /** + * {@inheritdoc} + */ + public function dispatch($eventName, Event $event = null) + { + return $this->dispatcher->dispatch($eventName, $event); + } + + /** + * {@inheritdoc} + */ + public function addListener($eventName, $listener, $priority = 0) + { + throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); + } + + /** + * {@inheritdoc} + */ + public function addSubscriber(EventSubscriberInterface $subscriber) + { + throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); + } + + /** + * {@inheritdoc} + */ + public function removeListener($eventName, $listener) + { + throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); + } + + /** + * {@inheritdoc} + */ + public function removeSubscriber(EventSubscriberInterface $subscriber) + { + throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); + } + + /** + * {@inheritdoc} + */ + public function getListeners($eventName = null) + { + return $this->dispatcher->getListeners($eventName); + } + + /** + * {@inheritdoc} + */ + public function hasListeners($eventName = null) + { + return $this->dispatcher->hasListeners($eventName); + } +} diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/LICENSE b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/LICENSE new file mode 100644 index 0000000000..0b3292cf90 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2014 Fabien Potencier + +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. diff --git a/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/README.md b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/README.md new file mode 100644 index 0000000000..22bf74fdc9 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/README.md @@ -0,0 +1,25 @@ +EventDispatcher Component +========================= + +The Symfony2 EventDispatcher component implements the Mediator pattern in a +simple and effective way to make your projects truly extensible. + + use Symfony\Component\EventDispatcher\EventDispatcher; + use Symfony\Component\EventDispatcher\Event; + + $dispatcher = new EventDispatcher(); + + $dispatcher->addListener('event_name', function (Event $event) { + // ... + }); + + $dispatcher->dispatch('event_name'); + +Resources +--------- + +You can run the unit tests with the following command: + + $ cd path/to/Symfony/Component/EventDispatcher/ + $ composer.phar install + $ phpunit From cb4428068d577f43a6b28657d34df080bb79f644 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 19 Aug 2014 19:10:00 -0600 Subject: [PATCH 34/63] #18 Refactoring per the new page events system --- system/src/Grav/Common/Grav.php | 10 +++++----- system/src/Grav/Common/Page/Page.php | 2 +- system/src/Grav/Common/Page/Pages.php | 6 +++--- system/src/Grav/Common/Twig.php | 12 ++++++------ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index d4dd899d60..19e6228820 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -118,23 +118,23 @@ public function process() $this['plugins']->init(); - $this->fireEvent('onAfterInitPlugins'); + $this->fireEvent('onPluginsInitialized'); $this['assets']->init(); - $this->fireEvent('onAfterGetAssets'); + $this->fireEvent('onAssetsInitialized'); $this['twig']->init(); $this['pages']->init(); - $this->fireEvent('onAfterGetPages'); + $this->fireEvent('onPagesInitialized'); - $this->fireEvent('onAfterGetPage'); + $this->fireEvent('onPageInitialized'); // Process whole page as required $this->output = $this['output']; - $this->fireEvent('onAfterGetOutput'); + $this->fireEvent('onOutputGenerated'); // Set the header type $this->header(); diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index dfced9a75a..21472ac1b6 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -1331,7 +1331,7 @@ public function collection($params = 'content') $grav = self::$grav['grav']; // New Custom event to handle things like pagination. - $grav->fireEvent('onAfterCollectionProcessed', new Event(['collection' => $collection])); + $grav->fireEvent('onCollectionProcessed', new Event(['collection' => $collection])); $params = $collection->params(); diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index f853b97ff3..24da249f3f 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -270,7 +270,7 @@ public function blueprints($type) } if (!$blueprint->initialized) { - $this->grav->fireEvent('onCreateBlueprint', new Event(['blueprint' => $blueprint])); + $this->grav->fireEvent('onBlueprintCreated', new Event(['blueprint' => $blueprint])); $blueprint->initialized = true; } @@ -421,7 +421,7 @@ protected function recurse($directory = PAGES_DIR, Page &$parent = null) $page->init($file); if ($config->get('system.pages.events.page')) { - $this->grav->fireEvent('onAfterPageProcessed', new Event(['page' => $page])); + $this->grav->fireEvent('onPageProcessed', new Event(['page' => $page])); } } elseif ($file->isDir() && !$file->isDot()) { @@ -448,7 +448,7 @@ protected function recurse($directory = PAGES_DIR, Page &$parent = null) $this->lastModified($file->getMTime()); if ($config->get('system.pages.events.page')) { - $this->grav->fireEvent('onAfterFolderProcessed', new Event(['page' => $page])); + $this->grav->fireEvent('onFolderProcessed', new Event(['page' => $page])); } } } diff --git a/system/src/Grav/Common/Twig.php b/system/src/Grav/Common/Twig.php index 38eec6c214..2f2ec7e7f0 100644 --- a/system/src/Grav/Common/Twig.php +++ b/system/src/Grav/Common/Twig.php @@ -67,7 +67,7 @@ public function init() $config = $this->grav['config']; $this->twig_paths = array(THEMES_DIR . $config->get('system.pages.theme') . '/templates'); - $this->grav->fireEvent('onAfterTwigTemplatesPaths'); + $this->grav->fireEvent('onTwigTemplatePaths'); $this->loader = new \Twig_Loader_Filesystem($this->twig_paths); $this->loaderArray = new \Twig_Loader_Array(array()); @@ -79,7 +79,7 @@ public function init() } $this->twig = new \Twig_Environment($loader_chain, $params); - $this->grav->fireEvent('onAfterTwigInit'); + $this->grav->fireEvent('onTwigInitialized'); // set default date format if set in config if ($config->get('system.pages.dateformat.long')) { @@ -90,7 +90,7 @@ public function init() $this->twig->addExtension(new \Twig_Extension_Debug()); } $this->twig->addExtension(new TwigExtension()); - $this->grav->fireEvent('onAfterTwigExtensions'); + $this->grav->fireEvent('onTwigExtensions'); $baseUrlAbsolute = $config->get('system.base_url_absolute'); $baseUrlRelative = $config->get('system.base_url_relative'); @@ -158,7 +158,7 @@ public function processPage(Page $item, $content = null) $content = $content !== null ? $content : $item->content(); // override the twig header vars for local resolution - $this->grav->fireEvent('onAfterTwigPageVars'); + $this->grav->fireEvent('onTwigPageVariables'); $twig_vars = $this->twig_vars; $twig_vars['page'] = $item; @@ -188,7 +188,7 @@ public function processPage(Page $item, $content = null) public function processString($string, array $vars = array()) { // override the twig header vars for local resolution - $this->grav->fireEvent('onAfterTwigVars'); + $this->grav->fireEvent('onTwigStringVariables'); $vars += $this->twig_vars; $name = '@Var:' . $string; @@ -209,7 +209,7 @@ public function processString($string, array $vars = array()) public function processSite($format = null) { // set the page now its been processed - $this->grav->fireEvent('onAfterTwigSiteVars'); + $this->grav->fireEvent('onTwigSiteVariables'); $twig_vars = $this->twig_vars; $pages = $this->grav['pages']; $page = $this->grav['page']; From 49244c3f0bc7a7c349826a98d6f2130cf0151e03 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 19 Aug 2014 21:57:29 -0600 Subject: [PATCH 35/63] made $grav public so its accessible in plugins --- system/src/Grav/Common/Twig.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/system/src/Grav/Common/Twig.php b/system/src/Grav/Common/Twig.php index 2f2ec7e7f0..c89be41e3f 100644 --- a/system/src/Grav/Common/Twig.php +++ b/system/src/Grav/Common/Twig.php @@ -13,15 +13,10 @@ */ class Twig { - /** - * @var Grav - */ - protected $grav; - /** * @var \Twig_Environment */ - protected $twig; + public $twig; /** * @var array @@ -38,6 +33,11 @@ class Twig */ public $template; + /** + * @var Grav + */ + protected $grav; + /** * @var \Twig_Loader_Filesystem */ @@ -48,6 +48,7 @@ class Twig */ protected $loaderArray; + /** * Constructor */ From 05b22965949d601f23ed43ee4b8defb89b80cdd7 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 19 Aug 2014 21:57:44 -0600 Subject: [PATCH 36/63] more semantic naming of variables --- system/src/Grav/Common/Cache.php | 78 +++++++++++++++++--------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/system/src/Grav/Common/Cache.php b/system/src/Grav/Common/Cache.php index 3b92b28499..d3592b3895 100644 --- a/system/src/Grav/Common/Cache.php +++ b/system/src/Grav/Common/Cache.php @@ -37,35 +37,64 @@ class Cache extends Getters /** * Constructor * - * @params Grav $c + * @params Grav $grav */ - public function __construct(Grav $c) + public function __construct(Grav $grav) { - $this->init($c); + $this->init($grav); } /** * Initialization that sets a base key and the driver based on configuration settings * - * @param Grav $c + * @param Grav $grav * @return void */ - public function init(Grav $c) + public function init(Grav $grav) { /** @var Config $config */ - $config = $c['config']; + $this->config = $grav['config']; /** @var Uri $uri */ - $uri = $c['uri']; + $uri = $grav['uri']; - $prefix = $config->get('system.cache.prefix'); + $prefix = $this->config->get('system.cache.prefix'); - $this->enabled = (bool) $config->get('system.cache.enabled'); + $this->enabled = (bool) $this->config->get('system.cache.enabled'); // Cache key allows us to invalidate all cache on configuration changes. - $this->key = substr(md5(($prefix ? $prefix : 'g') . $uri->rootUrl(true) . $config->key . GRAV_VERSION), 2, 8); + $this->key = substr(md5(($prefix ? $prefix : 'g') . $uri->rootUrl(true) . $this->config->key . GRAV_VERSION), 2, 8); - switch ($this->getCacheDriverName($config->get('system.cache.driver'))) { + $this->driver = $this->getCacheDriver(); + } + + /** + * Automatically picks the cache mechanism to use. If you pick one manually it will use that + * If there is no config option for $driver in the config, or it's set to 'auto', it will + * pick the best option based on which cache extensions are installed. + * + * @return DoctrineCacheDriver The cache driver to use + */ + public function getCacheDriver() + { + $setting = $this->config->get('system.cache.driver'); + $driver_name = 'file'; + + if (!$setting || $setting == 'auto') { + if (extension_loaded('apc')) { + $driver_name = 'apc'; + } elseif (extension_loaded('wincache')) { + $driver_name = 'wincache'; + } elseif (extension_loaded('xcache')) { + $driver_name = 'xcache'; + } elseif (extension_loaded('memcache')) { + $driver_name = 'memcache'; + } + } else { + $driver_name = $setting; + } + + switch ($driver_name) { case 'apc': $driver = new \Doctrine\Common\Cache\ApcCache(); break; @@ -90,33 +119,8 @@ public function init(Grav $c) $driver = new \Doctrine\Common\Cache\FilesystemCache(CACHE_DIR); break; } - $this->driver = $driver; - } - /** - * Automatically picks the cache mechanism to use. If you pick one manually it will use that - * If there is no config option for $driver in the config, or it's set to 'auto', it will - * pick the best option based on which cache extensions are installed. - * - * @param string $setting - * @return string The name of the best cache driver to use - */ - protected function getCacheDriverName($setting = null) - { - - if (!$setting || $setting == 'auto') { - if (extension_loaded('apc') && ini_get('apc.enabled')) { - return 'apc'; - } elseif (extension_loaded('wincache')) { - return 'wincache'; - } elseif (extension_loaded('xcache') && ini_get('xcache.size') && ini_get('xcache.cacher')) { - return 'xcache'; - } else { - return 'file'; - } - } else { - return $setting; - } + return $driver; } /** From 77172e7978943550e42b8ac70a7ce114129cde88 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 20 Aug 2014 12:18:26 +0300 Subject: [PATCH 37/63] Optimize autoloading and allow APC to cache plugin PHP --- bin/grav | 2 +- composer.json | 26 ++++++++++++++++---------- index.php | 8 ++------ system/autoload.php | 8 -------- system/src/Grav/Common/Grav.php | 8 ++++++++ system/src/Grav/Common/Plugins.php | 2 +- 6 files changed, 28 insertions(+), 26 deletions(-) delete mode 100644 system/autoload.php diff --git a/bin/grav b/bin/grav index 37b41e86cd..e886be3228 100755 --- a/bin/grav +++ b/bin/grav @@ -3,7 +3,7 @@ use Symfony\Component\Console\Application; -require_once(__DIR__ . '/../system/autoload.php'); +require_once(__DIR__ . '/../vendor/autoload.php'); if (!ini_get('date.timezone')) { date_default_timezone_set('UTC'); diff --git a/composer.json b/composer.json index 5b29130064..c12e41accf 100644 --- a/composer.json +++ b/composer.json @@ -13,17 +13,23 @@ ], "require": { "php": ">=5.4.0", - "twig/twig": "1.16.*@dev", - "erusev/parsedown-extra": "dev-master", - "symfony/yaml": "2.5.*@dev", - "symfony/console": "2.5.*@dev", - "symfony/event-dispatcher": "2.5.*@dev", - "doctrine/cache": "1.4.*@dev", - "tracy/tracy": "dev-master", - "gregwar/image": "dev-master", + "twig/twig": "~1.16", + "erusev/parsedown-extra": "~0.2", + "symfony/yaml": "~2.5", + "symfony/console": "~2.5", + "symfony/event-dispatcher": "~2.5", + "doctrine/cache": "~1.3", + "tracy/tracy": "~2.2", + "gregwar/image": "~2.0", "ircmaxell/password-compat": "1.0.*", - "mrclay/minify": "dev-master", - "ornicar/php-user-agent": "1.0.*@dev", + "mrclay/minify": "~2.2", + "ornicar/php-user-agent": "1.0.*", "pimple/pimple": "~3.0" + }, + "autoload": { + "psr-4": { + "Grav\\": "system/src/" + }, + "files": ["system/defines.php"] } } diff --git a/index.php b/index.php index b9ead227d5..796beaf862 100644 --- a/index.php +++ b/index.php @@ -8,8 +8,8 @@ use Grav\Common\Grav; use Grav\Common\Debugger; -// Register system libraries to the auto-loader. -$loader = require_once __DIR__ . '/system/autoload.php'; +// Register the auto-loader. +$loader = require_once __DIR__ . '/vendor/autoload.php'; if (!ini_get('date.timezone')) { date_default_timezone_set('UTC'); @@ -22,9 +22,6 @@ ] ); -// Use output buffering to prevent headers from being sent too early. -ob_start(); - try { $grav['debugger']->init(); $grav->process(); @@ -34,4 +31,3 @@ throw $e; } -ob_end_flush(); diff --git a/system/autoload.php b/system/autoload.php deleted file mode 100644 index 7419fb852a..0000000000 --- a/system/autoload.php +++ /dev/null @@ -1,8 +0,0 @@ -addPsr4('Grav\\', LIB_DIR . 'Grav'); - -return $loader; diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 19e6228820..16854a486a 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -113,6 +113,9 @@ protected static function load(array $values) public function process() { + // Use output buffering to prevent headers from being sent too early. + ob_start(); + // Initialize stream wrappers. $this['locator']; @@ -140,6 +143,11 @@ public function process() $this->header(); echo $this->output; + + ob_end_flush(); + flush(); + + $this->fireEvent('onOutputRendered'); } /** diff --git a/system/src/Grav/Common/Plugins.php b/system/src/Grav/Common/Plugins.php index e1b336f587..624c76c4ce 100644 --- a/system/src/Grav/Common/Plugins.php +++ b/system/src/Grav/Common/Plugins.php @@ -41,7 +41,7 @@ public function init() continue; } - $filePath = 'plugin://' . $plugin . DS . $plugin . PLUGIN_EXT; + $filePath = $this->grav['locator']('plugin://' . $plugin . DS . $plugin . PLUGIN_EXT); if (!is_file($filePath)) { throw new \RuntimeException(sprintf("Plugin '%s' enabled but not found!", $filePath, $plugin)); } From a6483f03339b5752f3b19a2354385c59ca2baed5 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 20 Aug 2014 14:51:03 +0300 Subject: [PATCH 38/63] Prevent fatal error when composer hasn't been run --- composer.json | 3 +++ index.php | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c12e41accf..c1b629b1c0 100644 --- a/composer.json +++ b/composer.json @@ -31,5 +31,8 @@ "Grav\\": "system/src/" }, "files": ["system/defines.php"] + }, + "archive": { + "exclude": ["VERSION"] } } diff --git a/index.php b/index.php index 796beaf862..1137ea3ca9 100644 --- a/index.php +++ b/index.php @@ -4,12 +4,16 @@ if (version_compare($ver = PHP_VERSION, $req = '5.4.0', '<')) { exit(sprintf('You are running PHP %s, but Grav needs at least PHP %s to run.', $ver, $req)); } +$autoload = __DIR__ . '/vendor/autoload.php'; +if (!is_file($autoload)) { + exit('Please run: composer install -o'); +} use Grav\Common\Grav; use Grav\Common\Debugger; // Register the auto-loader. -$loader = require_once __DIR__ . '/vendor/autoload.php'; +$loader = require_once $autoload; if (!ini_get('date.timezone')) { date_default_timezone_set('UTC'); From 9d0e917e60d23d062333a0df1952851615c7806d Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 20 Aug 2014 09:25:34 -0600 Subject: [PATCH 39/63] vendor commits --- vendor/autoload.php | 2 +- vendor/composer/autoload_classmap.php | 353 +++++++++++- vendor/composer/autoload_files.php | 5 +- vendor/composer/autoload_psr4.php | 1 + vendor/composer/autoload_real.php | 10 +- vendor/composer/installed.json | 540 +++++++++--------- .../Doctrine/Common/Cache/CacheProvider.php | 6 +- .../lib/Doctrine/Common/Cache/FileCache.php | 2 +- .../Doctrine/Common/Cache/FilesystemCache.php | 16 +- .../lib/Doctrine/Common/Cache/Version.php | 2 +- vendor/gregwar/cache/Gregwar/Cache/Cache.php | 80 ++- vendor/gregwar/image/Gregwar/Image/Image.php | 8 +- vendor/mrclay/minify/HISTORY.txt | 3 - .../minify/min/lib/Minify/CSS/UriRewriter.php | 4 +- .../minify/min/lib/Minify/Cache/File.php | 3 - .../minify/min/lib/Minify/ClosureCompiler.php | 42 +- vendor/ornicar/php-user-agent/CHANGELOG.md | 8 +- .../Console/Formatter/OutputFormatter.php | 6 +- vendor/tracy/tracy/readme.md | 2 +- vendor/tracy/tracy/src/Tracy/BlueScreen.php | 9 - vendor/tracy/tracy/src/Tracy/Debugger.php | 481 +++++++++------- vendor/tracy/tracy/src/Tracy/Dumper.php | 28 +- vendor/tracy/tracy/src/Tracy/FireLogger.php | 39 +- vendor/tracy/tracy/src/Tracy/Helpers.php | 50 +- vendor/tracy/tracy/src/Tracy/ILogger.php | 27 - vendor/tracy/tracy/src/Tracy/Logger.php | 105 +--- .../tracy/tracy/src/Tracy/OutputDebugger.php | 1 - .../tracy/tracy/src/Tracy/templates/bar.phtml | 7 + .../tracy/src/Tracy/templates/bluescreen.css | 19 +- .../src/Tracy/templates/bluescreen.phtml | 44 +- vendor/tracy/tracy/src/tracy.php | 3 +- vendor/twig/twig/CHANGELOG | 5 - vendor/twig/twig/lib/Twig/Compiler.php | 9 +- vendor/twig/twig/lib/Twig/Environment.php | 2 +- .../twig/twig/lib/Twig/ExpressionParser.php | 2 +- vendor/twig/twig/lib/Twig/Extension/Core.php | 6 +- vendor/twig/twig/lib/Twig/Node/AutoEscape.php | 2 +- vendor/twig/twig/lib/Twig/Node/Block.php | 2 +- .../twig/lib/Twig/Node/BlockReference.php | 2 +- vendor/twig/twig/lib/Twig/Node/Do.php | 2 +- .../twig/lib/Twig/Node/Expression/Array.php | 2 +- .../lib/Twig/Node/Expression/AssignName.php | 2 +- .../twig/lib/Twig/Node/Expression/Binary.php | 2 +- .../Twig/Node/Expression/Binary/EndsWith.php | 10 +- .../Twig/Node/Expression/Binary/FloorDiv.php | 2 +- .../lib/Twig/Node/Expression/Binary/In.php | 2 +- .../lib/Twig/Node/Expression/Binary/NotIn.php | 2 +- .../lib/Twig/Node/Expression/Binary/Power.php | 2 +- .../lib/Twig/Node/Expression/Binary/Range.php | 2 +- .../Node/Expression/Binary/StartsWith.php | 8 +- .../Twig/Node/Expression/BlockReference.php | 2 +- .../Node/Expression/ExtensionReference.php | 2 +- .../twig/lib/Twig/Node/Expression/GetAttr.php | 34 +- .../twig/lib/Twig/Node/Expression/Parent.php | 2 +- vendor/twig/twig/lib/Twig/Node/Flush.php | 2 +- vendor/twig/twig/lib/Twig/Node/For.php | 2 +- vendor/twig/twig/lib/Twig/Node/ForLoop.php | 2 +- vendor/twig/twig/lib/Twig/Node/If.php | 2 +- vendor/twig/twig/lib/Twig/Node/Import.php | 2 +- vendor/twig/twig/lib/Twig/Node/Include.php | 46 +- vendor/twig/twig/lib/Twig/Node/Macro.php | 2 +- vendor/twig/twig/lib/Twig/Node/Module.php | 2 +- vendor/twig/twig/lib/Twig/Node/Print.php | 2 +- vendor/twig/twig/lib/Twig/Node/Sandbox.php | 2 +- .../twig/lib/Twig/Node/SandboxedPrint.php | 2 +- vendor/twig/twig/lib/Twig/Node/Set.php | 2 +- vendor/twig/twig/lib/Twig/Node/Spaceless.php | 2 +- vendor/twig/twig/lib/Twig/Node/Text.php | 2 +- vendor/twig/twig/lib/Twig/NodeInterface.php | 2 +- vendor/twig/twig/lib/Twig/Template.php | 6 +- 70 files changed, 1137 insertions(+), 955 deletions(-) delete mode 100644 vendor/tracy/tracy/src/Tracy/ILogger.php diff --git a/vendor/autoload.php b/vendor/autoload.php index 3f854dda0c..d84c250d15 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit010a27b310c3146ba53b52651441075a::getLoader(); +return ComposerAutoloaderIniteef751e17db86fa31c0c46c61acf76f4::getLoader(); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 77d51d4810..b6b38da504 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -7,8 +7,102 @@ return array( 'CSSmin' => $vendorDir . '/mrclay/minify/min/lib/CSSmin.php', + 'Doctrine\\Common\\Cache\\ApcCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/ApcCache.php', + 'Doctrine\\Common\\Cache\\ArrayCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/ArrayCache.php', + 'Doctrine\\Common\\Cache\\Cache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php', + 'Doctrine\\Common\\Cache\\CacheProvider' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php', + 'Doctrine\\Common\\Cache\\CouchbaseCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseCache.php', + 'Doctrine\\Common\\Cache\\FileCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php', + 'Doctrine\\Common\\Cache\\FilesystemCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php', + 'Doctrine\\Common\\Cache\\MemcacheCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/MemcacheCache.php', + 'Doctrine\\Common\\Cache\\MemcachedCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/MemcachedCache.php', + 'Doctrine\\Common\\Cache\\MongoDBCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/MongoDBCache.php', + 'Doctrine\\Common\\Cache\\PhpFileCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/PhpFileCache.php', + 'Doctrine\\Common\\Cache\\RedisCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/RedisCache.php', + 'Doctrine\\Common\\Cache\\RiakCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/RiakCache.php', + 'Doctrine\\Common\\Cache\\Version' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/Version.php', + 'Doctrine\\Common\\Cache\\WinCacheCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/WinCacheCache.php', + 'Doctrine\\Common\\Cache\\XcacheCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/XcacheCache.php', + 'Doctrine\\Common\\Cache\\ZendDataCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/ZendDataCache.php', 'DooDigestAuth' => $vendorDir . '/mrclay/minify/min/lib/DooDigestAuth.php', 'FirePHP' => $vendorDir . '/mrclay/minify/min/lib/FirePHP.php', + 'Grav\\Common\\Assets' => $baseDir . '/system/src/Grav/Common/Assets.php', + 'Grav\\Common\\Cache' => $baseDir . '/system/src/Grav/Common/Cache.php', + 'Grav\\Common\\Config' => $baseDir . '/system/src/Grav/Common/Config.php', + 'Grav\\Common\\Data\\Blueprint' => $baseDir . '/system/src/Grav/Common/Data/Blueprint.php', + 'Grav\\Common\\Data\\Blueprints' => $baseDir . '/system/src/Grav/Common/Data/Blueprints.php', + 'Grav\\Common\\Data\\Data' => $baseDir . '/system/src/Grav/Common/Data/Data.php', + 'Grav\\Common\\Data\\DataInterface' => $baseDir . '/system/src/Grav/Common/Data/DataInterface.php', + 'Grav\\Common\\Data\\Validation' => $baseDir . '/system/src/Grav/Common/Data/Validation.php', + 'Grav\\Common\\Debugger' => $baseDir . '/system/src/Grav/Common/Debugger.php', + 'Grav\\Common\\Filesystem\\FileInterface' => $baseDir . '/system/src/Grav/Common/Filesystem/FileInterface.php', + 'Grav\\Common\\Filesystem\\File\\Config' => $baseDir . '/system/src/Grav/Common/Filesystem/File/Config.php', + 'Grav\\Common\\Filesystem\\File\\General' => $baseDir . '/system/src/Grav/Common/Filesystem/File/General.php', + 'Grav\\Common\\Filesystem\\File\\Json' => $baseDir . '/system/src/Grav/Common/Filesystem/File/Json.php', + 'Grav\\Common\\Filesystem\\File\\Log' => $baseDir . '/system/src/Grav/Common/Filesystem/File/Log.php', + 'Grav\\Common\\Filesystem\\File\\Markdown' => $baseDir . '/system/src/Grav/Common/Filesystem/File/Markdown.php', + 'Grav\\Common\\Filesystem\\File\\Yaml' => $baseDir . '/system/src/Grav/Common/Filesystem/File/Yaml.php', + 'Grav\\Common\\Filesystem\\Folder' => $baseDir . '/system/src/Grav/Common/Filesystem/Folder.php', + 'Grav\\Common\\Getters' => $baseDir . '/system/src/Grav/Common/Getters.php', + 'Grav\\Common\\Grav' => $baseDir . '/system/src/Grav/Common/Grav.php', + 'Grav\\Common\\GravTrait' => $baseDir . '/system/src/Grav/Common/GravTrait.php', + 'Grav\\Common\\Inflector' => $baseDir . '/system/src/Grav/Common/Inflector.php', + 'Grav\\Common\\Iterator' => $baseDir . '/system/src/Grav/Common/Iterator.php', + 'Grav\\Common\\Page\\Collection' => $baseDir . '/system/src/Grav/Common/Page/Collection.php', + 'Grav\\Common\\Page\\Media' => $baseDir . '/system/src/Grav/Common/Page/Media.php', + 'Grav\\Common\\Page\\Medium' => $baseDir . '/system/src/Grav/Common/Page/Medium.php', + 'Grav\\Common\\Page\\Page' => $baseDir . '/system/src/Grav/Common/Page/Page.php', + 'Grav\\Common\\Page\\Pages' => $baseDir . '/system/src/Grav/Common/Page/Pages.php', + 'Grav\\Common\\Plugin' => $baseDir . '/system/src/Grav/Common/Plugin.php', + 'Grav\\Common\\Plugins' => $baseDir . '/system/src/Grav/Common/Plugins.php', + 'Grav\\Common\\Registry' => $baseDir . '/system/src/Grav/Common/Registry.php', + 'Grav\\Common\\Service\\StreamsServiceProvider' => $baseDir . '/system/src/Grav/Common/Service/StreamsServiceProvider.php', + 'Grav\\Common\\Session\\Message' => $baseDir . '/system/src/Grav/Common/Session/Message.php', + 'Grav\\Common\\Session\\Session' => $baseDir . '/system/src/Grav/Common/Session/Session.php', + 'Grav\\Common\\Taxonomy' => $baseDir . '/system/src/Grav/Common/Taxonomy.php', + 'Grav\\Common\\Theme' => $baseDir . '/system/src/Grav/Common/Theme.php', + 'Grav\\Common\\Themes' => $baseDir . '/system/src/Grav/Common/Themes.php', + 'Grav\\Common\\Twig' => $baseDir . '/system/src/Grav/Common/Twig.php', + 'Grav\\Common\\TwigExtension' => $baseDir . '/system/src/Grav/Common/TwigExtension.php', + 'Grav\\Common\\Uri' => $baseDir . '/system/src/Grav/Common/Uri.php', + 'Grav\\Common\\User\\Authentication' => $baseDir . '/system/src/Grav/Common/User/Authentication.php', + 'Grav\\Common\\User\\User' => $baseDir . '/system/src/Grav/Common/User/User.php', + 'Grav\\Common\\Utils' => $baseDir . '/system/src/Grav/Common/Utils.php', + 'Grav\\Component\\ArrayTraits\\ArrayAccess' => $baseDir . '/system/src/Grav/Component/ArrayTraits/ArrayAccess.php', + 'Grav\\Component\\ArrayTraits\\Constructor' => $baseDir . '/system/src/Grav/Component/ArrayTraits/Constructor.php', + 'Grav\\Component\\ArrayTraits\\Countable' => $baseDir . '/system/src/Grav/Component/ArrayTraits/Countable.php', + 'Grav\\Component\\ArrayTraits\\Getters' => $baseDir . '/system/src/Grav/Component/ArrayTraits/Getters.php', + 'Grav\\Component\\DI\\Container' => $baseDir . '/system/src/Grav/Component/DI/Container.php', + 'Grav\\Component\\DI\\ServiceProviderInterface' => $baseDir . '/system/src/Grav/Component/DI/ServiceProviderInterface.php', + 'Grav\\Component\\EventDispatcher\\Event' => $baseDir . '/system/src/Grav/Component/EventDispatcher/Event.php', + 'Grav\\Component\\EventDispatcher\\EventDispatcher' => $baseDir . '/system/src/Grav/Component/EventDispatcher/EventDispatcher.php', + 'Grav\\Component\\EventDispatcher\\EventSubscriberInterface' => $baseDir . '/system/src/Grav/Component/EventDispatcher/EventSubscriberInterface.php', + 'Grav\\Component\\Filesystem\\ResourceLocator' => $baseDir . '/system/src/Grav/Component/Filesystem/ResourceLocator.php', + 'Grav\\Component\\Filesystem\\StreamWrapper\\ReadOnlyStream' => $baseDir . '/system/src/Grav/Component/Filesystem/StreamWrapper/ReadOnlyStream.php', + 'Grav\\Component\\Filesystem\\StreamWrapper\\Stream' => $baseDir . '/system/src/Grav/Component/Filesystem/StreamWrapper/Stream.php', + 'Grav\\Component\\Filesystem\\StreamWrapper\\StreamInterface' => $baseDir . '/system/src/Grav/Component/Filesystem/StreamWrapper/StreamInterface.php', + 'Grav\\Console\\BackupCommand' => $baseDir . '/system/src/Grav/Console/BackupCommand.php', + 'Grav\\Console\\CleanCommand' => $baseDir . '/system/src/Grav/Console/CleanCommand.php', + 'Grav\\Console\\ClearCacheCommand' => $baseDir . '/system/src/Grav/Console/ClearCacheCommand.php', + 'Grav\\Console\\InstallCommand' => $baseDir . '/system/src/Grav/Console/InstallCommand.php', + 'Grav\\Console\\NewProjectCommand' => $baseDir . '/system/src/Grav/Console/NewProjectCommand.php', + 'Grav\\Console\\SetupCommand' => $baseDir . '/system/src/Grav/Console/SetupCommand.php', + 'Gregwar\\Cache\\Cache' => $vendorDir . '/gregwar/cache/Gregwar/Cache/Cache.php', + 'Gregwar\\Cache\\GarbageCollect' => $vendorDir . '/gregwar/cache/Gregwar/Cache/GarbageCollect.php', + 'Gregwar\\Image\\Adapter\\Adapter' => $vendorDir . '/gregwar/image/Gregwar/Image/Adapter/Adapter.php', + 'Gregwar\\Image\\Adapter\\AdapterInterface' => $vendorDir . '/gregwar/image/Gregwar/Image/Adapter/AdapterInterface.php', + 'Gregwar\\Image\\Adapter\\Common' => $vendorDir . '/gregwar/image/Gregwar/Image/Adapter/Common.php', + 'Gregwar\\Image\\Adapter\\GD' => $vendorDir . '/gregwar/image/Gregwar/Image/Adapter/GD.php', + 'Gregwar\\Image\\Adapter\\Imagick' => $vendorDir . '/gregwar/image/Gregwar/Image/Adapter/Imagick.php', + 'Gregwar\\Image\\Exceptions\\GenerationError' => $vendorDir . '/gregwar/image/Gregwar/Image/Exceptions/GenerationError.php', + 'Gregwar\\Image\\GarbageCollect' => $vendorDir . '/gregwar/image/Gregwar/Image/GarbageCollect.php', + 'Gregwar\\Image\\Image' => $vendorDir . '/gregwar/image/Gregwar/Image/Image.php', + 'Gregwar\\Image\\ImageColor' => $vendorDir . '/gregwar/image/Gregwar/Image/ImageColor.php', + 'Gregwar\\Image\\Source\\Create' => $vendorDir . '/gregwar/image/Gregwar/Image/Source/Create.php', + 'Gregwar\\Image\\Source\\Data' => $vendorDir . '/gregwar/image/Gregwar/Image/Source/Data.php', + 'Gregwar\\Image\\Source\\File' => $vendorDir . '/gregwar/image/Gregwar/Image/Source/File.php', + 'Gregwar\\Image\\Source\\Resource' => $vendorDir . '/gregwar/image/Gregwar/Image/Source/Resource.php', + 'Gregwar\\Image\\Source\\Source' => $vendorDir . '/gregwar/image/Gregwar/Image/Source/Source.php', 'HTTP_ConditionalGet' => $vendorDir . '/mrclay/minify/min/lib/HTTP/ConditionalGet.php', 'HTTP_Encoder' => $vendorDir . '/mrclay/minify/min/lib/HTTP/Encoder.php', 'JSCompilerContext' => $vendorDir . '/mrclay/minify/min/lib/JSMinPlus.php', @@ -33,7 +127,6 @@ 'Minify_Cache_XCache' => $vendorDir . '/mrclay/minify/min/lib/Minify/Cache/XCache.php', 'Minify_Cache_ZendPlatform' => $vendorDir . '/mrclay/minify/min/lib/Minify/Cache/ZendPlatform.php', 'Minify_ClosureCompiler' => $vendorDir . '/mrclay/minify/min/lib/Minify/ClosureCompiler.php', - 'Minify_ClosureCompiler_Exception' => $vendorDir . '/mrclay/minify/min/lib/Minify/ClosureCompiler.php', 'Minify_CommentPreserver' => $vendorDir . '/mrclay/minify/min/lib/Minify/CommentPreserver.php', 'Minify_Controller_Base' => $vendorDir . '/mrclay/minify/min/lib/Minify/Controller/Base.php', 'Minify_Controller_Files' => $vendorDir . '/mrclay/minify/min/lib/Minify/Controller/Files.php', @@ -56,6 +149,99 @@ 'Minify_YUI_CssCompressor' => $vendorDir . '/mrclay/minify/min/lib/Minify/YUI/CssCompressor.php', 'MrClay\\Cli' => $vendorDir . '/mrclay/minify/min/lib/MrClay/Cli.php', 'MrClay\\Cli\\Arg' => $vendorDir . '/mrclay/minify/min/lib/MrClay/Cli/Arg.php', + 'Parsedown' => $vendorDir . '/erusev/parsedown/Parsedown.php', + 'ParsedownExtra' => $vendorDir . '/erusev/parsedown-extra/ParsedownExtra.php', + 'Pimple\\Container' => $vendorDir . '/pimple/pimple/src/Pimple/Container.php', + 'Pimple\\ServiceProviderInterface' => $vendorDir . '/pimple/pimple/src/Pimple/ServiceProviderInterface.php', + 'Pimple\\Tests\\Fixtures\\Invokable' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php', + 'Pimple\\Tests\\Fixtures\\NonInvokable' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php', + 'Pimple\\Tests\\Fixtures\\PimpleServiceProvider' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php', + 'Pimple\\Tests\\Fixtures\\Service' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php', + 'Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Symfony/Component/Console/Application.php', + 'Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Symfony/Component/Console/Command/Command.php', + 'Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Symfony/Component/Console/Command/HelpCommand.php', + 'Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/symfony/console/Symfony/Component/Console/Command/ListCommand.php', + 'Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/symfony/console/Symfony/Component/Console/ConsoleEvents.php', + 'Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/ApplicationDescription.php', + 'Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/Descriptor.php', + 'Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/DescriptorInterface.php', + 'Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/JsonDescriptor.php', + 'Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php', + 'Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/TextDescriptor.php', + 'Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/XmlDescriptor.php', + 'Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/symfony/console/Symfony/Component/Console/Event/ConsoleCommandEvent.php', + 'Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/symfony/console/Symfony/Component/Console/Event/ConsoleEvent.php', + 'Symfony\\Component\\Console\\Event\\ConsoleExceptionEvent' => $vendorDir . '/symfony/console/Symfony/Component/Console/Event/ConsoleExceptionEvent.php', + 'Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/symfony/console/Symfony/Component/Console/Event/ConsoleTerminateEvent.php', + 'Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php', + 'Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterInterface.php', + 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => $vendorDir . '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyle.php', + 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php', + 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php', + 'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/DescriptorHelper.php', + 'Symfony\\Component\\Console\\Helper\\DialogHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/DialogHelper.php', + 'Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/FormatterHelper.php', + 'Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/Helper.php', + 'Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/HelperInterface.php', + 'Symfony\\Component\\Console\\Helper\\HelperSet' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/HelperSet.php', + 'Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/InputAwareHelper.php', + 'Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/ProgressBar.php', + 'Symfony\\Component\\Console\\Helper\\ProgressHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/ProgressHelper.php', + 'Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/QuestionHelper.php', + 'Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/Table.php', + 'Symfony\\Component\\Console\\Helper\\TableHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/TableHelper.php', + 'Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/TableSeparator.php', + 'Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/TableStyle.php', + 'Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/ArgvInput.php', + 'Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/ArrayInput.php', + 'Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/Input.php', + 'Symfony\\Component\\Console\\Input\\InputArgument' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/InputArgument.php', + 'Symfony\\Component\\Console\\Input\\InputAwareInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/InputAwareInterface.php', + 'Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/InputDefinition.php', + 'Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/InputInterface.php', + 'Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/InputOption.php', + 'Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/StringInput.php', + 'Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/symfony/console/Symfony/Component/Console/Logger/ConsoleLogger.php', + 'Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/BufferedOutput.php', + 'Symfony\\Component\\Console\\Output\\ConsoleOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php', + 'Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/ConsoleOutputInterface.php', + 'Symfony\\Component\\Console\\Output\\NullOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/NullOutput.php', + 'Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/Output.php', + 'Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/OutputInterface.php', + 'Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/StreamOutput.php', + 'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Symfony/Component/Console/Question/ChoiceQuestion.php', + 'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Symfony/Component/Console/Question/ConfirmationQuestion.php', + 'Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Symfony/Component/Console/Question/Question.php', + 'Symfony\\Component\\Console\\Shell' => $vendorDir . '/symfony/console/Symfony/Component/Console/Shell.php', + 'Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tester/ApplicationTester.php', + 'Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tester/CommandTester.php', + 'Symfony\\Component\\Console\\Tests\\Descriptor\\ObjectsProvider' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php', + 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorApplication1' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.php', + 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorApplication2' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.php', + 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorCommand1' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.php', + 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorCommand2' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.php', + 'Symfony\\Component\\Console\\Tests\\Fixtures\\DummyOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DummyOutput.php', + 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php', + 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php', + 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php', + 'Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/WrappedListener.php', + 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php', + 'Symfony\\Component\\EventDispatcher\\Event' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Event.php', + 'Symfony\\Component\\EventDispatcher\\EventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php', + 'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcherInterface.php', + 'Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventSubscriberInterface.php', + 'Symfony\\Component\\EventDispatcher\\GenericEvent' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/GenericEvent.php', + 'Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php', + 'Symfony\\Component\\Yaml\\Dumper' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Dumper.php', + 'Symfony\\Component\\Yaml\\Escaper' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Escaper.php', + 'Symfony\\Component\\Yaml\\Exception\\DumpException' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Exception/DumpException.php', + 'Symfony\\Component\\Yaml\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Exception/ExceptionInterface.php', + 'Symfony\\Component\\Yaml\\Exception\\ParseException' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Exception/ParseException.php', + 'Symfony\\Component\\Yaml\\Exception\\RuntimeException' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Exception/RuntimeException.php', + 'Symfony\\Component\\Yaml\\Inline' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Inline.php', + 'Symfony\\Component\\Yaml\\Parser' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Parser.php', + 'Symfony\\Component\\Yaml\\Unescaper' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Unescaper.php', + 'Symfony\\Component\\Yaml\\Yaml' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Yaml.php', 'Tracy\\Bar' => $vendorDir . '/tracy/tracy/src/Tracy/Bar.php', 'Tracy\\BlueScreen' => $vendorDir . '/tracy/tracy/src/Tracy/BlueScreen.php', 'Tracy\\Debugger' => $vendorDir . '/tracy/tracy/src/Tracy/Debugger.php', @@ -64,7 +250,170 @@ 'Tracy\\FireLogger' => $vendorDir . '/tracy/tracy/src/Tracy/FireLogger.php', 'Tracy\\Helpers' => $vendorDir . '/tracy/tracy/src/Tracy/Helpers.php', 'Tracy\\IBarPanel' => $vendorDir . '/tracy/tracy/src/Tracy/IBarPanel.php', - 'Tracy\\ILogger' => $vendorDir . '/tracy/tracy/src/Tracy/ILogger.php', 'Tracy\\Logger' => $vendorDir . '/tracy/tracy/src/Tracy/Logger.php', 'Tracy\\OutputDebugger' => $vendorDir . '/tracy/tracy/src/Tracy/OutputDebugger.php', + 'Twig_Autoloader' => $vendorDir . '/twig/twig/lib/Twig/Autoloader.php', + 'Twig_Compiler' => $vendorDir . '/twig/twig/lib/Twig/Compiler.php', + 'Twig_CompilerInterface' => $vendorDir . '/twig/twig/lib/Twig/CompilerInterface.php', + 'Twig_Environment' => $vendorDir . '/twig/twig/lib/Twig/Environment.php', + 'Twig_Error' => $vendorDir . '/twig/twig/lib/Twig/Error.php', + 'Twig_Error_Loader' => $vendorDir . '/twig/twig/lib/Twig/Error/Loader.php', + 'Twig_Error_Runtime' => $vendorDir . '/twig/twig/lib/Twig/Error/Runtime.php', + 'Twig_Error_Syntax' => $vendorDir . '/twig/twig/lib/Twig/Error/Syntax.php', + 'Twig_ExistsLoaderInterface' => $vendorDir . '/twig/twig/lib/Twig/ExistsLoaderInterface.php', + 'Twig_ExpressionParser' => $vendorDir . '/twig/twig/lib/Twig/ExpressionParser.php', + 'Twig_Extension' => $vendorDir . '/twig/twig/lib/Twig/Extension.php', + 'Twig_ExtensionInterface' => $vendorDir . '/twig/twig/lib/Twig/ExtensionInterface.php', + 'Twig_Extension_Core' => $vendorDir . '/twig/twig/lib/Twig/Extension/Core.php', + 'Twig_Extension_Debug' => $vendorDir . '/twig/twig/lib/Twig/Extension/Debug.php', + 'Twig_Extension_Escaper' => $vendorDir . '/twig/twig/lib/Twig/Extension/Escaper.php', + 'Twig_Extension_Optimizer' => $vendorDir . '/twig/twig/lib/Twig/Extension/Optimizer.php', + 'Twig_Extension_Sandbox' => $vendorDir . '/twig/twig/lib/Twig/Extension/Sandbox.php', + 'Twig_Extension_Staging' => $vendorDir . '/twig/twig/lib/Twig/Extension/Staging.php', + 'Twig_Extension_StringLoader' => $vendorDir . '/twig/twig/lib/Twig/Extension/StringLoader.php', + 'Twig_Filter' => $vendorDir . '/twig/twig/lib/Twig/Filter.php', + 'Twig_FilterCallableInterface' => $vendorDir . '/twig/twig/lib/Twig/FilterCallableInterface.php', + 'Twig_FilterInterface' => $vendorDir . '/twig/twig/lib/Twig/FilterInterface.php', + 'Twig_Filter_Function' => $vendorDir . '/twig/twig/lib/Twig/Filter/Function.php', + 'Twig_Filter_Method' => $vendorDir . '/twig/twig/lib/Twig/Filter/Method.php', + 'Twig_Filter_Node' => $vendorDir . '/twig/twig/lib/Twig/Filter/Node.php', + 'Twig_Function' => $vendorDir . '/twig/twig/lib/Twig/Function.php', + 'Twig_FunctionCallableInterface' => $vendorDir . '/twig/twig/lib/Twig/FunctionCallableInterface.php', + 'Twig_FunctionInterface' => $vendorDir . '/twig/twig/lib/Twig/FunctionInterface.php', + 'Twig_Function_Function' => $vendorDir . '/twig/twig/lib/Twig/Function/Function.php', + 'Twig_Function_Method' => $vendorDir . '/twig/twig/lib/Twig/Function/Method.php', + 'Twig_Function_Node' => $vendorDir . '/twig/twig/lib/Twig/Function/Node.php', + 'Twig_Lexer' => $vendorDir . '/twig/twig/lib/Twig/Lexer.php', + 'Twig_LexerInterface' => $vendorDir . '/twig/twig/lib/Twig/LexerInterface.php', + 'Twig_LoaderInterface' => $vendorDir . '/twig/twig/lib/Twig/LoaderInterface.php', + 'Twig_Loader_Array' => $vendorDir . '/twig/twig/lib/Twig/Loader/Array.php', + 'Twig_Loader_Chain' => $vendorDir . '/twig/twig/lib/Twig/Loader/Chain.php', + 'Twig_Loader_Filesystem' => $vendorDir . '/twig/twig/lib/Twig/Loader/Filesystem.php', + 'Twig_Loader_String' => $vendorDir . '/twig/twig/lib/Twig/Loader/String.php', + 'Twig_Markup' => $vendorDir . '/twig/twig/lib/Twig/Markup.php', + 'Twig_Node' => $vendorDir . '/twig/twig/lib/Twig/Node.php', + 'Twig_NodeInterface' => $vendorDir . '/twig/twig/lib/Twig/NodeInterface.php', + 'Twig_NodeOutputInterface' => $vendorDir . '/twig/twig/lib/Twig/NodeOutputInterface.php', + 'Twig_NodeTraverser' => $vendorDir . '/twig/twig/lib/Twig/NodeTraverser.php', + 'Twig_NodeVisitorInterface' => $vendorDir . '/twig/twig/lib/Twig/NodeVisitorInterface.php', + 'Twig_NodeVisitor_Escaper' => $vendorDir . '/twig/twig/lib/Twig/NodeVisitor/Escaper.php', + 'Twig_NodeVisitor_Optimizer' => $vendorDir . '/twig/twig/lib/Twig/NodeVisitor/Optimizer.php', + 'Twig_NodeVisitor_SafeAnalysis' => $vendorDir . '/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php', + 'Twig_NodeVisitor_Sandbox' => $vendorDir . '/twig/twig/lib/Twig/NodeVisitor/Sandbox.php', + 'Twig_Node_AutoEscape' => $vendorDir . '/twig/twig/lib/Twig/Node/AutoEscape.php', + 'Twig_Node_Block' => $vendorDir . '/twig/twig/lib/Twig/Node/Block.php', + 'Twig_Node_BlockReference' => $vendorDir . '/twig/twig/lib/Twig/Node/BlockReference.php', + 'Twig_Node_Body' => $vendorDir . '/twig/twig/lib/Twig/Node/Body.php', + 'Twig_Node_Do' => $vendorDir . '/twig/twig/lib/Twig/Node/Do.php', + 'Twig_Node_Embed' => $vendorDir . '/twig/twig/lib/Twig/Node/Embed.php', + 'Twig_Node_Expression' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression.php', + 'Twig_Node_Expression_Array' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Array.php', + 'Twig_Node_Expression_AssignName' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/AssignName.php', + 'Twig_Node_Expression_Binary' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary.php', + 'Twig_Node_Expression_Binary_Add' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Add.php', + 'Twig_Node_Expression_Binary_And' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/And.php', + 'Twig_Node_Expression_Binary_BitwiseAnd' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php', + 'Twig_Node_Expression_Binary_BitwiseOr' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php', + 'Twig_Node_Expression_Binary_BitwiseXor' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php', + 'Twig_Node_Expression_Binary_Concat' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php', + 'Twig_Node_Expression_Binary_Div' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Div.php', + 'Twig_Node_Expression_Binary_EndsWith' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php', + 'Twig_Node_Expression_Binary_Equal' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php', + 'Twig_Node_Expression_Binary_FloorDiv' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php', + 'Twig_Node_Expression_Binary_Greater' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php', + 'Twig_Node_Expression_Binary_GreaterEqual' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php', + 'Twig_Node_Expression_Binary_In' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/In.php', + 'Twig_Node_Expression_Binary_Less' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Less.php', + 'Twig_Node_Expression_Binary_LessEqual' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php', + 'Twig_Node_Expression_Binary_Matches' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php', + 'Twig_Node_Expression_Binary_Mod' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php', + 'Twig_Node_Expression_Binary_Mul' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php', + 'Twig_Node_Expression_Binary_NotEqual' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php', + 'Twig_Node_Expression_Binary_NotIn' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php', + 'Twig_Node_Expression_Binary_Or' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Or.php', + 'Twig_Node_Expression_Binary_Power' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Power.php', + 'Twig_Node_Expression_Binary_Range' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Range.php', + 'Twig_Node_Expression_Binary_StartsWith' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php', + 'Twig_Node_Expression_Binary_Sub' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php', + 'Twig_Node_Expression_BlockReference' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/BlockReference.php', + 'Twig_Node_Expression_Call' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Call.php', + 'Twig_Node_Expression_Conditional' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Conditional.php', + 'Twig_Node_Expression_Constant' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Constant.php', + 'Twig_Node_Expression_ExtensionReference' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php', + 'Twig_Node_Expression_Filter' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Filter.php', + 'Twig_Node_Expression_Filter_Default' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Filter/Default.php', + 'Twig_Node_Expression_Function' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Function.php', + 'Twig_Node_Expression_GetAttr' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/GetAttr.php', + 'Twig_Node_Expression_MethodCall' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/MethodCall.php', + 'Twig_Node_Expression_Name' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Name.php', + 'Twig_Node_Expression_Parent' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Parent.php', + 'Twig_Node_Expression_TempName' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/TempName.php', + 'Twig_Node_Expression_Test' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test.php', + 'Twig_Node_Expression_Test_Constant' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Constant.php', + 'Twig_Node_Expression_Test_Defined' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Defined.php', + 'Twig_Node_Expression_Test_Divisibleby' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php', + 'Twig_Node_Expression_Test_Even' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Even.php', + 'Twig_Node_Expression_Test_Null' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Null.php', + 'Twig_Node_Expression_Test_Odd' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Odd.php', + 'Twig_Node_Expression_Test_Sameas' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php', + 'Twig_Node_Expression_Unary' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Unary.php', + 'Twig_Node_Expression_Unary_Neg' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php', + 'Twig_Node_Expression_Unary_Not' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Unary/Not.php', + 'Twig_Node_Expression_Unary_Pos' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php', + 'Twig_Node_Flush' => $vendorDir . '/twig/twig/lib/Twig/Node/Flush.php', + 'Twig_Node_For' => $vendorDir . '/twig/twig/lib/Twig/Node/For.php', + 'Twig_Node_ForLoop' => $vendorDir . '/twig/twig/lib/Twig/Node/ForLoop.php', + 'Twig_Node_If' => $vendorDir . '/twig/twig/lib/Twig/Node/If.php', + 'Twig_Node_Import' => $vendorDir . '/twig/twig/lib/Twig/Node/Import.php', + 'Twig_Node_Include' => $vendorDir . '/twig/twig/lib/Twig/Node/Include.php', + 'Twig_Node_Macro' => $vendorDir . '/twig/twig/lib/Twig/Node/Macro.php', + 'Twig_Node_Module' => $vendorDir . '/twig/twig/lib/Twig/Node/Module.php', + 'Twig_Node_Print' => $vendorDir . '/twig/twig/lib/Twig/Node/Print.php', + 'Twig_Node_Sandbox' => $vendorDir . '/twig/twig/lib/Twig/Node/Sandbox.php', + 'Twig_Node_SandboxedModule' => $vendorDir . '/twig/twig/lib/Twig/Node/SandboxedModule.php', + 'Twig_Node_SandboxedPrint' => $vendorDir . '/twig/twig/lib/Twig/Node/SandboxedPrint.php', + 'Twig_Node_Set' => $vendorDir . '/twig/twig/lib/Twig/Node/Set.php', + 'Twig_Node_SetTemp' => $vendorDir . '/twig/twig/lib/Twig/Node/SetTemp.php', + 'Twig_Node_Spaceless' => $vendorDir . '/twig/twig/lib/Twig/Node/Spaceless.php', + 'Twig_Node_Text' => $vendorDir . '/twig/twig/lib/Twig/Node/Text.php', + 'Twig_Parser' => $vendorDir . '/twig/twig/lib/Twig/Parser.php', + 'Twig_ParserInterface' => $vendorDir . '/twig/twig/lib/Twig/ParserInterface.php', + 'Twig_Sandbox_SecurityError' => $vendorDir . '/twig/twig/lib/Twig/Sandbox/SecurityError.php', + 'Twig_Sandbox_SecurityPolicy' => $vendorDir . '/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php', + 'Twig_Sandbox_SecurityPolicyInterface' => $vendorDir . '/twig/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php', + 'Twig_SimpleFilter' => $vendorDir . '/twig/twig/lib/Twig/SimpleFilter.php', + 'Twig_SimpleFunction' => $vendorDir . '/twig/twig/lib/Twig/SimpleFunction.php', + 'Twig_Template' => $vendorDir . '/twig/twig/lib/Twig/Template.php', + 'Twig_TemplateInterface' => $vendorDir . '/twig/twig/lib/Twig/TemplateInterface.php', + 'Twig_Test' => $vendorDir . '/twig/twig/lib/Twig/Test.php', + 'Twig_TestCallableInterface' => $vendorDir . '/twig/twig/lib/Twig/TestCallableInterface.php', + 'Twig_TestInterface' => $vendorDir . '/twig/twig/lib/Twig/TestInterface.php', + 'Twig_Test_Function' => $vendorDir . '/twig/twig/lib/Twig/Test/Function.php', + 'Twig_Test_IntegrationTestCase' => $vendorDir . '/twig/twig/lib/Twig/Test/IntegrationTestCase.php', + 'Twig_Test_Method' => $vendorDir . '/twig/twig/lib/Twig/Test/Method.php', + 'Twig_Test_Node' => $vendorDir . '/twig/twig/lib/Twig/Test/Node.php', + 'Twig_Test_NodeTestCase' => $vendorDir . '/twig/twig/lib/Twig/Test/NodeTestCase.php', + 'Twig_Token' => $vendorDir . '/twig/twig/lib/Twig/Token.php', + 'Twig_TokenParser' => $vendorDir . '/twig/twig/lib/Twig/TokenParser.php', + 'Twig_TokenParserBroker' => $vendorDir . '/twig/twig/lib/Twig/TokenParserBroker.php', + 'Twig_TokenParserBrokerInterface' => $vendorDir . '/twig/twig/lib/Twig/TokenParserBrokerInterface.php', + 'Twig_TokenParserInterface' => $vendorDir . '/twig/twig/lib/Twig/TokenParserInterface.php', + 'Twig_TokenParser_AutoEscape' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/AutoEscape.php', + 'Twig_TokenParser_Block' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Block.php', + 'Twig_TokenParser_Do' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Do.php', + 'Twig_TokenParser_Embed' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Embed.php', + 'Twig_TokenParser_Extends' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Extends.php', + 'Twig_TokenParser_Filter' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Filter.php', + 'Twig_TokenParser_Flush' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Flush.php', + 'Twig_TokenParser_For' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/For.php', + 'Twig_TokenParser_From' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/From.php', + 'Twig_TokenParser_If' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/If.php', + 'Twig_TokenParser_Import' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Import.php', + 'Twig_TokenParser_Include' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Include.php', + 'Twig_TokenParser_Macro' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Macro.php', + 'Twig_TokenParser_Sandbox' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Sandbox.php', + 'Twig_TokenParser_Set' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Set.php', + 'Twig_TokenParser_Spaceless' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Spaceless.php', + 'Twig_TokenParser_Use' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Use.php', + 'Twig_TokenStream' => $vendorDir . '/twig/twig/lib/Twig/TokenStream.php', ); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index 6f66c7e75b..945cea3258 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -6,8 +6,9 @@ $baseDir = dirname($vendorDir); return array( - $vendorDir . '/tracy/tracy/src/shortcuts.php', - $vendorDir . '/ircmaxell/password-compat/lib/password.php', $vendorDir . '/ornicar/php-user-agent/lib/phpUserAgent.php', $vendorDir . '/ornicar/php-user-agent/lib/phpUserAgentStringParser.php', + $vendorDir . '/tracy/tracy/src/shortcuts.php', + $vendorDir . '/ircmaxell/password-compat/lib/password.php', + $baseDir . '/system/defines.php', ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index b265c64a22..687a12874e 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -6,4 +6,5 @@ $baseDir = dirname($vendorDir); return array( + 'Grav\\' => array($baseDir . '/system/src'), ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 499efe4998..733b9e1e2e 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit010a27b310c3146ba53b52651441075a +class ComposerAutoloaderIniteef751e17db86fa31c0c46c61acf76f4 { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit010a27b310c3146ba53b52651441075a', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderIniteef751e17db86fa31c0c46c61acf76f4', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit010a27b310c3146ba53b52651441075a', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderIniteef751e17db86fa31c0c46c61acf76f4', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ public static function getLoader() $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequire010a27b310c3146ba53b52651441075a($file); + composerRequireeef751e17db86fa31c0c46c61acf76f4($file); } return $loader; } } -function composerRequire010a27b310c3146ba53b52651441075a($file) +function composerRequireeef751e17db86fa31c0c46c61acf76f4($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 3b92750048..863259012c 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,4 +1,63 @@ [ + { + "name": "twig/twig", + "version": "v1.16.0", + "version_normalized": "1.16.0.0", + "source": { + "type": "git", + "url": "https://github.com/fabpot/Twig.git", + "reference": "8ce37115802e257a984a82d38254884085060024" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fabpot/Twig/zipball/8ce37115802e257a984a82d38254884085060024", + "reference": "8ce37115802e257a984a82d38254884085060024", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "time": "2014-07-05 12:19:05", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.16-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Twig_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + }, + { + "name": "Twig Team", + "homepage": "https://github.com/fabpot/Twig/graphs/contributors", + "role": "Contributors" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "http://twig.sensiolabs.org", + "keywords": [ + "templating" + ] + }, { "name": "erusev/parsedown", "version": "1.0.1", @@ -42,8 +101,8 @@ }, { "name": "erusev/parsedown-extra", - "version": "dev-master", - "version_normalized": "9999999-dev", + "version": "0.2.0", + "version_normalized": "0.2.0.0", "source": { "type": "git", "url": "https://github.com/erusev/parsedown-extra.git", @@ -60,7 +119,7 @@ }, "time": "2014-08-16 11:20:35", "type": "library", - "installation-source": "source", + "installation-source": "dist", "autoload": { "psr-0": { "ParsedownExtra": "" @@ -88,17 +147,17 @@ }, { "name": "doctrine/cache", - "version": "dev-master", - "version_normalized": "9999999-dev", + "version": "v1.3.0", + "version_normalized": "1.3.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "72121e68265cd8b37f9b69778308251f6c5133e4" + "reference": "e16d7adf45664a50fa86f515b6d5e7f670130449" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/72121e68265cd8b37f9b69778308251f6c5133e4", - "reference": "72121e68265cd8b37f9b69778308251f6c5133e4", + "url": "https://api.github.com/repos/doctrine/cache/zipball/e16d7adf45664a50fa86f515b6d5e7f670130449", + "reference": "e16d7adf45664a50fa86f515b6d5e7f670130449", "shasum": "" }, "require": { @@ -111,14 +170,14 @@ "phpunit/phpunit": ">=3.7", "satooshi/php-coveralls": "~0.6" }, - "time": "2014-08-05 12:51:19", + "time": "2013-10-25 19:04:14", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.0.x-dev" } }, - "installation-source": "source", + "installation-source": "dist", "autoload": { "psr-0": { "Doctrine\\Common\\Cache\\": "lib/" @@ -130,24 +189,29 @@ ], "authors": [ { - "name": "Roman Borschel", - "email": "roman@code-factory.org" + "name": "Jonathan Wage", + "email": "jonwage@gmail.com", + "homepage": "http://www.jwage.com/", + "role": "Creator" }, { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com", + "homepage": "http://www.instaclick.com" }, { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" + "name": "Roman Borschel", + "email": "roman@code-factory.org" }, { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" }, { "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh", + "role": "Developer of wrapped JMSSerializerBundle" } ], "description": "Caching library offering an object-oriented API for many cache backends", @@ -158,140 +222,73 @@ ] }, { - "name": "tracy/tracy", - "version": "dev-master", - "version_normalized": "9999999-dev", + "name": "mrclay/minify", + "version": "2.2.0", + "version_normalized": "2.2.0.0", "source": { "type": "git", - "url": "https://github.com/nette/tracy.git", - "reference": "5b62cb55e904ba1a1325803686a9f90959c99585" + "url": "https://github.com/mrclay/minify.git", + "reference": "d245bca4987dec197d1e6d7dc117614b60ff7494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/tracy/zipball/5b62cb55e904ba1a1325803686a9f90959c99585", - "reference": "5b62cb55e904ba1a1325803686a9f90959c99585", + "url": "https://api.github.com/repos/mrclay/minify/zipball/d245bca4987dec197d1e6d7dc117614b60ff7494", + "reference": "d245bca4987dec197d1e6d7dc117614b60ff7494", "shasum": "" }, "require": { - "php": ">=5.3.1" - }, - "require-dev": { - "nette/tester": "~1.0" + "ext-pcre": "*", + "php": ">=5.2.1" }, - "time": "2014-08-17 22:39:47", + "time": "2014-03-12 12:54:23", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "installation-source": "source", + "installation-source": "dist", "autoload": { "classmap": [ - "src/Tracy" - ], - "files": [ - "src/shortcuts.php" + "min/lib/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "http://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "http://nette.org/contributors" - } - ], - "description": "Tracy: useful PHP debugger", - "homepage": "http://tracy.nette.org", - "keywords": [ - "debug", - "debugger", - "nette" - ] - }, - { - "name": "gregwar/cache", - "version": "v1.0.9", - "version_normalized": "1.0.9.0", - "target-dir": "Gregwar/Cache", - "source": { - "type": "git", - "url": "https://github.com/Gregwar/Cache.git", - "reference": "514b9b469082028d094e33e4a059c863c546b14e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Gregwar/Cache/zipball/514b9b469082028d094e33e4a059c863c546b14e", - "reference": "514b9b469082028d094e33e4a059c863c546b14e", - "shasum": "" - }, - "require": { - "php": ">=5.3" - }, - "time": "2014-07-05 17:42:36", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "Gregwar\\Cache": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Grégoire Passault", - "email": "g.passault@gmail.com", - "homepage": "http://www.gregwar.com/" + "name": "Steve Clay", + "email": "steve@mrclay.org", + "homepage": "http://www.mrclay.org/", + "role": "Developer" } ], - "description": "A lightweight file-system cache system", - "keywords": [ - "cache", - "caching", - "file-system", - "system" - ] + "description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers", + "homepage": "http://code.google.com/p/minify/" }, { - "name": "gregwar/image", - "version": "dev-master", - "version_normalized": "9999999-dev", - "target-dir": "Gregwar/Image", + "name": "ornicar/php-user-agent", + "version": "1.0.0", + "version_normalized": "1.0.0.0", "source": { "type": "git", - "url": "https://github.com/Gregwar/Image.git", - "reference": "31cf30151015d66f320011ea8646e90bb62ffb13" + "url": "https://github.com/ornicar/php-user-agent.git", + "reference": "9c6ae1274642695bffe57cd80228e5158ccbcf21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Gregwar/Image/zipball/31cf30151015d66f320011ea8646e90bb62ffb13", - "reference": "31cf30151015d66f320011ea8646e90bb62ffb13", + "url": "https://api.github.com/repos/ornicar/php-user-agent/zipball/9c6ae1274642695bffe57cd80228e5158ccbcf21", + "reference": "9c6ae1274642695bffe57cd80228e5158ccbcf21", "shasum": "" }, "require": { - "ext-gd": "*", - "gregwar/cache": "1.*", "php": ">=5.3.0" }, - "time": "2014-06-30 15:00:37", + "time": "2013-07-09 13:01:41", "type": "library", - "installation-source": "source", + "installation-source": "dist", "autoload": { - "psr-0": { - "Gregwar\\Image": "" - } + "files": [ + "lib/phpUserAgent.php", + "lib/phpUserAgentStringParser.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -299,60 +296,15 @@ ], "authors": [ { - "name": "Grégoire Passault", - "email": "g.passault@gmail.com", - "homepage": "http://www.gregwar.com/" + "name": "Thibault Duplessis", + "email": "thibault.duplessis@gmail.com", + "homepage": "http://ornicar.github.com" } ], - "description": "Image handling", - "homepage": "https://github.com/Gregwar/Image", "keywords": [ - "gd", - "image" + "user-agent" ] }, - { - "name": "mrclay/minify", - "version": "dev-master", - "version_normalized": "9999999-dev", - "source": { - "type": "git", - "url": "https://github.com/mrclay/minify.git", - "reference": "fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mrclay/minify/zipball/fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9", - "reference": "fb3931f8cd54a637b2a42170c3a9a1c4da9e69a9", - "shasum": "" - }, - "require": { - "ext-pcre": "*", - "php": ">=5.2.1" - }, - "time": "2014-04-03 23:53:48", - "type": "library", - "installation-source": "source", - "autoload": { - "classmap": [ - "min/lib/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Steve Clay", - "email": "steve@mrclay.org", - "homepage": "http://www.mrclay.org/", - "role": "Developer" - } - ], - "description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers", - "homepage": "http://code.google.com/p/minify/" - }, { "name": "pimple/pimple", "version": "v3.0.0", @@ -401,69 +353,10 @@ "dependency injection" ] }, - { - "name": "twig/twig", - "version": "dev-master", - "version_normalized": "9999999-dev", - "source": { - "type": "git", - "url": "https://github.com/fabpot/Twig.git", - "reference": "e2d2a250d963dd5bba4ad23fc01c7282fc042946" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fabpot/Twig/zipball/e2d2a250d963dd5bba4ad23fc01c7282fc042946", - "reference": "e2d2a250d963dd5bba4ad23fc01c7282fc042946", - "shasum": "" - }, - "require": { - "php": ">=5.2.4" - }, - "time": "2014-08-06 06:46:32", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.16-dev" - } - }, - "installation-source": "source", - "autoload": { - "psr-0": { - "Twig_": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" - }, - { - "name": "Twig Team", - "homepage": "https://github.com/fabpot/Twig/graphs/contributors", - "role": "Contributors" - } - ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "http://twig.sensiolabs.org", - "keywords": [ - "templating" - ] - }, { "name": "symfony/yaml", - "version": "2.5.x-dev", - "version_normalized": "2.5.9999999.9999999-dev", + "version": "v2.5.3", + "version_normalized": "2.5.3.0", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", @@ -486,7 +379,7 @@ "dev-master": "2.5-dev" } }, - "installation-source": "source", + "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\Yaml\\": "" @@ -511,18 +404,18 @@ }, { "name": "symfony/console", - "version": "2.5.x-dev", - "version_normalized": "2.5.9999999.9999999-dev", + "version": "v2.5.3", + "version_normalized": "2.5.3.0", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "748beed2a1e73179c3f5154d33fe6ae100c1aeb1" + "reference": "cd2d1e4bac2206b337326b0140ff475fe9ad5f63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/748beed2a1e73179c3f5154d33fe6ae100c1aeb1", - "reference": "748beed2a1e73179c3f5154d33fe6ae100c1aeb1", + "url": "https://api.github.com/repos/symfony/Console/zipball/cd2d1e4bac2206b337326b0140ff475fe9ad5f63", + "reference": "cd2d1e4bac2206b337326b0140ff475fe9ad5f63", "shasum": "" }, "require": { @@ -536,14 +429,14 @@ "psr/log": "For using the console logger", "symfony/event-dispatcher": "" }, - "time": "2014-08-14 16:10:54", + "time": "2014-08-05 09:00:40", "type": "library", "extra": { "branch-alias": { "dev-master": "2.5-dev" } }, - "installation-source": "source", + "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\Console\\": "" @@ -568,8 +461,8 @@ }, { "name": "symfony/event-dispatcher", - "version": "2.5.x-dev", - "version_normalized": "2.5.9999999.9999999-dev", + "version": "v2.5.3", + "version_normalized": "2.5.3.0", "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", @@ -602,7 +495,7 @@ "dev-master": "2.5-dev" } }, - "installation-source": "source", + "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\EventDispatcher\\": "" @@ -626,76 +519,172 @@ "homepage": "http://symfony.com" }, { - "name": "ircmaxell/password-compat", - "version": "1.0.3", - "version_normalized": "1.0.3.0", + "name": "tracy/tracy", + "version": "v2.2.2", + "version_normalized": "2.2.2.0", "source": { "type": "git", - "url": "https://github.com/ircmaxell/password_compat.git", - "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4" + "url": "https://github.com/nette/tracy.git", + "reference": "f5a2647c9d0174d218d626eab3952ea3a523c6e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/1fc1521b5e9794ea77e4eca30717be9635f1d4f4", - "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4", + "url": "https://api.github.com/repos/nette/tracy/zipball/f5a2647c9d0174d218d626eab3952ea3a523c6e7", + "reference": "f5a2647c9d0174d218d626eab3952ea3a523c6e7", "shasum": "" }, - "time": "2013-04-30 19:58:08", + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "nette/tester": "~1.0" + }, + "time": "2014-06-24 01:18:03", "type": "library", "installation-source": "dist", "autoload": { + "classmap": [ + "src/Tracy" + ], "files": [ - "lib/password.php" + "src/shortcuts.php" ] }, "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "http://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "http://nette.org/contributors" + } + ], + "description": "Tracy: useful PHP debugger", + "homepage": "http://tracy.nette.org", + "keywords": [ + "debug", + "debugger", + "nette" + ] + }, + { + "name": "gregwar/cache", + "version": "v1.0.7", + "version_normalized": "1.0.7.0", + "target-dir": "Gregwar/Cache", + "source": { + "type": "git", + "url": "https://github.com/Gregwar/Cache.git", + "reference": "b2d0197c07cc1ccf7436e1ae7bf64f9948e02052" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Gregwar/Cache/zipball/b2d0197c07cc1ccf7436e1ae7bf64f9948e02052", + "reference": "b2d0197c07cc1ccf7436e1ae7bf64f9948e02052", + "shasum": "" + }, + "time": "2014-02-20 20:04:58", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Gregwar\\Cache": "" + } + }, + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Anthony Ferrara", - "email": "ircmaxell@ircmaxell.com", - "homepage": "http://blog.ircmaxell.com" + "name": "Grégoire Passault", + "email": "g.passault@gmail.com", + "homepage": "http://www.gregwar.com/" } ], - "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", - "homepage": "https://github.com/ircmaxell/password_compat", + "description": "A lightweight file-system cache system", "keywords": [ - "hashing", - "password" + "cache", + "caching", + "file-system", + "system" ] }, { - "name": "ornicar/php-user-agent", - "version": "dev-master", - "version_normalized": "9999999-dev", + "name": "gregwar/image", + "version": "v2.0.17", + "version_normalized": "2.0.17.0", + "target-dir": "Gregwar/Image", "source": { "type": "git", - "url": "https://github.com/ornicar/php-user-agent.git", - "reference": "91f648fc5080ac1e8a8b51bcd90867b6ddeaf633" + "url": "https://github.com/Gregwar/Image.git", + "reference": "a7bba10ed0e3004c098bb7fde3a3e5bcafca8a2c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ornicar/php-user-agent/zipball/91f648fc5080ac1e8a8b51bcd90867b6ddeaf633", - "reference": "91f648fc5080ac1e8a8b51bcd90867b6ddeaf633", + "url": "https://api.github.com/repos/Gregwar/Image/zipball/a7bba10ed0e3004c098bb7fde3a3e5bcafca8a2c", + "reference": "a7bba10ed0e3004c098bb7fde3a3e5bcafca8a2c", "shasum": "" }, "require": { + "ext-gd": "*", + "gregwar/cache": "v1.0.7", "php": ">=5.3.0" }, - "time": "2013-07-09 13:04:43", + "time": "2014-02-20 22:20:45", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" + "installation-source": "dist", + "autoload": { + "psr-0": { + "Gregwar\\Image": "" } }, - "installation-source": "source", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Passault", + "email": "g.passault@gmail.com", + "homepage": "http://www.gregwar.com/" + } + ], + "description": "Image handling", + "homepage": "https://github.com/Gregwar/Image", + "keywords": [ + "gd", + "image" + ] + }, + { + "name": "ircmaxell/password-compat", + "version": "1.0.3", + "version_normalized": "1.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/ircmaxell/password_compat.git", + "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/1fc1521b5e9794ea77e4eca30717be9635f1d4f4", + "reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4", + "shasum": "" + }, + "time": "2013-04-30 19:58:08", + "type": "library", + "installation-source": "dist", "autoload": { "files": [ - "lib/phpUserAgent.php", - "lib/phpUserAgentStringParser.php" + "lib/password.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -704,13 +693,16 @@ ], "authors": [ { - "name": "Thibault Duplessis", - "email": "thibault.duplessis@gmail.com", - "homepage": "http://ornicar.github.com" + "name": "Anthony Ferrara", + "email": "ircmaxell@ircmaxell.com", + "homepage": "http://blog.ircmaxell.com" } ], + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "homepage": "https://github.com/ircmaxell/password_compat", "keywords": [ - "user-agent" + "hashing", + "password" ] } ] diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php index f896bc7082..ce88e49223 100644 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php @@ -43,7 +43,7 @@ abstract class CacheProvider implements Cache /** * The namespace version. * - * @var integer|null + * @var string */ private $namespaceVersion; @@ -162,7 +162,7 @@ private function getNamespaceCacheKey() /** * Returns the namespace version. * - * @return integer + * @return string */ private function getNamespaceVersion() { @@ -189,7 +189,7 @@ private function getNamespaceVersion() * * @param string $id The id of the cache entry to fetch. * - * @return string|boolean The cached data or FALSE, if no cache entry exists for the given id. + * @return string|bool The cached data or FALSE, if no cache entry exists for the given id. */ abstract protected function doFetch($id); diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php index d91d0bc6d6..1aa4d79118 100644 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php @@ -130,7 +130,7 @@ protected function doFlush() protected function doGetStats() { $usage = 0; - foreach ($this->getIterator() as $file) { + foreach ($this->getIterator() as $name => $file) { $usage += $file->getSize(); } diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php index 07eda8e874..23aaa37bd7 100644 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php @@ -105,21 +105,9 @@ protected function doSave($id, $data, $lifeTime = 0) $filepath = pathinfo($filename, PATHINFO_DIRNAME); if ( ! is_dir($filepath)) { - if (false === @mkdir($filepath, 0777, true) && !is_dir($filepath)) { - return false; - } - } elseif ( ! is_writable($filepath)) { - return false; - } - - $tmpFile = tempnam($filepath, basename($filename)); - - if ((file_put_contents($tmpFile, $lifeTime . PHP_EOL . $data) !== false) && @rename($tmpFile, $filename)) { - @chmod($filename, 0666 & ~umask()); - - return true; + mkdir($filepath, 0777, true); } - return false; + return file_put_contents($filename, $lifeTime . PHP_EOL . $data) !== false; } } diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php index d742fa080f..e35fbcc5a8 100644 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php @@ -21,5 +21,5 @@ class Version { - const VERSION = '1.4.0-DEV'; + const VERSION = '1.3.0'; } diff --git a/vendor/gregwar/cache/Gregwar/Cache/Cache.php b/vendor/gregwar/cache/Gregwar/Cache/Cache.php index db65ccaacb..2dfb2b0cd4 100644 --- a/vendor/gregwar/cache/Gregwar/Cache/Cache.php +++ b/vendor/gregwar/cache/Gregwar/Cache/Cache.php @@ -35,7 +35,7 @@ class Cache */ public function __construct($cacheDirectory = 'cache') { - $this->cacheDirectory = $cacheDirectory; + $this->cacheDirectory = $cacheDirectory; } /** @@ -45,9 +45,9 @@ public function __construct($cacheDirectory = 'cache') */ public function setCacheDirectory($cacheDirectory) { - $this->cacheDirectory = $cacheDirectory; + $this->cacheDirectory = $cacheDirectory; - return $this; + return $this; } /** @@ -57,7 +57,7 @@ public function setCacheDirectory($cacheDirectory) */ public function getCacheDirectory() { - return $this->cacheDirectory; + return $this->cacheDirectory; } /** @@ -112,24 +112,24 @@ protected function mkdir($directory) */ public function getCacheFile($filename, $actual = false, $mkdir = false) { - $path = array(); + $path = array(); - // Getting the length of the filename before the extension - $parts = explode('.', $filename); - $len = strlen($parts[0]); + // Getting the length of the filename before the extension + $parts = explode('.', $filename); + $len = strlen($parts[0]); - for ($i=0; $iprefixSize); $i++) { - $path[] = $filename[$i]; + for ($i=0; $iprefixSize); $i++) { + $path[] = $filename[$i]; } - $path = implode('/', $path); + $path = implode('/', $path); $actualDir = $this->getActualCacheDirectory() . '/' . $path; if ($mkdir && !is_dir($actualDir)) { - mkdir($actualDir, 0755, true); - } + mkdir($actualDir, 0755, true); + } - $path .= '/' . $filename; + $path .= '/' . $filename; if ($actual) { return $this->getActualCacheDirectory() . '/' . $path; @@ -148,20 +148,20 @@ protected function checkConditions($cacheFile, array $conditions = array()) { // Implicit condition: the cache file should exist if (!file_exists($cacheFile)) { - return false; - } + return false; + } - foreach ($conditions as $type => $value) { - switch ($type) { - case 'maxage': + foreach ($conditions as $type => $value) { + switch ($type) { + case 'maxage': case 'max-age': - // Return false if the file is older than $value + // Return false if the file is older than $value $age = time() - filectime($cacheFile); if ($age > $value) { return false; } - break; - case 'younger-than': + break; + case 'younger-than': case 'youngerthan': // Return false if the file is older than the file $value, or the files $value $check = function($filename) use ($cacheFile) { @@ -179,13 +179,13 @@ protected function checkConditions($cacheFile, array $conditions = array()) } } } - break; - default: - throw new \Exception('Cache condition '.$type.' not supported'); - } - } + break; + default: + throw new \Exception('Cache condition '.$type.' not supported'); + } + } - return true; + return true; } /** @@ -199,7 +199,7 @@ public function exists($filename, array $conditions = array()) { $cacheFile = $this->getCacheFile($filename, true); - return $this->checkConditions($cacheFile, $conditions); + return $this->checkConditions($cacheFile, $conditions); } /** @@ -215,7 +215,7 @@ public function check($filename, array $conditions = array()) */ public function set($filename, $contents = '') { - $cacheFile = $this->getCacheFile($filename, true, true); + $cacheFile = $this->getCacheFile($filename, true, true); file_put_contents($cacheFile, $contents); @@ -235,11 +235,11 @@ public function write($filename, $contents = '') */ public function get($filename, array $conditions = array()) { - if ($this->exists($filename, $conditions)) { - return file_get_contents($this->getCacheFile($filename, true)); - } else { - return null; - } + if ($this->exists($filename, $conditions)) { + return file_get_contents($this->getCacheFile($filename, true)); + } else { + return null; + } } /** @@ -259,12 +259,8 @@ protected function isRemote($file) * @param $file returns the cache file or the file contents * @param $actual returns the actual cache file */ - public function getOrCreate($filename, array $conditions = array(), $function, $file = false, $actual = false) + public function getOrCreate($filename, array $conditions = array(), \Closure $function, $file = false, $actual = false) { - if (!is_callable($function)) { - throw new InvalidArgumentException('The argument $function should be callable'); - } - $cacheFile = $this->getCacheFile($filename, true, true); $data = null; @@ -272,7 +268,7 @@ public function getOrCreate($filename, array $conditions = array(), $function, $ $data = file_get_contents($cacheFile); } else { @unlink($cacheFile); - $data = call_user_func($function, $cacheFile); + $data = $function($cacheFile); // Test if the closure wrote the file or if it returned the data if (!file_exists($cacheFile)) { @@ -288,7 +284,7 @@ public function getOrCreate($filename, array $conditions = array(), $function, $ /** * Alias to getOrCreate with $file = true */ - public function getOrCreateFile($filename, array $conditions = array(), $function, $actual = false) + public function getOrCreateFile($filename, array $conditions = array(), \Closure $function, $actual = false) { return $this->getOrCreate($filename, $conditions, $function, true, $actual); } diff --git a/vendor/gregwar/image/Gregwar/Image/Image.php b/vendor/gregwar/image/Gregwar/Image/Image.php index f43f3a7ad5..44ab9c4491 100644 --- a/vendor/gregwar/image/Gregwar/Image/Image.php +++ b/vendor/gregwar/image/Gregwar/Image/Image.php @@ -682,7 +682,7 @@ public function inline($type = 'jpg', $quality = 80) */ public static function open($file = '') { - return new static($file); + return new self($file); } /** @@ -690,7 +690,7 @@ public static function open($file = '') */ public static function create($width, $height) { - return new static(null, $width, $height); + return new self(null, $width, $height); } /** @@ -698,7 +698,7 @@ public static function create($width, $height) */ public static function fromData($data) { - $image = new static(); + $image = new self(); $image->setData($data); return $image; @@ -709,7 +709,7 @@ public static function fromData($data) */ public static function fromResource($resource) { - $image = new static(); + $image = new self(); $image->setResource($resource); return $image; diff --git a/vendor/mrclay/minify/HISTORY.txt b/vendor/mrclay/minify/HISTORY.txt index 9c44d164cd..aaba5acfe3 100644 --- a/vendor/mrclay/minify/HISTORY.txt +++ b/vendor/mrclay/minify/HISTORY.txt @@ -1,8 +1,5 @@ Minify Release History -(master) - * Builder styled with Bootstrap (thanks to help from acidvertigo) - Version 2.2.0 * Fix handling of RegEx in certain situations in JSMin * Thanks to Vovan-VE for reporting this diff --git a/vendor/mrclay/minify/min/lib/Minify/CSS/UriRewriter.php b/vendor/mrclay/minify/min/lib/Minify/CSS/UriRewriter.php index 43cc2548b0..50360ce7e0 100644 --- a/vendor/mrclay/minify/min/lib/Minify/CSS/UriRewriter.php +++ b/vendor/mrclay/minify/min/lib/Minify/CSS/UriRewriter.php @@ -70,7 +70,7 @@ public static function rewrite($css, $currentDir, $docRoot = null, $symlinks = a // rewrite $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/' ,array(self::$className, '_processUriCB'), $css); - $css = preg_replace_callback('/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/' + $css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/' ,array(self::$className, '_processUriCB'), $css); return $css; @@ -94,7 +94,7 @@ public static function prepend($css, $path) // append $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/' ,array(self::$className, '_processUriCB'), $css); - $css = preg_replace_callback('/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/' + $css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/' ,array(self::$className, '_processUriCB'), $css); self::$_prependPath = null; diff --git a/vendor/mrclay/minify/min/lib/Minify/Cache/File.php b/vendor/mrclay/minify/min/lib/Minify/Cache/File.php index c228eb2b2f..27b424a6ae 100644 --- a/vendor/mrclay/minify/min/lib/Minify/Cache/File.php +++ b/vendor/mrclay/minify/min/lib/Minify/Cache/File.php @@ -98,9 +98,6 @@ public function fetch($id) { if ($this->_locking) { $fp = fopen($this->_path . '/' . $id, 'rb'); - if (!$fp) { - return false; - } flock($fp, LOCK_SH); $ret = stream_get_contents($fp); flock($fp, LOCK_UN); diff --git a/vendor/mrclay/minify/min/lib/Minify/ClosureCompiler.php b/vendor/mrclay/minify/min/lib/Minify/ClosureCompiler.php index 53983a52aa..bdcdc7ee9c 100644 --- a/vendor/mrclay/minify/min/lib/Minify/ClosureCompiler.php +++ b/vendor/mrclay/minify/min/lib/Minify/ClosureCompiler.php @@ -33,11 +33,6 @@ */ class Minify_ClosureCompiler { - const OPTION_CHARSET = 'charset'; - const OPTION_COMPILATION_LEVEL = 'compilation_level'; - - public static $isDebug = false; - /** * Filepath of the Closure Compiler jar file. This must be set before * calling minifyJs(). @@ -70,28 +65,18 @@ class Minify_ClosureCompiler { * @see https://code.google.com/p/closure-compiler/source/browse/trunk/README * * @return string - * - * @throws Minify_ClosureCompiler_Exception */ public static function minify($js, $options = array()) { self::_prepare(); if (! ($tmpFile = tempnam(self::$tempDir, 'cc_'))) { - throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : could not create temp file in "'.self::$tempDir.'".'); + throw new Exception('Minify_ClosureCompiler : could not create temp file in "'.self::$tempDir.'".'); } file_put_contents($tmpFile, $js); - $cmd = self::_getCmd($options, $tmpFile); - exec($cmd, $output, $result_code); + exec(self::_getCmd($options, $tmpFile), $output, $result_code); unlink($tmpFile); if ($result_code != 0) { - $message = 'Minify_ClosureCompiler : Closure Compiler execution failed.'; - if (self::$isDebug) { - exec($cmd . ' 2>&1', $error); - if ($error) { - $message .= "\nReason:\n" . join("\n", $error); - } - } - throw new Minify_ClosureCompiler_Exception($message); + throw new Exception('Minify_ClosureCompiler : Closure Compiler execution failed.'); } return implode("\n", $output); } @@ -100,18 +85,17 @@ private static function _getCmd($userOptions, $tmpFile) { $o = array_merge( array( - self::OPTION_CHARSET => 'utf-8', - self::OPTION_COMPILATION_LEVEL => 'SIMPLE_OPTIMIZATIONS', + 'charset' => 'utf-8', + 'compilation_level' => 'SIMPLE_OPTIMIZATIONS', ), $userOptions ); - $charsetOption = $o[self::OPTION_CHARSET]; $cmd = self::$javaExecutable . ' -jar ' . escapeshellarg(self::$jarFile) - . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $charsetOption) - ? " --charset {$charsetOption}" + . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset']) + ? " --charset {$o['charset']}" : ''); - foreach (array(self::OPTION_COMPILATION_LEVEL) as $opt) { + foreach (array('compilation_level') as $opt) { if ($o[$opt]) { $cmd .= " --{$opt} ". escapeshellarg($o[$opt]); } @@ -122,18 +106,18 @@ private static function _getCmd($userOptions, $tmpFile) private static function _prepare() { if (! is_file(self::$jarFile)) { - throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $jarFile('.self::$jarFile.') is not a valid file.'); + throw new Exception('Minify_ClosureCompiler : $jarFile('.self::$jarFile.') is not a valid file.'); } if (! is_readable(self::$jarFile)) { - throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $jarFile('.self::$jarFile.') is not readable.'); + throw new Exception('Minify_ClosureCompiler : $jarFile('.self::$jarFile.') is not readable.'); } if (! is_dir(self::$tempDir)) { - throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $tempDir('.self::$tempDir.') is not a valid direcotry.'); + throw new Exception('Minify_ClosureCompiler : $tempDir('.self::$tempDir.') is not a valid direcotry.'); } if (! is_writable(self::$tempDir)) { - throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $tempDir('.self::$tempDir.') is not writable.'); + throw new Exception('Minify_ClosureCompiler : $tempDir('.self::$tempDir.') is not writable.'); } } } -class Minify_ClosureCompiler_Exception extends Exception {} +/* vim:ts=4:sw=4:et */ diff --git a/vendor/ornicar/php-user-agent/CHANGELOG.md b/vendor/ornicar/php-user-agent/CHANGELOG.md index 2d4aa7a13a..e8fa712581 100644 --- a/vendor/ornicar/php-user-agent/CHANGELOG.md +++ b/vendor/ornicar/php-user-agent/CHANGELOG.md @@ -1,13 +1,9 @@ # CHANGELOG -### 1.0.1 (????-??-??) - - * f1b82e5 - [Composer] Add branch alias support - ### 1.0.0 (2013-08-09) * Add a version following semver spec. -### v1.0 (2010-04-13) +### v1.0 - 2010-04-13 - * Create initial 1.0 version \ No newline at end of file + * create initial 1.0 version \ No newline at end of file diff --git a/vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php b/vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php index 3813b542d4..ca5f28731e 100644 --- a/vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -215,11 +215,7 @@ private function createStyleFromString($string) } elseif ('bg' == $match[0]) { $style->setBackground($match[1]); } else { - try { - $style->setOption($match[1]); - } catch (\InvalidArgumentException $e) { - return false; - } + $style->setOption($match[1]); } } diff --git a/vendor/tracy/tracy/readme.md b/vendor/tracy/tracy/readme.md index d0f0352a13..1564d592a8 100644 --- a/vendor/tracy/tracy/readme.md +++ b/vendor/tracy/tracy/readme.md @@ -2,7 +2,7 @@ ============================================== [![Downloads this Month](https://img.shields.io/packagist/dm/tracy/tracy.svg)](https://packagist.org/packages/tracy/tracy) -[![Build Status](https://travis-ci.org/nette/tracy.svg?branch=master)](https://travis-ci.org/nette/tracy) +[![Build Status](https://travis-ci.org/nette/tracy.svg?branch=v2.2)](https://travis-ci.org/nette/tracy) Tracy library is a useful PHP everyday programmer's helper. It helps you to: diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen.php b/vendor/tracy/tracy/src/Tracy/BlueScreen.php index 4e20fe167a..907bb6952f 100644 --- a/vendor/tracy/tracy/src/Tracy/BlueScreen.php +++ b/vendor/tracy/tracy/src/Tracy/BlueScreen.php @@ -50,15 +50,6 @@ public function render(\Exception $exception) { $panels = $this->panels; $info = array_filter($this->info); - $source = Helpers::getSource(); - $sourceIsUrl = preg_match('#^https?://#', $source); - $title = $exception instanceof \ErrorException - ? Helpers::errorTypeToString($exception->getSeverity()) - : get_class($exception); - $skipError = $sourceIsUrl && $exception instanceof \ErrorException && !empty($exception->skippable) - ? $source . (strpos($source, '?') ? '&' : '?') . '_tracy_skip_error' - : NULL; - require __DIR__ . '/templates/bluescreen.phtml'; } diff --git a/vendor/tracy/tracy/src/Tracy/Debugger.php b/vendor/tracy/tracy/src/Tracy/Debugger.php index 0c66cd99a9..b91016871a 100644 --- a/vendor/tracy/tracy/src/Tracy/Debugger.php +++ b/vendor/tracy/tracy/src/Tracy/Debugger.php @@ -14,39 +14,31 @@ /** * Debugger: displays and logs errors. * + * Behavior is determined by two factors: mode & output + * - modes: production / development + * - output: HTML / AJAX / CLI / other (e.g. XML) + * * @author David Grudl */ class Debugger { - /** server modes {@link Debugger::enable()} */ - const DEVELOPMENT = FALSE, - PRODUCTION = TRUE, - DETECT = NULL; - - const COOKIE_SECRET = 'tracy-debug'; - /** @var string */ - public static $version = '2.3-dev'; + public static $version = '2.2.2'; /** @var bool in production mode is suppressed any debugging output */ public static $productionMode = self::DETECT; - /** @var bool {@link Debugger::enable()} */ - private static $enabled = FALSE; - - /** @var bool prevent double rendering */ - private static $done; - - /********************* errors and exceptions reporting ****************d*g**/ + /** @var int timestamp with microseconds of the start of the request */ + public static $time; - /** @var bool|int determines whether any error will cause immediate death; if integer that it's matched against error severity */ - public static $strictMode = FALSE; + /** @var string requested URI or command line */ + public static $source; - /** @var bool disables the @ (shut-up) operator so that notices and warnings are no longer hidden */ - public static $scream = FALSE; + /** @var string URI pattern mask to open editor */ + public static $editor = 'editor://open/?file=%file&line=%line'; - /** @var array of callables specifies the functions that are automatically called after fatal error */ - public static $onFatalError = array(); + /** @var string command to open browser (use 'start ""' in Windows) */ + public static $browser; /********************* Debugger::dump() ****************d*g**/ @@ -59,53 +51,80 @@ class Debugger /** @var bool display location? {@link Debugger::dump()} */ public static $showLocation = FALSE; + /********************* errors and exceptions reporting ****************d*g**/ + + /** server modes {@link Debugger::enable()} */ + const DEVELOPMENT = FALSE, + PRODUCTION = TRUE, + DETECT = NULL; + + /** @var BlueScreen */ + private static $blueScreen; + + /** @var bool|int determines whether any error will cause immediate death; if integer that it's matched against error severity */ + public static $strictMode = FALSE; // $immediateDeath + + /** @var bool disables the @ (shut-up) operator so that notices and warnings are no longer hidden */ + public static $scream = FALSE; + + /** @var array of callables specifies the functions that are automatically called after fatal error */ + public static $onFatalError = array(); + + /** @var bool {@link Debugger::enable()} */ + private static $enabled = FALSE; + + /** @internal */ + public static $errorTypes = array( + E_ERROR => 'Fatal Error', + E_USER_ERROR => 'User Error', + E_RECOVERABLE_ERROR => 'Recoverable Error', + E_CORE_ERROR => 'Core Error', + E_COMPILE_ERROR => 'Compile Error', + E_PARSE => 'Parse Error', + E_WARNING => 'Warning', + E_CORE_WARNING => 'Core Warning', + E_COMPILE_WARNING => 'Compile Warning', + E_USER_WARNING => 'User Warning', + E_NOTICE => 'Notice', + E_USER_NOTICE => 'User Notice', + E_STRICT => 'Strict standards', + E_DEPRECATED => 'Deprecated', + E_USER_DEPRECATED => 'User Deprecated', + ); + /********************* logging ****************d*g**/ + /** @var Logger */ + private static $logger; + + /** @var FireLogger */ + private static $fireLogger; + /** @var string name of the directory where errors should be logged */ public static $logDirectory; - /** @var int log bluescreen in production mode for this error severity */ - public static $logSeverity = 0; - /** @var string|array email(s) to which send error notifications */ public static $email; - /** {@link Debugger::log()} and {@link Debugger::fireLog()} */ - const DEBUG = ILogger::DEBUG, - INFO = ILogger::INFO, - WARNING = ILogger::WARNING, - ERROR = ILogger::ERROR, - EXCEPTION = ILogger::EXCEPTION, - CRITICAL = ILogger::CRITICAL; - - /********************* misc ****************d*g**/ - - /** @var int timestamp with microseconds of the start of the request */ - public static $time; - /** @deprecated */ - public static $source; + public static $mailer = array('Tracy\Logger', 'defaultMailer'); - /** @var string URI pattern mask to open editor */ - public static $editor = 'editor://open/?file=%file&line=%line'; - - /** @var string command to open browser (use 'start ""' in Windows) */ - public static $browser; + /** @deprecated */ + public static $emailSnooze = 172800; - /********************* services ****************d*g**/ + /** {@link Debugger::log()} and {@link Debugger::fireLog()} */ + const DEBUG = 'debug', + INFO = 'info', + WARNING = 'warning', + ERROR = 'error', + EXCEPTION = 'exception', + CRITICAL = 'critical'; - /** @var BlueScreen */ - private static $blueScreen; + /********************* debug bar ****************d*g**/ /** @var Bar */ private static $bar; - /** @var ILogger */ - private static $logger; - - /** @var ILogger */ - private static $fireLogger; - /** * Static class - cannot be instantiated. @@ -118,32 +137,50 @@ final public function __construct() /** * Enables displaying or logging errors and exceptions. - * @param mixed production, development mode, autodetection or IP address(es) whitelist. - * @param string error log directory; enables logging in production mode, FALSE means that logging is disabled - * @param string administrator email; enables email sending in production mode + * @param mixed production, development mode, autodetection or IP address(es) whitelist. + * @param string error log directory; enables logging in production mode, FALSE means that logging is disabled + * @param string administrator email; enables email sending in production mode * @return void */ public static function enable($mode = NULL, $logDirectory = NULL, $email = NULL) { + self::$enabled = TRUE; self::$time = isset($_SERVER['REQUEST_TIME_FLOAT']) ? $_SERVER['REQUEST_TIME_FLOAT'] : microtime(TRUE); + if (isset($_SERVER['REQUEST_URI'])) { + self::$source = (!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://') + . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '') + . $_SERVER['REQUEST_URI']; + } else { + self::$source = empty($_SERVER['argv']) ? 'CLI' : 'CLI: ' . implode(' ', $_SERVER['argv']); + } error_reporting(E_ALL | E_STRICT); - if ($mode !== NULL || self::$productionMode === NULL) { - self::$productionMode = is_bool($mode) ? $mode : !self::detectDebugMode($mode); + // production/development mode detection + if (is_bool($mode)) { + self::$productionMode = $mode; + + } elseif ($mode !== self::DETECT || self::$productionMode === NULL) { // IP addresses or computer names whitelist detection + $list = is_string($mode) ? preg_split('#[,\s]+#', $mode) : (array) $mode; + if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { + $list[] = '127.0.0.1'; + $list[] = '::1'; + } + self::$productionMode = !in_array(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : php_uname('n'), $list, TRUE); } // logging configuration if ($email !== NULL) { self::$email = $email; } - if ($logDirectory !== NULL) { - self::$logDirectory = $logDirectory; + if (is_string($logDirectory)) { + self::$logDirectory = realpath($logDirectory); + if (self::$logDirectory === FALSE) { + self::_exceptionHandler(new \RuntimeException("Log directory is not found or is not directory.")); + } + } elseif ($logDirectory === FALSE) { + self::$logDirectory = NULL; } if (self::$logDirectory) { - if (!is_dir(self::$logDirectory) || !preg_match('#([a-z]:)?[/\\\\]#Ai', self::$logDirectory)) { - self::$logDirectory = NULL; - self::exceptionHandler(new \RuntimeException('Logging directory not found or is not absolute path.')); - } ini_set('error_log', self::$logDirectory . '/php_error.log'); } @@ -154,25 +191,97 @@ public static function enable($mode = NULL, $logDirectory = NULL, $email = NULL) ini_set('log_errors', FALSE); } elseif (ini_get('display_errors') != !self::$productionMode && ini_get('display_errors') !== (self::$productionMode ? 'stderr' : 'stdout')) { // intentionally == - self::exceptionHandler(new \RuntimeException("Unable to set 'display_errors' because function ini_set() is disabled.")); + self::_exceptionHandler(new \RuntimeException("Unable to set 'display_errors' because function ini_set() is disabled.")); } - if (!self::$enabled) { - register_shutdown_function(array(__CLASS__, 'shutdownHandler')); - set_exception_handler(array(__CLASS__, 'exceptionHandler')); - set_error_handler(array(__CLASS__, 'errorHandler')); + register_shutdown_function(array(__CLASS__, '_shutdownHandler')); + set_exception_handler(array(__CLASS__, '_exceptionHandler')); + set_error_handler(array(__CLASS__, '_errorHandler')); + + foreach (array('Tracy\Bar', 'Tracy\BlueScreen', 'Tracy\DefaultBarPanel', 'Tracy\Dumper', + 'Tracy\FireLogger', 'Tracy\Helpers', 'Tracy\Logger', ) as $class) { + class_exists($class); + } + } + + + /** + * @return BlueScreen + */ + public static function getBlueScreen() + { + if (!self::$blueScreen) { + self::$blueScreen = new BlueScreen; + self::$blueScreen->info = array( + 'PHP ' . PHP_VERSION, + isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : NULL, + 'Tracy ' . self::$version, + ); + } + return self::$blueScreen; + } + + + /** + * @return Bar + */ + public static function getBar() + { + if (!self::$bar) { + self::$bar = new Bar; + self::$bar->addPanel(new DefaultBarPanel('time')); + self::$bar->addPanel(new DefaultBarPanel('memory')); + self::$bar->addPanel(new DefaultBarPanel('errors'), __CLASS__ . ':errors'); // filled by _errorHandler() + self::$bar->addPanel(new DefaultBarPanel('dumps'), __CLASS__ . ':dumps'); // filled by barDump() + self::$bar->info = array( + 'PHP ' . PHP_VERSION, + isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : NULL, + 'Tracy ' . self::$version, + ); + } + return self::$bar; + } + + + /** + * @return void + */ + public static function setLogger($logger) + { + self::$logger = $logger; + } + + + /** + * @return Logger + */ + public static function getLogger() + { + if (!self::$logger) { + self::$logger = new Logger; + self::$logger->directory = & self::$logDirectory; + self::$logger->email = & self::$email; + self::$logger->mailer = & self::$mailer; + self::$logger->emailSnooze = & self::$emailSnooze; + } + return self::$logger; + } - foreach (array('Tracy\Bar', 'Tracy\BlueScreen', 'Tracy\DefaultBarPanel', 'Tracy\Dumper', - 'Tracy\FireLogger', 'Tracy\Helpers', 'Tracy\Logger', ) as $class) { - class_exists($class); - } - self::$enabled = TRUE; + /** + * @return FireLogger + */ + public static function getFireLogger() + { + if (!self::$fireLogger) { + self::$fireLogger = new FireLogger; } + return self::$fireLogger; } /** + * Is Debug enabled? * @return bool */ public static function isEnabled() @@ -181,20 +290,81 @@ public static function isEnabled() } + /** + * Logs message or exception to file (if not disabled) and sends email notification (if enabled). + * @param string|Exception + * @param int one of constant Debugger::INFO, WARNING, ERROR (sends email), EXCEPTION (sends email), CRITICAL (sends email) + * @return string logged error filename + */ + public static function log($message, $priority = self::INFO) + { + if (!self::$logDirectory) { + return; + } + + $exceptionFilename = NULL; + if ($message instanceof \Exception) { + $exception = $message; + while ($exception) { + $tmp[] = ($exception instanceof ErrorException + ? 'Fatal error: ' . $exception->getMessage() + : get_class($exception) . ': ' . $exception->getMessage()) + . ' in ' . $exception->getFile() . ':' . $exception->getLine(); + $exception = $exception->getPrevious(); + } + $exception = $message; + $message = implode($tmp, "\ncaused by "); + + $hash = md5(preg_replace('~(Resource id #)\d+~', '$1', $exception)); + $exceptionFilename = 'exception-' . @date('Y-m-d-H-i-s') . "-$hash.html"; + foreach (new \DirectoryIterator(self::$logDirectory) as $entry) { + if (strpos($entry, $hash)) { + $exceptionFilename = $entry; + $saved = TRUE; + break; + } + } + } elseif (!is_string($message)) { + $message = Dumper::toText($message); + } + + if ($exceptionFilename) { + $exceptionFilename = self::$logDirectory . '/' . $exceptionFilename; + if (empty($saved) && $logHandle = @fopen($exceptionFilename, 'w')) { + ob_start(); // double buffer prevents sending HTTP headers in some PHP + ob_start(function($buffer) use ($logHandle) { fwrite($logHandle, $buffer); }, 4096); + self::getBlueScreen()->render($exception); + ob_end_flush(); + ob_end_clean(); + fclose($logHandle); + } + } + + self::getLogger()->log(array( + @date('[Y-m-d H-i-s]'), + trim($message), + self::$source ? ' @ ' . self::$source : NULL, + $exceptionFilename ? ' @@ ' . basename($exceptionFilename) : NULL + ), $priority); + + return $exceptionFilename ? strtr($exceptionFilename, '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR) : NULL; + } + + /** * Shutdown handler to catch fatal errors and execute of the planned activities. * @return void * @internal */ - public static function shutdownHandler() + public static function _shutdownHandler() { - if (self::$done) { + if (!self::$enabled) { return; } $error = error_get_last(); - if (in_array($error['type'], array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE, E_RECOVERABLE_ERROR, E_USER_ERROR), TRUE)) { - self::exceptionHandler(Helpers::fixStack(new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line'])), FALSE); + if (in_array($error['type'], array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE), TRUE)) { + self::_exceptionHandler(Helpers::fixStack(new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line'])), FALSE); } elseif (!connection_aborted() && !self::$productionMode && self::isHtmlMode()) { self::getBar()->render(); @@ -204,15 +374,16 @@ public static function shutdownHandler() /** * Handler to catch uncaught exception. + * @param \Exception * @return void * @internal */ - public static function exceptionHandler(\Exception $exception, $exit = TRUE) + public static function _exceptionHandler(\Exception $exception, $exit = TRUE) { - if (self::$done) { + if (!self::$enabled) { return; } - self::$done = TRUE; + self::$enabled = FALSE; // prevent double rendering if (!headers_sent()) { $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; @@ -274,11 +445,16 @@ public static function exceptionHandler(\Exception $exception, $exit = TRUE) /** * Handler to catch warnings and notices. + * @param int level of the error raised + * @param string error message + * @param string file that the error was raised in + * @param int line number the error was raised at + * @param array an array of variables that existed in the scope the error was triggered in * @return bool FALSE to call normal error handler, NULL otherwise * @throws ErrorException * @internal */ - public static function errorHandler($severity, $message, $file, $line, $context) + public static function _errorHandler($severity, $message, $file, $line, $context) { if (self::$scream) { error_reporting(E_ALL | E_STRICT); @@ -289,7 +465,7 @@ public static function errorHandler($severity, $message, $file, $line, $context) $previous = isset($context['e']) && $context['e'] instanceof \Exception ? $context['e'] : NULL; $e = new ErrorException($message, 0, $severity, $file, $line, $previous); $e->context = $context; - self::exceptionHandler($e); + self::_exceptionHandler($e); } $e = new ErrorException($message, 0, $severity, $file, $line); @@ -299,22 +475,13 @@ public static function errorHandler($severity, $message, $file, $line, $context) } elseif (($severity & error_reporting()) !== $severity) { return FALSE; // calls normal error handler to fill-in error_get_last() - } elseif (($severity & self::$logSeverity) === $severity) { - $e = new ErrorException($message, 0, $severity, $file, $line); - $e->context = $context; - self::log($e, self::ERROR); - return NULL; - - } elseif (!self::$productionMode && !isset($_GET['_tracy_skip_error']) - && (is_bool(self::$strictMode) ? self::$strictMode : ((self::$strictMode & $severity) === $severity)) - ) { + } elseif (!self::$productionMode && (is_bool(self::$strictMode) ? self::$strictMode : ((self::$strictMode & $severity) === $severity))) { $e = new ErrorException($message, 0, $severity, $file, $line); $e->context = $context; - $e->skippable = TRUE; - self::exceptionHandler($e); + self::_exceptionHandler($e); } - $message = 'PHP ' . Helpers::errorTypeToString($severity) . ": $message"; + $message = 'PHP ' . (isset(self::$errorTypes[$severity]) ? self::$errorTypes[$severity] : 'Unknown error') . ": $message"; $count = & self::getBar()->getPanel(__CLASS__ . ':errors')->data["$file|$line|$message"]; if ($count++) { // repeated error @@ -331,89 +498,6 @@ public static function errorHandler($severity, $message, $file, $line, $context) } - private static function isHtmlMode() - { - return empty($_SERVER['HTTP_X_REQUESTED_WITH']) - && PHP_SAPI !== 'cli' - && !preg_match('#^Content-Type: (?!text/html)#im', implode("\n", headers_list())); - } - - - /********************* services ****************d*g**/ - - - /** - * @return BlueScreen - */ - public static function getBlueScreen() - { - if (!self::$blueScreen) { - self::$blueScreen = new BlueScreen; - self::$blueScreen->info = array( - 'PHP ' . PHP_VERSION, - isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : NULL, - 'Tracy ' . self::$version, - ); - } - return self::$blueScreen; - } - - - /** - * @return Bar - */ - public static function getBar() - { - if (!self::$bar) { - self::$bar = new Bar; - self::$bar->addPanel(new DefaultBarPanel('time')); - self::$bar->addPanel(new DefaultBarPanel('memory')); - self::$bar->addPanel(new DefaultBarPanel('errors'), __CLASS__ . ':errors'); // filled by errorHandler() - self::$bar->info = array( - 'PHP ' . PHP_VERSION, - isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : NULL, - 'Tracy ' . self::$version, - ); - } - return self::$bar; - } - - - /** - * @return void - */ - public static function setLogger(ILogger $logger) - { - self::$logger = $logger; - } - - - /** - * @return ILogger - */ - public static function getLogger() - { - if (!self::$logger) { - self::$logger = new Logger(self::$logDirectory, self::$email, self::getBlueScreen()); - self::$logger->directory = & self::$logDirectory; // back compatiblity - self::$logger->email = & self::$email; - } - return self::$logger; - } - - - /** - * @return ILogger - */ - public static function getFireLogger() - { - if (!self::$fireLogger) { - self::$fireLogger = new FireLogger; - } - return self::$fireLogger; - } - - /********************* useful tools ****************d*g**/ @@ -472,11 +556,7 @@ public static function timer($name = NULL) public static function barDump($var, $title = NULL, array $options = NULL) { if (!self::$productionMode) { - static $panel; - if (!$panel) { - self::getBar()->addPanel($panel = new DefaultBarPanel('dumps')); - } - $panel->data[] = array('title' => $title, 'dump' => Dumper::toHtml($var, (array) $options + array( + self::getBar()->getPanel(__CLASS__ . ':dumps')->data[] = array('title' => $title, 'dump' => Dumper::toHtml($var, (array) $options + array( Dumper::DEPTH => self::$maxDepth, Dumper::TRUNCATE => self::$maxLen, Dumper::LOCATION => self::$showLocation, @@ -486,19 +566,6 @@ public static function barDump($var, $title = NULL, array $options = NULL) } - /** - * Logs message or exception to file. - * @param string|Exception - * @return string logged error filename - */ - public static function log($message, $priority = ILogger::INFO) - { - if (self::getLogger()->directory) { - return self::getLogger()->log($message, $priority); - } - } - - /** * Sends message to FireLogger console. * @param mixed message to log @@ -512,27 +579,11 @@ public static function fireLog($message) } - /** - * Detects debug mode by IP address. - * @param string|array IP addresses or computer names whitelist detection - * @return bool - */ - public static function detectDebugMode($list = NULL) + private static function isHtmlMode() { - $addr = isset($_SERVER['REMOTE_ADDR']) - ? $_SERVER['REMOTE_ADDR'] - : php_uname('n'); - $secret = isset($_COOKIE[self::COOKIE_SECRET]) && is_string($_COOKIE[self::COOKIE_SECRET]) - ? $_COOKIE[self::COOKIE_SECRET] - : NULL; - $list = is_string($list) - ? preg_split('#[,\s]+#', $list) - : (array) $list; - if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { - $list[] = '127.0.0.1'; - $list[] = '::1'; - } - return in_array($addr, $list, TRUE) || in_array("$secret@$addr", $list, TRUE); + return empty($_SERVER['HTTP_X_REQUESTED_WITH']) + && PHP_SAPI !== 'cli' + && !preg_match('#^Content-Type: (?!text/html)#im', implode("\n", headers_list())); } } diff --git a/vendor/tracy/tracy/src/Tracy/Dumper.php b/vendor/tracy/tracy/src/Tracy/Dumper.php index 098958b37c..cdd8dbc5ad 100644 --- a/vendor/tracy/tracy/src/Tracy/Dumper.php +++ b/vendor/tracy/tracy/src/Tracy/Dumper.php @@ -21,12 +21,7 @@ class Dumper TRUNCATE = 'truncate', // how truncate long strings? (defaults to 150) COLLAPSE = 'collapse', // always collapse? (defaults to false) COLLAPSE_COUNT = 'collapsecount', // how big array/object are collapsed? (defaults to 7) - LOCATION = 'location'; // show location string? (defaults to 0) - - const - LOCATION_SOURCE = 1, // shows where dump was called - LOCATION_LINK = 2, // appends clickable anchor - LOCATION_CLASS = 4; // shows where class is defined + LOCATION = 'location'; // show location string? (defaults to false) /** @var array */ public static $terminalColors = array( @@ -78,15 +73,13 @@ public static function toHtml($var, array $options = NULL) self::TRUNCATE => 150, self::COLLAPSE => FALSE, self::COLLAPSE_COUNT => 7, + self::LOCATION => FALSE, ); - $loc = & $options[self::LOCATION]; - $loc = $loc === TRUE ? ~0 : (int) $loc; - - list($file, $line, $code) = $loc ? self::findLocation() : NULL; + list($file, $line, $code) = $options[self::LOCATION] ? self::findLocation() : NULL; return '
' : '>')
+			. ($file ? Helpers::createHtml(' title="%in file % on line %" data-tracy-href="%"', "$code\n", $file, $line, Helpers::editorUri($file, $line)) . '>' : '>')
 			. self::dumpVar($var, $options)
-			. ($file && $loc & self::LOCATION_LINK ? 'in ' . Helpers::editorLink($file, $line) . '' : '')
+			. ($file ? 'in ' . Helpers::editorLink($file, $line) . '' : '')
 			. "
\n"; } @@ -223,17 +216,12 @@ private static function dumpObject(& $var, $options, $level) $fields = (array) $var; } - $editor = NULL; - if ($options[self::LOCATION] & self::LOCATION_CLASS) { - $rc = $var instanceof \Closure ? new \ReflectionFunction($var) : new \ReflectionClass($var); - $editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine()); - } + static $list = array(); + $rc = $var instanceof \Closure ? new \ReflectionFunction($var) : new \ReflectionClass($var); $out = 'getFileName(), $rc->getStartLine(), $editor) : '') + . ($options[self::LOCATION] && ($editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine())) ? ' data-tracy-href="' . htmlspecialchars($editor) . '"' : '') . '>' . get_class($var) . ' #' . substr(md5(spl_object_hash($var)), 0, 4) . ''; - static $list = array(); - if (empty($fields)) { return $out . "\n"; diff --git a/vendor/tracy/tracy/src/Tracy/FireLogger.php b/vendor/tracy/tracy/src/Tracy/FireLogger.php index e09176a8aa..0ab1144583 100644 --- a/vendor/tracy/tracy/src/Tracy/FireLogger.php +++ b/vendor/tracy/tracy/src/Tracy/FireLogger.php @@ -16,16 +16,15 @@ * @see http://firelogger.binaryage.com * @author David Grudl */ -class FireLogger implements ILogger +class FireLogger { - /** @var int */ - public $maxDepth = 3; + const DEBUG = 'debug', + INFO = 'info', + WARNING = 'warning', + ERROR = 'error', + CRITICAL = 'critical'; - /** @var int */ - public $maxLenght = 150; - - /** @var array */ - private $payload = array('logs' => array()); + private static $payload = array('logs' => array()); /** @@ -33,7 +32,7 @@ class FireLogger implements ILogger * @param mixed * @return bool was successful? */ - public function log($message, $priority = self::DEBUG) + public static function log($message, $priority = self::DEBUG) { if (!isset($_SERVER['HTTP_X_FIRELOGGER']) || headers_sent()) { return FALSE; @@ -42,7 +41,7 @@ public function log($message, $priority = self::DEBUG) $item = array( 'name' => 'PHP', 'level' => $priority, - 'order' => count($this->payload['logs']), + 'order' => count(self::$payload['logs']), 'time' => str_pad(number_format((microtime(TRUE) - Debugger::$time) * 1000, 1, '.', ' '), 8, '0', STR_PAD_LEFT) . ' ms', 'template' => '', 'message' => '', @@ -58,7 +57,7 @@ public function log($message, $priority = self::DEBUG) $e = array_shift($args); $trace = $e->getTrace(); if (isset($trace[0]['class']) && $trace[0]['class'] === 'Tracy\Debugger' - && ($trace[0]['function'] === 'shutdownHandler' || $trace[0]['function'] === 'errorHandler') + && ($trace[0]['function'] === '_shutdownHandler' || $trace[0]['function'] === '_errorHandler') ) { unset($trace[0]); } @@ -101,8 +100,8 @@ public function log($message, $priority = self::DEBUG) $item['args'] = $args; - $this->payload['logs'][] = $this->jsonDump($item, -1); - foreach (str_split(base64_encode(@json_encode($this->payload)), 4990) as $k => $v) { // intentionally @ + self::$payload['logs'][] = self::jsonDump($item, -1); + foreach (str_split(base64_encode(@json_encode(self::$payload)), 4990) as $k => $v) { // intentionally @ header("FireLogger-de11e-$k:$v"); } return TRUE; @@ -115,14 +114,14 @@ public function log($message, $priority = self::DEBUG) * @param int current recursion level * @return string */ - private function jsonDump(& $var, $level = 0) + private static function jsonDump(& $var, $level = 0) { if (is_bool($var) || is_null($var) || is_int($var) || is_float($var)) { return $var; } elseif (is_string($var)) { - if ($this->maxLenght && strlen($var) > $this->maxLenght) { - $var = substr($var, 0, $this->maxLenght) . " \xE2\x80\xA6 "; + if (Debugger::$maxLen && strlen($var) > Debugger::$maxLen) { + $var = substr($var, 0, Debugger::$maxLen) . " \xE2\x80\xA6 "; } return Helpers::fixEncoding($var); @@ -134,12 +133,12 @@ private function jsonDump(& $var, $level = 0) if (isset($var[$marker])) { return "\xE2\x80\xA6RECURSION\xE2\x80\xA6"; - } elseif ($level < $this->maxDepth || !$this->maxDepth) { + } elseif ($level < Debugger::$maxDepth || !Debugger::$maxDepth) { $var[$marker] = TRUE; $res = array(); foreach ($var as $k => & $v) { if ($k !== $marker) { - $res[$this->jsonDump($k)] = $this->jsonDump($v, $level + 1); + $res[self::jsonDump($k)] = self::jsonDump($v, $level + 1); } } unset($var[$marker]); @@ -155,14 +154,14 @@ private function jsonDump(& $var, $level = 0) if (in_array($var, $list, TRUE)) { return "\xE2\x80\xA6RECURSION\xE2\x80\xA6"; - } elseif ($level < $this->maxDepth || !$this->maxDepth) { + } elseif ($level < Debugger::$maxDepth || !Debugger::$maxDepth) { $list[] = $var; $res = array("\x00" => '(object) ' . get_class($var)); foreach ($arr as $k => & $v) { if ($k[0] === "\x00") { $k = substr($k, strrpos($k, "\x00") + 1); } - $res[$this->jsonDump($k)] = $this->jsonDump($v, $level + 1); + $res[self::jsonDump($k)] = self::jsonDump($v, $level + 1); } array_pop($list); return $res; diff --git a/vendor/tracy/tracy/src/Tracy/Helpers.php b/vendor/tracy/tracy/src/Tracy/Helpers.php index d94f2ccd44..56f24e563f 100644 --- a/vendor/tracy/tracy/src/Tracy/Helpers.php +++ b/vendor/tracy/tracy/src/Tracy/Helpers.php @@ -30,7 +30,7 @@ public static function editorLink($file, $line) if (substr($dir, 0, strlen($base)) === $base) { $dir = '...' . substr($dir, strlen($base)); } - return self::formatHtml('%%%', + return self::createHtml('%%%', $editor, "$file:$line", rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR, @@ -38,7 +38,7 @@ public static function editorLink($file, $line) $line ? ":$line" : '' ); } else { - return self::formatHtml('%', $file . ($line ? ":$line" : '')); + return self::createHtml('%', $file . ($line ? ":$line" : '')); } } @@ -55,7 +55,7 @@ public static function editorUri($file, $line) } - public static function formatHtml($mask) + public static function createHtml($mask) { $args = func_get_args(); return preg_replace_callback('#%#', function() use (& $args, & $count) { @@ -79,7 +79,6 @@ public static function findTrace(array $trace, $method, & $index = NULL) } - /** @internal */ public static function fixStack($exception) { if (function_exists('xdebug_get_function_stack')) { @@ -105,7 +104,11 @@ public static function fixStack($exception) } - /** @internal */ + /** + * Returns correctly UTF-8 encoded string. + * @param string byte stream to fix + * @return string + */ public static function fixEncoding($s) { if (PHP_VERSION_ID < 50400) { @@ -115,41 +118,4 @@ public static function fixEncoding($s) } } - - /** @internal */ - public static function errorTypeToString($type) - { - $types = array( - E_ERROR => 'Fatal Error', - E_USER_ERROR => 'User Error', - E_RECOVERABLE_ERROR => 'Recoverable Error', - E_CORE_ERROR => 'Core Error', - E_COMPILE_ERROR => 'Compile Error', - E_PARSE => 'Parse Error', - E_WARNING => 'Warning', - E_CORE_WARNING => 'Core Warning', - E_COMPILE_WARNING => 'Compile Warning', - E_USER_WARNING => 'User Warning', - E_NOTICE => 'Notice', - E_USER_NOTICE => 'User Notice', - E_STRICT => 'Strict standards', - E_DEPRECATED => 'Deprecated', - E_USER_DEPRECATED => 'User Deprecated', - ); - return isset($types[$type]) ? $types[$type] : 'Unknown error'; - } - - - /** @internal */ - public static function getSource() - { - if (isset($_SERVER['REQUEST_URI'])) { - return (!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://') - . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '') - . $_SERVER['REQUEST_URI']; - } else { - return empty($_SERVER['argv']) ? 'CLI' : 'CLI: ' . implode(' ', $_SERVER['argv']); - } - } - } diff --git a/vendor/tracy/tracy/src/Tracy/ILogger.php b/vendor/tracy/tracy/src/Tracy/ILogger.php deleted file mode 100644 index 562f26b0ad..0000000000 --- a/vendor/tracy/tracy/src/Tracy/ILogger.php +++ /dev/null @@ -1,27 +0,0 @@ -directory = $directory; - $this->email = $email; - $this->blueScreen = $blueScreen; - $this->mailer = array($this, 'defaultMailer'); - } + /** @var string|array email or emails to which send error notifications */ + public $email; /** * Logs message or exception to file and sends email notification. - * @param string|Exception - * @param int one of constant ILogger::INFO, WARNING, ERROR (sends email), EXCEPTION (sends email), CRITICAL (sends email) - * @return string logged error filename + * @param string|array + * @param int one of constant Debugger::INFO, WARNING, ERROR (sends email), EXCEPTION (sends email), CRITICAL (sends email) + * @return void */ - public function log($value, $priority = self::INFO) + public function log($message, $priority = NULL) { if (!is_dir($this->directory)) { throw new \RuntimeException("Directory '$this->directory' is not found or is not directory."); } - $exceptionFile = $value instanceof \Exception ? $this->logException($value) : NULL; - $message = $this->formatMessage($value); + if (is_array($message)) { + $message = implode(' ', $message); + } + $message = preg_replace('#\s*\r?\n\s*#', ' ', trim($message)); $file = $this->directory . '/' . strtolower($priority ?: self::INFO) . '.log'; - if (!@file_put_contents($file, $message . PHP_EOL, FILE_APPEND | LOCK_EX)) { throw new \RuntimeException("Unable to write to log file '$file'. Is directory writable?"); } @@ -68,64 +64,6 @@ public function log($value, $priority = self::INFO) ) { call_user_func($this->mailer, $message, implode(', ', (array) $this->email)); } - - return $exceptionFile; - } - - - /** - * @return string - */ - private function formatMessage($value, $exceptionFile = NULL) - { - if ($value instanceof \Exception) { - while ($value) { - $tmp[] = ($value instanceof \ErrorException ? 'Fatal error: ' . $value->getMessage() : get_class($value) . ': ' . $value->getMessage()) - . ' in ' . $value->getFile() . ':' . $value->getLine(); - $value = $value->getPrevious(); - } - $value = implode($tmp, "\ncaused by "); - - } elseif (!is_string($value)) { - $value = Dumper::toText($value); - } - - $value = trim(preg_replace('#\s*\r?\n\s*#', ' ', $value)); - - return implode(' ', array( - @date('[Y-m-d H-i-s]'), - $value, - ' @ ' . Helpers::getSource(), - $exceptionFile ? ' @@ ' . basename($exceptionFile) : NULL - )); - } - - - /** - * @return string logged error filename - */ - private function logException(\Exception $exception) - { - $dir = strtr($this->directory . '/', '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR); - $hash = md5(preg_replace('~(Resource id #)\d+~', '$1', $exception)); - foreach (new \DirectoryIterator($this->directory) as $file) { - if (strpos($file, $hash)) { - return $dir . $file; - } - } - - $file = $dir . 'exception-' . @date('Y-m-d-H-i-s') . "-$hash.html"; - if ($handle = @fopen($file, 'w')) { - ob_start(); // double buffer prevents sending HTTP headers in some PHP - ob_start(function($buffer) use ($handle) { fwrite($handle, $buffer); }, 4096); - $bs = $this->blueScreen ?: new BlueScreen; - $bs->render($exception); - ob_end_flush(); - ob_end_clean(); - fclose($handle); - } - - return $file; } @@ -134,9 +72,8 @@ private function logException(\Exception $exception) * @param string * @param string * @return void - * @internal */ - public function defaultMailer($message, $email) + public static function defaultMailer($message, $email) { $host = preg_replace('#[^\w.-]+#', '', isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : php_uname('n')); $parts = str_replace( diff --git a/vendor/tracy/tracy/src/Tracy/OutputDebugger.php b/vendor/tracy/tracy/src/Tracy/OutputDebugger.php index 5f60dbbe78..f47abe94b7 100644 --- a/vendor/tracy/tracy/src/Tracy/OutputDebugger.php +++ b/vendor/tracy/tracy/src/Tracy/OutputDebugger.php @@ -42,7 +42,6 @@ public function start() } - /** @internal */ public function handler($s, $phase) { $trace = debug_backtrace(FALSE); diff --git a/vendor/tracy/tracy/src/Tracy/templates/bar.phtml b/vendor/tracy/tracy/src/Tracy/templates/bar.phtml index e3b85cfe78..4b39dc4e52 100644 --- a/vendor/tracy/tracy/src/Tracy/templates/bar.phtml +++ b/vendor/tracy/tracy/src/Tracy/templates/bar.phtml @@ -32,6 +32,13 @@ use Tracy; + + +
@@ -48,9 +47,7 @@ $counter = 0;

getCode() ? ' #' . $exception->getCode() : '') ?>

-

getMessage(), ENT_IGNORE) ?> - getMessage())) ?>" rel="noreferrer">search► - skip error►

+

getMessage(), ENT_IGNORE) ?> getMessage())) ?>" id="tracyBsSearch" rel="noreferrer">search►

getPrevious()): ?> @@ -104,7 +101,7 @@ $counter = 0; - +

Call stack

@@ -120,7 +117,7 @@ $counter = 0; inner-code - " class="tracy-toggle">source  + " class="tracy-toggle tracy-collapsed">source  " ?> @@ -131,11 +128,11 @@ $counter = 0;

-
id="tracyBsSrc">
+
id="tracyBsSrc">
-
">
+
">
@@ -150,7 +147,7 @@ $counter = 0; } foreach ($row['args'] as $k => $v) { echo '', htmlspecialchars(isset($params[$k]) ? '$' . $params[$k]->name : "#$k"), ''; - echo Dumper::toHtml($v, array(Dumper::LOCATION => Dumper::LOCATION_CLASS)); + echo Dumper::toHtml($v); echo "\n"; } ?> @@ -173,7 +170,7 @@ $counter = 0; context as $k => $v) { - echo '\n"; + echo '\n"; } ?>
$', htmlspecialchars($k), '', Dumper::toHtml($v, array(Dumper::LOCATION => Dumper::LOCATION_CLASS)), "
$', htmlspecialchars($k), '', Dumper::toHtml($v), "
@@ -219,7 +216,7 @@ $counter = 0; $v) echo '\n"; + foreach ($_SESSION as $k => $v) echo '\n"; ?>
', htmlspecialchars($k), '', $k === '__NF' ? 'Nette Session' : Dumper::toHtml($v, array(Dumper::LOCATION => Dumper::LOCATION_CLASS)), "
', htmlspecialchars($k), '', $k === '__NF' ? 'Nette Session' : Dumper::toHtml($v), "
@@ -231,7 +228,7 @@ $counter = 0;
$v) echo '\n"; + foreach ($_SESSION['__NF']['DATA'] as $k => $v) echo '\n"; ?>
', htmlspecialchars($k), '', Dumper::toHtml($v, array(Dumper::LOCATION => Dumper::LOCATION_CLASS)), "
', htmlspecialchars($k), '', Dumper::toHtml($v), "
@@ -333,8 +330,12 @@ $counter = 0;
    -
  • Report generated at
  • -
  • +
  • Report generated at
  • + +
  • + +
  • +
@@ -364,15 +365,6 @@ $counter = 0; bs.onclick = function(e) { e = e || window.event; - - if (e.ctrlKey) { - for (var link = e.target; link && (!link.getAttribute || !link.getAttribute('data-tracy-href')); link = link.parentNode) {} - if (link) { - location.href = link.getAttribute('data-tracy-href'); - return false; - } - } - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { return; } diff --git a/vendor/tracy/tracy/src/tracy.php b/vendor/tracy/tracy/src/tracy.php index dcd29100a3..f77af928e7 100644 --- a/vendor/tracy/tracy/src/tracy.php +++ b/vendor/tracy/tracy/src/tracy.php @@ -1,7 +1,7 @@ raw('array('); $first = true; - foreach ($value as $key => $v) { + foreach ($value as $key => $value) { if (!$first) { $this->raw(', '); } $first = false; $this->repr($key); $this->raw(' => '); - $this->repr($v); + $this->repr($value); } $this->raw(')'); } else { @@ -267,9 +267,4 @@ public function outdent($step = 1) return $this; } - - public function getVarName() - { - return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); - } } diff --git a/vendor/twig/twig/lib/Twig/Environment.php b/vendor/twig/twig/lib/Twig/Environment.php index f1fec00fca..d3ba9be91f 100644 --- a/vendor/twig/twig/lib/Twig/Environment.php +++ b/vendor/twig/twig/lib/Twig/Environment.php @@ -16,7 +16,7 @@ */ class Twig_Environment { - const VERSION = '1.16.1-DEV'; + const VERSION = '1.16.0'; protected $charset; protected $loader; diff --git a/vendor/twig/twig/lib/Twig/ExpressionParser.php b/vendor/twig/twig/lib/Twig/ExpressionParser.php index f685bad8ec..01594f7104 100644 --- a/vendor/twig/twig/lib/Twig/ExpressionParser.php +++ b/vendor/twig/twig/lib/Twig/ExpressionParser.php @@ -318,7 +318,7 @@ public function getFunctionNode($name, $line) throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line, $this->parser->getFilename()); } - return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line); + return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_Template::ANY_CALL, $line); default: if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) { $arguments = new Twig_Node_Expression_Array(array(), $line); diff --git a/vendor/twig/twig/lib/Twig/Extension/Core.php b/vendor/twig/twig/lib/Twig/Extension/Core.php index ef36576984..750ef0ff83 100644 --- a/vendor/twig/twig/lib/Twig/Extension/Core.php +++ b/vendor/twig/twig/lib/Twig/Extension/Core.php @@ -672,7 +672,7 @@ function _twig_markup2string(&$value) function twig_array_merge($arr1, $arr2) { if (!is_array($arr1) || !is_array($arr2)) { - throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or hashes; %s and %s given.', gettype($arr1), gettype($arr2))); + throw new Twig_Error_Runtime('The merge filter only works with arrays or hashes.'); } return array_merge($arr1, $arr2); @@ -702,7 +702,7 @@ function twig_slice(Twig_Environment $env, $item, $start, $length = null, $prese $item = (string) $item; if (function_exists('mb_get_info') && null !== $charset = $env->getCharset()) { - return (string) mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset); + return mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset); } return null === $length ? substr($item, $start) : substr($item, $start, $length); @@ -944,7 +944,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', static $htmlspecialcharsCharsets; if (null === $htmlspecialcharsCharsets) { - if (defined('HHVM_VERSION')) { + if ('hiphop' === substr(PHP_VERSION, -6)) { $htmlspecialcharsCharsets = array('utf-8' => true, 'UTF-8' => true); } else { $htmlspecialcharsCharsets = array( diff --git a/vendor/twig/twig/lib/Twig/Node/AutoEscape.php b/vendor/twig/twig/lib/Twig/Node/AutoEscape.php index fcabf90338..8f190e0bd8 100644 --- a/vendor/twig/twig/lib/Twig/Node/AutoEscape.php +++ b/vendor/twig/twig/lib/Twig/Node/AutoEscape.php @@ -30,7 +30,7 @@ public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'a /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Block.php b/vendor/twig/twig/lib/Twig/Node/Block.php index 989e4a0ca8..50eb67ed8c 100644 --- a/vendor/twig/twig/lib/Twig/Node/Block.php +++ b/vendor/twig/twig/lib/Twig/Node/Block.php @@ -25,7 +25,7 @@ public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = nul /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/BlockReference.php b/vendor/twig/twig/lib/Twig/Node/BlockReference.php index a05ea045bf..013e369ebe 100644 --- a/vendor/twig/twig/lib/Twig/Node/BlockReference.php +++ b/vendor/twig/twig/lib/Twig/Node/BlockReference.php @@ -25,7 +25,7 @@ public function __construct($name, $lineno, $tag = null) /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Do.php b/vendor/twig/twig/lib/Twig/Node/Do.php index 9981bc16ba..c528066b29 100644 --- a/vendor/twig/twig/lib/Twig/Node/Do.php +++ b/vendor/twig/twig/lib/Twig/Node/Do.php @@ -24,7 +24,7 @@ public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Array.php b/vendor/twig/twig/lib/Twig/Node/Expression/Array.php index 6cf7ca1445..1da785fe42 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Array.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Array.php @@ -63,7 +63,7 @@ public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $ke /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php b/vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php index 4d5dbdb903..2ddea78cf0 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php @@ -15,7 +15,7 @@ class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary.php index 5c383d1552..9dd5de2c83 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary.php @@ -19,7 +19,7 @@ public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php index 93b3b96f0e..5de6c72d21 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php @@ -12,14 +12,14 @@ class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary { public function compile(Twig_Compiler $compiler) { - $left = $compiler->getVarName(); - $right = $compiler->getVarName(); $compiler - ->raw(sprintf('(is_string($%s = ', $left)) + ->raw('(0 === substr_compare(') ->subcompile($this->getNode('left')) - ->raw(sprintf(') && is_string($%s = ', $right)) + ->raw(', ') ->subcompile($this->getNode('right')) - ->raw(sprintf(') && (\'\' === $%2$s || $%2$s === substr($%1$s, -strlen($%2$s))))', $left, $right)) + ->raw(', -strlen(') + ->subcompile($this->getNode('right')) + ->raw(')))') ; } diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php index d3518b558a..7fbd0556fc 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php @@ -13,7 +13,7 @@ class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php index 1d485b61c1..788f9377ae 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php @@ -13,7 +13,7 @@ class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php index 8f215f1c11..f347b7b6e8 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php @@ -13,7 +13,7 @@ class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php index 6cd3a217ce..b2c5904050 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php @@ -13,7 +13,7 @@ class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php index fc102fed30..bea4f2a607 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php @@ -13,7 +13,7 @@ class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php index d2e30d66e5..eb8c107cb1 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php @@ -12,14 +12,12 @@ class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary { public function compile(Twig_Compiler $compiler) { - $left = $compiler->getVarName(); - $right = $compiler->getVarName(); $compiler - ->raw(sprintf('(is_string($%s = ', $left)) + ->raw('(0 === strpos(') ->subcompile($this->getNode('left')) - ->raw(sprintf(') && is_string($%s = ', $right)) + ->raw(', ') ->subcompile($this->getNode('right')) - ->raw(sprintf(') && (\'\' === $%2$s || 0 === strpos($%1$s, $%2$s)))', $left, $right)) + ->raw('))') ; } diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php b/vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php index 4ddb2cf440..647196eb5b 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php @@ -25,7 +25,7 @@ public function __construct(Twig_NodeInterface $name, $asString = false, $lineno /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php b/vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php index db06abb0ad..00ac6701f4 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php @@ -24,7 +24,7 @@ public function __construct($name, $lineno, $tag = null) /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php b/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php index 6ce61111cf..55d9fcc320 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php @@ -11,7 +11,7 @@ */ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression { - public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression $arguments = null, $type, $lineno) + public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type, $lineno) { parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno); } @@ -32,30 +32,20 @@ public function compile(Twig_Compiler $compiler) $compiler->raw(', ')->subcompile($this->getNode('attribute')); - // only generate optional arguments when needed (to make generated code more readable) - $needFourth = $this->getAttribute('ignore_strict_check'); - $needThird = $needFourth || $this->getAttribute('is_defined_test'); - $needSecond = $needThird || Twig_Template::ANY_CALL !== $this->getAttribute('type'); - $needFirst = $needSecond || null !== $this->getNode('arguments'); - - if ($needFirst) { - if (null !== $this->getNode('arguments')) { - $compiler->raw(', ')->subcompile($this->getNode('arguments')); - } else { - $compiler->raw(', array()'); - } - } + if (count($this->getNode('arguments')) || Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) { + $compiler->raw(', ')->subcompile($this->getNode('arguments')); - if ($needSecond) { - $compiler->raw(', ')->repr($this->getAttribute('type')); - } + if (Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) { + $compiler->raw(', ')->repr($this->getAttribute('type')); + } - if ($needThird) { - $compiler->raw(', ')->repr($this->getAttribute('is_defined_test')); - } + if ($this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) { + $compiler->raw(', '.($this->getAttribute('is_defined_test') ? 'true' : 'false')); + } - if ($needFourth) { - $compiler->raw(', ')->repr($this->getAttribute('ignore_strict_check')); + if ($this->getAttribute('ignore_strict_check')) { + $compiler->raw(', '.($this->getAttribute('ignore_strict_check') ? 'true' : 'false')); + } } $compiler->raw(')'); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Parent.php b/vendor/twig/twig/lib/Twig/Node/Expression/Parent.php index a22ce03863..dcf618c04a 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Parent.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Parent.php @@ -25,7 +25,7 @@ public function __construct($name, $lineno, $tag = null) /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Flush.php b/vendor/twig/twig/lib/Twig/Node/Flush.php index 20d6aab43e..0467ddcefc 100644 --- a/vendor/twig/twig/lib/Twig/Node/Flush.php +++ b/vendor/twig/twig/lib/Twig/Node/Flush.php @@ -24,7 +24,7 @@ public function __construct($lineno, $tag) /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/For.php b/vendor/twig/twig/lib/Twig/Node/For.php index c54a23cc98..d1ff371da1 100644 --- a/vendor/twig/twig/lib/Twig/Node/For.php +++ b/vendor/twig/twig/lib/Twig/Node/For.php @@ -33,7 +33,7 @@ public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Nod /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/ForLoop.php b/vendor/twig/twig/lib/Twig/Node/ForLoop.php index d330283e78..b8841583d9 100644 --- a/vendor/twig/twig/lib/Twig/Node/ForLoop.php +++ b/vendor/twig/twig/lib/Twig/Node/ForLoop.php @@ -24,7 +24,7 @@ public function __construct($lineno, $tag = null) /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/If.php b/vendor/twig/twig/lib/Twig/Node/If.php index 980274e5cd..b42d107555 100644 --- a/vendor/twig/twig/lib/Twig/Node/If.php +++ b/vendor/twig/twig/lib/Twig/Node/If.php @@ -25,7 +25,7 @@ public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Import.php b/vendor/twig/twig/lib/Twig/Node/Import.php index 230665541a..99efc0911c 100644 --- a/vendor/twig/twig/lib/Twig/Node/Import.php +++ b/vendor/twig/twig/lib/Twig/Node/Import.php @@ -24,7 +24,7 @@ public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $va /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Include.php b/vendor/twig/twig/lib/Twig/Node/Include.php index 06548884a1..860aedfe2a 100644 --- a/vendor/twig/twig/lib/Twig/Node/Include.php +++ b/vendor/twig/twig/lib/Twig/Node/Include.php @@ -25,7 +25,7 @@ public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $va /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { @@ -60,26 +60,40 @@ public function compile(Twig_Compiler $compiler) protected function addGetTemplate(Twig_Compiler $compiler) { - $method = $this->getNode('expr') instanceof Twig_Node_Expression_Constant ? 'loadTemplate' : 'resolveTemplate'; - $compiler - ->write(sprintf('$this->env->%s(', $method)) - ->subcompile($this->getNode('expr')) - ->raw(')') - ; + if ($this->getNode('expr') instanceof Twig_Node_Expression_Constant) { + $compiler + ->write("\$this->env->loadTemplate(") + ->subcompile($this->getNode('expr')) + ->raw(")") + ; + } else { + $compiler + ->write("\$template = \$this->env->resolveTemplate(") + ->subcompile($this->getNode('expr')) + ->raw(");\n") + ->write('$template') + ; + } } protected function addTemplateArguments(Twig_Compiler $compiler) { - if (null === $this->getNode('variables')) { - $compiler->raw(false === $this->getAttribute('only') ? '$context' : 'array()'); - } elseif (false === $this->getAttribute('only')) { - $compiler - ->raw('array_merge($context, ') - ->subcompile($this->getNode('variables')) - ->raw(')') - ; + if (false === $this->getAttribute('only')) { + if (null === $this->getNode('variables')) { + $compiler->raw('$context'); + } else { + $compiler + ->raw('array_merge($context, ') + ->subcompile($this->getNode('variables')) + ->raw(')') + ; + } } else { - $compiler->subcompile($this->getNode('variables')); + if (null === $this->getNode('variables')) { + $compiler->raw('array()'); + } else { + $compiler->subcompile($this->getNode('variables')); + } } } } diff --git a/vendor/twig/twig/lib/Twig/Node/Macro.php b/vendor/twig/twig/lib/Twig/Node/Macro.php index 47c2915f77..89910618b8 100644 --- a/vendor/twig/twig/lib/Twig/Node/Macro.php +++ b/vendor/twig/twig/lib/Twig/Node/Macro.php @@ -24,7 +24,7 @@ public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Module.php b/vendor/twig/twig/lib/Twig/Node/Module.php index 9f66b28d50..3f80175722 100644 --- a/vendor/twig/twig/lib/Twig/Node/Module.php +++ b/vendor/twig/twig/lib/Twig/Node/Module.php @@ -31,7 +31,7 @@ public function setIndex($index) /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Print.php b/vendor/twig/twig/lib/Twig/Node/Print.php index 42635361a6..b0c41d1d92 100644 --- a/vendor/twig/twig/lib/Twig/Node/Print.php +++ b/vendor/twig/twig/lib/Twig/Node/Print.php @@ -25,7 +25,7 @@ public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Sandbox.php b/vendor/twig/twig/lib/Twig/Node/Sandbox.php index 8ca772bcdf..8cf3ed44f7 100644 --- a/vendor/twig/twig/lib/Twig/Node/Sandbox.php +++ b/vendor/twig/twig/lib/Twig/Node/Sandbox.php @@ -24,7 +24,7 @@ public function __construct(Twig_NodeInterface $body, $lineno, $tag = null) /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php b/vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php index 91872ccccd..73dfaa9639 100644 --- a/vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php +++ b/vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php @@ -29,7 +29,7 @@ public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Set.php b/vendor/twig/twig/lib/Twig/Node/Set.php index 407d147342..4c9c16ce2f 100644 --- a/vendor/twig/twig/lib/Twig/Node/Set.php +++ b/vendor/twig/twig/lib/Twig/Node/Set.php @@ -39,7 +39,7 @@ public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterf /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Spaceless.php b/vendor/twig/twig/lib/Twig/Node/Spaceless.php index 1478c59acb..7555fa0f18 100644 --- a/vendor/twig/twig/lib/Twig/Node/Spaceless.php +++ b/vendor/twig/twig/lib/Twig/Node/Spaceless.php @@ -26,7 +26,7 @@ public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/Node/Text.php b/vendor/twig/twig/lib/Twig/Node/Text.php index 6863604e50..21bdcea148 100644 --- a/vendor/twig/twig/lib/Twig/Node/Text.php +++ b/vendor/twig/twig/lib/Twig/Node/Text.php @@ -25,7 +25,7 @@ public function __construct($data, $lineno) /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { diff --git a/vendor/twig/twig/lib/Twig/NodeInterface.php b/vendor/twig/twig/lib/Twig/NodeInterface.php index 8077349b3c..43afd0df04 100644 --- a/vendor/twig/twig/lib/Twig/NodeInterface.php +++ b/vendor/twig/twig/lib/Twig/NodeInterface.php @@ -21,7 +21,7 @@ interface Twig_NodeInterface extends Countable, IteratorAggregate /** * Compiles the node to PHP. * - * @param Twig_Compiler $compiler A Twig_Compiler instance + * @param Twig_Compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler); diff --git a/vendor/twig/twig/lib/Twig/Template.php b/vendor/twig/twig/lib/Twig/Template.php index 63910dacc0..1e23e8b4fb 100644 --- a/vendor/twig/twig/lib/Twig/Template.php +++ b/vendor/twig/twig/lib/Twig/Template.php @@ -379,11 +379,7 @@ protected function getAttribute($object, $item, array $arguments = array(), $typ } elseif (is_object($object)) { $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface', $item, get_class($object)); } elseif (is_array($object)) { - if (empty($object)) { - $message = sprintf('Key "%s" does not exist as the array is empty', $arrayItem); - } else { - $message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object))); - } + $message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object))); } elseif (Twig_Template::ARRAY_CALL === $type) { $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object); } else { From fae64f5b7a89b3bd0aa14dd768c9d441a8eb5a40 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 20 Aug 2014 20:51:49 +0300 Subject: [PATCH 40/63] Add basic theme configuration support --- system/src/Grav/Common/Grav.php | 1 - system/src/Grav/Common/Plugins.php | 1 + system/src/Grav/Common/Theme.php | 55 ++++++++++++++++++++++++++++++ system/src/Grav/Common/Themes.php | 4 +-- 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 16854a486a..fc709de51a 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -5,7 +5,6 @@ use Grav\Component\DI\Container; use Grav\Component\EventDispatcher\Event; use Grav\Component\EventDispatcher\EventDispatcher; -use Grav\Component\Filesystem\ResourceLocator; /** * Grav diff --git a/system/src/Grav/Common/Plugins.php b/system/src/Grav/Common/Plugins.php index 624c76c4ce..5990ca0c4f 100644 --- a/system/src/Grav/Common/Plugins.php +++ b/system/src/Grav/Common/Plugins.php @@ -61,6 +61,7 @@ public function init() } $instance = $this->grav['themes']->load(); + $instance->configure(); if ($instance instanceof EventSubscriberInterface) { $events->addSubscriber($instance); } diff --git a/system/src/Grav/Common/Theme.php b/system/src/Grav/Common/Theme.php index 0b3e170172..d47e9b4fa9 100644 --- a/system/src/Grav/Common/Theme.php +++ b/system/src/Grav/Common/Theme.php @@ -1,6 +1,61 @@ name = $name; + + parent::__construct($grav, $config); + } + + public function configure() { + $themeConfig = Yaml::instance(THEMES_DIR . "{$this->name}/{$this->name}.yaml")->content(); + + $this->config->merge(['themes' => [$this->name => $themeConfig]]); + + /** @var ResourceLocator $locator */ + $locator = $this->grav['locator']; + + // TODO: move + $registered = stream_get_wrappers(); + $schemes = $this->config->get("themes.{$this->name}.streams.scheme"); + + foreach ($schemes as $scheme => $config) { + if (isset($config['paths'])) { + $locator->addPath($scheme, '', $config['paths']); + } + if (isset($config['prefixes'])) { + foreach ($config['prefixes'] as $prefix => $paths) { + $locator->addPath($scheme, $prefix, $paths); + } + } + + if (in_array($scheme, $registered)) { + stream_wrapper_unregister($scheme); + } + $type = !empty($config['type']) ? $config['type'] : 'ReadOnlyStream'; + if ($type[0] != '\\') { + $type = '\\Grav\\Component\\Filesystem\\StreamWrapper\\' . $type; + } + + if (!stream_wrapper_register($scheme, $type)) { + throw new \InvalidArgumentException("Stream '{$type}' could not be initialized."); + } + + } + } } diff --git a/system/src/Grav/Common/Themes.php b/system/src/Grav/Common/Themes.php index bfa80fc496..852a34df78 100644 --- a/system/src/Grav/Common/Themes.php +++ b/system/src/Grav/Common/Themes.php @@ -101,13 +101,13 @@ public function load($name = null) $className = '\\Grav\\Theme\\' . ucfirst($name); if (class_exists($className)) { - $class = new $className($this->grav, $config); + $class = new $className($this->grav, $config, $name); } } } if (empty($class)) { - $class = new Theme($this->grav, $config); + $class = new Theme($this->grav, $config, $name); } return $class; From 48d82841243f80a502e5373e124d1c48bce99cda Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 20 Aug 2014 20:55:27 +0300 Subject: [PATCH 41/63] Add support for theme stream wrappers --- system/src/Grav/Common/Theme.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Theme.php b/system/src/Grav/Common/Theme.php index d47e9b4fa9..407dee282c 100644 --- a/system/src/Grav/Common/Theme.php +++ b/system/src/Grav/Common/Theme.php @@ -32,7 +32,10 @@ public function configure() { // TODO: move $registered = stream_get_wrappers(); - $schemes = $this->config->get("themes.{$this->name}.streams.scheme"); + $schemes = $this->config->get( + "themes.{$this->name}.streams.scheme", + ['theme' => ['paths' => ["user/themes/{$this->name}"]]] + ); foreach ($schemes as $scheme => $config) { if (isset($config['paths'])) { From dd4a2aa288168927c95bbdcc023f72d47aace26a Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 20 Aug 2014 21:37:19 +0300 Subject: [PATCH 42/63] Add scheme support for Assets class --- system/src/Grav/Common/Assets.php | 3 +++ .../Component/Filesystem/ResourceLocator.php | 25 +++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php index b6266ed75a..4ebb4098ea 100644 --- a/system/src/Grav/Common/Assets.php +++ b/system/src/Grav/Common/Assets.php @@ -547,6 +547,9 @@ function($matches) use ($relative_path) { */ protected function buildLocalLink($asset) { + try { + return self::$grav['uri']->rootUrl() . '/' . self::$grav['locator']->findResource($asset, false); + } catch (\Exception $e) {} $matches = $this->assetIsGravPackage($asset); $base_url = $this->base_url; diff --git a/system/src/Grav/Component/Filesystem/ResourceLocator.php b/system/src/Grav/Component/Filesystem/ResourceLocator.php index 95c202cf34..c8f690a5e6 100644 --- a/system/src/Grav/Component/Filesystem/ResourceLocator.php +++ b/system/src/Grav/Component/Filesystem/ResourceLocator.php @@ -42,34 +42,38 @@ public function addPath($scheme, $prefix, $paths) */ public function __invoke($uri) { - return $this->find($uri, false); + return $this->find($uri, false, true); } /** * @param string $uri + * @param bool $absolute * @return string|bool */ - public function findResource($uri) + public function findResource($uri, $absolute = true) { - return $this->find($uri, false); + return $this->find($uri, false, $absolute); } /** * @param string $uri + * @param bool $absolute * @return array */ - public function findResources($uri) + public function findResources($uri, $absolute = true) { - return $this->find($uri, true); + return $this->find($uri, true, $absolute); } /** * @param string $uri + * @param bool $absolute * @param bool $array + * * @throws \InvalidArgumentException * @return array|string|bool */ - protected function find($uri, $array) + protected function find($uri, $array, $absolute) { $segments = explode('://', $uri, 2); $file = array_pop($segments); @@ -93,13 +97,14 @@ protected function find($uri, $array) } foreach ($paths as $path) { - $filename = ROOT_DIR . '/' . $path . '/' . ltrim(substr($file, strlen($prefix)), '\/'); + $filename = $path . '/' . ltrim(substr($file, strlen($prefix)), '\/'); + $lookup = ROOT_DIR . '/' . $filename; - if (file_exists($filename)) { + if (file_exists($lookup)) { if (!$array) { - return $filename; + return $absolute ? $lookup : $filename; } - $paths[] = $filename; + $paths[] = $absolute ? $lookup : $filename; } } } From ea227913dacaab01a8cbb4ed3ee54d8d7394eb6f Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 20 Aug 2014 13:46:46 -0600 Subject: [PATCH 43/63] switched assets to use new php stream locators --- system/src/Grav/Common/Assets.php | 42 ++----------------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php index 4ebb4098ea..78e389767e 100644 --- a/system/src/Grav/Common/Assets.php +++ b/system/src/Grav/Common/Assets.php @@ -24,9 +24,6 @@ class Assets { use GravTrait; - /** @const Regex to match grav asset shortcodes */ - const GRAV_ASSET_REGEX = '/@(plugin|theme)\/(.*?):(.*)/i'; - /** @const Regex to match CSS and JavaScript files */ const DEFAULT_REGEX = '/.\.(css|js)$/i'; @@ -70,7 +67,6 @@ class Assets // Some configuration variables protected $config; - protected $theme_url; protected $base_url; // Default values for pipeline settings @@ -103,8 +99,6 @@ public function init() $this->config($asset_config); $this->base_url = $base_url . '/'; - $this->theme_url = $base_url . '/' . USER_PATH . basename(THEMES_DIR) .'/'. $theme; - } /** @@ -548,45 +542,13 @@ function($matches) use ($relative_path) { protected function buildLocalLink($asset) { try { - return self::$grav['uri']->rootUrl() . '/' . self::$grav['locator']->findResource($asset, false); + return $this->base_url . self::$grav['locator']->findResource($asset, false); } catch (\Exception $e) {} - $matches = $this->assetIsGravPackage($asset); - $base_url = $this->base_url; - - - if($matches === false) - return $base_url . $asset; - - if($matches[1] == 'theme') { - return $this->theme_url . '/' . $matches[2] . '/' . $matches[3]; - } elseif ($matches[1] == 'plugin') { - return $base_url . 'user/plugins/' . $matches[2] . '/' . $matches[3]; - } else { - return $base_url . $asset; - } - - - } - - /** - * Determines if an asset contains a valid grav asset shortcode - * Currently supported formats are: - * @plugin/plugin_name/directories:assetname.js|css - * @theme/directories:assetname.js|css - * - * @param string $asset the asset string reference - * @return array|bool if there are matches, those regex matches are returned, else return false - */ - protected function assetIsGravPackage($asset) - { - if(preg_match(self::GRAV_ASSET_REGEX, $asset, $matches)) - return $matches; - return false; + return $this->base_url . $asset; } - /** * Determine whether a link is local or remote. * From 5e07b1ebfd82f44fa0a32c61e6fe5b4ace22f015 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 20 Aug 2014 13:47:10 -0600 Subject: [PATCH 44/63] added a helpful dump wrapper --- system/src/Grav/Common/Debugger.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system/src/Grav/Common/Debugger.php b/system/src/Grav/Common/Debugger.php index 2aff55e97a..7505224415 100644 --- a/system/src/Grav/Common/Debugger.php +++ b/system/src/Grav/Common/Debugger.php @@ -54,4 +54,9 @@ public function log($message) TracyDebugger::log(sprintf($message, TracyDebugger::timer() * 1000)); } } + + public static function dump($var) + { + TracyDebugger::dump($var); + } } From ec8cbbb920c34749ac3a34f6dfcb991c1129dfec Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 20 Aug 2014 13:57:16 -0600 Subject: [PATCH 45/63] updated composer configuration --- composer.json | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index c1b629b1c0..020e0b149b 100644 --- a/composer.json +++ b/composer.json @@ -1,16 +1,10 @@ { - "name": "rhuk/grav", + "name": "getgrav/grav", "type": "library", - "description": "Grav is a powerful flat CMS influenced by Pico, Stacey, Kirby and others...", - "keywords": ["cms"], + "description": "Modern, Crazy Fast, Ridiculously Easy and Amazingly Powerful Flat-File CMS", + "keywords": ["cms","flat-file cms","flat cms","flatfile cms","php"], "homepage": "http://getgrav.org", "license": "MIT", - "authors": [ - { - "name": "Andy Miller", - "email": "rhuk@getgrav.org" - } - ], "require": { "php": ">=5.4.0", "twig/twig": "~1.16", From 3f0af44e8c2e108099de448428a544e3a8c5b5fe Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 20 Aug 2014 18:26:14 -0600 Subject: [PATCH 46/63] Added /asssets dir to the setup command --- system/src/Grav/Console/SetupCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/system/src/Grav/Console/SetupCommand.php b/system/src/Grav/Console/SetupCommand.php index 7e7ab3a51e..fcc567a05a 100644 --- a/system/src/Grav/Console/SetupCommand.php +++ b/system/src/Grav/Console/SetupCommand.php @@ -13,6 +13,7 @@ class SetupCommand extends Command protected $directories = array('/cache', '/logs', '/images', + '/assets', '/user/accounts', '/user/config', '/user/pages', From ec3b5d6c73aba31d0e0555abf4d91c7dd93a4464 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 20 Aug 2014 18:26:46 -0600 Subject: [PATCH 47/63] OMG, cache was OFF by default, wandering what was going on! --- user/config/system.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user/config/system.yaml b/user/config/system.yaml index 9dead74070..8f3cb5decc 100644 --- a/user/config/system.yaml +++ b/user/config/system.yaml @@ -12,7 +12,7 @@ pages: twig: true cache: - enabled: false + enabled: true check: pages: true driver: auto From 045fce62a6c0a5b674bc46cec6d5a073bf386880 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 21 Aug 2014 11:40:51 -0600 Subject: [PATCH 48/63] updates to remove pimple tests from autoloader --- vendor/autoload.php | 2 +- vendor/composer/autoload_classmap.php | 10 --- vendor/composer/autoload_real.php | 10 +-- vendor/composer/installed.json | 118 +++++++++++++------------- 4 files changed, 65 insertions(+), 75 deletions(-) diff --git a/vendor/autoload.php b/vendor/autoload.php index d84c250d15..8b440acf7b 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderIniteef751e17db86fa31c0c46c61acf76f4::getLoader(); +return ComposerAutoloaderInit7a18ce01239c69086e27f1d973d24372::getLoader(); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index b6b38da504..52ac1cbd20 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -153,10 +153,6 @@ 'ParsedownExtra' => $vendorDir . '/erusev/parsedown-extra/ParsedownExtra.php', 'Pimple\\Container' => $vendorDir . '/pimple/pimple/src/Pimple/Container.php', 'Pimple\\ServiceProviderInterface' => $vendorDir . '/pimple/pimple/src/Pimple/ServiceProviderInterface.php', - 'Pimple\\Tests\\Fixtures\\Invokable' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php', - 'Pimple\\Tests\\Fixtures\\NonInvokable' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php', - 'Pimple\\Tests\\Fixtures\\PimpleServiceProvider' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php', - 'Pimple\\Tests\\Fixtures\\Service' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php', 'Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Symfony/Component/Console/Application.php', 'Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Symfony/Component/Console/Command/Command.php', 'Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Symfony/Component/Console/Command/HelpCommand.php', @@ -215,12 +211,6 @@ 'Symfony\\Component\\Console\\Shell' => $vendorDir . '/symfony/console/Symfony/Component/Console/Shell.php', 'Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tester/ApplicationTester.php', 'Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tester/CommandTester.php', - 'Symfony\\Component\\Console\\Tests\\Descriptor\\ObjectsProvider' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php', - 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorApplication1' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.php', - 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorApplication2' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.php', - 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorCommand1' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.php', - 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorCommand2' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.php', - 'Symfony\\Component\\Console\\Tests\\Fixtures\\DummyOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DummyOutput.php', 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php', diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 733b9e1e2e..70f77eb71f 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderIniteef751e17db86fa31c0c46c61acf76f4 +class ComposerAutoloaderInit7a18ce01239c69086e27f1d973d24372 { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderIniteef751e17db86fa31c0c46c61acf76f4', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit7a18ce01239c69086e27f1d973d24372', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderIniteef751e17db86fa31c0c46c61acf76f4', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit7a18ce01239c69086e27f1d973d24372', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ public static function getLoader() $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequireeef751e17db86fa31c0c46c61acf76f4($file); + composerRequire7a18ce01239c69086e27f1d973d24372($file); } return $loader; } } -function composerRequireeef751e17db86fa31c0c46c61acf76f4($file) +function composerRequire7a18ce01239c69086e27f1d973d24372($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 863259012c..2b1a89c322 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,63 +1,4 @@ [ - { - "name": "twig/twig", - "version": "v1.16.0", - "version_normalized": "1.16.0.0", - "source": { - "type": "git", - "url": "https://github.com/fabpot/Twig.git", - "reference": "8ce37115802e257a984a82d38254884085060024" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fabpot/Twig/zipball/8ce37115802e257a984a82d38254884085060024", - "reference": "8ce37115802e257a984a82d38254884085060024", - "shasum": "" - }, - "require": { - "php": ">=5.2.4" - }, - "time": "2014-07-05 12:19:05", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.16-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Twig_": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" - }, - { - "name": "Twig Team", - "homepage": "https://github.com/fabpot/Twig/graphs/contributors", - "role": "Contributors" - } - ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "http://twig.sensiolabs.org", - "keywords": [ - "templating" - ] - }, { "name": "erusev/parsedown", "version": "1.0.1", @@ -704,5 +645,64 @@ "hashing", "password" ] + }, + { + "name": "twig/twig", + "version": "v1.16.0", + "version_normalized": "1.16.0.0", + "source": { + "type": "git", + "url": "https://github.com/fabpot/Twig.git", + "reference": "8ce37115802e257a984a82d38254884085060024" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fabpot/Twig/zipball/8ce37115802e257a984a82d38254884085060024", + "reference": "8ce37115802e257a984a82d38254884085060024", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "time": "2014-07-05 12:19:05", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.16-dev" + } + }, + "installation-source": "source", + "autoload": { + "psr-0": { + "Twig_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + }, + { + "name": "Twig Team", + "homepage": "https://github.com/fabpot/Twig/graphs/contributors", + "role": "Contributors" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "http://twig.sensiolabs.org", + "keywords": [ + "templating" + ] } ] From 447abb928bbcd89ed74b5e32937588ba2d4efe30 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 21 Aug 2014 14:46:13 -0600 Subject: [PATCH 49/63] Added a fix that should help on some hosting providers --- .htaccess | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.htaccess b/.htaccess index 268afb8e96..e2a441c7df 100755 --- a/.htaccess +++ b/.htaccess @@ -1,4 +1,6 @@ +Options -Multiviews + RewriteEngine On # access site From f3aec6562467e7dba0db4dc4d62b88b8e8494679 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 21 Aug 2014 21:55:37 -0600 Subject: [PATCH 50/63] Added support for custom inline images with markdown #10, no more twig needed! --- system/src/Grav/Common/Markdown/Markdown.php | 13 +++ .../Grav/Common/Markdown/MarkdownExtra.php | 13 +++ .../Common/Markdown/MarkdownGravLinkTrait.php | 83 +++++++++++++++++++ system/src/Grav/Common/Page/Medium.php | 9 ++ system/src/Grav/Common/Page/Page.php | 10 ++- vendor/autoload.php | 2 +- vendor/composer/autoload_classmap.php | 3 + vendor/composer/autoload_real.php | 10 +-- 8 files changed, 134 insertions(+), 9 deletions(-) create mode 100644 system/src/Grav/Common/Markdown/Markdown.php create mode 100644 system/src/Grav/Common/Markdown/MarkdownExtra.php create mode 100644 system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php diff --git a/system/src/Grav/Common/Markdown/Markdown.php b/system/src/Grav/Common/Markdown/Markdown.php new file mode 100644 index 0000000000..f90cd06940 --- /dev/null +++ b/system/src/Grav/Common/Markdown/Markdown.php @@ -0,0 +1,13 @@ +page = $page; + } + +} diff --git a/system/src/Grav/Common/Markdown/MarkdownExtra.php b/system/src/Grav/Common/Markdown/MarkdownExtra.php new file mode 100644 index 0000000000..b85516f5a5 --- /dev/null +++ b/system/src/Grav/Common/Markdown/MarkdownExtra.php @@ -0,0 +1,13 @@ +page = $page; + } +} diff --git a/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php b/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php new file mode 100644 index 0000000000..fdad102ca1 --- /dev/null +++ b/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php @@ -0,0 +1,83 @@ + $params) { + // ignore any url or html actions + if (!in_array($action, ['html','url'])) + $command .= '->' . $action . '(' . $params . ')'; + } + } + + // if there is no host set but there is a path, the file is local + if (!isset($url['host']) && isset($url['path'])) { + // get the media objects for this page + $media = $this->page->media(); + + // if there is a media file that matches the path referenced.. + if (isset($media->images()[$url['path']])) { + // get the medium object + $medium = $media->images()[$url['path']]; + + // unless one of the actions is lightbox method get the url + if (!isset($actions['lightbox'])) { + $command .= '->url()'; + } else { + $command .= '->lightboxRaw()'; + } + + // evaluate the commands to run against the media object + eval ('$src = $medium'.$command.';'); + + // set the src element with the new generated url + if (!isset($actions['lightbox']) && !is_array($src)) { + $Excerpt['element']['attributes']['src'] = $src; + } else { + + // Create the custom lightbox element + $Element = array( + 'name' => 'a', + 'attributes' => array('rel' => $src['a_rel'], 'href' => $src['a_url']), + 'handler' => 'element', + 'text' => array( + 'name' => 'img', + 'attributes' => array('src' => $src['img_url'], 'alt' => $alt, 'title' => $title) + ), + ); + + // Set the lightbox element on the Excerpt + $Excerpt['element'] = $Element; + } + } + } + } + return $Excerpt; + } +} diff --git a/system/src/Grav/Common/Page/Medium.php b/system/src/Grav/Common/Page/Medium.php index 7cd97ccb6d..d9f3b5d06d 100644 --- a/system/src/Grav/Common/Page/Medium.php +++ b/system/src/Grav/Common/Page/Medium.php @@ -202,6 +202,15 @@ public function lightbox($width = null, $height = null) return $this->link($width, $height); } + public function lightboxRaw($width = null, $height = null) + { + $url = $this->url(); + $this->link($width, $height); + $lightbox_url = self::$grav['config']->get('system.base_url_relative') . '/'. $this->linkTarget; + + return array('a_url' => $lightbox_url, 'a_rel' => 'lightbox', 'img_url' => $url); + } + /** * Return link HTML for the medium. * diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 21472ac1b6..8d68d8c82b 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -12,6 +12,8 @@ use Grav\Common\Uri; use Grav\Common\Grav; use Grav\Common\Taxonomy; +use Grav\Common\Markdown\Markdown; +use Grav\Common\Markdown\MarkdownExtra; use Grav\Component\EventDispatcher\Event; use Symfony\Component\Yaml\Yaml; @@ -272,6 +274,9 @@ public function content($var = null) // If no content, process it if ($this->content === null) { + // Get media + $this->media(); + // Load cached content /** @var Cache $cache */ $cache = self::$grav['cache']; @@ -319,7 +324,6 @@ public function content($var = null) $this->content = $content; - $this->media(); } return $this->content; @@ -1514,9 +1518,9 @@ protected function parseMarkdownContent($content) /** @var Config $config */ $config = self::$grav['config']; if ($config->get('system.pages.markdown_extra')) { - $parsedown = new \ParsedownExtra(); + $parsedown = new MarkdownExtra($this); } else { - $parsedown = new \Parsedown(); + $parsedown = new Markdown($this); } $content = $parsedown->parse($content); return $content; diff --git a/vendor/autoload.php b/vendor/autoload.php index 8b440acf7b..14456ffc28 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit7a18ce01239c69086e27f1d973d24372::getLoader(); +return ComposerAutoloaderInit647726739e1bb1c8f9d4883b25b63e16::getLoader(); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 52ac1cbd20..e41627fa67 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -48,6 +48,9 @@ 'Grav\\Common\\GravTrait' => $baseDir . '/system/src/Grav/Common/GravTrait.php', 'Grav\\Common\\Inflector' => $baseDir . '/system/src/Grav/Common/Inflector.php', 'Grav\\Common\\Iterator' => $baseDir . '/system/src/Grav/Common/Iterator.php', + 'Grav\\Common\\Markdown\\Markdown' => $baseDir . '/system/src/Grav/Common/Markdown/Markdown.php', + 'Grav\\Common\\Markdown\\MarkdownExtra' => $baseDir . '/system/src/Grav/Common/Markdown/MarkdownExtra.php', + 'Grav\\Common\\Markdown\\MarkdownGravLinkTrait' => $baseDir . '/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php', 'Grav\\Common\\Page\\Collection' => $baseDir . '/system/src/Grav/Common/Page/Collection.php', 'Grav\\Common\\Page\\Media' => $baseDir . '/system/src/Grav/Common/Page/Media.php', 'Grav\\Common\\Page\\Medium' => $baseDir . '/system/src/Grav/Common/Page/Medium.php', diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 70f77eb71f..c8f6d58be0 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit7a18ce01239c69086e27f1d973d24372 +class ComposerAutoloaderInit647726739e1bb1c8f9d4883b25b63e16 { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit7a18ce01239c69086e27f1d973d24372', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit647726739e1bb1c8f9d4883b25b63e16', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit7a18ce01239c69086e27f1d973d24372', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit647726739e1bb1c8f9d4883b25b63e16', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ public static function getLoader() $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequire7a18ce01239c69086e27f1d973d24372($file); + composerRequire647726739e1bb1c8f9d4883b25b63e16($file); } return $loader; } } -function composerRequire7a18ce01239c69086e27f1d973d24372($file) +function composerRequire647726739e1bb1c8f9d4883b25b63e16($file) { require $file; } From 7a622c6f5b91b5ddab5dd36a3f38f20caba6a8bd Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Fri, 22 Aug 2014 14:07:45 -0600 Subject: [PATCH 51/63] switching user agent package --- composer.json | 2 +- system/src/Grav/Browser.php | 36 ++ system/src/Grav/Common/Grav.php | 4 +- system/src/Grav/Common/Twig.php | 2 +- system/src/Grav/Console/CleanCommand.php | 12 +- vendor/autoload.php | 2 +- vendor/composer/autoload_classmap.php | 1 + vendor/composer/autoload_files.php | 3 +- vendor/composer/autoload_real.php | 10 +- vendor/composer/installed.json | 91 ++--- .../phpuseragentparser/LICENSE.md} | 5 +- vendor/donatj/phpuseragentparser/README.md | 110 ++++++ .../Source/UserAgentParser.php | 144 ++++++++ vendor/ornicar/php-user-agent/CHANGELOG.md | 9 - vendor/ornicar/php-user-agent/README.md | 92 ----- .../php-user-agent/lib/phpUserAgent.php | 194 ----------- .../lib/phpUserAgentStringParser.php | 321 ------------------ 17 files changed, 361 insertions(+), 677 deletions(-) create mode 100644 system/src/Grav/Browser.php rename vendor/{ornicar/php-user-agent/LICENSE => donatj/phpuseragentparser/LICENSE.md} (94%) create mode 100644 vendor/donatj/phpuseragentparser/README.md create mode 100644 vendor/donatj/phpuseragentparser/Source/UserAgentParser.php delete mode 100644 vendor/ornicar/php-user-agent/CHANGELOG.md delete mode 100644 vendor/ornicar/php-user-agent/README.md delete mode 100644 vendor/ornicar/php-user-agent/lib/phpUserAgent.php delete mode 100644 vendor/ornicar/php-user-agent/lib/phpUserAgentStringParser.php diff --git a/composer.json b/composer.json index 020e0b149b..ef489a2348 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "gregwar/image": "~2.0", "ircmaxell/password-compat": "1.0.*", "mrclay/minify": "~2.2", - "ornicar/php-user-agent": "1.0.*", + "donatj/phpuseragentparser": "dev-master", "pimple/pimple": "~3.0" }, "autoload": { diff --git a/system/src/Grav/Browser.php b/system/src/Grav/Browser.php new file mode 100644 index 0000000000..2d6e0bdcd3 --- /dev/null +++ b/system/src/Grav/Browser.php @@ -0,0 +1,36 @@ +useragent = parse_user_agent(); + } + + public function getBrowser() + { + return strtolower($this->useragent['browser']); + } + + public function getPlatform() + { + return strtolower($this->useragent['platform']); + } + + public function getLongVersion() + { + return $this->useragent['version']; + } + + public function getVersion() + { + $version = explode('.', $this->getLongVersion()); + return intval($version[0]); + } +} diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index fc709de51a..07d548d758 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -101,8 +101,8 @@ protected static function load(array $values) $container['output'] = function ($c) { return $c['twig']->processSite($c['uri']->extension()); }; - $container['user_agent'] = function ($c) { - return new \phpUserAgent(); + $container['browser'] = function ($c) { + return new Browser(); }; $container->register(new StreamsServiceProvider); diff --git a/system/src/Grav/Common/Twig.php b/system/src/Grav/Common/Twig.php index c89be41e3f..749634748e 100644 --- a/system/src/Grav/Common/Twig.php +++ b/system/src/Grav/Common/Twig.php @@ -111,7 +111,7 @@ public function init() 'site' => $config->get('site'), 'assets' => $this->grav['assets'], 'taxonomy' => $this->grav['taxonomy'], - 'user_agent' => $this->grav['user_agent'], + 'browser' => $this->grav['browser'], ); } diff --git a/system/src/Grav/Console/CleanCommand.php b/system/src/Grav/Console/CleanCommand.php index 8fa7fde5df..0507b0812c 100644 --- a/system/src/Grav/Console/CleanCommand.php +++ b/system/src/Grav/Console/CleanCommand.php @@ -26,6 +26,13 @@ class CleanCommand extends Command { 'user/plugins/email/vendor/swiftmailer/swiftmailer/notes', 'user/plugins/email/vendor/swiftmailer/swiftmailer/doc', 'user/themes/antimatter/.sass-cache', + 'vendor/donatj/phpuseragentparser/.git', + 'vendor/donatj/phpuseragentparser/.gitignore', + 'vendor/donatj/phpuseragentparser/.travis.yml', + 'vendor/donatj/phpuseragentparser/composer.json', + 'vendor/donatj/phpuseragentparser/phpunit.xml.dist', + 'vendor/donatj/phpuseragentparser/Tests', + 'vendor/donatj/phpuseragentparser/Tools', 'vendor/doctrine/cache/.travis.yml', 'vendor/doctrine/cache/build.properties', 'vendor/doctrine/cache/build.xml', @@ -74,11 +81,6 @@ class CleanCommand extends Command { 'vendor/mrclay/minify/min/quick-test.css', 'vendor/mrclay/minify/min/quick-test.js', 'vendor/mrclay/minify/min/utils.php', - 'vendor/ornicar/php-user-agent/.git', - 'vendor/ornicar/php-user-agent/.gitignore', - 'vendor/ornicar/php-user-agent/composer.json', - 'vendor/ornicar/php-user-agent/prove.php', - 'vendor/ornicar/php-user-agent/test', 'vendor/pimple/pimple/.gitignore', 'vendor/pimple/pimple/.travis.yml', 'vendor/pimple/pimple/composer.json', diff --git a/vendor/autoload.php b/vendor/autoload.php index 14456ffc28..ef61f61382 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit647726739e1bb1c8f9d4883b25b63e16::getLoader(); +return ComposerAutoloaderInit3f16975091c92a1711741b1ac4f955c3::getLoader(); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index e41627fa67..42d97136e5 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -27,6 +27,7 @@ 'DooDigestAuth' => $vendorDir . '/mrclay/minify/min/lib/DooDigestAuth.php', 'FirePHP' => $vendorDir . '/mrclay/minify/min/lib/FirePHP.php', 'Grav\\Common\\Assets' => $baseDir . '/system/src/Grav/Common/Assets.php', + 'Grav\\Common\\Browser' => $baseDir . '/system/src/Grav/Browser.php', 'Grav\\Common\\Cache' => $baseDir . '/system/src/Grav/Common/Cache.php', 'Grav\\Common\\Config' => $baseDir . '/system/src/Grav/Common/Config.php', 'Grav\\Common\\Data\\Blueprint' => $baseDir . '/system/src/Grav/Common/Data/Blueprint.php', diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index 945cea3258..2c8b0e2b2b 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -6,9 +6,8 @@ $baseDir = dirname($vendorDir); return array( - $vendorDir . '/ornicar/php-user-agent/lib/phpUserAgent.php', - $vendorDir . '/ornicar/php-user-agent/lib/phpUserAgentStringParser.php', $vendorDir . '/tracy/tracy/src/shortcuts.php', $vendorDir . '/ircmaxell/password-compat/lib/password.php', + $vendorDir . '/donatj/phpuseragentparser/Source/UserAgentParser.php', $baseDir . '/system/defines.php', ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index c8f6d58be0..f6962e2189 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit647726739e1bb1c8f9d4883b25b63e16 +class ComposerAutoloaderInit3f16975091c92a1711741b1ac4f955c3 { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit647726739e1bb1c8f9d4883b25b63e16', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit3f16975091c92a1711741b1ac4f955c3', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit647726739e1bb1c8f9d4883b25b63e16', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit3f16975091c92a1711741b1ac4f955c3', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ public static function getLoader() $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequire647726739e1bb1c8f9d4883b25b63e16($file); + composerRequire3f16975091c92a1711741b1ac4f955c3($file); } return $loader; } } -function composerRequire647726739e1bb1c8f9d4883b25b63e16($file) +function composerRequire3f16975091c92a1711741b1ac4f955c3($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 2b1a89c322..20dfc0af64 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -204,48 +204,6 @@ "description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers", "homepage": "http://code.google.com/p/minify/" }, - { - "name": "ornicar/php-user-agent", - "version": "1.0.0", - "version_normalized": "1.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/ornicar/php-user-agent.git", - "reference": "9c6ae1274642695bffe57cd80228e5158ccbcf21" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ornicar/php-user-agent/zipball/9c6ae1274642695bffe57cd80228e5158ccbcf21", - "reference": "9c6ae1274642695bffe57cd80228e5158ccbcf21", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2013-07-09 13:01:41", - "type": "library", - "installation-source": "dist", - "autoload": { - "files": [ - "lib/phpUserAgent.php", - "lib/phpUserAgentStringParser.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Thibault Duplessis", - "email": "thibault.duplessis@gmail.com", - "homepage": "http://ornicar.github.com" - } - ], - "keywords": [ - "user-agent" - ] - }, { "name": "pimple/pimple", "version": "v3.0.0", @@ -704,5 +662,54 @@ "keywords": [ "templating" ] + }, + { + "name": "donatj/phpuseragentparser", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/donatj/PhpUserAgent.git", + "reference": "abbd69a119f067e4afc3c4baf28d04646114a668" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/donatj/PhpUserAgent/zipball/abbd69a119f067e4afc3c4baf28d04646114a668", + "reference": "abbd69a119f067e4afc3c4baf28d04646114a668", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "camspiers/json-pretty": "0.1.*" + }, + "time": "2014-08-06 03:39:39", + "type": "library", + "installation-source": "source", + "autoload": { + "files": [ + "Source/UserAgentParser.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jesse G. Donat", + "email": "donatj@gmail.com", + "homepage": "http://donatstudios.com", + "role": "Developer" + } + ], + "description": "Simple, streamlined PHP user-agent parser", + "homepage": "http://donatstudios.com/PHP-Parser-HTTP_USER_AGENT", + "keywords": [ + "parser", + "user agent", + "useragent" + ] } ] diff --git a/vendor/ornicar/php-user-agent/LICENSE b/vendor/donatj/phpuseragentparser/LICENSE.md similarity index 94% rename from vendor/ornicar/php-user-agent/LICENSE rename to vendor/donatj/phpuseragentparser/LICENSE.md index dd2630b84b..305b6996c4 100644 --- a/vendor/ornicar/php-user-agent/LICENSE +++ b/vendor/donatj/phpuseragentparser/LICENSE.md @@ -1,6 +1,7 @@ The MIT License +=============== -Copyright (c) 2010 Thibault Duplessis +Copyright (c) 2013 Jesse G. Donat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +19,4 @@ 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. +THE SOFTWARE. \ No newline at end of file diff --git a/vendor/donatj/phpuseragentparser/README.md b/vendor/donatj/phpuseragentparser/README.md new file mode 100644 index 0000000000..0d0210215f --- /dev/null +++ b/vendor/donatj/phpuseragentparser/README.md @@ -0,0 +1,110 @@ +# PHP User Agent Parser + +[![Latest Stable Version](https://poser.pugx.org/donatj/phpuseragentparser/v/stable.png)](https://packagist.org/packages/donatj/phpuseragentparser) [![Total Downloads](https://poser.pugx.org/donatj/phpuseragentparser/downloads.png)](https://packagist.org/packages/donatj/phpuseragentparser) [![Latest Unstable Version](https://poser.pugx.org/donatj/phpuseragentparser/v/unstable.png)](https://packagist.org/packages/donatj/phpuseragentparser) [![License](https://poser.pugx.org/donatj/phpuseragentparser/license.png)](https://packagist.org/packages/donatj/phpuseragentparser) +[![Build Status](https://travis-ci.org/donatj/PhpUserAgent.png?branch=master)](https://travis-ci.org/donatj/PhpUserAgent) +[![HHVM Status](http://hhvm.h4cc.de/badge/donatj/phpuseragentparser.png)](http://hhvm.h4cc.de/package/donatj/phpuseragentparser) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/donatj/PhpUserAgent/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/donatj/PhpUserAgent/?branch=master) + +## What It Is + +A simple, streamlined PHP user-agent parser! + +Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php + + +## Why Use This + +You have your choice in user-agent parsers. This one detects **all modern browsers** in a very light, quick, understandable fashion. +It is less than 150 lines of code, and consists of just two regular expressions! +It can also correctly identify exotic versions of IE others fail on. + +It offers 100% unit test coverage, is installable via Composer, and is very easy to use. + +## What It Doesn't Do + +### OS Versions + +User-agent strings **are not** a reliable source of OS Version! + +- Many agents simply don't send the information. +- Others provide varying levels of accuracy. +- Parsing Windows versions alone almost nearly doubles the size of the code. + +I'm much more interested in keeping this thing *tiny* and accurate than adding niché features and would rather focus on things that can be **done well**. + +All that said, there is the start of a [branch to do it](https://github.com/donatj/PhpUserAgent/tree/os_version_detection) I created for a client if you want to poke it, I update it from time to time, but frankly if you need to *reliably detect OS Version*, using user-agent isn't the way to do it. I'd go with JavaScript. + +## Requirements + + - PHP 5.3.0+ + +## Installing + +PHP User Agent is available through Packagist via Composer. + +```json +{ + "require": { + "donatj/phpuseragentparser": "*" + } +} +``` + +## Sample Usage + +```php +$ua_info = parse_user_agent(); +/* +array( + 'platform' => '[Detected Platform]', + 'browser' => '[Detected Browser]', + 'version' => '[Detected Browser Version]', +); +*/ +``` + +## Currently Detected Platforms + +- Desktop + - Windows + - Linux + - Macintosh + - Chrome OS +- Mobile + - Android + - iPhone + - iPad + - Windows Phone OS + - Kindle + - Kindle Fire + - BlackBerry + - Playbook +- Console + - Nintendo 3DS + - Nintendo Wii + - Nintendo WiiU + - PlayStation 3 + - PlayStation 4 + - PlayStation Vita + - Xbox 360 + - Xbox One + +## Currently Detected Browsers + +- Android Browser +- BlackBerry Browser +- Camino +- Kindle / Silk +- Firefox / Iceweasel +- Safari +- Internet Explorer +- IEMobile +- Chrome +- Opera +- Midori +- Lynx +- Wget +- Curl + + + +More information is available at [Donat Studios](http://donatstudios.com/PHP-Parser-HTTP_USER_AGENT). diff --git a/vendor/donatj/phpuseragentparser/Source/UserAgentParser.php b/vendor/donatj/phpuseragentparser/Source/UserAgentParser.php new file mode 100644 index 0000000000..06178e42e5 --- /dev/null +++ b/vendor/donatj/phpuseragentparser/Source/UserAgentParser.php @@ -0,0 +1,144 @@ + + * @link https://github.com/donatj/PhpUserAgent + * @link http://donatstudios.com/PHP-Parser-HTTP_USER_AGENT + * @param string|null $u_agent User agent string to parse or null. Uses $_SERVER['HTTP_USER_AGENT'] on NULL + * @throws InvalidArgumentException on not having a proper user agent to parse. + * @return array an array with browser, version and platform keys + */ +function parse_user_agent( $u_agent = null ) { + if( is_null($u_agent) ) { + if( isset($_SERVER['HTTP_USER_AGENT']) ) { + $u_agent = $_SERVER['HTTP_USER_AGENT']; + } else { + throw new \InvalidArgumentException('parse_user_agent requires a user agent'); + } + } + + $platform = null; + $browser = null; + $version = null; + + $empty = array( 'platform' => $platform, 'browser' => $browser, 'version' => $version ); + + if( !$u_agent ) return $empty; + + if( preg_match('/\((.*?)\)/im', $u_agent, $parent_matches) ) { + + preg_match_all('/(?PBB\d+;|Android|CrOS|iPhone|iPad|Linux|Macintosh|Windows(\ Phone)?|Silk|linux-gnu|BlackBerry|PlayBook|Nintendo\ (WiiU?|3DS)|Xbox(\ One)?) + (?:\ [^;]*)? + (?:;|$)/imx', $parent_matches[1], $result, PREG_PATTERN_ORDER); + + $priority = array( 'Android', 'Xbox One', 'Xbox' ); + $result['platform'] = array_unique($result['platform']); + if( count($result['platform']) > 1 ) { + if( $keys = array_intersect($priority, $result['platform']) ) { + $platform = reset($keys); + } else { + $platform = $result['platform'][0]; + } + } elseif( isset($result['platform'][0]) ) { + $platform = $result['platform'][0]; + } + } + + if( $platform == 'linux-gnu' ) { + $platform = 'Linux'; + } elseif( $platform == 'CrOS' ) { + $platform = 'Chrome OS'; + } + + preg_match_all('%(?PCamino|Kindle(\ Fire\ Build)?|Firefox|Iceweasel|Safari|MSIE|Trident/.*rv|AppleWebKit|Chrome|IEMobile|Opera|OPR|Silk|Lynx|Midori|Version|Wget|curl|NintendoBrowser|PLAYSTATION\ (\d|Vita)+) + (?:\)?;?) + (?:(?:[:/ ])(?P[0-9A-Z.]+)|/(?:[A-Z]*))%ix', + $u_agent, $result, PREG_PATTERN_ORDER); + + + // If nothing matched, return null (to avoid undefined index errors) + if( !isset($result['browser'][0]) || !isset($result['version'][0]) ) { + return $empty; + } + + $browser = $result['browser'][0]; + $version = $result['version'][0]; + + $find = function ( $search, &$key ) use ( $result ) { + $xkey = array_search(strtolower($search), array_map('strtolower', $result['browser'])); + if( $xkey !== false ) { + $key = $xkey; + + return true; + } + + return false; + }; + + $key = 0; + if( $browser == 'Iceweasel' ) { + $browser = 'Firefox'; + } elseif( $find('Playstation Vita', $key) ) { + $platform = 'PlayStation Vita'; + $browser = 'Browser'; + } elseif( $find('Kindle Fire Build', $key) || $find('Silk', $key) ) { + $browser = $result['browser'][$key] == 'Silk' ? 'Silk' : 'Kindle'; + $platform = 'Kindle Fire'; + if( !($version = $result['version'][$key]) || !is_numeric($version[0]) ) { + $version = $result['version'][array_search('Version', $result['browser'])]; + } + } elseif( $find('NintendoBrowser', $key) || $platform == 'Nintendo 3DS' ) { + $browser = 'NintendoBrowser'; + $version = $result['version'][$key]; + } elseif( $find('Kindle', $key) ) { + $browser = $result['browser'][$key]; + $platform = 'Kindle'; + $version = $result['version'][$key]; + } elseif( $find('OPR', $key) ) { + $browser = 'Opera Next'; + $version = $result['version'][$key]; + } elseif( $find('Opera', $key) ) { + $browser = 'Opera'; + $find('Version', $key); + $version = $result['version'][$key]; + } elseif( $find('Midori', $key) ) { + $browser = 'Midori'; + $version = $result['version'][$key]; + } elseif( $browser == 'MSIE' || strpos($browser, 'Trident') !== false ) { + if( $find('IEMobile', $key) ) { + $browser = 'IEMobile'; + } else { + $browser = 'MSIE'; + $key = 0; + } + $version = $result['version'][$key]; + } elseif( $find('Chrome', $key) ) { + $browser = 'Chrome'; + $version = $result['version'][$key]; + } elseif( $browser == 'AppleWebKit' ) { + if( ($platform == 'Android' && !($key = 0)) ) { + $browser = 'Android Browser'; + } elseif( strpos($platform, 'BB') === 0 ) { + $browser = 'BlackBerry Browser'; + $platform = 'BlackBerry'; + } elseif( $platform == 'BlackBerry' || $platform == 'PlayBook' ) { + $browser = 'BlackBerry Browser'; + } elseif( $find('Safari', $key) ) { + $browser = 'Safari'; + } + + $find('Version', $key); + + $version = $result['version'][$key]; + } elseif( $key = preg_grep('/playstation \d/i', array_map('strtolower', $result['browser'])) ) { + $key = reset($key); + + $platform = 'PlayStation ' . preg_replace('/[^\d]/i', '', $key); + $browser = 'NetFront'; + } + + return array( 'platform' => $platform, 'browser' => $browser, 'version' => $version ); + +} diff --git a/vendor/ornicar/php-user-agent/CHANGELOG.md b/vendor/ornicar/php-user-agent/CHANGELOG.md deleted file mode 100644 index e8fa712581..0000000000 --- a/vendor/ornicar/php-user-agent/CHANGELOG.md +++ /dev/null @@ -1,9 +0,0 @@ -# CHANGELOG - -### 1.0.0 (2013-08-09) - - * Add a version following semver spec. - -### v1.0 - 2010-04-13 - - * create initial 1.0 version \ No newline at end of file diff --git a/vendor/ornicar/php-user-agent/README.md b/vendor/ornicar/php-user-agent/README.md deleted file mode 100644 index 63813a2414..0000000000 --- a/vendor/ornicar/php-user-agent/README.md +++ /dev/null @@ -1,92 +0,0 @@ -# PHP User Agent - -Browser detection in PHP5. -Uses a simple and fast algorithm to recognize major browsers. - -## Overview - -``` php -$userAgent = new phpUserAgent(); - -$userAgent->getBrowserName() // firefox -$userAgent->getBrowserVersion() // 3.6 -$userAgent->getOperatingSystem() // linux -$userAgent->getEngine() // gecko -``` - -### Why you should use it - -PHP provides a native function to detect user browser: [get_browser()](http://us2.php.net/manual/en/function.get-browser.php). -get_browser() requires the "browscap.ini" file which is 300KB+. -Loading and processing this file impact script performance. -And sometimes, the production server just doesn't provide browscap.ini. - -Although get_browser() surely provides excellent detection results, in most -cases a much simpler method can be just as effective. -php-user-agent has the advantage of being compact and easy to extend. -It is performant as well, since it doesn't do any iteration or recursion. - -## Usage - -``` php -// include classes or rely on Composer autoloader -require_once '/path/to/php-user-agent/phpUserAgent.php'; -require_once '/path/to/php-user-agent/phpUserAgentStringParser.php'; - -// Create a user agent -$userAgent = new phpUserAgent(); - -// Interrogate the user agent -$userAgent->getBrowserName() // firefox -$userAgent->getBrowserVersion() // 3.6 -$userAgent->getOperatingSystem() // linux -$userAgent->getEngine() // gecko -``` - -## Advanced - -### Custom user agent string - -When you create a phpUserAgent object, the current user agent string is used. -You can specify another user agent string: - -``` php -// use another user agent string -$userAgent = new phpUserAgent('msnbot/2.0b (+http://search.msn.com/msnbot.htm)'); -$userAgent->getBrowserName() // msnbot - -// use current user agent string -$userAgent = new phpUserAgent($_SERVER['HTTP_USER_AGENT'); -// this is equivalent to: -$userAgent = new phpUserAgent(); -``` - -### Custom parser class - -By default, phpUserAgentStringParser is used to analyse the user agent string. -You can replace the parser instance and customize it to match your needs: - -``` php -// create a custom user agent string parser -class myUserAgentStringParser extends phpUserAgentStringParser -{ - // override methods -} - -// inject the custom parser when creating a user agent: -$userAgent = new phpUserAgent(null, new myUserAgentStringParser()); -``` - -## Run tests - -You can run the unit tests on your server: - -``` bash -$ php prove.php -``` - -## Contribute - -If you found a browser of operating system this library fails to recognize, -feel free to submit an issue. Please provide the user agent string. -And well, if you also want to provide the patch, it's even better. diff --git a/vendor/ornicar/php-user-agent/lib/phpUserAgent.php b/vendor/ornicar/php-user-agent/lib/phpUserAgent.php deleted file mode 100644 index 2e29b0d728..0000000000 --- a/vendor/ornicar/php-user-agent/lib/phpUserAgent.php +++ /dev/null @@ -1,194 +0,0 @@ - - * @license MIT License - * - * Documentation: http://github.com/ornicar/php-user-agent/blob/master/README.markdown - * Tickets: http://github.com/ornicar/php-user-agent/issues - */ - -class phpUserAgent -{ - protected $userAgentString; - protected $browserName; - protected $browserVersion; - protected $operatingSystem; - protected $engine; - - public function __construct($userAgentString = null, phpUserAgentStringParser $userAgentStringParser = null) - { - $this->configureFromUserAgentString($userAgentString, $userAgentStringParser); - } - - /** - * Get the browser name - * - * @return string the browser name - */ - public function getBrowserName() - { - return $this->browserName; - } - - /** - * Set the browser name - * - * @param string $name the browser name - */ - public function setBrowserName($name) - { - $this->browserName = $name; - } - - /** - * Get the browser version - * - * @return string the browser version - */ - public function getBrowserVersion() - { - return $this->browserVersion; - } - - /** - * Set the browser version - * - * @param string $version the browser version - */ - public function setBrowserVersion($version) - { - $this->browserVersion = $version; - } - - /** - * Get the operating system name - * - * @return string the operating system name - */ - public function getOperatingSystem() - { - return $this->operatingSystem; - } - - /** - * Set the operating system name - * - * @param string $operatingSystem the operating system name - */ - public function setOperatingSystem($operatingSystem) - { - $this->operatingSystem = $operatingSystem; - } - - /** - * Get the engine name - * - * @return string the engine name - */ - public function getEngine() - { - return $this->engine; - } - - /** - * Set the engine name - * - * @param string $operatingSystem the engine name - */ - public function setEngine($engine) - { - $this->engine = $engine; - } - - /** - * Get the user agent string - * - * @return string the user agent string - */ - public function getUserAgentString() - { - return $this->userAgentString; - } - - /** - * Set the user agent string - * - * @param string $userAgentString the user agent string - */ - public function setUserAgentString($userAgentString) - { - $this->userAgentString = $userAgentString; - } - - /** - * Tell whether this user agent is unknown or not - * - * @return boolean true if this user agent is unknown, false otherwise - */ - public function isUnknown() - { - return empty($this->browserName); - } - - /** - * @return string combined browser name and version - */ - public function getFullName() - { - return $this->getBrowserName().' '.$this->getBrowserVersion(); - } - - public function __toString() - { - return $this->getFullName(); - } - - /** - * Configure the user agent from a user agent string - * @param string $userAgentString the user agent string - * @param phpUserAgentStringParser $userAgentStringParser the parser used to parse the string - */ - public function configureFromUserAgentString($userAgentString, phpUserAgentStringParser $userAgentStringParser = null) - { - if(null === $userAgentStringParser) - { - $userAgentStringParser = new phpUserAgentStringParser(); - } - - $this->setUserAgentString($userAgentString); - - $this->fromArray($userAgentStringParser->parse($userAgentString)); - } - - /** - * Convert the user agent to a data array - * - * @return array data - */ - public function toArray() - { - return array( - 'browser_name' => $this->getBrowserName(), - 'browser_version' => $this->getBrowserVersion(), - 'operating_system' => $this->getOperatingSystem() - ); - } - - /** - * Configure the user agent from a data array - * - * @param array $data - */ - public function fromArray(array $data) - { - $this->setBrowserName($data['browser_name']); - $this->setBrowserVersion($data['browser_version']); - $this->setOperatingSystem($data['operating_system']); - $this->setEngine($data['engine']); - } -} diff --git a/vendor/ornicar/php-user-agent/lib/phpUserAgentStringParser.php b/vendor/ornicar/php-user-agent/lib/phpUserAgentStringParser.php deleted file mode 100644 index e33548e23e..0000000000 --- a/vendor/ornicar/php-user-agent/lib/phpUserAgentStringParser.php +++ /dev/null @@ -1,321 +0,0 @@ - 'firefox', - * 'browser_version' => '3.6', - * 'operating_system' => 'linux' - * ) - */ - public function parse($userAgentString = null) - { - // use current user agent string as default - if(!$userAgentString) - { - $userAgentString = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null; - } - - // parse quickly (with medium accuracy) - $informations = $this->doParse($userAgentString); - - - // run some filters to increase accuracy - foreach($this->getFilters() as $filter) - { - $this->$filter($informations); - } - - return $informations; - } - - /** - * Detect quickly informations from the user agent string - * - * @param string $userAgentString user agent string - * @return array user agent informations array - */ - protected function doParse($userAgentString) - { - $userAgent = array( - 'string' => $this->cleanUserAgentString($userAgentString), - 'browser_name' => null, - 'browser_version' => null, - 'operating_system' => null, - 'engine' => null - ); - - if(empty($userAgent['string'])) - { - return $userAgent; - } - - // build regex that matches phrases for known browsers - // (e.g. "Firefox/2.0" or "MSIE 6.0" (This only matches the major and minor - // version numbers. E.g. "2.0.0.6" is parsed as simply "2.0" - $pattern = '#('.join('|', $this->getKnownBrowsers()).')[/ ]+([0-9]+(?:\.[0-9]+)?)#'; - - // Find all phrases (or return empty array if none found) - if (preg_match_all($pattern, $userAgent['string'], $matches)) - { - // Since some UAs have more than one phrase (e.g Firefox has a Gecko phrase, - // Opera 7,8 have a MSIE phrase), use the last one found (the right-most one - // in the UA). That's usually the most correct. - $i = count($matches[1])-1; - - if (isset($matches[1][$i])) - { - $userAgent['browser_name'] = $matches[1][$i]; - } - if (isset($matches[2][$i])) - { - $userAgent['browser_version'] = $matches[2][$i]; - } - } - - // Find operating system - $pattern = '#'.join('|', $this->getKnownOperatingSystems()).'#'; - - if (preg_match($pattern, $userAgent['string'], $match)) - { - if (isset($match[0])) - { - $userAgent['operating_system'] = $match[0]; - } - } - - // Find engine - $pattern = '#'.join('|', $this->getKnownEngines()).'#'; - - if (preg_match($pattern, $userAgent['string'], $match)) - { - if (isset($match[0])) - { - $userAgent['engine'] = $match[0]; - } - } - - return $userAgent; - } - - /** - * Make user agent string lowercase, and replace browser aliases - * - * @param string $userAgentString the dirty user agent string - * @return string the clean user agent string - */ - public function cleanUserAgentString($userAgentString) - { - // clean up the string - $userAgentString = trim(strtolower($userAgentString)); - - // replace browser names with their aliases - $userAgentString = strtr($userAgentString, $this->getKnownBrowserAliases()); - - // replace operating system names with their aliases - $userAgentString = strtr($userAgentString, $this->getKnownOperatingSystemAliases()); - - // replace engine names with their aliases - $userAgentString = strtr($userAgentString, $this->getKnownEngineAliases()); - - return $userAgentString; - } - - /** - * Get the list of filters that get called when parsing a user agent - * - * @return array list of valid callables - */ - public function getFilters() - { - return array( - 'filterAndroid', - 'filterGoogleChrome', - 'filterSafariVersion', - 'filterOperaVersion', - 'filterYahoo', - 'filterMsie', - ); - } - - /** - * Add a filter to be called when parsing a user agent - * - * @param string $filter name of the filter method - */ - public function addFilter($filter) - { - $this->filters += $filter; - } - - /** - * Get known browsers - * - * @return array the browsers - */ - protected function getKnownBrowsers() - { - return array( - 'msie', - 'firefox', - 'safari', - 'webkit', - 'opera', - 'netscape', - 'konqueror', - 'gecko', - 'chrome', - 'googlebot', - 'iphone', - 'msnbot', - 'applewebkit' - ); - } - - /** - * Get known browser aliases - * - * @return array the browser aliases - */ - protected function getKnownBrowserAliases() - { - return array( - 'shiretoko' => 'firefox', - 'namoroka' => 'firefox', - 'shredder' => 'firefox', - 'minefield' => 'firefox', - 'granparadiso' => 'firefox' - ); - } - - /** - * Get known operating system - * - * @return array the operating systems - */ - protected function getKnownOperatingSystems() - { - return array( - 'windows', - 'macintosh', - 'linux', - 'freebsd', - 'unix', - 'iphone' - ); - } - - /** - * Get known operating system aliases - * - * @return array the operating system aliases - */ - protected function getKnownOperatingSystemAliases() - { - return array(); - } - - /** - * Get known engines - * - * @return array the engines - */ - protected function getKnownEngines() - { - return array( - 'gecko', - 'webkit', - 'trident', - 'presto' - ); - } - - /** - * Get known engines aliases - * - * @return array the engines aliases - */ - protected function getKnownEngineAliases() - { - return array(); - } - - /** - * Filters - */ - - /** - * Google chrome has a safari like signature - */ - protected function filterGoogleChrome(array &$userAgent) - { - if ('safari' === $userAgent['browser_name'] && strpos($userAgent['string'], 'chrome/')) - { - $userAgent['browser_name'] = 'chrome'; - $userAgent['browser_version'] = preg_replace('|.+chrome/([0-9]+(?:\.[0-9]+)?).+|', '$1', $userAgent['string']); - } - } - - /** - * Safari version is not encoded "normally" - */ - protected function filterSafariVersion(array &$userAgent) - { - if ('safari' === $userAgent['browser_name'] && strpos($userAgent['string'], ' version/')) - { - $userAgent['browser_version'] = preg_replace('|.+\sversion/([0-9]+(?:\.[0-9]+)?).+|', '$1', $userAgent['string']); - } - } - - /** - * Opera 10.00 (and higher) version number is located at the end - */ - protected function filterOperaVersion(array &$userAgent) - { - if('opera' === $userAgent['browser_name'] && strpos($userAgent['string'], ' version/')) - { - $userAgent['browser_version'] = preg_replace('|.+\sversion/([0-9]+\.[0-9]+)\s*.*|', '$1', $userAgent['string']); - } - } - - /** - * Yahoo bot has a special user agent string - */ - protected function filterYahoo(array &$userAgent) - { - if (null === $userAgent['browser_name'] && strpos($userAgent['string'], 'yahoo! slurp')) - { - $userAgent['browser_name'] = 'yahoobot'; - } - } - - /** - * MSIE does not always declare its engine - */ - protected function filterMsie(array &$userAgent) - { - if ('msie' === $userAgent['browser_name'] && empty($userAgent['engine'])) - { - $userAgent['engine'] = 'trident'; - } - } - - /** - * Android has a safari like signature - */ - protected function filterAndroid(array &$userAgent) { - if ('safari' === $userAgent['browser_name'] && strpos($userAgent['string'], 'android ')) { - $userAgent['browser_name'] = 'android'; - $userAgent['operating_system'] = 'android'; - $userAgent['browser_version'] = preg_replace('|.+android ([0-9]+(?:\.[0-9]+)+).+|', '$1', $userAgent['string']); - } - } -} From ca519dd5c4a7c2450b87bf0edfbaa01b02d11bc7 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Fri, 22 Aug 2014 20:39:25 -0600 Subject: [PATCH 52/63] Refactored the markdown link trait to use call_user_func_array() rather eval() which is slow and rather dangerous. --- .../Common/Markdown/MarkdownGravLinkTrait.php | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php b/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php index fdad102ca1..11475a0138 100644 --- a/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php +++ b/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php @@ -25,17 +25,6 @@ protected function identifyLink($Excerpt) //get the url and parse it $url = parse_url(htmlspecialchars_decode($Excerpt['element']['attributes']['src'])); - // if there is a query, then parse it and build action calls - if (isset($url['query'])) { - parse_str($url['query'], $actions); - - foreach ($actions as $action => $params) { - // ignore any url or html actions - if (!in_array($action, ['html','url'])) - $command .= '->' . $action . '(' . $params . ')'; - } - } - // if there is no host set but there is a path, the file is local if (!isset($url['host']) && isset($url['path'])) { // get the media objects for this page @@ -46,16 +35,27 @@ protected function identifyLink($Excerpt) // get the medium object $medium = $media->images()[$url['path']]; - // unless one of the actions is lightbox method get the url + // if there is a query, then parse it and build action calls + if (isset($url['query'])) { + parse_str($url['query'], $actions); + } + + // loop through actions for the image and call them + foreach ($actions as $action => $params) { + // as long as it's not an html, url or ligtbox action + if (!in_array($action, ['html','url','lightbox'])) { + call_user_func_array(array(&$medium, $action), explode(',', $params)); + } + } + + // Get the URL for regular images, or an array of bits needed to put together + // the lightbox HTML if (!isset($actions['lightbox'])) { - $command .= '->url()'; + $src = $medium->url(); } else { - $command .= '->lightboxRaw()'; + $src = $medium->lightboxRaw(); } - // evaluate the commands to run against the media object - eval ('$src = $medium'.$command.';'); - // set the src element with the new generated url if (!isset($actions['lightbox']) && !is_array($src)) { $Excerpt['element']['attributes']['src'] = $src; From a5a97b5396310e08ce8db4ea699d17be99320ff8 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sat, 23 Aug 2014 06:54:13 -0600 Subject: [PATCH 53/63] enabled page plugins by default as these are not called when cached --- system/config/system.yaml | 2 +- user/config/system.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system/config/system.yaml b/system/config/system.yaml index 65a7ce1936..a944a34885 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -16,7 +16,7 @@ pages: markdown: true # Process Markdown twig: false # Process Twig events: - page: false # Enable page level events + page: true # Enable page level events twig: true # Enable twig level events cache: diff --git a/user/config/system.yaml b/user/config/system.yaml index 8f3cb5decc..84a96f979f 100644 --- a/user/config/system.yaml +++ b/user/config/system.yaml @@ -8,7 +8,7 @@ pages: markdown: true twig: false events: - page: false + page: true twig: true cache: From 74b838c1bc683e531173fa9f6ca8612d53f7f34c Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sat, 23 Aug 2014 09:44:08 -0600 Subject: [PATCH 54/63] just a question... --- system/src/Grav/Common/Page/Page.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 8d68d8c82b..55bcd1da24 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -1319,7 +1319,7 @@ public function collection($params = 'content') } } - $config->set('system.cache.enabled', false); + $config->set('system.cache.enabled', false); // TODO: Do we still need this? } } // TODO: END OF MOVE From 6add01da97ada3935e43ff2ec6a40cd35b901f85 Mon Sep 17 00:00:00 2001 From: Djamil Legato Date: Sat, 23 Aug 2014 10:50:18 -0700 Subject: [PATCH 55/63] Added php version check on the CLI with message when exiting #25 --- bin/grav | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/grav b/bin/grav index e886be3228..79015cea1d 100755 --- a/bin/grav +++ b/bin/grav @@ -1,6 +1,10 @@ #!/usr/bin/env php Date: Sun, 24 Aug 2014 11:33:29 -0600 Subject: [PATCH 56/63] Added an entry about potential need of RewriteBase and tweaked the index.php rewrite rule --- .htaccess | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.htaccess b/.htaccess index e2a441c7df..1ecd2b9214 100755 --- a/.htaccess +++ b/.htaccess @@ -3,10 +3,17 @@ Options -Multiviews RewriteEngine On +# If you are getting 404 errors on subpages, you may have to uncomment the RewriteBase entry +# You should change the '/' to your appropriate subfolder. For example if you have +# your Grav install at the root of your site '/' should work, else it might be something +# along the lines of: RewriteBase / + +#RewriteBase / + # access site RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule . index.php [L] +RewriteRule ^(.*)$ index.php [QSA,L] # block various user files from being accessed directly RewriteRule ^user/accounts/(.*)$ error [R=301,L] From c1073fec0cb7fa0e1b7b60616e10cc6cdde9834e Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 24 Aug 2014 11:51:14 -0600 Subject: [PATCH 57/63] Different tweaks --- .htaccess | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.htaccess b/.htaccess index 1ecd2b9214..cf009b98d1 100755 --- a/.htaccess +++ b/.htaccess @@ -1,35 +1,39 @@ + Options -Multiviews RewriteEngine On +## # If you are getting 404 errors on subpages, you may have to uncomment the RewriteBase entry # You should change the '/' to your appropriate subfolder. For example if you have # your Grav install at the root of your site '/' should work, else it might be something # along the lines of: RewriteBase / +## -#RewriteBase / +# RewriteBase / -# access site +# Access site +RewriteCond %{REQUEST_URI} !^/index\.php RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^(.*)$ index.php [QSA,L] +RewriteRule .* index.php [L] -# block various user files from being accessed directly +# Block various user files from being accessed directly RewriteRule ^user/accounts/(.*)$ error [R=301,L] RewriteRule ^user/config/(.*)$ error [R=301,L] RewriteRule ^user/(.*)\.(txt|md|html|php|yaml|json|twig|sh|bat)$ error [R=301,L] -# block cache +# Block cache/ RewriteRule ^cache/(.*) error [R=301,L] -# block bin +# Block bin/ RewriteRule ^bin/(.*)$ error [R=301,L] -# block system +# Block system/ RewriteRule ^system/(.*)$ error [R=301,L] -# block vendor +# Block vendor/ RewriteRule ^vendor/(.*)$ error [R=301,L] From a585430a5cd4b7596f25a22b605eeaf26c7eed8d Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 24 Aug 2014 12:07:45 -0600 Subject: [PATCH 58/63] This would cause problem --- .htaccess | 1 - 1 file changed, 1 deletion(-) diff --git a/.htaccess b/.htaccess index cf009b98d1..0c51c06ee2 100755 --- a/.htaccess +++ b/.htaccess @@ -14,7 +14,6 @@ RewriteEngine On # RewriteBase / # Access site -RewriteCond %{REQUEST_URI} !^/index\.php RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule .* index.php [L] From 4a1989e3a822fb1030d8803c803b1f388890422b Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Mon, 25 Aug 2014 08:40:41 -0600 Subject: [PATCH 59/63] Added a default 'detect' mode for Tracy, can be changed via debugger.mode --- composer.json | 2 +- system/config/system.yaml | 13 ++-- system/src/Grav/Common/Debugger.php | 13 +++- vendor/autoload.php | 2 +- vendor/composer/autoload_real.php | 10 ++-- vendor/composer/installed.json | 92 ++++++++++++++--------------- 6 files changed, 72 insertions(+), 60 deletions(-) diff --git a/composer.json b/composer.json index ef489a2348..d247aa06e5 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "require": { "php": ">=5.4.0", "twig/twig": "~1.16", - "erusev/parsedown-extra": "~0.2", + "erusev/parsedown-extra": "dev-master", "symfony/yaml": "~2.5", "symfony/console": "~2.5", "symfony/event-dispatcher": "~2.5", diff --git a/system/config/system.yaml b/system/config/system.yaml index a944a34885..6fd85e6413 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -32,15 +32,16 @@ twig: auto_reload: true # Refresh cache on changes autoescape: false # Autoescape Twig vars -assets: # Configuration for Assets Manager (JS, CSS) - css_pipeline: false # The CSS pipeline is the unification of multiple CSS resources into one file - css_minify: true # Minify the CSS during pipelining - css_rewrite: true # Rewrite any CSS relative URLs during pipelining - js_pipeline: false # The JS pipeline is the unification of multiple JS resources into one file - js_minify: true # Minify the JS during pipelining +assets: # Configuration for Assets Manager (JS, CSS) + css_pipeline: false # The CSS pipeline is the unification of multiple CSS resources into one file + css_minify: true # Minify the CSS during pipelining + css_rewrite: true # Rewrite any CSS relative URLs during pipelining + js_pipeline: false # The JS pipeline is the unification of multiple JS resources into one file + js_minify: true # Minify the JS during pipelining debugger: enabled: false # Enable Grav debugger and following settings + mode: detect # Mode tracy Debugger should be set to when enabled: detect|development|production strict: false # Throw fatal error also on PHP warnings and notices max_depth: 10 # How many nested levels to display for objects or arrays log: diff --git a/system/src/Grav/Common/Debugger.php b/system/src/Grav/Common/Debugger.php index 7505224415..ee32ead766 100644 --- a/system/src/Grav/Common/Debugger.php +++ b/system/src/Grav/Common/Debugger.php @@ -11,6 +11,7 @@ class Debugger { const PRODUCTION = TracyDebugger::PRODUCTION; const DEVELOPMENT = TracyDebugger::DEVELOPMENT; + const DETECT = TracyDebugger::DETECT; public function __construct($mode = self::PRODUCTION) { @@ -27,6 +28,7 @@ public function init() /** @var Config $config */ $config = $grav['config']; + $mode = $config->get('system.debugger.mode'); TracyDebugger::$logDirectory = $config->get('system.debugger.log.enabled') ? LOG_DIR : null; TracyDebugger::$maxDepth = $config->get('system.debugger.max_depth'); @@ -39,7 +41,16 @@ public function init() if (function_exists('ini_set')) { ini_set('display_errors', true); } - TracyDebugger::$productionMode = TracyDebugger::DEVELOPMENT; + + if ($mode == strtolower('detect')) { + TracyDebugger::$productionMode = self::DETECT; + } elseif ($mode == strtolower('production')) { + TracyDebugger::$productionMode = self::PRODUCTION; + } else { + TracyDebugger::$productionMode = self::DEVELOPMENT; + } + + } } diff --git a/vendor/autoload.php b/vendor/autoload.php index ef61f61382..9922f69738 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit3f16975091c92a1711741b1ac4f955c3::getLoader(); +return ComposerAutoloaderInitc72d8fa047c31604816395255e8b35b9::getLoader(); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index f6962e2189..ede8c1c058 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit3f16975091c92a1711741b1ac4f955c3 +class ComposerAutoloaderInitc72d8fa047c31604816395255e8b35b9 { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit3f16975091c92a1711741b1ac4f955c3', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInitc72d8fa047c31604816395255e8b35b9', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit3f16975091c92a1711741b1ac4f955c3', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInitc72d8fa047c31604816395255e8b35b9', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ public static function getLoader() $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequire3f16975091c92a1711741b1ac4f955c3($file); + composerRequirec72d8fa047c31604816395255e8b35b9($file); } return $loader; } } -function composerRequire3f16975091c92a1711741b1ac4f955c3($file) +function composerRequirec72d8fa047c31604816395255e8b35b9($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 20dfc0af64..0ee0cd5f48 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -40,52 +40,6 @@ "parser" ] }, - { - "name": "erusev/parsedown-extra", - "version": "0.2.0", - "version_normalized": "0.2.0.0", - "source": { - "type": "git", - "url": "https://github.com/erusev/parsedown-extra.git", - "reference": "7578fe28ce42e7a1fff4ba2aada3807c4c03d04b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown-extra/zipball/7578fe28ce42e7a1fff4ba2aada3807c4c03d04b", - "reference": "7578fe28ce42e7a1fff4ba2aada3807c4c03d04b", - "shasum": "" - }, - "require": { - "erusev/parsedown": "~1.0" - }, - "time": "2014-08-16 11:20:35", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "ParsedownExtra": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Emanuil Rusev", - "email": "hello@erusev.com", - "homepage": "http://erusev.com" - } - ], - "description": "An extension of Parsedown that adds support for Markdown Extra.", - "homepage": "https://github.com/erusev/parsedown-extra", - "keywords": [ - "markdown", - "markdown extra", - "parsedown", - "parser" - ] - }, { "name": "doctrine/cache", "version": "v1.3.0", @@ -711,5 +665,51 @@ "user agent", "useragent" ] + }, + { + "name": "erusev/parsedown-extra", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/erusev/parsedown-extra.git", + "reference": "7578fe28ce42e7a1fff4ba2aada3807c4c03d04b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/erusev/parsedown-extra/zipball/7578fe28ce42e7a1fff4ba2aada3807c4c03d04b", + "reference": "7578fe28ce42e7a1fff4ba2aada3807c4c03d04b", + "shasum": "" + }, + "require": { + "erusev/parsedown": "~1.0" + }, + "time": "2014-08-16 11:20:35", + "type": "library", + "installation-source": "source", + "autoload": { + "psr-0": { + "ParsedownExtra": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "An extension of Parsedown that adds support for Markdown Extra.", + "homepage": "https://github.com/erusev/parsedown-extra", + "keywords": [ + "markdown", + "markdown extra", + "parsedown", + "parser" + ] } ] From 65720df28d03feaa242862cd15cebf9a4eb8b8ca Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Mon, 25 Aug 2014 08:56:38 -0600 Subject: [PATCH 60/63] Added a new `random` sort order option --- system/src/Grav/Common/Page/Pages.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index 24da249f3f..9dbcca008f 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -539,8 +539,14 @@ protected function buildSort($path, array $pages, $order_by = 'default', $manual } } - // Sort by the new list. - asort($list); + // handle special case when order_by is random + if ($order_by == 'random') { + $list = $this->array_shuffle($list); + } else { + // else just sort the list according to specified key + asort($list); + } + // Move manually ordered items into the beginning of the list. Order of the unlisted items does not change. if (is_array($manual) && !empty($manual)) { @@ -568,4 +574,17 @@ protected function buildSort($path, array $pages, $order_by = 'default', $manual $this->sort[$path][$order_by][$key] = $info; } } + + // Shuffles and associative array + protected function array_shuffle($list) { + $keys = array_keys($list); + shuffle($keys); + + $new = array(); + foreach($keys as $key) { + $new[$key] = $list[$key]; + } + + return $new; + } } From b442aa2dd6764fdb3c5caae6597e0846a06864b0 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Mon, 25 Aug 2014 09:29:35 -0600 Subject: [PATCH 61/63] Added page option for markdown_extra --- system/src/Grav/Common/Page/Page.php | 10 +++++++++- user/config/system.yaml | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 55bcd1da24..63ebc11521 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -70,6 +70,7 @@ class Page protected $modular_twig; protected $process; protected $summary_size; + protected $markdown_extra; /** * @var Page Unmodified (original) version of the page. Used for copying and moving the page. @@ -201,6 +202,9 @@ public function header($var = null) if (isset($this->header->date)) { $this->date = strtotime($this->header->date); } + if (isset($this->header->markdown_extra)) { + $this->markdown_extra = (bool)$this->header->markdown_extra; + } if (isset($this->header->taxonomy)) { foreach ($this->header->taxonomy as $taxonomy => $taxitems) { $this->taxonomy[$taxonomy] = (array)$taxitems; @@ -214,7 +218,9 @@ public function header($var = null) $this->process[$process] = $status; } } + } + return $this->header; } @@ -1517,7 +1523,9 @@ protected function parseMarkdownContent($content) { /** @var Config $config */ $config = self::$grav['config']; - if ($config->get('system.pages.markdown_extra')) { + + // get the appropriate setting for markdown extra + if (isset($this->markdown_extra) ? $this->markdown_extra : $config->get('system.pages.markdown_extra')) { $parsedown = new MarkdownExtra($this); } else { $parsedown = new Markdown($this); diff --git a/user/config/system.yaml b/user/config/system.yaml index 84a96f979f..be6a776ed0 100644 --- a/user/config/system.yaml +++ b/user/config/system.yaml @@ -3,7 +3,7 @@ home: pages: theme: antimatter - markdown_extra: true + markdown_extra: false process: markdown: true twig: false From 8a37278f79e068ff409fee7176ef9716a4f40115 Mon Sep 17 00:00:00 2001 From: Djamil Legato Date: Mon, 25 Aug 2014 09:11:16 -0700 Subject: [PATCH 62/63] Removing events settings from user config as they are now in the core --- user/config/system.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/user/config/system.yaml b/user/config/system.yaml index be6a776ed0..1bf0c1516e 100644 --- a/user/config/system.yaml +++ b/user/config/system.yaml @@ -7,9 +7,6 @@ pages: process: markdown: true twig: false - events: - page: true - twig: true cache: enabled: true From 1e39c7d925c0e81f5fde926f9ecb9aa5275be24a Mon Sep 17 00:00:00 2001 From: Djamil Legato Date: Mon, 25 Aug 2014 10:06:34 -0700 Subject: [PATCH 63/63] Preparing for release --- VERSION | 2 +- system/defines.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index a3df0a6959..ac39a106c4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.8.0 +0.9.0 diff --git a/system/defines.php b/system/defines.php index 58cd757c7f..6b05bdad71 100644 --- a/system/defines.php +++ b/system/defines.php @@ -2,7 +2,7 @@ // Some standard defines define('GRAV', true); -define('GRAV_VERSION', '0.8.1'); +define('GRAV_VERSION', '0.9.0'); define('DS', '/'); // Directories and Paths