Overview
Comment:Check links inside page and display errors
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | stable
Files: files | file ages | folders
SHA3-256: f2d230333263270609058fb6c1992cada7d6bd4f44b3ef83c8dcfd95dcc88ec0
User & Date: bohwaz on 2022-07-12 21:45:55
Other Links: manifest | tags
Context
2022-07-12
21:48
Fix don't display errors for sub-categories check-in: 74b2b60536 user: bohwaz tags: trunk, stable
21:45
Check links inside page and display errors check-in: f2d2303332 user: bohwaz tags: trunk, stable
21:44
Fix prefix in links check-in: 90f6a13cf1 user: bohwaz tags: trunk, stable
Changes

Modified src/include/lib/Garradin/Entities/Web/Page.php from [103caaaf73] to [fde50935fd].

1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
<?php

namespace Garradin\Entities\Web;

use Garradin\DB;
use Garradin\Entity;
use Garradin\UserException;
use Garradin\Utils;
use Garradin\Entities\Files\File;
use Garradin\Files\Files;
use Garradin\Web\Render\Render;


use KD2\DB\EntityManager as EM;

use const Garradin\WWW_URL;

class Page extends Entity
{











>







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

namespace Garradin\Entities\Web;

use Garradin\DB;
use Garradin\Entity;
use Garradin\UserException;
use Garradin\Utils;
use Garradin\Entities\Files\File;
use Garradin\Files\Files;
use Garradin\Web\Render\Render;
use Garradin\Web\Web;

use KD2\DB\EntityManager as EM;

use const Garradin\WWW_URL;

class Page extends Entity
{
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439



440
441
442
443
444
445
446
447

		return $out;
	}

	/**
	 * Return list of internal links in page that link to non-existing pages
	 */
	public function checkInternalLinks(): array
	{
		if ($this->format == Render::FORMAT_ENCRYPTED) {
			return [];
		}

		$html = $this->render();
		preg_match_all('/<a[^>]+href=["\']([^"\']+)["\']/', $html, $match, PREG_PATTERN_ORDER);
		$errors = [];

		foreach ($match[1] as $link) {
			if (strpos($link, WWW_URL) === 0) {
				$link = substr($link, strlen(WWW_URL));
			}

			$link = trim($link, '/');

			// Link is not internal
			if (preg_match('!https?:|\w+:|/!', $link)) {
				continue;
			}




			if (!Web::getByURI($link)) {
				$errors[] = $link;
			}
		}

		return array_unique($errors);
	}








|

















|



>
>
>
|







412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451

		return $out;
	}

	/**
	 * Return list of internal links in page that link to non-existing pages
	 */
	public function checkInternalLinks(?array &$pages = null): array
	{
		if ($this->format == Render::FORMAT_ENCRYPTED) {
			return [];
		}

		$html = $this->render();
		preg_match_all('/<a[^>]+href=["\']([^"\']+)["\']/', $html, $match, PREG_PATTERN_ORDER);
		$errors = [];

		foreach ($match[1] as $link) {
			if (strpos($link, WWW_URL) === 0) {
				$link = substr($link, strlen(WWW_URL));
			}

			$link = trim($link, '/');

			// Link is not internal
			if (preg_match('!https?:|\w+:|/|#!', $link)) {
				continue;
			}

			if (null !== $pages && !array_key_exists($link, $pages)) {
				$errors[] = $link;
			}
			elseif (null === $pages && !Web::getByURI($link)) {
				$errors[] = $link;
			}
		}

		return array_unique($errors);
	}

Modified src/include/lib/Garradin/Web/Web.php from [19b827614f] to [26f4bcaccb].

161
162
163
164
165
166
167
























168
169
170
171
172
173
174

		if (!$path) {
			return null;
		}

		return Files::getFromURI(File::CONTEXT_WEB . '/' . $path . '/' . Utils::basename($uri));
	}

























	static public function dispatchURI()
	{
		$uri = !empty($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';

		if ($pos = strpos($uri, '?')) {
			$uri = substr($uri, 0, $pos);







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







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

		if (!$path) {
			return null;
		}

		return Files::getFromURI(File::CONTEXT_WEB . '/' . $path . '/' . Utils::basename($uri));
	}

	static public function checkAllInternalLinks(): array
	{
		$sql = 'SELECT * FROM @TABLE ORDER BY title COLLATE U_NOCASE;';
		$list = [];

		foreach (EM::getInstance(Page::class)->iterate($sql) as $page) {
			if (!$page->file()) {
				continue;
			}

			$list[$page->uri] = $page;
		}

		$errors = [];

		foreach ($list as $page) {
			if (count($page->checkInternalLinks($list))) {
				$errors[] = $page;
			}
		}

		return $errors;
	}

	static public function dispatchURI()
	{
		$uri = !empty($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';

		if ($pos = strpos($uri, '?')) {
			$uri = substr($uri, 0, $pos);

Modified src/templates/web/index.tpl from [38a56e5fed] to [b9e9bbcaf2].

39
40
41
42
43
44
45












46
47
48
49
50
51
52
</nav>

{if $config.site_disabled && $session->canAccess($session::SECTION_WEB, $session::ACCESS_ADMIN)}
	<p class="block alert">
		Le site public est désactivé. <a href="{"!web/config.php"|local_url}">Activer le site dans la configuration.</a>
	</p>
{/if}













{form_errors}

{if count($categories)}
	<h2 class="ruler">Catégories</h2>
	<table class="list">
		<tbody>







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







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
</nav>

{if $config.site_disabled && $session->canAccess($session::SECTION_WEB, $session::ACCESS_ADMIN)}
	<p class="block alert">
		Le site public est désactivé. <a href="{"!web/config.php"|local_url}">Activer le site dans la configuration.</a>
	</p>
{/if}

{if count($links_errors)}
<div class="block alert">
	Des pages contiennent des liens qui mènent à des pages qui n'existent pas&nbsp;:
	<ul>
		{foreach from=$links_errors item="page"}
		<li>{link href="page.php?p=%s"|args:$page.path label=$page.title}</li>
		{/foreach}
	</ul>
</div>
{/if}


{form_errors}

{if count($categories)}
	<h2 class="ruler">Catégories</h2>
	<table class="list">
		<tbody>

Modified src/templates/web/page.tpl from [704d1904e7] to [53b7939df3].

32
33
34
35
36
37
38











39
40
41
42
43
44
45
		{foreach from=$breadcrumbs key="id" item="title"}
			<li><a href="?p={$id}">{$title}</a></li>
		{/foreach}
	</ul>
</nav>
{/if}













{if !$content}
	<p class="block alert">Cette page est vide, cliquez sur « Modifier » pour commencer à rédiger son contenu.</p>
{else}
	{$content|raw}

	{if count($images) || count($files)}







>
>
>
>
>
>
>
>
>
>
>







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
		{foreach from=$breadcrumbs key="id" item="title"}
			<li><a href="?p={$id}">{$title}</a></li>
		{/foreach}
	</ul>
</nav>
{/if}

{if count($links_errors)}
<div class="block alert">
	Cette page contient des liens qui mènent à des pages qui n'existent pas ou ont été renommées&nbsp;:
	<ul>
		{foreach from=$links_errors item="link"}
		<li>{$link}</li>
		{/foreach}
	</ul>
	Il est conseillé de modifier la page pour corriger les liens.
</div>
{/if}

{if !$content}
	<p class="block alert">Cette page est vide, cliquez sur « Modifier » pour commencer à rédiger son contenu.</p>
{else}
	{$content|raw}

	{if count($images) || count($files)}

Modified src/www/admin/web/index.php from [fbf5316a30] to [927003782d].

30
31
32
33
34
35
36


37
38
39
$title = $cat ? sprintf('Gestion du site web : %s', $cat->title) : 'Gestion du site web';
$type_page = Page::TYPE_PAGE;
$type_category = Page::TYPE_CATEGORY;
$breadcrumbs = $cat ? $cat->getBreadcrumbs() : [];

$parent = $cat ? $cat->parent : null;



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

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







>
>
|


30
31
32
33
34
35
36
37
38
39
40
41
$title = $cat ? sprintf('Gestion du site web : %s', $cat->title) : 'Gestion du site web';
$type_page = Page::TYPE_PAGE;
$type_category = Page::TYPE_CATEGORY;
$breadcrumbs = $cat ? $cat->getBreadcrumbs() : [];

$parent = $cat ? $cat->parent : null;

$links_errors = $parent ? [] : Web::checkAllInternalLinks();

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

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

Modified src/www/admin/web/page.php from [f1db880f10] to [740c4d525b].

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

namespace Garradin;

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

require_once __DIR__ . '/_inc.php';



if (!qg('p')) {
	throw new UserException('Page inconnue');
}



$page = Web::get(qg('p'));




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

if (qg('toggle_type') !== null && $session->canAccess($session::SECTION_WEB, $session::ACCESS_ADMIN)) {
	$page->toggleType();
	$page->save();
	Utils::redirect('!web/page.php?p=' . $page->path);
}

$membres = new Membres;

$tpl->assign('breadcrumbs', $page->getBreadcrumbs());

$images = $page->getImageGallery(true);
$files = $page->getAttachmentsGallery(true);

$content = $page->render(ADMIN_URL . 'web/page.php?p=');

$type_page = Page::TYPE_PAGE;
$type_category = Page::TYPE_CATEGORY;


$tpl->assign(compact('page', 'images', 'files', 'content', 'type_page', 'type_category'));

$tpl->assign('custom_js', ['wiki_gallery.js']);
$tpl->assign('custom_css', ['wiki.css', '!web/css.php']);

$tpl->display('web/page.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
<?php

namespace Garradin;

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

require_once __DIR__ . '/_inc.php';

$page = null;

if (qg('p')) {
	$page = Web::get(qg('p'));
}
elseif (qg('uri')) {
	$page = Web::getByURI(qg('uri'));
}

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

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

if (qg('toggle_type') !== null && $session->canAccess($session::SECTION_WEB, $session::ACCESS_ADMIN)) {
	$page->toggleType();
	$page->save();
	Utils::redirect('!web/page.php?p=' . $page->path);
}

$membres = new Membres;

$tpl->assign('breadcrumbs', $page->getBreadcrumbs());

$images = $page->getImageGallery(true);
$files = $page->getAttachmentsGallery(true);

$content = $page->render(ADMIN_URL . 'web/page.php?uri=');

$type_page = Page::TYPE_PAGE;
$type_category = Page::TYPE_CATEGORY;
$links_errors = $page->checkInternalLinks();

$tpl->assign(compact('page', 'images', 'files', 'content', 'type_page', 'type_category', 'links_errors'));

$tpl->assign('custom_js', ['wiki_gallery.js']);
$tpl->assign('custom_css', ['wiki.css', '!web/css.php']);

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