11762 use doctrine for schema creation and update
authorCornelius Weiß <c.weiss@metaways.de>
Tue, 5 Apr 2016 07:59:03 +0000 (09:59 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Mon, 27 Jun 2016 11:34:55 +0000 (13:34 +0200)
@TODO
* add 1:n, n:1, n:m
* test onDelete index

Change-Id: I723b7c36e44c4591534a44a8a0ae2fd534db59d3
Reviewed-on: http://gerrit.tine20.com/customers/3062
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
20 files changed:
tests/tine20/Inventory/AllTests.php
tests/tine20/Inventory/DoctrineModelTest.php [new file with mode: 0644]
tine20/Inventory/Controller.php
tine20/Inventory/Export/definitions/i_default_ods.xml
tine20/Inventory/Export/definitions/i_default_xls.xml
tine20/Inventory/Import/definitions/inv_tine_import_csv.xml
tine20/Inventory/Model/InventoryItem.php
tine20/Inventory/Setup/Update/Release9.php [new file with mode: 0644]
tine20/Inventory/Setup/setup.xml
tine20/Inventory/js/InventoryItemEditDialog.js
tine20/Setup/Controller.php
tine20/Setup/Core.php
tine20/Setup/SchemaTool.php [new file with mode: 0644]
tine20/Setup/Update/Abstract.php
tine20/Tinebase/Controller/Abstract.php
tine20/Tinebase/ModelConfiguration.php
tine20/Tinebase/Record/Abstract.php
tine20/Tinebase/Record/DoctrineMappingDriver.php [new file with mode: 0644]
tine20/composer.json
tine20/composer.lock

index 89fc26b..95c3114 100644 (file)
@@ -28,6 +28,7 @@ class Inventory_AllTests
         $suite->addTestSuite('Inventory_JsonTest');
         $suite->addTestSuite('Inventory_ControllerTest');
         $suite->addTestSuite('Inventory_Import_AllTests');
+        $suite->addTestSuite('Inventory_DoctrineModelTest');
         return $suite;
     }
 }
diff --git a/tests/tine20/Inventory/DoctrineModelTest.php b/tests/tine20/Inventory/DoctrineModelTest.php
new file mode 100644 (file)
index 0000000..d781e91
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     Inventory
+ * @subpackage  Record
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2016 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Cornelius Weiß <c.weiss@metaways.de>
+ */
+
+use Doctrine\DBAL\Schema\Comparator;
+
+/**
+ * Test class for Inventory_JsonTest
+ */
+class Inventory_DoctrineModelTest extends Inventory_TestCase
+{
+
+    protected function setUp()
+    {
+    }
+
+    public function testGetMetadataOfInventoryModel()
+    {
+        $em = Setup_SchemaTool::getEntityManager('Inventory', array('Inventory_Model_InventoryItem'));
+
+        $invItemMetadata = $em->getClassMetadata('Inventory_Model_InventoryItem');
+
+        $this->assertEquals('Doctrine\ORM\Mapping\ClassMetadata', get_class($invItemMetadata));
+        $this->assertTrue($invItemMetadata->hasField('name'));
+
+        $mapping = $invItemMetadata->getFieldMapping('name');
+        $this->assertEquals('string', $mapping['type']);
+    }
+
+    public function testExplicitRenameProblemExists()
+    {
+        $em = Setup_SchemaTool::getEntityManager('Inventory');
+        $sm = $em->getConnection()->getSchemaManager();
+
+        // NOTE: the DBAL schema is stateless and 'just' describes a schema in a plattform independend way
+        //       thus, all schema upgrade is based on schema comparisim
+        $fromSchema = $sm->createSchema();
+        $toSchema = clone $fromSchema;
+
+        $table = $toSchema->getTable('tine20_inventory_item');
+
+        $this->setExpectedException('Doctrine\DBAL\DBALException');
+        $table->renameColumn('id', 'ident');
+    }
+
+    public function testExplicitRename()
+    {
+        $this->markTestSkipped('evauate concept for explicit field rename with doctrine2 schema tool');
+        $em = Setup_SchemaTool::getEntityManager('Inventory');
+        $sm = $em->getConnection()->getSchemaManager();
+
+        // NOTE: the DBAL schema is stateless and 'just' describes a schema in a plattform independend way
+        //       thus, all schema upgrade is based on schema comparisim
+
+        $fromSchema = $sm->createSchema();
+        $toSchema = clone $fromSchema;
+
+        $table = $toSchema->getTable('tine20_inventory_item');
+
+
+        // workaround -> might have problems?!
+        $col = $table->getColumn('id');
+        $table->dropColumn('id');
+        $table->addColumn('ident', $col->getType()->getName(), $col->toArray());
+
+        // better create, copy, delete?
+        // @TODO ask some insider
+        //  ? Schema tool can't rename cols, but schema diff with compare (at least with mysql plattform) alters table name correctly when col is renamed in annotations
+
+        // non rename updates are a lot more easy
+        $table->changeColumn('name', array(
+            'length' => 200,
+        ));
+
+        $comparator = new Comparator();
+        $schemaDiff = $comparator->compare($fromSchema, $toSchema);
+
+        $updateSql = $schemaDiff->toSql($em->getConnection()->getDatabasePlatform());
+//        print_r($updateSql);
+    }
+}
index dc8f7e4..06476ec 100644 (file)
@@ -6,7 +6,7 @@
  * @subpackage  Controller
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  * @author      Stefanie Stamer <s.stamer@metaways.de>
- * @copyright   Copyright (c) 2007-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
  *
  */
 
index 83ef826..8bbc466 100644 (file)
@@ -48,7 +48,7 @@
             <identifier>invoice_date</identifier>
         </column>
         <column>
-            <identifier>depreciate_status</identifier>
+            <identifier>deprecated_status</identifier>
         </column>
         <column>
             <identifier>total_number</identifier>
index bd74104..1133ece 100644 (file)
@@ -44,7 +44,7 @@
             <identifier>invoice_date</identifier>
         </column>
         <column>
-            <identifier>depreciate_status</identifier>
+            <identifier>deprecated_status</identifier>
         </column>
         <column>
             <identifier>total_number</identifier>
index cd6600a..1e00738 100644 (file)
@@ -77,7 +77,7 @@
         </field>
         <field>
             <source>Abgeschrieben</source>
-            <destination>depreciate_status</destination>
+            <destination>deprecated_status</destination>
         </field>
         
         <field>
index dd63a3e..18c995e 100644 (file)
@@ -6,7 +6,7 @@
  * @subpackage  Model
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  * @author      Stefanie Stamer <s.stamer@metaways.de>
- * @copyright   Copyright (c) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
  * 
  */
 
@@ -15,6 +15,7 @@
  * 
  * @package     Inventory
  * @subpackage  Model
+ * @property    $name
  */
 class Inventory_Model_InventoryItem extends Tinebase_Record_Abstract
 {
@@ -24,13 +25,14 @@ class Inventory_Model_InventoryItem extends Tinebase_Record_Abstract
      * @var Tinebase_ModelConfiguration
      */
     protected static $_configurationObject = NULL;
-    
+
     /**
      * Holds the model configuration (must be assigned in the concrete class)
      *
      * @var array
      */
     protected static $_modelConfiguration = array(
+        'version'           => 7,
         'recordName'        => 'Inventory item',
         'recordsName'       => 'Inventory items', // ngettext('Inventory item', 'Inventory items', n)
         'containerProperty' => 'container_id',
@@ -49,28 +51,57 @@ class Inventory_Model_InventoryItem extends Tinebase_Record_Abstract
 
         'appName'         => 'Inventory',
         'modelName'       => 'InventoryItem',
-        
+
+        'table'           => array(
+            'name'    => 'inventory_item',
+            'options' => array('collate' => 'utf8_general_ci'),
+            'indexes' => array(
+                'container_id' => array(
+                    'columns' => array('container_id')
+                )
+            ),
+            // not now - is_deleted problem
+//            'uniqueConstraints' => array(
+//                'inventory_id' => array(
+//                    'columns' => array('inventory_id')
+//                )
+//            )
+        ),
+
+
+
         'fields'          => array(
             'name' => array(
+                'type'        => 'string',
+                'length'      => 255,
                 'validators'  => array(Zend_Filter_Input::ALLOW_EMPTY => false, 'presence' => 'required'),
                 'label'       => 'Name', // _('Name')
                 'queryFilter' => TRUE
             ),
             'status' => array(
                 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
+                'nullable' => true,
                 'label' => 'Status', // _('Status')
                 'type' => 'keyfield',
                 'name' => 'inventoryStatus',
             ),
             'inventory_id' => array(
+                'type'       => 'string',
+                'length'     => 100,
+                'nullable'   => true,
                 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
                 'label'      => 'Inventory ID' // _('Inventory ID')
             ),
             'description' => array(
+                'type'       => 'text',
+                'nullable'   => true,
                 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
                 'label'      =>'Description' // _('Description')
             ),
             'location' => array(
+                'type'       => 'string',
+                'length'     => 255,
+                'nullable'   => true,
                 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
                 'label'      => 'Location', // _('Location')
             ),
@@ -81,23 +112,39 @@ class Inventory_Model_InventoryItem extends Tinebase_Record_Abstract
                 'hidden'     => TRUE,
                 'default'    => NULL,
                 'type'       => 'datetime',
+                'nullable'     => true,
                 'inputFilters' => array('Zend_Filter_Empty' => NULL),
             ),
             'total_number' => array(
-                'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
-                'label'      => NULL,
+                'type'         => 'integer',
+                'nullable'     => true,
+                'validators'   => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
+                'label'        => NULL,
                 'inputFilters' => array('Zend_Filter_Empty' => NULL),
-                'default'    => 1,
+                'default'      => 1,
+            ),
+            'active_number' => array(
+                'type'         => 'integer',
+                'nullable'     => true,
+                'validators'   => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
+                'label'        => 'Available number', // _(Available number)
+                'inputFilters' => array('Zend_Filter_Empty' => NULL),
+                'default'      => 1,
             ),
             'invoice' => array(
+                'type'       => 'string',
+                'nullable'   => true,
                 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
                 'label'      => 'Invoice', // _('Invoice')
                 'hidden'     => TRUE
             ),
             'price' => array(
-                'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
-                'label'      => 'Price', // _('Price')
-                'hidden'     => TRUE,
+                'type'         => 'float',
+                'specialType'  => 'euMoney',
+                'nullable'     => true,
+                'validators'   => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
+                'label'        => 'Price', // _('Price')
+                'hidden'       => TRUE,
                 'inputFilters' => array('Zend_Filter_Empty' => NULL),
             ),
             'costcentre' => array(
@@ -105,6 +152,7 @@ class Inventory_Model_InventoryItem extends Tinebase_Record_Abstract
                 'label'      => 'Cost centre', // _('Cost Center')
                 'hidden'     => TRUE,
                 'type'       => 'record',
+                'nullable'   => true,
                 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE, Zend_Filter_Input::DEFAULT_VALUE => NULL),
                 'config' => array(
                     'appName'     => 'Sales',
@@ -117,33 +165,31 @@ class Inventory_Model_InventoryItem extends Tinebase_Record_Abstract
                 'label'      => 'Warranty', // _('Warranty')
                 'hidden'     => TRUE,
                 'inputFilters' => array('Zend_Filter_Empty' => NULL),
-                'type'       => 'datetime'
+                'type'       => 'datetime',
+                'nullable'   => true,
             ),
             'added_date' => array(
                 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
                 'label'      => 'Item added', // _('Item added')
                 'hidden'     => TRUE,
                 'inputFilters' => array('Zend_Filter_Empty' => NULL),
-                'type'       => 'datetime'
+                'type'       => 'datetime',
+                'nullable'   => true,
             ),
             'removed_date' => array(
                 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
                 'label'      => 'Item removed', // _('Item removed')
                 'hidden'     => TRUE,
                 'inputFilters' => array('Zend_Filter_Empty' => NULL),
-                'type'       => 'datetime'
-            ),
-            'active_number' => array(
-                'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
-                'label'      => 'Available number', // _(Available number)
-                'inputFilters' => array('Zend_Filter_Empty' => NULL),
-                'default'    => 1,
-            ),
-            'depreciate_status' => array(
-                'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE, Zend_Filter_Input::DEFAULT_VALUE => 0),
-                //'label' => 'Depreciate', // _('Depreciate')
-                'label'      => NULL,
-                'inputFilters' => array('Zend_Filter_Empty' => NULL),
+                'type'       => 'datetime',
+                'nullable'   => true,
+            ),
+            'deprecated_status' => array(
+                'type'         => 'boolean',
+                'validators'   => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE, Zend_Filter_Input::DEFAULT_VALUE => 0),
+                //'label'        => 'Deprecate', // _('Deprecate')
+                'label'        => NULL,
+                'default'      => false,
             ),
             'image' => array(
                 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => TRUE),
diff --git a/tine20/Inventory/Setup/Update/Release9.php b/tine20/Inventory/Setup/Update/Release9.php
new file mode 100644 (file)
index 0000000..cb075df
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Inventory
+ * @subpackage  Setup
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL3
+ * @copyright   Copyright (c) 2012-2016 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Stefanie Stamer <s.stamer@metaways.de>
+ */
+class Inventory_Setup_Update_Release9 extends Setup_Update_Abstract
+{
+    /**
+     * update to 10.0
+     *
+     * @return void
+     */
+    public function update_0()
+    {
+        // update according to current modelconfigV2 definition using doctrine2
+        // NOTE: depending on update action you might need to move this to a later update
+        //       as your update case might be gone ofter this got executetd in an previoud (this) update
+        $this->updateSchema('Inventory', array('Inventory_Model_InventoryItem'));
+
+        $this->setApplicationVersion('Inventory', '10.0');
+    }
+}
index e632650..3f0abe1 100644 (file)
@@ -2,158 +2,7 @@
 <application>
     <name>Inventory</name>
     <!-- gettext('Inventory') -->   
-    <version>9.0</version>
+    <version>10</version>
     <order>60</order>
     <status>enabled</status>
-    <tables>
-        <table>
-            <name>inventory_item</name>
-            <version>6</version>
-            <declaration>
-                <field>
-                    <name>id</name>
-                    <type>text</type>
-                    <length>40</length>
-                    <notnull>true</notnull>
-                </field>
-                <field>
-                    <name>container_id</name>
-                    <type>integer</type>
-                    <notnull>false</notnull>
-                </field>
-                <field>
-                    <name>name</name>
-                    <type>text</type>
-                    <length>250</length>
-                    <notnull>true</notnull>
-                </field>
-                <!-- keyfield 'status' -->
-                <field>
-                    <name>status</name>
-                    <type>text</type>
-                    <length>40</length>
-                </field>
-                <!-- add more fields here -->
-                <field>
-                    <name>inventory_id</name>
-                    <type>text</type>
-                    <length>100</length>
-                    <notnull>false</notnull>
-                </field>
-                <field>
-                    <name>description</name>
-                    <type>text</type>
-                    <notnull>false</notnull>
-                </field>
-                <field>
-                    <name>location</name>
-                    <type>text</type>
-                    <length>255</length>
-                </field>
-                <field>
-                    <name>total_number</name>
-                    <type>integer</type>
-                    <notnull>false</notnull>
-                </field>
-                <field>
-                    <name>active_number</name>
-                    <type>integer</type>
-                    <notnull>false</notnull>
-                </field>
-                <field>
-                    <name>invoice</name>
-                    <type>text</type>
-                    <length>255</length>
-                </field>
-                <field>
-                    <name>invoice_date</name>
-                    <type>datetime</type>
-                    <notnull>false</notnull>
-                </field>
-                <field>
-                    <name>price</name>
-                    <type>text</type>
-                    <length>50</length>
-                </field>
-                <field>
-                    <name>costcentre</name>
-                    <type>text</type>
-                    <length>255</length>
-                </field>
-                <field>
-                    <name>warranty</name>
-                    <type>datetime</type>
-                </field>
-                <field>
-                    <name>added_date</name>
-                    <type>datetime</type>
-                </field>
-                <field>
-                    <name>removed_date</name>
-                    <type>datetime</type>
-                </field>
-                <field>
-                    <name>depreciate_status</name>
-                    <type>boolean</type>
-                    <default>false</default>
-                </field>
-                <!-- defaults for tine system -->
-                <field>
-                    <name>created_by</name>
-                    <type>text</type>
-                    <length>40</length>
-                </field>
-                <field>
-                    <name>creation_time</name>
-                    <type>datetime</type>
-                </field> 
-                <field>
-                    <name>last_modified_by</name>
-                    <type>text</type>
-                    <length>40</length>
-                </field>
-                <field>
-                    <name>last_modified_time</name>
-                    <type>datetime</type>
-                </field>
-                <field>
-                    <name>is_deleted</name>
-                    <type>boolean</type>
-                    <default>false</default>
-                </field>
-                <field>
-                    <name>deleted_by</name>
-                    <type>text</type>
-                    <length>40</length>
-                </field>
-                <field>
-                    <name>deleted_time</name>
-                    <type>datetime</type>
-                </field>
-                <field>
-                    <name>seq</name>
-                    <type>integer</type>
-                    <notnull>true</notnull>
-                    <default>0</default>
-                </field>
-                <field>
-                    <name>adt_info</name>
-                    <type>text</type>
-                </field>
-                <index>
-                    <name>id</name>
-                    <primary>true</primary>
-                    <field>
-                        <name>id</name>
-                    </field>
-                </index>
-                <index>
-                    <name>container_id</name>
-                    <field>
-                        <name>container_id</name>
-                    </field>
-                </index>
-            </declaration>
-        </table>
-    </tables>
 </application>
index 36f976d..b843edb 100644 (file)
@@ -3,7 +3,7 @@
  * 
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  * @author      Stefanie Stamer <s.stamer@metaways.de>
- * @copyright   Copyright (c) 2007-2011 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
  */
 Ext.ns('Tine.Inventory');
 
@@ -281,7 +281,7 @@ Tine.Inventory.InventoryItemEditDialog = Ext.extend(Tine.widgets.dialog.EditDial
                                 xtype: 'checkbox',
                                 hideLabel: true,
                                 boxLabel: this.app.i18n._('Depreciate'),
-                                name: 'depreciate_status'
+                                name: 'deprecated_status'
                         }]
                     ]
                 }]
index e0355ca..95fb44b 100644 (file)
@@ -6,7 +6,7 @@
  * @subpackage  Controller
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  * @author      Lars Kneschke <l.kneschke@metaways.de>
- * @copyright   Copyright (c) 2008-2014 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2008-2016 Metaways Infosystems GmbH (http://www.metaways.de)
  *
  * @todo        move $this->_db calls to backend class
  */
@@ -1455,23 +1455,32 @@ class Setup_Controller
             if (Setup_Core::isLogLevel(Zend_Log::INFO)) Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Installing application: ' . $_xml->name);
 
             $createdTables = array();
+
+            // traditional xml declaration
             if (isset($_xml->tables)) {
                 foreach ($_xml->tables[0] as $tableXML) {
                     $table = Setup_Backend_Schema_Table_Factory::factory('Xml', $tableXML);
-                    $currentTable = $table->name;
-
-                    if (Setup_Core::isLogLevel(Zend_Log::DEBUG)) Setup_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Creating table: ' . $currentTable);
-
-                    try {
-                        $this->_backend->createTable($table);
-                    } catch (Zend_Db_Statement_Exception $zdse) {
-                        throw new Tinebase_Exception_Backend_Database('Could not create table: ' . $zdse->getMessage());
-                    } catch (Zend_Db_Adapter_Exception $zdae) {
-                        throw new Tinebase_Exception_Backend_Database('Could not create table: ' . $zdae->getMessage());
-                    }
+                    $this->_createTable($table);
                     $createdTables[] = $table;
                 }
             }
+
+            // do we have modelconfig
+            else {
+                // create tables using doctrine 2
+                $application = Setup_Core::getApplicationInstance($_xml->name, '', true);
+                $models = $application->getModels(true /* MCv2only */);
+                Setup_SchemaTool::createSchema($_xml->name, $models);
+
+                // adopt to old workflow
+                foreach($models as $model) {
+                    $modelConfiguration = $model::getConfiguration();
+                    $createdTables[] = (object) array(
+                        'name' => Tinebase_Helper::array_value('name', $modelConfiguration->getTable()),
+                        'version' => $modelConfiguration->getVersion(),
+                    );
+                }
+            }
     
             $application = new Tinebase_Model_Application(array(
                 'name'      => (string)$_xml->name,
@@ -1504,6 +1513,18 @@ class Setup_Controller
         }
     }
 
+    protected function _createTable($table)
+    {
+        if (Setup_Core::isLogLevel(Zend_Log::DEBUG)) Setup_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Creating table: ' . $table->name);
+
+        try {
+            $this->_backend->createTable($table);
+        } catch (Zend_Db_Statement_Exception $zdse) {
+            throw new Tinebase_Exception_Backend_Database('Could not create table: ' . $zdse->getMessage());
+        } catch (Zend_Db_Adapter_Exception $zdae) {
+            throw new Tinebase_Exception_Backend_Database('Could not create table: ' . $zdae->getMessage());
+        }
+    }
     /**
      * look for import definitions and put them into the db
      *
index fd972f0..806745d 100644 (file)
@@ -5,7 +5,7 @@
  * @package     Setup
  * @subpackage  Server
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright   Copyright (c) 2007-2011 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Philipp Schuele <p.schuele@metaways.de>
  *
  */
@@ -271,17 +271,17 @@ class Setup_Core extends Tinebase_Core
         parent::setupLogger($writer);
     }
     
-    /**\r
-     * initializes the build constants like buildtype, package information, ...\r
-     */\r
-    public static function setupBuildConstants()\r
-    {\r
+    /**
+     * initializes the build constants like buildtype, package information, ...
+     */
+    public static function setupBuildConstants()
+    {
         $config = self::getConfig();
         define('TINE20_BUILDTYPE',           strtoupper($config->get('buildtype', 'DEVELOPMENT')));
         define('TINE20SETUP_CODENAME',       Tinebase_Helper::getDevelopmentRevision());
         define('TINE20SETUP_PACKAGESTRING', 'none');
         define('TINE20SETUP_RELEASETIME',   'none');
-    }\r
+    }
     
     /**
      * setup the cache and add it to zend registry
diff --git a/tine20/Setup/SchemaTool.php b/tine20/Setup/SchemaTool.php
new file mode 100644 (file)
index 0000000..0e462cc
--- /dev/null
@@ -0,0 +1,109 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Setup
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2016 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Cornelius Weiss <c.weiss@metaways.de>
+ */
+
+use Doctrine\ORM\Tools\Setup;
+use Doctrine\ORM\EntityManager;
+use \Doctrine\ORM\Tools\SchemaTool;
+use Doctrine\Common\Persistence\Mapping\StaticReflectionService;
+use \Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver;
+
+/**
+ * helper around docrine2/dbal schema tools
+ */
+class Setup_SchemaTool
+{
+    /**
+     * convert tine20config to dbal config
+     *
+     * @return array
+     */
+    public static function getDBParams()
+    {
+        $dbParams = Tinebase_Config::getInstance()->get('database')->toArray();
+        $dbParams['driver'] = $dbParams['adapter'];
+        $dbParams['user'] = $dbParams['username'];
+
+        return $dbParams;
+    }
+
+    public static function getConfig($appName, $modelNames=null)
+    {
+        $mappingDriver = new Tinebase_Record_DoctrineMappingDriver();
+
+        if (! $modelNames) {
+            $modelNames = array();
+
+            foreach($mappingDriver->getAllClassNames() as $modelName) {
+                $modelConfig = $modelName::getConfiguration();
+
+                if ($modelConfig->getApplName() == $appName) {
+                    $modelNames[] = $modelName;
+                }
+            }
+        }
+
+        $tableNames = array();
+        foreach($modelNames as $modelName) {
+            $modelConfig = $modelName::getConfiguration();
+            if (! $mappingDriver->isTransient($modelName)) {
+                throw new Setup_Exception('Model not yet doctrine2 ready');
+            }
+            $tableNames[] = SQL_TABLE_PREFIX . Tinebase_Helper::array_value('name', $modelConfig->getTable());
+        }
+
+        $config = Setup::createConfiguration();
+        $config->setMetadataDriverImpl($mappingDriver);
+
+        $config->setFilterSchemaAssetsExpression('/'. implode('|',$tableNames) . '/');
+
+        return $config;
+
+    }
+
+    public static function getEntityManager($appName, $modelNames=null)
+    {
+        $em = EntityManager::create(self::getDBParams(), self::getConfig($appName, $modelNames));
+
+        // needed to prevent runtime reflection that needs private properties ...
+        $em->getMetadataFactory()->setReflectionService(new StaticReflectionService());
+
+        return $em;
+    }
+
+    public static function getMetadata($appName, $modelNames=null)
+    {
+        $em = self::getEntityManager($appName, $modelNames);
+
+        $classes = array();
+        foreach($modelNames as $modelName) {
+            $classes[] = $em->getClassMetadata($modelName);
+        }
+
+        return $classes;
+    }
+
+    public static function createSchema($appName, $modelNames=null)
+    {
+        $em = self::getEntityManager($appName, $modelNames);
+        $tool = new SchemaTool($em);
+        $classes = self::getMetadata($appName, $modelNames);
+
+        $tool->createSchema($classes);
+    }
+
+    public static function updateSchema($appName, $modelNames=null)
+    {
+        $em = self::getEntityManager($appName, $modelNames);
+        $tool = new SchemaTool($em);
+        $classes = self::getMetadata($appName, $modelNames);
+
+        $tool->updateSchema($classes, true);
+    }
+}
\ No newline at end of file
index 2de91e0..f2fc764 100644 (file)
@@ -5,7 +5,7 @@
  * @package     Setup
  * @subpackage  Update
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright   Copyright (c) 2007-2014 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Matthias Greiling <m.greiling@metaways.de>
  */
 
@@ -435,17 +435,17 @@ class Setup_Update_Abstract
      */
     protected function _createSetupuser()
     {
-        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' Creating new setupuser.');
+        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Creating new setupuser.');
 
         $adminGroup = Tinebase_Group::getInstance()->getDefaultAdminGroup();
         $setupUser = new Tinebase_Model_FullUser(array(
-            'accountLoginName'      => 'setupuser',
-            'accountStatus'         => Tinebase_Model_User::ACCOUNT_STATUS_DISABLED,
-            'visibility'            => Tinebase_Model_FullUser::VISIBILITY_HIDDEN,
-            'accountPrimaryGroup'   => $adminGroup->getId(),
-            'accountLastName'       => 'setupuser',
-            'accountDisplayName'    => 'setupuser',
-            'accountExpires'        => NULL,
+            'accountLoginName' => 'setupuser',
+            'accountStatus' => Tinebase_Model_User::ACCOUNT_STATUS_DISABLED,
+            'visibility' => Tinebase_Model_FullUser::VISIBILITY_HIDDEN,
+            'accountPrimaryGroup' => $adminGroup->getId(),
+            'accountLastName' => 'setupuser',
+            'accountDisplayName' => 'setupuser',
+            'accountExpires' => NULL,
         ));
         try {
             $setupUser = Tinebase_User::getInstance()->addUser($setupUser);
@@ -459,4 +459,35 @@ class Setup_Update_Abstract
 
         return $setupUser;
     }
+
+    /**
+     * update schema of modelconfig enabled app
+     *
+     * @param string $appName
+     * @param array $modelNames
+     * @throws Setup_Exception_NotFound
+     */
+    public function updateSchema($appName, $modelNames)
+    {
+        $updateRequired = false;
+        $setNewVersions = array();
+        foreach($modelNames as $modelName) {
+            $modelConfig = $modelName::getConfiguration();
+            $tableName = Tinebase_Helper::array_value('name', $modelConfig->getTable());
+            $currentVersion = $this->getTableVersion($tableName);
+            $schemaVersion = $modelConfig->getVersion();
+            if ($currentVersion < $schemaVersion) {
+                $updateRequired = true;
+                $setNewVersions[$tableName] = $schemaVersion;
+            }
+        }
+
+        if ($updateRequired) {
+            Setup_SchemaTool::updateSchema($appName, $modelNames);
+
+            foreach($setNewVersions as $table => $version) {
+                $this->setTableVersion($table, $version);
+            }
+        }
+    }
 }
index cee387a..294dd0f 100755 (executable)
@@ -259,9 +259,9 @@ abstract class Tinebase_Controller_Abstract extends Tinebase_Pluggable_Abstract
     /**
      * @return array
      *
-     * @todo maybe add param $mcv2only (new modelconfig with doctrine schema tool)
+     * @param bool $MCV2only filter for new modelconfig with doctrine schema tool
      */
-    public function getModels()
+    public function getModels($MCV2only = false)
     {
         if ($this->_models === null && ! empty($this->_applicationName)) {
             try {
@@ -289,9 +289,22 @@ abstract class Tinebase_Controller_Abstract extends Tinebase_Pluggable_Abstract
                     }
                 }
             }
+
             $this->_models = $models;
         }
 
+        if ($MCV2only) {
+            $md = new Tinebase_Record_DoctrineMappingDriver();
+            $MCv2Models = array();
+            foreach($models as $model) {
+                if ($md->isTransient($model)) {
+                    $MCv2Models[] = $model;
+                }
+            }
+
+            return $MCv2Models;
+        }
+
         return $this->_models;
     }
 
index 6589560..f3adfc4 100644 (file)
@@ -5,7 +5,7 @@
  * @package     Tinebase
  * @subpackage  Configuration
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright   Copyright (c) 2013-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2013-2016 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Alexander Stintzing <a.stintzing@metaways.de>
  */
 
@@ -31,6 +31,20 @@ class Tinebase_ModelConfiguration {
      * @var string
      */
     protected $_idProperty = 'id';
+
+    /**
+     * table definition
+     *
+     * @var array
+     */
+    protected $_table = array();
+
+    /**
+     * model version
+     *
+     * @var integer
+     */
+    protected $_version = null;
     
     // legacy
     protected $_identifier;
@@ -284,11 +298,11 @@ class Tinebase_ModelConfiguration {
      * boolean                   Boolean             boolean  bool                          bool              Tinebase_Model_Filter_Bool
      * integer                   Integer             integer  integer                       int               Tinebase_Model_Filter_Int                 number
      * integer     bytes         Bytes               integer  integer                       int               Tinebase_Model_Filter_Int
-     * integer     usMoney       Dollar in Cent      integer  integer                       int               Tinebase_Model_Filter_Int
-     * integer     euMoney       Euro in Cent        integer  integer                       int               Tinebase_Model_Filter_Int
      * integer     seconds       Seconds             integer  integer                       int               Tinebase_Model_Filter_Int
      * integer     minutes       Minutes             integer  integer                       int               Tinebase_Model_Filter_Int
      * float                     Float               float    float                         float             Tinebase_Model_Filter_Int
+     * float       usMoney       Dollar in Cent      float    float                         int               Tinebase_Model_Filter_Int
+     * float       euMoney       Euro in Cent        float    float                         int               Tinebase_Model_Filter_Int
      * json                      Json String         text     string                        array             Tinebase_Model_Filter_Text
      * container                 Container           string   Tine.Tinebase.Model.Container Tinebase_Model_Container                                    tine.widget.container.filtermodel
      * tag tinebase.tag
@@ -304,7 +318,7 @@ class Tinebase_ModelConfiguration {
      * the key will be used for the classname of a singleton (callable by getInstance),
      * the value will be used as method name.
      * 
-     * * record/foreign (legacy) 1:1 - Relation      text     Tine.<APP>.Model.<MODEL>      Tinebase_Record_Abstract  Tinebase_Model_Filter_ForeignId   Tine.widgets.grid.ForeignRecordFilter
+     * * record                  1:1 - Relation      text     Tine.<APP>.Model.<MODEL>      Tinebase_Record_Abstract  Tinebase_Model_Filter_ForeignId   Tine.widgets.grid.ForeignRecordFilter
      * * records                 1:n - Relation      -        Array of Record.data Objects  Tinebase_Record_RecordSet -                                 -
      * * relation                m:m - Relation      -        Tinebase.Model.Relation       Tinebase_Model_Relation   Tinebase_Model_Filter_Relation
      * * keyfield                String              string   <as defined>                  string            Tinebase_Model_Filter_Text
@@ -694,13 +708,16 @@ class Tinebase_ModelConfiguration {
         $this->_modelName   = $modelClassConfiguration['modelName'];
         $this->_idProperty  = $this->_identifier = (isset($modelClassConfiguration['idProperty']) || array_key_exists('idProperty', $modelClassConfiguration)) ? $modelClassConfiguration['idProperty'] : 'id';
 
+        $this->_table = isset($modelClassConfiguration['table']) ? $modelClassConfiguration['table'] : $this->_table;
+        $this->_version = isset($modelClassConfiguration['version']) ? $modelClassConfiguration['version'] : $this->_version;
+
         // some cruid validating
         foreach ($modelClassConfiguration as $propertyName => $propertyValue) {
             $this->{'_' . $propertyName} = $propertyValue;
         }
         
         $this->_filters = array();
-        $this->_fields[$this->_idProperty] = array('label' => NULL, 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true));
+        $this->_fields[$this->_idProperty] = array('id' => true, 'label' => NULL, 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'length' => 40);
 
         if ($this->_hasCustomFields) {
             $this->_fields['customfields'] = array('label' => NULL, 'type' => 'custom', 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true, Zend_Filter_Input::DEFAULT_VALUE => NULL));
@@ -712,6 +729,8 @@ class Tinebase_ModelConfiguration {
 
         if ($this->_containerProperty) {
             $this->_fields[$this->_containerProperty] = array(
+                'nullable'         => true,
+                'unsigned'         => true,
                 'label'            => $this->_containerUsesFilter ? $this->_containerName : NULL,
                 'shy'              => true,
                 'type'             => 'container',
@@ -755,16 +774,16 @@ class Tinebase_ModelConfiguration {
         if ($this->_modlogActive) {
             // notes are needed if modlog is active
             $this->_fields['notes']              = array('label' => NULL,                 'type' => 'note',     'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true, Zend_Filter_Input::DEFAULT_VALUE => NULL), 'useGlobalTranslation' => TRUE);
-            $this->_fields['created_by']         = array('label' => 'Created By',         'type' => 'user',     'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'shy' => true, 'useGlobalTranslation' => TRUE);
-            $this->_fields['creation_time']      = array('label' => 'Creation Time',      'type' => 'datetime', 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'shy' => true, 'useGlobalTranslation' => TRUE);
-            $this->_fields['last_modified_by']   = array('label' => 'Last Modified By',   'type' => 'user',     'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'shy' => true, 'useGlobalTranslation' => TRUE);
-            $this->_fields['last_modified_time'] = array('label' => 'Last Modified Time', 'type' => 'datetime', 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'shy' => true, 'useGlobalTranslation' => TRUE);
-            $this->_fields['seq']                = array('label' => NULL,                 'type' => 'integer',  'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'shy' => true, 'useGlobalTranslation' => TRUE);
+            $this->_fields['created_by']         = array('label' => 'Created By',         'type' => 'user',     'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'shy' => true, 'useGlobalTranslation' => TRUE, 'length' => 40, 'nullable' => true);
+            $this->_fields['creation_time']      = array('label' => 'Creation Time',      'type' => 'datetime', 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'shy' => true, 'useGlobalTranslation' => TRUE, 'nullable' => true);
+            $this->_fields['last_modified_by']   = array('label' => 'Last Modified By',   'type' => 'user',     'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'shy' => true, 'useGlobalTranslation' => TRUE, 'length' => 40, 'nullable' => true);
+            $this->_fields['last_modified_time'] = array('label' => 'Last Modified Time', 'type' => 'datetime', 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'shy' => true, 'useGlobalTranslation' => TRUE, 'nullable' => true);
+            $this->_fields['seq']                = array('label' => NULL,                 'type' => 'integer',  'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'shy' => true, 'useGlobalTranslation' => TRUE, 'default' => 0, 'unsigned' => true);
             
             // don't show deleted information
-            $this->_fields['deleted_by']         = array('label' => NULL, 'type' => 'user',     'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'useGlobalTranslation' => TRUE);
-            $this->_fields['deleted_time']       = array('label' => NULL, 'type' => 'datetime', 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'useGlobalTranslation' => TRUE);
-            $this->_fields['is_deleted']         = array('label' => NULL, 'type' => 'boolean',  'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'useGlobalTranslation' => TRUE);
+            $this->_fields['deleted_by']         = array('label' => NULL, 'type' => 'user',     'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'useGlobalTranslation' => TRUE, 'length' => 40, 'nullable' => true);
+            $this->_fields['deleted_time']       = array('label' => NULL, 'type' => 'datetime', 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'useGlobalTranslation' => TRUE, 'nullable' => true);
+            $this->_fields['is_deleted']         = array('label' => NULL, 'type' => 'boolean',  'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'useGlobalTranslation' => TRUE, 'default' => false);
 
         } elseif ($this->_hasNotes) {
             $this->_fields['notes'] = array('label' => NULL, 'type' => 'note', 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true, Zend_Filter_Input::DEFAULT_VALUE => NULL));
@@ -774,6 +793,8 @@ class Tinebase_ModelConfiguration {
         $queryFilters = array();
         
         foreach ($this->_fields as $fieldKey => &$fieldDef) {
+            $fieldDef['fieldName'] = $fieldKey;
+
             // set default type to string, if no type is given
             if (! (isset($fieldDef['type']) || array_key_exists('type', $fieldDef))) {
                 $fieldDef['type'] = 'string';
@@ -793,6 +814,10 @@ class Tinebase_ModelConfiguration {
                 $this->_useGroups = TRUE;
             }
 
+            if ($fieldDef['type'] == 'keyfield') {
+                $fieldDef['length'] = 40;
+            }
+
             if ($fieldDef['type'] == 'virtual') {
                 $fieldDef = isset($fieldDef['config']) ? $fieldDef['config'] : array();
                 $fieldDef['key'] = $fieldKey;
@@ -804,7 +829,8 @@ class Tinebase_ModelConfiguration {
                 $this->_virtualFields[] = $fieldDef;
                 continue;
             }
-            
+
+
             // set default value
             // TODO: implement complex default values
             if ((isset($fieldDef['default']))) {
@@ -938,6 +964,31 @@ class Tinebase_ModelConfiguration {
         $this->_filterModel['query'] = $queryFilterData;
     }
 
+    public function getIdProperty()
+    {
+        return $this->_idProperty;
+    }
+
+    public function getTable()
+    {
+        return $this->_table;
+    }
+
+    public function getVersion()
+    {
+        return $this->_version;
+    }
+
+    public function getApplName()
+    {
+        return $this->_appName;
+    }
+
+    public function getModelName()
+    {
+        return $this->_modelName;
+    }
+
     /**
      * populate model config properties
      * 
@@ -974,6 +1025,7 @@ class Tinebase_ModelConfiguration {
             case 'user':
                 $fieldDef['config'] = array(
                     'refIdField'              => 'id',
+                    'length'                  => 40,
                     'appName'                 => 'Addressbook',
                     'modelName'               => 'Contact',
                     'recordClassName'         => 'Addressbook_Model_Contact',
@@ -993,6 +1045,7 @@ class Tinebase_ModelConfiguration {
                 $fieldDef['config']['controllerClassName'] = (isset($fieldDef['config']['controllerClassName']) || array_key_exists('controllerClassName', $fieldDef['config'])) ? $fieldDef['config']['controllerClassName'] : $this->_getPhpClassName($fieldDef['config'], 'Controller');
                 $fieldDef['config']['filterClassName']     = (isset($fieldDef['config']['filterClassName']) || array_key_exists('filterClassName', $fieldDef['config']))     ? $fieldDef['config']['filterClassName']     : $this->_getPhpClassName($fieldDef['config']) . 'Filter';
                 if ($fieldDef['type'] == 'record') {
+                    $fieldDef['config']['length'] = 40;
                     $this->_recordFields[$fieldKey] = $fieldDef;
                 } else {
                     $fieldDef['config']['dependentRecords'] = (isset($fieldDef['config']['dependentRecords']) || array_key_exists('dependentRecords', $fieldDef['config'])) ? $fieldDef['config']['dependentRecords'] : FALSE;
index f0cb360..954b00f 100644 (file)
@@ -5,7 +5,7 @@
  * @package     Tinebase
  * @subpackage  Record
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright   Copyright (c) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Cornelius Weiss <c.weiss@metaways.de>
  */
 
@@ -272,7 +272,7 @@ abstract class Tinebase_Record_Abstract implements Tinebase_Record_Interface
     
         return static::$_configurationObject;
     }
-    
+
     /**
      * returns the relation config
      * 
diff --git a/tine20/Tinebase/Record/DoctrineMappingDriver.php b/tine20/Tinebase/Record/DoctrineMappingDriver.php
new file mode 100644 (file)
index 0000000..0ce9f37
--- /dev/null
@@ -0,0 +1,109 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Tinebase
+ * @subpackage  Record
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2016 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Cornelius Weiss <c.weiss@metaways.de>
+ */
+
+use Doctrine\Common\Persistence\Mapping\ClassMetadata;
+use Doctrine\Common\Persistence\Mapping\MappingException;
+
+/**
+ * Tinebase_Record_DoctrineMappingDriver
+ *
+ * @package     Tinebase
+ * @subpackage  Record
+ */
+class Tinebase_Record_DoctrineMappingDriver implements Doctrine\Common\Persistence\Mapping\Driver\MappingDriver
+{
+    /**
+     * @var array modelConfigType => Doctrine2Type
+     */
+    protected static $_typeMap= array(
+        'string'    => 'string',
+        'text'      => 'text',
+        'datetime'  => 'datetime',
+        'date'      => 'datetime',
+        'time'      => 'datetime',
+        'integer'   => 'integer',
+        'json'      => 'text',
+        'container' => 'integer',
+        'record'    => 'string',
+        'keyfield'  => 'string',
+        'user'      => 'string',
+        'boolean'   => 'boolean',
+    );
+
+    /**
+     * Loads the metadata for the specified class into the provided container.
+     *
+     * @param string        $className
+     * @param ClassMetadata $metadata
+     *
+     * @return void
+     */
+    public function loadMetadataForClass($className, ClassMetadata $metadata)
+    {
+        if (! $this->isTransient($className)) {
+            throw new MappingException('Class ' . $className . 'has no appropriate ModelConfiguration');
+        }
+
+        $modelConfig = $className::getConfiguration();
+
+        $table = $modelConfig->getTable();
+        $table['name'] = SQL_TABLE_PREFIX . $table['name'];
+        $metadata->setPrimaryTable($table);
+        foreach ($modelConfig->getFields() as $fieldName => $config) {
+            self::mapTypes($config);
+
+            if (! $config['doctrineIgnore']) {
+                $metadata->mapField($config);
+            }
+        }
+    }
+
+    /**
+     * map modelconfig type to doctrine type
+     *
+     * @param $config
+     */
+    public static function mapTypes(&$config)
+    {
+        $config['doctrineIgnore'] = true;
+        if (isset(self::$_typeMap[$config['type']])) {
+            $config['type'] = self::$_typeMap[$config['type']];
+            $config['doctrineIgnore'] = false;
+        }
+    }
+
+    /**
+     * Gets the names of all mapped classes known to this driver.
+     *
+     * @return array The names of all mapped classes known to this driver.
+     */
+    public function getAllClassNames()
+    {
+        // @TODO Walk all models, check for modelconfig with version OR
+        //       Walk all Controllers, ask for models and do the above
+        return array();
+    }
+
+    /**
+     * Returns whether the class with the specified name should have its metadata loaded.
+     * This is only the case if it is either mapped as an Entity or a MappedSuperclass.
+     *
+     * @param string $className
+     *
+     * @return boolean
+     */
+    public function isTransient($className)
+    {
+        $modelConfig = $className::getConfiguration();
+
+        return $modelConfig && is_int($modelConfig->getVersion());
+    }
+}
index c805cf8..32d1df8 100644 (file)
@@ -30,7 +30,8 @@
         "sabre/vobject": "3.1.3 as 2.1.313",
         "metaways/opendocument": "1.1",
         "metaways/timezoneconvert": "0.2",
-        "zendframework/zend-http": "2.2.8-p3 as 2.2.8"
+        "zendframework/zend-http": "2.2.8-p3 as 2.2.8",
+        "doctrine/orm": "2.5.*"
     },
     "require-dev": {
         "phpunit/phpunit": "3.7.*",
index 56a8ad7..9a27bbb 100644 (file)
@@ -4,8 +4,8 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "34cf6f6858c13aa6a897124d4d990a7d",
-    "content-hash": "eb93e145acf52f2a7fdff1acb6407033",
+    "hash": "bca4c331ae7bebaaac6bc00ec330930d",
+    "content-hash": "ecd95c963cbc906059240ce9ae0a9c27",
     "packages": [
         {
             "name": "codeplex/phpexcel",
             "time": "2012-11-21 10:55:52"
         },
         {
+            "name": "doctrine/annotations",
+            "version": "v1.2.7",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/annotations.git",
+                "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535",
+                "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/lexer": "1.*",
+                "php": ">=5.3.2"
+            },
+            "require-dev": {
+                "doctrine/cache": "1.*",
+                "phpunit/phpunit": "4.*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.3.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Doctrine\\Common\\Annotations\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Jonathan Wage",
+                    "email": "jonwage@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Docblock Annotations Parser",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "annotations",
+                "docblock",
+                "parser"
+            ],
+            "time": "2015-08-31 12:32:49"
+        },
+        {
+            "name": "doctrine/cache",
+            "version": "v1.5.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/cache.git",
+                "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/cache/zipball/47cdc76ceb95cc591d9c79a36dc3794975b5d136",
+                "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "conflict": {
+                "doctrine/common": ">2.2,<2.4"
+            },
+            "require-dev": {
+                "phpunit/phpunit": ">=3.7",
+                "predis/predis": "~1.0",
+                "satooshi/php-coveralls": "~0.6"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.5.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Jonathan Wage",
+                    "email": "jonwage@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Caching library offering an object-oriented API for many cache backends",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "cache",
+                "caching"
+            ],
+            "time": "2015-12-19 05:03:47"
+        },
+        {
+            "name": "doctrine/collections",
+            "version": "v1.3.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/collections.git",
+                "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/collections/zipball/6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
+                "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.2.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Doctrine\\Common\\Collections\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Jonathan Wage",
+                    "email": "jonwage@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Collections Abstraction library",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "array",
+                "collections",
+                "iterator"
+            ],
+            "time": "2015-04-14 22:21:58"
+        },
+        {
+            "name": "doctrine/common",
+            "version": "v2.5.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/common.git",
+                "reference": "10f1f19651343f87573129ca970aef1a47a6f29e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/common/zipball/10f1f19651343f87573129ca970aef1a47a6f29e",
+                "reference": "10f1f19651343f87573129ca970aef1a47a6f29e",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/annotations": "1.*",
+                "doctrine/cache": "1.*",
+                "doctrine/collections": "1.*",
+                "doctrine/inflector": "1.*",
+                "doctrine/lexer": "1.*",
+                "php": ">=5.3.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~3.7"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.5.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Doctrine\\Common\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Jonathan Wage",
+                    "email": "jonwage@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Common Library for Doctrine projects",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "annotations",
+                "collections",
+                "eventmanager",
+                "persistence",
+                "spl"
+            ],
+            "time": "2015-12-25 13:10:16"
+        },
+        {
+            "name": "doctrine/dbal",
+            "version": "v2.5.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/dbal.git",
+                "reference": "abbdfd1cff43a7b99d027af3be709bc8fc7d4769"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/dbal/zipball/abbdfd1cff43a7b99d027af3be709bc8fc7d4769",
+                "reference": "abbdfd1cff43a7b99d027af3be709bc8fc7d4769",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/common": ">=2.4,<2.7-dev",
+                "php": ">=5.3.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "4.*",
+                "symfony/console": "2.*"
+            },
+            "suggest": {
+                "symfony/console": "For helpful console commands such as SQL execution and import of files."
+            },
+            "bin": [
+                "bin/doctrine-dbal"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.5.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Doctrine\\DBAL\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Jonathan Wage",
+                    "email": "jonwage@gmail.com"
+                }
+            ],
+            "description": "Database Abstraction Layer",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "database",
+                "dbal",
+                "persistence",
+                "queryobject"
+            ],
+            "time": "2016-01-05 22:11:12"
+        },
+        {
+            "name": "doctrine/inflector",
+            "version": "v1.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/inflector.git",
+                "reference": "90b2128806bfde671b6952ab8bea493942c1fdae"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae",
+                "reference": "90b2128806bfde671b6952ab8bea493942c1fdae",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "4.*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Doctrine\\Common\\Inflector\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Jonathan Wage",
+                    "email": "jonwage@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Common String Manipulations with regard to casing and singular/plural rules.",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "inflection",
+                "pluralize",
+                "singularize",
+                "string"
+            ],
+            "time": "2015-11-06 14:35:42"
+        },
+        {
+            "name": "doctrine/instantiator",
+            "version": "1.0.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/instantiator.git",
+                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
+                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3,<8.0-DEV"
+            },
+            "require-dev": {
+                "athletic/athletic": "~0.1.8",
+                "ext-pdo": "*",
+                "ext-phar": "*",
+                "phpunit/phpunit": "~4.0",
+                "squizlabs/php_codesniffer": "~2.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Marco Pivetta",
+                    "email": "ocramius@gmail.com",
+                    "homepage": "http://ocramius.github.com/"
+                }
+            ],
+            "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+            "homepage": "https://github.com/doctrine/instantiator",
+            "keywords": [
+                "constructor",
+                "instantiate"
+            ],
+            "time": "2015-06-14 21:17:01"
+        },
+        {
+            "name": "doctrine/lexer",
+            "version": "v1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/lexer.git",
+                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
+                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Doctrine\\Common\\Lexer\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "lexer",
+                "parser"
+            ],
+            "time": "2014-09-09 13:34:57"
+        },
+        {
+            "name": "doctrine/orm",
+            "version": "v2.5.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/doctrine2.git",
+                "reference": "bc4ddbfb0114cb33438cc811c9a740d8aa304aab"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/bc4ddbfb0114cb33438cc811c9a740d8aa304aab",
+                "reference": "bc4ddbfb0114cb33438cc811c9a740d8aa304aab",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/cache": "~1.4",
+                "doctrine/collections": "~1.2",
+                "doctrine/common": ">=2.5-dev,<2.7-dev",
+                "doctrine/dbal": ">=2.5-dev,<2.6-dev",
+                "doctrine/instantiator": "~1.0.1",
+                "ext-pdo": "*",
+                "php": ">=5.4",
+                "symfony/console": "~2.5|~3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0",
+                "symfony/yaml": "~2.3|~3.0"
+            },
+            "suggest": {
+                "symfony/yaml": "If you want to use YAML Metadata Mapping Driver"
+            },
+            "bin": [
+                "bin/doctrine",
+                "bin/doctrine.php"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Doctrine\\ORM\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Jonathan Wage",
+                    "email": "jonwage@gmail.com"
+                }
+            ],
+            "description": "Object-Relational-Mapper for PHP",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "database",
+                "orm"
+            ],
+            "time": "2016-01-05 21:34:58"
+        },
+        {
             "name": "ezyang/htmlpurifier",
             "version": "v4.6.0",
             "source": {
                     "role": "Developer"
                 }
             ],
-            "description": "The VObject library for PHP allows you to easily parse and manipulate iCalendar and vCard objects",
-            "homepage": "https://github.com/fruux/sabre-vobject",
+            "description": "The VObject library for PHP allows you to easily parse and manipulate iCalendar and vCard objects",
+            "homepage": "https://github.com/fruux/sabre-vobject",
+            "keywords": [
+                "VObject",
+                "iCalendar",
+                "vCard"
+            ],
+            "time": "2013-10-02 15:59:03"
+        },
+        {
+            "name": "symfony/console",
+            "version": "v2.8.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/console.git",
+                "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/console/zipball/d0239fb42f98dd02e7d342f793c5d2cdee0c478d",
+                "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.9",
+                "symfony/polyfill-mbstring": "~1.0"
+            },
+            "require-dev": {
+                "psr/log": "~1.0",
+                "symfony/event-dispatcher": "~2.1|~3.0.0",
+                "symfony/process": "~2.1|~3.0.0"
+            },
+            "suggest": {
+                "psr/log": "For using the console logger",
+                "symfony/event-dispatcher": "",
+                "symfony/process": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Console\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Console Component",
+            "homepage": "https://symfony.com",
+            "time": "2016-01-14 08:33:16"
+        },
+        {
+            "name": "symfony/polyfill-mbstring",
+            "version": "v1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-mbstring.git",
+                "reference": "49ff736bd5d41f45240cec77b44967d76e0c3d25"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/49ff736bd5d41f45240cec77b44967d76e0c3d25",
+                "reference": "49ff736bd5d41f45240cec77b44967d76e0c3d25",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "suggest": {
+                "ext-mbstring": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Mbstring\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for the Mbstring extension",
+            "homepage": "https://symfony.com",
             "keywords": [
-                "VObject",
-                "iCalendar",
-                "vCard"
+                "compatibility",
+                "mbstring",
+                "polyfill",
+                "portable",
+                "shim"
             ],
-            "time": "2013-10-02 15:59:03"
+            "time": "2015-11-20 09:19:13"
         },
         {
             "name": "syncroton/syncroton",
             "time": "2013-09-23 12:00:18"
         },
         {
-            "name": "doctrine/annotations",
-            "version": "v1.2.7",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/doctrine/annotations.git",
-                "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535",
-                "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/lexer": "1.*",
-                "php": ">=5.3.2"
-            },
-            "require-dev": {
-                "doctrine/cache": "1.*",
-                "phpunit/phpunit": "4.*"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.3.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Doctrine\\Common\\Annotations\\": "lib/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Roman Borschel",
-                    "email": "roman@code-factory.org"
-                },
-                {
-                    "name": "Benjamin Eberlei",
-                    "email": "kontakt@beberlei.de"
-                },
-                {
-                    "name": "Guilherme Blanco",
-                    "email": "guilhermeblanco@gmail.com"
-                },
-                {
-                    "name": "Jonathan Wage",
-                    "email": "jonwage@gmail.com"
-                },
-                {
-                    "name": "Johannes Schmitt",
-                    "email": "schmittjoh@gmail.com"
-                }
-            ],
-            "description": "Docblock Annotations Parser",
-            "homepage": "http://www.doctrine-project.org",
-            "keywords": [
-                "annotations",
-                "docblock",
-                "parser"
-            ],
-            "time": "2015-08-31 12:32:49"
-        },
-        {
-            "name": "doctrine/lexer",
-            "version": "v1.0.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/doctrine/lexer.git",
-                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
-                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.2"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Doctrine\\Common\\Lexer\\": "lib/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Roman Borschel",
-                    "email": "roman@code-factory.org"
-                },
-                {
-                    "name": "Guilherme Blanco",
-                    "email": "guilhermeblanco@gmail.com"
-                },
-                {
-                    "name": "Johannes Schmitt",
-                    "email": "schmittjoh@gmail.com"
-                }
-            ],
-            "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
-            "homepage": "http://www.doctrine-project.org",
-            "keywords": [
-                "lexer",
-                "parser"
-            ],
-            "time": "2014-09-09 13:34:57"
-        },
-        {
             "name": "jms/metadata",
             "version": "1.5.1",
             "source": {
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/config/zipball/41ee6c70758f40fa1dbf90d019ae0a66c4a09e74",
+                "url": "https://api.github.com/repos/symfony/config/zipball/ee4cdda66aff834c8125e8f2c15932461667c521",
                 "reference": "41ee6c70758f40fa1dbf90d019ae0a66c4a09e74",
                 "shasum": ""
             },
             "time": "2016-01-03 15:33:41"
         },
         {
-            "name": "symfony/console",
-            "version": "v2.8.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/console.git",
-                "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/d0239fb42f98dd02e7d342f793c5d2cdee0c478d",
-                "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.9",
-                "symfony/polyfill-mbstring": "~1.0"
-            },
-            "require-dev": {
-                "psr/log": "~1.0",
-                "symfony/event-dispatcher": "~2.1|~3.0.0",
-                "symfony/process": "~2.1|~3.0.0"
-            },
-            "suggest": {
-                "psr/log": "For using the console logger",
-                "symfony/event-dispatcher": "",
-                "symfony/process": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.8-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Component\\Console\\": ""
-                },
-                "exclude-from-classmap": [
-                    "/Tests/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Console Component",
-            "homepage": "https://symfony.com",
-            "time": "2016-01-14 08:33:16"
-        },
-        {
             "name": "symfony/event-dispatcher",
             "version": "v2.8.2",
             "source": {
             "time": "2016-01-14 08:26:52"
         },
         {
-            "name": "symfony/polyfill-mbstring",
-            "version": "v1.0.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/polyfill-mbstring.git",
-                "reference": "49ff736bd5d41f45240cec77b44967d76e0c3d25"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/49ff736bd5d41f45240cec77b44967d76e0c3d25",
-                "reference": "49ff736bd5d41f45240cec77b44967d76e0c3d25",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "suggest": {
-                "ext-mbstring": "For best performance"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Polyfill\\Mbstring\\": ""
-                },
-                "files": [
-                    "bootstrap.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Nicolas Grekas",
-                    "email": "p@tchwork.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony polyfill for the Mbstring extension",
-            "homepage": "https://symfony.com",
-            "keywords": [
-                "compatibility",
-                "mbstring",
-                "polyfill",
-                "portable",
-                "shim"
-            ],
-            "time": "2015-11-20 09:19:13"
-        },
-        {
             "name": "symfony/process",
             "version": "v2.8.2",
             "source": {
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/process/zipball/6f1979c3b0f4c22c77a8a8971afaa7dd07f082ac",
+                "url": "https://api.github.com/repos/symfony/process/zipball/d9d21cfcc3e202ee34777d6da38897695d4d208d",
                 "reference": "6f1979c3b0f4c22c77a8a8971afaa7dd07f082ac",
                 "shasum": ""
             },