1
0
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:
Awilum
2020-06-26 22:31:40 +03:00
14 changed files with 871 additions and 3 deletions

1
.php_cs.cache Normal file
View 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
View 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> |

View File

@@ -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"
}

View File

@@ -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';

View File

@@ -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:

View File

@@ -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);

View 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;
}
}

View 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';
}
}

View 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;
}
}

View 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;
}
}

View File

@@ -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
*/

View 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);
});

View 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);
});