diff --git a/administrator/components/com_admin/sql/updates/mysql/3.5.0-2014-06-28.sql b/administrator/components/com_admin/sql/updates/mysql/3.5.0-2014-06-28.sql new file mode 100644 index 0000000000000..52570da8d68f4 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/3.5.0-2014-06-28.sql @@ -0,0 +1,5 @@ +INSERT INTO `#__content_types`(`type_id`, `type_title`, `type_alias`, `table`, `field_mappings`) VALUES +(16, 'Image', 'com_media.image', '{"special":{"dbtable":"#__ucm_content","key":"core_content_id","type":"Corecontent","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"core_content_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '{"common":{"core_content_item_id":"core_content_id","core_title":"core_title","core_state":"core_state","core_alias":"core_alias","core_created_time":"core_created_time","core_modified_time":"core_modified_time","core_body":"core_body", "core_hits":"core_hits","core_publish_up":"core_publish_up","core_publish_down":"core_publish_down","core_access":"core_access", "core_params":"core_params", "core_featured":"core_featured", "core_metadata":"core_metadata", "core_language":"core_language", "core_images":"core_images", "core_urls":"core_urls", "core_version":"core_version", "core_ordering":"core_ordering", "core_metakey":"core_metakey", "core_metadesc":"core_metadesc", "core_catid":"core_catid", "core_xreference":"core_xreference", "asset_id":"asset_id"}, "special":{"core_content_item_id":"core_content_id","core_title":"core_title","core_state":"core_state","core_alias":"core_alias","core_created_time":"core_created_time","core_modified_time":"core_modified_time","core_body":"core_body", "core_hits":"core_hits","core_publish_up":"core_publish_up","core_publish_down":"core_publish_down","core_access":"core_access", "core_params":"core_params", "core_featured":"core_featured", "core_metadata":"core_metadata", "core_language":"core_language", "core_images":"core_images", "core_urls":"core_urls", "core_version":"core_version", "core_ordering":"core_ordering", "core_metakey":"core_metakey", "core_metadesc":"core_metadesc", "core_catid":"core_catid", "core_xreference":"core_xreference", "asset_id":"asset_id"}}'), +(17, 'Media Category', 'com_media.category', '', ''); +INSERT INTO `#__categories`(`id`, `asset_id`, `parent_id`, `lft`, `rgt`, `level`, `path`, `extension`, `title`, `alias`, `published`, `access`, `params`, `metadata`, `created_user_id`, `hits`, `language`, `version`) VALUES +(8, 33, 1, 13, 14, 1, 'uncategorised', 'com_media', 'Uncategorised', 'uncategorised', 1, 1, '{"category_layout":"","image":""}', '{"author":"","robots":""}', 42, 0, '*', 1); \ No newline at end of file diff --git a/administrator/components/com_admin/sql/updates/postgresql/3.5.0-2014-06-28.sql b/administrator/components/com_admin/sql/updates/postgresql/3.5.0-2014-06-28.sql new file mode 100644 index 0000000000000..6a81a4804f545 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/3.5.0-2014-06-28.sql @@ -0,0 +1,5 @@ +INSERT INTO "#__content_types" ("type_id", "type_title", "type_alias", "table", "field_mappings") VALUES +(16, 'Image', 'com_media.image', '{"special":{"dbtable":"#__ucm_content","key":"core_content_id","type":"Corecontent","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"core_content_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '{"common":{"core_content_item_id":"core_content_id","core_title":"core_title","core_state":"core_state","core_alias":"core_alias","core_created_time":"core_created_time","core_modified_time":"core_modified_time","core_body":"core_body", "core_hits":"core_hits","core_publish_up":"core_publish_up","core_publish_down":"core_publish_down","core_access":"core_access", "core_params":"core_params", "core_featured":"core_featured", "core_metadata":"core_metadata", "core_language":"core_language", "core_images":"core_images", "core_urls":"core_urls", "core_version":"core_version", "core_ordering":"core_ordering", "core_metakey":"core_metakey", "core_metadesc":"core_metadesc", "core_catid":"core_catid", "core_xreference":"core_xreference", "asset_id":"asset_id"}, "special":{"core_content_item_id":"core_content_id","core_title":"core_title","core_state":"core_state","core_alias":"core_alias","core_created_time":"core_created_time","core_modified_time":"core_modified_time","core_body":"core_body", "core_hits":"core_hits","core_publish_up":"core_publish_up","core_publish_down":"core_publish_down","core_access":"core_access", "core_params":"core_params", "core_featured":"core_featured", "core_metadata":"core_metadata", "core_language":"core_language", "core_images":"core_images", "core_urls":"core_urls", "core_version":"core_version", "core_ordering":"core_ordering", "core_metakey":"core_metakey", "core_metadesc":"core_metadesc", "core_catid":"core_catid", "core_xreference":"core_xreference", "asset_id":"asset_id"}}'), +(17, 'Media Category', 'com_media.category', '', ''); +INSERT INTO "#__categories"("id", "asset_id", "parent_id", "lft", "rgt", "level", "path", "extension", "title", "alias", "published", "access", "params", "metadata", "created_user_id", "hits", "language", "version") VALUES +(8, 33, 1, 13, 14, 1, 'uncategorised', 'com_media', 'Uncategorised', 'uncategorised', 1, 1, '{"category_layout":"","image":""}', '{"author":"","robots":""}', 42, 0, '*', 1); diff --git a/administrator/components/com_admin/sql/updates/sqlazure/3.5.0-2014-06-28.sql b/administrator/components/com_admin/sql/updates/sqlazure/3.5.0-2014-06-28.sql new file mode 100644 index 0000000000000..1fdd9842f8de4 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/sqlazure/3.5.0-2014-06-28.sql @@ -0,0 +1,17 @@ +SET IDENTITY_INSERT [#__content_types] ON; + +INSERT INTO [#__content_types] ([type_id], [type_title], [type_alias], [table], [field_mappings]) +SELECT 16, 'Image', 'com_media.image', '{"special":{"dbtable":"#__ucm_content","key":"core_content_id","type":"Corecontent","prefix":"JTable","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"core_content_id","type":"Corecontent","prefix":"JTable","config":"array()"}}', '{"common":{"core_content_item_id":"core_content_id","core_title":"core_title","core_state":"core_state","core_alias":"core_alias","core_created_time":"core_created_time","core_modified_time":"core_modified_time","core_body":"core_body", "core_hits":"core_hits","core_publish_up":"core_publish_up","core_publish_down":"core_publish_down","core_access":"core_access", "core_params":"core_params", "core_featured":"core_featured", "core_metadata":"core_metadata", "core_language":"core_language", "core_images":"core_images", "core_urls":"core_urls", "core_version":"core_version", "core_ordering":"core_ordering", "core_metakey":"core_metakey", "core_metadesc":"core_metadesc", "core_catid":"core_catid", "core_xreference":"core_xreference", "asset_id":"asset_id"}, "special":{"core_content_item_id":"core_content_id","core_title":"core_title","core_state":"core_state","core_alias":"core_alias","core_created_time":"core_created_time","core_modified_time":"core_modified_time","core_body":"core_body", "core_hits":"core_hits","core_publish_up":"core_publish_up","core_publish_down":"core_publish_down","core_access":"core_access", "core_params":"core_params", "core_featured":"core_featured", "core_metadata":"core_metadata", "core_language":"core_language", "core_images":"core_images", "core_urls":"core_urls", "core_version":"core_version", "core_ordering":"core_ordering", "core_metakey":"core_metakey", "core_metadesc":"core_metadesc", "core_catid":"core_catid", "core_xreference":"core_xreference", "asset_id":"asset_id"}}' +UNION ALL +SELECT 17, 'Media Category', 'com_media.category', '', ''; + +SET IDENTITY_INSERT #__content_types OFF; + +SET IDENTITY_INSERT [#__categories] ON; + +INSERT INTO [#__categories] ([id], [asset_id], [parent_id], [lft], [rgt], [level], [path], [extension], [title], [alias], [published], [access], [params], [metadata], [created_user_id], [hits], [language], [version]) +SELECT 8, 33, 1, 13, 14, 1, 'uncategorised', 'com_media', 'Uncategorised', 'uncategorised', 1, 1, '{"category_layout":"","image":""}', '{"author":"","robots":""}', 42, 0, '*', 1; + +SET IDENTITY_INSERT #__categories OFF; + + diff --git a/administrator/components/com_media/access.xml b/administrator/components/com_media/access.xml index cee9d758a3938..42388234eab67 100644 --- a/administrator/components/com_media/access.xml +++ b/administrator/components/com_media/access.xml @@ -5,5 +5,15 @@ + + + + +
+ + + + +
diff --git a/administrator/components/com_media/config.xml b/administrator/components/com_media/config.xml index 06cd6ab436005..5c2f8635e556b 100644 --- a/administrator/components/com_media/config.xml +++ b/administrator/components/com_media/config.xml @@ -89,6 +89,17 @@ default="text/html" label="COM_MEDIA_FIELD_ILLEGAL_MIME_TYPES_LABEL" description="COM_MEDIA_FIELD_ILLEGAL_MIME_TYPES_DESC" /> + + + + +
input->get('view', 'media'); @@ -84,11 +86,11 @@ public function display($cachable = false, $urlparams = false) } /** - * Validate FTP credentials + * Validating FTP connection * - * @return void + * @return null * - * @since 1.5 + * @deprecated 4.0 */ public function ftpValidate() { diff --git a/administrator/components/com_media/controller/editor/cancel.php b/administrator/components/com_media/controller/editor/cancel.php new file mode 100644 index 0000000000000..c00c4a22d52e3 --- /dev/null +++ b/administrator/components/com_media/controller/editor/cancel.php @@ -0,0 +1,59 @@ +app->input->get('folder', '', 'raw'); + + $checkinController = new MediaControllerEditorCheckin; + $checkinController->execute(); + + // Delete if there is a hidden file + $file = $this->app->input->get('file'); + $model = new MediaModelEditor; + + $duplicateFile = $model->resolveDuplicateFilename(JPath::clean(COM_MEDIA_BASE . '/' . $folder . '/' . $file)); + + if (JFile::exists($duplicateFile)) + { + JFile::delete($duplicateFile); + } + + $this->redirect = 'index.php?option=com_media&controller=media.display.media&folder=' . $folder; + + parent::execute(); + } +} diff --git a/administrator/components/com_media/controller/editor/checkin.php b/administrator/components/com_media/controller/editor/checkin.php new file mode 100644 index 0000000000000..0859c9931b372 --- /dev/null +++ b/administrator/components/com_media/controller/editor/checkin.php @@ -0,0 +1,66 @@ +input->getWord('option', 'com_media'); + + $viewName = $this->input->getWord('view', 'editor'); + + $modelClass = $this->prefix . 'Model' . ucfirst($viewName); + + $id = $this->input->get('id'); + + $model = new $modelClass; + + // Access check. + if (!JFactory::getUser()->authorise('core.admin', $model->getState()->get('component.option'))) + { + $this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error'); + + return false; + } + + if (!$model->checkin($id)) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_ITEM_CHECKED_IN_FAILED')); + + return false; + } + + return true; + } +} diff --git a/administrator/components/com_media/controller/editor/crop.php b/administrator/components/com_media/controller/editor/crop.php new file mode 100644 index 0000000000000..2d7f1f49d409c --- /dev/null +++ b/administrator/components/com_media/controller/editor/crop.php @@ -0,0 +1,71 @@ +app->input->get('x'); + $y = $this->app->input->get('y'); + $w = $this->app->input->get('w'); + $h = $this->app->input->get('h'); + + $file = $this->app->input->get('file'); + $folder = $this->app->input->get('folder', '', 'path'); + $id = $this->app->input->get('id'); + + $viewName = $this->input->getWord('view', 'editor'); + $modelClass = $this->prefix . 'Model' . ucfirst($viewName); + + $model = new $modelClass; + + if (empty($w) && empty($h) && empty($x) && empty($y)) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_CROP_AREA_ERROR'), 'error'); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + elseif ($model->cropImage($id, $w, $h, $x, $y)) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_CROP_SUCCESS')); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + else + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_CROP_ERROR'), 'error'); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + + return; + } +} diff --git a/administrator/components/com_media/controller/editor/display.php b/administrator/components/com_media/controller/editor/display.php new file mode 100644 index 0000000000000..ff0acb1e97057 --- /dev/null +++ b/administrator/components/com_media/controller/editor/display.php @@ -0,0 +1,102 @@ +input->getWord('option', 'com_media'); + $folder = $this->app->input->get('folder', '', 'path'); + + if ($this->app->isAdmin()) + { + $viewName = $this->input->getWord('view', 'editor'); + } + + $viewFormat = $document->getType(); + $layoutName = $this->input->getWord('layout', 'default'); + + // Register the layout paths for the view + $paths = new SplPriorityQueue; + + if ($this->app->isAdmin()) + { + $paths->insert(JPATH_ADMINISTRATOR . '/components/' . $componentFolder . '/view/' . $viewName . '/tmpl', 1); + } + else + { + $paths->insert(JPATH_BASE . '/components/' . $componentFolder . '/view/' . $viewName . '/tmpl', 1); + } + + $viewClass = $this->prefix . 'View' . ucfirst($viewName) . ucfirst($viewFormat); + $modelClass = $this->prefix . 'Model' . ucfirst($viewName); + + if (class_exists($viewClass)) + { + $model = new $modelClass; + + // Access check. + if (!JFactory::getUser()->authorise('core.admin', $model->getState()->get('component.option'))) + { + $this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error'); + + return; + } + + $view = new $viewClass($model, $paths); + + $view->setLayout($layoutName); + + // Push document object into the view. + $view->document = $document; + + $id = $this->input->getInt('id'); + + // Check if another user already checked-out + if (!$model->checkout($id)) + { + $this->app->redirect(JRoute::_('index.php?option=com_media&folder=' . $folder, false)); + } + + // Reply for service requests + if ($viewFormat == 'json') + { + return $view->render(); + } + + // Render view. + echo $view->render(); + } + } +} diff --git a/administrator/components/com_media/controller/editor/filter.php b/administrator/components/com_media/controller/editor/filter.php new file mode 100644 index 0000000000000..8cce5142fb401 --- /dev/null +++ b/administrator/components/com_media/controller/editor/filter.php @@ -0,0 +1,61 @@ +app->input->get('filter'); + $value = $this->app->input->get('value', 0, 'int'); + + $file = $this->app->input->get('file'); + $folder = $this->app->input->get('folder', '', 'path'); + $id = $this->app->input->get('id'); + + $viewName = $this->input->getWord('view', 'editor'); + $modelClass = $this->prefix . 'Model' . ucfirst($viewName); + + $model = new $modelClass; + + if ($model->filterImage($id, $filter, $value)) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_FILTER_SUCCESS')); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + else + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_FILTER_ERROR'), 'error'); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + } +} diff --git a/administrator/components/com_media/controller/editor/flip.php b/administrator/components/com_media/controller/editor/flip.php new file mode 100644 index 0000000000000..00a68355c13a6 --- /dev/null +++ b/administrator/components/com_media/controller/editor/flip.php @@ -0,0 +1,60 @@ +app->input->get('mode'); + + $file = $this->app->input->get('file'); + $folder = $this->app->input->get('folder', '', 'path'); + $id = $this->app->input->get('id'); + + $viewName = $this->input->getWord('view', 'editor'); + $modelClass = $this->prefix . 'Model' . ucfirst($viewName); + + $model = new $modelClass; + + if ($model->flipImage($id, $mode)) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_FLIP_SUCCESS')); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + else + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_FLIP_ERROR'), 'error'); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + } +} diff --git a/administrator/components/com_media/controller/editor/resize.php b/administrator/components/com_media/controller/editor/resize.php new file mode 100644 index 0000000000000..20e93cf280b6b --- /dev/null +++ b/administrator/components/com_media/controller/editor/resize.php @@ -0,0 +1,61 @@ +app->input->get('width'); + $height = $this->app->input->get('height'); + + $file = $this->app->input->get('file'); + $folder = $this->app->input->get('folder', '', 'path'); + $id = $this->app->input->get('id'); + + $viewName = $this->input->getWord('view', 'editor'); + $modelClass = $this->prefix . 'Model' . ucfirst($viewName); + + $model = new $modelClass; + + if ($model->resizeImage($id, $width, $height)) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_RESIZE_SUCCESS')); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + else + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_RESIZE_ERROR'), 'error'); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + } +} diff --git a/administrator/components/com_media/controller/editor/rotate.php b/administrator/components/com_media/controller/editor/rotate.php new file mode 100644 index 0000000000000..cd7a30b72d0b9 --- /dev/null +++ b/administrator/components/com_media/controller/editor/rotate.php @@ -0,0 +1,66 @@ +app->input->get('angle'); + $direction = $this->app->input->get('direction', '+', 'raw'); + + $file = $this->app->input->get('file'); + $folder = $this->app->input->get('folder', '', 'path'); + $id = $this->app->input->get('id'); + + $viewName = $this->input->getWord('view', 'editor'); + $modelClass = $this->prefix . 'Model' . ucfirst($viewName); + + $model = new $modelClass; + + if ($direction == '-') + { + $angle = $angle * (-1); + } + + if ($model->rotateImage($id, $angle)) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_ROTATE_SUCCESS')); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + else + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_ROTATE_ERROR'), 'error'); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + } +} diff --git a/administrator/components/com_media/controller/editor/save.php b/administrator/components/com_media/controller/editor/save.php new file mode 100644 index 0000000000000..07c6c19f99e72 --- /dev/null +++ b/administrator/components/com_media/controller/editor/save.php @@ -0,0 +1,126 @@ +app->enqueueMessage(JText::_('JINVALID_TOKEN')); + $this->app->redirect('index.php'); + } + + // Check if the user is authorized to do this. + $user = JFactory::getUser(); + + if (!$user->authorise('core.edit', 'com_media')) + { + $this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR')); + $this->app->redirect('index.php'); + } + + $model = new MediaModelEditor; + $data = $this->input->post->get('jform', array(), 'array'); + $form = $model->getForm(); + + $file = $this->app->input->get('file'); + $folder = $this->app->input->get('folder', '', 'raw'); + $id = $this->input->get('id'); + + $data['core_content_id'] = $id; + + // Validate the posted data + $return = $model->validate($form, $data); + + if ($return === false) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_SAVE_ERROR'), 'error'); + $this->app->redirect( + JRoute::_( + 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id, + false + ) + ); + } + + // Attempt to save the configuration + $data = $return; + + // Call checkin controller + $checkinController = new MediaControllerEditorCheckin; + + if ($checkinController->execute()) + { + $return = $model->save($data); + } + + // Check the return value + if ($return === false) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_SAVE_ERROR'), 'error'); + $this->app->redirect( + JRoute::_( + 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id, + false + ) + ); + } + + // Handle hidden file + $originalFile = JPath::clean(COM_MEDIA_BASE . '/' . $folder . '/' . pathinfo($file, PATHINFO_FILENAME) . '.' . pathinfo($file, PATHINFO_EXTENSION)); + $duplicateFile = $model->resolveDuplicateFilename(COM_MEDIA_BASE . '/' . $folder . '/' . $file); + + if (JFile::exists($duplicateFile) && JFile::copy($duplicateFile, $originalFile)) + { + JFile::delete($duplicateFile); + } + + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_SAVE_SUCCESS')); + + // Set the redirect based on the task. + switch ($this->options[3]) + { + case 'apply': + { + + $this->app->redirect( + JRoute::_( + 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id, + false + ) + ); + break; + } + + case 'save': + default: + + $this->app->redirect(JRoute::_('index.php?option=com_media&folder=' . $folder, false)); + break; + } + } +} diff --git a/administrator/components/com_media/controller/editor/thumbs.php b/administrator/components/com_media/controller/editor/thumbs.php new file mode 100644 index 0000000000000..05222ff1f7a11 --- /dev/null +++ b/administrator/components/com_media/controller/editor/thumbs.php @@ -0,0 +1,69 @@ +app->input->get('s'); + $thumbsFolder = $this->app->input->get('t', null, 'FILE'); + $creationMethod = $this->app->input->get('c', JImage::SCALE_INSIDE, 'int'); + + $file = $this->app->input->get('file'); + $folder = $this->app->input->get('folder', '', 'path'); + $id = $this->app->input->get('id'); + + if (!empty($thumbsFolder)) + { + $thumbsFolder = JPath::clean(COM_MEDIA_BASE . '/' . $folder . '/' . $thumbsFolder); + } + + $viewName = $this->input->getWord('view', 'editor'); + $modelClass = $this->prefix . 'Model' . ucfirst($viewName); + + $model = new $modelClass; + + if ($model->createThumbs($id, $size, $creationMethod, $thumbsFolder)) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_THUMBS_SUCCESS')); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + else + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_EDITOR_FILE_THUMBS_ERROR'), 'error'); + $url = 'index.php?option=com_media&controller=media.display.editor&folder=' . $folder . '&file=' . $file . '&id=' . $id; + $this->app->redirect(JRoute::_($url, false)); + } + + return; + } +} diff --git a/administrator/components/com_media/controller/images/display.php b/administrator/components/com_media/controller/images/display.php new file mode 100644 index 0000000000000..6508185d73be3 --- /dev/null +++ b/administrator/components/com_media/controller/images/display.php @@ -0,0 +1,94 @@ +input->set('view', 'images'); + + // Get the document object. + $document = JFactory::getDocument(); + + $componentFolder = $this->input->getWord('option', 'com_config'); + + if ($this->app->isAdmin()) + { + $viewName = $this->input->getWord('view', 'application'); + } + else + { + $viewName = $this->input->getWord('view', 'config'); + } + + $viewFormat = $document->getType(); + $layoutName = $this->input->getWord('layout', 'default'); + + // Register the layout paths for the view + $paths = new SplPriorityQueue; + + $paths->insert(JPATH_ADMINISTRATOR . '/components/' . $componentFolder . '/view/' . $viewName . '/tmpl', 1); + + $viewClass = $this->prefix . 'View' . ucfirst($viewName) . ucfirst($viewFormat); + $modelClass = $this->prefix . 'Model' . ucfirst('media'); + + if (class_exists($viewClass)) + { + $model = new $modelClass; + + // Access check. + if (!JFactory::getUser()->authorise('core.admin', $model->getState()->get('component.option'))) + { + $this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error'); + + return; + } + + $view = new $viewClass($model, $paths); + + $view->setLayout($layoutName); + + // Push document object into the view. + $view->document = $document; + + // Reply for service requests + if ($viewFormat == 'json') + { + return $view->render(); + } + + // Render view. + echo $view->render(); + } + + return true; + } +} diff --git a/administrator/components/com_media/controller/imageslist/display.php b/administrator/components/com_media/controller/imageslist/display.php new file mode 100644 index 0000000000000..4916c8d605429 --- /dev/null +++ b/administrator/components/com_media/controller/imageslist/display.php @@ -0,0 +1,94 @@ +input->getWord('option', 'com_media'); + + $viewName = $this->input->getWord('view', 'imageslist'); + + $viewFormat = $document->getType(); + + $layoutName = $this->app->getUserStateFromRequest('images.list.layout', 'layout', 'default', 'word'); + + // Register the layout paths for the view + $paths = new SplPriorityQueue; + + $paths->insert(JPATH_ADMINISTRATOR . '/components/' . $componentFolder . '/view/' . $viewName . '/tmpl', 1); + + $viewClass = $this->prefix . 'View' . ucfirst($viewName) . ucfirst($viewFormat); + $modelClass = $this->prefix . 'Model' . ucfirst('medialist'); + + if (class_exists($viewClass)) + { + $model = new $modelClass; + + // Access check. + if (!JFactory::getUser()->authorise('core.admin', $model->getState('component.option'))) + { + $this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error'); + + return; + } + + $view = new $viewClass($model, $paths); + + $view->setLayout($layoutName); + + // Push document object into the view. + $view->document = $document; + + // Reply for service requests + if ($viewFormat == 'json') + { + return $view->render(); + } + + // Render view. + echo $view->render(); + } + + return true; + } +} diff --git a/administrator/components/com_media/controller/media/copy.php b/administrator/components/com_media/controller/media/copy.php new file mode 100644 index 0000000000000..12584e34aeb3c --- /dev/null +++ b/administrator/components/com_media/controller/media/copy.php @@ -0,0 +1,192 @@ +redirect() for all cases + * + * @since 3.5 + */ + public function execute() + { + if (!JSession::checkToken('request')) + { + $this->app->enqueueMessage(JText::_('JINVALID_TOKEN')); + $this->app->redirect('index.php'); + } + + // Get some data from the request + $tmpl = $this->input->get('tmpl'); + $paths = $this->input->get('rm', array(), 'array'); + $folder = $this->input->get('folder', '', 'raw'); + $targetPath = $this->input->get('targetPath', '', 'raw'); + $return = JFactory::getSession()->get('com_media.return_url', 'index.php?option=com_media&controller=media.display.media'); + + // Avoid issue with single string in a relative path + if (strlen(trim($targetPath)) == 0) + { + $targetPath = $this->input->get('targetPath', ''); + } + + if (strlen(trim($folder)) == 0) + { + $folder = $this->input->get('folder', ''); + } + + // Nothing to copy + if (empty($paths) || is_null($targetPath)) + { + return true; + } + + $user = JFactory::getUser(); + + // Authorize the user + if (!$user->authorise('core.create', 'com_media')) + { + // User is not authorised to copy + $this->app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_CREATE_NOT_PERMITTED')); + + return false; + } + + // Set FTP credentials, if given + JClientHelper::setCredentialsFromRequest('ftp'); + + JPluginHelper::importPlugin('content'); + $dispatcher = JEventDispatcher::getInstance(); + + foreach ($paths as $path) + { + if ($path !== JFile::makeSafe($path)) + { + // Filename is not safe + $filename = htmlspecialchars($path, ENT_COMPAT, 'UTF-8'); + + // Seperate method to make this class reusable for folder deletion + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_COPY_FILE_WARNFILENAME', substr($filename, strlen(COM_MEDIA_BASE))), 'error'); + continue; + } + + // Existing filepath filename + $fullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $folder, $path))); + + // Destination filepath with filename + $targetFullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $targetPath, $path))); + $object_file = new JObject(array('filepath' => $fullPath, 'targetpath' => $targetFullPath)); + + if (is_file($object_file->filepath)) + { + // Trigger the onContentBeforeCopy event. + $result = $dispatcher->trigger('onContentBeforeCopy', array('com_media.file', &$object_file)); + + if (in_array(false, $result, true)) + { + // There are some errors in the plugins + $this->app->enqueueMessage(JText::plural('COM_MEDIA_ERROR_BEFORE_COPY', count($errors = $object_file->getErrors()), implode('
', $errors)), 'error'); + continue; + } + + if (!JFile::copy($object_file->filepath, $object_file->targetpath)) + { + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_FILE_COPY', substr($object_file->filepath, strlen(COM_MEDIA_BASE))), 'error'); + $this->app->redirect(JRoute::_($return . '&folder=' . $this->folder, false)); + } + + // Model to change table record of the media + $model = new MediaModelMedia; + + // Creating a new table entry + if (!$model->copyMediaFromTable($fullPath, $targetFullPath)) + { + // Can't create a record in database + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_DATABASE_COPY', substr($object_file->filepath, strlen(COM_MEDIA_BASE))), 'error'); + $this->app->redirect(JRoute::_($return . '&folder=' . $this->folder, false)); + } + + // Trigger the onContentAfterCopy event. + $dispatcher->trigger('onContentAfterCopy', array('com_media.file', &$object_file)); + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_COPY_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); + + } + elseif (is_dir($object_file->filepath)) + { + // Create a new media folder + if (!JFolder::create($object_file->targetpath)) + { + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_FOLDER_COPY', substr($object_file->filepath, strlen(COM_MEDIA_BASE))), 'error'); + $this->app->redirect(JRoute::_($return . '&folder=' . $this->folder, false)); + } + + // Get files & folders inside the folder as an array + $mediaArray = array_merge(JFolder::files($object_file->filepath), JFolder::folders($object_file->filepath)); + + // Filter images only + for ($index = 0; $index < count($mediaArray); $index++) + { + $file = JPath::clean($mediaArray[$index]); + $fileFullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $folder, $path, $file))); + $targetFileFullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $targetPath, $path, $file))); + + if (!JHelperMedia::isImage($file) && !is_dir($fileFullPath)) + { + // Move other files directly + if (!JFile::copy($fileFullPath, $targetFileFullPath)) + { + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_FILE_COPY', substr($object_file->filepath, strlen(COM_MEDIA_BASE))), 'error'); + $this->app->redirect(JRoute::_($return . '&folder=' . $this->folder, false)); + } + + // Remove non-image from media array + unset($mediaArray[$index]); + } + } + + // New JInput for recursively move internal media + $newInput = new JInput; + $newInput->set('rm', $mediaArray); + $newInput->set('folder', JPath::clean(implode(DIRECTORY_SEPARATOR, array($folder, $path)))); + $newInput->set('targetPath', JPath::clean(implode(DIRECTORY_SEPARATOR, array($targetPath, $path)))); + $this->input = $newInput; + + // Not to redirect during recursion + JFactory::getSession()->set('com_media.return_url', false); + + $copyController = new MediaControllerMediaCopy; + + if (!$copyController->execute()) + { + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_FOLDER_COPY', substr($object_file->filepath, strlen(COM_MEDIA_BASE))), 'error'); + $this->app->redirect(JRoute::_($return . '&folder=' . $this->folder, false)); + } + } + } + + if ($return) + { + $this->app->redirect(JRoute::_($return . '&folder=' . $folder, false)); + } + else + { + return true; + } + } +} diff --git a/administrator/components/com_media/controller/media/create.php b/administrator/components/com_media/controller/media/create.php new file mode 100644 index 0000000000000..567c9666c0ff3 --- /dev/null +++ b/administrator/components/com_media/controller/media/create.php @@ -0,0 +1,63 @@ +input->get('file', '', 'array'); + + // Authorize the user + if (!$user->authorise('core.create', 'com_media')) + { + // User is not authorised to create + $this->app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_CREATE_NOT_PERMITTED')); + + return false; + } + + $model = new MediaModelMedia; + + $result = $model->create($file); + + if ($result == false) + { + $this->app->enqueueMessage(JText::_('JERROR')); + + return false; + } + + return true; + } +} diff --git a/administrator/components/com_media/controller/media/delete.php b/administrator/components/com_media/controller/media/delete.php new file mode 100644 index 0000000000000..75b219fb36736 --- /dev/null +++ b/administrator/components/com_media/controller/media/delete.php @@ -0,0 +1,164 @@ +redirect() for all cases except JSON + * + * @since 3.5 + */ + public function execute() + { + if (!JSession::checkToken('request')) + { + $this->app->enqueueMessage(JText::_('JINVALID_TOKEN')); + $this->app->redirect('index.php'); + } + + $user = JFactory::getUser(); + + // Get some data from the request + $tmpl = $this->input->get('tmpl'); + $paths = $this->input->get('rm', array(), 'array'); + $folder = $this->input->get('folder', '', 'path'); + $redirect = 'index.php?option=com_media&controller=media.display.media&folder=' . $folder; + + if ($tmpl == 'component') + { + // We are inside the iframe + $redirect .= '&tmpl=component'; + } + + // Nothing to delete + if (empty($paths)) + { + $this->app->enqueueMessage(JText::_('JERROR_NO_ITEMS_SELECTED'), 'error'); + + $this->app->redirect(JRoute::_($redirect, false)); + } + + // Authorize the user + if (!$user->authorise('core.delete', 'com_media')) + { + // User is not authorised to delete + $this->app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED')); + + $this->app->redirect(JRoute::_($redirect, false)); + } + + // Set FTP credentials, if given + JClientHelper::setCredentialsFromRequest('ftp'); + + JPluginHelper::importPlugin('content'); + $dispatcher = JEventDispatcher::getInstance(); + + foreach ($paths as $path) + { + if ($path !== JFile::makeSafe($path)) + { + // Filename is not safe + $filename = htmlspecialchars($path, ENT_COMPAT, 'UTF-8'); + + // Seperate method to make this class reusable for folder deletion + $this->unableToDeleteMessage($filename); + continue; + } + + $fullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $folder, $path))); + $object_file = new JObject(array('filepath' => $fullPath)); + + if (is_file($object_file->filepath)) + { + // Trigger the onContentBeforeDelete event. + $result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.file', &$object_file)); + + if (in_array(false, $result, true)) + { + // There are some errors in the plugins + $this->app->enqueueMessage(JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors = $object_file->getErrors()), implode('
', $errors))); + continue; + } + + JFile::delete($object_file->filepath); + + // Delete from table + $model = new MediaModelMedia; + $model->deleteMediaFromTable($object_file->filepath); + + // Trigger the onContentAfterDelete event. + $dispatcher->trigger('onContentAfterDelete', array('com_media.file', &$object_file)); + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_DELETE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); + } + elseif (is_dir($object_file->filepath)) + { + $contents = JFolder::files($object_file->filepath, '.', true, false, array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'index.html')); + + if (empty($contents)) + { + // Trigger the onContentBeforeDelete event. + $result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.folder', &$object_file)); + + if (in_array(false, $result, true)) + { + // There are some errors in the plugins + $this->app->enqueueMessage(JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors = $object_file->getErrors()), implode('
', $errors)), 'warning'); + continue; + } + + JFolder::delete($object_file->filepath); + + // Trigger the onContentAfterDelete event. + $dispatcher->trigger('onContentAfterDelete', array('com_media.folder', &$object_file)); + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_FOLDER_DELETE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); + } + else + { + // This makes no sense... + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FOLDER_NOT_EMPTY', substr($object_file->filepath, strlen(COM_MEDIA_BASE))), 'warning'); + } + } + } + + $this->app->redirect(JRoute::_($redirect, false)); + } + + /** + * Enqueue error when delete failed + * + * @param string $name Delete failed file name + * + * @return null + * + * @since 3.5 + */ + protected function unableToDeleteMessage($name) + { + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FILE_WARNFILENAME', substr($name, strlen(COM_MEDIA_BASE)))); + } +} diff --git a/administrator/components/com_media/controller/media/display.php b/administrator/components/com_media/controller/media/display.php new file mode 100644 index 0000000000000..2aaf48f05be4b --- /dev/null +++ b/administrator/components/com_media/controller/media/display.php @@ -0,0 +1,40 @@ +input->set('view', 'media'); + + parent::execute(); + } +} diff --git a/administrator/components/com_media/controller/media/ftpvalidate.php b/administrator/components/com_media/controller/media/ftpvalidate.php new file mode 100644 index 0000000000000..12a677fa9918c --- /dev/null +++ b/administrator/components/com_media/controller/media/ftpvalidate.php @@ -0,0 +1,41 @@ +app->redirect(JRoute::_('index.php?option=com_media', false)); + } +} diff --git a/administrator/components/com_media/controller/media/move.php b/administrator/components/com_media/controller/media/move.php new file mode 100644 index 0000000000000..d6da52b21a861 --- /dev/null +++ b/administrator/components/com_media/controller/media/move.php @@ -0,0 +1,191 @@ +redirect() for all cases + * + * @since 3.5 + */ + public function execute() + { + if (!JSession::checkToken('request')) + { + $this->app->enqueueMessage(JText::_('JINVALID_TOKEN')); + $this->app->redirect('index.php'); + } + + // Get some data from the request + $tmpl = $this->input->get('tmpl'); + $paths = $this->input->get('rm', array(), 'array'); + $folder = $this->input->get('folder', '', 'raw'); + $targetPath = $this->input->get('targetPath', '', 'raw'); + $return = JFactory::getSession()->get('com_media.return_url', 'index.php?option=com_media&controller=media.display.media'); + + // Nothing to move + if (empty($paths) || is_null($targetPath)) + { + return true; + } + + $user = JFactory::getUser(); + + // Authorize the user + if (!$user->authorise('core.create', 'com_media')) + { + // User is not authorised to create + $this->app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_CREATE_NOT_PERMITTED')); + + return false; + } + + if (!$user->authorise('core.delete', 'com_media')) + { + // User is not authorised to delete + $this->app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED')); + + return false; + } + + // Set FTP credentials, if given + JClientHelper::setCredentialsFromRequest('ftp'); + + JPluginHelper::importPlugin('content'); + $dispatcher = JEventDispatcher::getInstance(); + + foreach ($paths as $path) + { + if ($path !== JFile::makeSafe($path)) + { + // Filename is not safe + $filename = htmlspecialchars($path, ENT_COMPAT, 'UTF-8'); + + // Seperate method to make this class reusable for folder deletion + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_MOVE_FILE_WARNFILENAME', substr($filename, strlen(COM_MEDIA_BASE))), 'error'); + continue; + } + + // Existing filepath filename + $fullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $folder, $path))); + + // Destination filepath with filename + $targetFullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $targetPath, $path))); + $object_file = new JObject(array('filepath' => $fullPath, 'targetpath' => $targetFullPath)); + + if (is_file($object_file->filepath)) + { + // Trigger the onContentBeforeMove event. + $result = $dispatcher->trigger('onContentBeforeMove', array('com_media.file', &$object_file)); + + if (in_array(false, $result, true)) + { + // There are some errors in the plugins + $this->app->enqueueMessage(JText::plural('COM_MEDIA_ERROR_BEFORE_MOVE', count($errors = $object_file->getErrors()), implode('
', $errors)), 'error'); + continue; + } + + if (!JFile::move($object_file->filepath, $object_file->targetpath)) + { + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_FILE_MOVE', substr($object_file->filepath, strlen(COM_MEDIA_BASE))), 'error'); + $this->app->redirect(JRoute::_($return . '&folder=' . $this->folder, false)); + } + + // Model to change table record of the media + $model = new MediaModelMedia; + + if (!$model->moveMediaFromTable($fullPath, $targetFullPath)) + { + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_DATABASE_MOVE', substr($object_file->filepath, strlen(COM_MEDIA_BASE))), 'error'); + $this->app->redirect(JRoute::_($return . '&folder=' . $this->folder, false)); + } + + // Trigger the onContentAfterMove event. + $dispatcher->trigger('onContentAfterMove', array('com_media.file', &$object_file)); + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_MOVE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); + } + elseif (is_dir($object_file->filepath)) + { + // Create a new media folder + if (!JFolder::create($object_file->targetpath)) + { + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_FOLDER_MOVE', substr($object_file->filepath, strlen(COM_MEDIA_BASE))), 'error'); + $this->app->redirect(JRoute::_($return . '&folder=' . $this->folder, false)); + } + + // Get files & folders inside the folder as an array + $mediaArray = array_merge(JFolder::files($object_file->filepath), JFolder::folders($object_file->filepath)); + + // Filter images only + for ($index = 0; $index < count($mediaArray); $index++) + { + $file = JPath::clean($mediaArray[$index]); + $fileFullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $folder, $path, $file))); + $targetFileFullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $targetPath, $path, $file))); + + if (!JHelperMedia::isImage($file) && !is_dir($fileFullPath)) + { + // Move other files directly + if (!JFile::move($fileFullPath, $targetFileFullPath)) + { + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_FILE_MOVE', substr($object_file->filepath, strlen(COM_MEDIA_BASE))), 'error'); + $this->app->redirect(JRoute::_($return . '&folder=' . $this->folder, false)); + } + + // Remove non-image from media array + unset($mediaArray[$index]); + } + } + + // New JInput for recursively move internal media + $newInput = new JInput; + $newInput->set('rm', $mediaArray); + $newInput->set('folder', JPath::clean(implode(DIRECTORY_SEPARATOR, array($folder, $path)))); + $newInput->set('targetPath', JPath::clean(implode(DIRECTORY_SEPARATOR, array($targetPath, $path)))); + $this->input = $newInput; + + // Not to redirect during recursion + JFactory::getSession()->set('com_media.return_url', false); + + $moveController = new MediaControllerMediaMove; + + if ($moveController->execute()) + { + // Delete the source base folder + JFolder::delete($object_file->filepath); + } + else + { + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_FOLDER_MOVE', substr($object_file->filepath, strlen(COM_MEDIA_BASE))), 'error'); + $this->app->redirect(JRoute::_($return . '&folder=' . $this->folder, false)); + } + } + } + + if ($return) + { + $this->app->redirect(JRoute::_($return . '&folder=' . $folder, false)); + } + else + { + return true; + } + } +} diff --git a/administrator/components/com_media/controller/media/upload.php b/administrator/components/com_media/controller/media/upload.php new file mode 100644 index 0000000000000..83b5b5fed10ff --- /dev/null +++ b/administrator/components/com_media/controller/media/upload.php @@ -0,0 +1,253 @@ +app->enqueueMessage(JText::_('JINVALID_TOKEN'), 'error'); + + return $this->redirect(JRoute::_('index.php?option=com_media'), false); + } + + $params = JComponentHelper::getParams('com_media'); + + $user = JFactory::getUser(); + + // Get some data from the request + $files = $this->input->files->get('Filedata', '', 'array'); + $return = JFactory::getSession()->get('com_media.return_url', 'index.php?option=com_media'); + $this->folder = $this->input->get('folder', '', 'path'); + + // Authorize the user + if (!$user->authorise('core.create', 'com_media')) + { + // User is not authorised to create + $this->app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_CREATE_NOT_PERMITTED'), 'error'); + + return $this->redirect(JRoute::_($return . '&folder=' . $this->folder, false), false); + } + + // Total length of post back data in bytes. + $contentLength = (int) $_SERVER['CONTENT_LENGTH']; + + // Maximum allowed size of post back data in MB. + $postMaxSize = (int) ini_get('post_max_size'); + + // Maximum allowed size of script execution in MB. + $memoryLimit = (int) ini_get('memory_limit'); + + // Check for the total size of post back data. + if (($postMaxSize > 0 && $contentLength > $postMaxSize * 1024 * 1024) + || ($memoryLimit != -1 && $contentLength > $memoryLimit * 1024 * 1024)) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE'), 'warning'); + + return $this->redirect(JRoute::_($return . '&folder=' . $this->folder, false), false); + } + + $uploadMaxSize = $params->get('upload_maxsize', 0) * 1024 * 1024; + $uploadMaxFileSize = (int) ini_get('upload_max_filesize') * 1024 * 1024; + + // Perform basic checks on file info before attempting anything + foreach ($files as &$file) + { + $file['name'] = JFile::makeSafe($file['name']); + $file['filepath'] = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $this->folder, $file['name']))); + + if (($file['error'] == UPLOAD_ERR_INI_SIZE) + || ($uploadMaxSize > 0 && $file['size'] > $uploadMaxSize) + || ($uploadMaxFileSize > 0 && $file['size'] > $uploadMaxFileSize)) + { + // File size exceed either 'upload_max_filesize' or 'upload_maxsize'. + $this->app->enqueueMessage(JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE'), 'warning'); + + return $this->redirect(JRoute::_($return . '&folder=' . $this->folder, false), false); + } + + if (JFile::exists($file['filepath'])) + { + if ($params->get('overwrite_files', 0) == 1 && $user->authorise('core.delete', 'com_media')) + { + /* + * A file with this name already exists, + * the option to overwrite the file is set to yes and + * the current user is authorised to delete files + * so we delete it here and upload the new later. + * Note that we can't restore the old file if the uplaod fails. + */ + JFile::delete($file['filepath']); + $this->app->enqueueMessage(JText::_('COM_MEDIA_ERROR_FILE_EXISTS_OVERWRITE'), 'notice'); + } + else + { + /* + * A file with this name already exists and + * the option to overwrite the file is set to no + * or the user is not authorised to delete files. + */ + $this->app->enqueueMessage(JText::_('COM_MEDIA_ERROR_FILE_EXISTS'), 'error'); + + return $this->redirect(JRoute::_($return . '&folder=' . $this->folder, false), false); + } + } + + if (!isset($file['name'])) + { + // No filename (after the name was cleaned by JFile::makeSafe) + $this->app->enqueueMessage(JText::_('COM_MEDIA_INVALID_REQUEST'), 'error'); + + return $this->redirect(JRoute::_($return . '&folder=' . $this->folder, false), false); + } + + // Enable uploading filenames with alphanumeric and spaces + $fileparts = pathinfo($file['filepath']); + $file['original_name'] = $fileparts['filename']; + + // Transform filename to punycode + $fileparts['filename'] = JStringPunycode::toPunycode($fileparts['filename']); + + // Transform filename to punycode, then neglect otherthan non-alphanumeric characters & underscores. Also transform extension to lowercase + $safeFileName = preg_replace(array("/[\\s]/", "/[^a-zA-Z0-9_]/"), array("_", ""), $fileparts['filename']) . '.' . strtolower($fileparts['extension']); + + // Create filepath with safe-filename + $file['filepath'] = $fileparts['dirname'] . DIRECTORY_SEPARATOR . $safeFileName; + $file['name'] = $safeFileName; + } + + // Set FTP credentials, if given + JClientHelper::setCredentialsFromRequest('ftp'); + JPluginHelper::importPlugin('content'); + $dispatcher = JEventDispatcher::getInstance(); + + foreach ($files as &$file) + { + if (!JHelperMedia::canUpload($file, 'com_media')) + { + // The file can't be uploaded + return $this->redirect(JRoute::_($return . '&folder=' . $this->folder, false), false); + } + + // Trigger the onContentBeforeSave event. + $object_file = new JObject($file); + $result = $dispatcher->trigger('onContentBeforeSave', array('com_media.file', &$object_file, true)); + + if (in_array(false, $result, true)) + { + // There are some errors in the plugins + $this->app->enqueueMessage( + JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('
', $errors)), + 'warning'); + + return $this->redirect(JRoute::_($return . '&folder=' . $this->folder, false), false); + } + + if (!JFile::upload($object_file->tmp_name, $object_file->filepath)) + { + // Error in upload + $this->app->enqueueMessage(JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE'), 'warning'); + + return $this->redirect(JRoute::_($return . '&folder=' . $this->folder, false), false); + } + else + { + // Add to table + $this->input->set('file', $object_file->getProperties()); + + // Create controller instance + $createController = new MediaControllerMediaCreate; + + if (!$createController->execute()) + { + // Can't create a record in database + return $this->redirect(JRoute::_($return . '&folder=' . $this->folder, false), false); + } + + // Trigger the onContentAfterSave event. + $dispatcher->trigger('onContentAfterSave', array('com_media.file', &$object_file, true)); + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_UPLOAD_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); + } + } + + return $this->redirect(JRoute::_($return . '&folder=' . $this->folder, false), true); + } + + /** + * Redirect after uploading media + * + * @param mixed $redirectTo Redirecting location + * @param boolean $success Failure or Success + * + * @return void + * + * @since 3.5 + */ + private function redirect($redirectTo, $success = true) + { + $format = JFactory::getDocument()->getType(); + $response = $redirectTo; + + // Handle JSON requests + if ($format == 'json') + { + // For failed requests + if (!$success) + { + $messages = $this->app->getMessageQueue(); + $message = $messages[0]['message']; + $response = new Exception($message); + } + + echo new JResponseJson($response); + + return; + } + + // For HTML Requests + $this->app->redirect($response); + + return; + } +} diff --git a/administrator/components/com_media/controller/medialist/create.php b/administrator/components/com_media/controller/medialist/create.php new file mode 100644 index 0000000000000..716149e8cd130 --- /dev/null +++ b/administrator/components/com_media/controller/medialist/create.php @@ -0,0 +1,125 @@ +app->enqueueMessage(JText::_('JINVALID_TOKEN')); + $this->app->redirect('index.php'); + } + + $user = JFactory::getUser(); + + $folder = $this->input->get('foldername', ''); + $folderCheck = (string) $this->input->get('foldername', null, 'raw'); + $parent = $this->input->get('folderbase', '', 'path'); + + if (strlen($folder) > 0) + { + if (!$user->authorise('core.create', 'com_media')) + { + // User is not authorised to create + $this->app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_CREATE_NOT_PERMITTED')); + + return false; + } + + // Set FTP credentials, if given + JClientHelper::setCredentialsFromRequest('ftp'); + + $this->input->set('folder', $parent); + + if (($folderCheck !== null) && ($folder !== $folderCheck)) + { + $this->app->enqueueMessage(JText::_('COM_MEDIA_ERROR_UNABLE_TO_CREATE_FOLDER_WARNDIRNAME'), 'warning'); + + return false; + } + + $path = JPath::clean(COM_MEDIA_BASE . '/' . $parent . '/' . $folder); + + if (!is_dir($path) && !is_file($path)) + { + // Trigger the onContentBeforeSave event. + $object_file = new JObject(array('filepath' => $path)); + JPluginHelper::importPlugin('content'); + $dispatcher = JEventDispatcher::getInstance(); + $result = $dispatcher->trigger('onContentBeforeSave', array('com_media.folder', &$object_file, true)); + + if (in_array(false, $result, true)) + { + // There are some errors in the plugins + JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('
', $errors))); + + return false; + } + + if (JFolder::create($object_file->filepath)) + { + $data = "\n\n\n"; + JFile::write($object_file->filepath . "/index.html", $data); + + // Trigger the onContentAfterSave event. + $dispatcher->trigger('onContentAfterSave', array('com_media.folder', &$object_file, true)); + $this->app->enqueueMessage(JText::sprintf('COM_MEDIA_FOLDER_CREATE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); + } + } + + $this->input->set('folder', ($parent) ? $parent . '/' . $folder : $folder); + } + else + { + // File name is of zero length (null). + $this->app->enqueueMessage(JText::_('COM_MEDIA_ERROR_UNABLE_TO_CREATE_FOLDER_WARNDIRNAME'), 'warning'); + + return false; + } + + $this->app->redirect(JRoute::_('index.php?option=com_media&folder=' . $parent . '&tmpl=' . $this->input->get('tmpl', 'index'), false)); + + return true; + } +} diff --git a/administrator/components/com_media/controller/medialist/delete.php b/administrator/components/com_media/controller/medialist/delete.php new file mode 100644 index 0000000000000..cadf7ec7d2582 --- /dev/null +++ b/administrator/components/com_media/controller/medialist/delete.php @@ -0,0 +1,34 @@ +app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FOLDER_WARNDIRNAME', substr($name, strlen(COM_MEDIA_BASE)))); + } +} diff --git a/administrator/components/com_media/controller/medialist/display.php b/administrator/components/com_media/controller/medialist/display.php new file mode 100644 index 0000000000000..31b83a6c3043b --- /dev/null +++ b/administrator/components/com_media/controller/medialist/display.php @@ -0,0 +1,94 @@ +input->getWord('option', 'com_media'); + + $viewName = $this->input->getWord('view', 'medialist'); + + $viewFormat = $document->getType(); + + $layoutName = $this->app->getUserStateFromRequest('media.list.layout', 'layout', 'thumbs', 'word'); + + // Register the layout paths for the view + $paths = new SplPriorityQueue; + + $paths->insert(JPATH_ADMINISTRATOR . '/components/' . $componentFolder . '/view/' . $viewName . '/tmpl', 1); + + $viewClass = $this->prefix . 'View' . ucfirst($viewName) . ucfirst($viewFormat); + $modelClass = $this->prefix . 'Model' . ucfirst($viewName); + + if (class_exists($viewClass)) + { + $model = new $modelClass; + + // Access check. + if (!JFactory::getUser()->authorise('core.admin', $model->getState('component.option'))) + { + $this->app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error'); + + return; + } + + $view = new $viewClass($model, $paths); + + $view->setLayout($layoutName); + + // Push document object into the view. + $view->document = $document; + + // Reply for service requests + if ($viewFormat == 'json') + { + return $view->render(); + } + + // Render view. + echo $view->render(); + } + + return true; + } +} diff --git a/administrator/components/com_media/controllers/file.php b/administrator/components/com_media/controllers/file.php index 87a70800b9163..371b65f0bfa5c 100644 --- a/administrator/components/com_media/controllers/file.php +++ b/administrator/components/com_media/controllers/file.php @@ -9,13 +9,13 @@ defined('_JEXEC') or die; -jimport('joomla.filesystem.file'); -jimport('joomla.filesystem.folder'); - /** * Media File Controller * - * @since 1.5 + * @package Joomla.Administrator + * @subpackage com_media + * @since 1.5 + * @deprecated 4.0 */ class MediaControllerFile extends JControllerLegacy { @@ -32,136 +32,15 @@ class MediaControllerFile extends JControllerLegacy * @return boolean * * @since 1.5 + * @deprecated 4.0 Use MediaControllerMediaUpload instead. */ public function upload() { - // Check for request forgeries - JSession::checkToken('request') or jexit(JText::_('JINVALID_TOKEN')); - $params = JComponentHelper::getParams('com_media'); - - // Get some data from the request - $files = $this->input->files->get('Filedata', '', 'array'); - $return = JFactory::getSession()->get('com_media.return_url'); - $this->folder = $this->input->get('folder', '', 'path'); - - // Set the redirect - if ($return) - { - $this->setRedirect($return . '&folder=' . $this->folder); - } - else - { - $this->setRedirect('index.php?option=com_media&folder=' . $this->folder); - } - - // Authorize the user - if (!$this->authoriseUser('create')) - { - return false; - } - - // Total length of post back data in bytes. - $contentLength = (int) $_SERVER['CONTENT_LENGTH']; - - // Instantiate the media helper - $mediaHelper = new JHelperMedia; - - // 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)) - { - JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_WARNUPLOADTOOLARGE')); - - return false; - } - - $uploadMaxSize = $params->get('upload_maxsize', 0) * 1024 * 1024; - $uploadMaxFileSize = $mediaHelper->toBytes(ini_get('upload_max_filesize')); - - // Perform basic checks on file info before attempting anything - foreach ($files as &$file) - { - $file['name'] = JFile::makeSafe($file['name']); - $file['filepath'] = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $this->folder, $file['name']))); - - if (($file['error'] == 1) - || ($uploadMaxSize > 0 && $file['size'] > $uploadMaxSize) - || ($uploadMaxFileSize > 0 && $file['size'] > $uploadMaxFileSize)) - { - // File size exceed either 'upload_max_filesize' or 'upload_maxsize'. - JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE')); - - return false; - } - - if (JFile::exists($file['filepath'])) - { - // A file with this name already exists - JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_FILE_EXISTS')); - - return false; - } - - if (!isset($file['name'])) - { - // No filename (after the name was cleaned by JFile::makeSafe) - $this->setRedirect('index.php', JText::_('COM_MEDIA_INVALID_REQUEST'), 'error'); - - return false; - } - } - - // Set FTP credentials, if given - JClientHelper::setCredentialsFromRequest('ftp'); - JPluginHelper::importPlugin('content'); - $dispatcher = JEventDispatcher::getInstance(); - - foreach ($files as &$file) - { - // The request is valid - $err = null; + JLog::add('MediaControllerFile.upload() is deprecated. Use MediaControllerMediaUpload instead.', JLog::WARNING, 'deprecated'); - if (!MediaHelper::canUpload($file, $err)) - { - // The file can't be uploaded + $controller = new MediaControllerMediaUpload; - return false; - } - - // Trigger the onContentBeforeSave event. - $object_file = new JObject($file); - $result = $dispatcher->trigger('onContentBeforeSave', array('com_media.file', &$object_file, true)); - - if (in_array(false, $result, true)) - { - // There are some errors in the plugins - JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('
', $errors))); - - return false; - } - - if (!JFile::upload($object_file->tmp_name, $object_file->filepath)) - { - // Error in upload - JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE')); - - return false; - } - else - { - // Trigger the onContentAfterSave event. - $dispatcher->trigger('onContentAfterSave', array('com_media.file', &$object_file, true)); - $this->setMessage(JText::sprintf('COM_MEDIA_UPLOAD_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); - } - } - - return true; + return $controller->execute(); } /** @@ -172,6 +51,7 @@ public function upload() * @return boolean * * @since 1.6 + * @deprecated 4.0 */ protected function authoriseUser($action) { @@ -192,110 +72,14 @@ protected function authoriseUser($action) * @return boolean * * @since 1.5 + * @deprecated 4.0 Use MediaControllerMediaDelete instead. */ public function delete() { - JSession::checkToken('request') or jexit(JText::_('JINVALID_TOKEN')); - - // Get some data from the request - $tmpl = $this->input->get('tmpl'); - $paths = $this->input->get('rm', array(), 'array'); - $folder = $this->input->get('folder', '', 'path'); + JLog::add('MediaControllerFile.delete() is deprecated. Use MediaControllerMediaDelete instead.', JLog::WARNING, 'deprecated'); - $redirect = 'index.php?option=com_media&folder=' . $folder; - - if ($tmpl == 'component') - { - // We are inside the iframe - $redirect .= '&view=mediaList&tmpl=component'; - } - - $this->setRedirect($redirect); - - // Nothing to delete - if (empty($paths)) - { - return true; - } - - // Authorize the user - if (!$this->authoriseUser('delete')) - { - return false; - } - - // Set FTP credentials, if given - JClientHelper::setCredentialsFromRequest('ftp'); - - JPluginHelper::importPlugin('content'); - $dispatcher = JEventDispatcher::getInstance(); - - $ret = true; - - foreach ($paths as $path) - { - if ($path !== JFile::makeSafe($path)) - { - // Filename is not safe - $filename = htmlspecialchars($path, ENT_COMPAT, 'UTF-8'); - JError::raiseWarning(100, JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FILE_WARNFILENAME', substr($filename, strlen(COM_MEDIA_BASE)))); - continue; - } - - $fullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $folder, $path))); - $object_file = new JObject(array('filepath' => $fullPath)); - - if (is_file($object_file->filepath)) - { - // Trigger the onContentBeforeDelete event. - $result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.file', &$object_file)); - - if (in_array(false, $result, true)) - { - // There are some errors in the plugins - $errors = $object_file->getErrors(); - JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors), implode('
', $errors))); - continue; - } - - $ret &= JFile::delete($object_file->filepath); - - // Trigger the onContentAfterDelete event. - $dispatcher->trigger('onContentAfterDelete', array('com_media.file', &$object_file)); - $this->setMessage(JText::sprintf('COM_MEDIA_DELETE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); - } - elseif (is_dir($object_file->filepath)) - { - $contents = JFolder::files($object_file->filepath, '.', true, false, array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'index.html')); - - if (empty($contents)) - { - // Trigger the onContentBeforeDelete event. - $result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.folder', &$object_file)); - - if (in_array(false, $result, true)) - { - // There are some errors in the plugins - $errors = $object_file->getErrors(); - JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors), implode('
', $errors))); - continue; - } - - $ret &= JFolder::delete($object_file->filepath); - - // Trigger the onContentAfterDelete event. - $dispatcher->trigger('onContentAfterDelete', array('com_media.folder', &$object_file)); - $this->setMessage(JText::sprintf('COM_MEDIA_DELETE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); - } - else - { - // This makes no sense... - $folderPath = substr($object_file->filepath, strlen(COM_MEDIA_BASE)); - JError::raiseWarning(100, JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FOLDER_NOT_EMPTY', $folderPath)); - } - } - } + $controller = new MediaControllerMediaDelete; - return $ret; + return $controller->execute(); } } diff --git a/administrator/components/com_media/controllers/folder.php b/administrator/components/com_media/controllers/folder.php index 8d09c24fc1a05..188d1f9590333 100644 --- a/administrator/components/com_media/controllers/folder.php +++ b/administrator/components/com_media/controllers/folder.php @@ -9,13 +9,13 @@ defined('_JEXEC') or die; -jimport('joomla.filesystem.file'); -jimport('joomla.filesystem.folder'); - /** * Folder Media Controller * - * @since 1.5 + * @package Joomla.Administrator + * @subpackage com_media + * @since 1.5 + * @deprecated 4.0 */ class MediaControllerFolder extends JControllerLegacy { @@ -25,119 +25,15 @@ class MediaControllerFolder extends JControllerLegacy * @return boolean * * @since 1.5 + * @deprecated 4.0 Use MediaControllerMedialistDelete instead. */ public function delete() { - JSession::checkToken('request') or jexit(JText::_('JINVALID_TOKEN')); - - $user = JFactory::getUser(); - - // Get some data from the request - $tmpl = $this->input->get('tmpl'); - $paths = $this->input->get('rm', array(), 'array'); - $folder = $this->input->get('folder', '', 'path'); - - $redirect = 'index.php?option=com_media&folder=' . $folder; - - if ($tmpl == 'component') - { - // We are inside the iframe - $redirect .= '&view=mediaList&tmpl=component'; - } - - $this->setRedirect($redirect); - - // Just return if there's nothing to do - if (empty($paths)) - { - $this->setMessage(JText::_('JERROR_NO_ITEMS_SELECTED'), 'error'); - - return true; - } - - if (!$user->authorise('core.delete', 'com_media')) - { - // User is not authorised to delete - JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED')); - - return false; - } - - // Set FTP credentials, if given - JClientHelper::setCredentialsFromRequest('ftp'); - - $ret = true; - - JPluginHelper::importPlugin('content'); - $dispatcher = JEventDispatcher::getInstance(); - - if (count($paths)) - { - foreach ($paths as $path) - { - if ($path !== JFile::makeSafe($path)) - { - $dirname = htmlspecialchars($path, ENT_COMPAT, 'UTF-8'); - JError::raiseWarning(100, JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FOLDER_WARNDIRNAME', substr($dirname, strlen(COM_MEDIA_BASE)))); - continue; - } - - $fullPath = JPath::clean(implode(DIRECTORY_SEPARATOR, array(COM_MEDIA_BASE, $folder, $path))); - $object_file = new JObject(array('filepath' => $fullPath)); - - if (is_file($object_file->filepath)) - { - // Trigger the onContentBeforeDelete event. - $result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.file', &$object_file)); - - if (in_array(false, $result, true)) - { - // There are some errors in the plugins - $errors = $object_file->getErrors(); - JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors), implode('
', $errors))); - continue; - } - - $ret &= JFile::delete($object_file->filepath); + JLog::add('MediaControllerFolder.delete() is deprecated. Use MediaControllerMedialistDelete instead.', JLog::WARNING, 'deprecated'); - // Trigger the onContentAfterDelete event. - $dispatcher->trigger('onContentAfterDelete', array('com_media.file', &$object_file)); - $this->setMessage(JText::sprintf('COM_MEDIA_DELETE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); - } - elseif (is_dir($object_file->filepath)) - { - $contents = JFolder::files($object_file->filepath, '.', true, false, array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'index.html')); + $controller = new MediaControllerMedialistDelete; - if (empty($contents)) - { - // Trigger the onContentBeforeDelete event. - $result = $dispatcher->trigger('onContentBeforeDelete', array('com_media.folder', &$object_file)); - - if (in_array(false, $result, true)) - { - // There are some errors in the plugins - $errors = $object_file->getErrors(); - JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_DELETE', count($errors), implode('
', $errors))); - continue; - } - - $ret &= !JFolder::delete($object_file->filepath); - - // Trigger the onContentAfterDelete event. - $dispatcher->trigger('onContentAfterDelete', array('com_media.folder', &$object_file)); - $this->setMessage(JText::sprintf('COM_MEDIA_DELETE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); - } - else - { - // This makes no sense... - $folderPath = substr($object_file->filepath, strlen(COM_MEDIA_BASE)); - JError::raiseWarning(100, JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_DELETE_FOLDER_NOT_EMPTY', $folderPath)); - } - } - } - } - - return $ret; + return $controller->execute(); } /** @@ -146,82 +42,14 @@ public function delete() * @return boolean * * @since 1.5 + * @deprecated 4.0 Use MediaControllerMedialistCreate instead. */ public function create() { - // Check for request forgeries - JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); - - $user = JFactory::getUser(); - - $folder = $this->input->get('foldername', ''); - $folderCheck = (string) $this->input->get('foldername', null, 'raw'); - $parent = $this->input->get('folderbase', '', 'path'); - - $this->setRedirect('index.php?option=com_media&folder=' . $parent . '&tmpl=' . $this->input->get('tmpl', 'index')); - - if (strlen($folder) > 0) - { - if (!$user->authorise('core.create', 'com_media')) - { - // User is not authorised to create - JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_CREATE_NOT_PERMITTED')); - - return false; - } - - // Set FTP credentials, if given - JClientHelper::setCredentialsFromRequest('ftp'); - - $this->input->set('folder', $parent); - - if (($folderCheck !== null) && ($folder !== $folderCheck)) - { - $app = JFactory::getApplication(); - $app->enqueueMessage(JText::_('COM_MEDIA_ERROR_UNABLE_TO_CREATE_FOLDER_WARNDIRNAME'), 'warning'); - - return false; - } - - $path = JPath::clean(COM_MEDIA_BASE . '/' . $parent . '/' . $folder); - - if (!is_dir($path) && !is_file($path)) - { - // Trigger the onContentBeforeSave event. - $object_file = new JObject(array('filepath' => $path)); - JPluginHelper::importPlugin('content'); - $dispatcher = JEventDispatcher::getInstance(); - $result = $dispatcher->trigger('onContentBeforeSave', array('com_media.folder', &$object_file, true)); - - if (in_array(false, $result, true)) - { - // There are some errors in the plugins - JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('
', $errors))); - - return false; - } - - if (JFolder::create($object_file->filepath)) - { - $data = "\n\n\n"; - JFile::write($object_file->filepath . "/index.html", $data); - - // Trigger the onContentAfterSave event. - $dispatcher->trigger('onContentAfterSave', array('com_media.folder', &$object_file, true)); - $this->setMessage(JText::sprintf('COM_MEDIA_CREATE_COMPLETE', substr($object_file->filepath, strlen(COM_MEDIA_BASE)))); - } - } - - $this->input->set('folder', ($parent) ? $parent . '/' . $folder : $folder); - } - else - { - // File name is of zero length (null). - JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_UNABLE_TO_CREATE_FOLDER_WARNDIRNAME')); + JLog::add('MediaControllerFolder.create() is deprecated. Use MediaControllerMedialistCreate instead.', JLog::WARNING, 'deprecated'); - return false; - } + $controller = new MediaControllerMedialistCreate; - return true; + return $controller->execute(); } } diff --git a/administrator/components/com_media/helper/media.php b/administrator/components/com_media/helper/media.php new file mode 100644 index 0000000000000..e91a527fa593d --- /dev/null +++ b/administrator/components/com_media/helper/media.php @@ -0,0 +1,42 @@ +countFiles($dir); } + + /** + * Adding submenu to Media Manager + * + * @param string $vName View name + * + * @return null + * + * @deprecated 4.0 Use JHelperMedia::addSubmenu instead + */ + public static function addSubmenu($vName) + { + JLoader::register('MediaHelperMedia', JPATH_ADMINISTRATOR . '/components/com_media/helper/media.php'); + + MediaHelperMedia::addSubmenu($vName); + } } diff --git a/administrator/components/com_media/layout/index.html b/administrator/components/com_media/layout/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/administrator/components/com_media/layout/index.html @@ -0,0 +1 @@ + diff --git a/administrator/components/com_media/layout/toolbar/copymedia.php b/administrator/components/com_media/layout/toolbar/copymedia.php new file mode 100644 index 0000000000000..f20ec4e3ddec7 --- /dev/null +++ b/administrator/components/com_media/layout/toolbar/copymedia.php @@ -0,0 +1,18 @@ + + diff --git a/administrator/components/com_media/layout/toolbar/deletemedia.php b/administrator/components/com_media/layout/toolbar/deletemedia.php new file mode 100644 index 0000000000000..9547648b81aaa --- /dev/null +++ b/administrator/components/com_media/layout/toolbar/deletemedia.php @@ -0,0 +1,18 @@ + + diff --git a/administrator/components/com_media/layout/toolbar/movemedia.php b/administrator/components/com_media/layout/toolbar/movemedia.php new file mode 100644 index 0000000000000..de5673b43959c --- /dev/null +++ b/administrator/components/com_media/layout/toolbar/movemedia.php @@ -0,0 +1,18 @@ + + diff --git a/administrator/components/com_media/layout/toolbar/newfolder.php b/administrator/components/com_media/layout/toolbar/newfolder.php new file mode 100644 index 0000000000000..76b161b58f245 --- /dev/null +++ b/administrator/components/com_media/layout/toolbar/newfolder.php @@ -0,0 +1,18 @@ + + diff --git a/administrator/components/com_media/layout/toolbar/uploadmedia.php b/administrator/components/com_media/layout/toolbar/uploadmedia.php new file mode 100644 index 0000000000000..f4baaa0fe5a52 --- /dev/null +++ b/administrator/components/com_media/layout/toolbar/uploadmedia.php @@ -0,0 +1,18 @@ + + diff --git a/administrator/components/com_media/media.php b/administrator/components/com_media/media.php index d5d39793703ed..3af0b2ba2441c 100644 --- a/administrator/components/com_media/media.php +++ b/administrator/components/com_media/media.php @@ -9,7 +9,8 @@ defined('_JEXEC') or die; -$input = JFactory::getApplication()->input; +$app = JFactory::getApplication(); +$input = $app->input; $user = JFactory::getUser(); $asset = $input->get('asset'); $author = $input->get('author'); @@ -20,13 +21,16 @@ && count($user->getAuthorisedCategories($asset, 'core.create')) == 0) && !($user->id == $author && $user->authorise('core.edit.own', $asset)))) { - return JError::raiseWarning(403, JText::_('JERROR_ALERTNOAUTHOR')); + $app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error'); + + return; } $params = JComponentHelper::getParams('com_media'); -// Load the helper class -require_once JPATH_COMPONENT_ADMINISTRATOR . '/helpers/media.php'; +// Load classes +JLoader::registerPrefix('Media', JPATH_COMPONENT); +JLoader::registerPrefix('Media', JPATH_ROOT . '/components/com_media'); // Set the path definitions $popup_upload = $input->get('pop_up', null); @@ -42,6 +46,18 @@ define('COM_MEDIA_BASE', JPATH_ROOT . '/' . $params->get($path, 'images')); define('COM_MEDIA_BASEURL', JUri::root() . $params->get($path, 'images')); -$controller = JControllerLegacy::getInstance('Media', array('base_path' => JPATH_COMPONENT_ADMINISTRATOR)); -$controller->execute($input->get('task')); -$controller->redirect(); +// Load controller helper classes +JLoader::registerPrefix('Config', JPATH_ROOT . '/components/com_config'); + +if ($input->get('controller') == '') +{ + $input->set('controller', 'media.display.media'); +} + +$controllerHelper = new ConfigControllerHelper; +$controller = $controllerHelper->parseController($app); + +$controller->prefix = 'Media'; + +// Perform the Request task +$controller->execute(); diff --git a/administrator/components/com_media/media.xml b/administrator/components/com_media/media.xml index c5423007cc692..8a5fb32bf9d1d 100644 --- a/administrator/components/com_media/media.xml +++ b/administrator/components/com_media/media.xml @@ -22,11 +22,21 @@ config.xml controller.php media.php + + controllers helpers layouts models views + + + controller + helper + layout + table + model + view language/en-GB.com_media.ini diff --git a/administrator/components/com_media/model/cms.php b/administrator/components/com_media/model/cms.php new file mode 100644 index 0000000000000..610625b2f67f5 --- /dev/null +++ b/administrator/components/com_media/model/cms.php @@ -0,0 +1,316 @@ +option)) + { + $r = null; + + if (!preg_match('/(.*)Model/i', get_class($this), $r)) + { + throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500); + } + + $this->option = 'com_' . strtolower($r[1]); + } + + // Set the view name + if (empty($this->name)) + { + if (array_key_exists('name', $config)) + { + $this->name = $config['name']; + } + else + { + $this->name = $this->getName(); + } + } + + // Set the model state + if (array_key_exists('state', $config)) + { + $this->state = $config['state']; + } + else + { + $this->state = new JObject; + } + + // Set the model dbo + if (array_key_exists('dbo', $config)) + { + $this->_db = $config['dbo']; + } + else + { + $this->_db = JFactory::getDbo(); + } + + // Register the paths for the form + $paths = $this->registerTablePaths($config); + + // Set the internal state marker - used to ignore setting state from the request + if (!empty($config['ignore_request'])) + { + $this->__state_set = true; + } + + // Set the clean cache event + if (isset($config['event_clean_cache'])) + { + $this->event_clean_cache = $config['event_clean_cache']; + } + elseif (empty($this->event_clean_cache)) + { + $this->event_clean_cache = 'onContentCleanCache'; + } + + $state = new JRegistry($config); + + parent::__construct($state); + } + + /** + * Method to get the model name + * + * The model name. By default parsed using the classname or it can be set + * by passing a $config['name'] in the class constructor + * + * @return string The name of the model + * + * @since 3.5 + * @throws Exception + */ + public function getName() + { + if (empty($this->name)) + { + $r = null; + + if (!preg_match('/Model(.*)/i', get_class($this), $r)) + { + throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500); + } + + $this->name = strtolower($r[1]); + } + + return $this->name; + } + + /** + * Method to get model state variables + * + * @return object The property where specified, the state object where omitted + * + * @since 3.5 + */ + public function getState() + { + if (!$this->__state_set) + { + // Protected method to auto-populate the model state. + $this->populateState(); + + // Set the model state set flag to true. + $this->__state_set = true; + } + + return $this->state; + } + + /** + * Method to get a table object, load it if necessary. + * + * @param string $name The table name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $options Configuration array for model. Optional. + * + * @return JTable A JTable object + * + * @since 3.5 + * @throws Exception + */ + public function getTable($name = '', $prefix = 'Table', $options = array()) + { + if (empty($name)) + { + $name = $this->getName(); + } + + if ($table = $this->_createTable($name, $prefix, $options)) + { + return $table; + } + + throw new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_TABLE_NAME_NOT_SUPPORTED', $name), 0); + } + + /** + * Method to register paths for tables + * + * @param object $config Configuration with table paths. + * + * @return object The property where specified, the state object where omitted + * + * @since 3.5 + */ + public function registerTablePaths($config = array()) + { + // Set the default view search path + if (array_key_exists('table_path', $config)) + { + $this->addTablePath($config['table_path']); + } + elseif (defined('JPATH_COMPONENT_ADMINISTRATOR')) + { + // Register the paths for the form + $paths = new SplPriorityQueue; + $paths->insert(JPATH_COMPONENT_ADMINISTRATOR . '/table', 'normal'); + + // For legacy purposes. Remove for 4.0 + $paths->insert(JPATH_COMPONENT_ADMINISTRATOR . '/tables', 'normal'); + } + } + + /** + * Clean the cache + * + * @param string $group The cache group + * @param integer $client_id The ID of the client + * + * @return void + * + * @since 3.5 + */ + protected function cleanCache($group = null, $client_id = 0) + { + $conf = JFactory::getConfig(); + $dispatcher = JEventDispatcher::getInstance(); + + $options = array( + 'defaultgroup' => ($group) ? $group : (isset($this->option) ? $this->option : JFactory::getApplication()->input->get('option')), + 'cachebase' => ($client_id) ? JPATH_ADMINISTRATOR . '/cache' : $conf->get('cache_path', JPATH_SITE . '/cache')); + + $cache = JCache::getInstance('callback', $options); + $cache->clean(); + + // Trigger the onContentCleanCache event. + $dispatcher->trigger($this->event_clean_cache, $options); + } + + /** + * Method to auto-populate the model state. + * + * This method should only be called once per instantiation and is designed + * to be called on the first call to the getState() method unless the model + * configuration flag to ignore the request is set. + * + * @return void + * + * @note Calling getState in this method will result in recursion. + * @since 3.5 + */ + protected function populateState() + { + $this->loadState(); + } + + /** + * Method to test whether a record can be deleted. + * + * @param object $record A record object. + * + * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. + * + * @since 3.5 + */ + protected function canDelete($record) + { + if (!empty($record->id)) + { + if ($record->published != -2) + { + return; + } + + $user = JFactory::getUser(); + + return $user->authorise('core.delete', $this->option); + } + } + + /** + * Method to test whether a record can have its state changed. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 3.5 + */ + protected function canEditState($record) + { + $user = JFactory::getUser(); + + return $user->authorise('core.edit.state', $this->option); + } +} diff --git a/administrator/components/com_media/model/cmsitem.php b/administrator/components/com_media/model/cmsitem.php new file mode 100644 index 0000000000000..a57aa45096083 --- /dev/null +++ b/administrator/components/com_media/model/cmsitem.php @@ -0,0 +1,774 @@ +event_after_delete = $config['event_after_delete']; + } + elseif (empty($this->event_after_delete)) + { + $this->event_after_delete = 'onContentAfterDelete'; + } + + if (isset($config['event_after_save'])) + { + $this->event_after_save = $config['event_after_save']; + } + elseif (empty($this->event_after_save)) + { + $this->event_after_save = 'onContentAfterSave'; + } + + if (isset($config['event_before_delete'])) + { + $this->event_before_delete = $config['event_before_delete']; + } + elseif (empty($this->event_before_delete)) + { + $this->event_before_delete = 'onContentBeforeDelete'; + } + + if (isset($config['event_before_save'])) + { + $this->event_before_save = $config['event_before_save']; + } + elseif (empty($this->event_before_save)) + { + $this->event_before_save = 'onContentBeforeSave'; + } + + if (isset($config['event_change_state'])) + { + $this->event_change_state = $config['event_change_state']; + } + elseif (empty($this->event_change_state)) + { + $this->event_change_state = 'onContentChangeState'; + } + + // Guess the JText message prefix. Defaults to the option. + if (isset($config['text_prefix'])) + { + $this->text_prefix = strtoupper($config['text_prefix']); + } + elseif (empty($this->text_prefix)) + { + $this->text_prefix = strtoupper($this->option); + } + } + + /** + * Method to checkin a row. + * + * @param integer $pk The numeric id of the primary key. + * + * @return boolean False on failure or error, true otherwise. + * + * @since 3.5 + */ + public function checkin($pk = null) + { + // Only attempt to check the row in if it exists. + if ($pk) + { + $user = JFactory::getUser(); + + // Get an instance of the row to checkin. + $table = $this->getTable(); + + if (!$table->load($pk)) + { + $this->setError($table->getError()); + + return false; + } + + // Check if this is the user has previously checked out the row. + if ($table->checked_out > 0 && $table->checked_out != $user->get('id') && !$user->authorise('core.admin', 'com_checkin')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_CHECKIN_USER_MISMATCH')); + + return false; + } + + // Attempt to check the row in. + if (!$table->checkin($pk)) + { + $this->setError($table->getError()); + + return false; + } + } + + return true; + } + + /** + * Method to check-out a row for editing. + * + * @param integer $pk The numeric id of the primary key. + * + * @return boolean False on failure or error, true otherwise. + * + * @since 3.5 + */ + public function checkout($pk = null) + { + // Only attempt to check the row in if it exists. + if ($pk) + { + $user = JFactory::getUser(); + + // Get an instance of the row to checkout. + $table = $this->getTable(); + + if (!$table->load($pk)) + { + $this->setError($table->getError()); + + return false; + } + + // Check if this is the user having previously checked out the row. + if ($table->checked_out > 0 && $table->checked_out != $user->get('id')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_CHECKOUT_USER_MISMATCH')); + + return false; + } + + // Attempt to check the row out. + if (!$table->checkout($user->get('id'), $pk)) + { + $this->setError($table->getError()); + + return false; + } + } + + return true; + } + + /** + * Abstract method for getting the form from the model. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * + * @return mixed A JForm object on success, false on failure + * + * @since 3.5 + */ + public function getForm($data = array(), $loadData = true) + { + } + + /** + * Method to get a store id based on model configuration state. + * + * This is necessary because the model is used by the component and + * different modules that might need different sets of data or different + * ordering requirements. + * + * @param string $id A prefix for the store id. + * + * @return string A store id. + * + * @since 3.5 + */ + protected function getStoreId($id = '') + { + // Compile the store id. + return md5($id); + } + + /** + * Method to auto-populate the model state. + * + * @return void + * + * @note Calling getState in this method will result in recursion. + * @since 3.5 + */ + protected function populateState() + { + } + + /** + * Method to get an object. This only works for content types registered in the content_type table. + * + * @param integer $id The id of the object to get. + * + * @return mixed Object on success, false on failure. + */ + public function getItem($id = null) + { + if (empty($this->item)) + { + $table = $this->getTable(); + $tableClassName = get_class($table); + + $this->item = false; + $contentType = new JUcmType; + $type = $contentType->getTypeByTable($tableClassName); + + // Deal with examples where thre is no row in type table? + if (empty($id)) + { + $id = $this->getState($type, 'id'); + } + + $prefix = $this->getState($table, 'prefix'); + $typeTable = $type->table; + $typeTable = json_decode($typeTable); + + // Check to see if special exists .. if it doesn't use common + if (!empty($typeTable->special)) + { + $table = JTable::getInstance($typeTable->special->type, $typeTable->special->prefix); + } + else + { + if (empty($typeTable->common)) + { + // Should there be an exception here? + + return; + } + + $table = JTable::getInstance($typeTable->common->type, $typeTable->common->prefix); + } + + // Attempt to load the row. + if ($table->load($id)) + { + // Convert the JTable to a clean object. + $properties = $table->getProperties(1); + $this->item = JArrayHelper::toObject($properties); + } + elseif ($error = $table->getError()) + { + $this->setError($error); + } + } + + return $this->item; + } + + /** + * Returns a reference to the a Table object, always creating it. + * + * @param string $name The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $options Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 3.5 + */ + public function getTable($name = '', $prefix = 'Table', $options = array()) + { + return JTable::getInstance($name, $prefix, $options); + } + + /** + * Method to increment the hit counter for the weblink + * + * @param integer $id Optional ID of the weblink. + * + * @return boolean True on success + * + * @since 3.5 + */ + public function hit($id = null) + { + if (empty($id)) + { + $id = $this->getState($type . 'id'); + } + + $item = $this->getTable($type, $prefix); + + return $item->hit($id); + } + + /** + * Method to delete one or more records. + * + * @param mixed &$pks A primary key or array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 3.5 + */ + public function delete(&$pks) + { + if (empty($pks)) + { + throw new RuntimeException('No record selected', 404); + } + + $table = $this->getTable(); + $tableName = $table->getTableName(); + $key = $table->getKeyName(); + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + + $query->delete($db->quoteName($tableName)); + + if (!is_array($pks)) + { + $query->where($db->setQuery($key) . ' = ' . $pk); + } + else + { + $pksImploded = implode(',', $pks); + $query->where($db->quoteName($key) . ' IN (' . $pksImploded . ')'); + } + + $db->setQuery($query); + + try + { + $result = $db->execute(); + } + catch (Exception $e) + { + throw new RuntimeException('Error in query', 404); + } + + if ($result && $db->getAffectedRows()) + { + $app = JFactory::getApplication(); + $app->setHeader('status', '204 Deleted'); + + return true; + } + elseif ($result) + { + throw new RuntimeException('Record Not Found', 404); + } + else + { + throw new RuntimeException('Delete failed', 500); + } + } + + /** + * Prepare and sanitise the table data prior to saving. + * + * @param JTable $table A reference to a JTable object. + * + * @return void + * + * @since 3.5 + */ + protected function prepareTable($table) + { + // Derived class will provide its own implementation if required. + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success, False on error. + * + * @since 3.5 + */ + public function save($data) + { + $dispatcher = JEventDispatcher::getInstance(); + $table = $this->getTable(); + + if ((!empty($data['tags']) && $data['tags'][0] != '')) + { + $table->newTags = $data['tags']; + } + + $key = $table->getKeyName(); + $pk = (!empty($data[$key])) ? $data[$key] : (int) $this->getState($this->getName() . '.id'); + $isNew = true; + + // Include the content plugins for the on save events. + JPluginHelper::importPlugin('content'); + + // Allow an exception to be thrown. + try + { + // Load the row if saving an existing record. + if ($pk > 0) + { + $table->load($pk); + $isNew = false; + } + + // Bind the data. + if (!$table->bind($data)) + { + $this->setError($table->getError()); + + return false; + } + + // Prepare the row for saving + $this->prepareTable($table); + + // Check the data. + if (!$table->check()) + { + $this->setError($table->getError()); + + return false; + } + + // Trigger the onContentBeforeSave event. + $result = $dispatcher->trigger($this->event_before_save, array($this->option . '.' . $this->name, $table, $isNew)); + + if (in_array(false, $result, true)) + { + $this->setError($table->getError()); + + return false; + } + + // Store the data. + if (!$table->store()) + { + $this->setError($table->getError()); + + return false; + } + + // Clean the cache. + $this->cleanCache(); + + // Trigger the onContentAfterSave event. + $dispatcher->trigger($this->event_after_save, array($this->option . '.' . $this->name, $table, $isNew)); + } + catch (Exception $e) + { + + JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error'); + + return false; + } + + return true; + } + + /** + * Method to get a form object. + * + * @param string $name The name of the form. + * @param string $source The form source. Can be XML string if file flag is set to false. + * @param array $options Optional array of options for the form creation. + * @param boolean $clear Optional argument to force load a new form. + * @param string $xpath An optional xpath to search for the fields. + * + * @return mixed JForm object on success, False on error. + * + * @see JForm + * @since 3.5 + */ + protected function loadForm($name, $source = null, $options = array(), $clear = false, $xpath = false) + { + // Handle the optional arguments. + $options['control'] = JArrayHelper::getValue($options, 'control', false); + + // Create a signature hash. + $hash = sha1($source . serialize($options)); + + // Check if we can use a previously loaded form. + if (isset($this->_forms[$hash]) && !$clear) + { + return $this->_forms[$hash]; + } + + // Get the form. + // Register the paths for the form -- failing here + $paths = new SplPriorityQueue; + $paths->insert(JPATH_COMPONENT . '/model/form', 'normal'); + $paths->insert(JPATH_COMPONENT . '/model/field', 'normal'); + $paths->insert(JPATH_COMPONENT . '/model/rule', 'normal'); + + // Legacy support to be removed in 4.0. -- failing here + $paths->insert(JPATH_COMPONENT . '/models/forms', 'normal'); + $paths->insert(JPATH_COMPONENT . '/models/fields', 'normal'); + $paths->insert(JPATH_COMPONENT . '/models/rules', 'normal'); + + // Test -- prob with previous -- tempory solution + JForm::addFormPath(JPATH_COMPONENT . '/models/forms'); + JForm::addFieldPath(JPATH_COMPONENT . '/models/fields'); + JForm::addFormPath(JPATH_COMPONENT . '/model/form'); + JForm::addFieldPath(JPATH_COMPONENT . '/model/field'); + + try + { + $form = JForm::getInstance($name, $source, $options, false, $xpath); + + if (isset($options['load_data']) && $options['load_data']) + { + // Get the data for the form. + $data = $this->loadFormData(); + } + else + { + $data = array(); + } + + // Allow for additional modification of the form, and events to be triggered. + // We pass the data because plugins may require it. + $this->preprocessForm($form, $data); + + // Load the data into the form after the plugins have operated. + $form->bind($data); + } + catch (Exception $e) + { + + $app = JFactory::getApplication(); + $app->enqueueMessage($e->getMessage()); + + return false; + } + + // Store the form for later. + $this->_forms[$hash] = $form; + + return $form; + } + + /** + * Method to get the data that should be injected in the form. + * + * @return array The default data is an empty array. + * + * @since 3.5 + */ + protected function loadFormData() + { + return array(); + } + + /** + * Method to allow derived classes to preprocess the data. + * + * @param string $context The context identifier. + * @param mixed &$data The data to be processed. It gets altered directly. + * + * @return void + * + * @since 3.5 + */ + protected function preprocessData($context, &$data) + { + // Get the dispatcher and load the users plugins. + $dispatcher = JEventDispatcher::getInstance(); + JPluginHelper::importPlugin('content'); + + // Trigger the data preparation event. + $results = $dispatcher->trigger('onContentPrepareData', array($context, $data)); + + // Check for errors encountered while preparing the data. + if (count($results) > 0 && in_array(false, $results, true)) + { + $this->setError($dispatcher->getError()); + } + } + + /** + * Method to allow derived classes to preprocess the form. + * + * @param JForm $form A JForm object. + * @param mixed $data The data expected for the form. + * @param string $group The name of the plugin group to import (defaults to "content"). + * + * @return void + * + * @see JFormField + * @since 3.5 + * @throws Exception if there is an error in the form event. + */ + protected function preprocessForm(JForm $form, $data, $group = 'content') + { + // Import the appropriate plugin group. + JPluginHelper::importPlugin($group); + + // Get the dispatcher. + $dispatcher = JEventDispatcher::getInstance(); + + // Trigger the form preparation event. + $results = $dispatcher->trigger('onContentPrepareForm', array($form, $data)); + + // Check for errors encountered while preparing the form. + if (count($results) && in_array(false, $results, true)) + { + // Get the last error. + $error = $dispatcher->getError(); + + if (!($error instanceof Exception)) + { + throw new Exception($error); + } + } + } + + /** + * Method to validate the form data. + * + * @param JForm $form The form to validate against. + * @param array $data The data to validate. + * @param string $group The name of the field group to validate. + * + * @return mixed Array of filtered data if valid, false otherwise. + * + * @see JFormRule + * @see JFilterInput + * @since 3.5 + */ + public function validate($form, $data, $group = null) + { + // Filter and validate the form data. + $data = $form->filter($data); + $return = $form->validate($data, $group); + + // Check for an error. + if ($return instanceof Exception) + { + $this->setError($return->getMessage()); + + return false; + } + + // Check the validation results. + if ($return === false) + { + // Get the validation messages from the form. + foreach ($form->getErrors() as $message) + { + $this->setError($message); + } + + return false; + } + + return $data; + } + + /** + * Method to change the title & alias. + * + * @param integer $category_id The id of the category. + * @param string $alias The alias. + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + * @since 3.5 + */ + protected function generateNewTitle($category_id, $alias, $title) + { + // Alter the title & alias + $table = $this->getTable(); + + while ($table->load(array('alias' => $alias, 'catid' => $category_id))) + { + $title = JString::increment($title); + $alias = JString::increment($alias, 'dash'); + } + + return array($title, $alias); + } +} diff --git a/administrator/components/com_media/model/cmslist.php b/administrator/components/com_media/model/cmslist.php new file mode 100644 index 0000000000000..b69ab60a5fc67 --- /dev/null +++ b/administrator/components/com_media/model/cmslist.php @@ -0,0 +1,649 @@ +filter_fields = $config['filter_fields']; + } + + // Guess the context as Option.ModelName. + if (empty($this->context)) + { + $this->context = strtolower($this->option . '.' . $this->getName()); + } + } + + /** + * Method to cache the last query constructed. + * + * This method ensures that the query is constructed only once for a given state of the model. + * + * @return JDatabaseQuery A JDatabaseQuery object + * + * @since 3.5 + */ + protected function _getListQuery() + { + // Capture the last store id used. + static $lastStoreId; + + // Compute the current store id. + $currentStoreId = $this->getStoreId(); + + // If the last store id is different from the current, refresh the query. + if ($lastStoreId != $currentStoreId || empty($this->query)) + { + $lastStoreId = $currentStoreId; + $this->query = $this->getListQuery(); + } + + return $this->query; + } + + /** + * Method to get a JDatabaseQuery object for retrieving the data set from a database. + * + * @return JDatabaseQuery A JDatabaseQuery object to retrieve the data set. + * + * @since 3.5 + */ + protected function getListQuery() + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + + return $query; + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + * + * @since 3.5 + */ + public function getItems() + { + // Get a storage key. + $store = $this->getStoreId(); + + // Try to load the data from internal storage. + if (isset($this->cache[$store])) + { + return $this->cache[$store]; + } + + // Load the list items. + $query = $this->getListQuery(); + + try + { + $items = $this->getList($query, $this->getStart(), $this->state->get('list.limit')); + } + catch (RuntimeException $e) + { + $app = JFactory::getApplication(); + $app->enqueueMessage($e->getMessage(), 'error'); + + return false; + } + + // Add the items to the internal cache. + $this->cache[$store] = $items; + + return $this->cache[$store]; + } + + /** + * Method to get a JPagination object for the data set. + * + * @return JPagination A JPagination object for the data set. + * + * @since 3.5 + */ + public function getPagination() + { + // Get a storage key. + $store = $this->getStoreId('getPagination'); + + // Try to load the data from internal storage. + if (isset($this->cache[$store])) + { + return $this->cache[$store]; + } + + // Create the pagination object. + $limit = (int) $this->state->get('list.limit') - (int) $this->state->get('list.links'); + $page = new JPagination($this->getTotal(), $this->getStart(), $limit); + + // Add the object to the internal cache. + $this->cache[$store] = $page; + + return $this->cache[$store]; + } + + /** + * Method to get a store id based on the model configuration state. + * + * This is necessary because the model is used by the component and + * different modules that might need different sets of data or different + * ordering requirements. + * + * @param string $id An identifier string to generate the store id. + * + * @return string A store id. + * + * @since 3.5 + */ + protected function getStoreId($id = '') + { + // Add the list state to the store id. + $id .= ':' . $this->state->get('list.start'); + $id .= ':' . $this->state->get('list.limit'); + $id .= ':' . $this->state->get('list.ordering'); + $id .= ':' . $this->state->get('list.direction'); + + return md5($this->context . ':' . $id); + } + + /** + * Method to get the total number of items for the data set. + * + * @return integer The total number of items available in the data set. + * + * @since 3.5 + */ + public function getTotal() + { + // Get a storage key. + $store = $this->getStoreId('getTotal'); + + // Try to load the data from internal storage. + if (isset($this->cache[$store])) + { + return $this->cache[$store]; + } + + // Load the total. + $query = $this->getListQuery(); + + try + { + $total = (int) $this->getListCount($query); + } + catch (RuntimeException $e) + { + $app = JFactory::getApplication(); + $app->enqueueMessage($e->getMessage(), 'error'); + + return false; + } + + // Add the total to the internal cache. + $this->cache[$store] = $total; + + return $this->cache[$store]; + } + + /** + * Method to get the starting number of items for the data set. + * + * @return integer The starting number of items available in the data set. + * + * @since 3.5 + */ + public function getStart() + { + $store = $this->getStoreId('getstart'); + + // Try to load the data from internal storage. + if (isset($this->cache[$store])) + { + return $this->cache[$store]; + } + + $start = $this->state->get('list.start'); + $limit = $this->state->get('list.limit'); + $total = $this->getTotal(); + + if ($start > $total - $limit) + { + $start = max(0, (int) (ceil($total / $limit) - 1) * $limit); + } + + // Add the total to the internal cache. + $this->cache[$store] = $start; + + return $this->cache[$store]; + } + + /** + * Method to auto-populate the model state. + * + * This method should only be called once per instantiation and is designed + * to be called on the first call to the getState() method unless the model + * configuration flag to ignore the request is set. + * + * Note. Calling getState in this method will result in recursion. + * + * @param string $ordering An optional ordering field. + * @param string $direction An optional direction (asc|desc). + * + * @return void + * + * @since 3.5 + */ + protected function populateState($ordering = null, $direction = null) + { + // If the context is set, assume that stateful lists are used. + if ($this->context) + { + $app = JFactory::getApplication(); + + $value = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->getCfg('list_limit'), 'uint'); + $limit = $value; + $this->state->set('list.limit', $limit); + + $value = $app->getUserStateFromRequest($this->context . '.limitstart', 'limitstart', 0); + $limitstart = ($limit != 0 ? (floor($value / $limit) * $limit) : 0); + $this->state->set('list.start', $limitstart); + + // Check if the ordering field is in the white list, otherwise use the incoming value. + $value = $app->getUserStateFromRequest($this->context . '.ordercol', 'filter_order', $ordering); + + if (!in_array($value, $this->filter_fields)) + { + $value = $ordering; + $app->setUserState($this->context . '.ordercol', $value); + } + + $this->state->set('list.ordering', $value); + + // Check if the ordering direction is valid, otherwise use the incoming value. + $value = $app->getUserStateFromRequest($this->context . '.orderdirn', 'filter_order_Dir', $direction); + + if (!in_array(strtoupper($value), array('ASC', 'DESC', ''))) + { + $value = $direction; + $app->setUserState($this->context . '.orderdirn', $value); + } + + $this->state->set('list.direction', $value); + } + else + { + $this->state->set('list.start', 0); + $this->state->set('list.limit', 0); + } + } + + /** + * Gets the value of a user state variable and sets it in the session + * + * This is the same as the method in JApplication except that this also can optionally + * force you back to the first page when a filter has changed + * + * @param string $key The key of the user state variable. + * @param string $request The name of the variable passed in a request. + * @param string $default The default value for the variable if not found. Optional. + * @param string $type Filter for the variable, for valid values see {@link JFilterInput::clean()}. Optional. + * @param boolean $resetPage If true, the limitstart in request is set to zero + * + * @return The request user state. + * + * @since 3.5 + */ + public function getUserStateFromRequest($key, $request, $default = null, $type = 'none', $resetPage = true) + { + $app = JFactory::getApplication(); + $input = $app->input; + $old_state = $app->getUserState($key); + $cur_state = (!is_null($old_state)) ? $old_state : $default; + $new_state = $input->get($request, null, $type); + + if (($cur_state != $new_state) && ($resetPage)) + { + $input->set('limitstart', 0); + } + + // Save the new value only if it is set in this request. + if ($new_state !== null) + { + $app->setUserState($key, $new_state); + } + else + { + $new_state = $cur_state; + } + + return $new_state; + } + + /** + * Gets an array of objects from the results of database query. + * + * @param string $query The query. + * @param integer $limitstart Offset. + * @param integer $limit The number of records. + * + * @return array An array of results. + * + * @since 3.5 + * @throws RuntimeException + */ + protected function getList($query, $limitstart = 0, $limit = 0) + { + $this->db->setQuery($query, $limitstart, $limit); + $result = $this->db->loadObjectList(); + + return $result; + } + + /** + * Returns a record count for the query. + * + * @param JDatabaseQuery|string $query The query. + * + * @return integer Number of rows for query. + * + * @since 3.5 + */ + protected function getListCount($query) + { + // Use fast COUNT(*) on JDatabaseQuery objects if there no GROUP BY or HAVING clause: + if ($query instanceof JDatabaseQuery + && $query->type == 'select' + && $query->group === null + && $query->having === null) + { + $query = clone $query; + $query->clear('select')->clear('order')->select('COUNT(*)'); + + $this->_db->setQuery($query); + + return (int) $this->_db->loadResult(); + } + + // Otherwise fall back to inefficient way of counting all results. + $this->_db->setQuery($query); + $this->_db->execute(); + + return (int) $this->_db->getNumRows(); + } + + /** + * Method override to check-in a record or an array of record + * + * @param mixed $pks The ID of the primary key or an array of IDs + * + * @return mixed Boolean false if there is an error, otherwise the count of records checked in. + * + * @since 3.5 + */ + public function checkin($pks = array()) + { + $pks = (array) $pks; + $table = $this->getTable(); + $count = 0; + + if (empty($pks)) + { + $pks = array((int) $this->getState($this->getName() . '.id')); + } + + // Check in all items. + foreach ($pks as $pk) + { + if ($table->load($pk)) + { + if ($table->checked_out > 0) + { + if (!parent::checkin($pk)) + { + return false; + } + + $count++; + } + } + else + { + $this->setError($table->getError()); + + return false; + } + } + + return $count; + } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since 3.5 + */ + public function publish(&$pks, $value = 1) + { + $dispatcher = JEventDispatcher::getInstance(); + $user = JFactory::getUser(); + $table = $this->getTable(); + $pks = (array) $pks; + + // Include the content plugins for the change of state event. + JPluginHelper::importPlugin('content'); + + // Access checks. + foreach ($pks as $i => $pk) + { + $table->reset(); + + if ($table->load($pk)) + { + if (!$this->canEditState($table)) + { + // Prune items that you can't change. + unset($pks[$i]); + JLog::add(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), JLog::WARNING, 'jerror'); + + return false; + } + } + } + + // Attempt to change the state of the records. + if (!$table->publish($pks, $value, $user->get('id'))) + { + $this->setError($table->getError()); + + return false; + } + + $context = $this->option . '.' . $this->name; + + // Trigger the onContentChangeState event. + $result = $dispatcher->trigger($this->event_change_state, array($context, $pks, $value)); + + if (in_array(false, $result, true)) + { + $this->setError($table->getError()); + + return false; + } + + // Clear the component's cache + $this->cleanCache(); + + return true; + } + + /** + * Saves the manually set order of records. + * + * @param array $pks An array of primary key ids. + * @param integer $order +1 or -1 + * + * @return mixed + * + * @since 3.5 + */ + public function saveorder($pks = null, $order = null) + { + $table = $this->getTable(); + $tableClassName = get_class($table); + $contentType = new JUcmType; + $type = $contentType->getTypeByTable($tableClassName); + + if ($type) + { + $typeAlias = $type->type_alias; + $tagsObserver = $table->getObserverOfClass('JTableObserverTags'); + } + + $conditions = array(); + + if (empty($pks)) + { + return JError::raiseWarning(500, JText::_($this->text_prefix . '_ERROR_NO_ITEMS_SELECTED')); + } + + // Update ordering values + foreach ($pks as $i => $pk) + { + $table->load((int) $pk); + + // Access checks. + if (!$this->canEditState($table)) + { + // Prune items that you can't change. + unset($pks[$i]); + JLog::add(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), JLog::WARNING, 'jerror'); + } + elseif ($table->ordering != $order[$i]) + { + $table->ordering = $order[$i]; + + if ($type && !empty($typeAlias)) + { + $this->createTagsHelper($tagsObserver, $type, $pk, $typeAlias, $table); + } + + if (!$table->store()) + { + $this->setError($table->getError()); + + return false; + } + + // Remember to reorder within position and client_id + $condition = $this->getReorderConditions($table); + $found = false; + + foreach ($conditions as $cond) + { + if ($cond[1] == $condition) + { + $found = true; + break; + } + } + + if (!$found) + { + $key = $table->getKeyName(); + $conditions[] = array($table->$key, $condition); + } + } + } + + // Execute reorder for each category. + foreach ($conditions as $cond) + { + $table->load($cond[0]); + $table->reorder($cond[1]); + } + + // Clear the component's cache + $this->cleanCache(); + + return true; + } + + /** + * A protected method to get a set of ordering conditions. + * + * @param JTable $table A JTable object. + * + * @return array An array of conditions to add to ordering queries. + * + * @since 3.5 + */ + protected function getReorderConditions($table) + { + return array(); + } +} diff --git a/administrator/components/com_media/model/editor.php b/administrator/components/com_media/model/editor.php new file mode 100644 index 0000000000000..460b2e760e81a --- /dev/null +++ b/administrator/components/com_media/model/editor.php @@ -0,0 +1,698 @@ +getTable(); + + if (!$table->load($pk)) + { + $app->enqueueMessage($table->getError(), 'error'); + + return false; + } + + // Check if this is the user has previously checked out the row. + if ($table->core_checked_out_user_id > 0 && $table->core_checked_out_user_id != $user->get('id') && !$user->authorise('core.admin', 'com_checkin')) + { + $app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_CHECKIN_USER_MISMATCH'), 'error'); + + return false; + } + + // Attempt to check the row in. + if (!$table->checkin($pk)) + { + $app->enqueueMessage($table->getError(), 'error'); + + return false; + } + } + + return true; + } + + /** + * Method to check-out a row for editing in #__ucm_content. + * + * @param integer $pk The numeric id of the primary key. + * + * @return boolean False on failure or error, true otherwise. + * + * @since 3.5 + */ + public function checkout($pk = null) + { + // Only attempt to check the row in if it exists. + if ($pk) + { + $user = JFactory::getUser(); + $app = JFactory::getApplication(); + + // Get an instance of the row to checkout. + $table = $this->getTable(); + + if (!$table->load($pk)) + { + $app->enqueueMessage($table->getError(), 'error'); + + return false; + } + + // Check if this is the user having previously checked out the row. + if ($table->core_checked_out_user_id > 0 && $table->core_checked_out_user_id != $user->get('id')) + { + $app->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_CHECKOUT_USER_MISMATCH'), 'error'); + + return false; + } + + // Attempt to check the row out. + if (!$table->checkout($user->get('id'), $pk)) + { + $app->enqueueMessage($table->getError(), 'error'); + + return false; + } + } + + return true; + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return mixed Object on success, false on failure. + * + * @since 3.5 + */ + public function getItem($pk = null) + { + $input = JFactory::getApplication()->input; + $pk = (!empty($pk)) ? $pk :$input->get('id'); + + if (!isset($this->item)) + { + // Get a row instance. + $table = $this->getTable(); + + // Attempt to load the row. + $return = $table->load($pk); + + // Check for a table object error. + if ($return === false && $table->getError()) + { + throw new Exception($table->getError()); + + return false; + } + + // Convert to the JObject before adding other data. + $properties = $table->getProperties(1); + $this->item = JArrayHelper::toObject($properties); + + // Convert the params field to an array. + $registry = new JRegistry; + $registry->loadString($table->core_params); + $this->item->core_params = $registry->toArray(); + + if (!empty($this->item->core_content_id)) + { + // Overriding getTagIds in JHelperTags + $this->item->tags = $this->getTagIds($this->item->core_content_id, $this->item->core_type_alias); + } + } + + return $this->item; + } + + /** + * Returns a reference to the a Table object, always creating it. + * + * @param type $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + * + * @since 3.5 + */ + public function getTable($type = 'Media', $prefix = 'MediaTable', $config = array()) + { + return JTable::getInstance($type, $prefix, $config); + } + + /** + * Abstract method for getting the form from the model. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * + * @return mixed A JForm object on success, false on failure + * + * @since 3.5 + */ + public function getForm($data = array(), $loadData = true) + { + // Get the form. + $form = $this->loadForm('com_media.editor', 'image', array('control' => 'jform', 'load_data' => $loadData)); + + if (empty($form)) + { + return false; + } + + return $form; + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 3.5 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_media.edit.item.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + } + + $this->preprocessData('com_media.editor', $data); + + return $data; + } + + /** + * Update modified user and date after a change + * + * @return null + */ + private function updateData() + { + $input = JFactory::getApplication()->input; + $pk = $input->get('id'); + + $row = $this->getTable(); + $row->core_content_id = $pk; + + $row->store(); + } + + /** + * Auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @return void + * + * @since 3.5 + */ + protected function populateState() + { + $app = JFactory::getApplication(); + + $id = isset($this->id) && $this->id != 0 ? $this->id : $app->input->getInt('id'); + + $this->state->set('core_content_id', $id); + + // Load the parameters. + $params = JComponentHelper::getParams('com_media'); + $this->state->set('core_params', $params); + } + + /** + * Get the necessary data to load an item help screen. + * + * @return object An object with key, url, and local properties for loading the item help screen. + * + * @since 3.5 + */ + public function getHelp() + { + return (object) array('key' => $this->helpKey, 'url' => $this->helpURL); + } + + /** + * Custom clean cache method, plugins are cached in 2 places for different clients + * + * @param string $group Group + * @param int $client_id Id of the client + * + * @return null + * + * @since 3.5 + */ + protected function cleanCache($group = null, $client_id = 0) + { + parent::cleanCache('com_media'); + } + + /** + * Method to get model state variables + * + * @param string $property Property to retrieve + * @param string $default Default value + * + * @return object The property where specified, the state object where omitted + * + * @since 3.5 + */ + public function getState($property = null, $default = null) + { + static $set; + + if (!$set) + { + $input = JFactory::getApplication()->input; + + $folder = $input->get('folder', '', 'path'); + $this->state->set('folder', $folder); + + $fieldid = $input->get('fieldid', ''); + $this->state->set('field.id', $fieldid); + + $parent = str_replace("\\", "/", dirname($folder)); + $parent = ($parent == '.') ? null : $parent; + $this->state->set('parent', $parent); + $set = true; + } + + if (!$property) + { + return parent::getState(); + } + else + { + return parent::getState()->get($property, $default); + } + } + + /** + * Get an image address, height and width. + * + * @return array an associative array containing image address, height and width. + * + * @since 3.5 + */ + public function getImage() + { + $app = JFactory::getApplication(); + $fileName = $app->input->get('file'); + $folder = $app->input->get('folder', '', 'path'); + $path = JPath::clean(COM_MEDIA_BASE . '/'); + $uri = COM_MEDIA_BASEURL . '/'; + + if (!empty($folder)) + { + $path = JPath::clean(COM_MEDIA_BASE . '/' . $folder . '/'); + $uri = COM_MEDIA_BASEURL . '/' . $folder . '/'; + } + + if (file_exists(JPath::clean($path . $fileName))) + { + $JImage = new JImage(JPath::clean($path . $fileName)); + $image['address'] = $uri . $fileName; + $image['path'] = $fileName; + $image['height'] = $JImage->getHeight(); + $image['width'] = $JImage->getWidth(); + } + else + { + $app->enqueueMessage(JText::_('COM_MEDIA_ERROR_IMAGE_FILE_NOT_FOUND'), 'error'); + + return false; + } + + return $image; + } + + /** + * Crop an image. + * + * @param int $id The id of the entry + * @param string $w Width. + * @param string $h Height. + * @param string $x x-coordinate. + * @param string $y y-coordinate. + * + * @return boolean true if image cropped successfully, false otherwise. + * + * @since 3.5 + */ + public function cropImage($id, $w, $h, $x, $y) + { + $app = JFactory::getApplication(); + $table = $this->getTable(); + $table->load($id); + $file = $this->resolveDuplicateFilename(JPATH_ROOT . $table->core_urls); + + $JImage = new JImage($file); + + try + { + $image = $JImage->crop($w, $h, $x, $y, true); + $image->toFile($file); + + $this->updateData(); + + return true; + } + catch (Exception $e) + { + $app->enqueueMessage($e->getMessage(), 'error'); + } + } + + /** + * Resize an image. + * + * @param int $id The id of the entry + * @param string $width The new width of the image. + * @param string $height The new height of the image. + * + * @return boolean true if image resize successful, false otherwise. + * + * @since 3.5 + */ + public function resizeImage($id, $width, $height) + { + $app = JFactory::getApplication(); + $table = $this->getTable(); + $table->load($id); + $file = $this->resolveDuplicateFilename(JPATH_ROOT . $table->core_urls); + + $JImage = new JImage($file); + + try + { + $image = $JImage->resize($width, $height, true, 1); + $image->toFile($file); + + $this->updateData(); + + return true; + } + catch (Exception $e) + { + $app->enqueueMessage($e->getMessage(), 'error'); + } + } + + /** + * Rotate an image. + * + * @param int $id The id of the entry + * @param string $angle The new angle of the image. + * + * @return boolean true if image rotate successful, false otherwise. + * + * @since 3.5 + */ + public function rotateImage($id, $angle) + { + $app = JFactory::getApplication(); + $table = $this->getTable(); + $table->load($id); + $file = $this->resolveDuplicateFilename(JPATH_ROOT . $table->core_urls); + + $JImage = new JImage($file); + + try + { + $image = $JImage->rotate($angle, -1, false); + $image->toFile($file); + + $this->updateData(); + + return true; + } + catch (Exception $e) + { + $app->enqueueMessage($e->getMessage(), 'error'); + } + } + + /** + * Flip an image. + * + * @param int $id The id of the entry + * @param string $mode The flipping mode of the image. + * + * @return boolean true if image flip successful, false otherwise. + * + * @since 3.5 + */ + public function flipImage($id, $mode) + { + $app = JFactory::getApplication(); + $table = $this->getTable(); + $table->load($id); + $file = $this->resolveDuplicateFilename(JPATH_ROOT . $table->core_urls); + + $JImage = new JImage($file); + + try + { + $image = $JImage->flip($mode, true); + $image->toFile($file); + + $this->updateData(); + + return true; + } + catch (Exception $e) + { + $app->enqueueMessage($e->getMessage(), 'error'); + } + } + + /** + * Generating thumbs an image. + * + * @param int $id The id of the entry + * @param mixed $sizes The thumbnail sizes as a string or an array + * @param int $creationMethod The thumbnail creation method + * @param string $thumbsFolder The folder to save thumbnails + * + * @return boolean true if image generating thumbs successful, false otherwise. + * + * @since 3.5 + */ + public function createThumbs($id, $sizes, $creationMethod = JImage::SCALE_INSIDE, $thumbsFolder = null) + { + $app = JFactory::getApplication(); + $table = $this->getTable(); + $table->load($id); + $file = $this->resolveDuplicateFilename(JPATH_ROOT . $table->core_urls); + + $JImage = new JImage($file); + + try + { + $image = $JImage->createThumbs($sizes, $creationMethod, $thumbsFolder); + + return true; + } + catch (Exception $e) + { + $app->enqueueMessage($e->getMessage(), 'error'); + } + } + + /** + * Filter an image. + * + * @param int $id The id of the entry + * @param string $filter The new filter for the image. + * @param string $value The filter value only use in brightness, contrast and smooth filters. + * + * @return boolean true if image filtering successful, false otherwise. + * + * @since 3.5 + */ + public function filterImage($id, $filter, $value = null) + { + $app = JFactory::getApplication(); + $table = $this->getTable(); + $table->load($id); + $file = $this->resolveDuplicateFilename(JPATH_ROOT . $table->core_urls); + + $options = array_fill(0, 11, 0); + + if (!empty($value)) + { + $key = constant('IMG_FILTER_' . strtoupper($filter)); + $options[$key] = $value; + } + + $JImage = new JImage($file); + + try + { + $image = $JImage->filter($filter, $options); + $image->toFile($file); + + $this->updateData(); + + return true; + } + catch (Exception $e) + { + $app->enqueueMessage($e->getMessage(), 'error'); + } + } + + /** + * Method to get a list of tags for a given core content item. + * Normally used for displaying a list of tags within a layout + * This replaces the JHelperTags::getTagIds because it uses core_content_id + * + * @param mixed $ids The id or array of ids (primary key) of the item to be tagged. + * @param string $prefix Dot separated string with the option and view to be used for a url. + * + * @return string Comma separated list of tag Ids. + * + * @since 3.5 + */ + public function getTagIds($ids, $prefix) + { + if (empty($ids)) + { + return; + } + + /** + * Ids possible formats: + * --------------------- + * $id = 1; + * $id = array(1,2); + * $id = array('1,3,4,19'); + * $id = '1,3'; + */ + $ids = (array) $ids; + $ids = implode(',', $ids); + $ids = explode(',', $ids); + JArrayHelper::toInteger($ids); + + $db = JFactory::getDbo(); + + // Load the tags. + $query = $db->getQuery(true) + ->select($db->quoteName('t.id')) + ->from($db->quoteName('#__tags') . ' AS ' . $db->quoteName('t')) + ->join( + 'INNER', $db->quoteName('#__contentitem_tag_map') . ' AS m' + . ' ON ' . $db->quoteName('m.tag_id') . ' = ' . $db->quoteName('t.id') + + . ' AND ' . $db->quoteName('m.core_content_id') . ' IN ( ' . implode(',', $ids) . ')' + ); + + $db->setQuery($query); + + // Add the tags to the content data. + $tagsList = $db->loadColumn(); + $this->tags = implode(',', $tagsList); + + return $this->tags; + } + + /** + * This method is to compose the duplicate file name for a given filename + * + * @param string $file Exising origin filename. eg : COM_MEDIA_BASE/foo/bar/test.jpg + * + * @return string Generated duplicate filename + * + * @since 3.5 + */ + public function resolveDuplicateFilename($file) + { + $file = JPath::clean($file); + $controller = JFactory::getApplication()->input->get('controller'); + $mediaTmp = JPATH_ROOT . '/tmp/com_media'; + + // Create com_media tmp folder + if (!JFolder::exists($mediaTmp)) + { + JFolder::create($mediaTmp); + } + + // Create a new file eg: TMP_crc32hash_test.jpg + $duplicateFile = JPath::clean( + $mediaTmp . '/' . 'TMP_' . crc32($file) . '_' . + pathinfo($file, PATHINFO_FILENAME) . '.' . pathinfo($file, PATHINFO_EXTENSION) + ); + + if ($controller == 'media.display.editor' || JFile::exists($duplicateFile)) + { + return $duplicateFile; + } + elseif (JFile::copy($file, $duplicateFile)) + { + return $duplicateFile; + } + else + { + return $file; + } + } +} diff --git a/administrator/components/com_media/model/field/mediafilter.php b/administrator/components/com_media/model/field/mediafilter.php new file mode 100644 index 0000000000000..95917b503168d --- /dev/null +++ b/administrator/components/com_media/model/field/mediafilter.php @@ -0,0 +1,60 @@ +'; + $label .= JText::_('COM_MEDIA_EDITOR_IMAGE_FILTER_NAME'); + $label .= ''; + + return $label; + } + + /** + * Return Input for Mediafilter field + * + * @return string Input for Mediafilter field + * + * @see JFormField::getInput() + */ + public function getInput() + { + return ''; + } +} diff --git a/administrator/components/com_media/model/field/mediaflip.php b/administrator/components/com_media/model/field/mediaflip.php new file mode 100644 index 0000000000000..cb947ea62e16e --- /dev/null +++ b/administrator/components/com_media/model/field/mediaflip.php @@ -0,0 +1,55 @@ +'; + $label .= JText::_('COM_MEDIA_EDITOR_IMAGE_FLIP_MODE'); + $label .= ''; + + return $label; + } + + /** + * Return Input for Mediaflip field + * + * @return string Input for Mediaflip field + * + * @see JFormField::getInput() + */ + public function getInput() + { + return ''; + } +} diff --git a/administrator/components/com_media/model/field/mediathumbs.php b/administrator/components/com_media/model/field/mediathumbs.php new file mode 100644 index 0000000000000..50247cb5959e4 --- /dev/null +++ b/administrator/components/com_media/model/field/mediathumbs.php @@ -0,0 +1,58 @@ +'; + $label .= JText::_('COM_MEDIA_EDITOR_IMAGE_THUMBS_CREATION_METHOD'); + $label .= ''; + + return $label; + } + + /** + * Return Input for Mediathumbs field + * + * @return string Input for Mediathumbs field + * + * @see JFormField::getInput() + */ + public function getInput() + { + return ''; + } +} diff --git a/administrator/components/com_media/model/form/image.xml b/administrator/components/com_media/model/form/image.xml new file mode 100644 index 0000000000000..d8c4d11f3aedc --- /dev/null +++ b/administrator/components/com_media/model/form/image.xml @@ -0,0 +1,61 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
diff --git a/administrator/components/com_media/model/media.php b/administrator/components/com_media/model/media.php new file mode 100644 index 0000000000000..bff739a0dc155 --- /dev/null +++ b/administrator/components/com_media/model/media.php @@ -0,0 +1,404 @@ +input; + + $folder = $input->get('folder', '', 'path'); + $this->state->set('folder', $folder); + + $fieldid = $input->get('fieldid', ''); + $this->state->set('field.id', $fieldid); + + $parent = str_replace(DIRECTORY_SEPARATOR, "/", dirname($folder)); + $parent = ($parent == '.') ? null : $parent; + $this->state->set('parent', $parent); + $set = true; + } + + if (!$property) + { + return parent::getState(); + } + else + { + return parent::getState()->get($property, $default); + } + } + + /** + * Image Manager Popup + * + * @param string $base The image directory to display + * + * @return JHtml Object that contains folder list to display + * + * @since 3.5 + */ + public function getFolderList($base = null) + { + // Get some paths from the request + if (empty($base)) + { + $base = COM_MEDIA_BASE; + } + // Corrections for windows paths + $base = str_replace(DIRECTORY_SEPARATOR, '/', $base); + $com_media_base_uri = str_replace(DIRECTORY_SEPARATOR, '/', COM_MEDIA_BASE); + + // Get the list of folders + jimport('joomla.filesystem.folder'); + $folders = JFolder::folders($base, '.', true, true); + + $document = JFactory::getDocument(); + $document->setTitle(JText::_('COM_MEDIA_INSERT_IMAGE')); + + // Build the array of select options for the folder list + $options[] = JHtml::_('select.option', "", "/"); + + foreach ($folders as $folder) + { + $folder = str_replace($com_media_base_uri, "", str_replace(DIRECTORY_SEPARATOR, '/', $folder)); + $value = substr($folder, 1); + $text = str_replace(DIRECTORY_SEPARATOR, "/", $folder); + $options[] = JHtml::_('select.option', $value, $text); + } + + // Sort the folder list array + if (is_array($options)) + { + sort($options); + } + + // Get asset and author id (use integer filter) + $input = JFactory::getApplication()->input; + $asset = $input->get('asset', 0, 'integer'); + + // For new items the asset is a string. JAccess always checks type first + // so both string and integer are supported. + if ($asset == 0) + { + $asset = $input->get('asset', 0, 'string'); + } + + $author = $input->get('author', 0, 'integer'); + + // Create the drop-down folder select list + $list = JHtml::_( + 'select.genericlist', + $options, + 'folderlist', + 'size="1" onchange="ImageManager.setFolder(this.options[this.selectedIndex].value, ' . $asset . ', ' . $author . ')" ', + 'value', + 'text', + $base + ); + + return $list; + } + + /** + * Construct the folder tree for Media Manager + * + * @param string $base Base for folder tree + * + * @return multitype:StdClass + * + * @since 3.5 + */ + public function getFolderTree($base = null) + { + // Get some paths from the request + if (empty($base)) + { + $base = COM_MEDIA_BASE; + } + + $mediaBase = str_replace(DIRECTORY_SEPARATOR, '/', COM_MEDIA_BASE . '/'); + + // Get the list of folders + jimport('joomla.filesystem.folder'); + $folders = JFolder::folders($base, '.', true, true); + + $tree = array(); + + foreach ($folders as $folder) + { + $folder = str_replace(DIRECTORY_SEPARATOR, '/', $folder); + $name = substr($folder, strrpos($folder, '/') + 1); + $relative = str_replace($mediaBase, '', $folder); + $absolute = $folder; + $path = explode('/', $relative); + $node = (object) array('name' => $name, 'relative' => $relative, 'absolute' => $absolute); + + $tmp = &$tree; + + for ($i = 0, $n = count($path); $i < $n; $i++) + { + if (!isset($tmp['children'])) + { + $tmp['children'] = array(); + } + + if ($i == $n - 1) + { + // We need to place the node + $tmp['children'][$relative] = array('data' => $node, 'children' => array()); + break; + } + + if (array_key_exists($key = implode('/', array_slice($path, 0, $i + 1)), $tmp['children'])) + { + $tmp = &$tmp['children'][$key]; + } + } + } + + $tree['data'] = (object) array('name' => JText::_('COM_MEDIA_MEDIA'), 'relative' => '', 'absolute' => $base); + + return $tree; + } + + /** + * Method for getting the form from the model. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * + * @return null + * + * @since 3.5 + */ + public function getForm($data = array(), $loadData = true) + { + return; + } + + /** + * Create a table record for a media in table + * + * @param JObject $file Instance contain media information + * + * @return boolean Record created in the table or not + * + * @since 3.5 + */ + public function create($file) + { + $row = JTable::getInstance('Corecontent'); + + // Get type_id fron content_type table + $type = new JUcmType; + $typeId = $type->getTypeId('com_media.image'); + + // Get relative path + $rel_path = str_replace(JPATH_ROOT, "", $file['filepath']); + + $data = array(); + $data['core_urls'] = $rel_path; + + $fname = null; + + // Require when handling files with non-alphaneumeric filename + if (isset($file['original_name'])) + { + $fname = explode('.', $file['original_name']); + } + else + { + $fname = explode('.', $file['name']); + } + + $data['core_type_id'] = $typeId; + $data['core_type_alias'] = 'com_media.image'; + $data['core_title'] = $fname[0]; + $data['core_alias'] = JFilterOutput::stringURLSafe($fname[0]); + $data['core_state'] = '1'; + + $metadata = new stdClass; + $metadata->name = $file['name']; + $metadata->type = $file['type']; + $metadata->filepath = $rel_path; + $metadata->size = $file['size']; + $data['core_metadata'] = json_encode($metadata); + + $row->bind($data); + + if ($row->store()) + { + // Need to fix _ucm_base & _ucm_content tables here + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + + $query -> select($db->quoteName('core_content_id')) + -> from($db->quoteName('#__ucm_content')) + -> where($db->quoteName('core_urls') . ' = ' . $db->quote($rel_path)); + + $db->setQuery($query); + $result = $db->loadObject(); + $pk = $result->core_content_id; + + $query = $db->getQuery(true); + $query -> update($db->quoteName('#__ucm_content')) + -> set($db->quoteName('core_content_item_id') . ' = ' . $db->quote($pk)) + -> where($db->quoteName('core_content_id') . ' = ' . $db->quote($pk)); + + $db->setQuery($query); + $db->execute(); + + $query = $db->getQuery(true); + $query -> update($db->quoteName('#__ucm_base')) + -> set($db->quoteName('ucm_item_id') . ' = ' . $db->quote($pk)) + -> where($db->quoteName('ucm_id') . ' = ' . $db->quote($pk)); + + $db->setQuery($query); + $db->execute(); + + return true; + } + else + { + return false; + } + } + + /** + * Delete a media entry from table + * + * @param string $url Path of the media in file system + * + * @return void + * + * @since 3.5 + */ + public function deleteMediaFromTable($url) + { + // Get relative path + $url = str_replace(JPATH_ROOT, "", $url); + + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + + $query -> select($db->quoteName('core_content_id')) + -> from($db->quoteName('#__ucm_content')) + -> where($db->quoteName('core_urls') . ' = ' . $db->quote($url)); + + $db->setQuery($query); + + $result = $db->loadObject(); + + $pk = $result->core_content_id; + + $row = JTable::getInstance('Corecontent'); + $row->delete($pk); + } + + /** + * Update a media entry from table + * + * @param string $source_url Path of the media in file system + * @param string $target_url Path to copy the media in file system + * + * @return success/failure of db operation + * + * @since 3.5 + */ + public function moveMediaFromTable($source_url, $target_url) + { + // Get relative path + $source_url = str_replace(JPATH_ROOT, "", $source_url); + $target_url = str_replace(JPATH_ROOT, "", $target_url); + + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + + $query -> select($db->quoteName(array('core_content_id', 'core_metadata', 'core_urls'))) + -> from($db->quoteName('#__ucm_content')) + -> where($db->quoteName('core_urls') . ' = ' . $db->quote($source_url)); + + $db->setQuery($query); + + $result = $db->loadObject(); + + $result -> core_urls = $target_url; + $metadata = json_decode($result->core_metadata); + $metadata -> filepath = $target_url; + $result->core_metadata = json_encode($metadata); + + return $db -> updateObject('#__ucm_content', $result, 'core_content_id'); + } + + /** + * Copy a media entry from table - TODO: try to use create() + * + * @param string $source_url Path of the media in file system + * @param string $target_url Path to copy the media in file system + * + * @return success/failure of db operation + * + * @since 3.5 + */ + public function copyMediaFromTable($source_url, $target_url) + { + // Get relative path + $source_url = str_replace(JPATH_ROOT, "", $source_url); + $target_url = str_replace(JPATH_ROOT, "", $target_url); + + // Fetching existing record from table + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + + $query -> select($db->quoteName(array('core_content_id', 'core_metadata', 'core_urls'))) + -> from($db->quoteName('#__ucm_content')) + -> where($db->quoteName('core_urls') . ' = ' . $db->quote($source_url)); + + $db->setQuery($query); + + $result = $db->loadObject(); + + $result -> core_urls = $target_url; + $metadata = json_decode($result->core_metadata); + $metadata -> filepath = $target_url; + $result -> core_metadata = json_encode($metadata); + + // File object to create + $file = array(); + $file['filepath'] = $target_url; + $file['original_name'] = $metadata->name; + $file['name'] = $metadata->name; + $file['type'] = $metadata->type; + $file['size'] = $metadata->size; + + return $this->create($file); + } +} diff --git a/administrator/components/com_media/model/medialist.php b/administrator/components/com_media/model/medialist.php new file mode 100644 index 0000000000000..f73ffc2f4fba9 --- /dev/null +++ b/administrator/components/com_media/model/medialist.php @@ -0,0 +1,360 @@ +input; + $folder = $input->get('folder', '', 'path'); + $this->state->set('folder', $folder); + + $parent = str_replace(DIRECTORY_SEPARATOR, "/", dirname($folder)); + $parent = ($parent == '.') ? null : $parent; + $this->state->set('parent', $parent); + $set = true; + } + + if (!$property) + { + return parent::getState(); + } + else + { + return parent::getState()->get($property, $default); + } + } + + /** + * Get Videos from the list + * + * @return array Array containing list of videos + * + * @since 3.5 + */ + public function getVideos() + { + $list = $this->getList(); + + return $list['videos']; + } + + /** + * Get Audios from the list + * + * @return array Array containing list of audios + * + * @since 3.5 + */ + public function getAudios() + { + $list = $this->getList(); + + return $list['audios']; + } + + /** + * Get Images from the list + * + * @return array Array containing list of images + * + * @since 3.5 + */ + public function getImages() + { + $list = $this->getList(); + + return $list['images']; + } + + /** + * Get Folders from the list + * + * @return array Array containing list of folders + * + * @since 3.5 + */ + public function getFolders() + { + $list = $this->getList(); + + return $list['folders']; + } + + /** + * Get Documents from the list + * + * @return array Array containing list of documents + * + * @since 3.5 + */ + public function getDocuments() + { + $list = $this->getList(); + + return $list['docs']; + } + + /** + * Build media list + * + * @return array List of items in the folder + * + * @since 3.5 + */ + public function getList() + { + $mediaHelper = new JHelperMedia; + + static $list; + + // Only process the list once per request + if (is_array($list)) + { + return $list; + } + + // Get current path from request + $current = (string) $this->getState('folder'); + + $basePath = COM_MEDIA_BASE . ((strlen($current) > 0) ? '/' . $current : ''); + + $mediaBase = str_replace(DIRECTORY_SEPARATOR, '/', COM_MEDIA_BASE . '/'); + + $videos = array (); + $audios = array (); + $images = array (); + $folders = array (); + $docs = array (); + + $fileList = false; + $folderList = false; + + if (file_exists($basePath)) + { + // Get the list of files and folders from the given folder + $fileList = JFolder::files($basePath); + $folderList = JFolder::folders($basePath); + } + + // Iterate over the files if they exist + if ($fileList !== false) + { + foreach ($fileList as $file) + { + if (is_file($basePath . '/' . $file) && substr($file, 0, 1) != '.' && strtolower($file) !== 'index.html') + { + $tmp = new stdClass; + $tmp->name = $file; + $tmp->title = $file; + $tmp->path = str_replace(DIRECTORY_SEPARATOR, '/', JPath::clean($basePath . '/' . $file)); + $tmp->path_relative = str_replace($mediaBase, '', $tmp->path); + $tmp->size = filesize($tmp->path); + + $ext = strtolower(JFile::getExt($file)); + + switch ($ext) + { + // Image + case 'jpg': + case 'png': + case 'gif': + case 'xcf': + case 'odg': + case 'bmp': + case 'jpeg': + case 'ico': + $info = @getimagesize($tmp->path); + $tmp->width = @$info[0]; + $tmp->height = @$info[1]; + $tmp->type = @$info[2]; + $tmp->mime = @$info['mime']; + + if (($info[0] > 150) || ($info[1] > 150)) + { + $dimensions = $mediaHelper->imageResize($info[0], $info[1], 150); + $tmp->width_150 = $dimensions[0]; + $tmp->height_150 = $dimensions[1]; + } + else + { + $tmp->width_150 = $tmp->width; + $tmp->height_150 = $tmp->height; + } + + if (($info[0] > 60) || ($info[1] > 60)) + { + $dimensions = $mediaHelper->imageResize($info[0], $info[1], 60); + $tmp->width_60 = $dimensions[0]; + $tmp->height_60 = $dimensions[1]; + } + else + { + $tmp->width_60 = $tmp->width; + $tmp->height_60 = $tmp->height; + } + + if (($info[0] > 16) || ($info[1] > 16)) + { + $dimensions = $mediaHelper->imageResize($info[0], $info[1], 16); + $tmp->width_16 = $dimensions[0]; + $tmp->height_16 = $dimensions[1]; + } + else + { + $tmp->width_16 = $tmp->width; + $tmp->height_16 = $tmp->height; + } + + $images[] = $tmp; + break; + + // Video files + case 'mp4': + case 'ogg': + $tmp->icon_32 = "media/mime-icon-32/" . $ext . ".png"; + $tmp->icon_16 = "media/mime-icon-16/" . $ext . ".png"; + $tmp->media_type = "video/" . $ext; + $videos[] = $tmp; + break; + + // Audio files + case 'mp3': + case 'wav': + $tmp->icon_32 = "media/mime-icon-32/" . $ext . ".png"; + $tmp->icon_16 = "media/mime-icon-16/" . $ext . ".png"; + $tmp->media_type = "audio/" . $ext; + $audios[] = $tmp; + break; + + // Non-image document + default: + $tmp->icon_32 = "media/mime-icon-32/" . $ext . ".png"; + $tmp->icon_16 = "media/mime-icon-16/" . $ext . ".png"; + $docs[] = $tmp; + break; + } + + // Get image id from #__ucm_content table + $url = str_replace('/', DIRECTORY_SEPARATOR, $tmp->path); + + // Get the relative path + $url = str_replace(JPATH_ROOT, "", $url); + + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + + $query -> select($db->quoteName('core_content_id') . ',' . $db->quoteName('core_title')) + -> from($db->quoteName('#__ucm_content')) + -> where($db->quoteName('core_urls') . ' = ' . $db->quote($url)); + + $db->setQuery($query); + + $result = $db->loadObject(); + + if ($result != null) + { + $tmp->id = $result->core_content_id; + $tmp->title = $result->core_title; + } + else + { + // Logic to add image to #__ucm_content and get core_content_id + $newfile = array(); + $newfile['name'] = $tmp->name; + $newfile['type'] = $tmp->type; + $newfile['filepath'] = $url; + $newfile['size'] = $tmp->size; + + // Using create controller to create a new record + $createController = new MediaControllerMediaCreate; + $input = JFactory::getApplication()->input; + $input->set('file', $newfile); + + $createController->execute(); + + // Get core_content_id of newly created record + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + + $query -> select($db->quoteName('core_content_id')) + -> from($db->quoteName('#__ucm_content')) + -> where($db->quoteName('core_urls') . ' = ' . $db->quote($url)); + + $db->setQuery($query); + + $result = $db->loadObject(); + + $tmp->id = $result->core_content_id; + } + } + } + } + + // Iterate over the folders if they exist + if ($folderList !== false) + { + foreach ($folderList as $folder) + { + $tmp = new stdClass; + $tmp->name = basename($folder); + $tmp->path = str_replace(DIRECTORY_SEPARATOR, '/', JPath::clean($basePath . '/' . $folder)); + $tmp->path_relative = str_replace($mediaBase, '', $tmp->path); + $count = $mediaHelper->countFiles($tmp->path); + $tmp->files = $count[0]; + $tmp->folders = $count[1]; + + $folders[] = $tmp; + } + } + + $list = array('folders' => $folders, 'docs' => $docs, 'images' => $images, 'videos' => $videos, 'audios' => $audios); + + return $list; + } + + /** + * Method for getting the form from the model. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * + * @return null + * + * @since 3.5 + */ + public function getForm($data = array(), $loadData = true) + { + return; + } +} diff --git a/administrator/components/com_media/models/list.php b/administrator/components/com_media/models/list.php index ec76241c41227..4f17e2b0ca362 100644 --- a/administrator/components/com_media/models/list.php +++ b/administrator/components/com_media/models/list.php @@ -15,22 +15,32 @@ /** * Media Component List Model * - * @since 1.5 + * @package Joomla.Administrator + * @subpackage com_media + * @since 1.5 + * @deprecated 4.0 */ class MediaModelList extends JModelLegacy { /** * Method to get model state variables * - * @param string $property Optional parameter name - * @param mixed $default Optional default value + * @param string $property Property to retrieve + * @param string $default Default value * * @return object The property where specified, the state object where omitted * * @since 1.5 + * @deprecated 4.0 */ public function getState($property = null, $default = null) { + JLog::add( + 'MediaModelList is deprecated. Use MediaModelMedialist.getState() instead.', + JLog::WARNING, + 'deprecated' + ); + static $set; if (!$set) @@ -49,56 +59,84 @@ public function getState($property = null, $default = null) } /** - * Get the images on the current folder + * Get Images from the list * - * @return array + * @return array Array containing list of images * - * @since 1.5 + * @since 1.5 + * @deprecated 4.0 */ public function getImages() { + JLog::add( + 'MediaModelList is deprecated. Use MediaModelMedialist.getImages() instead.', + JLog::WARNING, + 'deprecated' + ); + $list = $this->getList(); return $list['images']; } /** - * Get the folders on the current folder + * Get Folders from the list * - * @return array + * @return array Array containing list of folders * - * @since 1.5 + * @since 1.5 + * @deprecated 4.0 */ public function getFolders() { + JLog::add( + 'MediaModelList is deprecated. Use MediaModelMedialist.getFolders() instead.', + JLog::WARNING, + 'deprecated' + ); + $list = $this->getList(); return $list['folders']; } /** - * Get the documents on the current folder + * Get Documents from the list * - * @return array + * @return array Array containing list of documents * - * @since 1.5 + * @since 1.5 + * @deprecated 4.0 */ public function getDocuments() { + JLog::add( + 'MediaModelList is deprecated. Use MediaModelMedialist.getDocuments() instead.', + JLog::WARNING, + 'deprecated' + ); + $list = $this->getList(); return $list['docs']; } /** - * Build imagelist + * Build media list * - * @return array + * @return array List of items in the folder * * @since 1.5 + * @deprecated 4.0 */ public function getList() { + JLog::add( + 'MediaModelList is deprecated. Use MediaModelMedialist.getList() instead.', + JLog::WARNING, + 'deprecated' + ); + static $list; // Only process the list once per request diff --git a/administrator/components/com_media/models/manager.php b/administrator/components/com_media/models/manager.php index 8537addd59cd0..1566d3a63ee67 100644 --- a/administrator/components/com_media/models/manager.php +++ b/administrator/components/com_media/models/manager.php @@ -12,22 +12,32 @@ /** * Media Component Manager Model * - * @since 1.5 + * @package Joomla.Administrator + * @subpackage com_media + * @since 1.5 + * @deprecated 4.0 */ class MediaModelManager extends JModelLegacy { /** * Method to get model state variables * - * @param string $property Optional parameter name - * @param mixed $default Optional default value + * @param string $property Property to retrieve + * @param string $default Default value * * @return object The property where specified, the state object where omitted * * @since 1.5 + * @deprecated 4.0 */ public function getState($property = null, $default = null) { + JLog::add( + 'MediaModelManager is deprecated. Use MediaModelMedia.getState() instead.', + JLog::WARNING, + 'deprecated' + ); + static $set; if (!$set) @@ -54,12 +64,19 @@ public function getState($property = null, $default = null) * * @param string $base The image directory to display * - * @return html + * @return JHtml Object that contains folder list to display * * @since 1.5 + * @deprecated 4.0 */ public function getFolderList($base = null) { + JLog::add( + 'MediaModelManager is deprecated. Use MediaModelMedia.getFolderList() instead.', + JLog::WARNING, + 'deprecated' + ); + // Get some paths from the request if (empty($base)) { @@ -114,16 +131,23 @@ public function getFolderList($base = null) } /** - * Get the folder tree + * Construct the folder tree for Media Manager * - * @param mixed $base Base folder | null for using base media folder + * @param string $base Base for folder tree * - * @return array + * @return multitype:StdClass * - * @since 1.5 + * @since 1.5 + * @deprecated 4.0 */ public function getFolderTree($base = null) { + JLog::add( + 'MediaModelManager is deprecated. Use MediaModelMedia.getFolderTree() instead.', + JLog::WARNING, + 'deprecated' + ); + // Get some paths from the request if (empty($base)) { diff --git a/administrator/components/com_media/table/media.php b/administrator/components/com_media/table/media.php new file mode 100644 index 0000000000000..f6989d5a131ac --- /dev/null +++ b/administrator/components/com_media/table/media.php @@ -0,0 +1,156 @@ + 'com_media.image')); + } + + /** + * Overriding JTable checkout method for #__ucm_core_content + * + * @param integer $userId The Id of the user checking out the row. + * @param mixed $pk An optional primary key value to check out. If not set + * the instance property value is used. + * + * @return boolean True on success. + * + * @since 3.5 + * @throws UnexpectedValueException + */ + public function checkOut($userId, $pk = null) + { + // If there is no checked_out or checked_out_time field, just return true. + if (!property_exists($this, 'core_checked_out_user_id') || !property_exists($this, 'core_checked_out_time')) + { + return true; + } + + if (is_null($pk)) + { + $pk = array(); + + foreach ($this->_tbl_keys AS $key) + { + $pk[$key] = $this->$key; + } + } + elseif (!is_array($pk)) + { + $pk = array($this->_tbl_key => $pk); + } + + foreach ($this->_tbl_keys AS $key) + { + $pk[$key] = is_null($pk[$key]) ? $this->$key : $pk[$key]; + + if ($pk[$key] === null) + { + throw new UnexpectedValueException('Null primary key not allowed.'); + } + } + + // Get the current time in the database format. + $time = JFactory::getDate()->toSql(); + + // Check the row out by primary key. + $query = $this->_db->getQuery(true) + ->update($this->_tbl) + ->set($this->_db->quoteName('core_checked_out_user_id') . ' = ' . (int) $userId) + ->set($this->_db->quoteName('core_checked_out_time') . ' = ' . $this->_db->quote($time)); + $this->appendPrimaryKeys($query, $pk); + $this->_db->setQuery($query); + $this->_db->execute(); + + // Set table values in the object. + $this->core_checked_out_user_id = (int) $userId; + $this->core_checked_out_time = $time; + + return true; + } + + /** + * Overriding JTable checkin method for #__ucm_core_content + * + * @param mixed $pk An optional primary key value to check out. If not set the instance property value is used. + * + * @return boolean True on success. + * + * @since 3.5 + * @throws UnexpectedValueException + */ + public function checkIn($pk = null) + { + // If there is no checked_out or checked_out_time field, just return true. + if (!property_exists($this, 'core_checked_out_user_id') || !property_exists($this, 'core_checked_out_time')) + { + return true; + } + + if (is_null($pk)) + { + $pk = array(); + + foreach ($this->_tbl_keys AS $key) + { + $pk[$this->$key] = $this->$key; + } + } + elseif (!is_array($pk)) + { + $pk = array($this->_tbl_key => $pk); + } + + foreach ($this->_tbl_keys AS $key) + { + $pk[$key] = empty($pk[$key]) ? $this->$key : $pk[$key]; + + if ($pk[$key] === null) + { + throw new UnexpectedValueException('Null primary key not allowed.'); + } + } + + // Check the row in by primary key. + $query = $this->_db->getQuery(true) + ->update($this->_tbl) + ->set($this->_db->quoteName('core_checked_out_user_id') . ' = 0') + ->set($this->_db->quoteName('core_checked_out_time') . ' = ' . $this->_db->quote($this->_db->getNullDate())); + $this->appendPrimaryKeys($query, $pk); + $this->_db->setQuery($query); + + // Check for a database error. + $this->_db->execute(); + + // Set table values in the object. + $this->core_checked_out_user_id = 0; + $this->core_checked_out_time = ''; + + return true; + } +} diff --git a/administrator/components/com_media/view/editor/html.php b/administrator/components/com_media/view/editor/html.php new file mode 100644 index 0000000000000..435e205b509cf --- /dev/null +++ b/administrator/components/com_media/view/editor/html.php @@ -0,0 +1,142 @@ +isAdmin()) + { + return $app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning'); + } + + // Only allow for users wit edit permission + if (!$user->authorise('core.edit', 'com_media')) + { + return; + } + + $lang = JFactory::getLanguage(); + + $document = JFactory::getDocument(); + + $ftp = !JClientHelper::hasCredentials('ftp'); + + $session = JFactory::getSession(); + $state = $this->model->getState(); + + $this->id = $app->input->get('id'); + $this->item = $this->model->getItem($this->id); + $this->form = $this->model->getForm(); + + $this->session = $session; + $this->config = &$config; + $this->state = &$state; + $this->require_ftp = $ftp; + + // From template manager + $this->folder = $app->input->get('folder', '', 'path'); + $this->file = $app->input->get('file'); + + $explodeArray = explode('.', $this->file); + $ext = end($explodeArray); + $imageExts = explode(',', $config->get('image_extensions')); + + if (in_array($ext, $imageExts)) + { + $this->image = $this->model->getImage(); + + // Handle hidden file + $duplicateFilename = $this->model->resolveDuplicateFilename(JPath::clean(COM_MEDIA_BASE . '/' . $this->folder . '/' . $this->file)); + + if (JFile::exists($duplicateFilename)) + { + $this->image['address'] = JUri::root() . '/tmp/com_media/' . pathinfo($duplicateFilename, PATHINFO_BASENAME); + } + } + else + { + // File extension not allowed + return $app->enqueueMessage(JText::_('JERROR'), 'warning'); + } + + // Set the toolbar + $this->addToolbar(); + + return parent::render(); + } + + /** + * Add the page title and toolbar. + * + * @return void + * + * @since 3.5 + */ + protected function addToolbar() + { + $user = JFactory::getUser(); + + JToolbarHelper::title(JText::_('COM_MEDIA_EDITOR'), 'images mediamanager'); + + // If not checked out, can save the item. + if ($user->authorise('core.edit', 'com_media')) + { + JToolbarHelper::apply('media.save.editor.apply'); + JToolbarHelper::save('media.save.editor.save'); + + // Actions on media + JToolbarHelper::custom('media.crop.editor', 'move', 'move', 'COM_MEDIA_EDITOR_BUTTON_CROP', false); + JToolbarHelper::modal('resizeModal', 'icon-contract-2', 'COM_MEDIA_EDITOR_BUTTON_RESIZE'); + JToolbarHelper::modal('rotateModal', 'icon-loop', 'COM_MEDIA_EDITOR_BUTTON_ROTATE'); + JToolbarHelper::modal('flipModal', 'icon-star-2', 'COM_MEDIA_EDITOR_BUTTON_FLIP'); + JToolbarHelper::modal('filterModal', 'icon-filter', 'COM_MEDIA_EDITOR_BUTTON_FILTER'); + JToolbarHelper::modal('thumbsModal', 'icon-grid', 'COM_MEDIA_EDITOR_BUTTON_THUMBS'); + + JToolbarHelper::divider(); + } + + JToolbarHelper::cancel('media.cancel.editor'); + + JToolbarHelper::divider(); + JToolbarHelper::help('JHELP_CONTENT_MEDIA_MANAGER_EDITOR'); + } +} diff --git a/administrator/components/com_media/view/editor/index.html b/administrator/components/com_media/view/editor/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/administrator/components/com_media/view/editor/index.html @@ -0,0 +1 @@ + diff --git a/administrator/components/com_media/view/editor/tmpl/default.php b/administrator/components/com_media/view/editor/tmpl/default.php new file mode 100644 index 0000000000000..e644e54fba96a --- /dev/null +++ b/administrator/components/com_media/view/editor/tmpl/default.php @@ -0,0 +1,395 @@ +input; + +JHtml::_('script', 'system/jquery.Jcrop.min.js', false, true); +JHtml::_('stylesheet', 'system/jquery.Jcrop.min.css', array(), true); + +JFormHelper::addFieldPath(JPATH_COMPONENT . '/model/field'); + +?> + + + + +
+ + + +
+ + + + +
+
+ + + + + + +
+
+ +
+ +
+ +
+ + loadTemplate('properties'); ?> + + + +
+ +
+ +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
diff --git a/administrator/components/com_media/view/editor/tmpl/default_properties.php b/administrator/components/com_media/view/editor/tmpl/default_properties.php new file mode 100644 index 0000000000000..90cf2893a859a --- /dev/null +++ b/administrator/components/com_media/view/editor/tmpl/default_properties.php @@ -0,0 +1,35 @@ +form->getControlGroup('core_title'); +echo $this->form->getControlGroup('core_alias'); + +// Hidden field +echo $this->form->getControlGroup('core_type_alias'); + +echo $this->form->getControlGroup('core_body'); +echo $this->form->getControlGroup('core_catid'); +echo $this->form->getControlGroup('tags'); + +echo $this->form->getControlGroup('core_created_time'); +echo $this->form->getControlGroup('core_created_user_id'); +echo $this->form->getControlGroup('core_created_by_alias'); + +echo $this->form->getControlGroup('core_modified_time'); +echo $this->form->getControlGroup('core_modified_user_id'); diff --git a/administrator/components/com_media/view/editor/tmpl/index.html b/administrator/components/com_media/view/editor/tmpl/index.html new file mode 100644 index 0000000000000..2efb97f319a35 --- /dev/null +++ b/administrator/components/com_media/view/editor/tmpl/index.html @@ -0,0 +1 @@ + diff --git a/administrator/components/com_media/view/images/html.php b/administrator/components/com_media/view/images/html.php new file mode 100644 index 0000000000000..e5dc4b7f2443b --- /dev/null +++ b/administrator/components/com_media/view/images/html.php @@ -0,0 +1,56 @@ +isRTL()) + { + JHtml::_('stylesheet', 'media/popup-imagemanager_rtl.css', array(), true); + } + + /* + * Display form for FTP credentials? + * Don't set them here, as there are other functions called before this one if there is any file write operation + */ + $ftp = !JClientHelper::hasCredentials('ftp'); + + $this->session = JFactory::getSession(); + $this->config = $config; + $this->state = $this->model->getState(); + $this->folderList = $this->model->getFolderList(); + + $this->require_ftp = $ftp; + + return parent::render(); + } +} diff --git a/administrator/components/com_media/view/images/tmpl/default.php b/administrator/components/com_media/view/images/tmpl/default.php new file mode 100644 index 0000000000000..0e547181e0de9 --- /dev/null +++ b/administrator/components/com_media/view/images/tmpl/default.php @@ -0,0 +1,178 @@ + false)); + +$user = JFactory::getUser(); +$input = JFactory::getApplication()->input; +?> + + + + +
+ + +
+ +
+ +
+ +
+
+ +
+
+ +
+
+ folderList; ?> + +
+
+
+
+ + +
+ + +
+
+
+ + + + + +
+ +
+
+ +
+
+ +
+
+ state->get('field.id')):?> +
+
+ +
+
+ +
+
+ + + state->get('field.id')):?> + +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ + + +
+
+ + + + + + + +
+ + + +
+ +
+ +authorise('core.create', 'com_media')) : ?> +
+ +
+
+
+
+ +
+
+ +

config->get('upload_maxsize') == '0' ? JText::_('COM_MEDIA_UPLOAD_FILES_NOLIMIT') : JText::sprintf('COM_MEDIA_UPLOAD_FILES', $this->config->get('upload_maxsize')); ?>

+
+
+
+ set('com_media.return_url', 'index.php?option=com_media&view=images&controller=media.display.images&tmpl=component&fieldid=' . $input->getCmd('fieldid', '') . '&e_name=' . $input->getCmd('e_name') . '&asset=' . $input->getCmd('asset') . '&author=' . $input->getCmd('author')); ?> +
+
+ + +
+
+
diff --git a/administrator/components/com_media/view/imageslist/html.php b/administrator/components/com_media/view/imageslist/html.php new file mode 100644 index 0000000000000..debbc5d5f2af6 --- /dev/null +++ b/administrator/components/com_media/view/imageslist/html.php @@ -0,0 +1,97 @@ +allowCache(false); + + $lang = JFactory::getLanguage(); + + JHtml::_('stylesheet', 'media/popup-imagelist.css', array(), true); + + if ($lang->isRTL()) + { + JHtml::_('stylesheet', 'media/popup-imagelist_rtl.css', array(), true); + } + + $document = JFactory::getDocument(); + $document->addScriptDeclaration("var ImageManager = window.parent.ImageManager;"); + + $images = $this->model->getImages(); + $folders = $this->model->getFolders(); + $state = $this->model->getState(); + + $this->baseURL = COM_MEDIA_BASEURL; + $this->images = &$images; + $this->folders = &$folders; + $this->state = &$state; + + return parent::render(); + } + + /** + * Set the folder + * + * @param int $index Index of the folder + * + * @return void + * + * @since 3.5 + */ + public function setFolder($index = 0) + { + if (isset($this->folders[$index])) + { + $this->_tmp_folder = &$this->folders[$index]; + } + else + { + $this->_tmp_folder = new JObject; + } + } + + /** + * Set the image + * + * @param int $index Index of the image + * + * @return void + * + * @since 3.5 + */ + public function setImage($index = 0) + { + if (isset($this->images[$index])) + { + $this->_tmp_img = &$this->images[$index]; + } + else + { + $this->_tmp_img = new JObject; + } + } +} diff --git a/administrator/components/com_media/view/imageslist/tmpl/default.php b/administrator/components/com_media/view/imageslist/tmpl/default.php new file mode 100644 index 0000000000000..384b3a4ec76e1 --- /dev/null +++ b/administrator/components/com_media/view/imageslist/tmpl/default.php @@ -0,0 +1,31 @@ + +images) > 0 || count($this->folders) > 0) + { ?> +
    + folders); $i < $n; $i++) : + $this->setFolder($i); + echo $this->loadTemplate('folder'); + endfor; ?> + + images); $i < $n; $i++) : + $this->setImage($i); + echo $this->loadTemplate('image'); + endfor; ?> +
+ +
+
+
+input; +?> +
  • + +
    + +
    +
    + _tmp_folder->name, 10, false); ?> +
    +
    +
  • diff --git a/administrator/components/com_media/view/imageslist/tmpl/default_image.php b/administrator/components/com_media/view/imageslist/tmpl/default_image.php new file mode 100644 index 0000000000000..c8f46b0b5ec09 --- /dev/null +++ b/administrator/components/com_media/view/imageslist/tmpl/default_image.php @@ -0,0 +1,27 @@ +trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_img, &$params)); +?> +
  • + +
    + baseURL . '/' . $this->_tmp_img->path_relative, JText::sprintf('COM_MEDIA_IMAGE_TITLE', $this->_tmp_img->title, JHtml::_('number.bytes', $this->_tmp_img->size)), array('width' => $this->_tmp_img->width_60, 'height' => $this->_tmp_img->height_60)); ?> +
    +
    + _tmp_img->title, 10, false); ?> +
    +
    +
  • +trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_img, &$params)); diff --git a/administrator/components/com_media/view/media/html.php b/administrator/components/com_media/view/media/html.php new file mode 100644 index 0000000000000..953a434fd30e5 --- /dev/null +++ b/administrator/components/com_media/view/media/html.php @@ -0,0 +1,214 @@ +isAdmin()) + { + return $app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning'); + } + + $lang = JFactory::getLanguage(); + + $style = $app->getUserStateFromRequest('media.list.layout', 'layout', 'thumbs', 'word'); + + $document = JFactory::getDocument(); + + JHtml::_('behavior.framework', true); + + JHtml::_('script', 'media/mediamanager.min.js', true, true); + /* + JHtml::_('stylesheet', 'media/mediamanager.css', array(), true); + if ($lang->isRTL()) : + JHtml::_('stylesheet', 'media/mediamanager_rtl.css', array(), true); + endif; + */ + JHtml::_('behavior.modal'); + $document->addScriptDeclaration(" + window.addEvent('domready', function() + { + document.preview = SqueezeBox; + });"); + + // JHtml::_('script', 'system/mootree.js', true, true, false, false); + JHtml::_('stylesheet', 'system/mootree.css', array(), true); + + if ($lang->isRTL()) + { + JHtml::_('stylesheet', 'media/mootree_rtl.css', array(), true); + } + + // For Drag & Drop Upload + JHtml::_('script', 'media/dragndrop_upload.js', true, true); + JHtml::stylesheet('media/media/css/dragndrop_upload.css'); + + if (DIRECTORY_SEPARATOR == '\\') + { + $base = str_replace(DIRECTORY_SEPARATOR, "\\\\", COM_MEDIA_BASE); + } + else + { + $base = COM_MEDIA_BASE; + } + + $js = " var basepath = '" . $base . "'; + var viewstyle = '" . $style . "'; "; + $document->addScriptDeclaration($js); + + /* + * Display form for FTP credentials? + * Don't set them here, as there are other functions called before this one if there is any file write operation + */ + $ftp = !JClientHelper::hasCredentials('ftp'); + + $session = JFactory::getSession(); + $state = $this->model->getState(); + $this->session = $session; + $this->config = &$config; + $this->state = &$state; + $this->require_ftp = $ftp; + $this->folders_id = ' id="media-tree"'; + $this->folders = $this->model->getFolderTree(); + $this->folderList = $this->model->getFolderList(); + + // Add sidebar + JLoader::register('MediaHelperMedia', JPATH_ADMINISTRATOR . '/components/com_media/helper/media.php'); + + MediaHelperMedia::addSubmenu('media'); + $this->sidebar = JHtmlSidebar::render(); + + // Set the toolbar + $this->addToolbar(); + + return parent::render(); + } + + /** + * Add the page title and toolbar. + * + * @return void + * + * @since 3.5 + */ + protected function addToolbar() + { + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + $user = JFactory::getUser(); + + // The toolbar functions depend on Bootstrap JS + JHtml::_('bootstrap.framework'); + + // Set the titlebar text + JToolbarHelper::title(JText::_('COM_MEDIA'), 'images mediamanager'); + + // Add a upload button + if ($user->authorise('core.create', 'com_media')) + { + // Instantiate a new JLayoutFile instance and render the layout + $layout = new JLayoutFile('toolbar.uploadmedia'); + + $bar->appendButton('Custom', $layout->render(array()), 'upload'); + + JToolbarHelper::divider(); + } + + // Add a create folder button + if ($user->authorise('core.create', 'com_media')) + { + // Instantiate a new JLayoutFile instance and render the layout + $layout = new JLayoutFile('toolbar.newfolder'); + + $bar->appendButton('Custom', $layout->render(array()), 'upload'); + + JToolbarHelper::divider(); + + // Instantiate a new JLayoutFile instance and render the layout for copy button + $layout = new JLayoutFile('toolbar.copymedia'); + + $bar->appendButton('Custom', $layout->render(array()), 'upload'); + + JToolbarHelper::divider(); + + // Instantiate a new JLayoutFile instance and render the layout for copy button + $layout = new JLayoutFile('toolbar.movemedia'); + + $bar->appendButton('Custom', $layout->render(array()), 'upload'); + + JToolbarHelper::divider(); + } + + // Add a delete button + if ($user->authorise('core.delete', 'com_media')) + { + // Instantiate a new JLayoutFile instance and render the layout + $layout = new JLayoutFile('toolbar.deletemedia'); + + $bar->appendButton('Custom', $layout->render(array()), 'upload'); + JToolbarHelper::divider(); + } + + // Add a preferences button + if ($user->authorise('core.admin', 'com_media')) + { + JToolbarHelper::preferences('com_media'); + JToolbarHelper::divider(); + } + + JToolbarHelper::help('JHELP_CONTENT_MEDIA_MANAGER'); + } + + /** + * Get the folder level + * + * @param string $folder Name of the folder + * + * @return void + * + * @since 3.5 + */ + public function getFolderLevel($folder) + { + $this->folders_id = null; + $txt = null; + + if (isset($folder['children']) && count($folder['children'])) + { + $tmp = $this->folders; + $this->folders = $folder; + $txt = $this->loadTemplate('folders'); + $this->folders = $tmp; + } + + return $txt; + } +} diff --git a/administrator/components/com_media/view/media/tmpl/default.php b/administrator/components/com_media/view/media/tmpl/default.php new file mode 100644 index 0000000000000..9e2dee310827c --- /dev/null +++ b/administrator/components/com_media/view/media/tmpl/default.php @@ -0,0 +1,258 @@ +input; +?> +
    + +
    + sidebar; ?> +
    +
    +

    +
    + +
    + + + +
    + loadTemplate('navigation'); ?> + authorise('core.create', 'com_media')) and $this->require_ftp) : ?> +
    +
    + +

    + +
    + + + +
    +
    +
    + + +
    + + + +
    + + authorise('core.create', 'com_media')):?> + + +
    + + +
    + + + + +
    + + +
    + + + + + + + + + + + + authorise('core.delete', 'com_media')):?> + + + + + + + + +
    +
    +
    + +
    + +
    +
    +
    + +
    diff --git a/administrator/components/com_media/view/media/tmpl/default_folders.php b/administrator/components/com_media/view/media/tmpl/default_folders.php new file mode 100644 index 0000000000000..ce245b794c96f --- /dev/null +++ b/administrator/components/com_media/view/media/tmpl/default_folders.php @@ -0,0 +1,31 @@ +folders['data']->relative); + +?> + diff --git a/administrator/components/com_media/view/media/tmpl/default_navigation.php b/administrator/components/com_media/view/media/tmpl/default_navigation.php new file mode 100644 index 0000000000000..176cfe31d4b62 --- /dev/null +++ b/administrator/components/com_media/view/media/tmpl/default_navigation.php @@ -0,0 +1,19 @@ +getUserStateFromRequest('media.list.layout', 'layout', 'thumbs', 'word'); +?> + diff --git a/administrator/components/com_media/view/medialist/html.php b/administrator/components/com_media/view/medialist/html.php new file mode 100644 index 0000000000000..0572c06371a43 --- /dev/null +++ b/administrator/components/com_media/view/medialist/html.php @@ -0,0 +1,191 @@ +isAdmin()) + { + return $app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning'); + } + + // Do not allow cache + $app->allowCache(false); + + JHtml::_('behavior.framework', true); + + JFactory::getDocument()->addScriptDeclaration(" + jQuery(function($) + { + window.parent.document.updateUploader(); + $('a.img-preview').each(function() + { + $(this).on('click', function() + { + window.top.document.preview.fromElement(this); + return false; + }); + }); + });"); + + $videos = $this->model->getVideos(); + $audios = $this->model->getAudios(); + $images = $this->model->getImages(); + $documents = $this->model->getDocuments(); + $folders = $this->model->getFolders(); + $state = $this->model->getState(); + + // Check for invalid folder name + if ($state->get('folder') == null) + { + $dirname = JRequest::getVar('folder', '', '', 'string'); + + if (!empty($dirname)) + { + $dirname = htmlspecialchars($dirname, ENT_COMPAT, 'UTF-8'); + $app->enqueueMessage(JText::sprintf('COM_MEDIA_ERROR_UNABLE_TO_BROWSE_FOLDER_WARNDIRNAME', $dirname), 'error'); + + return; + } + } + + $this->baseURL = JUri::root(); + $this->videos = &$videos; + $this->audios = &$audios; + $this->images = &$images; + $this->documents = &$documents; + $this->folders = &$folders; + $this->state = &$state; + + return parent::render(); + } + + /** + * Set the folder + * + * @param int $index Index of the image + * + * @return void + * + * @since 3.5 + */ + public function setFolder($index = 0) + { + if (isset($this->folders[$index])) + { + $this->_tmp_folder = &$this->folders[$index]; + } + else + { + $this->_tmp_folder = new JObject; + } + } + + /** + * Set the video + * + * @param int $index Index of the video + * + * @return void + * + * @since 3.5 + */ + public function setVideo($index = 0) + { + if (isset($this->videos[$index])) + { + $this->_tmp_video = &$this->videos[$index]; + } + else + { + $this->_tmp_video = new JObject; + } + } + + /** + * Set the audio + * + * @param int $index Index of the audio + * + * @return void + * + * @since 3.5 + */ + public function setAudio($index = 0) + { + if (isset($this->audios[$index])) + { + $this->_tmp_audio = &$this->audios[$index]; + } + else + { + $this->_tmp_audio = new JObject; + } + } + + /** + * Set the image + * + * @param int $index Index of the image + * + * @return void + * + * @since 3.5 + */ + public function setImage($index = 0) + { + if (isset($this->images[$index])) + { + $this->_tmp_img = &$this->images[$index]; + } + else + { + $this->_tmp_img = new JObject; + } + } + + /** + * Set the doc + * + * @param int $index Index of the doc + * + * @return void + * + * @since 3.5 + */ + public function setDoc($index = 0) + { + if (isset($this->documents[$index])) + { + $this->_tmp_doc = &$this->documents[$index]; + } + else + { + $this->_tmp_doc = new JObject; + } + } +} diff --git a/administrator/components/com_media/view/medialist/tmpl/default.php b/administrator/components/com_media/view/medialist/tmpl/default.php new file mode 100644 index 0000000000000..bd51f931f7856 --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/default.php @@ -0,0 +1,10 @@ + +
    +
    +

    + + state->get('folder') != '') : ?> + get($path, 'images') . '/' . $this->state->get('folder'); ?> + + get($path, 'images'); ?> + +

    +
    + +
    + + + + + + + + authorise('core.delete', 'com_media')):?> + + + + + + loadTemplate('up'); ?> + + folders); $i < $n; $i++) : + $this->setFolder($i); + echo $this->loadTemplate('folder'); + endfor; ?> + + documents); $i < $n; $i++) : + $this->setDoc($i); + echo $this->loadTemplate('doc'); + endfor; ?> + + images); $i < $n; $i++) : + $this->setImage($i); + echo $this->loadTemplate('img'); + endfor; ?> + + videos); $i < $n; $i++) : + $this->setVideo($i); + echo $this->loadTemplate('video'); + endfor; ?> + + audios); $i < $n; $i++) : + $this->setAudio($i); + echo $this->loadTemplate('audio'); + endfor; ?> + + +
    + + + + +
    +
    diff --git a/administrator/components/com_media/view/medialist/tmpl/details_audio.php b/administrator/components/com_media/view/medialist/tmpl/details_audio.php new file mode 100644 index 0000000000000..407fbdf28712d --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/details_audio.php @@ -0,0 +1,70 @@ +_tmp_audio->title . 'Modal'; +JHTML::_('behavior.modal'); +$dispatcher = JEventDispatcher::getInstance(); +$dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_audio, &$params)); +?> + + + + _tmp_audio->icon_16, $this->_tmp_audio->title, null, true, true) ? JHtml::_('image', $this->_tmp_audio->icon_16, $this->_tmp_audio->title, array('width' => 16, 'height' => 16), true) : JHtml::_('image', 'media/con_info.png', $this->_tmp_audio->title, array('width' => 16, 'height' => 16), true);?> + + + + + escape($this->_tmp_audio->title); ?> + + + + + + _tmp_audio->size); ?> + + authorise('core.delete', 'com_media')):?> + + + + + + + + +
    +
    + + + +
    +
    + + +
    +
    + + + +
    +
    + +trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_audio, &$params)); diff --git a/administrator/components/com_media/view/medialist/tmpl/details_doc.php b/administrator/components/com_media/view/medialist/tmpl/details_doc.php new file mode 100644 index 0000000000000..bb4d75e7886ff --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/details_doc.php @@ -0,0 +1,41 @@ +trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_doc, &$params)); +?> + + + + _tmp_doc->icon_16, $this->_tmp_doc->title, null, true, true) ? JHtml::_('image', $this->_tmp_doc->icon_16, $this->_tmp_doc->title, array('width' => 16, 'height' => 16), true) : JHtml::_('image', 'media/con_info.png', $this->_tmp_doc->title, array('width' => 16, 'height' => 16), true);?> + + + _tmp_doc->title; ?> + +   + + + + _tmp_doc->size); ?> + + authorise('core.delete', 'com_media')):?> + + + + + + +trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_doc, &$params)); +?> diff --git a/administrator/components/com_media/view/medialist/tmpl/details_folder.php b/administrator/components/com_media/view/medialist/tmpl/details_folder.php new file mode 100644 index 0000000000000..d136cab7f42be --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/details_folder.php @@ -0,0 +1,37 @@ + + + + + + + + _tmp_folder->name; ?> + +   + + +   + + + authorise('core.delete', 'com_media')):?> + + + + + + + + diff --git a/administrator/components/com_media/view/medialist/tmpl/details_img.php b/administrator/components/com_media/view/medialist/tmpl/details_img.php new file mode 100644 index 0000000000000..b498ca05af172 --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/details_img.php @@ -0,0 +1,40 @@ +trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_img, &$params)); +?> + + + _tmp_img->path_relative, JText::sprintf('COM_MEDIA_IMAGE_TITLE', $this->_tmp_img->title, JHtml::_('number.bytes', $this->_tmp_img->size)), array('width' => $this->_tmp_img->width_16, 'height' => $this->_tmp_img->height_16)); ?> + + + escape($this->_tmp_img->title); ?> + + + _tmp_img->width, $this->_tmp_img->height); ?> + + + _tmp_img->size); ?> + + authorise('core.delete', 'com_media')):?> + + + + + + +trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_img, &$params)); diff --git a/administrator/components/com_media/view/medialist/tmpl/details_up.php b/administrator/components/com_media/view/medialist/tmpl/details_up.php new file mode 100644 index 0000000000000..7b93e0dc12fb3 --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/details_up.php @@ -0,0 +1,29 @@ + +state->get('folder') != '') : ?> + + + + + + + .. + +   +   + authorise('core.delete', 'com_media')):?> +   + + + diff --git a/administrator/components/com_media/view/medialist/tmpl/details_video.php b/administrator/components/com_media/view/medialist/tmpl/details_video.php new file mode 100644 index 0000000000000..ce0a0e1b1040c --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/details_video.php @@ -0,0 +1,57 @@ +_tmp_video->title . 'Modal'; +JHTML::_('behavior.modal'); +$dispatcher = JEventDispatcher::getInstance(); +$dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_video, &$params)); +?> + + + + _tmp_video->icon_16, $this->_tmp_video->title, null, true, true) ? JHtml::_('image', $this->_tmp_video->icon_16, $this->_tmp_video->title, array('width' => 16, 'height' => 16), true) : JHtml::_('image', 'media/con_info.png', $this->_tmp_video->title, array('width' => 16, 'height' => 16), true);?> + + + + + escape($this->_tmp_video->title); ?> + + + + + + _tmp_video->size); ?> + + authorise('core.delete', 'com_media')):?> + + + + + + + + +
    +
    + + + +
    +
    +trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_video, &$params)); diff --git a/administrator/components/com_media/view/medialist/tmpl/thumbs.php b/administrator/components/com_media/view/medialist/tmpl/thumbs.php new file mode 100644 index 0000000000000..c193c0d7f3439 --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/thumbs.php @@ -0,0 +1,75 @@ + +
    +
    +

    + + state->get('folder') != '') : ?> + get($path, 'images') . '/' . $this->state->get('folder'); ?> + + get($path, 'images'); ?> + +

    +
    + +
      + loadTemplate('up'); + ?> + + folders); $i < $n; $i++) : + $this->setFolder($i); + echo $this->loadTemplate('folder'); + endfor; ?> + + documents); $i < $n; $i++) : + $this->setDoc($i); + echo $this->loadTemplate('doc'); + endfor; ?> + + images); $i < $n; $i++) : + $this->setImage($i); + echo $this->loadTemplate('img'); + endfor; ?> + + videos); $i < $n; $i++) : + $this->setVideo($i); + echo $this->loadTemplate('video'); + endfor; ?> + + audios); $i < $n; $i++) : + $this->setAudio($i); + echo $this->loadTemplate('audio'); + endfor; ?> + + + + + +
    +
    + + + + + \ No newline at end of file diff --git a/administrator/components/com_media/view/medialist/tmpl/thumbs_audio.php b/administrator/components/com_media/view/medialist/tmpl/thumbs_audio.php new file mode 100644 index 0000000000000..6d9b74876af90 --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/thumbs_audio.php @@ -0,0 +1,57 @@ +_tmp_audio->title . 'Modal'; +JHTML::_('behavior.modal'); +$dispatcher = JEventDispatcher::getInstance(); +$dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_audio, &$params)); +?> +
  • + +
  • + + +
    +
    + + + +
    +
    + +trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_audio, &$params)); diff --git a/administrator/components/com_media/view/medialist/tmpl/thumbs_doc.php b/administrator/components/com_media/view/medialist/tmpl/thumbs_doc.php new file mode 100644 index 0000000000000..89bd282383ebb --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/thumbs_doc.php @@ -0,0 +1,39 @@ +trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_doc, &$params)); +?> +
  • + +
  • +trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_doc, &$params)); diff --git a/administrator/components/com_media/view/medialist/tmpl/thumbs_folder.php b/administrator/components/com_media/view/medialist/tmpl/thumbs_folder.php new file mode 100644 index 0000000000000..a13a7b5661dc1 --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/thumbs_folder.php @@ -0,0 +1,33 @@ + +
  • + +
  • diff --git a/administrator/components/com_media/view/medialist/tmpl/thumbs_img.php b/administrator/components/com_media/view/medialist/tmpl/thumbs_img.php new file mode 100644 index 0000000000000..9070e2c7356c0 --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/thumbs_img.php @@ -0,0 +1,48 @@ +trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_img, &$params)); +?> + +
  • +
    +
    + + authorise('core.delete', 'com_media')):?> + + + + +
    + +
    +
    + _tmp_img->path_relative, JText::sprintf('COM_MEDIA_IMAGE_TITLE', $this->_tmp_img->title, JHtml::_('number.bytes', $this->_tmp_img->size)), array('width' => $this->_tmp_img->width_150, 'height' => $this->_tmp_img->height_150)); ?> +
    +
    +
    + _tmp_img->title, 12, false); ?> + + + + authorise('core.edit', 'com_media')):?> + + + + +
    +
    +
    +
  • +trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_img, &$params)); diff --git a/administrator/components/com_media/view/medialist/tmpl/thumbs_up.php b/administrator/components/com_media/view/medialist/tmpl/thumbs_up.php new file mode 100644 index 0000000000000..9cfe8b94f7dea --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/thumbs_up.php @@ -0,0 +1,29 @@ + +state->get('folder') != '') : ?> +
  • +
    +
    +
    + + +
    +
    +   +
    +
    + ... +
    +
    +
    +
  • + diff --git a/administrator/components/com_media/view/medialist/tmpl/thumbs_video.php b/administrator/components/com_media/view/medialist/tmpl/thumbs_video.php new file mode 100644 index 0000000000000..0f1589f9cd4f1 --- /dev/null +++ b/administrator/components/com_media/view/medialist/tmpl/thumbs_video.php @@ -0,0 +1,57 @@ +_tmp_video->title . 'Modal'; +JHTML::_('behavior.modal'); +$dispatcher = JEventDispatcher::getInstance(); +$dispatcher->trigger('onContentBeforeDisplay', array('com_media.file', &$this->_tmp_video, &$params)); +?> +
  • + +
  • + + +
    +
    + + + +
    +
    + +trigger('onContentAfterDisplay', array('com_media.file', &$this->_tmp_video, &$params)); diff --git a/administrator/language/en-GB/en-GB.com_media.ini b/administrator/language/en-GB/en-GB.com_media.ini index a23c5b84bb403..98d29ea86afb9 100644 --- a/administrator/language/en-GB/en-GB.com_media.ini +++ b/administrator/language/en-GB/en-GB.com_media.ini @@ -11,32 +11,104 @@ COM_MEDIA_CAPTION="Caption" COM_MEDIA_CAPTION_CLASS_LABEL="Caption Class" COM_MEDIA_CAPTION_CLASS_DESC="This will apply the entered class to the '
    ' element. For example: 'text-left', 'text-right', 'text-center'." COM_MEDIA_CLEAR_LIST="Clear List" +COM_MEDIA_CLOSE="Close" COM_MEDIA_CONFIGURATION="Media Manager Options" +COM_MEDIA_COPY_COMPLETE="Copy Complete: %s" +COM_MEDIA_COPY_MEDIA="Copy Media" +COM_MEDIA_COPY_TO_DIRECTORY="Copy To: " COM_MEDIA_CREATE_COMPLETE="Create Complete: %s" COM_MEDIA_CREATE_FOLDER="Create Folder" COM_MEDIA_CREATE_NEW_FOLDER="Create New Folder" COM_MEDIA_CURRENT_PROGRESS="Current progress" COM_MEDIA_DELETE_COMPLETE="Delete Complete: %s" +COM_MEDIA_DELETE_MEDIA="Delete Media" +COM_MEDIA_DELETE_MEDIA_MSG="Are you sure you want to delete selected file(s)?" COM_MEDIA_DESCFTPTITLE="FTP Login Details" COM_MEDIA_DESCFTP="To upload, change and delete media files, Joomla will most likely need your FTP account details. Please enter them in the form fields below." COM_MEDIA_DETAIL_VIEW="Detail View" COM_MEDIA_DIRECTORY="Directory" COM_MEDIA_DIRECTORY_UP="Directory Up" +COM_MEDIA_EDITOR="Media Editor" +COM_MEDIA_EDITOR_BUTTON_CROP="Crop" +COM_MEDIA_EDITOR_BUTTON_FILTER="Filter" +COM_MEDIA_EDITOR_BUTTON_FLIP="Flip" +COM_MEDIA_EDITOR_BUTTON_RESIZE="Resize" +COM_MEDIA_EDITOR_BUTTON_ROTATE="Rotate" +COM_MEDIA_EDITOR_BUTTON_THUMBS="Create Thumbnails" +COM_MEDIA_EDITOR_CROP_AREA_ERROR="Error in crop area. Select an area to crop" +COM_MEDIA_EDITOR_FILE_CROP_ERROR="Image cannot crop" +COM_MEDIA_EDITOR_FILE_CROP_SUCCESS="Cropping Successful" +COM_MEDIA_EDITOR_FILE_FILTER_ERROR="Failed to apply filter" +COM_MEDIA_EDITOR_FILE_FILTER_SUCCESS="Filtering Successful" +COM_MEDIA_EDITOR_FILE_FLIP_ERROR="Failed to flip" +COM_MEDIA_EDITOR_FILE_FLIP_SUCCESS="Flipping Successful" +COM_MEDIA_EDITOR_FILE_RESIZE_ERROR="Failed to resize" +COM_MEDIA_EDITOR_FILE_RESIZE_SUCCESS="Resizing Successful" +COM_MEDIA_EDITOR_FILE_ROTATE_ERROR="Failed to rotate" +COM_MEDIA_EDITOR_FILE_ROTATE_SUCCESS="Rotating Successful" +COM_MEDIA_EDITOR_FILE_SAVE_ERROR="Image Saving Failed" +COM_MEDIA_EDITOR_FILE_SAVE_SUCCESS="Image Saved" +COM_MEDIA_EDITOR_FILE_THUMBS_ERROR="Failed to create thumbnails" +COM_MEDIA_EDITOR_FILE_THUMBS_SUCCESS="Creating Thumbnails Successful" +COM_MEDIA_EDITOR_FILTER_IMAGE="Filter Image" +COM_MEDIA_EDITOR_FLIP_IMAGE="Flip Image" +COM_MEDIA_EDITOR_IMAGE_ANGLE="Angle" +COM_MEDIA_EDITOR_IMAGE_ANGLE_DIRECTION="Direction" +COM_MEDIA_EDITOR_IMAGE_FILTER_BRIGHTNESS="Brightness" +COM_MEDIA_EDITOR_IMAGE_FILTER_CONTRAST="Contrast" +COM_MEDIA_EDITOR_IMAGE_FILTER_EDGE_DETECT="Edge Detect" +COM_MEDIA_EDITOR_IMAGE_FILTER_EMBOSS="Emboss" +COM_MEDIA_EDITOR_IMAGE_FILTER_GRAYSCALE="Grayscale" +COM_MEDIA_EDITOR_IMAGE_FILTER_NAME="Filter name" +COM_MEDIA_EDITOR_IMAGE_FILTER_NEGATE="Negate" +COM_MEDIA_EDITOR_IMAGE_FILTER_SKETCHY="Sketchy" +COM_MEDIA_EDITOR_IMAGE_FILTER_SMOOTH="Smooth" +COM_MEDIA_EDITOR_IMAGE_FILTER_VALUE="Filter value" +COM_MEDIA_EDITOR_IMAGE_FLIP_BOTH="Flip Both Sides" +COM_MEDIA_EDITOR_IMAGE_FLIP_HORIZONTAL="Flip Horizontally" +COM_MEDIA_EDITOR_IMAGE_FLIP_MODE="Flipping mode" +COM_MEDIA_EDITOR_IMAGE_FLIP_VERTICAL="Flip Vertically" +COM_MEDIA_EDITOR_IMAGE_HEIGHT="Image height" +COM_MEDIA_EDITOR_IMAGE_ROTATE_ANTICLOCKWISE="Anti-Clockwise" +COM_MEDIA_EDITOR_IMAGE_ROTATE_CLOCKWISE="Clockwise" +COM_MEDIA_EDITOR_IMAGE_THUMBS_CREATION_METHOD="Thumbnailing method" +COM_MEDIA_EDITOR_IMAGE_THUMBS_CROP="Crop" +COM_MEDIA_EDITOR_IMAGE_THUMBS_CROP_RESIZE="Crop Resize" +COM_MEDIA_EDITOR_IMAGE_THUMBS_FOLDER="Thumbnail folder" +COM_MEDIA_EDITOR_IMAGE_THUMBS_SCALE_FILL="Scale Fill" +COM_MEDIA_EDITOR_IMAGE_THUMBS_SCALE_FIT="Scale Fit" +COM_MEDIA_EDITOR_IMAGE_THUMBS_SCALE_INSIDE="Scale Inside" +COM_MEDIA_EDITOR_IMAGE_THUMBS_SCALE_OUTSIDE="Scale Outside" +COM_MEDIA_EDITOR_IMAGE_THUMBS_SIZE="Thumbnail size" +COM_MEDIA_EDITOR_IMAGE_WIDTH="Image width" +COM_MEDIA_EDITOR_ITEM_CHECKED_IN_FAILED="Checkin user failed" +COM_MEDIA_EDITOR_RESIZE_IMAGE="Resize Image" +COM_MEDIA_EDITOR_ROTATE_IMAGE="Rotate Image" +COM_MEDIA_EDITOR_THUMBS_IMAGE="Create Thumbnails" COM_MEDIA_ERROR_BAD_REQUEST="Bad Request" +COM_MEDIA_ERROR_BEFORE_COPY="Some errors occur before copying the media: %s" COM_MEDIA_ERROR_BEFORE_DELETE_0="Some error occurs before deleting the media." COM_MEDIA_ERROR_BEFORE_DELETE_1="An error occurs before deleting the media: %s" COM_MEDIA_ERROR_BEFORE_DELETE_MORE="Some errors occur before deleting the media: %s" +COM_MEDIA_ERROR_BEFORE_MOVE="Some errors occur before moving the media: %s" COM_MEDIA_ERROR_BEFORE_SAVE_0="Some error occurs before saving the media." COM_MEDIA_ERROR_BEFORE_SAVE_1="An error occurs before saving the media: %s" COM_MEDIA_ERROR_BEFORE_SAVE_MORE="Some errors occur before saving the media: %s" COM_MEDIA_ERROR_CREATE_NOT_PERMITTED="Create not permitted." -COM_MEDIA_ERROR_FILE_EXISTS="File already exists." +COM_MEDIA_ERROR_DATABASE_COPY="Error occoured while copying databse entry for: %s" +COM_MEDIA_ERROR_DATABASE_MOVE="Error occoured while change databse entry for: %s" +COM_MEDIA_ERROR_FILE_COPY="Error occoured while file copying: %s" +COM_MEDIA_ERROR_FILE_EXISTS="A file with this name already exists and the option to overwrite the file is set to no and/or the user is not authorised to delete files." +COM_MEDIA_ERROR_FILE_EXISTS_OVERWRITE="File successful overwritten." +COM_MEDIA_ERROR_FILE_MOVE="Error occoured while file moving: %s" +COM_MEDIA_ERROR_UNABLE_TO_COPY_FILE_WARNFILENAME="Unable to copy: %s." COM_MEDIA_ERROR_UNABLE_TO_CREATE_FOLDER_WARNDIRNAME="Unable to create directory. Directory name must only contain alphanumeric characters and no spaces." COM_MEDIA_ERROR_UNABLE_TO_BROWSE_FOLDER_WARNDIRNAME="Unable to browse: %s. Directory name must only contain alphanumeric characters and no spaces." COM_MEDIA_ERROR_UNABLE_TO_DELETE_FILE_WARNFILENAME="Unable to delete: %s. File name must only contain alphanumeric characters and no spaces." COM_MEDIA_ERROR_UNABLE_TO_DELETE_FOLDER_NOT_EMPTY="Unable to delete: %s. Folder is not empty!" COM_MEDIA_ERROR_UNABLE_TO_DELETE_FOLDER_WARNDIRNAME="Unable to delete: %s." -COM_MEDIA_ERROR_UNABLE_TO_DELETE=" Unable to delete: " +COM_MEDIA_ERROR_UNABLE_TO_DELETE="Unable to delete: " +COM_MEDIA_ERROR_UNABLE_TO_MOVE_FILE_WARNFILENAME="Unable to move: %s." COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE="Unable to upload file." COM_MEDIA_ERROR_UPLOAD_INPUT="Please input a file for upload" COM_MEDIA_ERROR_WARNFILENAME="File name must only contain alphanumeric characters and no spaces." @@ -50,10 +122,18 @@ COM_MEDIA_ERROR_WARNNOTEMPTY="Not empty!" COM_MEDIA_ERROR_WARNUPLOADTOOLARGE="Total size of upload exceeds the limit." COM_MEDIA_FIELD_CHECK_MIME_DESC="Use MIME Magic or Fileinfo to attempt to verify files. Try disabling this if you get invalid mime type errors." COM_MEDIA_FIELD_CHECK_MIME_LABEL="Check MIME Types" +COM_MEDIA_FIELD_CREATED_BY_ALIAS_DESC="Enter an alias to be displayed instead of the name of the user who created the media." +COM_MEDIA_FIELD_CREATED_BY_ALIAS_LABEL="Created by alias" +COM_MEDIA_FIELD_CREATED_BY_DESC="Select the name of the user who created the media." +COM_MEDIA_FIELD_CREATED_BY_LABEL="Created by" +COM_MEDIA_FIELD_CREATED_DESC="Created Date" +COM_MEDIA_FIELD_CREATED_LABEL="Created Date" COM_MEDIA_FIELD_IGNORED_EXTENSIONS_DESC="Ignored file extensions for MIME type checking and restricted uploads." COM_MEDIA_FIELD_IGNORED_EXTENSIONS_LABEL="Ignored Extensions" COM_MEDIA_FIELD_ILLEGAL_MIME_TYPES_DESC="A comma separated list of illegal MIME types for upload (blacklist)." COM_MEDIA_FIELD_ILLEGAL_MIME_TYPES_LABEL="Illegal MIME Types" +COM_MEDIA_FIELD_IMAGETEXT_DESC="To label the image" +COM_MEDIA_FIELD_IMAGETEXT_LABEL="Image Label" COM_MEDIA_FIELD_LEGAL_EXTENSIONS_DESC=" Extensions (file types) you are allowed to upload (comma separated)." COM_MEDIA_FIELD_LEGAL_EXTENSIONS_LABEL="Legal Extensions (File Types)" COM_MEDIA_FIELD_LEGAL_IMAGE_EXTENSIONS_DESC=" Image extensions (file types) you are allowed to upload (comma separated). These are used to check for valid image headers." @@ -62,6 +142,9 @@ COM_MEDIA_FIELD_LEGAL_MIME_TYPES_DESC="A comma separated list of legal MIME type COM_MEDIA_FIELD_LEGAL_MIME_TYPES_LABEL="Legal MIME Types" COM_MEDIA_FIELD_MAXIMUM_SIZE_DESC="The maximum size for an upload (in megabytes). Use zero for no limit. Note: your server has a maximum limit." COM_MEDIA_FIELD_MAXIMUM_SIZE_LABEL="Maximum Size (in MB)" +COM_MEDIA_FIELD_MODIFIED_DESC="The date and time that the media was last modified." +COM_MEDIA_FIELD_OVERWRITE_FILES_LABEL="Allow overwriting files" +COM_MEDIA_FIELD_OVERWRITE_FILES_DESC="If you set this to yes and the user has delete permissions you can overwrite a file that already exists. Please note that if you enable this option and the upload fails the old file can't be restored." COM_MEDIA_FIELD_PATH_FILE_FOLDER_DESC="Enter the path to the files folder relative to the root of your webspace. Warning! Changing to another path than the default 'images' may break your links. Note: Do not start the path with a slash!" COM_MEDIA_FIELD_PATH_FILE_FOLDER_LABEL="Path to Files Folder" COM_MEDIA_FIELD_PATH_IMAGE_FOLDER_DESC="Enter the path to the images folder relative to the root of your webspace. This path has to be the same as path to files (default) or to a subfolder of the path to file folder.. Note: Do not start the path with a slash!" @@ -71,6 +154,8 @@ COM_MEDIA_FIELD_RESTRICT_UPLOADS_LABEL="Restrict Uploads" COM_MEDIA_FILES="Files" COM_MEDIA_FILESIZE="File size" COM_MEDIA_FOLDER="Folder" +COM_MEDIA_FOLDER_CREATE_COMPLETE="Folder Create Complete: %s" +COM_MEDIA_FOLDER_DELETE_COMPLETE="Folder Delete Complete: %s" COM_MEDIA_FOLDERS="Media Folders" COM_MEDIA_FOLDERS_PATH_LABEL="Warning! Path Folder
    Changing the default 'Path to files folder' to another folder other than default 'images' may break your links.
    The 'Path to images' folder has to be the same or a subfolder of 'Path to files'." COM_MEDIA_IMAGE_DESCRIPTION="Image Description" @@ -81,14 +166,21 @@ COM_MEDIA_INSERT_IMAGE="Insert Image" COM_MEDIA_INSERT="Insert" COM_MEDIA_INVALID_REQUEST="Invalid Request" COM_MEDIA_MEDIA="Media" +COM_MEDIA_MOVE_COMPLETE="Move Complete: %s" +COM_MEDIA_MOVE_MEDIA="Move Media" +COM_MEDIA_MOVE_TO_DIRECTORY="Move To: " COM_MEDIA_NAME="Image Name" COM_MEDIA_NO_IMAGES_FOUND="No Images Found" COM_MEDIA_NOT_SET="Not Set" COM_MEDIA_OVERALL_PROGRESS="Overall Progress" COM_MEDIA_PIXEL_DIMENSIONS="Dimensions (px)" COM_MEDIA_START_UPLOAD="Start Upload" +COM_MEDIA_SUBMENU_MEDIA="Media" +COM_MEDIA_SUBMENU_CATEGORIES="Categories" COM_MEDIA_THUMBNAIL_VIEW="Thumbnail View" COM_MEDIA_TITLE="Image Title" +COM_MEDIA_UPLOADER_DRAGNDROP="Drag & Drop Uploader" +COM_MEDIA_UPLOADER_REGULAR="Regular Uploader" COM_MEDIA_UPLOAD_COMPLETE="Upload Complete: %s" COM_MEDIA_UPLOAD_FILES_NOLIMIT="Upload files (No maximum size)" COM_MEDIA_UPLOAD_FILES="Upload files (Maximum Size: %s MB)" diff --git a/components/com_media/media.php b/components/com_media/media.php index af999e2bf444f..a44c91bdb8000 100644 --- a/components/com_media/media.php +++ b/components/com_media/media.php @@ -14,5 +14,26 @@ $lang->load('com_media', JPATH_ADMINISTRATOR, null, false, true) || $lang->load('com_media', JPATH_SITE, null, false, true); +$input = JFactory::getApplication()->input; + +if ($input->get('view') == 'image' && $input->get('id') && $input->get('Itemid')) +{ + JLoader::registerPrefix('Media', JPATH_ADMINISTRATOR . '/components/com_media'); + JLoader::registerPrefix('Media', JPATH_SITE . '/components/com_media'); + JLoader::registerPrefix('Config', JPATH_SITE . '/components/com_config'); + + $paths = new SplPriorityQueue; + $paths->insert(JPATH_COMPONENT . '/view/' . '/tmpl', 'normal'); + + $model = new MediaModelEditor; + $view = new MediaViewHtml($model, $paths); + echo $view->render(); + + return; +} + +// Register Media prefix to load backend classes +JLoader::registerPrefix('Media', JPATH_ADMINISTRATOR . '/components/com_media'); + // Hand processing over to the admin base file require_once JPATH_COMPONENT_ADMINISTRATOR . '/media.php'; diff --git a/components/com_media/view/html.php b/components/com_media/view/html.php new file mode 100644 index 0000000000000..0a818849eac43 --- /dev/null +++ b/components/com_media/view/html.php @@ -0,0 +1,36 @@ +model->getState(); + + $this->id = $app->input->get('id'); + $this->item = $this->model->getItem($this->id); + + return parent::render(); + } +} diff --git a/components/com_media/view/tmpl/default.php b/components/com_media/view/tmpl/default.php new file mode 100644 index 0000000000000..a4a4e2445c161 --- /dev/null +++ b/components/com_media/view/tmpl/default.php @@ -0,0 +1,56 @@ +item->core_urls; +$imageName = $this->item->core_title; +?> + +
    + + +
    + +
    + + +
    + + +
    +
    + + +
    +
    + + +
    + +
    + + + +
    \ No newline at end of file diff --git a/language/en-GB/en-GB.com_media.ini b/language/en-GB/en-GB.com_media.ini index 47fdf03429d85..e2a29598b8c6c 100644 --- a/language/en-GB/en-GB.com_media.ini +++ b/language/en-GB/en-GB.com_media.ini @@ -12,6 +12,8 @@ COM_MEDIA_CAPTION_CLASS_DESC="This will apply the entered class to the ''; + . ' rel="{handler: \'iframe\', size: {x: 1200, y: 600}}">'; $html[] = JText::_('JLIB_FORM_BUTTON_SELECT') . '"); + this.filename = jQuery("
    ").appendTo(this.statusbar); + this.size = jQuery("
    ").appendTo(this.statusbar); + this.progressBar = jQuery("
    ").appendTo(this.statusbar); + this.abort = jQuery("×").appendTo(this.statusbar); + + jQuery("#upload-container").prepend(this.statusbar); + + this.setFileNameSize = function(name,size) + { + var sizeStr=""; + var sizeKB = size/1024; + if(parseInt(sizeKB) > 1024) + { + var sizeMB = sizeKB/1024; + sizeStr = sizeMB.toFixed(2)+" MB"; + } + else + { + sizeStr = sizeKB.toFixed(2)+" KB"; + } + + var shortName = name.slice(0,28); + + this.filename.html(shortName); + this.size.html(sizeStr); + } + this.setProgress = function(progress) + { + var progressBarWidth =progress*this.progressBar.width()/ 100; + this.progressBar.find('.bar').animate({ width: progressBarWidth }, 10).html(progress + "% "); + if(parseInt(progress) >= 100) + { + this.abort.find('span').addClass('badge-success').removeClass('badge-important'); + this.abort.find('span').html('OK'); + } + } + this.setProgressError = function(error) + { + this.progressBar.find('div:first').addClass('progress progress-danger').removeClass('progress'); + this.progressBar.find('.bar').animate({ width: this.progressBar.width() }, 10).html("
    " + error + "
    "); + this.abort.find('span').addClass('badge-important').removeClass('badge-success').html ("error"); + } + this.setAbort = function(jqxhr) + { + var sb = this.statusbar; + this.abort.click(function() + { + jqxhr.abort(); + sb.hide(); + }); + } +} +function handleFileUpload(files,obj) +{ + for (var i = 0; i < files.length; i++) + { + var fd = new FormData(); + fd.append('Filedata[]', files[i]); + fd.append('folder', document.getElementById('folder').value); + fd.append(document.getElementById('form-token').value, '1'); + + var status = new createStatusbar(obj); //To set progress. + + status.setFileNameSize(files[i].name,files[i].size); + sendFileToUploadController(fd,status); + } + + + +} +jQuery(function() +{ +var obj = jQuery("#dragandrophandler"); + +obj.on('dragenter', function (e) +{ + e.stopPropagation(); + e.preventDefault(); + jQuery(this).css('border', '2px solid #0B85A1'); +}); +obj.on('dragover', function (e) +{ + e.stopPropagation(); + e.preventDefault(); +}); +obj.on('drop', function (e) +{ + + jQuery(this).css('border', '2px dotted #0B85A1'); + e.preventDefault(); + var files = e.originalEvent.dataTransfer.files; + + //We need to send dropped files to Server + handleFileUpload(files,obj); +}); +jQuery(document).on('dragenter', function (e) +{ + e.stopPropagation(); + e.preventDefault(); +}); +jQuery(document).on('dragover', function (e) +{ + e.stopPropagation(); + e.preventDefault(); + obj.css('border', '2px dotted #0B85A1'); +}); +jQuery(document).on('drop', function (e) +{ + e.stopPropagation(); + e.preventDefault(); +}); + +// Reload folder iFrame when exit +jQuery('#uploadModal').on('hide', function () { + jQuery('#folderframe').attr('src', function (i, val) { + // Setting folder name in iFrame url + return val.replace(/&folder=.*&/,"&folder="+document.getElementById('folder').value+"&") ; + }); +}); + +}); + diff --git a/media/media/js/mediamanager.js b/media/media/js/mediamanager.js index 40ba9e285e6a1..1594ce2485ab5 100644 --- a/media/media/js/mediamanager.js +++ b/media/media/js/mediamanager.js @@ -27,6 +27,8 @@ this.frame = window.frames.folderframe; this.frameurl = this.frame.location.href; + + this.setTreeviewState(); }, /** @@ -37,8 +39,9 @@ * @return void */ submit: function( task ) { - form = this.frame.document.getElementById( 'mediamanager-form' ); + var form = this.frame.document.getElementById( 'mediamanager-form' ); form.task.value = task; + form.action += ('&controller=' + task); if ( $( '#username' ).length ) { form.username.value = $( '#username' ).val(); @@ -48,6 +51,37 @@ form.submit(); }, + /** + * Called when copy and move execution + * + * @param string task [description] + * + * @return void + */ + submitWithTargetPath: function(task) + { + var form = window.frames['folderframe'].document.getElementById('mediamanager-form'); + form.task.value = task; + form.action += ('&controller=' + task); + if ($('#username').length) { + form.username.value = $('#username').val(); + form.password.value = $('#password').val(); + } + var inp = document.createElement("input"); + inp.type = "hidden"; + inp.name = "targetPath"; + + var method = task.split('.')[1]; + if (method == "copy") { + inp.value = $('#copyTarget #folderlist').find(":selected").text(); + } else if (method == "move") { + inp.value = $('#moveTarget #folderlist').find(":selected").text(); + } + + form.appendChild(inp); + form.submit(); + }, + /** * [onloadframe description] * @@ -67,7 +101,7 @@ el.value = folder; } ); - this.folderpath.value = basepath + (folder ? '/' + folder : ''); + this.folderpath.val(basepath + (folder ? '/' + folder : '/')); q.folder = folder; @@ -81,7 +115,7 @@ a.query = query.join( '&' ); a.fragment = null; - $( '#uploadForm' ).attr( 'action', buildUri(a) ); +// $( '#uploadForm' ).attr( 'action', buildUri(a) ); $( '#' + viewstyle ).addClass( 'active' ); }, @@ -96,7 +130,7 @@ viewstyle = type; var folder = this.getFolder(); - this.setFrameUrl( 'index.php?option=com_media&view=mediaList&tmpl=component&folder=' + folder + '&layout=' + type ); + this.setFrameUrl( 'index.php?option=com_media&controller=media.display.medialist&view=medialist&tmpl=component&folder=' + folder + '&layout=' + type ); }, refreshFrame: function() { @@ -118,6 +152,28 @@ this.frame.location.href = this.frameurl; }, + + setTreeviewState: function(){ + // Load the value from localStorage + if (typeof(Storage) !== "undefined") + { + var $visible = localStorage.getItem('jsidebar'); + } + + // Need to convert the value to a boolean + $visible = ($visible == 'true') ? true : false; + + // Toggle according to j-sidebar class status or storage saved status + var classStatus = jQuery('#j-sidebar-container').attr('class'); + if(classStatus.contains('j-toggle-hidden') || $visible) + { + jQuery('#treeview').attr('hidden', true); + } + else + { + jQuery('#treeview').attr('hidden', false); + } + }, }; /** @@ -188,4 +244,3 @@ }); }( jQuery, window )); - diff --git a/media/media/js/mediamanager.min.js b/media/media/js/mediamanager.min.js index 3cb090c23759f..4e5fee21d94b0 100644 --- a/media/media/js/mediamanager.min.js +++ b/media/media/js/mediamanager.min.js @@ -1 +1 @@ -!function(e,t){"use strict";function r(t){var r={};return t=t||"",e.each(t.split(/[&;]/),function(e,t){var a=t.split("=");r[decodeURIComponent(a[0])]=2==a.length?decodeURIComponent(a[1]):null}),r}function a(t){var r={},a=t.match(/^(?:([^:\/?#.]+):)?(?:\/\/)?(([^:\/?#]*)(?::(\d*))?)((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[\?#]|$)))*\/?)?([^?#\/]*))?(?:\?([^#]*))?(?:#(.*))?/);return e.each(["uri","scheme","authority","domain","port","path","directory","file","query","fragment"],function(e,t){r[t]=a&&a[e]?a[e]:""}),r}function o(e){return e.scheme+"://"+e.domain+(e.port?":"+e.port:"")+(e.path?e.path:"/")+(e.query?"?"+e.query:"")+(e.fragment?"#"+e.fragment:"")}var n=t.MediaManager={initialize:function(){this.folderpath=e("#folderpath"),this.updatepaths=e("input.update-folder"),this.frame=window.frames.folderframe,this.frameurl=this.frame.location.href},submit:function(t){form=this.frame.document.getElementById("mediamanager-form"),form.task.value=t,e("#username").length&&(form.username.value=e("#username").val(),form.password.value=e("#password").val()),form.submit()},onloadframe:function(){this.frameurl=this.frame.location.href;var t,n,i=this.getFolder()||"",l=[],u=a(e("#uploadForm").attr("action")),f=r(u.query);this.updatepaths.each(function(e,t){t.value=i}),this.folderpath.value=basepath+(i?"/"+i:""),f.folder=i;for(t in f)f.hasOwnProperty(t)&&(n=f[t],l.push(t+(null===n?"":"="+n)));u.query=l.join("&"),u.fragment=null,e("#uploadForm").attr("action",o(u)),e("#"+viewstyle).addClass("active")},setViewType:function(t){e("#"+t).addClass("active"),e("#"+viewstyle).removeClass("active"),viewstyle=t;var r=this.getFolder();this.setFrameUrl("index.php?option=com_media&view=mediaList&tmpl=component&folder="+r+"&layout="+t)},refreshFrame:function(){this.setFrameUrl()},getFolder:function(){var e=r(this.frame.location.search.substring(1));return e.folder=void 0===e.folder?"":e.folder,e.folder},setFrameUrl:function(e){null!==e&&(this.frameurl=e),this.frame.location.href=this.frameurl}};e(function(){n.initialize(),document.updateUploader=function(){n.onloadframe()},n.onloadframe()})}(jQuery,window); \ No newline at end of file +(function(e,t){"use strict";function r(t){var n={};return t=t||"",e.each(t.split(/[&;]/),function(e,t){var r=t.split("=");n[decodeURIComponent(r[0])]=r.length==2?decodeURIComponent(r[1]):null}),n}function i(t){var n={},r=t.match(/^(?:([^:\/?#.]+):)?(?:\/\/)?(([^:\/?#]*)(?::(\d*))?)((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[\?#]|$)))*\/?)?([^?#\/]*))?(?:\?([^#]*))?(?:#(.*))?/);return e.each(["uri","scheme","authority","domain","port","path","directory","file","query","fragment"],function(e,t){n[t]=!r||!r[e]?"":r[e]}),n}function s(e){return e.scheme+"://"+e.domain+(e.port?":"+e.port:"")+(e.path?e.path:"/")+(e.query?"?"+e.query:"")+(e.fragment?"#"+e.fragment:"")}var n=t.MediaManager={initialize:function(){this.folderpath=e("#folderpath"),this.updatepaths=e("input.update-folder"),this.frame=window.frames.folderframe,this.frameurl=this.frame.location.href,this.setTreeviewState()},submit:function(t){var n=this.frame.document.getElementById("mediamanager-form");n.task.value=t,n.action+="&controller="+t,e("#username").length&&(n.username.value=e("#username").val(),n.password.value=e("#password").val()),n.submit()},submitWithTargetPath:function(t){var n=window.frames.folderframe.document.getElementById("mediamanager-form");n.task.value=t,n.action+="&controller="+t,e("#username").length&&(n.username.value=e("#username").val(),n.password.value=e("#password").val());var r=document.createElement("input");r.type="hidden",r.name="targetPath";var i=t.split(".")[1];i=="copy"?r.value=e("#copyTarget #folderlist").find(":selected").text():i=="move"&&(r.value=e("#moveTarget #folderlist").find(":selected").text()),n.appendChild(r),n.submit()},onloadframe:function(){this.frameurl=this.frame.location.href;var t=this.getFolder()||"",n=[],s=i(e("#uploadForm").attr("action")),o=r(s.query),u,a;this.updatepaths.each(function(e,n){n.value=t}),this.folderpath.val(basepath+(t?"/"+t:"/")),o.folder=t;for(u in o){if(!o.hasOwnProperty(u))continue;a=o[u],n.push(u+(a===null?"":"="+a))}s.query=n.join("&"),s.fragment=null,e("#"+viewstyle).addClass("active")},setViewType:function(t){e("#"+t).addClass("active"),e("#"+viewstyle).removeClass("active"),viewstyle=t;var n=this.getFolder();this.setFrameUrl("index.php?option=com_media&controller=media.display.medialist&view=medialist&tmpl=component&folder="+n+"&layout="+t)},refreshFrame:function(){this.setFrameUrl()},getFolder:function(){var e=r(this.frame.location.search.substring(1));return e.folder=e.folder===undefined?"":e.folder,e.folder},setFrameUrl:function(e){e!==null&&(this.frameurl=e),this.frame.location.href=this.frameurl},setTreeviewState:function(){if(typeof Storage!="undefined")var e=localStorage.getItem("jsidebar");e=e=="true"?!0:!1;var t=jQuery("#j-sidebar-container").attr("class");t.contains("j-toggle-hidden")||e?jQuery("#treeview").attr("hidden",!0):jQuery("#treeview").attr("hidden",!1)}};e(function(){n.initialize(),document.updateUploader=function(){n.onloadframe()},n.onloadframe()})})(jQuery,window); \ No newline at end of file diff --git a/media/media/js/popup-imagemanager.js b/media/media/js/popup-imagemanager.js index 7dab2b3f8c390..5548f4102209d 100644 --- a/media/media/js/popup-imagemanager.js +++ b/media/media/js/popup-imagemanager.js @@ -43,6 +43,7 @@ var ImageManager = this.ImageManager = { this.upbutton = document.getElementById('upbutton'); $(this.upbutton).off('click'); $(this.upbutton).on('click', function(){ ImageManager.upFolder(); }); + }, onloadimageview: function() @@ -149,7 +150,7 @@ var ImageManager = this.ImageManager = { break; } } - this.frame.location.href='index.php?option=com_media&view=imagesList&tmpl=component&folder=' + folder + '&asset=' + asset + '&author=' + author; + this.frame.location.href='index.php?option=com_media&view=imageslist&controller=media.display.imageslist&tmpl=component&folder=' + folder + '&asset=' + asset + '&author=' + author; }, getFolder: function() { @@ -265,3 +266,4 @@ var ImageManager = this.ImageManager = { jQuery(function(){ ImageManager.initialize(); }); + diff --git a/media/system/css/jquery.Jcrop.min.css b/media/system/css/jquery.Jcrop.min.css index edc76b2b3f435..a3ff4b53f1aae 100644 --- a/media/system/css/jquery.Jcrop.min.css +++ b/media/system/css/jquery.Jcrop.min.css @@ -1,6 +1,6 @@ /* jquery.Jcrop.min.css v0.9.12 (build:20130126) */ .jcrop-holder{direction:ltr;text-align:left;} -.jcrop-vline,.jcrop-hline{background:#FFF url(Jcrop.gif);font-size:0;position:absolute;} +.jcrop-vline,.jcrop-hline{background:#FFF url(../images/Jcrop.gif);font-size:0;position:absolute;} .jcrop-vline{height:100%;width:1px!important;} .jcrop-vline.right{right:0;} .jcrop-hline{height:1px!important;width:100%;} diff --git a/media/system/images/Jcrop.gif b/media/system/images/Jcrop.gif new file mode 100644 index 0000000000000..72ea7ccb5321d Binary files /dev/null and b/media/system/images/Jcrop.gif differ diff --git a/plugins/editors-xtd/image/image.php b/plugins/editors-xtd/image/image.php index 0177692e91ddb..235debc0d237b 100644 --- a/plugins/editors-xtd/image/image.php +++ b/plugins/editors-xtd/image/image.php @@ -12,7 +12,9 @@ /** * Editor Image buton * - * @since 1.5 + * @package Joomla.Plugin + * @subpackage Editors-xtd.image + * @since 1.5 */ class PlgButtonImage extends JPlugin { @@ -51,7 +53,8 @@ public function onDisplay($name, $asset, $author) || (count($user->getAuthorisedCategories($extension, 'core.edit')) > 0) || (count($user->getAuthorisedCategories($extension, 'core.edit.own')) > 0 && $author == $user->id)) { - $link = 'index.php?option=com_media&view=images&tmpl=component&e_name=' . $name . '&asset=' . $asset . '&author=' . $author; + $link = 'index.php?option=com_media&view=images&controller=media.display.images&tmpl=component&e_name=' . $name + . '&asset=' . $asset . '&author=' . $author; JHtml::_('behavior.modal'); $button = new JObject; $button->modal = true; @@ -59,7 +62,7 @@ public function onDisplay($name, $asset, $author) $button->link = $link; $button->text = JText::_('PLG_IMAGE_BUTTON_IMAGE'); $button->name = 'picture'; - $button->options = "{handler: 'iframe', size: {x: 800, y: 500}}"; + $button->options = "{handler: 'iframe', size: {x: 1100, y: 600}}"; return $button; }