Merge branch '3.0'

Conflicts:
	admin/css/screen.css
	admin/scss/_forms.scss
	docs/en/changelogs/3.0.0.md
This commit is contained in:
Ingo Schommer 2012-07-05 17:53:25 +02:00
commit 64357a4522
12 changed files with 201 additions and 156 deletions

View File

@ -182,6 +182,7 @@ form.small .field input.text, form.small .field textarea, form.small .field sele
.field .chzn-container-single .chzn-single div b { background-position: 4px 0px; }
.field input.hasDatepicker { width: 50%; max-width: 96px; }
.field input.month, .field input.day, .field input.year { width: 56px; }
.field input.time { width: 64px; }
.field.remove-splitter { border-bottom: none; box-shadow: none; }
/** ---------------------------------------------------- Buttons ---------------------------------------------------- */

View File

@ -244,6 +244,10 @@ form.small .field, .field.small {
input.month, input.day, input.year {
width: ($grid-x * 7);
}
input.time {
width: ($grid-x * 8); // smaller time field, since input is restricted
}
/* Hides borders in settings/access. Activated from JS */
&.remove-splitter {

View File

@ -37,7 +37,8 @@ chdir(dirname($_SERVER['SCRIPT_FILENAME']));
*/
if(isset($_SERVER['argv'][2])) {
$args = array_slice($_SERVER['argv'],2);
$_GET = array();
if(!isset($_GET)) $_GET = array();
if(!isset($_REQUEST)) $_REQUEST = array();
foreach($args as $arg) {
if(strpos($arg,'=') == false) {
$_GET['args'][] = $arg;
@ -47,7 +48,7 @@ if(isset($_SERVER['argv'][2])) {
$_GET = array_merge($_GET, $newItems);
}
}
$_REQUEST = $_GET;
$_REQUEST = array_merge($_REQUEST, $_GET);
}
// Set 'url' GET parameter

View File

@ -409,7 +409,8 @@ function increase_memory_limit_to($memoryLimit = -1) {
// Check hard maximums
$max = get_increase_memory_limit_max();
if($max != -1 && translate_memstring($memoryLimit) > translate_memstring($max)) return false;
if($max && $max != -1 && trANSLATE_MEMSTRING($memoryLimit) > translate_memstring($max)) return false;
// Increase the memory limit if it's too low
if($memoryLimit == -1 || translate_memstring($memoryLimit) > translate_memstring($curLimit)) {

View File

@ -16,8 +16,10 @@
// speed up mysql_connect timeout if the server can't be found
ini_set('mysql.connect_timeout', 5);
// Don't die half was through installation; that does more harm than good
ini_set('max_execution_time', 0);
// Prevent a white-screen-of-death
ini_set('display_errors', 'on');
error_reporting(E_ALL | E_STRICT);

View File

@ -2,17 +2,26 @@
## Overview ##
* New template engine
* New CMS interface design
* Image/Link insertion moved into a modal dialog instead of a sidebar
### CMS
* New CMS interface design more geared towards complex content solutions
* List view for pages (sortable and filterable)
* More powerful media and link insertion (including auto-embedding of external sources)
* Batch actions on site tree moved to an "Edit Tree" view
* "Add pages" dropdown now an "Add new" button which goes to a more descriptive page
* Renaming of sapphire to SilverStripe framework
* FormField classes now have their own HTML templates
* Allow usage of SilverStripe framework without the "cms" module
* "Add pages" shows a dedicated interface with more info about the page type
* CMS JavaScript moved to [jQuery.entwine](https://github.com/hafriedlander/jquery.entwine)
* CMS stylesheets are generated by SCSS to provide more flexible and robust styling
### Framework
* Renaming of "sapphire" to SilverStripe "framework"
* Allow usage of SilverStripe framework without the "cms" module
* New template engine with more powerful syntax
* New ORM layer with expressive and fluent syntax
* New GridField component to replace ComplexTableField
* FormField classes now have their own HTML templates
* Moved functionality to modules: Widget, RestfulServer, SapphireSoapServer, Translatable, IPRestrictions, PageComment, HomepageForDomain
## Detailed change logs ##
The detailed change logs are broken down by pre-release:
@ -29,19 +38,67 @@ The detailed change logs are broken down by pre-release:
## Upgrading ##
### Common Upgrade Tasks
* Rename foder from `sapphire/`to `framework/`, replace own paths with `FRAMEWORK_DIR` (in PHP) or `$ModulePath(framework)` (in templates). Update paths in `.htaccess` or `web.config` ([more](#sapphire-rename))
* Replace `<% control %>` in your templates with `<% loop %>` and `<% with %>` ([more](/reference/templates-upgrading-guide#control))
* Replace `DataObjectSet` with `DataList` or `ArrayList` ([more](#deprecated-classes))
* Rewrite `ComplexTableField` and `DataObjectManager` instances to `GridField`
* Rewrite `Director::redirect()` and `Director::redirectBack()` calls ([more] (#director-static-functions-deprecated-director-redirect-and-director-redirectback-in-particular)
* Use `<MyModel>::get()` rather than `DataObject::get()` ([more](#new-orm-datalist))
* Use new syntax for `DataObjectDecorator::extraStatics` ([more](#extensions))
* Change CMS tab paths from `Root.Content.Main` to `Root.Main`, move some field changes to new `SiteTree->getSettingsFields()` method ([more](#tab-paths))
* Add new modules if using specific core features like Widget, RestfulServer, PageComment or Translatable
### sapphire renamed to framework {#sapphire-rename}
`sapphire` has been renamed to `framework`.
Please ensure the framework now resides in the new folder when upgrading.
Here's a list of steps to check:
The `sapphire` module has been renamed to `framework`. Please ensure the framework now resides in the new folder when upgrading. Here's a list of steps to check:
* Remove your existing `sapphire` directory, and replace with `framework` from the new SilverStripe 3.0 package
* Rename references of `sapphire` to `framework` in `.htaccess`, `web.config` and `/usr/bin/sake` (the last is only necessary if you use `sake`)
* Find and replace any references to `sapphire` in your custom code to `framework`. In your PHP code, you can use the constant `FRAMEWORK_DIR`,
which points to the framework directory, and in the templates you can use `$ModulePath(framework)`
### GridField: Replacement for TableListField and ComplexTableField [gridfield]###
We have a new component for managing lists of objects: The `[GridField](/topics/grid-field)`.
It's a substantial rewrite of the features previously captured by `TableListField`,
`ComplexTableField`, `HasManyComplexTableField` and `ManyManyComplexTableField`.
The legacy fields remain operational for now, although a switch to `GridField` is strongly encouraged,
for stability, interface and performance reasons. The `HasManyComplexTableField` and `ManyManyComplexTableField`
are no longer maintained, for those you do have to make the switch.
The `TableField` class will be deprecated soon, but we don't have an adequate replacement for it yet.
Upgrade example: Record listing
:::php
// before
$field = new TableListField('Companies', 'Company');
$field->setPageSize(20);
// after
$field = new GridField('Companies', null, Company::get());
$field->getConfig()->getComponentByType('GridFieldPaginator')->setItemsPerPage(20);
Upgrade example: Record listing with view/edit interface
:::php
// before
$field = new ComplexTableField($myController, 'Companies', 'Company');
// after
$field = new GridField('Companies', null, Company::get(), GridFieldConfig_RecordEditor::create());
Upgrade example: Relationship editing
:::php
// before
$field = new HasManyComplexTableField($myController, 'MyRelation', 'MyRelationObject');
// after
$field = new GridField('MyRelation', null, $myRecord->MyRelation(), GridFieldConfig_RelationEditor::create());
More information is available in the [GridField documentation](/topics/grid-field).
### Object static functions replaced with new Config class {#new-config}
Static functions for getting a static variable on the `Object` class have been deprecated,
in favour of using the new `Config` class instead.
@ -66,21 +123,17 @@ Note the different options for the third parameter of `get()`:
If you don't set an option, it will get all the values for the static, including inherited ones.
This was previously known as `Object::combined_static()`.
### Director static functions deprecated, Director::redirect() and Director::redirectBack() in particular
### Director static functions deprecated (e.g. redirect() and redirectBack())
`Director::redirect()` and `Director::redirectBack()` are now marked as deprecated.
`Director::redirect()` and `Director::redirectBack()` are now marked as deprecated. If you have a `Controller` instance and need to redirect, call `redirect()` or `redirectBack()` on the instance
instead, e.g. `$controller->redirect()` or `$controller->redirectBack()`. Most of the time, form action handler methods on a controller need only call `$this->redirect()` or `$this->redirectBack()`.
If you have a `Controller` instance and need to redirect, call `redirect()` or `redirectBack()` on the instance
instead, e.g. `$controller->redirect()` or `$controller->redirectBack()`. Most of the time, form action handler
methods on a controller need only call `$this->redirect()` or `$this->redirectBack()`.
Use `Controller::curr()->redirect()` and `Controller::curr()->redirectBack()` if you need to redirect in contexts
where a controller might not be immediately available.
Use `Controller::curr()->redirect()` and `Controller::curr()->redirectBack()` if you need to redirect in contexts where a controller might not be immediately available.
### DataExtension and deprecated extraStatics on extension classes {#extensions}
`DataObjectDecorator` has been renamed to `DataExtension`. Any classes that extend `DataObjectDecorator`
should now extend `DataExtension` instead.
`DataObjectDecorator` has been renamed to `DataExtension`. Please extend this class in case you
have written your own extensions.
`extraStatics()` on extensions is now deprecated.
@ -89,41 +142,36 @@ Instead of using `extraStatics()`, you can simply define static variables on you
If you need custom logic, e.g. checking for a class before applying the statics on the extension,
you can use `add_to_class()` as a replacement to `extraStatics()`.
Given the original `extraStatics` function:
<?php
//...
function extraStatics($class, $extensionClass) {
if($class == 'MyClass') {
return array(
'db' => array(
'Title' => 'Varchar'
:::php
class MyExtension extends Extension {
// before
function extraStatics($class, $extensionClass) {
if($class == 'MyClass') {
return array(
'db' => array(
'Title' => 'Varchar'
);
);
);
}
}
// after
static $db = array(
'Title' => 'Varchar'
);
// advanced syntax
static function add_to_class($class, $extensionClass, $args = null) {
if($class == 'MyClass') {
Config::inst()->update($class, 'db', array(
'Title' => 'Varchar'
));
}
parent::add_to_class($class, $extensionClass, $args);
}
}
This would now become a static function `add_to_class`, and calls `update()` with an array
instead of returning it. It also needs to call `parent::add_to_class()`:
<?php
//...
static function add_to_class($class, $extensionClass, $args = null) {
if($class == 'MyClass') {
Config::inst()->update($class, 'db', array(
'Title' => 'Varchar'
));
}
parent::add_to_class($class, $extensionClass, $args);
}
Alternatively, you can define statics on the extension directly, like this:
<?php
//...
static $db = array(
'Title' => 'Varchar'
);
### New ORM: More flexible and expressive querying via `DataList` {#new-orm-datalist}
@ -166,6 +214,7 @@ for the presence of records, please call the count() method on the `DataList`:
// after
if(!DataObject::get('SiteTree', '"ParentID" = 5')->count()) echo "Page 5 has no children";
Beware that `DataList->remove()` will delete an entry from the database.
See the ["datamodel" documentation](../../topics/datamodel) for more details.
### New ORM: Changes to manipulation of SQL queries {#new-orm-sql-queries}
@ -207,32 +256,10 @@ The abstract `RelationList` class and its implementations `ManyManyList` and `Ha
are replacing the `ComponentSet` API, which is only relevant if you have instanciated these manually.
Relations are retrieved through the same way (e.g. `$myMember->Groups()`).
### New ORM: DataObjectSet->groupBy() changed to GroupedList decorator
:::php
$members = Member::get();
// before
$grouped = $members->groupBy('Surname');
// after
$grouped = GroupedList::create($members)->groupBy('Surname');
### Aggregate changes for partial caching in templates ###
`DataObject::Aggregate()` and `DataObject::RelationshipAggregate()` are now deprecated. To replace your deprecated aggregate calls
in PHP code, you should query with something like `Member::get()->max('LastEdited')`, that is, calling the aggregate on the `DataList` directly.
The same concept applies for replacing `RelationshipAggregate()`, just call the aggregate method on the relationship instead,
so something like `Member::get()->Groups()->max('LastEdited')`.
For partial caching in templates, the syntax `<% cached Aggregate(Page).Max(LastEdited) %>` has been deprecated. The new syntax is similar,
except you use `List()` instead of `Aggregate()`, and the aggregate call `Max()` is now lowercase, as in `max()`.
An example of the new syntax is `<% cached List(Page).max(LastEdited) %>`. Check `DataList` class for more aggregate methods to use.
### `SQLQuery` changes ###
`SQLQuery` has been changed so direct access to internal properties `$from`, `$select`, `$orderby` is
now deprecated.
Instead, there are now methods you can call which allow you to get and set SQL clauses instead.
now deprecated. Instead, there are now methods you can call which allow you to get and set SQL clauses instead.
* `$from` getter is `getFrom()` and setters `setFrom()` and `addFrom()`
* `$select` getter is `getSelect()` and setters `setSelect()` and `addSelect()`
@ -244,23 +271,19 @@ Instead, there are now methods you can call which allow you to get and set SQL c
* `$distinct` getter is `getDistinct()` and setter `setDistinct()`
* `$delete` getter is `getDelete()` and setter `setDelete()`
* `$connective` getter is `getConnective()` and settter `setConnective()`
* `innerJoin()` has been renamed to `addInnerJoin()`
* `leftJoin()` has been renamed to `addLeftJoin()`
### TinyMCE upgraded to 3.5 ###
### Aggregate changes for partial caching in templates ###
TinyMCE has been upgraded to version 3.5.
`DataObject::Aggregate()` and `DataObject::RelationshipAggregate()` are now deprecated. To replace your deprecated aggregate calls
in PHP code, you should query with something like `Member::get()->max('LastEdited')`, that is, calling the aggregate on the `DataList` directly.
The same concept applies for replacing `RelationshipAggregate()`, just call the aggregate method on the relationship instead,
so something like `Member::get()->Groups()->max('LastEdited')`.
This change should be transparent to most people upgrading, but if you're using custom plugins for TinyMCE,
please ensure they are still working correctly with the new version.
If you're upgrading from an SS 3.0 beta, TinyMCE HTML source editor and other popups might be blank.
This is caused by the TinyMCE compressor leaving stale cache files in the system temp folder from an earlier
version.
To resolve this problem, simply delete the `{hash}.gz` files within your temp location (defined by `sys_get_temp_dir()` in PHP.)
These cache files will be regenerated next time the CMS is opened.
For partial caching in templates, the syntax `<% cached Aggregate(Page).Max(LastEdited) %>` has been deprecated. The new syntax is similar,
except you use `List()` instead of `Aggregate()`, and the aggregate call `Max()` is now lowercase, as in `max()`.
An example of the new syntax is `<% cached List(Page).max(LastEdited) %>`. Check `DataList` class for more aggregate methods to use.
### InnoDB driver for existing and new tables on MySQL (instead of MyISAM) [innodb]###
@ -282,12 +305,9 @@ Note: MySQL has made InnoDB the default engine in its [5.5 release](http://dev.m
### Convert::json2array() changes [raw2json]###
Convert JSON functions have been changed to use built-in json PHP functions `json_decode()` and `json_encode()`
Convert JSON functions have been changed to use built-in json PHP functions `json_decode()` and `json_encode()`.
Because `json_decode()` will convert nested JSON structures to arrays as well, this has changed the way it worked,
as before nested structures would be converted to an object instead.
So, given the following JSON input to `Convert::json2array()`:
as before nested structures would be converted to an object instead. So, given the following JSON input to `Convert::json2array()`:
{"Joe":"Bloggs","Tom":"Jones","My":{"Complicated":"Structure"}}
@ -311,47 +331,6 @@ Now in SilverStripe 3.x, nested structures are arrays:
)
)
### GridField: Replacement for TableListField and ComplexTableField [gridfield]###
We have a new component for managing lists of objects: The `[GridField](/topics/grid-field)`.
It's a substantial rewrite of the features previously captured by `TableListField`,
`ComplexTableField`, `HasManyComplexTableField` and `ManyManyComplexTableField`.
The legacy fields remain operational for now, although a switch to `GridField` is strongly encouraged,
for stability, interface and performance reasons. The `HasManyComplexTableField` and `ManyManyComplexTableField`
are no longer maintained, for those you do have to make the switch.
The `TableField` class will be deprecated soon, but we don't have an adequate replacement for it yet.
Upgrade example: Record listing
:::php
// before
$field = new TableListField('Companies', 'Company');
$field->setPageSize(20);
// after
$field = new GridField('Companies', null, Company::get());
$field->getConfig()->getComponentByType('GridFieldPaginator')->setItemsPerPage(20);
Upgrade example: Record listing with view/edit interface
:::php
// before
$field = new ComplexTableField($myController, 'Companies', 'Company');
// after
$field = new GridField('Companies', null, Company::get(), GridFieldConfig_RecordEditor::create());
Upgrade example: Relationship editing
:::php
// before
$field = new HasManyComplexTableField($myController, 'MyRelation', 'MyRelationObject');
// after
$field = new GridField('MyRelation', null, $myRecord->MyRelation(), GridFieldConfig_RelationEditor::create());
More information is available in the [GridField documentation](/topics/grid-field).
### New template engine [templates]###
The template engine has been completely rewritten, and although it is generally backward compatible, there are new features
@ -385,6 +364,18 @@ The page tree moved from a bespoke tree library to [JSTree](http://jstree.com),
which required changes to markup of the tree and its JavaScript architecture.
This includes changes to `TreeDropdownField` and `TreeMultiSelectField`.
### TinyMCE upgraded to 3.5 ###
TinyMCE has been upgraded to version 3.5.
This change should be transparent to most people upgrading, but if you're using custom plugins for TinyMCE,
please ensure they are still working correctly with the new version.
If you're upgrading from an SS 3.0 beta, TinyMCE HTML source editor and other popups might be blank.
This is caused by the TinyMCE compressor leaving stale cache files in the system temp folder from an earlier
version. To resolve this problem, simply delete the `{hash}.gz` files within your temp location (defined by `sys_get_temp_dir()` in PHP.)
These cache files will be regenerated next time the CMS is opened.
### Settings-related fields move from SiteTree->getCMSFields() to new SiteTree->getSettingsFields() [getcmsfields]###
The fields and tabs are now split into two separate forms, which required a structural
@ -503,10 +494,9 @@ Please use the appropriate setters on the form field instance instead.
### EmailField now uses type "email" instead of type "text" {#email-form-field}
EmailField now uses "email" for the `type` attribute, which integrates better with HTML5 features like
form validation in the browser.
If you want to change this back to "text", use `setAttribute()` when constructing the field:
form validation in the browser. If you want to change this back to "text", use `setAttribute()` when constructing the field:
:::php
$field = new EmailField('Email');
$field->setAttribute('type', 'text');
@ -514,7 +504,6 @@ If you want to change this back to "text", use `setAttribute()` when constructin
In order to make the SilverStripe framework useable without the `cms` module,
we've moved some files around.
CMS base functionality which is not directly related to content pages (`SiteTree`)
has been moved from the `cms` module into a new "sub-module" located in `framework/admin`.
This includes generic management interfaces like "Files & Images" (`AssetAdmin`),

View File

@ -83,11 +83,6 @@ class GridFieldDataColumns implements GridField_ColumnProvider {
}
/**
* Specify custom formatting for fields, e.g. to render a link instead of pure text.
* Caution: Make sure to escape special php-characters like in a normal php-statement.
* Example: "myFieldName" => '<a href=\"custom-admin/$ID\">$ID</a>'.
* Alternatively, pass a anonymous function, which takes one parameter: The list item.
*
* @return array
*/
public function getFieldCasting() {
@ -95,6 +90,12 @@ class GridFieldDataColumns implements GridField_ColumnProvider {
}
/**
* Specify custom formatting for fields, e.g. to render a link instead of pure text.
* Caution: Make sure to escape special php-characters like in a normal php-statement.
* Example: "myFieldName" => '<a href=\"custom-admin/$ID\">$ID</a>'.
* Alternatively, pass a anonymous function, which takes two parameters:
* The value returned by Convert::raw2xml and the original list item.
*
* @param array $formatting
*/
public function setFieldFormatting($formatting) {

View File

@ -253,7 +253,13 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
$comparisor = $this->applyFilterContext($field, $fieldArg, $value);
}
} else {
$SQL_Statements[] = '"'.Convert::raw2sql($field).'" '.$customQuery;
if($field == 'ID') {
$field = sprintf('"%s"."ID"', ClassInfo::baseDataClass($this->dataClass));
} else {
$field = '"' . Convert::raw2sql($field) . '"';
}
$SQL_Statements[] = $field . ' ' . $customQuery;
}
}
if(count($SQL_Statements)) {
@ -350,10 +356,16 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
$SQL_Statements = array();
foreach($whereArguments as $fieldName => $value) {
if(is_array($value)){
$SQL_Statements[] = ('"'.$fieldName.'" NOT IN (\''.implode('\',\'', Convert::raw2sql($value)).'\')');
if($fieldName == 'ID') {
$fieldName = sprintf('"%s"."ID"', ClassInfo::baseDataClass($this->dataClass));
} else {
$SQL_Statements[] = ('"'.$fieldName.'" != \''.Convert::raw2sql($value).'\'');
$fieldName = '"' . Convert::raw2sql($fieldName) . '"';
}
if(is_array($value)){
$SQL_Statements[] = ($fieldName . ' NOT IN (\''.implode('\',\'', Convert::raw2sql($value)).'\')');
} else {
$SQL_Statements[] = ($fieldName . ' != \''.Convert::raw2sql($value).'\'');
}
}
$this->dataQuery->whereAny($SQL_Statements);

View File

@ -28,7 +28,8 @@ if(!defined('BASE_PATH')) define('BASE_PATH', dirname($frameworkPath));
// Copied from cli-script.php, to enable same behaviour through phpunit runner.
if(isset($_SERVER['argv'][2])) {
$args = array_slice($_SERVER['argv'],2);
$_GET = array();
if(!isset($_GET)) $_GET = array();
if(!isset($_REQUEST)) $_REQUEST = array();
foreach($args as $arg) {
if(strpos($arg,'=') == false) {
$_GET['args'][] = $arg;
@ -38,7 +39,7 @@ if(isset($_SERVER['argv'][2])) {
$_GET = array_merge($_GET, $newItems);
}
}
$_REQUEST = $_GET;
$_REQUEST = array_merge($_REQUEST, $_GET);
}
// Always flush the manifest for phpunit test runs

24
tests/model/DataListTest.php Executable file → Normal file
View File

@ -14,7 +14,8 @@ class DataListTest extends SapphireTest {
'DataObjectTest_FieldlessSubTable',
'DataObjectTest_ValidatedObject',
'DataObjectTest_Player',
'DataObjectTest_TeamComment'
'DataObjectTest_TeamComment',
'DataObjectTest\NamespacedClass',
);
public function testSubtract(){
@ -397,7 +398,26 @@ class DataListTest extends SapphireTest {
$this->assertEquals(1, $list->count(), 'There should be one comments');
$this->assertEquals('Bob', $list->first()->Name, 'Only comment should be from Bob');
}
public function testFilterAndExcludeById() {
$id = $this->idFromFixture('DataObjectTest_SubTeam', 'subteam1');
$list = DataObjectTest_SubTeam::get()->filter('ID', $id);
$this->assertEquals($id, $list->first()->ID);
$list = DataObjectTest_SubTeam::get();
$this->assertEquals(3, count($list));
$this->assertEquals(2, count($list->exclude('ID', $id)));
// Check that classes with namespaces work.
$obj = new DataObjectTest\NamespacedClass();
$obj->Name = "Test";
$obj->write();
$list = DataObjectTest\NamespacedClass::get()->filter('ID', $obj->ID);
$this->assertEquals('Test', $list->First()->Name);
$this->assertEquals(0, $list->exclude('ID', $obj->ID)->count());
}
/**
* $list->exclude('Name', 'bob'); // exclude bob from list
*/

View File

@ -0,0 +1,13 @@
<?php
namespace DataObjectTest;
/**
* Right now this is only used in DataListTest, but extending it to DataObjectTest in the future would make sense.
* Note that it was deliberated named to include "\N" to try and trip bad code up.
*/
class NamespacedClass extends \DataObject {
static $db = array(
'Name' => 'Varchar',
);
}

View File

@ -6,7 +6,7 @@ if (!defined('PHPUnit_MAIN_METHOD')) {
/**
* Translate_Adapter_RailsYAML
*/
require_once 'Translate/Adapter/RailsYAML.php';
require_once dirname(__FILE__) . '/../../../library/Translate/Adapter/RailsYAML.php';
/**
* @category Zend