Pluggable storage backends: first steps

- add backend related columns in photo table
- add system resource storage class
- add code to load image data from backend class
- return "nosign" image as photo meta with SystemResource backend
This commit is contained in:
fabrixxm 2018-11-20 23:15:03 +01:00 committed by Hypolite Petovan
parent 89eaf508f1
commit 3b3c4e8cc7
4 changed files with 83 additions and 10 deletions

View file

@ -34,7 +34,7 @@
use Friendica\Database\DBA; use Friendica\Database\DBA;
if (!defined('DB_UPDATE_VERSION')) { if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1293); define('DB_UPDATE_VERSION', 1294);
} }
return [ return [
@ -955,6 +955,8 @@ return [
"allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed groups"], "allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed groups"],
"deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"], "deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"],
"deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied groups"], "deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied groups"],
"backend-class" => ["type" => "tinytext", "default" => "", "comment" => "Storage backend class"],
"backend-ref" => ["type" => "text", "default" => "", "comment" => "Storage backend data reference"]
], ],
"indexes" => [ "indexes" => [
"PRIMARY" => ["id"], "PRIMARY" => ["id"],

View file

@ -58,7 +58,7 @@ class Photo extends BaseObject
public static function selectFirst(array $fields = [], array $condition = [], array $params = []) public static function selectFirst(array $fields = [], array $condition = [], array $params = [])
{ {
if (empty($fields)) { if (empty($fields)) {
$selected = self::getFields(); $fields = self::getFields();
} }
return DBA::selectFirst("photo", $fields, $condition, $params); return DBA::selectFirst("photo", $fields, $condition, $params);
@ -68,7 +68,7 @@ class Photo extends BaseObject
* @brief Get a single photo given resource id and scale * @brief Get a single photo given resource id and scale
* *
* This method checks for permissions. Returns associative array * This method checks for permissions. Returns associative array
* on success, a generic "red sign" data if user has no permission, * on success, "no sign" image info, if user has no permission,
* false if photo does not exists * false if photo does not exists
* *
* @param string $resourceid Rescource ID for the photo * @param string $resourceid Rescource ID for the photo
@ -92,7 +92,7 @@ class Photo extends BaseObject
$photo = self::selectFirst([], $condition, $params); $photo = self::selectFirst([], $condition, $params);
if ($photo === false) { if ($photo === false) {
return false; ///TODO: Return info for red sign image return self::createPhotoForSystemResource("images/nosign.jpg");
} }
return $photo; return $photo;
} }
@ -116,13 +116,26 @@ class Photo extends BaseObject
* *
* @return \Friendica\Object\Image * @return \Friendica\Object\Image
*/ */
public static function getImageForPhotoId($id) public static function getImageForPhoto($photo)
{ {
$i = self::selectFirst(["data", "type"],["id"=>$id]); $data = "";
if ($photo["backend-class"] == "") {
// legacy data storage in "data" column
$i = self::selectFirst(["data"], ["id"=>$photo["id"]]);
if ($i===false) { if ($i===false) {
return null; return null;
} }
return new Image($i["data"], $i["type"]); $data = $i["data"];
} else {
$backendClass = $photo["backend-class"];
$backendRef = $photo["backend-ref"];
$data = $backendClass::get($backendRef);
}
if ($data === "") {
return null;
}
return new Image($data, $photo["type"]);
} }
/** /**
@ -138,6 +151,25 @@ class Photo extends BaseObject
return $fields; return $fields;
} }
/**
* @brief Construct a photo array for a system resource image
*
* @param string $filename Image file name relative to code root
* @param string $mimetype Image mime type. Defaults to "image/jpeg"
*
* @return array
*/
public static function createPhotoForSystemResource($filename, $mimetype = "image/jpeg")
{
$fields = self::getFields();
$values = array_fill(0, count($fields), "");
$photo = array_combine($fields, $values);
$photo["backend-class"] = "\Friendica\Model\Storage\SystemResource";
$photo["backend-ref"] = $filename;
$photo["type"] = $mimetype;
$photo['cacheable'] = false;
return $photo;
}
/** /**

View file

@ -0,0 +1,39 @@
<?php
/**
* @file src/Model/Storage/SystemStorage.php
*/
namespace Friendica\Model\Storage;
/**
* @brief System resource storage class
*
* This class is used to load system resources, like images.
* Is not itended to be selectable by admins as default storage class.
*/
class SystemResource
{
// Valid folders to look for resources
const VALID_FOLDERS = [ "images" ];
/**
* @brief get data
*
* @param string $resourceid
*
* @return string
*/
static function get($filename)
{
$folder = dirname($filename);
if (!in_array($folder, self::VALID_FOLDERS)) return "";
if (!file_exists($filename)) return "";
return file_get_contents($filename);
}
static function put($filename, $data)
{
throw new \BadMethodCallException();
}
}

View file

@ -77,9 +77,9 @@ class Photo extends BaseModule
killme(); killme();
} }
$cacheable = ($photo["allow_cid"].$photo["allow_gid"].$photo["deny_cid"].$photo["deny_gid"] === "") || defaults($photo, "cacheable", false); $cacheable = ($photo["allow_cid"].$photo["allow_gid"].$photo["deny_cid"].$photo["deny_gid"] === "") && (isset($photo["cacheable"])?$photo["cacheable"]:true);
$img = MPhoto::getImageForPhotoId($photo["id"]); $img = MPhoto::getImageForPhoto($photo);
if (is_null($img) || !$img->isValid()) { if (is_null($img) || !$img->isValid()) {
Logger::log("Invalid photo with id {$photo['id']}."); Logger::log("Invalid photo with id {$photo['id']}.");