1<?php 2namespace TYPO3\CMS\Core; 3 4/* 5 * This file is part of the TYPO3 CMS project. 6 * 7 * It is free software; you can redistribute it and/or modify it under 8 * the terms of the GNU General Public License, either version 2 9 * of the License, or any later version. 10 * 11 * For the full copyright and license information, please read the 12 * LICENSE.txt file that was distributed with this source code. 13 * 14 * The TYPO3 project - inspiring people to share! 15 */ 16 17use TYPO3\CMS\Core\Database\Connection; 18use TYPO3\CMS\Core\Database\ConnectionPool; 19use TYPO3\CMS\Core\Utility\GeneralUtility; 20 21/** 22 * A class to store and retrieve entries in a registry database table. 23 * 24 * This is a simple, persistent key-value-pair store. 25 * 26 * The intention is to have a place where we can store things (mainly settings) 27 * that should live for more than one request, longer than a session, and that 28 * shouldn't expire like it would with a cache. You can actually think of it 29 * being like the Windows Registry in some ways. 30 */ 31class Registry implements SingletonInterface 32{ 33 /** 34 * @var array 35 */ 36 protected $entries = []; 37 38 /** 39 * @var array 40 */ 41 protected $loadedNamespaces = []; 42 43 /** 44 * Returns a persistent entry. 45 * 46 * @param string $namespace Extension key of extension 47 * @param string $key Key of the entry to return. 48 * @param mixed $defaultValue Optional default value to use if this entry has never been set. Defaults to NULL. 49 * @return mixed Value of the entry. 50 * @throws \InvalidArgumentException Throws an exception if the given namespace is not valid 51 */ 52 public function get($namespace, $key, $defaultValue = null) 53 { 54 $this->validateNamespace($namespace); 55 if (!$this->isNamespaceLoaded($namespace)) { 56 $this->loadEntriesByNamespace($namespace); 57 } 58 return $this->entries[$namespace][$key] ?? $defaultValue; 59 } 60 61 /** 62 * Sets a persistent entry. 63 * 64 * This is the main method that can be used to store a key-value-pair. 65 * 66 * Do not store binary data into the registry, it's not build to do that, 67 * instead use the proper way to store binary data: The filesystem. 68 * 69 * @param string $namespace Extension key of extension 70 * @param string $key The key of the entry to set. 71 * @param mixed $value The value to set. This can be any PHP data type; This class takes care of serialization 72 * @throws \InvalidArgumentException Throws an exception if the given namespace is not valid 73 */ 74 public function set($namespace, $key, $value) 75 { 76 $this->validateNamespace($namespace); 77 if (!$this->isNamespaceLoaded($namespace)) { 78 $this->loadEntriesByNamespace($namespace); 79 } 80 $serializedValue = serialize($value); 81 $connection = GeneralUtility::makeInstance(ConnectionPool::class) 82 ->getConnectionForTable('sys_registry'); 83 $rowCount = $connection->count( 84 '*', 85 'sys_registry', 86 ['entry_namespace' => $namespace, 'entry_key' => $key] 87 ); 88 if ((int)$rowCount < 1) { 89 $connection->insert( 90 'sys_registry', 91 ['entry_namespace' => $namespace, 'entry_key' => $key, 'entry_value' => $serializedValue], 92 ['entry_value' => Connection::PARAM_LOB] 93 ); 94 } else { 95 $connection->update( 96 'sys_registry', 97 ['entry_value' => $serializedValue], 98 ['entry_namespace' => $namespace, 'entry_key' => $key], 99 ['entry_value' => Connection::PARAM_LOB] 100 ); 101 } 102 $this->entries[$namespace][$key] = $value; 103 } 104 105 /** 106 * Unset a persistent entry. 107 * 108 * @param string $namespace Extension key of extension 109 * @param string $key The key of the entry to unset. 110 * @throws \InvalidArgumentException Throws an exception if the given namespace is not valid 111 */ 112 public function remove($namespace, $key) 113 { 114 $this->validateNamespace($namespace); 115 GeneralUtility::makeInstance(ConnectionPool::class) 116 ->getConnectionForTable('sys_registry') 117 ->delete( 118 'sys_registry', 119 ['entry_namespace' => $namespace, 'entry_key' => $key] 120 ); 121 unset($this->entries[$namespace][$key]); 122 } 123 124 /** 125 * Unset all persistent entries of given namespace. 126 * 127 * @param string $namespace Extension key of extension 128 * @throws \InvalidArgumentException Throws an exception if given namespace is invalid 129 */ 130 public function removeAllByNamespace($namespace) 131 { 132 $this->validateNamespace($namespace); 133 GeneralUtility::makeInstance(ConnectionPool::class) 134 ->getConnectionForTable('sys_registry') 135 ->delete( 136 'sys_registry', 137 ['entry_namespace' => $namespace] 138 ); 139 unset($this->entries[$namespace]); 140 } 141 142 /** 143 * check if the given namespace is loaded 144 * 145 * @param string $namespace Extension key of extension 146 * @return bool True if namespace was loaded already 147 */ 148 protected function isNamespaceLoaded($namespace) 149 { 150 return isset($this->loadedNamespaces[$namespace]); 151 } 152 153 /** 154 * Loads all entries of given namespace into the internal $entries cache. 155 * 156 * @param string $namespace Extension key of extension 157 * @throws \InvalidArgumentException Thrown if given namespace is invalid 158 */ 159 protected function loadEntriesByNamespace($namespace) 160 { 161 $this->validateNamespace($namespace); 162 $this->entries[$namespace] = []; 163 $result = GeneralUtility::makeInstance(ConnectionPool::class) 164 ->getConnectionForTable('sys_registry') 165 ->select( 166 ['entry_key', 'entry_value'], 167 'sys_registry', 168 ['entry_namespace' => $namespace] 169 ); 170 while ($row = $result->fetch()) { 171 $this->entries[$namespace][$row['entry_key']] = unserialize($row['entry_value']); 172 } 173 $this->loadedNamespaces[$namespace] = true; 174 } 175 176 /** 177 * Check namespace key 178 * It must be at least two characters long. The word 'core' is reserved for TYPO3 core usage. 179 * 180 * @param string $namespace Namespace 181 * @throws \InvalidArgumentException Thrown if given namespace is invalid 182 */ 183 protected function validateNamespace($namespace) 184 { 185 if (strlen($namespace) < 2) { 186 throw new \InvalidArgumentException('Given namespace must be longer than two characters.', 1249755131); 187 } 188 } 189} 190