Comment: | Last progress on user forms, now mostly working |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | templates |
Files: | files | file ages | folders |
SHA3-256: |
64eda05d62fcd327e6db78a801d979e9 |
User & Date: | bohwaz on 2022-07-29 03:23:46 |
Other Links: | branch diff | manifest | tags |
2022-07-29
| ||
03:26 | Disable edit for now, as it's not done yet check-in: 798e3268e0 user: bohwaz tags: templates | |
03:23 | Last progress on user forms, now mostly working check-in: 64eda05d62 user: bohwaz tags: templates | |
2022-07-28
| ||
23:43 | Migrate away from documents, hello user forms check-in: 81d19a359b user: bohwaz tags: templates | |
Modified src/include/data/1.2.0_schema.sql from [c64b561387] to [f16cfdc412].
︙ | ︙ | |||
450 451 452 453 454 455 456 | -- List of forms special templates ( id INTEGER NOT NULL PRIMARY KEY, id_form INTEGER NOT NULL REFERENCES user_forms (id) ON DELETE CASCADE, name TEXT NOT NULL ); | | | 450 451 452 453 454 455 456 457 | -- List of forms special templates ( id INTEGER NOT NULL PRIMARY KEY, id_form INTEGER NOT NULL REFERENCES user_forms (id) ON DELETE CASCADE, name TEXT NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS user_forms_templates_name ON user_forms_templates (id_form, name); |
Modified src/include/lib/Garradin/Entities/UserForm.php from [c2ad7e5999] to [4937cc4b94].
1 2 3 4 | <?php namespace Garradin\Entities; | | > > > > > > > > > | | 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 | <?php namespace Garradin\Entities; use Garradin\Entity; use Garradin\DB; use Garradin\Files\Files; use Garradin\UserTemplate\UserTemplate; use Garradin\Membres\Session; use Garradin\Entities\Files\File; use const Garradin\{ROOT, WWW_URL}; class UserForm extends Entity { const ROOT = File::CONTEXT_SKELETON . '/forms'; const DIST_ROOT = ROOT . '/skel-dist/forms'; const META_FILE = 'form.json'; const CONFIG_TEMPLATE = 'config.html'; const SNIPPET_TRANSACTION = 'snippets/transaction_details.html'; const SNIPPET_USER = 'snippets/user_details.html'; const SNIPPET_HOME_ICON = 'snippets/home_icon.html'; |
︙ | ︙ | |||
28 29 30 31 32 33 34 | /** * Directory name */ protected string $name; protected string $label; protected ?string $description; | < < < < < < | | | | | > > > > > > | | | 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 | /** * Directory name */ protected string $name; protected string $label; protected ?string $description; protected ?\stdClass $config; public function selfCheck(): void { $this->assert(preg_match('/^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/', $this->name), 'Nom unique de formulaire invalide: ' . $this->name); $this->assert(trim($this->label) !== '', 'Le libellé ne peut rester vide'); } /** * Fills information from form.json file */ public function updateFromJSON(): bool { if ($file = Files::get($this->path(self::META_FILE))) { $json = $file->fetch(); } elseif (file_exists($this->distPath(self::META_FILE))) { $json = file_get_contents($this->distPath(self::META_FILE)); } else { return false; } $json = json_decode($json); if (!isset($json->label)) { return false; } $this->label = $json->label; $this->description = $json->description ?? null; return true; } public function updateTemplates(): void { $check = self::SNIPPETS + [self::CONFIG_TEMPLATE => 'Config']; $templates = []; $db = DB::getInstance(); $db->begin(); $db->delete('user_forms_templates', 'id_form = ' . (int)$this->id()); foreach ($check as $file => $label) { |
︙ | ︙ | |||
89 90 91 92 93 94 95 | public function path(string $file = null): string { return self::ROOT . '/' . $this->name . ($file ? '/' . $file : ''); } public function distPath(string $file = null): string { | | > > > > > | 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 | public function path(string $file = null): string { return self::ROOT . '/' . $this->name . ($file ? '/' . $file : ''); } public function distPath(string $file = null): string { return ROOT . '/skel-dist/forms/' . $this->name . ($file ? '/' . $file : ''); } public function dir(): ?File { return Files::get(self::ROOT . $this->name); } public function hasDist(): bool { return file_exists($this->distPath()); } public function hasConfig(): bool { return DB::getInstance()->test('user_forms_templates', 'id_form = ? AND name = ?', $this->id(), self::CONFIG_TEMPLATE); } public function canDelete(): bool |
︙ | ︙ | |||
126 127 128 129 130 131 132 | public function url(string $file = '', array $params = null) { if (null !== $params) { $params = '?' . http_build_query($params); } | | | | > > > > > > | | > | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 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 | public function url(string $file = '', array $params = null) { if (null !== $params) { $params = '?' . http_build_query($params); } return sprintf('%sform/%s/%s%s', WWW_URL, $this->name, $file, $params); } public function displayWeb(string $file) { try { $this->template($file)->displayWeb(); } catch (Brindille_Exception $e) { printf('<div style="border: 5px solid orange; padding: 10px; background: yellow;"><h2>Erreur dans le code du document</h2><p>%s</p></div>', nl2br(htmlspecialchars($e->getMessage()))); } } public function fetch(string $file, array $variables = []) { try { $t = $this->template($file); $t->assignArray($variables); return $t->fetch(); } catch (Brindille_Exception $e) { return sprintf('<div style="border: 5px solid orange; padding: 10px; background: yellow;"><h2>Erreur dans le code du document</h2><p>%s</p></div>', nl2br(htmlspecialchars($e->getMessage()))); } } public function template(string $file) { if ($file == self::CONFIG_TEMPLATE) { Session::getInstance()->requireAccess(Session::SECTION_CONFIG, Session::ACCESS_ADMIN); } if (!preg_match('!^(?:snippets/)?[\w\d_-]+(?:\.[\w\d_-]+)*$!i', $file)) { throw new \InvalidArgumentException('Invalid skeleton name'); } $ut = new UserTemplate('forms/' . $this->name . '/' . $file); $ut->assign('form', $this->asArray(false) + ['url' => $this->url()]); return $ut; } } |
Modified src/include/lib/Garradin/Upgrade.php from [f601f746e5] to [ff6c8a08b2].
︙ | ︙ | |||
455 456 457 458 459 460 461 | if (version_compare($v, '1.1.28', '<')) { $db->createFunction('html_decode', 'htmlspecialchars_decode'); $db->exec('UPDATE files_search SET content = html_decode(content);'); } if (version_compare($v, '1.2.0', '<')) { $db->begin(); | | > | 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 | if (version_compare($v, '1.1.28', '<')) { $db->createFunction('html_decode', 'htmlspecialchars_decode'); $db->exec('UPDATE files_search SET content = html_decode(content);'); } if (version_compare($v, '1.2.0', '<')) { $db->begin(); $db->import(ROOT . '/include/data/1.2.0_schema.sql'); $files = $db->firstColumn('SELECT value FROM config WHERE key = \'files\';'); $files = json_decode($files); $files->signature = null; $db->exec(sprintf('REPLACE INTO config (key, value) VALUES (\'files\', %s);', $db->quote(json_encode($files)))); $db->commit(); // Move skeletons from skel/ to skel/web/ |
︙ | ︙ |
Modified src/include/lib/Garradin/UserTemplate/CommonModifiers.php from [84113d4c5d] to [bd7144db61].
︙ | ︙ | |||
482 483 484 485 486 487 488 | } if ((string) $current_value === '0') { $current_value = ''; } $currency = Config::getInstance()->get('monnaie'); | | | 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | } if ((string) $current_value === '0') { $current_value = ''; } $currency = Config::getInstance()->get('monnaie'); $input = sprintf('<nobr><input type="text" pattern="-?[0-9]*([.,][0-9]{1,2})?" inputmode="decimal" size="8" class="money" %s value="%s" /><b>%s</b></nobr>', $attributes_string, htmlspecialchars((string) $current_value), $currency); } else { $value = isset($attributes['value']) ? '' : sprintf(' value="%s"', htmlspecialchars((string)$current_value)); $input = sprintf('<input type="%s" %s %s />', $type, $attributes_string, $value); } // No label? then we only want the input without the widget |
︙ | ︙ |
Modified src/include/lib/Garradin/UserTemplate/Functions.php from [0c1e69f4fe] to [704cf68144].
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | use Garradin\Template; use Garradin\Utils; use Garradin\UserException; use Garradin\Web\Skeleton; use Garradin\Users\Emails; use Garradin\Files\Files; use Garradin\Entities\Files\File; use const Garradin\{ROOT, WWW_URL}; class Functions { const FUNCTIONS_LIST = [ 'include', | > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | use Garradin\Template; use Garradin\Utils; use Garradin\UserException; use Garradin\Web\Skeleton; use Garradin\Users\Emails; use Garradin\Files\Files; use Garradin\Entities\Files\File; use Garradin\Entities\UserForm; use const Garradin\{ROOT, WWW_URL}; class Functions { const FUNCTIONS_LIST = [ 'include', |
︙ | ︙ | |||
76 77 78 79 80 81 82 | } $db->exec(sprintf('CREATE INDEX IF NOT EXISTS documents_%s_%s ON documents_data (%s);', $id, implode(',', $indexes))); } static public function save(array $params, Brindille $tpl, int $line): void { | | | > > | > | | > > > > > > > > > > > | > | | > > > > > > > > > > > > > > > > | | > > | > | > > > > > > | 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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | } $db->exec(sprintf('CREATE INDEX IF NOT EXISTS documents_%s_%s ON documents_data (%s);', $id, implode(',', $indexes))); } static public function save(array $params, Brindille $tpl, int $line): void { $name = Utils::basename(Utils::dirname($tpl->_tpl_path)); if (!$name) { throw new Brindille_Exception('Unique document name could not be found'); } $table = 'user_forms_' . $name; if (!empty($params['key'])) { if ($params['key'] == 'uuid') { $params['key'] = Utils::uuid(); } $where = 'key = ?'; $where_value = $params['key']; } elseif (!empty($params['id'])) { $where = 'id = ?'; $where_value = $params['id']; } else { throw new Brindille_Exception('Aucun paramètre "id" ou "key" n\'a été renseigné'); } $key = $params['key'] ?? null; unset($params['key'], $params['id']); $validate = null; if (isset($params['validate_schema'])) { $validate = $params['validate_schema']; unset($params['validate_schema']); } $db = DB::getInstance(); if ($key == 'config') { $exists = $db->firstColumn(sprintf('SELECT config FROM %s WHERE name = ?;', UserForm::TABLE), $name); } else { $db->exec(sprintf(' CREATE TABLE IF NOT EXISTS %s ( id INTEGER NOT NULL PRIMARY KEY, key TEXT NULL, value TEXT NOT NULL ); CREATE UNIQUE INDEX IF NOT EXISTS %1$s_key ON %1$s (key);', $table)); $exists = $db->first(sprintf('SELECT value FROM %s WHERE %s AND document = ?;', $table, $where), $where_value, $id); } $exists = json_decode((string) $exists, true); // Merge before update if ($exists) { $params = array_merge($exists, $params); } if ($validate) { $schema = self::read(['file' => $validate_schema], $tpl, $line); try { $s = JSONSchema::fromString($schema); $s->validate($params); } catch (\RuntimeException $e) { throw new Brindille_Exception(sprintf("line %d: error in validating data:\n%s\n\n%s", $line, $e->getMessage(), json_encode($params, JSON_PRETTY_PRINT))); } } $value = json_encode($params); if ($key == 'config') { $db->update(UserForm::TABLE, ['config' => $value], 'name = :name', compact('name')); return; } if (!$exists) { $db->insert($table, compact('value', 'key')); } else { $db->update($table, compact('value'), sprintf('%s = :match', $where), ['match' => $where_value]); } } static public function mail(array $params, Brindille $tpl, int $line) { if (empty($params['to'])) { throw new Brindille_Exception(sprintf('Ligne %d: argument "to" manquant pour la fonction "mail"', $line)); } |
︙ | ︙ | |||
160 161 162 163 164 165 166 | { throw new UserException($params['message']); } static protected function getFilePath(array $params, string $arg_name, UserTemplate $ut, int $line) { if (empty($params[$arg_name])) { | | | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | { throw new UserException($params['message']); } static protected function getFilePath(array $params, string $arg_name, UserTemplate $ut, int $line) { if (empty($params[$arg_name])) { throw new Brindille_Exception(sprintf('Ligne %d: argument "%s" manquant', $arg_name, $line)); } if (strpos($params[$arg_name], '..') !== false) { throw new Brindille_Exception(sprintf('Ligne %d: argument "%s" invalide', $line, $arg_name)); } $path = $params[$arg_name]; |
︙ | ︙ | |||
230 231 232 233 234 235 236 | } catch (\InvalidArgumentException $e) { throw new Brindille_Exception(sprintf('Ligne %d : fonction "include" : le fichier à inclure "%s" n\'existe pas', $line, $path)); } $params['included_from'] = array_merge($from, [$path]); | | | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | } catch (\InvalidArgumentException $e) { throw new Brindille_Exception(sprintf('Ligne %d : fonction "include" : le fichier à inclure "%s" n\'existe pas', $line, $path)); } $params['included_from'] = array_merge($from, [$path]); $include->assignArray(array_merge($ut->getAllVariables(), $params)); $include->display(); } static public function http(array $params, UserTemplate $tpl): void { if (headers_sent()) { return; |
︙ | ︙ | |||
310 311 312 313 314 315 316 | if (!isset($codes[$params['code']])) { throw new Brindille_Exception('Code HTTP inconnu'); } header(sprintf('HTTP/1.1 %d %s', $params['code'], $codes[$params['code']]), true); } | | < | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | if (!isset($codes[$params['code']])) { throw new Brindille_Exception('Code HTTP inconnu'); } header(sprintf('HTTP/1.1 %d %s', $params['code'], $codes[$params['code']]), true); } if (!empty($params['type'])) { if ($params['type'] == 'pdf') { $params['type'] = 'application/pdf'; } header('Content-Type: ' . $params['type'], true); } if (isset($params['download'])) { header(sprintf('Content-Disposition: attachment; filename="%s"', Utils::safeFileName($params['download'])), true); } } } |
Modified src/include/lib/Garradin/UserTemplate/Sections.php from [75ce8d8e62] to [d56883e034].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php namespace Garradin\UserTemplate; use KD2\Brindille_Exception; use Garradin\Config; use Garradin\DB; use Garradin\Utils; use Garradin\Membres\Session; use Garradin\Entities\Web\Page; use Garradin\Web\Web; use Garradin\Files\Files; use Garradin\Entities\Files\File; use const Garradin\WWW_URL; | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php namespace Garradin\UserTemplate; use KD2\Brindille_Exception; use Garradin\Config; use Garradin\DB; use Garradin\Utils; use Garradin\UserException; use Garradin\Membres\Session; use Garradin\Entities\Web\Page; use Garradin\Web\Web; use Garradin\Files\Files; use Garradin\Entities\Files\File; use const Garradin\WWW_URL; |
︙ | ︙ | |||
42 43 44 45 46 47 48 | } return self::$_cache[$id]; } static public function load(array $params, UserTemplate $tpl, int $line): \Generator { | | | | | < < < < < > > > > > | > | > | > > | | | | | | | | > > > > > > > > > | 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 | } return self::$_cache[$id]; } static public function load(array $params, UserTemplate $tpl, int $line): \Generator { $name = Utils::basename(Utils::dirname($tpl->_tpl_path)); if (!$name) { throw new Brindille_Exception('Unique document name could not be found'); } if (!isset($params['where'])) { $params['where'] = '1'; } if (isset($params['key'])) { $params['where'] .= ' AND key = :key'; $params['limit'] = 1; $params[':key'] = $params['key']; unset($params['key']); } elseif (isset($params['id'])) { $params['where'] .= ' AND id = :id'; $params['limit'] = 1; $params[':id'] = $params['id']; unset($params['id']); } $params['select'] = isset($params['select']) ? $params['select'] : 'value AS json'; $params['tables'] = 'user_forms_' . $name; try { $query = self::sql($params, $tpl, $line); foreach ($query as $row) { if (isset($row['json'])) { $json = json_decode($row['json'], true); if (is_array($json)) { unset($row['json']); $row = array_merge($row, $json); } } yield $row; } } catch (Brindille_Exception $e) { // Table does not exists: return nothing if (false !== strpos($e->getMessage(), 'no such table: ' . $params['tables'])) { return; } throw $e; } } static public function accounts_sums(array $params, UserTemplate $tpl, int $line): \Generator { $db = DB::getInstance(); |
︙ | ︙ | |||
225 226 227 228 229 230 231 | if (empty($params['level']) || !isset($convert[$params['level']])) { throw new Brindille_Exception(sprintf("Ligne %d: 'restrict' niveau d'accès inconnu : %s", $line, $params['level'] ?? '')); } $ok = $session->canAccess($params['section'] ?? '', $convert[$params['level']]); if ($ok) { | | | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | if (empty($params['level']) || !isset($convert[$params['level']])) { throw new Brindille_Exception(sprintf("Ligne %d: 'restrict' niveau d'accès inconnu : %s", $line, $params['level'] ?? '')); } $ok = $session->canAccess($params['section'] ?? '', $convert[$params['level']]); if ($ok) { return null; } if (!empty($params['block'])) { throw new UserException('Vous n\'avez pas accès à cette page.'); } return null; |
︙ | ︙ | |||
533 534 535 536 537 538 539 | if (!empty($params['debug'])) { echo sprintf('<pre style="padding: 5px; background: yellow; white-space: normal;">%s</pre>', htmlspecialchars($statement->getSQL(true))); } $result = $statement->execute(); } | | | 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 | if (!empty($params['debug'])) { echo sprintf('<pre style="padding: 5px; background: yellow; white-space: normal;">%s</pre>', htmlspecialchars($statement->getSQL(true))); } $result = $statement->execute(); } catch (\KD2\DB\DB_Exception $e) { throw new Brindille_Exception(sprintf("à la ligne %d erreur SQL :\n%s\n\nRequête exécutée :\n%s", $line, $db->lastErrorMsg(), $sql)); } while ($row = $result->fetchArray(\SQLITE3_ASSOC)) { if (isset($params['assign'])) { $tpl->assign($params['assign'], $row, 0); } yield $row; } } } |
Modified src/include/lib/Garradin/UserTemplate/UserForms.php from [3a7808a8ca] to [6bc2c4aa69].
1 2 | <?php | | > > > > > > > > | > > | 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 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 | <?php namespace Garradin\UserTemplate; use Garradin\Entities\UserForm; use Garradin\Files\Files; use Garradin\DB; use Garradin\Utils; use const Garradin\ROOT; use \KD2\DB\EntityManager as EM; class UserForms { /** * Lists all forms from files and stores a cache */ static public function refresh(): void { $existing = DB::getInstance()->getAssoc(sprintf('SELECT id, name FROM %s;', UserForm::TABLE)); $list = []; foreach (Files::list(UserForm::ROOT) as $file) { if ($file->type != $file::TYPE_DIRECTORY) { continue; } $list[] = $file->name; } foreach (glob(UserForm::DIST_ROOT . '/*') as $file) { if (!is_dir($file)) { continue; } $list[] = Utils::basename($file); } $list = array_unique($list); sort($list); $create = array_diff($list, $existing); $delete = array_diff($existing, $list); $existing = array_diff($list, $create); //echo '<pre>'; var_dump(compact('create', 'delete', 'existing', 'list')); exit; foreach ($create as $name) { self::create($name); } foreach ($delete as $name) { self::get($name)->delete(); |
︙ | ︙ | |||
67 68 69 70 71 72 73 74 75 76 | return $uf; } static public function list(): array { return EM::getInstance(UserForm::class)->all('SELECT * FROM @TABLE ORDER BY label COLLATE NOCASE ASC;'); } static public function listForSnippet(string $snippet): array { | > > > > > > > > > > > > | > | | | 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 | return $uf; } static public function list(): array { return EM::getInstance(UserForm::class)->all('SELECT * FROM @TABLE ORDER BY label COLLATE NOCASE ASC;'); } static public function getSnippets(string $snippet, array $variables = []): string { $out = ''; foreach (self::listForSnippet($snippet) as $form) { $out .= $form->fetch($snippet, $variables); $out .= PHP_EOL; } return $out; } static public function listForSnippet(string $snippet): array { return EM::getInstance(UserForm::class)->all('SELECT f.* FROM @TABLE f INNER JOIN user_forms_templates t ON t.id_form = f.id WHERE t.name = ? ORDER BY f.label COLLATE NOCASE ASC;', $snippet); } static public function get(string $name): ?UserForm { return EM::findOne(UserForm::class, 'SELECT * FROM @TABLE WHERE name = ?;', $name); } |
︙ | ︙ |
Modified src/include/lib/Garradin/UserTemplate/UserTemplate.php from [d7cda2cc08] to [4374d626dd].
︙ | ︙ | |||
29 30 31 32 33 34 35 | protected $code = null; protected $cache_path = USER_TEMPLATES_CACHE_ROOT; protected $escape_default = 'html'; static protected $root_variables; | < < | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | protected $code = null; protected $cache_path = USER_TEMPLATES_CACHE_ROOT; protected $escape_default = 'html'; static protected $root_variables; static public function getRootVariables() { if (null !== self::$root_variables) { return self::$root_variables; } static $keys = ['adresse_asso', 'champ_identifiant', 'champ_identite', 'couleur1', 'couleur2', 'email_asso', 'monnaie', 'nom_asso', 'pays', 'site_asso', 'telephone_asso', 'files']; |
︙ | ︙ | |||
296 297 298 299 300 301 302 | header(sprintf('Content-Disposition: attachment; filename="%s"', Utils::safeFileName($filename))); } header('Content-type: application/pdf'); Utils::streamPDF($html); } | < < < < > > > > > > | > | 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 | header(sprintf('Content-Disposition: attachment; filename="%s"', Utils::safeFileName($filename))); } header('Content-type: application/pdf'); Utils::streamPDF($html); } public function displayWeb(): void { $content = $this->fetch(); foreach (headers_list() as $header) { if (preg_match('/^Content-Type: (.*)$/', $header, $match)) { $type = $match[1]; break; } } $type = $type ?? 'text/html'; header(sprintf('Content-Type: %s;charset=utf-8', $type), true); if ($type == 'application/pdf') { Utils::streamPDF($content); } else { echo $content; } } } |
Modified src/include/lib/Garradin/Web/Web.php from [56b13472d4] to [0d0cf483a3].
1 2 3 4 5 6 7 8 9 10 11 12 | <?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\Plugin; | | | 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\Plugin; use Garradin\UserTemplate\UserForms; use Garradin\Utils; use Garradin\UserException; use Garradin\ValidationException; use Garradin\Membres\Session; use KD2\DB\EntityManager as EM; |
︙ | ︙ |
Modified src/skel-dist/forms/_footer.html from [8c4d109e74] to [8dcde0cdfe].
1 2 3 4 | </main> </div> | | > < | 1 2 3 4 5 6 7 8 9 10 11 12 13 | </main> </div> {{if $_GET.print == 'yes'}} <script type="text/javascript"> window.onafterprint = window.close; window.print(); </script> {{/if}} </body> </html> |
Modified src/skel-dist/forms/_header.html from [8b87cdcb91] to [faa609c763].
1 2 3 4 5 6 7 8 | {{if $_GET.print == 'pdf'}} {{:http type="pdf" download="%s.pdf"|args:$title}} {{/if}} <!DOCTYPE html> <html> <head> <title>{{$title}}</title> <style type="text/css"> | | | | | 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 | {{if $_GET.print == 'pdf'}} {{:http type="pdf" download="%s.pdf"|args:$title}} {{/if}} <!DOCTYPE html> <html> <head> <title>{{$title}}</title> <style type="text/css"> {{:include file="forms/form.css" page_size=$page_size}} </style> </head> <body> {{if !$_GET.print}} <div id="buttons"> {{:linkbutton href="%s&print=yes"|args:$request_url label="Imprimer" shape="print"}} {{:linkbutton href="%s&print=pdf"|args:$request_url label="Télécharger en PDF" shape="download"}} </div> {{/if}} <div id="page"> <header class="organization"> {{if $config.files.logo}} |
︙ | ︙ |
Modified src/skel-dist/forms/bilan_pc/form.json from [7daf140f3d] to [c544f2f588].
1 | { | | | < | 1 2 3 4 | { "name": "Bilan au modèle du plan comptable 2020", "description": "Bilan annuel basé sur le plan comptable des associations 2020" } |
Modified src/skel-dist/forms/form.css from [ab562df65c] to [52da7a6aaf].
︙ | ︙ | |||
12 13 14 15 16 17 18 | #buttons { display: none; } } @media screen { | | < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #buttons { display: none; } } @media screen { html, body { background: #666; } #page { margin: 0 auto; padding: .5cm; background: #fff; {{if $page_size == 'A5'}} width: 148mm; height: 210mm; {{else}} width: 210mm; height: 297mm; {{/if}} } } body { font-family: Arial, Helvetica, sans-serif; color: #000; font-size: 10pt; } main { font-size: 1.1em; |
︙ | ︙ | |||
82 83 84 85 86 87 88 | text-align: center; } #buttons a { margin: 1em; font-size: 1.2em; } | > > > > > > > > > > > > > > > > > > > > > > | 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 | text-align: center; } #buttons a { margin: 1em; font-size: 1.2em; } a.icn-btn { cursor: pointer; color: #fff; border: 1px solid #ccc; background: #333; user-select: none; display: inline-block; font-size: inherit; border-radius: .2em; padding: .2em .4em; margin: .2em .5em; white-space: pre; transition: box-shadow .3s; text-decoration: underline; } a.icn-btn:hover { text-decoration: none; box-shadow: 0px 0px 5px orange; } |
Added src/skel-dist/forms/recu_don/config.html version [96e2ba191b].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 31 32 33 34 35 36 37 38 | {{:admin_header title="Configuration du reçu fiscal"}} {{if $_POST.save}} {{if trim($_POST.accounts) == ''}} <p class="error block">Les numéros de comptes éligibles n'ont pas été renseignés.</p> {{else}} {{:save key="config" accounts=$_POST.accounts }} {{:http redirect="?ok=1"}} {{/if}} {{/if}} {{if $_GET.ok}} <p class="block confirm">Configuration enregistrée.</p> {{/if}} <form method="post" action=""> <fieldset> <legend>Configuration du modèle de reçu</legend> <dl> {{:input required=false name="accounts" type="text" label="Numéros de comptes éligibles aux reçus" source=$form.config default="756"}} <dd class="help"> Pour chaque numéro de compte indiqué dans ce champ, le reçu de don sera proposé (en dessous de la fiche de l'écriture).<br /> Séparer les numéros de compte avec des virgules, par exemple : <tt>754, 756</tt>.<br /> Laisser vide pour que le reçu de don soit proposé quel que soit le compte. </dd> </dl> </fieldset> <p class="submit"> {{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}} </p> </form> {{:admin_footer}} |
Modified src/skel-dist/forms/recu_don/index.html from [e5fa711c57] to [fa8b4c3bc1].
︙ | ︙ | |||
17 18 19 20 21 22 23 | <p class="submit"> {{:button type="submit" name="save" label="Voir le reçu (PDF)" shape="right" class="main"}} </form> {{:admin_footer}} {{else}} | | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <p class="submit"> {{:button type="submit" name="save" label="Voir le reçu (PDF)" shape="right" class="main"}} </form> {{:admin_footer}} {{else}} {{#transactions id=$_GET.id}} {{:include file="forms/_header.html" page_size="A5" title="Reçu de don %d - %s"|args:$id:$users_names}} <h1>Reçu de don</h1> <h4>Référence n°{{$id}} — {{$date|date_short}}</h4> <p>L'association « {{$config.nom_asso}} » atteste avoir reçu de la part de :</p> |
︙ | ︙ |
Modified src/skel-dist/forms/recu_don/snippets/transaction_details.html from [dce502db35] to [26090d459b].
|
| > | > > > > | | > > | | 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 | {{if $form.config.accounts === null}} {{:assign form.config.accounts='756'}} {{/if}} {{if $form.config.accounts}} {{:assign show=false}} {{:assign accounts=$form.config.accounts|regexp_replace:"/\s*,\s*/":"|"}} {{:assign accounts="/%s/"|args:$accounts}} {{#foreach from=$transaction_lines item="line"}} {{if $line.account_code|regexp_match:$accounts}} {{:assign show=true}} {{/if}} {{/foreach}} {{else}} {{:assign show=true}} {{/if}} {{if $show}} <h2 class="ruler">{{$form.label}}</h2> <p> {{:linkbutton href="%s?id=%d"|args:$form.url:$transaction.id target="_dialog" label="Prévisualiser" shape="eye"}} {{:linkbutton href="%s?id=%d&print=pdf"|args:$form.url:$transaction.id label="Télécharger en PDF" shape="download"}} {{:linkbutton href="%s?id=%d&print=yes"|args:$form.url:$transaction.id target="_blank" label="Imprimer" shape="print"}} </p> {{/if}} |
Modified src/skel-dist/forms/recu_fiscal/config.html from [3b59a2f4e6] to [a1f47b7d13].
|
| < < < | | | > > | > > | | > | | | | | | > > > > > > | > > > > | | > > > | | | | 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 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 | {{:admin_header title="Configuration du reçu fiscal"}} {{if $_POST.save}} {{if $_POST.topic|trim == ''}} <p class="error block">L'objet de l'association n'a pas été renseigné.</p> {{elseif $_POST.accounts|trim == ''}} <p class="error block">Les comptes éligibles aux reçus n'ont pas été renseignés.</p> {{elseif $_POST.accounts_cash|trim == ''}} <p class="error block">Les comptes d'espèces n'ont pas été renseignés.</p> {{elseif $_POST.accounts_cheques|trim == ''}} <p class="error block">Les comptes de chèques n'ont pas été renseignés.</p> {{else}} {{:save key="config" accounts=$_POST.accounts topic=$_POST.topic accounts_cash=$_POST.accounts_cash accounts_cheques=$_POST.accounts_cheques art200=$_POST.art200 art238=$_POST.art238 art885=$_POST.art885 }} {{:http redirect="?ok=1"}} {{/if}} {{/if}} {{if $_GET.ok}} <p class="block confirm">Configuration enregistrée.</p> {{/if}} <form method="post" action=""> <fieldset> <legend>Configuration du modèle de reçu fiscal</legend> <dl> {{:input required=true name="topic" type="textarea" label="Objet de l'association" source=$form.config cols="70" rows="4" help="Inscrire ici l'objet de l'association, conformément aux statuts."}} {{:input required=false name="accounts" type="text" label="Numéros des comptes éligibles aux reçus" source=$form.config default="756"}} <dd class="help"> Pour chaque numéro de compte indiqué dans ce champ, le reçu de don sera proposé (en dessous de la fiche de l'écriture).<br /> Séparer les numéros de compte avec des virgules, par exemple : <tt>754, 756</tt>.<br /> Laisser vide pour que le reçu de don soit proposé quel que soit le compte. </dd> {{:input required=true name="accounts_cash" type="text" label="Numéros des compte de caisse" source=$form.config default="530"}} <dd class="help"> Utilisé pour cocher automatiquement la bonne case dans le reçu.<br /> Séparer les numéros de compte avec des virgules, par exemple : <tt>530, 5301</tt>. </dd> {{:input required=true name="accounts_cheques" type="text" label="Numéros des comptes pour les chèques" source=$form.config default="5112"}} <dd class="help"> Utilisé pour cocher automatiquement la bonne case dans le reçu.<br /> Séparer les numéros de compte avec des virgules, par exemple : <tt>5112, 5113</tt>. </dd> <dt>Réduction d'impôt éligibles :</dt> {{:input type="checkbox" name="art200" value="1" source=$form.config label="Article 200"}} {{:input type="checkbox" name="art238" value="1" source=$form.config label="Article 238 bis"}} {{:input type="checkbox" name="art885" value="1" source=$form.config label="Article 885-0V bis A"}} </dl> </fieldset> <p class="submit"> {{:button type="submit" name="save" label="Enregistrer" shape="right" class="main"}} </p> </form> {{:admin_footer}} |
Modified src/skel-dist/forms/recu_fiscal/index.html from [527766fe40] to [760b9275f6].
1 2 3 | {{#restrict block=true section="accounting" level="read"}} {{/restrict}} | | | | > | | > > > > | | 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 31 32 33 34 35 | {{#restrict block=true section="accounting" level="read"}} {{/restrict}} {{if !$_GET.id}} {{:error message="Aucun numéro d'écriture n'a été fourni"}} {{/if}} {{if !$form.config}} {{* Valeurs par défaut *}} {{:assign var="form.config" topic="" accounts="756" accounts_cash="530" accounts_cheques="5112" art200=0 art238=0 art885=0}} {{/if}} {{#transactions id=$_GET.id}} {{:assign title="Reçu fiscal %d - %s"|args:$id:$users_names}} {{if $_GET.print == 'pdf'}} {{:http type="pdf" download="%s.pdf"|args:$title}} {{/if}} <!DOCTYPE html> <html> <head> <title>{{$title}}</title> <style type="text/css"> @media print { @page { size: A4 portrait; margin: 0; padding: 0; } |
︙ | ︙ | |||
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | #p2 { background-image: url('data:image/png;base64,{{:read base64=true file="./cerfa-2.png"}}'); } b { font-weight: normal; } </style> </head> <body> <div class="page" id="p1"> <div style="top: 10mm; left: 170mm;">{{$id}}</div> <div style="top: 35mm; left: 20mm;">{{$config.nom_asso}}</div> <div style="top: 46mm; left: 14mm; height: 11mm; width: 180mm; background: #fff;">{{$config.adresse_asso}}</div> | > > > > > | | | | | | | | 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 149 150 151 152 153 154 155 156 157 158 159 160 | #p2 { background-image: url('data:image/png;base64,{{:read base64=true file="./cerfa-2.png"}}'); } b { font-weight: normal; } .signature img { max-width: 50mm; max-height: 17mm; } </style> </head> <body> <div class="page" id="p1"> <div style="top: 10mm; left: 170mm;">{{$id}}</div> <div style="top: 35mm; left: 20mm;">{{$config.nom_asso}}</div> <div style="top: 46mm; left: 14mm; height: 11mm; width: 180mm; background: #fff;">{{$config.adresse_asso}}</div> <div style="top: 64mm; left: 14mm; background: white; width: 180mm; height: 17mm; overflow: hidden;">{{$form.config.topic|escape|nl2br}}</div> <div style="top: 128.5mm; left: 15mm;">X</div> </div> <div class="page" id="p2"> {{#transaction_users id_transaction=$id}} <div style="top: 18mm; left: 14mm; background: #fff; width: 175mm;padding: 2mm;">{{$name}}</div> <div style="top: 13mm; left: 100mm; background: #fff; width: 50mm; height: 6mm;"></div> <div style="top: 32mm; left: 18mm;">{{$adresse}}</div> <div style="top: 37mm; left: 38mm;">{{$code_postal}}</div> <div style="top: 37mm; left: 80mm;">{{$ville}}</div> {{/transaction_users}} <div style="top: 63mm; left: 87mm;">***{{$credit|raw|money}}***</div> <div style="top: 73mm; left: 58mm;">{{$credit|money_raw|spell_out_number}} euros</div> <div style="top: 82mm; left: 69mm;">{{$date|date:'d'}}</div> <div style="top: 82mm; left: 82mm;">{{$date|date:'m'}}</div> <div style="top: 82mm; left: 99mm;">{{$date|date:'Y'}}</div> <div style="top: 96mm; left: 53mm;">{{if $form.config.art200}}X{{/if}}</div> <div style="top: 96mm; left: 103mm;">{{if $form.config.art238}}X{{/if}}</div> <div style="top: 96mm; left: 153.0mm;">{{if $form.config.art885}}X{{/if}}</div> <div style="top: 113mm; left: 115mm;">X</div> {{* Abandon de frais par bénévoles *}} {{if $accounts_codes|strpos:'75412'}} <div style="top: 136mm; left: 115mm;">X</div> {{else}} <div style="top: 136mm; left: 15mm;">X</div> {{/if}} {{* Moyen de paiement *}} {{if $accounts_codes|strpos:$form.config.accounts_cash !== false}} <div style="top: 158.2mm; left: 15mm;">X</div> {{elseif $accounts_codes|strpos:$form.config.accounts_cheques !== false}} <div style="top: 158.2mm; left: 57.3mm;">X</div> {{else}} <div style="top: 158.2mm; left: 115.2mm;">X</div> {{/if}} {{* Date du jour *}} <div style="top: 239mm; left: 139mm;">{{$now|date:'d'}}</div> <div style="top: 239mm; left: 148mm;">{{$now|date:'m'}}</div> <div style="top: 239mm; left: 156mm;">{{$now|date:'Y'}}</div> <div style="top: 243mm; left: 137mm;">{{:signature}}</div> </div> {{/transactions}} </body> </html> |
Added src/skel-dist/forms/recu_fiscal/snippets/transaction_details.html version [f5406982e9].
> | 1 | {{:include file="forms/recu_don/snippets/transaction_details.html"}} |
Modified src/templates/acc/transactions/details.tpl from [edef472c69] to [17617c01f2].
1 2 3 4 5 6 7 8 9 10 | {include file="admin/_head.tpl" title="Écriture n°%d"|args:$transaction.id current="acc"} {if isset($_GET['created'])} <p class="block confirm"> L'écriture a bien été créée. </p> {/if} <nav class="tabs"> | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | {include file="admin/_head.tpl" title="Écriture n°%d"|args:$transaction.id current="acc"} {if isset($_GET['created'])} <p class="block confirm"> L'écriture a bien été créée. </p> {/if} <nav class="tabs"> {if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_ADMIN) && !$transaction->validated && !$transaction_year->closed} {linkbutton href="edit.php?id=%d"|args:$transaction.id shape="edit" label="Modifier cette écriture"} {linkbutton href="delete.php?id=%d"|args:$transaction.id shape="delete" label="Supprimer cette écriture"} {/if} {if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE)} {linkbutton href="new.php?copy=%d"|args:$transaction.id shape="plus" label="Dupliquer cette écriture"} {/if} </nav> |
︙ | ︙ | |||
74 75 76 77 78 79 80 | <dt>Date</dt> <dd>{$transaction.date|date:'l j F Y (d/m/Y)'}</dd> <dt>Numéro pièce comptable</dt> <dd>{if $transaction.reference}{$transaction.reference}{else}-{/if}</dd> <dt>Exercice</dt> <dd> | | | | | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | <dt>Date</dt> <dd>{$transaction.date|date:'l j F Y (d/m/Y)'}</dd> <dt>Numéro pièce comptable</dt> <dd>{if $transaction.reference}{$transaction.reference}{else}-{/if}</dd> <dt>Exercice</dt> <dd> <a href="{$admin_url}acc/reports/ledger.php?year={$transaction.id_year}">{$transaction_year.label}</a> | Du {$transaction_year.start_date|date_short} au {$transaction_year.end_date|date_short} | <strong>{if $transaction_year.closed}Clôturé{else}En cours{/if}</strong> </dd> <dt>Écriture créée par</dt> <dd> {if $transaction.id_creator} {if $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_READ)} <a href="{$admin_url}membres/fiche.php?id={$transaction.id_creator}">{$creator_name}</a> |
︙ | ︙ | |||
121 122 123 124 125 126 127 | <td class="money">Crédit</td> <td>Libellé ligne</td> <td>Référence ligne</td> <td>Projet</td> </tr> </thead> <tbody> | | | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | <td class="money">Crédit</td> <td>Libellé ligne</td> <td>Référence ligne</td> <td>Projet</td> </tr> </thead> <tbody> {foreach from=$transaction_lines item="line"} <tr> <td class="num"><a href="{$admin_url}acc/accounts/journal.php?id={$line.id_account}&year={$transaction.id_year}">{$line.account_code}</a></td> <td>{$line.account_label}</td> <td class="money">{if $line.debit}{$line.debit|escape|money}{/if}</td> <td class="money">{if $line.credit}{$line.credit|escape|money}{/if}</td> <td>{$line.label}</td> <td>{$line.reference}</td> |
︙ | ︙ | |||
145 146 147 148 149 150 151 152 153 | {if $files_edit || count($files)} <div class="attachments"> <h3 class="ruler">Fichiers joints</h3> {include file="common/files/_context_list.tpl" files=$files edit=$files_edit path=$file_parent} </div> {/if} {include file="admin/_foot.tpl"} | > > | 145 146 147 148 149 150 151 152 153 154 155 | {if $files_edit || count($files)} <div class="attachments"> <h3 class="ruler">Fichiers joints</h3> {include file="common/files/_context_list.tpl" files=$files edit=$files_edit path=$file_parent} </div> {/if} {$snippets|raw} {include file="admin/_foot.tpl"} |
Modified src/templates/admin/_head.tpl from [822d283ed5] to [ebf2bf8ea3].
1 2 | <?php if (!isset($current)) { | | | 1 2 3 4 5 6 7 8 9 10 | <?php if (!isset($current)) { $current = ''; } ?> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr" class="{if $dialog}dialog{/if}" data-version="{$version_hash}" data-url="{$admin_url}"> <head> <meta charset="utf-8" /> <meta name="v" content="{$version_hash}" /> |
︙ | ︙ |
Added src/templates/admin/config/forms/index.tpl version [4d1cc84ea3].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | {include file="admin/_head.tpl" title="Formulaires & modèles" current="config"} {include file="admin/config/_menu.tpl" current="forms"} <table class="list"> <tbody> {foreach from=$list item="form"} <tr> <td><h3>{$form.label}</h3>{$form.description|escape|nl2br}</td> <td class="actions"> {linkbutton label="Modifier" href="edit.php?form=%s"|args:$form.name shape="edit" target="_dialog"} {if $form->hasConfig()} <br />{linkbutton label="Configurer" href=$form->url($form::CONFIG_TEMPLATE) shape="settings" target="_dialog"} {/if} {if $form->canDelete()} <br /> {if $form->hasDist()} {linkbutton label="Remettre à zéro" href="delete.php?form=%s"|args:$form.name shape="reset" target="_dialog"} {else} {linkbutton label="Supprimer" href="delete.php?form=%s"|args:$form.name shape="delete" target="_dialog"} {/if} {/if} </td> </tr> {/foreach} </tbody> </table> {include file="admin/_foot.tpl"} |
Modified src/www/admin/acc/transactions/details.php from [48aefb0f02] to [0d689a34de].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?php namespace Garradin; use Garradin\Accounting\Transactions; require_once __DIR__ . '/../_inc.php'; $transaction = Transactions::get((int) qg('id')); if (!$transaction) { throw new UserException('Cette écriture n\'existe pas'); } $csrf_key = 'details_' . $transaction->id(); $form->runIf('mark_paid', function () use ($transaction) { $transaction->markPaid(); $transaction->save(); }, $csrf_key, Utils::getSelfURI()); | > > | | | | | < | | | | > > > > | 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 31 32 33 34 35 36 37 | <?php namespace Garradin; use Garradin\Accounting\Transactions; use Garradin\UserTemplate\UserForms; use Garradin\Entities\UserForm; require_once __DIR__ . '/../_inc.php'; $transaction = Transactions::get((int) qg('id')); if (!$transaction) { throw new UserException('Cette écriture n\'existe pas'); } $csrf_key = 'details_' . $transaction->id(); $form->runIf('mark_paid', function () use ($transaction) { $transaction->markPaid(); $transaction->save(); }, $csrf_key, Utils::getSelfURI()); $variables = compact('csrf_key', 'transaction') + [ 'transaction_lines' => $transaction->getLinesWithAccounts(false), 'transaction_year' => $transaction->year(), 'files' => $transaction->listFiles(), 'creator_name' => $transaction->id_creator ? (new Membres)->getNom($transaction->id_creator) : null, 'files_edit' => $session->canAccess($session::SECTION_ACCOUNTING, $session::ACCESS_WRITE), 'file_parent' => $transaction->getAttachementsDirectory(), 'related_users' => $transaction->listLinkedUsers(), 'related_transactions' => $transaction->listRelatedTransactions() ]; $tpl->assign($variables); $tpl->assign('snippets', UserForms::getSnippets(UserForm::SNIPPET_TRANSACTION, $variables)); $tpl->display('acc/transactions/details.tpl'); |
Added src/www/admin/config/forms/index.php version [0fba1ce665].
> > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?php namespace Garradin; use Garradin\UserTemplate\UserForms; require_once __DIR__ . '/../_inc.php'; UserForms::refresh(); $list = UserForms::list(); $tpl->assign(compact('list')); $tpl->display('admin/config/forms/index.tpl'); |