Overview
Comment:List of pages and categories
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dev
Files: files | file ages | folders
SHA1: 76f8f4650ad551f8b43b193ae07cc24ff817a9e2
User & Date: bohwaz on 2020-12-13 18:21:59
Other Links: branch diff | manifest | tags
Context
2020-12-14
02:21
More work on the rich text editor, but Trix sucks a lot :( check-in: e1d70bedb9 user: bohwaz tags: dev
2020-12-13
18:21
List of pages and categories check-in: 76f8f4650a user: bohwaz tags: dev
16:11
Reflect changes in config check-in: c83f057f54 user: bohwaz tags: dev
Changes

Modified src/include/lib/Garradin/Entities/Files/File.php from [f144751b28] to [06d115add3].

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	protected $content_id;

	protected $_types = [
		'id'           => 'int',
		'folder_id'    => '?int',
		'name'         => 'string',
		'type'         => '?string',
		'public'         => 'int',
		'image'        => 'int',
		'size'         => 'int',
		'hash'         => 'string',
		'storage'      => '?string',
		'storage_path' => '?string',
		'created'      => 'DateTime',
		'author_id'    => '?int',







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	protected $content_id;

	protected $_types = [
		'id'           => 'int',
		'folder_id'    => '?int',
		'name'         => 'string',
		'type'         => '?string',
		'public'       => 'int',
		'image'        => 'int',
		'size'         => 'int',
		'hash'         => 'string',
		'storage'      => '?string',
		'storage_path' => '?string',
		'created'      => 'DateTime',
		'author_id'    => '?int',
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162



163

164
165

166

167



168
169

170
171
172
173
174
175
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

			$db->preparedQuery('INSERT OR REPLACE INTO files_search (id, content) VALUES (?, ?);', $this->id(), $content);
		}

		return $return;
	}

	static protected function store(?string $path, string $name, string $source_path = null, $source_content = null): self
	{
		assert($path || $content);

		$finfo = \finfo_open(\FILEINFO_MIME_TYPE);
		$file = new self;
		$file->path = $path;

		if ($source_path && !$source_content)
		{
			$file->hash = sha1_file($source_path);
			$file->size = filesize($source_path);
			$file->type = finfo_file($finfo, $source_path);
		}
		else
		{
			$file->hash = sha1($source_content);
			$file->size = strlen($source_content);
			$file->type = finfo_buffer($finfo, $source_content);
		}

		$file->image = preg_match('/^image\/(?:png|jpe?g|gif)$/', $file->type);

		// Check that it's a real image
		if ($file->image) {
			try {
				if ($source_path && !$source_content) {
					$i = new Image($source_path);
				}
				else {
					$i = Image::createFromBlob($source_content);
				}

				// Recompress PNG files from base64, assuming they are coming
				// from JS canvas which doesn't know how to gzip (d'oh!)
				if ($i->format() == 'png' && null !== $source_content) {
					$source_content = $i->output('png', true);
					$file->hash = sha1($source_content);
					$file->size = strlen($source_content);
				}

				unset($i);
			}
			catch (\RuntimeException $e) {
				if (strstr($e->getMessage(), 'No suitable image library found')) {
					throw new \RuntimeException('Le serveur n\'a aucune bibliothèque de gestion d\'image installée, et ne peut donc pas accepter les images. Installez Imagick ou GD.');
				}

				throw new UserException('Fichier image invalide');
			}
		}




		$db = DB::getInstance();


		$db->begin();



		// Il peut arriver que l'on renvoie ici un fichier déjà stocké, auquel cas, ne pas le re-stocker



		if ($content_id = $db->firstColumn('SELECT id FROM files_contents WHERE hash = ?;', $hash)) {
			$file->content_id = $content_id;

		}
		else {
			$db->preparedQuery('INSERT INTO files_contents (hash, size) VALUES (?, ?);', [$file->hash, (int)$file->size]);
			$file->content_id = $db->lastInsertRowID();

			if (!Files::callStorage('store', $file, $path, $content)) {
				throw new UserException('Le fichier n\'a pas pu être enregistré.');

			}

		}



		$file->save();

		$db->commit();

		return $file;
	}

	/**
	 * Upload de fichier à partir d'une chaîne en base64
	 * @param  string $name
	 * @param  string $content
	 * @return File
	 */
	static public function storeFromBase64(?string $path, string $name, string $encoded_content): self
	{
		$content = base64_decode($encoded_content);
		return self::store($path, $name, null, $content);
	}

	/**
	 * Upload du fichier par POST
	 * @param  array  $file  Caractéristiques du fichier envoyé
	 * @return File
	 */







|

<
<
<
<
<
<


|
|
<



|
|
<


<
<

|












|
|













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


<
|
|
|
<
>
|
>
|
>

>



<









|


|







104
105
106
107
108
109
110
111
112






113
114
115
116

117
118
119
120
121

122
123


124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

172
173
174

175
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

			$db->preparedQuery('INSERT OR REPLACE INTO files_search (id, content) VALUES (?, ?);', $this->id(), $content);
		}

		return $return;
	}

	public function store(string $source_path = null, $source_content = null): self
	{






		if ($source_path && !$source_content)
		{
			$this->hash = sha1_file($source_path);
			$this->size = filesize($source_path);

		}
		else
		{
			$this->hash = sha1($source_content);
			$this->size = strlen($source_content);

		}



		// Check that it's a real image
		if ($this->image) {
			try {
				if ($source_path && !$source_content) {
					$i = new Image($source_path);
				}
				else {
					$i = Image::createFromBlob($source_content);
				}

				// Recompress PNG files from base64, assuming they are coming
				// from JS canvas which doesn't know how to gzip (d'oh!)
				if ($i->format() == 'png' && null !== $source_content) {
					$source_content = $i->output('png', true);
					$this->hash = sha1($source_content);
					$this->size = strlen($source_content);
				}

				unset($i);
			}
			catch (\RuntimeException $e) {
				if (strstr($e->getMessage(), 'No suitable image library found')) {
					throw new \RuntimeException('Le serveur n\'a aucune bibliothèque de gestion d\'image installée, et ne peut donc pas accepter les images. Installez Imagick ou GD.');
				}

				throw new UserException('Fichier image invalide');
			}
		}

		if (!Files::callStorage('store', $file, $source_path, $source_content)) {
			throw new UserException('Le fichier n\'a pas pu être enregistré.');
		}

		return $this;
	}

	static protected function create(string $name, string $source_path = null, $source_content = null): self
	{
		assert($source_path || $source_content);

		$finfo = \finfo_open(\FILEINFO_MIME_TYPE);
		$file = new self;
		$file->name = $name;

		if ($source_path && !$source_content) {
			$file->type = finfo_file($finfo, $source_path);
		}
		else {

			$file->type = finfo_buffer($finfo, $source_content);
		}


		$file->image = preg_match('/^image\/(?:png|jpe?g|gif)$/', $file->type);

		$db = DB::getInstance();

		$db->begin();

		$file->store($source_path, $source_content);
		$file->save();

		$db->commit();

		return $file;
	}

	/**
	 * Upload de fichier à partir d'une chaîne en base64
	 * @param  string $name
	 * @param  string $content
	 * @return File
	 */
	static public function storeFromBase64(string $name, string $encoded_content): self
	{
		$content = base64_decode($encoded_content);
		return self::store($name, null, $content);
	}

	/**
	 * Upload du fichier par POST
	 * @param  array  $file  Caractéristiques du fichier envoyé
	 * @return File
	 */

Modified src/include/lib/Garradin/Entities/Web/Page.php from [ab2d08746c] to [652702f2a8].

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























































<?php

namespace Garradin\Entities\Web;

use Garradin\Entity;
use Garradin\UserException;



use KD2\DB\EntityManager;

class Page extends Entity
{


	protected $id;
	protected $parent_id;

	protected $status;
	protected $title;
	protected $draft;
	protected $modified;

	protected $_types = [
		'id'        => 'int',
		'parent_id' => 'int',

		'status'    => 'int',

		'title'     => 'string',
		'draft'     => 'int',
		'modified'  => 'DateTime',
	];

	protected $_file;

	const STATUS_ONLINE = 1;
	const STATUS_DRAFT = 0;















	public function file(): File
	{
		if (null === $this->_file) {
			$this->_file = EM::findOneById(File::class, $this->id);
		}

		return $this->_file;
	}






	public function save()
	{


		$file = $this->file();
		$file->save();

		$this->id($file->id());

		parent::save();
	}
}






























































>
>
|



>
>


>


|




|
>

>

<







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










>
>
>
>
>
|

>
>





|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?php

namespace Garradin\Entities\Web;

use Garradin\Entity;
use Garradin\UserException;

use const Garradin\WWW_URL;

use KD2\DB\EntityManager as EM;

class Page extends Entity
{
	const TABLE = 'web_pages';

	protected $id;
	protected $parent_id;
	protected $type;
	protected $status;
	protected $title;
	protected $uri;
	protected $modified;

	protected $_types = [
		'id'        => 'int',
		'parent_id' => '?int',
		'type'      => 'int',
		'status'    => 'int',
		'uri'       => 'string',
		'title'     => 'string',

		'modified'  => 'DateTime',
	];

	protected $_file;

	const STATUS_ONLINE = 1;
	const STATUS_DRAFT = 0;

	const TYPE_CATEGORY = 1;
	const TYPE_PAGE = 2;

	public function url(): string
	{
		$url = WWW_URL . $this->uri;

		if ($this->type == self::TYPE_CATEGORY) {
			$url .= '/';
		}

		return $url;
	}

	public function file(): File
	{
		if (null === $this->_file) {
			$this->_file = EM::findOneById(File::class, $this->id);
		}

		return $this->_file;
	}

	public function setFile(File $file)
	{
		$this->_file = $file;
	}

	public function save(): bool
	{
		$this->modified = new \DateTime;

		$file = $this->file();
		$file->save();

		$this->id($file->id());

		return parent::save();
	}

	public function selfCheck(): void
	{
		$this->assert($this->type === self::TYPE_CATEGORY || $this->type === self::TYPE_PAGE, 'Unknown page type');
		$this->assert($this->status === self::STATUS_DRAFT || $this->status === self::STATUS_ONLINE, 'Unknown page status');
		$this->assert(trim($this->title) !== '', 'Le titre ne peut rester vide');
		$this->assert(trim($this->uri) !== '', 'L\'URI ne peut rester vide');
		$this->assert(!$this->_file, 'Fichier manquant');
	}

	public function importForm(array $source = null)
	{
		if (null === $source) {
			$source = $_POST;
		}

		$file = $this->file();

		if (isset($source['content']) && sha1($source['content']) != $file->hash) {
			$file->store(null, $content);
		}

		return $this->import($source);
	}

	static public function create(int $type, string $title, string $content, int $status = self::STATUS_ONLINE): Page
	{
		static $types = [self::TYPE_PAGE, self::TYPE_CATEGORY];

		if (!in_array($type, $types)) {
			throw new \InvalidArgumentException('Unknown type');
		}

		$page = new self;
		$page->type = $type;
		$page->title = $title;
		$page->uri = Utils::transformTitleToURI($title);
		$page->status = $status;

		$file = new File;
		$file->type = 'text/html';
		$file->image = 0;

		if ($type == self::TYPE_PAGE) {
			$file->name = $page->uri . '.html';
		}
		else {
			$file->name = 'index.html';
		}

		$file->store(null, $content);
		$page->save();

		return $page;
	}
}

Modified src/include/lib/Garradin/Files/Render/Skriv.php from [048c543789] to [0dba465910].

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
		$str = preg_replace_callback('!<a href="([^/.:@]+)">!i', function ($matches) use ($prefix) {
			return '<a href="' . $prefix . self::transformTitleToURI($matches[1]) . '">';
		}, $str);

		return $str;
	}

    static public function transformTitleToURI($str)
    {
        $str = Utils::transliterateToAscii($str);

        $str = preg_replace('![^\w\d_-]!i', '-', $str);
        $str = preg_replace('!-{2,}!', '-', $str);
        $str = trim($str, '-');

        return $str;
    }

	/**
	 * Callback utilisé pour l'extension <<fichier>> dans le wiki-texte
	 * @param array $args    Arguments passés à l'extension
	 * @param string $content Contenu éventuel (en mode bloc)
	 * @param object $skriv   Objet SkrivLite
	 */
	static public function SkrivFichier($args, $content, $skriv)







<
<
<
<
<
<
<
<
<
<
<







41
42
43
44
45
46
47











48
49
50
51
52
53
54
		$str = preg_replace_callback('!<a href="([^/.:@]+)">!i', function ($matches) use ($prefix) {
			return '<a href="' . $prefix . self::transformTitleToURI($matches[1]) . '">';
		}, $str);

		return $str;
	}












	/**
	 * Callback utilisé pour l'extension <<fichier>> dans le wiki-texte
	 * @param array $args    Arguments passés à l'extension
	 * @param string $content Contenu éventuel (en mode bloc)
	 * @param object $skriv   Objet SkrivLite
	 */
	static public function SkrivFichier($args, $content, $skriv)

Modified src/include/lib/Garradin/Template.php from [f94b6d765a] to [b8eafe3cb8].

188
189
190
191
192
193
194






195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
		$shape = $params['shape'];
		$label = $params['label'];

		// href can be prefixed with '!' to make the URL relative to ADMIN_URL
		if (substr($href, 0, 1) == '!') {
			$href = ADMIN_URL . substr($params['href'], 1);
		}







		unset($params['href'], $params['shape'], $params['label']);

		array_walk($params, function (&$v, $k) {
			$v = sprintf('%s="%s"', $k, $this->escape($v));
		});

		$params = implode(' ', $params);

		return sprintf('<a class="icn-btn" data-icon="%s" href="%s" %s>%s</a>', Utils::iconUnicode($shape), $this->escape($href), $params, $this->escape($label));
	}

	protected function formInput(array $params)
	{
		static $params_list = ['value', 'default', 'type', 'help', 'label', 'name', 'options', 'source'];

		// Extract params and keep attributes separated







>
>
>
>
>
>









|







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
		$shape = $params['shape'];
		$label = $params['label'];

		// href can be prefixed with '!' to make the URL relative to ADMIN_URL
		if (substr($href, 0, 1) == '!') {
			$href = ADMIN_URL . substr($params['href'], 1);
		}

		if (!isset($params['class'])) {
			$params['class'] = '';
		}

		$params['class'] .= ' icn-btn';

		unset($params['href'], $params['shape'], $params['label']);

		array_walk($params, function (&$v, $k) {
			$v = sprintf('%s="%s"', $k, $this->escape($v));
		});

		$params = implode(' ', $params);

		return sprintf('<a data-icon="%s" href="%s" %s>%s</a>', Utils::iconUnicode($shape), $this->escape($href), $params, $this->escape($label));
	}

	protected function formInput(array $params)
	{
		static $params_list = ['value', 'default', 'type', 'help', 'label', 'name', 'options', 'source'];

		// Extract params and keep attributes separated

Modified src/include/lib/Garradin/Utils.php from [f7c395e1cb] to [936bc987d3].

837
838
839
840
841
842
843
844











        }

        $config->set('last_version_check', json_encode($last));
        $config->save();

        return $last->version;
    }
}


















|
>
>
>
>
>
>
>
>
>
>
>
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
        }

        $config->set('last_version_check', json_encode($last));
        $config->save();

        return $last->version;
    }

    static public function transformTitleToURI($str)
    {
        $str = Utils::transliterateToAscii($str);

        $str = preg_replace('![^\w\d_-]!i', '-', $str);
        $str = preg_replace('!-{2,}!', '-', $str);
        $str = trim($str, '-');

        return $str;
    }
}

Modified src/include/lib/Garradin/Web.php from [eebca41282] to [8d933d1e83].

1
2
3
4




5
6
7
8
9
10
11
<?php

namespace Garradin;





class Web
{
    static public function search(string $search, bool $online_only = true): array
    {
        if (strlen($search) > 100) {
            throw new UserException('Recherche trop longue : maximum 100 caractères');
        }




>
>
>
>







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

namespace Garradin;

use Garradin\Entities\Web\Page;

use KD2\DB\EntityManager as EM;

class Web
{
    static public function search(string $search, bool $online_only = true): array
    {
        if (strlen($search) > 100) {
            throw new UserException('Recherche trop longue : maximum 100 caractères');
        }
24
25
26
27
28
29
30
31




















            INNER JOIN web_pages AS p USING (id)
            WHERE %s files_search MATCH ?
            ORDER BY points DESC
            LIMIT 0,50;', $where);

        return DB::getInstance()->get($query, $search);
    }
}



























|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
            INNER JOIN web_pages AS p USING (id)
            WHERE %s files_search MATCH ?
            ORDER BY points DESC
            LIMIT 0,50;', $where);

        return DB::getInstance()->get($query, $search);
    }

    static public function listCategories(?int $parent): array
    {
        $where = $parent ? sprintf('parent_id = %d', $parent) : 'parent_id IS NULL';
        $sql = sprintf('SELECT * FROM @TABLE WHERE %s AND type = %d ORDER BY title COLLATE NOCASE;', $where, Page::TYPE_CATEGORY);
        return EM::getInstance(Page::class)->all($sql);
    }

    static public function listPages(?int $parent, bool $order_by_date = true): array
    {
        $where = $parent ? sprintf('parent_id = %d', $parent) : 'parent_id IS NULL';
        $order = $order_by_date ? 'modified DESC' : 'title COLLATE NOCASE';
        $sql = sprintf('SELECT * FROM @TABLE WHERE %s AND type = %d ORDER BY %s;', $where, Page::TYPE_PAGE, $order);
        return EM::getInstance(Page::class)->all($sql);
    }

    static public function get(int $id): Page
    {
        return EM::findOneById(Page::class, $id);
    }
}

Added src/templates/web/edit.tpl version [5664c13bce].



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{include file="admin/_head.tpl" title="Édition : %s"|args:$page.title current="web"}

{form_errors}

<form method="post" action="{$self_url}" class="web-edit">
	<fieldset>
		<legend>Édition</legend>
		<dl>
			{input type="text" label="Titre" required=true name="title" source=$page}
			{input type="text" label="Adresse unique" required=true name="uri" source=$page}
			{input type="checkbox" label="Brouillon" name="status" value=$page::STATUS_DRAFT source=$page help="Si coché, ne sera pas visible sur le site public"}
		</dl>
	</fieldset>
</form>


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

Added src/templates/web/index.tpl version [3bd955603c].































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
{include file="admin/_head.tpl" title=$title current="web"}

<nav class="tabs">
	<aside>
		{linkbutton shape="plus" label="Nouvelle page" href="new.php?type=%d&parent=%d"|args:$type_page,$parent}
		{linkbutton shape="plus" label="Nouvelle catégorie" href="new.php?type=%d&parent=%d"|args:$type_category,$parent}
	</aside>
	<ul>
		<li class="current"><a href="./">Gestion du site web</a></li>
		{if $session->canAccess($session::SECTION_WEB, Membres::DROIT_ADMIN)}
			<li><a href="theme.php">Thèmes</a></li>
			<li><a href="config.php">Configuration</a></li>
		{/if}
	</ul>
</nav>

{if count($categories)}
	<h2 class="ruler">Catégories</h2>
	<table class="list">
		<tbody>
			{foreach from=$categories item="p"}
			<tr>
				<th><a href="?parent={$p.id}">{$p.title}</a></th>
				<td>{if $p.status == $p::STATUS_ONLINE}En ligne{else}<em>Brouillon</em>{/if}</td>
				<td class="actions">
					{if $p.status == $p::STATUS_ONLINE}
						{linkbutton shape="eye" label="Voir sur le site" href=$p->url() target="_blank"}
					{/if}
					{linkbutton shape="menu" label="Sous-catégories et pages" href="?parent=%d"|args:$p.id}
					{linkbutton shape="image" label="Prévisualiser" href="page.php?id=%d"|args:$p.id}
					{linkbutton shape="edit" label="Modifier" href="edit.php?id=%d"|args:$p.id}
					{linkbutton shape="delete" label="Supprimer" href="delete.php?id=%d"|args:$p.id}
				</td>
			</tr>
			{/foreach}
		</tbody>
	</table>
{else}
	<p class="submit">
		{linkbutton class="main" shape="plus" label="Nouvelle catégorie" href="new.php?type=%d&parent=%d"|args:$type_category,$parent}
	</p>
{/if}

{if count($pages)}
	<h2 class="ruler">Pages</h2>
	<p>
		{if !$order_date}
			{linkbutton shape="down" label="Trier par date" href="?parent=%d"|args:$parent}
		{else}
			{linkbutton shape="up" label="Trier par titre" href="?parent=%d&order_title"|args:$parent}
		{/if}
	</p>
	<table class="list">
		<tbody>
			{foreach from=$pages item="p"}
			<tr>
				<th>{$p.title}</th>
				<td>{if $p.status == $p::STATUS_ONLINE}En ligne{else}<em>Brouillon</em>{/if}</td>
				<td>Modifié le {$p.modified|date_long}</td>
				<td class="actions">
					{if $p.status == $p::STATUS_ONLINE}
						{linkbutton shape="eye" label="Voir sur le site" href=$p->url() target="_blank"}
					{/if}
					{linkbutton shape="image" label="Prévisualiser" href="page.php?id=%d"|args:$p.id}
					{linkbutton shape="edit" label="Modifier" href="edit.php?id=%d"|args:$p.id}
					{linkbutton shape="delete" label="Supprimer" href="delete.php?id=%d"|args:$p.id}
				</td>
			</tr>
			{/foreach}
		</tbody>
	</table>
{else}
	<p class="submit">
		{linkbutton shape="plus" class="main" label="Nouvelle page" href="new.php?type=%d&parent=%d"|args:$type_page,$parent}
	</p>
{/if}


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

Added src/www/admin/web/_inc.php version [c90c669bb9].























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
<?php

namespace Garradin;

use Garradin\Membres\Session;

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

$session->requireAccess(Session::SECTION_WEB, Membres::DROIT_ACCES);

$tpl->assign('custom_css', ['wiki.css']);

Added src/www/admin/web/edit.php version [8062efc532].





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

namespace Garradin;

use Garradin\Web;
use Garradin\Entities\Web\Page;

require_once __DIR__ . '/_inc.php';

$id = (int) qg('id');
$page = Web::get($id);

if (!$page) {
    throw new UserException('Page inconnue');
}

$csrf_key = 'edit_' . $page->id();

$form->runIf('save', function ($page) {
    $page->importForm();
    $page->save();
}, $csrf_key, Utils::getSelfURI());

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

$tpl->display('web/edit.tpl');

Added src/www/admin/web/index.php version [70815962e3].





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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\Web;
use Garradin\Entities\Web\Page;

require_once __DIR__ . '/_inc.php';

$parent = (int) qg('parent') ?: null;

if ($parent) {
	$cat = Web::get($parent);

	if (!$cat) {
		throw new UserException('Catégorie inconnue');
	}
}

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

$categories = Web::listCategories($parent);
$pages = Web::listPages($parent, $order_date);
$title = $parent ? sprintf('Gestion du site web : %s', $cat->title) : 'Gestion du site web';
$type_page = Page::TYPE_PAGE;
$type_category = Page::TYPE_CATEGORY;

$tpl->assign(compact('categories', 'pages', 'title', 'parent', 'type_page', 'type_category', 'order_date'));

$tpl->display('web/index.tpl');