View source
<?php
function book_copy_perm() {
return array(
'copy books',
'view book history',
);
}
function book_copy_menu() {
$items['book_copy/copy/%node'] = array(
'title' => 'Clone a book',
'page callback' => 'book_copy_batch_copy',
'page arguments' => array(
2,
),
'access callback' => 'book_copy_can_copy',
'access arguments' => array(
2,
),
'type' => MENU_CALLBACK,
);
$items['book_copy/copy/%node/%node'] = array(
'title' => 'Clone a book',
'page callback' => 'book_copy_batch_copy',
'page arguments' => array(
2,
3,
),
'access callback' => 'book_copy_can_copy',
'access arguments' => array(
2,
3,
),
'type' => MENU_CALLBACK,
);
$items['book_copy/history/%node'] = array(
'title' => 'Show a Books history',
'page callback' => 'book_copy_show_history',
'page arguments' => array(
2,
),
'access arguments' => array(
'view book history',
),
'type' => MENU_CALLBACK,
);
$items['book_copy/explain/%node'] = array(
'title' => 'Book Copy Status',
'page callback' => 'book_copy_explain',
'page arguments' => array(
2,
3,
),
'access arguments' => array(
'copy books',
),
'type' => MENU_CALLBACK,
);
return $items;
}
function book_copy_link($type, $node = NULL, $teaser = FALSE) {
global $user;
$links = array();
if ($type == 'node' && isset($node->book) && !$teaser) {
if (user_access('view book history')) {
$links['book_copy_history'] = array(
'title' => t('Show Book History'),
'href' => 'book_copy/history/' . $node->book['bid'],
);
}
if (user_access('copy books')) {
if (book_copy_can_copy($node->book['bid'])) {
$links['book_copy_copy'] = array(
'title' => t('Derive a Copy'),
'href' => 'book_copy/copy/' . $node->book['bid'],
);
}
elseif (variable_get('book_copy_always_display_copy_links', TRUE)) {
$links['book_copy_copy'] = array(
'title' => t('Derive a Copy'),
'href' => 'book_copy/explain/' . $node->book['bid'],
);
}
if ($node->book['bid'] != $node->nid && book_copy_can_copy($node->book['bid'], $node->nid)) {
$links['book_copy_subtree'] = array(
'title' => t('Copy subtree'),
'href' => 'book_copy/copy/' . $node->book['bid'] . '/' . $node->nid,
);
}
elseif (variable_get('book_copy_always_display_copy_links', TRUE)) {
$links['book_copy_subtree'] = array(
'title' => t('Copy subtree'),
'href' => 'book_copy/explain/' . $node->book['bid'] . '/' . $node->nid,
);
}
}
}
return $links;
}
function book_copy_copy_book($book, $subtree = 0, &$context) {
if (isset($book->book)) {
$bid = $book->book['bid'];
$book = node_load(array(
'nid' => $bid,
));
module_load_include('inc', 'clone', 'clone.pages');
if (!isset($context['sandbox']['progress'])) {
$nodes = book_copy_find_subtree($bid, $subtree);
$context['sandbox']['newbid'] = 0;
$context['sandbox']['max'] = count($nodes);
$context['sandbox']['nodes'] = $nodes;
$context['sandbox']['progress'] = 0;
$context['sandbox']['finished'] = 0;
$context['sandbox']['mlinks'] = array();
$context['sandbox']['nidmap'] = array();
$context['sandbox']['mlidmap'] = array();
}
if (!empty($context['sandbox']['nodes'])) {
while ($context['sandbox']['progress'] < $context['sandbox']['max']) {
$nid = $nodes[$context['sandbox']['progress']];
$sql = 'SELECT ml.* FROM {menu_links} ml LEFT JOIN {book} b ON b.mlid = ml.mlid WHERE b.bid = %d AND b.nid = %d';
$result = db_query($sql, $bid, $nid);
$row = db_fetch_array($result);
$plid = $row['plid'];
$mlid = $row['mlid'];
$context['sandbox']['progress']++;
$context['sandbox']['nidmap'][$nid] = clone_node_save($nid);
$node = node_load(array(
'nid' => $context['sandbox']['nidmap'][$nid],
));
$context['sandbox']['mlidmap'][$mlid] = $node->book['mlid'];
if ($context['sandbox']['newbid'] == 0) {
$context['sandbox']['newbid'] = $context['sandbox']['nidmap'][$nid];
$message = $row['link_title'];
drupal_alter("book_copy", $node, $bid, $context['sandbox']['newbid']);
$batch =& batch_get();
$data = book_copy_copy_redirection($context['sandbox']['newbid']);
$batch['redirect'] = $data['url'];
}
if ($subtree != 0 || $node->nid != $context['sandbox']['newbid']) {
$node->book['bid'] = $context['sandbox']['newbid'];
node_save($node);
}
if (isset($context['sandbox']['mlidmap'][$plid])) {
$node->book['plid'] = $context['sandbox']['mlidmap'][$plid];
menu_link_save($node->book);
}
}
}
}
if ($context['sandbox']['progress'] < $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
else {
if ($context['sandbox']['progress'] != 0) {
$context['finished'] = 1;
}
}
if ($context['finished'] == 1) {
foreach ($context['sandbox']['nidmap'] as $snid => $nid) {
db_query('INSERT INTO {book_copy_history} (nid, bid, sbid, snid, copied) VALUES (%d, %d, %d, %d, %d)', $nid, $context['sandbox']['newbid'], $bid, $snid, time());
}
}
}
function book_copy_batch_copy($book, $subtree = 0) {
if (!empty($book->book['bid'])) {
return drupal_get_form('book_copy_confirm_copy', $book, $subtree);
}
else {
drupal_set_title(t('Error copying book'));
if (!empty($book->title)) {
drupal_set_message(t('%title is not a book', array(
'%title' => $book->title,
)), 'warning');
drupal_goto('node/' . $book->nid);
}
else {
drupal_set_message(t('Could not find book corresponding to nid: %nid', array(
'%nid' => $bid,
)), 'warning');
}
}
}
function book_copy_confirm_copy(&$form_state, $book, $subtree = 0) {
if (!empty($subtree)) {
$path = 'node/' . $subtree->nid;
}
else {
$path = 'node/' . $book->nid;
}
$form['book'] = array(
'#type' => 'value',
'#value' => $book->nid,
);
if (!empty($subtree)) {
$form['subtree'] = array(
'#type' => 'value',
'#value' => $subtree->nid,
);
}
$form = confirm_form($form, t('Are you sure you want to copy %title', array(
'%title' => $book->title,
)), 'node/' . $book->nid, '');
return $form;
}
function book_copy_confirm_copy_submit($form, &$form_state) {
$book = node_load(array(
'nid' => $form_state['values']['book'],
));
$subtree = $form_state['values']['subtree'];
$batch = array(
'title' => t('Copying %title', array(
'%title' => $book->title,
)),
'operations' => array(
array(
'book_copy_copy_book',
array(
$book,
$subtree,
),
),
),
);
batch_set($batch);
batch_process();
}
function book_copy_copy_redirection($bid) {
$book = node_load(array(
'nid' => $bid,
));
$book->bookcopydata = array();
$book->bookcopydata['message'] = t('Successfully cloned "%message", now viewing copy.', array(
'%message' => $message,
));
if (_book_outline_access($book)) {
$book->bookcopydata['url'] = 'node/' . $bid . '/outline';
}
else {
$book->bookcopydata['url'] = 'node/' . $bid;
}
drupal_alter("book_copy_goto", $book);
return $book->bookcopydata;
}
function book_copy_clone_node_alter(&$node, $original_node, $method) {
if ($method == 'save-edit') {
$node->title = str_replace('Clone of ', '', $node->title);
if (isset($node->book)) {
if ($node->book['plid'] == 0) {
unset($node->book['nid']);
$node->book['bid'] = 'new';
}
}
}
}
function book_copy_show_history($book) {
drupal_set_title(t('Book History: @title', array(
'@title' => $book->title,
)));
$ssbid = _book_copy_initial_source($book->book['bid']);
$tree = _book_copy_get_book_history($ssbid);
$output = _book_copy_render_tree($tree, $book->book['bid']);
return $output;
}
function _book_copy_render_tree($tree, $bid) {
foreach ($tree as $nid => $info) {
if ($nid == $bid) {
$class = 'class="messages"';
}
else {
$class = '';
}
$output .= '<li>';
$output .= '<span ' . $class . '>';
$node = node_load($nid);
if ($node) {
$output .= l($node->title, 'node/' . $nid);
}
else {
$output .= t('Book Deleted');
}
if (!empty($info['copied'])) {
$output .= ' ' . t('Copied') . ': ' . format_date($info['copied']);
}
else {
$output .= ' ' . t('Originating Source');
}
$output .= '</span>';
if (!empty($info['children'])) {
$output .= '<ul class="book-children">';
foreach ($info['children'] as $key => $child) {
$output .= _book_copy_render_tree(array(
$key => $child,
), $bid);
}
$output .= '</ul>';
}
$output .= '</li>';
}
return $output;
}
function _book_copy_get_book_history($bid) {
$return[$bid] = array();
$return[$bid]['copied'] = 0;
$return[$bid]['children'] = _book_copy_tree($bid);
return $return;
}
function _book_copy_tree($bid) {
$result = db_query("SELECT * FROM {book_copy_history} WHERE sbid = %d", $bid);
$children = array();
while ($row = db_fetch_array($result)) {
$children[$row['bid']] = array(
'copied' => $row['copied'],
'children' => _book_copy_tree($row['bid']),
);
}
return $children;
}
function _book_copy_initial_source($bid) {
$result = db_query("SELECT * FROM {book_copy_history} WHERE bid = %d", $bid);
$parents = array();
while ($row = db_fetch_array($result)) {
return _book_copy_initial_source($row['sbid']);
}
return $bid;
}
function book_copy_find_subtree($bid, $subtree = 0) {
$nodes = array();
if (!empty($subtree)) {
$mlid = db_result(db_query("SELECT ml.mlid FROM {menu_links} ml LEFT JOIN {book} b ON b.mlid = ml.mlid WHERE b.nid = %d", $subtree));
$where = 'AND (ml.plid = %d OR ml.p1 = %d OR ml.p2 = %d OR ml.p3 = %d OR ml.p4 = %d OR ml.p5 = %d OR ml.p6 = %d OR ml.p7 = %d OR ml.p8 = %d OR ml.p9 = %d)';
$args = array_fill(0, 10, $mlid);
array_unshift($args, $bid);
}
else {
$where = '';
$args = array(
$bid,
);
}
$result = db_query("SELECT b.nid FROM {menu_links} ml LEFT JOIN {book} b ON b.mlid = ml.mlid WHERE b.bid = %d " . $where . " ORDER BY ml.depth, b.nid", $args);
while ($nid = db_result($result)) {
$nodes[] = $nid;
}
return $nodes;
}
function book_copy_can_copy($bid, $subtree = 0, &$data = array()) {
if (is_object($bid)) {
$bid = $bid->book['bid'];
}
if (is_object($subtree)) {
$subtree = $subtree->nid;
}
$nodes = book_copy_find_subtree($bid, $subtree);
$data = array();
$data['headers'] = array(
'node' => t('Book page'),
'filter' => t('Input format'),
'create' => t('Create node type'),
);
$can_copy = TRUE;
if (user_access('copy books')) {
if (!empty($nodes)) {
foreach ($nodes as $nid) {
$node = node_load(array(
'nid' => $nid,
));
$data[$nid]['node'] = l($node->title, 'node/' . $nid);
if (!filter_access($node->format)) {
$can_copy = FALSE;
$data[$nid]['filter']['status'] = FALSE;
$data[$nid]['filter']['message'] = $node->format;
}
else {
$data[$nid]['filter']['status'] = TRUE;
}
if (!node_access('create', $node->type)) {
$can_copy = FALSE;
$data[$nid]['create']['status'] = FALSE;
$data[$nid]['create']['message'] = $node->type;
}
else {
$data[$nid]['create']['status'] = TRUE;
}
}
return $can_copy;
}
}
else {
return FALSE;
}
}
function book_copy_explain($book, $subtree = 0) {
$table = array();
$output = '';
if (book_copy_can_copy($book->book['bid'], $subtree, $data)) {
if ($subtree != 0) {
$output = t('You can copy this sub-section of the book.');
}
else {
$output = t('You can copy this book.');
}
}
else {
if ($subtree != 0) {
$output = t('You cannot copy this sub-section of the book. ');
}
else {
$output = t('You cannot copy this book. ');
}
$output .= t('In order to copy this book the following issue(s) must be addressed. Please contact your site administrator for help.');
}
$table['headers'] = $data['headers'];
unset($data['headers']);
$table['rows'] = array();
foreach ($data as $nid => $column) {
$row = array();
$hide = TRUE;
foreach ($table['headers'] as $key => $header) {
if ($column[$key]['status'] === FALSE) {
$row['data'][] = t('N(%message)', array(
'%message' => $column[$key]['message'],
));
$hide = FALSE;
}
elseif ($column[$key]['status'] === TRUE) {
$row['data'][] = t('Y');
}
else {
$row['data'][] = $column[$key];
}
}
if (!$hide) {
$table['rows'][] = $row;
}
}
if (!empty($table['rows'])) {
$output .= theme_table($table['headers'], $table['rows']);
}
return $output;
}