diff options
| author | Jan-Hendrik Willms <tleilax+github@gmail.com> | 2021-07-22 16:07:19 +0200 |
|---|---|---|
| committer | Jan-Hendrik Willms <tleilax+github@gmail.com> | 2021-07-22 16:19:12 +0200 |
| commit | a3da1483a9e689846179159355badfec8073dbec (patch) | |
| tree | 770dcca6bdf5f6f2a11b0e7fcbbeda6919a3fc52 /lib/plugins/core | |
current code from svn, revision 62608
Diffstat (limited to 'lib/plugins/core')
23 files changed, 1425 insertions, 0 deletions
diff --git a/lib/plugins/core/AdminCourseAction.class.php b/lib/plugins/core/AdminCourseAction.class.php new file mode 100644 index 0000000..046502c --- /dev/null +++ b/lib/plugins/core/AdminCourseAction.class.php @@ -0,0 +1,22 @@ +<?php + +interface AdminCourseAction +{ + public function getAdminActionURL(); + + /** + * Defines if the Plugin wants to use the multimode to edit multiple courses at once. + * @return boolean|string: false, if multimode is not important, else true. But you can also set it to a string (means true) that is the label of the send-button like _("Veranstaltungen archivieren") + */ + public function useMultimode(); + + /** + * Returns a template for a small table cell (the <td> wraps the template-content) + * in which you can set inputs and links to display special actions for an admin + * for the given course. + * @param $course_id + * @param null $values + * @return null|Flex_Template + */ + public function getAdminCourseActionTemplate($course_id, $values = null); +} diff --git a/lib/plugins/core/AdminCourseContents.class.php b/lib/plugins/core/AdminCourseContents.class.php new file mode 100644 index 0000000..065cc9e --- /dev/null +++ b/lib/plugins/core/AdminCourseContents.class.php @@ -0,0 +1,23 @@ +<?php + +/** + * Interface AdminCourseContents + * With this interface a plugin is able to add columns to the course-overview table for admins and roots. + */ +interface AdminCourseContents +{ + /** + * The available columns for the course-overview table for admins. Index is the identifier of the column + * for the method adminAreaGetCourseContent. The value is the display name of the column. + * @return array : an associative array like array('index' => _("Translated display name")) + */ + public function adminAvailableContents(); + + /** + * Returns the value of the additional column for the course-overview table in the admin-area. + * @param Course $course : A Course-object of the given ... course + * @param string $index : the index that comes from adminAvailableContents to identify the column. + * @return Flexi_Template | String : Either one will do, but string is preferred, because it can exported as CSV-file more easily. + */ + public function adminAreaGetCourseContent($course, $index); +} diff --git a/lib/plugins/core/AdministrationPlugin.class.php b/lib/plugins/core/AdministrationPlugin.class.php new file mode 100644 index 0000000..c9aa8da --- /dev/null +++ b/lib/plugins/core/AdministrationPlugin.class.php @@ -0,0 +1,19 @@ +<?php +# Lifter010: TODO +/* + * AdministrationPlugin.class.php - administration plugin interface + * + * NOTE: This interface is deprecated, use SystemPlugin instead. + * + * Copyright (c) 2008 - Marcus Lunzenauer <mlunzena@uos.de> + * Copyright (c) 2009 - Elmar Ludwig + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +interface AdministrationPlugin +{ +} diff --git a/lib/plugins/core/CorePlugin.php b/lib/plugins/core/CorePlugin.php new file mode 100644 index 0000000..e16b77a --- /dev/null +++ b/lib/plugins/core/CorePlugin.php @@ -0,0 +1,151 @@ +<?php +/** + * CorePlugin.class.php - base class + * + * @author André Noack <noack@data-quest.de> + * @copyright 2021 Authors + * @license GPL2 or any later version + */ +abstract class CorePlugin +{ + + /** + * plugin meta data + */ + protected $plugin_info; + + /** + * plugin constructor + * TODO bindtextdomain() + */ + public function __construct() + { + $plugin_manager = PluginManager::getInstance(); + $this->plugin_info = $plugin_manager->getPluginInfo(static::class); + } + + /** + * Return the ID of this plugin. + */ + public function getPluginId() + { + return $this->plugin_info['id']; + } + + public function isEnabled() + { + return $this->plugin_info['enabled']; + } + + /** + * Return the name of this plugin. + */ + public function getPluginName() + { + return $this->plugin_info['name']; + } + + + public function getPluginURL() + { + return $GLOBALS['ABSOLUTE_URI_STUDIP']; + } + + /** + * Returns the version of this plugin as defined in manifest. + * @return string + */ + public function getPluginVersion() + { + return ''; + } + + /** + * Checks if the plugin is a core-plugin. Returns true if this is the case. + * + * @return boolean + */ + public function isCorePlugin() + { + return true; + } + + /** + * Get the activation status of this plugin in the given context. + * This also checks the plugin default activations. + * + * @param $context context range id (optional) + */ + public function isActivated($context = null) + { + $plugin_id = $this->getPluginId(); + $plugin_manager = PluginManager::getInstance(); + + if (!isset($context)) { + $context = Context::getId(); + } + $activated = $plugin_manager->isPluginActivated($plugin_id, $context); + return $activated; + } + + /** + * Returns whether the plugin may be activated in a certain context. + * + * @param Range $context + * @return bool + */ + public function isActivatableForContext(Range $context) + { + return true; + } + + /** + * Callback function called after enabling a plugin. + * The plugin's ID is transmitted for convenience. + * + * @param $plugin_id string The ID of the plugin just enabled. + */ + public static function onEnable($plugin_id) + { + } + + /** + * Callback function called after disabling a plugin. + * The plugin's ID is transmitted for convenience. + * + * @param $plugin_id string The ID of the plugin just disabled. + */ + public static function onDisable($plugin_id) + { + } + + /** + * Callback function called after enabling a plugin. + * The plugin's ID is transmitted for convenience. + * + * @param $plugin_id string The ID of the plugin just enabled. + */ + public static function onActivation($plugin_id, $range_id) + { + } + + /** + * Callback function called after disabling a plugin. + * The plugin's ID is transmitted for convenience. + * + * @param $plugin_id string The ID of the plugin just disabled. + */ + public static function onDeactivation($plugin_id, $range_id) + { + } + + /** + * @param $range_id string + * @return bool + */ + public static function checkActivation($range_id) + { + $core_plugin = PluginEngine::getPlugin(static::class); + return $core_plugin && $core_plugin->isActivated($range_id); + } +} diff --git a/lib/plugins/core/DetailspagePlugin.class.php b/lib/plugins/core/DetailspagePlugin.class.php new file mode 100644 index 0000000..15eda09 --- /dev/null +++ b/lib/plugins/core/DetailspagePlugin.class.php @@ -0,0 +1,27 @@ +<?php +/* + * DetailspagePlugin.class.php + * + * Copyright (c) 2019 - Rasmus Fuhse <fuhse@data-quest.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ +interface DetailspagePlugin +{ + /** + * Return a template (an instance of the Flexi_Template class) + * to be rendered on the details page. Return NULL to + * render nothing for this plugin or this course. + * + * The template will automatically get a standard layout, which + * can be configured via attributes set on the template: + * + * title title to display, defaults to plugin name + * + * @return object template object to render or NULL + */ + public function getDetailspageTemplate($course); +} diff --git a/lib/plugins/core/FileUploadHook.class.php b/lib/plugins/core/FileUploadHook.class.php new file mode 100644 index 0000000..27323fd --- /dev/null +++ b/lib/plugins/core/FileUploadHook.class.php @@ -0,0 +1,12 @@ +<?php +interface FileUploadHook +{ + /** + * If this method returns a URL the new page will be shown right after adding a file + * into a filesystem. + * + * @param $file_ref + * @return null|string: URL or null if no page should be added + */ + public function getAdditionalUploadWizardPage($file_ref); +} diff --git a/lib/plugins/core/FilesystemPlugin.class.php b/lib/plugins/core/FilesystemPlugin.class.php new file mode 100644 index 0000000..6d4c46c --- /dev/null +++ b/lib/plugins/core/FilesystemPlugin.class.php @@ -0,0 +1,82 @@ +<?php +interface FilesystemPlugin +{ + /** + * Returns a Navigation-object. Only the title and the image will be used. + * + * @return null|Navigation with title and image + */ + public function getFileSelectNavigation(); + + /** + * Returns an URL to a page, where the filesystem can be configured. + * + * @return mixed + */ + public function filesystemConfigurationURL(); + + /** + * Determines if this filesystem plugin should be a source for copying or a search. + * This may be dependend on the current user and his/her configurations. + * + * @return boolean + */ + public function isSource(); + + /** + * Determines if this filesystem-plugin should show up as a personal file-area and be a destination + * for copied files. + * This may be dependend on the current user and his/her configurations. + * + * @return boolean + */ + public function isPersonalFileArea(); + + /** + * This method is used to get a folder-object for this plugin. + * Not recommended but still possible is to return a Flexi_Template for the folder, if you want to + * take care of the frontend of displaying the folder as well. + * + * @param null $folder_id : folder_id of folder to get or null if you want the top-folder + * @return FolderType|Flexi_Template + */ + public function getFolder($folder_id = null); + + /** + * @param $file_id : The id for the file in the given filesystem of the plugin. + * @return array : the already prepared File just like a file-upload-array + */ + public function getPreparedFile($file_id, $with_blob = false); + + /** + * Defines if the filesystem-plugin has a search-function. + * + * @return mixed + */ + public function hasSearch(); + + /** + * Returns an array for each special search parameter. Each parameter is itself represented by as associative array + * like + * array( + * 'name' => "name of this parameter in the form", + * 'type' => "one of 'text', 'checkbox', 'select'", + * 'options' => array() //only neccesary if type is 'select' - a key-value array with the key key as the value of the select and the value as the label of the option + * 'placeholder' => "only possible for type 'text' but not mandatory" + * ) + * This method can also return an empty array or null if no search parameters are needed or no search is provided at all. + * + * @return null|array(array(), ...) + */ + public function getSearchParameters(); + + /** + * Returns a virtual folder that 'contains' all the files as a search-result. Only return null + * if search is not implemented. + * + * @param string $text a string + * @param array $parameters : an associative array of additional search parameters as defined in getSearchParameters() + * @return FolderType|null + */ + public function search($text, $parameters = []); +} diff --git a/lib/plugins/core/ForumModule.class.php b/lib/plugins/core/ForumModule.class.php new file mode 100644 index 0000000..33784db --- /dev/null +++ b/lib/plugins/core/ForumModule.class.php @@ -0,0 +1,140 @@ +<?php +/** + * ForumModule.class.php - Interface for all intersections between the Stud.IP + * Core and something that behaves like a forum + * + * Implement all interface methods and you can integrate your plugin like + * a real core-module into Stud.IP + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * @author Till Glöggler <tgloeggl@uos.de> + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL version 3 + * @category Stud.IP + */ + +interface ForumModule extends StandardPlugin +{ + /** + * Issues can be connected with an entry in a forum. This method + * has to return an url to the connected topic for the passed issue_id. + * If no topic is connected, it has to return "false" + * + * @param string $issue_id + * @return mixed URL or false + */ + function getLinkToThread($issue_id); + + /** + * This method is called in case of an creation OR an update of an issue. + * Normally one would update the title and the content of the linked topic + * when called + * + * @param string $issue_id + * @param string $title the title of the issue + * @param string $content the description of the issue + */ + function setThreadForIssue($issue_id, $title, $content); + + /** + * Return the number of postings the connected topic contains for + * the issue with the passed id + * + * @param type $issue_id + * + * @return int + */ + function getNumberOfPostingsForIssue($issue_id); + + /** + * Return the number of postings for the passed user + * + * @param type $user_id + * + * @return int + */ + function getNumberOfPostingsForUser($user_id); + + /** + * Return the number of postings for the passed seminar + * + * @param type $seminar_id + * + * @return int + */ + function getNumberOfPostingsForSeminar($seminar_id); + + /** + * Return the number of all postings served by your module. The + * results are used for statistics. + * + * @return int + */ + function getNumberOfPostings(); + + /** + * This function is called whenever Stud.IP needs to directly operate + * on your entries-table. Your entries-table MUST have at least fields + * for a date (a change-date is preferred, but make-date will suffice), + * posting-content, seminar_id and user_id. + * + * The returning array must have the following structure: + * Array ( + * 'table' => 'your_entry_table, + * 'content' => 'your_content_field', + * 'chdate' => 'your_date_field', + * 'seminar_id' => 'your_seminar_id_field', + * 'user_id' => 'your_user_id_field' + * ) + * + * @return array + */ + function getEntryTableInfo(); + + /** + * The caller expects an array of the ten seminars with the most postings + * in your module. + * + * Return an array of the following structure: + * Array ( + * Array ( + * 'seminar_id' => + * 'display' => + * 'count' => + * ) + * ) + * + * @return array + */ + function getTopTenSeminars(); + + /** + * Is called when the data of a user is moved to another user. + * Update all user_ids with the passed new one. + * + * @param string $user_from the user_id of the user who has the data + * @param string $user_to the user_id of the user who shall receive the data + */ + function migrateUser($user_from, $user_to); + + /** + * Clean up everything for the passed seminar, because the seminar + * is beeing deleted. + * + * @param string $seminar_id + */ + function deleteContents($seminar_id); + + /** + * Return a complete HTML-Dump of all entries in the forum-module. This is + * used for archiving purposes, so make it pretty! + * + * @param string $seminar_id + * + * @return string a single-page HTML-view of all contents in one string + */ + function getDump($seminar_id); +}
\ No newline at end of file diff --git a/lib/plugins/core/HomepagePlugin.class.php b/lib/plugins/core/HomepagePlugin.class.php new file mode 100644 index 0000000..74d0204 --- /dev/null +++ b/lib/plugins/core/HomepagePlugin.class.php @@ -0,0 +1,33 @@ +<?php +# Lifter010: TODO +/* + * HomepagePlugin.class.php - home page plugin interface + * + * Copyright (c) 2008 - Marcus Lunzenauer <mlunzena@uos.de> + * Copyright (c) 2009 - Elmar Ludwig + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +interface HomepagePlugin +{ + /** + * Return a template (an instance of the Flexi_Template class) + * to be rendered on the given user's home page. Return NULL to + * render nothing for this plugin. + * + * The template will automatically get a standard layout, which + * can be configured via attributes set on the template: + * + * title title to display, defaults to plugin name + * icon_url icon for this plugin (if any) + * admin_url admin link for this plugin (if any) + * admin_title title for admin link (default: Administration) + * + * @return object template object to render or NULL + */ + function getHomepageTemplate($user_id); +} diff --git a/lib/plugins/core/LibraryPlugin.class.php b/lib/plugins/core/LibraryPlugin.class.php new file mode 100644 index 0000000..a7fb873 --- /dev/null +++ b/lib/plugins/core/LibraryPlugin.class.php @@ -0,0 +1,55 @@ +<?php + + +/* + * LibraryPlugin.class.php - A plugin class for library plugins. + * + * Copyright (c) 2020 Moritz Strohm + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + + +interface LibraryPlugin +{ + /** + * Generates the URL that leads to the plugin action to create a request. + * The URL may vary depending on the ID of the library file that shall be + * requested. Therefore, the library file ID is passed to this method. + * + * @param $library_file_id The library file ID to which a request URL shall + * be generated. + * + * @returns string The URL for the request action of the plugin. + */ + public function getRequestURL(string $library_file_id) : string; + + + /** + * Generates the title for the plugin action to create a request. + * That title may vary depending on the library file that shall be requested. + * Therefore, the file is passed to this method. + * + * @param LibraryFile $file The file to which the request URL title shall be + * generated. + * + * @returns string The title for the request URL action of the plugin. + */ + public function getRequestTitle() : string; + + + /** + * Generates the icon for the plugin action to create a request. + * That icon may vary depending on the library file that shall be requested. + * Therefore, the file is passed to this method. + * + * @param LibraryFile $file The file to which the request URL icon shall be + * generated. + * + * @returns Icon The icon for the request URL action of the plugin. + */ + public function getRequestIcon() : Icon; +} diff --git a/lib/plugins/core/MetricsPlugin.class.php b/lib/plugins/core/MetricsPlugin.class.php new file mode 100644 index 0000000..95edaf1 --- /dev/null +++ b/lib/plugins/core/MetricsPlugin.class.php @@ -0,0 +1,23 @@ +<?php +/* + * MetricsPlugins take countings and measurements and transfer them to + * a specific backend like statsd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author <mlunzena@uos.de> + * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 + * @category Stud.IP + */ + +interface MetricsPlugin +{ + public function count($stat, $value, $sampleRate = null); + + public function timing($stat, $time, $sampleRate = null); + + public function gauge($stat, $value, $sampleRate = null); +} diff --git a/lib/plugins/core/PluginAssetsTrait.php b/lib/plugins/core/PluginAssetsTrait.php new file mode 100644 index 0000000..326809c --- /dev/null +++ b/lib/plugins/core/PluginAssetsTrait.php @@ -0,0 +1,215 @@ +<?php +/** + * Trait for assets handling in plugins. + * + * @author Jan-Hendrik Willms <tleilax+studip@gmail.com> + * @license GPL2 or any later version + * @since Stud.IP 4.4 + */ +trait PluginAssetsTrait +{ + /** + * Adds many stylesheeets at once. + * @param array $filenames List of relative filenames + * @param array $variables Optional array of variables to pass to the + * LESS compiler + * @param array $link_attr Attributes to pass to the link elements + * @param string $path Common path prefix for all filenames + */ + protected function addStylesheets(array $filenames, array $variables = [], array $link_attr = [], $path = '') + { + if (Studip\ENV === 'development') { + foreach ($filenames as $filename) { + $this->addStylesheet("{$path}{$filename}", $variables, $link_attr); + } + } + + $hash = substr(md5(serialize($filenames)), -8); + $filename = "combined-{$hash}.css"; + + // Get asset file from storage + $asset = Assets\Storage::getFactory()->createCSSFile( + $filename, + $this->createMetaData() + ); + + // Compile asset if neccessary + if ($asset->isNew()) { + $content = ''; + foreach ($filenames as $filename) { + $file = $this->resolveFilename($filename, $path); + $content .= $this->readPluginAssetFile($file, $variables); + } + $asset->setContent($content); + } + + $this->includeStyleAsset($asset, $link_attr); + } + + /** + * Includes given stylesheet in page, compiles less if neccessary + * + * @param string $filename Name of the stylesheet (css or less) to include + * (relative to plugin directory) + * @param array $variables Optional array of variables to pass to the + * LESS compiler + * @param array $link_attr Attributes to pass to the link element + */ + protected function addStylesheet($filename, array $variables = [], array $link_attr = []) + { + $extension = pathinfo($filename, PATHINFO_EXTENSION); + if (!in_array($extension, ['less', 'scss'])) { + PageLayout::addStylesheet( + "{$this->getPluginURL()}/{$filename}?v={$this->getPluginVersion()}", + $link_attr + ); + return; + } + + // Create absolute path to assets file + $file = $this->resolveFilename($filename); + + // Get asset file from storage + $asset = Assets\Storage::getFactory()->createCSSFile( + $file, + $this->createMetaData() + ); + + // Compile asset if neccessary + if ($asset->isNew()) { + $css = $this->readPluginAssetFile($file, $variables); + $asset->setContent($css); + } + + $this->includeStyleAsset($asset, $link_attr); + } + + private function includeStyleAsset(Assets\PluginAsset $asset, array $link_attr) + { + // Include asset in page by reference or directly + $download_uri = $asset->getDownloadLink(); + if ($download_uri === false) { + PageLayout::addStyle($asset->getContent(), $link_attr); + } else { + $link_attr['rel'] = 'stylesheet'; + $link_attr['href'] = $download_uri; + $link_attr['type'] = 'text/css'; + PageLayout::addHeadElement('link', $link_attr); + } + } + + /** + * Adds many scripts at once. + * @param array $filenames List of relative filenames + * @param array $link_attr Attributes to pass to the script elements + * @param string $path Common path prefix for all filenames + */ + protected function addScripts(array $filenames, array $link_attr = [], $path = '') + { + if (Studip\ENV === 'development') { + foreach ($filenames as $filename) { + $this->addScript("{$path}{$filename}", $link_attr); + } + return; + } + + $hash = substr(md5(serialize($filenames)), -8); + $filename = "combined-{$hash}.js"; + + // Get asset file from storage + $asset = Assets\Storage::getFactory()->createJSFile( + $filename, + $this->createMetaData() + ); + + // Compile asset if neccessary + if ($asset->isNew()) { + $content = ''; + foreach ($filenames as $filename) { + $file = $this->resolveFilename($filename, $path); + $content .= $this->readPluginAssetFile($file) . ';'; + } + $asset->setContent($content); + } + + // Include asset in page by reference or directly + $download_uri = $asset->getDownloadLink(); + if ($download_uri === false) { + PageLayout::addHeadElement('script', $link_attr, $asset->getContent()); + } else { + $link_attr['src'] = $download_uri; + PageLayout::addHeadElement('script', $link_attr); + } + } + + /** + * Includes given script in page. + * + * @param string $filename Name of script file + * @param array $link_attr Attributes to pass to the script element + */ + protected function addScript($filename, array $link_attr = []) + { + PageLayout::addScript( + "{$this->getPluginURL()}/{$filename}?v={$this->getPluginVersion()}", + $link_attr + ); + } + + /** + * Create metadata for plugin assets factory + * @return array + */ + private function createMetaData() + { + return [ + 'plugin_id' => $this->plugin_info['depends'] ?: $this->getPluginId(), + 'plugin_version' => $this->getPluginVersion(), + ]; + } + + /** + * Resolves relative filename to absolute filename. + * + * @param string $filename Relative filename + * @param string $path Optional relative path the file is stored in + * @return string + * @throws RuntimeException when absolute file is missing + */ + private function resolveFilename($filename, $path = '') + { + $file = $GLOBALS['ABSOLUTE_PATH_STUDIP'] + . $this->getPluginPath() . '/' + . "{$path}{$filename}"; + + // Fail if file does not exist + if (!file_exists($file)) { + throw new RuntimeException("Could not locate assets file '{$filename}'"); + } + + return $file; + } + + /** + * Reads assets file (and compiles if neccessary). + * @param string $filename Name of the file to read + * @param array $variables Additional variables for compiler (if appropriate) + * @return string + */ + private function readPluginAssetFile($filename, array $variables = []) + { + $contents = file_get_contents($filename); + + $extension = pathinfo($filename, PATHINFO_EXTENSION); + if ($extension === 'less') { + $contents = Assets\LESSCompiler::getInstance()->compile($contents, $variables + [ + 'plugin-path' => $this->getPluginURL(), + ]); + } elseif ($extension === 'scss') { + $contents = Assets\SASSCompiler::getInstance()->compile($contents, $variables + [ + 'plugin-path' => '"' . $this->getPluginURL() . '"', + ]); + } + return $contents; + } +} diff --git a/lib/plugins/core/PortalPlugin.class.php b/lib/plugins/core/PortalPlugin.class.php new file mode 100644 index 0000000..ed157a8 --- /dev/null +++ b/lib/plugins/core/PortalPlugin.class.php @@ -0,0 +1,33 @@ +<?php +# Lifter010: TODO +/* + * PortalPlugin.class.php - start / portal page plugin interface + * + * Copyright (c) 2008 - Marcus Lunzenauer <mlunzena@uos.de> + * Copyright (c) 2009 - Elmar Ludwig + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +interface PortalPlugin +{ + /** + * Return a template (an instance of the Flexi_Template class) + * to be rendered on the start or portal page. Return NULL to + * render nothing for this plugin. + * + * The template will automatically get a standard layout, which + * can be configured via attributes set on the template: + * + * title title to display, defaults to plugin name + * icon_url icon for this plugin (if any) + * admin_url admin link for this plugin (if any) + * admin_title title for admin link (default: Administration) + * + * @return object template object to render or NULL + */ + function getPortalTemplate(); +} diff --git a/lib/plugins/core/PrivacyPlugin.class.php b/lib/plugins/core/PrivacyPlugin.class.php new file mode 100644 index 0000000..73a971d --- /dev/null +++ b/lib/plugins/core/PrivacyPlugin.class.php @@ -0,0 +1,24 @@ +<?php +/** + * PrivacyPlugin are able to handle user data according the privacy policy. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author Timo Hartge <hartge@data-quest.de> + * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 + * @category Stud.IP + */ + +interface PrivacyPlugin +{ + /** + * Export available data of a given user into a storage object + * (an instance of the StoredUserData class) for that user. + * + * @param StoredUserData $storage object to store data into + */ + public function exportUserData(StoredUserData $storage); +} diff --git a/lib/plugins/core/QuestionnaireAssignmentPlugin.class.php b/lib/plugins/core/QuestionnaireAssignmentPlugin.class.php new file mode 100644 index 0000000..6892f8a --- /dev/null +++ b/lib/plugins/core/QuestionnaireAssignmentPlugin.class.php @@ -0,0 +1,55 @@ +<?php + +/** + * Interface QuestionnaireAssignmentPlugin + * Implement this interface if you want to relate Stud.IP-questionnaires to your plugin-contents. + * By storing an assignment you should set the range_type to something unique that is + * related to your plugin like "mytaskplugin". In all methods you should first check if the + * assignment is related to your plugin, because other QuestionnaireAssignmentPlugins might + * be installed as well. + */ +interface QuestionnaireAssignmentPlugin +{ + /** + * Returns if the questionnaire is viewable dependend on the assignment. Check for the range_type + * and range_id to see if the the assignment has to do with your plugin (and not with + * somebody else's plugin) and if type and id fit. + * @param QuestionnaireAssignment $questionnaire + * @return boolean + */ + public function isQuestionnaireViewable(QuestionnaireAssignment $questionnaire); + + /** + * Returns if the questionnaire is editable dependend on the assignment. Check for the range_type + * and range_id to see if the the assignment has to do with your plugin (and not with + * somebody else's plugin) and if type and id fit. + * @param QuestionnaireAssignment $questionnaire + * @return boolean + */ + public function isQuestionnaireEditable(QuestionnaireAssignment $questionnaire); + + /** + * The display name of the assignment. + * @param QuestionnaireAssignment $questionnaire + * @return string + */ + public function getQuestionnaireAssignmentName(QuestionnaireAssignment $questionnaire); + + /** + * This template will get displayed when someone at tools -> questionnaires + * wants to edit the contexts of the questionnaire. Maybe you don't want to provide a + * template here, so return null or just a readonly html-snippet. + * @param Questionnaire $questionnaire + * @return null|Flexi_Template + */ + public function getQuestionnaireAssignmentEditTemplate(Questionnaire $questionnaire); + + /** + * When the context of the questionnaire is stored at tools -> questionnaires (where + * the template from getQuestionnaireAssignmentEditTemplate was displayed) you should + * use this method to store your assignments as well. + * @param Questionnaire $questionnaire + * @return null + */ + public function storeQuestionnaireAssignments(Questionnaire $questionnaire); +} diff --git a/lib/plugins/core/RESTAPIPlugin.class.php b/lib/plugins/core/RESTAPIPlugin.class.php new file mode 100644 index 0000000..d395dea --- /dev/null +++ b/lib/plugins/core/RESTAPIPlugin.class.php @@ -0,0 +1,23 @@ +<?php +/* + * REST-API Plugins add maps to the REST-API router. + * + * Copyright (c) 2014 - Marcus Lunzenauer <mlunzena@uos.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +interface RESTAPIPlugin +{ + /** + * Returns one or more instances of RESTAPI\RouteMap to register + * to the Router. + * + * @return RouteMap|Array either a single instance of class + * RouteMap or an array of them + */ + public function getRouteMaps(); +} diff --git a/lib/plugins/core/Role.class.php b/lib/plugins/core/Role.class.php new file mode 100644 index 0000000..3ca8a11 --- /dev/null +++ b/lib/plugins/core/Role.class.php @@ -0,0 +1,89 @@ +<?php +/** + * Role.class.php + * + * @author Dennis Reil <dennis.reil@offis.de> + * @author Michael Riehemann <michael.riehemann@uni-oldenburg.de> + * @package pluginengine + * @subpackage core + * @copyright 2009 Stud.IP + * @license http://www.gnu.org/licenses/gpl.html GPL Licence 3 + */ +class Role +{ + const UNKNOWN_ROLE_ID = null; + + public $roleid; + public $rolename; + public $systemtype; + + /** + * Constructor + */ + public function __construct($id = self::UNKNOWN_ROLE_ID, $name = '', $system = false) + { + $this->setRoleid($id); + $this->setRolename($name); + $this->setSystemtype($system); + } + + /** + * Returns the role's id. + * + * @return int + */ + public function getRoleid() + { + return $this->roleid; + } + + /** + * Set the role's id. + * + * @param int $newid + */ + public function setRoleid($newid) + { + $this->roleid = $newid; + } + + /** + * Returns the role's name. + * + * @return string + */ + public function getRolename() + { + return $this->rolename; + } + + /** + * Set the role's name. + * + * @param string $newrole + */ + public function setRolename($newrole) + { + $this->rolename = $newrole; + } + + /** + * Returns whether the role is a system role. + * + * @return boolean + */ + public function getSystemtype() + { + return $this->systemtype; + } + + /** + * Sets whether the role is a system role. + * + * @param boolean $newtype + */ + public function setSystemtype($newtype) + { + $this->systemtype = (bool) $newtype; + } +} diff --git a/lib/plugins/core/ScorePlugin.class.php b/lib/plugins/core/ScorePlugin.class.php new file mode 100644 index 0000000..064ddc3 --- /dev/null +++ b/lib/plugins/core/ScorePlugin.class.php @@ -0,0 +1,29 @@ +<?php +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +interface ScorePlugin +{ + /** + * Returns null or an array of associated arrays - each one to + * indicate a db-table in which the plugin stores user activities. + * + * For a bullitin-board-plugin this array could look like this: + * + * return array( + * array( + * 'table' => "bullitin_board_entries", + * 'user_id_column' => "user_id", + * 'date_column' => "mkdate", + * 'where' => "public = '1'" //only public entries should be counted + * ) + * ); + * + * @return null|array of associated arrays + */ + function getPluginActivityTables(); +} diff --git a/lib/plugins/core/StandardPlugin.class.php b/lib/plugins/core/StandardPlugin.class.php new file mode 100644 index 0000000..960ffd0 --- /dev/null +++ b/lib/plugins/core/StandardPlugin.class.php @@ -0,0 +1,17 @@ +<?php +# Lifter010: TODO +/* + * StandardPlugin.class.php - course or institute plugin interface + * + * Copyright (c) 2008 - Marcus Lunzenauer <mlunzena@uos.de> + * Copyright (c) 2009 - Elmar Ludwig + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +interface StandardPlugin extends StudipModule +{ +} diff --git a/lib/plugins/core/StudIPPlugin.class.php b/lib/plugins/core/StudIPPlugin.class.php new file mode 100644 index 0000000..2fa9703 --- /dev/null +++ b/lib/plugins/core/StudIPPlugin.class.php @@ -0,0 +1,218 @@ +<?php +/** + * StudIPPlugin.class.php - generic plugin base class + * + * @author Elmar Ludwig <ludwig@uos.de> + * @copyright 2009 Authors + * @license GPL2 or any later version + */ +abstract class StudIPPlugin +{ + use PluginAssetsTrait; + use TranslatablePluginTrait; + + /** + * plugin meta data + */ + protected $plugin_info; + + /** + * Plugin manifest + */ + protected $manifest = null; + + /** + * plugin constructor + */ + public function __construct() + { + $plugin_manager = PluginManager::getInstance(); + $this->plugin_info = $plugin_manager->getPluginInfo(static::class); + } + + /** + * Return the ID of this plugin. + */ + public function getPluginId() + { + return $this->plugin_info['id']; + } + + public function isEnabled() + { + return $this->plugin_info['enabled']; + } + + /** + * Return the name of this plugin. + */ + public function getPluginName() + { + return $this->plugin_info['name']; + } + + /** + * Return the filesystem path to this plugin. + */ + public function getPluginPath() + { + return "plugins_packages/{$this->plugin_info['path']}"; + } + + /** + * Return the URL of this plugin. Can be used to refer to resources + * (images, style sheets, etc.) inside the installed plugin package. + */ + public function getPluginURL() + { + return $GLOBALS['ABSOLUTE_URI_STUDIP'] . $this->getPluginPath(); + } + + /** + * Return metadata stored in the manifest of this plugin. + */ + public function getMetadata() + { + if ($this->manifest === null) { + $plugin_manager = PluginManager::getInstance(); + $this->manifest = $plugin_manager->getPluginManifest($this->getPluginPath()); + } + return $this->manifest; + } + + /** + * Returns the version of this plugin as defined in manifest. + * @return string + */ + public function getPluginVersion() + { + return $this->getMetadata()['version']; + } + + /** + * Checks if the plugin is a core-plugin. Returns true if this is the case. + * + * @return boolean + */ + public function isCorePlugin() + { + return $this->plugin_info['core']; + } + + /** + * Get the activation status of this plugin in the given context. + * This also checks the plugin default activations. + * + * @param $context context range id (optional) + * @param $type type of activation (optional), can be set to 'user' + * in order to point to a homepage plugin + */ + public function isActivated($context = null, $type = 'sem') + { + $plugin_id = $this->getPluginId(); + $plugin_manager = PluginManager::getInstance(); + + /* + * Context can be a Seminar ID or the current user ID if not set. + * Identification is done via the "username" parameter. + */ + if (!isset($context)) { + if ($type === 'user') { + $context = get_userid(Request::username('username', $GLOBALS['user']->username)); + } else { + $context = Context::getId(); + } + } + + if ($type === 'user') { + $activated = $plugin_manager->isPluginActivatedForUser($plugin_id, $context); + } else { + $activated = $plugin_manager->isPluginActivated($plugin_id, $context); + } + + return $activated; + } + + /** + * Returns whether the plugin may be activated in a certain context. + * + * @param Range $context + * @return bool + */ + public function isActivatableForContext(Range $context) + { + return true; + } + + /** + * This method dispatches all actions. + * + * @param string part of the dispatch path that was not consumed + * + * @return void + */ + public function perform($unconsumed_path) + { + $args = explode('/', $unconsumed_path); + $action = $args[0] !== '' ? array_shift($args).'_action' : 'show_action'; + + if (!method_exists($this, $action)) { + $trails_root = $this->getPluginPath(); + $trails_uri = rtrim(PluginEngine::getLink($this, [], null, true), '/'); + + $dispatcher = new Trails_Dispatcher($trails_root, $trails_uri, 'index'); + $dispatcher->current_plugin = $this; + try { + $dispatcher->dispatch($unconsumed_path); + } catch (Trails_UnknownAction $exception) { + if (count($args) > 0) { + throw $exception; + } else { + throw new Exception(_('unbekannte Plugin-Aktion: ') . $unconsumed_path); + } + } + } else { + call_user_func_array([$this, $action], $args); + } + } + + /** + * Callback function called after enabling a plugin. + * The plugin's ID is transmitted for convenience. + * + * @param $plugin_id string The ID of the plugin just enabled. + */ + public static function onEnable($plugin_id) + { + } + + /** + * Callback function called after disabling a plugin. + * The plugin's ID is transmitted for convenience. + * + * @param $plugin_id string The ID of the plugin just disabled. + */ + public static function onDisable($plugin_id) + { + } + + /** + * Callback function called after enabling a plugin. + * The plugin's ID is transmitted for convenience. + * + * @param $plugin_id string The ID of the plugin just enabled. + */ + public static function onActivation($plugin_id, $range_id) + { + } + + /** + * Callback function called after disabling a plugin. + * The plugin's ID is transmitted for convenience. + * + * @param $plugin_id string The ID of the plugin just disabled. + */ + public static function onDeactivation($plugin_id, $range_id) + { + } +} diff --git a/lib/plugins/core/SystemPlugin.class.php b/lib/plugins/core/SystemPlugin.class.php new file mode 100644 index 0000000..c204567 --- /dev/null +++ b/lib/plugins/core/SystemPlugin.class.php @@ -0,0 +1,17 @@ +<?php +# Lifter010: TODO +/* + * SystemPlugin.class.php - generic system plugin interface + * + * Copyright (c) 2008 - Marcus Lunzenauer <mlunzena@uos.de> + * Copyright (c) 2009 - Elmar Ludwig + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +interface SystemPlugin +{ +} diff --git a/lib/plugins/core/TranslatablePluginTrait.php b/lib/plugins/core/TranslatablePluginTrait.php new file mode 100644 index 0000000..13e0903 --- /dev/null +++ b/lib/plugins/core/TranslatablePluginTrait.php @@ -0,0 +1,104 @@ +<?php +/** + * Trait used to allow plugins to be translated in a generic way. + * + * @author Jan-Hendrik Willms <tleilax+studip@gmail.com> + * @license GPL2 or any later version + * @since Stud.IP 5.0 + */ +trait TranslatablePluginTrait +{ + protected $translation_domain = null; + + /** + * Initializes the translation for the plugin. + * + * @param string $domain + */ + protected function initializeTranslation($domain) + { + bindtextdomain($domain, $this->getPluginPath() . '/locale'); + bind_textdomain_codeset($domain, 'UTF-8'); + } + + /** + * Returns the defined translation domain from plugin manifest. If none + * is set, false is returned. + * + * @return false|string The translation domain from manifest, if set + */ + protected function getTranslationDomain() + { + if ($this->translation_domain === null) { + $manifest = $this->getMetadata(); + $this->translation_domain = $manifest['localedomain'] ?? false; + + if ($this->translation_domain !== false) { + $this->initializeTranslation($this->translation_domain); + } + } + return $this->translation_domain; + } + + /** + * Returns whether the plugin has a translation defined or not. + * + * @return bool + */ + public function hasTranslation() + { + return $this->getTranslationDomain() !== false; + } + + /** + * Plugin localization for a single string. + * + * @param string $string String to translate + * @return string + */ + public function _($string) + { + $domain = $this->getTranslationDomain(); + if (!$domain) { + return $string; + } + + $result = dgettext($domain, $string); + + // Fallback to possible translations from core system + if ($result === $string) { + $result = _($string); + } + + return $result; + } + + /** + * Plugin localization for plural strings. + * + * @param string $string0 String to translate (singular) + * @param string $string1 String to translate (plural) + * @param mixed $n Quantity factor (may be an array or array-like) + * @return string + */ + public function _n($string0, $string1, $n) + { + if (is_array($n)) { + $n = count($n); + } + + $domain = $this->getTranslationDomain(); + if (!$domain) { + return $n == 1 ? $string0 : $string1; + } + + $result = dngettext($domain, $string0, $string1, $n); + + // Fallback to possible translations from core system + if ($result === $string0 || $result === $string1) { + $result = ngettext($string0, $string1, $n); + } + + return $result; + } +} diff --git a/lib/plugins/core/WebServicePlugin.class.php b/lib/plugins/core/WebServicePlugin.class.php new file mode 100644 index 0000000..ff3e757 --- /dev/null +++ b/lib/plugins/core/WebServicePlugin.class.php @@ -0,0 +1,14 @@ +<?php +/* + * Copyright (c) 2011 <mlunzena@uos.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +interface WebServicePlugin +{ + function getWebServices(); +} |
