galitem.class.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. <?php
  2. /**
  3. * Gallery
  4. *
  5. * Copyright 2010-2012 by Shaun McCormick <shaun@modx.com>
  6. *
  7. * Gallery is free software; you can redistribute it and/or modify it under the
  8. * terms of the GNU General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option) any later
  10. * version.
  11. *
  12. * Gallery is distributed in the hope that it will be useful, but WITHOUT ANY
  13. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  14. * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along with
  17. * Gallery; if not, write to the Free Software Foundation, Inc., 59 Temple
  18. * Place, Suite 330, Boston, MA 02111-1307 USA
  19. *
  20. * @package gallery
  21. */
  22. /**
  23. * @package gallery
  24. */
  25. class galItem extends xPDOSimpleObject {
  26. private $mediaSource = false;
  27. private function getMediaSource() {
  28. if($this->mediaSource) return $this->mediaSource;
  29. //get modMediaSource
  30. $mediaSource = $this->xpdo->getOption('gallery.mediaSource',null,1);
  31. $def = $this->xpdo->getObject('sources.modMediaSource',array(
  32. 'id' => $mediaSource,
  33. ));
  34. $def->initialize();
  35. $this->mediaSource = $def;
  36. return $this->mediaSource;
  37. }
  38. public function get($k, $format = null, $formatTemplate= null) {
  39. switch ($k) {
  40. case 'thumbnail':
  41. $value = $this->getPhpThumbUrl();
  42. if (empty($format)) $format = array();
  43. $filename = $this->get('filename');
  44. if ($this->get('absolute_filename')) {
  45. $format['src'] = $filename;
  46. } else {
  47. $format['src'] = $this->getSiteUrl();
  48. $format['src'] .= $this->xpdo->call('galAlbum','getFilesUrl',array(&$this->xpdo)).$filename;
  49. }
  50. $ms = $this->getMediaSource();
  51. if($ms->getBaseUrl() != '/') {
  52. $format['src'] = $ms->getBaseUrl().$this->xpdo->call('galAlbum','getFilesUrl',array(&$this->xpdo)).$filename;
  53. }
  54. $url = $value.'&'.http_build_query($format,'','&');
  55. if ($this->xpdo->getOption('xhtml_urls',null,false)) {
  56. $value = str_replace('&','&amp;',$url);
  57. $value = str_replace('&amp;amp;','&amp;',$value);
  58. } else {
  59. $value = $url;
  60. }
  61. break;
  62. case 'image':
  63. if (empty($format)) $format = array();
  64. $filename = $this->get('filename');
  65. if ($this->get('absolute_filename')) {
  66. $format['src'] = $filename;
  67. } else {
  68. $format['src'] = $this->getSiteUrl();
  69. $format['src'] .= $this->xpdo->call('galAlbum','getFilesUrl',array(&$this->xpdo)).$filename;
  70. }
  71. $ms = $this->getMediaSource();
  72. if($ms->getBaseUrl() != '/') {
  73. $format['src'] = $ms->getBaseUrl().$this->xpdo->call('galAlbum','getFilesUrl',array(&$this->xpdo)).$filename;
  74. }
  75. $value = $this->getPhpThumbUrl().'&'.http_build_query($format,'','&');
  76. $value = $this->xpdo->getOption('xhtml_urls',null,false) ? str_replace('&','&amp;',$value) : $value;
  77. break;
  78. case 'absoluteImage':
  79. $siteUrl = $this->getSiteUrl();
  80. $value = $siteUrl.$this->xpdo->call('galAlbum','getFilesUrl',array(&$this->xpdo)).$this->get('filename');
  81. // $ms = $this->getMediaSource();
  82. // if($ms->getBaseUrl() != '/') {
  83. // $value = $ms->getBaseUrl().$this->xpdo->call('galAlbum','getFilesUrl',array(&$this->xpdo)).$filename;
  84. // }
  85. break;
  86. case 'relativeImage':
  87. $baseUrl = $this->getOption('base_url');
  88. $path = $this->xpdo->call('galAlbum','getFilesUrl',array(&$this->xpdo)).$this->get('filename');
  89. if ($baseUrl == '/') {
  90. $value = ltrim($path,'/');
  91. } else {
  92. $value = str_replace($baseUrl,'',$path);
  93. }
  94. // $ms = $this->getMediaSource(); // for absolute + relative the link NEEDS the http:// domain
  95. // if($ms->getBaseUrl() != '/') {
  96. // $value = $ms->getBaseUrl().$this->xpdo->call('galAlbum','getFilesUrl',array(&$this->xpdo)).$baseUrl;
  97. // }
  98. break;
  99. case 'filesize':
  100. $filename = $this->xpdo->call('galAlbum','getFilesPath',array(&$this->xpdo)).$this->get('filename');
  101. $value = @filesize($filename);
  102. $value = $this->formatFileSize($value);
  103. break;
  104. case 'image_path':
  105. $value = $this->xpdo->call('galAlbum','getFilesPath',array(&$this->xpdo)).$this->get('filename');
  106. break;
  107. case 'base_url':
  108. $ms = $this->getMediaSource();
  109. $value='';
  110. if($ms->getBaseUrl() != '/') {
  111. $value = $ms->getBaseUrl();
  112. }
  113. break;
  114. default:
  115. $value = parent::get($k,$format,$formatTemplate);
  116. break;
  117. }
  118. return $value;
  119. }
  120. public function getPath($absolute = true) {
  121. $path = $this->get('filename');
  122. if ($absolute) {
  123. $path = $this->xpdo->call('galAlbum','getFilesPath',array(&$this->xpdo)).$path;
  124. }
  125. return $path;
  126. }
  127. public function getPhpThumbUrl() {
  128. $assetsUrl = $this->xpdo->getOption('gallery.assets_url',null,$this->xpdo->getOption('assets_url',null,MODX_ASSETS_URL).'components/gallery/');
  129. $assetsUrl .= 'connector.php?action=web/phpthumb&ctx='.$this->xpdo->context->get('key');
  130. return $assetsUrl;
  131. }
  132. private function getSiteUrl() {
  133. $url = '';
  134. if ($this->xpdo->getOption('gallery.thumbs_prepend_site_url',null,false)) {
  135. $url = MODX_URL_SCHEME.$_SERVER['HTTP_HOST'];
  136. }
  137. return $url;
  138. }
  139. /**
  140. * Override set to trim string fields
  141. *
  142. * {@inheritDoc}
  143. */
  144. public function set($k, $v= null, $vType= '') {
  145. switch ($k) {
  146. case 'name':
  147. case 'description':
  148. if (is_string($v)) {
  149. $v = trim($v);
  150. }
  151. break;
  152. }
  153. return parent::set($k,$v,$vType);
  154. }
  155. /**
  156. * Upload a file to an album
  157. *
  158. * @var array $file
  159. * @var int $albumId
  160. * @return boolean
  161. */
  162. public function upload($file,$albumId) {
  163. if (empty($file) || empty($file['tmp_name']) || empty($file['name'])) return false;
  164. if (in_array($this->get('id'),array(0,null,''))) return false;
  165. /** @var galAlbum $album */
  166. $album = $this->xpdo->getObject('galAlbum',$albumId);
  167. if (empty($album)) return false;
  168. $fileName = $album->uploadItem($this,$file['tmp_name'], $file['name'], $this->getMediaSource());
  169. if (empty($fileName)) {
  170. return false;
  171. }
  172. $this->set('filename',$fileName);
  173. return true;
  174. }
  175. public function save($cacheFlag= null) {
  176. if ($this->isNew() && !$this->get('createdon')) {
  177. $this->set('createdon', strftime('%Y-%m-%d %H:%M:%S'));
  178. }
  179. if ($this->isNew() && !$this->get('createdby')) {
  180. if (!empty($this->xpdo->user) && $this->xpdo->user instanceof modUser) {
  181. if ($this->xpdo->user->isAuthenticated()) {
  182. $this->set('createdby',$this->xpdo->user->get('id'));
  183. }
  184. }
  185. }
  186. $saved= parent :: save($cacheFlag);
  187. if ($saved) {
  188. if ($this->xpdo->getCacheManager()) {
  189. $this->xpdo->cacheManager->delete('gallery/item/list/');
  190. }
  191. }
  192. return $saved;
  193. }
  194. public function remove(array $ancestors = array()) {
  195. $filename = $this->get('filename');
  196. if (!empty($filename)) {
  197. $filename = $this->xpdo->call('galAlbum','getFilesPath',array(&$this->xpdo)).$filename;
  198. $filename = str_ireplace(MODX_BASE_PATH, '', $filename);
  199. $ms = $this->getMediaSource();
  200. if (!@$ms->removeObject($filename)) {
  201. $this->xpdo->log(xPDO::LOG_LEVEL_ERROR,'[Gallery] An error occurred while trying to remove the attachment file at: '.$filename);
  202. }
  203. }
  204. return parent::remove($ancestors);
  205. }
  206. protected function formatFileSize($bytes, $precision = 2) {
  207. $units = array('B', 'KB', 'MB', 'GB', 'TB');
  208. $bytes = max($bytes, 0);
  209. $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
  210. $pow = min($pow, count($units) - 1);
  211. $bytes /= pow(1024, $pow);
  212. return round($bytes, $precision) . ' ' . $units[$pow];
  213. }
  214. public function getSize() {
  215. $imagePath = $this->get('image_path');
  216. $size = @getimagesize($imagePath);
  217. if (is_array($size)) {
  218. $this->set('image_width',$size[0]);
  219. $this->set('image_height',$size[1]);
  220. $this->set('image_type',$size[2]);
  221. }
  222. }
  223. /**
  224. * Move the item to a new album
  225. *
  226. * @param int|galAlbum $album
  227. * @return boolean
  228. */
  229. public function move($album) {
  230. /** @var galAlbum $newAlbum */
  231. $newAlbum = is_object($album) && $album instanceof galAlbum ? $album : $this->xpdo->getObject('galAlbum',$album);
  232. if (empty($newAlbum)) return false;
  233. /** @var galAlbumItem $albumItem */
  234. $albumItem = $this->xpdo->getObject('galAlbumItem',array(
  235. 'item' => $this->get('id'),
  236. ));
  237. if (empty($albumItem)) return false;
  238. /* set new related object */
  239. $oldRank = $albumItem->get('rank');
  240. $oldAlbum = $albumItem->get('album');
  241. $albumItem->set('album',$newAlbum->get('id'));
  242. $albumItem->set('rank',$this->xpdo->getCount('galAlbumItem',array('album' => $newAlbum->get('id'))));
  243. if (!$albumItem->save()) {
  244. return false;
  245. }
  246. /* fix old album ranks */
  247. $sql = 'UPDATE '.$this->xpdo->getTableName('galAlbumItem').' SET rank = rank - 1 WHERE rank >= '.$oldRank.' AND album = '.$oldAlbum;
  248. $this->xpdo->exec($sql);
  249. /* move actual file */
  250. $oldPath = $this->getPath();
  251. $newPath = $newAlbum->getPath().basename($oldPath);
  252. if ($oldPath != $newPath) {
  253. if (!@copy($oldPath,$newPath)) {
  254. $this->xpdo->log(modX::LOG_LEVEL_ERROR,'[Gallery] Could not move Item from '.$oldPath.' to '.$newPath);
  255. return false;
  256. }
  257. @unlink($oldPath);
  258. }
  259. $this->set('filename',$newAlbum->get('id').'/'.basename($oldPath));
  260. $this->save();
  261. return true;
  262. }
  263. public static function getList(modX &$modx,array $scriptProperties = array()) {
  264. $sort = $modx->getOption('sort',$scriptProperties,'rank');
  265. $cacheKey = 'gallery/item/list/'.md5(serialize($scriptProperties));
  266. if ($modx->getCacheManager() && $cache = $modx->cacheManager->get($cacheKey)) {
  267. $items = array();
  268. foreach ($cache['items'] as $data) {
  269. /** @var galItem $item */
  270. $item = $modx->newObject('galItem');
  271. $item->fromArray($data,'',true,true);
  272. $items[] = $item;
  273. }
  274. if (in_array(strtolower($sort),array('random','rand()','rand'))) {
  275. shuffle($items);
  276. }
  277. $data = array(
  278. 'items' => $items,
  279. 'total' => $cache['total'],
  280. 'album' => $cache['album'],
  281. );
  282. } else {
  283. $album = $modx->getOption('album',$scriptProperties,false);
  284. $tag = $modx->getOption('tag',$scriptProperties,'');
  285. $limit = $modx->getOption('limit',$scriptProperties,0);
  286. $start = $modx->getOption('start',$scriptProperties,0);
  287. /* Fix to make it work with getPage which uses "offset" instead of "start" */
  288. $offset = $modx->getOption('offset',$scriptProperties,0);
  289. if ($offset > 0) { $start = $offset; }
  290. $sortAlias = $modx->getOption('sortAlias',$scriptProperties,'galItem');
  291. if ($sort == 'rank') $sortAlias = 'AlbumItems';
  292. $dir = $modx->getOption('dir',$scriptProperties,'ASC');
  293. $showInactive = $modx->getOption('showInactive',$scriptProperties,false);
  294. $activeAlbum = array(
  295. 'id' => '',
  296. 'name' => '',
  297. 'description' => '',
  298. );
  299. $tagc = $modx->newQuery('galTag');
  300. $tagc->setClassAlias('TagsJoin');
  301. $tagc->select('GROUP_CONCAT('.$modx->getSelectColumns('galTag','TagsJoin','',array('tag')).')');
  302. $tagc->where($modx->getSelectColumns('galTag','TagsJoin','',array('item')).' = '.$modx->getSelectColumns('galItem','galItem','',array('id')));
  303. $tagc->prepare();
  304. $tagSql = $tagc->toSql();
  305. $c = $modx->newQuery('galItem');
  306. $c->innerJoin('galAlbumItem','AlbumItems');
  307. $c->innerJoin('galAlbum','Album',$modx->getSelectColumns('galAlbumItem','AlbumItems','',array('album')).' = '.$modx->getSelectColumns('galAlbum','Album','',array('id')));
  308. /* pull by album */
  309. if (!empty($album)) {
  310. $albumField = is_numeric($album) ? 'id' : 'name';
  311. $albumWhere = $albumField == 'name' ? array('name' => $album) : $album;
  312. /** @var galAlbum $album */
  313. $album = $modx->getObject('galAlbum',$albumWhere);
  314. if (empty($album)) return '';
  315. $c->where(array(
  316. 'Album.'.$albumField => $album->get($albumField),
  317. ));
  318. $activeAlbum['id'] = $album->get('id');
  319. $activeAlbum['name'] = $album->get('name');
  320. $activeAlbum['description'] = $album->get('description');
  321. $activeAlbum['year'] = $album->get('year');
  322. unset($albumWhere,$albumField);
  323. }
  324. if (!empty($tag)) { /* pull by tag */
  325. $c->innerJoin('galTag','Tags');
  326. $c->where(array(
  327. 'Tags.tag' => $tag,
  328. ));
  329. if (empty($album)) {
  330. $activeAlbum['id'] = 0;
  331. $activeAlbum['name'] = $tag;
  332. $activeAlbum['description'] = '';
  333. }
  334. }
  335. $c->where(array(
  336. 'galItem.mediatype' => $modx->getOption('mediatype',$scriptProperties,'image'),
  337. ));
  338. if (!$showInactive) {
  339. $c->where(array(
  340. 'galItem.active' => true,
  341. ));
  342. }
  343. $count = $modx->getCount('galItem',$c);
  344. $c->select($modx->getSelectColumns('galItem','galItem'));
  345. $c->select(array(
  346. '('.$tagSql.') AS tags',
  347. ));
  348. if (in_array(strtolower($sort),array('random','rand()','rand'))) {
  349. $c->sortby('RAND()',$dir);
  350. } else {
  351. $c->sortby($sortAlias.'.'.$sort,$dir);
  352. }
  353. if (!empty($limit)) $c->limit($limit,$start);
  354. $items = $modx->getCollection('galItem',$c);
  355. $data = array(
  356. 'items' => $items,
  357. 'total' => $count,
  358. 'album' => $activeAlbum,
  359. );
  360. $cache = array(
  361. 'items' => array(),
  362. 'total' => $count,
  363. 'album' => $activeAlbum,
  364. );
  365. /** @var galItem $item */
  366. foreach ($items as $item) {
  367. $cache['items'][] = $item->toArray('',true);
  368. }
  369. $modx->cacheManager->set($cacheKey,$cache);
  370. }
  371. return $data;
  372. }
  373. }