Elgg  Version 2.2
 All Classes Namespaces Files Functions Variables Pages
filestore.php
Go to the documentation of this file.
1 <?php
18 function get_dir_size($dir, $total_size = 0) {
19  $handle = @opendir($dir);
20  while ($file = @readdir($handle)) {
21  if (in_array($file, array('.', '..'))) {
22  continue;
23  }
24  if (is_dir($dir . $file)) {
25  $total_size = get_dir_size($dir . $file . "/", $total_size);
26  } else {
27  $total_size += filesize($dir . $file);
28  }
29  }
30  @closedir($handle);
31 
32  return($total_size);
33 }
34 
44  $files = _elgg_services()->request->files;
45  if (!$files->has($input_name)) {
46  return false;
47  }
48 
49  $file = $files->get($input_name);
50  if (empty($file)) {
51  // a file input was provided but no file uploaded
52  return false;
53  }
54  if ($file->getError() !== 0) {
55  return false;
56  }
57 
58  return file_get_contents($file->getPathname());
59 }
60 
75 function get_resized_image_from_uploaded_file($input_name, $maxwidth, $maxheight,
76 $square = false, $upscale = false) {
77  $files = _elgg_services()->request->files;
78  if (!$files->has($input_name)) {
79  return false;
80  }
81 
82  $file = $files->get($input_name);
83  if (empty($file)) {
84  // a file input was provided but no file uploaded
85  return false;
86  }
87  if ($file->getError() !== 0) {
88  return false;
89  }
90 
91  return get_resized_image_from_existing_file($file->getPathname(), $maxwidth,
92  $maxheight, $square, 0, 0, 0, 0, $upscale);
93 }
94 
115 function get_resized_image_from_existing_file($input_name, $maxwidth, $maxheight, $square = false,
116 $x1 = 0, $y1 = 0, $x2 = 0, $y2 = 0, $upscale = false) {
117 
118  // Get the size information from the image
119  $imgsizearray = getimagesize($input_name);
120  if ($imgsizearray == false) {
121  return false;
122  }
123 
124  $width = $imgsizearray[0];
125  $height = $imgsizearray[1];
126 
127  $accepted_formats = array(
128  'image/jpeg' => 'jpeg',
129  'image/pjpeg' => 'jpeg',
130  'image/png' => 'png',
131  'image/x-png' => 'png',
132  'image/gif' => 'gif'
133  );
134 
135  // make sure the function is available
136  $load_function = "imagecreatefrom" . $accepted_formats[$imgsizearray['mime']];
137  if (!is_callable($load_function)) {
138  return false;
139  }
140 
141  // get the parameters for resizing the image
142  $options = array(
143  'maxwidth' => $maxwidth,
144  'maxheight' => $maxheight,
145  'square' => $square,
146  'upscale' => $upscale,
147  'x1' => $x1,
148  'y1' => $y1,
149  'x2' => $x2,
150  'y2' => $y2,
151  );
152  $params = get_image_resize_parameters($width, $height, $options);
153  if ($params == false) {
154  return false;
155  }
156 
157  // load original image
158  $original_image = call_user_func($load_function, $input_name);
159  if (!$original_image) {
160  return false;
161  }
162 
163  // allocate the new image
164  $new_image = imagecreatetruecolor($params['newwidth'], $params['newheight']);
165  if (!$new_image) {
166  return false;
167  }
168 
169  // color transparencies white (default is black)
170  imagefilledrectangle(
171  $new_image, 0, 0, $params['newwidth'], $params['newheight'],
172  imagecolorallocate($new_image, 255, 255, 255)
173  );
174 
175  $rtn_code = imagecopyresampled( $new_image,
176  $original_image,
177  0,
178  0,
179  $params['xoffset'],
180  $params['yoffset'],
181  $params['newwidth'],
182  $params['newheight'],
183  $params['selectionwidth'],
184  $params['selectionheight']);
185  if (!$rtn_code) {
186  return false;
187  }
188 
189  // grab a compressed jpeg version of the image
190  ob_start();
191  imagejpeg($new_image, null, 90);
192  $jpeg = ob_get_clean();
193 
194  imagedestroy($new_image);
195  imagedestroy($original_image);
196 
197  return $jpeg;
198 }
199 
210 function get_image_resize_parameters($width, $height, $options) {
211 
212  $defaults = array(
213  'maxwidth' => 100,
214  'maxheight' => 100,
215 
216  'square' => false,
217  'upscale' => false,
218 
219  'x1' => 0,
220  'y1' => 0,
221  'x2' => 0,
222  'y2' => 0,
223  );
224 
225  $options = array_merge($defaults, $options);
226 
227  // Avoiding extract() because it hurts static analysis
228  $maxwidth = $options['maxwidth'];
229  $maxheight = $options['maxheight'];
230  $square = $options['square'];
231  $upscale = $options['upscale'];
232  $x1 = $options['x1'];
233  $y1 = $options['y1'];
234  $x2 = $options['x2'];
235  $y2 = $options['y2'];
236 
237  // crop image first?
238  $crop = true;
239  if ($x1 == 0 && $y1 == 0 && $x2 == 0 && $y2 == 0) {
240  $crop = false;
241  }
242 
243  // how large a section of the image has been selected
244  if ($crop) {
245  $selection_width = $x2 - $x1;
246  $selection_height = $y2 - $y1;
247  } else {
248  // everything selected if no crop parameters
249  $selection_width = $width;
250  $selection_height = $height;
251  }
252 
253  // determine cropping offsets
254  if ($square) {
255  // asking for a square image back
256 
257  // detect case where someone is passing crop parameters that are not for a square
258  if ($crop == true && $selection_width != $selection_height) {
259  return false;
260  }
261 
262  // size of the new square image
263  $new_width = $new_height = min($maxwidth, $maxheight);
264 
265  // find largest square that fits within the selected region
266  $selection_width = $selection_height = min($selection_width, $selection_height);
267 
268  // set offsets for crop
269  if ($crop) {
270  $widthoffset = $x1;
271  $heightoffset = $y1;
272  $width = $x2 - $x1;
273  $height = $width;
274  } else {
275  // place square region in the center
276  $widthoffset = floor(($width - $selection_width) / 2);
277  $heightoffset = floor(($height - $selection_height) / 2);
278  }
279  } else {
280  // non-square new image
281  $new_width = $maxwidth;
282  $new_height = $maxheight;
283 
284  // maintain aspect ratio of original image/crop
285  if (($selection_height / (float)$new_height) > ($selection_width / (float)$new_width)) {
286  $new_width = floor($new_height * $selection_width / (float)$selection_height);
287  } else {
288  $new_height = floor($new_width * $selection_height / (float)$selection_width);
289  }
290 
291  // by default, use entire image
292  $widthoffset = 0;
293  $heightoffset = 0;
294 
295  if ($crop) {
296  $widthoffset = $x1;
297  $heightoffset = $y1;
298  }
299  }
300 
301  if (!$upscale && ($selection_height < $new_height || $selection_width < $new_width)) {
302  // we cannot upscale and selected area is too small so we decrease size of returned image
303  if ($square) {
304  $new_height = $selection_height;
305  $new_width = $selection_width;
306  } else {
307  if ($selection_height < $new_height && $selection_width < $new_width) {
308  $new_height = $selection_height;
309  $new_width = $selection_width;
310  }
311  }
312  }
313 
314  $params = array(
315  'newwidth' => $new_width,
316  'newheight' => $new_height,
317  'selectionwidth' => $selection_width,
318  'selectionheight' => $selection_height,
319  'xoffset' => $widthoffset,
320  'yoffset' => $heightoffset,
321  );
322 
323  return $params;
324 }
325 
333 function file_delete($guid) {
335  if (!$file || !$file->canEdit()) {
336  return false;
337  }
338 
339  $thumbnail = $file->thumbnail;
340  $smallthumb = $file->smallthumb;
341  $largethumb = $file->largethumb;
342  if ($thumbnail) {
343  $delfile = new \ElggFile();
344  $delfile->owner_guid = $file->owner_guid;
345  $delfile->setFilename($thumbnail);
346  $delfile->delete();
347  }
348  if ($smallthumb) {
349  $delfile = new \ElggFile();
350  $delfile->owner_guid = $file->owner_guid;
351  $delfile->setFilename($smallthumb);
352  $delfile->delete();
353  }
354  if ($largethumb) {
355  $delfile = new \ElggFile();
356  $delfile->owner_guid = $file->owner_guid;
357  $delfile->setFilename($largethumb);
358  $delfile->delete();
359  }
360 
361  return $file->delete();
362 }
363 
371 function delete_directory($directory) {
372  // sanity check: must be a directory
373  if (!$handle = opendir($directory)) {
374  return false;
375  }
376 
377  // loop through all files
378  while (($file = readdir($handle)) !== false) {
379  if (in_array($file, array('.', '..'))) {
380  continue;
381  }
382 
383  $path = "$directory/$file";
384  if (is_dir($path)) {
385  // recurse down through directory
386  if (!delete_directory($path)) {
387  return false;
388  }
389  } else {
390  // delete file
391  unlink($path);
392  }
393  }
394 
395  // remove empty directory
396  closedir($handle);
397  return rmdir($directory);
398 }
399 
416  $dir = new \Elgg\EntityDirLocator($entity->guid);
417  $file_path = elgg_get_config('dataroot') . $dir;
418  if (file_exists($file_path)) {
419  delete_directory($file_path);
420  }
421 }
422 
423 
426 
434  elgg_deprecated_notice(__FUNCTION__ . ' is deprecated.', '2.1');
435 
436  return $GLOBALS['DEFAULT_FILE_STORE'];
437 }
438 
447 function set_default_filestore(\ElggFilestore $filestore) {
448  elgg_deprecated_notice(__FUNCTION__ . ' is deprecated.', '2.1');
449 
450  $GLOBALS['DEFAULT_FILE_STORE'] = $filestore;
451  return true;
452 }
453 
462 function elgg_get_file_simple_type($mime_type) {
463  $params = array('mime_type' => $mime_type);
464  return elgg_trigger_plugin_hook('simple_type', 'file', $params, 'general');
465 }
466 
474  global $CONFIG;
475 
476  // Now register a default filestore
477  if (isset($CONFIG->dataroot)) {
478  $GLOBALS['DEFAULT_FILE_STORE'] = new \ElggDiskFilestore($CONFIG->dataroot);
479  }
480 }
481 
489 
490  // Fix MIME type detection for Microsoft zipped formats
491  elgg_register_plugin_hook_handler('mime_type', 'file', '_elgg_filestore_detect_mimetype');
492 
493  // Parse category of file from MIME type
494  elgg_register_plugin_hook_handler('simple_type', 'file', '_elgg_filestore_parse_simpletype');
495 
496  // Unit testing
497  elgg_register_plugin_hook_handler('unit_test', 'system', '_elgg_filestore_test');
498 
499  // Handler for serving embedded icons
500  elgg_register_page_handler('serve-icon', '_elgg_filestore_serve_icon_handler');
501 
502  // Touch entity icons if entity access id has changed
503  elgg_register_event_handler('update:after', 'object', '_elgg_filestore_touch_icons');
504  elgg_register_event_handler('update:after', 'group', '_elgg_filestore_touch_icons');
505 
506  // Move entity icons if entity owner has changed
507  elgg_register_event_handler('update:after', 'object', '_elgg_filestore_move_icons');
508  elgg_register_event_handler('update:after', 'group', '_elgg_filestore_move_icons');
509 }
510 
522 function _elgg_filestore_detect_mimetype($hook, $type, $mime_type, $params) {
523 
524  $original_filename = elgg_extract('original_filename', $params);
525  $ext = pathinfo($original_filename, PATHINFO_EXTENSION);
526 
527  return (new \Elgg\Filesystem\MimeTypeDetector())->fixDetectionErrors($mime_type, $ext);
528 }
529 
541 function _elgg_filestore_parse_simpletype($hook, $type, $simple_type, $params) {
542 
543  $mime_type = elgg_extract('mime_type', $params);
544 
545  switch ($mime_type) {
546  case "application/msword":
547  case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
548  case "application/pdf":
549  return "document";
550 
551  case "application/ogg":
552  return "audio";
553  }
554 
555  if (preg_match('~^(audio|image|video)/~', $mime_type, $m)) {
556  return $m[1];
557  }
558  if (0 === strpos($mime_type, 'text/') || false !== strpos($mime_type, 'opendocument')) {
559  return "document";
560  }
561 
562  // unrecognized MIME
563  return $simple_type;
564 }
565 
576 function _elgg_filestore_test($hook, $type, $value) {
577  global $CONFIG;
578  $value[] = "{$CONFIG->path}engine/tests/ElggCoreFilestoreTest.php";
579  return $value;
580 }
581 
582 
593 function elgg_get_download_url(\ElggFile $file, $use_cookie = true, $expires = '+2 hours') {
594  $file_svc = new Elgg\FileService\File();
595  $file_svc->setFile($file);
596  $file_svc->setExpires($expires);
597  $file_svc->setDisposition('attachment');
598  $file_svc->bindSession($use_cookie);
599  return $file_svc->getURL();
600 }
601 
613 function elgg_get_inline_url(\ElggFile $file, $use_cookie = false, $expires = '') {
614  $file_svc = new Elgg\FileService\File();
615  $file_svc->setFile($file);
616  if ($expires) {
617  $file_svc->setExpires($expires);
618  }
619  $file_svc->setDisposition('inline');
620  $file_svc->bindSession($use_cookie);
621  return $file_svc->getURL();
622 }
623 
637  return elgg_normalize_url("serve-icon/$entity->guid/$size");
638 }
639 
649  $response = _elgg_services()->iconService->handleServeIconRequest();
650  $response->send();
651  exit;
652 }
653 
664  $original_attributes = $entity->getOriginalAttributes();
665  if (!array_key_exists('access_id', $original_attributes)) {
666  return;
667  }
668  if ($entity instanceof \ElggFile) {
669  // we touch the file to invalidate any previously generated download URLs
670  $entity->setModifiedTime();
671  }
672  $sizes = array_keys(elgg_get_icon_sizes($entity->getType(), $entity->getSubtype()));
673  foreach ($sizes as $size) {
674  $icon = $entity->getIcon($size);
675  if ($icon->exists()) {
676  $icon->setModifiedTime();
677  }
678  }
679 }
680 
698 
699  $original_attributes = $entity->getOriginalAttributes();
700  if (empty($original_attributes['owner_guid'])) {
701  return;
702  }
703 
704  $previous_owner_guid = $original_attributes['owner_guid'];
705  $new_owner_guid = $entity->owner_guid;
706 
707  $sizes = elgg_get_icon_sizes($entity->getType(), $entity->getSubtype());
708 
709  foreach ($sizes as $size => $opts) {
710  $new_icon = $entity->getIcon($size);
711  if ($new_icon->owner_guid == $entity->guid) {
712  // we do not need to update icons that are owned by the entity itself
713  continue;
714  }
715 
716  if ($new_icon->owner_guid != $new_owner_guid) {
717  // a plugin implements some custom logic
718  continue;
719  }
720 
721  $old_icon = new \ElggIcon();
722  $old_icon->owner_guid = $previous_owner_guid;
723  $old_icon->setFilename($new_icon->getFilename());
724  if (!$old_icon->exists()) {
725  // there is no icon to move
726  continue;
727  }
728 
729  if ($new_icon->exists()) {
730  // there is already a new icon
731  // just removing the old one
732  $old_icon->delete();
733  elgg_log("Entity $entity->guid has been transferred to a new owner but an icon was left behind under {$old_icon->getFilenameOnFilestore()}. "
734  . "Old icon has been deleted", 'NOTICE');
735  continue;
736  }
737 
738  $old_icon->transfer($new_icon->owner_guid, $new_icon->getFilename());
739  elgg_log("Entity $entity->guid has been transferred to a new owner. "
740  . "Icon was moved from {$old_icon->getFilenameOnFilestore()} to {$new_icon->getFilenameOnFilestore()}.", 'NOTICE');
741  }
742 }
743 
744 return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
745  $events->registerHandler('boot', 'system', '_elgg_filestore_boot', 100);
746  $events->registerHandler('init', 'system', '_elgg_filestore_init', 100);
747 };
_elgg_filestore_boot()
Bootstraps the default filestore at "boot, system" event.
Definition: filestore.php:473
elgg_get_config($name, $site_guid=0)
Get an Elgg configuration value.
_elgg_filestore_serve_icon_handler()
Handler for /serve-icon resources /serve-icon/<entity_guid>/<size>
Definition: filestore.php:648
if(!array_key_exists($filename, $text_files)) $file
$m
Definition: metadata.php:11
File service.
Definition: File.php:12
elgg_normalize_url($url)
Definition: output.php:290
$DEFAULT_FILE_STORE
Variable holding the default datastore.
Definition: filestore.php:425
$defaults
elgg_get_icon_sizes($entity_type=null, $entity_subtype=null, $type= 'icon')
Returns a configuration array of icon sizes.
elgg_get_download_url(\ElggFile $file, $use_cookie=true, $expires= '+2 hours')
Returns file's download URL.
Definition: filestore.php:593
$input_name
Definition: item.php:14
elgg_get_embed_url(\ElggEntity $entity, $size)
Returns a URL suitable for embedding entity's icon in a text editor.
Definition: filestore.php:636
$path
Definition: details.php:88
$value
Definition: longtext.php:26
get_dir_size($dir, $total_size=0)
Get the size of the specified directory.
Definition: filestore.php:18
_elgg_filestore_parse_simpletype($hook, $type, $simple_type, $params)
Parse a file category of file from a MIME type.
Definition: filestore.php:541
$guid
Removes an admin notice.
elgg_register_plugin_hook_handler($hook, $type, $callback, $priority=500)
Definition: elgglib.php:715
get_image_resize_parameters($width, $height, $options)
Calculate the parameters for resizing an image.
Definition: filestore.php:210
get_default_filestore()
Return the default filestore.
Definition: filestore.php:433
$options
Elgg admin footer.
Definition: footer.php:6
if(!$owner) $icon
Definition: default.php:16
$params
Definition: login.php:72
get_resized_image_from_existing_file($input_name, $maxwidth, $maxheight, $square=false, $x1=0, $y1=0, $x2=0, $y2=0, $upscale=false)
Gets the jpeg contents of the resized version of an already uploaded image (Returns false if the file...
Definition: filestore.php:115
elgg_get_inline_url(\ElggFile $file, $use_cookie=false, $expires= '')
Returns file's URL for inline display Suitable for displaying cacheable resources, such as user avatars.
Definition: filestore.php:613
get_uploaded_file($input_name)
Get the contents of an uploaded file.
Definition: filestore.php:43
global $CONFIG
elgg_trigger_plugin_hook($hook, $type, $params=null, $returnvalue=null)
Definition: elgglib.php:801
elgg_deprecated_notice($msg, $dep_version, $backtrace_level=1)
Log a notice about deprecated use of a function, view, etc.
Definition: elgglib.php:1070
_elgg_services(\Elgg\Di\ServiceProvider $services=null)
Get the global service provider.
Definition: autoloader.php:17
file_delete($guid)
Delete an file.
Definition: filestore.php:333
elgg_extract($key, $array, $default=null, $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
Definition: elgglib.php:1310
_elgg_filestore_move_icons($event, $type, $entity)
Listen to entity ownership changes and update icon ownership by moving icons to their new owner's dir...
Definition: filestore.php:697
elgg_register_event_handler($event, $object_type, $callback, $priority=500)
Definition: elgglib.php:538
elgg_log($message, $level= 'NOTICE')
Display or log a message.
Definition: elgglib.php:1000
$size
Definition: default.php:20
_elgg_filestore_detect_mimetype($hook, $type, $mime_type, $params)
Fix MIME type detection for Microsoft zipped formats.
Definition: filestore.php:522
$entity
Definition: delete.php:7
get_resized_image_from_uploaded_file($input_name, $maxwidth, $maxheight, $square=false, $upscale=false)
Gets the jpeg contents of the resized version of an uploaded image (Returns false if the uploaded fil...
Definition: filestore.php:75
exit
Definition: autoloader.php:34
delete_directory($directory)
Delete a directory and all its contents.
Definition: filestore.php:371
set_default_filestore(\ElggFilestore $filestore)
Set the default filestore for the system.
Definition: filestore.php:447
foreach($resources as $id=> $href) if(!empty($resources_html)) $files
Definition: details.php:141
_elgg_filestore_init()
Register file-related handlers on "init, system" event.
Definition: filestore.php:488
_elgg_filestore_test($hook, $type, $value)
Unit tests for files.
Definition: filestore.php:576
_elgg_clear_entity_files($entity)
Removes all entity files.
Definition: filestore.php:415
elgg_get_file_simple_type($mime_type)
Returns the category of a file from its MIME type.
Definition: filestore.php:462
get_entity($guid)
Loads and returns an entity object from a guid.
Definition: entities.php:204
_elgg_filestore_touch_icons($event, $type, $entity)
Reset icon URLs if access_id has changed.
Definition: filestore.php:663
if(!$display_name) $type
Definition: delete.php:27