| 1 |
<?php
|
| 2 |
// $Id: image_import.module,v 1.17 2005/11/20 03:31:19 syscrusher Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* image_import.module BETA release -- not for production use
|
| 6 |
* Maintainer: Scott Courtney (scott@4th.com) "syscrusher" on drupal.org
|
| 7 |
*
|
| 8 |
* This module is an adjunct to image.module by James Walker ("walkah").
|
| 9 |
*
|
| 10 |
* WARNING: This module calls one private function, _image_build_derivatives(),
|
| 11 |
* from image.module. If that is deprecated or changed, this module will break.
|
| 12 |
*/
|
| 13 |
|
| 14 |
// Constants to decouple this module from changes to others
|
| 15 |
define('IMAGE_IMPORT_IMAGE_NODETYPE','image');
|
| 16 |
define('IMAGE_IMPORT_STATUS_ABORT',-1);
|
| 17 |
define('IMAGE_IMPORT_STATUS_ERROR',-2);
|
| 18 |
define('IMAGE_IMPORT_STATUS_OK',1);
|
| 19 |
define('IMAGE_IMPORT_STATUS_OK_CAPTION',2);
|
| 20 |
define('IMAGE_IMPORT_STATUS_OK_TIMEOUT',3);
|
| 21 |
|
| 22 |
/**
|
| 23 |
* Implementation of hook_help
|
| 24 |
*/
|
| 25 |
function image_import_help($section) {
|
| 26 |
global $user;
|
| 27 |
global $base_url;
|
| 28 |
switch ($section) {
|
| 29 |
case 'admin/modules#description':
|
| 30 |
return t('Allows mass import of images from a directory on the server.');
|
| 31 |
case 'node/add#image_import':
|
| 32 |
return t('Import multiple images and (optionally) captions from a directory on the web server into %site. This feature allows you to upload an entire gallery of images using FTP, SSH, or other tools, then import all of them in one step. If you are new to this feature, you may find the %helplink useful.',array('%site'=>variable_get('site_name',t('this web site')), '%helplink'=>l(t('detailed instructions'),'node/add/image_import/help')));
|
| 33 |
case 'admin/image_import':
|
| 34 |
return t('Image import allows users who have uploaded image (and optionally, caption) files to a directory on the server to mass-import these as image nodes.');
|
| 35 |
case 'node/add/image_import/help':
|
| 36 |
$path = image_import_get_import_path(TRUE);
|
| 37 |
$upload_path = image_import_get_upload_path();
|
| 38 |
$upload_host = preg_replace('#^\w+://(.*)/?.*$#','\1',$base_url);
|
| 39 |
if (empty($upload_host)) {
|
| 40 |
$upload_host = 'www.example.com';
|
| 41 |
}
|
| 42 |
$can_override = user_access('override image import path');
|
| 43 |
$max_res = variable_get('upload_max_resolution','');
|
| 44 |
$max_size = _image_import_max_upload_size();
|
| 45 |
$res = explode('x',$max_res);
|
| 46 |
$h_res = empty($res[0]) ? t('(unlimited)') : $res[0];
|
| 47 |
$v_res = empty($res[1]) ? t('(unlimited)') : $res[1];
|
| 48 |
$sizetext = $max_size ? t('may be up to %size megabytes in size', array('%size'=>$max_size)) : t('are limited in size only by the web server configuration');
|
| 49 |
$html = '<p>' . t('This feature is designed to allow you to import many images into a gallery in one step, rather than creating them one-at-a-time. This only makes sense if the images share common attributes, such as relating to the same set of topics and being part of the same gallery or album. To create multiple galleries, you will need to repeat all the steps in these instructions for each gallery.');
|
| 50 |
$html .= '<p>' . t('The %formlink provides specific instructions for filling in the form to do an import. This additional help explains the overall process in more detail than will fit on the import page itself.', array('%formlink'=>l(t('image import form'), 'node/add/image_import', array('title'=>t('Begin importing your images')))));
|
| 51 |
$html .= '<p>' . t('Here are the steps for importing all the images for one gallery. This may seem complicated the first time you do it, but remember that you can import a large number of images at once, so in the long run this feature will save you a lot of time. Also, the steps become easier once you have done this a couple of times.') . '<ol>';
|
| 52 |
$html .= '<li><p>' . t('If it does not already exist, make sure you or the site administrator create the directory "%dir" underneath the top-level directory for this site. If you are not the site administrator, that person will need to tell you how to access that directory for uploading your files.', array('%dir'=>$path));
|
| 53 |
if ($can_override) {
|
| 54 |
$html .= '<p>' . t(' (Your user privileges allow you to override the import directory path, but whatever directory you choose must be located underneath the top-level directory for the web site and must be readable and writeable by the web server.)');
|
| 55 |
}
|
| 56 |
$html .= '<li><p>' . t('Prepare your images on your personal computer or workstation, cropping, scaling, and editing them as you prefer using your choice of image editing software. (You may wish to make a copy of your originals and then edit the copy for importing to the web galleries.) The version of each image that you import should be the <em>largest size</em> that you wish to make available on the web. Do not worry about creating thumbnails or other scaled-down versions, because the import process will do that automatically for you.');
|
| 57 |
$html .= '<p>' . t('Images on this site are limited to a maximum resolution of %h x %v (<i>horizontal</i> x <i>vertical</i>) pixels and %sizetext.', array('%h'=>$h_res, '%v'=>$v_res, '%sizetext'=>$sizetext));
|
| 58 |
$html .= t(' The allowed file extensions for images are: %ext.', array('%ext'=>implode(', ',_image_import_img_extensions())));
|
| 59 |
$html .= '<li><p>' . t('Optionally, add captions for some or all of your images by creating a file in the same directory with the same name as its corresponding image, but with one of the following extensions: %ext. For example, the caption for "photo-0132.jpg" might be "photo-0132.txt".', array('%ext'=>implode(', ',_image_import_cap_extensions())));
|
| 60 |
$html .= '<p>' . t('For each image with a caption file, the import will read the contents of that file and add it as a description for the corresponding image in the gallery. Images without captions will still be imported, but their description will be blank.');
|
| 61 |
$html .= '<li><p>' . t('Upload all of your images and caption files to the import directory. From an FTP prompt, for example, you might need to "<code>cd %updir</code>" before doing "<code>mput *</code>" to send the files. If you use "scp" (part of OpenSSH) to upload, you might execute a command like this from your workstation, from the directory containing your files:<br><code>scp * %uname@%host:%updir</code>', array('%updir'=>$upload_path, '%uname'=>($user->name), '%host'=>$upload_host));
|
| 62 |
$html .= '<li><p>' . t('Browse to the %formlink, and follow the instructions to import your images and captions.', array('%formlink'=>l(t('image import form'), 'node/add/image_import', array('title'=>t('Begin importing your images')))));
|
| 63 |
$html .= '</ol>';
|
| 64 |
$html .= '<p>' . t('If you are importing many images at once, or your image files are really large, you may find that the import process (the last step in the list above) causes a timeout error from the web server. If that happens, either split your gallery into smaller groups of files and import each of these groups with the same category and gallery selections, or ask your site administrator to check the PHP settings for script execution time limits.');
|
| 65 |
// Need a trailing paragraph break in case there is site-specific guide
|
| 66 |
// text from the main node configuration page. Drupal core will
|
| 67 |
// automatically append that text.
|
| 68 |
$html .= '<p>';
|
| 69 |
return $html;
|
| 70 |
}
|
| 71 |
}
|
| 72 |
|
| 73 |
/**
|
| 74 |
* Implementation of hook_perm
|
| 75 |
*/
|
| 76 |
function image_import_perm() {
|
| 77 |
return array('import images', 'import system images', 'override image import path');
|
| 78 |
}
|
| 79 |
|
| 80 |
/**
|
| 81 |
* Implementation of hook_access
|
| 82 |
*/
|
| 83 |
function image_import_access($op, $node) {
|
| 84 |
switch ($op) {
|
| 85 |
case 'create': return (user_access('import images') || user_access('import system images'));
|
| 86 |
default:
|
| 87 |
return NULL;
|
| 88 |
}
|
| 89 |
}
|
| 90 |
|
| 91 |
/**
|
| 92 |
* Dummy implementation of hook_nodeapi
|
| 93 |
*/
|
| 94 |
//function image_import_nodeapi(&$node, $op, $arg1, $arg2) {
|
| 95 |
// return;
|
| 96 |
//}
|
| 97 |
|
| 98 |
/**
|
| 99 |
* implentation of hook_node_info
|
| 100 |
*/
|
| 101 |
function image_import_node_info() {
|
| 102 |
return array('image_import' => array('name' => 'image_import', 'base' => 'image_import'));
|
| 103 |
}
|
| 104 |
|
| 105 |
/**
|
| 106 |
* Implementation of hook_settings
|
| 107 |
*/
|
| 108 |
function image_import_settings() {
|
| 109 |
// First, check the status of the directory path and report any problems
|
| 110 |
_image_import_check_settings(FALSE, 'image_import_default_import_path');
|
| 111 |
|
| 112 |
$form = array();
|
| 113 |
$form['file_path'] = array(
|
| 114 |
'#type' => 'fieldset',
|
| 115 |
'#title' => t('File path settings'),
|
| 116 |
'#description' => t('These settings control the path on the server from which image and caption files will be imported. You can put the string <code>%u</code> or <code>%U</code> in the path fields, and these strings will be replaced by the username of the person doing the import. %U and %u are the same except that %U automatically removes space, %, <, >, *, /, \, and ? from the username.'),
|
| 117 |
'#tree' => FALSE,
|
| 118 |
'#collapsible' => TRUE,
|
| 119 |
'#collapsed' => FALSE,
|
| 120 |
);
|
| 121 |
$form['file_path']['image_import_default_import_path'] = array(
|
| 122 |
'#type' => 'textfield',
|
| 123 |
'#title' => t('Default import path'),
|
| 124 |
'#description' => t('<p>Subdirectory beneath the Drupal directory from which images may be imported in bulk. Drupal must have read/write access to this directory and subdirectories beneath it. This path must be <strong>different</strong> from the %imgsettings, which on this site is currently set to "%imgpath"</strong>.<p>Users with the "override image import path" permission can manually override this setting.', array('%imgsettings'=>l(t('image default path'), 'admin/settings/image'), '%imgpath'=>_image_import_get_image_path())),
|
| 125 |
'#default_value' => variable_get('image_import_default_import_path','image_import/%U'),
|
| 126 |
'#maxlength' => 50,
|
| 127 |
'#size' => 30,
|
| 128 |
'#required' => TRUE,
|
| 129 |
);
|
| 130 |
$form['file_path']['image_import_default_upload_path'] = array(
|
| 131 |
'#type' => 'textfield',
|
| 132 |
'#title' => t('Default import path'),
|
| 133 |
'#description' => t('<p>This should be set to the default import path (see above), but as viewed by a typical user during an FTP or similar upload. This may be either an absolute path or a path relative to the user\'s system home directory.<p>If you specify this setting, the interactive help for this module will use it in the text explaining how to upload files, customizing the help text as needed for each individual. The setting is not used for anything except generating help text.'),
|
| 134 |
'#default_value' => variable_get('image_import_default_upload_path',''),
|
| 135 |
'#maxlength' => 50,
|
| 136 |
'#size' => 30,
|
| 137 |
);
|
| 138 |
$form['file_path']['image_import_system_nou'] = array(
|
| 139 |
'#type' => 'checkbox',
|
| 140 |
'#title' => t('Ignore %u and %U for system user'),
|
| 141 |
'#description' => t('<p>If checked, the special administrative user (the first account created when the site was set up) will not be affected by <code>%u</code> or <code>%U</code> in the import path setting. Note that the system user can <i>always</i> override the path if they wish, because that special account has all available privileges.'),
|
| 142 |
'#return_value' => '1',
|
| 143 |
'#default_value' => variable_get('image_import_system_nou', '0'),
|
| 144 |
);
|
| 145 |
$form['image_import_force_delete'] = array(
|
| 146 |
'#type' => 'checkbox',
|
| 147 |
'#title' => t('Force deletion of upload files'),
|
| 148 |
'#description' => t('<p>If checked, this option forces image_import to delete any files from the upload directory that have been successfully imported. This is strongly recommended, because if they are not deleted, the next import from the same server directory may re-import these files and create duplicate image nodes. If this option is disabled, users will be offered a choice of whether to keep or delete the files.'),
|
| 149 |
'#return_value' => '1',
|
| 150 |
'#default_value' => variable_get('image_import_force_delete', '1'),
|
| 151 |
);
|
| 152 |
$form['advanced'] = array(
|
| 153 |
'#type' => 'fieldset',
|
| 154 |
'#title' => t('Advanced settings'),
|
| 155 |
'#description' => t('These settings can normally be left at the default values'),
|
| 156 |
'#tree' => FALSE,
|
| 157 |
'#collapsible' => TRUE,
|
| 158 |
'#collapsed' => TRUE,
|
| 159 |
);
|
| 160 |
$form['advanced']['image_import_debug'] = array(
|
| 161 |
'#type' => 'checkbox',
|
| 162 |
'#title' => t('Debug Mode'),
|
| 163 |
'#description' => t('<p>Turn this option on to enable verbose error checking and detailed messages. May be confusing to novice users, but extremely useful if you are having problems with importing images.'),
|
| 164 |
'#return_value' => '1',
|
| 165 |
'#default_value' => variable_get('image_import_debug', '0'),
|
| 166 |
);
|
| 167 |
$form['advanced']['image_import_adjust_order'] = array(
|
| 168 |
'#type' => 'checkbox',
|
| 169 |
'#title' => t('Adjust timestamp order of images'),
|
| 170 |
'#description' => t('By default, imported images are marked as created at the actual time they are imported. Since images are imported in filename order, this may cause some albums or galleries to appear in reverse order. Checking this option causes the import to apply a reversed-order timestamp to correct this, though that means the displayed creation timewill differ by a few seconds from the actual creation time. This setting establishes a default for this option, but users can override that default for each import, if they prefer.'),
|
| 171 |
'#return_value' => '1',
|
| 172 |
'#default_value' => variable_get('image_import_adjust_order', '0'),
|
| 173 |
);
|
| 174 |
$form['advanced']['image_import_timeout'] = array(
|
| 175 |
'#type' => 'select',
|
| 176 |
'#title' => t('Time limit per run (seconds)'),
|
| 177 |
'#description' => t('If you are having problems with the import script timing out on large directories, and you are not able to modify the web server or PHP parameters to fix the problem, you can enable this option to set a limit on how long image import will process images during a single run. If the time limit is reached, the user can simply re-run the same job again to do the next group of images, repeating until the entire directory has been imported. <strong>This option is ignored unless you and/or the user enable deletion of images after import, because otherwise you would import the same files over and over.</strong> It is recommended to set this option to slightly <em>less than</em> the PHP <code>max_execution_time</code> limit. On this site, <code>max_execution_time</code>=%met seconds currently. The PHP <code>max_execution_time</code> setting is usually changed in php.ini or httpd.conf (server-wide) or (if allowed) the .htaccess file for this site.', array('%met'=>ini_get('max_execution_time'))),
|
| 178 |
'#options' => drupal_map_assoc(array(15, 20, 30, 45, 60, 90, 120, 180, 240, 300)),
|
| 179 |
'#default_value' => variable_get('image_import_timeout', '0'),
|
| 180 |
);
|
| 181 |
$form['text1'] = array(
|
| 182 |
'#type' => 'fieldset',
|
| 183 |
'#title' => t('Security settings'),
|
| 184 |
'#description' => t('<p>You will need to define appropriate %roles that have %permission to upload files, then establish an appropriate list of permitted %extensions for each of these roles.', array('%roles'=>l(t('security roles'),'admin/access/roles'), '%permission'=>l(t('permission'),'admin/access'), '%extensions'=>l(t('file extensions'),'admin/settings/upload'))),
|
| 185 |
'#collapsible' => TRUE,
|
| 186 |
'#collapsed' => FALSE,
|
| 187 |
);
|
| 188 |
|
| 189 |
return $form;
|
| 190 |
}
|
| 191 |
|
| 192 |
/**
|
| 193 |
* Checks the path settings and reports any problems detected.
|
| 194 |
* $with_post (default TRUE) is passed to image_import_get_import_path()
|
| 195 |
* (q.v.). $path_fieldname indicates the fieldname with which any path
|
| 196 |
* error should be associated (the outer subscript 'edit' is implied and
|
| 197 |
* should not be included in the fieldname). The fieldname defaults to none.
|
| 198 |
*/
|
| 199 |
function _image_import_check_settings($with_post=TRUE, $path_fieldname='') {
|
| 200 |
$filepath = variable_get('file_directory_path','');
|
| 201 |
if (empty($filepath)) {
|
| 202 |
drupal_set_message(t('Upload module has not yet been configured.'),'error');
|
| 203 |
return FALSE;
|
| 204 |
}
|
| 205 |
$pathsetting = variable_get('image_import_default_import_path','');
|
| 206 |
if (empty($pathsetting)) {
|
| 207 |
drupal_set_message(t('Image import module has not yet been configured.'),'error');
|
| 208 |
return FALSE;
|
| 209 |
}
|
| 210 |
$image_path = _image_import_get_image_path();
|
| 211 |
if ($pathsetting == $image_path) {
|
| 212 |
drupal_set_message(t('Image import path may not be the same as the image path.'),'error');
|
| 213 |
return FALSE;
|
| 214 |
}
|
| 215 |
if (! user_access('upload files')) {
|
| 216 |
drupal_set_message(t('You do not have permission to upload files, which is a prerequisite for image import.'),'error');
|
| 217 |
return FALSE;
|
| 218 |
}
|
| 219 |
$extensions = _image_import_img_extensions();
|
| 220 |
if (count($extensions) < 1) {
|
| 221 |
drupal_set_message(t('Your user account has not been configured to allow any upload extensions. The site administrator will need to fix this for you in the settings for the "upload" module.'),'error');
|
| 222 |
return FALSE;
|
| 223 |
}
|
| 224 |
$path = image_import_get_import_path($with_post);
|
| 225 |
if (! module_exist('image')) {
|
| 226 |
drupal_set_message(t('Image module, a prerequisite for image import, is not installed or is disabled.'),'error');
|
| 227 |
return FALSE;
|
| 228 |
}
|
| 229 |
if (! is_writable($path)) {
|
| 230 |
drupal_set_message(t('The image import directory, %p, is missing or is not writable by the web server.', array('%p'=>$path)),'error');
|
| 231 |
if (user_access('override image import path')) {
|
| 232 |
drupal_set_message(t('Directory must be changed before import will work.'),'warning');
|
| 233 |
} else {
|
| 234 |
return FALSE;
|
| 235 |
}
|
| 236 |
}
|
| 237 |
$ok = file_check_directory($path, FALSE, $path_fieldname);
|
| 238 |
return $ok;
|
| 239 |
}
|
| 240 |
|
| 241 |
/**
|
| 242 |
* Scans a multi-level array with term ID numbers buried inside arrays
|
| 243 |
* inside arrays inside arrays...etc., and returns a simple array with just
|
| 244 |
* the tid numbers linearized plus, optionally, any free-tags entered by the
|
| 245 |
* user if a free-tag string is present in the input array.
|
| 246 |
*
|
| 247 |
* WARNING: This function uses recursion; modify with care or an infinite
|
| 248 |
* recursion loop is possible.
|
| 249 |
*
|
| 250 |
* For the outermost (non-recursed) invocation only, the parameter $keep_tags
|
| 251 |
* (default TRUE) tells the function to retain, unmodified, any element of
|
| 252 |
* the $tid_array whose subscript is 'tags'. This causes the subarray placed
|
| 253 |
* by the free-tag patch to taxonomy.module to work correctly across previews.
|
| 254 |
* Note that $tid_array['tags'] is a sub-array containing one or more string
|
| 255 |
* element(s), indexed by vocabulary ID (vid), with the free-form tags.
|
| 256 |
*
|
| 257 |
* If your installation does not have the free-tag support, the $keep_tags
|
| 258 |
* parameter has no effect since $tid_array['tags'] will not be present.
|
| 259 |
* It is necessary to disable $keep_tags only if you want to ensure that the
|
| 260 |
* returned array from this function has only existing tids in it.
|
| 261 |
*/
|
| 262 |
function _image_import_extract_tids($tid_array, $keep_tags=TRUE) {
|
| 263 |
$tids = array();
|
| 264 |
if (is_array($tid_array)) {
|
| 265 |
foreach ($tid_array as $key=>$element) {
|
| 266 |
if (is_int($key)) {
|
| 267 |
if (is_array($element)) {
|
| 268 |
// $keep_tags is NEVER useful when recursing
|
| 269 |
$tids = array_merge($tids, _image_import_extract_tids($element, FALSE));
|
| 270 |
} else {
|
| 271 |
// Toss out zero values
|
| 272 |
if (intval($element)) {
|
| 273 |
$tids[] = $element;
|
| 274 |
}
|
| 275 |
}
|
| 276 |
}
|
| 277 |
}
|
| 278 |
}
|
| 279 |
if ($keep_tags && isset($tid_array['tags'])) {
|
| 280 |
$tids['tags'] = $tid_array['tags'];
|
| 281 |
}
|
| 282 |
return $tids;
|
| 283 |
}
|
| 284 |
|
| 285 |
/**
|
| 286 |
* This internal function looks up a variable containing a default path for
|
| 287 |
* something (optionally defaulting to the value in the second parameter)
|
| 288 |
* and then applies this module's path mangling rules for replaceable
|
| 289 |
* parameters and other features, plus some syntax cleanup.
|
| 290 |
*/
|
| 291 |
function _image_import_get_path($variable_name, $variable_default_value='') {
|
| 292 |
global $user;
|
| 293 |
$uname = $user->name;
|
| 294 |
// If this is the system user, and settings instruct ignoring %u and %U for that
|
| 295 |
// user, then force $uname to be empty.
|
| 296 |
if ($user->uid == 1 && variable_get('image_import_system_nou',FALSE)) {
|
| 297 |
$uname = '';
|
| 298 |
}
|
| 299 |
// Remove space, %, <, >, *, /, \, and ? from the username for %U
|
| 300 |
$uname_mod = preg_replace('#[%<>*\\\\ \/?]#','',$uname,-1);
|
| 301 |
$pathsetting = variable_get($variable_name, $variable_default_value);
|
| 302 |
$path = trim(preg_replace('/%u/',$uname,$pathsetting,-1));
|
| 303 |
$path = trim(preg_replace('/%U/',$uname_mod,$pathsetting,-1));
|
| 304 |
if (! preg_match('#/$#', $path)) {
|
| 305 |
$path .= '/';
|
| 306 |
}
|
| 307 |
// Remove any double-slashes
|
| 308 |
$path = preg_replace('#//#','/',$path,-1);
|
| 309 |
return $path;
|
| 310 |
}
|
| 311 |
|
| 312 |
/**
|
| 313 |
* Returns the current import path for this user (may be the same as the system
|
| 314 |
* default, if "%u"/"%U" wasn't used in the system path setting). The returned path
|
| 315 |
* will always have a trailing slash.
|
| 316 |
*
|
| 317 |
* If $with_post is TRUE (default FALSE), then the value of $_POST['edit']['import_path']
|
| 318 |
* will override the other sources of settings *if* the user has the correct permissions.
|
| 319 |
*/
|
| 320 |
function image_import_get_import_path($with_post = FALSE) {
|
| 321 |
if (user_access('override image import path') && ! empty($_POST['edit']['import_path'])) {
|
| 322 |
$path = trim($_POST['edit']['import_path']);
|
| 323 |
if (! preg_match('#/$#', $path)) {
|
| 324 |
$path .= '/';
|
| 325 |
}
|
| 326 |
// Remove any double-slashes
|
| 327 |
$path = preg_replace('#//#','/',$path,-1);
|
| 328 |
return $path;
|
| 329 |
}
|
| 330 |
return _image_import_get_path('image_import_default_import_path','image_import/%u');
|
| 331 |
}
|
| 332 |
|
| 333 |
/**
|
| 334 |
* For the purpose of user-specific help text, this function returns this user's
|
| 335 |
* version of the default upload path. The default, if the config variable is
|
| 336 |
* missing or empty, is to return image_import_get_import_path().
|
| 337 |
*
|
| 338 |
* WARNING: Callers should NOT rely on this being any particular format, because
|
| 339 |
* it is strictly intended to create strings for help messages. The site admin
|
| 340 |
* is allowed to munge the syntax of the setting any way they wish to make it
|
| 341 |
* clear to their user community.
|
| 342 |
*/
|
| 343 |
function image_import_get_upload_path() {
|
| 344 |
return _image_import_get_path('image_import_default_upload_path',
|
| 345 |
image_import_get_import_path());
|
| 346 |
}
|
| 347 |
|
| 348 |
/**
|
| 349 |
* Implementation of hook_menu
|
| 350 |
*/
|
| 351 |
function image_import_menu($may_cache) {
|
| 352 |
global $user;
|
| 353 |
$items = array();
|
| 354 |
if ($may_cache) {
|
| 355 |
$items[] = array('path' => 'node/add/image_import', 'title' => t('import images'),
|
| 356 |
'callback' => '_image_import_add',
|
| 357 |
'access' => user_access('import images'));
|
| 358 |
// $items[] = array('path' => 'admin/settings/image_import/legacy', 'title' => t('import from legacy image.module'),
|
| 359 |
// 'callback' => 'image_import_legacy',
|
| 360 |
// 'access' => ($user->uid == 1));
|
| 361 |
}
|
| 362 |
return $items;
|
| 363 |
}
|
| 364 |
|
| 365 |
/**
|
| 366 |
* Menu handler for the import functions
|
| 367 |
*/
|
| 368 |
function _image_import_add() {
|
| 369 |
$html = '';
|
| 370 |
// Don't disable the processing of the form if we've already been there,
|
| 371 |
// because any "settings failure" will be due to settings in the form
|
| 372 |
// itself and not at the system level.
|
| 373 |
if (arg(3) == 'help') {
|
| 374 |
// Leave HTML alone and let image_import_help() handle it
|
| 375 |
} else if (_image_import_check_settings(TRUE, 'import_path') || is_array($_POST['edit'])) {
|
| 376 |
$html .= _image_import_form();
|
| 377 |
} else {
|
| 378 |
$html .= '<p>' . t('Image import is disabled until the %config problem is corrected.', array('%config'=>l('configuration', 'admin/settings/image_import')));
|
| 379 |
}
|
| 380 |
print(theme('page',"<p>".$html));
|
| 381 |
}
|
| 382 |
|
| 383 |
/**
|
| 384 |
* Helper function returns a form for initiating the upload
|
| 385 |
*/
|
| 386 |
function _image_import_form() {
|
| 387 |
global $user;
|
| 388 |
|
| 389 |
if (is_array($_POST['edit'])) {
|
| 390 |
// Assume precheck if the button to actually do it was *not* pressed
|
| 391 |
$precheck = $_POST['op']!='Import images'?1:0;
|
| 392 |
$status = image_import_import($precheck);
|
| 393 |
// Some options set from POST or from system-wide defaults
|
| 394 |
$delete_after = $_POST['edit']['delete_after'];
|
| 395 |
$adjust_order = $_POST['edit']['adjust_order'];
|
| 396 |
} else {
|
| 397 |
// Some options set from POST or from system-wide defaults
|
| 398 |
$delete_after = variable_get('image_import_force_delete',FALSE);
|
| 399 |
$adjust_order = variable_get('image_import_adjust_order', 0);
|
| 400 |
}
|
| 401 |
$dummy_node =& new stdClass();
|
| 402 |
$dummy_node->type = IMAGE_IMPORT_IMAGE_NODETYPE;
|
| 403 |
// $dummy_node->taxonomy =& _image_import_extract_tids($_POST['edit']['taxonomy']);
|
| 404 |
$dummy_node->taxonomy = $_POST['edit']['taxonomy'];
|
| 405 |
|
| 406 |
$html = '<p>' . t('An explanation of how to import images is available on the %helplink page.',array('%helplink'=>l(t('detailed instructions'),'node/add/image_import/help')));
|
| 407 |
|
| 408 |
$form = array();
|
| 409 |
/*if ($taxonomy_form = taxonomy_node_form($dummy_node)) {
|
| 410 |
$form += $taxonomy_form;
|
| 411 |
}*/
|
| 412 |
|
| 413 |
$form['advanced'] = array(
|
| 414 |
'#type' => 'fieldset',
|
| 415 |
'#title' => t('Advanced settings'),
|
| 416 |
'#description' => t('These settings can normally be left at the default values'),
|
| 417 |
'#tree' => FALSE,
|
| 418 |
'#collapsible' => TRUE,
|
| 419 |
'#collapsed' => TRUE,
|
| 420 |
);
|
| 421 |
$form['advanced']['title_pattern'] = array(
|
| 422 |
'#type' => 'textfield',
|
| 423 |
'#title' => t('Title pattern'),
|
| 424 |
'#default_value' => $_POST['edit']['title_pattern'],
|
| 425 |
'#maxlength' => 50,
|
| 426 |
'#size' => 30,
|
| 427 |
'#description' => t('If you leave this blank, each imported file\'s title will be set to match the filename. If you wish, you can specify an alternative title pattern here that will be used as a prefix (e.g., a title pattern of "my title:" will label a file called "photo-0032.jpg" as "my title: photo-0032.jpg"; the import software adds a space if needed between the prefix and the filename). You can embed the label %f within the pattern to specify exactly where you want the filename to go; if you do that, be sure to add your own space(s) where you want them, because the software will create the titles exactly as you specify. And you can embed %c within the pattern; this will be replaced with the first line of the caption file (if found), allowing you to title the image based on its caption file. If this substitution is made, the first line is removed from the caption file after it is extracted for the title.'),
|
| 428 |
);
|
| 429 |
if (user_access('override image import path')) {
|
| 430 |
$form['advanced']['import_path'] = array(
|
| 431 |
'#type' => 'textfield',
|
| 432 |
'#title' => t('Import path'),
|
| 433 |
'#default_value' => image_import_get_import_path(FALSE),
|
| 434 |
'#maxlength' => 50,
|
| 435 |
'#size' => 30,
|
| 436 |
'#description' => t('You can optionally override the directory from which image files will be imported. This is relative to the site\'s top-level directory. The default value is "%path".', array('%path'=>image_import_get_import_path(FALSE))),
|
| 437 |
);
|
| 438 |
}
|
| 439 |
$form['advanced']['adjust_order'] = array(
|
| 440 |
'#type' => 'checkbox',
|
| 441 |
'#title' => t('Adjust timestamp order of images'),
|
| 442 |
'#default_value' => $adjust_order,
|
| 443 |
'#return_value' => 1,
|
| 444 |
'#description' => t('By default, imported images are marked as created at the actual time they are imported. Since images are imported in filename order, this may cause some albums or galleries to appear in reverse order. Checking this option causes the import to apply a reversed-order timestamp to correct this, though that means the displayed creation timewill differ by a few seconds from the actual creation time.'),
|
| 445 |
);
|
| 446 |
if ($user->uid == 1 || ! variable_get('image_import_force_delete',FALSE)) {
|
| 447 |
$form['delete_after'] = array(
|
| 448 |
'#type' => 'checkbox',
|
| 449 |
'#title' => t('Delete uploaded image files after import'),
|
| 450 |
'#default_value' => $delete_after,
|
| 451 |
'#return_value' => 1,
|
| 452 |
'#description' => t('This option causes the import program to delete the images and any caption files from the import directory after they are imported into the gallery.'),
|
| 453 |
);
|
| 454 |
}
|
| 455 |
$form['submit_preview'] = array(
|
| 456 |
'#type' => 'submit',
|
| 457 |
'#value' => t('Preview import'),
|
| 458 |
);
|
| 459 |
$form['submit_import'] = array(
|
| 460 |
'#type' => 'submit',
|
| 461 |
'#value' => t('Import images'),
|
| 462 |
);
|
| 463 |
|
| 464 |
/* added the following to trick taxonomy_form_alter into adding the categories form element */
|
| 465 |
$node = new stdclass();
|
| 466 |
$node->type = 'image';
|
| 467 |
$form['#node'] = $node;
|
| 468 |
$form['type'] = array('#value' => 'image');
|
| 469 |
/* end of trick */
|
| 470 |
|
| 471 |
// changed the form_id to contain the fragment _node_form; also needed to trick taxonomy_form_alter
|
| 472 |
$html .= drupal_get_form('image_node_form', $form);
|
| 473 |
return $html;
|
| 474 |
}
|
| 475 |
|
| 476 |
/**
|
| 477 |
* From a list of all extensions this module recognizes as image files, returns
|
| 478 |
* an array containing only those permitted by system settings for the upload
|
| 479 |
* module.
|
| 480 |
*/
|
| 481 |
function _image_import_img_extensions() {
|
| 482 |
return _image_import_check_ext(array('gif','jpg','jpeg','png','tif','tiff'));
|
| 483 |
}
|
| 484 |
|
| 485 |
/**
|
| 486 |
* From a list of all extensions this module recognizes as caption files, returns
|
| 487 |
* an array containing only those permitted by system settings for the upload
|
| 488 |
* module.
|
| 489 |
*/
|
| 490 |
function _image_import_cap_extensions() {
|
| 491 |
return _image_import_check_ext(array('html','htm','txt','caption'));
|
| 492 |
}
|
| 493 |
|
| 494 |
/**
|
| 495 |
* Given an array of extensions allowed by this module specifically, intersects
|
| 496 |
* these with the system-defined list of permitted upload extensions in order
|
| 497 |
* to create a subset of only the ones legal in both contexts. The parameter is
|
| 498 |
* a simple array whose values are significant but whose keys are not. The return
|
| 499 |
* is a simple integer-subscripted array.
|
| 500 |
*
|
| 501 |
* The lists of extensions for different security roles are stored in variables
|
| 502 |
* whose names are "upload_extensions_${rid}". This function merges all of the
|
| 503 |
* extensions for the user's roles, then intersects the $ext_array with the
|
| 504 |
* result of that merge.
|
| 505 |
*/
|
| 506 |
function _image_import_check_ext($ext_array) {
|
| 507 |
global $user;
|
| 508 |
// Special handling for the superuser
|
| 509 |
if ($user->uid == 1) {
|
| 510 |
return $ext_array;
|
| 511 |
}
|
| 512 |
$extensions = array();
|
| 513 |
foreach($user->roles as $rid=>$role) {
|
| 514 |
$rid = intval($rid);
|
| 515 |
$role_extensions = explode(' ',variable_get('upload_extensions_'.$rid, ''));
|
| 516 |
$extensions = array_merge($extensions, $role_extensions);
|
| 517 |
}
|
| 518 |
$extensions = array_values(array_intersect($ext_array, $extensions));
|
| 519 |
return $extensions;
|
| 520 |
}
|
| 521 |
|
| 522 |
/**
|
| 523 |
* Calculates the largest upload size for the current user, by finding the
|
| 524 |
* maximum of variables named "upload_uploadsize_${rid}" and the system
|
| 525 |
* upload limit.
|
| 526 |
*/
|
| 527 |
function _image_import_max_upload_size() {
|
| 528 |
global $user;
|
| 529 |
$size = 0;
|
| 530 |
foreach($user->roles as $rid=>$role) {
|
| 531 |
$rid = intval($rid);
|
| 532 |
$role_size = intval(variable_get('upload_uploadsize_'.$rid, 0));
|
| 533 |
$size = max($size, $role_size);
|
| 534 |
}
|
| 535 |
$size = min(intval(variable_get('upload_maxsize_total',99999999)), $size);
|
| 536 |
return $size;
|
| 537 |
}
|
| 538 |
|
| 539 |
/**
|
| 540 |
* Processes, or pre-checks, the import of the file(s) in the import directory.
|
| 541 |
* Returns an associative array (keyed by basename) of the images that would
|
| 542 |
* be imported (precheck mode) or for which import was attempted.
|
| 543 |
*
|
| 544 |
* Returns one of the status code constants.
|
| 545 |
*/
|
| 546 |
function image_import_import($precheck_only=TRUE) {
|
| 547 |
global $user;
|
| 548 |
$debug = variable_get('image_import_debug', 0);
|
| 549 |
if ($debug) drupal_set_message(t('DEBUG MODE ENABLED for image_import_import() function. There will be extra messages issued.'),'debug');
|
| 550 |
|
| 551 |
$start = time();
|
| 552 |
$timeout = intval(variable_get('image_import_timeout', 0));
|
| 553 |
$adjust_order = $_POST['edit']['adjust_order'];
|
| 554 |
if ($debug && $adjust_order) drupal_set_message(t('DEBUG: Throttle is enabled.'),'debug');
|
| 555 |
$is_personal = ($_POST['edit']['personal'] || ! user_access('import system images'));
|
| 556 |
$extensions = _image_import_img_extensions();
|
| 557 |
$cap_extensions = _image_import_cap_extensions();
|
| 558 |
if ($is_personal) {
|
| 559 |
drupal_set_message(t('Personal albums not yet supported; importing to system galleries.'),'warning');
|
| 560 |
}
|
| 561 |
if ($user->uid == 1 || ! variable_get('image_import_force_delete',FALSE)) {
|
| 562 |
$do_delete = $_POST['edit']['delete_after'];
|
| 563 |
} else {
|
| 564 |
$do_delete = variable_get('image_import_force_delete',FALSE);
|
| 565 |
}
|
| 566 |
if (! $do_delete && $timeout > 0) {
|
| 567 |
drupal_set_message(t('Normal %time second time limit will be ignored because files are not being deleted after import.', array('%time'=>$timeout)), 'warning');
|
| 568 |
$timeout = 0;
|
| 569 |
}
|
| 570 |
$title_pattern = $_POST['edit']['title_pattern'];
|
| 571 |
// If the user specified an exact pattern, take it on faith that they know what they're doing.
|
| 572 |
// Otherwise, make sure it ends with a blank and then append %f so that the actual import
|
| 573 |
// has a place to put the filename.
|
| 574 |
if (! preg_match('/%[fc]/',$title_pattern)) {
|
| 575 |
$title_pattern .= ' %f';
|
| 576 |
$title_pattern = preg_replace('/ /',' ',$title_pattern,-1);
|
| 577 |
}
|
| 578 |
// No matter what, no leading or trailing blanks
|
| 579 |
$title_pattern = trim($title_pattern);
|
| 580 |
if (is_array($extensions)) {
|
| 581 |
$img_ext = array();
|
| 582 |
foreach ($extensions as $extension) {
|
| 583 |
$lc = strtolower($extension);
|
| 584 |
$uc = strtoupper($extension);
|
| 585 |
$img_ext[] = $lc;
|
| 586 |
$img_ext[] = $uc;
|
| 587 |
}
|
| 588 |
if ($debug) drupal_set_message(t('DEBUG: Image file extensions: %ext',array('%ext'=>implode(',',$img_ext))),'debug');
|
| 589 |
} else {
|
| 590 |
drupal_set_message(t('Internal error: invalid file extension list in image_import_import()'),'error');
|
| 591 |
return IMAGE_IMPORT_STATUS_ABORT;
|
| 592 |
}
|
| 593 |
$path = image_import_get_import_path(TRUE);
|
| 594 |
$img_mask = '\.(' . implode('|',$img_ext) . ')$';
|
| 595 |
$files = file_scan_directory($path, $img_mask, array('.', '..', 'CVS'), 0, FALSE, 'name');
|
| 596 |
if (! count($files)) {
|
| 597 |
drupal_set_message(t('No image files were found in the import directory %p.',array('%p'=>$path)), 'warning');
|
| 598 |
} else {
|
| 599 |
// The directory scan doesn't necessarily return the files in a reasonable order
|
| 600 |
ksort($files);
|
| 601 |
$found_count = 0;
|
| 602 |
$captioned_count = 0;
|
| 603 |
$imported_count = 0;
|
| 604 |
$error_count = 0;
|
| 605 |
if (is_array($cap_extensions)) {
|
| 606 |
$cap_ext = array();
|
| 607 |
foreach ($cap_extensions as $extension) {
|
| 608 |
$lc = strtolower($extension);
|
| 609 |
$uc = strtoupper($extension);
|
| 610 |
$cap_ext[] = $lc;
|
| 611 |
$cap_ext[] = $uc;
|
| 612 |
}
|
| 613 |
if ($debug) drupal_set_message(t('DEBUG: Caption file extensions: %ext',array('%ext'=>implode(',',$cap_ext))),'debug');
|
| 614 |
} else {
|
| 615 |
drupal_set_message(t('Internal error: invalid caption extension list in image_import_import()'),'error');
|
| 616 |
return IMAGE_IMPORT_STATUS_ABORT;
|
| 617 |
}
|
| 618 |
$terms =& _image_import_extract_tids($_POST['edit']['taxonomy']);
|
| 619 |
|
| 620 |
if (! is_array($terms) || count($terms) < 1) {
|
| 621 |
drupal_set_message(t('No categories selected for images; aborting.'),'error');
|
| 622 |
return IMAGE_IMPORT_STATUS_ABORT;
|
| 623 |
}
|
| 624 |
$last = time() + count($files);
|
| 625 |
$nfile = 0;
|
| 626 |
foreach($files as $file) {
|
| 627 |
$nfile++;
|
| 628 |
// Do the files in reverse time order so they'll sort sensibly
|
| 629 |
$now = $last - $nfile;
|
| 630 |
if ($debug) drupal_set_message(t("DEBUG: Timestamp for file number %n is %t", array('%n'=>$nfile, '%t'=>$now)), 'debug');
|
| 631 |
$elapsed = time() - $start;
|
| 632 |
if ($timeout > 0 && $elapsed >= $timeout) {
|
| 633 |
drupal_set_message(t('Time limit expired. One or more images remain to be imported. Repeat the import to continue processing these images.'),'warning');
|
| 634 |
return IMAGE_IMPORT_STATUS_OK_TIMEOUT;
|
| 635 |
}
|
| 636 |
$found_count++;
|
| 637 |
// Import or check ONE file only
|
| 638 |
$rc = image_import_import_one($file, $cap_ext, $precheck_only, $title_pattern, $do_delete, $terms, ($adjust_order ? $now : 0));
|
| 639 |
switch ($rc) {
|
| 640 |
case IMAGE_IMPORT_STATUS_OK_CAPTION:
|
| 641 |
$captioned_count++;
|
| 642 |
// Intentional fall-through here.
|
| 643 |
case IMAGE_IMPORT_STATUS_OK:
|
| 644 |
$imported_count++;
|
| 645 |
if ($do_delete && ! $precheck_only) $deleted_count++;
|
| 646 |
break;
|
| 647 |
case IMAGE_IMPORT_STATUS_ABORT:
|
| 648 |
drupal_set_message(t('Fatal error. Import processing aborted.'), 'error');
|
| 649 |
break 2;
|
| 650 |
case IMAGE_IMPORT_STATUS_ERROR:
|
| 651 |
$error_count++;
|
| 652 |
break;
|
| 653 |
default:
|
| 654 |
if ($rc < 0) {
|
| 655 |
$error_count++;
|
| 656 |
} else {
|
| 657 |
$imported_count++;
|
| 658 |
if ($do_delete && ! $precheck_only) $deleted_count++;
|
| 659 |
}
|
| 660 |
}
|
| 661 |
}
|
| 662 |
if ($precheck_only) {
|
| 663 |
drupal_set_message(t('Found %n file(s) to import, with %c captioned from files.',array('%n'=>$found_count,'%c'=>$captioned_count)));
|
| 664 |
} else {
|
| 665 |
drupal_set_message(t('Successfully imported %i file(s) out of %n, with %c captioned from files.', array('%i'=>$imported_count, '%n'=>$found_count, '%c'=>$captioned_count)));
|
| 666 |
watchdog('image import',t('Successfully imported %i file(s) out of %n, with %c captioned from files.', array('%i'=>$imported_count, '%n'=>$found_count, '%c'=>$captioned_count)), WATCHDOG_NOTICE);
|
| 667 |
}
|
| 668 |
if ($deleted_count) {
|
| 669 |
drupal_set_message(t('Deleted %d image(s) and associated caption(s) from the import directory.', array('%d'=>$deleted_count)));
|
| 670 |
}
|
| 671 |
}
|
| 672 |
return IMAGE_IMPORT_STATUS_OK;
|
| 673 |
}
|
| 674 |
|
| 675 |
/**
|
| 676 |
* Attempt to import, or just to check, one file.
|
| 677 |
*
|
| 678 |
* Returns one of the following status values:
|
| 679 |
* IMAGE_IMPORT_STATUS_ABORT The attempt was aborted due to an internal
|
| 680 |
* error, and a message has been queued to the user.
|
| 681 |
* IMAGE_IMPORT_STATUS_OK The attempt succeeded and the image was imported
|
| 682 |
* (or would be expected to import okay).
|
| 683 |
* IMAGE_IMPORT_STATUS_OK_CAPTION The attempt succeeded (or is expected to succeed)
|
| 684 |
* and a caption file was found for the image.
|
| 685 |
* IMAGE_IMPORT_STATUS_ERROR The image cannot be imported; a message has been
|
| 686 |
* queued to report the specific problem.
|
| 687 |
* Other status codes may be added in the future. The application may safely assume
|
| 688 |
* that any code >= 0 is some form of success, and any code < 0 is some form of failure.
|
| 689 |
*/
|
| 690 |
function image_import_import_one($file, $cap_ext, $precheck_only=TRUE, $title_pattern='%f', $do_delete=FALSE, $terms=NULL, $timestamp=0) {
|
| 691 |
global $user;
|
| 692 |
$debug = variable_get('image_import_debug', 0);
|
| 693 |
if (! is_object($file)) {
|
| 694 |
drupal_set_message(t('Import function called with null file; aborting.'),'error');
|
| 695 |
return IMAGE_IMPORT_STATUS_ABORT;
|
| 696 |
}
|
| 697 |
if (! is_array($cap_ext)) {
|
| 698 |
drupal_set_message(t('Import function called with empty caption list; aborting.'),'error');
|
| 699 |
return IMAGE_IMPORT_STATUS_ABORT;
|
| 700 |
}
|
| 701 |
if (! is_array($terms) || count($terms) < 1) {
|
| 702 |
drupal_set_message(t('No categories selected for images; aborting.'),'error');
|
| 703 |
return IMAGE_IMPORT_STATUS_ABORT;
|
| 704 |
}
|
| 705 |
if (! $timestamp) {
|
| 706 |
$timestamp = time();
|
| 707 |
}
|
| 708 |
$cap_mask = '\.(' . implode('|',$cap_ext) . ')$';
|
| 709 |
// Double-slashes in paths don't seem to matter to the o.s., but they
|
| 710 |
// confuse the user in error messages, so we get rid of them here.
|
| 711 |
$path = preg_replace('#//#','/',$file->filename,-1);
|
| 712 |
if ($debug) drupal_set_message(t('DEBUG: Import called for path=%path',array('%path'=>$path)),'debug');
|
| 713 |
// Access checks on the file
|
| 714 |
if (! is_readable($path)) {
|
| 715 |
drupal_set_message(t('The web server cannot read %f -- skipping.', array('%f'=>$path)),'error');
|
| 716 |
return IMAGE_IMPORT_STATUS_ERROR;
|
| 717 |
}
|
| 718 |
if (! is_writable($path)) {
|
| 719 |
drupal_set_message(t('Image file %f is not writable by the web server -- skipping.', array('%f'=>$path)),'error');
|
| 720 |
return IMAGE_IMPORT_STATUS_ERROR;
|
| 721 |
}
|
| 722 |
if ($debug) drupal_set_message(t('DEBUG: Access checks succeeded for %path',array('%path'=>$path)),'debug');
|
| 723 |
$caption = '';
|
| 724 |
$cap_extensions = _image_import_cap_extensions();
|
| 725 |
$cap_firstline = '';
|
| 726 |
foreach ($cap_extensions as $ext) {
|
| 727 |
$caption_path = preg_replace('#\.[^.]+$#','.'.$ext, $path);
|
| 728 |
if (file_exists($caption_path)) {
|
| 729 |
if ($debug) drupal_set_message(t('DEBUG: Found caption file %file',array('%file'=>$caption_path)),'debug');
|
| 730 |
if (! is_readable($caption_path)) {
|
| 731 |
drupal_set_message(t('The web server cannot read %f -- skipping.', array('%f'=>$caption_path)),'error');
|
| 732 |
return IMAGE_IMPORT_STATUS_ERROR;
|
| 733 |
}
|
| 734 |
if ($do_delete && ! is_writable($caption_path)) {
|
| 735 |
drupal_set_message(t('Delete of imported files is enabled, but caption file %f is not writable by the web server -- skipping image.', array('%f'=>$caption_path)),'error');
|
| 736 |
return IMAGE_IMPORT_STATUS_ERROR;
|
| 737 |
}
|
| 738 |
$caption = file_get_contents($caption_path, FALSE);
|
| 739 |
$caption = preg_replace('#\r\n#m',"\n",$caption,-1);
|
| 740 |
$caption = preg_replace('#\r#m',"\n",$caption,-1);
|
| 741 |
if (strpos($title_pattern, '%c') !== FALSE) {
|
| 742 |
$lines = explode("\n", $caption);
|
| 743 |
$cap_firstline = trim(strip_tags($lines[0]));
|
| 744 |
if (! empty($cap_firstline)) {
|
| 745 |
unset($lines[0]);
|
| 746 |
$caption = implode("\n", $lines);
|
| 747 |
}
|
| 748 |
}
|
| 749 |
$caption = '<p>' . $caption;
|
| 750 |
$caption = preg_replace('#\n\s*\n#m',"\n<p>\n",$caption,-1);
|
| 751 |
$caption = preg_replace('#<p>\s*<p>#m','<p>',$caption,-1);
|
| 752 |
break;
|
| 753 |
}
|
| 754 |
}
|
| 755 |
$title = trim(preg_replace('#%f#',$file->basename,$title_pattern));
|
| 756 |
$title = trim(preg_replace('#%c#',$cap_firstline,$title));
|
| 757 |
if ($debug) drupal_set_message(t('DEBUG: Title pattern is "%p".', array('%p'=>$title_pattern)), 'debug');
|
| 758 |
if ($debug) drupal_set_message(t('DEBUG: Title is "%t".', array('%t'=>$title)), 'debug');
|
| 759 |
$files[$name]->title = $title;
|
| 760 |
$teaser = node_teaser($caption);
|
| 761 |
if ($debug) drupal_set_message(t('DEBUG: Caption %c characters, teaser %t characters, for %n.', array('%c'=>strlen($caption), '%t'=>strlen($teaser), '%n'=>$file->basename)),'debug');
|
| 762 |
|
| 763 |
$nodeoptions = variable_get('node_options_image_import','');
|
| 764 |
if (! is_array($nodeoptions)) {
|
| 765 |
drupal_set_message(t('Node workflow options have not been %configured for the image_import type. Defaults will be used.', array('%configured'=>l(t('configured'),'admin/node/configure/types/image_import'))), 'warning');
|
| 766 |
$nodeoptions = array();
|
| 767 |
}
|
| 768 |
|
| 769 |
// ****** All prechecks are completed here *******
|
| 770 |
if ($precheck_only || $debug) {
|
| 771 |
drupal_set_message(($debug ? t('DEBUG: ') : '') . t('Image %n prechecks okay and should import successfully.', array('%n'=>$file->basename)), $debug ? 'debug' : 'status');
|
| 772 |
}
|
| 773 |
if ($precheck_only) {
|
| 774 |
return (empty($caption) ? IMAGE_IMPORT_STATUS_OK : IMAGE_IMPORT_STATUS_OK_CAPTION);
|
| 775 |
}
|
| 776 |
|
| 777 |
// ****** The following executes only if we are doing a real import ******
|
| 778 |
|
| 779 |
$node =& new stdClass();
|
| 780 |
$node->type = IMAGE_IMPORT_IMAGE_NODETYPE;
|
| 781 |
$node->uid = $user->uid;
|
| 782 |
$node->title = $title;
|
| 783 |
$node->body = $caption;
|
| 784 |
$node->teaser = $teaser;
|
| 785 |
$node->created = $timestamp;
|
| 786 |
$node->changed = $timestamp;
|
| 787 |
$node->promote = in_array('promote', $nodeoptions) ? 1 : 0;
|
| 788 |
$node->status = in_array('status', $nodeoptions) ? 1 : 0;
|
| 789 |
$node->sticky = in_array('sticky', $nodeoptions) ? 1 : 0;
|
| 790 |
$node->revision = in_array('revision', $nodeoptions) ? 1 : 0;
|
| 791 |
$node->moderate = in_array('moderate', $nodeoptions) ? 1 : 0;
|
| 792 |
$node->comment = variable_get('comment_image_import',0);
|
| 793 |
|
| 794 |
if (! image_import_do_node($node, $path)) {
|
| 795 |
return IMAGE_IMPORT_STATUS_ERROR;
|
| 796 |
}
|
| 797 |
|
| 798 |
$nid = $node->nid;
|
| 799 |
|
| 800 |
taxonomy_node_save($nid, $terms);
|
| 801 |
if ($debug) drupal_set_message(t('DEBUG: Saved taxonomy for node nid=%nid',array('%nid'=>$nid)),'debug');
|
| 802 |
_image_build_derivatives($node, FALSE);
|
| 803 |
if ($debug) drupal_set_message(t('DEBUG: Built derivatives for node nid=%nid',array('%nid'=>$nid)),'debug');
|
| 804 |
|
| 805 |
if ($do_delete) {
|
| 806 |
$cap_ok = file_exists($caption_path) ? file_delete($caption_path) : FALSE;
|
| 807 |
if ($cap_ok) drupal_set_message(t('Deleted caption file %p',array('%p'=>$caption_path)),'status');
|
| 808 |
$img_ok = file_exists($path) ? file_delete($path) : FALSE;
|
| 809 |
if ($img_ok) drupal_set_message(t('Deleted image file %p',array('%p'=>$path)),'status');
|
| 810 |
}
|
| 811 |
|
| 812 |
if (empty($caption)) {
|
| 813 |
return IMAGE_IMPORT_STATUS_OK;
|
| 814 |
} else {
|
| 815 |
return IMAGE_IMPORT_STATUS_OK_CAPTION;
|
| 816 |
}
|
| 817 |
}
|
| 818 |
|
| 819 |
/**
|
| 820 |
* Perform the bare image import process on a predefined (existing or new)
|
| 821 |
* node object. All this function does is to physically the file from its
|
| 822 |
* current location into the image directory, then save the node object
|
| 823 |
* using the Drupal node API.
|
| 824 |
*
|
| 825 |
* $path is the Drupal path to the image file in the import directory.
|
| 826 |
*/
|
| 827 |
function image_import_do_node(&$node, $path) {
|
| 828 |
$debug = variable_get('image_import_debug', 0);
|
| 829 |
|
| 830 |
$image_dir = _image_import_get_image_path();
|
| 831 |
if ($debug) drupal_set_message(t('DEBUG: System image directory is \'%id\'.', array('%id'=>$image_dir)), 'debug');
|
| 832 |
|
| 833 |
// Need this dummy array because node_save() calls image_insert() since
|
| 834 |
// this is a node of type 'image'. In this situation, however, we will
|
| 835 |
// take care of importing the file for this node separately.
|
| 836 |
$node->images = array();
|
| 837 |
|
| 838 |
// Copy the image file into the appropriate directory
|
| 839 |
$new_path = $path;
|
| 840 |
if ($debug) drupal_set_message(t('DEBUG: Invoking file_copy(\'%path\', \'%dir\', FILE_EXISTS_RENAME)', array('%path'=>$new_path,'%dir'=>$image_dir)), 'debug');
|
| 841 |
if (file_copy($new_path, $image_dir, FILE_EXISTS_RENAME)) {
|
| 842 |
// The $tmp_path receives the destination path
|
| 843 |
if ($debug) drupal_set_message(t('DEBUG: Copied %p to %np.', array('%p'=>$path, '%np'=>$new_path)), 'debug');
|
| 844 |
} else {
|
| 845 |
drupal_set_message(t('File copy failed for %p to %tp', array('%p'=>$path, '%tp'=>$tmp_path)), 'error');
|
| 846 |
return FALSE;
|
| 847 |
}
|
| 848 |
$node->file = $node->images['_original'] = $new_path;
|
| 849 |
|
| 850 |
// saving a node - first step is to validate
|
| 851 |
$node = node_submit($node);
|
| 852 |
if ($node->validated) {
|
| 853 |
// ... then we save the node
|
| 854 |
node_save($node);
|
| 855 |
if ($debug) drupal_set_message(t('DEBUG: Saved node nid=%nid',array('%nid'=>$nid)),'debug');
|
| 856 |
watchdog('image import',t('Imported "%p" as node %nid',array('%p'=>$path, '%nid'=>$nid)), WATCHDOG_NOTICE, l(t('view'),"node/$nid"));
|
| 857 |
} else {
|
| 858 |
drupal_set_message(t('Unable to create image node.'),'error');
|
| 859 |
return FALSE;
|
| 860 |
}
|
| 861 |
return TRUE;
|
| 862 |
}
|
| 863 |
|
| 864 |
/**
|
| 865 |
* Attempt to fully process an input image file, creating all resized
|
| 866 |
* versions and storing it into the {files} database table.
|
| 867 |
*/
|
| 868 |
function &_image_import_get_file_object($filepath) {
|
| 869 |
$info = image_get_info($filepath);
|
| 870 |
$file = new StdClass();
|
| 871 |
$file->filename = trim(basename($filepath), '.');
|
| 872 |
$file->filemime = $info['mime_type'];
|
| 873 |
$file->filepath = $filepath;
|
| 874 |
$file->error = '';
|
| 875 |
$file->filesize = filesize($filepath);
|
| 876 |
return $file;
|
| 877 |
}
|
| 878 |
|
| 879 |
/**
|
| 880 |
* Looks up the current default path for images, from the image.module and
|
| 881 |
* uploads.module settings.
|
| 882 |
*/
|
| 883 |
function _image_import_get_image_path() {
|
| 884 |
$imgpath = variable_get('image_default_path','');
|
| 885 |
$filepath = variable_get('file_directory_path','');
|
| 886 |
$path = $filepath . '/' . $imgpath;
|
| 887 |
$path = preg_replace('#//#','',$path,-1);
|
| 888 |
// file_downloads value is 1 for public, 2 for private
|
| 889 |
$dl_type = variable_get('file_downloads','');
|
| 890 |
if ($dl_type<>2) {
|
| 891 |
$path = preg_replace('#^/#','',$path);
|
| 892 |
}
|
| 893 |
$path = preg_replace('#/$#','',$path);
|
| 894 |
return $path;
|
| 895 |
}
|
| 896 |
?>
|