template rapport_dactivitees avec pdf à télécharger
@@ -1,3 +1,24 @@
|
||||
# v1.7.9
|
||||
## 03/19/2021
|
||||
|
||||
1. [](#new)
|
||||
* Added `Media::hide()` method to hide files from media
|
||||
* Added `Utils::getPathFromToken()` method which works also with `Flex Objects`
|
||||
* Added `FlexMediaTrait::getMediaField()`, which can be used to access custom media set in the blueprint fields
|
||||
* Added `FlexMediaTrait::getFieldSettings()`, which can be used to get media field settings
|
||||
1. [](#improved)
|
||||
* Method `Utils::getPagePathFromToken()` now calls the more generic `Utils::getPathFromToken()`
|
||||
* Updated `SECURITY.md` to use security@getgrav.org
|
||||
1. [](#bugfix)
|
||||
* Fixed broken media upload in `Flex` with `@self/path`, `@page` and `@theme` destinations [#3275](https://github.com/getgrav/grav/issues/3275)
|
||||
* Fixed media fields excluding newly deleted files before saving the object
|
||||
* Fixed method `$pages->find()` should never redirect [#3266](https://github.com/getgrav/grav/pull/3266)
|
||||
* Fixed `Page::activeChild()` throwing an error [#3276](https://github.com/getgrav/grav/issues/3276)
|
||||
* Fixed `Flex Page` CRUD ACL when creating a new page (needs Flex Objects plugin update) [grav-plugin-flex-objects#115](https://github.com/trilbymedia/grav-plugin-flex-objects/issues/115)
|
||||
* Fixed the list of pages not showing up in admin [#3280](https://github.com/getgrav/grav/issues/3280)
|
||||
* Fixed text field min/max validation for UTF8 characters [#3281](https://github.com/getgrav/grav/issues/3281)
|
||||
* Fixed redirects using wrong redirect code
|
||||
|
||||
# v1.7.8
|
||||
## 03/17/2021
|
||||
|
||||
|
||||
@@ -18,4 +18,4 @@ If you cannot update to the latest stable version available because, for example
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please contact contact@getgrav.org with a detailed explaination of the security issue found and we will work with you to get it resolved as fast as possible.
|
||||
Please contact security@getgrav.org with a detailed explaination of the security issue found and we will work with you to get it resolved as fast as possible.
|
||||
|
||||
@@ -381,16 +381,16 @@
|
||||
},
|
||||
{
|
||||
"name": "donatj/phpuseragentparser",
|
||||
"version": "v1.3.0",
|
||||
"version": "v1.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/donatj/PhpUserAgent.git",
|
||||
"reference": "f9a521726b2ce4c5173281ceaab5a02c05b691ef"
|
||||
"reference": "246c1cf0a44f07168c702203bf30d5f48f17bab0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/donatj/PhpUserAgent/zipball/f9a521726b2ce4c5173281ceaab5a02c05b691ef",
|
||||
"reference": "f9a521726b2ce4c5173281ceaab5a02c05b691ef",
|
||||
"url": "https://api.github.com/repos/donatj/PhpUserAgent/zipball/246c1cf0a44f07168c702203bf30d5f48f17bab0",
|
||||
"reference": "246c1cf0a44f07168c702203bf30d5f48f17bab0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -433,7 +433,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/donatj/PhpUserAgent/issues",
|
||||
"source": "https://github.com/donatj/PhpUserAgent/tree/v1.3.0"
|
||||
"source": "https://github.com/donatj/PhpUserAgent/tree/v1.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -445,7 +445,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-02-18T04:30:49+00:00"
|
||||
"time": "2021-03-16T16:25:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dragonmantank/cron-expression",
|
||||
@@ -642,16 +642,16 @@
|
||||
},
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
"version": "2.9.2",
|
||||
"version": "2.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/filp/whoops.git",
|
||||
"reference": "df7933820090489623ce0be5e85c7e693638e536"
|
||||
"reference": "6ecda5217bf048088b891f7403b262906be5a957"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/df7933820090489623ce0be5e85c7e693638e536",
|
||||
"reference": "df7933820090489623ce0be5e85c7e693638e536",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/6ecda5217bf048088b891f7403b262906be5a957",
|
||||
"reference": "6ecda5217bf048088b891f7403b262906be5a957",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -701,7 +701,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/filp/whoops/issues",
|
||||
"source": "https://github.com/filp/whoops/tree/2.9.2"
|
||||
"source": "https://github.com/filp/whoops/tree/2.10.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -709,7 +709,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-24T12:00:00+00:00"
|
||||
"time": "2021-03-16T12:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "gregwar/cache",
|
||||
@@ -4929,16 +4929,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.5.2",
|
||||
"version": "9.5.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "f661659747f2f87f9e72095bb207bceb0f151cb4"
|
||||
"reference": "27241ac75fc37ecf862b6e002bf713b6566cbe41"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f661659747f2f87f9e72095bb207bceb0f151cb4",
|
||||
"reference": "f661659747f2f87f9e72095bb207bceb0f151cb4",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/27241ac75fc37ecf862b6e002bf713b6566cbe41",
|
||||
"reference": "27241ac75fc37ecf862b6e002bf713b6566cbe41",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5016,7 +5016,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.2"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5028,7 +5028,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-02-02T14:45:58+00:00"
|
||||
"time": "2021-03-17T07:30:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-client",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '1.7.8');
|
||||
define('GRAV_VERSION', '1.7.9');
|
||||
define('GRAV_SCHEMA', '1.7.0_2020-11-20_1');
|
||||
define('GRAV_TESTING', false);
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ use function is_bool;
|
||||
use function is_float;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
use function strlen;
|
||||
|
||||
/**
|
||||
* Class Validation
|
||||
@@ -239,16 +238,20 @@ class Validation
|
||||
$value = trim($value);
|
||||
}
|
||||
|
||||
if (isset($params['min']) && strlen($value) < $params['min']) {
|
||||
$len = mb_strlen($value);
|
||||
|
||||
$min = (int)($params['min'] ?? 0);
|
||||
if ($min && $len < $min) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($params['max']) && strlen($value) > $params['max']) {
|
||||
$max = (int)($params['max'] ?? 0);
|
||||
if ($max && $len > $max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$min = $params['min'] ?? 0;
|
||||
if (isset($params['step']) && (strlen($value) - $min) % $params['step'] === 0) {
|
||||
$step = (int)($params['step'] ?? 0);
|
||||
if ($step && ($len - $min) % $step === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -271,11 +274,13 @@ class Validation
|
||||
return '';
|
||||
}
|
||||
|
||||
$value = (string)$value;
|
||||
|
||||
if (!empty($params['trim'])) {
|
||||
$value = trim($value);
|
||||
}
|
||||
|
||||
return (string) $value;
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -332,7 +337,7 @@ class Validation
|
||||
*/
|
||||
protected static function filterLower($value, array $params)
|
||||
{
|
||||
return strtolower($value);
|
||||
return mb_strtolower($value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,7 +347,7 @@ class Validation
|
||||
*/
|
||||
protected static function filterUpper($value, array $params)
|
||||
{
|
||||
return strtoupper($value);
|
||||
return mb_strtoupper($value);
|
||||
}
|
||||
|
||||
|
||||
@@ -534,7 +539,7 @@ class Validation
|
||||
*/
|
||||
protected static function filterNumber($value, array $params, array $field)
|
||||
{
|
||||
return (string)(int)$value !== (string)(float)$value ? (float) $value : (int) $value;
|
||||
return (string)(int)$value !== (string)(float)$value ? (float)$value : (int)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -522,12 +522,13 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
$tmp = $child->children()->getIndex();
|
||||
$child_count = $tmp->count();
|
||||
$count = $filters ? $tmp->filterBy($filters, true)->count() : null;
|
||||
$route = $child->getRoute();
|
||||
$payload = [
|
||||
'item-key' => basename($child->rawRoute() ?? $child->getKey()),
|
||||
'icon' => $icon,
|
||||
'title' => htmlspecialchars($child->menu()),
|
||||
'route' => [
|
||||
'display' => $child->getRoute()->toString(false) ?: '/',
|
||||
'display' => ($route ? ($route->toString(false) ?: '/') : null) ?? '',
|
||||
'raw' => $child->rawRoute(),
|
||||
],
|
||||
'modified' => $this->jsDate($child->modified()),
|
||||
|
||||
@@ -22,6 +22,7 @@ use Grav\Common\Flex\Types\Pages\Traits\PageTranslateTrait;
|
||||
use Grav\Common\Language\Language;
|
||||
use Grav\Common\Page\Interfaces\PageInterface;
|
||||
use Grav\Common\Page\Pages;
|
||||
use Grav\Common\User\Interfaces\UserInterface;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Framework\Filesystem\Filesystem;
|
||||
use Grav\Framework\Flex\FlexObject;
|
||||
@@ -321,6 +322,28 @@ class PageObject extends FlexPageObject
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserInterface $user
|
||||
* @param string $action
|
||||
* @param string $scope
|
||||
* @param bool $isMe
|
||||
* @return bool|null
|
||||
*/
|
||||
protected function isAuthorizedOverride(UserInterface $user, string $action, string $scope, bool $isMe): ?bool
|
||||
{
|
||||
// Special case: creating a new page means checking parent for its permissions.
|
||||
if ($action === 'create' && !$this->exists()) {
|
||||
$parent = $this->parent();
|
||||
if ($parent && method_exists($parent, 'isAuthorized')) {
|
||||
return $parent->isAuthorized($action, $scope, $user);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::isAuthorizedOverride($user, $action, $scope, $isMe);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $ordering
|
||||
* @return PageCollection|null
|
||||
|
||||
@@ -15,6 +15,7 @@ use Grav\Common\Grav;
|
||||
use Grav\Common\Page\Interfaces\PageCollectionInterface;
|
||||
use Grav\Common\Page\Interfaces\PageInterface;
|
||||
use Grav\Common\Page\Pages;
|
||||
use Grav\Common\Uri;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Framework\Filesystem\Filesystem;
|
||||
use RuntimeException;
|
||||
@@ -97,6 +98,7 @@ trait PageRoutableTrait
|
||||
public function activeChild(): bool
|
||||
{
|
||||
$grav = Grav::instance();
|
||||
/** @var Uri $uri */
|
||||
$uri = $grav['uri'];
|
||||
/** @var Pages $pages */
|
||||
$pages = $grav['pages'];
|
||||
|
||||
@@ -426,7 +426,7 @@ class Grav extends Container
|
||||
// Clean route for redirect
|
||||
$route = preg_replace("#^\/[\\\/]+\/#", '/', $route);
|
||||
|
||||
if (null !== $code || $code < 300 || $code > 399) {
|
||||
if ($code < 300 || $code > 399) {
|
||||
$code = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -198,6 +198,17 @@ abstract class AbstractMedia implements ExportInterface, MediaCollectionInterfac
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function hide($name)
|
||||
{
|
||||
$this->offsetUnset($name);
|
||||
|
||||
unset($this->images[$name], $this->videos[$name], $this->audios[$name], $this->files[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Medium from a file.
|
||||
*
|
||||
|
||||
@@ -2496,21 +2496,23 @@ class Page implements PageInterface
|
||||
*/
|
||||
public function activeChild()
|
||||
{
|
||||
$uri = Grav::instance()['uri'];
|
||||
$pages = Grav::instance()['pages'];
|
||||
$grav = Grav::instance();
|
||||
/** @var Uri $uri */
|
||||
$uri = $grav['uri'];
|
||||
/** @var Pages $pages */
|
||||
$pages = $grav['pages'];
|
||||
$uri_path = rtrim(urldecode($uri->path()), '/');
|
||||
$routes = Grav::instance()['pages']->routes();
|
||||
$routes = $pages->routes();
|
||||
|
||||
if (isset($routes[$uri_path])) {
|
||||
$page = $pages->find($uri->route());
|
||||
/** @var PageInterface|null $child_page */
|
||||
$child_page = $pages->find($uri->route())->parent();
|
||||
if ($child_page) {
|
||||
while (!$child_page->root()) {
|
||||
if ($this->path() === $child_page->path()) {
|
||||
return true;
|
||||
}
|
||||
$child_page = $child_page->parent();
|
||||
$child_page = $page ? $page->parent() : null;
|
||||
while ($child_page && !$child_page->root()) {
|
||||
if ($this->path() === $child_page->path()) {
|
||||
return true;
|
||||
}
|
||||
$child_page = $child_page->parent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -880,103 +880,146 @@ class Pages
|
||||
}
|
||||
|
||||
/**
|
||||
* alias method to return find a page.
|
||||
* Find a page based on route.
|
||||
*
|
||||
* @param string $route The relative URL of the page
|
||||
* @param bool $all
|
||||
* @param string $route The route of the page
|
||||
* @param bool $all If true, return also non-routable pages, otherwise return null if page isn't routable
|
||||
* @return PageInterface|null
|
||||
*/
|
||||
public function find($route, $all = false)
|
||||
{
|
||||
return $this->dispatch($route, $all, false);
|
||||
$route = urldecode((string)$route);
|
||||
|
||||
// Fetch page if there's a defined route to it.
|
||||
$path = $this->routes[$route] ?? null;
|
||||
$page = null !== $path ? $this->get($path) : null;
|
||||
|
||||
// Try without trailing slash
|
||||
if (null === $page && Utils::endsWith($route, '/')) {
|
||||
$path = $this->routes[rtrim($route, '/')] ?? null;
|
||||
$page = null !== $path ? $this->get($path) : null;
|
||||
}
|
||||
|
||||
if (!$all && !isset($this->grav['admin'])) {
|
||||
if (null === $page || !$page->routable()) {
|
||||
// If the page cannot be accessed, look for the site wide routes and wildcards.
|
||||
$page = $this->findSiteBasedRoute($route) ?? $page;
|
||||
}
|
||||
}
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check site based routes.
|
||||
*
|
||||
* @param string $route
|
||||
* @return PageInterface|null
|
||||
*/
|
||||
protected function findSiteBasedRoute($route)
|
||||
{
|
||||
/** @var Config $config */
|
||||
$config = $this->grav['config'];
|
||||
|
||||
$site_routes = $config->get('site.routes');
|
||||
if (!is_array($site_routes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$page = null;
|
||||
|
||||
// See if route matches one in the site configuration
|
||||
$site_route = $site_routes[$route] ?? null;
|
||||
if ($site_route) {
|
||||
$page = $this->find($site_route);
|
||||
} else {
|
||||
// Use reverse order because of B/C (previously matched multiple and returned the last match).
|
||||
foreach (array_reverse($site_routes, true) as $pattern => $replace) {
|
||||
$pattern = '#^' . str_replace('/', '\/', ltrim($pattern, '^')) . '#';
|
||||
try {
|
||||
$found = preg_replace($pattern, $replace, $route);
|
||||
if ($found && $found !== $route) {
|
||||
$page = $this->find($found);
|
||||
if ($page) {
|
||||
return $page;
|
||||
}
|
||||
}
|
||||
} catch (ErrorException $e) {
|
||||
$this->grav['log']->error('site.routes: ' . $pattern . '-> ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch URI to a page.
|
||||
*
|
||||
* @param string $route The relative URL of the page
|
||||
* @param bool $all
|
||||
* @param bool $redirect
|
||||
* @param bool $all If true, return also non-routable pages, otherwise return null if page isn't routable
|
||||
* @param bool $redirect If true, allow redirects
|
||||
* @return PageInterface|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dispatch($route, $all = false, $redirect = true)
|
||||
{
|
||||
$route = urldecode($route);
|
||||
$page = $this->find($route, true);
|
||||
|
||||
// Fetch page if there's a defined route to it.
|
||||
$path = $this->routes[$route] ?? null;
|
||||
$page = null !== $path ? $this->get($path) : null;
|
||||
// Try without trailing slash
|
||||
if (!$page && Utils::endsWith($route, '/')) {
|
||||
$path = $this->routes[rtrim($route, '/')] ?? null;
|
||||
$page = null !== $path ? $this->get($path) : null;
|
||||
// If we want all pages or are in admin, return what we already have.
|
||||
if ($all || isset($this->grav['admin'])) {
|
||||
return $page;
|
||||
}
|
||||
|
||||
// Are we in the admin? this is important!
|
||||
$not_admin = !isset($this->grav['admin']);
|
||||
|
||||
// If the page cannot be reached, look into site wide redirects, routes + wildcards
|
||||
if (!$all && $not_admin) {
|
||||
// If the page is a simple redirect, just do it.
|
||||
if ($redirect && $page && $page->redirect()) {
|
||||
$this->grav->redirectLangSafe($page->redirect());
|
||||
}
|
||||
|
||||
// fall back and check site based redirects
|
||||
if (!$page || !$page->routable()) {
|
||||
// Redirect to the first child (placeholder page)
|
||||
if ($redirect && $page && count($children = $page->children()->visible()->routable()->published()) > 0) {
|
||||
$this->grav->redirectLangSafe($children->first()->route());
|
||||
if ($page) {
|
||||
$routable = $page->routable();
|
||||
if ($redirect) {
|
||||
if ($page->redirect()) {
|
||||
// Follow a redirect page.
|
||||
$this->grav->redirectLangSafe($page->redirect());
|
||||
}
|
||||
|
||||
/** @var Config $config */
|
||||
$config = $this->grav['config'];
|
||||
if (!$routable && ($child = $page->children()->visible()->routable()->published()->first()) !== null) {
|
||||
// Redirect to the first visible child as current page isn't routable.
|
||||
$this->grav->redirectLangSafe($child->route());
|
||||
}
|
||||
}
|
||||
|
||||
// See if route matches one in the site configuration
|
||||
$site_route = $config->get("site.routes.{$route}");
|
||||
if ($site_route) {
|
||||
$page = $this->dispatch($site_route, $all, $redirect);
|
||||
} else {
|
||||
/** @var Uri $uri */
|
||||
$uri = $this->grav['uri'];
|
||||
/** @var \Grav\Framework\Uri\Uri $source_url */
|
||||
$source_url = $uri->uri(false);
|
||||
if ($routable) {
|
||||
return $page;
|
||||
}
|
||||
}
|
||||
|
||||
// Try Regex style redirects
|
||||
$site_redirects = $config->get('site.redirects');
|
||||
if (is_array($site_redirects)) {
|
||||
foreach ((array)$site_redirects as $pattern => $replace) {
|
||||
$pattern = ltrim($pattern, '^');
|
||||
$pattern = '#^' . str_replace('/', '\/', $pattern) . '#';
|
||||
try {
|
||||
/** @var string $found */
|
||||
$found = preg_replace($pattern, $replace, $source_url);
|
||||
if ($found && $found !== $source_url) {
|
||||
$this->grav->redirectLangSafe($found);
|
||||
}
|
||||
} catch (ErrorException $e) {
|
||||
$this->grav['log']->error('site.redirects: ' . $pattern . '-> ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try Regex style routes
|
||||
$site_routes = $config->get('site.routes');
|
||||
if (is_array($site_routes)) {
|
||||
foreach ((array)$site_routes as $pattern => $replace) {
|
||||
$pattern = '#^' . str_replace('/', '\/', ltrim($pattern, '^')) . '#';
|
||||
try {
|
||||
/** @var string $found */
|
||||
$found = preg_replace($pattern, $replace, $source_url);
|
||||
if ($found && $found !== $source_url) {
|
||||
$page = $this->dispatch($found, $all, $redirect);
|
||||
}
|
||||
} catch (ErrorException $e) {
|
||||
$this->grav['log']->error('site.routes: ' . $pattern . '-> ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
$route = urldecode((string)$route);
|
||||
|
||||
// The page cannot be reached, look into site wide redirects, routes and wildcards.
|
||||
$redirectedPage = $this->findSiteBasedRoute($route);
|
||||
if ($redirectedPage) {
|
||||
$page = $this->dispatch($redirectedPage->route(), false, $redirect);
|
||||
}
|
||||
|
||||
/** @var Config $config */
|
||||
$config = $this->grav['config'];
|
||||
|
||||
/** @var Uri $uri */
|
||||
$uri = $this->grav['uri'];
|
||||
/** @var \Grav\Framework\Uri\Uri $source_url */
|
||||
$source_url = $uri->uri(false);
|
||||
|
||||
// Try Regex style redirects
|
||||
$site_redirects = $config->get('site.redirects');
|
||||
if (is_array($site_redirects)) {
|
||||
foreach ((array)$site_redirects as $pattern => $replace) {
|
||||
$pattern = ltrim($pattern, '^');
|
||||
$pattern = '#^' . str_replace('/', '\/', $pattern) . '#';
|
||||
try {
|
||||
/** @var string $found */
|
||||
$found = preg_replace($pattern, $replace, $source_url);
|
||||
if ($found && $found !== $source_url) {
|
||||
$this->grav->redirectLangSafe($found);
|
||||
}
|
||||
} catch (ErrorException $e) {
|
||||
$this->grav['log']->error('site.redirects: ' . $pattern . '-> ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,7 +519,7 @@ class Uri
|
||||
* Return the full uri
|
||||
*
|
||||
* @param bool $include_root
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
public function uri($include_root = true)
|
||||
{
|
||||
|
||||
@@ -12,11 +12,15 @@ namespace Grav\Common;
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
use Exception;
|
||||
use Grav\Common\Flex\Types\Pages\PageObject;
|
||||
use Grav\Common\Helpers\Truncator;
|
||||
use Grav\Common\Page\Interfaces\PageInterface;
|
||||
use Grav\Common\Markdown\Parsedown;
|
||||
use Grav\Common\Markdown\ParsedownExtra;
|
||||
use Grav\Common\Page\Markdown\Excerpts;
|
||||
use Grav\Common\Page\Pages;
|
||||
use Grav\Framework\Flex\Flex;
|
||||
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
|
||||
use InvalidArgumentException;
|
||||
use Negotiation\Accept;
|
||||
use Negotiation\Negotiator;
|
||||
@@ -1520,7 +1524,7 @@ abstract class Utils
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path based on a token
|
||||
* Get relative page path based on a token.
|
||||
*
|
||||
* @param string $path
|
||||
* @param PageInterface|null $page
|
||||
@@ -1529,47 +1533,122 @@ abstract class Utils
|
||||
*/
|
||||
public static function getPagePathFromToken($path, PageInterface $page = null)
|
||||
{
|
||||
$path_parts = pathinfo($path);
|
||||
$grav = Grav::instance();
|
||||
return static::getPathFromToken($path, $page);
|
||||
}
|
||||
|
||||
$basename = '';
|
||||
if (isset($path_parts['extension'])) {
|
||||
$basename = '/' . $path_parts['basename'];
|
||||
$path = rtrim($path_parts['dirname'], ':');
|
||||
/**
|
||||
* Get relative path based on a token.
|
||||
*
|
||||
* Path supports following syntaxes:
|
||||
*
|
||||
* 'self@', 'self@/path'
|
||||
* 'page@:/route', 'page@:/route/filename.ext'
|
||||
* 'theme@:', 'theme@:/path'
|
||||
*
|
||||
* @param string $path
|
||||
* @param FlexObjectInterface|PageInterface|null $object
|
||||
* @return string
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public static function getPathFromToken($path, $object = null)
|
||||
{
|
||||
$matches = static::resolveTokenPath($path);
|
||||
if (null === $matches) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
$regex = '/(@self|self@)|((?:@page|page@):(?:.*))|((?:@theme|theme@):(?:.*))/';
|
||||
preg_match($regex, $path, $matches);
|
||||
$grav = Grav::instance();
|
||||
|
||||
if ($matches) {
|
||||
if ($matches[1]) {
|
||||
if (null === $page) {
|
||||
throw new RuntimeException('Page not available for this self@ reference');
|
||||
switch ($matches[0]) {
|
||||
case 'self':
|
||||
if (null === $object) {
|
||||
throw new RuntimeException(sprintf('Page not available for self@ reference: %s', $path));
|
||||
}
|
||||
} elseif ($matches[2]) {
|
||||
// page@
|
||||
$parts = explode(':', $path);
|
||||
$route = $parts[1];
|
||||
$page = $grav['page']->find($route);
|
||||
} elseif ($matches[3]) {
|
||||
// theme@
|
||||
$parts = explode(':', $path);
|
||||
$route = $parts[1];
|
||||
$theme = str_replace(ROOT_DIR, '', $grav['locator']->findResource('theme://'));
|
||||
|
||||
return $theme . $route . $basename;
|
||||
if ($matches[2] === '') {
|
||||
if ($object->exists()) {
|
||||
$route = '/' . $matches[1];
|
||||
|
||||
if ($object instanceof PageInterface) {
|
||||
return trim($object->relativePagePath() . $route, '/');
|
||||
}
|
||||
|
||||
$folder = $object->getMediaFolder();
|
||||
if ($folder) {
|
||||
return trim($folder . $route, '/');
|
||||
}
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 'page':
|
||||
if ($matches[1] === '') {
|
||||
$route = '/' . $matches[2];
|
||||
|
||||
// Exclude filename from the page lookup.
|
||||
if (pathinfo($route, PATHINFO_EXTENSION)) {
|
||||
$basename = '/' . basename($route);
|
||||
$route = \dirname($route);
|
||||
} else {
|
||||
$basename = '';
|
||||
}
|
||||
|
||||
$key = trim($route === '/' ? $grav['config']->get('system.home.alias') : $route, '/');
|
||||
if ($object instanceof PageObject) {
|
||||
$object = $object->getFlexDirectory()->getObject($key);
|
||||
} elseif (static::isAdminPlugin()) {
|
||||
/** @var Flex|null $flex */
|
||||
$flex = $grav['flex'] ?? null;
|
||||
$object = $flex ? $flex->getObject($key, 'pages') : null;
|
||||
} else {
|
||||
/** @var Pages $pages */
|
||||
$pages = $grav['pages'];
|
||||
$object = $pages->find($route);
|
||||
}
|
||||
|
||||
if ($object instanceof PageInterface) {
|
||||
return trim($object->relativePagePath() . $basename, '/');
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 'theme':
|
||||
if ($matches[1] === '') {
|
||||
$route = '/' . $matches[2];
|
||||
$theme = $grav['locator']->findResource('theme://', false);
|
||||
if (false !== $theme) {
|
||||
return trim($theme . $route, '/');
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('Token path not found: %s', $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [token, route, path] from '@token/route:/path'. Route and path are optional. If pattern does not match, return null.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string[]|null
|
||||
*/
|
||||
private static function resolveTokenPath(string $path): ?array
|
||||
{
|
||||
if (strpos($path, '@') !== false) {
|
||||
$regex = '/^(@\w+|\w+@|@\w+@)([^:]*)(.*)$/u';
|
||||
if (preg_match($regex, $path, $matches)) {
|
||||
return [
|
||||
trim($matches[1], '@'),
|
||||
trim($matches[2], '/'),
|
||||
trim($matches[3], ':/')
|
||||
];
|
||||
}
|
||||
} else {
|
||||
return $path . $basename;
|
||||
}
|
||||
|
||||
if (!$page) {
|
||||
throw new RuntimeException('Page route not found: ' . $path);
|
||||
}
|
||||
|
||||
$path = str_replace($matches[0], rtrim($page->relativePagePath(), '/'), $path);
|
||||
|
||||
return $path . $basename;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -420,9 +420,11 @@ trait PageRoutableTrait
|
||||
return $this->_parentCache;
|
||||
}
|
||||
|
||||
// Use filesystem as \dirname() does not work in Windows because of '/foo' becomes '\'.
|
||||
$filesystem = Filesystem::getInstance(false);
|
||||
$directory = $this->getFlexDirectory();
|
||||
$parentKey = ltrim(dirname("/{$this->getKey()}"), '/');
|
||||
if ($parentKey) {
|
||||
$parentKey = ltrim($filesystem->dirname("/{$this->getKey()}"), '/');
|
||||
if ('' !== $parentKey) {
|
||||
$parent = $directory->getObject($parentKey);
|
||||
$language = $this->getLanguage();
|
||||
if ($language && $parent && method_exists($parent, 'getTranslation')) {
|
||||
@@ -433,7 +435,7 @@ trait PageRoutableTrait
|
||||
} else {
|
||||
$index = $directory->getIndex();
|
||||
|
||||
$this->_parentCache = method_exists($index, 'getRoot') ? $index->getRoot() : null;
|
||||
$this->_parentCache = \is_callable([$index, 'getRoot']) ? $index->getRoot() : null;
|
||||
}
|
||||
|
||||
return $this->_parentCache;
|
||||
@@ -497,22 +499,22 @@ trait PageRoutableTrait
|
||||
public function activeChild(): bool
|
||||
{
|
||||
$grav = Grav::instance();
|
||||
/** @var Uri $uri */
|
||||
$uri = $grav['uri'];
|
||||
/** @var Pages $pages */
|
||||
$pages = $grav['pages'];
|
||||
$uri_path = rtrim(urldecode($uri->path()), '/');
|
||||
$routes = $pages->routes();
|
||||
|
||||
if (isset($routes[$uri_path])) {
|
||||
/** @var PageInterface $child_page|null */
|
||||
$child_page = $pages->find($uri->route())->parent();
|
||||
if (null !== $child_page) {
|
||||
while (!$child_page->root()) {
|
||||
if ($this->path() === $child_page->path()) {
|
||||
return true;
|
||||
}
|
||||
/** @var PageInterface $child_page|null */
|
||||
$child_page = $child_page->parent();
|
||||
$page = $pages->find($uri->route());
|
||||
/** @var PageInterface|null $child_page */
|
||||
$child_page = $page ? $page->parent() : null;
|
||||
while ($child_page && !$child_page->root()) {
|
||||
if ($this->path() === $child_page->path()) {
|
||||
return true;
|
||||
}
|
||||
$child_page = $child_page->parent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,10 @@ use Grav\Common\Grav;
|
||||
use Grav\Common\Media\Interfaces\MediaCollectionInterface;
|
||||
use Grav\Common\Media\Interfaces\MediaUploadInterface;
|
||||
use Grav\Common\Media\Traits\MediaTrait;
|
||||
use Grav\Common\Page\Media;
|
||||
use Grav\Common\Page\Medium\Medium;
|
||||
use Grav\Common\Page\Medium\MediumFactory;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Framework\Cache\CacheInterface;
|
||||
use Grav\Framework\Filesystem\Filesystem;
|
||||
use Grav\Framework\Flex\FlexDirectory;
|
||||
@@ -23,6 +25,7 @@ use Grav\Framework\Form\FormFlashFile;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
use RuntimeException;
|
||||
use function array_key_exists;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
use function is_callable;
|
||||
@@ -75,11 +78,40 @@ trait FlexMediaTrait
|
||||
return $media;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @return MediaCollectionInterface|null
|
||||
*/
|
||||
public function getMediaField(string $field): ?MediaCollectionInterface
|
||||
{
|
||||
// Field specific media.
|
||||
$settings = $this->getFieldSettings($field);
|
||||
if (!empty($settings['media_field'])) {
|
||||
$var = 'destination';
|
||||
} elseif (!empty($settings['media_picker_field'])) {
|
||||
$var = 'folder';
|
||||
}
|
||||
|
||||
if (empty($var)) {
|
||||
// Not a media field.
|
||||
$media = null;
|
||||
} elseif ($settings['self']) {
|
||||
// Uses main media.
|
||||
$media = $this->getMedia();
|
||||
} else {
|
||||
// Uses custom media.
|
||||
$media = new Media($settings[$var]);
|
||||
$this->addUpdatedMedia($media);
|
||||
}
|
||||
|
||||
return $media;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @return array|null
|
||||
*/
|
||||
protected function getFieldSettings(string $field): ?array
|
||||
public function getFieldSettings(string $field): ?array
|
||||
{
|
||||
if ($field === '') {
|
||||
return null;
|
||||
@@ -88,14 +120,32 @@ trait FlexMediaTrait
|
||||
// Load settings for the field.
|
||||
$schema = $this->getBlueprint()->schema();
|
||||
$settings = $field && is_object($schema) ? (array)$schema->getProperty($field) : null;
|
||||
if (!isset($settings) || !is_array($settings)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isset($settings['type']) && (in_array($settings['type'], ['avatar', 'file', 'pagemedia']) || !empty($settings['destination']))) {
|
||||
// Set destination folder.
|
||||
$type = $settings['type'] ?? '';
|
||||
|
||||
// Media field.
|
||||
if (!empty($settings['media_field']) || array_key_exists('destination', $settings) || in_array($type, ['avatar', 'file', 'pagemedia'], true)) {
|
||||
$settings['media_field'] = true;
|
||||
if (empty($settings['destination']) || in_array($settings['destination'], ['@self', 'self@', '@self@'], true)) {
|
||||
$settings['destination'] = $this->getMediaFolder();
|
||||
$var = 'destination';
|
||||
}
|
||||
|
||||
// Media picker field.
|
||||
if (!empty($settings['media_picker_field']) || in_array($type, ['filepicker', 'pagemediaselect'], true)) {
|
||||
$settings['media_picker_field'] = true;
|
||||
$var = 'folder';
|
||||
}
|
||||
|
||||
// Set media folder for media fields.
|
||||
if (isset($var)) {
|
||||
$folder = $settings[$var] ?? '';
|
||||
if (in_array(rtrim($folder, '/'), ['', '@self', 'self@', '@self@'], true)) {
|
||||
$settings[$var] = $this->getMediaFolder();
|
||||
$settings['self'] = true;
|
||||
} else {
|
||||
$settings[$var] = Utils::getPathFromToken($folder, $this);
|
||||
$settings['self'] = false;
|
||||
}
|
||||
}
|
||||
@@ -115,7 +165,6 @@ trait FlexMediaTrait
|
||||
return $settings + ['accept' => '*', 'limit' => 1000, 'self' => true];
|
||||
}
|
||||
|
||||
|
||||
protected function getMediaFields(): array
|
||||
{
|
||||
// Load settings for the field.
|
||||
@@ -206,12 +255,13 @@ trait FlexMediaTrait
|
||||
*/
|
||||
public function uploadMediaFile(UploadedFileInterface $uploadedFile, string $filename = null, string $field = null): void
|
||||
{
|
||||
$media = $this->getMedia();
|
||||
$settings = $this->getMediaFieldSettings($field ?? '');
|
||||
|
||||
$media = $field ? $this->getMediaField($field) : $this->getMedia();
|
||||
if (!$media instanceof MediaUploadInterface) {
|
||||
throw new RuntimeException("Media for {$this->getFlexDirectory()->getFlexType()} doesn't support file uploads.");
|
||||
}
|
||||
|
||||
$settings = $this->getMediaFieldSettings($field ?? '');
|
||||
$filename = $media->checkUploadedFile($uploadedFile, $filename, $settings);
|
||||
$media->copyUploadedFile($uploadedFile, $filename, $settings);
|
||||
$this->clearMediaCache();
|
||||
@@ -322,13 +372,20 @@ trait FlexMediaTrait
|
||||
foreach ($this->getUpdatedMedia() as $filename => $upload) {
|
||||
if (is_array($upload)) {
|
||||
// Uses new format with [UploadedFileInterface, array].
|
||||
$upload = $upload[0];
|
||||
$settings = $upload[1];
|
||||
if ($settings['destination'] === $media->getPath()) {
|
||||
$upload = $upload[0];
|
||||
} else {
|
||||
$upload = false;
|
||||
}
|
||||
}
|
||||
if ($upload) {
|
||||
$medium = MediumFactory::fromUploadedFile($upload);
|
||||
if (false !== $upload) {
|
||||
$medium = $upload ? MediumFactory::fromUploadedFile($upload) : null;
|
||||
$updated = true;
|
||||
if ($medium) {
|
||||
$updated = true;
|
||||
$media->add($filename, $medium);
|
||||
} else {
|
||||
$media->hide($filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -356,7 +413,6 @@ trait FlexMediaTrait
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Upload/delete altered files.
|
||||
/**
|
||||
* @var string $filename
|
||||
|
||||
@@ -42,4 +42,3 @@ form:
|
||||
.portrait:
|
||||
type: filepicker
|
||||
label: Portrait
|
||||
folder: 'user/pages/01.home/04._gouvernance'
|
||||
|
||||
@@ -41,4 +41,3 @@ form:
|
||||
name: logo_du_programme
|
||||
type: filepicker
|
||||
label: Logo
|
||||
folder: 'user/pages/01.home/02._programmes'
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
title: Rapport d'activitées
|
||||
'@extends': default
|
||||
|
||||
form:
|
||||
fields:
|
||||
tabs:
|
||||
fields:
|
||||
advanced:
|
||||
fields:
|
||||
columns:
|
||||
fields:
|
||||
column1:
|
||||
fields:
|
||||
name:
|
||||
default: modular/rapport_dactivitees
|
||||
'@data-options': '\Grav\Common\Page\Pages::modularTypes'
|
||||
overrides:
|
||||
fields:
|
||||
header.template:
|
||||
default: modular/rapport_dactivitees
|
||||
'@data-options': '\Grav\Common\Page\Pages::modularTypes'
|
||||
rapports:
|
||||
type: tab
|
||||
title: Rapports d'activitées
|
||||
fields:
|
||||
header.rapports:
|
||||
name: rapports
|
||||
type: list
|
||||
label: Rapports d'activitées
|
||||
|
||||
fields:
|
||||
.titre_du_rapport:
|
||||
type: text
|
||||
label: Titre du rapport
|
||||
.texte_de_presentation:
|
||||
type: markdown
|
||||
label: Texte de présentation du rapport
|
||||
validate:
|
||||
type: textarea
|
||||
.couverture:
|
||||
name: couv_du_rapport
|
||||
type: filepicker
|
||||
label: Image de couverture
|
||||
.pdf:
|
||||
type: filepicker
|
||||
label: pdf à télécharger
|
||||
accept:
|
||||
- .pdf
|
||||
@@ -1,7 +1,7 @@
|
||||
title: 'GIP EPAU'
|
||||
default_lang: fr
|
||||
author:
|
||||
name: 'Ouidade Soussi'
|
||||
name: 'Ouidade Soussi Chiadmi'
|
||||
email: ouidade@figureslibres.io
|
||||
taxonomies:
|
||||
- category
|
||||
|
||||
@@ -96,7 +96,7 @@ pages:
|
||||
cache:
|
||||
enabled: true
|
||||
check:
|
||||
method: file
|
||||
method: hash
|
||||
driver: auto
|
||||
prefix: g
|
||||
purge_at: '0 4 * * *'
|
||||
|
||||
|
After Width: | Height: | Size: 56 KiB |
@@ -17,10 +17,10 @@ programmes:
|
||||
-
|
||||
nom_du_programme: Coubertin
|
||||
texte_de_presentation: 'Le programme de recherche-action Coubertin construit le récit, au fil de l’eau, de la conception des ouvrages et des opérations d’aménagement des Jeux Olympiques et Paralympiques de Paris 2024. À travers une observation embarquée au sein de la SOLIDEO, l’équipe de chercheurs analyse la production architecturale et urbaine et sa capacité à transformer les pratiques d’aménagement.'
|
||||
logo: null
|
||||
logo: logo_coubertin.png
|
||||
visible: true
|
||||
debugger: true
|
||||
media_order: 'popsu.png,forum_solution.png,europan_france.jpg'
|
||||
media_order: 'popsu.png,forum_solution.png,europan_france.jpg,logo_coubertin.png'
|
||||
process:
|
||||
markdown: true
|
||||
twig: false
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: 'Rapports d''activitées'
|
||||
body_classes: modular
|
||||
media_order: 'images.jpeg,190410_events2event.pdf'
|
||||
visible: true
|
||||
debugger: true
|
||||
rapports:
|
||||
-
|
||||
titre_du_rapport: 'rapport d''activitées POPSU 2019'
|
||||
texte_de_presentation: "#### # ozMIHEFMJBZNDKCJbnW NX;, \r\noipouepuoaiejhrglnk\r\n_loremnksjdqs _\r\n"
|
||||
couverture: images.jpeg
|
||||
pdf: 190410_events2event.pdf
|
||||
template: modular/rapport_dactivitees
|
||||
process:
|
||||
markdown: true
|
||||
twig: false
|
||||
---
|
||||
|
||||
### Rapports d’activitées
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
title: 'Rapports d''activités'
|
||||
body_classes: modular
|
||||
media_order: images.jpeg
|
||||
visible: true
|
||||
debugger: true
|
||||
---
|
||||
|
||||
### Rapports d’activités de l’Europe des projets architecturaux et urbains
|
||||
|
||||
|
||||
[Lien pour télécharger]()
|
||||
![]images.jpeg(http://)+ images couv
|
||||
@@ -10,6 +10,7 @@ personnes:
|
||||
portrait: photo_butlen.jpeg
|
||||
debugger: true
|
||||
template: modular/personnes
|
||||
media_order: photo_butlen.jpeg
|
||||
---
|
||||
|
||||
### Membres du conseil d'administration
|
||||
|
||||
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
@@ -12,6 +12,7 @@ personnes:
|
||||
fonction: 'Président de l’Association Europan France'
|
||||
biographie: "Né le 23 avril 1943 à Nérac (Lot-et-Garonne), Alain Maugard est un ancien élève de l’École polytechnique et Ingénieur général des Ponts et Chaussées. Il débute sa carrière au ministère de l’Équipement au service des Affaires économiques et internationales et dans les services urbanisme construction des Directions Départementales. Chef du service de la politique technique à la direction de la Construction et secrétaire permanent du Plan Construction, de 1978 à 1981, il devient successivement directeur adjoint de cabinet des ministres de l’Urbanisme et du Logement Roger Quilliot et Paul Quilès puis directeur de la Construction au ministère de l’Équipement, du Logement, des Transports et de la Mer. En 1990, il est nommé directeur général de l’Établissement public d’aménagement de la Défense (epad), jusqu’en 1993 où il prend la présidence du cstb. Il quitte ces fonctions en 2008 pour rejoindre le Conseil général de l’environnement et du développement durable où il assure la présidence de la section « risques, sécurité, sûreté ». En septembre 2009, il accède à la présidence de Qualibat. \r\nEn outre, Alain Maugard est membre du conseil d’administration de l’Ademe. Il a également piloté le Comité opérationnel (comop) du chantier n°1 « Bâtiments neufs publics et privés » du Grenelle de l’Environnement. \r\n\r\nBibliographie\_:\r\n- Regards sur le bâtiment — Le futur en construction, éditions Le Moniteur, 2006\r\n - Regard sur la ville durable, Alain Maugard et Jean-Pierre Cuisinier, CSTB, mars 2010\r\n - Le BEPOS pour tous (livre électronique), http://outils.xpair.com/livre/bepos-pourtous/7.htm (25 juin 2015) \r\n"
|
||||
portrait: 'Alain Maugard_TROUVE.jpg'
|
||||
media_order: 'Alain Maugard_TROUVE.jpg'
|
||||
---
|
||||
|
||||
## Équipe EPAU
|
||||
|
||||
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 162 KiB |
|
Before Width: | Height: | Size: 97 KiB |
@@ -15,7 +15,6 @@ content:
|
||||
admin:
|
||||
children_display_order: collection
|
||||
debugger: true
|
||||
media_order: '1612260288596.jpg,Alain Maugard_TROUVE.jpg,aurelie-cousi-nommee-aux-fonctions-de-directrice.jpg,catherine-chevillot-nouvelle-presidente-de-cite.JPG,photo_butlen.jpeg'
|
||||
---
|
||||
|
||||
# Gouvernance
|
||||
|
||||
@@ -11,7 +11,7 @@ content:
|
||||
custom:
|
||||
- _accueil
|
||||
- _programmes
|
||||
- _rapports-dactivites
|
||||
- _rapports-dactivitees
|
||||
- _gouvernance
|
||||
- _contact
|
||||
media_order: 'jeux-olypiques-paris-2024-village-athle-lot-e2.jpg,Logotype_GIP_EPAU.svg.png'
|
||||
|
||||
@@ -3,12 +3,7 @@
|
||||
<div class="feature-items">
|
||||
{% for personne in page.header.personnes %}
|
||||
<div class="feature">
|
||||
{% if personne.icon %}
|
||||
<i class="fa fa-fw fa-{{ personne.icon }}"></i>
|
||||
<div class="feature-content icon-offset">
|
||||
{% else %}
|
||||
<div class="feature-content">
|
||||
{% endif %}
|
||||
|
||||
{% if personne.nom %}
|
||||
<h5>{{ personne.nom }}</h5>
|
||||
{% endif %}
|
||||
@@ -16,11 +11,13 @@
|
||||
<h6>{{ personne.fonction }}</h6>
|
||||
{% endif %}
|
||||
{% if personne.biographie %}
|
||||
<p>{{ personne.biographie }}</p>
|
||||
<p>{{ personne.biographie|markdown }}</p>
|
||||
{% endif %}
|
||||
{% if personne.portrait %}
|
||||
<img src="/user/pages/01.home/04._gouvernance/{{personne.portrait}}" alt="portrait de {{personne.nom}}" />
|
||||
<img src="{{page.media[personne.portrait].url|e }}" alt="portrait de {{personne.nom}}" />
|
||||
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
@@ -3,17 +3,18 @@
|
||||
|
||||
<div class="">
|
||||
{% for programme in page.header.programmes %}
|
||||
|
||||
<div class="">
|
||||
<div class="">
|
||||
{% if programme.nom_du_programme %}
|
||||
<h4>{{ programme.nom_du_programme }}</h4>
|
||||
{% endif %}
|
||||
{% if programme.texte_de_presentation %}
|
||||
<p>{{ programme.texte_de_presentation }}</p>
|
||||
<p>{{ programme.texte_de_presentation|markdown }}</p>
|
||||
{% endif %}
|
||||
{% if programme.logo %}
|
||||
<img src="/user/pages/01.home/02._programmes/{{programme.logo}} " alt="logo du programme {{programme.nom_du_programme}}" />
|
||||
{{ dump(programme.logo) }}
|
||||
<img src="{{page.media[programme.logo].url|e }}" alt="logo du programme {{programme.nom_du_programme}}" />
|
||||
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<div class="modular-row {{ page.header.class}}">
|
||||
{{ content|raw }}
|
||||
|
||||
<div class="">
|
||||
{% for rapport in page.header.rapports %}
|
||||
|
||||
<div class="">
|
||||
<div class="">
|
||||
{% if rapport.titre_du_rapport %}
|
||||
<h4>{{ rapport.titre_du_rapport }}</h4>
|
||||
{% endif %}
|
||||
{% if rapport.texte_de_presentation %}
|
||||
<p>{{ rapport.texte_de_presentation|markdown }}</p>
|
||||
{% endif %}
|
||||
{% if rapport.couverture and rapport.pdf %}
|
||||
<a href="{{page.media[rapport.pdf].url|e }}" {{rapport.titre_du_rapport}}>
|
||||
<img src="{{page.media[rapport.couverture].url|e }}" alt="couverture du {{rapport.titre_du_rapport}}" />
|
||||
</a>
|
||||
{% endif %}
|
||||
{{ dump(rapport)}}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||