mediatheque

This commit is contained in:
armansansd
2023-07-18 10:47:46 +01:00
commit 4b7c97a02e
3044 changed files with 544089 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
.DS_Store
.php_cs.cache
+83
View File
@@ -0,0 +1,83 @@
<?php
/**
* This file represents the configuration for Code Sniffing PSR-2-related
* checks of coding guidelines and is based on a template from the news extension
* by Georg Ringer for the TYPO3 CMS.
*
* Install @fabpot's great php-cs-fixer tool via
*
* $ composer global require friendsofphp/php-cs-fixer
*
* And then simply run
*
* $ php-cs-fixer fix --config .php_cs
*
* For more information read:
* http://www.php-fig.org/psr/psr-2/
* http://cs.sensiolabs.org
*/
if (PHP_SAPI !== 'cli') {
die('This script supports command line usage only. Please check your command.');
}
// Define in which folders to search and which folders to exclude
// Exclude some directories that are excluded by Git anyways to speed up the sniffing
$finder = PhpCsFixer\Finder::create()
->exclude('vendor/')
->in(__DIR__);
// Return a Code Sniffing configuration using
// all sniffers needed for PSR-2
// and additionally:
// - Remove leading slashes in use clauses.
// - PHP single-line arrays should not have trailing comma.
// - Single-line whitespace before closing semicolon are prohibited.
// - Remove unused use statements in the PHP source code
// - Ensure Concatenation to have at least one whitespace around
// - Remove trailing whitespace at the end of blank lines.
return PhpCsFixer\Config::create()
->setRiskyAllowed(true)
->setRules([
'@PSR2' => true,
'align_multiline_comment' => [
'comment_type' => 'all_multiline',
],
'array_syntax' => [
'syntax' => 'short'
],
'binary_operator_spaces' => [
'default' => 'single_space'
],
'concat_space' => [
'spacing' => 'one'
],
'function_typehint_space' => true,
'hash_to_slash_comment' => true,
'lowercase_cast' => true,
'native_function_casing' => true,
'no_alias_functions' => true,
'no_blank_lines_after_phpdoc' => true,
'no_empty_statement' => true,
'no_extra_consecutive_blank_lines' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_short_bool_cast' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_unused_imports' => true,
'no_unneeded_control_parentheses' => true,
'no_whitespace_in_blank_line' => true,
'ordered_imports' => true,
'phpdoc_no_empty_return' => true,
'phpdoc_no_package' => false,
'phpdoc_scalar' => true,
'phpdoc_trim' => true,
'return_type_declaration' => [
'space_before' => 'none'
],
'self_accessor' => true,
'single_quote' => true,
'standardize_not_equals' => true,
'whitespace_after_comma_in_array' => true,
])
->setFinder($finder);
+37
View File
@@ -0,0 +1,37 @@
# v.1.1.0
## 05-06-2020
1. [](#new)
* Page specific media metadata fields can be added to a pages frontmatter (see README --> Configuration)
2. [](#improved)
* meta.yaml file will not be created upon upload anymore: this allows the creation of the file with the setting media.auto_metadata_exif turned on (in Admin Plugin 1.9); in Admin Plugin 1.10 it did not work anyway **NOTE: in Admin Plugin 1.10 with setting media.auto_metadata_exif turned on, make sure to save the page with a newly uploaded image before adding other metadata using this plugin**
# v1.0.2
## 16-04-2020
1. [](#improved)
* The button next to a media file will now also be translated. It was hard-coded to English before.
# v1.0.1
## 10-04-2020
1. [](#bugfix)
* meta.yaml file will now be created for an already uploaded media file that did not have an associated meta.yaml file before
# v1.0.0
## 20-03-2020
1. [](#improved)
* using core technology (Grav\Common\Yaml) for parsing and writing the meta.yaml files  kudos to https://github.com/renards for adding crucial parts to the code
# v0.9.1
## 16-03-2020
1. [](#bugfix)
* adding /vendor/ and composer.lock, needed for composer autoload functionality
# v0.9.0
## 15-03-2020
1. [](#new)
* Initial release
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2020 Clive Beckett
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+90
View File
@@ -0,0 +1,90 @@
# Admin Addon Media Metadata Plugin
The **Admin Addon Media Metadata** Plugin is an extension for the [Grav CMS](http://github.com/getgrav/grav) [Admin plugin](https://github.com/getgrav/grav-plugin-admin). It lets you add and **edit metadata for media files** in the Page Media browser.
The Admin plugin has not been offering a feature like this yet. In order to add/edit metadata e.g. for an image you had to create a [image.filename].meta.yaml for the image in your file browser and edit it in a text editor.
## Usage and Features
- the plugin will create and edit [mediafile].meta.yaml files in your page folder via a simple form in the Admin plugin
- by default you can add/edit a **title,** **alt** text, and a **caption** see *Configuration* section below on how to adapt this for your Grav installation
- multiline text can be added (e.g. for caption)
- in case you are storing additional, manually added data in your [mediafile].meta.yaml file, it will not be overwritten even if the form does not let you change it
### How to use it
*(see also screenshots below)*
1. hover any file in your Page Media section
2. hit the small «i» button to open the metadata form *(the regular «i» button which just showed the metadata will be overwritten by the plugin)*
### NOTE on setting “Auto metadata from Exif”
If your system is set to automatically write EXIF metadata
`(system.yaml → media.auto_metadata_exif: true)`
- On **Admin Plugin 1.10:**
Please **save the page** after uploading an image and **before** you write additional metadata using this plugin. On saving the page, the Admin Plugin will create the meta.yaml file including the EXIF data but it wont do so if a meta.yaml file already exists.
- On **Admin Plugin 1.9** and **admin-addon-media-metadata >= 1.1.0:**
Theres no problem here: the EXIF data will be written immediately upon upload whereas this plugin now only writes or edits meta.yaml files when needed.
## Installation
### Grav Package Manager (GPM)
If you can access your Grav installation via the command line, install the plugin by typing the following from your Grav root:
```
bin/gpm install admin-addon-media-metadata
```
### Admin Tool Web Interface
In the **Plugins** section, hit the **[+ Add]** button, search for Admin Addon Media Metadata and install.
### Manual Installation
To install the plugin manually, download the ZIP version of the latest release of this repository and unzip it under `/your/site/grav/user/plugins`. Then rename the folder to `admin-addon-media-metadata`. You can find these files on [GitHub](https://github.com/clivebeckett/grav-plugin-admin-addon-media-metadata/releases).
## Configuration
The default fields in the metadata form are alt, title, and caption. If you want to add more data to your meta.yaml files, please copy
`user/plugins/admin-addon-media-metadata/admin-addon-media-metadata.yaml` to
`user/config/plugins/admin-addon-media-metadata.yaml`
and add more form fields to the form by updating the copy. E.g. if you want to add a field for a web link, you might add the following lines:
```
- type: text
label: Web link
name: weblink
placeholder: https://domain.tld/
```
The URL field will be available in your metadata form and youll be able edit the information.
### Additional Page Specific Metadata Fields (v1.1 and later)
You may also add page specific fields to a pages frontmatter. *Note: The fields will be added to the form, not override the ones from the above mentioned config files:*
```
admin-addon-media-metadata:
metadata_form:
fields:
-
type: text
label: 'Yet another field'
name: yetAnotherField
placeholder: 'yet yet yet'
```
## Credits
I have based the plugin on Dávid Szabó’s [Admin Addon Media Rename plugin](https://github.com/david-szabo97/grav-plugin-admin-addon-media-rename). Much of the code would not have been possible for me without Dávids work.
[@renards](https://github.com/renards) helped a lot in replacing my original self-written Yaml parsing and writing code with Grav core technology and thus made version 1.0.0 possible.
## Screenshots
![](assets/1-open-form.jpg)
![](assets/2-form-opened.jpg)
@@ -0,0 +1,40 @@
span[data-dz-name] {
cursor: text;
}
.dz-metadata-edit {
display: none;
position: absolute;
width: 25px;
height: 25px;
right: -26px;
font-size: 0;
cursor: pointer;
background: #ededed;
/* bottom: 25px; */
top: 49px;
}
.dz-metadata-edit:after {
text-align: center;
display: block;
font-family: FontAwesome;
font-size: 18px;
line-height: 25px;
/* content: "\f044"; */
content: "\f05a";
color: #737c81;
}
.dz-metadata-edit:hover:after {
color: #0082ba;
}
.dropzone .dz-preview:hover .dz-metadata-edit {
display: block;
}
div.form-label { padding-right: 1rem; }
[data-remodal-id=modal-admin-addon-media-metadata] h1 { line-height: 1; }
form h1 span.header { }
form h1 span.filename { font-size: 1rem; }
@@ -0,0 +1,113 @@
/**
* some of the code is based on the Admin Addon Media Rename by Dávid Szabó
* see https://github.com/david-szabo97/grav-plugin-admin-addon-media-rename
*/
$(function() {
adminAddonMediaMetadata.metadata = {};
var clickedElement;
var fileName;
var $elementName;
var modal;
var $modal;
var isPageMedia = false;
// Append modal
$('body').append(adminAddonMediaMetadata.MODAL);
$(document).off('click', '[data-dz-name], .dz-metadata-edit');
$(document).on('click', '[data-dz-name], .dz-metadata-edit', function(e) {
clickedElement = $(this);
modal = $.remodal.lookup[$('[data-remodal-id=modal-admin-addon-media-metadata]').data('remodal')];
$modal = modal.$modal;
modal.open();
// Populate fields
elementName = clickedElement.closest('.dz-preview').find('[data-dz-name]')
fileName = elementName.text();
$('[name=filename]', $modal).val(fileName);
if (mediaListOnLoad[fileName] !== undefined) {
for (var i = 0; i < metadataFormFields.length; i++) {
$('[name=' + metadataFormFields[i] + ']', $modal).val(mediaListOnLoad[fileName][metadataFormFields[i]]);
}
} else {
for (var i = 0; i < metadataFormFields.length; i++) {
$('[name=' + metadataFormFields[i] + ']', $modal).val('');
}
}
$modal.find('form span.filename').text(fileName);
// Reset loading state
$('.loading', $modal).addClass('hidden');
// $('.button', $modal).removeClass('hidden').css('visibility', 'hidden');
$('.button', $modal).removeClass('hidden');
isPageMedia = !clickedElement.closest('.dz-preview').hasClass('dz-no-editor');
$modal.find('.block-toggle').toggleClass('hidden', !isPageMedia);
$modal.find('.page-media-info').toggleClass('hidden', !isPageMedia);
$modal.find('.non-page-media-info').toggleClass('hidden', isPageMedia);
});
/**
* add the new data dynamically to mediaListOnLoad JSON object
* for newly uploaded media files as well as for “older” files, overwriting the data already in that JSON object
* and save it in the YAML file
* Variables from above ($(document).on), like fileName and $modal are still available
*/
$(document).on('click', '[data-remodal-id=modal-admin-addon-media-metadata] .button', function(e) {
// hiding the button and showing the loading icon
$('.loading', $modal).removeClass('hidden');
$('.button', $modal).addClass('hidden');
// create the file object for newly uploaded files
if (mediaListOnLoad[fileName] === undefined) {
mediaListOnLoad[fileName] = new Object();
mediaListOnLoad[fileName]['filename'] = fileName;
}
// Do request with JS Fetch API: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
var data = new FormData();
data.append('filename', fileName);
data.append('admin-nonce', GravAdmin.config.admin_nonce);
// add the new values to mediaListOnLoad (for later updates before page reload)
// append the new values to the FormData (data.append)
for (var i = 0; i < metadataFormFields.length; i++) {
var newVal = $('[name=' + metadataFormFields[i] + ']', $modal).val();
mediaListOnLoad[fileName][metadataFormFields[i]] = newVal;
data.append(metadataFormFields[i], newVal);
}
fetch(adminAddonMediaMetadata.PATH, { method: 'POST', body: data, credentials: 'same-origin' })
//.then(res => res.json())
.then(result => {
if (result.error) {
var alertModal = $.remodal.lookup[$('[data-remodal-id=modal-admin-addon-media-metadata-alert]').data('remodal')];
alertModal.open();
$('p', alertModal.$modal).html(result.error.msg);
return;
}
modal.close();
});
});
// adding the “edit metadata” button next to all media files
setInterval(function addMetadataButton() {
$('.dz-preview').each(function(i, dz) {
if ($(this).find('.dz-metadata-edit').length == 0) {
var editButton = document.createElement('a');
//editButton.href = 'javascript:undefined;';
editButton.title = adminAddonMediaMetadataButton;
editButton.className = 'dz-metadata-edit';
editButton.innerText = adminAddonMediaMetadataButton;
var fileName = $(this).find('[data-dz-name]').text();
editButton.setAttribute('data-filename', fileName);
$(this).append(editButton);
}
$(this).find('.dz-metadata').remove();
});
}, 1000);
});
@@ -0,0 +1,321 @@
<?php
namespace Grav\Plugin;
use Composer\Autoload\ClassLoader;
use Grav\Common\Page\Media;
use Grav\Common\Plugin;
use Grav\Common\Yaml;
use RocketTheme\Toolbox\File\File;
/**
* Class AdminAddonMediaMetadataPlugin
* some of the code is based on the Admin Addon Media Rename by Dávid Szabó
* see https://github.com/david-szabo97/grav-plugin-admin-addon-media-rename
* @package Grav\Plugin
*/
class AdminAddonMediaMetadataPlugin extends Plugin
{
const ROUTE = '/admin-addon-media-metadata';
const TASK_METADATA = 'AdminAddonMediaMetadataEdit';
/**
* @return array
*
* The getSubscribedEvents() gives the core a list of events
* that the plugin wants to listen to. The key of each
* array section is the event that the plugin listens to
* and the value (in the form of an array) contains the
* callable (or function) as well as the priority. The
* higher the number the higher the priority.
*/
public static function getSubscribedEvents()
{
return [
['autoload', 100000], // TODO: Remove when plugin requires Grav >=1.7
'onPluginsInitialized' => ['onPluginsInitialized', 0]
];
}
/**
* Composer autoload.
* is
* @return ClassLoader
*/
public function autoload(): ClassLoader
{
return require __DIR__ . '/vendor/autoload.php';
}
public function getPath()
{
return '/' . trim($this->grav['admin']->base, '/') . '/' . trim(self::ROUTE, '/');
}
public function buildBaseUrl()
{
return rtrim($this->grav['uri']->rootUrl(true), '/') . '/' . trim($this->getPath(), '/');
}
/**
* Initialize the plugin
*/
public function onPluginsInitialized()
{
if (!$this->isAdmin() || !$this->grav['user']->authenticated) {
return;
}
if ($this->grav['uri']->path() == $this->getPath()) {
$this->enable([
'onPagesInitialized' => ['processRenameRequest', 0]
]);
return;
}
$this->enable([
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0],
'onPagesInitialized' => ['onTwigExtensions', 0],
//'onAdminAfterAddMedia' => ['createMetaYaml', 0], // removing the call of this method: see method below
'onAdminTaskExecute' => ['editMetaDataFile', 0],
]);
}
public function onTwigTemplatePaths()
{
$this->grav['twig']->twig_paths[] = __DIR__ . '/templates';
}
public function onTwigExtensions()
{
$page = $this->grav['admin']->page(true);
if (!$page) {
return;
}
/**
* get metadata form field config from plugin admin-addon-media-metadata.yaml file
* or local override in user/config/plugins/admin-addon-media-metadata.yaml
* or from page frontmatter
*/
//$formFields = $this->config->get('plugins.admin-addon-media-metadata.metadata_form');
$config = $this->mergeConfig($page, true);
$formFields = $config->get('metadata_form');
/**
* list all needed data keys from the fields configuration
*/
$arrMetaKeys = $this->editableFields($formFields['fields']);
$path = $page->path();
$media = new Media($path);
$allMedia = $media->all();
$arrFiles = [];
$i = 0;
foreach ($allMedia as $filename => $file) {
$metadata = $file->meta();
$arrFiles[$filename] = [
'filename' => $filename,
];
/**
* for each file: write stored metadata for each editable field into an array
* this will be output as inline JS variable adminAddonMediaMetadata
*/
foreach ($arrMetaKeys as $metaKey => $info) {
$arrFiles[$filename][$metaKey] = $metadata->$metaKey;
}
$i++;
}
$jsArrFormFields = '';
$i = 0;
foreach ($arrMetaKeys as $metaKey => $info) {
$jsArrFormFields .= ($i > 0) ? ",'" . $metaKey . "'" : "'" . $metaKey . "'";
$i++;
}
$inlineJs = 'var metadataFormFields = [' . $jsArrFormFields . '];';
$inlineJs .= PHP_EOL . 'var mediaListOnLoad = ' . json_encode($arrFiles) . ';';
$modal = $this->grav['twig']->twig()->render('metadata-modal.html.twig', $formFields);
$jsConfig = [
'PATH' => $this->buildBaseUrl() . '/' . $page->route() . '/task:' . self::TASK_METADATA,
'MODAL' => $modal
];
$inlineJs .= PHP_EOL . 'var adminAddonMediaMetadata = ' . json_encode($jsConfig) . ';';
$inlineJs .= PHP_EOL . $this->grav['twig']->twig()->render('additionalInlineJS.html.twig');
$this->grav['assets']->addInlineJs($inlineJs, -1000);
$this->grav['assets']->addCss('plugin://admin-addon-media-metadata/admin-addon-media-metadata.css', -1000);
$this->grav['assets']->addJs('plugin://admin-addon-media-metadata/admin-addon-media-metadata.js', -1000);
}
public function editTest()
{
$this->outputError('blob');
}
/**
* writes metadata into the [mediafile].meta.yaml file
* creates the .meta.yaml file if it does not yet exist
*/
public function editMetaDataFile($e)
{
$method = $e['method'];
if ($method === 'task' . self::TASK_METADATA) {
$fileName = $_POST['filename'];
$pageObj = $this->grav['admin']->page();
$basePath = $pageObj->path() . DS;
$filePath = $basePath . $fileName;
/**
* temporarily removing the condition that checks for the media file to exist
* as in Admin plugin 1.10 a media file will be uploaded to a tmp folder first
* and moved to the page folder on saving the page
*
* there needs to be a better solution for this
*
* also: take care of system.yaml → media.auto_metadata_exif
* if set to TRUE, a meta.yaml with EXIF data will be written, but only if the meta.yaml does not yet exist
* in Admin 1.10 you need to save a page in order to have the meta.yaml file with EXIF data created
* in Admin 1.9 this is not a problem since this plugin now (>=1.1.0) writes metadata only when needed
*/
// if (!file_exists($filePath)) {
// $this->outputError($this->grav['language']->translate(['PLUGIN_ADMIN_ADDON_MEDIA_METADATA.ERRORS.MEDIA_FILE_NOT_FOUND', $filePath]));
// } else {
$metaDataFilePath = $filePath . '.meta.yaml';
/**
* get the list of form data from the fields configuration
*/
$arrMetaKeys = $this->editableFields();
if (file_exists($metaDataFilePath)) {
/**
* get array of all current metadata for the file
* this is to avoid overwriting data that has been added to the meta.yaml file in the file browser
*/
$storedMetaData = Yaml::parse(file_get_contents($metaDataFilePath));
/**
* overwrite the currently stored data for each field in the form
*/
foreach ($arrMetaKeys as $metaKey => $info) {
if (isset($_POST[$metaKey])) {
$storedMetaData[$metaKey] = $_POST[$metaKey];
}
}
} else {
/**
* create metaData in case the meta data file does not yet exist
*/
$storedMetaData = [];
foreach ($arrMetaKeys as $metaKey => $info) {
if (isset($_POST[$metaKey])) {
$storedMetaData[$metaKey] = $_POST[$metaKey];
} else {
$storedMetaData[$metaKey] = '';
}
}
}
/**
* Get an instance of the meta file and write the data to it
* @see \Grav\Common\Page\Media
*/
$metaDataFile = File::instance($metaDataFilePath);
$metaDataFile->save(Yaml::dump($storedMetaData));
//$this->outputError($newYamlText);
// }
}
}
/**
* this method will not be called in Admin Plugin v1.10 (up until rc.11 anyway)
* additionally, writing the YAML file on upload will meddle with the system functionality
* that writes exif data
* in Admin Plugin v1.9 this functionality writes the meta.yaml file
* on upload, this plugin will then just add the other metadata
* when writing the meta.yaml file upon upload the system functionality will be overwritten
* in Admin Plugin v1.10 you need to save the page before using this plugin on a file
* if you want the exif data to be stored
*/
/**
* creates an image.meta.yaml file
* this file will be deleted by the core when deleting an image
* will be called after a media file has been added (see onPluginsInitialized())
*/
// public function createMetaYaml()
// {
// $fileName = $_FILES['file']['name'];
//
// $pageObj = $this->grav['admin']->page();
// $basePath = $pageObj->path() . DS;
//
// $filePath = $basePath . $fileName;
// if (!file_exists($filePath)) {
// $this->outputError($this->grav['language']->translate(['PLUGIN_ADMIN_ADDON_MEDIA_METADATA.ERRORS.MEDIA_FILE_NOT_FOUND', $filePath]));
// } else {
// // TODO: do that only for image files?
// $metaDataFileName = $fileName . '.meta.yaml';
// $metaDataFilePath = $basePath . $metaDataFileName;
// if (!file_exists($metaDataFilePath)) {
// /**
// * get the list of form data from the fields configuration
// */
// $arrMetaKeys = $this->editableFields();
//
// $newMetaData = [];
// foreach ($arrMetaKeys as $metaKey => $info) {
// $newMetaData[$metaKey] = '';
// }
//
// /**
// * Get an instance of the meta file and write the data to it
// * @see \Grav\Common\Page\Media
// */
// $metaDataFile = File::instance($metaDataFilePath);
// $metaDataFile->save(Yaml::dump($newMetaData));
// }
// }
// }
/**
* return all editable fields from form configuration
*/
private function editableFields($fieldsConf = null)
{
if ($fieldsConf === null) {
$page = $this->grav['admin']->page(true);
if (!$page) {
return;
}
/**
* get metadata form field config from plugin admin-addon-media-metadata.yaml file
* or local override in user/config/plugins/admin-addon-media-metadata.yaml
* or from page frontmatter
*/
//$formFields = $this->config->get('plugins.admin-addon-media-metadata.metadata_form');
$config = $this->mergeConfig($page, true);
$formFields = $config->get('metadata_form');
$fieldsConf = $formFields['fields'];
}
$arrMetaKeys = [];
foreach ($fieldsConf as $singleFieldConf) {
if (isset($singleFieldConf['name'], $singleFieldConf['type']) && $singleFieldConf['name'] !== 'filename') {
$arrMetaKeys[$singleFieldConf['name']] = [
'name' => $singleFieldConf['name'],
'type' => $singleFieldConf['type']
];
}
}
return $arrMetaKeys;
}
public function outputError($msg)
{
header('HTTP/1.1 400 Bad Request');
die(json_encode(['error' => ['msg' => $msg]]));
}
}
@@ -0,0 +1,21 @@
enabled: true
metadata_form:
fields:
- type: hidden
title: PLUGIN_ADMIN_ADDON_MEDIA_METADATA.FILENAME
name: filename
readonly: true
- type: text
label: PLUGIN_ADMIN_ADDON_MEDIA_METADATA.TITLE
name: title
- type: text
label: PLUGIN_ADMIN_ADDON_MEDIA_METADATA.ALT
name: alt
- type: textarea
label: PLUGIN_ADMIN_ADDON_MEDIA_METADATA.CAPTION
name: caption
rows: 3
Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

+30
View File
@@ -0,0 +1,30 @@
name: Admin Addon Media Metadata
version: 1.1.0
description: 'This plugin is an addon for the Grav CMS Admin plugin and lets you add and edit metadata for media files'
icon: plug
author:
name: Clive Beckett
email: clive@musikinsnetz.de
homepage: https://github.com/clivebeckett/grav-plugin-admin-addon-media-metadata
keywords: grav, admin, plugin, metadata, image, alt, title, caption
bugs: https://github.com/clivebeckett/grav-plugin-admin-addon-media-metadata/issues
docs: https://github.com/clivebeckett/grav-plugin-admin-addon-media-metadata/blob/develop/README.md
license: MIT
dependencies:
- { name: grav, version: '1.5 - 1.7' }
- { name: admin, version: '1.8 - 1.10' }
form:
validation: loose
fields:
enabled:
type: toggle
label: PLUGIN_ADMIN.PLUGIN_STATUS
highlight: 1
default: 0
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
+29
View File
@@ -0,0 +1,29 @@
{
"name": "clivebeckett/admin-addon-media-metadata",
"type": "grav-plugin",
"description": "Add Metadata (title, alt, caption) to image files in admin plugin",
"keywords": ["plugin"],
"homepage": "https://github.com/clivebeckett/grav-plugin-admin-addon-media-metadata",
"license": "MIT",
"authors": [
{
"name": "Clive Beckett",
"email": "clive@musikinsnetz.de",
"role": "Developer"
}
],
"require": {
"php": ">=7.1.3"
},
"autoload": {
"psr-4": {
"Grav\\Plugin\\AdminAddonMediaMetadata\\": "classes/"
},
"classmap": ["admin-addon-media-metadata.php"]
},
"config": {
"platform": {
"php": "7.1.3"
}
}
}
+23
View File
@@ -0,0 +1,23 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b884fad27830ca91d1b5af86da9aff06",
"packages": [],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=7.1.3"
},
"platform-dev": [],
"platform-overrides": {
"php": "7.1.3"
},
"plugin-api-version": "1.1.0"
}
+11
View File
@@ -0,0 +1,11 @@
PLUGIN_ADMIN_ADDON_MEDIA_METADATA:
BUTTON: Metadaten ändern
FORM_HEADER: Metadaten für Mediendatei ändern
FILENAME: Dateiname
TITLE: Titel
ALT: Beschreibung für den Fall, dass die Datei nicht angezeigt werden kann (alternativer Text)
CAPTION: Bildunterschrift
WRITING_DATA: Metadaten werden geschrieben
WRITING_FAILED: Metadaten konnten nicht geschrieben werden
ERRORS:
MEDIA_FILE_NOT_FOUND: Die Mediendatei konnte nicht gefunden werden
+11
View File
@@ -0,0 +1,11 @@
PLUGIN_ADMIN_ADDON_MEDIA_METADATA:
BUTTON: Edit metadata
FORM_HEADER: Edit metadata for media file
FILENAME: Filename
TITLE: Title
ALT: Describe the media file for when it cant be displayed (alternative text)
CAPTION: Caption
WRITING_DATA: Writing metadata
WRITING_FAILED: Writing image metadata failed
ERRORS:
MEDIA_FILE_NOT_FOUND: The media file could not be found
+11
View File
@@ -0,0 +1,11 @@
PLUGIN_ADMIN_ADDON_MEDIA_METADATA:
BUTTON: Editer les métadonnées pour ce média
FORM_HEADER: Editer les métadonnées pour ce média
FILENAME: Nom du fichier
TITLE: Titre
ALT: Description du média lorsqu'il ne peut être affiché (texte alternatif)
CAPTION: Légende
WRITING_DATA: Ajout des métadonnées
WRITING_FAILED: Impossible d'ajouter les métadonnées
ERRORS:
MEDIA_FILE_NOT_FOUND: Le fichier du média ne peut être trouvé
@@ -0,0 +1,2 @@
var adminAddonMediaMetadataButton = '{{ 'PLUGIN_ADMIN_ADDON_MEDIA_METADATA.BUTTON'|t }}';
var adminAddonMediaMetadataLang = '{{ grav.user.language|default('en') }}';
@@ -0,0 +1,36 @@
<div class="remodal" data-remodal-id="modal-admin-addon-media-metadata" data-remodal-options="hashTracking: false">
<form method="post" onsubmit='return false;'>
<div class="block block-section">
<h1>
<span class="header">{{ "PLUGIN_ADMIN_ADDON_MEDIA_METADATA.FORM_HEADER"|t }}</span><br>
<span class="filename"></span>
</h1>
</div>
{% for field in fields %}
{% if field.type %}
{% set value = data.value(field.name) %}
<div class="block block-{{field.type}}">
{% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
</div>
{% endif %}
{% endfor %}
<div class="button-bar">
<div class="loading">
{{ "PLUGIN_ADMIN_ADDON_MEDIA_METADATA.WRITING_DATA"|t }} … <i class="fa fa-spinner fa-spin"></i>
</div>
<button class="button primary">{{ "PLUGIN_ADMIN.SAVE"|tu }}</button>
</div>
</form>
</div>
<div class="remodal" data-remodal-id="modal-admin-addon-media-metadata-alert" data-remodal-options="hashTracking: false">
<form method="post" onsubmit='return false;'>
<h1>{{ "PLUGIN_ADMIN_ADDON_MEDIA_METADATA.WRITING_FAILED"|t }}</h1>
<p class="bigger"></p>
<div class="button-bar">
<button data-remodal-action="confirm" class="button primary">{{ "PLUGIN_ADMIN.CONTINUE"|tu }}</button>
</div>
</form>
</div>
+7
View File
@@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit487bda5860f2ea416ef2181e18c0fcbf::getLoader();
+445
View File
@@ -0,0 +1,445 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}
+21
View File
@@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,10 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Grav\\Plugin\\AdminAddonMediaMetadataPlugin' => $baseDir . '/admin-addon-media-metadata.php',
);
@@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);
+10
View File
@@ -0,0 +1,10 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Grav\\Plugin\\AdminAddonMediaMetadata\\' => array($baseDir . '/classes'),
);
+55
View File
@@ -0,0 +1,55 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit487bda5860f2ea416ef2181e18c0fcbf
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit487bda5860f2ea416ef2181e18c0fcbf', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit487bda5860f2ea416ef2181e18c0fcbf', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit487bda5860f2ea416ef2181e18c0fcbf::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit487bda5860f2ea416ef2181e18c0fcbf
{
public static $prefixLengthsPsr4 = array (
'G' =>
array (
'Grav\\Plugin\\AdminAddonMediaMetadata\\' => 36,
),
);
public static $prefixDirsPsr4 = array (
'Grav\\Plugin\\AdminAddonMediaMetadata\\' =>
array (
0 => __DIR__ . '/../..' . '/classes',
),
);
public static $classMap = array (
'Grav\\Plugin\\AdminAddonMediaMetadataPlugin' => __DIR__ . '/../..' . '/admin-addon-media-metadata.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit487bda5860f2ea416ef2181e18c0fcbf::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit487bda5860f2ea416ef2181e18c0fcbf::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit487bda5860f2ea416ef2181e18c0fcbf::$classMap;
}, null, ClassLoader::class);
}
}
+1
View File
@@ -0,0 +1 @@
[]