Comment: | Fix issues with out of sync files and web pages, and duplicate URIs in web pages |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
cc5a0e1c1d0e97ec0d94bb5684352d59 |
User & Date: | bohwaz on 2021-06-07 17:01:09 |
Other Links: | manifest | tags |
2021-10-05
| ||
02:17 | Merge missing commits, fix upgrade check-in: 701cb83b3b user: bohwaz tags: dev | |
2021-06-10
| ||
23:09 | Fix missing schema for upgrades from < 1.0.0 check-in: e26736bdec user: bohwaz tags: trunk | |
2021-06-07
| ||
19:23 | Merge trunk/stable changes check-in: b7a5f89a8c user: bohwaz tags: dev | |
17:01 | Fix issues with out of sync files and web pages, and duplicate URIs in web pages check-in: cc5a0e1c1d user: bohwaz tags: trunk | |
16:56 | Fix [f5fb202bfbe7bdc4e735a97cc21bbce92cf76fa8] wrong link in user files list check-in: aa49026ae5 user: bohwaz tags: trunk, stable | |
Modified src/VERSION from [798bc47d06] to [07c940882d].
|
| | | 1 | 1.1.8 |
Modified src/include/data/1.1.0_schema.sql from [6ed1cd0bc8] to [ed688bac27].
︙ | ︙ | |||
322 323 324 325 326 327 328 329 330 331 332 333 334 335 | published TEXT NOT NULL CHECK (datetime(published) = published), modified TEXT NOT NULL CHECK (datetime(modified) = modified), title TEXT NOT NULL, content TEXT NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS web_pages_path ON web_pages (path); CREATE UNIQUE INDEX IF NOT EXISTS web_pages_file_path ON web_pages (file_path); CREATE INDEX IF NOT EXISTS web_pages_parent ON web_pages (parent); CREATE INDEX IF NOT EXISTS web_pages_published ON web_pages (published); CREATE INDEX IF NOT EXISTS web_pages_title ON web_pages (title); -- FIXME: rename to english CREATE TABLE IF NOT EXISTS recherches | > | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | published TEXT NOT NULL CHECK (datetime(published) = published), modified TEXT NOT NULL CHECK (datetime(modified) = modified), title TEXT NOT NULL, content TEXT NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS web_pages_path ON web_pages (path); CREATE UNIQUE INDEX IF NOT EXISTS web_pages_uri ON web_pages (uri); CREATE UNIQUE INDEX IF NOT EXISTS web_pages_file_path ON web_pages (file_path); CREATE INDEX IF NOT EXISTS web_pages_parent ON web_pages (parent); CREATE INDEX IF NOT EXISTS web_pages_published ON web_pages (published); CREATE INDEX IF NOT EXISTS web_pages_title ON web_pages (title); -- FIXME: rename to english CREATE TABLE IF NOT EXISTS recherches |
︙ | ︙ |
Added src/include/data/1.1.8_migration.sql version [cc434f178d].
> > > > > | 1 2 3 4 5 | -- Remove any leftover duplicates DELETE FROM web_pages WHERE id IN (SELECT id FROM web_pages GROUP BY uri HAVING COUNT(*) > 1); -- Add unique index CREATE UNIQUE INDEX IF NOT EXISTS web_pages_uri ON web_pages (uri); |
Modified src/include/data/schema.sql from [6ed1cd0bc8] to [ed688bac27].
︙ | ︙ | |||
322 323 324 325 326 327 328 329 330 331 332 333 334 335 | published TEXT NOT NULL CHECK (datetime(published) = published), modified TEXT NOT NULL CHECK (datetime(modified) = modified), title TEXT NOT NULL, content TEXT NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS web_pages_path ON web_pages (path); CREATE UNIQUE INDEX IF NOT EXISTS web_pages_file_path ON web_pages (file_path); CREATE INDEX IF NOT EXISTS web_pages_parent ON web_pages (parent); CREATE INDEX IF NOT EXISTS web_pages_published ON web_pages (published); CREATE INDEX IF NOT EXISTS web_pages_title ON web_pages (title); -- FIXME: rename to english CREATE TABLE IF NOT EXISTS recherches | > | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | published TEXT NOT NULL CHECK (datetime(published) = published), modified TEXT NOT NULL CHECK (datetime(modified) = modified), title TEXT NOT NULL, content TEXT NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS web_pages_path ON web_pages (path); CREATE UNIQUE INDEX IF NOT EXISTS web_pages_uri ON web_pages (uri); CREATE UNIQUE INDEX IF NOT EXISTS web_pages_file_path ON web_pages (file_path); CREATE INDEX IF NOT EXISTS web_pages_parent ON web_pages (parent); CREATE INDEX IF NOT EXISTS web_pages_published ON web_pages (published); CREATE INDEX IF NOT EXISTS web_pages_title ON web_pages (title); -- FIXME: rename to english CREATE TABLE IF NOT EXISTS recherches |
︙ | ︙ |
Modified src/include/lib/Garradin/API.php from [fca20dc380] to [808f82b79d].
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | { if (null == $this->body) { $this->body = trim(file_get_contents('php://input')); } return $this->body; } protected function download() { if ($this->method != 'GET') { throw new APIException('Wrong request method', 400); } | > > > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | { if (null == $this->body) { $this->body = trim(file_get_contents('php://input')); } return $this->body; } protected function hasParam(string $param): bool { return array_key_exists($param, $_GET); } protected function download() { if ($this->method != 'GET') { throw new APIException('Wrong request method', 400); } |
︙ | ︙ | |||
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | return ['results' => Recherche::rawSQL($body)]; } catch (\Exception $e) { http_response_code(400); return ['error' => 'Error in SQL statement', 'sql_error' => $e->getMessage()]; } } public function checkAuth(): void { if (!isset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) { throw new APIException('No username or password supplied', 401); } if ($_SERVER['PHP_AUTH_USER'] !== API_USER || $_SERVER['PHP_AUTH_PW'] !== API_PASSWORD) { throw new APIException('Invalid username or password', 403); } } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | | 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 137 138 139 140 141 142 143 144 145 146 147 148 | return ['results' => Recherche::rawSQL($body)]; } catch (\Exception $e) { http_response_code(400); return ['error' => 'Error in SQL statement', 'sql_error' => $e->getMessage()]; } } protected function web(string $uri): ?array { if ($this->method != 'GET') { throw new APIException('Wrong request method', 400); } $fn = strtok($uri, '/'); $param = strtok(''); switch ($fn) { case 'list': return ['categories' => Web::listCategories($param), 'pages' => Web::listPages($param)]; case 'attachment': $attachment = Web::getAttachmentFromURI($param); if (!$attachment) { throw new APIException('Page not found', 404); } $attachment->serve(); return null; case 'html': case 'page': $page = Web::getByURI($param); if (!$page) { throw new APIException('Page not found', 404); } if ($fn == 'page') { $out = compact('page'); if ($this->hasParam('html')) { $out['html'] = $page->render(); } return $out; } // HTML render echo $page->render(); return null; default: throw new APIException('Unknown web action', 404); } } public function checkAuth(): void { if (!isset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) { throw new APIException('No username or password supplied', 401); } if ($_SERVER['PHP_AUTH_USER'] !== API_USER || $_SERVER['PHP_AUTH_PW'] !== API_PASSWORD) { throw new APIException('Invalid username or password', 403); } } public function dispatch(string $fn, string $uri) { $this->checkAuth(); switch ($fn) { case 'sql': return $this->sql(); case 'download': return $this->download(); case 'web': return $this->web($uri); default: throw new APIException('Unknown path', 404); } } static public function dispatchURI(string $uri) { $fn = strtok($uri, '/'); $api = new self; $api->method = $_SERVER['REQUEST_METHOD'] ?? null; http_response_code(200); try { $return = $api->dispatch($fn, strtok('')); if (null !== $return) { echo json_encode($return); } } catch (\Exception $e) { if ($e instanceof APIException) { |
︙ | ︙ |
Modified src/include/lib/Garradin/Entities/Web/Page.php from [67cb9d89e8] to [9c9ff955e9].
︙ | ︙ | |||
69 70 71 72 73 74 75 76 77 78 79 80 81 82 | const TYPE_PAGE = 2; const TEMPLATES = [ self::TYPE_PAGE => 'article.html', self::TYPE_CATEGORY => 'category.html', ]; protected $_file; protected $_attachments; static public function create(int $type, ?string $parent, string $title, string $status = self::STATUS_ONLINE): self { $page = new self; $data = compact('type', 'parent', 'title', 'status'); | > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | const TYPE_PAGE = 2; const TEMPLATES = [ self::TYPE_PAGE => 'article.html', self::TYPE_CATEGORY => 'category.html', ]; const DUPLICATE_URI_ERROR = 42; protected $_file; protected $_attachments; static public function create(int $type, ?string $parent, string $title, string $status = self::STATUS_ONLINE): self { $page = new self; $data = compact('type', 'parent', 'title', 'status'); |
︙ | ︙ | |||
236 237 238 239 240 241 242 | $this->assert(trim($this->title) !== '', 'Le titre ne peut rester vide'); $this->assert(trim($this->file_path) !== '', 'Le chemin de fichier ne peut rester vide'); $this->assert(trim($this->path) !== '', 'Le chemin ne peut rester vide'); $this->assert(trim($this->uri) !== '', 'L\'URI ne peut rester vide'); $this->assert($this->path !== $this->parent, 'Invalid parent page'); $this->assert($this->parent === '' || $db->test(self::TABLE, 'path = ?', $this->parent), 'Page parent inexistante'); | | | | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | $this->assert(trim($this->title) !== '', 'Le titre ne peut rester vide'); $this->assert(trim($this->file_path) !== '', 'Le chemin de fichier ne peut rester vide'); $this->assert(trim($this->path) !== '', 'Le chemin ne peut rester vide'); $this->assert(trim($this->uri) !== '', 'L\'URI ne peut rester vide'); $this->assert($this->path !== $this->parent, 'Invalid parent page'); $this->assert($this->parent === '' || $db->test(self::TABLE, 'path = ?', $this->parent), 'Page parent inexistante'); $this->assert(!$this->exists() || !$db->test(self::TABLE, 'uri = ? AND id != ?', $this->uri, $this->id()), 'Cette adresse URI est déjà utilisée par une autre page, merci d\'en choisir une autre : ' . $this->uri, self::DUPLICATE_URI_ERROR); $this->assert($this->exists() || !$db->test(self::TABLE, 'uri = ?', $this->uri), 'Cette adresse URI est déjà utilisée par une autre page, merci d\'en choisir une autre : ' . $this->uri, self::DUPLICATE_URI_ERROR); } public function importForm(array $source = null) { if (null === $source) { $source = $_POST; } |
︙ | ︙ |
Modified src/include/lib/Garradin/Entity.php from [e19cdc4d7b] to [722d6cf126].
︙ | ︙ | |||
53 54 55 56 57 58 59 | return \DateTime::createFromFormat('d/m/Y H:i', $value); } } return parent::filterUserValue($type, $value, $key); } | | | | 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 | return \DateTime::createFromFormat('d/m/Y H:i', $value); } } return parent::filterUserValue($type, $value, $key); } protected function assert(?bool $test, string $message = null, int $code = 0): void { if ($test) { return; } if (null === $message) { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); $caller_class = array_pop($backtrace); $caller = array_pop($backtrace); $message = sprintf('Entity assertion fail from class %s on line %d', $caller_class['class'], $caller['line']); throw new \UnexpectedValueException($message); } else { throw new ValidationException($message, $code); } } // Add plugin signals to save/delete public function save(): bool { $name = get_class($this); |
︙ | ︙ |
Modified src/include/lib/Garradin/Files/Storage/FileSystem.php from [c060f854cf] to [33ec3a8fb7].
︙ | ︙ | |||
207 208 209 210 211 212 213 214 215 216 217 218 219 220 | // directory_blabla // file_image.jpeg $files[$file->getType() . '_' .$file->getFilename()] = self::_SplToFile($file); } return Utils::knatcasesort($files); } static public function getTotalSize(): float { if (null !== self::$_size) { return self::$_size; } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | // directory_blabla // file_image.jpeg $files[$file->getType() . '_' .$file->getFilename()] = self::_SplToFile($file); } return Utils::knatcasesort($files); } static public function listDirectoriesRecursively(string $path): array { $fullpath = self::_getRoot() . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $path); $fullpath = rtrim($fullpath, DIRECTORY_SEPARATOR); if (!file_exists($fullpath)) { return []; } return self::_recurseGlob($fullpath, '*', \GLOB_ONLYDIR); } static protected function _recurseGlob(string $path, string $pattern = '*', int $flags = 0): array { $target = $path . DIRECTORY_SEPARATOR . $pattern; $list = []; // glob is the fastest way to recursely list directories and files apparently // after comparing with opendir(), dir() and filesystem recursive iterators foreach(glob($target, $flags) as $file) { $file = basename($file); if ($file[0] == '.') { continue; } $list[] = $file; if (is_dir($path . DIRECTORY_SEPARATOR . $file)) { foreach (self::_recurseGlob($path . DIRECTORY_SEPARATOR . $file, $pattern, $flags) as $subfile) { $list[] = $file . DIRECTORY_SEPARATOR . $subfile; } } } return $list; } static public function getTotalSize(): float { if (null !== self::$_size) { return self::$_size; } |
︙ | ︙ |
Modified src/include/lib/Garradin/Files/Storage/SQLite.php from [95f7674e72] to [ce000d8bf2].
︙ | ︙ | |||
120 121 122 123 124 125 126 127 128 129 130 131 132 133 | return EM::findOne(File::class, $sql, $path); } static public function list(string $path): array { return EM::getInstance(File::class)->all('SELECT * FROM @TABLE WHERE parent = ? ORDER BY type DESC, name COLLATE NOCASE ASC;', $path); } static public function exists(string $path): bool { return DB::getInstance()->test('files', 'path = ?', $path); } static public function delete(File $file): bool | > > > > > > > > > > > > | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | return EM::findOne(File::class, $sql, $path); } static public function list(string $path): array { return EM::getInstance(File::class)->all('SELECT * FROM @TABLE WHERE parent = ? ORDER BY type DESC, name COLLATE NOCASE ASC;', $path); } static public function listDirectoriesRecursively(string $path): array { $files = []; $it = DB::getInstance()->iterate('SELECT path FROM files WHERE parent LIKE ? ORDER BY path;', $path . '/%'); foreach ($it as $file) { $files[] = $file->path; } return $files; } static public function exists(string $path): bool { return DB::getInstance()->test('files', 'path = ?', $path); } static public function delete(File $file): bool |
︙ | ︙ |
Modified src/include/lib/Garradin/Files/Storage/StorageInterface.php from [dea0474d61] to [67b35b24ca].
︙ | ︙ | |||
64 65 66 67 68 69 70 71 72 73 74 75 76 77 | static public function get(string $path): ?File; /** * Return an array of File objects for a given path */ static public function list(string $path): array; /** * Moves a file to a new path, when its name or path has changed */ static public function move(File $file, string $new_path): bool; /** * Return total size of used space by files stored in this backed | > > > > > > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | static public function get(string $path): ?File; /** * Return an array of File objects for a given path */ static public function list(string $path): array; /** * Return an array of (string) paths of all subdirectories inside a path * @param string $path Parent path */ static public function listDirectoriesRecursively(string $path): array; /** * Moves a file to a new path, when its name or path has changed */ static public function move(File $file, string $new_path): bool; /** * Return total size of used space by files stored in this backed |
︙ | ︙ |
Modified src/include/lib/Garradin/Upgrade.php from [ec884a2e61] to [0b2351ebf8].
︙ | ︙ | |||
280 281 282 283 284 285 286 287 288 289 290 291 292 293 | $config->save(); } if (version_compare($v, '1.1.7', '<')) { $db->begin(); $db->import(ROOT . '/include/data/1.1.7_migration.sql'); $db->commit(); } // Vérification de la cohérence des clés étrangères $db->foreignKeyCheck(); // Delete local cached files | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | $config->save(); } if (version_compare($v, '1.1.7', '<')) { $db->begin(); $db->import(ROOT . '/include/data/1.1.7_migration.sql'); $db->commit(); } if (version_compare($v, '1.1.8', '<')) { $db->begin(); // Force sync to remove pages that don't exist anymore \Garradin\Web\Web::sync(); $uris = []; $i = 1; $treat_duplicate_uris = function ($path) use (&$i, &$uris, &$treat_duplicate_uris) { // Rename duplicate URIs foreach (Files::callStorage('list', $path) as $f) { if ($f->type != $f::TYPE_DIRECTORY) { continue; } if (array_key_exists($f->name, $uris)) { $f->changeFileName($f->name . '_' . $i++); } $uris[$f->name] = $f->path; $treat_duplicate_uris($f->path); } }; $treat_duplicate_uris(\Garradin\Entities\Files\File::CONTEXT_WEB); // Force sync to add renamed pages \Garradin\Web\Web::sync(); // Add UNIQUE index $db->import(ROOT . '/include/data/1.1.8_migration.sql'); $db->commit(); } // Vérification de la cohérence des clés étrangères $db->foreignKeyCheck(); // Delete local cached files |
︙ | ︙ |
Modified src/include/lib/Garradin/Web/Web.php from [8b024968b4] to [bd32cd07a7].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?php namespace Garradin\Web; use Garradin\Entities\Web\Page; use Garradin\Entities\Files\File; use Garradin\Web\Skeleton; use Garradin\Files\Files; use Garradin\API; use Garradin\Config; use Garradin\DB; use Garradin\Utils; use Garradin\UserException; use Garradin\Membres\Session; use KD2\DB\EntityManager as EM; use const Garradin\{WWW_URI, ADMIN_URL}; class Web | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?php namespace Garradin\Web; use Garradin\Entities\Web\Page; use Garradin\Entities\Files\File; use Garradin\Web\Skeleton; use Garradin\Files\Files; use Garradin\API; use Garradin\Config; use Garradin\DB; use Garradin\Utils; use Garradin\UserException; use Garradin\ValidationException; use Garradin\Membres\Session; use KD2\DB\EntityManager as EM; use const Garradin\{WWW_URI, ADMIN_URL}; class Web |
︙ | ︙ | |||
33 34 35 36 37 38 39 | $result->breadcrumbs[$path] = $part; } } return $results; } | > > > | | < | | < < | < < < < | | | > > > > > > > > > | 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 | $result->breadcrumbs[$path] = $part; } } return $results; } /** * This syncs the whole website between the actual files and the web_pages table */ static public function sync(): array { $path = File::CONTEXT_WEB; $errors = []; $exists = array_flip(Files::callStorage('listDirectoriesRecursively', $path)); $db = DB::getInstance(); $in_db = $db->getGrouped('SELECT path, file_path, modified FROM web_pages;'); $deleted = array_diff_key($in_db, $exists); $new = array_diff_key($exists, $in_db); if ($deleted) { $deleted = array_map(function ($page) { return $page->path; }, $deleted); $db->exec(sprintf('DELETE FROM web_pages WHERE %s;', $db->where('path', $deleted))); } foreach (array_keys($new) as $path) { $f = Files::get(File::CONTEXT_WEB . '/' . $path . '/index.txt'); if (!$f) { // This is a directory without content, ignore continue; } try { Page::fromFile($f)->save(); } catch (ValidationException $e) { // Ignore validation errors, just don't add pages to index $errors[] = sprintf('Erreur à l\'import, page "%s": %s', str_replace(File::CONTEXT_WEB . '/', '', $f->parent), $e->getMessage()); } } return $errors; /* // There's no need for that sync as it is triggered when loading a Page entity! $intersection = array_intersect_key($in_db, $exists); foreach ($intersection as $page) { $file = Files::get($page->file_path); |
︙ | ︙ | |||
103 104 105 106 107 108 109 110 111 112 113 114 115 116 | static public function listPages(string $parent, bool $order_by_date = true): array { $order = $order_by_date ? 'published DESC' : 'title COLLATE NOCASE'; $sql = sprintf('SELECT * FROM @TABLE WHERE parent = ? AND type = %d ORDER BY %s;', Page::TYPE_PAGE, $order); return EM::getInstance(Page::class)->all($sql, $parent); } static public function get(string $path): ?Page { $page = EM::findOne(Page::class, 'SELECT * FROM @TABLE WHERE path = ?;', $path); if ($page && !$page->file()) { return null; | > > > > > > | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | static public function listPages(string $parent, bool $order_by_date = true): array { $order = $order_by_date ? 'published DESC' : 'title COLLATE NOCASE'; $sql = sprintf('SELECT * FROM @TABLE WHERE parent = ? AND type = %d ORDER BY %s;', Page::TYPE_PAGE, $order); return EM::getInstance(Page::class)->all($sql, $parent); } static public function listAll(string $parent): array { $sql = 'SELECT * FROM @TABLE WHERE parent = ? ORDER BY title COLLATE NOCASE;'; return EM::getInstance(Page::class)->all($sql, $parent); } static public function get(string $path): ?Page { $page = EM::findOne(Page::class, 'SELECT * FROM @TABLE WHERE path = ?;', $path); if ($page && !$page->file()) { return null; |
︙ | ︙ |
Modified src/templates/web/index.tpl from [1471b88a5d] to [387d7766db].
︙ | ︙ | |||
39 40 41 42 43 44 45 46 47 48 49 50 51 52 | </nav> {if $config.site_disabled && $session->canAccess($session::SECTION_WEB, $session::ACCESS_ADMIN)} <p class="block alert"> Le site public est désactivé. <a href="{"!web/config.php"|local_url}">Activer le site dans la configuration.</a> </p> {/if} {if count($categories)} <h2 class="ruler">Catégories</h2> <table class="list"> <tbody> {foreach from=$categories item="p"} <tr> | > > | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | </nav> {if $config.site_disabled && $session->canAccess($session::SECTION_WEB, $session::ACCESS_ADMIN)} <p class="block alert"> Le site public est désactivé. <a href="{"!web/config.php"|local_url}">Activer le site dans la configuration.</a> </p> {/if} {form_errors} {if count($categories)} <h2 class="ruler">Catégories</h2> <table class="list"> <tbody> {foreach from=$categories item="p"} <tr> |
︙ | ︙ |
Modified src/www/admin/web/index.php from [5baaa10463] to [030354055c].
1 2 3 4 5 6 7 8 9 10 11 12 | <?php namespace Garradin; use Garradin\Web\Web; use Garradin\Entities\Web\Page; require_once __DIR__ . '/_inc.php'; $current_path = qg('p') ?: ''; $cat = null; | < < > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <?php namespace Garradin; use Garradin\Web\Web; use Garradin\Entities\Web\Page; require_once __DIR__ . '/_inc.php'; $current_path = qg('p') ?: ''; $cat = null; if ($current_path) { $cat = Web::get($current_path); if (!$cat) { throw new UserException('Catégorie inconnue'); } } else { foreach (Web::sync() as $error) { $form->addError($error); } } $order_date = qg('order_title') === null; $categories = Web::listCategories($cat ? $cat->path : ''); $pages = Web::listPages($cat ? $cat->path : '', $order_date); $title = $cat ? sprintf('Gestion du site web : %s', $cat->title) : 'Gestion du site web'; |
︙ | ︙ |