Release Notes for Agavi 1.0.7

AGAVI RELEASE NOTES
===================

Version 1.0.7 - December 22, 2011
=================================

The getCredentials() method on an Action is no longer called unconditionally (i.e. whether or not the isSecure() method returned false) but only if the Action is "secure".

It is now possible to manually call shutdown() on any database adapter to close the underlying connection; another call to getConnection() will cause a reconnect.

AgaviFormPopulationFilter will now populate multiple forms in the order specified in the "populate" request attribute (when populating via an array with form IDs as keys and parameter holders as values) in namespace "org.agavi.filter.FormPopulationFilter"); however, if the value for a key in the "populate" array is boolean true (to re-populate from request data), this form will always be handled first, so error messages are inserted on that form first.

Testing is now compatible with both PHPUnit 3.5 and 3.6. If you want to specify code coverage filters, AgaviTesting::getCodeCoverageFilter() returns the correct instance (singleton or not depending on the PHPUnit version) for you to use. A base constraint class named "AgaviBaseConstraintBecausePhpunitSucksAtBackwardsCompatibility" can be used for constraints that work with both PHPUnit 3.5 and 3.6; if you implement the new matches() method introduced in PHPUnit 3.6 instead of the old evaluate(), it will automatically be called in the proper fashion depending on the PHPUnit version.

AgaviTesting::dispatch() can now call exit() with the appropriate shell status code (the same as returned by a vanilla PHPUnit run) to indicate success or failures/errors to the calling process. This behavior is triggered when the new optional second argument, defaulting to false, is set to true. If set to false, it returns the PHPUnit result object that may be used by custom code to perform further analysis of the test run.

Several other minor changes and fixes are included in this release as well; most notably, AgaviBooleanValidator's casting and exporting logic has been repaired, and AgaviConsoleRequest now properly creates an AgaviUploadedFile object with STDIN contents (when configured to read those) instead of a plain array. The PHPTAL renderer now supports configuration of character encoding via parameter "encoding".

The timezone database was updated to version 2011n.


Version 1.0.6 - July 23, 2011
=============================

This release adds a database adapter for Doctrine 2, a renderer for the Twig template engine, a native session storage for ext/sqlsrv and various enhancements such as support for Smarty 3 in the existing renderer and extended configuration abilities for the Doctrine 1 database adapter.

Doctrine 2 support was added, both for the ORM (AgaviDoctrine2ormDatabase) and the DBAL (AgaviDoctrine2dbalDatabase) libraries. The ORM adapter can optionally utilize a pre-configured DBAL connection instead of specifying connection details itself. Both adapters allow for easy extensibility with custom logic by exposing a prepareConfiguration() and a prepareEventManager() method that can be used to customize the configuration and the event manager, respectively. The API documentation for both classes contains a detailed list of all options; a typical ORM adapter configuration would look similar to this:
<database name="master" class="AgaviDoctrine2ormDatabase">
	<ae:parameter name="connection">
		<ae:parameter name="driver">pdo_mysql</ae:parameter>
		<ae:parameter name="host">127.0.0.1</ae:parameter>
		<ae:parameter name="user">root</ae:parameter>
		<ae:parameter name="dbname">test</ae:parameter>
	</ae:parameter>
	<ae:parameter name="configuration">
		<ae:parameter name="metadata_driver_impl_argument">%core.model_dir%/Entities</ae:parameter>
	</ae:parameter>
</database>
An example cli-config.php file demonstrating how to integrate Agavi with the Doctrine command line utilities can be found in etc/database/doctrine2.

The database adapter for Doctrine 1 now allows basic configuration of cache drivers for result and query caches, and added the ability to specify the class to use as the connection event listener - this allows a custom implementation to be used, where more advanced logic can be executed in the preConnect() event handler method, which is useful for modifying the connection or manager objects in ways not supported through configuration options.

It is now possible to use ext/sqlsrv as a session storage via AgaviSqlsrvSessionStorage as an alternative to interfacing with SQL Server via PDO. The session table's data column must be of type "varbinary".

The Twig template engine is supported through AgaviTwigRenderer; includes and inheritance lookups are performed on the current directory first by default before falling back to the main template directory. The lookup sequence is configurable. The renderer will also attempt to load a localized template from a locale subdirectory first before picking a generic one if the template that initiated the include or extension was a localized template.

AgaviSmartyRenderer received minor adjustments to support Smarty 3 without triggering deprecation notices.

The Sample App now uses the regular "web" context to serve the WSDL for the product service; the WSDL contents can now be retrieved through the URL "/products.wsdl".

The timezone database was updated to version 2011h.


Version 1.0.5 - June 16, 2011
=============================

This release improves the robustness of AgaviFormPopulationFilter especially for XHTML and HTML5, and fixes several issues. The database adapters for ext/mysql, ext/mysqli and ext/pdo (when used with MySQL connections) now also prevent potentially unsafe setting of connection encodings.

PHPUnit 3.5 is now supported. Due to breaking changes in PHPUnit, it was unavoidable to drop support for PHPUnit 3.4. Application tests are unaffected; the only file requiring changes is run-tests.php, where calls to PHPUnit_Util_Filter::addDirectoryToFilter() must be replaced with PHP_CodeCoverage_Filter::getInstance()->addDirectoryToBlacklist().

AgaviFormPopulationFilter can now recover from various non-fatal parse errors, such as unknown tags or malformed markup in HTML parsing mode, and undefined entities in XML parsing mode.
This marks an end to issues with non-XML entities like "&nbsp;" in XML parsing mode, and allows the use of HTML5 elements (which libxml does not know yet) in HTML parsing mode (i.e. without using the XML serialization of HTML5).
Instead of a boolean true or false, the configuration parameter "ignore_parse_errors" now takes the possible values "LIBXML_ERR_NONE" (equivalent to boolean false), "LIBXML_ERR_WARNING" (quite useless), "LIBXML_ERR_ERROR" (the new default) and "LIBXML_ERR_FATAL" (equivalent to boolean true). FPF will suppress errors and continue operation if the errors encountered during parsing do not exceed the configured maximum ignore level. In the event of a fatal error, such as malformed markup in XML parsing mode, FPF will silently abort execution if "LIBXML_ERR_FATAL" is configured, as fatal errors are not recoverable. In all other cases, FPF will throw an exception or recover from the error, depending on the configured ignore level and the highest error level encountered during parsing.
The new default ignore level "LIBXML_ERR_ERROR" means that users will see significantly fewer errors during development; it also means, however, that in HTML parsing mode in particular, well-formedness errors may remain unnoticed. For this reason, FPF will continue to log errors (if logging is enabled), and map the error level of the parse error (LIBXML_ERR_WARNING, LIBXML_ERR_ERROR or LIBXML_ERR_FATAL) to the error level of the logging system (AgaviILogger::WARN, AgaviILogger::ERROR or AgaviILogger::FATAL). As a consequence, the "logging_severity" configuration parameter has been removed.

AgaviZendclouddocumentserviceDatabase is a database adapter for Zend Framework's Zend_Cloud_DocumentService. It has a convenience interface mirroring most of the Zend_Cloud_DocumentService_Adapter functions in such a way that the collection/domain/database name does not have to be passed to every call. The collection name can then be configured in databases.xml.

AgaviMysqlDatabase, AgaviMysqliDatabase and AgaviPdoDatabase now throw errors when attempting to use a statement like "SET NAMES utf8" as an initialization query, since the respective client libraries (libmysql or mysqlnd) will not be aware of this changed character set. For the usual connection encodings like "latin1" or "utf8", this is not a problem, but in combination with multi-byte character sets that use bytes without the most significant bit set in multi-byte character sequences (such as GBK or Big5), this may result in incorrectly quoted strings, which could ultimately result in vulnerabilities in applications.
For AgaviMysqlDatabase and AgaviMysqliDatabase, the simple fix is to remove the "SET NAMES" query from "init_queries" and use the new option "charset" instead. For AgaviPdoDatabase, a similar approach (specifying the charset in the DSN) works for PHP version 5.3.6 and newer, but in older versions of PHP, the PDO MySQL driver ignores the "charset" option in the DSN. If your my.cnf configuration file specifies "latin1" and you simply switch to UTF-8 using "SET NAMES utf8", this is no problem, but for some charsets, this may result in the quoting issues mentioned above. This is why AgaviPdoDatabase requires you to set "warn_mysql_charset" to false in such environments. With this flag explicitly disabled, it will also be possible to use "SET NAMES" init queries again, but be advised that this is at your own risk. You may mitigate the risks by using native prepared statements (disable PDO::ATTR_EMULATE_PREPARES), but this will not affect calls to PDO::quote() or prepared statements where this flag has been overridden.

Passing an empty string as the scheme in the options array when generating a URL with AgaviWebRouting will now produce a protocol-relative URL starting with "//". This is useful for generated content embedded by third party sites that use both normal and secured HTTP transports.

AgaviMysqlSessionStorage and AgaviPdoSessionStorage have improved update and insert behaviors for MySQL that should eliminate occasional non-critical "exception thrown without a stack frame" errors on shutdown when no session data (including the timestamp) was modified.

AgaviCreoleDatabase, AgaviCreoleSessionStorage and support for Propel versions older than 1.3 in AgaviPropelDatabase have been marked deprecated and are slated for removal in Agavi 1.1.

The recommended URL rewrites in Apache .htaccess files have been adjusted once more to disable the DirectorySlash directive.

X-Forwarded-Proto style HTTPS indicators as used on Amazon's Elastic Load Balancers are now supported for the "HTTPS" data source key in AgaviWebRequest.

The timezone database has been updated to 2011g.


Version 1.0.4 - December 19, 2010
=================================

This release adds support for the Windows Azure platform and brings a couple of enhancements.

Azure support consists of support for IIS7 as a web server in AgaviWebRouting and AgaviWebRequest, AgaviSqlsrvDatabase as a database adapter for ext/sqlsrv (to access SQL Server 2010 and SQL Azure), and AgaviWindowsazureSessionStorage for storing sessions in the cloud.
To run an Agavi application on Azure, you need to follow three simple steps.
1) adjust app/config/factories.xml to configure a different storage class (for sessions). An example can be found in http://trac.agavi.org/ticket/1266.
2) instruct AgaviWebRequest to use fixed values for the server port and (at least for production) server name. This is because Azure instances run behind a load balancer that doesn't forward the necessary request details in additional headers. An example can be found in http://trac.agavi.org/ticket/1265.
3) edit web.config (in your WebRole root) to rewrite all requests to the pub/ subdirectory and correctly dispatch Agavi with the requested path. An example can be found in http://trac.agavi.org/ticket/1265.
Example configurations for AgaviSqlsrvDatabase can be found in http://trac.agavi.org/ticket/1264. Ticket http://trac.agavi.org/ticket/1265 also contains an example for plain IIS7 deployments without Windows Azure, where unlike in an Azure deployment, you can set the document root for a site to pub/.

The new AgaviXsltRenderer takes the inner content of the rendering process as its input document and transforms it using the given XSLT stylesheet. That means that you should return the document you would like to transform from your view. By default, the renderer creates an envelope document containing wrappers for the inner document as well as for the slots. In many cases though, you want to use XSLT only for the content layer to transform some XML document (e.g. as returned from a Web service), and use regular PHP templates for the other layers. In these cases, you can tell the renderer to deliver the original input document straight to the XSL template by setting the "envelope" parameter on the renderer to false. http://trac.agavi.org/ticket/1265 has more details and examples on how to use AgaviXsltRenderer.

AgaviDoctrineDatabase now uses Doctrine event listeners to set the configured charset and run the configured initialization queries after Doctrine opened a connection; this will prevent Doctrine from always connecting on initialization of the adapter if either a charset or init queries are configured.

AgaviLoggerMessage now uses "message" and "level" as the internal parameter names. AgaviPassthruLoggerLayout can be configured to return the raw message contents, a specific parameter from the message object or the full object. AgaviJsonLoggerLayout encodes all message parameters as a JSON string, and AgaviScribeLoggerAppender logs to Facebook Scribe or a compatible Thrift interface like Cloudera Flume.

AgaviBooleanValidator is new, and AgaviRegexValidator now allows the extraction of matched subpatterns.

The default .htaccess file containing rewrite rules to remove the "index.php" portion from the URL on Apache web servers has been improved.

PHPUnit is no longer bundled; please install PHPUnit via PEAR. Only PHPUnit 3.4.x is supported at this point.

The timezone database has been updated to 2010o.

For a complete list of changes and fixes, please refer to the CHANGELOG.


Version 1.0.3 - April 16, 2010
==============================

This maintenance release fixes a number of issues over Agavi 1.0.2 and features a few minor enhancements.

Several issues and inconsistencies have been fixed in AgaviNumberValidator and AgaviDecimalFormatter::parse(). Parsing behavior is now consistent with the NumberFormatter implementations of ICU and ext/intl. No integer overflow occurs when checking against min and max values, and the validator accepts non-strings as input. Exporting of the validated value is now possible, in which case the original argument is not mutated. Please note that the "number" validator shortcut definition specifies "int" as the default value for the "type" parameter. No value for "type" will automatically lead to integer or float values, depending on the size of the number in the input string. A cast to the specified type is now automatically performed if no "cast_to" parameter is given.

All file validators now perform case-insensitive checks against the list of allowed file extensions, which may now also be a parameter array instead of a space-separated list of values.

This release bumps the minimum required version of Phing to 2.4.0; this was necessary to fix some bugs with the build system that were next to impossible to fix for both 2.3 and 2.4 (which drastically changed some internals structures) at the same time.

An issue relating to the behavior of DOM in PHP 5.1.12 and PHP 5.2.3 has been addressed. Running Agavi 1.0.3 might be necessary under certain circumstances when using these versions of PHP.

A couple of minor fixes have been made to the routing; most notably, overwriting of routes in other <ae:configuration> blocks now always works as expected, even when using implied routes.

Some default code templates have been updated; most notably, caching configuration files now explicitly disable caching, as otherwise, Actions that do not use a View would be cached automatically.

The timezone database has been updated to version 2010h.

For a full list of changes, please refer to the CHANGELOG.


Version 1.0.2 - January 27, 2010
================================

This maintenance release fixes a number of issues over Agavi 1.0.1 and brings a couple of minor enhancements.

Important enhancements and changes:
- Support for HTML 5 forms in AgaviFormPopulationFilter.
- Support for Doctrine 1.2.
- Support for Propel 1.4.
- Support for Phing 2.4.0.
- Support for PHPTAL 1.2.
- Optional strict comparison of elements in AgaviInarrayValidator and AgaviEqualsValidator.
- Validator shortcut "arraylength" now defaults to minimum of one element.
- Routing callback parameters are now set before initialize method is called.
- Lots of ICU bugfix and change backports to the date and translation system. As a result, custom time zones now have identifiers like "GMT+0200".
- Support for PHP 5.3 namespaces in all configuration files.
- AgaviValidator::getArgument() now accepts an argument identifier.

The following fixes are worth mentioning:
- AgaviArraylengthValidator didn't work with files.
- AgaviValidationManager::clear() didn't clear validation errors.
- Multiple settings blocks and settings prefixes were not allowed in module configs.
- Several ICU bugfixes have been ported.
- Validation used to drop the first element when exporting multi-dimensional arrays.
- Configuration parameter values containing only whitespace are now converted to NULL instead of an empty string.
- FPF will now discard empty error messages.

Due to changes in Doctrine 1.2 that broke backwards compatibility without prior notice, attribute names and values must now be specified using fully qualified constant names, for example:
<ae:parameter name="attributes">
  <ae:parameter name="Doctrine_Core::ATTR_PORTABILITY">Doctrine_Core::PORTABILITY_RTRIM</ae:parameter>
</ae:parameter>
The new model autoloading modes are also supported, as are extensions.

For Propel 1.4, the format of the keys for the "overrides" parameter has changed. It's now mandatory to use Propel's internal config syntax with the full parameter name. Examples
<ae:parameter name="overrides">
  <ae:parameter name="datasources.bookstore.connection.dsn">pgsql:...</ae:parameter>
  <ae:parameter name="classmap.Zomg">path/to/Zomg</ae:parameter>
  <ae:parameter name="datasources.bookstore.connection.attributes.ATTR_EMULATE_PREPARES.value">false</ae:parameter>
</ae:parameter>
This new approach is much more forward compatible and allows for more control over the overrides; for instance, the ATTR_EMULATE_PREPARES setting above was not possible before.
For older Propel versions, the old-style syntax still applies:
<ae:parameter name="overrides">
  <ae:parameter name="connection">
    <ae:parameter name="dsn">pgsql:...</ae:parameter>
  </ae:parameter>
  <ae:parameter name="classes">
    <ae:parameter name="Zomg">path/to/Zomg</ae:parameter>
  </ae:parameter>
</ae:parameter>

Bundle updates:
- The timezone database has been updated to version 2010b.
- PHPUnit has been updated to version 3.4.2.
- ISO Schematron has been updated to the final version 2010-01-25.

Please refer to CHANGELOG for a full list of changes.


Version 1.0.1 - May 1, 2009
===========================

This maintenance release fixes a number of issues over Agavi 1.0.0 and brings a couple of minor enhancements.

The following are worth mentioning:
- Most notable, a race condition in configuration file compilation was fixed that could lead to corrupt compiled files on disk.
- Arrays that failed validation are now always purged correctly from request data.
- Exporting values from validators with argument bases is now possible, and it's possible to control the exact use of keys in the process.
- Caching callbacks in the Execution Filter are now passed the current Execution Container as last argument.
- It's now possible to set session_cache_expire(), session_cache_limiter() and session_module_name() through configuration.
- Support for document/literal wrapped style SOAP services has been improved.
- Two regressions related to AgaviRoutingCallback::onGenerate() have been fixed.
- A memory leak in AgaviTranslationManager::getLocaleIdentifier() was fixed.
- Handling of slashes and dots in Action, View and Model names has been unified - slashes are now always used internally.
- The bundled timezone database was updated to version 2009i.
- Several other minor fixes and enhancements.

As usual, please check the CHANGELOG for a complete list of changes.


Version 1.0.0 - Feburary 25, 2009
=================================

The following is a brief summary of the most important changes in this release. For a full list of new features, changes and bugfixes, please refer to the CHANGELOG.

Also, please pay special attention to the list of deprecated elements at the end of this description.

ATTENTION: Some bugfixes caused changes to internal behavior. Make absolutely sure that your application is ready for an upgrade to 1.0 by reading the UPGRADING document.

Configuration
-------------
A new configuration subsystem that natively deals with XML files replaces the current implementation. This has numerous advantages; for instance, Agavi now supports any number of XML Schema (including XML Schema Instance declarations), RELAX NG or Schematron files to be validated against config files or merged result documents in several different stages, can apply XSL transformations (including those declared in <?xml-stylesheet?> PIs) and has extended namespaces support that allow backwards-compatibility to old config files in future versions.
New-style configuration handlers extending AgaviXmlConfigHandler are now given a single AgaviXmlConfigDomDocument (extends DOMDocument) instance to work on, which already holds only the relevant <configuration> blocks in the correct order. Together with other subclasses of ext/dom classes, it provides several convenience methods to ease the processing of configuration files, but of course, all capabilities of DOM, including XPath, are usable inside configuration handlers.
Backwards compabibility requires PHP's XSL extension enabled; other than that, everything still works as usual. Old-style configuration file handlers are still supported (but deprecated), but don't support the new features explained above.
Also, the namespaces of configuration files have been changed, with envelope namespaces (<configurations> and other elements) decoupled from the actual config content namespaces. Again, backwards compatibility is maintained, but you should upgrade your configuration files when moving to 1.0 in order to be able to fully leverage all features and make future transitions easier.
Of note, the legacy support for configuration files with no namespace at all (just <configurations>) has been dropped completely, so your files at the very least have to be in the global 0.11 namespace (http://agavi.org/agavi/1.0/config).
Two built-in configuration handlers have not been ported to the new infrastructure: AgaviLdmlConfigHandler (to be migrated together with a future update to Unicode CLDR v1.7) and AgaviReturnArrayConfigHandler (will remain old-style for the time being; a more flexible replacement is planned for Agavi 1.1). The latter means that your custom configuration files need to remain entirely in the old http://agavi.org/agavi/1.0/config namespace; several features exclusive to the new system such as XSL transformations or multiple validations will not be available.

Names of compiled configuration files are now different from before; they now consist of the file base name, environment, context, and then a sha1 hash of these three components to make the filename unique. This prevents theoretical situations where configuration file names are ambiguous, and at the same time makes it easier to find a specific file in the cache directory. The files now contain the path to the source file in a header comment so configs with the same base name can be told apart.

Module/Action/View/Model
------------------------
The module.xml configuration file has been redesigned. It now needs a <module enabled="true"> element, and inside, there can be any number of <settings> blocks, which like in settings.xml, can have a "prefix" attribute to change the prefix. In the prefix and in setting names, ${moduleName} is expanded to the current module's name. Specifying the module name inside this configuration file is not necessary anymore.

Every module can now have a config_handlers.xml file.

Models can use the same dot-notation for nesting as Actions, e.g. model Foo.Bar sitting in models/Foo/BarModel.class.php with class name Foo_BarModel

Models and Views from other modules can now be used safely even if those other module have base classes in a local autoload.xml etc.

Actions, Views and Models must now use fully qualified class names, including the module name. Examples:
%core.app_dir%/models/Foo/BarModel.class.php is class Foo_BarModel
%core.app_dir%/modules/Default/models/FooModel.class.php is class Default_FooModel
%core.app_dir%/modules/Default/actions/Foo_BarAction.class.php is class Default_Foo_BarAction
The legacy naming schemes (leaving out module name for Actions, Views and non-global Models; leaving out sub-notation paths except the last one) are not supported anymore.

Finally, you can now define the filesystem structure of the following elements on a per-module basis:
- Actions
- Caching XML configs
- Validation XML configs
- Views
You can also customize these aspects:
- Default template "directory" part
- View shortname resolution ("Success" => "Default_Sub_MarineSuccess")
This allows you to put all the files for a feature into a single subdirectory, instead of having the separate files cluttered over action/, template/, view/ etc. subfolders inside the module directory.
Ticket #668 has more details and an example.

Routing
-------
Large parts of the routing have been rewritten; gen() and execute() have seen the most changes.

Most notably, the encoding of values in the result string has been moved to the very end of the generation process, which has a bunch of nice benefits:
- gen() can now handle objects and arrays as input parameters (__toString() is called on objects unless callbacks do something something more intelligent)
- gen() now wraps all values in AgaviRoutingValue objects, which hold encoding information for the value, as well as for the prefix and postfix (which can now be set this way, too). The object has a fluent interface, and a new instance for use in gen() can be created by calling AgaviRouting::createValue()
- callbacks don't have to do something as stupid as rawurldecode() on a value that should appear literally anymore; instead, it's sufficient to call the routing value's setValueNeedsEncoding() method and passing false.

Furthermore, gen() accepts strings in the form of "+rss" and "-locale", i.e. with leading "+" or "-" signs, in which case this modification will be applied to the list of incoming matched routes (think of it as null+"rss").

This new implementation should be backwards compatible in virtually all cases, especially since AgaviRoutingValue has a __toString() overload now that returns the encoded representation of its value. Setting literal strings into parameter arrays still works as before, but using the routing value object is of course recommended. If you run into BC problems, try implementing the AgaviILegacyRoutingCallback interface in your callback class.

Multiple callbacks per route are now supported. The new configuration schema uses <callback> elements inside the route instead of the "callback" attribute on the <route> element itself. Every callback definition can hold <parameter>s, which are then available inside the callback object (AgaviRoutingCallback now extends AgaviParameterHolder), which should make it easier to write generic and re-usable callbacks.
Callbacks are run in the order they are defined; once an onMatched() callback returns false, onNotMatched() will be called on subsequent callbacks of that route.

Inside a callback's onMatched() and onNotMatched() methods it is now possible to perform any kind of modifications on the execution container directly. Specifically, it is recommended you use AgaviExecutionContainer::setModuleName() and AgaviExecutionContainer::setActionName() inside callbacks instead of modifying the request parameter array from now on, because the "module" and "action" parameters might not be available anymore depending on the setting inside the application (see "Request" below).
The execution container instance passed to the callback now reflects the actual current state of the routing execution, so checks can be performed against values on the container, and containers can be mutated (as mentioned above). As before, developers are advised not to perform any changes on containers or request data in onMatched() methods if the method will return false.
Agavi will now explicitly call onNotMatched() on a routing callback that returned false from onMatched().

You can now return an AgaviResponse object (use AgaviContext::createInstanceFor('response') for convenience) directly from a routing callback's onMatched() or onNotMatched() method. This response will then be handled right away by the Controller, and any kind of execution will be skipped (there isn't even an Execution Container in this case).

Request
-------
By default, the old "module" and "action" request data parameters are not assigned or used anymore, and also do not receive special treatment by the validation system.
To re-enable their use and availability, set the configuration parameter "use_module_action_parameters" to true for the request implementation in factories.xml.

AgaviWebRequest now moves POST data that is not of content type application/x-www-form-urlencoded or multipart/form-data, i.e. any POST data that PHP does not decode already, into a file in the request data.
PUT data of content type application/x-www-form-urlencoded is automatically decoded into request parameters now (can be disabled via config parameter "http_put_decode_urlencoded").
Both of these measures should lower the barrier for implementing RESTful web services even further.

Command Line
------------
Agavi now ships with Request, Routing and Response implementations for console applications. The Sample App has a demonstration implementation using this functionality.

Testing
-------
Agavi 1.0 features an EXPERIMENTAL infrastructure for testing of applications. It supports unit tests, as well as testing fragments of the application such as Actions and Views, and also complete dispatch runs.
This functionality will be constantly modified, improved and refactored until 1.1, so it's very likely that tests written now will not work without modifications in a future version. On the bright side, what matters is *what* you test, and not how you test it, so changing your tests later to comply with the then-stable system will be a comparatively easy effort as 90% of the work (figuring out the test logic, how and what to test, etc.) is already done.

Project development environment
-------------------------------
Agavi 1.0 introduces a new environment for creating and managing Agavi-based projects. This environment effectively replaces the older agavi script and Phing build environment. The new environment is also based on Phing. It adds a few useful features:
- Skeleton projects may be created
- Targets are included for creating views and other project elements
- Project-specific build.xml files are now recognized and targets are automatically imported
- Build files may define objects that act as event listeners for targets, tasks, or build messages

Execution
---------
Execution containers now have their own request method. By default, it is equal to the global request's request method. It can, however, be changed using the last (and new) argument of AgaviController::createExecutionContainer() and the related methods in AgaviExecutionContainer and AgaviView. Like the output type, the request method is carried over from the "parent" container if AgaviExecutionContainer::createExecutionContainer() is used (or the methods in AgaviView, which use this method). You can define a slot's request method using the new "method" attribute of the <slot> element in your output_types.xml layout declarations.

When Agavi does an internal forward, for example to the login "system action" when an action requires authentication, the corresponding information in the "org.agavi.controller.forwards.*" namespaces will now be set on as attributes on the respective containers, in addition to the existing request attributes, which remain for BC.

AgaviController::dispatch() now accepts an Execution Container as an optional second argument. If this argument is used, then the Routing will not execute, and the given container is executed right away. This is most useful for testing purposes, "page controllers" or utility scripts.

Caching
-------
A new cache group source called "callback" has been added. You can use it to specify the name of a method implemented in the respective Action class. The value this callback returns is used as the group key. You can also throw an AgaviUncacheableException from the callback to prevent caching altogether. These two different abilities offer very nice caching capabilities, such as:
- Having a cache variant for the owner of an element, and one for everyone else
- Enabling a cache only for users that are not logged in

The caching system will now call adequate callbacks that users can use together with extensions to checkCache() to implement protection mechanisms against so-called stampedes, race conditions where expired or non-existant caches are tried to be generated by many parallel requests under high load situations, causing the web server to grind to a halt. This is usually only necessary in very high load situations. A reference implementation is to follow.

Security
--------
The check against isSecure() is now performed in the Security Filter, which always runs unconditionally when core.use_security is enabled. This is a bug fix that was made because it would otherwise be impossible to make certain changes to Agavi's authentication model.

Validation
----------
AgaviValidationManager now assumes "strict" mode by default when no "mode" configuration parameter was given. Agavi code templates always shipped with "strict" for production and "conditional" for development.* environments, so you shouldn't be affected at all.
If you rely on the less secure "relaxed" mode being default (which you shouldn't), then you might need to adjust your factories.xml configuration.

A new API for accessing information about the result of a validation run is available through AgaviValidationManager::getReport(). It is vastly more convenient and capable of the previous APIs which have been deprecated. This change also fixes some problems where the validation system could not reliably tell input from different sources apart. The old API has been deprecated.
The primary instrument for accessing validation result information are query objects, which you can retrieve using AgaviValidationReport::createQuery(). They have methods for defining query filter rules (byArgument, byValidator, byMinSeverity, byErrorName), which form a fluent interface. Methods like has(), count() or getErrorMessages() are available to retrieve information from the resulting collection. Please see ticket #1022 for usage examples.

When using new-style validation XML configs, it is necessary to explicitly import Agavi's default definitions of validator shortcuts ("string", "isset" and so on) in %core.agavi_dir%/config/defaults/validators.xml to be able to use them; the most convenient way to achieve this is using the "parent" attribute on the <configurations> element, which also is the approach the build system takes by default. Existing configuration files from the 0.11 namespace are automatically handled this way and thus are not affected.

Validators are not handed a "method" parameter anymore with the request method they should run for. This was extremely redundant since the validators weren't even registered if the request method was "wrong". For manual registering, registerReadValidators(), registerWriteValidators() etc are always used in actions anyway, so no problem here, either. As a result, AgaviValidator::validatesInMethod() is gone, too.

An AgaviArrayLengthValidator has been added.
AgaviDateTimeValidator now accepts strotime() syntax format strings in "min" and "max" parameters, which is most useful for relative date declarations like "+2 weeks" or "last monday this month".

SOAP
----
Agavi can now automatically pack and unpack document/literal wrapped style web service requests and responses if the Controller config parameter "force_document_literal_wrapped_marshalling" is set to true. Future releases of Agavi will enhance this functionality further and add automatic detection for services using this convention.

Multiple SOAP services can now be implemented in the same application. To do this, simply use multiple SOAP contexts of different names. XSD schemas for the generated WSDL documents can remain inside <configurations>, or be put into the relevant <configuration> blocks for each service. The same is valid for the "targetNamespace" attribute or WSDL message definitions.

Sample App
----------
The Sample App has been refactored to a large extent to better reflect recommended coding standards, module organization and use of models.

Filters
-------
An AgaviTidyFilter has been added.

Deprecated elements
-------------------
- The "core.use_routing" configuration directive is now deprecated. Instead, please use <parameter name="enabled"> in factories.xml's <routing> element to control the use of routing on a per-context basis (this is a new feature).
Existing "core.use_routing" directives will be used as a fallback until the directive is removed completely in Agavi 1.1

- AgaviSecureWebRequest has been deprecated. There is no replacement available. It will be removed in Agavi 1.1, but of course, you can continue to use the implementation from an older release.

- AgaviAdodbDatabase has been deprecated. There is no replacement available. It will be removed in Agavi 1.1, but of course, you can continue to use the implementation from an older release.

- Validation severity "none" is now called "silent".

- AgaviException::printStackTrace() is now called AgaviException::render()

- AgaviTranslationManager::getCurrentTimeZone() is now called AgaviTranslationManager::getDefaultTimeZone()

- Several methods in AgaviValidationManager have been deprecated in favor of the new Report object available through AgaviValidationManager::getReport() (see above)

- AgaviValidationError::getMessageIndex() and AgaviValidationError::setMessageIndex() have been renamed to getName() and setName(), respectively.