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
$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)))







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$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)))
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
                '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',
        'conditions' => [
            [
                'column'   => $config->get('champ_identite'),
                'operator' => '= ?',
                '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');







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













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


















>









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
                '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',
        'conditions' => [
            [
                'column'   => $config->get('champ_identite'),
                'operator' => '= ?',
                '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].

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

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');










<

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











|


|

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




>

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

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');