Comment: | Rename 'url' to 'author_url' in module/plugin.ini, add "open" button in extensions list, better handle errors in plugin.ini |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | dev |
Files: | files | file ages | folders |
SHA3-256: |
f95cf4f0aa53f8f7ec93138a3a6fcd1a |
User & Date: | bohwaz on 2023-02-17 12:38:47 |
Other Links: | branch diff | manifest | tags |
2023-02-17
| ||
21:21 | Fix missing use constant statement for emails check-in: d8c24cbf4a user: bohwaz tags: dev | |
12:38 | Rename 'url' to 'author_url' in module/plugin.ini, add "open" button in extensions list, better handle errors in plugin.ini check-in: f95cf4f0aa user: bohwaz tags: dev | |
12:37 | Update default colors in CSS, use admin_color1 and 2 even in install, if set check-in: 2e065b30bb user: bohwaz tags: dev | |
Modified src/include/lib/Garradin/Entities/Module.php from [d85fe33668] to [2994320732].
︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 | { const ROOT = File::CONTEXT_SKELETON . '/modules'; const DIST_ROOT = ROOT . '/skel-dist/modules'; const META_FILE = 'module.ini'; const ICON_FILE = 'icon.svg'; const README_FILE = 'README.md'; const CONFIG_FILE = 'config.html'; // Snippets, don't forget to create alias constant in UserTemplate\Modules class const SNIPPET_TRANSACTION = 'snippets/transaction_details.html'; const SNIPPET_USER = 'snippets/user_details.html'; const SNIPPET_HOME_BUTTON = 'snippets/home_button.html'; const SNIPPETS = [ | > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | { const ROOT = File::CONTEXT_SKELETON . '/modules'; const DIST_ROOT = ROOT . '/skel-dist/modules'; const META_FILE = 'module.ini'; const ICON_FILE = 'icon.svg'; const README_FILE = 'README.md'; const CONFIG_FILE = 'config.html'; const INDEX_FILE = 'index.html'; // Snippets, don't forget to create alias constant in UserTemplate\Modules class const SNIPPET_TRANSACTION = 'snippets/transaction_details.html'; const SNIPPET_USER = 'snippets/user_details.html'; const SNIPPET_HOME_BUTTON = 'snippets/home_button.html'; const SNIPPETS = [ |
︙ | ︙ | |||
40 41 42 43 44 45 46 | * Directory name */ protected string $name; protected string $label; protected ?string $description; protected ?string $author; | | | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | * Directory name */ protected string $name; protected string $label; protected ?string $description; protected ?string $author; protected ?string $author_url; protected ?string $restrict_section; protected ?int $restrict_level; protected bool $home_button; protected bool $menu; protected ?\stdClass $config; protected bool $enabled; |
︙ | ︙ | |||
84 85 86 87 88 89 90 | if (!isset($ini->name)) { return false; } $this->set('label', $ini->name); $this->set('description', $ini->description ?? null); $this->set('author', $ini->author ?? null); | | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | if (!isset($ini->name)) { return false; } $this->set('label', $ini->name); $this->set('description', $ini->description ?? null); $this->set('author', $ini->author ?? null); $this->set('author_url', $ini->author_url ?? null); $this->set('home_button', !empty($ini->home_button)); $this->set('menu', !empty($ini->menu)); $this->set('restrict_section', $ini->restrict_section ?? null); $this->set('restrict_level', isset($ini->restrict_section, $ini->restrict_level, Session::ACCESS_WORDS[$ini->restrict_level]) ? Session::ACCESS_WORDS[$ini->restrict_level] : null); return true; } |
︙ | ︙ |
Modified src/include/lib/Garradin/Entities/Plugin.php from [e14930c4dd] to [0b3948c904].
︙ | ︙ | |||
62 63 64 65 66 67 68 | protected string $name; protected string $label; protected string $version; protected ?string $description; protected ?string $author; | | > > | | > > > > > > > > > > | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | protected string $name; protected string $label; protected string $version; protected ?string $description; protected ?string $author; protected ?string $author_url; protected bool $home_button; protected bool $menu; protected ?string $restrict_section; protected ?int $restrict_level; protected ?\stdClass $config; protected bool $enabled; protected ?string $_broken_message = null; public function hasCode(): bool { return file_exists($this->path()); } public function selfCheck(): void { $this->assert(preg_match('/^' . Plugins::NAME_REGEXP . '$/', $this->name), 'Nom unique d\'extension invalide: ' . $this->name); $this->assert(isset($this->label) && trim($this->label) !== '', sprintf('%s : le nom de l\'extension ("name") ne peut rester vide', $this->name)); $this->assert(isset($this->label) && trim($this->version) !== '', sprintf('%s : la version ne peut rester vide', $this->name)); if ($this->hasCode() || $this->enabled) { $this->assert(!$this->menu || $this->hasFile(self::INDEX_FILE), 'Le fichier admin/index.php n\'existe pas alors que la directive "menu" est activée.'); $this->assert(!$this->home_button || $this->hasFile(self::INDEX_FILE), 'Le fichier admin/index.php n\'existe pas alors que la directive "home_button" est activée.'); $this->assert(!$this->home_button || $this->hasFile(self::ICON_FILE), 'Le fichier admin/icon.svg n\'existe pas alors que la directive "home_button" est activée.'); } } public function setBrokenMessage(string $str) { $this->_broken_message = $str; } public function getBrokenMessage(): ?string { return $this->_broken_message; } /** * Fills information from plugin.ini file */ public function updateFromINI(): bool { $ini = parse_ini_file($this->path(self::META_FILE), false, \INI_SCANNER_TYPED); |
︙ | ︙ | |||
113 114 115 116 117 118 119 | $this->assert(empty($ini->min_version) || version_compare(\Garradin\garradin_version(), $ini->min_version, '>='), sprintf('L\'extension "%s" nécessite Paheko version %s ou supérieure.', $this->name, $ini->min_version)); $this->set('label', $ini->name); $this->set('version', $ini->version); $this->set('description', $ini->description ?? null); $this->set('author', $ini->author ?? null); | | | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | $this->assert(empty($ini->min_version) || version_compare(\Garradin\garradin_version(), $ini->min_version, '>='), sprintf('L\'extension "%s" nécessite Paheko version %s ou supérieure.', $this->name, $ini->min_version)); $this->set('label', $ini->name); $this->set('version', $ini->version); $this->set('description', $ini->description ?? null); $this->set('author', $ini->author ?? null); $this->set('author_url', $ini->author_url ?? null); $this->set('home_button', !empty($ini->home_button)); $this->set('menu', !empty($ini->menu)); $this->set('restrict_section', $ini->restrict_section ?? null); $this->set('restrict_level', isset($ini->restrict_section, $ini->restrict_level, Session::ACCESS_WORDS[$ini->restrict_level]) ? Session::ACCESS_WORDS[$ini->restrict_level] : null); return true; } |
︙ | ︙ | |||
152 153 154 155 156 157 158 | public function url(string $file = '', array $params = null) { if (null !== $params) { $params = '?' . http_build_query($params); } | > > > > > > > > | > > > > | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | public function url(string $file = '', array $params = null) { if (null !== $params) { $params = '?' . http_build_query($params); } if (substr($file, 0, 6) == 'admin/') { $url = ADMIN_URL; $file = substr($file, 6); } else { $url = WWW_URL; } return sprintf('%sp/%s/%s%s', $url, $this->name, $file, $params); } public function getConfig(string $key = null) { if (is_null($key)) { return $this->config; } if (property_exists($this->config, $key)) { return $this->config->$key; } return null; } public function setConfigProperty(string $key, $value = null) { if (null === $this->config) { $this->config = new \stdClass; } if (is_null($value)) { unset($this->config->$key); } else { $this->config->$key = $value; } |
︙ | ︙ | |||
344 345 346 347 348 349 350 | } } public function route(string $uri): void { $uri = ltrim($uri, '/'); | | > > > > > | 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | } } public function route(string $uri): void { $uri = ltrim($uri, '/'); if (0 === strpos($uri, 'admin/')) { if (!Session::getInstance()->isLogged()) { Utils::redirect('!login.php'); } } else { $uri = 'public/' . $uri; } if (!$uri || substr($uri, -1) == '/') { $uri .= 'index.php'; } |
︙ | ︙ |
Modified src/include/lib/Garradin/Install.php from [0a113d106d] to [83fa8d0d78].
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 | use Garradin\Entities\Users\User; use Garradin\Entities\Files\File; use Garradin\Entities\Search; use Garradin\Users\DynamicFields; use Garradin\Users\Session; use Garradin\Files\Files; use Garradin\UserTemplate\Modules; use KD2\HTTP; /** * Pour procéder à l'installation de l'instance Garradin * Utile pour automatiser l'installation sans passer par la page d'installation */ | > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | use Garradin\Entities\Users\User; use Garradin\Entities\Files\File; use Garradin\Entities\Search; use Garradin\Users\DynamicFields; use Garradin\Users\Session; use Garradin\Files\Files; use Garradin\UserTemplate\Modules; use Garradin\Plugins; use KD2\HTTP; /** * Pour procéder à l'installation de l'instance Garradin * Utile pour automatiser l'installation sans passer par la page d'installation */ |
︙ | ︙ | |||
351 352 353 354 355 356 357 | ]); $search->created = new \DateTime; $search->save(); $config->save(); // Install welcome plugin if available | | | | | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | ]); $search->created = new \DateTime; $search->save(); $config->save(); // Install welcome plugin if available $has_welcome_plugin = Plugins::exists('welcome'); if ($has_welcome_plugin) { Plugins::install('welcome'); } foreach ($plugins as $plugin) { Plugins::install($plugin); } Modules::refresh(); foreach ($modules as $module) { $m = Modules::get($module); $m->set('enabled', true); |
︙ | ︙ |
Modified src/include/lib/Garradin/Plugins.php from [2cbb616829] to [1823da1b99].
︙ | ︙ | |||
44 45 46 47 48 49 50 51 52 53 54 55 56 57 | if (file_exists(PLUGINS_ROOT . '/' . $name . '.tar.gz')) { return 'phar://' . PLUGINS_ROOT . '/' . $name . '.tar.gz'; } else { return PLUGINS_ROOT . '/' . $name; } } /** * Déclenche le signal donné auprès des plugins enregistrés * @param string $signal Nom du signal * @param array $params Paramètres du callback (array ou null) * @return NULL NULL si aucun plugin n'a été appelé, * TRUE si un plugin a été appelé et a arrêté l'exécution, | > > > > > | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | if (file_exists(PLUGINS_ROOT . '/' . $name . '.tar.gz')) { return 'phar://' . PLUGINS_ROOT . '/' . $name . '.tar.gz'; } else { return PLUGINS_ROOT . '/' . $name; } } static public function exists(string $name): bool { return file_exists(self::getPath($name)); } /** * Déclenche le signal donné auprès des plugins enregistrés * @param string $signal Nom du signal * @param array $params Paramètres du callback (array ou null) * @return NULL NULL si aucun plugin n'a été appelé, * TRUE si un plugin a été appelé et a arrêté l'exécution, |
︙ | ︙ | |||
87 88 89 90 91 92 93 | if (null === $params) { $params = []; } foreach ($list as $row) { | | | > > | > > > | | | | | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | if (null === $params) { $params = []; } foreach ($list as $row) { $path = self::exists($row->plugin); // Ne pas appeler les plugins dont le code n'existe pas/plus, if (!$path) { continue; } $callback = 'Garradin\\Plugin\\' . $row->callback; if (!is_callable($callback)) { continue; } $params['plugin_root'] = self::getPath($row->plugin); $return = call_user_func_array($callback, [&$params, &$callback_return]); if (true === $return) { return true; } } return false; } static public function listModulesAndPlugins(bool $installable = false): array { $list = []; if ($installable) { foreach (EM::getInstance(Module::class)->iterate('SELECT * FROM @TABLE WHERE enabled = 0;') as $m) { $list[$m->name] = ['module' => $m]; } foreach (self::listInstallable() as $name => $p) { $list[$name] = ['plugin' => $p]; } foreach (self::listInstalled() as $p) { if ($p->enabled) { continue; } |
︙ | ︙ | |||
155 156 157 158 159 160 161 | foreach ($list as &$item) { $c = isset($item['plugin']) ? $item['plugin'] : $item['module']; $item['icon_url'] = $c->icon_url(); $item['name'] = $c->name; $item['label'] = $c->label; $item['description'] = $c->description; $item['author'] = $c->author; | | > > > > > > > | | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | foreach ($list as &$item) { $c = isset($item['plugin']) ? $item['plugin'] : $item['module']; $item['icon_url'] = $c->icon_url(); $item['name'] = $c->name; $item['label'] = $c->label; $item['description'] = $c->description; $item['author'] = $c->author; $item['author_url'] = $c->author_url; $item['config_url'] = $c->hasConfig() ? $c->url($c::CONFIG_FILE) : null; $item['readme_url'] = $c->hasFile($c::README_FILE) ? $c->url($c::README_FILE) : null; $item['enabled'] = $c->enabled; $item['installed'] = isset($item['plugin']) ? $c->exists() : true; $item['broken'] = isset($item['plugin']) ? !$c->hasCode() : false; $item['broken_message'] = isset($item['plugin']) ? $c->getBrokenMessage() : false; $item['restrict_section'] = $c->restrict_section; $item['restrict_level'] = $c->restrict_level; $item['url'] = null; if ($c->hasFile($c::INDEX_FILE)) { $item['url'] = $c->url($c::INDEX_FILE); } } unset($item); usort($list, fn ($a, $b) => strnatcasecmp($a['label'] ?? $a['name'], $b['label'] ?? $b['name'])); return $list; } static public function listModulesAndPluginsMenu(Session $session): array { $list = []; |
︙ | ︙ | |||
259 260 261 262 263 264 265 | { return EM::getInstance(Plugin::class)->all('SELECT * FROM @TABLE ORDER BY label COLLATE NOCASE ASC;'); } /** * Liste les plugins téléchargés mais non installés */ | | > > | > > > > | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | { return EM::getInstance(Plugin::class)->all('SELECT * FROM @TABLE ORDER BY label COLLATE NOCASE ASC;'); } /** * Liste les plugins téléchargés mais non installés */ static public function listInstallable(bool $check_exists = true): array { $list = []; if ($check_exists) { $exists = DB::getInstance()->getAssoc('SELECT name, name FROM plugins;'); } else { $exists = []; } foreach (glob(PLUGINS_ROOT . '/*') as $file) { if (substr($file, 0, 1) == '.') { continue; } |
︙ | ︙ | |||
289 290 291 292 293 294 295 | // Ignore existing plugins if (in_array($name, $exists)) { continue; } $list[$file] = null; | < | | | < | | > > > | | 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | // Ignore existing plugins if (in_array($name, $exists)) { continue; } $list[$file] = null; $p = new Plugin; $p->name = $name; $p->updateFromINI(); $list[$name] = $p; try { $p->selfCheck(); } catch (ValidationException $e) { $p->setBrokenMessage($e->getMessage()); } } ksort($list); return $list; } |
︙ | ︙ |
Modified src/include/lib/Garradin/UserTemplate/CommonFunctions.php from [dfd204480b] to [cc6c1c6c13].
︙ | ︙ | |||
341 342 343 344 345 346 347 348 349 350 351 352 353 354 | } static public function link(array $params): string { $href = $params['href']; $label = $params['label']; $prefix = $params['prefix'] ?? ''; // href can be prefixed with '!' to make the URL relative to ADMIN_URL if (substr($href, 0, 1) == '!') { $href = ADMIN_URL . substr($params['href'], 1); } // propagate _dialog param if we are in an iframe | > > > > | 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | } static public function link(array $params): string { $href = $params['href']; $label = $params['label']; $prefix = $params['prefix'] ?? ''; if (!$href || !$label) { return ''; } // href can be prefixed with '!' to make the URL relative to ADMIN_URL if (substr($href, 0, 1) == '!') { $href = ADMIN_URL . substr($params['href'], 1); } // propagate _dialog param if we are in an iframe |
︙ | ︙ |
Modified src/include/lib/Garradin/UserTemplate/UserTemplate.php from [3f0c556abf] to [26f1142bcc].
︙ | ︙ | |||
85 86 87 88 89 90 91 | 'logged_user' => $is_logged ? $session->getUser() : null, 'dialog' => isset($_GET['_dialog']) ? ($_GET['_dialog'] ?: true) : false, ]; return self::$root_variables; } | | | | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 'logged_user' => $is_logged ? $session->getUser() : null, 'dialog' => isset($_GET['_dialog']) ? ($_GET['_dialog'] ?: true) : false, ]; return self::$root_variables; } public function __construct(?string $path) { $this->_tpl_path = $path; if ($path && $file = Files::get(File::CONTEXT_SKELETON . '/' . $path)) { if ($file->type != $file::TYPE_FILE) { throw new \LogicException('Cannot construct a UserTemplate with a directory'); } $this->file = $file; $this->modified = $file->modified->getTimestamp(); } elseif ($path) { $this->path = self::DIST_ROOT . $path; if (!($this->modified = @filemtime($this->path))) { throw new \InvalidArgumentException('File not found: ' . $this->path); } } |
︙ | ︙ |
Modified src/include/migrations/1.3/1.3.0.sql from [99fcb50e59] to [d138e6e6bc].
︙ | ︙ | |||
45 46 47 48 49 50 51 | DROP TABLE services_reminders_sent_old; DROP TABLE acc_transactions_users_old; DROP TABLE acc_transactions_old; DROP TABLE services_users_old; -- Remove old plugin as it cannot be uninstalled as it no longer exists | | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | DROP TABLE services_reminders_sent_old; DROP TABLE acc_transactions_users_old; DROP TABLE acc_transactions_old; DROP TABLE services_users_old; -- Remove old plugin as it cannot be uninstalled as it no longer exists DELETE FROM plugins_old WHERE id = 'ouvertures'; DELETE FROM plugins_signaux_old WHERE plugin = 'ouvertures'; -- Rename plugins table columns to English INSERT INTO plugins (name, label, description, author, author_url, version, config, enabled, menu, restrict_level, restrict_section) SELECT id, nom, description, auteur, url, version, config, 1, menu, CASE WHEN menu_condition IS NOT NULL THEN 2 ELSE NULL END, CASE WHEN menu_condition IS NOT NULL THEN 'users' ELSE NULL END FROM plugins_old; INSERT INTO plugins_signals SELECT * FROM plugins_signaux_old; DROP TABLE plugins_signaux_old; |
︙ | ︙ |
Modified src/include/migrations/1.3/schema.sql from [c3e1dca3f5] to [a912bda722].
︙ | ︙ | |||
30 31 32 33 34 35 36 | CREATE TABLE IF NOT EXISTS plugins ( id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL, label TEXT NOT NULL, description TEXT NULL, author TEXT NULL, | | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | CREATE TABLE IF NOT EXISTS plugins ( id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL, label TEXT NOT NULL, description TEXT NULL, author TEXT NULL, author_url TEXT NULL, version TEXT NOT NULL, menu INT NOT NULL DEFAULT 0, home_button INT NOT NULL DEFAULT 0, restrict_section TEXT NULL, restrict_level INT NULL, config TEXT NULL, enabled INTEGER NOT NULL DEFAULT 0 |
︙ | ︙ | |||
59 60 61 62 63 64 65 | -- List of modules ( id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL, label TEXT NOT NULL, description TEXT NULL, author TEXT NULL, | | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | -- List of modules ( id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL, label TEXT NOT NULL, description TEXT NULL, author TEXT NULL, author_url TEXT NULL, menu INT NOT NULL DEFAULT 0, home_button INT NOT NULL DEFAULT 0, restrict_section TEXT NULL, restrict_level INT NULL, config TEXT NULL, enabled INTEGER NOT NULL DEFAULT 0 ); |
︙ | ︙ |
Modified src/templates/config/ext/index.tpl from [0f165e3e3f] to [c2160f4936].
︙ | ︙ | |||
24 25 26 27 28 29 30 31 32 33 34 35 36 | <thead> <td></td> <td>Extension</td> <td>Accès restreint</td> <td></td> <td></td> <td></td> </thead> <tbody> {foreach from=$list item="item"} <tr {if $_GET.focus == $item.name}class="highlight"{/if}> <td class="icon"> {if $item.icon_url} | > > > > > > > > < | > | > | > | > | | < | | | | | | | | | | | | > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | <thead> <td></td> <td>Extension</td> <td>Accès restreint</td> <td></td> <td></td> <td></td> <td></td> </thead> <tbody> {foreach from=$list item="item"} <tr {if $_GET.focus == $item.name}class="highlight"{/if}> {if $item.broken_message} <td></td> <td colspan="6"> <strong class="error">Extension cassée : {$item.name}</strong><br /> {$item.broken_message} </td> {else} <td class="icon"> {if $item.icon_url} <svg><use xlink:href='{$item.icon_url}#img' href="{$item.icon_url}#img"></use></svg> {if $item.url} </a> {/if} {/if} </td> <td> <h3>{if $item.label}{$item.label}{else}{$item.name}{/if} {if $item.module && $item.module->canDelete()} <strong class="tag">Modifiée</strong> {elseif $item.module} <span class="tag">Modifiable</span> {/if} </h3> <small>{$item.description|escape|nl2br}</small><br /> <small class="help"> {if $item.author} Par {link label=$item.author href=$item.url target="_blank"} {/if} {if $item.plugin && $item.plugin.version}— Version {$item.plugin.version}{/if} {if $item.readme_url} — {link href=$item.readme_url label="Documentation" target="_dialog"} {/if} </small> </td> {if $item.broken} <td colspan="5"> {if ENABLE_TECH_DETAILS} <strong>Le code source de l'extension est absent du répertoire <tt>…/data/plugins/</tt></strong> {else} <strong>Cette extension n'est pas installée sur ce serveur.</strong><br /> {/if} <br /> <small>Il n'est pas possible de la supprimer non plus, le code source est nécessaire pour pouvoir la supprimer.</small> </td> {else} <td> {if $item.restrict_section} <span class="permissions">{display_permissions section=$item.restrict_section level=$item.restrict_level}</span> {/if} </td> <td> {if $item.enabled && $item.url} {linkbutton shape="right" label="Ouvrir" href=$item.url} {/if} </td> <td class="actions"> {if $item.module && $item.enabled} {if $item.module->hasLocal() && $item.module->hasDist()} {linkbutton label="Remettre à zéro" href="delete.php?module=%s"|args:$item.name shape="reset" target="_dialog"} {/if} {*FIXME{linkbutton label="Modifier" href="edit.php?module=%s"|args:$item.name shape="edit" target="_dialog"}*} {elseif $item.module && !$item.enabled && $item.module->canDelete()} {linkbutton label="Supprimer" href="delete.php?module=%s"|args:$item.name shape="delete" target="_dialog"} {elseif $item.plugin && !$item.enabled && $item.installed} {linkbutton label="Supprimer" href="delete.php?plugin=%s"|args:$item.name shape="delete" target="_dialog"} {/if} </td> <td class="actions"> {if $item.config_url && $item.enabled} {linkbutton label="Configurer" href=$item.config_url shape="settings" target="_dialog"} {/if} </td> <td class="actions"> {if $item.module} {if $item.enabled} {button type="submit" label="Désactiver" shape="eye-off" name="disable_module" value=$item.name} {else} {button type="submit" label="Activer" shape="eye" name="enable" value=$item.name} {/if} {else} {if $item.enabled} {button type="submit" label="Désactiver" shape="eye-off" name="disable_plugin" value=$item.name} {else} {button type="submit" label="Activer" shape="eye" name="install" value=$item.name} {/if} {/if} </td> {/if} {/if} </tr> {/foreach} </tbody> </table> {csrf_field key=$csrf_key} </form> <p class="help"> La mention <em class="tag">Modifiable</em> indique que cette extension est un module que vous pouvez modifier. {linkbutton shape="help" label="Documentation des modules" href=$url_help_modules target="_dialog"} </p> {include file="_foot.tpl"} |