[BUGFIX] StorageRepository fails to load storages
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Resource / StorageRepository.php
index 22fe6b5..eed5977 100644 (file)
@@ -4,7 +4,7 @@ namespace TYPO3\CMS\Core\Resource;
 /***************************************************************
  *  Copyright notice
  *
- *  (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ *  (c) 2011-2013 Andreas Wolf <andreas.wolf@ikt-werk.de>
  *  All rights reserved
  *
  *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -15,7 +15,7 @@ namespace TYPO3\CMS\Core\Resource;
  *
  *  The GNU General Public License can be found at
  *  http://www.gnu.org/copyleft/gpl.html.
- *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  A copy is found in the text file GPL.txt and important notices to the license
  *  from the author is found in LICENSE.txt distributed with these scripts.
  *
  *
@@ -31,10 +31,13 @@ namespace TYPO3\CMS\Core\Resource;
  *
  * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
  * @author Ingmar Schlecht <ingmar@typo3.org>
- * @package TYPO3
- * @subpackage t3lib
  */
-class StorageRepository extends \TYPO3\CMS\Core\Resource\AbstractRepository {
+class StorageRepository extends AbstractRepository {
+
+       /**
+        * @var null|array‚
+        */
+       protected static $storageRowCache = NULL;
 
        /**
         * @var string
@@ -49,23 +52,114 @@ class StorageRepository extends \TYPO3\CMS\Core\Resource\AbstractRepository {
        /**
         * @var string
         */
-       protected $typeField = 'type';
+       protected $typeField = 'driver';
+
+       /**
+        * @var string
+        */
+       protected $driverField = 'driver';
+
+       /**
+        * @var \TYPO3\CMS\Core\Log\Logger
+        */
+       protected $logger;
+
+       /**
+        * @var \TYPO3\CMS\Core\Database\DatabaseConnection
+        */
+       protected $db;
+
+       public function __construct() {
+               parent::__construct();
+
+               /** @var $logManager \TYPO3\CMS\Core\Log\LogManager */
+               $logManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager');
+               $this->logger = $logManager->getLogger(__CLASS__);
+               $this->db = $GLOBALS['TYPO3_DB'];
+       }
+
+       /**
+        * @param integer $uid
+        *
+        * @return null|ResourceStorage
+        */
+       public function findByUid($uid) {
+               $this->initializeLocalCache();
+               if (isset(self::$storageRowCache[$uid])) {
+                       return  $this->factory->getStorageObject($uid, self::$storageRowCache[$uid]);
+               }
+               return NULL;
+       }
+
+
+       /**
+        * Initializes the Storage
+        *
+        * @return void
+        */
+       protected function initializeLocalCache() {
+               if (static::$storageRowCache === NULL) {
+
+                       static::$storageRowCache = $this->db->exec_SELECTgetRows(
+                               '*',
+                               $this->table,
+                               '1=1' . $this->getWhereClauseForEnabledFields(),
+                               '',
+                               '',
+                               '',
+                               'uid'
+                       );
+                       // if no storage is created before or the user has not access to a storage
+                       // static::$storageRowCache would have the value array()
+                       // so check if there is any record. If no record is found, create the fileadmin/ storage
+                       // selecting just one row is enoung
+
+                       if (static::$storageRowCache === array()) {
+                               $storageObjectsExists = $this->db->exec_SELECTgetSingleRow('uid', $this->table, '');
+                               if ($storageObjectsExists !== NULL) {
+                                       if ($this->createLocalStorage(
+                                               'fileadmin/ (auto-created)',
+                                               $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'],
+                                               'relative',
+                                               'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.',
+                                               TRUE
+                                       ) > 0 ) {
+                                               // reset to null to force reloading of storages
+                                               static::$storageRowCache = NULL;
+                                               // call self for initialize Cache
+                                               $this->initializeLocalCache();
+                                       }
+                               }
+                       }
+               }
+       }
 
        /**
-        * Finds storages by type.
+        * Finds storages by type, i.e. the driver used
         *
         * @param string $storageType
-        * @return t3lib_file_Storage[]
+        * @return ResourceStorage[]
         */
        public function findByStorageType($storageType) {
+               $this->initializeLocalCache();
+
+               /** @var $driverRegistry Driver\DriverRegistry */
+               $driverRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Driver\\DriverRegistry');
+
                $storageObjects = array();
-               $whereClause = 'deleted=0 AND hidden=0';
-               $whereClause .= ((' AND ' . $this->typeField) . ' = ') . $GLOBALS['TYPO3_DB']->fullQuoteStr($storageType, $this->table);
-               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $this->table, $whereClause);
-               while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
-                       $storageObjects[] = $this->createDomainObject($row);
+               foreach (static::$storageRowCache as $storageRow) {
+                       if (!$storageRow['driver'] !== $storageType) {
+                               continue;
+                       }
+                       if ($driverRegistry->driverExists($storageRow['driver'])) {
+                               $storageObjects[] = $this->factory->getStorageObject($storageRow['uid'], $storageRow);
+                       } else {
+                               $this->logger->warning(
+                                       sprintf('Could not instantiate storage "%s" because of missing driver.', array($storageRow['name'])),
+                                       $storageRow
+                               );
+                       }
                }
-               $GLOBALS['TYPO3_DB']->sql_free_result($res);
                return $storageObjects;
        }
 
@@ -73,22 +167,24 @@ class StorageRepository extends \TYPO3\CMS\Core\Resource\AbstractRepository {
         * Returns a list of mountpoints that are available in the VFS.
         * In case no storage exists this automatically created a storage for fileadmin/
         *
-        * @return t3lib_file_Storage[]
+        * @return ResourceStorage[]
         */
        public function findAll() {
+               $this->initializeLocalCache();
+
+               /** @var $driverRegistry Driver\DriverRegistry */
+               $driverRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Driver\\DriverRegistry');
+
                $storageObjects = array();
-               $whereClause = 'deleted=0 AND hidden=0';
-               if ($this->type != '') {
-                       $whereClause .= ((' AND ' . $this->typeField) . ' = ') . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->type, $this->table);
-               }
-               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $this->table, $whereClause);
-               while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
-                       $storageObjects[] = $this->createDomainObject($row);
-               }
-               $GLOBALS['TYPO3_DB']->sql_free_result($res);
-               if (count($storageObjects) === 0) {
-                       $this->createLocalStorage('fileadmin/ (auto-created)', $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], 'relative', 'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.');
-                       $storageObjects = self::findAll();
+               foreach (static::$storageRowCache as $storageRow) {
+                       if ($driverRegistry->driverExists($storageRow['driver'])) {
+                               $storageObjects[] = $this->factory->getStorageObject($storageRow['uid'], $storageRow);
+                       } else {
+                               $this->logger->warning(
+                                       sprintf('Could not instantiate storage "%s" because of missing driver.', array($storageRow['name'])),
+                                       $storageRow
+                               );
+                       }
                }
                return $storageObjects;
        }
@@ -100,9 +196,29 @@ class StorageRepository extends \TYPO3\CMS\Core\Resource\AbstractRepository {
         * @param string $basePath
         * @param string $pathType
         * @param string $description
+        * @param bool $default set to default storage
         * @return integer uid of the inserted record
         */
-       public function createLocalStorage($name, $basePath, $pathType, $description = '') {
+       public function createLocalStorage($name, $basePath, $pathType, $description = '', $default = FALSE) {
+               $caseSensitive = $this->testCaseSensitivity($pathType === 'relative' ? PATH_site . $basePath : $basePath);
+               // create the FlexForm for the driver configuration
+               $flexFormData = array(
+                       'data' => array(
+                               'sDEF' => array(
+                                       'lDEF' => array(
+                                               'basePath' => array('vDEF' => rtrim($basePath, '/') . '/'),
+                                               'pathType' => array('vDEF' => $pathType),
+                                               'caseSensitive' => array('vDEF' => $caseSensitive)
+                                       )
+                               )
+                       )
+               );
+
+               /** @var $flexObj \TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools */
+               $flexObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Configuration\\FlexForm\\FlexFormTools');
+               $flexFormXml = $flexObj->flexArray2Xml($flexFormData, TRUE);
+
+                       // create the record
                $field_values = array(
                        'pid' => 0,
                        'tstamp' => $GLOBALS['EXEC_TIME'],
@@ -110,41 +226,54 @@ class StorageRepository extends \TYPO3\CMS\Core\Resource\AbstractRepository {
                        'name' => $name,
                        'description' => $description,
                        'driver' => 'Local',
-                       'configuration' => ((('<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-                               <T3FlexForms>
-                                       <data>
-                                               <sheet index="sDEF">
-                                                       <language index="lDEF">
-                                                               <field index="basePath">
-                                                                       <value index="vDEF">' . rtrim($basePath, '/')) . '/</value>
-                                                               </field>
-                                                               <field index="pathType">
-                                                                       <value index="vDEF">') . $pathType) . '</value>
-                                                               </field>
-                                                       </language>
-                                               </sheet>
-                                       </data>
-                               </T3FlexForms>',
+                       'configuration' => $flexFormXml,
                        'is_online' => 1,
                        'is_browsable' => 1,
                        'is_public' => 1,
-                       'is_writable' => 1
+                       'is_writable' => 1,
+                       'is_default' => $default ? 1 : 0
                );
-               $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_file_storage', $field_values);
-               return (int) $GLOBALS['TYPO3_DB']->sql_insert_id();
+               $this->db->exec_INSERTquery('sys_file_storage', $field_values);
+               return (int)$this->db->sql_insert_id();
        }
 
        /**
         * Creates an object managed by this repository.
         *
         * @param array $databaseRow
-        * @return \TYPO3\CMS\Core\Resource\ResourceStorage
+        * @return ResourceStorage
         */
        protected function createDomainObject(array $databaseRow) {
                return $this->factory->getStorageObject($databaseRow['uid'], $databaseRow);
        }
 
-}
+       /**
+        * Test if the local filesystem is case sensitive
+        *
+        * @param string $absolutePath
+        * @return boolean
+        */
+       protected function testCaseSensitivity($absolutePath) {
+               $caseSensitive = TRUE;
+               $path = rtrim($absolutePath, '/') . '/aAbB';
+               $testFileExists = @file_exists($path);
 
+               // create test file
+               if (!$testFileExists) {
+                       touch($path);
+               }
 
-?>
\ No newline at end of file
+               // do the actual sensitivity check
+               if (@file_exists(strtoupper($path)) && @file_exists(strtolower($path))) {
+                       $caseSensitive = FALSE;
+               }
+
+               // clean filesystem
+               if (!$testFileExists) {
+                       unlink($path);
+               }
+
+               return $caseSensitive;
+       }
+
+}