PageRenderTime 30ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/fuel/modules/fuel/models/Fuel_assets_model.php

http://github.com/daylightstudio/FUEL-CMS
PHP | 553 lines | 277 code | 78 blank | 198 comment | 24 complexity | f7adb1b910b9febc61bb8f0204826102 MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception
  1. <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * FUEL CMS
  4. * http://www.getfuelcms.com
  5. *
  6. * An open source Content Management System based on the
  7. * Codeigniter framework (http://codeigniter.com)
  8. *
  9. * @package FUEL CMS
  10. * @author David McReynolds @ Daylight Studio
  11. * @copyright Copyright (c) 2018, Daylight Studio LLC.
  12. * @license http://docs.getfuelcms.com/general/license
  13. * @link http://www.getfuelcms.com
  14. */
  15. // ------------------------------------------------------------------------
  16. /**
  17. * Extends CI_Model
  18. *
  19. * <strong>Fuel_assets_model</strong> is used for managing asset data with the file system which includes retrieving and deleting images, PDFs, etc.
  20. *
  21. * @package FUEL CMS
  22. * @subpackage Models
  23. * @category Models
  24. * @author David McReynolds @ Daylight Studio
  25. * @link http://docs.getfuelcms.com/models/fuel_assets_model
  26. */
  27. // not pulling from the database so just extend the normal model
  28. class Fuel_assets_model extends CI_Model {
  29. public $filters = array('group_id' => 'images'); // the default list view group value for filtering
  30. public $filter_value = null; // the default filter value
  31. public $key_field = 'id'; // placed here to prevent errors since we are not extended Base_module_model
  32. public $boolean_fields = array(); // placed here to prevent errors since we are not extended Base_module_model
  33. public $default_file_types = 'jpg|jpeg|jpe|png|gif|mov|mpeg|mp3|wav|aiff|pdf|css'; // default file types to associate to folders without associations
  34. protected $validator = NULL; // the validator object
  35. private $_encoded = FALSE;
  36. /**
  37. * Constructor
  38. *
  39. * @access public
  40. * @return void
  41. */
  42. public function __construct()
  43. {
  44. parent::__construct();
  45. $CI =& get_instance();
  46. $CI->load->library('validator');
  47. $CI->load->helper(array('directory', 'file', 'number'));
  48. $this->validator = new Validator();
  49. $this->validator->register_to_global_errors = FALSE;
  50. }
  51. /**
  52. * Placeholder function (not used)
  53. *
  54. * @access public
  55. * @param array Search filters
  56. * @return string
  57. */
  58. public function table_name()
  59. {
  60. return '';
  61. }
  62. // --------------------------------------------------------------------
  63. /**
  64. * Adds search filters
  65. *
  66. * @access public
  67. * @param array Search filters
  68. * @return void
  69. */
  70. public function add_filters($filters)
  71. {
  72. if (empty($this->filters))
  73. {
  74. $this->filters = $filters;
  75. }
  76. else
  77. {
  78. $this->filters = array_merge($this->filters, $filters);
  79. }
  80. }
  81. // --------------------------------------------------------------------
  82. /**
  83. * Returns an array of data used for the CMS's list view
  84. *
  85. * @access public
  86. * @param int limit
  87. * @param int offset
  88. * @param string column
  89. * @param string order
  90. * @return array|int
  91. */
  92. public function list_items($limit = null, $offset = 0, $col = 'name', $order = 'asc', $just_count = FALSE)
  93. {
  94. $CI =& get_instance();
  95. $CI->load->helper('array');
  96. $CI->load->helper('convert');
  97. if (!isset($this->filters['group_id'])) return array();
  98. $group_id = $this->filters['group_id'];
  99. // not encoded yet... then decode
  100. if (!$this->_encoded)
  101. {
  102. $this->filters['group_id'] = uri_safe_encode($group_id); // to pass the current folder
  103. $this->_encoded = TRUE;
  104. }
  105. else
  106. {
  107. $group_id = uri_safe_decode($group_id);
  108. }
  109. $asset_dir = $CI->fuel->assets->dir($group_id);
  110. $assets_path = $CI->asset->assets_server_path().$asset_dir.DIRECTORY_SEPARATOR;
  111. $exclude = $CI->fuel->config('assets_excluded_dirs');
  112. $exclude[] = 'index.html';
  113. $tmpfiles = directory_to_array($assets_path, TRUE, $exclude, FALSE);
  114. $cnt = count($tmpfiles);
  115. if ($just_count)
  116. {
  117. return $cnt;
  118. }
  119. $files = get_dir_file_info($assets_path, FALSE, TRUE);
  120. $return = array();
  121. $asset_type_path = WEB_PATH.$CI->config->item('assets_path').$asset_dir.'/';
  122. //for ($i = $offset; $i < $cnt - 1; $i++)
  123. for ($i = 0; $i < $cnt; $i++)
  124. {
  125. if (!empty($tmpfiles[$i]) AND !empty($files[$tmpfiles[$i]]))
  126. {
  127. $key = $tmpfiles[$i];
  128. if (empty($this->filters['name']) ||
  129. (!empty($this->filters['name']) AND
  130. (stripos($files[$key]['name'], $this->filters['name']) !== FALSE || stripos($key, $this->filters['name']) !== FALSE)))
  131. {
  132. $file['id'] = uri_safe_encode(assets_server_to_web_path($files[$tmpfiles[$i]]['server_path'], TRUE));
  133. //$file['filename'] = $files[$key]['name'];
  134. $file['name'] = $key;
  135. $file['preview/kb'] = round($files[$key]['size'] / 1024, 2);
  136. $file['link'] = NULL;
  137. $file['last_updated'] = date('Y-m-d H:i:s', $files[$key]['date']);
  138. $return[] = $file;
  139. }
  140. }
  141. }
  142. $order = ($order == 'desc') ? SORT_DESC : SORT_ASC;
  143. $return = array_orderby($return, $col, $order);
  144. //$return = array_sorter($return, $col, $order, TRUE);
  145. // do a check for empty limit values to prevent issues found where an empty $limit value would return nothing in 5.16
  146. $return = (empty($limit)) ? array_slice($return, $offset) : array_slice($return, $offset, $limit);
  147. // after sorting add the images
  148. foreach ($return as $key => $val)
  149. {
  150. if (is_image_file($return[$key]['name']))
  151. {
  152. $return[$key]['preview/kb'] = $return[$key]['preview/kb'].' kB <div class="img_crop"><a href="'.$asset_type_path.$return[$key]['name'].'" target="_blank"><img src="'.$asset_type_path.($return[$key]['name']).'?c='.time().'" border="0"></a></div>';
  153. $return[$key]['link'] = '<a href="'.$asset_type_path.$return[$key]['name'].'" target="_blank">'.$asset_dir.'/'.$return[$key]['name'].'</a>';
  154. }
  155. else
  156. {
  157. $return[$key]['preview/kb'] = $return[$key]['preview/kb'];
  158. $return[$key]['link'] = '<a href="'.$asset_type_path.$return[$key]['name'].'" target="_blank">'.$asset_dir.'/'.$return[$key]['name'].'</a>';
  159. }
  160. }
  161. return $return;
  162. }
  163. // --------------------------------------------------------------------
  164. /**
  165. * Returns the number of asset files
  166. *
  167. * @access public
  168. * @return int
  169. */
  170. public function list_items_total()
  171. {
  172. return $this->list_items(NULL, 0, 'name', 'asc', TRUE);
  173. }
  174. // --------------------------------------------------------------------
  175. /**
  176. * Returns an array of information about a particular asset file
  177. *
  178. * @access public
  179. * @param string An asset file
  180. * @return array
  181. */
  182. public function find_by_key($file)
  183. {
  184. $file = $this->get_file($file);
  185. $CI =& get_instance();
  186. $assets_folder = WEB_ROOT.$CI->config->item('assets_path');
  187. // normalize file path
  188. $file = trim(str_replace($assets_folder, '', $file), '/');
  189. $asset_path = $assets_folder.$file;
  190. $asset_path = str_replace('/', DIRECTORY_SEPARATOR, $asset_path); // for windows
  191. // Causes issues in some environments like GoDaddy... was originally changed for the assets to potentially be in a parent folder
  192. // $doc_root = preg_replace("!${_SERVER['SCRIPT_NAME']}$!", '', $_SERVER['SCRIPT_FILENAME']);
  193. // $asset_path = $doc_root.$file;
  194. return get_file_info($asset_path);
  195. }
  196. // --------------------------------------------------------------------
  197. /**
  198. * Returns the name of the file and will decode it if necessary
  199. *
  200. * @access public
  201. * @param string An asset file
  202. * @return string
  203. */
  204. public function get_file($file)
  205. {
  206. // if no extension is provided, then we determine that it needs to be decoded
  207. if (strpos($file, '.') === FALSE)
  208. {
  209. $file = uri_safe_decode($file);
  210. }
  211. return $file;
  212. }
  213. // --------------------------------------------------------------------
  214. /**
  215. * Returns the number of assets in a given folder
  216. *
  217. * @access public
  218. * @param string An asset folder
  219. * @return int
  220. */
  221. public function record_count($dir = 'images')
  222. {
  223. $CI =& get_instance();
  224. $files = $CI->fuel->assets->dir_files($dir, FALSE, FALSE);
  225. return count($files);
  226. }
  227. // --------------------------------------------------------------------
  228. /**
  229. * Deletes an asset
  230. *
  231. * @access public
  232. * @param string An asset file to delete
  233. * @return string
  234. */
  235. public function delete($file)
  236. {
  237. if (is_array($file))
  238. {
  239. $valid = TRUE;
  240. foreach($file as $f)
  241. {
  242. if (!$this->_delete($f))
  243. {
  244. $valid = FALSE;
  245. }
  246. }
  247. return $valid;
  248. }
  249. else
  250. {
  251. return $this->_delete($file);
  252. }
  253. }
  254. // --------------------------------------------------------------------
  255. /**
  256. * Deletes an asset and will perform any necessary folder cleanup
  257. *
  258. * @access protected
  259. * @param string An asset file to delete
  260. * @return string
  261. */
  262. protected function _delete($file)
  263. {
  264. $CI =& get_instance();
  265. $file = $this->get_file($file);
  266. $deleted = FALSE;
  267. // cleanup beginning slashes
  268. $assets_folder = WEB_ROOT.$CI->config->item('assets_path');
  269. $file = trim(str_replace($assets_folder, '', $file), '/');
  270. // Causes issues in some environments like GoDaddy... was originally changed for the assets to potentially be in a parent folder
  271. // $doc_root = preg_replace("!${_SERVER['SCRIPT_NAME']}$!", '', $_SERVER['SCRIPT_FILENAME']);
  272. // $filepath = $doc_root.$file;
  273. // normalize file path
  274. $filepath = $assets_folder.$file;
  275. $parent_folder = dirname($filepath).'/';
  276. if (file_exists($filepath))
  277. {
  278. $deleted = unlink($filepath);
  279. }
  280. $max_depth = 5;
  281. $i = 0;
  282. $end = FALSE;
  283. while(!$end)
  284. {
  285. // if it is the last file in a subfolder (not one of the main asset folders), then we recursively remove the folder to clean things up
  286. $excluded_asset_folders = $CI->fuel->assets->excluded_asset_server_folders();
  287. if (!in_array($parent_folder, $excluded_asset_folders))
  288. {
  289. $dir_files = directory_to_array($parent_folder);
  290. // if empty, now remove
  291. if (empty($dir_files))
  292. {
  293. @rmdir($parent_folder);
  294. }
  295. else
  296. {
  297. $end = TRUE;
  298. }
  299. }
  300. else
  301. {
  302. $end = TRUE;
  303. }
  304. $parent_folder = dirname($parent_folder).'/';
  305. }
  306. $i++;
  307. if ($max_depth == $i) $end = TRUE;
  308. return $deleted;
  309. }
  310. // --------------------------------------------------------------------
  311. /**
  312. * Returns the field to be used as the key for a record
  313. *
  314. * @access public
  315. * @return string
  316. */
  317. public function key_field()
  318. {
  319. return $this->key_field;
  320. }
  321. // --------------------------------------------------------------------
  322. /**
  323. * Get the validation object
  324. *
  325. * @access public
  326. * @return object
  327. */
  328. public function &get_validation()
  329. {
  330. return $this->validator;
  331. }
  332. // --------------------------------------------------------------------
  333. /**
  334. * Return validation errors
  335. *
  336. * @access public
  337. * @return array
  338. */
  339. public function get_errors()
  340. {
  341. return $this->validator->get_errors();
  342. }
  343. // --------------------------------------------------------------------
  344. /**
  345. * Returns an array of form field parameters that can be used by Form_builder
  346. *
  347. * @access public
  348. * @param array An array of values to be passed to the form fields
  349. * @return array
  350. */
  351. public function form_fields($values = array())
  352. {
  353. $CI =& get_instance();
  354. $fields = array();
  355. $editable_asset_types = $CI->fuel->config('editable_asset_filetypes');
  356. $accepts = (!empty($editable_asset_types['assets']) ? $editable_asset_types['assets'] : $this->default_file_types);
  357. $fields[lang('assets_heading_general')] = array('type' => 'fieldset', 'class' => 'tab');
  358. $fields['userfile'] = array('label' => lang('form_label_file'), 'type' => 'file', 'class' => 'multifile', 'accept' => $accepts); // key is userfile because that is what CI looks for in Upload Class
  359. $fields['asset_folder'] = array('label' => lang('form_label_asset_folder'), 'type' => 'select', 'options' => $CI->fuel->assets->dirs(), 'comment' => lang('assets_comment_asset_folder'));
  360. $fields['userfile_file_name'] = array('label' => lang('form_label_new_file_name'), 'comment' => lang('assets_comment_filename'));
  361. if ($CI->config->item('assets_allow_subfolder_creation', 'fuel'))
  362. {
  363. $fields['subfolder'] = array('label' => lang('form_label_subfolder'), 'comment' => lang('assets_comment_subfolder'));
  364. }
  365. $fields['overwrite'] = array('label' => lang('form_label_overwrite'), 'type' => 'checkbox', 'comment' => lang('assets_comment_overwrite'), 'checked' => TRUE, 'value' => '1');
  366. $fields['unzip'] = array('type' => 'checkbox', 'label' => lang('form_label_unzip'), 'comment' => lang('assets_comment_unzip'), 'value' => 1);
  367. $fields[lang('assets_heading_image_specific')] = array('type' => 'fieldset', 'class' => 'tab');
  368. $fields['create_thumb'] = array('label' => lang('form_label_create_thumb'), 'type' => 'checkbox', 'comment' => lang('assets_comment_thumb'), 'value' => '1');
  369. $resize_type_options = array('maintain_ratio' => lang('form_label_maintain_ratio'), 'resize_and_crop' => lang('form_label_resize_and_crop'));
  370. $fields['resize_method'] = array('label' => lang('form_label_resize_method'), 'type' => 'select', 'options' => $resize_type_options, 'comment' => lang('assets_comment_resize_method'));
  371. $fields['width'] = array('label' => lang('form_label_width'), 'comment' => lang('assets_comment_width'), 'size' => '3');
  372. $fields['height'] = array('label' => lang('form_label_height'), 'comment' => lang('assets_comment_height'), 'size' => '3');
  373. $fields['master_dim'] = array('type' => 'select', 'label' => lang('form_label_master_dim'), 'options' => array('auto' => 'auto', 'width' => 'width', 'height' => 'height'), 'comment' => lang('assets_comment_master_dim'));
  374. $fields['hide_options'] = array('type' => 'hidden');
  375. $fields['hide_image_options'] = array('type' => 'hidden');
  376. $fields['remove_subfolder'] = array('type' => 'hidden');
  377. $fields['uploaded_file_name'] = array('type' => 'hidden');
  378. return $fields;
  379. }
  380. /**
  381. * Placeholder function (not used)
  382. *
  383. * @access public
  384. * @return void
  385. */
  386. public function on_before_post()
  387. {
  388. }
  389. /**
  390. * Placeholder function (not used)
  391. *
  392. * @access public
  393. * @param array Posted values
  394. * @return void
  395. */
  396. public function on_after_post($values)
  397. {
  398. }
  399. /**
  400. * Placeholder function (not used)
  401. *
  402. * @access public
  403. * @return boolean
  404. */
  405. public function has_auto_increment()
  406. {
  407. return TRUE;
  408. }
  409. /**
  410. * Placeholder function (not used)
  411. *
  412. * @access public
  413. * @param array Posted values
  414. * @return array
  415. */
  416. public function filters($values = array())
  417. {
  418. return array();
  419. }
  420. /**
  421. * Displays the most recently uploaded
  422. *
  423. * @access public
  424. * @param array View variable data (optional)
  425. * @return mixed Can be an array of items or a string value
  426. */
  427. public function related_items($params)
  428. {
  429. $CI =& get_instance();
  430. $uploaded_post = $CI->session->flashdata('uploaded_post');
  431. if (!empty($uploaded_post['uploaded_file_webpath']))
  432. {
  433. $img = '';
  434. foreach($uploaded_post['uploaded_file_webpath'] as $uploaded_image)
  435. {
  436. if (is_image_file($uploaded_image))
  437. {
  438. $img .= '<a href="'.assets_path($uploaded_image).'" target="_blank"><img src="'.assets_path($uploaded_image).'?c='.time().'" alt="" style="max-width: 100%;" /></a>';
  439. }
  440. }
  441. return $img;
  442. }
  443. return '';
  444. }
  445. // --------------------------------------------------------------------
  446. /**
  447. * Returns the module object for this model
  448. *
  449. * @access public
  450. * @return object
  451. */
  452. public function get_module()
  453. {
  454. return $this->fuel->modules->get(strtolower(get_class($this)));
  455. }
  456. // --------------------------------------------------------------------
  457. /**
  458. * Function to return the display name as defined by the display_field in MY_fuel_modules
  459. * @param array $values The values of the current record
  460. * @return string
  461. */
  462. public function display_name($values)
  463. {
  464. $module = $this->get_module();
  465. $key = $module->info('display_field');
  466. if(isset($values[$key]))
  467. {
  468. return (is_array($values[$key])) ? json_encode($values[$key]) : $values[$key];
  469. }
  470. else
  471. {
  472. return "";
  473. }
  474. }
  475. }