api/playlists and image resizing + delivery
authorChristian Weiske <cweiske@cweiske.de>
Wed, 11 Sep 2013 18:18:48 +0000 (20:18 +0200)
committerChristian Weiske <cweiske@cweiske.de>
Wed, 11 Sep 2013 18:18:48 +0000 (20:18 +0200)
.gitignore [new file with mode: 0644]
src/imagestore/Autoloader.php [new file with mode: 0644]
src/imagestore/Controller/Api.php [new file with mode: 0644]
src/imagestore/Controller/Api/Playlists.php [new file with mode: 0644]
src/imagestore/Controller/Image.php [new file with mode: 0644]
www/.htaccess [new file with mode: 0644]
www/index.php [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..d041e45
--- /dev/null
@@ -0,0 +1 @@
+/data/config.php
diff --git a/src/imagestore/Autoloader.php b/src/imagestore/Autoloader.php
new file mode 100644 (file)
index 0000000..cde5c89
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+namespace imagestore;
+class Autoloader
+{
+    public static function load($class)
+    {
+        $file = str_replace(array('_', '\\'), '/', $class) . '.php';
+        include_once $file;
+    }
+
+    public static function register()
+    {
+        set_include_path(
+            get_include_path()
+            . PATH_SEPARATOR
+            . __DIR__ . '/../'
+        );
+
+        spl_autoload_register('imagestore\Autoloader::load');
+    }
+}
+?>
diff --git a/src/imagestore/Controller/Api.php b/src/imagestore/Controller/Api.php
new file mode 100644 (file)
index 0000000..42f045a
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+namespace imagestore;
+
+class Controller_Api
+{
+    public function handle($uri)
+    {
+        if (substr($uri, 0, 3) != 'v1/') {
+            $this->error(404, 'Only API v1 supported');
+        }
+
+        $actionName = substr($uri, 3);
+        $class = 'imagestore\Controller_Api_' . ucfirst($actionName);
+
+        $action = new $class();
+        $action->handle();
+    }
+}
+?>
diff --git a/src/imagestore/Controller/Api/Playlists.php b/src/imagestore/Controller/Api/Playlists.php
new file mode 100644 (file)
index 0000000..98d4974
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+namespace imagestore;
+
+class Controller_Api_Playlists
+{
+    public function handle()
+    {
+        $playlists = (object) array(
+            'games' => array(),
+            'playlists' => array()
+        );
+        //-1 - link to playlists
+        //-2 - ????
+        //1 - featured
+        //2 - trending now
+        $id = 0;
+        foreach ($this->groupByParent($this->getDirs()) as $dir => $arDirs) {
+            $plnum = count($playlists->playlists);
+            $playlists->playlists[$plnum] = (object) array(
+                'id'    => ++$id,
+                'image' => '',
+                'name'  => $dir,
+                'tiles' => array()
+            );
+            foreach ($arDirs as $dirInfo) {
+                //FIXME: uuid dots?
+                $uuid = $this->getRelPath($dirInfo->getPathname());
+                $playlists->games[] = (object) array(
+                    'content_rating' => 'Everyone', 
+                    'image'   => $this->getImageUrl($this->getFirstImage($dirInfo)),
+                    'title'   => basename($dirInfo->getPathname()), 
+                    'uuid'    =>  $uuid,
+                    'version' => '11111111-0000-1111-0000-111111111111'
+                );
+                $playlists->playlists[$plnum]->tiles[] = (object) array(
+                    'game' => $uuid
+                );
+            }
+        }
+
+        header('Content-Type: application/json');
+        echo json_encode($playlists, JSON_PRETTY_PRINT);
+    }
+
+    protected function getDirs()
+    {
+        $dirs = new \GlobIterator($GLOBALS['imagestore']['basedir'] . '/*');
+        $dirs2 = new \GlobIterator($GLOBALS['imagestore']['basedir'] . '/*/*');
+
+        $all = new \AppendIterator();
+        $all->append($dirs);
+        $all->append($dirs2);
+
+        $allDirs = new \CallbackFilterIterator(
+            $all,
+            function ($fileInfo) {
+                return $fileInfo->isDir() && $this->hasImages($fileInfo);
+            }
+        );
+        return new \CachingIterator($allDirs);
+    }
+
+    protected function hasImages(\SplFileInfo $dirInfo)
+    {
+        $it = $this->getImageIterator($dirInfo);
+        $it->rewind();
+        return $it->valid();
+    }
+
+    protected function getImageIterator(\SplFileInfo $dirInfo)
+    {
+        $it = new \AppendIterator();
+        $it->append(
+            new \LimitIterator(
+                new \GlobIterator($dirInfo->getPathName() . '/*.jpg'),
+                0, 1
+            )
+        );
+        $it->append(
+            new \LimitIterator(
+                new \GlobIterator($dirInfo->getPathName() . '/*.JPG'),
+                0, 1
+            )
+        );
+        return $it;
+    }
+
+    protected function groupByParent($dirs)
+    {
+        $arGroups = array();
+        foreach ($dirs as $dirInfo) {
+            $arGroups[basename($dirInfo->getPathInfo())][] = $dirInfo;
+        }
+        return $arGroups;
+    }
+
+    protected function getRelPath($path)
+    {
+        return substr($path, strlen($GLOBALS['imagestore']['basedir']));
+    }
+
+    protected function getImageUrl($path)
+    {
+        if (isset($_SERVER['HTTPS'])) {
+        } else {
+            $protocol = 'http';
+        }
+        return $protocol . '://' . $_SERVER['HTTP_HOST']
+            . '/image?path=' . urlencode($this->getRelPath($path));
+    }
+
+    protected function getFirstImage(\SplFileInfo $dirInfo)
+    {
+        $it = $this->getImageIterator($dirInfo);
+        $it->rewind();
+        return $it->current();
+    }
+}
+?>
diff --git a/src/imagestore/Controller/Image.php b/src/imagestore/Controller/Image.php
new file mode 100644 (file)
index 0000000..31831b8
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+namespace imagestore;
+
+class Controller_Image
+{
+    public function handle($uri)
+    {
+        if (!isset($_GET['path'])) {
+            return $this->error('400 Bad request', 'Path missing');
+        }
+
+        $path = $GLOBALS['imagestore']['basedir'] . $_GET['path'];
+        if (!file_exists($path)) {
+            return $this->error('404 Not Found', 'File not found');
+        }
+        
+        if (!isset($_GET['w'])) {
+            header('Content-type: image/jpeg');
+            header('Content-length: ' . filesize($path));
+            return readfile($path);
+        }
+        
+        //resize
+        $img = imagecreatefromjpeg($path);
+
+        $newWidth = (int) $_GET['w'];
+        //if (isset($_GET['h'])) {
+        //    $newHeight = (int) $_GET['h'];
+        //} else {
+        $newHeight = intval($newWidth / imagesx($img) * imagesy($img));
+        //}
+        
+        $thumb = imagecreatetruecolor($newWidth, $newHeight);
+        // Resize
+        imagecopyresampled(
+            $thumb, $img, 0, 0, 0, 0,
+            $newWidth, $newHeight, imagesx($img), imagesy($img)
+        );
+        imagedestroy($img);
+
+        header('Content-type: image/jpeg');
+        imagejpeg($thumb);
+        imagedestroy($thumb);
+    }
+
+    protected function error($error, $message)
+    {
+        header('HTTP/1.0 ' . $error);
+        header('Content-type: text/plain; charset=utf-8');
+        echo $message;
+    }
+}
+?>
diff --git a/www/.htaccess b/www/.htaccess
new file mode 100644 (file)
index 0000000..dc57549
--- /dev/null
@@ -0,0 +1,11 @@
+<IfModule mod_rewrite.c>
+  RewriteEngine On
+
+  RewriteCond %{REQUEST_FILENAME} -f [OR]
+  RewriteCond %{REQUEST_FILENAME} -d [OR]
+  RewriteCond %{REQUEST_FILENAME} -l
+  RewriteRule .* - [L]
+
+  # Rewrite the rest to index.php
+  RewriteRule .* /index.php [L]
+</IfModule>
diff --git a/www/index.php b/www/index.php
new file mode 100644 (file)
index 0000000..8417d26
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+namespace imagestore;
+
+require_once __DIR__ . '/../src/imagestore/Autoloader.php';
+Autoloader::register();
+
+require_once __DIR__ . '/../data/config.php';
+
+$url = $_SERVER['REDIRECT_URL'];
+if (substr($url, 0, 5) == '/api/') {
+    $api = new Controller_Api();
+    $api->handle(substr($url, 5));
+} else if ($url == '/image') {
+    $api = new Controller_Image();
+    $api->handle($url);
+} else {
+    header('HTTP/1.0 404 Not Found');
+    echo "I can't handle this request\n";
+}
+?>
\ No newline at end of file