%PDF- %PDF-
Direktori : /home/lightco1/luminero.com.au/libraries/compojoom/model/ |
Current File : /home/lightco1/luminero.com.au/libraries/compojoom/model/multimedia.php |
<?php /** * @package Lib_Compojoom * @author DanielDimitrov <daniel@compojoom.com> * @date 11.02.2015 * * @copyright Copyright (C) 2008 - 2013 compojoom.com . All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE */ defined('_JEXEC') or die('Restricted access'); jimport('joomla.filesystem.path'); jimport('joomla.filesystem.folder'); jimport('joomla.filesystem.file'); /** * Class CompojoomMultimedia * * @since 4.0.31 */ class CompojoomModelMultimedia extends JModelLegacy { /** * @var string */ protected $component; /** * Constructor * * @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request). * * @throws Exception */ public function __construct($config = array()) { if (!isset($config['type_alias'])) { throw new Exception('You need to specify a type_alias. For example: com_hotspots.hotspot'); } $this->typeAlias = $config['type_alias']; $typeAlias = explode('.', $this->typeAlias); $this->component = $typeAlias[0]; $this->contentType = $typeAlias[1]; if (isset($config['deleteUrl'])) { $this->deleteUrl = $config['deleteUrl']; } else { $this->deleteUrl = 'index.php?option=' . $this->component . '&task=multimedia.doIt&action=delete&' . JSession::getFormToken() . '=1'; } parent::__construct($config); } /** * Uploads the images temporary to the cache folder * If the user doesn't save his entry the cron job will delete * the images * * @param array $file - the file array * * @return boolean */ public function uploadTmp($file) { $appl = JFactory::getApplication(); // Total length of post back data in bytes. $contentLength = (int) $_SERVER['CONTENT_LENGTH']; $mediaHelper = new CompojoomHelperMedia; // Maximum allowed size of post back data in MB. $postMaxSize = $mediaHelper->toBytes(ini_get('post_max_size')); // Maximum allowed size of script execution in MB. $memoryLimit = $mediaHelper->toBytes(ini_get('memory_limit')); // Check for the total size of post back data. if (($postMaxSize > 0 && $contentLength > $postMaxSize) || ($memoryLimit != -1 && $contentLength > $memoryLimit)) { $appl->enqueueMessage(JText::_('LIB_COMPOJOOM_ERROR_WARNUPLOADTOOLARGE')); return false; } // Do we have a file? if (isset($file['name'])) { JLoader::import('joomla.filesystem.file'); $user = JFactory::getUser(); $canUpload = $user->authorise('core.multimedia.create', $this->component); $params = JComponentHelper::getParams($this->component); $sizes = (array) $params->get('thumbs'); // Some cameras just add whitespace, let's change this $file['name'] = str_replace(' ', '_', $file['name']); // Some users are uploading files with umlauts, change them to normal characters, otherwise we get an error on upload $file['name'] = preg_replace("/&([a-z])[a-z]+;/i", "$1", htmlentities($file['name'])); // The user doesn't seem to have upload privilegies if (!$canUpload) { $appl->enqueueMessage(JText::_('LIB_COMPOJOOM_YOU_DONT_HAVE_UPLOAD_PRIVILEGES')); return false; } // Check if we pass all other checks if (!$mediaHelper->canUpload($file, $this->component)) { return false; } // Get a (very!) randomised name $serverkey = JFactory::getConfig()->get('secret', ''); $sig = microtime() . $serverkey; if (function_exists('sha256')) { $mangledname = sha256($sig); } elseif (function_exists('sha1')) { $mangledname = sha1($sig); } else { $mangledname = md5($sig); } $mangledname .= '_' . $file['name']; // ...and its full path $filepath = JPath::clean($this->getFilePath() . $mangledname); // If we have a name clash, abort the upload if (JFile::exists($filepath)) { $appl->enqueueMessage(JText::_('LIB_COMPOJOOM_ATTACHMENTS_ERR_NAMECLASH')); return false; } // Do the upload if (!JFile::upload($file['tmp_name'], $filepath)) { $appl->enqueueMessage(JText::_('LIB_COMPOJOOM_ATTACHMENTS_ERR_CANTJFILEUPLOAD')); return false; } // Get the MIME type if (function_exists('mime_content_type')) { $mime = mime_content_type($filepath); } elseif (function_exists('finfo_open')) { $finfo = finfo_open(FILEINFO_MIME_TYPE); $mime = finfo_file($finfo, $filepath); } else { $mime = 'application/octet-stream'; } // Create a temporary thumb file $image = new CompojoomImage($filepath); $thumbs = $image->createThumbs($sizes['small']); $imageData = base64_encode(file_get_contents($thumbs[0]->getPath())); // Now remove the thumb JFile::delete($thumbs[0]->getPath()); // Format the image SRC: data:{mime};base64,{data}; $src = 'data: ' . $mime . ';base64,' . $imageData; // Return the file info $fileData = array( 'name' => $mangledname, 'title' => JFile::stripExt($file['name']), 'thumbnailUrl' => $src, 'size' => $file['size'], 'type' => $file['type'], 'deleteType' => 'delete', 'url' => '', 'deleteUrl' => $this->deleteUrl . '&file=' . $mangledname ); return $fileData; } else { $appl->enqueueMessage(JText::_('LIB_COMPOJOOM_ATTACHMENTS_ERR_NOFILE')); return false; } } /** * Move the images from their temporary location to their final location * * @param int $itemId - the item id * @param array $files - the files to save * @param array $meta - meta information about the image such as title & description * * @return void */ public function uploadPermanent($itemId, $files, $meta = array()) { $dbFiles = $this->getFilesFromDb($itemId, 'mangled_filename'); // If the file is already in the Database we don't have to manipulate it again foreach ($files as $key => $file) { if (isset($dbFiles[$file])) { unset($files[$key]); } } $moved = $this->permanentlyMoveFiles($itemId, $files); // Do we have meta Information (normally title & description)? if (count($meta)) { // Try to match it to the moved images foreach ($moved as $key => $value) { if ($meta[$key]) { $moved[$key]['meta'] = $meta[$key]; } } } // Save the new files $this->saveInDb($itemId, $moved); // Now let's update the already existing files $this->updateExistingFiles($itemId, $dbFiles, $meta); } /** * Let's update the existing images just in case something has changed * * @param int $itemId - the item id * @param array $files - the files to save * @param array $meta - meta information about the image such as title & description * * @return void */ private function updateExistingFiles($itemId, $files, $meta = array()) { $params = JComponentHelper::getParams($this->component); $table = JTable::getInstance('Multimedia', 'CompojoomTable'); $sizes = (array) $params->get('thumbs'); foreach ($files as $file) { $filePath = $this->getFilePath($file->mangled_filename, $itemId); // Now let's create some thumbs if (file_exists($filePath)) { $params = array(); $image = new CompojoomImage($filePath); $thumbs = $image->createThumbs($sizes); foreach ($thumbs as $tkey => $tvalue) { $params['thumbs'][$tkey] = array( 'name' => basename($tvalue->getPath()) ); } $file->mime_type = $image->getImageFileProperties($filePath)->mime; $params = new JRegistry($params); $file->params = $params->toString(); if ($meta[$file->mangled_filename]) { $file->title = $meta[$file->mangled_filename]['title']; $file->description = $meta[$file->mangled_filename]['description']; } $image->destroy(); } // Let's store the changes $table->bind($file); $table->store(); } } /** * Permanently moves a file from the temp location to the final location. * Creates all necessary thumbs and ads the information to the database * * @param int $itemId - the item id * @param array $files - array with filename to save * @param string $tmpPath - temporary path to file. If none given, we'll use the default file path * * @return array */ public function permanentlyMoveFiles($itemId, $files, $tmpPath = '') { $status = array(); $params = JComponentHelper::getParams($this->component); $destFolder = JPath::clean($this->getFilePath('', $itemId)); // If the folder doesn't exist, let's crete it first if (!JFolder::exists($destFolder)) { JFolder::create($destFolder); } // Now let's move the files foreach ($files as $file) { if ($tmpPath) { $tmpLocation = JPath::clean(rtrim($tmpPath, '\\/') . '/' . $file); } else { $tmpLocation = JPath::clean($this->getFilePath($file, '')); } $newLocation = JPath::clean($destFolder . $file); $status[$file]['status'] = JFile::move($tmpLocation, $newLocation); // Now let's create some thumbs if ($status[$file]['status']) { $sizes = (array) $params->get('thumbs'); $image = new CompojoomImage($newLocation); $status[$file]['thumbs'] = $image->createThumbs($sizes); $status[$file]['properties'] = $image->getImageFileProperties($newLocation); $image->destroy(); } } return $status; } /** * Get the already stored files in the database * * @param array $ids - array with item ids to fetch * @param string $key - the sort key * * @return mixed */ public function getFilesFromDb($ids, $key = '') { $db = JFactory::getDbo(); $query = $db->getQuery(true); $ids = (array) $ids; $query->select('*')->from('#__compojoom_multimedia') ->where(CompojoomQueryHelper::in('item_id', $ids, $db)) ->where('type_alias = ' . $db->q($this->typeAlias)); $db->setQuery($query); return $db->loadObjectList($key); } /** * Save the files paths and info into the database * * @param int $itemId - the item id * @param array $files - the files array * * @return void */ private function saveInDb($itemId, $files) { $db = JFactory::getDbo(); $query = $db->getQuery(true); $values = array(); foreach ($files as $key => $value) { if ($value['status']) { $params = array(); if ($value['thumbs']) { foreach ($value['thumbs'] as $tkey => $tvalue) { $params['thumbs'][$tkey] = array( 'name' => basename($tvalue->getPath()) ); } } $title = $key; $description = ''; if ($value['meta']) { $title = $value['meta']['title']; $description = $value['meta']['description']; } $params = new JRegistry($params); $values[] = implode( ',', array( $db->q($itemId), $db->q($title), $db->q($description), $db->q($this->typeAlias), $db->q($key), $db->q($value['properties']->mime), $db->q('web'), $db->q(JFactory::getDate()->toSql()), $db->q(JFactory::getUser()->get('id')), $db->q(1), $db->q($params->toString()) ) ); } } if (count($values)) { $query->insert('#__compojoom_multimedia') ->columns('item_id, title, description, type_alias, mangled_filename, mime_type, origin, created_on, created_by, enabled, params') ->values($values); $db->setQuery($query); $db->execute(); } } /** * Deletes a file from the disk and from the database * * @param string $file - the filename * @param int $id - the itemid * * @return bool */ public function delete($file, $id) { if ($id) { $db = JFactory::getDbo(); $query = $db->getQuery(true); $user = JFactory::getUser(); $createdByRestriction = false; // Can the user delete his own items? if ($user->authorise('core.multimedia.delete.own', $this->component)) { $createdByRestriction = true; } // Does the user have global delete privileges. If he does, he can delete images everywhere if ($user->authorise('core.multimedia.delete', $this->component)) { $createdByRestriction = false; } // First we need to grab the image since we need to make sure to delete the thumbnails as well $query->select('*')->from('#__compojoom_multimedia')->where('mangled_filename = ' . $db->q($file)) ->where('type_alias = ' . $db->q($this->typeAlias)); $db->setQuery($query); $image = $db->loadObject(); if ($image) { // The image should be deleted by the same user who tries to delete it if ($createdByRestriction) { if ($image->created_by != $user->id) { JFactory::getApplication()->enqueueMessage('LIB_COMPOJOOM_NOT_AUTORISED_TO_DELETE'); return false; } } $params = new JRegistry($image->params); $thumbs = $params->get('thumbs', array()); // Delete the thumbs first foreach ($thumbs as $thumb) { JFile::delete($this->getFilePath($thumb->name, $id, true)); } // Now let's delete the db entry and the file $query->clear(); $query->delete('#__compojoom_multimedia')->where('mangled_filename = ' . $db->q($file)) ->where('item_id = ' . $db->q($id)); if ($createdByRestriction) { $query->where('created_by = ' . $db->q(JFactory::getUser()->id)); } $db->setQuery($query); if ($db->execute()) { return JFile::delete($this->getFilePath($file, $id)); } } return false; } // So, we are dealing with temp File? return JFile::delete($this->getFilePath($file, $id)); } /** * Gets the filepath to a file * * @param string $file - the file name * @param int $id - the item id * @param bool $isThumb - are we dealing with a thumb? * * @return string */ public function getFilePath($file = '', $id = 0, $isThumb = false) { $params = JComponentHelper::getParams($this->component); if ($id) { $path = JPATH_ROOT . '/' . $params->get('image_path', 'images') . '/' . $this->typeAlias; if ($id) { $path .= '/' . $id; } if ($isThumb) { $path .= '/thumbs'; } } else { // If we don't have an ID, then we are dealing with the cache $path = JPATH_ROOT . '/' . $params->get('tmp_file_path', 'cache') . '/lib_compojoom.multimedia'; } return JPath::clean($path . '/' . $file); } /** * Get the web path to a file * * @param string $file - the file name * @param int $id - the id * @param bool $isThumb - are we dealing with a thumb * * @return string */ public function getWebFilePath($file, $id, $isThumb = false) { $params = JComponentHelper::getParams($this->component); $path = Juri::root() . $params->get('image_path', 'images') . '/' . $this->typeAlias . '/' . $id; if ($isThumb) { $path .= '/thumbs'; } $path .= '/' . $file; return $path; } /** * Get all files for an item. If we don't pass an item id, then we are trying to find * if we have information about the files in the user state * * @param int $id - the item id * * @return array */ public function getFiles($id) { $app = JFactory::getApplication(); $files = array(); if ($id) { $dbFiles = $this->getFilesFromDb($id); foreach ($dbFiles as $file) { $params = new JRegistry($file->params); $thumb = $params->get('thumbs.small'); $web = isset($thumb) ? $this->getWebFilePath($thumb->name, $id, true) : ''; $url = $this->getWebFilePath($file->mangled_filename, $id); $fileSize = @filesize($this->getFilePath($file->mangled_filename, $id)); $deleteUrl = $this->deleteUrl . '&file=' . $file->mangled_filename . '&id=' . $id; $files[] = $this->fileArray( $file->mangled_filename, $web, $fileSize, $file->mime_type, $url, $deleteUrl, 'delete', $file->title, $file->description ); } } else { $state = $app->getUserState($this->context); $params = JComponentHelper::getParams($this->component); $sizes = (array) $params->get('thumbs'); if (isset($state[$this->fieldName])) { foreach ($state[$this->fieldName] as $file) { $path = $this->getFilePath($file, ''); // Create a temporary thumb file $image = new CompojoomImage($this->getFilePath($file, '')); $mime = $image->getImageFileProperties($path)->mime; $thumbs = $image->createThumbs($sizes['small']); $imageData = base64_encode(file_get_contents($thumbs[0]->getPath())); // Format the image SRC: data:{mime};base64,{data}; $src = 'data: ' . $mime . ';base64,' . $imageData; $deleteUrl = $this->deleteUrl . '&file=' . $file; $info = ''; if (isset($state[$this->fieldName . '_data'][$file])) { $info = $state[$this->fieldName . '_data'][$file]; } $title = ''; $description = ''; if (isset($info['title'])) { $title = $info['title']; } if (isset($info['description'])) { $description = $info['description']; } // Return the file info $files[] = $this->fileArray($file, $src, filesize($path), $mime, '', $deleteUrl, 'delete', $title, $description); // Now remove the thumb JFile::delete($thumbs[0]->getPath()); $image->destroy(); } } } return $files; } /** * Create an array with file information for json output * * @param string $fileName - the file name * @param string $thumbnailUrl - the thumbnail url * @param string $size - the size of the file * @param string $type - the type of the file * @param string $url - the url * @param string $deleteUrl - the delete url for this item * @param string $deleteType - the delete type * @param string $title - the title for the image * @param string $description - the description of the image * * @return array */ private function fileArray($fileName, $thumbnailUrl, $size, $type, $url, $deleteUrl, $deleteType = 'delete', $title = '', $description = '') { return array( 'name' => $fileName, 'title' => $title, 'description' => $description, 'thumbnailUrl' => $thumbnailUrl, 'size' => $size, 'type' => $type, 'deleteType' => $deleteType, 'url' => $url, 'deleteUrl' => $deleteUrl ); } /** * Checks if we have any items that need to be migrated & if we have files * that are set to non-existing by a previous migration * * @return mixed */ public function healthCheck() { $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('COUNT(compojoom_multimedia_id) AS count')->from('#__compojoom_multimedia') ->where($db->qn('origin') . ' = ' . $db->q($this->component . '.migrate')); $db->setQuery($query); $health['update'] = (int) $db->loadObject()->count; $query->clear(); $query->select('item_id, mangled_filename')->from('#__compojoom_multimedia') ->where($db->qn('origin') . ' = ' . $db->q($this->component . '.migrate.nonexisting')); $db->setQuery($query); $health['nonexisting'] = $db->loadObjectList(); return $health; } /** * Performs a migration of a file from an old location, to the new one * * @param string $origin - the origin column value * @param string $path - the path to the old files * * @return array */ public function migrate($origin, $path) { $table = JTable::getInstance('Multimedia', 'CompojoomTable'); $result = $table->load(array('origin' => $origin)); $response = array( 'status' => true, 'msg' => '', 'shouldContinue' => false ); $path = JPath::clean($path); $filePath = JPath::clean($path . '/' . $table->mangled_filename); // If we don't have any row, then there is no point in continuing if ($result) { if (file_exists($filePath)) { $moved = $this->permanentlyMoveFiles($table->item_id, array($table->mangled_filename), $path); $fileData = $moved[$table->mangled_filename]; if ($fileData['status']) { $params = array(); if ($fileData['thumbs']) { foreach ($fileData['thumbs'] as $tkey => $tvalue) { $params['thumbs'][$tkey] = array( 'name' => basename($tvalue->getPath()) ); } } $registry = new JRegistry($params); $table->params = $registry->toString(); $table->origin = 'web'; $table->title = JFile::stripExt($table->mangled_filename); $table->mime_type = $fileData['properties']->mime; if ($table->store()) { $itemsLeft = $this->healthCheck(); $response = array( 'success' => 'true', 'message' => JText::sprintf( 'LIB_COMPOJOOM_FILE_DATA_UPDATED', 'index.php?option=com_hotspots&task=hotspot.edit&id=' . $table->item_id, $table->item_id, $itemsLeft['update'] ), 'shouldContinue' => $itemsLeft ? true : false ); } } } else { // Let's change the origin for this file $table->origin = 'com_hotspots.migrate.nonexisting'; if ($table->store()) { $itemsLeft = $this->healthCheck(); $response = array('success' => 'true', 'message' => JText::sprintf( 'LIB_COMPOJOOM_FILE_MULTIMEDIA_NEEDS_TO_BE_DELETED', $table->mangled_filename, 'index.php?option=com_hotspots&task=hotspot.edit&id=' . $table->item_id, $table->item_id, $itemsLeft['update'] ), 'shouldContinue' => $itemsLeft ? true : false ); } } } return $response; } }