PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/turba/lib/Object.php

https://github.com/wrobel/horde-fw3
PHP | 433 lines | 260 code | 40 blank | 133 comment | 49 complexity | 17ebd3118df8302969683a94760f4117 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, LGPL-2.1, BSD-2-Clause
  1. <?php
  2. /**
  3. * The Turba_Object:: class provides a base implementation for Turba
  4. * objects - people, groups, restaurants, etc.
  5. *
  6. * $Horde: turba/lib/Object.php,v 1.17.10.13 2009-10-24 18:48:23 mrubinsk Exp $
  7. *
  8. * @author Chuck Hagenbuch <chuck@horde.org>
  9. * @author Jon Parise <jon@csh.rit.edu>
  10. * @package Turba
  11. */
  12. class Turba_Object {
  13. /**
  14. * Underlying driver.
  15. *
  16. * @var Turba_Driver
  17. */
  18. var $driver;
  19. /**
  20. * Hash of attributes for this contact.
  21. *
  22. * @var array
  23. */
  24. var $attributes;
  25. /**
  26. * Reference to this object's VFS instance.
  27. *
  28. * @var VFS
  29. */
  30. var $_vfs;
  31. /**
  32. * Constructs a new Turba_Object object.
  33. *
  34. * @param Turba_Driver $driver The source that this object came from.
  35. * @param array $attributes Hash of attributes for this object.
  36. */
  37. function Turba_Object(&$driver, $attributes = array())
  38. {
  39. $this->driver = &$driver;
  40. $this->attributes = $attributes;
  41. $this->attributes['__type'] = 'Object';
  42. }
  43. /**
  44. * Returns a key-value hash containing all properties of this object.
  45. *
  46. * @return array All properties of this object.
  47. */
  48. function getAttributes()
  49. {
  50. return $this->attributes;
  51. }
  52. /**
  53. * Returns the name of the address book that this object is from.
  54. */
  55. function getSource()
  56. {
  57. return $this->driver->getName();
  58. }
  59. /**
  60. * Get a fully qualified key for this contact.
  61. *
  62. * @param string $delimiter Delimiter for the parts of the key, defaults to ':'.
  63. *
  64. * @return string Fully qualified contact id.
  65. */
  66. function getGuid($delimiter = ':')
  67. {
  68. return 'turba' . $delimiter . $this->driver->getName() . $delimiter . $this->getValue('__uid');
  69. }
  70. /**
  71. * Returns the value of the specified attribute.
  72. *
  73. * @param string $attribute The attribute to retrieve.
  74. *
  75. * @return mixed The value of $attribute, an array (for photo type)
  76. * or the empty string.
  77. */
  78. function getValue($attribute)
  79. {
  80. /* Cache hooks to avoid multiple file_exists() calls. */
  81. static $hooks;
  82. if (!isset($hooks)) {
  83. $hooks = array();
  84. if (is_callable(array('Horde', 'loadConfiguration'))) {
  85. Horde::loadConfiguration('hooks.php', null, 'turba');
  86. } else {
  87. if (file_exists(TURBA_BASE . '/config/hooks.php')) {
  88. include_once TURBA_BASE . '/config/hooks.php';
  89. }
  90. }
  91. }
  92. if (!isset($hooks[$attribute])) {
  93. $function = '_turba_hook_decode_' . $attribute;
  94. if (function_exists($function)) {
  95. $hooks[$attribute] = $function;
  96. } else {
  97. $hooks[$attribute] = false;
  98. }
  99. }
  100. if (isset($this->attributes[$attribute]) &&
  101. !empty($hooks[$attribute])) {
  102. return call_user_func_array($hooks[$attribute],
  103. array($this->attributes[$attribute], &$this));
  104. }
  105. if (isset($this->driver->map[$attribute]) &&
  106. is_array($this->driver->map[$attribute])) {
  107. $args = array();
  108. foreach ($this->driver->map[$attribute]['fields'] as $field) {
  109. $args[] = $this->getValue($field);
  110. }
  111. return trim(vsprintf($this->driver->map[$attribute]['format'], $args), " \t\n\r\0\x0B,");
  112. } elseif (!isset($this->attributes[$attribute])) {
  113. return null;
  114. } elseif (isset($GLOBALS['attributes'][$attribute]) &&
  115. $GLOBALS['attributes'][$attribute]['type'] == 'image') {
  116. return empty($this->attributes[$attribute])
  117. ? null
  118. : array('load' => array('file' => basename(tempnam(Horde::getTempDir(), 'horde_form_')),
  119. 'data' => $this->attributes[$attribute]));
  120. } else {
  121. return $this->attributes[$attribute];
  122. }
  123. }
  124. /**
  125. * Sets the value of the specified attribute.
  126. *
  127. * @param string $attribute The attribute to set.
  128. * @param string $value The value of $attribute.
  129. */
  130. function setValue($attribute, $value)
  131. {
  132. /* Cache hooks to avoid multiple file_exists() calls. */
  133. static $hooks;
  134. if (!isset($hooks)) {
  135. $hooks = array();
  136. if (is_callable(array('Horde', 'loadConfiguration'))) {
  137. Horde::loadConfiguration('hooks.php', null, 'turba');
  138. } else {
  139. if (file_exists(TURBA_BASE . '/config/hooks.php')) {
  140. include_once TURBA_BASE . '/config/hooks.php';
  141. }
  142. }
  143. }
  144. if (!isset($hooks[$attribute])) {
  145. $function = '_turba_hook_encode_' . $attribute;
  146. if (function_exists($function)) {
  147. $hooks[$attribute] = $function;
  148. } else {
  149. $hooks[$attribute] = false;
  150. }
  151. }
  152. if ($hooks[$attribute]) {
  153. $value = call_user_func_array($hooks[$attribute], array($value, $this->attributes[$attribute], &$this));
  154. }
  155. if (isset($this->driver->map[$attribute]) &&
  156. is_array($this->driver->map[$attribute]) &&
  157. !isset($this->driver->map[$attribute]['attribute'])) {
  158. return false;
  159. }
  160. $this->attributes[$attribute] = $value;
  161. return true;
  162. }
  163. /**
  164. * Determines whether or not the object has a value for the specified
  165. * attribute.
  166. *
  167. * @param string $attribute The attribute to check.
  168. *
  169. * @return boolean Whether or not there is a value for $attribute.
  170. */
  171. function hasValue($attribute)
  172. {
  173. if (isset($this->driver->map[$attribute]) &&
  174. is_array($this->driver->map[$attribute])) {
  175. foreach ($this->driver->map[$attribute]['fields'] as $field) {
  176. if ($this->hasValue($field)) {
  177. return true;
  178. }
  179. }
  180. return false;
  181. } else {
  182. return !is_null($this->getValue($attribute));
  183. }
  184. }
  185. /**
  186. * Returns true if this object is a group of multiple contacts.
  187. *
  188. * @return boolean True if this object is a group of multiple contacts.
  189. */
  190. function isGroup()
  191. {
  192. return false;
  193. }
  194. /**
  195. * Returns true if this object is editable by the current user.
  196. *
  197. * @return boolean Whether or not the current user can edit this object
  198. */
  199. function isEditable()
  200. {
  201. return $this->driver->hasPermission(PERMS_EDIT);
  202. }
  203. /**
  204. * Returns whether or not the current user has the requested permission.
  205. *
  206. * @param integer $perm The permission to check.
  207. *
  208. * @return boolean True if user has the permission.
  209. */
  210. function hasPermission($perm)
  211. {
  212. return $this->driver->hasPermission($perm);
  213. }
  214. /**
  215. * Contact url.
  216. */
  217. function url($view = null, $full = false)
  218. {
  219. $url = Util::addParameter('contact.php',
  220. array('source' => $this->driver->name,
  221. 'key' => $this->getValue('__key')));
  222. if (!is_null($view)) {
  223. $url = Util::addParameter($url, 'view', $view);
  224. }
  225. return Horde::applicationUrl($url, $full);
  226. }
  227. /**
  228. * Saves a file into the VFS backend associated with this object.
  229. *
  230. * @param array $info A hash with the file information as returned from a
  231. * Horde_Form_Type_file.
  232. */
  233. function addFile($info)
  234. {
  235. $result = $this->_vfsInit();
  236. if (is_a($result, 'PEAR_Error')) {
  237. return $result;
  238. }
  239. $dir = TURBA_VFS_PATH . '/' . $this->getValue('__uid');
  240. $file = $info['name'];
  241. while ($this->_vfs->exists($dir, $file)) {
  242. if (preg_match('/(.*)\[(\d+)\](\.[^.]*)?$/', $file, $match)) {
  243. $file = $match[1] . '[' . ++$match[2] . ']' . $match[3];
  244. } else {
  245. $dot = strrpos($file, '.');
  246. if ($dot === false) {
  247. $file .= '[1]';
  248. } else {
  249. $file = substr($file, 0, $dot) . '[1]' . substr($file, $dot);
  250. }
  251. }
  252. }
  253. return $this->_vfs->write($dir, $file, $info['tmp_name'], true);
  254. }
  255. /**
  256. * Deletes a file from the VFS backend associated with this object.
  257. *
  258. * @param string $file The file name.
  259. */
  260. function deleteFile($file)
  261. {
  262. if (!is_a($result = $this->_vfsInit(), 'PEAR_Error')) {
  263. return $this->_vfs->deleteFile(TURBA_VFS_PATH . '/' . $this->getValue('__uid'), $file);
  264. } else {
  265. return $result;
  266. }
  267. }
  268. /**
  269. * Deletes all files from the VFS backend associated with this object.
  270. */
  271. function deleteFiles()
  272. {
  273. if (!is_a($result = $this->_vfsInit(), 'PEAR_Error')) {
  274. if ($this->_vfs->exists(TURBA_VFS_PATH, $this->getValue('__uid'))) {
  275. return $this->_vfs->deleteFolder(TURBA_VFS_PATH, $this->getValue('__uid'), true);
  276. }
  277. return true;
  278. }
  279. return $result;
  280. }
  281. /**
  282. * Returns all files from the VFS backend associated with this object.
  283. *
  284. * @return array A list of hashes with file informations.
  285. */
  286. function listFiles()
  287. {
  288. $result = $this->_vfsInit();
  289. if (!is_a($result, 'PEAR_Error') && $this->_vfs->exists(TURBA_VFS_PATH, $this->getValue('__uid'))) {
  290. return $this->_vfs->listFolder(TURBA_VFS_PATH . '/' . $this->getValue('__uid'));
  291. } else {
  292. return array();
  293. }
  294. }
  295. /**
  296. * Returns a link to display and download a file from the VFS backend
  297. * associated with this object.
  298. *
  299. * @param string $file The file name.
  300. *
  301. * @return string The HTML code of the generated link.
  302. */
  303. function vfsDisplayUrl($file)
  304. {
  305. global $registry, $mime_drivers_map, $mime_drivers;
  306. require_once 'Horde/MIME/Magic.php';
  307. require_once 'Horde/MIME/Part.php';
  308. require_once 'Horde/MIME/Viewer.php';
  309. if (is_callable(array('Horde', 'loadConfiguration'))) {
  310. $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'horde');
  311. extract($result);
  312. $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'turba');
  313. require_once 'Horde/Array.php';
  314. if (isset($result['mime_drivers'])) {
  315. $mime_drivers = Horde_Array::array_merge_recursive_overwrite($mime_drivers, $result['mime_drivers']);
  316. }
  317. if (isset($result['mime_drivers_map'])) {
  318. $mime_drivers_map = Horde_Array::array_merge_recursive_overwrite($mime_drivers_map, $result['mime_drivers_map']);
  319. }
  320. } else {
  321. require HORDE_BASE . '/config/mime_drivers.php';
  322. require TURBA_BASE . '/config/mime_drivers.php';
  323. }
  324. $mime_part = new MIME_Part(MIME_Magic::extToMIME($file['type']), '');
  325. $viewer = MIME_Viewer::factory($mime_part);
  326. // We can always download files.
  327. $url_params = array('actionID' => 'download_file',
  328. 'file' => $file['name'],
  329. 'type' => $file['type'],
  330. 'source' => $this->driver->name,
  331. 'key' => $this->getValue('__key'));
  332. $dl = Horde::link(Horde::downloadUrl($file['name'], $url_params), $file['name']) . Horde::img('download.png', _("Download"), '', $registry->getImageDir('horde')) . '</a>';
  333. // Let's see if we can view this one, too.
  334. if ($viewer && !is_a($viewer, 'MIME_Viewer_default')) {
  335. $url = Horde::applicationUrl('view.php');
  336. $url_params['actionID'] = 'view_file';
  337. $url = Util::addParameter($url, $url_params);
  338. $link = Horde::link($url, $file['name'], null, '_blank') . $file['name'] . '</a>';
  339. } else {
  340. $link = $file['name'];
  341. }
  342. return $link . ' ' . $dl;
  343. }
  344. /**
  345. * Returns a link to display, download, and delete a file from the VFS
  346. * backend associated with this object.
  347. *
  348. * @param string $file The file name.
  349. *
  350. * @return string The HTML code of the generated link.
  351. */
  352. function vfsEditUrl($file)
  353. {
  354. $delform = '<form action="deletefile.php" style="display:inline" method="post">' . Util::formInput() .
  355. '<input type="hidden" name="file" value="' . htmlspecialchars($file['name']) . '" />' .
  356. '<input type="hidden" name="source" value="' . htmlspecialchars($this->driver->name) . '" />' .
  357. '<input type="hidden" name="key" value="' . htmlspecialchars($this->getValue('__key')) . '" />' .
  358. '<input type="image" class="img" src="' . $GLOBALS['registry']->getImageDir('horde') . '/delete.png" />' .
  359. '</form>';
  360. return $this->vfsDisplayUrl($file) . ' ' . $delform;
  361. }
  362. /**
  363. * Saves the current state of the object to the storage backend.
  364. */
  365. function store()
  366. {
  367. $object_id = $this->driver->save($this);
  368. if (is_a($object_id, 'PEAR_Error')) {
  369. return $object_id;
  370. }
  371. return $this->setValue('__key', $object_id);
  372. }
  373. /**
  374. * Loads the VFS configuration and initializes the VFS backend.
  375. */
  376. function _vfsInit()
  377. {
  378. if (!isset($this->_vfs)) {
  379. $v_params = Horde::getVFSConfig('documents');
  380. if (is_a($v_params, 'PEAR_Error')) {
  381. Horde::fatal($v_params, __FILE__, __LINE__);
  382. }
  383. require_once 'VFS.php';
  384. $result = &VFS::singleton($v_params['type'], $v_params['params']);
  385. if (is_a($result, 'PEAR_Error')) {
  386. return $result;
  387. } else {
  388. $this->_vfs = &$result;
  389. return true;
  390. }
  391. }
  392. }
  393. }