diff --git a/classes/MarketPlugin.class.php b/classes/MarketPlugin.class.php index 1f40f62582f0e1bd9d0ead099565bd7f2962caaa..9cc8245582455c73beaa340cc534c89b09ece19e 100755 --- a/classes/MarketPlugin.class.php +++ b/classes/MarketPlugin.class.php @@ -170,4 +170,5 @@ class MarketPlugin extends SimpleORMap { return $rating; } + } \ No newline at end of file diff --git a/classes/MarketRelease.class.php b/classes/MarketRelease.class.php index c3ee241df2795b6f577e6d154703eedf49a31093..6286acc7ea189966ca905c5037fc366b408179e5 100755 --- a/classes/MarketRelease.class.php +++ b/classes/MarketRelease.class.php @@ -30,7 +30,7 @@ class MarketRelease extends SimpleORMap { public function delete() { parent::delete(); - unlink($this->getFilePath()); + @unlink($this->getFilePath()); } public function installFile() { @@ -56,7 +56,13 @@ class MarketRelease extends SimpleORMap { } else { $plugin_dir = $tmp_folder; } - $this->installFromDirectory($plugin_dir, $file); + try { + $this->installFromDirectory($plugin_dir, $file); + } catch (PluginInstallationException $e) { + rmdirr($tmp_folder); + unlink($file); + throw $e; + } rmdirr($tmp_folder); unlink($file); @@ -80,7 +86,7 @@ class MarketRelease extends SimpleORMap { header('Content-Type: ' . $this->getMimeType()); header('Content-Disposition: attachment; filename="' . $this->getFilename() . '"'); - readfile($this->getFilePath()); + @readfile($this->getFilePath()); } public function getMimeType() @@ -90,7 +96,7 @@ class MarketRelease extends SimpleORMap { public function getFilename() { - return $this->plugin['name'] . '.zip'; + return $this->plugin['pluginname'] . '.zip'; } public function getContentLength() @@ -113,9 +119,26 @@ class MarketRelease extends SimpleORMap { protected function installFromDirectory($dir, $originalfile = null) { $manifest = PluginManager::getInstance()->getPluginManifest($dir); - if ($manifest['pluginclassname']) { - $this->plugin['pluginclassname'] = $manifest['pluginclassname']; - $this->plugin->store(); + if ($manifest['pluginname']) { + if ($this->plugin->isNew()) { + $this->plugin['pluginname'] = $manifest['pluginname']; + $this->plugin['name'] = @$manifest['displayname'] ?: $manifest['pluginname']; + $this->plugin['short_description'] = @$manifest['description'] ?: ''; + $this->plugin['description'] = @$manifest['descriptionlong'] ?: ''; + if (!$this->plugin['description']) { + $this['repository_overwrites_descriptionfrom'] = 1; + } + if (MarketPlugin::findOneByPluginname($this->plugin->pluginname)) { + throw new PluginInstallationException(_("Ein Plugin mit diesem Namen ist schon im Marktplatz vorhanden!")); + } + $this->plugin->store(); + } else { + if ($this->plugin['pluginname'] != $manifest['pluginname']) { + throw new PluginInstallationException(sprintf(_("Release hat falschen Pluginnamen, erwartet:%s gefunden:%s"), $this->plugin['pluginname'], $manifest['pluginname'])); + } + } + } else { + throw new PluginInstallationException(_("Im Manifest fehlt der Pluginname")); } $this['studip_min_version'] = $manifest['studipMinVersion']; $this['studip_max_version'] = $manifest['studipMaxVersion']; @@ -198,4 +221,18 @@ class MarketRelease extends SimpleORMap { return implode("\n", $arr); } + public function getPluginName() + { + $zip = new ZipArchive(); + if ($zip->open($this->getFilePath())) { + $manifest = $zip->getFromIndex($zip->locateName('plugin.manifest', ZipArchive::FL_NOCASE|ZipArchive::FL_NODIR)); + foreach (array_map('trim',explode("\n", $manifest)) as $line) { + list($key, $value) = explode('=', $line); + if ($key === 'pluginname') { + return trim($value); + } + } + } + } + } \ No newline at end of file diff --git a/controllers/extern.php b/controllers/extern.php index b5e1bce2bde82220c3c70537930b5c974d7fdba1..9f89019554479195c500df6ccf68d68a8f292776 100755 --- a/controllers/extern.php +++ b/controllers/extern.php @@ -20,7 +20,8 @@ class ExternController extends MarketController $plugins = MarketPlugin::findBySQL("publiclyvisible = 1 AND approved = 1 ORDER BY name ASC"); foreach ($plugins as $plugin) { $xml_plugin = $xml_plugins->appendChild($this->create_xml_element($doc, 'plugin', null, array( - 'name' => $plugin->name, + 'displayname' => $plugin->name, + 'name' => $plugin->pluginname, 'homepage' => $plugin->url, 'short_description' => $plugin->short_description, 'description' => $plugin->description, diff --git a/controllers/myplugins.php b/controllers/myplugins.php index ca345e1bee93d412c7ea74f564270ef2a4656a36..7896930c87a754369f2c092c62d4e3d4c3ecb50f 100755 --- a/controllers/myplugins.php +++ b/controllers/myplugins.php @@ -16,11 +16,28 @@ class MypluginsController extends MarketController $this->plugins = MarketPlugin::findBySQL("user_id = ? ORDER BY mkdate DESC", array($GLOBALS['user']->id)); } + public function addfromzip_action() + { + CSRFProtection::verifyUnsafeRequest(); + if (isset($_FILES['release_file']['tmp_name'])) { + $plugin = new MarketPlugin(); + $plugin->setId($plugin->getNewId()); + $plugin->user_id = $GLOBALS['user']->id; + $release = new MarketRelease(); + $release->plugin = $plugin; + $release['user_id'] = $GLOBALS['user']->id; + //throws Exception on error + $release->installFile(); + $this->redirect($this->url_for('/overview', ['edit_plugin_id' => $plugin->id])); + } + } + public function add_action() { $this->marketplugin = new MarketPlugin(); if (Request::isXhr()) { $this->set_layout(null); } + $this->render_action("edit"); } @@ -80,6 +97,10 @@ class MypluginsController extends MarketController $data['donationsaccepted'] = 0; } $this->marketplugin->setData($data); + if ($this->marketplugin->isNew() && (MarketPlugin::findOneByPluginname($this->marketplugin->pluginname) || !strlen(trim($this->marketplugin->pluginname)))) { + PageLayout::postError(_("Ein Plugin mit diesem Namen ist schon im Marktplatz vorhanden!")); + return $this->redirect($this->url_for('/overview')); + } if ($this->marketplugin->isNew()) { $this->marketplugin['user_id'] = $GLOBALS['user']->id; } @@ -129,9 +150,15 @@ class MypluginsController extends MarketController $release->setData($release_data); $release['plugin_id'] = $this->marketplugin->getId(); $release['user_id'] = $GLOBALS['user']->id; - $release->installFile(); - $release->store(); + try { + $release->installFile(); + } catch (PluginInstallationException $e) { + PageLayout::postError($e->getMessage()); + + return $this->redirect($this->url_for('/overview')); + } } + } PageLayout::postMessage(MessageBox::success(_("Plugin wurde gespeichert."))); $this->redirect('presenting/details/' . $this->marketplugin->getId()); diff --git a/controllers/presenting.php b/controllers/presenting.php index fe7335409a41d87ced51873323966febf135e94f..93ce2949d680bf579a7277bbbf6c0bff7666e2e0 100755 --- a/controllers/presenting.php +++ b/controllers/presenting.php @@ -115,6 +115,7 @@ class PresentingController extends MarketController $this->plugins = MarketPlugin::findBySQL(" ( name LIKE :likesearch + OR pluginname LIKE :likesearch OR (SELECT CONCAT(Vorname, ' ', Nachname) FROM auth_user_md5 WHERE user_id = pluginmarket_plugins.user_id LIMIT 1) LIKE :likesearch OR MATCH (short_description, description) AGAINST (:search IN BOOLEAN MODE) OR (SELECT GROUP_CONCAT(' ', tag) FROM pluginmarket_tags WHERE pluginmarket_tags.plugin_id = plugin_id GROUP BY pluginmarket_tags.plugin_id LIMIT 1) LIKE :likesearch diff --git a/migrations/07_add_pluginname.php b/migrations/07_add_pluginname.php new file mode 100644 index 0000000000000000000000000000000000000000..268b52586d402509608391867c4d0b48e7632ccb --- /dev/null +++ b/migrations/07_add_pluginname.php @@ -0,0 +1,39 @@ +<?php +class AddPluginname extends Migration { + +public function up() { + + DBManager::get()->exec(" + ALTER TABLE `pluginmarket_plugins` CHANGE `pluginclassname` `pluginname` VARCHAR(64) NOT NULL + "); + SimpleORMap::expireTableScheme(); + foreach (MarketPlugin::findBySQL("1") as $plugin) { + if ($plugin->releases->count()) { + $pluginnames = array_count_values(array_filter($plugin->releases->getPluginName())); + arsort($pluginnames); + $pluginname = key($pluginnames); + if ($pluginname) { + $plugin->pluginname = $pluginname; + + $plugin->releases->each(function ($one) use ($pluginname) { + if ($one->getPluginName() != $pluginname) { + $one->delete(); + } + }); + } else { + $plugin->name .= " (no pluginname)"; + $plugin->releases->delete(); + $plugin->approved = 0; + } + } else { + $plugin->name .= " (no release)"; + $plugin->approved = 0; + } + $plugin->store(); + } +} + +public function down() { +} + +} \ No newline at end of file diff --git a/plugin.manifest b/plugin.manifest index 01a4c73e6edfd25fda740945f5eb3a537aae179e..c903f4fefa4750350b9d6e19f0509ba629c8b40e 100755 --- a/plugin.manifest +++ b/plugin.manifest @@ -1,4 +1,4 @@ pluginname=PluginMarktplatz pluginclassname=PluginMarket origin=studip -version=1.0.15 +version=1.0.16 diff --git a/views/myplugins/edit.php b/views/myplugins/edit.php index f2f932d3f66f13a279f75c7f0962c4a38305c681..67af53800f8a451c4598a60364aef1193e1b4c99 100755 --- a/views/myplugins/edit.php +++ b/views/myplugins/edit.php @@ -5,10 +5,13 @@ <?= _("Informationen") ?> </legend> <label> - <?= _("Name des Plugins") ?> - <input type="text" name="data[name]" value="<?= htmlReady($marketplugin['name']) ?>"> + <?= _("Angezeigter Name des Plugins") ?> + <input required type="text" name="data[name]" value="<?= htmlReady($marketplugin['name']) ?>"> + </label> + <label> + <?= _("Interner Name des Plugins (aus dem Manifest)") ?> + <input required type="text" name="data[pluginname]" value="<?= htmlReady($marketplugin['pluginname']) ?>" <?=!$marketplugin->isNew() ? 'disabled' : ''?>> </label> - <label> <?= _("Kurzbeschreibung") ?> <input type="text" name="data[short_description]" value="<?= htmlReady($marketplugin['short_description']) ?>" maxlength="160"> @@ -25,7 +28,7 @@ <label> <?= _("Lange Beschreibung") ?> - <textarea class="add_toolbar" name="data[description]"><?= htmlReady($marketplugin['description']) ?></textarea> + <textarea class="wysiwyg" name="data[description]"><?= htmlReady($marketplugin['description']) ?></textarea> </label> <label> diff --git a/views/myplugins/overview.php b/views/myplugins/overview.php index d0d41e24a90e73993919c76dd66deadd972b399f..29ea77221ac1f07cc3d70d69513e3c59a5d1d9bc 100755 --- a/views/myplugins/overview.php +++ b/views/myplugins/overview.php @@ -66,7 +66,13 @@ </tbody> </table> - +<? if ($edit_plugin_id = Request::option('edit_plugin_id')): ?> + <script> + jQuery(function ($) { + STUDIP.Dialog.fromURL('<?= $controller->url_for('myplugins/edit/' . $edit_plugin_id) ?>'); + }); + </script> +<? endif; ?> <? $sidebar = Sidebar::Get(); $sidebar->setImage(Assets::image_path("sidebar/plugin-sidebar.png")); @@ -74,5 +80,14 @@ $actions = new ActionsWidget(); $actions->addLink(_("Neues Plugin eintragen"), $controller->url_for('myplugins/add'), Icon::create('add'))->asDialog(); +$actions->addElement(new WidgetElement( + '<form action="' . $controller->url_for('myplugins/addfromzip') .'" + method="post" enctype="multipart/form-data" class="drag-and-drop"> + <input type="hidden" name="release[type]" value="zipfile"> + '. CSRFProtection::tokenTag() .' + '._('Plugin via Drag and Drop eintragen') .' + <input type="file" name="release_file"> + </form>' +)); $sidebar->addWidget($actions);