Compare commits
2 Commits
2fdf78ccef
...
6ad6bb4cdd
Author | SHA1 | Date | |
---|---|---|---|
|
6ad6bb4cdd | ||
|
2aac4c0638 |
@ -1,3 +1,25 @@
|
||||
# v4.0.4
|
||||
## 07/10/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fix for email file attachments using stream
|
||||
|
||||
# v4.0.3
|
||||
## 06/29/2023
|
||||
|
||||
1. [](#improved)
|
||||
* Simplified the `Email::processRecipients()` logic for readability
|
||||
1. [](#bugfix)
|
||||
* Fix an issue with 2 email addresses provided with 'just' email and no name [#176](https://github.com/getgrav/grav-plugin-email/issues/176)
|
||||
* Fix for blank subjectlines when using `Message::setSubject()` in Twig templates [getgrav/grav-plugin-login#299](https://github.com/getgrav/grav-plugin-login/issues/299)
|
||||
|
||||
# v4.0.2
|
||||
## 06/27/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* some recipient handling improvements. e.g. missing `bcc_name` throwing error
|
||||
* Allow overriding of defaults with a form configuration. Use `null` to remove default email configuration
|
||||
|
||||
# v4.0.1
|
||||
## 05/20/2023
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
name: Email
|
||||
slug: email
|
||||
type: plugin
|
||||
version: 4.0.1
|
||||
version: 4.0.4
|
||||
testing: false
|
||||
description: Enables the emailing system for Grav
|
||||
icon: envelope
|
||||
|
@ -138,8 +138,9 @@ class Email
|
||||
$email = $message->getEmail();
|
||||
|
||||
// Extend parameters with defaults.
|
||||
$params += [
|
||||
$defaults = [
|
||||
'bcc' => $config->get('plugins.email.bcc', []),
|
||||
'bcc_name' => $config->get('plugins.email.bcc_name'),
|
||||
'body' => $config->get('plugins.email.body', '{% include "forms/data.html.twig" %}'),
|
||||
'cc' => $config->get('plugins.email.cc', []),
|
||||
'cc_name' => $config->get('plugins.email.cc_name'),
|
||||
@ -157,6 +158,12 @@ class Email
|
||||
'message' => $message
|
||||
];
|
||||
|
||||
foreach ($defaults as $key => $value) {
|
||||
if (!key_exists($key, $params)) {
|
||||
$params[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$params['to']) {
|
||||
throw new \RuntimeException($language->translate('PLUGIN_EMAIL.PLEASE_CONFIGURE_A_TO_ADDRESS'));
|
||||
}
|
||||
@ -237,38 +244,39 @@ class Email
|
||||
*/
|
||||
protected function processRecipients(string $type, array $params): array
|
||||
{
|
||||
if (array_key_exists($type, $params) && $params[$type] === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$recipients = $params[$type] ?? Grav::instance()['config']->get('plugins.email.'.$type) ?? [];
|
||||
|
||||
$list = [];
|
||||
|
||||
if (!empty($recipients)) {
|
||||
if (is_array($recipients) && Utils::isAssoc($recipients)) {
|
||||
$list[] = $this->createAddress($recipients);
|
||||
if (is_array($recipients)) {
|
||||
if (Utils::isAssoc($recipients) || (count($recipients) ===2 && $this->isValidEmail($recipients[0]) && !$this->isValidEmail($recipients[1]))) {
|
||||
$list[] = $this->createAddress($recipients);
|
||||
} else {
|
||||
foreach ($recipients as $recipient) {
|
||||
$list[] = $this->createAddress($recipient);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (is_array($recipients)) {
|
||||
if (count($recipients) ===2 && $this->isValidEmail($recipients[0]) && is_string($recipients[1])) {
|
||||
$list[] = $this->createAddress($recipients);
|
||||
} else {
|
||||
foreach ($recipients as $recipient) {
|
||||
$list[] = $this->createAddress($recipient);
|
||||
}
|
||||
if (is_string($recipients) && Utils::contains($recipients, ',')) {
|
||||
$recipients = array_map('trim', explode(',', $recipients));
|
||||
foreach ($recipients as $recipient) {
|
||||
$list[] = $this->createAddress($recipient);
|
||||
}
|
||||
} else {
|
||||
if (is_string($recipients) && Utils::contains($recipients, ',')) {
|
||||
$recipients = array_map('trim', explode(',', $recipients));
|
||||
foreach ($recipients as $recipient) {
|
||||
$list[] = $this->createAddress($recipient);
|
||||
}
|
||||
} else {
|
||||
if (!Utils::contains($recipients, ['<','>']) && ($params[$type."_name"])) {
|
||||
$recipients = [$recipients, $params[$type."_name"]];
|
||||
}
|
||||
$list[] = $this->createAddress($recipients);
|
||||
if (!Utils::contains($recipients, ['<','>']) && (isset($params[$type."_name"]))) {
|
||||
$recipients = [$recipients, $params[$type."_name"]];
|
||||
}
|
||||
$list[] = $this->createAddress($recipients);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,12 @@ class Message
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setSubject($subject): self
|
||||
{
|
||||
$this->subject($subject);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function to($to): self
|
||||
{
|
||||
$this->email->to($to);
|
||||
|
@ -125,6 +125,7 @@ class EmailPlugin extends Plugin
|
||||
{
|
||||
// Build message
|
||||
$message = $this->email->buildMessage($params, $vars);
|
||||
$locator = $this->grav['locator'];
|
||||
|
||||
if (isset($params['attachments'])) {
|
||||
$filesToAttach = (array)$params['attachments'];
|
||||
@ -135,9 +136,11 @@ class EmailPlugin extends Plugin
|
||||
if (isset($fileValues['file'])) {
|
||||
$filename = $fileValues['file'];
|
||||
} else {
|
||||
$filename = ROOT_DIR . $fileValues['path'];
|
||||
$filename = $fileValues['path'];
|
||||
}
|
||||
|
||||
$filename = $locator->findResource($filename, true, true);
|
||||
|
||||
try {
|
||||
$message->attachFromPath($filename);
|
||||
} catch (\Exception $e) {
|
||||
|
@ -78,6 +78,7 @@ fr:
|
||||
PLUGIN_EMAIL:
|
||||
MAIL_ENGINE: "Moteur de messagerie"
|
||||
MAIL_ENGINE_DISABLED: "Désactivé"
|
||||
MAIL_ENGINE_DESC: "NOTE : Si vous sélectionnez un moteur fourni par un autre plugin, vous devez configurer les options dans ce même plugin."
|
||||
CONTENT_TYPE: "Type de contenu"
|
||||
CONTENT_TYPE_PLAIN_TEXT: "Texte brut"
|
||||
CHARSET: "Jeu de caractères"
|
||||
@ -130,7 +131,9 @@ fr:
|
||||
QUEUE_FLUSH_MSG_LIMIT: "Messages par Flush"
|
||||
QUEUE_FLUSH_MSG_LIMIT_APPEND: "Messages"
|
||||
QUEUE_FLUSH_TIME_LIMIT: "Délai de Flush"
|
||||
QUEUE_FLUSH_TIME_LIMIT_APPEND: "Seconds"
|
||||
QUEUE_FLUSH_TIME_LIMIT_APPEND: "Secondes"
|
||||
EMAIL_FORMAT: "Utilisez le format `addr` : `email@adresse.org` ou le format `name-addr` : `Votre nom <email@adresse.org>`. Séparer par des virgules pour plusieurs adresses."
|
||||
|
||||
|
||||
hr:
|
||||
PLUGIN_EMAIL:
|
||||
|
@ -1,3 +1,11 @@
|
||||
# v7.2.1
|
||||
## 06/27/2023
|
||||
|
||||
1. [](#improved)
|
||||
* Added some optional debug output to help isolate form loading problems
|
||||
1. [](#bugfix)
|
||||
* More robust fix for multi-language form caching
|
||||
|
||||
# v7.2.0
|
||||
## 06/21/2023
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
name: Form
|
||||
slug: form
|
||||
type: plugin
|
||||
version: 7.2.0
|
||||
version: 7.2.1
|
||||
description: Enables forms handling and processing
|
||||
icon: check-square
|
||||
author:
|
||||
@ -34,6 +34,17 @@ form:
|
||||
title: PLUGIN_FORM.GENERAL
|
||||
|
||||
fields:
|
||||
debug:
|
||||
type: toggle
|
||||
label: Debug
|
||||
highlight: 1
|
||||
default: 0
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
built_in_css:
|
||||
type: toggle
|
||||
label: PLUGIN_FORM.USE_BUILT_IN_CSS
|
||||
|
@ -26,6 +26,7 @@ use Grav\Plugin\Form\Form;
|
||||
use Grav\Plugin\Form\Forms;
|
||||
use Grav\Plugin\Form\TwigExtension;
|
||||
use Grav\Common\HTTP\Client;
|
||||
use Monolog\Logger;
|
||||
use ReCaptcha\ReCaptcha;
|
||||
use ReCaptcha\RequestMethod\CurlPost;
|
||||
use RecursiveArrayIterator;
|
||||
@ -66,6 +67,7 @@ class FormPlugin extends Plugin
|
||||
/** @var array */
|
||||
protected $json_response = [];
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
@ -147,6 +149,8 @@ class FormPlugin extends Plugin
|
||||
'onTwigSiteVariables' => ['onTwigVariables', 0],
|
||||
'onFormValidationProcessed' => ['onFormValidationProcessed', 0],
|
||||
]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,9 +228,8 @@ class FormPlugin extends Plugin
|
||||
/** @var PageInterface $page */
|
||||
$page = $this->grav['page'];
|
||||
|
||||
// Force rebuild form when form has not been built and form cache expired.
|
||||
// This happens when form cache expires before the page cache
|
||||
// and then does not trigger 'onPageProcessed' event.
|
||||
|
||||
// DEPRECATED: This should no longer ever happen
|
||||
if (!$this->forms) {
|
||||
$this->onPageProcessed(new Event(['page' => $page]));
|
||||
}
|
||||
@ -311,9 +314,11 @@ class FormPlugin extends Plugin
|
||||
/** @var Forms $forms */
|
||||
$forms = $this->grav['forms'];
|
||||
|
||||
$lang = $this->grav['language']->getLanguage();
|
||||
|
||||
/** @var Route $route */
|
||||
$route = $this->grav['route'];
|
||||
$pageForms = $this->forms[$route->getRoute()] ?? [];
|
||||
$pageForms = $this->forms[$lang][$route->getRoute()] ?? [];
|
||||
|
||||
/**
|
||||
* @var string $name
|
||||
@ -828,10 +833,11 @@ class FormPlugin extends Plugin
|
||||
public function addFormDefinition(PageInterface $page, string $name, array $form): void
|
||||
{
|
||||
$route = ($page->home() ? '/' : $page->route()) ?? '/';
|
||||
$lang = $this->grav['language']->getLanguage();
|
||||
|
||||
if (!isset($this->forms[$route][$name])) {
|
||||
if (!isset($this->forms[$lang][$route][$name])) {
|
||||
$form['_page_routable'] = !$page->isModule();
|
||||
$this->forms[$route][$name] = $form;
|
||||
$this->forms[$lang][$route][$name] = $form;
|
||||
$this->saveCachedForms();
|
||||
}
|
||||
}
|
||||
@ -849,12 +855,13 @@ class FormPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
$lang = $this->grav['language']->getLanguage();
|
||||
$name = $form->getName();
|
||||
|
||||
if (!isset($this->forms[$route][$name])) {
|
||||
if (!isset($this->forms[$lang][$route][$name])) {
|
||||
$form['_page_routable'] = true;
|
||||
|
||||
$this->forms[$route][$name] = $form;
|
||||
$this->forms[$lang][$route][$name] = $form;
|
||||
$this->saveCachedForms();
|
||||
}
|
||||
}
|
||||
@ -869,6 +876,7 @@ class FormPlugin extends Plugin
|
||||
{
|
||||
/** @var Pages $pages */
|
||||
$pages = $this->grav['pages'];
|
||||
$lang = $this->grav['language']->getLanguage();
|
||||
|
||||
// Handle parameters.
|
||||
if (is_array($data)) {
|
||||
@ -914,7 +922,7 @@ class FormPlugin extends Plugin
|
||||
|
||||
// Attempt to find the form from the page.
|
||||
if ('' !== $route) {
|
||||
$forms = $this->forms[$route] ?? [];
|
||||
$forms = $this->forms[$lang][$route] ?? [];
|
||||
|
||||
if (!$unnamed) {
|
||||
// Get form by the name.
|
||||
@ -930,9 +938,7 @@ class FormPlugin extends Plugin
|
||||
if (null === $form) {
|
||||
// First check if we requested a specific form which didn't exist.
|
||||
if ($route_provided || $unnamed) {
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = $this->grav['debugger'];
|
||||
$debugger->addMessage(sprintf('Form %s not found in page %s', $name ?? 'unnamed', $route), 'warning');
|
||||
$this->grav['debugger']->addMessage(sprintf('Form %s not found in page %s', $name ?? 'unnamed', $route), 'warning');
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -946,8 +952,7 @@ class FormPlugin extends Plugin
|
||||
|
||||
// Check for naming conflicts.
|
||||
if (count($forms) > 1) {
|
||||
$debugger = $this->grav['debugger'];
|
||||
$debugger->addMessage(sprintf('Fetching form by its name, but there are multiple pages with the same form name %s', $name), 'warning');
|
||||
$this->grav['debugger']->addMessage(sprintf('Fetching form by its name, but there are multiple pages with the same form name %s', $name), 'warning');
|
||||
}
|
||||
|
||||
[$route, $name, $form] = $first;
|
||||
@ -959,9 +964,7 @@ class FormPlugin extends Plugin
|
||||
if (is_array($form)) {
|
||||
// Form was cached as an array, try to create the object.
|
||||
if (null === $page) {
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = $this->grav['debugger'];
|
||||
$debugger->addMessage(sprintf('Form %s cannot be created as page %s does not exist', $name, $route), 'warning');
|
||||
$this->grav['debugger']->addMessage(sprintf('Form %s cannot be created as page %s does not exist', $name, $route), 'warning');
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -1096,7 +1099,10 @@ class FormPlugin extends Plugin
|
||||
protected function findFormByName(string $name): array
|
||||
{
|
||||
$list = [];
|
||||
foreach ($this->forms as $route => $forms) {
|
||||
$lang = $this->grav['language']->getLanguage();
|
||||
$lang_forms = $this->forms[$lang] ?? [];
|
||||
|
||||
foreach ($lang_forms as $route => $forms) {
|
||||
foreach ($forms as $key => $form) {
|
||||
if ($name === $key && !empty($form['_page_routable'])) {
|
||||
$list[] = [$route, $key, $form];
|
||||
@ -1233,12 +1239,9 @@ class FormPlugin extends Plugin
|
||||
/** @var Cache $cache */
|
||||
$cache = $this->grav['cache'];
|
||||
|
||||
[$forms] = $cache->fetch($this->getFormCacheId());
|
||||
$forms = $cache->fetch($this->getFormCacheId());
|
||||
} catch (Exception $e) {
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = Grav::instance()['debugger'];
|
||||
$debugger->addMessage(sprintf('Unserializing cached forms failed: %s', $e->getMessage()), 'error');
|
||||
|
||||
$this->grav['debugger']->addMessage(sprintf('Unserializing cached forms failed: %s', $e->getMessage()), 'error');
|
||||
$forms = null;
|
||||
}
|
||||
|
||||
@ -1248,7 +1251,11 @@ class FormPlugin extends Plugin
|
||||
|
||||
// Only update the forms if it's not empty
|
||||
if ($forms) {
|
||||
$this->forms = array_merge($this->forms, $forms);
|
||||
$this->forms = Utils::arrayMergeRecursiveUnique($this->forms, $forms);
|
||||
if ($this->config()['debug']) {
|
||||
$this->grav['log']->addDebug(sprintf("<<<< Loaded cached forms: %s\n%s", $this->getFormCacheId(), $this->arrayToString($this->forms)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1261,8 +1268,17 @@ class FormPlugin extends Plugin
|
||||
{
|
||||
/** @var Cache $cache */
|
||||
$cache = $this->grav['cache'];
|
||||
$cache_id = $this->getFormCacheId();
|
||||
|
||||
$cache->save($this->getFormCacheId(), [$this->forms]);
|
||||
$forms = $cache->fetch($cache_id);
|
||||
if ($forms) {
|
||||
$this->forms = Utils::arrayMergeRecursiveUnique($this->forms, $forms);
|
||||
}
|
||||
|
||||
$cache->save($cache_id, $this->forms);
|
||||
if ($this->config()['debug']) {
|
||||
$this->grav['log']->addDebug(sprintf(">>>> Saved cached forms: %s\n%s", $this->getFormCacheId(), $this->arrayToString($this->forms)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1272,10 +1288,10 @@ class FormPlugin extends Plugin
|
||||
*/
|
||||
protected function getFormCacheId(): string
|
||||
{
|
||||
/** @var Pages $pages */
|
||||
$pages = $this->grav['pages'];
|
||||
|
||||
return $pages->getPagesCacheId() . '-form-plugin';
|
||||
/** @var \Grav\Common\Cache $cache */
|
||||
$cache = $this->grav['cache'];
|
||||
$cache_id = $cache->getKey() . '-form-plugin';
|
||||
return $cache_id;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1308,4 +1324,25 @@ class FormPlugin extends Plugin
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
protected function arrayToString($array, $level = 2) {
|
||||
$result = $this->limitArrayLevels($array, $level);
|
||||
return json_encode($result, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
protected function limitArrayLevels($array, $levelsToKeep, $currentLevel = 0) {
|
||||
if ($currentLevel >= $levelsToKeep) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$value = $this->limitArrayLevels($value, $levelsToKeep, $currentLevel + 1);
|
||||
}
|
||||
$result[$key] = $value;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ built_in_css: true
|
||||
inline_css: true
|
||||
refresh_prevention: false
|
||||
client_side_validation: true
|
||||
debug: false
|
||||
inline_errors: false
|
||||
files:
|
||||
multiple: false # To allow multiple files, default is single
|
||||
|
@ -1,9 +1,15 @@
|
||||
# v3.7.6
|
||||
## 06/29/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* Don't save an empty user file on password reset of non-existing user
|
||||
|
||||
# v3.7.5
|
||||
## 06/14/2023
|
||||
|
||||
1. [](#bugfix)
|
||||
* Sanitized `email` during the "forgot password" process to protect against XSS attacks
|
||||
* Fixed an account enumeration vulneratiblity in forgot password [#293](https://github.com/getgrav/grav-plugin-login/pull/293)
|
||||
* Fixed an account enumeration vulnerability in forgot password [#293](https://github.com/getgrav/grav-plugin-login/pull/293)
|
||||
|
||||
# v3.7.4
|
||||
## 05/09/2023
|
||||
|
@ -1,7 +1,7 @@
|
||||
name: Login
|
||||
slug: login
|
||||
type: plugin
|
||||
version: 3.7.5
|
||||
version: 3.7.6
|
||||
testing: false
|
||||
description: Enables user authentication and login screen.
|
||||
icon: sign-in
|
||||
|
@ -347,61 +347,66 @@ class Controller
|
||||
$config = $this->grav['config'];
|
||||
$data = $this->post;
|
||||
|
||||
/** @var Language $language */
|
||||
$language = $this->grav['language'];
|
||||
$messages = $this->grav['messages'];
|
||||
|
||||
/** @var UserCollectionInterface $users */
|
||||
$users = $this->grav['accounts'];
|
||||
|
||||
$email = $data['email'] ?? '';
|
||||
|
||||
// Sanitize $email
|
||||
$email = htmlspecialchars(strip_tags($email), ENT_QUOTES, 'UTF-8');
|
||||
|
||||
$user = !empty($email) ? $users->find($email, ['email']) : null;
|
||||
// Find user if they exist
|
||||
$user = $users->find($email, ['email']);
|
||||
|
||||
/** @var Language $language */
|
||||
$language = $this->grav['language'];
|
||||
$messages = $this->grav['messages'];
|
||||
if ($user->exists()) {
|
||||
if (!isset($this->grav['Email'])) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
|
||||
$this->setRedirect($this->login->getRoute('forgot') ?? '/');
|
||||
|
||||
if (!isset($this->grav['Email'])) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
|
||||
$this->setRedirect($this->login->getRoute('forgot') ?? '/');
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
$from = $config->get('plugins.email.from');
|
||||
|
||||
$from = $config->get('plugins.email.from');
|
||||
if (empty($from)) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
|
||||
$this->setRedirect($this->login->getRoute('forgot') ?? '/');
|
||||
|
||||
if (empty($from)) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error');
|
||||
$this->setRedirect($this->login->getRoute('forgot') ?? '/');
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
$userKey = $user->username;
|
||||
$rateLimiter = $this->login->getRateLimiter('pw_resets');
|
||||
$rateLimiter->registerRateLimitedAction($userKey);
|
||||
|
||||
$userKey = $user->username;
|
||||
$rateLimiter = $this->login->getRateLimiter('pw_resets');
|
||||
$rateLimiter->registerRateLimitedAction($userKey);
|
||||
if ($rateLimiter->isRateLimited($userKey)) {
|
||||
$messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $email, $rateLimiter->getInterval()]), 'error');
|
||||
$this->setRedirect($this->login->getRoute('login') ?? '/');
|
||||
|
||||
if ($rateLimiter->isRateLimited($userKey)) {
|
||||
$messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $email, $rateLimiter->getInterval()]), 'error');
|
||||
$this->setRedirect($this->login->getRoute('login') ?? '/');
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
$token = md5(uniqid((string)mt_rand(), true));
|
||||
$expire = time() + 604800; // next week
|
||||
|
||||
$token = md5(uniqid((string)mt_rand(), true));
|
||||
$expire = time() + 604800; // next week
|
||||
$user->reset = $token . '::' . $expire;
|
||||
$user->save();
|
||||
|
||||
$user->reset = $token . '::' . $expire;
|
||||
$user->save();
|
||||
|
||||
try {
|
||||
Email::sendResetPasswordEmail($user);
|
||||
try {
|
||||
Email::sendResetPasswordEmail($user);
|
||||
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), 'info');
|
||||
} catch (\Exception $e) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_FAILED_TO_EMAIL'), 'error');
|
||||
}
|
||||
} else {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), 'info');
|
||||
} catch (\Exception $e) {
|
||||
$messages->add($language->translate('PLUGIN_LOGIN.FORGOT_FAILED_TO_EMAIL'), 'error');
|
||||
}
|
||||
|
||||
|
||||
$this->setRedirect($this->login->getRoute('login') ?? '/');
|
||||
|
||||
return true;
|
||||
|
38
plugins/markdown-notices/CHANGELOG.md
Normal file
38
plugins/markdown-notices/CHANGELOG.md
Normal file
@ -0,0 +1,38 @@
|
||||
# v1.1.0
|
||||
## 12/02/2020
|
||||
|
||||
1. [](#new)
|
||||
* Support for indent-sensitive notices [#17](https://github.com/getgrav/grav-plugin-markdown-notices/pull/17)
|
||||
* Pass phpstan level 1 tests
|
||||
* Require Grav v1.6
|
||||
|
||||
# v1.0.4
|
||||
## 09/10/2019
|
||||
|
||||
1. [](#improved)
|
||||
* Reverted PR#10 which was breaking multiline notices and also unintentionally marking up notices with `<space>!<space>` in paragraphs
|
||||
|
||||
# v1.0.3
|
||||
## 08/16/2019
|
||||
|
||||
1. [](#improved)
|
||||
* Fixed issue where PR#10 clobbered PR#9
|
||||
|
||||
# v1.0.2
|
||||
## 08/11/2019
|
||||
|
||||
1. [](#new)
|
||||
* Ability to specify your own base classes [#9](https://github.com/getgrav/grav-plugin-markdown-notices/pull/9)
|
||||
* Allow adding inline notices inside tables [#10](https://github.com/getgrav/grav-plugin-markdown-notices/pull/10)
|
||||
|
||||
# v1.0.1
|
||||
## 03/09/2018
|
||||
|
||||
1. [](#improved)
|
||||
* Updated blueprint file
|
||||
|
||||
# v1.0.0
|
||||
## 12/22/2015
|
||||
|
||||
1. [](#new)
|
||||
* ChangeLog started...
|
21
plugins/markdown-notices/LICENSE
Normal file
21
plugins/markdown-notices/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Grav
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
62
plugins/markdown-notices/README.md
Normal file
62
plugins/markdown-notices/README.md
Normal file
@ -0,0 +1,62 @@
|
||||
# Grav Markdown Notices Plugin
|
||||
|
||||
The **markdown-notices plugin** for [Grav](http://github.com/getgrav/grav) allows generation of notice blocks of text via markdown:
|
||||
|
||||
![](assets/screenshot.png)
|
||||
|
||||
# Installation
|
||||
|
||||
This plugin is easy to install with GPM.
|
||||
|
||||
```
|
||||
$ bin/gpm install markdown-notices
|
||||
```
|
||||
|
||||
# Configuration
|
||||
|
||||
Simply copy the `user/plugins/markdown-notices/markdown-notices.yaml` into `user/config/plugins/markdown-notices.yaml` and make your modifications.
|
||||
|
||||
```
|
||||
enabled: true
|
||||
built_in_css: true
|
||||
base_classes: 'notices'
|
||||
level_classes: [yellow, red, blue, green]
|
||||
```
|
||||
|
||||
# Examples
|
||||
|
||||
Using one level of `!`
|
||||
|
||||
```
|
||||
! Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris feugiat quam erat, ut iaculis diam posuere nec.
|
||||
! Vestibulum eu condimentum urna. Vestibulum feugiat odio ut sodales porta. Donec sit amet ante mi. Donec lobortis
|
||||
! orci dolor. Donec tristique volutpat ultricies. Nullam tempus, enim sit amet fringilla facilisis, ipsum ex
|
||||
! tincidunt ipsum, vel placerat sem sem vitae risus. Aenean posuere sed purus nec pretium.
|
||||
```
|
||||
|
||||
You will output the following HTML
|
||||
|
||||
```
|
||||
<div class="notices yellow">
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris feugiat quam erat, ut iaculis diam posuere nec.
|
||||
Vestibulum eu condimentum urna. Vestibulum feugiat odio ut sodales porta. Donec sit amet ante mi. Donec lobortis
|
||||
orci dolor. Donec tristique volutpat ultricies. Nullam tempus, enim sit amet fringilla facilisis, ipsum ex
|
||||
tincidunt ipsum, vel placerat sem sem vitae risus. Aenean posuere sed purus nec pretium.
|
||||
</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
The `notices` class determined by the `base_classes` and `yellow` class is determined by the `level_classes` in the configuration. You can customize this as you need.
|
||||
|
||||
```
|
||||
!! Lorem ipsum dolor sit amet, **consectetur adipiscing** elit. Mauris feugiat quam erat, ut iaculis diam posuere nec.
|
||||
!!
|
||||
!! * List item a
|
||||
!! * List item b
|
||||
!!
|
||||
!! orci dolor. Donec tristique volutpat ultricies. Nullam tempus, enim sit amet fringilla facilisis, ipsum ex
|
||||
!! tincidunt ipsum, vel placerat sem sem vitae risus. Aenean posuere sed purus nec pretium.
|
||||
```
|
||||
|
||||
Two levels of `!!` will use the second level class etc. You can also use complex markdown inside the notices.
|
32
plugins/markdown-notices/assets/notices.css
Normal file
32
plugins/markdown-notices/assets/notices.css
Normal file
@ -0,0 +1,32 @@
|
||||
.notices {
|
||||
padding: 1px 1px 1px 30px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.notices p {
|
||||
|
||||
}
|
||||
|
||||
.notices.yellow {
|
||||
border-left: 10px solid #f0ad4e;
|
||||
background: #fcf8f2;
|
||||
color: #df8a13;
|
||||
}
|
||||
|
||||
.notices.red {
|
||||
border-left: 10px solid #d9534f;
|
||||
background: #fdf7f7;
|
||||
color: #b52b27;
|
||||
}
|
||||
|
||||
.notices.blue {
|
||||
border-left: 10px solid #5bc0de;
|
||||
background: #f4f8fa;
|
||||
color: #28a1c5;
|
||||
}
|
||||
|
||||
.notices.green {
|
||||
border-left: 10px solid #5cb85c;
|
||||
background: #f1f9f1;
|
||||
color: #3d8b3d;
|
||||
}
|
BIN
plugins/markdown-notices/assets/screenshot.png
Normal file
BIN
plugins/markdown-notices/assets/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 85 KiB |
59
plugins/markdown-notices/blueprints.yaml
Normal file
59
plugins/markdown-notices/blueprints.yaml
Normal file
@ -0,0 +1,59 @@
|
||||
name: 'Markdown Notices'
|
||||
type: plugin
|
||||
slug: markdown-notices
|
||||
version: 1.1.0
|
||||
description: 'Adds the ability to render notices blocks in Markdown'
|
||||
icon: asterisk
|
||||
author:
|
||||
name: Team Grav
|
||||
email: devs@getgrav.org
|
||||
url: http://getgrav.org
|
||||
homepage: https://github.com/getgrav/grav-plugin-markdown-notices
|
||||
license: MIT
|
||||
dependencies:
|
||||
- { name: grav, version: '>=1.6.0' }
|
||||
|
||||
form:
|
||||
validation: strict
|
||||
fields:
|
||||
enabled:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.PLUGIN_STATUS
|
||||
highlight: 1
|
||||
default: 0
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
built_in_css:
|
||||
type: toggle
|
||||
label: PLUGIN_MARKDOWN_NOTICES.USE_BUILT_IN_CSS
|
||||
highlight: 1
|
||||
default: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
base_classes:
|
||||
type: selectize
|
||||
label: PLUGIN_MARKDOWN_NOTICES.BASE_CLASSES
|
||||
size: large
|
||||
placeholder: PLUGIN_MARKDOWN_NOTICES.BASE_CLASSES_PLACEHOLDER
|
||||
help: PLUGIN_MARKDOWN_NOTICES.BASE_CLASSES_HELP
|
||||
classes: fancy
|
||||
validate:
|
||||
type: string
|
||||
|
||||
level_classes:
|
||||
type: selectize
|
||||
label: PLUGIN_MARKDOWN_NOTICES.LEVEL_CLASSES
|
||||
size: large
|
||||
placeholder: PLUGIN_MARKDOWN_NOTICES.LEVEL_CLASSES_PLACEHOLDER
|
||||
help: PLUGIN_MARKDOWN_NOTICES.LEVEL_CLASSES_HELP
|
||||
classes: fancy
|
||||
validate:
|
||||
type: commalist
|
27
plugins/markdown-notices/composer.json
Normal file
27
plugins/markdown-notices/composer.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "grav-plugin-markdown-notices",
|
||||
"type": "grav-plugin",
|
||||
"description": "Markdown notices plugin for Grav CMS",
|
||||
"keywords": ["notices"],
|
||||
"homepage": "https://github.com/getgrav/grav-plugin-markdown-notices/",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Team Grav",
|
||||
"email": "devs@getgrav.org",
|
||||
"homepage": "http://getgrav.org",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.1.3"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": ["markdown-notices.php"]
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.1.3"
|
||||
}
|
||||
}
|
||||
}
|
22
plugins/markdown-notices/composer.lock
generated
Normal file
22
plugins/markdown-notices/composer.lock
generated
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "683006688355ff7a1f71b2726c2629b6",
|
||||
"packages": [],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.1.3"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"platform-overrides": {
|
||||
"php": "7.1.3"
|
||||
}
|
||||
}
|
29
plugins/markdown-notices/languages.yaml
Normal file
29
plugins/markdown-notices/languages.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
en:
|
||||
PLUGIN_MARKDOWN_NOTICES:
|
||||
USE_BUILT_IN_CSS: 'Use built-in CSS'
|
||||
BASE_CLASSES: 'Base classes'
|
||||
BASE_CLASSES_HELP: 'These classes will be added before the class level'
|
||||
BASE_CLASSES_PLACEHOLDER: 'e.g. notices'
|
||||
LEVEL_CLASSES: 'Level classes'
|
||||
LEVEL_CLASSES_HELP: 'The classes to use for each level of notices depth'
|
||||
LEVEL_CLASSES_PLACEHOLDER: 'e.g. yellow, red, blue, green'
|
||||
|
||||
ru:
|
||||
PLUGIN_MARKDOWN_NOTICES:
|
||||
USE_BUILT_IN_CSS: 'Использовать встроенный CSS'
|
||||
BASE_CLASSES: 'Базовые классы'
|
||||
BASE_CLASSES_HELP: 'Эти классы будут добавлены до уровня класса'
|
||||
BASE_CLASSES_PLACEHOLDER: 'например notices'
|
||||
LEVEL_CLASSES: 'Классы уровней'
|
||||
LEVEL_CLASSES_HELP: 'Эти классы используются на каждом уровне глубины уведомлений'
|
||||
LEVEL_CLASSES_PLACEHOLDER: 'например yellow, red, blue, green'
|
||||
|
||||
uk:
|
||||
PLUGIN_MARKDOWN_NOTICES:
|
||||
USE_BUILT_IN_CSS: 'Використовувати вбудований CSS'
|
||||
BASE_CLASSES: 'Базові класи'
|
||||
BASE_CLASSES_HELP: 'Ці класи будуть додані до рівня класу'
|
||||
BASE_CLASSES_PLACEHOLDER: 'наприклад notices'
|
||||
LEVEL_CLASSES: 'Класи рівнів'
|
||||
LEVEL_CLASSES_HELP: 'Ці класи використовуються на кожному рівні глибини повідомлень'
|
||||
LEVEL_CLASSES_PLACEHOLDER: 'наприклад yellow, red, blue, green'
|
92
plugins/markdown-notices/markdown-notices.php
Normal file
92
plugins/markdown-notices/markdown-notices.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
namespace Grav\Plugin;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Grav\Common\Plugin;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
|
||||
class MarkdownNoticesPlugin extends Plugin
|
||||
{
|
||||
protected $base_classes;
|
||||
protected $level_classes;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
'onPluginsInitialized' => [
|
||||
['autoload', 100001],
|
||||
],
|
||||
'onMarkdownInitialized' => ['onMarkdownInitialized', 0],
|
||||
'onTwigSiteVariables' => ['onTwigSiteVariables', 0]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* [onPluginsInitialized:100000] Composer autoload.
|
||||
*
|
||||
* @return ClassLoader
|
||||
*/
|
||||
public function autoload()
|
||||
{
|
||||
return require __DIR__ . '/vendor/autoload.php';
|
||||
}
|
||||
|
||||
public function onMarkdownInitialized(Event $event)
|
||||
{
|
||||
$markdown = $event['markdown'];
|
||||
|
||||
$markdown->addBlockType('!', 'Notices', true, false);
|
||||
|
||||
$markdown->blockNotices = function($Line) {
|
||||
|
||||
$this->level_classes = $this->config->get('plugins.markdown-notices.level_classes');
|
||||
$this->base_classes = $this->config->get('plugins.markdown-notices.base_classes');
|
||||
|
||||
if (preg_match('/^(!{1,'.count($this->level_classes).'}) (.*)/', $Line['text'], $matches))
|
||||
{
|
||||
$level = strlen($matches[1]) - 1;
|
||||
|
||||
$text = $matches[2];
|
||||
$base_classes = (empty($this->base_classes)) ? '' : str_replace(',', ' ', $this->base_classes) . ' ';
|
||||
|
||||
$Block = [
|
||||
'element' => [
|
||||
'name' => 'div',
|
||||
'handler' => 'lines',
|
||||
'attributes' => [
|
||||
'class' => $base_classes . $this->level_classes[$level],
|
||||
],
|
||||
'text' => (array) $text,
|
||||
],
|
||||
];
|
||||
|
||||
return $Block;
|
||||
}
|
||||
};
|
||||
|
||||
$markdown->blockNoticesContinue = function($Line, array $Block) {
|
||||
if (isset($Block['interrupted']))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (preg_match('/^(!{1,'.count($this->level_classes).'}) ?(.*)/', $Line['text'], $matches))
|
||||
{
|
||||
$Block['element']['text'] []= $matches[2];
|
||||
|
||||
return $Block;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public function onTwigSiteVariables()
|
||||
{
|
||||
if ($this->config->get('plugins.markdown-notices.built_in_css')) {
|
||||
$this->grav['assets']
|
||||
->add('plugin://markdown-notices/assets/notices.css');
|
||||
}
|
||||
}
|
||||
}
|
4
plugins/markdown-notices/markdown-notices.yaml
Normal file
4
plugins/markdown-notices/markdown-notices.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
enabled: true
|
||||
built_in_css: true
|
||||
base_classes: 'notices'
|
||||
level_classes: [yellow, red, blue, green]
|
7
plugins/markdown-notices/vendor/autoload.php
vendored
Normal file
7
plugins/markdown-notices/vendor/autoload.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit83fb2a7c0fd89ecaed52b0401a5f24c0::getLoader();
|
445
plugins/markdown-notices/vendor/composer/ClassLoader.php
vendored
Normal file
445
plugins/markdown-notices/vendor/composer/ClassLoader.php
vendored
Normal file
@ -0,0 +1,445 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see http://www.php-fig.org/psr/psr-0/
|
||||
* @see http://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
// PSR-4
|
||||
private $prefixLengthsPsr4 = array();
|
||||
private $prefixDirsPsr4 = array();
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
private $prefixesPsr0 = array();
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
private $useIncludePath = false;
|
||||
private $classMap = array();
|
||||
private $classMapAuthoritative = false;
|
||||
private $missingClasses = array();
|
||||
private $apcuPrefix;
|
||||
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', $this->prefixesPsr0);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classMap Class to filename map
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 base directories
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath.'\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
}
|
21
plugins/markdown-notices/vendor/composer/LICENSE
vendored
Normal file
21
plugins/markdown-notices/vendor/composer/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
10
plugins/markdown-notices/vendor/composer/autoload_classmap.php
vendored
Normal file
10
plugins/markdown-notices/vendor/composer/autoload_classmap.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Grav\\Plugin\\MarkdownNoticesPlugin' => $baseDir . '/markdown-notices.php',
|
||||
);
|
9
plugins/markdown-notices/vendor/composer/autoload_namespaces.php
vendored
Normal file
9
plugins/markdown-notices/vendor/composer/autoload_namespaces.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
9
plugins/markdown-notices/vendor/composer/autoload_psr4.php
vendored
Normal file
9
plugins/markdown-notices/vendor/composer/autoload_psr4.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
52
plugins/markdown-notices/vendor/composer/autoload_real.php
vendored
Normal file
52
plugins/markdown-notices/vendor/composer/autoload_real.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit83fb2a7c0fd89ecaed52b0401a5f24c0
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit83fb2a7c0fd89ecaed52b0401a5f24c0', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit83fb2a7c0fd89ecaed52b0401a5f24c0', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
if ($useStaticLoader) {
|
||||
require_once __DIR__ . '/autoload_static.php';
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit83fb2a7c0fd89ecaed52b0401a5f24c0::getInitializer($loader));
|
||||
} else {
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->set($namespace, $path);
|
||||
}
|
||||
|
||||
$map = require __DIR__ . '/autoload_psr4.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->setPsr4($namespace, $path);
|
||||
}
|
||||
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
}
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
20
plugins/markdown-notices/vendor/composer/autoload_static.php
vendored
Normal file
20
plugins/markdown-notices/vendor/composer/autoload_static.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit83fb2a7c0fd89ecaed52b0401a5f24c0
|
||||
{
|
||||
public static $classMap = array (
|
||||
'Grav\\Plugin\\MarkdownNoticesPlugin' => __DIR__ . '/../..' . '/markdown-notices.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->classMap = ComposerStaticInit83fb2a7c0fd89ecaed52b0401a5f24c0::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
1
plugins/markdown-notices/vendor/composer/installed.json
vendored
Normal file
1
plugins/markdown-notices/vendor/composer/installed.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
[]
|
Loading…
Reference in New Issue
Block a user