Mixin_NggLegacy_GalleryStorage_Driver

The NextGEN Gallery Mixin NggLegacy GalleryStorage Driver 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_NggLegacy_GalleryStorage_Driver extends Mixin 
  2. /** 
  3. * Returns the named sizes available for images 
  4. * @return array 
  5. */ 
  6. function get_image_sizes() 
  7. return array('full', 'thumbnail'); 
  8. function get_upload_abspath($gallery = FALSE) 
  9. // Base upload path 
  10. $retval = C_NextGen_Settings::get_instance()->gallerypath; 
  11. $fs = C_Fs::get_instance(); 
  12. // If a gallery has been specified, then we'll 
  13. // append the slug 
  14. if ($gallery) { 
  15. $retval = $this->get_gallery_abspath($gallery); 
  16. // We need to make this an absolute path 
  17. if (strpos($retval, $fs->get_document_root('gallery')) !== 0) { 
  18. $retval = rtrim($fs->join_paths($fs->get_document_root('gallery'), $retval), "/\\"); 
  19. // Convert slashes 
  20. return $this->object->convert_slashes($retval); 
  21. /** 
  22. * Get the gallery path persisted in the database for the gallery 
  23. * @param int|stdClass|C_NextGen_Gallery $gallery 
  24. */ 
  25. function get_gallery_abspath($gallery) 
  26. $retval = NULL; 
  27. $fs = C_Fs::get_instance(); 
  28. // Get the gallery entity from the database 
  29. if ($gallery) { 
  30. if (is_numeric($gallery)) { 
  31. $gallery = $this->object->_gallery_mapper->find($gallery); 
  32. // It just doesn't exist 
  33. if (!$gallery || is_numeric($gallery)) { 
  34. return $retval; 
  35. // We we have a gallery, determine it's path 
  36. if ($gallery) { 
  37. if (isset($gallery->path)) { 
  38. $retval = $gallery->path; 
  39. } elseif (isset($gallery->slug)) { 
  40. $fs = C_Fs::get_instance(); 
  41. $basepath = C_NextGen_Settings::get_instance()->gallerypath; 
  42. $retval = $fs->join_paths($basepath, sanitize_file_name(sanitize_title($gallery->slug))); 
  43. $root_type = defined('NGG_GALLERY_ROOT_TYPE') ? NGG_GALLERY_ROOT_TYPE : 'site'; 
  44. if ($root_type == 'content') { 
  45. // This requires explanation: in case our content root ends with the same directory name 
  46. // that the gallery path begins with we remove the duplicate name from $retval. This is 
  47. // necessary because the default WP_CONTENT_DIR setting ends in /wp-content/ and 
  48. // NextGEN's default gallery path begins with /wp-content/. This also allows gallery 
  49. // paths to also be expressed as simply "/gallery-name/" 
  50. $exploded_root = explode(DIRECTORY_SEPARATOR, trim($fs->get_document_root('content'), '/\\')); 
  51. $exploded_gallery = explode(DIRECTORY_SEPARATOR, trim($retval, '/\\')); 
  52. $exploded_gallery = array_values($exploded_gallery); 
  53. $last_gallery_dirname = $exploded_gallery[0]; 
  54. $last_root_dirname = end($exploded_root); 
  55. if ($last_root_dirname === $last_gallery_dirname) { 
  56. unset($exploded_gallery[0]); 
  57. $retval = implode(DIRECTORY_SEPARATOR, $exploded_gallery); 
  58. // Ensure that the path is absolute 
  59. if (strpos($retval, $fs->get_document_root('gallery')) !== 0) { 
  60. $retval = rtrim($fs->join_paths($fs->get_document_root('gallery'), $retval), "/\\"); 
  61. return $this->object->convert_slashes(rtrim($retval, "/\\")); 
  62. /** 
  63. * Gets the absolute path where the image is stored 
  64. * Can optionally return the path for a particular sized image 
  65. */ 
  66. function get_image_abspath($image, $size = 'full', $check_existance = FALSE) 
  67. $retval = NULL; 
  68. $fs = C_Fs::get_instance(); 
  69. // Ensure that we have a size 
  70. if (!$size) { 
  71. $size = 'full'; 
  72. // If we have the id, get the actual image entity 
  73. if (is_numeric($image)) { 
  74. $image = $this->object->_image_mapper->find($image); 
  75. // Ensure we have the image entity - user could have passed in an 
  76. // incorrect id 
  77. if (is_object($image)) { 
  78. if ($gallery_path = $this->object->get_gallery_abspath($image->galleryid)) { 
  79. $folder = $prefix = $size; 
  80. switch ($size) { 
  81. # Images are stored in the associated gallery folder 
  82. case 'full': 
  83. case 'original': 
  84. case 'image': 
  85. $retval = $fs->join_paths($gallery_path, $image->filename); 
  86. break; 
  87. case 'backup': 
  88. $retval = $fs->join_paths($gallery_path, $image->filename . '_backup'); 
  89. if ($check_existance && !@file_exists($retval)) { 
  90. $retval = $fs->join_paths($gallery_path, $image->filename); 
  91. break; 
  92. case 'thumbnails': 
  93. case 'thumbnail': 
  94. case 'thumb': 
  95. case 'thumbs': 
  96. $size = 'thumbnail'; 
  97. $folder = 'thumbs'; 
  98. $prefix = 'thumbs'; 
  99. // deliberately no break here 
  100. // We assume any other size of image is stored in the a 
  101. //subdirectory of the same name within the gallery folder 
  102. // gallery folder, but with the size appended to the filename 
  103. // deliberately no break here 
  104. // We assume any other size of image is stored in the a 
  105. //subdirectory of the same name within the gallery folder 
  106. // gallery folder, but with the size appended to the filename 
  107. default: 
  108. $image_path = $fs->join_paths($gallery_path, $folder); 
  109. // NGG 2.0 stores relative filenames in the meta data of 
  110. // an image. It does this because it uses filenames 
  111. // that follow conventional WordPress naming scheme. 
  112. if (isset($image->meta_data) && isset($image->meta_data[$size]) && isset($image->meta_data[$size]['filename'])) { 
  113. $image_path = $fs->join_paths($image_path, $image->meta_data[$size]['filename']); 
  114. } else { 
  115. $image_path = $fs->join_paths($image_path, "{$prefix}_{$image->filename}"); 
  116. $retval = $image_path; 
  117. break; 
  118. // Check the existance of the file 
  119. if ($retval && $check_existance) { 
  120. if (!@file_exists($retval)) { 
  121. $retval = NULL; 
  122. return $retval ? rtrim($retval, "/\\") : $retval; 
  123. /** 
  124. * Gets the url of a particular-sized image 
  125. * @param int|object $image 
  126. * @param string $size 
  127. * @returns array 
  128. */ 
  129. function get_image_url($image, $size = 'full', $check_existance = FALSE, $image_abspath = FALSE) 
  130. $retval = NULL; 
  131. $fs = C_Fs::get_instance(); 
  132. $router = C_Router::get_instance(); 
  133. if (!$image_abspath) { 
  134. $image_abspath = $this->object->get_image_abspath($image, $size, $check_existance); 
  135. if ($image_abspath) { 
  136. // Use multibyte pathinfo() in case of UTF8 gallery or file names 
  137. $parts = M_I18n::mb_pathinfo($image_abspath); 
  138. $image_abspath = $parts['dirname'] . DIRECTORY_SEPARATOR . $parts['basename']; 
  139. $doc_root = $fs->get_document_root('gallery'); 
  140. if ($doc_root != null) { 
  141. $doc_root = rtrim($doc_root, "/\\") . DIRECTORY_SEPARATOR; 
  142. // if docroot is "/" we would generate urls like /wp-contentpluginsnextgen-galleryetcetc 
  143. if ($doc_root !== '/') { 
  144. $request_uri = str_replace($doc_root, '', $image_abspath); 
  145. } else { 
  146. $request_uri = $image_abspath; 
  147. $request_uri = '/' . ltrim(str_replace("\\", '/', $request_uri), "/"); 
  148. // Because like%@this.jpg is a valid directory and filename 
  149. $request_uri = explode('/', $request_uri); 
  150. foreach ($request_uri as $ndx => $segment) { 
  151. $request_uri[$ndx] = rawurlencode($segment); 
  152. $request_uri = implode('/', $request_uri); 
  153. $retval = $router->remove_url_segment('/index.php', $router->get_url($request_uri, FALSE, 'gallery')); 
  154. return apply_filters('ngg_get_image_url', $retval, $image, $size); 
  155. /** 
  156. * Uploads an image for a particular gallerys 
  157. * @param int|stdClass|C_NextGEN_Gallery $gallery 
  158. * @param type $filename, specifies the name of the file 
  159. * @param type $data if specified, expects base64 encoded string of data 
  160. * @return C_Image 
  161. */ 
  162. function upload_image($gallery, $filename = FALSE, $data = FALSE) 
  163. $retval = NULL; 
  164. // Ensure that we have the data present that we require 
  165. if (isset($_FILES['file']) && $_FILES['file']['error'] == 0) { 
  166. // $_FILES = Array( 
  167. // [file] => Array ( 
  168. // [name] => Canada_landscape4.jpg 
  169. // [type] => image/jpeg 
  170. // [tmp_name] => /private/var/tmp/php6KO7Dc 
  171. // [error] => 0 
  172. // [size] => 64975 
  173. // ) 
  174. // 
  175. $file = $_FILES['file']; 
  176. if ($this->object->is_zip()) { 
  177. $retval = $this->object->upload_zip($gallery); 
  178. } else { 
  179. if ($this->is_image_file()) { 
  180. $retval = $this->object->upload_base64_image($gallery, file_get_contents($file['tmp_name']), $filename ? $filename : (isset($file['name']) ? $file['name'] : FALSE)); 
  181. } else { 
  182. // Remove the non-valid (and potentially insecure) file from the PHP upload directory 
  183. if (isset($_FILES['file']['tmp_name'])) { 
  184. $filename = $_FILES['file']['tmp_name']; 
  185. @unlink($filename); 
  186. throw new E_UploadException(__('Invalid image file. Acceptable formats: JPG, GIF, and PNG.', 'nggallery')); 
  187. } elseif ($data) { 
  188. $retval = $this->object->upload_base64_image($filename, $data); 
  189. } else { 
  190. throw new E_UploadException(); 
  191. return $retval; 
  192. function get_image_size_params($image, $size, $params = null, $skip_defaults = false) 
  193. // Get the image entity 
  194. if (is_numeric($image)) { 
  195. $image = $this->object->_image_mapper->find($image); 
  196. $params = apply_filters('ngg_get_image_size_params', $params, $size, $image); 
  197. // Ensure we have a valid image 
  198. if ($image) { 
  199. $settings = C_NextGen_Settings::get_instance(); 
  200. if (!$skip_defaults) { 
  201. // Get default settings 
  202. if ($size == 'full') { 
  203. if (!isset($params['quality'])) { 
  204. $params['quality'] = $settings->imgQuality; 
  205. } else { 
  206. if (!isset($params['crop'])) { 
  207. $params['crop'] = $settings->thumbfix; 
  208. if (!isset($params['quality'])) { 
  209. $params['quality'] = $settings->thumbquality; 
  210. // Not sure why this was here... commenting out for now, always require watermark parameters to be explicit 
  211. # if (!isset($params['watermark'])) { 
  212. # $params['watermark'] = $settings->wmType; 
  213. # } 
  214. // width and height when omitted make generate_image_clone create a clone with original size, so try find defaults regardless of $skip_defaults 
  215. if (!isset($params['width']) || !isset($params['height'])) { 
  216. // First test if this is a "known" image size, i.e. if we store these sizes somewhere when users re-generate these sizes from the UI...this is required to be compatible with legacy 
  217. // try the 2 default built-in sizes, first thumbnail... 
  218. if ($size == 'thumbnail') { 
  219. if (!isset($params['width'])) { 
  220. $params['width'] = $settings->thumbwidth; 
  221. if (!isset($params['height'])) { 
  222. $params['height'] = $settings->thumbheight; 
  223. } else { 
  224. if ($size == 'full') { 
  225. if (!isset($params['width'])) { 
  226. if ($settings->imgAutoResize) { 
  227. $params['width'] = $settings->imgWidth; 
  228. if (!isset($params['height'])) { 
  229. if ($settings->imgAutoResize) { 
  230. $params['height'] = $settings->imgHeight; 
  231. } else { 
  232. if (isset($image->meta_data) && isset($image->meta_data[$size])) { 
  233. $dimensions = $image->meta_data[$size]; 
  234. if (!isset($params['width'])) { 
  235. $params['width'] = $dimensions['width']; 
  236. if (!isset($params['height'])) { 
  237. $params['height'] = $dimensions['height']; 
  238. if (!isset($params['crop_frame'])) { 
  239. $crop_frame_size_name = 'thumbnail'; 
  240. if (isset($image->meta_data[$size]['crop_frame'])) { 
  241. $crop_frame_size_name = $size; 
  242. if (isset($image->meta_data[$crop_frame_size_name]['crop_frame'])) { 
  243. $params['crop_frame'] = $image->meta_data[$crop_frame_size_name]['crop_frame']; 
  244. if (!isset($params['crop_frame']['final_width'])) { 
  245. $params['crop_frame']['final_width'] = $image->meta_data[$crop_frame_size_name]['width']; 
  246. if (!isset($params['crop_frame']['final_height'])) { 
  247. $params['crop_frame']['final_height'] = $image->meta_data[$crop_frame_size_name]['height']; 
  248. } else { 
  249. if (!isset($params['crop_frame']['final_width'])) { 
  250. $params['crop_frame']['final_width'] = $params['width']; 
  251. if (!isset($params['crop_frame']['final_height'])) { 
  252. $params['crop_frame']['final_height'] = $params['height']; 
  253. return $params; 
  254. /** 
  255. * Returns an array of dimensional properties (width, height, real_width, real_height) of a resulting clone image if and when generated 
  256. * @param string $image_path 
  257. * @param string $clone_path 
  258. * @param array $params 
  259. * @return array 
  260. */ 
  261. function calculate_image_size_dimensions($image, $size, $params = null, $skip_defaults = false) 
  262. $retval = FALSE; 
  263. // Get the image entity 
  264. if (is_numeric($image)) { 
  265. $image = $this->object->_image_mapper->find($image); 
  266. // Ensure we have a valid image 
  267. if ($image) { 
  268. $params = $this->object->get_image_size_params($image, $size, $params, $skip_defaults); 
  269. // Get the image filename 
  270. $image_path = $this->object->get_original_abspath($image, 'original'); 
  271. $clone_path = $this->object->get_image_abspath($image, $size); 
  272. $retval = $this->object->calculate_image_clone_dimensions($image_path, $clone_path, $params); 
  273. return $retval; 
  274. /** 
  275. * Generates a specific size for an image 
  276. * @param int|stdClass|C_Image $image 
  277. * @return bool|object 
  278. */ 
  279. function generate_image_size($image, $size, $params = null, $skip_defaults = false) 
  280. $retval = FALSE; 
  281. // Get the image entity 
  282. if (is_numeric($image)) { 
  283. $image = $this->object->_image_mapper->find($image); 
  284. // Ensure we have a valid image 
  285. if ($image) { 
  286. $params = $this->object->get_image_size_params($image, $size, $params, $skip_defaults); 
  287. $settings = C_NextGen_Settings::get_instance(); 
  288. // Get the image filename 
  289. $filename = $this->object->get_original_abspath($image, 'original'); 
  290. $thumbnail = null; 
  291. if ($size == 'full' && $settings->imgBackup == 1) { 
  292. // XXX change this? 'full' should be the resized path and 'original' the _backup path 
  293. $backup_path = $this->object->get_backup_abspath($image); 
  294. if (!@file_exists($backup_path)) { 
  295. @copy($filename, $backup_path); 
  296. // Generate the thumbnail using WordPress 
  297. $existing_image_abpath = $this->object->get_image_abspath($image, $size); 
  298. $existing_image_dir = dirname($existing_image_abpath); 
  299. // removing the old thumbnail is actually not needed as generate_image_clone() will replace it, leaving commented in as reminder in case there are issues in the future 
  300. if (@file_exists($existing_image_abpath)) { 
  301. //unlink($existing_image_abpath); 
  302. wp_mkdir_p($existing_image_dir); 
  303. $clone_path = $existing_image_abpath; 
  304. $thumbnail = $this->object->generate_image_clone($filename, $clone_path, $params); 
  305. // We successfully generated the thumbnail 
  306. if ($thumbnail != null) { 
  307. $clone_path = $thumbnail->fileName; 
  308. if (function_exists('getimagesize')) { 
  309. $dimensions = getimagesize($clone_path); 
  310. } else { 
  311. $dimensions = array($params['width'], $params['height']); 
  312. if (!isset($image->meta_data)) { 
  313. $image->meta_data = array(); 
  314. $size_meta = array('width' => $dimensions[0], 'height' => $dimensions[1], 'filename' => M_I18n::mb_basename($clone_path), 'generated' => microtime()); 
  315. if (isset($params['crop_frame'])) { 
  316. $size_meta['crop_frame'] = $params['crop_frame']; 
  317. $image->meta_data[$size] = $size_meta; 
  318. if ($size == 'full') { 
  319. $image->meta_data['width'] = $size_meta['width']; 
  320. $image->meta_data['height'] = $size_meta['height']; 
  321. $retval = $this->object->_image_mapper->save($image); 
  322. do_action('ngg_generated_image', $image, $size, $params); 
  323. if ($retval == 0) { 
  324. $retval = false; 
  325. if ($retval) { 
  326. $retval = $thumbnail; 
  327. } else { 
  328. // Something went wrong. Thumbnail generation failed! 
  329. return $retval; 
  330. /** 
  331. * Generates a thumbnail for an image 
  332. * @param int|stdClass|C_Image $image 
  333. * @return bool 
  334. */ 
  335. function generate_thumbnail($image, $params = null, $skip_defaults = false) 
  336. $sized_image = $this->object->generate_image_size($image, 'thumbnail', $params, $skip_defaults); 
  337. $retval = false; 
  338. if ($sized_image != null) { 
  339. $retval = true; 
  340. $sized_image->destruct(); 
  341. return $retval; 
  342. /** 
  343. * Outputs/renders an image 
  344. * @param int|stdClass|C_NextGen_Gallery_Image $image 
  345. * @return bool 
  346. */ 
  347. function render_image($image, $size = FALSE) 
  348. $format_list = $this->object->get_image_format_list(); 
  349. $abspath = $this->get_image_abspath($image, $size, true); 
  350. if ($abspath == null) { 
  351. $thumbnail = $this->object->generate_image_size($image, $size); 
  352. if ($thumbnail != null) { 
  353. $abspath = $thumbnail->fileName; 
  354. $thumbnail->destruct(); 
  355. if ($abspath != null) { 
  356. $data = @getimagesize($abspath); 
  357. $format = 'jpg'; 
  358. if ($data != null && is_array($data) && isset($format_list[$data[2]])) { 
  359. $format = $format_list[$data[2]]; 
  360. // Clear output 
  361. while (ob_get_level() > 0) { 
  362. ob_end_clean(); 
  363. $format = strtolower($format); 
  364. // output image and headers 
  365. header('Content-type: image/' . $format); 
  366. readfile($abspath); 
  367. return true; 
  368. return false; 
  369. function delete_gallery($gallery) 
  370. $retval = FALSE; 
  371. $fs = C_Fs::get_instance(); 
  372. $safe_dirs = array(DIRECTORY_SEPARATOR, $fs->get_document_root('plugins'), $fs->get_document_root('plugins_mu'), $fs->get_document_root('templates'), $fs->get_document_root('stylesheets'), $fs->get_document_root('content'), $fs->get_document_root('galleries'), $fs->get_document_root()); 
  373. $abspath = $this->object->get_gallery_abspath($gallery); 
  374. if ($abspath && file_exists($abspath) && !in_array(stripslashes($abspath), $safe_dirs)) { 
  375. // delete the directory and everything in it 
  376. $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($abspath), RecursiveIteratorIterator::CHILD_FIRST); 
  377. foreach ($iterator as $file) { 
  378. if (in_array($file->getBasename(), array('.', '..'))) { 
  379. continue; 
  380. } elseif ($file->isDir()) { 
  381. rmdir($file->getPathname()); 
  382. } elseif ($file->isFile() || $file->isLink()) { 
  383. unlink($file->getPathname()); 
  384. $retval = @rmdir($abspath); 
  385. return $retval; 
  386. function delete_image($image, $size = FALSE) 
  387. $retval = FALSE; 
  388. // Ensure that we have the image entity 
  389. if (is_numeric($image)) { 
  390. $image = $this->object->_image_mapper->find($image); 
  391. if ($image) { 
  392. $image_id = $image->{$image->id_field}; 
  393. do_action('ngg_delete_image', $image_id, $size); 
  394. // Delete only a particular image size 
  395. if ($size) { 
  396. $abspath = $this->object->get_image_abspath($image, $size); 
  397. if ($abspath && @file_exists($abspath)) { 
  398. unlink($abspath); 
  399. if (isset($image->meta_data) && isset($image->meta_data[$size])) { 
  400. unset($image->meta_data[$size]); 
  401. $this->object->_image_mapper->save($image); 
  402. } else { 
  403. // Get the paths to fullsize and thumbnail files 
  404. $abspaths = array($this->object->get_full_abspath($image), $this->object->get_thumb_abspath($image), $this->object->get_backup_abspath($image)); 
  405. if (isset($image->meta_data)) { 
  406. foreach (array_keys($image->meta_data) as $size) { 
  407. $abspaths[] = $this->object->get_image_abspath($image, $size); 
  408. // Delete each image 
  409. foreach ($abspaths as $abspath) { 
  410. if ($abspath && @file_exists($abspath)) { 
  411. unlink($abspath); 
  412. // Delete the entity 
  413. $this->object->_image_mapper->destroy($image); 
  414. $retval = TRUE; 
  415. return $retval; 
  416. function set_post_thumbnail($post, $image) 
  417. $attachment_id = null; 
  418. // Get the post id 
  419. $post_id = $post; 
  420. if (is_object($post)) { 
  421. if (property_exists($post, 'ID')) { 
  422. $post_id = $post->ID; 
  423. } elseif (property_exists($post, 'post_id')) { 
  424. $post_id = $post->post_id; 
  425. } elseif (is_array($post)) { 
  426. if (isset($post['ID'])) { 
  427. $post_id = $post['ID']; 
  428. } elseif (isset($post['post_id'])) { 
  429. $post_id = $post['post_id']; 
  430. // Get the image object 
  431. if (is_int($image)) { 
  432. $image = C_Image_Mapper::get_instance()->find($image); 
  433. // Do we have what we need? 
  434. if ($image && is_int($post_id)) { 
  435. $args = array('post_type' => 'attachment', 'meta_key' => '_ngg_image_id', 'meta_compare' => '==', 'meta_value' => $image->{$image->id_field}); 
  436. $upload_dir = wp_upload_dir(); 
  437. $basedir = $upload_dir['basedir']; 
  438. $thumbs_dir = implode(DIRECTORY_SEPARATOR, array($basedir, 'ngg_featured')); 
  439. $gallery_abspath = $this->object->get_gallery_abspath($image->galleryid); 
  440. $image_abspath = $this->object->get_full_abspath($image); 
  441. $target_path = null; 
  442. $copy_image = TRUE; 
  443. // Have we previously set the post thumbnail? 
  444. if ($posts = get_posts($args)) { 
  445. $attachment_id = $posts[0]->ID; 
  446. $attachment_file = get_attached_file($attachment_id); 
  447. $target_path = $attachment_file; 
  448. if (filemtime($image_abspath) > filemtime($target_path)) { 
  449. $copy_image = TRUE; 
  450. } else { 
  451. $url = $this->object->get_full_url($image); 
  452. $target_relpath = null; 
  453. $target_basename = M_I18n::mb_basename($image_abspath); 
  454. if (strpos($image_abspath, $gallery_abspath) === 0) { 
  455. $target_relpath = substr($image_abspath, strlen($gallery_abspath)); 
  456. } else { 
  457. if ($image->galleryid) { 
  458. $target_relpath = path_join(strval($image->galleryid), $target_basename); 
  459. } else { 
  460. $target_relpath = $target_basename; 
  461. $target_relpath = trim($target_relpath, '\\/'); 
  462. $target_path = path_join($thumbs_dir, $target_relpath); 
  463. $max_count = 100; 
  464. $count = 0; 
  465. while (@file_exists($target_path) && $count <= $max_count) { 
  466. $count++; 
  467. $pathinfo = M_I18n::mb_pathinfo($target_path); 
  468. $dirname = $pathinfo['dirname']; 
  469. $filename = $pathinfo['filename']; 
  470. $extension = $pathinfo['extension']; 
  471. $rand = mt_rand(1, 9999); 
  472. $basename = $filename . '_' . sprintf('%04d', $rand) . '.' . $extension; 
  473. $target_path = path_join($dirname, $basename); 
  474. if (@file_exists($target_path)) { 
  475. // XXX handle very rare case in which $max_count wasn't enough? 
  476. $target_dir = dirname($target_path); 
  477. wp_mkdir_p($target_dir); 
  478. if ($copy_image) { 
  479. @copy($image_abspath, $target_path); 
  480. if (!$attachment_id) { 
  481. $size = @getimagesize($target_path); 
  482. $image_type = $size ? $size['mime'] : 'image/jpeg'; 
  483. $title = sanitize_file_name($image->alttext); 
  484. $caption = sanitize_file_name($image->description); 
  485. $attachment = array('post_title' => $title, 'post_content' => $caption, 'post_status' => 'attachment', 'post_parent' => 0, 'post_mime_type' => $image_type, 'guid' => $url); 
  486. $attachment_id = wp_insert_attachment($attachment, $target_path); 
  487. update_post_meta($attachment_id, '_ngg_image_id', $image->{$image->id_field}); 
  488. wp_update_attachment_metadata($attachment_id, wp_generate_attachment_metadata($attachment_id, $target_path)); 
  489. return $attachment_id; 
  490. /** 
  491. * Copies (or moves) images into another gallery 
  492. * @param array $images 
  493. * @param int|object $gallery 
  494. * @param boolean $db optionally only copy the image files 
  495. * @param boolean $move move the image instead of copying 
  496. * @return mixed NULL on failure, array|image-ids on success 
  497. */ 
  498. function copy_images($images, $gallery, $db = TRUE, $move = FALSE) 
  499. $new_image_pids = array(); 
  500. // the return value 
  501. // legacy requires passing just a numeric ID 
  502. if (is_numeric($gallery)) { 
  503. $gallery = $this->object->_gallery_mapper->find($gallery); 
  504. // move_images() is a wrapper to this function so we implement both features here 
  505. $func = $move ? 'rename' : 'copy'; 
  506. // legacy allows for arrays of just the ID 
  507. if (!is_array($images)) { 
  508. $images = array($images); 
  509. // Ensure we have a valid gallery 
  510. $gallery_id = $this->object->_get_gallery_id($gallery); 
  511. if (!$gallery_id) { 
  512. return array(); 
  513. $image_key = $this->object->_image_mapper->get_primary_key_column(); 
  514. $gallery_abspath = $this->object->get_gallery_abspath($gallery); 
  515. // Check for folder permission 
  516. if (!is_dir($gallery_abspath) && !wp_mkdir_p($gallery_abspath)) { 
  517. echo sprintf(__('Unable to create directory %s.', 'nggallery'), esc_html($gallery_abspath)); 
  518. return $new_image_pids; 
  519. if (!is_writable($gallery_abspath)) { 
  520. echo sprintf(__('Unable to write to directory %s. Is this directory writable by the server?', 'nggallery'), esc_html($gallery_abspath)); 
  521. return $new_image_pids; 
  522. $old_gallery_ids = array(); 
  523. $image_pid_map = array(); 
  524. foreach ($images as $image) { 
  525. if ($this->object->is_current_user_over_quota()) { 
  526. throw new E_NoSpaceAvailableException(__('Sorry, you have used your space allocation. Please delete some files to upload more files.', 'nggallery')); 
  527. // again legacy requires that it be able to pass just a numeric ID 
  528. if (is_numeric($image)) { 
  529. $image = $this->object->_image_mapper->find($image); 
  530. $old_gallery_ids[] = $image->galleryid; 
  531. $old_pid = $image->{$image_key}; 
  532. // update the DB if requested 
  533. $new_image = clone $image; 
  534. $new_pid = $old_pid; 
  535. if ($db) { 
  536. unset($new_image->extras_post_id); 
  537. $new_image->galleryid = $gallery_id; 
  538. if (!$move) { 
  539. $new_image->image_slug = nggdb::get_unique_slug(sanitize_title_with_dashes($image->alttext), 'image'); 
  540. unset($new_image->{$image_key}); 
  541. $new_pid = $this->object->_image_mapper->save($new_image); 
  542. if (!$new_pid) { 
  543. echo sprintf(__('Failed to copy database row for picture %s', 'nggallery'), $old_pid) . '<br />'; 
  544. continue; 
  545. // 'backup' is not included in get_image_sizes() 
  546. $sizes = $this->object->get_image_sizes(); 
  547. $sizes[] = 'backup'; 
  548. // Copy each image size 
  549. foreach ($sizes as $size) { 
  550. // if backups are off there's no backup file to copy 
  551. if (!C_NextGen_Settings::get_instance()->imgBackup && $size == 'backup') { 
  552. continue; 
  553. $orig_path = $this->object->get_image_abspath($image, $size, TRUE); 
  554. if (!$orig_path || !@file_exists($orig_path)) { 
  555. echo sprintf(__('Failed to get image path for %s', 'nggallery'), esc_html(M_I18n::mb_basename($orig_path))) . '<br/>'; 
  556. continue; 
  557. $new_path = $this->object->get_image_abspath($new_image, $size, FALSE); 
  558. // Prevent duplicate filenames: check if the filename exists and begin appending '-#' 
  559. if (!ini_get('safe_mode') && @file_exists($new_path)) { 
  560. // prevent get_image_abspath() from using the thumbnail filename in metadata 
  561. unset($new_image->meta_data['thumbnail']['filename']); 
  562. $file_exists = TRUE; 
  563. $i = 0; 
  564. do { 
  565. $i++; 
  566. $parts = explode('.', $image->filename); 
  567. $extension = array_pop($parts); 
  568. $tmp_filename = implode('.', $parts) . '-' . $i . '.' . $extension; 
  569. $new_image->filename = $tmp_filename; 
  570. $tmp_path = $this->object->get_image_abspath($new_image, $size, FALSE); 
  571. if (!@file_exists($tmp_path)) { 
  572. $file_exists = FALSE; 
  573. $new_path = $tmp_path; 
  574. if ($db) { 
  575. $this->object->_image_mapper->save($new_image); 
  576. } while ($file_exists == TRUE); 
  577. // Copy files 
  578. if (!@$func($orig_path, $new_path)) { 
  579. echo sprintf(__('Failed to copy image %1$s to %2$s', 'nggallery'), esc_html($orig_path), esc_html($new_path)) . '<br/>'; 
  580. continue; 
  581. // disabling: this is a bit too verbose 
  582. // if (!empty($tmp_path)) 
  583. // echo sprintf(__('Image %1$s (%2$s) copied as image %3$s (%4$s) » The file already existed in the destination gallery.', 'nggallery'), $old_pid, esc_html($orig_path), $new_pid, esc_html($new_path)) . '<br />'; 
  584. // else 
  585. // echo sprintf(__('Image %1$s (%2$s) copied as image %3$s (%4$s)', 'nggallery'), $old_pid, esc_html($orig_path), $new_pid, esc_html($new_path)) . '<br />'; 
  586. // Copy tags 
  587. if ($db) { 
  588. $tags = wp_get_object_terms($old_pid, 'ngg_tag', 'fields=ids'); 
  589. $tags = array_map('intval', $tags); 
  590. wp_set_object_terms($new_pid, $tags, 'ngg_tag', true); 
  591. $new_image_pids[] = $new_pid; 
  592. $image_pid_map[$old_pid] = $new_pid; 
  593. $old_gallery_ids = array_unique($old_gallery_ids); 
  594. if ($move) { 
  595. do_action('ngg_moved_images', $images, $old_gallery_ids, $gallery_id); 
  596. } else { 
  597. do_action('ngg_copied_images', $image_pid_map, $old_gallery_ids, $gallery_id); 
  598. $title = '<a href="' . admin_url() . 'admin.php?page=nggallery-manage-gallery&mode=edit&gid=' . $gallery_id . '" >'; 
  599. $title .= $gallery->title; 
  600. $title .= '</a>'; 
  601. echo '<hr/>' . sprintf(__('Copied %1$s picture(s) to gallery %2$s .', 'nggallery'), count($new_image_pids), $title); 
  602. return $new_image_pids; 
  603. /** 
  604. * Recover image from backup copy and reprocess it 
  605. * @param int|stdClass|C_Image $image 
  606. * @return string result code 
  607. */ 
  608. function recover_image($image) 
  609. $retval = FALSE; 
  610. if (is_numeric($image)) { 
  611. $image = $this->object->_image_mapper->find($image); 
  612. if ($image) { 
  613. $full_abspath = $this->object->get_image_abspath($image); 
  614. $backup_abspath = $this->object->get_image_abspath($image, 'backup'); 
  615. if ($backup_abspath != $full_abspath && @file_exists($backup_abspath)) { 
  616. if (is_writable($full_abspath) && is_writable(dirname($full_abspath))) { 
  617. // Copy the backup 
  618. if (@copy($backup_abspath, $full_abspath)) { 
  619. // Re-create non-fullsize image sizes 
  620. foreach ($this->object->get_image_sizes($image) as $named_size) { 
  621. if ($named_size == 'full') { 
  622. continue; 
  623. $this->object->generate_image_clone($backup_abspath, $this->object->get_image_abspath($image, $named_size), $this->object->get_image_size_params($image, $named_size)); 
  624. do_action('ngg_recovered_image', $image); 
  625. // Reimport all metadata 
  626. $retval = $this->object->_image_mapper->reimport_metadata($image); 
  627. return $retval;