monster_menus-9.0.x-dev/src/Plugin/MMTreeBrowserDisplay/Nodes.php
src/Plugin/MMTreeBrowserDisplay/Nodes.php
<?php
namespace Drupal\monster_menus\Plugin\MMTreeBrowserDisplay;
use Drupal\Core\Database\Query\TableSortExtender;
use Drupal\Core\Database\Query\PagerSelectExtender;
use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\file\Entity\File;
use Drupal\filter\Render\FilteredMarkup;
use Drupal\monster_menus\Constants;
use Drupal\monster_menus\MMTreeBrowserDisplay\MMTreeBrowserDisplayInterface;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\node\Entity\NodeType;
/**
* Provides the MM Tree display generator for node entities.
*
* @MMTreeBrowserDisplay(
* id = "mm_tree_browser_display_node",
* admin_label = @Translation("MM Tree node display"),
* )
*/
class Nodes extends Fallback implements MMTreeBrowserDisplayInterface {
final public const BROWSER_MODE_NODE = 'nod';
public static function supportedModes() {
return [self::BROWSER_MODE_NODE];
}
/**
* @inheritDoc
*/
public function label($mode) {
return t('Select a piece of content');
}
public function alterLeftQuery($mode, $query, &$params) {
$allowed_node_types = [];
if ($field_id = $query->get('browserFieldID')) {
[$field_name, $bundle, $type] = explode(',', $field_id);
if ($widget = EntityFormDisplay::load("$type.$bundle.default")->getRenderer($field_name)) {
foreach ($widget->getSetting('mm_list_nodetypes') as $node_type) {
if (!empty($node_type)) {
$allowed_node_types[] = "'" . $node_type . "'";
}
}
}
}
$wheres = $allowed_node_types ? 'AND nd.type IN (' . implode(', ', $allowed_node_types) . ') ' : '';
$wheres .= 'AND nfd.status = 1';
$params[Constants::MM_GET_TREE_ADD_SELECT] = "(SELECT COUNT(DISTINCT n.nid) FROM {mm_node2tree} n INNER JOIN {node} nd ON nd.nid = n.nid INNER JOIN {node_field_data} nfd ON nfd.nid = n.nid WHERE n.mmtid = o.container {$wheres}) AS nodecount ";
$params[Constants::MM_GET_TREE_FILTER_NORMAL] = $params[Constants::MM_GET_TREE_FILTER_USERS] = TRUE;
}
/**
* {@inheritdoc}
*/
public function alterRightButtons($mode, $query, $item, $permissions, &$actions, &$dialogs) {
parent::alterRightButtons($mode, $query, $item, $permissions, $actions, $dialogs);
$this->addSearchAction($query, $actions, t('Filter by title'), 100);
}
/**
* {@inheritdoc}
*/
public function viewRight($mode, $query, $perms, $item, $database) {
// This retrieves the attributes of the content type.
// Allow all node types by default.
$mmtid = $item->mmtid;
$settings = ['mm_list_nodetypes' => []];
if ($field_id = $query->get('browserFieldID', '')) {
[$field_name, $bundle, $type] = explode(',', $field_id);
if ($widget = EntityFormDisplay::load("$type.$bundle.default")->getRenderer($field_name)) {
$settings = $widget->getSettings();
}
}
if (empty($settings['mm_list_selectable'])) {
$settings['mm_list_selectable'] = Constants::MM_PERMS_READ;
}
if (empty($perms[$settings['mm_list_selectable']])) {
$out = '';
if ($mmtid > 0) {
$out = '<div id="mmtree-browse-thumbnails"><br /><p>' . t('You do not have permission to use the content on this page.') . '</p>';
$options = [
Constants::MM_PERMS_WRITE => t('delete it or change its settings'),
Constants::MM_PERMS_SUB => t('append subpages to it'),
Constants::MM_PERMS_APPLY => t('add content to it'),
Constants::MM_PERMS_READ => t('read it'),
];
if (isset($options[$settings['mm_list_selectable']])) {
$out .= t('<p>To use content from this page, you must be able to @do.</p>', ['@do' => $options[$settings['mm_list_selectable']]]);
}
$out .= '</div>';
}
$json = [
'title' => mm_content_get_name($mmtid),
'body' => $out,
];
return mm_json_response($json);
}
$all_types = [];
/** @var NodeType $type */
foreach (NodeType::loadMultiple() as $id => $type) {
$all_types[$id] = $type->label();
}
$allowed_node_types = [];
foreach ($settings['mm_list_nodetypes'] as $node_type) {
if (!empty($node_type)) {
$allowed_node_types[] = $node_type;
}
}
$table_header = [
['data' => t('Type'), 'field' => 'fd.type'],
['data' => t('Title'), 'field' => 'fd.title'],
['data' => t('Last Modified'), 'field' => 'fd.changed', 'sort' => 'desc'],
];
$select = $database->select('node', 'n');
$select->addTag(__FUNCTION__);
$select->join('mm_node2tree', 'm', 'm.nid = n.nid');
$select->join('node_field_data', 'fd', 'fd.nid = n.nid');
$select->fields('fd', ['nid', 'title', 'type', 'changed']);
$select->condition('m.mmtid', $mmtid);
$select->condition('n.type', $allowed_node_types ?: array_keys($all_types), 'IN');
$select->condition('fd.status', 1);
if ($search_terms = $this->getSearchTerms($query)) {
foreach ($search_terms as $term) {
// $term is already sanitized in ::getSearchTerms().
$select->where("fd.title REGEXP '" . $term . "'");
}
}
$result = $select->extend(TableSortExtender::class)
->orderByHeader($table_header)
->extend(PagerSelectExtender::class)
->limit(mm_get_setting('nodes.nodelist_pager_limit'))
->execute();
$nids = [];
foreach ($result as $r) {
$nids[$r->nid] = $all_types[$r->type];
}
$nodes = Node::loadMultiple(array_keys($nids));
$rows = [];
foreach ($nids as $nid => $name) {
$row = [];
/** @var NodeInterface $node */
$node = $nodes[$nid];
$file = NULL;
// FIXME: This won't work because there is no mm_media type anymore.
// While we could look through all the fields on a node searching for
// File, Image or Media entities, this isn't always the best thing to do.
// if ($node->getType() == 'mm_media' && isset($node->field_multimedia[$node->language][0]['fid'])) {
// $file = File::load($node->field_multimedia[$node->language][0]['fid']);
// if ($file) {
// $name .= ' - ' . $file->getMimeType();
// if (!empty($node->label())) {
// $file->set('title', Html::escape($node->label()));
// }
// }
// }
$link = $this->getLink($mode, $node, $mmtid, $file);
$row[] = Html::escape($name);
$row[] = FilteredMarkup::create($link);
$row[] = mm_format_date($node->getChangedTime(), 'custom', 'M j, Y g:i A');
$rows[] = $row;
}
if (!$rows) {
$msg = !empty($search_terms) ? t('There is no selectable content on this page which matches the filter.') : t('There is no selectable content on this page.');
$content = ['#markup' => '<p>' . $msg . '</p>'];
$this->removeSearchAction();
}
else {
$content = [
[
'#type' => 'table',
'#header' => $table_header,
'#rows' => $rows,
],
[
'#type' => 'pager',
'#route_name' => 'monster_menus.browser_getright',
'#tags' => NULL,
'#element' => 0,
],
];
}
return $content;
}
/**
* Get the appropriate link for the current mode.
*
* @param string $mode
* Display mode constant
* @param NodeInterface|File $item
* Can be a node, can be a file, etc., depending on browser mode
* @param $mmtid
* MMTID of the current page
* @param File $file
* Optional File entity to generate a thumbnail
* @return string|array
* The HTML code or render array of the link
*/
private function getLink($mode, &$item, $mmtid, File $file = NULL) {
$onclick = "Drupal.mm_browser_nodepicker_add({$mmtid}, '" . mm_ui_js_escape($item->label()) . "', {$item->id()});";
return mm_empty_anchor($item->label(), ['onclick' => $onclick]);
}
}
