diff options
author | Roeland Douma <rullzer@users.noreply.github.com> | 2015-09-06 16:56:35 +0200 |
---|---|---|
committer | Roeland Douma <rullzer@users.noreply.github.com> | 2015-09-06 16:56:35 +0200 |
commit | 24f5f50b20c4f49bcd602a3c322f2ee2deb0f95b (patch) | |
tree | b5ba1876566dfa1cc39341e8f58e419bc137d722 /lib/private | |
parent | 3642fb701a7fc0caba779de9f5d53bf12c27f5aa (diff) | |
parent | c6314fc699c7316973fa79f75b7d585e620323e9 (diff) | |
download | nextcloud-server-24f5f50b20c4f49bcd602a3c322f2ee2deb0f95b.tar.gz nextcloud-server-24f5f50b20c4f49bcd602a3c322f2ee2deb0f95b.zip |
Merge pull request #18742 from owncloud/mimetype-updatedb
Introduce mimetype DB update occ command
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/files/cache/cache.php | 96 | ||||
-rw-r--r-- | lib/private/files/type/detection.php | 30 | ||||
-rw-r--r-- | lib/private/files/type/loader.php | 165 | ||||
-rw-r--r-- | lib/private/server.php | 14 |
4 files changed, 217 insertions, 88 deletions
diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php index 8cf097421d4..5c04da1f0d5 100644 --- a/lib/private/files/cache/cache.php +++ b/lib/private/files/cache/cache.php @@ -35,6 +35,8 @@ namespace OC\Files\Cache; +use \OCP\Files\IMimeTypeLoader; + /** * Metadata cache for a storage * @@ -66,8 +68,8 @@ class Cache { */ protected $storageCache; - protected static $mimetypeIds = array(); - protected static $mimetypes = array(); + /** @var IMimeTypeLoader */ + protected $mimetypeLoader; /** * @param \OC\Files\Storage\Storage|string $storage @@ -83,6 +85,7 @@ class Cache { } $this->storageCache = new Storage($storage); + $this->mimetypeLoader = \OC::$server->getMimeTypeLoader(); } /** @@ -95,72 +98,6 @@ class Cache { } /** - * Get the numeric id for a mimetype - * - * Mimetypes are stored as integers in the cache to prevent duplicated data of the (usually) fairly limited amount of unique mimetypes - * If the supplied mimetype does not yet have a numeric id a new one will be generated - * - * @param string $mime - * @return int - */ - public function getMimetypeId($mime) { - if (empty($mime)) { - // Can not insert empty string into Oracle NOT NULL column. - $mime = 'application/octet-stream'; - } - if (empty(self::$mimetypeIds)) { - $this->loadMimetypes(); - } - - if (!isset(self::$mimetypeIds[$mime])) { - try { - $connection = \OC_DB::getConnection(); - $connection->insertIfNotExist('*PREFIX*mimetypes', [ - 'mimetype' => $mime, - ]); - $this->loadMimetypes(); - } catch (\Doctrine\DBAL\DBALException $e) { - \OCP\Util::writeLog('core', 'Exception during mimetype insertion: ' . $e->getmessage(), \OCP\Util::DEBUG); - return -1; - } - } - - return self::$mimetypeIds[$mime]; - } - - - /** - * Get the mimetype (as string) from a mimetype id - * - * @param int $id - * @return string | null the mimetype for the id or null if the id is not known - */ - public function getMimetype($id) { - if (empty(self::$mimetypes)) { - $this->loadMimetypes(); - } - - return isset(self::$mimetypes[$id]) ? self::$mimetypes[$id] : null; - } - - /** - * Load all known mimetypes and mimetype ids from the database - * - * @throws \OC\DatabaseException - */ - public function loadMimetypes() { - self::$mimetypeIds = self::$mimetypes = array(); - - $result = \OC_DB::executeAudited('SELECT `id`, `mimetype` FROM `*PREFIX*mimetypes`', array()); - if ($result) { - while ($row = $result->fetchRow()) { - self::$mimetypeIds[$row['mimetype']] = $row['id']; - self::$mimetypes[$row['id']] = $row['mimetype']; - } - } - } - - /** * get the stored metadata of a file or folder * * the returned cache entry contains at least the following values: @@ -222,8 +159,8 @@ class Cache { $data['storage_mtime'] = (int)$data['storage_mtime']; $data['encrypted'] = (bool)$data['encrypted']; $data['storage'] = $this->storageId; - $data['mimetype'] = $this->getMimetype($data['mimetype']); - $data['mimepart'] = $this->getMimetype($data['mimepart']); + $data['mimetype'] = $this->mimetypeLoader->getMimetypeById($data['mimetype']); + $data['mimepart'] = $this->mimetypeLoader->getMimetypeById($data['mimepart']); if ($data['storage_mtime'] == 0) { $data['storage_mtime'] = $data['mtime']; } @@ -258,8 +195,8 @@ class Cache { $result = \OC_DB::executeAudited($sql, array($fileId)); $files = $result->fetchAll(); foreach ($files as &$file) { - $file['mimetype'] = $this->getMimetype($file['mimetype']); - $file['mimepart'] = $this->getMimetype($file['mimepart']); + $file['mimetype'] = $this->mimetypeLoader->getMimetypeById($file['mimetype']); + $file['mimepart'] = $this->mimetypeLoader->getMimetypeById($file['mimepart']); if ($file['storage_mtime'] == 0) { $file['storage_mtime'] = $file['mtime']; } @@ -385,9 +322,9 @@ class Cache { $params[] = md5($value); $queryParts[] = '`path_hash`'; } elseif ($name === 'mimetype') { - $params[] = $this->getMimetypeId(substr($value, 0, strpos($value, '/'))); + $params[] = $this->mimetypeLoader->getId(substr($value, 0, strpos($value, '/'))); $queryParts[] = '`mimepart`'; - $value = $this->getMimetypeId($value); + $value = $this->mimetypeLoader->getId($value); } elseif ($name === 'storage_mtime') { if (!isset($data['mtime'])) { $params[] = $value; @@ -613,7 +550,6 @@ class Cache { * @return array an array of cache entries where the name matches the search pattern */ public function search($pattern) { - // normalize pattern $pattern = $this->normalize($pattern); @@ -630,8 +566,8 @@ class Cache { $files = array(); while ($row = $result->fetchRow()) { - $row['mimetype'] = $this->getMimetype($row['mimetype']); - $row['mimepart'] = $this->getMimetype($row['mimepart']); + $row['mimetype'] = $this->mimetypeLoader->getMimetypeById($row['mimetype']); + $row['mimepart'] = $this->mimetypeLoader->getMimetypeById($row['mimepart']); $files[] = $row; } return $files; @@ -652,12 +588,12 @@ class Cache { } $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`, `permissions` FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?'; - $mimetype = $this->getMimetypeId($mimetype); + $mimetype = $this->mimetypeLoader->getId($mimetype); $result = \OC_DB::executeAudited($sql, array($mimetype, $this->getNumericStorageId())); $files = array(); while ($row = $result->fetchRow()) { - $row['mimetype'] = $this->getMimetype($row['mimetype']); - $row['mimepart'] = $this->getMimetype($row['mimepart']); + $row['mimetype'] = $this->mimetypeLoader->getMimetypeById($row['mimetype']); + $row['mimepart'] = $this->mimetypeLoader->getMimetypeById($row['mimepart']); $files[] = $row; } return $files; diff --git a/lib/private/files/type/detection.php b/lib/private/files/type/detection.php index ba286637df3..3dc3975fb2a 100644 --- a/lib/private/files/type/detection.php +++ b/lib/private/files/type/detection.php @@ -6,6 +6,7 @@ * @author Robin Appelman <icewind@owncloud.com> * @author Roeland Jago Douma <roeland@famdouma.nl> * @author Thomas Tanghus <thomas@tanghus.net> + * @author Robin McCorkell <rmccorkell@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 @@ -101,16 +102,23 @@ class Detection implements IMimeTypeDetector { return; } - $file = file_get_contents($this->configDir . '/mimetypealiases.dist.json'); - $this->mimeTypeAlias = get_object_vars(json_decode($file)); + $this->mimeTypeAlias = json_decode(file_get_contents($this->configDir . '/mimetypealiases.dist.json'), true); if (file_exists($this->configDir . '/mimetypealiases.json')) { - $custom = get_object_vars(json_decode(file_get_contents($this->configDir . '/mimetypealiases.json'))); + $custom = json_decode(file_get_contents($this->configDir . '/mimetypealiases.json'), true); $this->mimeTypeAlias = array_merge($this->mimeTypeAlias, $custom); } } /** + * @return array + */ + public function getAllAliases() { + $this->loadAliases(); + return $this->mimeTypeAlias; + } + + /** * Add mimetype mappings if they are not yet present */ private function loadMappings() { @@ -118,20 +126,26 @@ class Detection implements IMimeTypeDetector { return; } - $dist = file_get_contents($this->configDir . '/mimetypemapping.dist.json'); - $mimetypemapping = get_object_vars(json_decode($dist)); + $mimetypemapping = json_decode(file_get_contents($this->configDir . '/mimetypemapping.dist.json'), true); //Check if need to load custom mappings if (file_exists($this->configDir . '/mimetypemapping.json')) { - $custom = file_get_contents($this->configDir . '/mimetypemapping.json'); - $custom_mapping = get_object_vars(json_decode($custom)); - $mimetypemapping = array_merge($mimetypemapping, $custom_mapping); + $custom = json_decode(file_get_contents($this->configDir . '/mimetypemapping.json'), true); + $mimetypemapping = array_merge($mimetypemapping, $custom); } $this->registerTypeArray($mimetypemapping); } /** + * @return array + */ + public function getAllMappings() { + $this->loadMappings(); + return $this->mimetypes; + } + + /** * detect mimetype only based on filename, content of file is not used * * @param string $path diff --git a/lib/private/files/type/loader.php b/lib/private/files/type/loader.php new file mode 100644 index 00000000000..df893306615 --- /dev/null +++ b/lib/private/files/type/loader.php @@ -0,0 +1,165 @@ +<?php +/** + * @author Robin McCorkell <rmccorkell@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OC\Files\Type; + +use OCP\Files\IMimeTypeLoader; +use OCP\IDBConnection; + +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; + +/** + * Mimetype database loader + * + * @package OC\Files\Type + */ +class Loader implements IMimeTypeLoader { + + /** @var IDBConnection */ + private $dbConnection; + + /** @var array [id => mimetype] */ + protected $mimetypes; + + /** @var array [mimetype => id] */ + protected $mimetypeIds; + + /** + * @param IDBConnection $dbConnection + */ + public function __construct(IDBConnection $dbConnection) { + $this->dbConnection = $dbConnection; + $this->mimetypes = []; + $this->mimetypeIds = []; + } + + /** + * Get a mimetype from its ID + * + * @param int $id + * @return string|null + */ + public function getMimetypeById($id) { + if (!$this->mimetypes) { + $this->loadMimetypes(); + } + if (isset($this->mimetypes[$id])) { + return $this->mimetypes[$id]; + } + return null; + } + + /** + * Get a mimetype ID, adding the mimetype to the DB if it does not exist + * + * @param string $mimetype + * @return int + */ + public function getId($mimetype) { + if (!$this->mimetypeIds) { + $this->loadMimetypes(); + } + if (isset($this->mimetypeIds[$mimetype])) { + return $this->mimetypeIds[$mimetype]; + } + return $this->store($mimetype); + } + + /** + * Test if a mimetype exists in the database + * + * @param string $mimetype + * @return bool + */ + public function exists($mimetype) { + if (!$this->mimetypeIds) { + $this->loadMimetypes(); + } + return isset($this->mimetypeIds[$mimetype]); + } + + /** + * Store a mimetype in the DB + * + * @param string $mimetype + * @param int inserted ID + */ + protected function store($mimetype) { + try { + $qb = $this->dbConnection->getQueryBuilder(); + $qb->insert('mimetypes') + ->values([ + 'mimetype' => $qb->createNamedParameter($mimetype) + ]); + $qb->execute(); + } catch (UniqueConstraintViolationException $e) { + // something inserted it before us + } + + $fetch = $this->dbConnection->getQueryBuilder(); + $fetch->select('id') + ->from('mimetypes') + ->where( + $fetch->expr()->eq('mimetype', $fetch->createNamedParameter($mimetype) + )); + $row = $fetch->execute()->fetch(); + + $this->mimetypes[$row['id']] = $mimetype; + $this->mimetypeIds[$mimetype] = $row['id']; + return $row['id']; + } + + /** + * Load all mimetypes from DB + */ + private function loadMimetypes() { + $qb = $this->dbConnection->getQueryBuilder(); + $qb->select('id', 'mimetype') + ->from('mimetypes'); + $results = $qb->execute()->fetchAll(); + + foreach ($results as $row) { + $this->mimetypes[$row['id']] = $row['mimetype']; + $this->mimetypeIds[$row['mimetype']] = $row['id']; + } + } + + /** + * Update filecache mimetype based on file extension + * + * @param string $ext file extension + * @param int $mimetypeId + * @return int number of changed rows + */ + public function updateFilecache($ext, $mimetypeId) { + $update = $this->dbConnection->getQueryBuilder(); + $update->update('filecache') + ->set('mimetype', $update->createNamedParameter($mimetypeId)) + ->where($update->expr()->neq( + 'mimetype', $update->createNamedParameter($mimetypeId) + )) + ->andWhere($update->expr()->like( + $update->createFunction('LOWER(`name`)'), $update->createNamedParameter($ext) + )); + return $update->execute(); + } + +} diff --git a/lib/private/server.php b/lib/private/server.php index 24674d2e3c7..393c1840973 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -470,6 +470,11 @@ class Server extends SimpleContainer implements IServerContainer { $c->getURLGenerator(), \OC::$configDir); }); + $this->registerService('MimeTypeLoader', function(Server $c) { + return new \OC\Files\Type\Loader( + $c->getDatabaseConnection() + ); + }); $this->registerService('CapabilitiesManager', function (Server $c) { $manager = new \OC\CapabilitiesManager(); $manager->registerCapability(function() use ($c) { @@ -1011,6 +1016,15 @@ class Server extends SimpleContainer implements IServerContainer { } /** + * Get the MimeTypeLoader + * + * @return \OCP\Files\IMimeTypeLoader + */ + public function getMimeTypeLoader() { + return $this->query('MimeTypeLoader'); + } + + /** * Get the manager of all the capabilities * * @return \OC\CapabilitiesManager |