Overview
Comment:Implement dynamic field delete and edit
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dev
Files: files | file ages | folders
SHA3-256: 3e93b9feec29274e0a053e19e7aec3fe5d906ab24a1a46663284c52910647a92
User & Date: bohwaz on 2022-03-15 00:42:53
Other Links: branch diff | manifest | tags
Context
2022-03-16
02:03
Implement edit and adding new fields check-in: c2c72edead user: bohwaz tags: dev
2022-03-15
00:42
Implement dynamic field delete and edit check-in: 3e93b9feec user: bohwaz tags: dev
00:42
Remove uninstalled presets check-in: 0c4a61cd92 user: bohwaz tags: dev
Changes

Modified src/include/data/1.2.0_migration.sql from [72795b0652] to [66b98794ee].

50
51
52
53
54
55
56
57
58
59
60
61
DELETE FROM config WHERE key IN ('champs_membres', 'champ_identite', 'champ_identifiant');

-- Seems that some installations had this leftover? Let's just drop it.
DROP TABLE IF EXISTS srs_old;

-- Drop membres
DROP TABLE IF EXISTS membres;

-- Manually update foreign keys
PRAGMA writable_schema = 1;
UPDATE sqlite_master SET sql = REPLACE(sql, 'REFERENCES membres', 'REFERENCES users') WHERE sql LIKE '%REFERENCES users' AND type = 'table';
PRAGMA writable_schema = 0;







<
<
<
<
<
50
51
52
53
54
55
56





DELETE FROM config WHERE key IN ('champs_membres', 'champ_identite', 'champ_identifiant');

-- Seems that some installations had this leftover? Let's just drop it.
DROP TABLE IF EXISTS srs_old;

-- Drop membres
DROP TABLE IF EXISTS membres;





Modified src/include/init.php from [dcc287710a] to [ddc6c0aeef].

339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
if (ERRORS_REPORT_URL)
{
	ErrorManager::setRemoteReporting(ERRORS_REPORT_URL, true);
}

ErrorManager::setProductionErrorTemplate(defined('Garradin\ERRORS_TEMPLATE') && ERRORS_TEMPLATE ? ERRORS_TEMPLATE : '<!DOCTYPE html><html><head><title>Erreur interne</title>
	<style type="text/css">
	body {font-family: sans-serif; }
	code, p, h1 { max-width: 400px; margin: 1em auto; display: block; }
	code { text-align: right; color: #666; }
	a { color: blue; }
	form { text-align: center; }
	</style></head><body><h1>Erreur interne</h1><p>Désolé mais le serveur a rencontré une erreur interne
	et ne peut répondre à votre requête. Merci de ré-essayer plus tard.</p>
	<p>Si vous suspectez un bug dans Garradin, vous pouvez suivre 
	<a href="https://fossil.kd2.org/garradin/wiki?name=Rapporter+un+bug&p">ces instructions</a>
	pour le rapporter.</p>
	<if(sent)><p>Un-e responsable a été notifié-e et cette erreur sera corrigée dès que possible.</p></if>
	<if(logged)><code>L\'erreur a été enregistrée dans les journaux système (error.log) sous la référence : <b>{$ref}</b></code></if>
	<p><a href="' . WWW_URL . '">&larr; Retour à la page d\'accueil</a></p>
	</body></html>');

ErrorManager::setHtmlHeader('<!DOCTYPE html><meta charset="utf-8" /><style type="text/css">
	body { font-family: sans-serif; } * { margin: 0; padding: 0; }
	u, code b, i, h3 { font-style: normal; font-weight: normal; text-decoration: none; }
	#icn { color: #fff; font-size: 2em; float: right; margin: 1em; padding: 1em; background: #900; border-radius: 50%; }
	section header { background: #fdd; padding: 1em; }
	section article { margin: 1em; }
	section article h3, section article h4 { font-size: 1em; font-family: mono; }
	code { border: 1px dotted #ccc; display: block; }
	code b { margin-right: 1em; color: #999; }







|















|







339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
if (ERRORS_REPORT_URL)
{
	ErrorManager::setRemoteReporting(ERRORS_REPORT_URL, true);
}

ErrorManager::setProductionErrorTemplate(defined('Garradin\ERRORS_TEMPLATE') && ERRORS_TEMPLATE ? ERRORS_TEMPLATE : '<!DOCTYPE html><html><head><title>Erreur interne</title>
	<style type="text/css">
	body {font-family: sans-serif; background: #fff; }
	code, p, h1 { max-width: 400px; margin: 1em auto; display: block; }
	code { text-align: right; color: #666; }
	a { color: blue; }
	form { text-align: center; }
	</style></head><body><h1>Erreur interne</h1><p>Désolé mais le serveur a rencontré une erreur interne
	et ne peut répondre à votre requête. Merci de ré-essayer plus tard.</p>
	<p>Si vous suspectez un bug dans Garradin, vous pouvez suivre 
	<a href="https://fossil.kd2.org/garradin/wiki?name=Rapporter+un+bug&p">ces instructions</a>
	pour le rapporter.</p>
	<if(sent)><p>Un-e responsable a été notifié-e et cette erreur sera corrigée dès que possible.</p></if>
	<if(logged)><code>L\'erreur a été enregistrée dans les journaux système (error.log) sous la référence : <b>{$ref}</b></code></if>
	<p><a href="' . WWW_URL . '">&larr; Retour à la page d\'accueil</a></p>
	</body></html>');

ErrorManager::setHtmlHeader('<!DOCTYPE html><meta charset="utf-8" /><style type="text/css">
	body { font-family: sans-serif; background: #fff; } * { margin: 0; padding: 0; }
	u, code b, i, h3 { font-style: normal; font-weight: normal; text-decoration: none; }
	#icn { color: #fff; font-size: 2em; float: right; margin: 1em; padding: 1em; background: #900; border-radius: 50%; }
	section header { background: #fdd; padding: 1em; }
	section article { margin: 1em; }
	section article h3, section article h4 { font-size: 1em; font-family: mono; }
	code { border: 1px dotted #ccc; display: block; }
	code b { margin-right: 1em; color: #999; }

Modified src/include/lib/Garradin/Entities/Users/DynamicField.php from [7162a58dd1] to [0e567ce101].

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
	 * Index of row in users list
	 */
	protected ?int $list_row;

	/**
	 * Multiple options (JSON) for select and multiple fields
	 */
	protected ?string $options;

	/**
	 * Default value
	 */
	protected ?string $default_value;

	/**







|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
	 * Index of row in users list
	 */
	protected ?int $list_row;

	/**
	 * Multiple options (JSON) for select and multiple fields
	 */
	protected ?array $options = [];

	/**
	 * Default value
	 */
	protected ?string $default_value;

	/**
73
74
75
76
77
78
79

80
81
82
83
84
85
86

	const TYPES = [
		'email'		=>	'Adresse E-Mail',
		'url'		=>	'Adresse URL',
		'checkbox'	=>	'Case à cocher',
		'date'		=>	'Date',
		'datetime'	=>	'Date et heure',

		'file'      =>  'Fichier',
		'password'  =>  'Mot de passe',
		'number'	=>	'Nombre',
		'tel'		=>	'Numéro de téléphone',
		'select'	=>	'Sélecteur à choix unique',
		'multiple'  =>  'Sélecteur à choix multiple',
		'country'	=>	'Sélecteur de pays',







>







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

	const TYPES = [
		'email'		=>	'Adresse E-Mail',
		'url'		=>	'Adresse URL',
		'checkbox'	=>	'Case à cocher',
		'date'		=>	'Date',
		'datetime'	=>	'Date et heure',
		'month'     =>  'Mois et année',
		'file'      =>  'Fichier',
		'password'  =>  'Mot de passe',
		'number'	=>	'Nombre',
		'tel'		=>	'Numéro de téléphone',
		'select'	=>	'Sélecteur à choix unique',
		'multiple'  =>  'Sélecteur à choix multiple',
		'country'	=>	'Sélecteur de pays',
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
		'textarea' => 'TEXT',
	];

	const SQL_CONSTRAINTS = [
		'checkbox' => '%1s = 1 OR %1s = 0',
		'date'     => '%1s IS NULL OR (date(%1$s) IS NOT NULL AND date(%1s) = %1$s)',
		'datetime' => '%1s IS NULL OR (date(%1$s) IS NOT NULL AND date(%1s) = %1$s)',

	];

	const SYSTEM_FIELDS = [
		'id'           => '?int',
		'id_category'  => 'int',
		'pgp_key'      => '?string',
		'otp_secret'   => '?string',
		'date_login'   => '?DateTime',
		'date_created' => '?date',
	];

	public function delete(): bool
	{
		if ($this->system) {
			throw new ValidationException('Ce champ est utilisé en interne, il n\'est pas possible de le supprimer');
		}







		return parent::delete();
	}

	public function selfCheck(): void
	{
		$this->name = strtolower($this->name);







>
















>
>
>
>
>
>







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
		'textarea' => 'TEXT',
	];

	const SQL_CONSTRAINTS = [
		'checkbox' => '%1s = 1 OR %1s = 0',
		'date'     => '%1s IS NULL OR (date(%1$s) IS NOT NULL AND date(%1s) = %1$s)',
		'datetime' => '%1s IS NULL OR (date(%1$s) IS NOT NULL AND date(%1s) = %1$s)',
		'month'    => '%1s IS NULL OR (date(%1s || \'-03\') = %1$s || \'-03\')', // Use 3rd day to avoid any potential issue with timezones
	];

	const SYSTEM_FIELDS = [
		'id'           => '?int',
		'id_category'  => 'int',
		'pgp_key'      => '?string',
		'otp_secret'   => '?string',
		'date_login'   => '?DateTime',
		'date_created' => '?date',
	];

	public function delete(): bool
	{
		if ($this->system) {
			throw new ValidationException('Ce champ est utilisé en interne, il n\'est pas possible de le supprimer');
		}

		if ($this->type == 'file') {
			foreach (Files::glob(File::CONTEXT_USER . '/*/' . $this->name) as $file) {
				$file->delete();
			}
		}

		return parent::delete();
	}

	public function selfCheck(): void
	{
		$this->name = strtolower($this->name);

Modified src/include/lib/Garradin/Entities/Users/User.php from [0932410200] to [73f2b6b410].

106
107
108
109
110
111
112


113
114
115
116
117
118
119
		if ($session->isLogged()) {
			$user = $session->getUser();

			if ($user->id == $this->id) {
				throw new UserException('Il n\'est pas possible de supprimer son propre compte. Merci de demander à un administrateur de le faire.');
			}
		}



		return parent::delete();
	}

	public function category(): Category
	{
		return Categories::get($this->id_category);







>
>







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
		if ($session->isLogged()) {
			$user = $session->getUser();

			if ($user->id == $this->id) {
				throw new UserException('Il n\'est pas possible de supprimer son propre compte. Merci de demander à un administrateur de le faire.');
			}
		}

		Files::delete($this->attachementsDirectory());

		return parent::delete();
	}

	public function category(): Category
	{
		return Categories::get($this->id_category);

Modified src/include/lib/Garradin/Upgrade.php from [70de025310] to [95ffb05e25].

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
				$db->import(ROOT . '/include/data/1.2.0_schema.sql');

				// Migrate users table
				$df = \Garradin\Users\DynamicFields::fromOldINI($config->champs_membres, $config->champ_identifiant, $config->champ_identite, 'numero');
				$df->save();

				// Migrate other stuff
				$db->commitSchemaUpdate();
				$db->close();

				ini_set('sqlite3.defensive', 0);
				$db->beginSchemaUpdate();
				$db->import(ROOT . '/include/data/1.2.0_migration.sql');
				$db->commitSchemaUpdate();
			}

			// Réinstaller les plugins système si nécessaire
			Plugin::checkAndInstallSystemPlugins();








<
<
<
<
<







270
271
272
273
274
275
276





277
278
279
280
281
282
283
				$db->import(ROOT . '/include/data/1.2.0_schema.sql');

				// Migrate users table
				$df = \Garradin\Users\DynamicFields::fromOldINI($config->champs_membres, $config->champ_identifiant, $config->champ_identite, 'numero');
				$df->save();

				// Migrate other stuff





				$db->import(ROOT . '/include/data/1.2.0_migration.sql');
				$db->commitSchemaUpdate();
			}

			// Réinstaller les plugins système si nécessaire
			Plugin::checkAndInstallSystemPlugins();

Modified src/templates/admin/config/_menu.tpl from [ab9107d0d2] to [b82fb8771c].


1
2
3
4
5
6
7

<nav class="tabs">
	<ul>
		<li{if $current == 'index'} class="current"{/if}><a href="{$admin_url}config/">Général</a></li>
		<li{if $current == 'custom'} class="current"{/if}><a href="{$admin_url}config/custom.php">Personnalisation</a></li>
		<li{if $current == 'categories'} class="current"{/if}><a href="{$admin_url}config/categories/">Catégories de membres</a></li>
		<li{if $current == 'fields'} class="current"{/if}><a href="{$admin_url}config/fields/">Fiche des membres</a></li>
		<li{if $current == 'backup'} class="current"{/if}><a href="{$admin_url}config/backup/">Sauvegardes</a></li>
>







1
2
3
4
5
6
7
8
{if !$dialog}
<nav class="tabs">
	<ul>
		<li{if $current == 'index'} class="current"{/if}><a href="{$admin_url}config/">Général</a></li>
		<li{if $current == 'custom'} class="current"{/if}><a href="{$admin_url}config/custom.php">Personnalisation</a></li>
		<li{if $current == 'categories'} class="current"{/if}><a href="{$admin_url}config/categories/">Catégories de membres</a></li>
		<li{if $current == 'fields'} class="current"{/if}><a href="{$admin_url}config/fields/">Fiche des membres</a></li>
		<li{if $current == 'backup'} class="current"{/if}><a href="{$admin_url}config/backup/">Sauvegardes</a></li>
18
19
20
21
22
23
24

		{if SQL_DEBUG}
		<li{if $sub_current == 'sql_debug'} class="current"{/if}><a href="{$admin_url}config/advanced/sql_debug.php">Journal SQL</a></li>
		{/if}
		{/if}
	</ul>
	{/if}
</nav>








>
19
20
21
22
23
24
25
26
		{if SQL_DEBUG}
		<li{if $sub_current == 'sql_debug'} class="current"{/if}><a href="{$admin_url}config/advanced/sql_debug.php">Journal SQL</a></li>
		{/if}
		{/if}
	</ul>
	{/if}
</nav>
{/if}

Modified src/templates/admin/config/categories/index.tpl from [885e1ad798] to [1057f70315].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
				<th>{$cat.name}</th>
				<td class="num">{$cat.count}</td>
				<td class="permissions">
					{display_permissions permissions=$cat}
				</td>
				<td class="actions">
					{if $cat.id != $logged_user.id_category}
						{linkbutton shape="delete" label="Supprimer" href="supprimer.php?id=%d"|args:$cat.id}
					{/if}
					{linkbutton shape="edit" label="Modifier" href="modifier.php?id=%d"|args:$cat.id}
					{linkbutton shape="users" label="Liste des membres" href="!membres/?cat=%d"|args:$cat.id}
				</td>
			</tr>
		{/foreach}
	</tbody>







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
				<th>{$cat.name}</th>
				<td class="num">{$cat.count}</td>
				<td class="permissions">
					{display_permissions permissions=$cat}
				</td>
				<td class="actions">
					{if $cat.id != $logged_user.id_category}
						{linkbutton shape="delete" label="Supprimer" href="supprimer.php?id=%d"|args:$cat.id target="_dialog"}
					{/if}
					{linkbutton shape="edit" label="Modifier" href="modifier.php?id=%d"|args:$cat.id}
					{linkbutton shape="users" label="Liste des membres" href="!membres/?cat=%d"|args:$cat.id}
				</td>
			</tr>
		{/foreach}
	</tbody>

Added src/templates/admin/config/fields/delete.tpl version [79517ab2b0].





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
{include file="admin/_head.tpl" title="Supprimer un champ" current="config"}

{include file="common/delete_form.tpl"
	legend="Supprimer ce champ ?"
	confirm="Cocher cette case pour supprimer le champ, cela effacera de manière permanente cette donnée de toutes les fiches membres."
	warning="Êtes-vous sûr de vouloir supprimer le champ « %s » ?"|args:$field.label
	alert="Attention, ce champ ainsi que les données qu'il contient seront supprimés de toutes les fiches membres existantes."
}

{include file="admin/_foot.tpl"}

Added src/templates/admin/config/fields/edit.tpl version [4e4c6cc5a2].





















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
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
<?php
$title = $field->exists() ? 'Modifier un champ' : 'Ajouter un champ';
?>
{include file="admin/_head.tpl" current="config" title=$title}

{include file="admin/config/_menu.tpl" current="fields"}

{form_errors}

<form method="post" action="{$self_url}">
<fieldset>
	<legend>{$title}</legend>
	{if !$field->exists()}
	<p class="help block">Avant de demander une information personnelle à vos membres… en avez-vous vraiment besoin&nbsp;?<br />
		La loi demande à minimiser au strict minimum les données collectées. Pensez également aux risques de sécurité&nbsp;: si vous demandez la date de naissance complète, cela pourrait être utilisé pour de l'usurpation d'identité, il serait donc plus sage de ne demander que le mois et l'année de naissance, si ces données sont nécessaires afin d'avoir l'âge de la personne.
	</p>
	{/if}
	<dl>
	{if !$field->exists()}
		{input type="select" name="type" options=$field::TYPES source=$field label="Type" help="Il ne sera plus possible de modifier le type une fois le champ créé." required=true}
	{else}
		{input type="select" name="type" options=$field::TYPES source=$field label="Type" help="Il n'est plus possible de modifier le titre." disabled=true}
	{/if}

		{input type="text" name="label" label="Libellé" required=true source=$field}
		{input type="text" name="help" label="Texte d'aide" help="Apparaîtra dans les formulaires comme ce texte." source=$field}

		{input type="checkbox" name="required" value=1 label="Champ obligatoire" help="Si coché, une fiche membre ne pourra pas être enregistrée si ce champ n'est pas renseigné." source=$field}

		{input type="text" name="default" source=$field label="Valeur par défaut" help="Si renseigné, le champ aura cette valeur par défaut lors de l'ajout d'un nouveau membre"}

		<dt>Le champ est visible…</dt>
		{input type="radio" name="read_access" value=$field::ACCESS_ADMIN label="Seulement aux personnes qui gèrent les membres" source=$field}
		{input type="radio" name="read_access" value=$field::ACCESS_USER label="Au membre lui-même, et aux personnes qui gèrent les membres" source=$field help="Le membre pourra voir cette information en se connectant"}

		<dt>Le champ peut être modifié…</dt>
		{input type="radio" name="write_access" value=$field::ACCESS_ADMIN label="Par les personnes qui gèrent les membres" source=$field}
		{input type="radio" name="write_access" value=$field::ACCESS_USER label="Par le membre lui-même, et aux personnes qui gèrent les membres" source=$field help="Le membre pourra modifier cette information en se connectant"}
	</dl>
</fieldset>

<fieldset class="type-select type-multiple">
	<legend>Options possibles</legend>

	<p class="alert block type-select">Attention renommer ou supprimer une option n'affecte pas ce qui a déjà été enregistré dans les fiches des membres.</p>
	<p class="alert block type-multiple">Attention changer l'ordre des options peut avoir des effets indésirables.</p>

	<dl class="type-multiple type-select options">
		{foreach from=$field.options item="option"}
		<dd>{input type="text" name="options[]" default=$option}</dd>
		{/foreach}
		<dd>{input type="text" name="options[]"}</dd>
	</dl>
</fieldset>

<p class="submit">
	{csrf_field key=$csrf_key}
	{linkbutton label="Annuler les changements" shape="left" href="./"}
	{button type="submit" name="save" label="Enregistrer les changements" shape="right" class="main"}
</p>

</form>

<script type="text/javascript">
{literal}
var addBtn = document.createElement('button');
addBtn.type = "button";
addBtn.dataset.icon = "➕";
addBtn.className = "icn add";
addBtn.title = "Ajouter une option";

var delBtn = document.createElement('button');
delBtn.type = "button";
delBtn.dataset.icon = "➖";
delBtn.className = "icn delete";
delBtn.title = "Enlever cette option";

var options = $('.options dd');

options.forEach((o, i) => {
	if (i == 0) {
		return;
	}

	let btn = delBtn.cloneNode(true);
	btn.onclick = delOption;
	o.appendChild(btn);
});

addPlusButton();

function addOption(e) {
	var options = $('.options dd');
	var target = e.target;
	var new_option = target.parentNode.cloneNode(true);
	new_option.querySelector('input').value = '';

	new_option.querySelectorAll('button').forEach((b) => b.remove());

	var btn = delBtn.cloneNode();
	btn.onclick = delOption;
	new_option.appendChild(btn);

	target.parentNode.parentNode.appendChild(new_option);
	target.remove(); // Remove add button from previous line

	addPlusButton();
}

function delOption(e) {
	var options = $('.options dd');
	if (options.length == 1) {
		return;
	}

	e.target.parentNode.remove();
	addPlusButton();
}

function addPlusButton () {
	var options = $('.options dd');
	var btn = addBtn.cloneNode();
	btn.onclick = addOption;

	if (options.length < 30) {
		let last = options[options.length - 1];

		if (last.querySelector('.add')) {
			return;
		}

		last.appendChild(btn);
	}
}
{/literal}
</script>

{include file="admin/_foot.tpl"}

Modified src/templates/admin/config/fields/index.tpl from [aba9e76cf1] to [2b943be0f1].

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




16
17
18
19
20
21
22
{include file="admin/_head.tpl" current="config" title="Fiche des membres"}

{include file="admin/config/_menu.tpl" current="fields"}

<nav class="tabs">
	{linkbutton shape="plus" label="Ajouter un champ" href="new.php"}
</nav>

{if $_GET.msg == 'SAVED'}
	<p class="block confirm">
		L'ordre a bien été enregistré.
	</p>
{elseif isset($status) && $status == 'ADDED'}
	<p class="block alert">
		Le champ a été ajouté à la fin de la liste. Pour vérifier et sauvegarder les modifications de la fiche membre cliquer sur le bouton «&nbsp;Vérifier les changements&nbsp;» en base de page.




	</p>
{/if}

{form_errors}

<form method="post" action="{$self_url_no_qs}">
	<table class="list">





|


|



|
|
|
>
>
>
>







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
{include file="admin/_head.tpl" current="config" title="Fiche des membres"}

{include file="admin/config/_menu.tpl" current="fields"}

<nav class="tabs">
	{linkbutton shape="plus" label="Ajouter un champ" href="edit.php"}
</nav>

{if $_GET.msg == 'ORDER_SAVED'}
	<p class="block confirm">
		L'ordre a bien été enregistré.
	</p>
{elseif $_GET.msg == 'SAVED'}
	<p class="block confirm">
		Les modifications ont bien été enregistrées.
	</p>
{elseif $_GET.msg == 'DELETED'}
	<p class="block confirm">
		Le champ a bien été supprimé.
	</p>
{/if}

{form_errors}

<form method="post" action="{$self_url_no_qs}">
	<table class="list">
43
44
45
46
47
48
49




50
51
52
53
54
55
56
57
58
59
60
61
62
63
					{/if}
					{linkbutton shape="edit" label="Modifier" href="edit.php?id=%d"|args:$field.id target="_dialog"}
				</td>
			</tr>
		{/foreach}
		</tbody>
	</table>





	<p class="submit">
		{csrf_field key=$csrf_key}
		{button type="submit" name="save" label="Enregistrer" shape="right" class="main"}
	</p>
</form>

<p class="help">
	Cliquer et glisser-déposer sur une ligne pour en changer l'ordre.
</p>

<script type="text/javascript" src="{$admin_url}static/scripts/dragdrop-table.js"></script>

{include file="admin/_foot.tpl"}







>
>
>
>



|



<
<
<
<



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64




65
66
67
					{/if}
					{linkbutton shape="edit" label="Modifier" href="edit.php?id=%d"|args:$field.id target="_dialog"}
				</td>
			</tr>
		{/foreach}
		</tbody>
	</table>

	<p class="help">
		Cliquer et glisser-déposer sur une ligne pour en changer l'ordre.
	</p>

	<p class="submit">
		{csrf_field key=$csrf_key}
		{button type="submit" name="save" label="Enregistrer l'ordre" shape="right"}
	</p>
</form>





<script type="text/javascript" src="{$admin_url}static/scripts/dragdrop-table.js"></script>

{include file="admin/_foot.tpl"}

Added src/www/admin/config/fields/delete.php version [bbd2f22de5].























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?php
namespace Garradin;

use Garradin\Users\DynamicFields;

require_once __DIR__ . '/../_inc.php';

$csrf_key = 'change_fields_delete';
$fields = DynamicFields::getInstance();

$field = $fields->fieldById((int)qg('id'));

if (!$field) {
	throw new UserException('Le champ indiqué n\'existe pas.');
}

$form->runIf('delete', function () use ($field, $fields) {
	if (!f('confirm_delete')) {
		throw new UserException('Merci de bien vouloir cocher la case pour confirmer la suppression.');
	}

	$fields->delete($field->name);
}, $csrf_key, '!config/fields/?msg=DELETED');

$tpl->assign(compact('csrf_key', 'field'));

$tpl->display('admin/config/fields/delete.tpl');

Added src/www/admin/config/fields/edit.php version [4f4bd678e4].





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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\Entities\Users\DynamicField;
use Garradin\Users\DynamicFields;

require_once __DIR__ . '/../_inc.php';

$csrf_key = 'change_fields_edit_' . (int)qg('id');
$fields = DynamicFields::getInstance();

if (qg('id')) {
	$field = $fields->fieldById((int)qg('id'));
}
else {
	$field = new DynamicField;
}

if (!$field) {
	throw new UserException('Le champ indiqué n\'existe pas.');
}

$form->runIf('save', function () use ($field) {
	$field->importForm();
	$field->save();
}, $csrf_key, '!config/fields/?msg=SAVED');

$tpl->assign(compact('csrf_key', 'field'));

$tpl->display('admin/config/fields/edit.tpl');