Mixin_GalleryStorage_Driver_Base

The NextGEN Gallery Mixin GalleryStorage Driver Base class.

Defined (1)

The class is defined in the following location(s).

/products/photocrati_nextgen/modules/nextgen_data/package.module.nextgen_data.php  
  1. class Mixin_GalleryStorage_Driver_Base extends Mixin 
  2. /** 
  3. * Set correct file permissions (taken from wp core). Should be called 
  4. * after writing any file 
  5. * @class nggAdmin 
  6. * @param string $filename 
  7. * @return bool $result 
  8. */ 
  9. function _chmod($filename = '') 
  10. $stat = @stat(dirname($filename)); 
  11. $perms = $stat['mode'] & 0666; 
  12. // Remove execute bits for files 
  13. if (@chmod($filename, $perms)) { 
  14. return TRUE; 
  15. return FALSE; 
  16. /** 
  17. * Gets the id of a gallery, regardless of whether an integer 
  18. * or object was passed as an argument 
  19. * @param mixed $gallery_obj_or_id 
  20. */ 
  21. function _get_gallery_id($gallery_obj_or_id) 
  22. $retval = NULL; 
  23. $gallery_key = $this->object->_gallery_mapper->get_primary_key_column(); 
  24. if (is_object($gallery_obj_or_id)) { 
  25. if (isset($gallery_obj_or_id->{$gallery_key})) { 
  26. $retval = $gallery_obj_or_id->{$gallery_key}; 
  27. } elseif (is_numeric($gallery_obj_or_id)) { 
  28. $retval = $gallery_obj_or_id; 
  29. return $retval; 
  30. /** 
  31. * Gets the id of an image, regardless of whether an integer 
  32. * or object was passed as an argument 
  33. * @param type $image_obj_or_id 
  34. */ 
  35. function _get_image_id($image_obj_or_id) 
  36. $retval = NULL; 
  37. $image_key = $this->object->_image_mapper->get_primary_key_column(); 
  38. if (is_object($image_obj_or_id)) { 
  39. if (isset($image_obj_or_id->{$image_key})) { 
  40. $retval = $image_obj_or_id->{$image_key}; 
  41. } elseif (is_numeric($image_obj_or_id)) { 
  42. $retval = $image_obj_or_id; 
  43. return $retval; 
  44. function convert_slashes($path) 
  45. $search = array('/', "\\"); 
  46. $replace = array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR); 
  47. return str_replace($search, $replace, $path); 
  48. function delete_directory($abspath) 
  49. $retval = FALSE; 
  50. if (@file_exists($abspath)) { 
  51. $files = scandir($abspath); 
  52. array_shift($files); 
  53. array_shift($files); 
  54. foreach ($files as $file) { 
  55. $file_abspath = implode(DIRECTORY_SEPARATOR, array(rtrim($abspath, "/\\"), $file)); 
  56. if (is_dir($file_abspath)) { 
  57. $this->object->delete_directory($file_abspath); 
  58. } else { 
  59. unlink($file_abspath); 
  60. rmdir($abspath); 
  61. $retval = @file_exists($abspath); 
  62. return $retval; 
  63. /** 
  64. * Backs up an image file 
  65. * @param int|object $image 
  66. */ 
  67. function backup_image($image) 
  68. $retval = FALSE; 
  69. $image_path = $this->object->get_image_abspath($image); 
  70. if ($image_path && @file_exists($image_path)) { 
  71. $retval = copy($image_path, $this->object->get_backup_abspath($image)); 
  72. // Store the dimensions of the image 
  73. if (function_exists('getimagesize')) { 
  74. $mapper = C_Image_Mapper::get_instance(); 
  75. if (!is_object($image)) { 
  76. $image = $mapper->find($image); 
  77. if ($image) { 
  78. if (!property_exists($image, 'meta_data')) { 
  79. $image->meta_data = array(); 
  80. $dimensions = getimagesize($image_path); 
  81. $image->meta_data['backup'] = array('filename' => basename($image_path), 'width' => $dimensions[0], 'height' => $dimensions[1], 'generated' => microtime()); 
  82. $mapper->save($image); 
  83. return $retval; 
  84. /** 
  85. * Copies images into another gallery 
  86. * @param array $images 
  87. * @param int|object $gallery 
  88. * @param boolean $db optionally only copy the image files 
  89. * @param boolean $move move the image instead of copying 
  90. */ 
  91. function copy_images($images, $gallery, $db = TRUE, $move = FALSE) 
  92. $retval = FALSE; 
  93. // Ensure we have a valid gallery 
  94. if ($gallery = $this->object->_get_gallery_id($gallery)) { 
  95. $gallery_path = $this->object->get_gallery_abspath($gallery); 
  96. $image_key = $this->object->_image_mapper->get_primary_key_column(); 
  97. $retval = TRUE; 
  98. // Iterate through each image to copy... 
  99. foreach ($images as $image) { 
  100. // Copy each image size 
  101. foreach ($this->object->get_image_sizes() as $size) { 
  102. $image_path = $this->object->get_image_abspath($image, $size); 
  103. $dst = implode(DIRECTORY_SEPARATOR, array($gallery_path, M_I18n::mb_basename($image_path))); 
  104. $success = $move ? move($image_path, $dst) : copy($image_path, $dst); 
  105. if (!$success) { 
  106. $retval = FALSE; 
  107. // Copy the db entry 
  108. if ($db) { 
  109. if (is_numeric($image)) { 
  110. $this->object->_image_mapper($image); 
  111. unset($image->{$image_key}); 
  112. $image->galleryid = $gallery; 
  113. return $retval; 
  114. /** 
  115. * Empties the gallery cache directory of content 
  116. */ 
  117. function flush_cache($gallery) 
  118. $cache = C_Cache::get_instance(); 
  119. $cache->flush_directory($this->object->get_cache_abspath($gallery)); 
  120. /** 
  121. * Gets the absolute path of the backup of an original image 
  122. * @param string $image 
  123. */ 
  124. function get_backup_abspath($image) 
  125. $retval = null; 
  126. if ($image_path = $this->object->get_image_abspath($image)) { 
  127. $retval = $image_path . '_backup'; 
  128. return $retval; 
  129. function get_backup_dimensions($image) 
  130. return $this->object->get_image_dimensions($image, 'backup'); 
  131. function get_backup_url($image) 
  132. return $this->object->get_image_url($image, 'backup'); 
  133. /** 
  134. * Returns the absolute path to the cache directory of a gallery. 
  135. * Without the gallery parameter the legacy (pre 2.0) shared directory is returned. 
  136. * @param int|stdClass|C_Gallery $gallery (optional) 
  137. * @return string Absolute path to cache directory 
  138. */ 
  139. function get_cache_abspath($gallery = FALSE) 
  140. $retval = NULL; 
  141. if (FALSE == $gallery) { 
  142. $gallerypath = C_NextGen_Settings::get_instance()->gallerypath; 
  143. $retval = implode(DIRECTORY_SEPARATOR, array(rtrim(C_Fs::get_instance()->get_document_root('gallery'), "/\\"), rtrim($gallerypath, "/\\"), 'cache')); 
  144. } else { 
  145. if (is_numeric($gallery)) { 
  146. $gallery = $this->object->_gallery_mapper->find($gallery); 
  147. $retval = rtrim(implode(DIRECTORY_SEPARATOR, array($this->object->get_gallery_abspath($gallery), 'dynamic')), "/\\"); 
  148. return $retval; 
  149. /** 
  150. * Gets the absolute path where the full-sized image is stored 
  151. * @param int|object $image 
  152. */ 
  153. function get_full_abspath($image) 
  154. return $this->object->get_image_abspath($image, 'full'); 
  155. /** 
  156. * Alias to get_image_dimensions() 
  157. * @param int|object $image 
  158. * @return array 
  159. */ 
  160. function get_full_dimensions($image) 
  161. return $this->object->get_image_dimensions($image, 'full'); 
  162. /** 
  163. * Alias to get_image_html() 
  164. * @param int|object $image 
  165. * @return string 
  166. */ 
  167. function get_full_html($image) 
  168. return $this->object->get_image_html($image, 'full'); 
  169. /** 
  170. * Alias for get_original_url() 
  171. * @param int|stdClass|C_Image $image 
  172. * @return string 
  173. */ 
  174. function get_full_url($image, $check_existance = FALSE) 
  175. return $this->object->get_image_url($image, 'full', $check_existance); 
  176. function get_image_checksum($image, $size = 'full') 
  177. $retval = NULL; 
  178. if ($image_abspath = $this->get_image_abspath($image, $size, TRUE)) { 
  179. $retval = md5_file($image_abspath); 
  180. return $retval; 
  181. /** 
  182. * Gets the dimensions for a particular-sized image 
  183. * @param int|object $image 
  184. * @param string $size 
  185. * @return array 
  186. */ 
  187. function get_image_dimensions($image, $size = 'full') 
  188. $retval = NULL; 
  189. // If an image id was provided, get the entity 
  190. if (is_numeric($image)) { 
  191. $image = $this->object->_image_mapper->find($image); 
  192. // Ensure we have a valid image 
  193. if ($image) { 
  194. // Adjust size parameter 
  195. switch ($size) { 
  196. case 'original': 
  197. $size = 'full'; 
  198. break; 
  199. case 'thumbnails': 
  200. case 'thumbnail': 
  201. case 'thumb': 
  202. case 'thumbs': 
  203. $size = 'thumbnail'; 
  204. break; 
  205. // Image dimensions are stored in the $image->meta_data 
  206. // property for all implementations 
  207. if (isset($image->meta_data) && isset($image->meta_data[$size])) { 
  208. $retval = $image->meta_data[$size]; 
  209. } else { 
  210. $abspath = $this->object->get_image_abspath($image, $size); 
  211. if (@file_exists($abspath)) { 
  212. $dims = getimagesize($abspath); 
  213. if ($dims) { 
  214. $retval['width'] = $dims[0]; 
  215. $retval['height'] = $dims[1]; 
  216. } elseif ($size == 'backup') { 
  217. $retval = $this->object->get_image_dimensions($image, 'full'); 
  218. return $retval; 
  219. /** 
  220. * Gets the HTML for an image 
  221. * @param int|object $image 
  222. * @param string $size 
  223. * @return string 
  224. */ 
  225. function get_image_html($image, $size = 'full', $attributes = array()) 
  226. $retval = ""; 
  227. if (is_numeric($image)) { 
  228. $image = $this->object->_image_mapper->find($image); 
  229. if ($image) { 
  230. // Set alt text if not already specified 
  231. if (!isset($attributes['alttext'])) { 
  232. $attributes['alt'] = esc_attr($image->alttext); 
  233. // Set the title if not already set 
  234. if (!isset($attributes['title'])) { 
  235. $attributes['title'] = esc_attr($image->alttext); 
  236. // Set the dimensions if not set already 
  237. if (!isset($attributes['width']) or !isset($attributes['height'])) { 
  238. $dimensions = $this->object->get_image_dimensions($image, $size); 
  239. if (!isset($attributes['width'])) { 
  240. $attributes['width'] = $dimensions['width']; 
  241. if (!isset($attributes['height'])) { 
  242. $attributes['height'] = $dimensions['height']; 
  243. // Set the url if not already specified 
  244. if (!isset($attributes['src'])) { 
  245. $attributes['src'] = $this->object->get_image_url($image, $size); 
  246. // Format attributes 
  247. $attribs = array(); 
  248. foreach ($attributes as $attrib => $value) { 
  249. $attribs[] = "{$attrib}=\"{$value}\""; 
  250. $attribs = implode(" ", $attribs); 
  251. // Return HTML string 
  252. $retval = "<img {$attribs} />"; 
  253. return $retval; 
  254. /** 
  255. * An alias for get_full_abspath() 
  256. * @param int|object $image 
  257. */ 
  258. function get_original_abspath($image, $check_existance = FALSE) 
  259. return $this->object->get_image_abspath($image, 'full', $check_existance); 
  260. /** 
  261. * Alias to get_image_dimensions() 
  262. * @param int|object $image 
  263. * @return array 
  264. */ 
  265. function get_original_dimensions($image) 
  266. return $this->object->get_image_dimensions($image, 'full'); 
  267. /** 
  268. * Alias to get_image_html() 
  269. * @param int|object $image 
  270. * @return string 
  271. */ 
  272. function get_original_html($image) 
  273. return $this->object->get_image_html($image, 'full'); 
  274. /** 
  275. * Gets the url to the original-sized image 
  276. * @param int|stdClass|C_Image $image 
  277. * @return string 
  278. */ 
  279. function get_original_url($image, $check_existance = FALSE) 
  280. return $this->object->get_image_url($image, 'full', $check_existance); 
  281. /** 
  282. * Gets the upload path, optionally for a particular gallery 
  283. * @param int|C_Gallery|stdClass $gallery 
  284. */ 
  285. function get_upload_relpath($gallery = FALSE) 
  286. $fs = C_Fs::get_instance(); 
  287. $retval = str_replace($fs->get_document_root('gallery'), '', $this->object->get_upload_abspath($gallery)); 
  288. return DIRECTORY_SEPARATOR . ltrim($retval, "/\\"); 
  289. /** 
  290. * Moves images from to another gallery 
  291. * @param array $images 
  292. * @param int|object $gallery 
  293. * @param boolean $db optionally only move the image files, not the db entries 
  294. * @return boolean 
  295. */ 
  296. function move_images($images, $gallery, $db = TRUE) 
  297. return $this->object->copy_images($images, $gallery, $db, TRUE); 
  298. function is_image_file($filename = NULL) 
  299. $retval = FALSE; 
  300. if (!$filename && isset($_FILES['file']) && $_FILES['file']['error'] == 0) { 
  301. $filename = $_FILES['file']['tmp_name']; 
  302. $valid_types = array('image/gif', 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png'); 
  303. // If we can, we'll verify the mime type 
  304. if (function_exists('exif_imagetype')) { 
  305. if (($image_type = @exif_imagetype($filename)) !== FALSE) { 
  306. $retval = in_array(image_type_to_mime_type($image_type), $valid_types); 
  307. } else { 
  308. $file_info = @getimagesize($filename); 
  309. if (isset($file_info[2])) { 
  310. $retval = in_array(image_type_to_mime_type($file_info[2]), $valid_types); 
  311. return $retval; 
  312. function is_zip() 
  313. $retval = FALSE; 
  314. if (isset($_FILES['file']) && $_FILES['file']['error'] == 0) { 
  315. $file_info = $_FILES['file']; 
  316. if (isset($file_info['type'])) { 
  317. $type = $file_info['type']; 
  318. $type_parts = explode('/', $type); 
  319. if (strtolower($type_parts[0]) == 'application') { 
  320. $spec = $type_parts[1]; 
  321. $spec_parts = explode('-', $spec); 
  322. $spec_parts = array_map('strtolower', $spec_parts); 
  323. if (in_array($spec, array('zip', 'octet-stream')) || in_array('zip', $spec_parts)) { 
  324. $retval = true; 
  325. return $retval; 
  326. function upload_zip($gallery_id) 
  327. $memory_limit = intval(ini_get('memory_limit')); 
  328. if (!extension_loaded('suhosin') && $memory_limit < 256) { 
  329. @ini_set('memory_limit', '256M'); 
  330. $retval = FALSE; 
  331. if ($this->object->is_zip()) { 
  332. $fs = C_Fs::get_instance(); 
  333. // Uses the WordPress ZIP abstraction API 
  334. include_once $fs->join_paths(ABSPATH, 'wp-admin', 'includes', 'file.php'); 
  335. WP_Filesystem(); 
  336. // Ensure that we truly have the gallery id 
  337. $gallery_id = $this->_get_gallery_id($gallery_id); 
  338. $zipfile = $_FILES['file']['tmp_name']; 
  339. $dest_path = implode(DIRECTORY_SEPARATOR, array(rtrim(get_temp_dir(), "/\\"), 'unpacked-' . M_I18n::mb_basename($zipfile))); 
  340. wp_mkdir_p($dest_path); 
  341. if (unzip_file($zipfile, $dest_path) === TRUE) { 
  342. $dest_dir = $dest_path . DIRECTORY_SEPARATOR; 
  343. $files = glob($dest_dir . '*'); 
  344. $size = 0; 
  345. foreach ($files as $file) { 
  346. if (is_file($dest_dir . $file)) { 
  347. $size += filesize($dest_dir . $file); 
  348. if ($size == 0) { 
  349. $this->object->delete_directory($dest_path); 
  350. $destination = wp_upload_dir(); 
  351. $destination_path = $destination['basedir']; 
  352. $dest_path = implode(DIRECTORY_SEPARATOR, array(rtrim($destination_path, "/\\"), 'unpacked-' . M_I18n::mb_basename($zipfile))); 
  353. wp_mkdir_p($dest_path); 
  354. if (unzip_file($zipfile, $dest_path) === TRUE) { 
  355. $retval = $this->object->import_gallery_from_fs($dest_path, $gallery_id); 
  356. } else { 
  357. $retval = $this->object->import_gallery_from_fs($dest_path, $gallery_id); 
  358. $this->object->delete_directory($dest_path); 
  359. if (!extension_loaded('suhosin')) { 
  360. @ini_set('memory_limit', $memory_limit . 'M'); 
  361. return $retval; 
  362. function is_current_user_over_quota() 
  363. $retval = FALSE; 
  364. $settings = C_NextGen_Settings::get_instance(); 
  365. if (is_multisite() && $settings->get('wpmuQuotaCheck')) { 
  366. require_once ABSPATH . 'wp-admin/includes/ms.php'; 
  367. $retval = upload_is_user_over_quota(FALSE); 
  368. return $retval; 
  369. /** 
  370. * Uploads base64 file to a gallery 
  371. * @param int|stdClass|C_Gallery $gallery 
  372. * @param $data base64-encoded string of data representing the image 
  373. * @param type $filename specifies the name of the file 
  374. * @return C_Image 
  375. */ 
  376. function upload_base64_image($gallery, $data, $filename = FALSE, $image_id = FALSE, $override = FALSE) 
  377. $settings = C_NextGen_Settings::get_instance(); 
  378. $memory_limit = intval(ini_get('memory_limit')); 
  379. if (!extension_loaded('suhosin') && $memory_limit < 256) { 
  380. @ini_set('memory_limit', '256M'); 
  381. $retval = NULL; 
  382. if ($gallery_id = $this->object->_get_gallery_id($gallery)) { 
  383. if ($this->object->is_current_user_over_quota()) { 
  384. $message = sprintf(__('Sorry, you have used your space allocation. Please delete some files to upload more files.', 'nggallery')); 
  385. throw new E_NoSpaceAvailableException($message); 
  386. // Get path information. The use of get_upload_abspath() might 
  387. // not be the best for some drivers. For example, if using the 
  388. // WordPress Media Library for uploading, then the wp_upload_bits() 
  389. // function should perhaps be used 
  390. $upload_dir = $this->object->get_upload_abspath($gallery); 
  391. // Perhaps a filename was given instead of base64 data? 
  392. if (preg_match("#/\\\\#", $data[0]) && @file_exists($data)) { 
  393. if (!$filename) { 
  394. $filename = M_I18n::mb_basename($data); 
  395. $data = file_get_contents($data); 
  396. // Determine filenames 
  397. $original_filename = $filename; 
  398. $filename = $filename ? sanitize_file_name($original_filename) : uniqid('nextgen-gallery'); 
  399. if (preg_match("/\\-(png|jpg|gif|jpeg)\$/i", $filename, $match)) { 
  400. $filename = str_replace($match[0], '.' . $match[1], $filename); 
  401. $abs_filename = implode(DIRECTORY_SEPARATOR, array($upload_dir, $filename)); 
  402. // Ensure that the filename is valid 
  403. if (!preg_match("/(png|jpeg|jpg|gif)\$/i", $abs_filename)) { 
  404. throw new E_UploadException(__('Invalid image file. Acceptable formats: JPG, GIF, and PNG.', 'nggallery')); 
  405. // Prevent duplicate filenames: check if the filename exists and 
  406. // begin appending '-i' until we find an open slot 
  407. if (!ini_get('safe_mode') && @file_exists($abs_filename) && !$override) { 
  408. $file_exists = TRUE; 
  409. $i = 0; 
  410. do { 
  411. $i++; 
  412. $parts = explode('.', $filename); 
  413. $extension = array_pop($parts); 
  414. $new_filename = implode('.', $parts) . '-' . $i . '.' . $extension; 
  415. $new_abs_filename = implode(DIRECTORY_SEPARATOR, array($upload_dir, $new_filename)); 
  416. if (!@file_exists($new_abs_filename)) { 
  417. $file_exists = FALSE; 
  418. $filename = $new_filename; 
  419. $abs_filename = $new_abs_filename; 
  420. } while ($file_exists == TRUE); 
  421. // Create or retrieve the image object 
  422. $image = NULL; 
  423. if ($image_id) { 
  424. $image = $this->object->_image_mapper->find($image_id, TRUE); 
  425. if ($image) { 
  426. unset($image->meta_data['saved']); 
  427. if (!$image) { 
  428. $image = $this->object->_image_mapper->create(); 
  429. $retval = $image; 
  430. // Create or update the database record 
  431. $image->alttext = str_replace('.' . M_I18n::mb_pathinfo($original_filename, PATHINFO_EXTENSION), '', M_I18n::mb_basename($original_filename)); 
  432. $image->galleryid = $this->object->_get_gallery_id($gallery); 
  433. $image->filename = $filename; 
  434. $image->image_slug = nggdb::get_unique_slug(sanitize_title_with_dashes($image->alttext), 'image'); 
  435. $image_key = $this->object->_image_mapper->get_primary_key_column(); 
  436. // If we can't write to the directory, then there's no point in continuing 
  437. if (!@file_exists($upload_dir)) { 
  438. @wp_mkdir_p($upload_dir); 
  439. if (!is_writable($upload_dir)) { 
  440. throw new E_InsufficientWriteAccessException(FALSE, $upload_dir, FALSE); 
  441. // Save the image 
  442. if ($image_id = $this->object->_image_mapper->save($image)) { 
  443. try { 
  444. // Try writing the image 
  445. $fp = fopen($abs_filename, 'w'); 
  446. fwrite($fp, $data); 
  447. fclose($fp); 
  448. if ($settings->imgBackup) { 
  449. $this->object->backup_image($image); 
  450. if ($settings->imgAutoResize) { 
  451. $this->object->generate_image_clone($abs_filename, $abs_filename, $this->object->get_image_size_params($image_id, 'full')); 
  452. // Ensure that fullsize dimensions are added to metadata array 
  453. $dimensions = getimagesize($abs_filename); 
  454. $full_meta = array('width' => $dimensions[0], 'height' => $dimensions[1], 'md5' => $this->object->get_image_checksum($image, 'full')); 
  455. if (!isset($image->meta_data) or is_string($image->meta_data) && strlen($image->meta_data) == 0) { 
  456. $image->meta_data = array(); 
  457. $image->meta_data = array_merge($image->meta_data, $full_meta); 
  458. $image->meta_data['full'] = $full_meta; 
  459. // Generate a thumbnail for the image 
  460. $this->object->generate_thumbnail($image); 
  461. // Set gallery preview image if missing 
  462. C_Gallery_Mapper::get_instance()->set_preview_image($gallery, $image_id, TRUE); 
  463. // Notify other plugins that an image has been added 
  464. do_action('ngg_added_new_image', $image); 
  465. // delete dirsize after adding new images 
  466. delete_transient('dirsize_cache'); 
  467. // Seems redundant to above hook. Maintaining for legacy purposes 
  468. do_action('ngg_after_new_images_added', $gallery_id, array($image->{$image_key})); 
  469. } catch (E_No_Image_Library_Exception $ex) { 
  470. throw $ex; 
  471. } catch (E_Clean_Exit $ex) { 
  472. // pass 
  473. } catch (Exception $ex) { 
  474. throw new E_InsufficientWriteAccessException(FALSE, $abs_filename, FALSE, $ex); 
  475. } else { 
  476. throw new E_InvalidEntityException(); 
  477. } else { 
  478. throw new E_EntityNotFoundException(); 
  479. if (!extension_loaded('suhosin')) { 
  480. @ini_set('memory_limit', $memory_limit . 'M'); 
  481. return $retval; 
  482. function import_gallery_from_fs($abspath, $gallery_id = FALSE, $create_new_gallerypath = TRUE, $gallery_title = NULL, $filenames = array()) 
  483. $retval = FALSE; 
  484. if (@file_exists($abspath)) { 
  485. $fs = C_Fs::get_instance(); 
  486. // Ensure that this folder has images 
  487. // Ensure that this folder has images 
  488. $i = 0; 
  489. $files = array(); 
  490. foreach (scandir($abspath) as $file) { 
  491. if ($file == '.' || $file == '..') { 
  492. continue; 
  493. $file_abspath = $fs->join_paths($abspath, $file); 
  494. // The first directory is considered valid 
  495. if (is_dir($file_abspath) && $i === 0) { 
  496. $files[] = $file_abspath; 
  497. } elseif ($this->is_image_file($file_abspath)) { 
  498. if ($filenames && array_search($file_abspath, $filenames) !== FALSE) { 
  499. $files[] = $file_abspath; 
  500. } else { 
  501. if (!$filenames) { 
  502. $files[] = $file_abspath; 
  503. if (!empty($files)) { 
  504. // Get needed utilities 
  505. $gallery_mapper = C_Gallery_Mapper::get_instance(); 
  506. // Sometimes users try importing a directory, which actually has all images under another directory 
  507. if (is_dir($files[0])) { 
  508. return $this->import_gallery_from_fs($files[0], $gallery_id, $create_new_gallerypath, $gallery_title, $filenames); 
  509. // If no gallery has been specified, then use the directory name as the gallery name 
  510. if (!$gallery_id) { 
  511. // Create the gallery 
  512. $gallery = $gallery_mapper->create(array('title' => $gallery_title ? $gallery_title : M_I18n::mb_basename($abspath))); 
  513. if (!$create_new_gallerypath) { 
  514. $gallery->path = str_ireplace(ABSPATH, '', $abspath); 
  515. // Save the gallery 
  516. if ($gallery->save()) { 
  517. $gallery_id = $gallery->id(); 
  518. // Ensure that we have a gallery id 
  519. if ($gallery_id) { 
  520. $retval = array('gallery_id' => $gallery_id, 'image_ids' => array()); 
  521. foreach ($files as $file_abspath) { 
  522. if (!preg_match("/\\.(jpg|jpeg|gif|png)\$/i", $file_abspath)) { 
  523. continue; 
  524. $image = null; 
  525. if ($create_new_gallerypath) { 
  526. $image = $this->object->upload_base64_image($gallery_id, file_get_contents($file_abspath), str_replace(' ', '_', M_I18n::mb_basename($file_abspath))); 
  527. } else { 
  528. // Create the database record ... TODO cleanup, some duplication here from upload_base64_image 
  529. $factory = C_Component_Factory::get_instance(); 
  530. $image = $factory->create('image'); 
  531. $image->alttext = sanitize_title_with_dashes(str_replace('.' . M_I18n::mb_pathinfo($file_abspath, PATHINFO_EXTENSION), '', M_I18n::mb_basename($file_abspath))); 
  532. $image->galleryid = $this->object->_get_gallery_id($gallery_id); 
  533. $image->filename = M_I18n::mb_basename($file_abspath); 
  534. $image->image_slug = nggdb::get_unique_slug(sanitize_title_with_dashes($image->alttext), 'image'); 
  535. $image_key = $this->object->_image_mapper->get_primary_key_column(); 
  536. $abs_filename = $file_abspath; 
  537. if ($image_id = $this->object->_image_mapper->save($image)) { 
  538. try { 
  539. if (C_NextGen_settings::get_instance()->imgBackup) { 
  540. $this->object->backup_image($image); 
  541. # if ($settings->imgAutoResize) 
  542. # $this->object->generate_image_clone( 
  543. # $abs_filename,  
  544. # $abs_filename,  
  545. # $this->object->get_image_size_params($image_id, 'full') 
  546. # ); 
  547. // Ensure that fullsize dimensions are added to metadata array 
  548. $dimensions = getimagesize($abs_filename); 
  549. $full_meta = array('width' => $dimensions[0], 'height' => $dimensions[1]); 
  550. if (!isset($image->meta_data) or is_string($image->meta_data) && strlen($image->meta_data) == 0) { 
  551. $image->meta_data = array(); 
  552. $image->meta_data = array_merge($image->meta_data, $full_meta); 
  553. $image->meta_data['full'] = $full_meta; 
  554. // Generate a thumbnail for the image 
  555. $this->object->generate_thumbnail($image); 
  556. // Set gallery preview image if missing 
  557. C_Gallery_Mapper::get_instance()->set_preview_image($gallery, $image_id, TRUE); 
  558. // Notify other plugins that an image has been added 
  559. do_action('ngg_added_new_image', $image); 
  560. // delete dirsize after adding new images 
  561. delete_transient('dirsize_cache'); 
  562. // Seems redundant to above hook. Maintaining for legacy purposes 
  563. do_action('ngg_after_new_images_added', $gallery_id, array($image->{$image_key})); 
  564. } catch (Exception $ex) { 
  565. throw new E_InsufficientWriteAccessException(FALSE, $abs_filename, FALSE, $ex); 
  566. } else { 
  567. throw new E_InvalidEntityException(); 
  568. $retval['image_ids'][] = $image->{$image->id_field}; 
  569. // Add the gallery name to the result 
  570. $gallery = $gallery_mapper->find($gallery_id); 
  571. $retval['gallery_name'] = $gallery->title; 
  572. unset($gallery); 
  573. return $retval; 
  574. function get_image_format_list() 
  575. $format_list = array(IMAGETYPE_GIF => 'gif', IMAGETYPE_JPEG => 'jpg', IMAGETYPE_PNG => 'png'); 
  576. return $format_list; 
  577. /** 
  578. * Returns an array of properties of a resulting clone image if and when generated 
  579. * @param string $image_path 
  580. * @param string $clone_path 
  581. * @param array $params 
  582. * @return array 
  583. */ 
  584. function calculate_image_clone_result($image_path, $clone_path, $params) 
  585. $width = isset($params['width']) ? $params['width'] : NULL; 
  586. $height = isset($params['height']) ? $params['height'] : NULL; 
  587. $quality = isset($params['quality']) ? $params['quality'] : NULL; 
  588. $type = isset($params['type']) ? $params['type'] : NULL; 
  589. $crop = isset($params['crop']) ? $params['crop'] : NULL; 
  590. $watermark = isset($params['watermark']) ? $params['watermark'] : NULL; 
  591. $rotation = isset($params['rotation']) ? $params['rotation'] : NULL; 
  592. $reflection = isset($params['reflection']) ? $params['reflection'] : NULL; 
  593. $crop_frame = isset($params['crop_frame']) ? $params['crop_frame'] : NULL; 
  594. $result = NULL; 
  595. // Ensure we have a valid image 
  596. if ($image_path && @file_exists($image_path)) { 
  597. // Ensure target directory exists, but only create 1 subdirectory 
  598. $image_dir = dirname($image_path); 
  599. $clone_dir = dirname($clone_path); 
  600. $image_extension = M_I18n::mb_pathinfo($image_path, PATHINFO_EXTENSION); 
  601. $image_extension_str = null; 
  602. $clone_extension = M_I18n::mb_pathinfo($clone_path, PATHINFO_EXTENSION); 
  603. $clone_extension_str = null; 
  604. if ($image_extension != null) { 
  605. $image_extension_str = '.' . $image_extension; 
  606. if ($clone_extension != null) { 
  607. $clone_extension_str = '.' . $clone_extension; 
  608. $image_basename = M_I18n::mb_basename($image_path, $image_extension_str); 
  609. $clone_basename = M_I18n::mb_basename($clone_path, $clone_extension_str); 
  610. // We use a default suffix as passing in null as the suffix will make WordPress use a default 
  611. $clone_suffix = null; 
  612. $format_list = $this->object->get_image_format_list(); 
  613. $clone_format = null; 
  614. // format is determined below and based on $type otherwise left to null 
  615. // suffix is only used to reconstruct paths for image_resize function 
  616. if (strpos($clone_basename, $image_basename) === 0) { 
  617. $clone_suffix = substr($clone_basename, strlen($image_basename)); 
  618. if ($clone_suffix != null && $clone_suffix[0] == '-') { 
  619. // WordPress adds '-' on its own 
  620. $clone_suffix = substr($clone_suffix, 1); 
  621. // Get original image dimensions 
  622. $dimensions = getimagesize($image_path); 
  623. if ($width == null && $height == null) { 
  624. if ($dimensions != null) { 
  625. if ($width == null) { 
  626. $width = $dimensions[0]; 
  627. if ($height == null) { 
  628. $height = $dimensions[1]; 
  629. } else { 
  630. // XXX Don't think there's any other option here but to fail miserably...use some hard-coded defaults maybe? 
  631. return null; 
  632. if ($dimensions != null) { 
  633. $dimensions_ratio = $dimensions[0] / $dimensions[1]; 
  634. if ($width == null) { 
  635. $width = (int) round($height * $dimensions_ratio); 
  636. if ($width == $dimensions[0] - 1) { 
  637. $width = $dimensions[0]; 
  638. } else { 
  639. if ($height == null) { 
  640. $height = (int) round($width / $dimensions_ratio); 
  641. if ($height == $dimensions[1] - 1) { 
  642. $height = $dimensions[1]; 
  643. if ($width > $dimensions[0]) { 
  644. $width = $dimensions[0]; 
  645. if ($height > $dimensions[1]) { 
  646. $height = $dimensions[1]; 
  647. $image_format = $dimensions[2]; 
  648. if ($type != null) { 
  649. if (is_string($type)) { 
  650. $type = strtolower($type); 
  651. // Indexes in the $format_list array correspond to IMAGETYPE_XXX values appropriately 
  652. if (($index = array_search($type, $format_list)) !== false) { 
  653. $type = $index; 
  654. if ($type != $image_format) { 
  655. // Note: this only changes the FORMAT of the image but not the extension 
  656. $clone_format = $type; 
  657. if ($width == null || $height == null) { 
  658. // Something went wrong... 
  659. return null; 
  660. $result['clone_path'] = $clone_path; 
  661. $result['clone_directory'] = $clone_dir; 
  662. $result['clone_suffix'] = $clone_suffix; 
  663. $result['clone_format'] = $clone_format; 
  664. $result['base_width'] = $dimensions[0]; 
  665. $result['base_height'] = $dimensions[1]; 
  666. // image_resize() has limitations: 
  667. // - no easy crop frame support 
  668. // - fails if the dimensions are unchanged 
  669. // - doesn't support filename prefix, only suffix so names like thumbs_original_name.jpg for $clone_path are not supported 
  670. // also suffix cannot be null as that will make WordPress use a default suffix...we could use an object that returns empty string from __toString() but for now just fallback to ngg generator 
  671. if (FALSE) { 
  672. // disabling the WordPress method for Iteration #6 
  673. // if (($crop_frame == null || !$crop) && ($dimensions[0] != $width && $dimensions[1] != $height) && $clone_suffix != null) 
  674. $result['method'] = 'wordpress'; 
  675. $new_dims = image_resize_dimensions($dimensions[0], $dimensions[1], $width, $height, $crop); 
  676. if ($new_dims) { 
  677. list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $new_dims; 
  678. $width = $dst_w; 
  679. $height = $dst_h; 
  680. } else { 
  681. $result['error'] = new WP_Error('error_getting_dimensions', __('Could not calculate resized image dimensions')); 
  682. } else { 
  683. $result['method'] = 'nextgen'; 
  684. $original_width = $dimensions[0]; 
  685. $original_height = $dimensions[1]; 
  686. $aspect_ratio = $width / $height; 
  687. $orig_ratio_x = $original_width / $width; 
  688. $orig_ratio_y = $original_height / $height; 
  689. if ($crop) { 
  690. $algo = 'shrink'; 
  691. // either 'adapt' or 'shrink' 
  692. if ($crop_frame != null) { 
  693. $crop_x = (int) round($crop_frame['x']); 
  694. $crop_y = (int) round($crop_frame['y']); 
  695. $crop_width = (int) round($crop_frame['width']); 
  696. $crop_height = (int) round($crop_frame['height']); 
  697. $crop_final_width = (int) round($crop_frame['final_width']); 
  698. $crop_final_height = (int) round($crop_frame['final_height']); 
  699. $crop_width_orig = $crop_width; 
  700. $crop_height_orig = $crop_height; 
  701. $crop_factor_x = $crop_width / $crop_final_width; 
  702. $crop_factor_y = $crop_height / $crop_final_height; 
  703. $crop_ratio_x = $crop_width / $width; 
  704. $crop_ratio_y = $crop_height / $height; 
  705. if ($algo == 'adapt') { 
  706. // XXX not sure about this...don't use for now 
  707. # $crop_width = (int) round($width * $crop_factor_x); 
  708. # $crop_height = (int) round($height * $crop_factor_y); 
  709. } else { 
  710. if ($algo == 'shrink') { 
  711. if ($crop_ratio_x < $crop_ratio_y) { 
  712. $crop_width = max($crop_width, $width); 
  713. $crop_height = (int) round($crop_width / $aspect_ratio); 
  714. } else { 
  715. $crop_height = max($crop_height, $height); 
  716. $crop_width = (int) round($crop_height * $aspect_ratio); 
  717. if ($crop_width == $crop_width_orig - 1) { 
  718. $crop_width = $crop_width_orig; 
  719. if ($crop_height == $crop_height_orig - 1) { 
  720. $crop_height = $crop_height_orig; 
  721. $crop_diff_x = (int) round(($crop_width_orig - $crop_width) / 2); 
  722. $crop_diff_y = (int) round(($crop_height_orig - $crop_height) / 2); 
  723. $crop_x += $crop_diff_x; 
  724. $crop_y += $crop_diff_y; 
  725. $crop_max_x = $crop_x + $crop_width; 
  726. $crop_max_y = $crop_y + $crop_height; 
  727. // Check if we're overflowing borders 
  728. // 
  729. if ($crop_x < 0) { 
  730. $crop_x = 0; 
  731. } else { 
  732. if ($crop_max_x > $original_width) { 
  733. $crop_x -= $crop_max_x - $original_width; 
  734. if ($crop_y < 0) { 
  735. $crop_y = 0; 
  736. } else { 
  737. if ($crop_max_y > $original_height) { 
  738. $crop_y -= $crop_max_y - $original_height; 
  739. } else { 
  740. if ($orig_ratio_x < $orig_ratio_y) { 
  741. $crop_width = $original_width; 
  742. $crop_height = (int) round($height * $orig_ratio_x); 
  743. } else { 
  744. $crop_height = $original_height; 
  745. $crop_width = (int) round($width * $orig_ratio_y); 
  746. if ($crop_width == $width - 1) { 
  747. $crop_width = $width; 
  748. if ($crop_height == $height - 1) { 
  749. $crop_height = $height; 
  750. $crop_x = (int) round(($original_width - $crop_width) / 2); 
  751. $crop_y = (int) round(($original_height - $crop_height) / 2); 
  752. $result['crop_area'] = array('x' => $crop_x, 'y' => $crop_y, 'width' => $crop_width, 'height' => $crop_height); 
  753. } else { 
  754. // Just constraint dimensions to ensure there's no stretching or deformations 
  755. list($width, $height) = wp_constrain_dimensions($original_width, $original_height, $width, $height); 
  756. $result['width'] = $width; 
  757. $result['height'] = $height; 
  758. $result['quality'] = $quality; 
  759. $real_width = $width; 
  760. $real_height = $height; 
  761. if ($rotation && in_array(abs($rotation), array(90, 270))) { 
  762. $real_width = $height; 
  763. $real_height = $width; 
  764. if ($reflection) { 
  765. // default for nextgen was 40%, this is used in generate_image_clone as well 
  766. $reflection_amount = 40; 
  767. // Note, round() would probably be best here but using the same code that C_NggLegacy_Thumbnail uses for compatibility 
  768. $reflection_height = intval($real_height * ($reflection_amount / 100)); 
  769. $real_height = $real_height + $reflection_height; 
  770. $result['real_width'] = $real_width; 
  771. $result['real_height'] = $real_height; 
  772. return $result; 
  773. /** 
  774. * Returns an array of dimensional properties (width, height, real_width, real_height) of a resulting clone image if and when generated 
  775. * @param string $image_path 
  776. * @param string $clone_path 
  777. * @param array $params 
  778. * @return array 
  779. */ 
  780. function calculate_image_clone_dimensions($image_path, $clone_path, $params) 
  781. $retval = null; 
  782. $result = $this->object->calculate_image_clone_result($image_path, $clone_path, $params); 
  783. if ($result != null) { 
  784. $retval = array('width' => $result['width'], 'height' => $result['height'], 'real_width' => $result['real_width'], 'real_height' => $result['real_height']); 
  785. return $retval; 
  786. /** 
  787. * Generates a "clone" for an existing image, the clone can be altered using the $params array 
  788. * @param string $image_path 
  789. * @param string $clone_path 
  790. * @param array $params 
  791. * @return object 
  792. */ 
  793. function generate_image_clone($image_path, $clone_path, $params) 
  794. $crop = isset($params['crop']) ? $params['crop'] : NULL; 
  795. $watermark = isset($params['watermark']) ? $params['watermark'] : NULL; 
  796. $reflection = isset($params['reflection']) ? $params['reflection'] : NULL; 
  797. $rotation = isset($params['rotation']) ? $params['rotation'] : NULL; 
  798. $flip = isset($params['flip']) ? $params['flip'] : NULL; 
  799. $destpath = NULL; 
  800. $thumbnail = NULL; 
  801. $result = $this->object->calculate_image_clone_result($image_path, $clone_path, $params); 
  802. // XXX this should maybe be removed and extra settings go into $params? 
  803. $settings = apply_filters('ngg_settings_during_image_generation', C_NextGen_Settings::get_instance()->to_array()); 
  804. // Ensure we have a valid image 
  805. if ($image_path && @file_exists($image_path) && $result != null && !isset($result['error'])) { 
  806. $image_dir = dirname($image_path); 
  807. $clone_path = $result['clone_path']; 
  808. $clone_dir = $result['clone_directory']; 
  809. $clone_format = $result['clone_format']; 
  810. $format_list = $this->object->get_image_format_list(); 
  811. // Ensure target directory exists, but only create 1 subdirectory 
  812. if (!@file_exists($clone_dir)) { 
  813. if (strtolower(realpath($image_dir)) != strtolower(realpath($clone_dir))) { 
  814. if (strtolower(realpath($image_dir)) == strtolower(realpath(dirname($clone_dir)))) { 
  815. wp_mkdir_p($clone_dir); 
  816. $method = $result['method']; 
  817. $width = $result['width']; 
  818. $height = $result['height']; 
  819. $quality = $result['quality']; 
  820. if ($quality == null) { 
  821. $quality = 100; 
  822. if ($method == 'wordpress') { 
  823. $original = wp_get_image_editor($image_path); 
  824. $destpath = $clone_path; 
  825. if (!is_wp_error($original)) { 
  826. $original->resize($width, $height, $crop); 
  827. $original->set_quality($quality); 
  828. $original->save($clone_path); 
  829. } else { 
  830. if ($method == 'nextgen') { 
  831. $destpath = $clone_path; 
  832. $thumbnail = new C_NggLegacy_Thumbnail($image_path, true); 
  833. if (!$thumbnail->error) { 
  834. if ($crop) { 
  835. $crop_area = $result['crop_area']; 
  836. $crop_x = $crop_area['x']; 
  837. $crop_y = $crop_area['y']; 
  838. $crop_width = $crop_area['width']; 
  839. $crop_height = $crop_area['height']; 
  840. $thumbnail->crop($crop_x, $crop_y, $crop_width, $crop_height); 
  841. $thumbnail->resize($width, $height); 
  842. } else { 
  843. $thumbnail = NULL; 
  844. // We successfully generated the thumbnail 
  845. if (is_string($destpath) && (@file_exists($destpath) || $thumbnail != null)) { 
  846. if ($clone_format != null) { 
  847. if (isset($format_list[$clone_format])) { 
  848. $clone_format_extension = $format_list[$clone_format]; 
  849. $clone_format_extension_str = null; 
  850. if ($clone_format_extension != null) { 
  851. $clone_format_extension_str = '.' . $clone_format_extension; 
  852. $destpath_info = M_I18n::mb_pathinfo($destpath); 
  853. $destpath_extension = $destpath_info['extension']; 
  854. if (strtolower($destpath_extension) != strtolower($clone_format_extension)) { 
  855. $destpath_dir = $destpath_info['dirname']; 
  856. $destpath_basename = $destpath_info['filename']; 
  857. $destpath_new = $destpath_dir . DIRECTORY_SEPARATOR . $destpath_basename . $clone_format_extension_str; 
  858. if (@file_exists($destpath) && rename($destpath, $destpath_new) || $thumbnail != null) { 
  859. $destpath = $destpath_new; 
  860. if (is_null($thumbnail)) { 
  861. $thumbnail = new C_NggLegacy_Thumbnail($destpath, true); 
  862. if ($thumbnail->error) { 
  863. $thumbnail = null; 
  864. return null; 
  865. } else { 
  866. $thumbnail->fileName = $destpath; 
  867. // This is quite odd, when watermark equals int(0) it seems all statements below ($watermark == 'image') and ($watermark == 'text') both evaluate as true 
  868. // so we set it at null if it evaluates to any null-like value 
  869. if ($watermark == null) { 
  870. $watermark = null; 
  871. if ($watermark == 1 || $watermark === true) { 
  872. if (in_array(strval($settings['wmType']), array('image', 'text'))) { 
  873. $watermark = $settings['wmType']; 
  874. } else { 
  875. $watermark = 'text'; 
  876. $watermark = strval($watermark); 
  877. if ($watermark == 'image') { 
  878. $thumbnail->watermarkImgPath = $settings['wmPath']; 
  879. $thumbnail->watermarkImage($settings['wmPos'], $settings['wmXpos'], $settings['wmYpos']); 
  880. } else { 
  881. if ($watermark == 'text') { 
  882. $thumbnail->watermarkText = $settings['wmText']; 
  883. $thumbnail->watermarkCreateText($settings['wmColor'], $settings['wmFont'], $settings['wmSize'], $settings['wmOpaque']); 
  884. $thumbnail->watermarkImage($settings['wmPos'], $settings['wmXpos'], $settings['wmYpos']); 
  885. if ($rotation && in_array(abs($rotation), array(90, 180, 270))) { 
  886. $thumbnail->rotateImageAngle($rotation); 
  887. $flip = strtolower($flip); 
  888. if ($flip && in_array($flip, array('h', 'v', 'hv'))) { 
  889. $flip_h = in_array($flip, array('h', 'hv')); 
  890. $flip_v = in_array($flip, array('v', 'hv')); 
  891. $thumbnail->flipImage($flip_h, $flip_v); 
  892. if ($reflection) { 
  893. $thumbnail->createReflection(40, 40, 50, FALSE, '#a4a4a4'); 
  894. if ($clone_format != null && isset($format_list[$clone_format])) { 
  895. // Force format 
  896. $thumbnail->format = strtoupper($format_list[$clone_format]); 
  897. $thumbnail = apply_filters('ngg_before_save_thumbnail', $thumbnail); 
  898. $thumbnail->save($destpath, $quality); 
  899. // IF the original contained IPTC metadata we should attempt to copy it 
  900. if (isset($detailed_size['APP13']) && function_exists('iptcembed')) { 
  901. $metadata = @iptcembed($detailed_size['APP13'], $destpath); 
  902. $fp = @fopen($destpath, 'wb'); 
  903. @fwrite($fp, $metadata); 
  904. @fclose($fp); 
  905. return $thumbnail;