ExtBase:
authorJochen Rau <j.rau@web.de>
Fri, 3 Apr 2009 11:47:51 +0000 (11:47 +0000)
committerJochen Rau <j.rau@web.de>
Fri, 3 Apr 2009 11:47:51 +0000 (11:47 +0000)
* Started to back-port parts of the FLOW3 manual
* Removed isNonCachableAction() method
* Implemented validation error handling (errorAction() and preProcessArgument() methods in Action Controller)
* Removed property $dataTypeValidator (using $validator instead)
* Added getErrors() and areValid() to Arguments
* Removed dependency to TYPO3 v4.3

23 files changed:
typo3/sysext/extbase/Classes/MVC/Controller/ActionController.php
typo3/sysext/extbase/Classes/MVC/Controller/Argument.php
typo3/sysext/extbase/Classes/MVC/Controller/Arguments.php
typo3/sysext/extbase/Classes/Persistence/Hook/TCEMainValueObjectUpdater.php
typo3/sysext/extbase/Classes/Persistence/Mapper/ColumnMap.php
typo3/sysext/extbase/Classes/Persistence/Mapper/DataMap.php
typo3/sysext/extbase/Classes/Persistence/Mapper/ObjectRelationalMapper.php
typo3/sysext/extbase/Classes/Persistence/Repository.php
typo3/sysext/extbase/Classes/Validation/Validator/Text.php
typo3/sysext/extbase/Documentation/Manual/en/AppendixCodingGuidelines.xml [new file with mode: 0644]
typo3/sysext/extbase/Documentation/Manual/en/AppendixCodingGuidelines_TrueFalse.jpg [new file with mode: 0644]
typo3/sysext/extbase/Documentation/Manual/en/Index.xml [new file with mode: 0644]
typo3/sysext/extbase/Documentation/Manual/en/Introduction.xml [new file with mode: 0644]
typo3/sysext/extbase/Documentation/Manual/en/MVCFramework.xml [new file with mode: 0644]
typo3/sysext/extbase/Documentation/Manual/en/MVCFramework_ModelViewController.png [new file with mode: 0755]
typo3/sysext/extbase/Documentation/Manual/en/MVCFramework_RequestResponseWorkflow.png [new file with mode: 0644]
typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework.xml [new file with mode: 0644]
typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_BlogDomainModel.png [new file with mode: 0644]
typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_PersistenceProcess.png [new file with mode: 0644]
typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_QueryProcess.png [new file with mode: 0644]
typo3/sysext/extbase/Documentation/todo.txt
typo3/sysext/extbase/class.tx_extbase_dispatcher.php
typo3/sysext/extbase/ext_emconf.php

index bf545db..b8fc740 100644 (file)
@@ -60,6 +60,12 @@ class Tx_ExtBase_MVC_Controller_ActionController extends Tx_ExtBase_MVC_Controll
         * @var string
         */
        protected $actionMethodName = 'indexAction';
+       
+       /**
+        * Name of the special error action method which is called in case of errors
+        * @var string
+        */
+       protected $errorMethodName = 'errorAction';
 
        /**
         * Handles a request. The result output is returned by altering the given response.
@@ -81,7 +87,7 @@ class Tx_ExtBase_MVC_Controller_ActionController extends Tx_ExtBase_MVC_Controll
                $this->initializeAction();
                $this->callActionMethod();
        }
-
+       
        /**
         * Implementation of the arguments initilization in the action controller:
         * Automatically registers arguments of the current action
@@ -133,36 +139,39 @@ class Tx_ExtBase_MVC_Controller_ActionController extends Tx_ExtBase_MVC_Controll
        }
 
        /**
-        * Returns TRUE if the given action (a name of an action like 'show'; without
-        * trailing 'Action') should be cached, otherwise it returns FALSE.
-        *
-        * @param string $actionName
-        * @return void
-        * @author Jochen Rau <jochen.rau@typoplanet.de>
-        */
-       public function isCachableAction($actionName) {
-                return !in_array($actionName, $this->nonCachableActions);
-       }
-
-       /**
         * Calls the specified action method and passes the arguments.
         * If the action returns a string, it is appended to the content in the
         * response object.
         *
-        * @param string $actionMethodName Name of the action method
         * @return void
+        * @internal
         */
        protected function callActionMethod() {
+               $preparedArguments = array();           
                foreach ($this->arguments as $argument) {
+                       $this->preProcessArgument($argument);
                        $preparedArguments[] = $argument->getValue();
                }
-               $actionResult = call_user_func_array(array($this, $this->actionMethodName), $preparedArguments);
+               if (!$this->arguments->areValid()) {
+                       $actionResult = call_user_func(array($this, $this->errorMethodName));
+               } else {
+                       $actionResult = call_user_func_array(array($this, $this->actionMethodName), $preparedArguments);
+               }
                if ($actionResult === NULL && $this->view instanceof Tx_ExtBase_MVC_View_ViewInterface) {
                        $this->response->appendContent($this->view->render());
                } elseif (is_string($actionResult) && strlen($actionResult) > 0) {
                        $this->response->appendContent($actionResult);
                }
        }
+       
+       /**
+        * This is a template method to process unvalid arguments. Overwrite this method in your concrete controller.
+        *
+        * @param Tx_ExtBase_MVC_Controller_Argument $argument The argument
+        * @return void
+        */
+       protected function preProcessArgument(Tx_ExtBase_MVC_Controller_Argument $argument) {
+       }
 
        /**
         * Prepares a view for the current action and stores it in $this->view.
@@ -206,15 +215,21 @@ class Tx_ExtBase_MVC_Controller_ActionController extends Tx_ExtBase_MVC_Controll
        }
 
        /**
-        * The default action of this controller.
+        * A special action which is called if the originally intended action could
+        * not be called, for example if the arguments were not valid.
         *
-        * This method should always be overridden by the concrete action
-        * controller implementation.
-        *
-        * @return void
+        * @return string
         */
-       protected function indexAction() {
-               return 'No index action has been implemented yet for this controller.';
+       protected function errorAction() {
+               $message = 'An error occurred while trying to call ' . get_class($this) . '->' . $this->actionMethodName . '(). <br />' . PHP_EOL;
+               foreach ($this->arguments as $argument) {
+                       if (!$argument->isValid()) {
+                               foreach ($argument->getErrors() as $errorMessage) {
+                                       $message .= 'Error:   ' . $errorMessage . '<br />' . PHP_EOL;
+                               }
+                       }
+               }
+               return $message;
        }
 }
 ?>
\ No newline at end of file
index 433e2c0..ec5cb7f 100644 (file)
@@ -72,7 +72,7 @@ class Tx_ExtBase_MVC_Controller_Argument {
         * The argument is valid
         * @var boolean
         */
-       protected $isValid = NULL;
+       protected $isValid = FALSE;
 
        /**
         * Any error (Tx_ExtBase_Error_Error) that occured while initializing this argument (e.g. a mapping error)
@@ -87,13 +87,6 @@ class Tx_ExtBase_MVC_Controller_Argument {
        protected $validator = NULL;
 
        /**
-        * The property validator for this arguments datatype
-        * @var Tx_ExtBase_Validation_Validator_ValidatorInterface
-        */
-       // TODO Remove DatatypeValidator
-       protected $datatypeValidator = NULL;
-
-       /**
         * Uid for the argument, if it has one
         * @var string
         */
@@ -166,11 +159,11 @@ class Tx_ExtBase_MVC_Controller_Argument {
        public function setDataType($dataType) {
                $this->dataType = ($dataType != '' ? $dataType : 'Text');
                // TODO Make validator path and class names configurable
-               $dataTypeValidatorClassName = 'Tx_ExtBase_Validation_Validator_' . $this->dataType;
+               $validatorClassName = 'Tx_ExtBase_Validation_Validator_' . $this->dataType;
                $classFilePathAndName = t3lib_extMgm::extPath('extbase') . 'Classes/Validation/Validator/' . $this->dataType . '.php';
                if (isset($classFilePathAndName) && file_exists($classFilePathAndName)) {
                        require_once($classFilePathAndName);
-                       $this->datatypeValidator = t3lib_div::makeInstance($dataTypeValidatorClassName);
+                       $this->validator = t3lib_div::makeInstance($validatorClassName);
                }
                return $this;
        }
@@ -248,12 +241,10 @@ class Tx_ExtBase_MVC_Controller_Argument {
         */
        protected function isValidValueForThisArgument($value) {
                $isValid = TRUE;
+               $this->clearErrors();
                $validatorErrors = t3lib_div::makeInstance('Tx_ExtBase_Validation_Errors');
-               // TODO use only Validator; do not distinguish between Validator and DatatypeValidator
                if ($this->getValidator() !== NULL) {
-                       $isValid &= $this->getValidator()->isValid($value, $validatorErrors);
-               } elseif ($this->getDatatypeValidator() !== NULL) {
-                       $isValid = $this->getDatatypeValidator()->isValid($value, $validatorErrors);
+                       $isValid &= (boolean)$this->getValidator()->isValid($value, $validatorErrors);
                } else {
                        throw new Tx_ExtBase_Validation_Exception_NoValidatorFound('No appropriate validator for the argument "' . $this->getName() . '" was found.', 1235748909);
                }
@@ -262,8 +253,18 @@ class Tx_ExtBase_MVC_Controller_Argument {
                                $this->addError($error);
                        }
                }
-               $this->isValid = $isValid;
-               return (boolean)$isValid;
+               $this->setIsValid($isValid);
+               return $isValid;
+       }
+
+       /**
+        * Sets the validity of the argument
+        *
+        * @return void
+        */
+       // TODO naming of the method setIsValid()
+       public function setIsValid($isValid) {
+               return $this->isValid = $isValid;
        }
 
        /**
@@ -286,6 +287,15 @@ class Tx_ExtBase_MVC_Controller_Argument {
        }
 
        /**
+        * Removes all errors
+        *
+        * @return void
+        */
+       public function clearErrors() {
+               $this->errors = array();
+       }
+
+       /**
         * Get all initialization errors
         *
         * @return array An array containing Tx_ExtBase_Error_Error objects
@@ -296,6 +306,15 @@ class Tx_ExtBase_MVC_Controller_Argument {
        }
 
        /**
+        * Returns true if any error was recognized
+        *
+        * @return boolean True if an error occured
+        */
+       public function hasErrors() {
+               return (count($this->errors) > 0);
+       }
+
+       /**
         * Set an additional validator
         *
         * @param string Class name of a validator
@@ -316,15 +335,6 @@ class Tx_ExtBase_MVC_Controller_Argument {
        }
 
        /**
-        * Returns the set datatype validator
-        *
-        * @return Tx_ExtBase_Validation_Validator_ValidatorInterface The set datatype validator
-        */
-       public function getDatatypeValidator() {
-               return $this->datatypeValidator;
-       }
-
-       /**
         * Create and set a validator chain
         *
         * @param array Object names of the validators
index 39cb2ca..9ff53d2 100644 (file)
@@ -185,6 +185,35 @@ class Tx_ExtBase_MVC_Controller_Arguments extends ArrayObject {
        }
 
        /**
+        * Returns errors of all arguments
+        *
+        * @return array An array of error messages
+        */
+       public function getErrors() {
+               $errors = array();
+               foreach ($this as $argument) {
+                       $errors = array_merge($errors, $argument->getErrors());
+               }
+               return $errors;
+       }
+       
+       /**
+        * Returns true if all arguments are valid
+        *
+        * @return boolean TRUE if all arguments are valid
+        */
+       public function areValid() {
+               $valid = TRUE;
+               foreach ($this as $argument) {
+                       if (!$argument->isValid()) {
+                               $valid = FALSE;
+                               break;
+                       }
+               }
+               return $valid;
+       }
+
+       /**
         * Magic setter method for the argument values. Each argument
         * value can be set by just calling the setArgumentName() method.
         *
@@ -218,7 +247,6 @@ class Tx_ExtBase_MVC_Controller_Arguments extends ArrayObject {
         * @return string long argument name or empty string
         */
        protected function translateToLongArgumentName($argumentName) {
-
                if (in_array($argumentName, $this->getArgumentNames())) return $argumentName;
 
                foreach ($this as $argument) {
index 11f14d6..b069179 100644 (file)
@@ -9,9 +9,6 @@ class tx_ExtBase_Persistence_Hook_TCEMainValueObjectUpdater {
                        $uid = $this->findUid($incomingFieldArray, $table);
                        if ($uid !== NULL) {
                                // FOUND a UID.
-
-                               var_dump($uid, $id);
-                               var_dump($incomingFieldArray);
                                if ($isNewRecord) {
                                        // re-map the insertion to an update!
                                        $tcemain->substNEWwitIDs[$id] = (int)$uid;
index aea6281..6641658 100644 (file)
@@ -29,7 +29,6 @@
  * @subpackage extbase
  * @version $ID:$
  */
-// SK: I did not do an in-depth check of this class
 // SK: PHPDoc ;-)
 class Tx_ExtBase_Persistence_Mapper_ColumnMap {
 
index fa97a43..17e8830 100644 (file)
@@ -274,6 +274,15 @@ class Tx_ExtBase_Persistence_Mapper_DataMap {
        public function isPersistableProperty($propertyName) {
                return isset($this->columnMaps[$propertyName]);
        }
+       
+       /**
+        * Check if versioning is enabled .
+        *
+        * @return boolean
+        */
+       public function isVersionable() {
+               return ($GLOBALS['TCA'] [$this->tableName] ['ctrl'] ['versioningWS'] === '1');
+       }
 
        /**
         * Returns TRUE if the table has a pid column holding the id of the page the record is virtually stored on.
index 26989d1..257c471 100644 (file)
@@ -60,7 +60,7 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
         *
         * @var t3lib_refindex
         **/
-       protected $refIndex;
+       protected $referenceIndex;
        
        /**
         * Statistics with counts of database operations
@@ -84,7 +84,7 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
                $this->persistenceSession = t3lib_div::makeInstance('Tx_ExtBase_Persistence_Session');
                $GLOBALS['TSFE']->includeTCA();
                $this->database = $GLOBALS['TYPO3_DB'];
-               $this->refIndex = t3lib_div::makeInstance('t3lib_refindex');
+               $this->referenceIndex = t3lib_div::makeInstance('t3lib_refindex');
        }
 
        /**
@@ -127,7 +127,7 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
         *
         * @return string The where part
         */
-       protected function buildQueryByConditions(&$dataMap, $conditions) {
+       protected function buildQueryByConditions(Tx_ExtBase_Persistence_Mapper_DataMap &$dataMap, $conditions) {
                $whereParts = array();
                foreach ($conditions as $key => $condition) {
                        if (is_array($condition) && isset($condition[0])) {
@@ -153,7 +153,7 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
         *
         * @return string The where part
         */
-       protected function buildQueryByExample(&$dataMap, $propertyName, $example) {
+       protected function buildQueryByExample(Tx_ExtBase_Persistence_Mapper_DataMap &$dataMap, $propertyName, $example) {
                $sql = '';
                $columnMap = $dataMap->getColumnMap($propertyName);
                if (!$columnMap) {
@@ -179,7 +179,7 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
         *
         * @return string The query part with replaced placeholders
         */
-       protected function replacePlaceholders(&$dataMap, $queryPart, $parameters) {
+       protected function replacePlaceholders(Tx_ExtBase_Persistence_Mapper_DataMap &$dataMap, $queryPart, $parameters) {
                $sql = $queryPart;
                foreach ($parameters as $parameter) {
                        $markPosition = strpos($sql, '?');
@@ -232,9 +232,11 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
                $fieldMap = $this->getFieldMapFromResult($res);
                $rows = $this->getRowsFromResult($res);
                $this->database->sql_free_result($res);
+               // TODO Implement language and workspace overlay
+               // foreach ($rows as $row) {
+               //      $this->doLanguageAndWorkspaceOverlay($dataMap, $fieldMap, $row);
+               // }
 
-               // SK: Do we want to make it possible to ignore "enableFields"?
-               // TODO language overlay; workspace overlay
                $objects = array();
                if (is_array($rows)) {
                        if (count($rows) > 0) {
@@ -244,6 +246,24 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
                $this->statistics['fetch']++;
                return $objects;
        }
+       
+       /**
+        * Fetches a rows from the database by given SQL statement snippets taking a relation table into account
+        *
+        * @param string Optional WHERE clauses put in the end of the query, defaults to '1=1. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
+        * @param string Optional GROUP BY field(s), defaults to blank string.
+        * @param string Optional ORDER BY field(s), defaults to blank string.
+        * @param string Optional LIMIT value ([begin,]max), defaults to blank string.
+        */
+       public function fetchWithRelationTable($parentObject, $columnMap, $where = '', $groupBy = '', $orderBy = '', $limit = '', $useEnableFields = TRUE) {
+               if (!strlen($where)) {
+                       $where = '1=1';
+               }
+               $from = $columnMap->getChildTableName() . ' LEFT JOIN ' . $columnMap->getRelationTableName() . ' ON (' . $columnMap->getChildTableName() . '.uid=' . $columnMap->getRelationTableName() . '.uid_foreign)';
+               $where .= ' AND ' . $columnMap->getRelationTableName() . '.uid_local=' . t3lib_div::intval_positive($parentObject->getUid());
+
+               return $this->fetch($columnMap->getChildClassName(), $where, $from, $groupBy, $orderBy, $limit, $useEnableFields);
+       }
 
        protected function getFieldMapFromResult($res) {
                $fieldMap = array();
@@ -266,6 +286,57 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
                }
                return $rows;
        }
+       
+       /**
+        * Performs woekspace and language overlay on the given row array..The language and workspaceid is automatically 
+        * detected (depending on FE or BE context). You can also explicitly set the language/workspace uid.
+        *
+        * @param Tx_ExtBase_Persistence_Mapper_DataMap $dataMap 
+        * @param array $row The row array (as reference) 
+        * @param string $languageUid The language uid
+        * @param string $workspaceUidUid The workspace uid
+        * @return void
+        */
+       protected function doLanguageAndWorkspaceOverlay(Tx_ExtBase_Persistence_Mapper_DataMap $dataMap, array &$fieldMap, array &$row, $languageUid = null, $workspaceUid = null) {
+               $tableName = $dataMap->getTableName();
+               if (TYPO3_MODE == 'FE') {
+                       if (is_object($GLOBALS ['TSFE'])) {
+                               $pageSelectObject = $GLOBALS ['TSFE']->sys_page;
+                               if ($languageUid === NULL) {
+                                       $languageUid = $GLOBALS ['TSFE']->sys_language_content;
+                               }
+                       }
+                       else {
+                               require_once(PATH_t3lib . 'class.t3lib_page.php');
+                               $pageSelectObject = t3lib_div::makeInstance('t3lib_pageSelect');
+
+                               if ($languageUid === NULL) {
+                                       $languageUid = intval(t3lib_div::_GP('L'));
+                               }
+                       }
+
+
+                       if ($workspaceUid !== NULL) {
+                               $pageSelectObject->versioningWorkspaceId = $workspaceUid;
+                       }
+               } else {
+                       require_once(PATH_t3lib . 'class.t3lib_page.php');
+                       $pageSelectObject = t3lib_div::makeInstance( 't3lib_pageSelect' );
+                       //$pageSelectObject->versioningPreview =  TRUE;
+                       if ($workspaceUid === NULL) {
+                               $workspaceUid = $GLOBALS ['BE_USER']->workspace;
+                       }
+                       $pageSelectObject->versioningWorkspaceId = $workspaceUid;
+               }
+
+               $row = $pageSelectObject->getRecordOverlay($tableName, $row, $languageUid, ''); //'hideNonTranslated'
+
+               // TODO Skip if empty languageoverlay (languagevisibility)
+
+               if ($dataMap->isVersionable($tableName)) {
+                       $t3lib_pageSelect->versionOL($tableName, $row);
+               }
+       }
 
        /**
         * Get the join clause for the fetch method for a specific class. This will
@@ -287,24 +358,6 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
        }
 
        /**
-        * Fetches a rows from the database by given SQL statement snippets taking a relation table into account
-        *
-        * @param string Optional WHERE clauses put in the end of the query, defaults to '1=1. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
-        * @param string Optional GROUP BY field(s), defaults to blank string.
-        * @param string Optional ORDER BY field(s), defaults to blank string.
-        * @param string Optional LIMIT value ([begin,]max), defaults to blank string.
-        */
-       public function fetchWithRelationTable($parentObject, $columnMap, $where = '', $groupBy = '', $orderBy = '', $limit = '', $useEnableFields = TRUE) {
-               if (!strlen($where)) {
-                       $where = '1=1';
-               }
-               $from = $columnMap->getChildTableName() . ' LEFT JOIN ' . $columnMap->getRelationTableName() . ' ON (' . $columnMap->getChildTableName() . '.uid=' . $columnMap->getRelationTableName() . '.uid_foreign)';
-               $where .= ' AND ' . $columnMap->getRelationTableName() . '.uid_local=' . t3lib_div::intval_positive($parentObject->getUid());
-
-               return $this->fetch($columnMap->getChildClassName(), $where, $from, $groupBy, $orderBy, $limit, $useEnableFields);
-       }
-
-       /**
         * reconstitutes domain objects from $rows (array)
         *
         * @param Tx_ExtBase_Persistence_Mapper_DataMap $dataMap The data map corresponding to the domain object
@@ -312,8 +365,7 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
         * @param array $rows The rows array fetched from the database (not associative)
         * @return array An array of reconstituted domain objects
         */
-       // SK: I Need to check this method more thoroughly.
-       // SK: Are loops detected during reconstitution?
+       // TODO Check for infinite loops during reconstitution
        protected function reconstituteObjects(Tx_ExtBase_Persistence_Mapper_DataMap $dataMap, array &$fieldMap, array &$rows) {
                $objects = array();
                foreach ($rows as $row) {
@@ -330,11 +382,9 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
                                                $object->_reconstituteProperty($columnMap->getPropertyName(), $relatedObject);
                                        } elseif ($columnMap->getTypeOfRelation() === Tx_ExtBase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) {
                                                $where = $columnMap->getParentKeyFieldName() . '=' . intval($object->getUid());
-                                               $relatedDataMap = $this->getDataMap($columnMap->getChildClassName());
                                                $relatedObjects = $this->fetch($columnMap->getChildClassName(), $where);
                                                $object->_reconstituteProperty($columnMap->getPropertyName(), $relatedObjects);
                                        } elseif ($columnMap->getTypeOfRelation() === Tx_ExtBase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
-                                               $relatedDataMap = $this->getDataMap($columnMap->getChildClassName());
                                                $relatedObjects = $this->fetchWithRelationTable($object, $columnMap);
                                                $object->_reconstituteProperty($columnMap->getPropertyName(), $relatedObjects);
                                        }
@@ -347,6 +397,14 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
                return $objects;
        }
 
+       /**
+        * Returns an array of properties with the property name as key and the converted property value as value.
+        *
+        * @param Tx_ExtBase_Persistence_Mapper_DataMap $dataMap The data map of the target object
+        * @param string $fieldMap the field map of the related database table.
+        * @param string $row The row to be mapped on properties
+        * @return void
+        */
        protected function getProperties(Tx_ExtBase_Persistence_Mapper_DataMap $dataMap, array &$fieldMap, array &$row) {
                $properties = array();
                foreach ($dataMap->getColumnMaps() as $columnMap) {
@@ -422,12 +480,11 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
         * @param string $recurseIntoRelations
         * @return void
         */
-       // SK: I need to check this more thorougly
        protected function insertObject(Tx_ExtBase_DomainObject_DomainObjectInterface $object, $parentObject = NULL, $parentPropertyName = NULL, $recurseIntoRelations = TRUE) {
                $properties = $object->_getProperties();
                $className = get_class($object);
                $dataMap = $this->getDataMap($className);
-               $row = $this->getRow($dataMap, $properties);
+               $row = $this->getRowToBeInstertedOrUpdated($dataMap, $properties);
                
                if ($object instanceof Tx_ExtBase_DomainObject_AbstractValueObject) {
                        $conditions = $properties;
@@ -473,7 +530,7 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
                $uid = $this->database->sql_insert_id();
                $object->_reconstituteProperty('uid', $uid);
                
-               $this->refIndex->updateRefIndexTable($tableName, $uid);
+               $this->referenceIndex->updateRefIndexTable($tableName, $uid);
 
                $this->persistRelations($object, $propertyName, $this->getRelations($dataMap, $properties));
        }
@@ -483,11 +540,10 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
         *
         * @return void
         */
-       // SK: I need to check this more thorougly
        protected function updateObject(Tx_ExtBase_DomainObject_DomainObjectInterface $object, $parentObject = NULL, $parentPropertyName = NULL, $recurseIntoRelations = TRUE) {
                $properties = $object->_getDirtyProperties();
                $dataMap = $this->getDataMap(get_class($object));
-               $row = $this->getRow($dataMap, $properties);
+               $row = $this->getRowToBeInstertedOrUpdated($dataMap, $properties);
 
                if ($parentObject instanceof Tx_ExtBase_DomainObject_DomainObjectInterface && $parentPropertyName !== NULL) {
                        $parentDataMap = $this->getDataMap(get_class($parentObject));
@@ -525,7 +581,6 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
         *
         * @return void
         */
-       // SK: I need to check this more thorougly
        protected function deleteObject(Tx_ExtBase_DomainObject_DomainObjectInterface $object, $parentObject = NULL, $parentPropertyName = NULL, $recurseIntoRelations = FALSE, $onlySetDeleted = TRUE) {
                $relations = array();
                $properties = $object->_getDirtyProperties();
@@ -548,7 +603,7 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
                                );
                        $this->statistics['delete']++;
                }
-               $this->refIndex->updateRefIndexTable($tableName, $uid);
+               $this->referenceIndex->updateRefIndexTable($tableName, $uid);
 
                if ($recurseIntoRelations === TRUE) {
                        // FIXME disabled, recursive delete has to be implemented
@@ -563,8 +618,7 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
         * @param array $properties The properties of the object
         * @return array A single row to be inserted in the database
         */
-       // SK: I need to check this more thorougly
-       protected function getRow(Tx_ExtBase_Persistence_Mapper_DataMap $dataMap, $properties) {
+       protected function getRowToBeInstertedOrUpdated(Tx_ExtBase_Persistence_Mapper_DataMap $dataMap, $properties) {
                $relations = array();
                foreach ($dataMap->getColumnMaps() as $columnMap) {
                        $propertyName = $columnMap->getPropertyName();
@@ -714,7 +768,7 @@ class Tx_ExtBase_Persistence_Mapper_ObjectRelationalMapper implements t3lib_Sing
                        $this->statistics['delete']++;
                }
        }
-
+               
        /**
         * Delegates the call to the Data Map.
         * Returns TRUE if the property is persistable (configured in $TCA)
index 8391d2e..4b227b3 100644 (file)
@@ -112,6 +112,7 @@ abstract class Tx_ExtBase_Persistence_Repository implements Tx_ExtBase_Persisten
         * @return void
         */
        public function __call($methodName, $arguments) {
+               // TODO Forward arguments to find ByConditions 
                if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
                        $propertyName = Tx_ExtBase_Utility_Strings::lowercaseFirst(substr($methodName,6));
                        return $this->findByConditions(array($propertyName => $arguments[0]));
index 588fd78..c9e1a57 100644 (file)
@@ -44,7 +44,7 @@ class Tx_ExtBase_Validation_Validator_Text implements Tx_ExtBase_Validation_Vali
         */
        public function isValid($value, Tx_ExtBase_Validation_Errors &$errors, array $validationOptions = array()) {
                if ($value !== filter_var($value, FILTER_SANITIZE_STRING)) {
-                       $errors->append('The given subject was not a valid text (e.g. contained XML tags)."');
+                       $errors->append('The given subject was not a valid text (e.g. contained XML tags).');
                        return FALSE;
                }
                return TRUE;
diff --git a/typo3/sysext/extbase/Documentation/Manual/en/AppendixCodingGuidelines.xml b/typo3/sysext/extbase/Documentation/Manual/en/AppendixCodingGuidelines.xml
new file mode 100644 (file)
index 0000000..b1fdb62
--- /dev/null
@@ -0,0 +1,1300 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<appendix version="5.0" xmlns="http://docbook.org/ns/docbook"
+          xmlns:xl="http://www.w3.org/1999/xlink"
+          xmlns:xi="http://www.w3.org/2001/XInclude"
+          xmlns:xhtml="http://www.w3.org/1999/xhtml"
+          xmlns:svg="http://www.w3.org/2000/svg"
+          xmlns:ns="http://docbook.org/ns/docbook"
+          xmlns:mathml="http://www.w3.org/1998/Math/MathML">
+  <title>Coding Guidelines</title>
+
+  <para>Coding Standards are an important factor for achieving a high code
+  quality. A common visual style, naming conventions and other technical
+  settings allow us to produce a homogenous code which is easy to read and
+  maintain. However, not all important factors can be covered by rules and
+  coding standards. Equally important is the style in which certain problems
+  are solved programmatically - it's the personality and experience of the
+  individual developer which shines through and ultimately makes the
+  difference between technically okay code or a well considered, mature
+  solution.</para>
+
+  <para>These guidelines try to cover both, the technical standards as well as
+  giving incentives for a common development style. These guidelines must be
+  followed by everyone who creates code for the FLOW3 core. Because TYPO3 is
+  based on FLOW3, it follows the same principles - therefore, whenever we
+  mention FLOW3 in the following sections, we equally refer to TYPO3. We hope
+  that you feel encouraged to follow these guidelines as well when creating
+  your own packages and FLOW3 based applications.</para>
+
+  <section>
+    <title>Code formatting and layout</title>
+
+    <subtitle>aka "beautiful code"</subtitle>
+
+    <para>The visual style of programming code is very important. In the TYPO3
+    project we want many programmers to contribute, but in the same style.
+    This will help us to:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>Easily read/understand each others code and consequently easily
+        spot security problems or optimization opportunities</para>
+      </listitem>
+
+      <listitem>
+        <para>It is a signal about consistency and cleanliness, which is a
+        motivating factor for programmers striving for excellence</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>Some people may object to the visual guidelines since everyone has
+    his own habits. You will have to overcome that in the case of FLOW3; the
+    visual guidelines must be followed along with coding guidelines for
+    security. We want all contributions to the project to be as similar in
+    style and as secure as possible.</para>
+
+    <section>
+      <title>General considerations</title>
+
+      <itemizedlist>
+        <listitem>
+          <para>Almost every PHP file in FLOW3 contains exactly one class and
+          does not output anything if it is called directly. Therefore you
+          start your file with a <code>&lt;?php</code> tag and end it with the
+          closing <code>?&gt;</code>.</para>
+        </listitem>
+
+        <listitem>
+          <para>Every file must contain a header stating encoding, namespace,
+          copyright and licensing information</para>
+
+          <para><orderedlist>
+              <listitem>
+                <para>Declare your namespace. The namespace must start with
+                "F3"!</para>
+              </listitem>
+
+              <listitem>
+                <para>Because it is likely that more than one person will work
+                on a class in the long run, we recommend adding a copyright
+                statement like <quote>Copyright belongs to the respective
+                authors</quote> and add yourself to the list of authors for
+                the methods you implemented or changed (significantly).</para>
+              </listitem>
+
+              <listitem>
+                <para>The copyright header itself must not start with
+                <literal>/**</literal>, as this may confuse documentation
+                generators!</para>
+              </listitem>
+            </orderedlist></para>
+
+          <example>
+            <title>The FLOW3 standard file header</title>
+
+            <programlisting language="php">&lt;?php
+declare(ENCODING = 'utf-8');
+namespace F3\Your\Stuff\Here;
+
+/*                                                                        *
+ * This script belongs to the FLOW3 framework.                            *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU Lesser General Public License as published by the *
+ * Free Software Foundation, either version 3 of the License, or (at your *
+ * option) any later version.                                             *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
+ * General Public License for more details.                               *
+ *                                                                        *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with the script.                                         *
+ * If not, see http://www.gnu.org/licenses/lgpl.html                      *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */</programlisting>
+          </example>
+        </listitem>
+
+        <listitem>
+          <para>Code lines are of arbitrary length, no limitations to 80
+          characters or something similar (wake up, graphical displays have
+          been available for decades now...)</para>
+        </listitem>
+
+        <listitem>
+          <para>Lines end with a newline a.k.a <code>chr(10)</code> - UNIX
+          style</para>
+        </listitem>
+
+        <listitem>
+          <para>Files must be encoded in UTF-8</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Make sure you use the correct license and mention the correct
+      package in the header, See <link
+      xl:href="http://forge.typo3.org/wiki/flow3-overview/Licensing_boilerplates_to_use_with_your_code">http://forge.typo3.org/wiki/flow3-overview/Licensing_boilerplates_to_use_with_your_code</link>
+      for some boilerplate text.</para>
+    </section>
+
+    <section>
+      <title>Indentation and line formatting</title>
+
+      <para>Indentation is done with tabs - and not spaces! The beginning of a
+      line is the only place where tabs are used, in all other places use
+      spaces. Always trim whitespace off the end of a line.</para>
+
+      <para>Here's a code snippet which shows the correct usage of tabs and
+      spaces:</para>
+
+      <para><example>
+          <title>Correct use of tabs and spaces</title>
+
+          <programlisting language="php">/**
+ * Returns the name of the currently set context.
+ *
+ * @return string Name of the current context
+ * @author Your Name &lt;your@email.here&gt;
+ */
+public function getContextName() {
+»   return $this-&gt;contextName;
+}</programlisting>
+        </example></para>
+
+      <para>There seem to be very passionate opinions about whether TABs or
+      spaces should be used for indentation of code blocks in the scripts. If
+      you'd like to read more about this religious discussion, you find some
+      nice arguments in the <link
+      xl:href="http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&amp;ixPost=3978">Joels
+      on Software forum</link>.</para>
+    </section>
+
+    <section>
+      <title>Naming</title>
+
+      <para>Naming is a repeatedly undervalued factor in the art of software
+      development. Although everybody seems to agree on that nice names are a
+      nice thing to have, most developers choose cryptic abbreviations in the
+      end (to save some typing). Beware that we TYPO3 core developers are very
+      passionate about naming (some people call it fanatic, well ...). In our
+      opinion spending 15 minutes (or more ...) just to find a good name for a
+      method is well spent time! There are zillions of reasons for using
+      proper names and in the end they all lead to better readable,
+      manageable, stable and secure code.</para>
+
+      <para><itemizedlist>
+          <listitem>
+            <para>As a general note, english words (or abbreviations if
+            neccessary) must be used for all class names, method names,
+            comments, variables names, database table and field names.
+            Although PHP6 allows for using funny japanese, tibetian or
+            don't-know-what characters, the consensus is that english is much
+            better to read for the most of us.</para>
+          </listitem>
+
+          <listitem>
+            <para>If acronyms or abbreviations are embedded in names, keep
+            them in the case they usually are, i.e. keep
+            <acronym>URL</acronym> uppercase, also when used in a method name
+            like <methodname>getURLForLink()</methodname>,
+            <classname>ACMEManager</classname> etc.</para>
+          </listitem>
+        </itemizedlist></para>
+
+      <section>
+        <title>Package names</title>
+
+        <para>All package names are written in
+        <package>UpperCamelCase</package>. In order to avoid problems with
+        different filesystems, only the characters a-z, A-Z and 0-9 are
+        allowed for package names – don't use special characters.</para>
+      </section>
+
+      <section>
+        <title>Namespace names</title>
+
+        <para>Only the characters a-z, A-Z and 0-9 are allowed for namespace
+        names – don't use special characters. All namespace names are written
+        in <classname>UpperCamelCase</classname>, all uppercase names are
+        allowed for well established abbreviations.</para>
+
+        <note>
+          <para>When specifying class names to PHP, always reference the
+          global namespace inside namespaced code by using a leading
+          backslash. When referencing a class name inside a string (e.g. given
+          to the <methodname>create</methodname>-Method of the
+          <classname>ObjectFactory</classname>, in pointcut expressions or in
+          YAML files), never use a leading backslash. This follows the native
+          PHP notion of names in strings always being seen as fully
+          qualified.</para>
+        </note>
+      </section>
+
+      <section>
+        <title>Class names</title>
+
+        <para>Only the characters a-z, A-Z and 0-9 are allowed for class names
+        – don't use special characters.</para>
+
+        <para>All class names are written in
+        <classname>UpperCamelCase</classname>, all uppercase names are allowed
+        for well established abbreviations. Class names must be nouns, never
+        adjectives.</para>
+
+        <para>The name of abstract classes should start with the word
+        "Abstract".</para>
+
+        <para>A few examples follow:</para>
+
+        <example>
+          <title>Correct naming of classes</title>
+
+          <itemizedlist>
+            <listitem>
+              <para><classname>\F3\FLOW3\Object</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\FLOW3\Object\Manager</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\MyPackage\MyObject\MySubObject</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\MyPackage\MyObject\MyHTMLParser</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\Foo\Controller\DefaultController</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\MyPackage\MyObject\AbstractLogger</classname></para>
+            </listitem>
+          </itemizedlist>
+        </example>
+
+        <example>
+          <title>Incorrect naming of classes</title>
+
+          <itemizedlist>
+            <listitem>
+              <para><classname>\myClass</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\Urlwrapper</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\someObject\classname</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\MyPackage\MyObjectMySubObject</classname></para>
+            </listitem>
+          </itemizedlist>
+        </example>
+      </section>
+
+      <section>
+        <title>Interface names</title>
+
+        <para>Only the characters a-z, A-Z and 0-9 are allowed for interface
+        names – don't use special characters.</para>
+
+        <para>All interface names are written in
+        <classname>UpperCamelCase</classname>, all uppercase names are allowed
+        for well established abbreviations. Interface names must be adjectives
+        or nouns and have the Interface suffix. A few examples follow:</para>
+
+        <example>
+          <title>Correct naming of interfaces</title>
+
+          <itemizedlist>
+            <listitem>
+              <para><classname>\F3\FLOW3\Object\ObjectInterface</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\FLOW3\Object\ManagerInterface</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\MyPackage\MyObject\MySubObjectInterface</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\MyPackage\MyObject\MyHTMLParserInterface</classname></para>
+            </listitem>
+          </itemizedlist>
+        </example>
+
+        <example>
+          <title>Incorrect naming of interfaces</title>
+
+          <itemizedlist>
+            <listitem>
+              <para><classname>\myInterface</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\Urlwrapper</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\IsomeObject\classname</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\FLOW3\Object\Manager\Interface</classname></para>
+            </listitem>
+          </itemizedlist>
+        </example>
+      </section>
+
+      <section>
+        <title>Exception names</title>
+
+        <para>Exception naming basically follows the rules for naming classes.
+        There are two possible types of exceptions: Generic exceptions and
+        specific exceptions. Generic exceptions should be named "Exception"
+        preceeded by their namespace. Specific exceptions should reside in
+        their own sub-namespace and must not contain the word
+        <literal>Exception</literal>.</para>
+
+        <example>
+          <title>Correct naming of exceptions</title>
+
+          <itemizedlist>
+            <listitem>
+              <para><classname>\F3\FLOW3\Object\Exception</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\FLOW3\Object\Exception\InvalidClassName</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\MyPackage\MyObject\Exception</classname></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>\F3\MyPackage\MyObject\Exception\OutOfCoffee</classname></para>
+            </listitem>
+          </itemizedlist>
+        </example>
+      </section>
+
+      <section>
+        <title>Method names</title>
+
+        <para>All method names are written in lowerCamelCase, all uppercase
+        names are allowed for well established abbreviations. In order to
+        avoid problems with different filesystems, only the characters a-z,
+        A-Z and 0-9 are allowed for method names – don't use special
+        characters.</para>
+
+        <para>Make method names descriptive, but keep them concise at the same
+        time. Constructors must always be called
+        <function>__construct()</function>, never use the class name as a
+        method name.</para>
+
+        <para>A few examples:</para>
+
+        <example>
+          <title>Correct naming of methods</title>
+
+          <itemizedlist>
+            <listitem>
+              <para><methodname>myMethod()</methodname></para>
+            </listitem>
+
+            <listitem>
+              <para><methodname>someNiceMethodName()</methodname></para>
+            </listitem>
+
+            <listitem>
+              <para><methodname>betterWriteLongMethodNamesThanNamesNobodyUnderstands()</methodname></para>
+            </listitem>
+
+            <listitem>
+              <para><methodname>singYMCALoudly()</methodname></para>
+            </listitem>
+
+            <listitem>
+              <para><methodname>__construct()</methodname></para>
+            </listitem>
+          </itemizedlist>
+        </example>
+      </section>
+
+      <section>
+        <title>Variable names</title>
+
+        <para>Variable names are written in <varname>lowerCamelCase</varname>
+        and should be</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>self-explaining</para>
+          </listitem>
+
+          <listitem>
+            <para>not shortened beyond recognition, but rather longer if it
+            makes their meaning clearer</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>The following example shows two variables with the same meaning
+        but different naming. You'll surely agree the longer versions are
+        better (don't you ...?).</para>
+
+        <example>
+          <title>Correct naming of variables</title>
+
+          <itemizedlist>
+            <listitem>
+              <para><varname>$singletonObjectsRegistry</varname></para>
+            </listitem>
+
+            <listitem>
+              <para><varname>$argumentsArray</varname></para>
+            </listitem>
+
+            <listitem>
+              <para><varname>$aLotOfHTMLCode</varname></para>
+            </listitem>
+          </itemizedlist>
+        </example>
+
+        <example>
+          <title>Incorrect naming of variables</title>
+
+          <itemizedlist>
+            <listitem>
+              <para><varname>$sObjRgstry</varname></para>
+            </listitem>
+
+            <listitem>
+              <para><varname>$argArr</varname></para>
+            </listitem>
+
+            <listitem>
+              <para><varname>$cx</varname></para>
+            </listitem>
+          </itemizedlist>
+        </example>
+
+        <para>As a special exception you may use variable names like
+        <varname>$i</varname>, <varname>$j</varname> and <varname>$k</varname>
+        for numeric indexes in <function>for</function> loops if it's clear
+        what they mean on the first sight. But even then you might want to
+        avoid them.</para>
+      </section>
+
+      <section>
+        <title>Constant names</title>
+
+        <para>All constant names are written in
+        <constant>UPPERCASE</constant>. This includes
+        <constant>TRUE</constant>, <constant>FALSE</constant> and
+        <constant>NULL</constant>. Words can be separated by underscores - you
+        can also use the underscore to group constants thematically:</para>
+
+        <example>
+          <title>Correct naming of constants</title>
+
+          <itemizedlist>
+            <listitem>
+              <para><constant>STUFF_LEVEL</constant></para>
+            </listitem>
+
+            <listitem>
+              <para><constant>COOLNESS_FACTOR</constant></para>
+            </listitem>
+
+            <listitem>
+              <para><constant>PATTERN_MATCH_EMAILADDRESS</constant></para>
+            </listitem>
+
+            <listitem>
+              <para><classname>PATTERN_MATCH_VALIDHTMLTAGS</classname></para>
+            </listitem>
+          </itemizedlist>
+        </example>
+
+        <para>It is, by the way, a good idea to use constants for defining
+        regular expression patterns (as seen above) instead of defining them
+        somewhere in your code.</para>
+      </section>
+
+      <section>
+        <title>File names</title>
+
+        <para>These are the rules for naming files:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>All file names are
+            <filename>UpperCamelCase</filename>.</para>
+          </listitem>
+
+          <listitem>
+            <para>Class and interface files are named according to the class
+            or interface they represent</para>
+          </listitem>
+
+          <listitem>
+            <para>Each file must contain only one class or interface</para>
+          </listitem>
+
+          <listitem>
+            <para>Names of files containing code for unit tests must be the
+            same as the class which is tested, appended with
+            "Test.php".</para>
+          </listitem>
+
+          <listitem>
+            <para>Files are placed in a directory structure representing the
+            namespace structure.</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>Here are some examples:<example>
+            <title>File naming in FLOW3</title>
+
+            <para><itemizedlist>
+                <listitem>
+                  <para><filename>TemplateEngine/TemplateEngineInterface.php</filename></para>
+
+                  <para>Contains the interface
+                  <classname>\F3\TemplateEngine\TemplateEngineInterface</classname>
+                  which is part of the package
+                  <package>\F3\TemplateEngine</package></para>
+                </listitem>
+
+                <listitem>
+                  <para><filename>Error/RuntimeException.php</filename></para>
+
+                  <para>Contains the
+                  <classname>\F3\Error\RuntimeException</classname> being a
+                  part of the package <package>\F3\Error</package></para>
+                </listitem>
+
+                <listitem>
+                  <para><filename>DataAccess/Manager.php</filename></para>
+
+                  <para>Contains class
+                  <classname>\F3\DataAccess\Manager</classname> which is part
+                  of the package <package>\F3\DataAccess</package></para>
+                </listitem>
+
+                <listitem>
+                  <para><filename>FLOW3/Package/Manager.php</filename></para>
+
+                  <para>Contains the class
+                  <classname>\F3\FLOW3\Package\Manager</classname> which is
+                  part of the package <package>\F3\FLOW3</package></para>
+                </listitem>
+
+                <listitem>
+                  <para><filename>Package/ManagerTest.php</filename></para>
+
+                  <para>Contains the class
+                  <classname>\F3\FLOW3\Package\ManagerTest</classname> which
+                  is a test case for PHPUnit.</para>
+                </listitem>
+              </itemizedlist></para>
+          </example></para>
+      </section>
+    </section>
+
+    <section>
+      <title>PHP code formatting</title>
+
+      <section>
+        <title>Strings</title>
+
+        <para>In general, we use single quotes to enclose literal
+        strings:</para>
+
+        <example>
+          <title>String literals</title>
+
+          <programlisting language="php">$vision = 'Inspiring people to share';</programlisting>
+        </example>
+
+        <para>If the string itself contains single quotes or apostrophes, we
+        use double quotes:</para>
+
+        <example>
+          <title>String literals enclosed by double quotes</title>
+
+          <programlisting language="php">$message = "'Kasper' is the name of the friendly ghost.";</programlisting>
+        </example>
+
+        <para>If you'd like to insert values from variables, we prefer to
+        concatenate strings:</para>
+
+        <example>
+          <title>Variable substitution</title>
+
+          <programlisting language="php">$message = 'Hey ' . $name . ', you look ' . $look . ' today!';</programlisting>
+        </example>
+
+        <para>A space must be inserted before and after the dot for better
+        readability:</para>
+
+        <example>
+          <title>Concatenated strings</title>
+
+          <programlisting language="php">$vision = 'Inspiring people ' . 'to share.';</programlisting>
+        </example>
+
+        <para>You may break a string into multiple lines if you use the dot
+        operator. You'll have to indent each following line to mark them as
+        part of the value assignment:</para>
+
+        <example>
+          <title>Multi-line strings</title>
+
+          <programlisting language="php">$vision = 'Inspiring' .
+   'people ' .
+   'to ' .
+   'share';</programlisting>
+        </example>
+      </section>
+
+      <section>
+        <title>Arrays</title>
+
+        <para/>
+      </section>
+
+      <section>
+        <title>Classes</title>
+
+        <para>...<example>
+            <title>Classes</title>
+
+            <programlisting language="php">namespace F3\MyPackage;
+
+class MyObject {
+
+}</programlisting>
+          </example></para>
+      </section>
+
+      <section>
+        <title>Functions and methods</title>
+
+        <para/>
+      </section>
+
+      <section>
+        <title>if statements</title>
+
+        <para><itemizedlist>
+            <listitem>
+              <para>There needs to be one space between the
+              <function>if</function> keyword and the opening brace "(" of the
+              test expression</para>
+            </listitem>
+
+            <listitem>
+              <para>After the closing brace ")" of the test expression follows
+              one space before the curly brace "{"</para>
+            </listitem>
+
+            <listitem>
+              <para><function>else</function> and <function>elseif</function>
+              are on the same line as their corresponding curly braces</para>
+            </listitem>
+          </itemizedlist><example>
+            <title>if statements</title>
+
+            <programlisting language="php">if ($something || $somethingElse) {
+   doThis();
+} else {
+   doSomethingElse();
+}
+
+if (allGoesWrong() === TRUE) throw new \Exception('Hey, all went wrong!', 123);
+
+if (weHaveALotOfCriteria() === TRUE
+   &amp;&amp; notEverythingFitsIntoOneLine() === TRUE
+   || youJustTendToLikeIt() === TRUE) {
+      doThis();
+
+} else {
+   ...
+}</programlisting>
+          </example></para>
+      </section>
+    </section>
+  </section>
+
+  <section>
+    <title>Documentation</title>
+
+    <para>All code must be documented with inline comments. The syntax is that
+    known from the Java programming language (JavaDoc). This way code
+    documentation can automatically be generated using tools like
+    phpDocumentor or Doxygen. The "official" tool used is
+    phpDocumentor<footnote>
+        <para>We look into Doxygen as well, currently both tools have problems
+        with using namespaces in PHP.</para>
+      </footnote>, so syntax and documentation usage are chosen to work best
+    with it.</para>
+
+    <section>
+      <title>Documentation blocks</title>
+
+      <para>A file can contain different documentation blocks, relating to the
+      file itself, the class in the file and finally the members of the class.
+      A documentation block is always used for the entity it precedes.</para>
+
+      <section>
+        <title>File documentation</title>
+
+        <para>The first documentation block in the file is essential for
+        defining the package the file and it's contents belong to. Although it
+        would not be strictly needed to have the file level documentation
+        block (because each file contains only one class in FLOW3), we still
+        use it because it</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>avoids warnings when rendering the documentation</para>
+          </listitem>
+
+          <listitem>
+            <para>makes sure that even code outside of classes is assigned to
+            the correct package and documented correctly</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>That means that each file must contain a documentation block
+        like shown below, right below the header stating the license and
+        before any
+        <methodname>require</methodname>/<methodname>include</methodname>
+        calls:</para>
+
+        <example>
+          <title>Standard file level documentation block</title>
+
+          <programlisting language="php">/**
+ * @package [packagename]
+ * @subpackage [subpackage name if necessary]
+ * @version $Id$
+ */</programlisting>
+        </example>
+
+        <para>The package and version tag are mandatory, the subpackage tag is
+        optional.</para>
+
+        <important>
+          <title>$Id$, Subversion and keyword expansion</title>
+
+          <para>The $Id$ in the version tag will be expanded with information
+          about the file version by Subversion. This so-called keyword
+          expansion needs to be explicitly enabled, though! We recommend to
+          put this into your <filename>~.subversion/config</filename>
+          file:</para>
+
+          <example>
+            <title>Suggested configuration for Subversion in
+            <filename>~/.subversion/config</filename></title>
+
+            <para><literallayout>[miscellany]
+global-ignores = #*# *.rej *.orig *.bak *~ .*
+log-encoding = utf-8
+enable-auto-props = yes
+[auto-props]
+*.php = svn:keywords=Id Revision
+*.yaml = svn:keywords=Id Revision</literallayout></para>
+          </example>
+
+          <para>This does a little more than just enable the keyword
+          expansion, it also sets the character encoding for the log messages
+          and makes Subversion ignore some standard backup and metadata
+          filenames.</para>
+        </important>
+      </section>
+
+      <section>
+        <title>Class documentation</title>
+
+        <para>Classes have their own documentation block describing the
+        classes purpose, assigning a package and subpackage. Very often the
+        code within a class is expanded and modified by a number of authors.
+        We therefore recommend to add the names of the developers to the
+        method documentation. An exception should be the documentation for
+        interfaces where you list all authors in the interface documentation.
+        Exceptions itself never have an author annotation.</para>
+
+        <example>
+          <title>Standard class documentation block</title>
+
+          <programlisting language="php">/**
+ * First sentence is short description. Then you can write more, just as you like
+ *
+ * Here may follow some detailed description about what the class is for.
+ *
+ * Paragraphs are seperated by a empty line.
+ *
+ * @package [packagename]
+ * @subpackage [subpackage name if necessary]
+ * @version $Id$
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public ↩
+      License, version 3 or later
+ */
+class SomeClass {
+ ...</programlisting>
+        </example>
+
+        <example>
+          <title>Standard interface documentation block</title>
+
+          <programlisting language="php">/**
+ * First sentence is short description. Then you can write more, just as you like
+ *
+ * Here may follow some detailed description about what the interface is for.
+ *
+ * Paragraphs are seperated by a empty line.
+ *
+ * @package [packagename]
+ * @subpackage [subpackage name if necessary]
+ * @version $Id$
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public ↩
+      License, version 3 or later
+ * @author Your Name &lt;your@email.here&gt;
+ */
+interface SomeInterface {
+ ...</programlisting>
+        </example>
+
+        <example>
+          <title>Standard exception documentation block</title>
+
+          <programlisting language="php">/**
+ * First sentence is short description. Then you can write more, just as you like
+ *
+ * Here may follow some detailed description about what the interface is for.
+ *
+ * Paragraphs are seperated by a empty line.
+ *
+ * @package [packagename]
+ * @subpackage [subpackage name if necessary]
+ * @version $Id$
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public ↩
+      License, version 3 or later
+ */
+class SomeException extends \Exception {
+ ...</programlisting>
+        </example>
+
+        <para>Additional tags or annotations, such as @see or @aspect, can be
+        added as needed.</para>
+      </section>
+
+      <section>
+        <title>Documenting variables, constants, includes</title>
+
+        <para>Properties of a class should be documented as well. We use the
+        short version for documenting them:</para>
+
+        <example>
+          <title>Standard variable documentation block</title>
+
+          <programlisting language="php">/**
+ * A short description, very much recommended
+ * @var string
+ */
+protected $title = 'Untitled';</programlisting>
+        </example>
+      </section>
+
+      <section>
+        <title>Method documentation</title>
+
+        <para>For a method, at least all parameters and the return value must
+        be documented. Please also add your name by using the @author tag. The
+        @access tag must not be used as it makes no sense (we're using PHP
+        &gt;= 5 for some reason, don't we?)</para>
+
+        <example>
+          <title>Standard method documentation block</title>
+
+          <programlisting language="php">/**
+ * A description for this method
+ *
+ * Paragraphs are seperated by a empty line.
+ *
+ * @param \F3\FLOW3\Log\LoggerInterface $logger A logger
+ * @param string $someString This parameter should contain some string
+ * @return void
+ * @author Your Name &lt;your@email.here&gt;
+ */
+public function __construct(\F3\FLOW3\Log\LoggerInterface $logger, $someString) {
+ ...</programlisting>
+        </example>
+
+        <para>A special note about the @param tags: The parameter type and
+        name are seperated by one space, not aligned. Do not put a colon after
+        the parameter name. Always document the return type, even if it is
+        void - that way it is clearly visible it hasn't just been
+        forgotten.</para>
+      </section>
+    </section>
+
+    <section>
+      <title>Documentation tags</title>
+
+      <para>There are quite a few documentation tags that can be used. Here is
+      a list of tags that can and should be used within the TYPO3
+      project:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>@author</para>
+        </listitem>
+
+        <listitem>
+          <para>@copyright</para>
+        </listitem>
+
+        <listitem>
+          <para>@deprecated</para>
+        </listitem>
+
+        <listitem>
+          <para>@example</para>
+        </listitem>
+
+        <listitem>
+          <para>@filesource</para>
+        </listitem>
+
+        <listitem>
+          <para>@global</para>
+        </listitem>
+
+        <listitem>
+          <para>@ignore</para>
+        </listitem>
+
+        <listitem>
+          <para>@internal</para>
+        </listitem>
+
+        <listitem>
+          <para>@license</para>
+        </listitem>
+
+        <listitem>
+          <para>@link</para>
+        </listitem>
+
+        <listitem>
+          <para>@package</para>
+        </listitem>
+
+        <listitem>
+          <para>@param</para>
+        </listitem>
+
+        <listitem>
+          <para>@return</para>
+        </listitem>
+
+        <listitem>
+          <para>@see</para>
+        </listitem>
+
+        <listitem>
+          <para>@since</para>
+        </listitem>
+
+        <listitem>
+          <para>@subpackage</para>
+        </listitem>
+
+        <listitem>
+          <para>@todo</para>
+        </listitem>
+
+        <listitem>
+          <para>@uses</para>
+        </listitem>
+
+        <listitem>
+          <para>@var</para>
+        </listitem>
+
+        <listitem>
+          <para>@version</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>Some are useless for PHP5 and PHP6, such as the tag for declaring
+      a variable or method private:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>@access</para>
+        </listitem>
+      </itemizedlist>
+
+      <important>
+        <para>If you are unsure about the meaning or ose of those tags, look
+        them up in the phpDocumentor manual, rather than doing
+        guesswork.</para>
+      </important>
+
+      <note>
+        <para>There are more tags which are used in FLOW3, however their
+        purpose is not documention but configuration. Currently annotations
+        are also used for defining aspects and advices for the AOP framework
+        as well as for giving instructions to the Persistence
+        framework.</para>
+      </note>
+    </section>
+  </section>
+
+  <section>
+    <title>Coding</title>
+
+    <section>
+      <title>Overview</title>
+
+      <para>This section gives you an overview of FLOW3's coding rules and
+      best practices.</para>
+    </section>
+
+    <section>
+      <title>General PHP best practices</title>
+
+      <itemizedlist>
+        <listitem>
+          <para>All code should be object oriented. This means there should be
+          no functions outside classes if not absolutely necessary. If you
+          need a "container" for some helper methods, consider creating a
+          static class.</para>
+        </listitem>
+
+        <listitem>
+          <para>All code must make use of PHP5 / PHP6 advanced features for
+          object oriented programming.<itemizedlist>
+              <listitem>
+                <para>Use PHP namespaces (see <link
+                xl:href="http://www.php.net/manual/language.namespaces.php">http://www.php.net/manual/language.namespaces.php</link>)</para>
+              </listitem>
+
+              <listitem>
+                <para>Always declare the scope (public, protected, private) of
+                methods and member variables</para>
+              </listitem>
+
+              <listitem>
+                <para>Make use of iterators and exceptions, have a look at the
+                SPL (see <link
+                xl:href="http://www.php.net/manual/ref.spl.php">http://www.php.net/manual/ref.spl.php</link>
+                and <link
+                xl:href="http://www.php.net/~helly/php/ext/spl/">http://www.php.net/~helly/php/ext/spl/</link>)</para>
+              </listitem>
+
+              <listitem>
+                <para>Make use of type-hinting wherever possible (see <link
+                xl:href="http://www.php.net/manual/language.oop5.typehinting.php">http://www.php.net/manual/language.oop5.typehinting.php</link>)</para>
+              </listitem>
+            </itemizedlist></para>
+        </listitem>
+
+        <listitem>
+          <para>Always use <code>&lt;?php</code> as opening tags (never only
+          <code>&lt;?</code>)</para>
+        </listitem>
+
+        <listitem>
+          <para>Add an encoding declaration as the first line of your PHP
+          code, followed by the namespace declaration. For TYPO3 the encoding
+          must be <acronym>UTF-8</acronym></para>
+
+          <example>
+            <title>Encoding statement for .php files</title>
+
+            <programlisting language="php">&lt;?php
+declare(ENCODING = 'utf-8');
+namespace F3\Your\Stuff\Here;
+
+...</programlisting>
+          </example>
+        </listitem>
+
+        <listitem>
+          <para>Prefer strict comparisons whenever possible, to avoid problems
+          with truthy and falsy <sidebar>
+              <figure>
+                <title>Truthy and falsy are fuzzy...</title>
+
+                <mediaobject>
+                  <imageobject>
+                    <imagedata fileref="AppendixCodingGuidelines_TrueFalse.jpg"/>
+                  </imageobject>
+                </mediaobject>
+              </figure>
+            </sidebar>values that might behave different than what you expect.
+          Here are some examples:<example>
+              <title>Examples of good and bad comparisons</title>
+
+              <para><programlisting language="php">if ($template)             // BAD
+if (isset($template))      // GOOD
+if ($template !== NULL))   // GOOD
+if ($template !== ''))     // GOOD
+
+if (strlen($template) &gt; 0) // BAD! strlen("-1") is greater than 0
+if (is_string($template) &amp;&amp; strlen($template) &gt;0) // BETTER
+
+if ($foo == $bar)          // BAD, avoid truthy comparisons
+if ($foo != $bar)          // BAD, avoid falsy comparisons
+if ($foo === $bar))        // GOOD
+if ($foo !== $bar))        // GOOD</programlisting></para>
+            </example></para>
+        </listitem>
+
+        <listitem>
+          <para>Order of methods in classes. To gain a better overview, it
+          helps if methods in classes are always ordered in a certain way. We
+          prefer the following:<orderedlist>
+              <listitem>
+                <para>constructor</para>
+              </listitem>
+
+              <listitem>
+                <para>injection methods</para>
+              </listitem>
+
+              <listitem>
+                <para>initialization methods (including
+                initializeObject())</para>
+              </listitem>
+
+              <listitem>
+                <para>public methods</para>
+              </listitem>
+
+              <listitem>
+                <para>protected methods</para>
+              </listitem>
+
+              <listitem>
+                <para>private methods</para>
+              </listitem>
+
+              <listitem>
+                <para>shutdown methods</para>
+              </listitem>
+
+              <listitem>
+                <para>destructor</para>
+              </listitem>
+            </orderedlist></para>
+        </listitem>
+
+        <listitem>
+          <para>Avoid double-negation. Instead of
+          <literal>exportSystemView(..., $noRecurse)</literal> use
+          <literal>exportSystemView(..., $recurse)</literal>. It is more
+          logical to pass TRUE if you want recursion instead of having to pass
+          FALSE. In general, parameters negating things are a bad idea.</para>
+        </listitem>
+      </itemizedlist>
+
+      <section>
+        <title>Comments</title>
+
+        <para>In general, comments are a good thing and we strive for creating
+        a well-documented source code. However, inline comments can often be a
+        sign for a bad code structure or method naming.<footnote>
+            <para>This is also referred to as a bad "smell" in the theory of
+            Refactoring. We highly recommend reading "Refactoring" by Martin
+            Fowler - if you didn't already.</para>
+          </footnote>As an example, consider the following code:<example>
+            <title>Bad coding smell: Comments</title>
+
+            <programlisting language="php">   // We only allow valid persons:
+if (is_object($p) &amp;&amp; strlen($p-&gt;lastN) &gt; 0 &amp;&amp; $p-&gt;hidden === FALSE &amp;&amp; ↩
+  $this-&gt;environment-&gt;moonPhase === MOON_LIB::CRESCENT) {
+   $xmM = $thd;
+}</programlisting>
+          </example></para>
+
+        <para>This is a perfect case for the refactoring technique "extract
+        method": In order to avoid the comment, create a new method which is
+        as explanatory as the comment:</para>
+
+        <example>
+          <title>Smells better!</title>
+
+          <programlisting language="php">if ($this-&gt;isValidPerson($person) {
+   $xmM = $thd;
+}</programlisting>
+        </example>
+
+        <para>Bottom line is: You may (and are encouraged to) use inline
+        comments if they support the readability of your code. But always be
+        aware of possible design flaws you probably try to hide with
+        them.</para>
+      </section>
+    </section>
+
+    <section>
+      <title>Error handling and exceptions</title>
+
+      <para>FLOW3 makes use of a hierarchy for its exception classes. The
+      general rule is to throw preferably specific exceptions and usually let
+      them bubble up until a place where more general exceptions are catched.
+      Consider the following example:</para>
+
+      <para>Some method tried to retrieve an object from the object manager.
+      However, instead of providing a string containing the object name, the
+      method passed an object (of course not on purpose - something went
+      wrong). The object manager now throws an
+      <classname>InvalidObjectName</classname> exception. In order to catch
+      this exception you can, of course, catch it specifically - or only
+      consider a more general <classname>Object</classname> exception (or an
+      even more general <classname>FLOW3</classname> exception). This all
+      works because we have the following hierarchy:</para>
+
+      <literallayout>+ \F3\FLOW3\Exception
+  + \F3\FLOW3\Object\Exception
+    + \F3\FLOW3\Object\Exception\InvalidObjectName</literallayout>
+
+      <section>
+        <title>Throwing an exception</title>
+
+        <para>When throwing an exception, make sure to provide a clear error
+        message and an error code being the unix timestamp of when you write
+        the <function>throw</function> statement. That error code must be
+        unique, so watch out when doing copy and paste!</para>
+
+        <para>For every exception there should be a page on the TYPO3 wiki, as
+        exception messages link to that page, identified by the error code
+        (unix timestamp).</para>
+      </section>
+    </section>
+
+    <section>
+      <title>Cross platform issues</title>
+
+      <para/>
+    </section>
+  </section>
+</appendix>
diff --git a/typo3/sysext/extbase/Documentation/Manual/en/AppendixCodingGuidelines_TrueFalse.jpg b/typo3/sysext/extbase/Documentation/Manual/en/AppendixCodingGuidelines_TrueFalse.jpg
new file mode 100644 (file)
index 0000000..0bdafe9
Binary files /dev/null and b/typo3/sysext/extbase/Documentation/Manual/en/AppendixCodingGuidelines_TrueFalse.jpg differ
diff --git a/typo3/sysext/extbase/Documentation/Manual/en/Index.xml b/typo3/sysext/extbase/Documentation/Manual/en/Index.xml
new file mode 100644 (file)
index 0000000..e5c5531
--- /dev/null
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<book version="5.0" xmlns="http://docbook.org/ns/docbook"
+      xmlns:xl="http://www.w3.org/1999/xlink"
+      xmlns:xi="http://www.w3.org/2001/XInclude"
+      xmlns:xhtml="http://www.w3.org/1999/xhtml"
+      xmlns:svg="http://www.w3.org/2000/svg"
+      xmlns:ns="http://docbook.org/ns/docbook"
+      xmlns:mathml="http://www.w3.org/1998/Math/MathML">
+
+  <title>FLOW3 Framework</title>
+
+  <!-- Meta information -->
+
+  <info>
+    <abstract>
+      <para>FLOW3 is a modern application framework for enterprise-grade PHP
+      applications. This reference describes FLOW3's main features.</para>
+    </abstract>
+
+    <author>
+      <personname>
+        <firstname>Robert</firstname>
+
+        <surname>Lemke</surname>
+      </personname>
+
+      <email>robert@typo3.org</email>
+    </author>
+
+    <author>
+      <personname>
+        <firstname>Karsten</firstname>
+
+        <surname>Dambekalns</surname>
+      </personname>
+
+      <email>karsten@typo3.org</email>
+    </author>
+
+    <copyright>
+      <year>2007</year>
+
+      <year>2008</year>
+
+      <year>2009</year>
+
+      <holder>Robert Lemke</holder>
+
+      <holder>Karsten Dambekalns</holder>
+    </copyright>
+  </info>
+
+  <!-- Chapters -->
+
+  <xi:include href="Introduction.xml" />
+
+       <xi:include href="MVCFramework.xml" />
+
+       <xi:include href="PersistenceFramework.xml" />
+
+  <!-- Appendixes -->
+
+  <xi:include href="AppendixCodingGuidelines.xml" />
+
+</book>
diff --git a/typo3/sysext/extbase/Documentation/Manual/en/Introduction.xml b/typo3/sysext/extbase/Documentation/Manual/en/Introduction.xml
new file mode 100644 (file)
index 0000000..5a97526
--- /dev/null
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter version="5.0" xmlns="http://docbook.org/ns/docbook"
+         xmlns:ns6="http://www.w3.org/1999/xlink"
+         xmlns:ns5="http://www.w3.org/2000/svg"
+         xmlns:ns4="http://www.w3.org/1999/xhtml"
+         xmlns:ns3="http://www.w3.org/1998/Math/MathML"
+         xmlns:ns="http://docbook.org/ns/docbook">
+  <title>Introduction</title>
+
+  <para>FLOW3 is a PHP-based application framework. It is especially
+  well-suited for enterprise-grade applications and explicitly supports
+  Domain-Driven Design, a powerful software design philosophy. Convention over
+  configuration, Test-Driven Development, Continuous Integration and an
+  easy-to-read source code are other important principles we follow for the
+  development of FLOW3.</para>
+
+  <para>Although we created FLOW3 as the foundation for the TYPO3 Content
+  Management System, its approach is general enough to be useful as a basis
+  for any other PHP application. We're happy to share the FLOW3 framework with
+  the whole PHP community and are looking forward to the hundreds of new
+  features and enhancements contributed as packages by other enthusiastic
+  developers. In fact most of the packages which will be developed for the
+  TYPO3 CMS can be used in any other FLOW3-based application. In essence this
+  reflects the vision of the TYPO3 project: "Inspiring People to
+  Share".</para>
+
+  <para>This reference describes all features of FLOW3 and provides you with
+  in-depth information. If you'd like to get a feeling for FLOW3 and get
+  started quickly, we suggest that you try out our Getting Started tutorial
+  first.</para>
+
+  <note>
+    <para>Please note that FLOW3 is still under heavy development. Although we
+    hope that the documentation is at least accurate and up to date, it is by
+    no means complete and most likely not proof-read. If you find errors or
+    would like to help us improving the documentation, we're happy to hear
+    from you on our mailing list!</para>
+  </note>
+
+  <section>
+    <title>Overview</title>
+
+    <para>The FLOW3 framework is composed of the following submodules:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>The <emphasis>FLOW3</emphasis> bootstrap takes care of
+        configuring and initializing the whole framework.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Package</emphasis> Manager allows you to download,
+        install, configure and uninstall packages.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Object</emphasis> Manager is in charge of
+        building, caching and combining objects.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Configuration Framework</emphasis> reads and
+        cascades various kinds of configuration from different sources and
+        provides access to it.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Resource</emphasis> Manager contains functions for
+        providing, caching, securing and retrieving resources.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>MVC</emphasis> Framework takes care of requests
+        and responses and provides you with a powerful, easy-to use
+        Model-View-Controller implementation.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Cache</emphasis> framework provides different
+        kinds of caches with can be combined with a selection of cache
+        backends.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Error</emphasis> module handles errors and
+        exceptions and provides utility classes for this purpose.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Log</emphasis> module provides simple but powerful
+        means to log any kind of event or signal into different types of
+        backends.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Signal Slot</emphasis> module implements the
+        event-driven concept of signals and slots through AOP aspects.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Validation</emphasis> module provides a validation
+        and filtering framework with built-in rules as well as support for
+        custom validation of any object.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Property</emphasis> module implements the concept
+        of property editors and is used for setting and retrieving object
+        properties.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Reflection</emphasis> API complements PHP's
+        built-in reflection support by advanced annotation handling and a
+        cached reflection service.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>AOP</emphasis> Framework enables you to use the
+        powerful techniques of <firstterm>Aspect Oriented
+        Programming</firstterm>.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Persistence</emphasis> module allows you to
+        transparently persist your objects following principles of
+        <emphasis>Domain Driven Design</emphasis>.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Security</emphasis> Framework enforces security
+        policies and provides an API for managing those.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Session</emphasis> Framework takes care of session
+        handling and storing session information in different backends</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Locale</emphasis> service manages languages and
+        other regional settings and makes them accessible to other packages
+        and FLOW3 sub packages.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <emphasis>Utility</emphasis> module is a library of useful
+        general-purpose functions for file handling, algorithms, environment
+        abstraction and more.</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>If you are overwhelmed by the amount of information in this
+    reference, just keep in mind that you don't need to know all of it to
+    write your own FLOW3 packages. You can always come back and look up a
+    specific topic once you need to know about it - that's what references are
+    for. But even if you don't need to know everything, we recommend that you
+    get familiar with the concepts of each module and read the whole manual.
+    This way you make sure that you don't miss any of the great features FLOW3
+    provides and hopefully feel inspired to produce clean and
+    easy-maintainable code.</para>
+
+    <tip>
+      <para>A strong coffee helps most people over even the longest
+      documentation.</para>
+    </tip>
+  </section>
+</chapter>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Documentation/Manual/en/MVCFramework.xml b/typo3/sysext/extbase/Documentation/Manual/en/MVCFramework.xml
new file mode 100644 (file)
index 0000000..3c2c591
--- /dev/null
@@ -0,0 +1,651 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter version="5.0" xmlns="http://docbook.org/ns/docbook"
+         xmlns:ns52="http://www.w3.org/1998/Math/MathML"
+         xmlns:ns5="http://www.w3.org/1999/xlink"
+         xmlns:ns4="http://www.w3.org/2000/svg"
+         xmlns:ns3="http://www.w3.org/1999/xhtml"
+         xmlns:ns="http://docbook.org/ns/docbook">
+  <title>MVC Framework</title>
+
+  <section>
+    <title>Introduction</title>
+
+    <section>
+      <title>Model-View-Controller</title>
+
+      <para>In the design of FLOW3's architecture we have taken great care to
+      separate concerns and assign each part of the framework with
+      well-defined tasks. The separation of concerns is an important principle
+      of good software design and its most prominent representative probably
+      is the Model-View-Controller pattern. MVC separates the business logic
+      from the presentation by splitting up user interaction into three
+      roles:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>The <emphasis>model</emphasis> is an object which contains
+          data and business logic of a certain domain. It doesn't contain any
+          information about the presentation of that data, but rather defines
+          the behaviour. In the FLOW3 project we prefer a special kind of
+          model, the <link
+          ns5:href="http://martinfowler.com/eaaCatalog/domainModel.html">Domain
+          Model</link>.</para>
+        </listitem>
+
+        <listitem>
+          <para>The <emphasis>view</emphasis> represents the display of the
+          model on the web or another output channel. Views only display data,
+          they don't build or modify it.</para>
+        </listitem>
+
+        <listitem>
+          <para>The <emphasis>controller</emphasis> reacts on user input,
+          selects and manipulates the model as accordingly, selects a view and
+          passes it the prepared model for rendering.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>This diagram outlines the collaboration between model, view and
+      controller:</para>
+
+      <figure>
+        <title>Model-View-Controller Pattern</title>
+
+        <mediaobject>
+          <imageobject>
+            <imagedata contentdepth="100%"
+                       fileref="MVCFramework_ModelViewController.png"
+                       scalefit="1" width="100%"></imagedata>
+          </imageobject>
+        </mediaobject>
+      </figure>
+    </section>
+
+    <section>
+      <title>Other Patterns Used</title>
+
+      <para>Design Patterns (and MVC is one of them) are not only great for
+      solving reoccuring design problems in a structured manner - they also
+      help you communicating software designs. The following patterns play an
+      important role in FLOW3's MVC mechanism and might give you a better idea
+      of the overall design:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>Incoming requests are handled by a Request Handler which takes
+          the role of a <link ns5:href="???">Front Controller</link>.</para>
+        </listitem>
+
+        <listitem>
+          <para><link ns5:href="???">Template View</link> is the most commonly
+          used pattern for views, but <link ns5:href="???">Transform
+          Views</link> and <link ns5:href="???">Two-Step Views</link> are
+          equally supported.</para>
+        </listitem>
+
+        <listitem>
+          <para>The preferred type of model is the <link ns5:href="???">Domain
+          Model</link>.</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title>Hello World!</title>
+
+      <para>Let's start with an example before we go into greater detail of
+      request handling and the internals of the MVC framework. The minimal
+      approach is to create an Action Controller which just returns
+      <quote>Hello World!</quote>. To begin with, we need to create some
+      directories which contain the code of our FLOW3 package and eventually
+      the controller class:</para>
+
+      <literallayout>Packages/
+  Demo/
+    Classes/
+      Controller/
+        DefaultController.php</literallayout>
+
+      <para>The DefaultController class looks as simple as this (leaving out
+      the very recommended comments):</para>
+
+      <example>
+        <title>Hello World! controller</title>
+
+        <programlisting language="PHP">namespace F3\Demo\Controller;
+
+class DefaultController extends \F3\FLOW3\MVC\Controller\ActionController {
+   public function indexAction() {
+      return "Hello World!";
+   }
+}</programlisting>
+      </example>
+
+      <para>Provided that the document root of your local server points to
+      FLOW3's <filename>Public/</filename> directory, you will get the
+      following output when calling the URI
+      <uri>http://localhost/demo/</uri>:</para>
+
+      <screen>Hello World!</screen>
+
+      <para>Great, that was easy - but didn't we say that it's the view's
+      responsibility to take care of the presentation? Let's create a simple
+      PHP-based view for that purpose:</para>
+
+      <literallayout>Packages/
+  Demo/
+    Classes/
+      Controller/
+        DefaultController.php
+      View/
+        DefaultIndex.php</literallayout>
+
+      <para>The view's code is equally trivial:</para>
+
+      <example>
+        <title>Hello World! view</title>
+
+        <programlisting language="php">namespace F3\Demo\View;
+
+class DefaultIndex extends \F3\FLOW3\MVC\View\AbstractView {
+   public function render() {
+      return "Hello World!";
+   }
+}</programlisting>
+      </example>
+
+      <para>Finally our action controller needs a little tweak to return the
+      rendered view instead of shouting <quote>Hello World!</quote>
+      itself:</para>
+
+      <example>
+        <title>Improved Hello World! controller</title>
+
+        <programlisting language="php">namespace F3\Demo\Controller;
+
+class DefaultController extends \F3\FLOW3\MVC\Controller\ActionController {
+   public function indexAction() {
+      return $this-&gt;view-&gt;render();
+   }
+}</programlisting>
+      </example>
+    </section>
+
+    <section>
+      <title>Recommended File Structure</title>
+
+      <para>As you have seen in the hello world example, conventions for the
+      directory layout simplify your development a lot. There's no need to
+      register controllers, actions or views if you follow our recommended
+      file structure. These are the rules:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>Controllers</emphasis> are located in their own
+          directory <filename>Controller</filename> just below the
+          <filename>Classes</filename> directory of your package. They can
+          have arbitrary names while the
+          <classname>DefaultController</classname> has a special meaning: If
+          the package was specified in the request but no controller, the
+          <classname>DefaultController</classname> will be used.</para>
+        </listitem>
+
+        <listitem>
+          <para><emphasis>View</emphasis> classes are situated below a
+          <filename>View</filename> directory. The classname of the view is a
+          combination of the name of the controller and the name of the
+          action.</para>
+        </listitem>
+      </itemizedlist>
+
+      <para>This sample directory layout demonstrates the above rules:</para>
+
+      <example>
+        <title>Sample file structure</title>
+
+        <literallayout>Packages/
+  Demo/
+    Classes/
+      Controller/
+        DefaultController.php
+        CustomerController.php
+        OrderController.php
+      View/
+        DefaultIndex.php
+        CustomerIndex.php
+        CustomerList.php
+        CustomerDetails.php
+        OrderList.php</literallayout>
+      </example>
+
+      <para>Adhering to these conventions has the advantage that the classname
+      of the view for example is resolved automatically. However it is
+      possible (and not really difficult) to deviate from this layout and have
+      a completely different structure.</para>
+    </section>
+
+    <section>
+      <title>From the URI to the view</title>
+
+      <caution>
+        <para>For the example URIs we assume that the web root directory of
+        your local server points to FLOW3's <filename>public/</filename>
+        directory. If that's not the case you have to extend the URI
+        accordingly.</para>
+      </caution>
+
+      <para>FLOW3 provides a standard way of resolving the URI to your
+      MVC-Objects.</para>
+
+      <para>Say, you want to see the list of customers (based on the
+      file-structure-example above). The URI to get the list would be:
+      <uri>http://localhost/demo/customer/list.html</uri> or just
+      <uri>http://localhost/demo/customer/list</uri>.</para>
+
+      <para>This URI will be resolved into the package-name
+      (<emphasis>Demo</emphasis>), controller-name
+      (<emphasis>Customer</emphasis>), action-name(<emphasis>list</emphasis>)
+      and format-name (<emphasis>html</emphasis> - which is the default
+      format).</para>
+
+      <para>Depending on that, the controller
+      <classname>\F3\Demo\Controller\CustomerController</classname> (Pattern:
+      '<code>F3\@package\Controller\@controllerController'</code>) and its
+      method <methodname>listAction()</methodname> will be used. The
+      corresponding view is <classname>\F3\Demo\View\CustomerList</classname>
+      (Pattern:
+      <code>'F3\@package\View\@controller@action@format'</code>).</para>
+
+      <para>If you have a look at the view pattern, you see, that you can
+      easily add a view that creates an xml-output by creating the class
+      <classname>\F3\Demo\View\CustomerListXML</classname>. You will get the
+      xml-output by calling the URI
+      <uri>http://localhost/demo/customer/list.xml</uri>.</para>
+    </section>
+  </section>
+
+  <section>
+    <title>Request and Response</title>
+
+    <para>No matter if a FLOW3 application runs in a web context or is
+    launched from the command line, the basic workflow is always the same: The
+    user request is analyzed and forwarded to an appropriate controller which
+    decides on which actions to take and finally returns a response which is
+    handed over to the user. This section highlights the flow and the
+    collaborators in the request-response machinery.</para>
+
+    <section>
+      <title>Request Processing Overview</title>
+
+      <para>A sequence diagram is worth a thousand words said my grandma, so
+      let's take a look at the standard request-response workflow in
+      FLOW3:</para>
+
+      <figure>
+        <title>Example of a Web Request-Response Workflow</title>
+
+        <mediaobject>
+          <imageobject>
+            <imagedata contentdepth="100%"
+                       fileref="MVCFramework_RequestResponseWorkflow.png"
+                       scalefit="1" width="100%"></imagedata>
+          </imageobject>
+        </mediaobject>
+      </figure>
+
+      <para>As you see, there are a lot of parts of the framework involved for
+      answering a request - and the diagram doesn't even consider caching or
+      forwarding of requests. But we didn't create this structure just for the
+      fun of it - each object plays an important role as you'll see in the
+      next sections.</para>
+    </section>
+
+    <section>
+      <title>Request Handler</title>
+
+      <para>The request handler takes the important task to handle and respond
+      to a request. There exists exactly one request handler for each request
+      type. By default web and command line requests are supported, but more
+      specialized request handlers can be developed, too.</para>
+
+      <para>Before one of the request handlers comes to play, the framework
+      needs to determine which of them is the most suitable for the current
+      request. The request handler resolver asks all of the registered request
+      handlers to rate on a scale how well they can handle the current raw
+      request. The resolver then chooses the request handler with the most
+      points and passes over the control.</para>
+
+      <para>Custom request handlers for special purposes just need to
+      implement the
+      <interfacename>\F3\FLOW3\MVC\RequestHandlerInterface</interfacename>.
+      All classes implementing that interface are automatically registered and
+      will be considered while resolving a suitable request handler.</para>
+    </section>
+
+    <section>
+      <title>Request Builder</title>
+
+      <para>When a request handler receives a raw request, it needs to build a
+      request object which can be passed to the dispatcher and later to the
+      controller. The request building delegated to a request builder which
+      can build the required request type (ie. web, CLI etc.).</para>
+
+      <para>The building process mainly consists of</para>
+
+      <procedure>
+        <step>
+          <para>create a new request object</para>
+        </step>
+
+        <step>
+          <para>set some request-type specific parameters (like the request
+          URI for a web request)</para>
+        </step>
+
+        <step>
+          <para>determine and set the responsible controller, action and
+          action arguments</para>
+        </step>
+      </procedure>
+
+      <para>Especially the last step is important and requires some more or
+      less complex routing in case of web requests.</para>
+    </section>
+
+    <section>
+      <title>Request Processors</title>
+
+      <para>Requests which were built by the request builder usually fit the
+      most common needs. For special demands it is possible to postprocess the
+      request object before it is sent to the dispatcher. Request processors
+      can be registered through the Request Processor Chain Manager and are -
+      as the name suggests - invoked in a chain.</para>
+    </section>
+
+    <section>
+      <title>Request Dispatcher</title>
+
+      <para>The final task of the MVC framework consists in dispatching the
+      request to the controller specified in the request object. The request
+      dispatcher will try to call the action specified in the request object
+      and if none was specified fall back on a default action.</para>
+
+      <note>
+        <para>There are more features planned for the dispatcher, but at the
+        time of this writing they have not yet been implemented.</para>
+      </note>
+    </section>
+
+    <section>
+      <title>Request Types</title>
+
+      <para>FLOW3 supports the most important request types out of the box.
+      Additional request types can easily be implemented by extending the
+      <classname>\F3\FLOW3\MVC\Request</classname> class and registering a
+      request handling which can handle the new request type (and takes care
+      of building the request object). Here are the request types which come
+      with the default FLOW3 distribution:</para>
+
+      <section>
+        <title>Web Request / Response</title>
+
+        <para>Web requests are the most common request types. Currently only
+        the basic features are implemented, but further options - especially
+        for the web response - are in the pipeline.</para>
+      </section>
+
+      <section>
+        <title>CLI Request / Response</title>
+
+        <para>Requests from the command line are recognized by the used SAPI
+        (Server Application Programming Interface). This request type is
+        basically the same as the generic request type and mainly exists as a
+        marker.</para>
+      </section>
+
+      <section>
+        <title>AJAX Request / Response</title>
+
+        <note>
+          <para>This request type has not yet been implemented</para>
+        </note>
+      </section>
+    </section>
+  </section>
+
+  <section>
+    <title>Controller</title>
+
+    <para></para>
+
+    <section>
+      <title>Action Controller</title>
+
+      <para>Setting $this-&gt;viewObjectName to a view object name overrides
+      the automatic resolving of the view name. Can be used for definining a
+      standard view, for example \F3\Fluid\View\TemplateView.</para>
+
+      <para></para>
+
+      <section>
+        <title>Initialization Methods</title>
+
+        <para>initializeController</para>
+
+        <para>initializeAction</para>
+
+        <para>initializeView</para>
+      </section>
+
+      <section>
+        <title>Configuration</title>
+
+        <para></para>
+      </section>
+
+      <section>
+        <title>Supported Request Types</title>
+
+        <para></para>
+      </section>
+
+      <section>
+        <title>Arguments</title>
+
+        <para></para>
+      </section>
+
+      <section>
+        <title>Action Methods</title>
+
+        <para>$this-&gt;indexActionMethodName</para>
+
+        <para></para>
+      </section>
+
+      <section>
+        <title>Action View</title>
+
+        <para>- $this-&gt;initializeView = TRUE | FALSE</para>
+      </section>
+    </section>
+
+    <section>
+      <title>Other Controllers</title>
+
+      <section>
+        <title>Abstract Controller</title>
+
+        <para></para>
+      </section>
+
+      <section>
+        <title>Request Handling Controller</title>
+
+        <para></para>
+      </section>
+
+      <section>
+        <title>Default Controller</title>
+
+        <para></para>
+      </section>
+
+      <section>
+        <title>Not Found Controller</title>
+
+        <para>The
+        <classname>F3\FLOW3\MVC\Controller\NotFoundController</classname> is
+        used whenever no other controller could be resolved which would match
+        the current request. It displays a generic "404 Page Not Found"
+        message.</para>
+
+        <para>It is possible to define your own custom controller which is
+        used in these cases. Just specify the object name in the FLOW3
+        settings.</para>
+      </section>
+    </section>
+  </section>
+
+  <section>
+    <title>View</title>
+
+    <para></para>
+
+    <section>
+      <title>Template View</title>
+
+      <para></para>
+    </section>
+
+    <section>
+      <title>Special Views</title>
+
+      <section>
+        <title>Default View</title>
+
+        <para></para>
+      </section>
+
+      <section>
+        <title>Empty View</title>
+
+        <para></para>
+      </section>
+    </section>
+  </section>
+
+  <section>
+    <title>Helpers</title>
+
+    <para></para>
+  </section>
+
+  <section>
+    <title>Model</title>
+
+    <para></para>
+  </section>
+
+  <section>
+    <title>Routing</title>
+
+    <para></para>
+  </section>
+
+  <section>
+    <title>CLI request handling</title>
+
+    <para>FLOW3's CLI request handling offers a comfortable and flexible way
+    of calling code from the command line:</para>
+
+    <para><command>php index.php [<replaceable>command</replaceable>]
+    [<replaceable>options</replaceable>] [--]
+    [<replaceable>arguments</replaceable>]</command></para>
+
+    <para><replaceable>command</replaceable>,
+    <replaceable>options</replaceable> and
+    <replaceable>arguments</replaceable> are optional, with varying results.
+    The command structure follows what is commonly accpeted on unixoid systems
+    for CLI programs:<variablelist>
+        <varlistentry>
+          <term>command</term>
+
+          <listitem>
+            <para>If not given, the default controller of the FLOW3 package is
+            used and it's index action is called. While this is an allowed
+            call, it hardly makes sense (other than checking if FLOW basically
+            works). If command is given then it is defined as
+            <emphasis><replaceable>package</replaceable>
+            [[<replaceable>sub1..N</replaceable>]
+            <replaceable>controller</replaceable>
+            <replaceable>action</replaceable>]</emphasis></para>
+
+            <para>First part is always the package. If only the package is
+            given, it's default controller's index action is called.</para>
+
+            <para>If at least three command parts are given, the last two
+            sepcify controller and action. Anything in between specifys a sub
+            package structure.<example>
+                <title>Some FLOW3 CLI command specifications</title>
+
+                <para><literal>testing cli run</literal> would call the "run"
+                action of the "cli" controller in the "Testing" package</para>
+
+                <para><literal>typo3cr admin setup default</literal> would
+                call the "setup" controller's "default" action in the
+                subpackage "admin" of the package "TYPO3CR"</para>
+              </example></para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>options</term>
+
+          <listitem>
+            <para>Options are either short- or long-style. The first option
+            detected ends collecting command parts. Here are some
+            examples:<example>
+                <title>Giving options to FLOW3 CLI requests</title>
+
+                <para><literal>-o -f=value --a-long-option --with-spaces="is
+                possible" --input file1 -o=file2 --event-this =
+                works</literal></para>
+              </example></para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>arguments</term>
+
+          <listitem>
+            <para>Arguments can follow and will be available to the called
+            controller in the request object. To distinguish between
+            <replaceable>command</replaceable> and
+            <replaceable>arguments</replaceable> in cases where no
+            <replaceable>options</replaceable> are given the seperator
+            <literal>--</literal> must be used.</para>
+          </listitem>
+        </varlistentry>
+      </variablelist></para>
+
+    <example>
+      <title>Some FLOW3 CLI commands</title>
+
+      <para>Calling the TYPO3CR setup:</para>
+
+      <para><code>php index.php typo3cr admin setup setup
+      --dsn=sqlite:/tmp/typo3cr.db --indexlocation=/tmp/lucene/</code></para>
+
+      <para>Running FLOW3 unit tests:</para>
+
+      <para><code>php index.php testing cli run --package-key=FLOW3
+      --output-directory=./</code></para>
+
+      <para>Rendering the FLOW3 documentation to HTML:</para>
+
+      <para><code>php index.php doctools render render -p FLOW3 -o
+      flow3-manual/</code></para>
+    </example>
+  </section>
+</chapter>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Documentation/Manual/en/MVCFramework_ModelViewController.png b/typo3/sysext/extbase/Documentation/Manual/en/MVCFramework_ModelViewController.png
new file mode 100755 (executable)
index 0000000..fe30d11
Binary files /dev/null and b/typo3/sysext/extbase/Documentation/Manual/en/MVCFramework_ModelViewController.png differ
diff --git a/typo3/sysext/extbase/Documentation/Manual/en/MVCFramework_RequestResponseWorkflow.png b/typo3/sysext/extbase/Documentation/Manual/en/MVCFramework_RequestResponseWorkflow.png
new file mode 100644 (file)
index 0000000..6b5e542
Binary files /dev/null and b/typo3/sysext/extbase/Documentation/Manual/en/MVCFramework_RequestResponseWorkflow.png differ
diff --git a/typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework.xml b/typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework.xml
new file mode 100644 (file)
index 0000000..f7db2f0
--- /dev/null
@@ -0,0 +1,336 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter version="5.0" xmlns="http://docbook.org/ns/docbook"
+         xmlns:xl="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         xmlns:xhtml="http://www.w3.org/1999/xhtml"
+         xmlns:svg="http://www.w3.org/2000/svg"
+         xmlns:ns="http://docbook.org/ns/docbook"
+         xmlns:mathml="http://www.w3.org/1998/Math/MathML">
+  <title>Persistence Framework</title>
+
+  <section>
+    <title>Introductory Example</title>
+
+    <para>Let's look at the following example as an introduction to how FLOW3
+    handles persistence. We have a domain model of a Blog, consisting of Blog,
+    Post, Comment and Tag objects:<figure>
+        <title>The objects of the Blog domain model</title>
+
+        <mediaobject>
+          <imageobject>
+            <imagedata contentdepth="100%"
+                       fileref="PersistenceFramework_BlogDomainModel.png"
+                       scalefit="1" width="100%"></imagedata>
+          </imageobject>
+        </mediaobject>
+      </figure></para>
+
+    <para>Connections between those objects are built by simple references in
+    PHP, as a look at the <methodname>addPost()</methodname> method of the
+    <classname>Blog</classname> class shows:<example>
+        <title>The Blog's addPost() method</title>
+
+        <para><programlisting language="php">/**
+ * @param \F3\Blog\Domain\Post $post
+ * @return void
+ */
+public function addPost(\F3\Blog\Domain\Post $post) {
+    $this-&gt;posts[$post-&gt;getIdentifier()] = $post;
+}</programlisting></para>
+      </example></para>
+
+    <para>The same principles are applied to the rest of the classes,
+    resulting in an object tree of a blog object holding several posts, those
+    in turn having references to their associated comments and tags. But now
+    we need to make sure the Blog and the data in it are still available the
+    next time we need them. In the good old days of programming you might have
+    added some ugly database calls all over the system at this point. In the
+    currently widespread practice of loving Active Record you'd still add
+    save() methods to all or most of your objects. But can it be even
+    easier?</para>
+
+    <para>To access an object you need to hold some reference to it. You can
+    get that reference by creating an object or by following some reference to
+    it from some object you already have. This leaves you at a point where you
+    need to find that "first object". This is done by using a Repository. A
+    Repository is the librarian of your system, knowing about all the objects
+    it manages. In our model the Blog is the entry point to our object tree,
+    so we will add a BlogRepository, allowing us to find Blogs by the criteria
+    we need.</para>
+
+    <para>Now, before we can find a Blog, we need to create and save one. What
+    we do is create the object (using FLOW3's object factory) and add it to
+    the BlogRepository. This will automagically persist your Blog and you can
+    retrieve it again later. No save() call needed. Oh, and the posts,
+    comments and tags in your Blog are persisted as well, of course.</para>
+
+    <para>For all that magic to work as expected, you need to give some hints.
+    This doesn't mean you need to write tons of XML, a few annotations in your
+    code are enough:<example>
+        <title>Persistence-related annotations in the Blog class</title>
+
+        <para><programlisting language="php">/**
+ * A Blog object
+ *
+ * @package Blog
+ * @entity
+ */
+class Blog {
+
+    /**
+     * @var string
+     */
+    protected $title;
+
+    /**
+     * @var array
+     */
+    protected $posts = array();
+
+  ...
+
+}</programlisting></para>
+      </example>The first annotation to note is the
+    <emphasis>@entity</emphasis> annotation, which tells the persistence
+    framework it needs to persist Blog instances if they have been added to a
+    Repository. In the Blog class we have some member variables, they are
+    persisted as well by default. The persistence framework knows their types
+    by looking at the <emphasis>@var</emphasis> annotation you use anyway when
+    documenting your code (you do document your code, right?). In case of the
+    $posts array the persistence framework persists the objects held in that
+    array as independent objects. Apart from those annotations your domain
+    object's code is completely unaware of the persistence
+    infrastructure.</para>
+
+    <para>Let's conclude by taking a look at the BlogRepository code:<example>
+        <title>Code of a simple BlogRepository</title>
+
+        <programlisting language="php">/**
+ * A BlogRepository
+ *
+ * @package Blog
+ */
+class BlogRepository extends \F3\FLOW3\Persistence\Repository {
+
+    /**
+     * Finds Blogs with a matching name.
+     *
+     * @param string $name
+     * @return array
+     */
+    public function findByName($name) {
+        $query = $this-&gt;createQuery();
+        return $query-&gt;matching($query-&gt;equals('name', $name))-&gt;execute();
+    }
+}</programlisting>
+      </example>As you can see we get away with very little code by simply
+    extending the FLOW3-provided repository class. Nice, eh? If you like to do
+    things the hard way you can get away with implementing
+    <interfacename>\F3\FLOW3\Persistence\RepositoryInterface</interfacename>
+    yourself.</para>
+  </section>
+
+  <section>
+    <title>On the priciples of DDD</title>
+
+    <para>From Evans, the rules we need to enforce include:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>The root Entity has global identity and is ultimately
+        responsible for checking invariants.</para>
+      </listitem>
+
+      <listitem>
+        <para>Root Entities have global identity. Entities inside the boundary
+        have local identity, unique only within the Aggregate.</para>
+      </listitem>
+
+      <listitem>
+        <para>Nothing outside the Aggregate boundary can hold a reference to
+        anything inside, except to the root Entity. The root Entity can hand
+        references to the internal Entities to other objects, but they can
+        only use them transiently (within a single method or block).</para>
+      </listitem>
+
+      <listitem>
+        <para>Only Aggregate Roots can be obtained directly with database
+        queries. Everything else must be done through traversal.</para>
+      </listitem>
+
+      <listitem>
+        <para>Objects within the Aggregate can hold references to other
+        Aggregate roots.</para>
+      </listitem>
+
+      <listitem>
+        <para>A delete operation must remove everything within the Aggregate
+        boundary all at once.</para>
+      </listitem>
+
+      <listitem>
+        <para>When a change to any object within the Aggregate boundary is
+        committed, all invariants of the whole Aggregate must be
+        satisfied.</para>
+      </listitem>
+    </itemizedlist>
+  </section>
+
+  <section>
+    <title>Persistence-related annotations</title>
+
+    <para>The following table lists all annotations used by the persistence
+    framework with their name, scope and meaning:<table>
+        <title>Persistence-related code annotations</title>
+
+        <tgroup cols="3">
+          <colspec colwidth="1*" />
+
+          <colspec colwidth="1*" />
+
+          <colspec colwidth="4*" />
+
+          <thead>
+            <row>
+              <entry>Annotation</entry>
+
+              <entry>Scope</entry>
+
+              <entry>Meaning</entry>
+            </row>
+          </thead>
+
+          <tbody>
+            <row>
+              <entry>@entity</entry>
+
+              <entry>Class</entry>
+
+              <entry>Declares a class as an Entity.</entry>
+            </row>
+
+            <row>
+              <entry>@valueobject</entry>
+
+              <entry>Class</entry>
+
+              <entry>Declares a class as a Value Object, allowing the
+              persistence framework to reuse an existing object if one
+              exists.</entry>
+            </row>
+
+            <row>
+              <entry>@var</entry>
+
+              <entry>Variable</entry>
+
+              <entry>Is used to detect the type a variable has.</entry>
+            </row>
+
+            <row>
+              <entry>@transient</entry>
+
+              <entry>Variable</entry>
+
+              <entry>Makes the persistence framework ignore the variable.
+              Neither will it's value be persisted, nor will it be touched
+              during reconstitution.</entry>
+            </row>
+
+            <row>
+              <entry>@uuid</entry>
+
+              <entry>Variable</entry>
+
+              <entry>Marks the variable as being the object uuid. This makes
+              the persistence backend use the value of this variable as
+              identifier for the internal representation of the object.
+              <emphasis>You must make sure your identifier is an
+              UUID.</emphasis></entry>
+            </row>
+
+            <row>
+              <entry>@identity</entry>
+
+              <entry>Variable</entry>
+
+              <entry>Marks the variable as being relevant for determining the
+              identity of an object in the domain.</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </table></para>
+  </section>
+
+  <section>
+    <title>Inside the Persistence Framework</title>
+
+    <para>To the domain code the persistence handling transparent, aside from
+    the need to add a few annotations. The custom repositories are a little
+    closer to the inner workings of the framework, but still the inner
+    workings are very invisible. This is how it is supposed to be, but a
+    little understanding of how persistence works internally can help
+    understand problems and develop more efficient client code.</para>
+
+    <section>
+      <title>Persisting a domain object</title>
+
+      <para>After an object has been added to a repository it will be seen
+      when FLOW3 calls <methodname>persistAll()</methodname> at the end of a
+      script run. Internally all instances implementing the
+      <interfacename>\F3\FLOW3\Persistence\RepositoryInterface</interfacename>
+      will be fetched and asked for the objects they hold. Those will then be
+      handed to the persistence backend in use and processed by it.</para>
+
+      <para>FLOW3 defines interfaces for persistence backends and queries, the
+      details of how objects are persisted and queried are up to the
+      persistence backend implementation. Have a look at the documentatoin of
+      the respective package for more information. The following diagram shows
+      (most of) the way an object takes from creation until it is persisted
+      when using the TYPO3 Content Repository:</para>
+
+      <para><figure>
+          <title>Object persistence process</title>
+
+          <mediaobject>
+            <imageobject>
+              <imagedata contentdepth="100%"
+                         fileref="PersistenceFramework_PersistenceProcess.png"
+                         scalefit="1" width="100%"></imagedata>
+            </imageobject>
+          </mediaobject>
+        </figure>Keep in mind that the diagram omits some details like dirty
+      checking on objects and how exactly objects and their properties are
+      stored in the Content Repository.</para>
+    </section>
+
+    <section>
+      <title>Querying the storage backend</title>
+
+      <para>As we saw in the introductory example there is a query mechanism
+      available that provides easy fetching of objects through the persistence
+      framework. You ask for instances of a specific class that match certain
+      filters and get back an array of those reconstituted objects. Here is a
+      diagram of the internal process when using the TYPO3 Content Repository
+      as persistence backend:<figure>
+          <title>Object querying and reconstitution process</title>
+
+          <mediaobject>
+            <imageobject>
+              <imagedata contentdepth="100%"
+                         fileref="PersistenceFramework_QueryProcess.png"
+                         scalefit="1" width="100%"></imagedata>
+            </imageobject>
+          </mediaobject>
+        </figure>For the developer the complexity is hidden between the
+      query's <methodname>execute()</methodname> method and the array of
+      objects being returned. The <classname>QOMFactory</classname>, "right"
+      <classname>Query</classname> and <classname>QueryResult</classname>
+      objects are part of the standard JSR-283 API, whereas
+      <classname>QueryFactory</classname>, "left" <classname>Query</classname>
+      and <classname>DataMapper</classname> are part of the FLOW3 persistence
+      backend implementation that comes with the TYPO3 Content
+      Repository.</para>
+    </section>
+  </section>
+</chapter>
diff --git a/typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_BlogDomainModel.png b/typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_BlogDomainModel.png
new file mode 100644 (file)
index 0000000..5583ac5
Binary files /dev/null and b/typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_BlogDomainModel.png differ
diff --git a/typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_PersistenceProcess.png b/typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_PersistenceProcess.png
new file mode 100644 (file)
index 0000000..6174794
Binary files /dev/null and b/typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_PersistenceProcess.png differ
diff --git a/typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_QueryProcess.png b/typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_QueryProcess.png
new file mode 100644 (file)
index 0000000..5186aed
Binary files /dev/null and b/typo3/sysext/extbase/Documentation/Manual/en/PersistenceFramework_QueryProcess.png differ
index 5ca5129..015f49d 100644 (file)
@@ -1 +1,56 @@
-PLEASE USE THE TODO LIST AT http://forge.typo3.org/wiki/typo3v4-mvc/ToDo_List
\ No newline at end of file
+PLEASE USE THE TODO LIST AT http://forge.typo3.org/wiki/typo3v4-mvc/ToDo_List
+
+public function render($view, $arguments, $templateSource, $variables) {
+ $this->initializeLocalization($view);
+ // SF first replace variables and then translate
+ $key = $arguments['key'];
+ $view->replaceReferencesWithValues($key, $variables);
+ $translation = $this->translate($key);
+ // SF default values wasn't returned
+ $default = $arguments['default'];
+ $view->replaceReferencesWithValues($default, $variables);
+ return (is_string($translation) && !empty($translation)) ? $translation : $default;
+}
+
+
+
+public function render($view, $arguments, $templateSource, $variables) {
+ $condition = FALSE;
+ $keys = array_keys($arguments);
+ $key = $keys[0];
+ $value = $arguments[$key];
+ switch ($key) {
+  case 'istrue':
+   if (($value != '' AND $value != 'false') OR $value > 0) {
+    $condition = TRUE;
+   }
+   break;
+  case 'isfalse':
+   if (empty($value) OR $value == 'false') {
+    $condition = TRUE;
+   }
+   #debug(array($key, $value, $condition), 'isfalse');
+   break;
+  case 'equals':
+   if ($value == $arguments['value']) {
+    $conditon = TRUE;
+   }
+   break;
+  case 'islessthan':
+   if ($value > $arguments['value']) {
+    $condition = TRUE;
+   }
+   break;
+  case 'isgreaterthan':
+   if ($value < $arguments['value']) {
+    $condition = TRUE;
+   }
+   break;
+ }
+#debug(array($key, $value, $condition));
+ if ($condition) {
+  return $view->renderTemplate($templateSource, $variables);
+ }
+
+ return '';
+}
\ No newline at end of file
index fab7c7c..a449f8b 100644 (file)
@@ -64,6 +64,9 @@ class Tx_ExtBase_Dispatcher {
                try {
                        $controller->processRequest($request, $response);
                } catch (Tx_ExtBase_Exception_StopAction $ignoredException) {
+               } catch (Tx_ExtBase_Exception_InvalidArgumentValue $exception) {
+                       $persistenceSession->clear();
+                       return '';
                }
                // var_dump($persistenceSession);
                $persistenceSession->commit();
@@ -128,6 +131,7 @@ class Tx_ExtBase_Dispatcher {
                        if ($classNameParts[0] === 'ux') {
                                array_shift($classNameParts);
                        }
+                       $className = implode('_', $classNameParts);
                        if (count($classNameParts) > 2 && $classNameParts[0] === 'Tx') {
                                $classFilePathAndName = t3lib_extMgm::extPath(strtolower($classNameParts[1])) . 'Classes/';
                                $classFilePathAndName .= implode(array_slice($classNameParts, 2, -1), '/') . '/';
index ff49b96..a9fd7b0 100644 (file)
@@ -12,7 +12,7 @@
 
 $EM_CONF[$_EXTKEY] = array(
        'title' => 'MVC Framework for Extensions',
-       'description' => 'A MVC framework to build extensions: It\'s based on the MVC framework of FLOW3.',
+       'description' => 'A framework to build extensions upon: It\'s based on the MVC framework of FLOW3.',
        'category' => 'plugin',
        'author' => 'Jochen Rau',
        'author_email' => 'jochen.rau@typoplanet.de',
@@ -21,7 +21,7 @@ $EM_CONF[$_EXTKEY] = array(
        'conflicts' => '',
        'priority' => '',
        'module' => '',
-       'state' => 'beta',
+       'state' => 'alpha',
        'internal' => '',
        'uploadfolder' => 0,
        'createDirs' => '',
@@ -33,7 +33,7 @@ $EM_CONF[$_EXTKEY] = array(
        'constraints' => array(
                'depends' => array(
                        'php' => '5.2.0-0.0.0',
-                       'typo3' => '4.3.dev-4.3.99',
+                       'typo3' => '4.2.0-4.3.99',
                ),
                'conflicts' => array(
                ),