]> git.mxchange.org Git - friendica.git/commitdiff
Move Photo module, update Photo model
authorfabrixxm <fabrix.xm@gmail.com>
Tue, 20 Nov 2018 21:33:35 +0000 (22:33 +0100)
committerHypolite Petovan <hypolite@mrpetovan.com>
Mon, 21 Jan 2019 13:40:47 +0000 (08:40 -0500)
mod/photo.php [deleted file]
src/Model/Photo.php
src/Module/Photo.php [new file with mode: 0644]

diff --git a/mod/photo.php b/mod/photo.php
deleted file mode 100644 (file)
index 54418f7..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-<?php
-
-/**
- * @file mod/photo.php
- */
-use Friendica\App;
-use Friendica\Database\DBA;
-use Friendica\Object\Image;
-use Friendica\Util\Security;
-
-function photo_init(App $a)
-{
-       global $_SERVER;
-
-       $prvcachecontrol = false;
-       $file = "";
-
-       switch ($a->argc) {
-               case 4:
-                       $person = $a->argv[3];
-                       $customres = intval($a->argv[2]);
-                       $type = $a->argv[1];
-                       break;
-               case 3:
-                       $person = $a->argv[2];
-                       $type = $a->argv[1];
-                       break;
-               case 2:
-                       $photo = $a->argv[1];
-                       $file = $photo;
-                       break;
-               case 1:
-               default:
-                       killme();
-                       // NOTREACHED
-       }
-
-       if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
-               header('HTTP/1.1 304 Not Modified');
-               header("Last-Modified: " . gmdate("D, d M Y H:i:s", time()) . " GMT");
-               if (!empty($_SERVER['HTTP_IF_NONE_MATCH'])) {
-                       header('Etag: ' . $_SERVER['HTTP_IF_NONE_MATCH']);
-               }
-               header("Expires: " . gmdate("D, d M Y H:i:s", time() + (31536000)) . " GMT");
-               header("Cache-Control: max-age=31536000");
-               if (function_exists('header_remove')) {
-                       header_remove('Last-Modified');
-                       header_remove('Expires');
-                       header_remove('Cache-Control');
-               }
-               exit;
-       }
-
-       $default = 'images/person-300.jpg';
-       $public = true;
-
-       if (isset($type)) {
-               // Profile photos
-               switch ($type) {
-                       case 'profile':
-                       case 'custom':
-                               $resolution = 4;
-                               break;
-                       case 'micro':
-                               $resolution = 6;
-                               $default = 'images/person-48.jpg';
-                               break;
-                       case 'avatar':
-                       default:
-                               $resolution = 5;
-                               $default = 'images/person-80.jpg';
-                               break;
-               }
-
-               $uid = str_replace(['.jpg', '.png', '.gif'], ['', '', ''], $person);
-
-               foreach (Image::supportedTypes() AS $m => $e) {
-                       $uid = str_replace('.' . $e, '', $uid);
-               }
-
-               $r = q("SELECT * FROM `photo` WHERE `scale` = %d AND `uid` = %d AND `profile` = 1 LIMIT 1",
-                       intval($resolution),
-                       intval($uid)
-               );
-               if (DBA::isResult($r)) {
-                       $data = $r[0]['data'];
-                       $mimetype = $r[0]['type'];
-               }
-               if (empty($data)) {
-                       $data = file_get_contents($default);
-                       $mimetype = 'image/jpeg';
-               }
-       } else {
-               // Other photos
-               $resolution = 0;
-               $photo = str_replace(['.jpg', '.png', '.gif'], ['', '', ''], $photo);
-
-               foreach (Image::supportedTypes() AS $m => $e) {
-                       $photo = str_replace('.' . $e, '', $photo);
-               }
-
-               if (substr($photo, -2, 1) == '-') {
-                       $resolution = intval(substr($photo, -1, 1));
-                       $photo = substr($photo, 0, -2);
-               }
-
-               // check if the photo exists and get the owner of the photo
-               $r = q("SELECT `uid` FROM `photo` WHERE `resource-id` = '%s' LIMIT 1",
-                       DBA::escape($photo),
-                       intval($resolution)
-               );
-               if (DBA::isResult($r)) {
-                       $sql_extra = Security::getPermissionsSQLByUserId($r[0]['uid']);
-
-                       // Now we'll see if we can access the photo
-                       $r = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `scale` <= %d $sql_extra ORDER BY scale DESC LIMIT 1",
-                               DBA::escape($photo),
-                               intval($resolution)
-                       );
-                       if (DBA::isResult($r)) {
-                               $resolution = $r[0]['scale'];
-                               $data = $r[0]['data'];
-                               $mimetype = $r[0]['type'];
-                               $public = $r[0]['allow_cid'] == '' && $r[0]['allow_gid'] == '' && $r[0]['deny_cid'] == '' && $r[0]['deny_gid'] == '';
-                       } else {
-                               // The picure exists. We already checked with the first query.
-                               // obviously, this is not an authorized viev!
-                               $data = file_get_contents('images/nosign.jpg');
-                               $mimetype = 'image/jpeg';
-                               $prvcachecontrol = true;
-                               $public = false;
-                       }
-               }
-       }
-
-       if (empty($data)) {
-               if (isset($resolution)) {
-                       switch ($resolution) {
-                               case 4:
-                                       $data = file_get_contents('images/person-300.jpg');
-                                       $mimetype = 'image/jpeg';
-                                       break;
-                               case 5:
-                                       $data = file_get_contents('images/person-80.jpg');
-                                       $mimetype = 'image/jpeg';
-                                       break;
-                               case 6:
-                                       $data = file_get_contents('images/person-48.jpg');
-                                       $mimetype = 'image/jpeg';
-                                       break;
-                               default:
-                                       killme();
-                                       // NOTREACHED
-                                       break;
-                       }
-               }
-       }
-
-       // Resize only if its not a GIF and it is supported by the library
-       if ($mimetype != "image/gif" && in_array($mimetype, Image::supportedTypes())) {
-               $Image = new Image($data, $mimetype);
-               if ($Image->isValid()) {
-                       if (isset($customres) && $customres > 0 && $customres < 500) {
-                               $Image->scaleToSquare($customres);
-                       }
-                       $data = $Image->asString();
-                       $mimetype = $Image->getType();
-               }
-       }
-
-       if (function_exists('header_remove')) {
-               header_remove('Pragma');
-               header_remove('pragma');
-       }
-
-       header("Content-type: " . $mimetype);
-
-       if ($prvcachecontrol) {
-               // it is a private photo that they have no permission to view.
-               // tell the browser not to cache it, in case they authenticate
-               // and subsequently have permission to see it
-               header("Cache-Control: no-store, no-cache, must-revalidate");
-       } else {
-               header("Last-Modified: " . gmdate("D, d M Y H:i:s", time()) . " GMT");
-               header('Etag: "' . md5($data) . '"');
-               header("Expires: " . gmdate("D, d M Y H:i:s", time() + (31536000)) . " GMT");
-               header("Cache-Control: max-age=31536000");
-       }
-       echo $data;
-
-       // If the photo is public and there is an existing photo directory store the photo there
-       if ($public and $file != '') {
-               // If the photo path isn't there, try to create it
-               $basepath = $a->getBasePath();
-               if (!is_dir($basepath . "/photo")) {
-                       if (is_writable($basepath)) {
-                               mkdir($basepath . "/photo");
-                       }
-               }
-
-               if (is_dir($basepath . "/photo")) {
-                       file_put_contents($basepath . "/photo/" . $file, $data);
-               }
-       }
-
-       killme();
-       // NOTREACHED
-}
index ca909a41cc13d752ae18b0458cf06933b0b6a6d0..298ca39201a5aa2c9581d04e864f947b3e23ed78 100644 (file)
@@ -6,11 +6,13 @@
  */
 namespace Friendica\Model;
 
+use Friendica\BaseObject;
 use Friendica\Core\Cache;
 use Friendica\Core\Config;
 use Friendica\Core\L10n;
 use Friendica\Core\System;
 use Friendica\Database\DBA;
+use Friendica\Database\DBStructure;
 use Friendica\Object\Image;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Network;
@@ -19,9 +21,128 @@ use Friendica\Util\Security;
 /**
  * Class to handle photo dabatase table
  */
-class Photo
+class Photo extends BaseObject
 {
        /**
+        * @brief Select rows from the photo table
+        *
+        * @param array  $fields    Array of selected fields, empty for all
+        * @param array  $condition Array of fields for condition
+        * @param array  $params    Array of several parameters
+        *
+        * @return boolean|array
+        *
+        * @see \Friendica\Database\DBA::select
+        */
+       public static function select(array $fields = [], array $condition = [], array $params = [])
+       {
+               if (empty($fields)) {
+                       $selected = self::getFields();
+               }
+
+               $r = DBA::select("photo", $fields, $condition, $params);
+               return DBA::toArray($r);
+       }
+
+       /**
+        * @brief Retrieve a single record from the photo table
+        *
+        * @param array  $fields    Array of selected fields, empty for all
+        * @param array  $condition Array of fields for condition
+        * @param array  $params    Array of several parameters
+        *
+        * @return bool|array
+        *
+        * @see \Friendica\Database\DBA::select
+        */
+       public static function selectFirst(array $fields = [], array $condition = [], array $params = [])
+       {
+               if (empty($fields)) {
+                       $selected = self::getFields();
+               }
+
+               return DBA::selectFirst("photo", $fields, $condition, $params);
+       }
+
+       /**
+        * @brief Get a single photo given resource id and scale
+        *
+        * This method checks for permissions. Returns associative array
+        * on success, a generic "red sign" data if user has no permission,
+        * false if photo does not exists
+        *
+        * @param string  $resourceid  Rescource ID for the photo
+        * @param integer $scale       Scale of the photo. Defaults to 0
+        *
+        * @return boolean|array
+        */
+       public static function getPhoto($resourceid, $scale = 0)
+       {
+               $r = self::selectFirst(["uid"], ["resource-id" => $resourceid]);
+               if ($r===false) return false;
+
+               $sql_acl = Security::getPermissionsSQLByUserId($r["uid"]);
+
+               $condition = [
+                       "`resource-id` = ? AND `scale` <= ? " . $sql_acl,
+                       $resourceid, $scale
+               ];
+
+               $params = [ "order" => ["scale" => true]];
+
+               $photo = self::selectFirst([], $condition, $params);
+               if ($photo === false) {
+                       return false; ///TODO: Return info for red sign image
+               }
+               return $photo;
+       }
+
+       /**
+        * @brief Check if photo with given resource id exists
+        *
+        * @param string  $resourceid  Resource ID of the photo
+        *
+        * @return boolean
+        */
+       public static function exists($resourceid)
+       {
+               return DBA::count("photo", ["resource-id" => $resourceid]) > 0;
+       }
+
+       /**
+        * @brief Get Image object for given row id. null if row id does not exist
+        *
+        * @param integer  $id  Row id
+        *
+        * @return \Friendica\Object\Image
+        */
+       public static function getImageForPhotoId($id)
+       {
+               $i = self::selectFirst(["data", "type"],["id"=>$id]);
+               if ($i===false) {
+                       return null;
+               }
+               return new Image($i["data"], $i["type"]);
+       }
+
+       /**
+        * @brief Return a list of fields that are associated with the photo table
+        *
+        * @return array field list
+        */
+       private static function getFields()
+       {
+               $allfields = DBStructure::definition(false);
+               $fields = array_keys($allfields["photo"]["fields"]);
+               array_splice($fields, array_search("data", $fields), 1);
+               return $fields;
+       }
+
+
+
+       /**
+        * @brief store photo metadata in db and binary in default backend
+        *
         * @param Image   $Image     image
         * @param integer $uid       uid
         * @param integer $cid       cid
@@ -35,7 +156,8 @@ class Photo
         * @param string  $deny_cid  optional, default = ''
         * @param string  $deny_gid  optional, default = ''
         * @param string  $desc      optional, default = ''
-        * @return object
+        *
+        * @return boolean True on success
         */
        public static function store(Image $Image, $uid, $cid, $rid, $filename, $album, $scale, $profile = 0, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '', $desc = '')
        {
diff --git a/src/Module/Photo.php b/src/Module/Photo.php
new file mode 100644 (file)
index 0000000..0fddb82
--- /dev/null
@@ -0,0 +1,158 @@
+<?php
+/**
+ * @file src/Module/Photo.php
+ */
+
+namespace Friendica\Module;
+
+use Friendica\BaseModule;
+use Friendica\Core\Logger;
+use Friendica\Model\Photo as MPhoto;
+use Friendica\Object\Image;
+use Friendica\Util\Security;
+use Friendica\Network\HTTPException\NotFoundException;
+use Friendica\Network\HTTPException\BadRequestException;
+use Friendica\Network\HTTPException\InternalServerErrorException;
+
+/**
+ * @brief Photo Module
+ */
+class Photo extends BaseModule
+{
+
+       /**
+        * @brief Module initializer
+        *
+        * Fetch a photo or an avatar, in optional size, check for permissions and
+        * return the image
+        */
+       public static function init()
+       {
+               $a = self::getApp();
+               if ($a->argc <= 1 || $a->argc > 4) {
+                       throw new BadRequestException();
+                       killme();
+               }
+
+               if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
+                       header('HTTP/1.1 304 Not Modified');
+                       header("Last-Modified: " . gmdate("D, d M Y H:i:s", time()) . " GMT");
+                       if (!empty($_SERVER['HTTP_IF_NONE_MATCH'])) {
+                               header('Etag: ' . $_SERVER['HTTP_IF_NONE_MATCH']);
+                       }
+                       header("Expires: " . gmdate("D, d M Y H:i:s", time() + (31536000)) . " GMT");
+                       header("Cache-Control: max-age=31536000");
+                       if (function_exists('header_remove')) {
+                               header_remove('Last-Modified');
+                               header_remove('Expires');
+                               header_remove('Cache-Control');
+                       }
+                       exit;
+               }
+
+               $customsize = 0;
+               switch($a->argc) {
+               case 4:
+                       $customsize = intval($a->argv[2]);
+                       $uid = self::stripExtension($a->argv[3]);
+                       $photo = self::getAvatar($uid, $a->argv[1]);
+                       break;
+               case 3:
+                       $uid = self::stripExtension($a->argv[2]);
+                       $photo = self::getAvatar($uid, $a->argv[1]);
+                       break;
+               case 2:
+                       $photoid = self::stripExtension($a->argv[1]);
+                       $scale = 0;
+                       if (substr($photoid, -2, 1) == '-') {
+                               $scale = intval(substr($photoid, -1, 1));
+                               $photoid = substr($photoid, 0, -2);
+                       }
+                       $photo = MPhoto::getPhoto($photoid, $scale);
+                       break;
+               }
+
+               if ($photo===false) {
+                       header($_SERVER["SERVER_PROTOCOL"] . " 404 Not Found" , true, 404);
+                       killme();
+               }
+
+               $cacheable = ($photo["allow_cid"].$photo["allow_gid"].$photo["deny_cid"].$photo["deny_gid"] === "") || defaults($photo, "cacheable", false);
+
+               $img = MPhoto::getImageForPhotoId($photo["id"]);
+
+               if (is_null($img) || !$img->isValid()) {
+                       Logger::log("Invalid photo with id {$photo['id']}.");
+                       throw new InternalServerErrorException();
+               }
+
+
+               // if customsize is set and image is not a gif, resize it
+               if ($img->getType() !== "image/gif" && $customsize > 0 && $customsize < 501) {
+                       $img->scaleToSquare($customsize);
+               }
+
+
+               if (function_exists('header_remove')) {
+                       header_remove('Pragma');
+                       header_remove('pragma');
+               }
+
+               header("Content-type: " . $img->getType());
+
+               if (!$cacheable) {
+                       // it is a private photo that they have no permission to view.
+                       // tell the browser not to cache it, in case they authenticate
+                       // and subsequently have permission to see it
+                       header("Cache-Control: no-store, no-cache, must-revalidate");
+               } else {
+                       header("Last-Modified: " . gmdate("D, d M Y H:i:s", time()) . " GMT");
+                       header('Etag: "' . md5($img->asString()) . '"');
+                       header("Expires: " . gmdate("D, d M Y H:i:s", time() + (31536000)) . " GMT");
+                       header("Cache-Control: max-age=31536000");
+               }
+
+
+
+               echo $img->asString();
+
+
+               killme();
+       }
+
+       private static function stripExtension($name)
+       {
+               $name = str_replace([".jpg", ".png", ".gif"], ["", "", ""], $name);
+               foreach (Image::supportedTypes() AS $m => $e) {
+                       $name = str_replace('.' . $e, '', $name);
+               }
+               return $name;
+       }
+
+       private static function getAvatar($uid, $type="avatar")
+       {
+
+               switch($type) {
+               case "profile":
+               case "custom":
+                       $scale = 4;
+                       $default = "images/person-300.jpg";
+                       break;
+               case "micro":
+                       $scale = 6;
+                       $default = "images/person-48.jpg";
+                       break;
+               case "avatar":
+               default:
+                       $scale = 5;
+                       $default = "images/person-80.jpg";
+               }
+
+               $photo = MPhoto::selectFirst([], ["scale" => $scale, "uid" => $uid, "profile" => 1]);
+               if ($photo===false) {
+                       // todo default image info
+               }
+               return $photo;
+       }
+
+}
\ No newline at end of file