From 7adb49837e3644e7f278638f994792c819ab5809 Mon Sep 17 00:00:00 2001
From: Rasmus Fuhse <fuhse@data-quest.de>
Date: Mon, 15 Sep 2014 18:05:43 +0200
Subject: [PATCH] add images

---
 classes/MarketImage.class.php    | 39 ++++++++++++++
 classes/MarketPlugin.class.php   | 20 +++++++
 classes/MarketRelease.class.php  |  5 ++
 controllers/myplugins.php        | 89 ++++++++++++++++++++++++++------
 controllers/presenting.php       |  6 +++
 install.sql                      |  8 +++
 views/myplugins/_edit_images.php | 37 +++++++++++++
 views/myplugins/edit.php         |  4 ++
 views/myplugins/edit_images.php  |  8 +++
 views/myplugins/overview.php     |  6 ++-
 views/presenting/details.php     | 24 +++++++--
 views/presenting/overview.php    |  4 +-
 12 files changed, 229 insertions(+), 21 deletions(-)
 create mode 100644 views/myplugins/_edit_images.php
 create mode 100644 views/myplugins/edit_images.php

diff --git a/classes/MarketImage.class.php b/classes/MarketImage.class.php
index a288955..e2ae574 100644
--- a/classes/MarketImage.class.php
+++ b/classes/MarketImage.class.php
@@ -1,6 +1,15 @@
 <?php
 
 class MarketImage extends SimpleORMap {
+
+    static public function findByPlugin_id($plugin_id) {
+        return self::findBySQL("plugin_id = ? ORDER BY position ASC, mkdate ASC", array($plugin_id));
+    }
+
+    static public function getImageDataPath() {
+        return $GLOBALS['STUDIP_BASE_PATH'] . "/data/pluginmarket_images";
+    }
+
     protected static function configure($config = array())
     {
         $config['db_table'] = 'pluginmarket_images';
@@ -10,4 +19,34 @@ class MarketImage extends SimpleORMap {
         );
         parent::configure($config);
     }
+
+    public function getURL() {
+        return URLHelper::getURL("plugins.php/pluginmarket/presenting/image/".$this->getId(), array(), true);
+    }
+
+    public function delete() {
+        parent::delete();
+        unlink($this->getFilePath());
+    }
+
+    public function installFromPath($path) {
+        copy($path, $this->getFilePath());
+    }
+
+    protected function getFilePath() {
+        if (!file_exists(self::getImageDataPath())) {
+            mkdir(self::getImageDataPath());
+        }
+        if (!$this->getId()) {
+            $this->setId($this->getNewId());
+        }
+        return self::getImageDataPath()."/".$this->getId();
+    }
+
+    public function outputImage() {
+        $path = self::getImageDataPath()."/".$this->getId();
+        header("Content-Type: ".$this['mimetype']);
+        header("Content-Disposition: inline; filename=".$this['filename']);
+        echo file_get_contents($path);
+    }
 }
\ No newline at end of file
diff --git a/classes/MarketPlugin.class.php b/classes/MarketPlugin.class.php
index addb205..41e6d42 100644
--- a/classes/MarketPlugin.class.php
+++ b/classes/MarketPlugin.class.php
@@ -9,10 +9,30 @@ class MarketPlugin extends SimpleORMap {
             'on_delete' => 'delete',
             'on_store' => 'store',
         );
+        $config['has_many']['images'] = array(
+            'class_name' => 'MarketImage',
+            'on_delete' => 'delete',
+            'on_store' => 'store',
+        );
         $config['belongs_to']['user'] = array(
             'class_name' => 'User',
             'foreign_key' => 'user_id',
         );
         parent::configure($config);
     }
+
+    public function isWritable($user_id = null) {
+        $user_id || $user_id = $GLOBALS['user']->id;
+        return $this['user_id'] === $user_id;
+    }
+
+    public function isRootable($user_id = null) {
+        $user_id || $user_id = $GLOBALS['user']->id;
+        return $GLOBALS['perm']->have_perm("root", $user_id);
+    }
+
+    public function getLogoURL() {
+        $firstimage = $this->images->first();
+        return $firstimage ? $firstimage->getURL() : null;
+    }
 }
\ No newline at end of file
diff --git a/classes/MarketRelease.class.php b/classes/MarketRelease.class.php
index 2468442..917499f 100644
--- a/classes/MarketRelease.class.php
+++ b/classes/MarketRelease.class.php
@@ -22,6 +22,11 @@ class MarketRelease extends SimpleORMap {
         parent::configure($config);
     }
 
+    public function delete() {
+        parent::delete();
+        unlink($this->getFilePath());
+    }
+
     public function installFile() {
         $hash = md5(uniqid());
         $tmp_folder = $GLOBALS['TMP_PATH']."/temp_plugin_".$hash;
diff --git a/controllers/myplugins.php b/controllers/myplugins.php
index 1ced4c3..503088c 100644
--- a/controllers/myplugins.php
+++ b/controllers/myplugins.php
@@ -32,6 +32,16 @@ class MypluginsController extends PluginController {
         }
     }
 
+    public function add_release_action($plugin_id) {
+        $this->marketplugin = new MarketPlugin($plugin_id);
+        $this->release = new MarketRelease();
+        if (Request::isXhr()) {
+            $this->response->add_header('X-Title', _("Release hinzuf�gen"));
+            $this->set_layout(null);
+        }
+        $this->render_action("edit_release");
+    }
+
     public function edit_release_action($release_id) {
         $this->release = new MarketRelease($release_id);
         if (Request::isXhr()) {
@@ -40,28 +50,77 @@ class MypluginsController extends PluginController {
         }
     }
 
+    public function edit_images_action($plugin_id) {
+        $this->marketplugin = new MarketPlugin($plugin_id);
+        if (Request::isXhr()) {
+            $this->response->add_header('X-Title', _("Galerie bearbeiten"));
+            $this->set_layout(null);
+        }
+    }
+
     public function save_action() {
         if (!Request::isPost()) {
             throw new Exception("Method not allowed. Try a POST request.");
         }
-        $data = Request::getArray("data");
-        if (!isset($data["publiclyvisible"])) {
-            $data['publiclyvisible'] = 0;
-        }
         $this->marketplugin = new MarketPlugin(Request::option("id") ?: null);
-        $this->marketplugin->setData($data);
-        if ($this->marketplugin->isNew()) {
-            $this->marketplugin['user_id'] = $GLOBALS['user']->id;
+        if (!$this->marketplugin->isNew() && !$this->marketplugin->isWritable()) {
+            throw new AccessDeniedException("Kein Zugriff");
+        }
+
+        if (Request::submitted("data")) {
+            $data = Request::getArray("data");
+            if (!isset($data["publiclyvisible"])) {
+                $data['publiclyvisible'] = 0;
+            }
+            $this->marketplugin->setData($data);
+            if ($this->marketplugin->isNew()) {
+                $this->marketplugin['user_id'] = $GLOBALS['user']->id;
+            }
         }
+
         $this->marketplugin->store();
-        $release_data = Request::getArray("release");
-        if ($release_data['type'] !== "zipfile" || $_FILES['release_file']['tmp_path']) {
-            $release = new MarketRelease();
-            $release->setData($release_data);
-            $release['plugin_id'] = $this->marketplugin->getId();
-            $release['user_id'] = $GLOBALS['user']->id;
-            $release->installFile();
-            $release->store();
+
+        if (Request::submitted("image_order")) {
+            $order = array_flip(Request::getArray("image_order"));
+            foreach ($this->marketplugin->images as $image) {
+                $image['position'] = $order[$image->getId()] + 1;
+                $image->store();
+            }
+        }
+
+        if (Request::submitted("delete_image")) {
+            foreach (Request::getArray("delete_image") as $image_id) {
+                MarketImage::find($image_id)->delete();
+            }
+        }
+
+        if (Request::submitted("edit_images")) {
+            $files = $_FILES['new_images'];
+            $position = count($this->marketplugin->images);
+            foreach ($files['name'] as $index => $name) {
+                if ($files['size'][$index]) {
+                    $position++;
+                    $file = new MarketImage();
+                    $file['plugin_id'] = $this->marketplugin->getId();
+                    $file['filename'] = $name;
+                    $file['mimetype'] = $files['type'][$index];
+                    $file['position'] = $position;
+                    $file->installFromPath($files['tmp_name'][$index]);
+                    $file->store();
+                }
+            }
+        }
+
+        if (Request::submitted("release")) {
+            $release_data = Request::getArray("release");
+            if ($release_data['type'] !== "zipfile" || $_FILES['release_file']['tmp_path']) {
+                $release = new MarketRelease();
+                $release->setData($release_data);
+                $release['plugin_id'] = $this->marketplugin->getId();
+                $release['user_id'] = $GLOBALS['user']->id;
+                $release->installFile();
+                $release->store();
+            }
         }
         PageLayout::postMessage(MessageBox::success(_("Plugin wurde gespeichert.")));
         $this->redirect("pluginmarket/presenting/details/".$this->marketplugin->getId());
diff --git a/controllers/presenting.php b/controllers/presenting.php
index 4740373..3b15256 100644
--- a/controllers/presenting.php
+++ b/controllers/presenting.php
@@ -37,4 +37,10 @@ class PresentingController extends PluginController {
         $this->render_nothing();
     }
 
+    public function image_action($image_id) {
+        $this->image = new MarketImage($image_id);
+        $this->image->outputImage();
+        $this->render_nothing();
+    }
+
 }
\ No newline at end of file
diff --git a/install.sql b/install.sql
index f706c11..eafc817 100644
--- a/install.sql
+++ b/install.sql
@@ -61,3 +61,11 @@ CREATE TABLE IF NOT EXISTS `pluginmarket_tags` (
     KEY `plugin_id` (`plugin_id`)
 ) ENGINE=MyISAM;
 
+CREATE TABLE IF NOT EXISTS `pluginmarket_rezension` (
+  `rezension_id` varchar(32) NOT NULL,
+  `rezension_txt` text NOT NULL,
+  `user_id` varchar(32) NOT NULL,
+  `mkdate` int(20) NOT NULL,
+  `plugin_id` varchar(32) NOT NULL,
+  KEY `plugin_id` (`plugin_id`)
+) ENGINE=MyISAM;
\ No newline at end of file
diff --git a/views/myplugins/_edit_images.php b/views/myplugins/_edit_images.php
new file mode 100644
index 0000000..3e4d88f
--- /dev/null
+++ b/views/myplugins/_edit_images.php
@@ -0,0 +1,37 @@
+<fieldset>
+    <input type="hidden" name="edit_images" value="1">
+    <legend>
+        <?= _("Galerie") ?>
+    </legend>
+
+    <ol id="galery_edit">
+    <? foreach ($marketplugin->images as $image) : ?>
+        <li>
+            <input type="checkbox" name="delete_image[]" value="<?= htmlReady($image->getId()) ?>" id="delete_image_<?= htmlReady($image->getId()) ?>">
+            <div>
+                <img src="<?= htmlReady($image->getURL()) ?>" style="max-height: 200px;">
+                <input type="hidden" name="image_order[]" value="<?= htmlReady($image->getId()) ?>">
+                <label for="delete_image_<?= htmlReady($image->getId()) ?>">
+                    <?= Assets::img("icons/20/blue/delete") ?>
+                </label>
+            </div>
+        </li>
+    <? endforeach ?>
+    </ol>
+    <script>
+        jQuery(function() {
+            jQuery("#galery_edit").sortable();
+        });
+    </script>
+
+    <div id="new_image_container">
+        <div>
+            <label>
+                <?= Assets::img("icons/20/blue/upload", array('class' => "text-bottom", 'style' => "cursor: pointer;")) ?>
+                <input type="file" name="new_images[]">
+            </label>
+            <a href="#" onClick="if (jQuery('#new_image_container > div').length > 1) jQuery(this).closest('div').remove(); else jQuery(this).closest('div').find('input[type=file]').val(''); return false;"><?= Assets::img("icons/20/blue/trash") ?></a>
+        </div>
+    </div>
+    <?= \Studip\LinkButton::create(_("Weiteres Bild"), "#", array('onClick' => "jQuery('#new_image_container > div').first().clone().appendTo('#new_image_container').find('input[type=file]').val(''); return false;")) ?>
+</fieldset>
\ No newline at end of file
diff --git a/views/myplugins/edit.php b/views/myplugins/edit.php
index b9ad3de..f50f05b 100644
--- a/views/myplugins/edit.php
+++ b/views/myplugins/edit.php
@@ -42,7 +42,11 @@
         </div>
     </fieldset>
 
+    <?= $this->render_partial("myplugins/_edit_images.php", compact("marketplugin")) ?>
+
+    <? if ($marketplugin->isNew()) : ?>
     <?= $this->render_partial("myplugins/_edit_release.php", array('release' => new MarketRelease())) ?>
+    <? endif ?>
 
     <div data-dialog-button>
         <?= \Studip\Button::create(_("speichern")) ?>
diff --git a/views/myplugins/edit_images.php b/views/myplugins/edit_images.php
new file mode 100644
index 0000000..bad18cd
--- /dev/null
+++ b/views/myplugins/edit_images.php
@@ -0,0 +1,8 @@
+<form action="<?= PluginEngine::getLink($plugin, array(), "myplugins/save") ?>" method="post" enctype="multipart/form-data" class="studip_form">
+    <input type="hidden" name="id" value="<?= $marketplugin->getId() ?>">
+    <?= $this->render_partial("myplugins/_edit_images.php", compact("marketplugin")) ?>
+
+    <div data-dialog-button>
+        <?= \Studip\Button::create(_("speichern")) ?>
+    </div>
+</form>
\ No newline at end of file
diff --git a/views/myplugins/overview.php b/views/myplugins/overview.php
index ce4c8b4..b45dc4d 100644
--- a/views/myplugins/overview.php
+++ b/views/myplugins/overview.php
@@ -13,6 +13,9 @@
         <? foreach ($plugins as $marketplugin) : ?>
         <tr>
             <td>
+                <? if ($marketplugin['publiclyvisible'] && !$marketplugin['approved']) : ?>
+                    <?= Assets::img("icons/20/red/exclaim-circle", array('title' => _("Plugin wurde noch nicht von einem Administrator freigeschaltet."), 'class' => "text-bottom")) ?>
+                <? endif ?>
                 <a href="<?= PluginEngine::getLink($plugin, array(), "presenting/details/".$marketplugin->getId()) ?>">
                     <?= htmlReady($marketplugin['name']) ?>
                 </a>
@@ -32,7 +35,8 @@
                 <? endif ?>
             </td>
             <td>
-                <a href="<?= PluginEngine::getLink($plugin, array(), "myplugins/edit/".$marketplugin->getId()) ?>" data-dialog><?= Assets::img("icons/20/blue/edit") ?></a>
+                <a href="<?= PluginEngine::getLink($plugin, array(), "myplugins/edit/".$marketplugin->getId()) ?>" data-dialog title="<?= _("Plugin-Info bearbeiten") ?>"><?= Assets::img("icons/20/blue/edit") ?></a>
+                <a href="<?= PluginEngine::getLink($plugin, array(), "myplugins/add_release/".$marketplugin->getId()) ?>" data-dialog title="<?= _("Neues Release hinzuf�gen") ?>"><?= Assets::img("icons/20/blue/add") ?></a>
             </td>
         </tr>
         <? endforeach ?>
diff --git a/views/presenting/details.php b/views/presenting/details.php
index ae365ab..47e8888 100644
--- a/views/presenting/details.php
+++ b/views/presenting/details.php
@@ -1,3 +1,15 @@
+<?
+//OpenGraph attributes
+PageLayout::addHeadElement("meta", array('property' => "og:site_name", 'content' => _("Stud.IP Plugin-Marktplatz")));
+PageLayout::addHeadElement("meta", array('property' => "og:type", 'content' => "article"));
+PageLayout::addHeadElement("meta", array('property' => "og:title", 'content' => $marketplugin['name']));
+PageLayout::addHeadElement("meta", array('property' => "og:description", 'content' => $marketplugin['short_description']));
+$icon = $marketplugin->images->first();
+if ($icon) {
+    PageLayout::addHeadElement("meta", array('property' => "og:image", 'content' => $icon->getURL()));
+}
+?>
+
 <? if (!$marketplugin['publiclyvisible']) : ?>
     <?= PageLayout::postMessage(MessageBox::info(_("Dieses Plugin ist nicht �ffentlich."))) ?>
 <? endif ?>
@@ -10,8 +22,13 @@
 <h2><?= _("Galerie") ?></h2>
 
 <div>
-    <? if ($marketplugin['user_id'] === $GLOBALS['user']->id) : ?>
-    <div><a href=""><?= Assets::img("icons/20/blue/add") ?></a></div>
+    <? foreach ($marketplugin->images as $image) : ?>
+    <div>
+        <img src="<?= htmlReady($image->getURL()) ?>" style="max-height: 150px;">
+    </div>
+    <? endforeach ?>
+    <? if ($marketplugin->isWritable()) : ?>
+    <div><a href="<?= PluginEngine::getLink($plugin, array(), "myplugins/edit_images/".$marketplugin->getId()) ?>" data-dialog><?= Assets::img("icons/20/blue/add") ?></a></div>
     <? endif ?>
 </div>
 
@@ -97,8 +114,9 @@ $bitcoin_datafield = $author['datafields']->findBy("name", "Bitcoin-Wallet")->va
 
 
 
-<? if ($marketplugin['user_id'] === $GLOBALS['user']->id) : ?>
+<? if ($marketplugin->isWritable()) : ?>
 <div style="text-align: center">
     <?= \Studip\LinkButton::create(_("bearbeiten"), PluginEngine::getURL($plugin, array(), "myplugins/edit/".$marketplugin->getId()), array('data-dialog' => 1)) ?>
+    <?= \Studip\LinkButton::create(_("Release hinzuf�gen"), PluginEngine::getURL($plugin, array(), "myplugins/add_release/".$marketplugin->getId()), array('data-dialog' => 1)) ?>
 </div>
 <? endif ?>
\ No newline at end of file
diff --git a/views/presenting/overview.php b/views/presenting/overview.php
index 6cb20e0..4cd6523 100644
--- a/views/presenting/overview.php
+++ b/views/presenting/overview.php
@@ -99,7 +99,7 @@
         <? foreach ($new_plugins as $marketplugin) : ?>
             <article>
                 <h1><a href="<?= PluginEngine::getLink($plugin, array(), "presenting/details/".$marketplugin->getId()) ?>"><?= htmlReady($marketplugin['name']) ?></a></h1>
-                <div class="image" style="background-image: url(http://plugins.studip.de/content/screenshots/a1d85f695cfe506241d398d272ae43f0_thumb);"></div>
+                <div class="image" style="background-image: url(<?= $marketplugin->getLogoURL() ?>);"></div>
                 <p class="shortdescription">
                     <?= htmlReady($marketplugin['short_description']) ?>
                 </p>
@@ -113,7 +113,7 @@
     <? foreach ($plugins as $marketplugin) : ?>
         <article>
             <h1><a href="<?= PluginEngine::getLink($plugin, array(), "presenting/details/".$marketplugin->getId()) ?>"><?= htmlReady($marketplugin['name']) ?></a></h1>
-            <div class="image" style="background-image: url(http://plugins.studip.de/content/screenshots/a1d85f695cfe506241d398d272ae43f0_thumb);"></div>
+            <div class="image" style="background-image: url(<?= $marketplugin->getLogoURL() ?>);"></div>
             <p class="shortdescription">
                 <?= htmlReady($marketplugin['short_description']) ?>
             </p>
-- 
GitLab