| 1 |
<?php
|
| 2 |
// $Id: export_dxml.module,v 1.3 2005-11-29 19:28:10 puregin Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* Allows authorized users to export a book as XML for offline
|
| 7 |
* editing, processing, or re-import to another book or site.
|
| 8 |
*/
|
| 9 |
|
| 10 |
/**
|
| 11 |
* Implementation of hook_perm().
|
| 12 |
*/
|
| 13 |
function export_dxml_perm() {
|
| 14 |
return array('export books as dxml');
|
| 15 |
}
|
| 16 |
|
| 17 |
|
| 18 |
/**
|
| 19 |
* Implementation of hook_link().
|
| 20 |
*/
|
| 21 |
function export_dxml_link($type, $node = 0, $main = 0) {
|
| 22 |
$links = array();
|
| 23 |
if ($type == 'node' && isset($node->parent)) {
|
| 24 |
if (!$main) {
|
| 25 |
if (user_access('export books as dxml')) {
|
| 26 |
$links[] = l(t('export Drupal XML'),
|
| 27 |
'book/export/dxml/'. $node->nid,
|
| 28 |
array('title' => t('Export this book page and its sub-pages as Drupal XML (suitable for re-import)')));
|
| 29 |
}
|
| 30 |
}
|
| 31 |
}
|
| 32 |
|
| 33 |
return $links;
|
| 34 |
}
|
| 35 |
|
| 36 |
/**
|
| 37 |
* This function is called by book_export() to generate DXML for export.
|
| 38 |
*
|
| 39 |
* The function also calls drupal_set_header() to set a header suitable
|
| 40 |
* for returning XML content.
|
| 41 |
*
|
| 42 |
* Note that the user must have both 'access content' permissions (checked
|
| 43 |
* when the menu item for export is invoked in book.module) and
|
| 44 |
* 'export books as dxml' permissions to export a book.
|
| 45 |
*
|
| 46 |
* @param nid
|
| 47 |
* - an integer representing the node id (nid) of the node to export
|
| 48 |
* @param depth
|
| 49 |
* - an integer giving the depth in the book hierarchy of the node
|
| 50 |
which is to be exported
|
| 51 |
* @return
|
| 52 |
* - the DXML representing the node and its children in the book hierarchy
|
| 53 |
*/
|
| 54 |
function book_export_dxml($nid, $depth) {
|
| 55 |
if (user_access('export books as dxml')) {
|
| 56 |
drupal_set_header('Content-Type: text/xml; charset=utf-8');
|
| 57 |
$xml = "<?xml version='1.0'?>\n";
|
| 58 |
$xml .= "<!DOCTYPE book PUBLIC \"-//Drupal//DTD DXML V1.0//EN\" \"http://drupal.org/xml/dxml.dtd\">\n";
|
| 59 |
$xml .= book_recurse($nid, $depth, 'book_node_visitor_dxml_pre', 'book_node_visitor_dxml_post');
|
| 60 |
return $xml;
|
| 61 |
}
|
| 62 |
else {
|
| 63 |
drupal_access_denied();
|
| 64 |
}
|
| 65 |
}
|
| 66 |
|
| 67 |
/**
|
| 68 |
* Generates XML for a given node. This function is a 'pre-node'
|
| 69 |
* visitor function for book_recurse(). The generated XML consists
|
| 70 |
* of nested <node> elements. Each Drupal node's HTML content
|
| 71 |
* is wrapped in a CDATA section. The node body has an md5-hash
|
| 72 |
* applied; the value of this is stored as node metadata to allow
|
| 73 |
* importing code to determine if contents have changed. The weight
|
| 74 |
* of a node is also stored as metadata to allow the node to be
|
| 75 |
* properly re-imported.
|
| 76 |
*
|
| 77 |
* @param $node
|
| 78 |
* - the node to generate output for.
|
| 79 |
* @param $depth
|
| 80 |
* - the depth of the given node in the hierarchy.
|
| 81 |
* @param $nid
|
| 82 |
* - the node id (nid) of the given node. This
|
| 83 |
* is used only for generating output (e.g., id attribute)
|
| 84 |
* @return
|
| 85 |
* - the generated XML for the given node.
|
| 86 |
*/
|
| 87 |
function book_node_visitor_dxml_pre($node, $depth, $nid) {
|
| 88 |
|
| 89 |
$title = "<title>". check_plain($node->title) ."</title>\n";
|
| 90 |
|
| 91 |
$allow_php = variable_get('Allow PHP Export', false);
|
| 92 |
$filter_formats = filter_formats(); /* get the array of formats */
|
| 93 |
if (($filter_formats[$node->format]->name == 'PHP code') && (!$allow_php) ) {
|
| 94 |
// convert PHP on the fly if PHP export is not allowed
|
| 95 |
$node = node_invoke($node, 'content');
|
| 96 |
}
|
| 97 |
|
| 98 |
// wrap the node body in a CDATA declaration
|
| 99 |
$content = "<content>\n";
|
| 100 |
$content .= "<![CDATA[";
|
| 101 |
if ($node->body) {
|
| 102 |
$content .= $node->body;
|
| 103 |
}
|
| 104 |
$content .= "]]>\n";
|
| 105 |
$content .= "</content>\n";
|
| 106 |
|
| 107 |
// wrap the teaser in a CDATA declaration
|
| 108 |
$teaser = "<teaser>\n";
|
| 109 |
$teaser .= "<![CDATA[";
|
| 110 |
# if PHP code export is not allowed, supply an empty teaser
|
| 111 |
if ($allow_php) {
|
| 112 |
if ($node->body) {
|
| 113 |
$teaser .= $node->teaser;
|
| 114 |
}
|
| 115 |
}
|
| 116 |
$teaser .= "]]>\n";
|
| 117 |
$teaser .= "</teaser>\n";
|
| 118 |
|
| 119 |
$output = "<node id=\"node-".$node->nid ."\">\n";
|
| 120 |
|
| 121 |
// now store metadata
|
| 122 |
$output .= "<nodeinfo ";
|
| 123 |
$output .= " type='$node->type'";
|
| 124 |
$output .= " uid='$node->uid'";
|
| 125 |
$output .= " status='$node->status'";
|
| 126 |
$output .= " created='$node->created'";
|
| 127 |
$output .= " promote='$node->promote'";
|
| 128 |
$output .= " moderate='$node->moderate'";
|
| 129 |
$output .= " changed='$node->changed'";
|
| 130 |
$output .= " sticky='$node->sticky'";
|
| 131 |
$output .= " vid='$node->vid'";
|
| 132 |
|
| 133 |
$output .= " format='$node->format'";
|
| 134 |
|
| 135 |
$output .= " md5_body='" . md5($node->body) . "'";
|
| 136 |
$output .= " weight='$node->weight'";
|
| 137 |
$output .= " depth='$depth'";
|
| 138 |
$output .= " author='"._get_username($node->uid)."'";
|
| 139 |
$output .= "/>\n";
|
| 140 |
|
| 141 |
$output .= $title;
|
| 142 |
$output .= $teaser;
|
| 143 |
$output .= $content;
|
| 144 |
|
| 145 |
return $output;
|
| 146 |
}
|
| 147 |
|
| 148 |
/**
|
| 149 |
* Completes the XML generation for the node. This function is a
|
| 150 |
* 'post-node' visitor function for book_recurse().
|
| 151 |
*/
|
| 152 |
function book_node_visitor_dxml_post($node, $depth) {
|
| 153 |
return "</node>\n";
|
| 154 |
}
|
| 155 |
|
| 156 |
/**
|
| 157 |
* Implementation of hook_help().
|
| 158 |
*/
|
| 159 |
function export_dxml_help($section) {
|
| 160 |
switch ($section) {
|
| 161 |
case 'admin/help#export_dxml':
|
| 162 |
$output .= '<p>'. t('Users can choose to <em>export</em> the page and its subsections as Drupal XML for offline editing, import to another book or another Drupal site, or other post-processing, by selecting the <em>Export Drupal XML</em> link. Note: it may be neccessary to shift-click on the link to save the results to a file on the local computer.') . '</p>';
|
| 163 |
return $output;
|
| 164 |
case 'admin/modules#description':
|
| 165 |
return t('Allows authorized users to export a book as Drupal XML.');
|
| 166 |
case 'admin/node/export_dxml':
|
| 167 |
return t("<p>The export_dxml module allows authorized users to export a book as DocBook XML (for offline editing, or production of print or other electronic publication formats).") . '</p>';
|
| 168 |
case 'admin/export_dxml':
|
| 169 |
return '<p>' . t("If the <em>Allow PHP Export</em> setting is enabled, then PHP code in books to be exported will be included in the output as PHP. Otherwise, the PHP will be evaluated and the resulting output will be exported.") . '</p>';
|
| 170 |
|
| 171 |
}
|
| 172 |
}
|
| 173 |
|
| 174 |
/**
|
| 175 |
* Implementation of hook_menu().
|
| 176 |
*/
|
| 177 |
function export_dxml_menu($may_cache) {
|
| 178 |
$items = array();
|
| 179 |
|
| 180 |
if ($may_cache) {
|
| 181 |
$items[] = array(
|
| 182 |
'path' => 'admin/export_dxml',
|
| 183 |
'title' => t('book export (dxml)'),
|
| 184 |
'callback' => 'export_dxml_admin',
|
| 185 |
'type' => MENU_NORMAL_ITEM,
|
| 186 |
'weight' => 0);
|
| 187 |
}
|
| 188 |
|
| 189 |
return $items;
|
| 190 |
}
|
| 191 |
|
| 192 |
/**
|
| 193 |
* Menu callback; displays the book administration page.
|
| 194 |
*/
|
| 195 |
function export_dxml_admin($nid = 0) {
|
| 196 |
$op = $_POST['op'];
|
| 197 |
$edit = $_POST['edit'];
|
| 198 |
$php_export_flag = $edit['flag'];
|
| 199 |
|
| 200 |
if ($op == t('Update settings')) {
|
| 201 |
if ($php_export_flag) {
|
| 202 |
$flag = "true";
|
| 203 |
variable_set('Allow PHP Export', true);
|
| 204 |
}
|
| 205 |
else {
|
| 206 |
$flag = "false";
|
| 207 |
variable_set('Allow PHP Export', false);
|
| 208 |
}
|
| 209 |
drupal_set_message(t("<em>Allow PHP Export</em> has been set to $flag"));
|
| 210 |
}
|
| 211 |
|
| 212 |
$output .= "<b>The following settings affect all books:</b>";
|
| 213 |
$form['flag'] = array('#type' => 'checkbox',
|
| 214 |
'#title' => 'Allow PHP Export',
|
| 215 |
'#value' => variable_get('Allow PHP Export', false)
|
| 216 |
);
|
| 217 |
$form['set_flag'] = array('#type' => 'submit',
|
| 218 |
'#value' => t('Update settings'));
|
| 219 |
|
| 220 |
$output .= drupal_get_form('book_admin_set_flag', $form);
|
| 221 |
|
| 222 |
return $output;
|
| 223 |
|
| 224 |
}
|
| 225 |
|
| 226 |
/**
|
| 227 |
* Utility function, get the name of a user from uid.
|
| 228 |
* @param $uid
|
| 229 |
* - the uid of the user whose name we wish to look up
|
| 230 |
* @return
|
| 231 |
* - string containing the name of the user, if found.
|
| 232 |
*/
|
| 233 |
function _get_username($uid) {
|
| 234 |
static $users = array();
|
| 235 |
global $user_cache_stats;
|
| 236 |
|
| 237 |
$username = "";
|
| 238 |
if (is_string($users[$uid]) && $users[$uid] != '') {
|
| 239 |
$username = $users[$uid];
|
| 240 |
}
|
| 241 |
else {
|
| 242 |
$user = user_load(array('uid' => $uid));
|
| 243 |
$username = $user->name;
|
| 244 |
$users[$uid] = $username;
|
| 245 |
}
|
| 246 |
return $username;
|
| 247 |
}
|