addfolder
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\ng_lightbox\Form;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Form\ConfigFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\ng_lightbox\NgLightbox;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
class NgLightboxSettingsForm extends ConfigFormBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Config\ConfigFactoryInterface
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* An array of Lightbox renderers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $renderers = [];
|
||||
|
||||
/**
|
||||
* Constructs a \Drupal\system\ConfigFormBase object.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The factory for configuration objects.
|
||||
*/
|
||||
public function __construct(ConfigFactoryInterface $config_factory, array $lightbox_renderers) {
|
||||
parent::__construct($config_factory);
|
||||
$this->renderers = $lightbox_renderers;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('config.factory'),
|
||||
$container->getParameter('ng_lightbox_renderers')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$this->config = $this->configFactory()->getEditable('ng_lightbox.settings');
|
||||
|
||||
$form['container']['patterns'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => $this->t('Paths'),
|
||||
'#default_value' => $this->config->get('patterns'),
|
||||
'#description' => $this->t('New line separated paths that must start with a leading slash. Wildcard character is *. E.g. /comment/*/reply.'),
|
||||
);
|
||||
$form['container']['default_width'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Default Width'),
|
||||
'#default_value' => $this->config->get('default_width'),
|
||||
'#description' => $this->t('The default width for modals opened with NG Lightbox.'),
|
||||
);
|
||||
$form['container']['lightbox_class'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Lightbox Class'),
|
||||
'#default_value' => $this->config->get('lightbox_class'),
|
||||
'#description' => $this->t('The css custom class for modals opened with NG Lightbox.'),
|
||||
);
|
||||
$form['container']['skip_admin_paths'] = array(
|
||||
'#title' => $this->t('Skip all admin paths'),
|
||||
'#type' => 'checkbox',
|
||||
'#default_value' => $this->config->get('skip_admin_paths'),
|
||||
'#description' => $this->t('This will exclude all admin paths from the lightbox. If you want some paths, see hook_ng_lightbox_ajax_path_alter().'),
|
||||
);
|
||||
$form['container']['renderer'] = array(
|
||||
'#title' => $this->t('Renderer'),
|
||||
'#type' => 'select',
|
||||
'#default_value' => $this->config->get('renderer') ?: NgLightbox::DEFAULT_MODAL,
|
||||
'#description' => $this->t('Select which renderer should be used for the lightbox.'),
|
||||
'#options' => $this->renderers,
|
||||
);
|
||||
|
||||
return parent::buildForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$values = $form_state->getValues();
|
||||
$this->config
|
||||
->set('patterns', $values['patterns'])
|
||||
->set('default_width', $values['default_width'])
|
||||
->set('lightbox_class', $values['lightbox_class'])
|
||||
->set('skip_admin_paths', $values['skip_admin_paths'])
|
||||
->set('renderer', $values['renderer'])
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'ng_lightbox_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEditableConfigNames() {
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\ng_lightbox;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Path\AliasManagerInterface;
|
||||
use Drupal\Core\Path\PathMatcherInterface;
|
||||
use Drupal\Core\Routing\AdminContext;
|
||||
use Drupal\Core\Routing\RouteMatch;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class NgLightbox {
|
||||
|
||||
/**
|
||||
* The default modal when none is selected.
|
||||
*/
|
||||
const DEFAULT_MODAL = 'drupal_modal';
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Path\PathMatcherInterface
|
||||
*/
|
||||
protected $pathMatcher;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Path\AliasManagerInterface
|
||||
*/
|
||||
protected $aliasManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Config\ImmutableConfig
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Routing\AdminContext
|
||||
*/
|
||||
protected $adminContext;
|
||||
|
||||
/**
|
||||
* An array of paths that were already checked and their match status.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $matches = [];
|
||||
|
||||
/**
|
||||
* Constructs a new NgLightbox service.
|
||||
*
|
||||
* @param \Drupal\Core\Path\PathMatcherInterface $path_matcher
|
||||
* Patch matcher services for comparing the lightbox patterns.
|
||||
* @param \Drupal\Core\Path\AliasManagerInterface $alias_manager
|
||||
* Alias manager so we can also test path aliases.
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The config factory so we can get the lightbox settings.
|
||||
*/
|
||||
public function __construct(PathMatcherInterface $path_matcher, AliasManagerInterface $alias_manager, ConfigFactoryInterface $config_factory, AdminContext $admin_context) {
|
||||
$this->pathMatcher = $path_matcher;
|
||||
$this->aliasManager = $alias_manager;
|
||||
$this->config = $config_factory->get('ng_lightbox.settings');
|
||||
$this->adminContext = $admin_context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a give path matches the ng-lightbox path rules.
|
||||
* This function checks both internal paths and aliased paths.
|
||||
*
|
||||
* @param \Drupal\Core\Url $url
|
||||
* The Url object.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if it matches the given rules.
|
||||
*/
|
||||
public function isNgLightboxEnabledPath(Url $url) {
|
||||
|
||||
// No lightbox on external Urls.
|
||||
if ($url->isExternal()) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// If we don't want to enable the Lightbox on admin pages.
|
||||
if ($this->config->get('skip_admin_paths') && $this->adminContext->isAdminRoute()) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// @TODO, decide whether we want to try and support paths or to adopt routes
|
||||
// like core is trying to force us into.
|
||||
$path = strtolower($url->toString());
|
||||
|
||||
// We filter out empty paths because some modules (such as Media) use
|
||||
// theme_link() to generate links with empty paths and we filter out paths
|
||||
// that do not start with a /, such as #hash-only URLs.
|
||||
if (empty($path) || $path[0] !== '/') {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Remove the base path.
|
||||
if ($base_path = \Drupal::request()->getBasePath()) {
|
||||
$path = substr($path, strlen($base_path));
|
||||
}
|
||||
|
||||
// Check the cache, see if we've handled this before.
|
||||
if (isset($this->matches[$path])) {
|
||||
return $this->matches[$path];
|
||||
}
|
||||
|
||||
// Normalise the patterns as well so they match the normalised paths.
|
||||
$patterns = strtolower($this->config->get('patterns'));
|
||||
|
||||
// Check for internal paths first which is much quicker than the alias lookup.
|
||||
if ($this->pathMatcher->matchPath($path, $patterns)) {
|
||||
$this->matches[$path] = TRUE;
|
||||
}
|
||||
else {
|
||||
// Now check for aliases paths.
|
||||
$aliased_path = strtolower($this->aliasManager->getAliasByPath($path));
|
||||
if ($path != $aliased_path && $this->pathMatcher->matchPath($aliased_path, $patterns)) {
|
||||
$this->matches[$path] = TRUE;
|
||||
}
|
||||
else {
|
||||
// No match.
|
||||
$this->matches[$path] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->matches[$path];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a lightbox to a link.
|
||||
*
|
||||
* @param array $link
|
||||
* The link we want to add the lightbox to.
|
||||
*/
|
||||
public function addLightbox(array &$link) {
|
||||
// Safety check if class isn't an array.
|
||||
if (!isset($link['options']['attributes']['class'])) {
|
||||
$link['options']['attributes']['class'] = array();
|
||||
}
|
||||
|
||||
// Add our lightbox class.
|
||||
$link['options']['attributes']['class'][] = 'use-ajax';
|
||||
$link['options']['attributes']['data-dialog-type'] = str_replace('drupal_', '', $this->config->get('renderer') ?: static::DEFAULT_MODAL);
|
||||
$data = [
|
||||
'width' => $this->config->get('default_width'),
|
||||
'dialogClass' => $this->config->get('lightbox_class'),
|
||||
];
|
||||
|
||||
$link['options']['attributes']['data-dialog-options'] = json_encode($data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ng_lightbox\NgLightboxPass
|
||||
*/
|
||||
|
||||
namespace Drupal\ng_lightbox;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* The NgLightboxPass class.
|
||||
*/
|
||||
class NgLightboxPass implements CompilerPassInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container) {
|
||||
$lightbox_renderers = [];
|
||||
foreach ($container->findTaggedServiceIds('render.main_content_renderer') as $id => $attributes_list) {
|
||||
foreach ($attributes_list as $attributes) {
|
||||
if (!empty($attributes['ng_lightbox'])) {
|
||||
$format = $attributes['format'];
|
||||
$lightbox_renderers[$format] = $attributes['ng_lightbox'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$container->setParameter('ng_lightbox_renderers', $lightbox_renderers);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ng_lightbox\NgLightboxServiceProvider
|
||||
*/
|
||||
|
||||
namespace Drupal\ng_lightbox;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceProviderBase;
|
||||
|
||||
/**
|
||||
* The NgLightboxServiceProvider class.
|
||||
*/
|
||||
class NgLightboxServiceProvider extends ServiceProviderBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function register(ContainerBuilder $container) {
|
||||
$container->addCompilerPass(new NgLightboxPass());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(ContainerBuilder $container) {
|
||||
$this->addLightbox($container, 'main_content_renderer.dialog', 'Core Dialog');
|
||||
$this->addLightbox($container, 'main_content_renderer.modal', 'Core Modal');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Drupal\Core\DependencyInjection\ContainerBuilder $container
|
||||
* @param $id
|
||||
* @param $title
|
||||
*/
|
||||
protected function addLightbox(ContainerBuilder $container, $id, $title) {
|
||||
$definition = $container->getDefinition($id);
|
||||
$tags = $definition->getTags();
|
||||
|
||||
foreach ($tags as $delta => &$tag) {
|
||||
if ($delta === 'render.main_content_renderer') {
|
||||
foreach ($tag as &$attribute) {
|
||||
$attribute['ng_lightbox'] = $title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$definition->setTags($tags);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* NG Lightbox tests.
|
||||
*/
|
||||
|
||||
namespace Drupal\ng_lightbox\Tests;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Test basic functionality of the lightbox.
|
||||
*
|
||||
* @group ng_lightbox
|
||||
*/
|
||||
class NgLightboxTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['system', 'node', 'user', 'ng_lightbox'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('system', ['router', 'url_alias']);
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installSchema('node', ['node_access']);
|
||||
$this->installConfig(['ng_lightbox']);
|
||||
|
||||
// Create the node type.
|
||||
NodeType::create(['type' => 'page'])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the pattern matching for link paths.
|
||||
*/
|
||||
public function testPatternMatching() {
|
||||
|
||||
// Test the patterns are enabled on links as expected.
|
||||
$node = Node::create(['type' => 'page', 'title' => $this->randomString()]);
|
||||
$node->save();
|
||||
$config = \Drupal::configFactory()->getEditable('ng_lightbox.settings');
|
||||
$config->set('patterns', $node->url())->save();
|
||||
$this->assertLightboxEnabled(\Drupal::l('Normal Path', $node->urlInfo()));
|
||||
|
||||
// Create a second node and make sure it doesn't get lightboxed.
|
||||
$node = Node::create(['type' => 'page', 'title' => $this->randomString()]);
|
||||
$node->save();
|
||||
$this->assertLightboxNotEnabled(\Drupal::l('Normal Path', $node->urlInfo()));
|
||||
|
||||
|
||||
// @TODO, these were in D7 but in D8, I can't see how you can even generate
|
||||
// a link with such a format so maybe it isn't needed at all?
|
||||
// The uppercase path should still be matched for a lightbox.
|
||||
// $this->assertLightboxNotEnabled(\Drupal::l('Uppercase Path', 'NODE/1'));
|
||||
// $this->assertLightboxNotEnabled(\Drupal::l('Alaised Path', $alias));
|
||||
// $this->assertLightboxNotEnabled(\Drupal::l('Empty Path', ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the lightbox was enabled for the generated link.
|
||||
*
|
||||
* @param string $link
|
||||
* The rendered link.
|
||||
*/
|
||||
protected function assertLightboxEnabled($link) {
|
||||
$this->assertContains('use-ajax', $link);
|
||||
$this->assertContains('data-dialog-type', $link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the lightbox was not enabled for the generated link.
|
||||
*
|
||||
* @param string $link
|
||||
* The rendered link.
|
||||
*/
|
||||
protected function assertLightboxNotEnabled($link) {
|
||||
$this->assertNotContains('use-ajax', $link);
|
||||
$this->assertNotContains('data-dialog-type', $link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts a string does exist in the haystack.
|
||||
*
|
||||
* @param string $needle
|
||||
* The string to search for.
|
||||
* @param string $haystack
|
||||
* The string to search within.
|
||||
* @param string $message
|
||||
* The message to log.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if it was found otherwise FALSE.
|
||||
*/
|
||||
protected function assertContains($needle, $haystack, $message = '') {
|
||||
if (empty($message)) {
|
||||
$message = t('%needle was found within %haystack', array('%needle' => $needle, '%haystack' => $haystack));
|
||||
}
|
||||
return $this->assertTrue(stripos($haystack, $needle) !== FALSE, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts a string does not exist in the haystack.
|
||||
*
|
||||
* @param string $needle
|
||||
* The string to search for.
|
||||
* @param string $haystack
|
||||
* The string to search within.
|
||||
* @param string $message
|
||||
* The message to log.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if it was not found otherwise FALSE.
|
||||
*/
|
||||
protected function assertNotContains($needle, $haystack, $message = '') {
|
||||
if (empty($message)) {
|
||||
$message = t('%needle was not found within %haystack', array('%needle' => $needle, '%haystack' => $haystack));
|
||||
}
|
||||
return $this->assertTrue(stripos($haystack, $needle) === FALSE, $message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\ng_lightbox\Tests\NgLightboxWebTest
|
||||
*/
|
||||
|
||||
namespace Drupal\ng_lightbox\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* A web test for NG Lightbox.
|
||||
*
|
||||
* @group ng_lightbox
|
||||
*/
|
||||
class NgLightboxWebTest extends WebTestBase {
|
||||
|
||||
protected $profile = 'minimal';
|
||||
|
||||
/**
|
||||
* Default modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['ng_lightbox', 'views', 'node', 'filter'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$config = \Drupal::configFactory()->getEditable('ng_lightbox.settings');
|
||||
$this->createContentType(['type' => 'page']);
|
||||
$node = $this->drupalCreateNode();
|
||||
$config->set('patterns', '/node/' . $node->id());
|
||||
$config->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that we can render a modal even before selecting one from the admin.
|
||||
*/
|
||||
public function testDefaultModal() {
|
||||
$this->drupalGet('/node');
|
||||
$this->assertRaw('data-dialog-type="modal"');
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user