PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/_WV2/MetaInfo.php

https://bitbucket.org/webvariants/extended-meta-infos
PHP | 372 lines | 154 code | 47 blank | 171 comment | 10 complexity | 36ede6f83e613aac824cd092b2e8b6f8 MD5 | raw file
  1. <?php
  2. /*
  3. * Copyright (c) 2010, webvariants GbR, http://www.webvariants.de
  4. *
  5. * This file is released under the terms of the MIT license. You can find the
  6. * complete text in the attached LICENSE file or online at:
  7. *
  8. * http://www.opensource.org/licenses/mit-license.php
  9. */
  10. /**
  11. * @defgroup objects Objekt-Abstraktion
  12. */
  13. /**
  14. * Metainformation
  15. *
  16. * Eine Metainformation ist eine zusätzliche Information, die einem Artikel /
  17. * Kategorie / Medium zugewiesen werden kann. Sie besteht aus einem internen
  18. * Namen, einem Ttel, einem Datentyp sowie einigen weiteren Daten.
  19. *
  20. * Metainformationen können über Artikeltypen gruppiert werden. Auf diese Weise
  21. * kann einem Artikel immer eine ganz bestimmte Teilmenge aller verfügbaren
  22. * Metainformationen zugewiesen werden.
  23. *
  24. * Eine einzelne Metainformation kann nur entweder für Artikel oder für Kategorien
  25. * oder für Medien verwendet werden. Die internen Namen müssen für jeden dieser
  26. * drei Bereiche jeweils eindeutig sein.
  27. *
  28. * Artikel-Metainformationen können noch einmal in zwei Bereiche unterteilt
  29. * werden:
  30. *
  31. * - Content-Seite: Die Information (das Formular) wird direkt auf der
  32. * Slice-Seite eines Artikels angezeigt.
  33. * - Extra-Seite: Die Information wird auf der separaten Meta-Seite von
  34. * Redaxo angezeigt.
  35. *
  36. * @ingroup objects
  37. * @author Christoph
  38. */
  39. class _WV2_MetaInfo extends WV_Object implements _WV_IProperty {
  40. protected $id; ///< int die interne ID
  41. protected $name; ///< string der interne Name
  42. protected $title; ///< string der angezeigte Name (Titel)
  43. protected $position; ///< int Position in der Sortierreihenfolge
  44. protected $datatype; ///< int die Datentyp-ID
  45. protected $params; ///< string die Datentyp-Parameter
  46. protected $default; ///< string der Standardwert der Metainformation
  47. protected $separatePage; ///< boolean wenn true, wird die Information nur auf der separaten Meta-Seite von Artikeln angezeigt
  48. protected $articleTypes; ///< array Liste von Artikeltypen, denen diese Information zugewiesen ist
  49. protected $type; ///< int Typ (Artikel-, Kategorie- oder Medium-Metainformation)
  50. protected $helptext; ///< string der Hilfetext
  51. protected $hidden; ///< boolean wenn true wird die Info im Backend nicht angezeigt
  52. protected $origArticleTypes;
  53. protected static $instances = array();
  54. /**
  55. * Singleton
  56. *
  57. * Gibt eine Instanz der Klasse zurück.
  58. *
  59. * @throws WV2_Exception falls die ID nicht gefunden wurde
  60. * @param mixed $idOrName die ID (int) oder der interne Name (string) der Metainformation
  61. * @param int $type der Typ
  62. * @param array $prefetchedData falls durch eine SQL-Anfrage bereits ganze Tupel geholt werden, können diese hier angegeben werden, um eine SQL-Anfrage zu sparen
  63. * @return _WV2_MetaInfo
  64. */
  65. public static function getInstance($idOrName, $type) {
  66. $id = self::getIDForName($idOrName, $type);
  67. $key = $id.'_'.intval($type);
  68. if (empty(self::$instances[$key])) {
  69. $callback = array(__CLASS__, '_getInstance');
  70. $instance = self::getFromCache('metainfoex.objects', $key, $callback, array($id, $type));
  71. self::$instances[$key] = $instance;
  72. }
  73. return self::$instances[$key];
  74. }
  75. protected static function _getInstance($id, $type) {
  76. return new self($id, $type);
  77. }
  78. /**
  79. * Konstruktor
  80. *
  81. * Holt (wenn nötig) die Daten der Metainformation und erzeugt das Objekt.
  82. *
  83. * @throws WV2_Exception falls die ID nicht gefunden wurde
  84. * @param mixed $id die ID (int) der Metainformation
  85. * @param int $type der Typ
  86. * @param array $prefetchedData falls durch eine SQL-Anfrage bereits ganze Tupel geholt werden, können diese hier angegeben werden, um eine SQL-Anfrage zu sparen
  87. */
  88. protected function __construct($id, $type)
  89. {
  90. $sql = WV_SQLEx::getInstance();
  91. $data = $sql->safeFetch('*', 'wv2_metainfo', 'id = ?', $id);
  92. if (!$data) {
  93. throw new WV2_Exception('Die Metainfo #'.$id.' konnte nicht gefunden werden!');
  94. }
  95. $this->id = (int) $data['id'];
  96. $this->name = $data['name'];
  97. $this->title = $data['title'];
  98. $this->position = (int) $data['position'];
  99. $this->datatype = (int) $data['datatype'];
  100. $this->params = $data['params'];
  101. $this->default = $data['default_option'];
  102. $this->separatePage = (bool) $data['separate_page'];
  103. $this->helptext = $data['helptext'];
  104. $this->hidden = (bool) $data['hidden'];
  105. $this->type = (int) $type;
  106. $this->articleTypes = array();
  107. if ($type == WV2_Metainfoex::TYPE_ARTICLE) {
  108. $this->articleTypes = $sql->getArray('SELECT type_id FROM ~wv2_metainfo_type WHERE metainfo_id = ?', $this->id, '~');
  109. $this->origArticleTypes = $this->articleTypes;
  110. }
  111. }
  112. /**
  113. * Datensatz aktualisieren
  114. *
  115. * Diese Methode prüft und speichert die über die Setter-Methoden gemachten
  116. * Änderungen permanent in der Datenbank. Sollte es dabei zu einem Konflikt
  117. * mit den Datentypen kommen, so wird die Methode standardmäßig die
  118. * notwendigen Konvertierungen direkt vornehmen, es sei denn, ihr wird dies
  119. * mit $convertDataIfRequired verboten.
  120. *
  121. * Geprüft wird, ob die nötigen Rechte bestehen, die Metainformation zu
  122. * bearbeiten und ob der (ggf. neue, geänderte) interne Name immer noch
  123. * eindeutig ist.
  124. *
  125. * Zusätzlich werden, falls sich die Zuordnung zu Artikeltypen geändert hat,
  126. * die nun nicht mehr benötigten / erlaubten Metadaten von Objekten entfernt.
  127. *
  128. * @throws WV2_Exception falls nicht genug Rechte bestehen oder der interne Name nicht eindeutig ist
  129. * @param boolean $convertDataIfRequired wenn true, werden Konflikte beim Datentyp automatisch bearbeitet
  130. * @param boolean $applyDefaults wenn true wird der Standardwert auf alle Artikel mit dieser Metainformation angewandt
  131. */
  132. public function update($convertDataIfRequired = true, $applyDefaults = false) {
  133. $crud = new _WV2_MetaInfo_CRUD($this, $this->origArticleTypes);
  134. $params = array($convertDataIfRequired, $applyDefaults);
  135. $retval = self::transactionGuard(array($crud, 'update'), $params, 'WV2_Exception');
  136. $this->origArticleTypes = $this->articleTypes;
  137. return $retval;
  138. }
  139. /**
  140. * Neue Metainformation erzeugen
  141. *
  142. * Diese Methode legt in der Datenbank eine neue Metainformation an. Dabei
  143. * werden die Rechte sowie die Eindeutigkeit des intenen Namens geprüft.
  144. *
  145. * @throws WV2_Exception falls die Rechte nicht ausreichen oder der interne Name nicht eindeutig ist
  146. * @param string $name interner Name
  147. * @param string $title angezeigter Titel
  148. * @param boolean $separatePage auf Slice-Seite (true) oder auf Meta-Seite (false)?
  149. * @param int $datatype Datentyp-ID
  150. * @param string $params Datentyp-Parameter
  151. * @param string $default der Standardwert (abhängig vom Datentyp)
  152. * @param string $helptext Hilfetext
  153. * @param array $arttypes Liste von Artikeltyp-IDs (int) (wird bei nicht-Artikel-Metainfos ignoriert)
  154. * @param int $type Typ (Artikel, Kategorie, Medium) (WV2_Metainfoex::TYPE-Konstante)
  155. * @param boolean $hidden wenn true wird die Metainfo im Backend nicht angezeigt
  156. * @return int die ID der neuen Metainfo
  157. */
  158. public static function create($name, $title, $separatePage, $datatype, $params, $default, $helptext, $arttypes, $type, $hidden = false) {
  159. $params = array($name, $title, $separatePage, $datatype, $params, $default, $helptext, $arttypes, $type, $hidden);
  160. return self::transactionGuard(array('_WV2_MetaInfo_CRUD', 'create'), $params, 'WV2_Exception');
  161. }
  162. /**
  163. * Metainformation löschen
  164. *
  165. * Hiermit wird eine Metainfo inkl. der zu ihr gehörenden Metadaten aus der
  166. * Datenbank entfernt. Das Löschen ist nur erlaubt, wenn der Benutzer das
  167. * Recht metainfo_complete hat.
  168. */
  169. public function delete() {
  170. $crud = new _WV2_MetaInfo_CRUD($this, array());
  171. return self::transactionGuard(array($crud, 'delete'), array(), 'WV2_Exception');
  172. }
  173. /**
  174. * Verschieben
  175. *
  176. * Diese Methode wird vom Ajax-Handler aufgerufen, um eine Metainformation
  177. * zu verschieben. Die neue Position ist dabei eindeutig innerhalb von
  178. * Metainfo-Typen (d.h., die drei Listen von Metainfos werden einzeln
  179. * nummeriert).
  180. *
  181. * @param int $position die neue Position (1 bis n)
  182. */
  183. public function shift($position) {
  184. $crud = new _WV2_MetaInfo_CRUD($this, array());
  185. $retval = self::transactionGuard(array($crud, 'shift'), $position, 'WV2_Exception');
  186. $this->position = $position;
  187. return $retval;
  188. }
  189. /**
  190. * Datentyp/Parameter-Kompatibilität prüfen
  191. *
  192. * Diese Methode prüft, ob bei einer Datentyp-Änderung die neuen Typen
  193. * ineinander konvertiert werden können. Falls sich die Parameter geändert
  194. * haben, wird geprüft, ob diese weiterhin kompatibel sind.
  195. *
  196. * Tritt eine Inkompatibilität auf, wird der Benutzer informiert und eine
  197. * Bestätigung von ihm eingefordert.
  198. *
  199. * @param boolean $confirmed wenn true, beendet die Methode direkt mit true
  200. * @param _WV2_MetaInfo $metainfo die betreffende Metainformation
  201. * @param int $newDatatype die ID des neuen Datentyps
  202. * @return boolean true, wenn alles i.O. ist, false, wenn ein Formular generiert wurde und der Controller anhalten soll
  203. */
  204. public static function checkCompatibility($confirmed, $metainfo, $newDatatype) {
  205. $params = array($confirmed, $metainfo, $newDatatype);
  206. return call_user_func_array(array('_WV2_MetaInfo_CRUD', 'checkCompatibility'), $params);
  207. }
  208. /**
  209. * Datentyp und Parameter ermitteln
  210. *
  211. * Gibt die ID des Datentyps und die Parameter für eine beliebige
  212. * Metainformation zurück. NICHT für das aktuelle MetaInfo-Objekt!
  213. *
  214. * @throws WV2_Exception falls der Name als String nicht gefunden wurde
  215. * @param mixed $metainfo der interne Name (string), die ID (int) oder direkt ein _WV2_MetaInfo-Objekt
  216. * @param int $type der Typ der Metainformation
  217. * @return array assoziatives Array mit 'datatype' und 'params' als Schlüssel
  218. */
  219. public static function getDatatypeWithParams($metainfo, $type = WV2_Metainfoex::TYPE_ARTICLE) {
  220. if ($metainfo instanceof self) {
  221. return array('datatype' => $metainfo->getDatatypeID(), 'params' => $metainfo->getParams());
  222. }
  223. elseif ($metainfo instanceof _WV2_MetaInfo_CRUD) {
  224. return array('datatype' => $metainfo->call('getDatatypeID'), 'params' => $metainfo->call('getParams'));
  225. }
  226. $metainfo = self::getIDForName($metainfo, $type);
  227. return WV_SQLEx::getInstance()->fetch('datatype,params', 'wv2_metainfo', 'id = ?', $metainfo);
  228. }
  229. /**
  230. * ID ermitteln
  231. *
  232. * Gibt die ID einer Metainfo für deren Namen zurück.
  233. *
  234. * @throws WV2_Exception falls der Name nicht gefunden wurde
  235. * @param string $name der interne Name der Metainformation
  236. * @param int $type der Typ der Metainformation
  237. * @return int die ID
  238. */
  239. public static function getIDForName($name, $type = WV2_Metainfoex::TYPE_ARTICLE)
  240. {
  241. if (sly_Util_String::isInteger($name)) {
  242. return (int) $name;
  243. }
  244. $cache = WV_DeveloperUtils::getCache();
  245. $namespace = 'metainfoex.idmappings';
  246. $cacheKey = WV_Cache::generateKey('metainfo', $name, $type);
  247. $id = $cache->get($namespace, $cacheKey, -1);
  248. if ($id >= 0) {
  249. return (int) $id;
  250. }
  251. $id = WV_SQLEx::getInstance()->safeFetch('id', 'wv2_metainfo', 'name = ? AND meta_type = ?', array($name, $type));
  252. if ($id === false) {
  253. throw new WV2_Exception(t('metainfo_infonotfound', $name));
  254. }
  255. $cache->set($namespace, $cacheKey, (int) $id);
  256. return (int) $id;
  257. }
  258. /*@{*/
  259. /**
  260. * Getter
  261. *
  262. * Gibt die entsprechende Eigenschaft ungefiltert zurück.
  263. *
  264. * @return mixed die entsprechende Eigenschaft
  265. */
  266. public function getID() { return $this->id; }
  267. public function getName() { return $this->name; }
  268. public function getTitle() { return $this->title; }
  269. public function getPosition() { return $this->position; }
  270. public function getDatatype() { return $this->datatype; }
  271. public function getDatatypeID() { return $this->datatype; }
  272. public function getParams() { return $this->params; }
  273. public function getDefault() { return $this->default; }
  274. public function getArticleTypes() { return $this->articleTypes; }
  275. public function getSeparatePage() { return $this->separatePage; }
  276. public function getType() { return $this->type; }
  277. public function getHelpText() { return $this->helptext; }
  278. public function isHidden() { return $this->hidden; }
  279. public function isMultilingual() { return false; }
  280. /*@}*/
  281. /*@{*/
  282. /**
  283. * Setter
  284. *
  285. * Setzt die entsprechende Eigenschaft. Für alle bis auf den Artikeltyp
  286. * wird das Recht metainfo_complete benötigt. Für den Artikeltyp benötigt
  287. * man metainfo_articletype.
  288. * Das Überprüfen der Werte übernimmt erst die update()-Methode.
  289. *
  290. * @param mixed $value der neue Wert
  291. */
  292. public function setDatatype($value) {
  293. $this->datatype = (int) $value;
  294. }
  295. public function setDefault($value) {
  296. $this->default = trim($value);
  297. }
  298. public function setHelpText($value) {
  299. $this->helptext = trim($value);
  300. }
  301. public function setName($value) {
  302. $value = trim($value);
  303. if (empty($value)) {
  304. throw new WV2_Exception(t('metainfo_intnameempty'));
  305. }
  306. $this->name = $value;
  307. }
  308. public function setParams($value) {
  309. $this->params = $value;
  310. }
  311. public function setTitle($value) {
  312. $value = trim($value);
  313. if (empty($value)) {
  314. throw new WV2_Exception(t('metainfo_titleempty'));
  315. }
  316. $this->title = $value;
  317. }
  318. public function setArticleTypes($value) {
  319. $this->articleTypes = array_unique(array_map('intval', sly_makeArray($value)));
  320. }
  321. public function setSeparatePage($value) {
  322. $this->separatePage = (bool) $value;
  323. }
  324. /*@}*/
  325. }