mirror of
https://github.com/flextype/flextype.git
synced 2025-08-13 08:34:19 +02:00
Merge branch '428-files-api' into dev
# Conflicts: # src/flextype/bootstrap.php # src/flextype/config/settings.yaml
This commit is contained in:
1
.php_cs.cache
Normal file
1
.php_cs.cache
Normal file
@@ -0,0 +1 @@
|
||||
{"php":"7.2.20","version":"2.15.0","indent":" ","lineEnding":"\n","rules":{"blank_line_after_namespace":true,"braces":true,"class_definition":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_constants":true,"lowercase_keywords":true,"method_argument_space":{"on_multiline":"ensure_fully_multiline"},"no_break_comment":true,"no_closing_tag":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":true,"encoding":true,"full_opening_tag":true},"hashes":{"vendor\/flextype-components\/arr\/Arr.php":3460238454}}
|
31
api.md
Normal file
31
api.md
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
Warning: PHP Startup: Unable to load dynamic library 'curl' (tried: /usr/local/Cellar/php@7.2/7.2.20/lib/php/20170718/curl (dlopen(/usr/local/Cellar/php@7.2/7.2.20/lib/php/20170718/curl, 9): image not found), /usr/local/Cellar/php@7.2/7.2.20/lib/php/20170718/curl.so (dlopen(/usr/local/Cellar/php@7.2/7.2.20/lib/php/20170718/curl.so, 9): image not found)) in Unknown on line 0
|
||||
## Table of contents
|
||||
|
||||
- [\Flextype\Component\Arr\Arr](#class-flextypecomponentarrarr)
|
||||
|
||||
<hr />
|
||||
|
||||
### Class: \Flextype\Component\Arr\Arr
|
||||
|
||||
| Visibility | Function |
|
||||
|:-----------|:---------|
|
||||
| public static | <strong>average(</strong><em>array</em> <strong>$array</strong>, <em>int/\integer</em> <strong>$decimals</strong>)</strong> : <em>int/\Flextype\Component\Arr\double</em><br /><em>Returns the average value of the current array.</em> |
|
||||
| public static | <strong>createFromJson(</strong><em>\string</em> <strong>$json</strong>, <em>\boolean</em> <strong>$assoc=true</strong>, <em>\integer</em> <strong>$depth=512</strong>, <em>int/\integer</em> <strong>$options</strong>)</strong> : <em>array</em><br /><em>Create an new Array from JSON string.</em> |
|
||||
| public static | <strong>createFromString(</strong><em>\string</em> <strong>$str</strong>, <em>\string</em> <strong>$delimiter=null</strong>, <em>\string</em> <strong>$regEx=null</strong>)</strong> : <em>array</em><br /><em>Create an new Array object via string.</em> |
|
||||
| public static | <strong>delete(</strong><em>array</em> <strong>$array</strong>, <em>\string</em> <strong>$path</strong>)</strong> : <em>mixed</em><br /><em>Deletes an array value using "dot notation".</em> |
|
||||
| public static | <strong>dot(</strong><em>array</em> <strong>$array</strong>, <em>\string</em> <strong>$prepend=`''`</strong>)</strong> : <em>array</em><br /><em>Flatten a multi-dimensional associative array with dots.</em> |
|
||||
| public static | <strong>first(</strong><em>array</em> <strong>$array</strong>)</strong> : <em>mixed The first element</em><br /><em>Returns the first element of an array</em> |
|
||||
| public static | <strong>get(</strong><em>array</em> <strong>$array</strong>, <em>\string</em> <strong>$path</strong>, <em>mixed</em> <strong>$default=null</strong>)</strong> : <em>mixed</em><br /><em>Returns value from array using "dot notation". If the key does not exist in the array, the default value will be returned instead.</em> |
|
||||
| public static | <strong>isAssoc(</strong><em>array</em> <strong>$array</strong>)</strong> : <em>bool</em><br /><em>Returns TRUE if the array is associative and FALSE if not.</em> |
|
||||
| public static | <strong>keyExists(</strong><em>array</em> <strong>$array</strong>, <em>mixed</em> <strong>$path</strong>)</strong> : <em>bool</em><br /><em>Checks if the given dot-notated key exists in the array.</em> |
|
||||
| public static | <strong>last(</strong><em>array</em> <strong>$array</strong>)</strong> : <em>mixed The last element</em><br /><em>Returns the last element of an array</em> |
|
||||
| public static | <strong>overwrite(</strong><em>array</em> <strong>$array1</strong>, <em>array</em> <strong>$array2</strong>)</strong> : <em>array</em><br /><em>Overwrites an array with values from input arrays. Keys that do not exist in the first array will not be added!</em> |
|
||||
| public static | <strong>random(</strong><em>array</em> <strong>$array</strong>)</strong> : <em>mixed</em><br /><em>Returns a random value from an array.</em> |
|
||||
| public | <strong>reverse(</strong><em>array</em> <strong>$array</strong>, <em>\boolean</em> <strong>$preserve_keys=false</strong>)</strong> : <em>array</em><br /><em>Return an array with elements in reverse order. Non-numeric keys are not affected by this setting and will always be preserved.</em> |
|
||||
| public static | <strong>set(</strong><em>array</em> <strong>$array</strong>, <em>\string</em> <strong>$path</strong>, <em>mixed</em> <strong>$value</strong>)</strong> : <em>void</em><br /><em>Sets an array value using "dot notation".</em> |
|
||||
| public static | <strong>size(</strong><em>array</em> <strong>$array</strong>, <em>int/\integer</em> <strong>$mode</strong>)</strong> : <em>void</em><br /><em>Counts all elements in an array. COUNT_RECURSIVE (or 1), count will recursively count the array. This is particularly useful for counting all the elements of a multidimensional array. count does not detect infinite recursion.</em> |
|
||||
| public static | <strong>sort(</strong><em>array</em> <strong>$array</strong>, <em>\string</em> <strong>$field</strong>, <em>\string</em> <strong>$direction=`'ASC'`</strong>, <em>\Flextype\Component\Arr\const</em> <strong>$method</strong>)</strong> : <em>array</em><br /><em>Sorts a multi-dimensional array by a certain field path</em> |
|
||||
| public static | <strong>toJson(</strong><em>array</em> <strong>$array</strong>, <em>int/\integer</em> <strong>$options</strong>, <em>\integer</em> <strong>$depth=512</strong>)</strong> : <em>string The JSON string</em><br /><em>Converts an array to a JSON string</em> |
|
||||
| public static | <strong>undot(</strong><em>array</em> <strong>$array</strong>)</strong> : <em>array</em><br /><em>Expands a dot notation array into a full multi-dimensional array.</em> |
|
||||
|
@@ -26,7 +26,7 @@
|
||||
"doctrine/cache": "~1.10.0",
|
||||
"doctrine/collections": "~1.6.4",
|
||||
|
||||
"flextype-components/arr" : "1.2.5",
|
||||
"flextype-components/arr" : "1.2.8",
|
||||
"flextype-components/cookie" : "1.2.0",
|
||||
"flextype-components/date" : "1.1.0",
|
||||
"flextype-components/filesystem" : "2.0.6",
|
||||
@@ -77,8 +77,8 @@
|
||||
]
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "~6.0.0",
|
||||
"victorjonsson/markdowndocs": "dev-master",
|
||||
"doctrine/coding-standard": "7.0.2",
|
||||
"victorjonsson/markdowndocs": "^1.3",
|
||||
"phpstan/phpstan": "^0.11.19",
|
||||
"symfony/var-dumper": "^4.4"
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Flextype;
|
||||
|
||||
use Flextype\Component\Arr\Arr;
|
||||
use Flextype\Component\Filesystem\Filesystem;
|
||||
use Flextype\Component\Registry\Registry;
|
||||
use Flextype\Component\Session\Session;
|
||||
@@ -131,7 +132,12 @@ include_once 'dependencies.php';
|
||||
include_once 'endpoints/access/access.php';
|
||||
include_once 'endpoints/delivery/entries.php';
|
||||
include_once 'endpoints/delivery/registry.php';
|
||||
<<<<<<< HEAD
|
||||
include_once 'endpoints/delivery/config.php';
|
||||
=======
|
||||
include_once 'endpoints/delivery/media/files.php';
|
||||
include_once 'endpoints/delivery/media/folders.php';
|
||||
>>>>>>> 428-files-api
|
||||
include_once 'endpoints/management/entries.php';
|
||||
include_once 'endpoints/management/config.php';
|
||||
include_once 'endpoints/images/images.php';
|
||||
|
@@ -236,6 +236,17 @@ cors:
|
||||
expose: []
|
||||
credentials: false
|
||||
|
||||
# Media
|
||||
media:
|
||||
accept_file_types: 'gif, jpg, jpeg, png, ico, zip, tgz, txt, md, doc, docx, pdf, epub, xls, xlsx, ppt, pptx, mp3, ogg, wav, m4a, mp4, m4v, ogv, wmv, avi, webm, svg'
|
||||
max_file_size: 5000000
|
||||
safe_names: true
|
||||
image_width: 1600
|
||||
image_height: 0
|
||||
image_quality: 70
|
||||
max_image_width: null
|
||||
max_image_height: null
|
||||
|
||||
# Content APIs
|
||||
api:
|
||||
delivery:
|
||||
@@ -245,7 +256,11 @@ api:
|
||||
registry:
|
||||
enabled: true
|
||||
default_token:
|
||||
<<<<<<< HEAD
|
||||
config:
|
||||
=======
|
||||
files:
|
||||
>>>>>>> 428-files-api
|
||||
enabled: true
|
||||
default_token:
|
||||
management:
|
||||
|
@@ -14,6 +14,7 @@ use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\Common\Collections\Expr\Comparison;
|
||||
use Flextype\Component\Filesystem\Filesystem;
|
||||
use Flextype\Component\Session\Session;
|
||||
use Flextype\Component\Arr\Arr;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use function array_merge;
|
||||
use function count;
|
||||
@@ -391,6 +392,9 @@ class Entries
|
||||
// For each founded entry we should create $entries array.
|
||||
$entry = $this->fetch($uid);
|
||||
|
||||
// Flatten a multi-dimensional entries array with dots.
|
||||
$entry = Arr::dot($entry);
|
||||
|
||||
// Add entry into the entries
|
||||
$entries[$uid] = $entry;
|
||||
|
||||
@@ -483,6 +487,11 @@ class Entries
|
||||
// Gets a native PHP array representation of the collection.
|
||||
$entries = $entries->toArray();
|
||||
|
||||
// Magic is here... dot and undot for entries array
|
||||
// 1. Flatten a multi-dimensional entries array with dots.
|
||||
// 2. Restore entries array with dots into correct multi-dimensional entries array
|
||||
$entries = Arr::undot(Arr::dot($entries));
|
||||
|
||||
// Restore error_reporting
|
||||
error_reporting($oldErrorReporting);
|
||||
|
||||
|
328
src/flextype/core/Media/MediaFiles.php
Normal file
328
src/flextype/core/Media/MediaFiles.php
Normal file
@@ -0,0 +1,328 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Flextype (http://flextype.org)
|
||||
* Founded by Sergey Romanenko and maintained by Flextype Community.
|
||||
*/
|
||||
|
||||
namespace Flextype;
|
||||
|
||||
use Flextype\Component\Filesystem\Filesystem;
|
||||
use Flextype\Component\Arr\Arr;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
use Slim\Http\Environment;
|
||||
use Slim\Http\Uri;
|
||||
|
||||
class MediaFiles
|
||||
{
|
||||
/**
|
||||
* Flextype Dependency Container
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private $flextype;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function __construct($flextype)
|
||||
{
|
||||
$this->flextype = $flextype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a media file
|
||||
*
|
||||
* @param array $file Raw file data (multipart/form-data).
|
||||
* @param string $folder The folder you're targetting.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function create(array $file, string $folder)
|
||||
{
|
||||
$upload_folder = PATH['project'] . '/uploads/' . $folder . '/';
|
||||
$upload_metadata_folder = PATH['project'] . '/uploads/.meta/' . $folder . '/';
|
||||
|
||||
if (! Filesystem::has($upload_folder)) {
|
||||
Filesystem::createDir($upload_folder);
|
||||
}
|
||||
|
||||
if (! Filesystem::has($upload_metadata_folder)) {
|
||||
Filesystem::createDir($upload_metadata_folder);
|
||||
}
|
||||
|
||||
$accept_file_types = $this->flextype['registry']->get('flextype.settings.media.accept_file_types');
|
||||
$max_file_size = $this->flextype['registry']->get('flextype.settings.media.max_file_size');
|
||||
$safe_names = $this->flextype['registry']->get('flextype.settings.media.safe_names');
|
||||
$max_image_width = $this->flextype['registry']->get('flextype.settings.media.max_image_width');
|
||||
$max_image_height = $this->flextype['registry']->get('flextype.settings.media.max_image_height');
|
||||
|
||||
$exact = false;
|
||||
$chmod = 0644;
|
||||
$filename = null;
|
||||
$exif_data = [];
|
||||
|
||||
//
|
||||
// Tests if a successful upload has been made.
|
||||
//
|
||||
if (isset($file['error'])
|
||||
and isset($file['tmp_name'])
|
||||
and $file['error'] === UPLOAD_ERR_OK
|
||||
and is_uploaded_file($file['tmp_name'])) {
|
||||
//
|
||||
// Tests if upload data is valid, even if no file was uploaded.
|
||||
//
|
||||
if (isset($file['error'])
|
||||
and isset($file['name'])
|
||||
and isset($file['type'])
|
||||
and isset($file['tmp_name'])
|
||||
and isset($file['size'])) {
|
||||
//
|
||||
// Test if an uploaded file is an allowed file type, by extension.
|
||||
//
|
||||
if (strpos($accept_file_types, strtolower(pathinfo($file['name'], PATHINFO_EXTENSION))) !== false) {
|
||||
//
|
||||
// Validation rule to test if an uploaded file is allowed by file size.
|
||||
//
|
||||
if (($file['error'] != UPLOAD_ERR_INI_SIZE)
|
||||
and ($file['error'] == UPLOAD_ERR_OK)
|
||||
and ($file['size'] <= $max_file_size)) {
|
||||
//
|
||||
// Validation rule to test if an upload is an image and, optionally, is the correct size.
|
||||
//
|
||||
if (in_array(mime_content_type($file['tmp_name']), ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'])) {
|
||||
function validateImage($file, $max_image_width, $max_image_height, $exact)
|
||||
{
|
||||
try {
|
||||
// Get the width and height from the uploaded image
|
||||
list($width, $height) = getimagesize($file['tmp_name']);
|
||||
} catch (ErrorException $e) {
|
||||
// Ignore read errors
|
||||
}
|
||||
if (empty($width) or empty($height)) {
|
||||
// Cannot get image size, cannot validate
|
||||
return false;
|
||||
}
|
||||
if (!$max_image_width) {
|
||||
// No limit, use the image width
|
||||
$max_image_width = $width;
|
||||
}
|
||||
if (!$max_image_height) {
|
||||
// No limit, use the image height
|
||||
$max_image_height = $height;
|
||||
}
|
||||
if ($exact) {
|
||||
// Check if dimensions match exactly
|
||||
return ($width === $max_image_width and $height === $max_image_height);
|
||||
} else {
|
||||
// Check if size is within maximum dimensions
|
||||
return ($width <= $max_image_width and $height <= $max_image_height);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (validateImage($file, $max_image_width, $max_image_height, $exact) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!isset($file['tmp_name']) or !is_uploaded_file($file['tmp_name'])) {
|
||||
// Ignore corrupted uploads
|
||||
return false;
|
||||
}
|
||||
if ($filename === null) {
|
||||
// Use the default filename
|
||||
$filename = $file['name'];
|
||||
}
|
||||
if ($safe_names === true) {
|
||||
// Remove spaces from the filename
|
||||
$filename = $this->flextype['slugify']->slugify(pathinfo($filename)['filename']) . '.' . pathinfo($filename)['extension'];
|
||||
}
|
||||
if (!is_dir($upload_folder) or !is_writable(realpath($upload_folder))) {
|
||||
throw new \RuntimeException("Directory {$upload_folder} must be writable");
|
||||
}
|
||||
// Make the filename into a complete path
|
||||
$filename = realpath($upload_folder) . DIRECTORY_SEPARATOR . $filename;
|
||||
if (move_uploaded_file($file['tmp_name'], $filename)) {
|
||||
// Set permissions on filename
|
||||
chmod($filename, $chmod);
|
||||
|
||||
if (in_array(mime_content_type($filename), ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'])) {
|
||||
// open an image file
|
||||
$img = Image::make($filename);
|
||||
|
||||
// now you are able to resize the instance
|
||||
if ($this->flextype['registry']->get('plugins.admin.settings.entries.media.upload_images_width') > 0 && $this->flextype['registry']->get('plugins.admin.settings.entries.media.upload_images_height') > 0) {
|
||||
$img->resize($this->flextype['registry']->get('plugins.admin.settings.entries.media.upload_images_width'), $this->flextype['registry']->get('plugins.admin.settings.entries.media.upload_images_height'), function($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
});
|
||||
} elseif ($this->flextype['registry']->get('plugins.admin.settings.entries.media.upload_images_width') > 0) {
|
||||
$img->resize($this->flextype['registry']->get('plugins.admin.settings.entries.media.upload_images_width'), null, function($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
});
|
||||
} elseif ($this->flextype['registry']->get('plugins.admin.settings.entries.media.upload_images_height') > 0) {
|
||||
$img->resize(null, $this->flextype['registry']->get('plugins.admin.settings.entries.media.upload_images_height'), function($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
});
|
||||
}
|
||||
|
||||
// finally we save the image as a new file
|
||||
$img->save($filename, $this->flextype['registry']->get('plugins.admin.settings.entries.media.upload_images_quality'));
|
||||
|
||||
// destroy
|
||||
$img->destroy();
|
||||
|
||||
$headers = exif_read_data($filename);
|
||||
|
||||
$exif_data = [];
|
||||
|
||||
foreach ($headers['COMPUTED'] as $header => $value) {
|
||||
$exif_data[$header] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$metadata = ['title' => substr(basename($filename), 0, strrpos(basename($filename), '.')),
|
||||
'description' => '',
|
||||
'type' => mime_content_type($filename),
|
||||
'filesize' => Filesystem::getSize($filename),
|
||||
'uploaded_on' => time(),
|
||||
'exif' => $exif_data];
|
||||
|
||||
Filesystem::write($upload_metadata_folder . basename($filename) . '.yaml',
|
||||
$this->flextype['serializer']->encode($metadata, 'yaml'));
|
||||
|
||||
|
||||
// Return new file path
|
||||
return $filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch single file
|
||||
*
|
||||
* @param string $directory The directory to list.
|
||||
*
|
||||
* @return array A list of file metadata.
|
||||
*/
|
||||
public function fetchsingle(string $id) : array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
if (Filesystem::has($this->flextype['media_files_meta']->getFileMetaLocation($id))) {
|
||||
$result = $this->flextype['serializer']->decode(Filesystem::read($this->flextype['media_files_meta']->getFileMetaLocation($id)), 'yaml');
|
||||
|
||||
$result['filename'] = pathinfo(str_replace("/.meta", "", $this->flextype['media_files_meta']->getFileMetaLocation($id)))['filename'];
|
||||
$result['basename'] = explode(".", basename($this->flextype['media_files_meta']->getFileMetaLocation($id)))[0];
|
||||
$result['extension'] = ltrim(strstr($id, '.'), '.');
|
||||
$result['dirname'] = pathinfo(str_replace("/.meta", "", $this->flextype['media_files_meta']->getFileMetaLocation($id)))['dirname'];
|
||||
|
||||
$result['url'] = 'project/uploads/' . $id;
|
||||
|
||||
if ($this->flextype['registry']->has('flextype.settings.url') && $this->flextype['registry']->get('flextype.settings.url') != '') {
|
||||
$full_url = $this->flextype['registry']->get('flextype.settings.url');
|
||||
} else {
|
||||
$full_url = Uri::createFromEnvironment(new Environment($_SERVER))->getBaseUrl();
|
||||
}
|
||||
|
||||
$result['full_url'] = $full_url . '/project/uploads/' . $id;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch files collection
|
||||
*
|
||||
* @param string $folder The directory to list.
|
||||
*
|
||||
* @return array A list of file metadata.
|
||||
*/
|
||||
public function fetchCollection(string $folder) : array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach (Filesystem::listContents($this->flextype['media_folders_meta']->getDirMetaLocation($folder)) as $file) {
|
||||
$result[$file['basename']] = $this->flextype['serializer']->decode(Filesystem::read($file['path']), 'yaml');
|
||||
|
||||
$result[$file['basename']]['filename'] = pathinfo(str_replace("/.meta", "", $this->flextype['media_files_meta']->getFileMetaLocation($file['basename'])))['filename'];
|
||||
$result[$file['basename']]['basename'] = explode(".", basename($this->flextype['media_files_meta']->getFileMetaLocation($file['basename'])))[0];
|
||||
$result[$file['basename']]['extension'] = ltrim(strstr($file['basename'], '.'), '.');
|
||||
$result[$file['basename']]['dirname'] = pathinfo(str_replace("/.meta", "", $file['path']))['dirname'];
|
||||
|
||||
$result[$file['basename']]['url'] = 'project/uploads/' . $folder . '/' . $file['basename'];
|
||||
|
||||
if ($this->flextype['registry']->has('flextype.settings.url') && $this->flextype['registry']->get('flextype.settings.url') != '') {
|
||||
$full_url = $this->flextype['registry']->get('flextype.settings.url');
|
||||
} else {
|
||||
$full_url = Uri::createFromEnvironment(new Environment($_SERVER))->getBaseUrl();
|
||||
}
|
||||
|
||||
$result[$file['basename']]['full_url'] = $full_url . '/project/uploads/' . $folder . '/' . $file['basename'];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename file
|
||||
*
|
||||
* @param string $id Unique identifier of the file.
|
||||
* @param string $new_id New Unique identifier of the file.
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function rename(string $id, string $new_id) : bool
|
||||
{
|
||||
if (!Filesystem::has($this->getFileLocation($new_id)) && !Filesystem::has($this->flextype['media_files_meta']->getFileMetaLocation($new_id))) {
|
||||
if (rename($this->getFileLocation($id), $this->getFileLocation($new_id)) && rename($this->flextype['media_files_meta']->getFileMetaLocation($id), $this->flextype['media_files_meta']->getFileMetaLocation($new_id))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file
|
||||
*
|
||||
* @param string $id Unique identifier of the file.
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function delete(string $id)
|
||||
{
|
||||
Filesystem::delete($this->getFileLocation($id));
|
||||
Filesystem::delete($this->flextype['media_files_meta']->getFileMetaLocation($id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file location
|
||||
*
|
||||
* @param string $id Unique identifier of the file.
|
||||
*
|
||||
* @return string entry file location
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function getFileLocation(string $id) : string
|
||||
{
|
||||
return PATH['project'] . '/uploads/' . $id;
|
||||
}
|
||||
}
|
101
src/flextype/core/Media/MediaFilesMeta.php
Normal file
101
src/flextype/core/Media/MediaFilesMeta.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Flextype (http://flextype.org)
|
||||
* Founded by Sergey Romanenko and maintained by Flextype Community.
|
||||
*/
|
||||
|
||||
namespace Flextype;
|
||||
|
||||
use Flextype\Component\Filesystem\Filesystem;
|
||||
use Flextype\Component\Arr\Arr;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
use Slim\Http\Environment;
|
||||
use Slim\Http\Uri;
|
||||
|
||||
class MediaFilesMeta
|
||||
{
|
||||
/**
|
||||
* Update file meta information
|
||||
*
|
||||
* @param string $id Unique identifier of the file.
|
||||
* @param string $field Field name
|
||||
* @param string $value Field value
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function updateMeta(string $id, string $field, string $value) : bool
|
||||
{
|
||||
$file_data = $this->flextype['serializer']->decode(Filesystem::read($this->getFileMetaLocation($id)), 'yaml');
|
||||
|
||||
if (Arr::keyExists($file_data, $field)) {
|
||||
Arr::set($file_data, $field, $value);
|
||||
return Filesystem::write($this->getFileMetaLocation($id), $this->flextype['serializer']->encode($file_data, 'yaml'));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add file meta information
|
||||
*
|
||||
* @param string $id Unique identifier of the file.
|
||||
* @param string $field Field name
|
||||
* @param string $value Field value
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function addMeta(string $id, string $field, string $value) : bool
|
||||
{
|
||||
$file_data = $this->flextype['serializer']->decode(Filesystem::read($this->getFileMetaLocation($id)), 'yaml');
|
||||
|
||||
if (!Arr::keyExists($file_data, $field)) {
|
||||
Arr::set($file_data, $field, $value);
|
||||
return Filesystem::write($this->getFileMetaLocation($id), $this->flextype['serializer']->encode($file_data, 'yaml'));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file meta information
|
||||
*
|
||||
* @param string $id Unique identifier of the file.
|
||||
* @param string $field Field name
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function deleteMeta(string $id, string $field) : bool
|
||||
{
|
||||
$file_data = $this->flextype['serializer']->decode(Filesystem::read($this->getFileMetaLocation($id)), 'yaml');
|
||||
|
||||
if (Arr::keyExists($file_data, $field)) {
|
||||
Arr::delete($file_data, $field);
|
||||
return Filesystem::write($this->getFileMetaLocation($id), $this->flextype['serializer']->encode($file_data, 'yaml'));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file meta location
|
||||
*
|
||||
* @param string $id Unique identifier of the file.
|
||||
*
|
||||
* @return string entry file location
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function getFileMetaLocation(string $id) : string
|
||||
{
|
||||
return PATH['project'] . '/uploads/.meta/' . $id . '.yaml';
|
||||
}
|
||||
}
|
110
src/flextype/core/Media/MediaFolders.php
Normal file
110
src/flextype/core/Media/MediaFolders.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Flextype (http://flextype.org)
|
||||
* Founded by Sergey Romanenko and maintained by Flextype Community.
|
||||
*/
|
||||
|
||||
namespace Flextype;
|
||||
|
||||
use Flextype\Component\Filesystem\Filesystem;
|
||||
use Flextype\Component\Arr\Arr;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
use Slim\Http\Environment;
|
||||
use Slim\Http\Uri;
|
||||
|
||||
class MediaFolders
|
||||
{
|
||||
/**
|
||||
* Flextype Dependency Container
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private $flextype;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function __construct($flextype)
|
||||
{
|
||||
$this->flextype = $flextype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create folder
|
||||
*
|
||||
* @param string $id Unique identifier of the folder.
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function create(string $id) : bool
|
||||
{
|
||||
if (!Filesystem::has($this->getDirLocation($id)) && !Filesystem::has($this->flextype['media_folders_meta']->getDirMetaLocation($id))) {
|
||||
if (Filesystem::createDir($this->getDirLocation($id)) && Filesystem::createDir($this->flextype['media_folders_meta']->getDirMetaLocation($id))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename folder
|
||||
*
|
||||
* @param string $id Unique identifier of the folder.
|
||||
* @param string $new_id New Unique identifier of the folder.
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function rename(string $id, string $new_id) : bool
|
||||
{
|
||||
if (!Filesystem::has($this->getDirLocation($new_id)) && !Filesystem::has($this->flextype['media_folders_meta']->getDirMetaLocation($new_id))) {
|
||||
if (rename($this->getDirLocation($id), $this->getDirLocation($new_id)) && rename($this->flextype['media_folders_meta']->getDirMetaLocation($id), $this->flextype['media_folders_meta']->getDirMetaLocation($new_id))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete dir
|
||||
*
|
||||
* @param string $id Unique identifier of the file.
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function delete(string $id)
|
||||
{
|
||||
Filesystem::deleteDir($this->getDirLocation($id));
|
||||
Filesystem::deleteDir($this->flextype['media_folders_meta']->getDirMetaLocation($id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get files directory location
|
||||
*
|
||||
* @param string $id Unique identifier of the folder.
|
||||
*
|
||||
* @return string entry directory location
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function getDirLocation(string $id) : string
|
||||
{
|
||||
return PATH['project'] . '/uploads/' . $id;
|
||||
}
|
||||
}
|
27
src/flextype/core/Media/MediaFoldersMeta.php
Normal file
27
src/flextype/core/Media/MediaFoldersMeta.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Flextype (http://flextype.org)
|
||||
* Founded by Sergey Romanenko and maintained by Flextype Community.
|
||||
*/
|
||||
|
||||
namespace Flextype;
|
||||
|
||||
class MediaFoldersMeta
|
||||
{
|
||||
/**
|
||||
* Get files directory meta location
|
||||
*
|
||||
* @param string $id Unique identifier of the folder.
|
||||
*
|
||||
* @return string entry directory location
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function getDirMetaLocation(string $id) : string
|
||||
{
|
||||
return PATH['project'] . '/uploads/.meta/' . $id;
|
||||
}
|
||||
}
|
@@ -203,6 +203,34 @@ $flextype['entries'] = static function ($container) {
|
||||
return new Entries($container);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add media folders service to Flextype container
|
||||
*/
|
||||
$flextype['media_folders'] = static function ($container) use ($flextype, $app) {
|
||||
return new MediaFolders($flextype, $app);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add media files service to Flextype container
|
||||
*/
|
||||
$flextype['media_files'] = static function ($container) use ($flextype, $app) {
|
||||
return new MediaFiles($flextype, $app);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add media folders meta service to Flextype container
|
||||
*/
|
||||
$flextype['media_folders_meta'] = static function ($container) use ($flextype, $app) {
|
||||
return new MediaFoldersMeta($flextype, $app);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add media files meta service to Flextype container
|
||||
*/
|
||||
$flextype['media_files_meta'] = static function ($container) use ($flextype, $app) {
|
||||
return new MediaFilesMeta($flextype, $app);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add plugins service to Flextype container
|
||||
*/
|
||||
|
106
src/flextype/endpoints/delivery/media/files.php
Normal file
106
src/flextype/endpoints/delivery/media/files.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Flextype (http://flextype.org)
|
||||
* Founded by Sergey Romanenko and maintained by Flextype Community.
|
||||
*/
|
||||
|
||||
namespace Flextype;
|
||||
|
||||
use Flextype\Component\Filesystem\Filesystem;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use function array_replace_recursive;
|
||||
|
||||
/**
|
||||
* API sys messages
|
||||
*/
|
||||
$api_sys_messages['AccessTokenInvalid'] = ['sys' => ['type' => 'Error', 'id' => 'AccessTokenInvalid'], 'message' => 'The access token you sent could not be found or is invalid.'];
|
||||
$api_sys_messages['NotFound'] = ['sys' => ['type' => 'Error', 'id' => 'NotFound'], 'message' => 'The resource could not be found.'];
|
||||
|
||||
/**
|
||||
* Validate delivery media files token
|
||||
*/
|
||||
function validate_delivery_media_files_token($token) : bool
|
||||
{
|
||||
return Filesystem::has(PATH['project'] . '/tokens/delivery/media/files/' . $token . '/token.yaml');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch media file(s)
|
||||
*
|
||||
* endpoint: GET /api/delivery/media/files
|
||||
*
|
||||
* Query:
|
||||
* path - [REQUIRED] - Unique identifier of the file path.
|
||||
* token - [REQUIRED] - Valid Content Delivery API token for Entries.
|
||||
*
|
||||
* Returns:
|
||||
* An array of entry item objects.
|
||||
*/
|
||||
$app->get('/api/delivery/media/files', function (Request $request, Response $response) use ($flextype, $api_sys_messages) {
|
||||
|
||||
// Get Query Params
|
||||
$query = $request->getQueryParams();
|
||||
|
||||
// Set variables
|
||||
$path = $query['path'];
|
||||
$token = $query['token'];
|
||||
|
||||
if ($flextype['registry']->get('flextype.settings.api.delivery.media.files.enabled')) {
|
||||
|
||||
// Validate delivery token
|
||||
if (validate_delivery_media_files_token($token)) {
|
||||
$delivery_files_token_file_path = PATH['project'] . '/tokens/delivery/media/files/' . $token. '/token.yaml';
|
||||
|
||||
// Set delivery token file
|
||||
if ($delivery_files_token_file_data = $flextype['serializer']->decode(Filesystem::read($delivery_files_token_file_path), 'yaml')) {
|
||||
if ($delivery_files_token_file_data['state'] === 'disabled' ||
|
||||
($delivery_files_token_file_data['limit_calls'] !== 0 && $delivery_files_token_file_data['calls'] >= $delivery_files_token_file_data['limit_calls'])) {
|
||||
return $response->withJson($api_sys_messages['AccessTokenInvalid'], 401);
|
||||
}
|
||||
|
||||
// Create files array
|
||||
$files = [];
|
||||
|
||||
// Get list if file or files for specific folder
|
||||
if (is_dir($path)) {
|
||||
$files = $flextype['media_files']->fetchCollection($path);
|
||||
} else {
|
||||
$files = $flextype['media_files']->fetchSingle($path);
|
||||
}
|
||||
|
||||
// Write response data
|
||||
$response_data['data'] = $files;
|
||||
|
||||
// Set response code
|
||||
$response_code = count($response_data['data']) > 0 ? 200 : 404;
|
||||
|
||||
// Update calls counter
|
||||
Filesystem::write($delivery_files_token_file_path, $flextype['serializer']->encode(array_replace_recursive($delivery_files_token_file_data, ['calls' => $delivery_files_token_file_data['calls'] + 1]), 'yaml'));
|
||||
|
||||
if ($response_code == 404) {
|
||||
|
||||
// Return response
|
||||
return $response
|
||||
->withJson($api_sys_messages['NotFound'], $response_code);
|
||||
}
|
||||
|
||||
// Return response
|
||||
return $response
|
||||
->withJson($response_data, $response_code);
|
||||
}
|
||||
|
||||
return $response
|
||||
->withJson($api_sys_messages['AccessTokenInvalid'], 401);
|
||||
}
|
||||
|
||||
return $response
|
||||
->withJson($api_sys_messages['AccessTokenInvalid'], 401);
|
||||
}
|
||||
|
||||
return $response
|
||||
->withJson($api_sys_messages['AccessTokenInvalid'], 401);
|
||||
});
|
106
src/flextype/endpoints/management/media/files.php
Normal file
106
src/flextype/endpoints/management/media/files.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Flextype (http://flextype.org)
|
||||
* Founded by Sergey Romanenko and maintained by Flextype Community.
|
||||
*/
|
||||
|
||||
namespace Flextype;
|
||||
|
||||
use Flextype\Component\Filesystem\Filesystem;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use function array_replace_recursive;
|
||||
|
||||
/**
|
||||
* API sys messages
|
||||
*/
|
||||
$api_sys_messages['AccessTokenInvalid'] = ['sys' => ['type' => 'Error', 'id' => 'AccessTokenInvalid'], 'message' => 'The access token you sent could not be found or is invalid.'];
|
||||
$api_sys_messages['NotFound'] = ['sys' => ['type' => 'Error', 'id' => 'NotFound'], 'message' => 'The resource could not be found.'];
|
||||
|
||||
/**
|
||||
* Validate delivery media files token
|
||||
*/
|
||||
function validate_delivery_media_files_token($token) : bool
|
||||
{
|
||||
return Filesystem::has(PATH['project'] . '/tokens/delivery/media/files/' . $token . '/token.yaml');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch media file(s)
|
||||
*
|
||||
* endpoint: GET /api/delivery/media/files
|
||||
*
|
||||
* Query:
|
||||
* path - [REQUIRED] - Unique identifier of the file path.
|
||||
* token - [REQUIRED] - Valid Content Delivery API token for Entries.
|
||||
*
|
||||
* Returns:
|
||||
* An array of entry item objects.
|
||||
*/
|
||||
$app->get('/api/delivery/media/files', function (Request $request, Response $response) use ($flextype, $api_sys_messages) {
|
||||
|
||||
// Get Query Params
|
||||
$query = $request->getQueryParams();
|
||||
|
||||
// Set variables
|
||||
$path = $query['path'];
|
||||
$token = $query['token'];
|
||||
|
||||
if ($flextype['registry']->get('flextype.settings.api.delivery.media.files.enabled')) {
|
||||
|
||||
// Validate delivery token
|
||||
if (validate_delivery_media_files_token($token)) {
|
||||
$delivery_files_token_file_path = PATH['project'] . '/tokens/delivery/media/files/' . $token. '/token.yaml';
|
||||
|
||||
// Set delivery token file
|
||||
if ($delivery_files_token_file_data = $flextype['serializer']->decode(Filesystem::read($delivery_files_token_file_path), 'yaml')) {
|
||||
if ($delivery_files_token_file_data['state'] === 'disabled' ||
|
||||
($delivery_files_token_file_data['limit_calls'] !== 0 && $delivery_files_token_file_data['calls'] >= $delivery_files_token_file_data['limit_calls'])) {
|
||||
return $response->withJson($api_sys_messages['AccessTokenInvalid'], 401);
|
||||
}
|
||||
|
||||
// Create files array
|
||||
$files = [];
|
||||
|
||||
// Get list if file or files for specific folder
|
||||
if (is_dir($path)) {
|
||||
$files = $flextype['media_files']->fetchCollection($path);
|
||||
} else {
|
||||
$files = $flextype['media_files']->fetchSingle($path);
|
||||
}
|
||||
|
||||
// Write response data
|
||||
$response_data['data'] = $files;
|
||||
|
||||
// Set response code
|
||||
$response_code = count($response_data['data']) > 0 ? 200 : 404;
|
||||
|
||||
// Update calls counter
|
||||
Filesystem::write($delivery_files_token_file_path, $flextype['serializer']->encode(array_replace_recursive($delivery_files_token_file_data, ['calls' => $delivery_files_token_file_data['calls'] + 1]), 'yaml'));
|
||||
|
||||
if ($response_code == 404) {
|
||||
|
||||
// Return response
|
||||
return $response
|
||||
->withJson($api_sys_messages['NotFound'], $response_code);
|
||||
}
|
||||
|
||||
// Return response
|
||||
return $response
|
||||
->withJson($response_data, $response_code);
|
||||
}
|
||||
|
||||
return $response
|
||||
->withJson($api_sys_messages['AccessTokenInvalid'], 401);
|
||||
}
|
||||
|
||||
return $response
|
||||
->withJson($api_sys_messages['AccessTokenInvalid'], 401);
|
||||
}
|
||||
|
||||
return $response
|
||||
->withJson($api_sys_messages['AccessTokenInvalid'], 401);
|
||||
});
|
0
src/flextype/endpoints/management/media/folders.php
Normal file
0
src/flextype/endpoints/management/media/folders.php
Normal file
Reference in New Issue
Block a user