Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /**
|
Chris@0
|
4 * @file
|
Chris@0
|
5 * Hooks specific to the Node module.
|
Chris@0
|
6 */
|
Chris@0
|
7
|
Chris@0
|
8 use Drupal\node\NodeInterface;
|
Chris@0
|
9 use Drupal\Component\Utility\Html;
|
Chris@0
|
10 use Drupal\Component\Utility\Xss;
|
Chris@0
|
11 use Drupal\Core\Access\AccessResult;
|
Chris@0
|
12
|
Chris@0
|
13 /**
|
Chris@0
|
14 * @addtogroup hooks
|
Chris@0
|
15 * @{
|
Chris@0
|
16 */
|
Chris@0
|
17
|
Chris@0
|
18 /**
|
Chris@0
|
19 * Inform the node access system what permissions the user has.
|
Chris@0
|
20 *
|
Chris@0
|
21 * This hook is for implementation by node access modules. In this hook,
|
Chris@0
|
22 * the module grants a user different "grant IDs" within one or more
|
Chris@0
|
23 * "realms". In hook_node_access_records(), the realms and grant IDs are
|
Chris@0
|
24 * associated with permission to view, edit, and delete individual nodes.
|
Chris@0
|
25 *
|
Chris@0
|
26 * The realms and grant IDs can be arbitrarily defined by your node access
|
Chris@0
|
27 * module; it is common to use role IDs as grant IDs, but that is not required.
|
Chris@0
|
28 * Your module could instead maintain its own list of users, where each list has
|
Chris@0
|
29 * an ID. In that case, the return value of this hook would be an array of the
|
Chris@0
|
30 * list IDs that this user is a member of.
|
Chris@0
|
31 *
|
Chris@0
|
32 * A node access module may implement as many realms as necessary to properly
|
Chris@0
|
33 * define the access privileges for the nodes. Note that the system makes no
|
Chris@0
|
34 * distinction between published and unpublished nodes. It is the module's
|
Chris@0
|
35 * responsibility to provide appropriate realms to limit access to unpublished
|
Chris@0
|
36 * content.
|
Chris@0
|
37 *
|
Chris@0
|
38 * Node access records are stored in the {node_access} table and define which
|
Chris@0
|
39 * grants are required to access a node. There is a special case for the view
|
Chris@0
|
40 * operation -- a record with node ID 0 corresponds to a "view all" grant for
|
Chris@0
|
41 * the realm and grant ID of that record. If there are no node access modules
|
Chris@0
|
42 * enabled, the core node module adds a node ID 0 record for realm 'all'. Node
|
Chris@0
|
43 * access modules can also grant "view all" permission on their custom realms;
|
Chris@0
|
44 * for example, a module could create a record in {node_access} with:
|
Chris@0
|
45 * @code
|
Chris@0
|
46 * $record = array(
|
Chris@0
|
47 * 'nid' => 0,
|
Chris@0
|
48 * 'gid' => 888,
|
Chris@0
|
49 * 'realm' => 'example_realm',
|
Chris@0
|
50 * 'grant_view' => 1,
|
Chris@0
|
51 * 'grant_update' => 0,
|
Chris@0
|
52 * 'grant_delete' => 0,
|
Chris@0
|
53 * );
|
Chris@18
|
54 * \Drupal::database()->insert('node_access')->fields($record)->execute();
|
Chris@0
|
55 * @endcode
|
Chris@0
|
56 * And then in its hook_node_grants() implementation, it would need to return:
|
Chris@0
|
57 * @code
|
Chris@0
|
58 * if ($op == 'view') {
|
Chris@0
|
59 * $grants['example_realm'] = array(888);
|
Chris@0
|
60 * }
|
Chris@0
|
61 * @endcode
|
Chris@0
|
62 * If you decide to do this, be aware that the node_access_rebuild() function
|
Chris@0
|
63 * will erase any node ID 0 entry when it is called, so you will need to make
|
Chris@0
|
64 * sure to restore your {node_access} record after node_access_rebuild() is
|
Chris@0
|
65 * called.
|
Chris@0
|
66 *
|
Chris@0
|
67 * For a detailed example, see node_access_example.module.
|
Chris@0
|
68 *
|
Chris@0
|
69 * @param \Drupal\Core\Session\AccountInterface $account
|
Chris@0
|
70 * The account object whose grants are requested.
|
Chris@0
|
71 * @param string $op
|
Chris@0
|
72 * The node operation to be performed, such as 'view', 'update', or 'delete'.
|
Chris@0
|
73 *
|
Chris@0
|
74 * @return array
|
Chris@0
|
75 * An array whose keys are "realms" of grants, and whose values are arrays of
|
Chris@0
|
76 * the grant IDs within this realm that this user is being granted.
|
Chris@0
|
77 *
|
Chris@0
|
78 * @see node_access_view_all_nodes()
|
Chris@0
|
79 * @see node_access_rebuild()
|
Chris@0
|
80 * @ingroup node_access
|
Chris@0
|
81 */
|
Chris@0
|
82 function hook_node_grants(\Drupal\Core\Session\AccountInterface $account, $op) {
|
Chris@0
|
83 if ($account->hasPermission('access private content')) {
|
Chris@0
|
84 $grants['example'] = [1];
|
Chris@0
|
85 }
|
Chris@0
|
86 if ($account->id()) {
|
Chris@0
|
87 $grants['example_author'] = [$account->id()];
|
Chris@0
|
88 }
|
Chris@0
|
89 return $grants;
|
Chris@0
|
90 }
|
Chris@0
|
91
|
Chris@0
|
92 /**
|
Chris@0
|
93 * Set permissions for a node to be written to the database.
|
Chris@0
|
94 *
|
Chris@0
|
95 * When a node is saved, a module implementing hook_node_access_records() will
|
Chris@0
|
96 * be asked if it is interested in the access permissions for a node. If it is
|
Chris@0
|
97 * interested, it must respond with an array of permissions arrays for that
|
Chris@0
|
98 * node.
|
Chris@0
|
99 *
|
Chris@0
|
100 * Node access grants apply regardless of the published or unpublished status
|
Chris@0
|
101 * of the node. Implementations must make sure not to grant access to
|
Chris@0
|
102 * unpublished nodes if they don't want to change the standard access control
|
Chris@0
|
103 * behavior. Your module may need to create a separate access realm to handle
|
Chris@0
|
104 * access to unpublished nodes.
|
Chris@0
|
105 *
|
Chris@0
|
106 * Note that the grant values in the return value from your hook must be
|
Chris@0
|
107 * integers and not boolean TRUE and FALSE.
|
Chris@0
|
108 *
|
Chris@0
|
109 * Each permissions item in the array is an array with the following elements:
|
Chris@0
|
110 * - 'realm': The name of a realm that the module has defined in
|
Chris@0
|
111 * hook_node_grants().
|
Chris@0
|
112 * - 'gid': A 'grant ID' from hook_node_grants().
|
Chris@0
|
113 * - 'grant_view': If set to 1 a user that has been identified as a member
|
Chris@0
|
114 * of this gid within this realm can view this node. This should usually be
|
Chris@0
|
115 * set to $node->isPublished(). Failure to do so may expose unpublished content
|
Chris@0
|
116 * to some users.
|
Chris@0
|
117 * - 'grant_update': If set to 1 a user that has been identified as a member
|
Chris@0
|
118 * of this gid within this realm can edit this node.
|
Chris@0
|
119 * - 'grant_delete': If set to 1 a user that has been identified as a member
|
Chris@0
|
120 * of this gid within this realm can delete this node.
|
Chris@0
|
121 * - langcode: (optional) The language code of a specific translation of the
|
Chris@0
|
122 * node, if any. Modules may add this key to grant different access to
|
Chris@0
|
123 * different translations of a node, such that (e.g.) a particular group is
|
Chris@0
|
124 * granted access to edit the Catalan version of the node, but not the
|
Chris@0
|
125 * Hungarian version. If no value is provided, the langcode is set
|
Chris@0
|
126 * automatically from the $node parameter and the node's original language (if
|
Chris@0
|
127 * specified) is used as a fallback. Only specify multiple grant records with
|
Chris@0
|
128 * different languages for a node if the site has those languages configured.
|
Chris@0
|
129 *
|
Chris@0
|
130 * A "deny all" grant may be used to deny all access to a particular node or
|
Chris@0
|
131 * node translation:
|
Chris@0
|
132 * @code
|
Chris@0
|
133 * $grants[] = array(
|
Chris@0
|
134 * 'realm' => 'all',
|
Chris@0
|
135 * 'gid' => 0,
|
Chris@0
|
136 * 'grant_view' => 0,
|
Chris@0
|
137 * 'grant_update' => 0,
|
Chris@0
|
138 * 'grant_delete' => 0,
|
Chris@0
|
139 * 'langcode' => 'ca',
|
Chris@0
|
140 * );
|
Chris@0
|
141 * @endcode
|
Chris@0
|
142 * Note that another module node access module could override this by granting
|
Chris@0
|
143 * access to one or more nodes, since grants are additive. To enforce that
|
Chris@0
|
144 * access is denied in a particular case, use hook_node_access_records_alter().
|
Chris@0
|
145 * Also note that a deny all is not written to the database; denies are
|
Chris@0
|
146 * implicit.
|
Chris@0
|
147 *
|
Chris@0
|
148 * @param \Drupal\node\NodeInterface $node
|
Chris@0
|
149 * The node that has just been saved.
|
Chris@0
|
150 *
|
Chris@0
|
151 * @return
|
Chris@0
|
152 * An array of grants as defined above.
|
Chris@0
|
153 *
|
Chris@0
|
154 * @see hook_node_access_records_alter()
|
Chris@0
|
155 * @ingroup node_access
|
Chris@0
|
156 */
|
Chris@0
|
157 function hook_node_access_records(\Drupal\node\NodeInterface $node) {
|
Chris@0
|
158 // We only care about the node if it has been marked private. If not, it is
|
Chris@0
|
159 // treated just like any other node and we completely ignore it.
|
Chris@0
|
160 if ($node->private->value) {
|
Chris@0
|
161 $grants = [];
|
Chris@0
|
162 // Only published Catalan translations of private nodes should be viewable
|
Chris@0
|
163 // to all users. If we fail to check $node->isPublished(), all users would be able
|
Chris@0
|
164 // to view an unpublished node.
|
Chris@0
|
165 if ($node->isPublished()) {
|
Chris@0
|
166 $grants[] = [
|
Chris@0
|
167 'realm' => 'example',
|
Chris@0
|
168 'gid' => 1,
|
Chris@0
|
169 'grant_view' => 1,
|
Chris@0
|
170 'grant_update' => 0,
|
Chris@0
|
171 'grant_delete' => 0,
|
Chris@17
|
172 'langcode' => 'ca',
|
Chris@0
|
173 ];
|
Chris@0
|
174 }
|
Chris@0
|
175 // For the example_author array, the GID is equivalent to a UID, which
|
Chris@0
|
176 // means there are many groups of just 1 user.
|
Chris@0
|
177 // Note that an author can always view his or her nodes, even if they
|
Chris@0
|
178 // have status unpublished.
|
Chris@0
|
179 if ($node->getOwnerId()) {
|
Chris@0
|
180 $grants[] = [
|
Chris@0
|
181 'realm' => 'example_author',
|
Chris@0
|
182 'gid' => $node->getOwnerId(),
|
Chris@0
|
183 'grant_view' => 1,
|
Chris@0
|
184 'grant_update' => 1,
|
Chris@0
|
185 'grant_delete' => 1,
|
Chris@17
|
186 'langcode' => 'ca',
|
Chris@0
|
187 ];
|
Chris@0
|
188 }
|
Chris@0
|
189
|
Chris@0
|
190 return $grants;
|
Chris@0
|
191 }
|
Chris@0
|
192 }
|
Chris@0
|
193
|
Chris@0
|
194 /**
|
Chris@0
|
195 * Alter permissions for a node before it is written to the database.
|
Chris@0
|
196 *
|
Chris@0
|
197 * Node access modules establish rules for user access to content. Node access
|
Chris@0
|
198 * records are stored in the {node_access} table and define which permissions
|
Chris@0
|
199 * are required to access a node. This hook is invoked after node access modules
|
Chris@0
|
200 * returned their requirements via hook_node_access_records(); doing so allows
|
Chris@0
|
201 * modules to modify the $grants array by reference before it is stored, so
|
Chris@0
|
202 * custom or advanced business logic can be applied.
|
Chris@0
|
203 *
|
Chris@0
|
204 * Upon viewing, editing or deleting a node, hook_node_grants() builds a
|
Chris@0
|
205 * permissions array that is compared against the stored access records. The
|
Chris@0
|
206 * user must have one or more matching permissions in order to complete the
|
Chris@0
|
207 * requested operation.
|
Chris@0
|
208 *
|
Chris@0
|
209 * A module may deny all access to a node by setting $grants to an empty array.
|
Chris@0
|
210 *
|
Chris@0
|
211 * The preferred use of this hook is in a module that bridges multiple node
|
Chris@0
|
212 * access modules with a configurable behavior, as shown in the example with the
|
Chris@0
|
213 * 'is_preview' field.
|
Chris@0
|
214 *
|
Chris@0
|
215 * @param array $grants
|
Chris@0
|
216 * The $grants array returned by hook_node_access_records().
|
Chris@0
|
217 * @param \Drupal\node\NodeInterface $node
|
Chris@0
|
218 * The node for which the grants were acquired.
|
Chris@0
|
219 *
|
Chris@0
|
220 * @see hook_node_access_records()
|
Chris@0
|
221 * @see hook_node_grants()
|
Chris@0
|
222 * @see hook_node_grants_alter()
|
Chris@0
|
223 * @ingroup node_access
|
Chris@0
|
224 */
|
Chris@0
|
225 function hook_node_access_records_alter(&$grants, Drupal\node\NodeInterface $node) {
|
Chris@0
|
226 // Our module allows editors to mark specific articles with the 'is_preview'
|
Chris@0
|
227 // field. If the node being saved has a TRUE value for that field, then only
|
Chris@0
|
228 // our grants are retained, and other grants are removed. Doing so ensures
|
Chris@0
|
229 // that our rules are enforced no matter what priority other grants are given.
|
Chris@0
|
230 if ($node->is_preview) {
|
Chris@0
|
231 // Our module grants are set in $grants['example'].
|
Chris@0
|
232 $temp = $grants['example'];
|
Chris@0
|
233 // Now remove all module grants but our own.
|
Chris@0
|
234 $grants = ['example' => $temp];
|
Chris@0
|
235 }
|
Chris@0
|
236 }
|
Chris@0
|
237
|
Chris@0
|
238 /**
|
Chris@0
|
239 * Alter user access rules when trying to view, edit or delete a node.
|
Chris@0
|
240 *
|
Chris@0
|
241 * Node access modules establish rules for user access to content.
|
Chris@0
|
242 * hook_node_grants() defines permissions for a user to view, edit or delete
|
Chris@0
|
243 * nodes by building a $grants array that indicates the permissions assigned to
|
Chris@0
|
244 * the user by each node access module. This hook is called to allow modules to
|
Chris@0
|
245 * modify the $grants array by reference, so the interaction of multiple node
|
Chris@0
|
246 * access modules can be altered or advanced business logic can be applied.
|
Chris@0
|
247 *
|
Chris@0
|
248 * The resulting grants are then checked against the records stored in the
|
Chris@0
|
249 * {node_access} table to determine if the operation may be completed.
|
Chris@0
|
250 *
|
Chris@0
|
251 * A module may deny all access to a user by setting $grants to an empty array.
|
Chris@0
|
252 *
|
Chris@0
|
253 * Developers may use this hook to either add additional grants to a user or to
|
Chris@0
|
254 * remove existing grants. These rules are typically based on either the
|
Chris@0
|
255 * permissions assigned to a user role, or specific attributes of a user
|
Chris@0
|
256 * account.
|
Chris@0
|
257 *
|
Chris@0
|
258 * @param array $grants
|
Chris@0
|
259 * The $grants array returned by hook_node_grants().
|
Chris@0
|
260 * @param \Drupal\Core\Session\AccountInterface $account
|
Chris@0
|
261 * The account requesting access to content.
|
Chris@0
|
262 * @param string $op
|
Chris@0
|
263 * The operation being performed, 'view', 'update' or 'delete'.
|
Chris@0
|
264 *
|
Chris@0
|
265 * @see hook_node_grants()
|
Chris@0
|
266 * @see hook_node_access_records()
|
Chris@0
|
267 * @see hook_node_access_records_alter()
|
Chris@0
|
268 * @ingroup node_access
|
Chris@0
|
269 */
|
Chris@0
|
270 function hook_node_grants_alter(&$grants, \Drupal\Core\Session\AccountInterface $account, $op) {
|
Chris@0
|
271 // Our sample module never allows certain roles to edit or delete
|
Chris@0
|
272 // content. Since some other node access modules might allow this
|
Chris@0
|
273 // permission, we expressly remove it by returning an empty $grants
|
Chris@0
|
274 // array for roles specified in our variable setting.
|
Chris@0
|
275
|
Chris@0
|
276 // Get our list of banned roles.
|
Chris@0
|
277 $restricted = \Drupal::config('example.settings')->get('restricted_roles');
|
Chris@0
|
278
|
Chris@0
|
279 if ($op != 'view' && !empty($restricted)) {
|
Chris@0
|
280 // Now check the roles for this account against the restrictions.
|
Chris@0
|
281 foreach ($account->getRoles() as $rid) {
|
Chris@0
|
282 if (in_array($rid, $restricted)) {
|
Chris@0
|
283 $grants = [];
|
Chris@0
|
284 }
|
Chris@0
|
285 }
|
Chris@0
|
286 }
|
Chris@0
|
287 }
|
Chris@0
|
288
|
Chris@0
|
289 /**
|
Chris@0
|
290 * Controls access to a node.
|
Chris@0
|
291 *
|
Chris@0
|
292 * Modules may implement this hook if they want to have a say in whether or not
|
Chris@0
|
293 * a given user has access to perform a given operation on a node.
|
Chris@0
|
294 *
|
Chris@0
|
295 * The administrative account (user ID #1) always passes any access check, so
|
Chris@0
|
296 * this hook is not called in that case. Users with the "bypass node access"
|
Chris@0
|
297 * permission may always view and edit content through the administrative
|
Chris@0
|
298 * interface.
|
Chris@0
|
299 *
|
Chris@17
|
300 * The access to a node can be influenced in several ways:
|
Chris@17
|
301 * - To explicitly allow access, return an AccessResultInterface object with
|
Chris@17
|
302 * isAllowed() returning TRUE. Other modules can override this access by
|
Chris@17
|
303 * returning TRUE for isForbidden().
|
Chris@17
|
304 * - To explicitly forbid access, return an AccessResultInterface object with
|
Chris@17
|
305 * isForbidden() returning TRUE. Access will be forbidden even if your module
|
Chris@17
|
306 * (or another module) also returns TRUE for isNeutral() or isAllowed().
|
Chris@17
|
307 * - To neither allow nor explicitly forbid access, return an
|
Chris@17
|
308 * AccessResultInterface object with isNeutral() returning TRUE.
|
Chris@17
|
309 * - If your module does not return an AccessResultInterface object, neutral
|
Chris@17
|
310 * access will be assumed.
|
Chris@0
|
311 *
|
Chris@0
|
312 * Also note that this function isn't called for node listings (e.g., RSS feeds,
|
Chris@0
|
313 * the default home page at path 'node', a recent content block, etc.) See
|
Chris@0
|
314 * @link node_access Node access rights @endlink for a full explanation.
|
Chris@0
|
315 *
|
Chris@0
|
316 * @param \Drupal\node\NodeInterface|string $node
|
Chris@0
|
317 * Either a node entity or the machine name of the content type on which to
|
Chris@0
|
318 * perform the access check.
|
Chris@0
|
319 * @param string $op
|
Chris@0
|
320 * The operation to be performed. Possible values:
|
Chris@0
|
321 * - "create"
|
Chris@0
|
322 * - "delete"
|
Chris@0
|
323 * - "update"
|
Chris@0
|
324 * - "view"
|
Chris@0
|
325 * @param \Drupal\Core\Session\AccountInterface $account
|
Chris@0
|
326 * The user object to perform the access check operation on.
|
Chris@0
|
327 *
|
Chris@0
|
328 * @return \Drupal\Core\Access\AccessResultInterface
|
Chris@0
|
329 * The access result.
|
Chris@0
|
330 *
|
Chris@0
|
331 * @ingroup node_access
|
Chris@0
|
332 */
|
Chris@0
|
333 function hook_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Session\AccountInterface $account) {
|
Chris@0
|
334 $type = $node->bundle();
|
Chris@0
|
335
|
Chris@0
|
336 switch ($op) {
|
Chris@0
|
337 case 'create':
|
Chris@0
|
338 return AccessResult::allowedIfHasPermission($account, 'create ' . $type . ' content');
|
Chris@0
|
339
|
Chris@0
|
340 case 'update':
|
Chris@17
|
341 if ($account->hasPermission('edit any ' . $type . ' content')) {
|
Chris@0
|
342 return AccessResult::allowed()->cachePerPermissions();
|
Chris@0
|
343 }
|
Chris@0
|
344 else {
|
Chris@17
|
345 return AccessResult::allowedIf($account->hasPermission('edit own ' . $type . ' content') && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node);
|
Chris@0
|
346 }
|
Chris@0
|
347
|
Chris@0
|
348 case 'delete':
|
Chris@17
|
349 if ($account->hasPermission('delete any ' . $type . ' content')) {
|
Chris@0
|
350 return AccessResult::allowed()->cachePerPermissions();
|
Chris@0
|
351 }
|
Chris@0
|
352 else {
|
Chris@17
|
353 return AccessResult::allowedIf($account->hasPermission('delete own ' . $type . ' content') && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node);
|
Chris@0
|
354 }
|
Chris@0
|
355
|
Chris@0
|
356 default:
|
Chris@0
|
357 // No opinion.
|
Chris@0
|
358 return AccessResult::neutral();
|
Chris@0
|
359 }
|
Chris@0
|
360 }
|
Chris@0
|
361
|
Chris@0
|
362 /**
|
Chris@0
|
363 * Act on a node being displayed as a search result.
|
Chris@0
|
364 *
|
Chris@0
|
365 * This hook is invoked from the node search plugin during search execution,
|
Chris@0
|
366 * after loading and rendering the node.
|
Chris@0
|
367 *
|
Chris@0
|
368 * @param \Drupal\node\NodeInterface $node
|
Chris@0
|
369 * The node being displayed in a search result.
|
Chris@0
|
370 *
|
Chris@0
|
371 * @return array
|
Chris@0
|
372 * Extra information to be displayed with search result. This information
|
Chris@0
|
373 * should be presented as an associative array. It will be concatenated with
|
Chris@0
|
374 * the post information (last updated, author) in the default search result
|
Chris@0
|
375 * theming.
|
Chris@0
|
376 *
|
Chris@0
|
377 * @see template_preprocess_search_result()
|
Chris@0
|
378 * @see search-result.html.twig
|
Chris@0
|
379 *
|
Chris@0
|
380 * @ingroup entity_crud
|
Chris@0
|
381 */
|
Chris@0
|
382 function hook_node_search_result(\Drupal\node\NodeInterface $node) {
|
Chris@0
|
383 $rating = db_query('SELECT SUM(points) FROM {my_rating} WHERE nid = :nid', ['nid' => $node->id()])->fetchField();
|
Chris@0
|
384 return ['rating' => \Drupal::translation()->formatPlural($rating, '1 point', '@count points')];
|
Chris@0
|
385 }
|
Chris@0
|
386
|
Chris@0
|
387 /**
|
Chris@0
|
388 * Act on a node being indexed for searching.
|
Chris@0
|
389 *
|
Chris@0
|
390 * This hook is invoked during search indexing, after loading, and after the
|
Chris@0
|
391 * result of rendering is added as $node->rendered to the node object.
|
Chris@0
|
392 *
|
Chris@0
|
393 * @param \Drupal\node\NodeInterface $node
|
Chris@0
|
394 * The node being indexed.
|
Chris@0
|
395 *
|
Chris@0
|
396 * @return string
|
Chris@0
|
397 * Additional node information to be indexed.
|
Chris@0
|
398 *
|
Chris@0
|
399 * @ingroup entity_crud
|
Chris@0
|
400 */
|
Chris@0
|
401 function hook_node_update_index(\Drupal\node\NodeInterface $node) {
|
Chris@0
|
402 $text = '';
|
Chris@0
|
403 $ratings = db_query('SELECT title, description FROM {my_ratings} WHERE nid = :nid', [':nid' => $node->id()]);
|
Chris@0
|
404 foreach ($ratings as $rating) {
|
Chris@0
|
405 $text .= '<h2>' . Html::escape($rating->title) . '</h2>' . Xss::filter($rating->description);
|
Chris@0
|
406 }
|
Chris@0
|
407 return $text;
|
Chris@0
|
408 }
|
Chris@0
|
409
|
Chris@0
|
410 /**
|
Chris@0
|
411 * Provide additional methods of scoring for core search results for nodes.
|
Chris@0
|
412 *
|
Chris@0
|
413 * A node's search score is used to rank it among other nodes matched by the
|
Chris@0
|
414 * search, with the highest-ranked nodes appearing first in the search listing.
|
Chris@0
|
415 *
|
Chris@0
|
416 * For example, a module allowing users to vote on content could expose an
|
Chris@0
|
417 * option to allow search results' rankings to be influenced by the average
|
Chris@0
|
418 * voting score of a node.
|
Chris@0
|
419 *
|
Chris@0
|
420 * All scoring mechanisms are provided as options to site administrators, and
|
Chris@0
|
421 * may be tweaked based on individual sites or disabled altogether if they do
|
Chris@0
|
422 * not make sense. Individual scoring mechanisms, if enabled, are assigned a
|
Chris@0
|
423 * weight from 1 to 10. The weight represents the factor of magnification of
|
Chris@0
|
424 * the ranking mechanism, with higher-weighted ranking mechanisms having more
|
Chris@0
|
425 * influence. In order for the weight system to work, each scoring mechanism
|
Chris@0
|
426 * must return a value between 0 and 1 for every node. That value is then
|
Chris@0
|
427 * multiplied by the administrator-assigned weight for the ranking mechanism,
|
Chris@0
|
428 * and then the weighted scores from all ranking mechanisms are added, which
|
Chris@0
|
429 * brings about the same result as a weighted average.
|
Chris@0
|
430 *
|
Chris@0
|
431 * @return array
|
Chris@0
|
432 * An associative array of ranking data. The keys should be strings,
|
Chris@0
|
433 * corresponding to the internal name of the ranking mechanism, such as
|
Chris@0
|
434 * 'recent', or 'comments'. The values should be arrays themselves, with the
|
Chris@0
|
435 * following keys available:
|
Chris@0
|
436 * - title: (required) The human readable name of the ranking mechanism.
|
Chris@0
|
437 * - join: (optional) An array with information to join any additional
|
Chris@0
|
438 * necessary table. This is not necessary if the table required is already
|
Chris@0
|
439 * joined to by the base query, such as for the {node} table. Other tables
|
Chris@0
|
440 * should use the full table name as an alias to avoid naming collisions.
|
Chris@0
|
441 * - score: (required) The part of a query string to calculate the score for
|
Chris@0
|
442 * the ranking mechanism based on values in the database. This does not need
|
Chris@0
|
443 * to be wrapped in parentheses, as it will be done automatically; it also
|
Chris@0
|
444 * does not need to take the weighted system into account, as it will be
|
Chris@0
|
445 * done automatically. It does, however, need to calculate a decimal between
|
Chris@0
|
446 * 0 and 1; be careful not to cast the entire score to an integer by
|
Chris@0
|
447 * inadvertently introducing a variable argument.
|
Chris@0
|
448 * - arguments: (optional) If any arguments are required for the score, they
|
Chris@0
|
449 * can be specified in an array here.
|
Chris@0
|
450 *
|
Chris@0
|
451 * @ingroup entity_crud
|
Chris@0
|
452 */
|
Chris@0
|
453 function hook_ranking() {
|
Chris@0
|
454 // If voting is disabled, we can avoid returning the array, no hard feelings.
|
Chris@0
|
455 if (\Drupal::config('vote.settings')->get('node_enabled')) {
|
Chris@0
|
456 return [
|
Chris@0
|
457 'vote_average' => [
|
Chris@0
|
458 'title' => t('Average vote'),
|
Chris@0
|
459 // Note that we use i.sid, the search index's search item id, rather than
|
Chris@0
|
460 // n.nid.
|
Chris@0
|
461 'join' => [
|
Chris@0
|
462 'type' => 'LEFT',
|
Chris@0
|
463 'table' => 'vote_node_data',
|
Chris@0
|
464 'alias' => 'vote_node_data',
|
Chris@0
|
465 'on' => 'vote_node_data.nid = i.sid',
|
Chris@0
|
466 ],
|
Chris@0
|
467 // The highest possible score should be 1, and the lowest possible score,
|
Chris@0
|
468 // always 0, should be 0.
|
Chris@0
|
469 'score' => 'vote_node_data.average / CAST(%f AS DECIMAL)',
|
Chris@0
|
470 // Pass in the highest possible voting score as a decimal argument.
|
Chris@0
|
471 'arguments' => [\Drupal::config('vote.settings')->get('score_max')],
|
Chris@0
|
472 ],
|
Chris@0
|
473 ];
|
Chris@0
|
474 }
|
Chris@0
|
475 }
|
Chris@0
|
476
|
Chris@0
|
477 /**
|
Chris@0
|
478 * Alter the links of a node.
|
Chris@0
|
479 *
|
Chris@0
|
480 * @param array &$links
|
Chris@0
|
481 * A renderable array representing the node links.
|
Chris@0
|
482 * @param \Drupal\node\NodeInterface $entity
|
Chris@0
|
483 * The node being rendered.
|
Chris@0
|
484 * @param array &$context
|
Chris@0
|
485 * Various aspects of the context in which the node links are going to be
|
Chris@0
|
486 * displayed, with the following keys:
|
Chris@0
|
487 * - 'view_mode': the view mode in which the node is being viewed
|
Chris@0
|
488 * - 'langcode': the language in which the node is being viewed
|
Chris@0
|
489 *
|
Chris@0
|
490 * @see \Drupal\node\NodeViewBuilder::renderLinks()
|
Chris@0
|
491 * @see \Drupal\node\NodeViewBuilder::buildLinks()
|
Chris@0
|
492 * @see entity_crud
|
Chris@0
|
493 */
|
Chris@0
|
494 function hook_node_links_alter(array &$links, NodeInterface $entity, array &$context) {
|
Chris@0
|
495 $links['mymodule'] = [
|
Chris@0
|
496 '#theme' => 'links__node__mymodule',
|
Chris@0
|
497 '#attributes' => ['class' => ['links', 'inline']],
|
Chris@0
|
498 '#links' => [
|
Chris@0
|
499 'node-report' => [
|
Chris@0
|
500 'title' => t('Report'),
|
Chris@0
|
501 'url' => Url::fromRoute('node_test.report', ['node' => $entity->id()], ['query' => ['token' => \Drupal::getContainer()->get('csrf_token')->get("node/{$entity->id()}/report")]]),
|
Chris@0
|
502 ],
|
Chris@0
|
503 ],
|
Chris@0
|
504 ];
|
Chris@0
|
505 }
|
Chris@0
|
506
|
Chris@0
|
507 /**
|
Chris@0
|
508 * @} End of "addtogroup hooks".
|
Chris@0
|
509 */
|