addField('s', 'nid'); $query->addJoin('INNER', 'node', 'n', 's.nid = n.nid'); $query->addJoin('INNER', 'users', 'u', 'u.uid = n.uid'); $query->condition('s.publish_on', 0, '>'); $query->condition('s.publish_on', REQUEST_TIME, '<='); $query_result = $query->execute(); $nids = array(); while ($node = $query_result->fetchObject()) { $nids[] = $node->nid; } $action = 'publish'; // Allow other modules to add to the list of nodes to be published. $nids = array_unique(array_merge($nids, _scheduler_scheduler_nid_list($action))); // Allow other modules to alter the list of nodes to be published. drupal_alter('scheduler_nid_list', $nids, $action); foreach ($nids as $nid) { $n = node_load($nid); // Check that scheduled publishing is (still) enabled for this type. if (!variable_get('scheduler_publish_enable_' . $n->type, 0)) { continue; } // Check that other modules allow the action on this node. if (!_scheduler_allow($n, $action)) { continue; } // Update timestamps. $n->changed = $n->publish_on; $old_creation_date = $n->created; if (variable_get('scheduler_publish_touch_' . $n->type, 0) == 1) { $n->created = $n->publish_on; } $create_publishing_revision = variable_get('scheduler_publish_revision_' . $n->type, 0) == 1; if ($create_publishing_revision) { $n->revision = TRUE; // Use a core date format to guarantee a time is included. $n->log = t('Node published by Scheduler on @now. Previous creation date was @date.', array( '@now' => format_date(REQUEST_TIME, 'short'), '@date' => format_date($old_creation_date, 'short'), )); } // Unset publish_on so the node will not get rescheduled by subsequent calls // to node_save(). Save the value for use when calling Rules. $publish_on = $n->publish_on; $n->publish_on = NULL; // Invoke scheduler API to allow modules to alter the node before it is // saved. // For 8.x this 'pre' call is moved up to just before 'Update timestamps'. // See https://www.drupal.org/node/2311273 _scheduler_scheduler_api($n, 'pre_' . $action); // Use the actions system to publish the node. watchdog('scheduler', '@type: scheduled publishing of %title.', array('@type' => $n->type, '%title' => $n->title), WATCHDOG_NOTICE, l(t('view'), 'node/' . $n->nid, array('alias' => TRUE))); $actions = array('node_publish_action', 'node_save_action'); $context['node'] = $n; actions_do($actions, $n, $context, NULL, NULL); // Invoke the event to tell Rules that Scheduler has published this node. if (module_exists('rules')) { rules_invoke_event('scheduler_node_has_been_published_event', $n, $publish_on, $n->unpublish_on); } // Invoke scheduler API for modules to react after the node is published. _scheduler_scheduler_api($n, $action); $result = TRUE; } return $result; } /** * Unpublish scheduled nodes. * * @return bool * TRUE is any node has been unpublished, FALSE otherwise. */ function _scheduler_unpublish() { $result = FALSE; // If the time is greater than the time to unpublish a node, unpublish it. // The INNER join on 'node' and 'users' is just to ensure the nodes are valid. $query = db_select('scheduler', 's'); $query->addField('s', 'nid'); $query->addJoin('INNER', 'node', 'n', 's.nid = n.nid'); $query->addJoin('INNER', 'users', 'u', 'u.uid = n.uid'); $query->condition('s.unpublish_on', 0, '>'); $query->condition('s.unpublish_on', REQUEST_TIME, '<='); $query_result = $query->execute(); $nids = array(); while ($node = $query_result->fetchObject()) { $nids[] = $node->nid; } $action = 'unpublish'; // Allow other modules to add to the list of nodes to be unpublished. $nids = array_unique(array_merge($nids, _scheduler_scheduler_nid_list($action))); // Allow other modules to alter the list of nodes to be unpublished. drupal_alter('scheduler_nid_list', $nids, $action); foreach ($nids as $nid) { $n = node_load($nid); // Check that scheduled publishing is (still) enabled for this type. if (!variable_get('scheduler_unpublish_enable_' . $n->type, 0)) { continue; } // Check that other modules allow the action on this node. if (!_scheduler_allow($n, $action)) { continue; } // Do not process the node if it has a publish_on time which is in the past, // as this implies that scheduled publishing has been blocked by one of the // API functions we provide. Hence unpublishing should be halted too. if (!empty($n->publish_on) && $n->publish_on <= REQUEST_TIME) { continue; } // Update timestamps. $old_change_date = $n->changed; $n->changed = $n->unpublish_on; $create_unpublishing_revision = variable_get('scheduler_unpublish_revision_' . $n->type, 0) == 1; if ($create_unpublishing_revision) { $n->revision = TRUE; // Use a core date format to guarantee a time is included. $n->log = t('Node unpublished by Scheduler on @now. Previous change date was @date.', array( '@now' => format_date(REQUEST_TIME, 'short'), '@date' => format_date($old_change_date, 'short'), )); } // Unset unpublish_on so the node will not get rescheduled by subsequent // calls to node_save(). Save the value for use when calling Rules. $unpublish_on = $n->unpublish_on; $n->unpublish_on = NULL; // Invoke scheduler API to allow modules to alter the node before it is // saved. // For 8.x this 'pre' call is moved up to just before 'Update timestamps'. // See https://www.drupal.org/node/2311273 _scheduler_scheduler_api($n, 'pre_' . $action); // Use the actions system to unpublish the node. watchdog('scheduler', '@type: scheduled unpublishing of %title.', array('@type' => $n->type, '%title' => $n->title), WATCHDOG_NOTICE, l(t('view'), 'node/' . $n->nid, array('alias' => TRUE))); $actions = array('node_unpublish_action', 'node_save_action'); $context['node'] = $n; actions_do($actions, $n, $context, NULL, NULL); // Invoke event to tell Rules that Scheduler has unpublished this node. if (module_exists('rules')) { rules_invoke_event('scheduler_node_has_been_unpublished_event', $n, $n->publish_on, $unpublish_on); } // Invoke scheduler API for modules to react after the node is unpublished. _scheduler_scheduler_api($n, 'unpublish'); $result = TRUE; } return $result; } /** * Gather node IDs for all nodes that need to be $action'ed. * * @param string $action * The action being performed, either "publish" or "unpublish". * * @return array * An array of node ids. */ function _scheduler_scheduler_nid_list($action) { $nids = array(); foreach (module_implements('scheduler_nid_list') as $module) { $function = $module . '_scheduler_nid_list'; $nids = array_merge($nids, $function($action)); } return $nids; } /** * Run the lightweight cron. * * The Scheduler part of the processing performed here is the same as in the * normal Drupal cron run. The difference is that only scheduler_cron() is * executed, no other modules hook_cron() functions are called. * * This function is called from the external crontab job via url /scheduler/cron * or it can be run interactively from the Scheduler configuration page at * /admin/config/content/scheduler/cron. */ function _scheduler_run_cron() { $log = variable_get('scheduler_lightweight_log', 1); if ($log) { watchdog('scheduler', 'Lightweight cron run activated', array(), WATCHDOG_NOTICE); } scheduler_cron(); if (ob_get_level() > 0) { $handlers = ob_list_handlers(); if (isset($handlers[0]) && $handlers[0] == 'default output handler') { ob_clean(); } } if ($log) { watchdog('scheduler', 'Lightweight cron run completed', array(), WATCHDOG_NOTICE, l(t('settings'), 'admin/config/content/scheduler/cron')); } $menu_item = menu_get_item(); if ($menu_item['path'] == 'admin/config/content/scheduler/cron') { // This cron run has been initiated manually from the configuration form. // Give a message and return something so that an output page is created. // No output should be returned if running from a crontab job. if (module_exists('dblog')) { drupal_set_message(t('Lightweight cron run completed - see log for details.', array('@url' => url('admin/reports/dblog')))); } else { drupal_set_message(t('Lightweight cron run completed.')); } return ' '; } // drupal_exit() is the proper controlled way to terminate the request, as // this will invoke all implementations of hook_exit(). drupal_exit(); }