log.module 27.2 KB
Newer Older
1
2
3
4
<?php

/**
 * @file
m.stenta's avatar
m.stenta committed
5
 * Log - A general purpose record keeping system.
6
7
8
9
10
11
12
13
14
15
 */

/****************************************************************
 * Drupal hooks
 * **************************************************************/

/**
 * Implements hook_permission().
 */
function log_permission() {
16
  $perms = array(
17
18
19
20
21
22
    'administer log module' => array(
      'title' => t('Administer log module'),
      'description' => t('Gives full access to everything in the log module.'),
      'restrict access' => TRUE,
    ),
    'administer log types' => array(
m.stenta's avatar
m.stenta committed
23
      'title' => t('Administer log types'),
24
25
      'restrict access' => TRUE,
    ),
26
27
28
29
    'view all logs' => array(
      'title' => t('View all log entities'),
      'description' => t('Allows users to view the full list of log entities.'),
    ),
30
  );
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

  // Add permissions for each log type.
  foreach (log_types() as $log_type) {
    $type = $log_type->type;
    $ops = array('view', 'edit', 'delete');
    $scopes = array('any', 'own');
    $perms += array(
      "create $type log entities" => array(
        'title' => t('Create new %type_name log entities', array('%type_name' => $log_type->label)),
      ),
    );
    foreach ($ops as $op) {
      foreach ($scopes as $scope) {
        $perms += array(
          "$op $scope $type log entities" => array(
m.stenta's avatar
m.stenta committed
46
            'title' => drupal_ucfirst($op) . ' ' . $scope . ' ' . t('%type_name log entities', array('%type_name' => $log_type->label)),
47
48
49
50
51
52
53
          ),
        );
      }
    }
  }

  return $perms;
54
55
56
57
58
59
60
61
62
63
64
}

/**
 * Implements hook_menu().
 */
function log_menu() {
  $items = array();

  $items['log/add'] = array(
    'title' => 'Add log',
    'page callback' => 'log_add_types_page',
65
    'access callback' => 'log_add_access',
66
    'file' => 'log.pages.inc',
67
  );
68
69
70
71
72
73
74
75
76
77
  foreach (log_types() as $type => $info) {
    $items['log/add/' . $type] = array(
      'title' => 'Add log',
      'page callback' => 'log_add',
      'page arguments' => array(2),
      'access callback' => 'log_access',
      'access arguments' => array('create', 2),
      'file' => 'log.pages.inc',
    );
  }
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

  $log_uri = 'log/%log';
  $log_uri_argument_position = 1;

  $items[$log_uri] = array(
    'title callback' => 'entity_label',
    'title arguments' => array('log', $log_uri_argument_position),
    'page callback' => 'log_view',
    'page arguments' => array($log_uri_argument_position),
    'access callback' => 'log_access',
    'access arguments' => array('view', $log_uri_argument_position),
    'file' => 'log.pages.inc',
  );

  $items[$log_uri . '/view'] = array(
    'title' => 'View',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -10,
  );

  $items[$log_uri . '/delete'] = array(
    'title' => 'Delete log',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('log_delete_form', $log_uri_argument_position),
    'access callback' => 'log_access',
103
    'access arguments' => array('update', $log_uri_argument_position),
104
    'file' => 'log.pages.inc',
105
106
107
108
109
110
111
  );

  $items[$log_uri . '/edit'] = array(
    'title' => 'Edit',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('log_form', $log_uri_argument_position),
    'access callback' => 'log_access',
112
    'access arguments' => array('update', $log_uri_argument_position),
113
    'file' => 'log.pages.inc',
114
115
116
117
    'type' => MENU_LOCAL_TASK,
    'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
  );

m.stenta's avatar
m.stenta committed
118
  // Log settings form.
119
120
121
122
  $items['admin/config/log'] = array(
    'title' => 'Log',
    'description' => 'Configure log module.',
    'page callback' => 'system_admin_menu_block_page',
123
    'access arguments' => array('administer log module'),
124
125
126
127
128
129
130
131
132
133
134
135
    'file' => 'system.admin.inc',
    'file path' => drupal_get_path('module', 'system'),
  );
  $items['admin/config/log/settings'] = array(
    'title' => 'Log settings',
    'description' => 'Administer log settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('log_settings_form', 4),
    'access arguments' => array('administer log module'),
    'file' => 'log.admin.inc',
  );

m.stenta's avatar
m.stenta committed
136
  // Log type delete form.
137
  $items['admin/config/log/types/%log_type/delete'] = array(
138
139
140
141
142
143
144
145
146
147
148
149
    'title' => 'Delete',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('log_type_form_delete_confirm', 4),
    'access arguments' => array('administer log types'),
    'weight' => 1,
    'type' => MENU_NORMAL_ITEM,
    'file' => 'log.admin.inc',
  );

  return $items;
}

150
151
152
153
/**
 * Implements hook_admin_paths().
 */
function log_admin_paths() {
154
155

  // Display log paths with the admin theme, if specified.
m.stenta's avatar
m.stenta committed
156
  $paths = array();
157
158
159
160
161
  if (variable_get('log_admin_theme', TRUE)) {
    $paths = array(
      'log*' => TRUE,
    );
  }
m.stenta's avatar
m.stenta committed
162
  return $paths;
163
164
}

165
166
167
168
169
170
171
172
173
174
175
176
/**
 * Implements hook_entity_info().
 */
function log_entity_info() {
  $return = array(
    'log' => array(
      'label' => t('Log'),
      'entity class' => 'Log',
      'controller class' => 'LogController',
      'base table' => 'log',
      'fieldable' => TRUE,
      'entity keys' => array(
m.stenta's avatar
m.stenta committed
177
        'id' => 'id',
178
        'bundle' => 'type',
179
        'label' => 'name',
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
      ),
      'bundle keys' => array(
        'bundle' => 'type',
      ),
      'bundles' => array(),
      'load hook' => 'log_load',
      'view modes' => array(
        'full' => array(
          'label' => t('Default'),
          'custom settings' => FALSE,
        ),
      ),
      'label callback' => 'entity_class_label',
      'uri callback' => 'entity_class_uri',
      'module' => 'log',
      'access callback' => 'log_access',
    ),
  );
  $return['log_type'] = array(
    'label' => t('Log type'),
    'entity class' => 'LogType',
    'controller class' => 'LogTypeController',
    'base table' => 'log_type',
    'fieldable' => FALSE,
    'bundle of' => 'log',
    'exportable' => TRUE,
    'entity keys' => array(
      'id' => 'id',
      'name' => 'type',
      'label' => 'label',
    ),
    'module' => 'log',
m.stenta's avatar
m.stenta committed
212
    // Enable the entity API admin UI.
213
    'admin ui' => array(
214
      'path' => 'admin/config/log/types',
215
216
217
218
219
220
221
222
223
224
225
      'file' => 'log.admin.inc',
      'controller class' => 'LogTypeUIController',
    ),
    'access callback' => 'log_type_access',
  );

  return $return;
}

/**
 * Implements hook_entity_info_alter().
m.stenta's avatar
m.stenta committed
226
227
 *
 * @inheritdoc
228
229
230
231
232
233
 */
function log_entity_info_alter(&$entity_info) {
  foreach (log_types() as $type => $info) {
    $entity_info['log']['bundles'][$type] = array(
      'label' => $info->label,
      'admin' => array(
234
235
        'path' => 'admin/config/log/types/manage/%log_type',
        'real path' => 'admin/config/log/types/manage/' . $type,
236
        'bundle argument' => 5,
237
238
239
240
241
242
243
244
245
246
      ),
    );
  }
}

/**
 * Implements hook_entity_property_info_alter().
 */
function log_entity_property_info_alter(&$info) {
  $properties = &$info['log']['properties'];
247
248
249
250
251
252
  $properties['name'] = array(
    'label' => t('Name'),
    'description' => t('The name of the log item.'),
    'setter callback' => 'entity_property_verbatim_set',
    'schema field' => 'name',
  );
253
  $properties['type'] = array(
254
    'label' => t('Log type'),
255
    'type' => 'token',
256
    'description' => t('The type of the log.'),
257
258
259
260
261
262
    'setter callback' => 'entity_property_verbatim_set',
    'setter permission' => 'administer log module',
    'options list' => 'log_type_get_names',
    'required' => TRUE,
    'schema field' => 'type',
  );
263
264
265
266
267
268
269
270
271
  $properties['uid'] = array(
    'label' => t('Owner'),
    'type' => 'user',
    'description' => t('The owner of the log.'),
    'setter callback' => 'entity_property_verbatim_set',
    'setter permission' => 'administer log module',
    'required' => TRUE,
    'schema field' => 'uid',
  );
272
273
274
275
276
277
278
279
280
  $properties['timestamp'] = array(
    'label' => t('Timestamp'),
    'type' => 'date',
    'description' => t('The timestamp of the event being logged.'),
    'setter callback' => 'entity_property_verbatim_set',
    'setter permission' => 'administer log module',
    'required' => TRUE,
    'schema field' => 'timestamp',
  );
281
282
  $properties['created'] = array(
    'label' => t('Created'),
283
    'type' => 'date',
m.stenta's avatar
m.stenta committed
284
    'description' => t('The timestamp when the log entity was created.'),
285
286
287
    'setter callback' => 'entity_property_verbatim_set',
    'setter permission' => 'administer log module',
    'required' => TRUE,
288
289
290
291
292
    'schema field' => 'created',
  );
  $properties['changed'] = array(
    'label' => t('Changed'),
    'type' => 'date',
m.stenta's avatar
m.stenta committed
293
    'description' => t('The timestamp when the log entity was last modified.'),
294
295
296
297
    'setter callback' => 'entity_property_verbatim_set',
    'setter permission' => 'administer log module',
    'required' => TRUE,
    'schema field' => 'changed',
298
  );
299
300
301
302
303
304
305
306
  $properties['done'] = array(
    'label' => t('Done'),
    'description' => t('Whether the log is done.'),
    'setter callback' => 'entity_property_verbatim_set',
    'setter permission' => 'administer log module',
    'schema field' => 'done',
    'type' => 'boolean',
  );
307
308
}

309
310
311
312
313
314
315
316
317
318
/**
 * Implements hook_field_extra_fields().
 */
function log_field_extra_fields() {
  $log_types = log_types();
  $extra_fields = array(
    'log' => array(),
  );
  foreach ($log_types as $type) {

319
320
321
322
323
324
325
326
    // Display the name field if names are editable.
    if ($type->name_edit) {
      $extra_fields['log'][$type->type]['form']['name'] = array(
        'label' => t('Name'),
        'description' => t('The name of the log entry.'),
        'weight' => -10,
      );
    }
327
328
329
330
331
332
333

    // Display the timestamp field.
    $extra_fields['log'][$type->type]['form']['timestamp'] = array(
      'label' => t('Timestamp'),
      'description' => t('The timestamp of the log entry.'),
      'weight' => -5,
    );
334
335
336
337
  }
  return $extra_fields;
}

m.stenta's avatar
m.stenta committed
338
/**
m.stenta's avatar
m.stenta committed
339
 * Implements hook_log_insert().
m.stenta's avatar
m.stenta committed
340
341
342
 */
function log_log_insert($log) {

343
344
  // Generate the log's name.
  log_name_generate($log);
m.stenta's avatar
m.stenta committed
345
346
}

347
/**
m.stenta's avatar
m.stenta committed
348
 * Implements hook_log_update().
349
350
351
 */
function log_log_update($log) {

352
353
  // Generate the log's name.
  log_name_generate($log);
354
355
}

356
357
358
359
360
361
362
363
364
365
/**
 * Implements hook_action_info().
 */
function log_action_info() {
  return array(
    'log_done_action' => array(
      'type' => 'log',
      'label' => t('Mark as done'),
      'configurable' => FALSE,
      'triggers' => array('any'),
366
367
368
369
370
371
372
    ),
    'log_undone_action' => array(
      'type' => 'log',
      'label' => t('Mark as not done'),
      'configurable' => FALSE,
      'triggers' => array('any'),
    ),
m.stenta's avatar
m.stenta committed
373
374
375
376
377
378
    'log_clone_action' => array(
      'type' => 'log',
      'label' => t('Clone'),
      'configurable' => TRUE,
      'triggers' => array('any'),
    ),
379
380
381
382
383
384
    'log_reschedule_action' => array(
      'type' => 'log',
      'label' => t('Reschedule'),
      'configurable' => TRUE,
      'triggers' => array('any'),
    ),
385
386
387
  );
}

388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
/**
 * Implements hook_filter_info().
 */
function log_filter_info() {
  $filters['log_filter'] = array(
    'title' => t('Parse log placeholders.'),
    'description' => t('Create links to logs with [log:ID] placeholders.'),
    'process callback' => 'log_filter_log',
    'tips callback' => 'log_filter_log_tips',
  );
  return $filters;
}

/***************************************************************
 * Log filter callback
 * *************************************************************/

/**
 * Parse log placeholders.
 */
function log_filter_log($text) {
409
410
411
412
413

  // Maintain a static array of log links that have been generated already.
  $links = &drupal_static(__FUNCTION__);

  // Look for pattern matches and iterate through them.
414
415
416
417
418
419
420
421
422
  $matches = array();
  preg_match_all('/\[log:[0-9]+\]/', $text, $matches);
  if (!empty($matches[0])) {
    foreach ($matches[0] as $match) {

      // Extract the log id.
      $id = str_replace('[log:', '', $match);
      $id = str_replace(']', '', $id);

423
424
      // If the log has not been loaded already...
      if (empty($links[$id])) {
425

426
427
        // Load the log's name from the database.
        $name = db_query('SELECT name FROM {log} WHERE id = :id', array(':id' => $id))->fetchField();
428

429
430
        // If the name is empty, skip it.
        if (empty($name)) {
431
432
433
434
          continue;
        }

        // Generate a link with the log's label.
435
        $link = l('[Log #' . $id . ': '. check_plain($name) . ']', 'log/' . $id);
436

437
438
439
440
441
442
443
444
445
        // Store the link in the static cache.
        $links[$id] = $link;
      }

      // If a link is available, replace all occurrences of the original token
      // in the text.
      if (!empty($links[$id])) {
        $text = str_replace($match, $links[$id], $text);
      }
446
447
    }
  }
448
449

  // Return the formatted text.
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
  return $text;
}

/**
 * Tips for parsing log placeholders.
 */
function log_filter_log_tips($filter, $format, $long = FALSE) {
  if ($long) {
    return t('Create links to logs with [log:ID] placeholders. Replace ID with the numerical ID of the log. The link will contain the log ID and title.');
  }
  else {
    return t('Create links to logs with [log:ID] placeholders.');
  }
}

465
466
467
468
469
470
471
472
473
/***************************************************************
 * Log action callbacks
 * *************************************************************/

/**
 * Action function for log_done_action.
 *
 * Marks a log as done.
 *
m.stenta's avatar
m.stenta committed
474
 * @param Log $log
475
476
477
478
 *   The log entity object.
 * @param array $context
 *   Array with parameters for this action.
 */
m.stenta's avatar
m.stenta committed
479
function log_done_action(Log $log, $context = array()) {
480
481
482
483
484
485
486
487
488

  // Only proceed if the log is not already done.
  if ($log->done) {
    return;
  }

  // Mark the log as done.
  $log->done = TRUE;

m.stenta's avatar
m.stenta committed
489
  // Save the log.
490
491
492
  log_save($log);
}

493
494
495
496
497
/**
 * Action function for log_undone_action.
 *
 * Marks a log as not done.
 *
m.stenta's avatar
m.stenta committed
498
 * @param Log $log
499
500
501
502
 *   The log entity object.
 * @param array $context
 *   Array with parameters for this action.
 */
m.stenta's avatar
m.stenta committed
503
function log_undone_action(Log $log, $context = array()) {
504
505
506
507
508
509
510
511
512

  // Only proceed if the log is already done.
  if (!$log->done) {
    return;
  }

  // Mark the log as done.
  $log->done = FALSE;

m.stenta's avatar
m.stenta committed
513
  // Save the log.
514
515
516
  log_save($log);
}

517
518
/**
 * Log reschedule action configuration form.
m.stenta's avatar
m.stenta committed
519
520
521
522
523
524
525
526
 *
 * @param array $context
 *   The context passed into the action form function.
 * @param array $form_state
 *   The form state passed into the action form function.
 *
 * @return array
 *   Returns a form array.
527
 */
m.stenta's avatar
m.stenta committed
528
function log_reschedule_action_form(array $context, array $form_state) {
529
530
531
532
533
  return _log_action_date_form($context, $form_state, 'Reschedule');
}

/**
 * Log reschedule action configuration form submit.
m.stenta's avatar
m.stenta committed
534
535
536
537
538
539
540
541
 *
 * @param array $form
 *   The form array.
 * @param array $form_state
 *   The form state array.
 *
 * @return array
 *   Returns an array that will end up in the action's context.
542
 */
m.stenta's avatar
m.stenta committed
543
function log_reschedule_action_submit(array $form, array $form_state) {
544
545
  return _log_action_date_form_submit($form, $form_state);
}
546

547
548
549
550
551
/**
 * Action function for log_reschedule_action.
 *
 * Changes the date of a log.
 *
m.stenta's avatar
m.stenta committed
552
 * @param Log $log
553
554
555
556
 *   The log entity object.
 * @param array $context
 *   Array with parameters for this action.
 */
m.stenta's avatar
m.stenta committed
557
function log_reschedule_action(Log $log, $context = array()) {
558
559
560
  _log_action_date_form_action($log, $context);
}

m.stenta's avatar
m.stenta committed
561
562
/**
 * Log clone action configuration form.
m.stenta's avatar
m.stenta committed
563
564
565
566
567
568
569
570
 *
 * @param array $context
 *   The context passed into the action form function.
 * @param array $form_state
 *   The form state passed into the action form function.
 *
 * @return array
 *   Returns a form array.
m.stenta's avatar
m.stenta committed
571
 */
m.stenta's avatar
m.stenta committed
572
function log_clone_action_form(array $context, array $form_state) {
573
  return _log_action_date_form($context, $form_state, 'Clone', FALSE);
m.stenta's avatar
m.stenta committed
574
575
576
577
}

/**
 * Log clone action configuration form submit.
m.stenta's avatar
m.stenta committed
578
579
580
581
582
583
584
585
 *
 * @param array $form
 *   The form array.
 * @param array $form_state
 *   The form state array.
 *
 * @return array
 *   Returns an array that will end up in the action's context.
m.stenta's avatar
m.stenta committed
586
 */
m.stenta's avatar
m.stenta committed
587
function log_clone_action_submit(array $form, array $form_state) {
m.stenta's avatar
m.stenta committed
588
589
590
591
592
593
594
595
  return _log_action_date_form_submit($form, $form_state);
}

/**
 * Action function for log_clone_action.
 *
 * Clones a log and gives it a new timestamp.
 *
m.stenta's avatar
m.stenta committed
596
 * @param Log $log
m.stenta's avatar
m.stenta committed
597
598
599
600
 *   The log entity object.
 * @param array $context
 *   Array with parameters for this action.
 */
m.stenta's avatar
m.stenta committed
601
function log_clone_action(Log $log, $context = array()) {
m.stenta's avatar
m.stenta committed
602
603
604
605
606
607
608
609

  // Clear the log id.
  unset($log->id);

  // Set the date and save.
  _log_action_date_form_action($log, $context);
}

610
611
612
/**
 * Log action form with date field (helper function).
 *
m.stenta's avatar
m.stenta committed
613
 * @param array $context
614
 *   The context passed into the action form function.
m.stenta's avatar
m.stenta committed
615
 * @param array $form_state
616
 *   The form state passed into the action form function.
m.stenta's avatar
m.stenta committed
617
 * @param string $name
618
 *   The action name.
m.stenta's avatar
m.stenta committed
619
 * @param bool $default_timestamp
620
 *   Whether or not to use the log's timestamp as default (defaults to TRUE).
621
622
623
624
 *
 * @return array
 *   Returns a form array.
 */
m.stenta's avatar
m.stenta committed
625
function _log_action_date_form(array $context, array $form_state, $name, $default_timestamp = TRUE) {
626
627

  // Build a list of the logs being cloned.
628
629
630
631
632
633
634
635
636
637
638
639
  if (!empty($form_state['selection'])) {
    $logs = array();
    $query = db_select('log', 'l');
    $query->addField('l', 'name');
    $query->condition('l.id', $form_state['selection']);
    $results = $query->execute();
    foreach ($results as $result) {
      $logs[] = $result->name;
    }

    // If there is more than one log, theme an item list.
    if (count($logs) > 1) {
m.stenta's avatar
m.stenta committed
640
      $markup = theme('item_list', array('items' => $logs, 'title' => $name . ':'));
641
642
643
644
    }

    // Otherwise, display the one.
    else {
m.stenta's avatar
m.stenta committed
645
      $markup = '<h3>' . $name . ' ' . reset($logs) . '</h3>';
646
647
    }

648
    // Display the log(s) in the form.
649
650
651
652
653
654
655
    $form['logs'] = array(
      '#type' => 'markup',
      '#markup' => $markup,
    );
  }

  // Default timestamp to today.
656
657
  $timestamp = REQUEST_TIME;

658
659
660
  // If only one log item is selected, and the $default_timestamp parameter is
  // set, use it's timestamp as the default.
  if (!empty($logs) && count($logs) == 1 && $default_timestamp) {
661
662
663
664
665
666
667
668
    $log_id = reset($form_state['selection']);
    $log = log_load($log_id);
    $timestamp = $log->timestamp;
  }

  // Convert the timestamp to the format Date API expects.
  $default_value = date('Y-m-d H:i', $timestamp);

m.stenta's avatar
m.stenta committed
669
  // "Date" field.
670
671
672
673
674
675
  $form['timestamp'] = array(
    '#type' => 'date_select',
    '#title' => t('Date'),
    '#date_format' => 'M j Y',
    '#date_type' => DATE_FORMAT_UNIX,
    '#date_year_range' => '-10:+3',
676
    '#default_value' => $default_value,
677
678
679
680
681
682
683
    '#required' => TRUE,
  );

  return $form;
}

/**
684
685
 * Log action form with date field submit (helper function).
 *
m.stenta's avatar
m.stenta committed
686
687
688
 * @param array $form
 *   The form passed into the action form submit function.
 * @param array $form_state
689
690
691
692
 *   The form state passed into the action form submit function.
 *
 * @return array
 *   Returns an array that will end up in the action's context.
693
 */
m.stenta's avatar
m.stenta committed
694
function _log_action_date_form_submit(array $form, array $form_state) {
695
696
697
698
699
700
  return array(
    'timestamp' => $form_state['values']['timestamp'],
  );
}

/**
701
 * Log action form with date field (action helper function).
702
 *
m.stenta's avatar
m.stenta committed
703
704
705
 * @param Log $log
 *   The log passed into the action function.
 * @param array $context
706
 *   The context passed into the action function.
707
 */
m.stenta's avatar
m.stenta committed
708
function _log_action_date_form_action(Log $log, array $context) {
709
710
711
712
713
714
715

  // Set the date.
  $log->timestamp = strtotime($context['timestamp']);

  // Mark the log as "not done".
  $log->done = FALSE;

716
  // Save the log.
717
718
719
  log_save($log);
}

720
721
722
723
724
725
726
/***************************************************************
 * Access functions
 * *************************************************************/

/**
 * Access callback for log entities.
 *
m.stenta's avatar
m.stenta committed
727
 * @param string $op
728
 *   The operation being performed. One of 'view', 'update', 'create', 'delete'.
m.stenta's avatar
m.stenta committed
729
730
731
 * @param Log|string $log
 *   Optionally a specific log entity to check, or a log type.
 * @param object $account
732
733
 *   The user to check for. Leave it to NULL to check for the global user.
 *
m.stenta's avatar
m.stenta committed
734
 * @return bool
735
736
737
 *   Whether access is allowed or not.
 */
function log_access($op, $log = NULL, $account = NULL) {
738
  $rights = &drupal_static(__FUNCTION__, array());
739

740
741
  // If $op is not one of the supported ones, deny access.
  if (!in_array($op, array('create', 'view', 'update', 'delete'), TRUE)) {
742
743
744
    return FALSE;
  }
  // If no user object is supplied, the access check is for the current user.
745
746
747
748
749
  if (empty($account)) {
    global $user;
    $account = $user;
  }

750
751
752
753
754
  // If no log is provided, check for access to all logs.
  if (empty($log)) {
    return user_access('view all logs', $account);
  }

755
756
757
758
759
760
761
762
763
764
  // $log may be either an object or a log type. Since log types cannot be
  // an integer, use either id or type as the static cache id.
  $cid = is_object($log) ? $log->id : $log;

  // If we've already checked access for this log, user and op, return from
  // cache.
  if (isset($rights[$account->uid][$cid][$op])) {
    return $rights[$account->uid][$cid][$op];
  }

765
766
  // If the user has 'administer log module' permission, grant them access.
  if (user_access('administer log module', $account)) {
767
    $rights[$account->uid][$cid][$op] = TRUE;
768
769
770
    return TRUE;
  }

771
772
773
774
775
776
  // Check access to the log based on it's type.
  $type = is_string($log) ? $log : $log->type;
  $log_types = log_types();
  $type_names = array();
  foreach ($log_types as $name => $log_type) {
    $type_names[] = $name;
777
  }
778
779
780
781
782
  if (in_array($type, $type_names)) {
    if ($op == 'create' && user_access('create ' . $type . ' log entities', $account)) {
      $rights[$account->uid][$cid][$op] = TRUE;
      return TRUE;
    }
783

784
785
786
787
788
789
    if ($op == 'view') {
      if (user_access('view any ' . $type . ' log entities', $account) || (user_access('view own ' . $type . ' log entities', $account) && ($account->uid == $log->uid))) {
        $rights[$account->uid][$cid][$op] = TRUE;
        return TRUE;
      }
    }
790

791
    if ($op == 'update') {
792
793
794
795
796
797
798
799
800
801
802
      if (user_access('edit any ' . $type . ' log entities', $account) || (user_access('edit own ' . $type . ' log entities', $account) && ($account->uid == $log->uid))) {
        $rights[$account->uid][$cid][$op] = TRUE;
        return TRUE;
      }
    }

    if ($op == 'delete') {
      if (user_access('delete any ' . $type . ' log entities', $account) || (user_access('delete own ' . $type . ' log entities', $account) && ($account->uid == $log->uid))) {
        $rights[$account->uid][$cid][$op] = TRUE;
        return TRUE;
      }
803
    }
804
805
806
807
808
809
810
811
812
  }

  // If all else fails, deny access.
  return FALSE;
}

/**
 * Access callback: Checks whether the user has permission to add a log.
 *
m.stenta's avatar
m.stenta committed
813
814
815
816
817
 * @param object|null $account
 *   Optionally, a user account to check access for.
 *
 * @return bool
 *   Returns TRUE if the user has add permission, otherwise FALSE.
818
819
820
821
822
823
824
825
 */
function log_add_access($account = NULL) {

  // If no user object is supplied, the access check is for the current user.
  if (empty($account)) {
    global $user;
    $account = $user;
  }
826

827
828
829
830
831
  // Check each of the log types to see if the user has access.
  $types = log_types();
  foreach ($types as $type) {
    if (log_access('create', $type->type, $account)) {
      return TRUE;
832
833
834
835
836
837
838
839
840
    }
  }

  // If all else fails, deny access.
  return FALSE;
}

/**
 * Access callback for log type.
m.stenta's avatar
m.stenta committed
841
842
843
844
845
846
847
848
 *
 * @param string $op
 *   The operation being performed.
 * @param Log|null $log
 *   Optionally, a log entity to check access for.
 *
 * @return bool
 *   Returns TRUE if user has access.
849
850
851
852
853
854
855
856
857
858
859
 */
function log_type_access($op, $log = NULL) {
  return user_access('administer log types');
}

/***************************************************************
 * Log API functions
 * *************************************************************/

/**
 * Load a log.
m.stenta's avatar
m.stenta committed
860
861
862
863
864
865
866
867
 *
 * @param int $id
 *   The log id.
 * @param bool $reset
 *   Boolean: whether or not to reset the entity cache.
 *
 * @return Log
 *   Returns a log entity.
868
 */
m.stenta's avatar
m.stenta committed
869
870
function log_load($id, $reset = FALSE) {
  $logs = log_load_multiple(array($id), array(), $reset);
871
872
873
874
875
  return reset($logs);
}

/**
 * Load multiple logs based on certain conditions.
m.stenta's avatar
m.stenta committed
876
877
878
879
880
881
882
883
884
885
 *
 * @param array|bool $ids
 *   An array of log ids.
 * @param array $conditions
 *   An array of log load conditions.
 * @param bool $reset
 *   Boolean: whether or not to reset the entity cache.
 *
 * @return array
 *   Returns an array of logs.
886
 */
m.stenta's avatar
m.stenta committed
887
function log_load_multiple($ids = FALSE, $conditions = array(), $reset = FALSE) {
m.stenta's avatar
m.stenta committed
888
  return entity_load('log', $ids, $conditions, $reset);
889
890
891
892
}

/**
 * Save log.
m.stenta's avatar
m.stenta committed
893
894
895
 *
 * @param Log $log
 *   The log entity.
896
 */
m.stenta's avatar
m.stenta committed
897
function log_save(Log $log) {
898
899
900
901
902
  entity_save('log', $log);
}

/**
 * Delete single log.
m.stenta's avatar
m.stenta committed
903
904
905
 *
 * @param Log $log
 *   The log entity.
906
 */
m.stenta's avatar
m.stenta committed
907
908
function log_delete(Log $log) {
  entity_delete('log', entity_id('log', $log));
909
910
911
912
}

/**
 * Delete multiple logs.
m.stenta's avatar
m.stenta committed
913
914
915
 *
 * @param array $log_ids
 *   An array of log ids.
916
 */
m.stenta's avatar
m.stenta committed
917
function log_delete_multiple(array $log_ids) {
918
919
920
  entity_delete_multiple('log', $log_ids);
}

m.stenta's avatar
m.stenta committed
921
922
923
/**
 * Generate a log name.
 *
m.stenta's avatar
m.stenta committed
924
 * @param Log $log
m.stenta's avatar
m.stenta committed
925
926
927
 *   The log entity.
 *
 * @return string
928
 *   The log name.
m.stenta's avatar
m.stenta committed
929
 */
m.stenta's avatar
m.stenta committed
930
function log_name_generate(Log $log) {
931

932
  // If the log doesn't have an id, bail!
933
  if (empty($log->id) || !is_numeric($log->id)) {
934
    return $log->name;
935
936
  }

937
938
939
  // Load the log type.
  $log_type = log_type_load($log->type);

940
  // If the log type's name is editable, only generate a name if
941
  // the current name is empty.
942
943
944
945
  if (!empty($log_type->name_edit) && !empty($log->name)) {
    return $log->name;
  }

946
947
  // Get the name pattern from the log type.
  $pattern = $log_type->name_pattern;
948
949
950

  // If Token is installed, run replacements.
  if (module_exists('token')) {
951
    $name = token_replace($pattern, array('log' => $log), array('clear' => TRUE, 'sanitize' => FALSE));
952
953
954
955
956
957
958
  }

  // If Token is not available, at least replace the default [log:id].
  else {
    $name = str_replace('[log:id]', $log->id, $pattern);
  }

m.stenta's avatar
m.stenta committed
959
960
  // Strip extraneous spaces (explode on spaces, remove empty items, implode
  // with spaces).
961
962
  $name = implode(' ', array_filter(explode(' ', $name)));

963
964
965
966
967
  // If the name is empty, set it to a sensible default.
  if (empty($name)) {
    $name = 'Log ' . $log->id;
  }

968
969
970
  // If the name length is greater than 255 (the size of the database column),
  // truncate it with word-safe boundaries and an ellipsis.
  if (strlen($name) > 255) {
m.stenta's avatar
m.stenta committed
971
    $name = truncate_utf8($name, 255, TRUE, TRUE);
972
973
  }

974
975
976
977
978
979
980
981
  // Update the log's name in the database.
  db_update('log')
    ->fields(array('name' => $name))
    ->condition('id', $log->id)
    ->execute();

  // Return it.
  return $name;
m.stenta's avatar
m.stenta committed
982
983
}

984
985
986
987
988
/***************************************************************
 * Log type API functions
 * *************************************************************/

/**
m.stenta's avatar
m.stenta committed
989
 * Load log type.
m.stenta's avatar
m.stenta committed
990
991
992
993
994
995
 *
 * @param string $log_type
 *   The machine name of the log type to load.
 *
 * @return LogType
 *   Returns the log type requested.
996
997
998
999
1000
1001
 */
function log_type_load($log_type) {
  return log_types($log_type);
}

/**
m.stenta's avatar
m.stenta committed
1002
 * List of log types.
m.stenta's avatar
m.stenta committed
1003
1004
1005
1006
1007
1008
 *
 * @param string $type_name
 *   The name of the log type.
 *
 * @return LogType|array
 *   Returns the log type(s) requested.
1009
1010
1011
1012
1013
1014
1015
1016
 */
function log_types($type_name = NULL) {
  $types = entity_load_multiple_by_name('log_type', isset($type_name) ? array($type_name) : FALSE);
  return isset($type_name) ? reset($types) : $types;
}

/**
 * Save log type entity.
m.stenta's avatar
m.stenta committed
1017
1018
1019
 *
 * @param LogType $log_type
 *   The log type.
1020
 */
m.stenta's avatar
m.stenta committed
1021
function log_type_save(LogType $log_type) {
1022
1023
1024
1025
  entity_save('log_type', $log_type);
}

/**
m.stenta's avatar
m.stenta committed
1026
 * Delete single log type.
m.stenta's avatar
m.stenta committed
1027
1028
1029
 *
 * @param LogType $log_type
 *   The log type.
1030
 */
m.stenta's avatar
m.stenta committed
1031
1032
function log_type_delete(LogType $log_type) {
  entity_delete('log_type', entity_id('log_type', $log_type));
1033
1034
1035
}

/**
m.stenta's avatar
m.stenta committed
1036
 * Delete multiple log types.
m.stenta's avatar
m.stenta committed
1037
1038
1039
 *
 * @param array $log_type_ids
 *   Array of log type ids.
1040
 */
m.stenta's avatar
m.stenta committed
1041
function log_type_delete_multiple(array $log_type_ids) {
1042
  entity_delete_multiple('log_type', $log_type_ids);
1043
}
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

/**
 * Get the names of all log types.
 *
 * @return array
 *   Returns an array of log type names, keyed by machine name.
 */
function log_type_get_names() {
  $names = array();
  $types = log_types();
  foreach ($types as $type) {
    $names[$type->type] = $type->label;
  }
  return $names;
}