Overview
Comment:Enregistrement / modification / liste de recherches enregistrées
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dev
Files: files | file ages | folders
SHA1: 769382af320cbabb737186bfb1db9964dc40de02
User & Date: bohwaz on 2018-09-27 14:52:52
Other Links: branch diff | manifest | tags
Context
2018-10-01
17:14
Édition et suppression de recherche enregistrée check-in: a4991057b3 user: bohwaz tags: dev
2018-09-27
14:52
Enregistrement / modification / liste de recherches enregistrées check-in: 769382af32 user: bohwaz tags: dev
11:40
Donner le namespace dans le PHP des templates, pour simplifier le code des templates eux-même check-in: 438eb98248 user: bohwaz tags: dev
Changes

Modified src/include/lib/Garradin/Recherche.php from [5a3bd60873] to [ae6601ff1c].

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
	const TYPE_SQL = 'sql';

	const TARGETS = [
		'membres',
		'compta_journal',
	];

	protected function _checkFields($intitule, $id_membre, $type, $cible, &$query)
	{
		$db = DB::getInstance();

		if (trim($intitule) === '')
		{
			throw new UserException('Le champ intitulé ne peut être vide.');
		}

		if (null !== $id_membre)
		{
			$id_membre = (int)$id_membre;
		}

		if (null !== $id_membre && !$db->test('membres', 'id = ?', $id_membre))
		{
			throw new \InvalidArgumentException('Numéro d\'utilisateur inconnu.');
		}

		if ($type !== self::TYPE_SQL && $type !== self::TYPE_JSON)
		{
			throw new \InvalidArgumentException('Type de recherche inconnu.');
		}

		if (!in_array($cible, self::TARGETS, true))
		{
			throw new \InvalidArgumentException('Cible de recherche invalide.');
		}








		if ($type == self::TYPE_SQL && !is_string($query))
		{
			throw new \InvalidArgumentException('Recherche invalide pour le type SQL');
		}



		if ($type == self::TYPE_JSON)
		{
			if (!is_array($query))
			{
				throw new \InvalidArgumentException('Recherche invalide pour le type JSON');
			}

			$query = json_encode($query);

			if (!json_decode($query))
			{
				throw new \InvalidArgumentException('JSON invalide pour le type JSON');

			}
		}

		return true;
	}

	public function edit($id, $intitule, $id_membre, $type, $cible, $contenu)
	{





		$this->_checkFields($intitule, $id_membre, $type, $cible, $contenu);






		return DB::getInstance()->update('recherches',
			compact('intitule', 'id_membre', 'type', 'cible', 'contenu'),
			'id = ' . (int)$id);
	}

	public function add($intitule, $id_membre, $type, $cible, $contenu)
	{

		$this->_checkFields($intitule, $id_membre, $type, $cible, $contenu);

		$db = DB::getInstance();

		$db->insert('recherches',
			compact('intitule', 'id_membre', 'type', 'cible', 'contenu'));

		return $db->lastInsertRowId();
	}

	public function remove($id)
	{
		return DB::getInstance()->delete('recherches', 'id = ?', (int) $id);







|



|




|

|


|




|




|




>
>
>
>
>
>
>
|
|
|
|

>
>
|
|
|
|
|
|

|

|
|
|
>



|


|

>
>
>
>
>
|

>
>
>
>
>
|
<
<




>
|



|
<







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
	const TYPE_SQL = 'sql';

	const TARGETS = [
		'membres',
		'compta_journal',
	];

	protected function _checkFields($data)
	{
		$db = DB::getInstance();

		if (array_key_exists('intitule', $data) && trim($data['intitule']) === '')
		{
			throw new UserException('Le champ intitulé ne peut être vide.');
		}

		if (array_key_exists('id_membre', $data) && null !== $data['id_membre'])
		{
			$data['id_membre'] = (int)$data['id_membre'];
		}

		if (array_key_exists('id_membre', $data) && null !== $data['id_membre'] && !$db->test('membres', 'id = ?', $data['id_membre']))
		{
			throw new \InvalidArgumentException('Numéro d\'utilisateur inconnu.');
		}

		if (array_key_exists('type', $data) && $data['type'] !== self::TYPE_SQL && $data['type'] !== self::TYPE_JSON)
		{
			throw new \InvalidArgumentException('Type de recherche inconnu.');
		}

		if (array_key_exists('cible', $data) && !in_array($data['cible'], self::TARGETS, true))
		{
			throw new \InvalidArgumentException('Cible de recherche invalide.');
		}

		if (array_key_exists('type', $data))
		{
			if (empty($data['contenu']))
			{
				throw new UserException('Le contenu ne peut être vide.');
			}

			if ($data['type'] == self::TYPE_SQL && !is_string($data['contenu']))
			{
				throw new \InvalidArgumentException('Recherche invalide pour le type SQL');
			}

			$query = $data['contenu'];

			if ($data['type']  == self::TYPE_JSON)
			{
				if (!is_array($query))
				{
					throw new \InvalidArgumentException('Recherche invalide pour le type JSON');
				}

				$query = json_encode($query);

				if (!json_decode($query))
				{
					throw new \InvalidArgumentException('JSON invalide pour le type JSON');
				}
			}
		}

		return $query;
	}

	public function edit($id, $data)
	{
		$allowed = ['intitule', 'id_membre', 'type', 'cible', 'contenu'];

		// Supprimer les champs qui ne sont pas ceux de la BDD
		$data = array_intersect_key($data, array_flip($allowed));

		$query = $this->_checkFields($data);

		if (isset($data['contenu']))
		{
			$data['contenu'] = $query;
		}

		return DB::getInstance()->update('recherches', $data, 'id = ' . (int)$id);


	}

	public function add($intitule, $id_membre, $type, $cible, $contenu)
	{
		$data = compact('intitule', 'id_membre', 'type', 'cible', 'contenu');
		$data['contenu'] = $this->_checkFields($data);

		$db = DB::getInstance();

		$db->insert('recherches', $data);


		return $db->lastInsertRowId();
	}

	public function remove($id)
	{
		return DB::getInstance()->delete('recherches', 'id = ?', (int) $id);

Modified src/templates/admin/_head.tpl from [77c2a89a17] to [d52ff56450].

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
    <?php
    $current_parent = substr($current, 0, strpos($current, '/'));
    ?>
        <li class="home{if $current == 'home'} current{elseif $current_parent == 'home'} current_parent{/if}">
            <a href="{$admin_url}"><b class="icn">⌂</b><i> Accueil</i></a>
            {if !empty($plugins_menu)}
                <ul>
                {foreach from=$plugins_menu key="id" item="name"}
                    <li class="plugins {if $current == sprintf("plugin_%s", $id)} current{/if}"><a href="{plugin_url id=$id}">{$name}</a></li>
                {/foreach}
                </ul>
            {/if}
        </li>
        {if $session->canAccess('membres', Membres::DROIT_ACCES)}
            <li class="member list{if $current == 'membres'} current{elseif $current_parent == 'membres'} current_parent{/if}"><a href="{$admin_url}membres/"><b class="icn">👪</b><i> Membres</i></a>
            {if $session->canAccess('membres', Membres::DROIT_ECRITURE)}







|
|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
    <?php
    $current_parent = substr($current, 0, strpos($current, '/'));
    ?>
        <li class="home{if $current == 'home'} current{elseif $current_parent == 'home'} current_parent{/if}">
            <a href="{$admin_url}"><b class="icn">⌂</b><i> Accueil</i></a>
            {if !empty($plugins_menu)}
                <ul>
                {foreach from=$plugins_menu key="plugin_id" item="name"}
                    <li class="plugins {if $current == sprintf("plugin_%s", $plugin_id)} current{/if}"><a href="{plugin_url id=$plugin_id}">{$name}</a></li>
                {/foreach}
                </ul>
            {/if}
        </li>
        {if $session->canAccess('membres', Membres::DROIT_ACCES)}
            <li class="member list{if $current == 'membres'} current{elseif $current_parent == 'membres'} current_parent{/if}"><a href="{$admin_url}membres/"><b class="icn">👪</b><i> Membres</i></a>
            {if $session->canAccess('membres', Membres::DROIT_ECRITURE)}

Modified src/templates/admin/membres/recherche.tpl from [5180e73789] to [83ce1eddb2].

16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
			</label>
			<label><input type="checkbox" name="desc" value="1" {form_field name="desc" checked=1 default=$desc} /> Tri inversé</label>
			<label>Limiter à <input type="number" value="{$limit}" name="limit" size="5" /> résultats</label>
		</p>
		<p class="submit">
			<input type="submit" value="Chercher &rarr;" id="send" />
			<input type="hidden" name="q" id="jsonQuery" />
			<input type="submit" value="Enregistrer cette recherche" class="minor" />

		</p>
	</fieldset>
</form>

<script type="text/javascript">
var colonnes = {$colonnes|escape:'json'};








|
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
			</label>
			<label><input type="checkbox" name="desc" value="1" {form_field name="desc" checked=1 default=$desc} /> Tri inversé</label>
			<label>Limiter à <input type="number" value="{$limit}" name="limit" size="5" /> résultats</label>
		</p>
		<p class="submit">
			<input type="submit" value="Chercher &rarr;" id="send" />
			<input type="hidden" name="q" id="jsonQuery" />
			<input type="hidden" name="id" value="{$id}" />
			<input type="submit" name="save" value="{if $id}Enregistrer : {$recherche.intitule|truncate:40:"…":true}{else}Enregistrer cette recherche{/if}" class="minor" />
		</p>
	</fieldset>
</form>

<script type="text/javascript">
var colonnes = {$colonnes|escape:'json'};

Modified src/templates/admin/membres/recherche_sql.tpl from [b838ae91f5] to [f417399f3f].

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
        <dl>
            <dt><label for="f_query">Requête SQL</label></dt>
            <dd class="help">Si aucune limite n'est précisée, une limite de 100 résultats sera appliquée.</dd>
            <dd><textarea name="query" id="f_query" cols="70" rows="7" required="required">{$query}</textarea></dd>
        </dl>
        <p class="submit">
            <input type="submit" name="run" value="Exécuter &rarr;" />
            {if $query}<input type="submit" name="save" value="Enregistrer la requête" class="minor" />{/if}



        </p>
    </fieldset>
</form>

{if !empty($error)}
<p class="error">
    <strong>Erreur dans la requête SQL :</strong><br />
    {$error}
</p>
{/if}

<form method="post" action="{$admin_url}membres/action.php" class="memberList">

{if !empty($result)}
<p class="alert">{$result|count} résultats retournés.</p>
<table class="list search">
    <thead>







|
>
>
>




<
<
<
|
<
<







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23



24


25
26
27
28
29
30
31
        <dl>
            <dt><label for="f_query">Requête SQL</label></dt>
            <dd class="help">Si aucune limite n'est précisée, une limite de 100 résultats sera appliquée.</dd>
            <dd><textarea name="query" id="f_query" cols="70" rows="7" required="required">{$query}</textarea></dd>
        </dl>
        <p class="submit">
            <input type="submit" name="run" value="Exécuter &rarr;" />
            {if $query}
                {if $id}<input type="hidden" name="id" value="{$id}" />{/if}
                <input type="submit" name="save" value="{if $id}Enregistrer : {$recherche.intitule}{else}Enregistrer cette recherche{/if}" class="minor" />
            {/if}
        </p>
    </fieldset>
</form>




{form_errors}



<form method="post" action="{$admin_url}membres/action.php" class="memberList">

{if !empty($result)}
<p class="alert">{$result|count} résultats retournés.</p>
<table class="list search">
    <thead>

Modified src/templates/admin/membres/recherches.tpl from [e06b9310ec] to [b6b05b2ed5].

17
18
19
20
21
22
23


24


25
26
27
28
29
30
31
32
		<tbody>
			{foreach from=$liste item="recherche"}
			<tr>
				<th>{$recherche.intitule}</th>
				<td>{if $recherche.type == Recherche::TYPE_JSON}Avancée{else}SQL{/if}</td>
				<td>{if !$recherche.id_membre}Publique{else}Personnelle{/if}</td>
				<td class="actions">


					<a href="{$admin_url}membres/recherches.php?id={$recherche.id}" class="icn" title="Modifier">✎</a>


				</td>
			</tr>
			{/foreach}
		</tbody>
	</table>
{/if}

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







>
>
|
>
>








17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
		<tbody>
			{foreach from=$liste item="recherche"}
			<tr>
				<th>{$recherche.intitule}</th>
				<td>{if $recherche.type == Recherche::TYPE_JSON}Avancée{else}SQL{/if}</td>
				<td>{if !$recherche.id_membre}Publique{else}Personnelle{/if}</td>
				<td class="actions">
					<a href="{$admin_url}membres/recherche{if $recherche.type == Recherche::TYPE_SQL}_sql{/if}.php?id={$recherche.id}" class="icn" title="Exécuter">𝍢</a>
					{if $recherche.id_membre || $session->canAccess('membres', Membres::DROIT_ADMIN)}
					<a href="{$admin_url}membres/recherches.php?edit={$recherche.id}" class="icn" title="Modifier">✎</a>
					<a href="{$admin_url}membres/recherches.php?delete={$recherche.id}" class="icn" title="Supprimer">✘</a>
					{/if}
				</td>
			</tr>
			{/foreach}
		</tbody>
	</table>
{/if}

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

Modified src/www/admin/membres/recherche.php from [0e8c0cdaf4] to [3aa7457440].

8
9
10
11
12
13
14

15
16
17
18
19
20
21
..
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
..
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
$champs = $config->get('champs_membres');
$text_query = trim(qg('qt'));
$query = null;
$limit = f('limit') ?: 100;
$order = f('order');
$desc = (bool) f('desc');
$sql_query = null;


// Recherche simple
if ($text_query !== '')
{
    $operator = 'LIKE %?%';

    if (is_numeric(trim($text_query)))
................................................................................
                'column'   => $column,
                'operator' => $operator,
                'values'   => [$text_query],
            ],
        ],
    ]];
}


















elseif (f('q') !== null)
{
    $query = json_decode(f('q'), true);
}

if ($query)
{
    $sql_query = $recherche->buildQuery('membres', $query, $order, $desc, $limit);
    $result = $recherche->searchSQL('membres', $sql_query);

    if (count($result) == 1 && $text_query !== '')
    {
        Utils::redirect(ADMIN_URL . 'membres/fiche.php?id=' . (int)$result[0]->id);
    }

























    $tpl->assign('result_header', $membres->getSearchHeaderFields($result));
}
else
{
    $query = [[
        'operator' => 'AND',
................................................................................
                'values'   => ['Souad Massi'],
            ],
        ],
    ]];
    $result = null;
}


$tpl->assign('query', $query);
$tpl->assign('sql_query', $sql_query);
$tpl->assign('result', $result);
$tpl->assign('order', $order);
$tpl->assign('desc', $desc);
$tpl->assign('limit', $limit);
$tpl->assign('colonnes', $recherche->getColumns('membres'));

$tpl->display('admin/membres/recherche.tpl');







>







 







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













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







 







>









8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
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
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
$champs = $config->get('champs_membres');
$text_query = trim(qg('qt'));
$query = null;
$limit = f('limit') ?: 100;
$order = f('order');
$desc = (bool) f('desc');
$sql_query = null;
$id = f('id') ?: qg('id');

// Recherche simple
if ($text_query !== '')
{
    $operator = 'LIKE %?%';

    if (is_numeric(trim($text_query)))
................................................................................
                'column'   => $column,
                'operator' => $operator,
                'values'   => [$text_query],
            ],
        ],
    ]];
}
elseif ($id)
{
    $r = $recherche->get($id);

    if (!$r || $r->type != Recherche::TYPE_JSON)
    {
        throw new UserException('Recherche inconnue ou invalide');
    }

    $r->contenu = (object) json_decode($r->contenu, true);
    $query = $r->contenu->query;
    $order = $r->contenu->order;
    $desc = $r->contenu->desc;
    $limit = $r->contenu->limit;

    $tpl->assign('recherche', $r);
}

if (f('q') !== null)
{
    $query = json_decode(f('q'), true);
}

if ($query)
{
    $sql_query = $recherche->buildQuery('membres', $query, $order, $desc, $limit);
    $result = $recherche->searchSQL('membres', $sql_query);

    if (count($result) == 1 && $text_query !== '')
    {
        Utils::redirect(ADMIN_URL . 'membres/fiche.php?id=' . (int)$result[0]->id);
    }

    if (f('save'))
    {
        $query = [
            'query' => $query,
            'order' => $order,
            'limit' => $limit,
            'desc'  => $desc,
        ];

        if ($id)
        {
            $recherche->edit($id, [
                'type'    => Recherche::TYPE_JSON,
                'contenu' => $query,
            ]);
        }
        else
        {
            $id = $recherche->add('Recherche avancée du ' . date('d/m/Y H:i:s'), $user->id, $recherche::TYPE_JSON, 'membres', $query);
        }

        Utils::redirect('/admin/membres/recherches.php?id=' . $id);
    }

    $tpl->assign('result_header', $membres->getSearchHeaderFields($result));
}
else
{
    $query = [[
        'operator' => 'AND',
................................................................................
                'values'   => ['Souad Massi'],
            ],
        ],
    ]];
    $result = null;
}

$tpl->assign('id', $id);
$tpl->assign('query', $query);
$tpl->assign('sql_query', $sql_query);
$tpl->assign('result', $result);
$tpl->assign('order', $order);
$tpl->assign('desc', $desc);
$tpl->assign('limit', $limit);
$tpl->assign('colonnes', $recherche->getColumns('membres'));

$tpl->display('admin/membres/recherche.tpl');

Modified src/www/admin/membres/recherche_sql.php from [64a09b2404] to [177e1e82d4].

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
require_once __DIR__ . '/_inc.php';

$session->requireAccess('membres', Membres::DROIT_ADMIN);

$recherche = new Recherche;

$query = trim(qg('query'));
$error = null;
$result = null;















$tpl->assign('schema', $recherche->schema('membres'));
$tpl->assign('query', $query);

if ($query != '')
{
	try {
		$result = $recherche->searchSQL('membres', $query);
	}
	catch (\Exception $e)
	{
		$error = $e->getMessage();
	}

	if (!$error && qg('save'))
	{









		$id = $recherche->add('Recherche SQL du ' . date('d/m/Y H:i:s'), $user->id, $recherche::TYPE_SQL, 'membres', $query);


		Utils::redirect('/admin/recherches.php?id=' . $id);
	}
}

$tpl->assign('result', $result);

$tpl->display('admin/membres/recherche_sql.tpl');







<

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











|


|

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




>

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
require_once __DIR__ . '/_inc.php';

$session->requireAccess('membres', Membres::DROIT_ADMIN);

$recherche = new Recherche;

$query = trim(qg('query'));

$result = null;
$id = (int) qg('id');

if ($id)
{
	$r = $recherche->get($id);

	if (!$r || $r->type != Recherche::TYPE_SQL)
	{
		throw new UserException('Recherche inconnue');
	}

	$query = $r->contenu;
	$tpl->assign('recherche', $r);
}

$tpl->assign('schema', $recherche->schema('membres'));
$tpl->assign('query', $query);

if ($query != '')
{
	try {
		$result = $recherche->searchSQL('membres', $query);
	}
	catch (\Exception $e)
	{
		$form->addError($e->getMessage());
	}

	if (!$form->hasErrors() && qg('save'))
	{
		if ($id)
		{
			$recherche->edit($id, [
				'type'    => Recherche::TYPE_SQL,
				'contenu' => $query,
			]);
		}
		else
		{
			$id = $recherche->add('Recherche SQL du ' . date('d/m/Y H:i:s'), $user->id, $recherche::TYPE_SQL, 'membres', $query);
		}

		Utils::redirect('/admin/membres/recherches.php?id=' . $id);
	}
}

$tpl->assign('result', $result);
$tpl->assign('id', $id);
$tpl->display('admin/membres/recherche_sql.tpl');