mirror of
https://github.com/getgrav/grav-plugin-admin.git
synced 2025-10-30 09:56:11 +01:00
Introduce the mediapicker field (#1125)
Added a new `mediapicker` form field which allows to select a media from any page + Provided an option to control how parent select field displays
This commit is contained in:
@@ -32,6 +32,8 @@ define('LOGIN_REDIRECT_COOKIE', 'grav-login-redirect');
|
||||
|
||||
class Admin
|
||||
{
|
||||
const MEDIA_PAGINATION_INTERVAL = 20;
|
||||
|
||||
/**
|
||||
* @var Grav
|
||||
*/
|
||||
@@ -95,6 +97,16 @@ class Admin
|
||||
*/
|
||||
protected $permissions;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $load_additional_files_in_background = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $loading_additional_files_in_background = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -532,6 +544,28 @@ class Admin
|
||||
?: $this->grav['locator']->findResource("config://{$type}.yaml", true, true);
|
||||
$file = CompiledYamlFile::instance($filename);
|
||||
$obj->file($file);
|
||||
$data[$type] = $obj;
|
||||
} elseif (preg_match('|media-manager/|', $type)) {
|
||||
$filename = base64_decode(preg_replace('|media-manager/|', '', $type));
|
||||
|
||||
$file = File::instance($filename);
|
||||
|
||||
$obj = new \StdClass();
|
||||
$obj->title = $file->basename();
|
||||
$obj->path = $file->filename();
|
||||
$obj->file = $file;
|
||||
$obj->page = $this->grav['pages']->get(dirname($obj->path));
|
||||
|
||||
$filename = pathinfo($obj->title)['filename'];
|
||||
$filename = str_replace(['@3x', '@2x'], '', $filename);
|
||||
if (isset(pathinfo($obj->title)['extension'])) {
|
||||
$filename .= '.' . pathinfo($obj->title)['extension'];
|
||||
}
|
||||
|
||||
if ($obj->page && isset($obj->page->media()[$filename])) {
|
||||
$obj->metadata = new Data($obj->page->media()[$filename]->metadata());
|
||||
}
|
||||
|
||||
$data[$type] = $obj;
|
||||
} else {
|
||||
throw new \RuntimeException("Data type '{$type}' doesn't exist!");
|
||||
@@ -540,6 +574,17 @@ class Admin
|
||||
return $data[$type];
|
||||
}
|
||||
|
||||
protected function hasErrorMessage()
|
||||
{
|
||||
$msgs = $this->grav['messages']->all();
|
||||
foreach ($msgs as $msg) {
|
||||
if (isset($msg['scope']) && $msg['scope'] === 'error') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns blueprints for the given type.
|
||||
*
|
||||
@@ -1373,4 +1418,260 @@ class Admin
|
||||
return [$this->base, $this->location, $this->route];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the files list
|
||||
*
|
||||
* @todo allow pagination
|
||||
* @return array
|
||||
*/
|
||||
public function files($filtered = true, $page_index = 0)
|
||||
{
|
||||
$param_type = $this->grav['uri']->param('type');
|
||||
$param_date = $this->grav['uri']->param('date');
|
||||
$param_page = $this->grav['uri']->param('page');
|
||||
$param_page = str_replace('\\', '/', $param_page);
|
||||
|
||||
$files_cache_key = 'media-manager-files';
|
||||
|
||||
if ($param_type) {
|
||||
$files_cache_key .= "-{$param_type}";
|
||||
}
|
||||
if ($param_date) {
|
||||
$files_cache_key .= "-{$param_date}";
|
||||
}
|
||||
if ($param_page) {
|
||||
$files_cache_key .= "-{$param_page}";
|
||||
}
|
||||
|
||||
$page_files = null;
|
||||
|
||||
$cache_enabled = $this->grav['config']->get('plugins.admin.cache_enabled');
|
||||
if (!$cache_enabled) {
|
||||
$this->grav['cache']->setEnabled(true);
|
||||
}
|
||||
|
||||
$page_files = $this->grav['cache']->fetch(md5($files_cache_key));
|
||||
|
||||
if (!$cache_enabled) {
|
||||
$this->grav['cache']->setEnabled(false);
|
||||
}
|
||||
|
||||
if (!$page_files) {
|
||||
$page_files = [];
|
||||
$pages = $this->grav['pages'];
|
||||
|
||||
if ($param_page) {
|
||||
$page = $pages->dispatch($param_page);
|
||||
|
||||
$page_files = $this->getFiles('images', $page, $page_files, $filtered);
|
||||
$page_files = $this->getFiles('videos', $page, $page_files, $filtered);
|
||||
$page_files = $this->getFiles('audios', $page, $page_files, $filtered);
|
||||
$page_files = $this->getFiles('files', $page, $page_files, $filtered);
|
||||
} else {
|
||||
$allPages = $pages->all();
|
||||
|
||||
if ($allPages) foreach ($allPages as $page) {
|
||||
$page_files = $this->getFiles('images', $page, $page_files, $filtered);
|
||||
$page_files = $this->getFiles('videos', $page, $page_files, $filtered);
|
||||
$page_files = $this->getFiles('audios', $page, $page_files, $filtered);
|
||||
$page_files = $this->getFiles('files', $page, $page_files, $filtered);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($page_files) >= self::MEDIA_PAGINATION_INTERVAL) {
|
||||
$this->shouldLoadAdditionalFilesInBackground(true);
|
||||
}
|
||||
|
||||
if (!$cache_enabled) {
|
||||
$this->grav['cache']->setEnabled(true);
|
||||
}
|
||||
$this->grav['cache']->save(md5($files_cache_key), $page_files, 600); //cache for 10 minutes
|
||||
if (!$cache_enabled) {
|
||||
$this->grav['cache']->setEnabled(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (count($page_files) >= self::MEDIA_PAGINATION_INTERVAL) {
|
||||
$page_files = array_slice($page_files, $page_index * self::MEDIA_PAGINATION_INTERVAL, self::MEDIA_PAGINATION_INTERVAL);
|
||||
}
|
||||
|
||||
return $page_files;
|
||||
}
|
||||
|
||||
public function shouldLoadAdditionalFilesInBackground($status = null)
|
||||
{
|
||||
if ($status) {
|
||||
$this->load_additional_files_in_background = true;
|
||||
}
|
||||
|
||||
return $this->load_additional_files_in_background;
|
||||
}
|
||||
|
||||
public function loadAdditionalFilesInBackground($status = null)
|
||||
{
|
||||
if (!$this->loading_additional_files_in_background) {
|
||||
$this->loading_additional_files_in_background = true;
|
||||
$this->files(false, false);
|
||||
$this->shouldLoadAdditionalFilesInBackground(false);
|
||||
$this->loading_additional_files_in_background = false;
|
||||
}
|
||||
}
|
||||
|
||||
private function getFiles($type, $page, $page_files, $filtered)
|
||||
{
|
||||
$page_files = $this->getMediaOfType($type, $page, $page_files);
|
||||
|
||||
if ($filtered) {
|
||||
$page_files = $this->filterByType($page_files);
|
||||
$page_files = $this->filterByDate($page_files);
|
||||
}
|
||||
|
||||
return $page_files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the media of a type ('images' | 'audios' | 'videos' | 'files')
|
||||
*
|
||||
* @param string $type
|
||||
* @param Page\Page $page
|
||||
* @param array $files
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getMediaOfType($type, $page, $page_files) {
|
||||
if ($page) {
|
||||
|
||||
// $path = $page->path();
|
||||
$media = $page->media();
|
||||
$mediaOfType = $media->$type();
|
||||
|
||||
foreach($mediaOfType as $title => $file) {
|
||||
$page_files[] = [
|
||||
'title' => $title,
|
||||
'type' => $type,
|
||||
'page_route' => $page->route(),
|
||||
'file' => $file->higherQualityAlternative()
|
||||
];
|
||||
}
|
||||
|
||||
return $page_files;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter media by type
|
||||
*
|
||||
* @param array $filesFiltered
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function filterByType($filesFiltered)
|
||||
{
|
||||
$filter_type = $this->grav['uri']->param('type');
|
||||
if (!$filter_type) {
|
||||
return $filesFiltered;
|
||||
}
|
||||
|
||||
$filesFiltered = array_filter($filesFiltered, function ($file) use ($filter_type) {
|
||||
return $file['type'] == $filter_type;
|
||||
});
|
||||
|
||||
return $filesFiltered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter media by date
|
||||
*
|
||||
* @param array $filesFiltered
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function filterByDate($filesFiltered)
|
||||
{
|
||||
$filter_date = $this->grav['uri']->param('date');
|
||||
if (!$filter_date) {
|
||||
return $filesFiltered;
|
||||
}
|
||||
|
||||
$year = substr($filter_date, 0, 4);
|
||||
$month = substr($filter_date, 5, 2);
|
||||
|
||||
$filesFilteredByDate = [];
|
||||
|
||||
foreach($filesFiltered as $file) {
|
||||
$filedate = $this->fileDate($file['file']);
|
||||
$fileYear = $filedate->format('Y');
|
||||
$fileMonth = $filedate->format('m');
|
||||
|
||||
if ($fileYear == $year && $fileMonth == $month) {
|
||||
$filesFilteredByDate[] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
return $filesFilteredByDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DateTime object representation of a file modified date
|
||||
*
|
||||
* @param File $file
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
private function fileDate($file) {
|
||||
$datetime = new \DateTime();
|
||||
$datetime->setTimestamp($file->toArray()['modified']);
|
||||
return $datetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the files dates list to be used in the Media Files filter
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filesDates()
|
||||
{
|
||||
$files = $this->files(false);
|
||||
$dates = [];
|
||||
|
||||
foreach ($files as $file) {
|
||||
$datetime = $this->fileDate($file['file']);
|
||||
$year = $datetime->format('Y');
|
||||
$month = $datetime->format('m');
|
||||
|
||||
if (!isset($dates[$year])) {
|
||||
$dates[$year] = [];
|
||||
}
|
||||
|
||||
if (!isset($dates[$year][$month])) {
|
||||
$dates[$year][$month] = 1;
|
||||
} else {
|
||||
$dates[$year][$month]++;
|
||||
}
|
||||
}
|
||||
|
||||
return $dates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pages list to be used in the Media Files filter
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function pages()
|
||||
{
|
||||
$pages = $this->grav['pages']->all();
|
||||
|
||||
$pagesWithFiles = [];
|
||||
if ($pages) foreach ($pages as $page) {
|
||||
if (count($page->media()->all())) {
|
||||
$pagesWithFiles[] = $page;
|
||||
}
|
||||
}
|
||||
|
||||
return $pagesWithFiles;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user