From 0e1e101f4b7099a982533562dca7324349ae417f Mon Sep 17 00:00:00 2001 From: froschdesign Date: Fri, 6 May 2016 22:09:09 +0200 Subject: [PATCH 01/10] [Docs] Rename documentation files --- .../{zend.module-manager.best-practices.md => best-practices.md} | 0 doc/book/{zend.module-manager.intro.md => intro.md} | 0 ...d.module-manager.module-autoloader.md => module-autoloader.md} | 0 doc/book/{zend.module-manager.module-class.md => module-class.md} | 0 .../{zend.module-manager.module-manager.md => module-manager.md} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename doc/book/{zend.module-manager.best-practices.md => best-practices.md} (100%) rename doc/book/{zend.module-manager.intro.md => intro.md} (100%) rename doc/book/{zend.module-manager.module-autoloader.md => module-autoloader.md} (100%) rename doc/book/{zend.module-manager.module-class.md => module-class.md} (100%) rename doc/book/{zend.module-manager.module-manager.md => module-manager.md} (100%) diff --git a/doc/book/zend.module-manager.best-practices.md b/doc/book/best-practices.md similarity index 100% rename from doc/book/zend.module-manager.best-practices.md rename to doc/book/best-practices.md diff --git a/doc/book/zend.module-manager.intro.md b/doc/book/intro.md similarity index 100% rename from doc/book/zend.module-manager.intro.md rename to doc/book/intro.md diff --git a/doc/book/zend.module-manager.module-autoloader.md b/doc/book/module-autoloader.md similarity index 100% rename from doc/book/zend.module-manager.module-autoloader.md rename to doc/book/module-autoloader.md diff --git a/doc/book/zend.module-manager.module-class.md b/doc/book/module-class.md similarity index 100% rename from doc/book/zend.module-manager.module-class.md rename to doc/book/module-class.md diff --git a/doc/book/zend.module-manager.module-manager.md b/doc/book/module-manager.md similarity index 100% rename from doc/book/zend.module-manager.module-manager.md rename to doc/book/module-manager.md From 463670227fca7ef619648216473ef2cd9e73f05e Mon Sep 17 00:00:00 2001 From: froschdesign Date: Fri, 6 May 2016 22:13:48 +0200 Subject: [PATCH 02/10] [Docs] Switch from Bookdown to MkDocs configuration --- doc/bookdown.json | 11 ----------- mkdocs.yml | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 11 deletions(-) delete mode 100644 doc/bookdown.json create mode 100644 mkdocs.yml diff --git a/doc/bookdown.json b/doc/bookdown.json deleted file mode 100644 index b4eae34..0000000 --- a/doc/bookdown.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "title": "Zend\\Module-manager", - "target": "html/", - "content": [ - "book/zend.module-manager.intro.md", - "book/zend.module-manager.module-manager.md", - "book/zend.module-manager.module-class.md", - "book/zend.module-manager.module-autoloader.md", - "book/zend.module-manager.best-practices.md" - ] -} \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..c40b1f8 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,14 @@ +docs_dir: doc/book +site_dir: doc/html +pages: + - index.md + - Intro: intro.md + - Reference: + - "The Module Manager": module-manager.md + - "The Module Class": module-class.md + - "The Module Autoloader": module-autoloader.md + - "Best Practices when Creating Modules": best-practices.md +site_name: zend-modulemanager +site_description: zend-modulemanager +repo_url: 'https://github.com/zendframework/zend-modulemanager' +copyright: 'Copyright (c) 2016 Zend Technologies USA Inc.' \ No newline at end of file From 2954984a6e6fe750aff78d51a0a45a0aa6cd74b6 Mon Sep 17 00:00:00 2001 From: froschdesign Date: Fri, 6 May 2016 22:14:21 +0200 Subject: [PATCH 03/10] [Docs] Add symlink for README.md --- doc/book/index.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/book/index.md diff --git a/doc/book/index.md b/doc/book/index.md new file mode 100644 index 0000000..fe84005 --- /dev/null +++ b/doc/book/index.md @@ -0,0 +1 @@ +../../README.md \ No newline at end of file From b5de31fbfc0d6471be991f142f5bf2762f82912b Mon Sep 17 00:00:00 2001 From: froschdesign Date: Fri, 6 May 2016 22:16:13 +0200 Subject: [PATCH 04/10] [Docs] Create a doc/book/index.html --- doc/book/index.html | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 doc/book/index.html diff --git a/doc/book/index.html b/doc/book/index.html new file mode 100644 index 0000000..b17ff58 --- /dev/null +++ b/doc/book/index.html @@ -0,0 +1,11 @@ +
+
+

zend-modulemanager

+ +

+ ModuleManager component from Zend Framework +

+ +
$ composer require zendframework/zend-modulemanager
+
+
\ No newline at end of file From afedf5c415f01684ce75aa3fe79b9878e89997da Mon Sep 17 00:00:00 2001 From: froschdesign Date: Fri, 6 May 2016 22:16:41 +0200 Subject: [PATCH 05/10] [Docs] Update .gitignore file --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index a7fc91d..28d2d11 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ .*.un~ nbproject tmp/ +doc/html/ +zf-mkdoc-theme/ clover.xml composer.lock From 6a2d4dc1afd7c4983220874d0471a60c8d4ed023 Mon Sep 17 00:00:00 2001 From: froschdesign Date: Fri, 6 May 2016 22:19:24 +0200 Subject: [PATCH 06/10] [Docs] Update .travis.yml file --- .travis.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3526442..2ba452e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,11 +10,18 @@ branches: cache: directories: - $HOME/.composer/cache + - $HOME/.local + - zf-mkdoc-theme env: global: - EVENT_MANAGER_VERSION="^3.0" - SERVICE_MANAGER_VERSION="^3.0.3" + - SITE_URL: https://zendframework.github.io/zend-modulemanager + - GH_USER_NAME: "Matthew Weier O'Phinney" + - GH_USER_EMAIL: matthew@weierophinney.net + - GH_REF: github.com/zendframework/zend-modulemanager.git + - secure: "" matrix: fast_finish: true @@ -29,6 +36,8 @@ matrix: - php: 5.6 env: - EXECUTE_TEST_COVERALLS=true + - DEPLOY_DOCS="$(if [[ $TRAVIS_BRANCH == 'master' && $TRAVIS_PULL_REQUEST == 'false' ]]; then echo -n 'true' ; else echo -n 'false' ; fi)" + - PATH="$HOME/.local/bin:$PATH" - php: 5.6 env: - EVENT_MANAGER_VERSION="^2.6.2" @@ -64,6 +73,10 @@ script: - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/phpunit --coverage-clover clover.xml ; fi - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then ./vendor/bin/phpunit ; fi - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/php-cs-fixer fix -v --diff --dry-run ; fi + - if [[ $DEPLOY_DOCS + +after_success: + - if [[ $DEPLOY_DOCS == "true" ]]; then echo "Preparing to build and deploy documentation" ; ./zf-mkdoc-theme/deploy.sh ; echo "Completed deploying documentation" ; fi after_script: - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/coveralls ; fi From 87c81378e6ae3875173295bf337034a44ea40bd2 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 9 May 2016 17:05:22 -0500 Subject: [PATCH 07/10] Fixed .travis.yml DEPLOY_DOCS conditional --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2ba452e..4a0e381 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,7 +73,7 @@ script: - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/phpunit --coverage-clover clover.xml ; fi - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then ./vendor/bin/phpunit ; fi - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/php-cs-fixer fix -v --diff --dry-run ; fi - - if [[ $DEPLOY_DOCS + - if [[ $DEPLOY_DOCS == "true" && "$TRAVIS_TEST_RESULT" == "0" ]]; then travis_retry curl -sSL https://raw.githubusercontent.com/zendframework/zf-mkdoc-theme/master/theme-installer.sh | bash ; fi after_success: - if [[ $DEPLOY_DOCS == "true" ]]; then echo "Preparing to build and deploy documentation" ; ./zf-mkdoc-theme/deploy.sh ; echo "Completed deploying documentation" ; fi From 8871e5391530a0d276ba909b29bdb92be8682f90 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 9 May 2016 17:49:46 -0500 Subject: [PATCH 08/10] Edited documentation for content and formatting --- doc/book/best-practices.md | 69 +++++----- doc/book/index.html | 4 +- doc/book/intro.md | 75 ++++++----- doc/book/module-autoloader.md | 91 +++++++------ doc/book/module-class.md | 101 +++++++------- doc/book/module-manager.md | 244 +++++++++++++++++++--------------- 6 files changed, 322 insertions(+), 262 deletions(-) diff --git a/doc/book/best-practices.md b/doc/book/best-practices.md index b944a16..7a088ee 100644 --- a/doc/book/best-practices.md +++ b/doc/book/best-practices.md @@ -4,43 +4,50 @@ When creating a ZF2 module, there are some best practices you should keep in min ## Keep the `init()` and `onBootstrap()` methods lightweight -Be conservative with the actions you perform in the `init()` and `onBootstrap()` methods of your -`Module` class. These methods are run for **every** page request, and should not perform anything -heavy. As a rule of thumb, registering event listeners is an appropriate task to perform in these -methods. Such lightweight tasks will generally not have a measurable impact on the performance of -your application, even with many modules enabled. It is considered bad practice to utilize these -methods for setting up or configuring instances of application resources such as a database -connection, application logger, or mailer. Tasks such as these are better served through the -`ServiceManager` capabilities of Zend Framework 2. +Be conservative with the actions you perform in the `init()` and `onBootstrap()` +methods of your `Module` class. These methods are run for **every** page +request, and should not perform anything heavy. As a rule of thumb, registering +event listeners is an appropriate task to perform in these methods. Such +lightweight tasks will generally not have a measurable impact on the performance +of your application, even with many modules enabled. It is considered bad +practice to utilize these methods for setting up or configuring instances of +application resources such as a database connection, application logger, or +mailer. Tasks such as these are better served through the `ServiceManager` +capabilities. ## Do not perform writes within a module -You should **never** code your module to perform or expect any writes within the module's directory. -Once installed, the files within a module's directory should always match the distribution verbatim. -Any user-provided configuration should be performed via overrides in the Application module or via -application-level configuration files. Any other required filesystem writes should be performed in -some writeable path that is outside of the module's directory. - -There are two primary advantages to following this rule. First, any modules which attempt to write -within themselves will not be compatible with phar packaging. Second, by keeping the module in sync -with the upstream distribution, updates via mechanisms such as Git will be simple and trouble-free. -Of course, the Application module is a special exception to this rule, as there is typically no -upstream distribution for this module, and it's unlikely you would want to run this package from -within a phar archive. +You should **never** code your module to perform or expect any writes within the +module's directory. Once installed, the files within a module's directory +should always match the distribution verbatim. Any user-provided configuration +should be performed via overrides in the `Application` module or via +application-level configuration files. Any other required filesystem writes +should be performed in some writeable path that is outside of the module's +directory. + +There are two primary advantages to following this rule. First, any modules +which attempt to write within themselves will not be compatible with phar +packaging. Second, by keeping the module in sync with the upstream distribution, +updates via mechanisms such as git will be simple and trouble-free. Of course, +the `Application` module is a special exception to this rule, as there is +typically no upstream distribution for this module, and it's unlikely you would +want to run this package from within a phar archive. ## Utilize a vendor prefix for module names -To avoid module naming conflicts, you are encouraged to prefix your module namespace with a vendor -prefix. As an example, the (incomplete) developer tools module distributed by Zend is named -"ZendDeveloperTools" instead of simply "DeveloperTools". +To avoid module naming conflicts, you are encouraged to prefix your module +namespace with a vendor prefix. As an example, the developer tools module +distributed by Zend is named "ZendDeveloperTools" instead of simply +"DeveloperTools". ## Utilize a module prefix for service names -If you define services in the top-level Service Manager, you are encouraged to prefix these services -with the name of your module to avoid conflicts with other modules' services. For example, the -database adapter used by MyModule should be called "MyModuleDbAdapter" rather than simply -"DbAdapter." If you need to share a service with other modules, remember that the Service Manager -"alias" feature can be used in a merged configuration to override factories defined by individual -modules. Ideally, modules should define their own service dependencies, but aliases can be -configured at the application level to ensure that common services in individual modules all refer -to the same instance. +If you define services in the top-level service manager, you are encouraged to +prefix these services with the name of your module to avoid conflicts with other +modules' services. For example, the database adapter used by MyModule should be +called "MyModuleDbAdapter" rather than simply "DbAdapter." If you need to share +a service with other modules, remember that the Service Manager "alias" feature +can be used in a merged configuration to override factories defined by +individual modules. Ideally, modules should define their own service +dependencies, but aliases can be configured at the application level to ensure +that common services in individual modules all refer to the same instance. diff --git a/doc/book/index.html b/doc/book/index.html index b17ff58..acaf628 100644 --- a/doc/book/index.html +++ b/doc/book/index.html @@ -3,9 +3,9 @@

zend-modulemanager

- ModuleManager component from Zend Framework + Modular application system for zend-mvc applications.

$ composer require zendframework/zend-modulemanager
- \ No newline at end of file + diff --git a/doc/book/intro.md b/doc/book/intro.md index 0320e29..5c515d8 100644 --- a/doc/book/intro.md +++ b/doc/book/intro.md @@ -1,36 +1,42 @@ # Introduction to the Module System -Zend Framework 2.0 introduces a new and powerful approach to modules. This new module system is -designed with flexibility, simplicity, and re-usability in mind. A module may contain just about -anything: PHP code, including MVC functionality; library code; view scripts; and/or public assets -such as images, CSS, and JavaScript. The possibilities are endless. +Zend Framework 2.0 introduced a new and powerful approach to modules. This new +module system is designed with flexibility, simplicity, and re-usability in +mind. A module may contain just about anything: PHP code, including MVC +functionality; library code; view scripts; and/or public assets such as images, +CSS, and JavaScript. The possibilities are endless. -> ## Note -The module system in ZF2 has been designed to be a generic and powerful foundation from which -developers and other projects can build their own module or plugin systems. -For a better understanding of the event-driven concepts behind the ZF2 module system, it may be -helpful to read the [EventManager documentation](zend.event-manager.event-manager). +> ### Event-based system +> +> The module system in ZF2 has been designed to be a generic and powerful foundation from which +> developers and other projects can build their own module or plugin systems. +> For a better understanding of the event-driven concepts behind the ZF2 module system, it may be +> helpful to read the [EventManager documentation](https://zendframework.github.io/zend-eventmanager/). The module system is made up of the following: -* [The Module Autoloader](zend.loader.module-autoloader) - `Zend\Loader\ModuleAutoloader` is a -specialized autoloader that is responsible for the locating and loading of modules' `Module` classes -from a variety of sources. -* [The Module Manager](zend.module-manager.module-manager.md) - `Zend\ModuleManager\ModuleManager` -simply takes an array of module names and fires a sequence of events for each one, allowing the -behavior of the module system to be defined entirely by the listeners which are attached to the -module manager. -* **ModuleManager Listeners** - Event listeners can be attached to the module manager's various -events. These listeners can do everything from resolving and loading modules to performing complex -initialization tasks and introspection into each returned module object. +- [The Module Autoloader](https://zendframework.github.io/zend-loader/module-autoloader/) - + `Zend\Loader\ModuleAutoloader` is a specialized autoloader that is responsible + for the locating and loading of modules' `Module` classes from a variety of + sources. +- [The Module Manager](module-manager.md) - `Zend\ModuleManager\ModuleManager` + takes an array of module names and fires a sequence of events for each one, + allowing the behavior of the module system to be defined entirely by the + listeners which are attached to the module manager. +- **ModuleManager Listeners** - Event listeners can be attached to the module + manager's various events. These listeners can do everything from resolving and + loading modules to performing complex initialization tasks and introspection + into each returned module object. -> ## Note -The name of a module in a typical Zend Framework 2 application is simply a [PHP -namespace](http://php.net/namespaces) and must follow all of the same rules for naming. +> ### Modules are PHP namespaces +> +> The name of a module in a Zend Framework application is a +> [PHP namespace](http://php.net/namespaces), and must follow all of the same +> rules for naming. -The recommended structure of a typical MVC-oriented ZF2 module is as follows: +The recommended structure for an MVC-oriented ZF2 module is as follows: -``` +```text module_root/ Module.php autoload_classmap.php @@ -60,14 +66,15 @@ module_root/ The three `autoload_*.php` files are not required, but recommended. They provide the following: -* `autoload_classmap.php` should return an array classmap of class name/filename pairs (with the -filenames resolved via the `__DIR__` magic constant). -* `autoload_function.php` should return a PHP callback that can be passed to -`spl_autoload_register()`. Typically, this callback should utilize the map returned by -`autoload_classmap.php`. -* `autoload_register.php` should register a PHP callback (typically that returned by -`autoload_function.php` with `spl_autoload_register()`. +- `autoload_classmap.php` should return an array classmap of class name/filename + pairs (with the filenames resolved via the `__DIR__` magic constant). +- `autoload_function.php` should return a PHP callback that can be passed to + `spl_autoload_register()`. Typically, this callback should utilize the map + returned by `autoload_classmap.php`. +- `autoload_register.php` should register a PHP callback (typically that + returned by `autoload_function.php` with `spl_autoload_register()`. -The purpose of these three files is to provide reasonable default mechanisms for autoloading the -classes contained in the module, thus providing a trivial way to consume the module without -requiring `Zend\ModuleManager` (e.g., for use outside a ZF2 application). +The purpose of these three files is to provide reasonable default mechanisms for +autoloading the classes contained in the module, thus providing a trivial way to +consume the module without requiring zend-modulemanager` (e.g., for use outside +a ZF2 application). diff --git a/doc/book/module-autoloader.md b/doc/book/module-autoloader.md index 846f5b9..cf9148f 100644 --- a/doc/book/module-autoloader.md +++ b/doc/book/module-autoloader.md @@ -1,25 +1,28 @@ # The Module Autoloader -Zend Framework 2 ships with the default module autoloader `Zend\Loader\ModuleAutoloader`. It is a -specialized autoloader responsible for locating and on-demand loading of, the `Module` classes from -a variety of sources. +zend-modulemanager ships with the default module autoloader +`Zend\Loader\ModuleAutoloader`. It is a specialized autoloader responsible for +locating and on-demand loading of, the `Module` classes from a variety of +sources. ## Module Autoloader Usage -By default, the provided `Zend\ModuleManager\Listener\DefaultListenerAggregate` sets up the -`ModuleAutoloader`; as a developer, you need only provide an array of module paths, either absolute -or relative to the application's root, for the `ModuleAutoloader` to check when loading modules. The -`DefaultListenerAggregate` will take care of instantiating and registering the `ModuleAutoloader` -for you. +By default, the provided `Zend\ModuleManager\Listener\DefaultListenerAggregate` +sets up the `ModuleAutoloader`; as a developer, you need only provide an array +of module paths, either absolute or relative to the application's root, for the +`ModuleAutoloader` to check when loading modules. The `DefaultListenerAggregate` +will take care of instantiating and registering the `ModuleAutoloader` for you. -> ## Note -In order for paths relative to your application directory to work, you must have the directive -`chdir(dirname(__DIR__));` in your `public/index.php` file. +> ### Must be in application root +> +> In order for paths relative to your application directory to work, you must +> have the directive `chdir(dirname(__DIR__));` in your `public/index.php` file. ### Registering module paths with the `DefaultListenerAggregate` -The following example will search for modules in three different `module_paths`. Two are local -directories of this application and the third is a system-wide shared directory. +The following example will search for modules in three different `module_paths`. +Two are local directories of this application and the third is a system-wide +shared directory. ```php // public/index.php @@ -29,31 +32,33 @@ use Zend\ModuleManager\ModuleManager; chdir(dirname(__DIR__)); // Instantiate and configure the default listener aggregate -$listenerOptions = new Listener\ListenerOptions(array( - 'module_paths' => array( +$listenerOptions = new Listener\ListenerOptions([ + 'module_paths' => [ './module', './vendor', '/usr/share/zfmodules', - ) -)); + ] +]); $defaultListeners = new Listener\DefaultListenerAggregate($listenerOptions); // Instantiate the module manager -$moduleManager = new ModuleManager(array( +$moduleManager = new ModuleManager([ 'Application', 'FooModule', 'BarModule', -)); +]); // Attach the default listener aggregate and load the modules $moduleManager->getEventManager()->attachAggregate($defaultListeners); $moduleManager->loadModules(); ``` -> ## Note -Module paths behave very similar to PHP's `include_path` and are searched in the order they are -defined. If you have modules with the same name in more than one registered module path, the module -autoloader will return the first one it finds. +> ### Module paths are FIFO +> +> Module paths behave very similar to PHP's `include_path` and are searched in +> the order they are defined. If you have modules with the same name in more +> than one registered module path, the module autoloader will return the first +> one it finds. ## Non-Standard / Explicit Module Paths @@ -63,8 +68,8 @@ Sometimes you may want to specify exactly where a module is instead of having ### Registering a Non-Standard / Explicit Module Path In this example, the autoloader will first check for `MyModule\Module` in -`/path/to/mymoduledir-v1.2/Module.php`. If it's not found, then it will fall back to searching any -other registered module paths. +`/path/to/mymoduledir-v1.2/Module.php`. If it's not found, then it will fall +back to searching any other registered module paths. ```php // ./public/index.php @@ -75,35 +80,35 @@ use Zend\ModuleManager\ModuleManager; chdir(dirname(__DIR__)); // Instantiate and configure the default listener aggregate -$listenerOptions = new Listener\ListenerOptions(array( - 'module_paths' => array( +$listenerOptions = new Listener\ListenerOptions([ + 'module_paths' => [ './module', './vendor', '/usr/share/zfmodules', 'MyModule' => '/path/to/mymoduledir-v1.2', - ) -)); + ] +]); $defaultListeners = new Listener\DefaultListenerAggregate($listenerOptions); /** * Without DefaultListenerAggregate: * - * $moduleAutoloader = new ModuleAutoloader(array( + * $moduleAutoloader = new ModuleAutoloader([ * './module', * './vendor', * '/usr/share/zfmodules', * 'MyModule' => '/path/to/mymoduledir-v1.2', - * )); + * ]); * $moduleAutoloader->register(); * */ // Instantiate the module manager -$moduleManager = new ModuleManager(array( +$moduleManager = new ModuleManager([ 'MyModule', 'FooModule', 'BarModule', -)); +]); // Attach the default listener aggregate and load the modules $moduleManager->getEventManager()->attachAggregate($defaultListeners); @@ -114,14 +119,16 @@ This same method works if you provide the path to a phar archive. ## Packaging Modules with Phar -If you prefer, you may easily package your module as a [phar archive](http://php.net/phar). The -module autoloader is able to autoload modules in the following archive formats: .phar, .phar.gz, -.phar.bz2, .phar.tar, .phar.tar.gz, .phar.tar.bz2, .phar.zip, .tar, .tar.gz, .tar.bz2, and .zip. +If you prefer, you may easily package your module as a +[phar archive](http://php.net/phar). The module autoloader is able to autoload +modules in the following archive formats: .phar, .phar.gz, .phar.bz2, .phar.tar, +.phar.tar.gz, .phar.tar.bz2, .phar.zip, .tar, .tar.gz, .tar.bz2, and .zip. -The easiest way to package your module is to simply tar the module directory. You can then replace -the `MyModule/` directory with `MyModule.tar`, and it should still be autoloaded without any -additional changes! +Package your module by performing a tar the module directory. You can then +replace the `MyModule/` directory with `MyModule.tar`, and it should still be +autoloaded without any additional changes! -> ## Note -If possible, avoid using any type of compression (bz2, gz, zip) on your phar archives, as it -introduces unnecessary CPU overhead to each request. +> ### Avoid compression +> +> If possible, avoid using any type of compression (bz2, gz, zip) on your phar +> archives, as it introduces unnecessary CPU overhead to each request. diff --git a/doc/book/module-class.md b/doc/book/module-class.md index 17b9f64..7253c15 100644 --- a/doc/book/module-class.md +++ b/doc/book/module-class.md @@ -1,20 +1,22 @@ # The Module Class -By default, the Zend Framework 2 module system simply expects each module name to be capable of +By default, the module system expects each module name to be capable of resolving to an object instance. The default module resolver, -`Zend\ModuleManager\Listener\ModuleResolverListener`, simply instantiates an instance of -`{moduleName}\Module` for each enabled module. +`Zend\ModuleManager\Listener\ModuleResolverListener`, instantiates an instance +of `{moduleName}\Module` for each enabled module. ## A Minimal Module As an example, provided the module name "MyModule", -`Zend\ModuleManager\Listener\ModuleResolverListener` will simply expect the class `MyModule\Module` -to be available. It relies on a registered autoloader (typically `Zend\Loader\ModuleAutoloader`) to -find and include the `MyModule\Module` class if it isn't already available. +`Zend\ModuleManager\Listener\ModuleResolverListener` will expect the class +`MyModule\Module` to be available. It relies on a registered autoloader +(typically `Zend\Loader\ModuleAutoloader`) to find and include the +`MyModule\Module` class if it isn't already available. -The directory structure of a module named "MyModule" might start out looking something like this: +The directory structure of a module named "MyModule" might start out looking +something like this: -``` +```text MyModule/ Module.php ``` @@ -29,13 +31,15 @@ class Module } ``` -Though it will not serve any purpose at this point, this "MyModule" module now has everything -required to be considered a valid module and to be loaded by the module system! +Though it will not serve any purpose at this point, this "MyModule" module now +has everything required to be considered a valid module and to be loaded by the +module system! -This `Module` class serves as the single entry point for `ModuleManager` listeners to interact with -a module. From within this simple - yet powerful - class, modules can override or provide additional -application configuration, perform initialization tasks such as registering autoloader(s), services -and event listeners, declaring dependencies, and much more. +This `Module` class serves as the single entry point for `ModuleManager` +listeners to interact with a module. From within this class, modules can +override or provide additional application configuration, perform initialization +tasks such as registering autoloader(s), services and event listeners, declaring +dependencies, and much more. ## A Typical Module Class @@ -48,16 +52,16 @@ class Module { public function getAutoloaderConfig() { - return array( - 'Zend\Loader\ClassMapAutoloader' => array( + return [ + 'Zend\Loader\ClassMapAutoloader' => [ __DIR__ . '/autoload_classmap.php', - ), - 'Zend\Loader\StandardAutoloader' => array( - 'namespaces' => array( + ], + 'Zend\Loader\StandardAutoloader' => [ + 'namespaces' => [ __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, - ), - ), - ); + ], + ], + ]; } public function getConfig() @@ -68,19 +72,21 @@ class Module ``` For a list of the provided module manager listeners and the interfaces and methods that `Module` -classes may implement in order to interact with the module manager and application, see the [module -manager listeners](zend.module-manager.module-manager.md#module-manager-listeners) and the [module -mananger events](zend.module-manager.module-manager.md#module-manager-events) documentations. +classes may implement in order to interact with the module manager and application, see the +[module manager listeners](module-manager.md#module-manager-listeners) and the +[module mananger events](module-manager.md#module-manager-events) documentation. -## The "loadModules.post" Event +## The loadModules.post Event -It is not safe for a module to assume that any other modules have already been loaded at the time -`init()` method is called. If your module needs to perform any actions after all other modules have -been loaded, the module manager's "loadModules.post" event makes this easy. +It is not safe for a module to assume that any other modules have already been +loaded at the time `init()` method is called. If your module needs to perform +any actions after all other modules have been loaded, use the module manager's +`loadModules.post`. -> ## Note -For more information on methods like `init()` and `getConfig()`, refer to the [module -manager listeners documentation](zend.module-manager.module-manager.md#module-manager-listeners). +> ### Event information +> +> For more information on methods like `init()` and `getConfig()`, refer to the +> [module manager listeners documentation](module-manager.md#module-manager-listeners). ### Sample Usage of "loadModules.post" Event @@ -94,7 +100,7 @@ class Module { // Remember to keep the init() method as lightweight as possible $events = $moduleManager->getEventManager(); - $events->attach('loadModules.post', array($this, 'modulesLoaded')); + $events->attach('loadModules.post', [$this, 'modulesLoaded']); } public function modulesLoaded(Event $e) @@ -102,24 +108,26 @@ class Module // This method is called once all modules are loaded. $moduleManager = $e->getTarget(); $loadedModules = $moduleManager->getLoadedModules(); + // To get the configuration from another module named 'FooModule' $config = $moduleManager->getModule('FooModule')->getConfig(); } } ``` -> ## Note -The `init()` method is called for **every** module implementing this feature, on **every** page -request, and should **only** be used for performing **lightweight** tasks such as registering event -listeners. +> ### Use init() sparingly +> +> The `init()` method is called for **every** module implementing this feature, +> on **every** page request, and should **only** be used for performing +> **lightweight** tasks such as registering event listeners. ## The MVC "bootstrap" Event -If you are writing an MVC-oriented module for Zend Framework 2, you may need access to additional -parts of the application in your `Module` class such as the instance of `Zend\Mvc\Application` or -its registered `ServiceManager` instance. For this, you may utilize the MVC "bootstrap" event. The -bootstrap event is triggered after the "loadModule.post" event, once *$application->bootstrap()* -is called. +If you are writing an MVC-oriented module, you may need access to additional +parts of the application in your `Module` class such as the instance of +`Zend\Mvc\Application` or its registered `ServiceManager` instance. For this, +you may utilize the MVC `bootstrap` event. The bootstrap event is triggered +after the `loadModule.post` event, once `$application->bootstrap()` is called. ### Sample Usage of the MVC "bootstrap" Event @@ -137,7 +145,8 @@ class Module } ``` -> ## Note -The `onBootstrap()` method is called for **every** module implementing this feature, on **every** -page request, and should **only** be used for performing **lightweight** tasks such as registering -event listeners. +> ### Use onBootstrap() sparingly +> +> The `onBootstrap()` method is called for **every** module implementing this +> feature, on **every** page request, and should **only** be used for performing +> **lightweight** tasks such as registering event listeners. diff --git a/doc/book/module-manager.md b/doc/book/module-manager.md index 4032f0e..d87ecb6 100644 --- a/doc/book/module-manager.md +++ b/doc/book/module-manager.md @@ -1,145 +1,158 @@ # The Module Manager -The module manager, `Zend\ModuleManager\ModuleManager`, is a very simple class which is responsible -for iterating over an array of module names and triggering a sequence of events for each. -Instantiation of module classes, initialization tasks, and configuration are all performed by -attached event listeners. +The module manager, `Zend\ModuleManager\ModuleManager`, is responsible for +iterating over an array of module names and triggering a sequence of events for +each. Instantiation of module classes, initialization tasks, and configuration +are all performed by attached event listeners. ## Module Manager Events The Module Manager events are defined in `Zend\ModuleManager\ModuleEvent`. -### Events triggered by `Zend\ModuleManager\ModuleManager` +### loadModules (`ModuleEvent::EVENT_LOAD_MODULES`) -#### loadModules (ModuleEvent::EVENT\_LOAD\_MODULES) +This event is primarily used internally to help encapsulate the work of loading +modules in event listeners, and allows the `loadModules.post` event to be more +user-friendly. Internal listeners will attach to this event with a negative +priority instead of `loadModules.post` so that users can safely assume things like +config merging have been done once `loadModules.post` is triggered, without having +to worry about priorities. -This event is primarily used internally to help encapsulate the work of loading modules in event -listeners, and allow the loadModules.post event to be more user-friendly. Internal listeners will -attach to this event with a negative priority instead of loadModules.post so that users can safely -assume things like config merging have been done once loadModules.post is triggered, without having -to worry about priorities at all. +### loadModule.resolve (`ModuleEvent::EVENT_LOAD_MODULE_RESOLVE`) -#### loadModule.resolve (ModuleEvent::EVENT\_LOAD\_MODULE\_RESOLVE) +Triggered for each module that is to be loaded. The listener(s) to this event +are responsible for taking a module name and resolving it to an instance of some +class. The default module resolver looks for the class `{modulename}\Module`, +instantiating and returning it if it exists. -Triggered for each module that is to be loaded. The listener(s) to this event are responsible for -taking a module name and resolving it to an instance of some class. The default module resolver -shipped with ZF2 simply looks for the class `{modulename}\Module`, instantiating and returning it if -it exists. +The name of the module may be retrieved by listeners using the `getModuleName()` +method of the `Event` object; a listener should then take that name and resolve +it to an object instance representing the given module. Multiple listeners can +be attached to this event, and the module manager will trigger them in order of +their priority until one returns an object. This allows you to attach additional +listeners which have alternative methods of resolving modules from a given +module name. -The name of the module may be retrieved by listeners using the `getModuleName()` method of the -`Event` object; a listener should then take that name and resolve it to an object instance -representing the given module. Multiple listeners can be attached to this event, and the module -manager will trigger them in order of their priority until one returns an object. This allows you to -attach additional listeners which have alternative methods of resolving modules from a given module -name. +### loadModule (`ModuleEvent::EVENT_LOAD_MODULE`) -#### loadModule (ModuleEvent::EVENT\_LOAD\_MODULE) +Once a module resolver listener has resolved the module name to an object, the +module manager then triggers this event, passing the newly created object to all +listeners. -Once a module resolver listener has resolved the module name to an object, the module manager then -triggers this event, passing the newly created object to all listeners. - -#### mergeConfig (ModuleEvent::EVENT\_MERGE\_CONFIG) +### mergeConfig (`ModuleEvent::EVENT_MERGE_CONFIG`) After all modules have been loaded, the `mergeConfig` event is triggered. By default, `Zend\ModuleManager\Listener\ConfigLister` listens on this event at priority 1000, and merges all configuration. You may attach additional listeners to this event in order to manipulate the merged -configuration. See [the tutorial on manipulating merged -configuration](tutorials.config.advanced.manipulating-merged-configuration) for more information. +configuration. See [the tutorial on manipulating merged configuration](http://framework.zend.com/manual/current/en/tutorials/config.advanced.html#manipulating-merged-configuration) +for more information. -#### loadModules.post (ModuleEvent::EVENT\_LOAD\_MODULES\_POST) +### loadModules.post (`ModuleEvent::EVENT_LOAD_MODULES_POST`) -This event is triggered by the module manager to allow any listeners to perform work after every -module has finished loading. For example, the default configuration listener, -`Zend\ModuleManager\Listener\ConfigListener` (covered later), attaches to this event to merge -additional user-supplied configuration which is meant to override the default supplied -configurations of installed modules. +This event is triggered by the module manager to allow any listeners to perform +work after every module has finished loading. For example, the default +configuration listener, `Zend\ModuleManager\Listener\ConfigListener` (covered +later), attaches to this event to merge additional user-supplied configuration +which is meant to override the default supplied configurations of installed +modules. ## Module Manager Listeners -By default, Zend Framework provides several useful module manager listeners. - -### Provided Module Manager Listeners +By default, Zend Framework provides several useful module manager listeners. All +shipped listeners are in the `Zend\ModuleManager\Listener` namespace. -#### Zend\\ModuleManager\\Listener\\DefaultListenerAggregate +### DefaultListenerAggregate -To help simplify the most common use case of the module manager, ZF2 provides this default aggregate -listener. In most cases, this will be the only listener you will need to attach to use the module -manager, as it will take care of properly attaching the requisite listeners (those listed below) for -the module system to function properly. +To address the most common use case of the module manager, ZF2 provides +this default aggregate listener. In most cases, this will be the only listener +you will need to attach to use the module manager, as it will take care of +properly attaching the requisite listeners (those listed below) for the module +system to function properly. -#### Zend\\ModuleManager\\Listener\\AutoloaderListener +### AutoloaderListener This listener checks each module to see if it has implemented -`Zend\ModuleManager\Feature\AutoloaderProviderInterface` or simply defined the -`getAutoloaderConfig()` method. If so, it calls the `getAutoloaderConfig()` method on the module -class and passes the returned array to `Zend\Loader\AutoloaderFactory`. +`Zend\ModuleManager\Feature\AutoloaderProviderInterface` or defined the +`getAutoloaderConfig()` method. If so, it calls the `getAutoloaderConfig()` +method on the module class and passes the returned array to +`Zend\Loader\AutoloaderFactory`. -#### Zend\\ModuleManager\\Listener\\ModuleDependencyCheckerListener +### ModuleDependencyCheckerListener -This listener checks each module to verify if all the modules it depends on were loaded. When a -module class implements `Zend\ModuleManager\Feature\DependencyIndicatorInterface` or simply has a -defined `getModuleDependencies()` method, the listener will call `getModuleDependencies()`. Each of -the values returned by the method is checked against the loaded modules list: if one of the values -is not in that list, a `Zend\ModuleManager\Exception\MissingDependencyModuleException` is be thrown. +This listener checks each module to verify if all the modules it depends on were +loaded. When a module class implements +`Zend\ModuleManager\Feature\DependencyIndicatorInterface` or has defined the +`getModuleDependencies()` method, the listener will call +`getModuleDependencies()`. Each of the values returned by the method is checked +against the loaded modules list: if one of the values is not in that list, a +`Zend\ModuleManager\Exception\MissingDependencyModuleException` is thrown. -#### Zend\\ModuleManager\\Listener\\ConfigListener +### ConfigListener If a module class has a `getConfig()` method, or implements -`Zend\ModuleManager\Feature\ConfigProviderInterface`, this listener will call it and merge the -returned array (or `Traversable` object) into the main application configuration. +`Zend\ModuleManager\Feature\ConfigProviderInterface`, this listener will call it +and merge the returned array (or `Traversable` object) into the main application +configuration. -#### Zend\\ModuleManager\\Listener\\InitTrigger +### InitTrigger -If a module class either implements `Zend\ModuleManager\Feature\InitProviderInterface`, or simply -defines an `init()` method, this listener will call `init()` and pass the current instance of -`Zend\ModuleManager\ModuleManager` as the sole parameter. +If a module class either implements `Zend\ModuleManager\Feature\InitProviderInterface`, +or defines an `init()` method, this listener will call `init()` and pass the +current instance of `Zend\ModuleManager\ModuleManager` as the sole parameter. -Like the `OnBootstrapListener`, the `init()` method is called for **every** module implementing this -feature, on **every** page request and should **only** be used for performing **lightweight** tasks -such as registering event listeners. +Like the `OnBootstrapListener`, the `init()` method is called for **every** +module implementing this feature, on **every** page request and should **only** +be used for performing **lightweight** tasks such as registering event +listeners. -#### Zend\\ModuleManager\\Listener\\LocatorRegistrationListener +### LocatorRegistrationListener -If a module class implements `Zend\ModuleManager\Feature\LocatorRegisteredInterface`, this listener -will inject the module class instance into the `ServiceManager` using the module class name as the -service name. This allows you to later retrieve the module class from the `ServiceManager`. +If a module class implements `Zend\ModuleManager\Feature\LocatorRegisteredInterface`, +this listener will inject the module class instance into the `ServiceManager` +using the module class name as the service name. This allows you to later +retrieve the module class from the `ServiceManager`. -#### Zend\\ModuleManager\\Listener\\ModuleResolverListener +### ModuleResolverListener -nThis is the default module resolver. It attaches to the "loadModule.resolve" event and simply -returns an instance of `{moduleName}\Module`. +This is the default module resolver. It attaches to the `loadModule.resolve` +event and returns an instance of `{moduleName}\Module`. -#### Zend\\ModuleManager\\Listener\\OnBootstrapListener +### OnBootstrapListener -If a module class implements `Zend\ModuleManager\Feature\BootstrapListenerInterface`, or simply -defines an `onBootstrap()` method, this listener will register the `onBootstrap()` method with the -`Zend\Mvc\Application` `bootstrap` event. This method will then be triggered during the `bootstrap` -event (and passed an `MvcEvent` instance). +If a module class implements +`Zend\ModuleManager\Feature\BootstrapListenerInterface`, or defines an +`onBootstrap()` method, this listener will register the `onBootstrap()` method +with the `Zend\Mvc\Application` `bootstrap` event. This method will then be +triggered during the `bootstrap` event (and passed an `MvcEvent` instance). -Like the `InitTrigger`, the `onBootstrap()` method is called for **every** module implementing this -feature, on **every** page request, and should **only** be used for performing **lightweight** tasks -such as registering event listeners. +Like the `InitTrigger`, the `onBootstrap()` method is called for **every** +module implementing this feature, on **every** page request, and should **only** +be used for performing **lightweight** tasks such as registering event +listeners. -#### Zend\\ModuleManager\\Listener\\ServiceListener +### ServiceListener -If a module class implements `Zend\ModuleManager\Feature\ServiceProviderInterface`, or simply -defines an `getServiceConfig()` method, this listener will call that method and aggregate the return -values for use in configuring the `ServiceManager`. +If a module class implements `Zend\ModuleManager\Feature\ServiceProviderInterface`, +or defines an `getServiceConfig()` method, this listener will call that method +and aggregate the return values for use in configuring the `ServiceManager`. -The `getServiceConfig()` method may return either an array of configuration compatible with -`Zend\ServiceManager\Config`, an instance of that class, or the string name of a class that extends -it. Values are merged and aggregated on completion, and then merged with any configuration from the -`ConfigListener` falling under the `service_manager` key. For more information, see the +The `getServiceConfig()` method may return either an array of configuration +compatible with `Zend\ServiceManager\Config`, an instance of that class, or the +string name of a class that extends it. Values are merged and aggregated on +completion, and then merged with any configuration from the `ConfigListener` +falling under the `service_manager` key. For more information, see the `ServiceManager` documentation. -Unlike the other listeners, this listener is not managed by the `DefaultListenerAggregate`; instead, -it is created and instantiated within the `Zend\Mvc\Service\ModuleManagerFactory`, where it is -injected with the current `ServiceManager` instance before being registered with the `ModuleManager` +Unlike the other listeners, this listener is not managed by the `DefaultListenerAggregate`; +instead, it is created and instantiated within the +`Zend\Mvc\Service\ModuleManagerFactory`, where it is injected with the current +`ServiceManager` instance before being registered with the `ModuleManager` events. -Additionally, this listener manages a variety of plugin managers, including [view -helpers](zend.view.helpers), [controllers](zend.mvc.controllers), and -[controller plugins](zend.mvc.controller-plugins). In each case, +Additionally, this listener manages a variety of plugin managers, including +[view helpers](https://github.com/zendframework/zend-view), +[controllers](https://zendframework.github.io/zend-mvc/controllers/), and +[controller plugins](https://zendframework.github.io/zend-mvc/plugins/). In each case, you may either specify configuration to define plugins, or provide configuration via a `Module` class. Configuration follows the same format as for the `ServiceManager`. The following table outlines the plugin managers that may be configured this way (including the `ServiceManager`), the @@ -147,8 +160,8 @@ configuration key to use, the `ModuleManager` feature interface to optionally im interfaces specified live in the `Zend\ModuleManager\Feature` namespace) , and the module method to optionally define to provide configuration. -Plugin Manage | Config Key | Interface | Module Method ---------------|------------|-----------|-------------- +Plugin Manager | Config Key | Interface | Module Method +---------------|------------|-----------|-------------- `Zend\Mvc\Controller\ControllerManager` | `controllers` | `ControllerProviderInterface` | `getControllerConfig` `Zend\Mvc\Controller\PluginManager` | `controller_plugins` | `ControllerPluginProviderInterface` | `getControllerPluginConfig` `Zend\Filter\FilterPluginManager` | `filters` | `FilterProviderInterface` | `getFilterConfig` @@ -163,14 +176,14 @@ Plugin Manage | Config Key | Interface | Module Method `Zend\Log\ProcessorPluginManager` | `log_processors` | `LogProcessorProviderInterface` | `getLogProcessorConfig` `Zend\Log\WriterPluginManager` | `log_writers` | `LogWriterProviderInterface` | `getLogWriterConfig` -Configuration follows the examples in the ServiceManager [configuration -section](zend.service-manager.quick-start.md#config). As a brief recap, the following -configuration keys and values are allowed: +Configuration follows the examples in the ServiceManager +[configuration section](https://zendframework.github.io/zend-servicemanager/configuring-the-service-manager/). +As a brief recap, the following configuration keys and values are allowed: Config Key | Allowed values -----------|--------------- `services` | service name/instance pairs (these should likely be defined only in `Module` classes -`invokables` | service name/class name pairs of classes that may be invoked without constructor arguments +`invokables` | service name/class name pairs of classes that may be invoked without constructor arguments (deprecated with zend-servicemanager v3; use the `InvokableFactory` instead) `factories` | service names pointing to factories. Factories may be any PHP callable, or a string class name of a class implementing `Zend\ServiceManager\FactoryInterface`, or of a class implementing the `__invoke` method (if a callable is used, it should be defined only in `Module` classes) `abstract_factories` | array of either concrete instances of `Zend\ServiceManager\AbstractFactoryInterface`, or string class names of classes implementing that interface (if an instance is used, it should be defined only in `Module` classes) `initializers` | array of PHP callables or string class names of classes implementing `Zend\ServiceManager\InitializerInterface` (if a callable is used, it should be defined only in `Module` classes) @@ -182,20 +195,37 @@ the `getServiceLocator()` method, as in the following example: ```php public function getViewHelperConfig() { - return array('factories' => array( + return ['factories' => [ 'foo' => function ($helpers) { - $services = $helpers->getServiceLocator(); - $someService = $services->get('SomeService'); + $container = $helpers->getServiceLocator(); + $someService = $container->get('SomeService'); $helper = new Helper\Foo($someService); return $helper; }, - )); + ]]; } ``` -This is a powerful technique, as it allows your various plugins to remain agnostic with regards to -where and how dependencies are injected, and thus allows you to use Inversion of Control principals -even with plugins. - - +This is a powerful technique, as it allows your various plugins to remain +agnostic with regards to where and how dependencies are injected, and thus +allows you to use Inversion of Control principals even with plugins. + +> #### Factories with zend-servicemanager v3 +> +> Starting in the v3 releases of zend-servicemanager, factories invoked by +> plugin managers now receive the *parent* container, and not the plugin manager +> itself. You can write your factories under v2, and prepare them for v3, by +> testing the incoming argument to see if it is a plugin manager: +> +> ```php +> use Zend\SserviceManager\AbstractPluginManager; +> +> function ($container) { +> $container = $container instanceof AbstractPluginManager +> ? $container->getServiceLocator() +> : $container; +> +> // create instance with dependencies pulled from app container... +> } +> ``` From e4eb34953abf1a3d17b51933b8bca790d155f43d Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 9 May 2016 17:56:37 -0500 Subject: [PATCH 09/10] Added EOL to mkdocs.yml Ensures build will work --- mkdocs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index c40b1f8..876a336 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,4 +11,5 @@ pages: site_name: zend-modulemanager site_description: zend-modulemanager repo_url: 'https://github.com/zendframework/zend-modulemanager' -copyright: 'Copyright (c) 2016 Zend Technologies USA Inc.' \ No newline at end of file +copyright: 'Copyright (c) 2016 Zend Technologies USA Inc.' + From 26cdc6d22cf539ccf7fa5533ec48dedfe8dfa578 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Mon, 9 May 2016 17:59:04 -0500 Subject: [PATCH 10/10] Added CHANGELOG for #38 --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5083f64..c29efd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ All notable changes to this project will be documented in this file, in reverse ### Added -- Nothing. +- [#38](https://github.com/zendframework/zend-modulemanager/pull/38) prepares + and publishes the documentation to https://zendframework.github.io/zend-modulemanager/ ### Deprecated