Overview
Comment:Re-merge missing stuff
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dev
Files: files | file ages | folders
SHA3-256: 0688a410c3a393ea6841227ee41422c22434f16e3406c62e275afbba62d91d76
User & Date: bohwaz on 2021-10-05 02:28:07
Other Links: branch diff | manifest | tags
Context
2021-10-05
02:58
Rename plugin fields check-in: d65ebca7db user: bohwaz tags: dev
02:28
Re-merge missing stuff check-in: 0688a410c3 user: bohwaz tags: dev
02:17
Merge missing commits, fix upgrade check-in: 701cb83b3b user: bohwaz tags: dev
00:47
Implement generic signals for entities check-in: 84133f87d4 user: bohwaz tags: trunk, stable
Changes

Modified src/Makefile from [7364cd9885] to [7915fce3ed].

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
	rm -rf "include/lib/KD2"
	unzip "${TMP_KD2}/kd2.zip" -d include/lib

	rm -rf ${TMP_KD2}

	wget -O "include/lib/Parsedown.php" "https://raw.githubusercontent.com/erusev/parsedown/1.7.x/Parsedown.php"

	wget -O "include/lib/Parsedown.php" "https://raw.githubusercontent.com/erusev/parsedown/1.7.x/Parsedown.php"
	wget -O "include/lib/ParsedownExtra.php" "https://raw.githubusercontent.com/erusev/parsedown-extra/0.8.x/ParsedownExtra.php"

dev-server:
	php -S localhost:8082 -t www www/_route.php

test:
	find . -name '*.php' -print0 | xargs -0 -n1 php -l > /dev/null

phpstan:







<
<
<







10
11
12
13
14
15
16



17
18
19
20
21
22
23
	rm -rf "include/lib/KD2"
	unzip "${TMP_KD2}/kd2.zip" -d include/lib

	rm -rf ${TMP_KD2}

	wget -O "include/lib/Parsedown.php" "https://raw.githubusercontent.com/erusev/parsedown/1.7.x/Parsedown.php"




dev-server:
	php -S localhost:8082 -t www www/_route.php

test:
	find . -name '*.php' -print0 | xargs -0 -n1 php -l > /dev/null

phpstan:

Modified src/include/data/1.0.0_migration.sql from [4e16391488] to [931bc31a61].

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
UPDATE acc_accounts SET type = 5, description = (SELECT description FROM compta_categories WHERE compte = acc_accounts.code)
	WHERE id IN (SELECT a.id FROM acc_accounts a INNER JOIN compta_categories c ON c.compte = a.code AND c.type = -1 AND c.compte NOT LIKE '4%' AND a.position = 4);

-- Tiers
UPDATE acc_accounts SET type = 4, description = (SELECT description FROM compta_categories WHERE compte = acc_accounts.code)
	WHERE id IN (SELECT a.id FROM acc_accounts a INNER JOIN compta_categories c ON c.compte = a.code AND c.type = -1 AND c.compte LIKE '4%');

-- Recopie des opérations, mais le nom a changé pour acc_transactions_users
INSERT INTO acc_transactions_users
	SELECT * FROM membres_operations_old;

-- Recopie des exercices, mais la date de fin ne peut être nulle
INSERT INTO acc_years (id, label, start_date, end_date, closed, id_chart)
	SELECT id, libelle, debut, CASE WHEN fin IS NULL THEN date(debut, '+1 year') ELSE fin END, cloture, 1 FROM compta_exercices;

-- Recopie des catégories, on supprime la colonne id_cotisation_obligatoire
INSERT INTO membres_categories
	SELECT id, nom, droit_wiki, droit_membres, droit_compta, droit_inscription, droit_connexion, droit_config, cacher FROM membres_categories_old;

DROP TABLE membres_categories_old;

-- Transfert des rapprochements
UPDATE acc_transactions_lines SET reconciled = 1 WHERE id_transaction IN (SELECT id_operation FROM compta_rapprochement);

--------- MIGRATION COTISATIONS ----------

-- A edge-case where the end date is after the start date, let's fix it…
UPDATE cotisations SET fin = debut WHERE fin < debut;


INSERT INTO services SELECT id, intitule, description, duree, debut, fin FROM cotisations;

INSERT INTO services_fees (id, label, amount, id_service, id_account, id_year)
	SELECT id, intitule, CASE WHEN montant IS NOT NULL THEN CAST(montant*100 AS integer) ELSE NULL END, id,
		(SELECT id FROM acc_accounts WHERE code = (SELECT compte FROM compta_categories WHERE id = id_categorie_compta)),
		(SELECT MAX(id) FROM acc_years WHERE closed = 0)







<
<
<
<

















>







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
UPDATE acc_accounts SET type = 5, description = (SELECT description FROM compta_categories WHERE compte = acc_accounts.code)
	WHERE id IN (SELECT a.id FROM acc_accounts a INNER JOIN compta_categories c ON c.compte = a.code AND c.type = -1 AND c.compte NOT LIKE '4%' AND a.position = 4);

-- Tiers
UPDATE acc_accounts SET type = 4, description = (SELECT description FROM compta_categories WHERE compte = acc_accounts.code)
	WHERE id IN (SELECT a.id FROM acc_accounts a INNER JOIN compta_categories c ON c.compte = a.code AND c.type = -1 AND c.compte LIKE '4%');





-- Recopie des exercices, mais la date de fin ne peut être nulle
INSERT INTO acc_years (id, label, start_date, end_date, closed, id_chart)
	SELECT id, libelle, debut, CASE WHEN fin IS NULL THEN date(debut, '+1 year') ELSE fin END, cloture, 1 FROM compta_exercices;

-- Recopie des catégories, on supprime la colonne id_cotisation_obligatoire
INSERT INTO membres_categories
	SELECT id, nom, droit_wiki, droit_membres, droit_compta, droit_inscription, droit_connexion, droit_config, cacher FROM membres_categories_old;

DROP TABLE membres_categories_old;

-- Transfert des rapprochements
UPDATE acc_transactions_lines SET reconciled = 1 WHERE id_transaction IN (SELECT id_operation FROM compta_rapprochement);

--------- MIGRATION COTISATIONS ----------

-- A edge-case where the end date is after the start date, let's fix it…
UPDATE cotisations SET fin = debut WHERE fin < debut;
UPDATE cotisations SET duree = NULL WHERE duree = 0;

INSERT INTO services SELECT id, intitule, description, duree, debut, fin FROM cotisations;

INSERT INTO services_fees (id, label, amount, id_service, id_account, id_year)
	SELECT id, intitule, CASE WHEN montant IS NOT NULL THEN CAST(montant*100 AS integer) ELSE NULL END, id,
		(SELECT id FROM acc_accounts WHERE code = (SELECT compte FROM compta_categories WHERE id = id_categorie_compta)),
		(SELECT MAX(id) FROM acc_years WHERE closed = 0)
156
157
158
159
160
161
162






163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178




































INSERT INTO services_reminders SELECT * FROM rappels;
INSERT INTO services_reminders_sent SELECT id, id_membre, id_cotisation,
	CASE WHEN id_rappel IS NULL THEN (SELECT MAX(id) FROM rappels) ELSE id_rappel END, date
	FROM rappels_envoyes
	WHERE id_rappel IS NOT NULL
	GROUP BY id_membre, id_cotisation, id_rappel;







DROP TABLE cotisations;
DROP TABLE cotisations_membres;
DROP TABLE rappels;
DROP TABLE rappels_envoyes;

-- Suppression inutilisées
DROP TABLE compta_rapprochement;
DROP TABLE compta_journal;
DROP TABLE compta_categories;
DROP TABLE compta_comptes;
DROP TABLE compta_exercices;
DROP TABLE membres_operations_old;

DROP TABLE compta_projets;
DROP TABLE compta_comptes_bancaires;
DROP TABLE compta_moyens_paiement;











































>
>
>
>
>
>
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
INSERT INTO services_reminders SELECT * FROM rappels;
INSERT INTO services_reminders_sent SELECT id, id_membre, id_cotisation,
	CASE WHEN id_rappel IS NULL THEN (SELECT MAX(id) FROM rappels) ELSE id_rappel END, date
	FROM rappels_envoyes
	WHERE id_rappel IS NOT NULL
	GROUP BY id_membre, id_cotisation, id_rappel;

-- Recopie des opérations par membre, mais le nom a changé pour acc_transactions_users, et il faut valider l'existence du membre ET du service
INSERT INTO acc_transactions_users
	SELECT a.* FROM membres_operations_old a
	INNER JOIN membres b ON b.id = a.id_membre
	INNER JOIN services_users c ON c.id = a.id_cotisation;

DROP TABLE cotisations;
DROP TABLE cotisations_membres;
DROP TABLE rappels;
DROP TABLE rappels_envoyes;

-- Suppression inutilisées
DROP TABLE compta_rapprochement;
DROP TABLE compta_journal;
DROP TABLE compta_categories;
DROP TABLE compta_comptes;
DROP TABLE compta_exercices;
DROP TABLE membres_operations_old;

DROP TABLE compta_projets;
DROP TABLE compta_comptes_bancaires;
DROP TABLE compta_moyens_paiement;

INSERT INTO acc_charts (country, code, label) VALUES ('FR', 'PCA2018', 'Plan comptable associatif 2018');

CREATE TEMP TABLE tmp_accounts (code,label,description,position,type);

.import charts/fr_2018.csv tmp_accounts

INSERT INTO acc_accounts (id_chart, code, label, description, position, type) SELECT
	(SELECT id FROM acc_charts WHERE code = 'PCA2018'),
	code, label, description,
	CASE position
		WHEN 'Actif' THEN 1
		WHEN 'Passif' THEN 2
		WHEN 'Actif ou passif' THEN 3
		WHEN 'Charge' THEN 4
		WHEN 'Produit' THEN 5
		ELSE 0
	END,
	CASE type
		WHEN 'Banque' THEN 1
		WHEN 'Caisse' THEN 2
		WHEN 'Attente d''encaissement' THEN 3
		WHEN 'Tiers' THEN 4
		WHEN 'Dépenses' THEN 5
		WHEN 'Recettes' THEN 6
		WHEN 'Analytique' THEN 7
		WHEN 'Bénévolat' THEN 8
		WHEN 'Ouverture' THEN 9
		WHEN 'Clôture' THEN 10
		WHEN 'Résultat excédentaire' THEN 11
		WHEN 'Résultat déficitaire' THEN 12
		ELSE 0
	END
	FROM tmp_accounts;

DROP TABLE tmp_accounts;

Modified src/include/lib/Garradin/Entities/Accounting/Transaction.php from [f45c5b736f] to [7faa864717].

87
88
89
90
91
92
93


94
95
96
97
98
99
100
		'reference' => 'string|max:200',
		'date'      => 'required|date_format:d/m/Y',
	];

	protected $_lines;
	protected $_old_lines = [];



	/**
	 * @var Transaction
	 */
	protected $_related;

	static public function getTypeFromAccountType(int $account_type)
	{







>
>







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
		'reference' => 'string|max:200',
		'date'      => 'required|date_format:d/m/Y',
	];

	protected $_lines;
	protected $_old_lines = [];

	protected $_accounts = [];

	/**
	 * @var Transaction
	 */
	protected $_related;

	static public function getTypeFromAccountType(int $account_type)
	{
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
				return self::TYPE_ADVANCED;
		}
	}

	/**
	 * @param  bool $restrict_year Set to TRUE to only return lines linked to the correct chart, or FALSE (deprecated/legacy) to return all lines even if they are linked to accounts in the wrong chart!
	 */
	public function getLinesWithAccounts(bool $restrict_year = true)
	{
		$restrict = $restrict_year ? 'AND a.id_chart = y.id_chart' : '';



		$sql = sprintf('SELECT
			l.*, a.label AS account_name, a.code AS account_code,
			b.label AS analytical_name
			FROM acc_transactions_lines l
			INNER JOIN acc_accounts a ON a.id = l.id_account %s
			INNER JOIN acc_transactions t ON t.id = l.id_transaction
			INNER JOIN acc_years y ON y.id = t.id_year
			LEFT JOIN acc_accounts b ON b.id = l.id_analytical
			WHERE l.id_transaction = ? ORDER BY l.id;', $restrict);







		$em = EntityManager::getInstance(Line::class);




		return $em->DB()->get($sql, $this->id);


	}





















	public function getLines($with_accounts = false)
	{
		if (null === $this->_lines && $this->exists()) {
			$em = EntityManager::getInstance(Line::class);
			$this->_lines = $em->all('SELECT * FROM @TABLE WHERE id_transaction = ? ORDER BY id;', $this->id);
		}
		elseif (null === $this->_lines) {
			$this->_lines = [];







|

|

>
>
|
|
|
|
|
|
|
|
|

>
>
>
>
>
>
|
>
>
>
>
|
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







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
176
177
178
179
180
181
				return self::TYPE_ADVANCED;
		}
	}

	/**
	 * @param  bool $restrict_year Set to TRUE to only return lines linked to the correct chart, or FALSE (deprecated/legacy) to return all lines even if they are linked to accounts in the wrong chart!
	 */
	public function getLinesWithAccounts(bool $restrict_year = true): array
	{
		$db = EntityManager::getInstance(Line::class)->DB();

		if (null === $this->_lines || $restrict_year === false) {
			$restrict = $restrict_year ? 'AND a.id_chart = y.id_chart' : '';
			$sql = sprintf('SELECT
				l.*, a.label AS account_name, a.code AS account_code,
				b.label AS analytical_name
				FROM acc_transactions_lines l
				INNER JOIN acc_accounts a ON a.id = l.id_account %s
				INNER JOIN acc_transactions t ON t.id = l.id_transaction
				INNER JOIN acc_years y ON y.id = t.id_year
				LEFT JOIN acc_accounts b ON b.id = l.id_analytical
				WHERE l.id_transaction = %d ORDER BY l.id;', $restrict, $this->id());

			return $db->get($sql);
		}
		else {
			// Merge data from accounts with lines
			$accounts = [];
			$lines_with_accounts = [];

			foreach ($this->getLines() as $line) {
				if (!array_key_exists($line->id_account, $this->_accounts)) {
					$accounts[] = $line->id_account;
				}

				if ($line->id_analytical && !array_key_exists($line->id_analytical, $this->_accounts)) {
					$accounts[] = $line->id_analytical;
				}
			}

			if (count($accounts)) {
				$sql = sprintf('SELECT id, label, code FROM acc_accounts WHERE %s;', $db->where('id', 'IN', $accounts));
				$this->_accounts += $db->getGrouped($sql);
			}

			foreach ($this->getLines() as $line) {
				$account = [
					'account_code' => $this->_accounts[$line->id_account]->code,
					'account_name' => $this->_accounts[$line->id_account]->label,
					'analytical_name' => $line->id_analytical ? $this->_accounts[$line->id_analytical]->label : null,
				];

				$lines_with_accounts[] = (object) ($line->asArray() + $account);
			}

			return $lines_with_accounts;
		}
	}

	public function getLines(): array
	{
		if (null === $this->_lines && $this->exists()) {
			$em = EntityManager::getInstance(Line::class);
			$this->_lines = $em->all('SELECT * FROM @TABLE WHERE id_transaction = ? ORDER BY id;', $this->id);
		}
		elseif (null === $this->_lines) {
			$this->_lines = [];
250
251
252
253
254
255
256









































257
258
259
260
261
262
263
		$type = $this->getTypesDetails()[$this->type];

		return [
			$type->accounts[0]->position == 'credit' ? $credit : $debit,
			$type->accounts[1]->position == 'credit' ? $credit : $debit,
		];
	}










































/*
	public function getHash()
	{
		if (!$this->id_year) {
			throw new \LogicException('Il n\'est pas possible de hasher un mouvement qui n\'est pas associé à un exercice');
		}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
330
331
332
333
334
335
336
337
338
339
340
		$type = $this->getTypesDetails()[$this->type];

		return [
			$type->accounts[0]->position == 'credit' ? $credit : $debit,
			$type->accounts[1]->position == 'credit' ? $credit : $debit,
		];
	}

	/**
	 * Creates a new Transaction entity (not saved) from an existing one,
	 * trying to adapt to a different chart if possible
	 * @param  int    $id
	 * @param  Year   $year Target year
	 * @return Transaction
	 */
	public function duplicate(Year $year): Transaction
	{
		$new = new Transaction;

		$copy = ['type', 'status', 'label', 'notes', 'reference', 'date'];

		foreach ($copy as $field) {
			$new->$field = $this->$field;
		}

		$copy = ['credit', 'debit', 'id_account', 'label', 'reference'];
		$lines = DB::getInstance()->get('SELECT
				l.credit, l.debit, l.label, l.reference, b.id AS id_account
			FROM acc_transactions_lines l
			INNER JOIN acc_accounts a ON a.id = l.id_account
			LEFT JOIN acc_accounts b ON b.code = a.code AND b.id_chart = ?
			WHERE l.id_transaction = ?;',
			$year->chart()->id,
			$this->id()
		);

		foreach ($lines as $l) {
			$line = new Line;
			foreach ($copy as $field) {
				$line->$field = $l->$field;
			}

			$new->addLine($line);
		}

		return $new;
	}


/*
	public function getHash()
	{
		if (!$this->id_year) {
			throw new \LogicException('Il n\'est pas possible de hasher un mouvement qui n\'est pas associé à un exercice');
		}
310
311
312
313
314
315
316


317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335

336
337
338
339
340
341
342
343
344
345
346

	public function save(): bool
	{
		if ($this->validated && empty($this->_modified['validated'])) {
			throw new ValidationException('Il n\'est pas possible de modifier une écriture qui a été validée');
		}



		$db = DB::getInstance();

		if ($db->test(Year::TABLE, 'id = ? AND closed = 1', $this->id_year)) {
			throw new ValidationException('Il n\'est pas possible de créer ou modifier une écriture dans un exercice clôturé');
		}

		if (!parent::save()) {
			return false;
		}

		foreach ($this->getLines() as $line)
		{
			$line->id_transaction = $this->id();
			$line->save();
		}

		foreach ($this->_old_lines as $line)
		{

			$line->delete();

		}

		// Remove flag
		if ((self::TYPE_DEBT == $this->type || self::TYPE_CREDIT == $this->type) && $this->_related) {
			$this->_related->markPaid();
			$this->_related->save();
		}

		return true;
	}








>
>


















>
|
>



|







387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427

	public function save(): bool
	{
		if ($this->validated && empty($this->_modified['validated'])) {
			throw new ValidationException('Il n\'est pas possible de modifier une écriture qui a été validée');
		}

		$exists = $this->exists();

		$db = DB::getInstance();

		if ($db->test(Year::TABLE, 'id = ? AND closed = 1', $this->id_year)) {
			throw new ValidationException('Il n\'est pas possible de créer ou modifier une écriture dans un exercice clôturé');
		}

		if (!parent::save()) {
			return false;
		}

		foreach ($this->getLines() as $line)
		{
			$line->id_transaction = $this->id();
			$line->save();
		}

		foreach ($this->_old_lines as $line)
		{
			if ($line->exists()) {
				$line->delete();
			}
		}

		// Remove flag
		if (!$exists && $this->_related) {
			$this->_related->markPaid();
			$this->_related->save();
		}

		return true;
	}

462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
		else {
			$details = self::getTypesDetails();

			if (!array_key_exists($type, $details)) {
				throw new ValidationException('Type d\'écriture inconnu');
			}

			if (empty($this->_related) && ($type == self::TYPE_DEBT || $type == self::TYPE_CREDIT)) {
				$this->addStatus(self::STATUS_WAITING);
			}
			else {
				$this->removeStatus(self::STATUS_WAITING);
			}

			if (empty($source['amount'])) {
				throw new UserException('Montant non précisé');
			}

			$amount = $source['amount'];







|
|

|
|







543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
		else {
			$details = self::getTypesDetails();

			if (!array_key_exists($type, $details)) {
				throw new ValidationException('Type d\'écriture inconnu');
			}

			if (!empty($this->_related) && ($type == self::TYPE_DEBT || $type == self::TYPE_CREDIT)) {
				$this->set('type', self::TYPE_ADVANCED);
			}
			elseif (!$this->exists() && ($type == self::TYPE_DEBT || $type == self::TYPE_CREDIT)) {
				$this->addStatus(self::STATUS_WAITING);
			}

			if (empty($source['amount'])) {
				throw new UserException('Montant non précisé');
			}

			$amount = $source['amount'];

Modified src/include/lib/Garradin/UserTemplate/UserTemplate.php from [af2cae2f01] to [67a24ca43b].

174
175
176
177
178
179
180
181












	public function fetch(): string
	{
		ob_start();
		$this->display();
		return ob_get_clean();
	}
}


















|
>
>
>
>
>
>
>
>
>
>
>
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192

	public function fetch(): string
	{
		ob_start();
		$this->display();
		return ob_get_clean();
	}

	public function displayPDF(?string $filename = null): void
	{
		header('Content-type: application/pdf');

		if ($filename) {
			header(sprintf('Content-Disposition: attachment; filename="%s"', Utils::safeFileName($filename)));
		}

		Utils::streamPDF($this->fetch());
	}
}

Modified src/include/lib/Garradin/Web/Render/EncryptedSkriv.php from [d0d2a69554] to [42fbb7e0fc].

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
<?php

namespace Garradin\Web\Render;

use Garradin\Entities\Files\File;
use Garradin\Template;
use const Garradin\ADMIN_URL;

class EncryptedSkriv
{
	public function render(File $file, ?string $content = null): string
	{
		$tpl = Template::getInstance();

		$content = $content ?? $file->fetch();
		$tpl->assign('admin_url', ADMIN_URL);
		$tpl->assign(compact('file', 'content'));
		return $tpl->fetch('common/files/_file_render_encrypted.tpl');
	}
}








|

|


>






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

namespace Garradin\Web\Render;

use Garradin\Entities\Files\File;
use Garradin\Template;
use const Garradin\ADMIN_URL;

class EncryptedSkriv extends AbstractRender
{
	public function render(?string $content = null): string
	{
		$tpl = Template::getInstance();
		$file = $this->file;
		$content = $content ?? $file->fetch();
		$tpl->assign('admin_url', ADMIN_URL);
		$tpl->assign(compact('file', 'content'));
		return $tpl->fetch('common/files/_file_render_encrypted.tpl');
	}
}

Modified src/include/lib/Garradin/Web/Render/Skriv.php from [0ea4ef11c0] to [ce5e528272].

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
66
67
68
69
70
71
72
73
<?php

namespace Garradin\Web\Render;

use Garradin\Entities\Files\File;

use Garradin\Plugin;
use Garradin\UserTemplate\CommonModifiers;

use KD2\SkrivLite;

use const Garradin\{ADMIN_URL, WWW_URL};

class Skriv
{
	use AttachmentAwareTrait;

	static protected $skriv;

	public function render(?File $file, ?string $content = null, array $options = []): string
	{
		if (!self::$skriv)

		{
			self::$skriv = new \KD2\SkrivLite;
			self::$skriv->registerExtension('file', [self::class, 'SkrivFile']);

			self::$skriv->registerExtension('image', [self::class, 'SkrivImage']);

			// Enregistrer d'autres extensions éventuellement
			Plugin::fireSignal('skriv.init', ['skriv' => self::$skriv]);
		}

		$skriv =& self::$skriv;


		if ($file) {
			$this->isRelativeTo($file);
		}

		$str = $content ?? $file->fetch();

		$str = preg_replace_callback('/#file:\[([^\]\h]+)\]/', function ($match) {
			return $this->resolveAttachment($match[1]);
		}, $str);

		$str = $skriv->render($str);

		$str = CommonModifiers::typo($str);

		$str = preg_replace_callback(';<a href="((?!https?://|\w+:).+)">;i', function ($matches) {
			return sprintf('<a href="%s" target="_parent">', $this->resolveLink($matches[1]));
		}, $str);

		return sprintf('<div class="web-content">%s</div>', $str);
	}








	/**
	 * Callback utilisé pour l'extension <<file>> dans le wiki-texte
	 * @param array $args    Arguments passés à l'extension
	 * @param string $content Contenu éventuel (en mode bloc)
	 * @param SkrivLite $skriv   Objet SkrivLite
	 */
	static public function SkrivFile(array $args, ?string $content, SkrivLite $skriv): string
	{
		$name = $args[0] ?? null;
		$caption = $args[1] ?? null;

		if (!$name || !$this->current_path)
		{
			return $skriv->parseError('/!\ Tag file : aucun nom de fichier indiqué.');
		}

		if (empty($caption))
		{
			$caption = $name;













|

<
<
|

|

<
>
|
|
|
>
|

|
|
|

<
>
|
<
|
|
<
|















>
>
>
>
>
>
>







|




|







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
66
67
68
69
70
71
72
73
74
75
76
77
<?php

namespace Garradin\Web\Render;

use Garradin\Entities\Files\File;

use Garradin\Plugin;
use Garradin\UserTemplate\CommonModifiers;

use KD2\SkrivLite;

use const Garradin\{ADMIN_URL, WWW_URL};

class Skriv extends AbstractRender
{


	protected $skriv;

	public function __construct(?File $file = null, ?string $user_prefix = null)
	{

		parent::__construct($file, $user_prefix);

		$this->skriv = new SkrivLite;
		$this->skriv->registerExtension('file', [$this, 'SkrivFile']);
		$this->skriv->registerExtension('fichier', [$this, 'SkrivFile']);
		$this->skriv->registerExtension('image', [$this, 'SkrivImage']);

		// Enregistrer d'autres extensions éventuellement
		Plugin::fireSignal('skriv.init', ['skriv' => $this->skriv]);
	}


	public function render(?string $content = null): string
	{

		$skriv =& $this->skriv;


		$str = $content ?? $this->file->fetch();

		$str = preg_replace_callback('/#file:\[([^\]\h]+)\]/', function ($match) {
			return $this->resolveAttachment($match[1]);
		}, $str);

		$str = $skriv->render($str);

		$str = CommonModifiers::typo($str);

		$str = preg_replace_callback(';<a href="((?!https?://|\w+:).+)">;i', function ($matches) {
			return sprintf('<a href="%s" target="_parent">', $this->resolveLink($matches[1]));
		}, $str);

		return sprintf('<div class="web-content">%s</div>', $str);
	}

	public function callExtension(array $match)
	{
		$method = new \ReflectionMethod($this->skriv, '_callExtension');
		$method->setAccessible(true);
		return $method->invoke($this->skriv, $match);
	}

	/**
	 * Callback utilisé pour l'extension <<file>> dans le wiki-texte
	 * @param array $args    Arguments passés à l'extension
	 * @param string $content Contenu éventuel (en mode bloc)
	 * @param SkrivLite $skriv   Objet SkrivLite
	 */
	public function SkrivFile(array $args, ?string $content, SkrivLite $skriv): string
	{
		$name = $args[0] ?? null;
		$caption = $args[1] ?? null;

		if (!$name || null === $this->current_path)
		{
			return $skriv->parseError('/!\ Tag file : aucun nom de fichier indiqué.');
		}

		if (empty($caption))
		{
			$caption = $name;
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98


99
100
101
102
103
104
105
106

	/**
	 * Callback utilisé pour l'extension <<image>> dans le wiki-texte
	 * @param array $args    Arguments passés à l'extension
	 * @param string $content Contenu éventuel (en mode bloc)
	 * @param SkrivLite $skriv   Objet SkrivLite
	 */
	static public function SkrivImage(array $args, ?string $content, SkrivLite $skriv): string
	{
		static $align_values = ['left', 'right', 'center'];

		$name = $args[0] ?? null;
		$align = $args[1] ?? null;
		$caption = $args[2] ?? null;



		if (!$name || !$this->current_path)
		{
			return $skriv->parseError('/!\ Tag image : aucun nom de fichier indiqué.');
		}

		$url = $this->resolveAttachment($name);
		$thumb_url = sprintf('%s?%dpx', $url, $align == 'center' ? 500 : 200);








|

|





>
>
|







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

	/**
	 * Callback utilisé pour l'extension <<image>> dans le wiki-texte
	 * @param array $args    Arguments passés à l'extension
	 * @param string $content Contenu éventuel (en mode bloc)
	 * @param SkrivLite $skriv   Objet SkrivLite
	 */
	public function SkrivImage(array $args, ?string $content, SkrivLite $skriv): string
	{
		static $align_replace = ['gauche' => 'left', 'droite' => 'right', 'centre' => 'center'];

		$name = $args[0] ?? null;
		$align = $args[1] ?? null;
		$caption = $args[2] ?? null;

		$align = strtr($align, $align_replace);

		if (!$name || null === $this->current_path)
		{
			return $skriv->parseError('/!\ Tag image : aucun nom de fichier indiqué.');
		}

		$url = $this->resolveAttachment($name);
		$thumb_url = sprintf('%s?%dpx', $url, $align == 'center' ? 500 : 200);

Modified src/include/lib/Garradin/Web/Skeleton.php from [f4f75cf9cf] to [03f267b710].

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
			}

			$ut->assignArray($params);

			$ut->display();
		}
		elseif ($this->file) {
			$this->file->display();
		}
		else {
			readfile($this->defaultPath());
		}
	}

	public function exists()







|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
			}

			$ut->assignArray($params);

			$ut->display();
		}
		elseif ($this->file) {
			echo $this->file->fetch();
		}
		else {
			readfile($this->defaultPath());
		}
	}

	public function exists()
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
			return 'text/html';
		}
		elseif ($ext == 'js') {
			return 'text/javascript';
		}

		if ($this->file) {
			return $this->file->type;
  		}

		$finfo = \finfo_open(\FILEINFO_MIME_TYPE);
		return finfo_file($finfo, $this->defaultPath());

	}








|







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
			return 'text/html';
		}
		elseif ($ext == 'js') {
			return 'text/javascript';
		}

		if ($this->file) {
			return $this->file->mime;
  		}

		$finfo = \finfo_open(\FILEINFO_MIME_TYPE);
		return finfo_file($finfo, $this->defaultPath());

	}

Modified src/www/admin/web/index.php from [9ff309f525] to [fbf5316a30].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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);
	}
}
else {
	foreach (Web::sync() as $error) {
		$form->addError($error);
	}
}

$order_date = qg('order_date') !== null;







<
<
<
<
<







13
14
15
16
17
18
19





20
21
22
23
24
25
26
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_date') !== null;