2015-08-17 17:00:26 -07:00
< ? php
/**
* @ file
* Contains \Drupal\node\Controller\NodeController .
*/
namespace Drupal\node\Controller ;
2015-09-04 13:20:09 -07:00
use Drupal\Component\Utility\Xss ;
2015-08-17 17:00:26 -07:00
use Drupal\Core\Controller\ControllerBase ;
2015-10-08 11:40:12 -07:00
use Drupal\Core\Datetime\DateFormatterInterface ;
2015-08-17 17:00:26 -07:00
use Drupal\Core\DependencyInjection\ContainerInjectionInterface ;
2015-10-08 11:40:12 -07:00
use Drupal\Core\Language\LanguageInterface ;
2015-08-17 17:00:26 -07:00
use Drupal\Core\Render\RendererInterface ;
use Drupal\Core\Url ;
use Drupal\node\NodeTypeInterface ;
use Drupal\node\NodeInterface ;
use Symfony\Component\DependencyInjection\ContainerInterface ;
/**
* Returns responses for Node routes .
*/
class NodeController extends ControllerBase implements ContainerInjectionInterface {
/**
* The date formatter service .
*
2015-10-08 11:40:12 -07:00
* @ var \Drupal\Core\Datetime\DateFormatterInterface
2015-08-17 17:00:26 -07:00
*/
protected $dateFormatter ;
/**
* The renderer service .
*
* @ var \Drupal\Core\Render\RendererInterface
*/
protected $renderer ;
/**
* Constructs a NodeController object .
*
2015-10-08 11:40:12 -07:00
* @ param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
2015-08-17 17:00:26 -07:00
* The date formatter service .
* @ param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service .
*/
2015-10-08 11:40:12 -07:00
public function __construct ( DateFormatterInterface $date_formatter , RendererInterface $renderer ) {
2015-08-17 17:00:26 -07:00
$this -> dateFormatter = $date_formatter ;
$this -> renderer = $renderer ;
}
/**
* { @ inheritdoc }
*/
public static function create ( ContainerInterface $container ) {
return new static (
$container -> get ( 'date.formatter' ),
$container -> get ( 'renderer' )
);
}
/**
* Displays add content links for available content types .
*
* Redirects to node / add / [ type ] if only one content type is available .
*
2015-09-04 13:20:09 -07:00
* @ return array | \Symfony\Component\HttpFoundation\RedirectResponse
2015-08-17 17:00:26 -07:00
* A render array for a list of the node types that can be added ; however ,
* if there is only one node type defined for the site , the function
2015-09-04 13:20:09 -07:00
* will return a RedirectResponse to the node add page for that one node
* type .
2015-08-17 17:00:26 -07:00
*/
public function addPage () {
2015-10-08 11:40:12 -07:00
$build = [
'#theme' => 'node_add_list' ,
'#cache' => [
'tags' => $this -> entityManager () -> getDefinition ( 'node_type' ) -> getListCacheTags (),
],
];
2015-08-17 17:00:26 -07:00
$content = array ();
// Only use node types the user has access to.
foreach ( $this -> entityManager () -> getStorage ( 'node_type' ) -> loadMultiple () as $type ) {
2015-10-08 11:40:12 -07:00
$access = $this -> entityManager () -> getAccessControlHandler ( 'node' ) -> createAccess ( $type -> id (), NULL , [], TRUE );
if ( $access -> isAllowed ()) {
2015-08-17 17:00:26 -07:00
$content [ $type -> id ()] = $type ;
}
2015-10-08 11:40:12 -07:00
$this -> renderer -> addCacheableDependency ( $build , $access );
2015-08-17 17:00:26 -07:00
}
// Bypass the node/add listing if only one content type is available.
if ( count ( $content ) == 1 ) {
$type = array_shift ( $content );
return $this -> redirect ( 'node.add' , array ( 'node_type' => $type -> id ()));
}
2015-10-08 11:40:12 -07:00
$build [ '#content' ] = $content ;
return $build ;
2015-08-17 17:00:26 -07:00
}
/**
* Provides the node submission form .
*
* @ param \Drupal\node\NodeTypeInterface $node_type
* The node type entity for the node .
*
* @ return array
* A node submission form .
*/
public function add ( NodeTypeInterface $node_type ) {
$node = $this -> entityManager () -> getStorage ( 'node' ) -> create ( array (
'type' => $node_type -> id (),
));
$form = $this -> entityFormBuilder () -> getForm ( $node );
return $form ;
}
/**
* Displays a node revision .
*
* @ param int $node_revision
* The node revision ID .
*
* @ return array
* An array suitable for drupal_render () .
*/
public function revisionShow ( $node_revision ) {
$node = $this -> entityManager () -> getStorage ( 'node' ) -> loadRevision ( $node_revision );
$node_view_controller = new NodeViewController ( $this -> entityManager , $this -> renderer );
$page = $node_view_controller -> view ( $node );
unset ( $page [ 'nodes' ][ $node -> id ()][ '#cache' ]);
return $page ;
}
/**
* Page title callback for a node revision .
*
* @ param int $node_revision
* The node revision ID .
*
* @ return string
* The page title .
*/
public function revisionPageTitle ( $node_revision ) {
$node = $this -> entityManager () -> getStorage ( 'node' ) -> loadRevision ( $node_revision );
return $this -> t ( 'Revision of %title from %date' , array ( '%title' => $node -> label (), '%date' => format_date ( $node -> getRevisionCreationTime ())));
}
/**
* Generates an overview table of older revisions of a node .
*
* @ param \Drupal\node\NodeInterface $node
* A node object .
*
* @ return array
* An array as expected by drupal_render () .
*/
public function revisionOverview ( NodeInterface $node ) {
$account = $this -> currentUser ();
2015-10-08 11:40:12 -07:00
$langcode = $this -> languageManager () -> getCurrentLanguage ( LanguageInterface :: TYPE_CONTENT ) -> getId ();
$langname = $this -> languageManager () -> getLanguageName ( $langcode );
$languages = $node -> getTranslationLanguages ();
$has_translations = ( count ( $languages ) > 1 );
2015-08-17 17:00:26 -07:00
$node_storage = $this -> entityManager () -> getStorage ( 'node' );
$type = $node -> getType ();
2015-10-08 11:40:12 -07:00
$build [ '#title' ] = $has_translations ? $this -> t ( '@langname revisions for %title' , [ '@langname' => $langname , '%title' => $node -> label ()]) : $this -> t ( 'Revisions for %title' , [ '%title' => $node -> label ()]);
2015-08-17 17:00:26 -07:00
$header = array ( $this -> t ( 'Revision' ), $this -> t ( 'Operations' ));
$revert_permission = (( $account -> hasPermission ( " revert $type revisions " ) || $account -> hasPermission ( 'revert all revisions' ) || $account -> hasPermission ( 'administer nodes' )) && $node -> access ( 'update' ));
$delete_permission = (( $account -> hasPermission ( " delete $type revisions " ) || $account -> hasPermission ( 'delete all revisions' ) || $account -> hasPermission ( 'administer nodes' )) && $node -> access ( 'delete' ));
$rows = array ();
$vids = $node_storage -> revisionIds ( $node );
2015-10-08 11:40:12 -07:00
$latest_revision = TRUE ;
2015-08-17 17:00:26 -07:00
foreach ( array_reverse ( $vids ) as $vid ) {
2015-10-08 11:40:12 -07:00
/** @var \Drupal\node\NodeInterface $revision */
2015-08-27 12:03:05 -07:00
$revision = $node_storage -> loadRevision ( $vid );
2015-10-08 11:40:12 -07:00
if ( $revision -> hasTranslation ( $langcode ) && $revision -> getTranslation ( $langcode ) -> isRevisionTranslationAffected ()) {
$username = [
'#theme' => 'username' ,
'#account' => $revision -> uid -> entity ,
];
2015-08-27 12:03:05 -07:00
2015-10-08 11:40:12 -07:00
// Use revision link to link to revisions that are not active.
$date = $this -> dateFormatter -> format ( $revision -> revision_timestamp -> value , 'short' );
if ( $vid != $node -> getRevisionId ()) {
$link = $this -> l ( $date , new Url ( 'entity.node.revision' , [ 'node' => $node -> id (), 'node_revision' => $vid ]));
}
else {
$link = $node -> link ( $date );
}
$row = [];
$column = [
2015-09-04 13:20:09 -07:00
'data' => [
2015-10-08 11:40:12 -07:00
'#type' => 'inline_template' ,
'#template' => '{% trans %}{{ date }} by {{ username }}{% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}' ,
'#context' => [
'date' => $link ,
'username' => $this -> renderer -> renderPlain ( $username ),
'message' => [ '#markup' => $revision -> revision_log -> value , '#allowed_tags' => Xss :: getHtmlTagList ()],
],
2015-09-04 13:20:09 -07:00
],
2015-08-27 12:03:05 -07:00
];
2015-10-08 11:40:12 -07:00
// @todo Simplify once https://www.drupal.org/node/2334319 lands.
$this -> renderer -> addCacheableDependency ( $column [ 'data' ], $username );
$row [] = $column ;
if ( $latest_revision ) {
$row [] = [
'data' => [
'#prefix' => '<em>' ,
'#markup' => $this -> t ( 'Current revision' ),
'#suffix' => '</em>' ,
],
2015-08-27 12:03:05 -07:00
];
2015-10-08 11:40:12 -07:00
foreach ( $row as & $current ) {
$current [ 'class' ] = [ 'revision-current' ];
}
$latest_revision = FALSE ;
2015-08-17 17:00:26 -07:00
}
2015-10-08 11:40:12 -07:00
else {
$links = [];
if ( $revert_permission ) {
$links [ 'revert' ] = [
'title' => $this -> t ( 'Revert' ),
'url' => $has_translations ?
Url :: fromRoute ( 'node.revision_revert_translation_confirm' , [ 'node' => $node -> id (), 'node_revision' => $vid , 'langcode' => $langcode ]) :
Url :: fromRoute ( 'node.revision_revert_confirm' , [ 'node' => $node -> id (), 'node_revision' => $vid ]),
];
}
if ( $delete_permission ) {
$links [ 'delete' ] = [
'title' => $this -> t ( 'Delete' ),
'url' => Url :: fromRoute ( 'node.revision_delete_confirm' , [ 'node' => $node -> id (), 'node_revision' => $vid ]),
];
}
$row [] = [
'data' => [
'#type' => 'operations' ,
'#links' => $links ,
],
2015-08-27 12:03:05 -07:00
];
2015-08-17 17:00:26 -07:00
}
2015-10-08 11:40:12 -07:00
$rows [] = $row ;
2015-08-17 17:00:26 -07:00
}
}
$build [ 'node_revisions_table' ] = array (
'#theme' => 'table' ,
'#rows' => $rows ,
'#header' => $header ,
'#attached' => array (
'library' => array ( 'node/drupal.node.admin' ),
),
);
return $build ;
}
/**
* The _title_callback for the node . add route .
*
* @ param \Drupal\node\NodeTypeInterface $node_type
* The current node .
*
* @ return string
* The page title .
*/
public function addPageTitle ( NodeTypeInterface $node_type ) {
return $this -> t ( 'Create @name' , array ( '@name' => $node_type -> label ()));
}
}