security update for uuid xmlsitemap file_field_path
This commit is contained in:
121
sites/all/modules/filefield_paths/.travis.yml
Normal file
121
sites/all/modules/filefield_paths/.travis.yml
Normal file
@@ -0,0 +1,121 @@
|
||||
# @file
|
||||
# .travis.yml - Drupal for Travis CI Integration
|
||||
#
|
||||
# Template provided by https://github.com/LionsAd/drupal_ti.
|
||||
#
|
||||
# Based for simpletest upon:
|
||||
# https://github.com/sonnym/travis-ci-drupal-module-example
|
||||
|
||||
language: php
|
||||
|
||||
sudo: false
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- php: 7
|
||||
|
||||
env:
|
||||
global:
|
||||
# add composer's global bin directory to the path
|
||||
# see: https://github.com/drush-ops/drush#install---composer
|
||||
- PATH="$PATH:$HOME/.composer/vendor/bin"
|
||||
|
||||
# Configuration variables.
|
||||
- DRUPAL_TI_MODULE_NAME="filefield_paths"
|
||||
- DRUPAL_TI_SIMPLETEST_GROUP="File (Field) Paths"
|
||||
|
||||
# Define runners and environment vars to include before and after the
|
||||
# main runners / environment vars.
|
||||
#- DRUPAL_TI_SCRIPT_DIR_BEFORE="./drupal_ti/before"
|
||||
#- DRUPAL_TI_SCRIPT_DIR_AFTER="./drupal_ti/after"
|
||||
|
||||
# The environment to use, supported are: drupal-7, drupal-8
|
||||
- DRUPAL_TI_ENVIRONMENT="drupal-7"
|
||||
|
||||
# Drupal specific variables.
|
||||
- DRUPAL_TI_DB="drupal_travis_db"
|
||||
- DRUPAL_TI_DB_URL="mysql://root:@127.0.0.1/drupal_travis_db"
|
||||
# Note: Do not add a trailing slash here.
|
||||
- DRUPAL_TI_WEBSERVER_URL="http://127.0.0.1"
|
||||
- DRUPAL_TI_WEBSERVER_PORT="8080"
|
||||
|
||||
# Simpletest specific commandline arguments, the DRUPAL_TI_SIMPLETEST_GROUP is appended at the end.
|
||||
- DRUPAL_TI_SIMPLETEST_ARGS="--verbose --color --concurrency 4 --url $DRUPAL_TI_WEBSERVER_URL:$DRUPAL_TI_WEBSERVER_PORT"
|
||||
|
||||
# === Behat specific variables.
|
||||
# This is relative to $TRAVIS_BUILD_DIR
|
||||
- DRUPAL_TI_BEHAT_DIR="./tests/behat"
|
||||
# These arguments are passed to the bin/behat command.
|
||||
- DRUPAL_TI_BEHAT_ARGS=""
|
||||
# Specify the filename of the behat.yml with the $DRUPAL_TI_DRUPAL_DIR variables.
|
||||
- DRUPAL_TI_BEHAT_YML="behat.yml.dist"
|
||||
# This is used to setup Xvfb.
|
||||
- DRUPAL_TI_BEHAT_SCREENSIZE_COLOR="1280x1024x16"
|
||||
# The version of seleniumthat should be used.
|
||||
- DRUPAL_TI_BEHAT_SELENIUM_VERSION="2.44"
|
||||
# Set DRUPAL_TI_BEHAT_DRIVER to "selenium" to use "firefox" or "chrome" here.
|
||||
- DRUPAL_TI_BEHAT_DRIVER="phantomjs"
|
||||
- DRUPAL_TI_BEHAT_BROWSER="firefox"
|
||||
|
||||
# PHPUnit specific commandline arguments.
|
||||
- DRUPAL_TI_PHPUNIT_ARGS=""
|
||||
# Specifying the phpunit-core src/ directory is useful when e.g. a vendor/
|
||||
# directory is present in the module directory, which phpunit would then
|
||||
# try to find tests in. This option is relative to $TRAVIS_BUILD_DIR.
|
||||
#- DRUPAL_TI_PHPUNIT_CORE_SRC_DIRECTORY="./tests/src"
|
||||
|
||||
# Code coverage via coveralls.io
|
||||
- DRUPAL_TI_COVERAGE="satooshi/php-coveralls:0.6.*"
|
||||
# This needs to match your .coveralls.yml file.
|
||||
- DRUPAL_TI_COVERAGE_FILE="build/logs/clover.xml"
|
||||
|
||||
# Debug options
|
||||
#- DRUPAL_TI_DEBUG="-x -v"
|
||||
# Set to "all" to output all files, set to e.g. "xvfb selenium" or "selenium",
|
||||
# etc. to only output those channels.
|
||||
#- DRUPAL_TI_DEBUG_FILE_OUTPUT="selenium xvfb webserver"
|
||||
|
||||
matrix:
|
||||
# [[[ SELECT ANY OR MORE OPTIONS ]]]
|
||||
#- DRUPAL_TI_RUNNERS="phpunit"
|
||||
#- DRUPAL_TI_RUNNERS="simpletest"
|
||||
#- DRUPAL_TI_RUNNERS="behat"
|
||||
#- DRUPAL_TI_RUNNERS="phpunit simpletest behat"
|
||||
# Use phpunit-core to test modules with phpunit with Drupal 8 core.
|
||||
#- DRUPAL_TI_RUNNERS="phpunit-core"
|
||||
- DRUPAL_TI_RUNNERS="simpletest"
|
||||
|
||||
mysql:
|
||||
database: drupal_travis_db
|
||||
username: root
|
||||
encoding: utf8
|
||||
|
||||
before_install:
|
||||
- composer self-update
|
||||
- cd ./tests
|
||||
- composer global require "lionsad/drupal_ti:1.*"
|
||||
- drupal-ti before_install
|
||||
|
||||
install:
|
||||
- drupal-ti install
|
||||
|
||||
before_script:
|
||||
- drupal-ti before_script
|
||||
- drush dl pathauto-7.x redirect-7.x token-7.x transliteration-7.x --destination="$TRAVIS_BUILD_DIR/../drupal-7/drupal/sites/all/modules"
|
||||
|
||||
script:
|
||||
- drupal-ti script
|
||||
|
||||
after_script:
|
||||
- drupal-ti after_script
|
||||
|
||||
notifications:
|
||||
email: false
|
@@ -1,4 +1,100 @@
|
||||
File (Field) Paths 7.x-1.x-dev, xxxx-xx-xx (development release)
|
||||
File (Field) Paths 7.x-1.1, 2018-08-14
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- Fixed security issue
|
||||
- #2643026: Fixed issue when anonymous function not created.
|
||||
|
||||
|
||||
|
||||
File (Field) Paths 7.x-1.0, 2015-11-17
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- #2615704 by morenstrat: Fixed issue with temporary path and schemes.
|
||||
- Added variable module integration.
|
||||
|
||||
|
||||
|
||||
File (Field) Paths 7.x-1.0-rc3, 2015-11-11
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- #2612396: Added watchdog message for unmoved files.
|
||||
- #2607302: Added configurable temporary file location.
|
||||
|
||||
|
||||
|
||||
File (Field) Paths 7.x-1.0-rc2, 2015-10-28
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- #2592519: Fixed issue with temporary upload location and field collections.
|
||||
- #2576547: Fixed issue with Media Youtube files being processed.
|
||||
- #2570127: Added stricter checks for filefield_paths_form_alter().
|
||||
- #2569589: Fixed issue with unicode characters in pathauto processing.
|
||||
|
||||
|
||||
|
||||
File (Field) Paths 7.x-1.0-rc1, 2015-09-15
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- #2551187: Changed token tree to dialog.
|
||||
- #2514874 by Deciphered, smithmilner: Fixed issue with Drush command and
|
||||
permissions.
|
||||
- #2468547 by Deciphered, smithmilner: Added Redirect module integration.
|
||||
- #2398411: Added default value of file_directory to file path.
|
||||
- #2395903: Added truncating of long file paths.
|
||||
- #2383527: Changed unprocessed destination to temporary://.
|
||||
- #2276435 by Deciphered, david_garcia, rajmataj: Fixed issue with retroactive
|
||||
updates and instance settings.
|
||||
- #2271595 by Deciphered, tstoeckler, Reg: Fixed issue with empty batch.
|
||||
- #2214409: Updated field form layout.
|
||||
- #2211665: Added File path validation to remove unnecessary slashes.
|
||||
- #2103151 by Deciphered, david_garcia, Sumeet.Pareek, kitikonti, kolier:
|
||||
Fixed deprecated /e modifier in preg_replace().
|
||||
- #2185755 by treksler: Fixed issue with regex, backreferences and numbers.
|
||||
- #2119789: Fixed issue with complex characters in regex functionality.
|
||||
- #2068365 by Deciphered, vinmassaro: Fixed issue when no instance in update.
|
||||
- #2047835: Fixed issue with pathauto replacemenets and periods (.).
|
||||
- #2019723 by Deciphered, szantog, jcandan, justafish: Fixed issue with remote
|
||||
file stream wrappers.
|
||||
- #1985650: Fixed issue with moved Drush file in .info.
|
||||
- #1985280 by Deciphered, drasgardian: Fixed issue with hook_entity_update()
|
||||
foreach loop.
|
||||
- #1942720 by Deciphered, kaare, alex.designworks, pp, BWPanda: Added slash
|
||||
cleanup functionality.
|
||||
- #1854450: Updated file processing logic.
|
||||
- #1495716/#1986472: Fixed issue with D6 -> D7 upgrade path.
|
||||
- #1292436 by maximpodorov, InternetDevels: Fixed issue pathinfo and UTF files.
|
||||
- Added tests.
|
||||
- Removed dependency on the Token module.
|
||||
|
||||
|
||||
|
||||
File (Field) Paths 7.x-1.0-beta4, 2013-04-25
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- #1945148: Fixed issue with File path cleanup process.
|
||||
- #1942720 by pp: Fixed issue with cleanup wehn token contains a '/' character.
|
||||
- #1925298 by David_Rothstein: Fixed issue with Image derivatives.
|
||||
- #1866450: Fixed issue with foreign characters in Regex.
|
||||
- #1714596: Fixed issue with file_attach_update() introduced in Drupal 7.15.
|
||||
- #1705298: Fixed extra beggining slash.
|
||||
- #1601104 by tseven: Fixed notice when no extension present.
|
||||
- #1572206: Add ability to disable for certain fields.
|
||||
- #1549474: Fixed path replacement in summary text.
|
||||
- #1512466 by maximpodorov, perarnet: Fixed issue with multi-value updates.
|
||||
- #1499442 by hass: Improved translatable strings.
|
||||
- #1464404: Fixed issue with field_attach_update().
|
||||
- #1438290 by xtfer: Fixed D6 to D7 upgrade path.
|
||||
- #1432200: Fixed issue with missing langcode variable.
|
||||
- #1420700: Fixed issue with pass-by-reference issue.
|
||||
- #1364492 by j0rd, Deciphered: Improved require_once routine.
|
||||
- #1361884 by burningdog, dwkitchen, Deciphered: Fixed processing remote files.
|
||||
- #1262828 by Pablo Gosse: Fixed issue with regex.
|
||||
- #860848 by mostou: Fixed File name field length.
|
||||
- Fixed issue with malformed URIs.
|
||||
|
||||
|
||||
|
||||
File (Field) Paths 7.x-1.0-beta3, 2012-02-08
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- #1429238 by ocanzillon: Fixed Drush command syntax error.
|
||||
@@ -6,6 +102,7 @@ File (Field) Paths 7.x-1.x-dev, xxxx-xx-xx (development release)
|
||||
- Changed a large chunk of core functionality to simplify.
|
||||
|
||||
|
||||
|
||||
File (Field) Paths 7.x-1.0-beta2, 2012-02-05
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -16,6 +113,7 @@ File (Field) Paths 7.x-1.0-beta2, 2012-02-05
|
||||
- Added support for Video module.
|
||||
|
||||
|
||||
|
||||
File (Field) Paths 7.x-1.0-beta1, 2011-11-08
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -36,5 +134,6 @@ File (Field) Paths 7.x-1.0-beta1, 2011-11-08
|
||||
- Added Entity support.
|
||||
|
||||
|
||||
|
||||
File (Field) Paths 7.x-1.0-alpha1, 2011-06-12
|
||||
--------------------------------------------------------------------------------
|
||||
|
@@ -1,63 +1,66 @@
|
||||
The File (Field) Paths module extends the default functionality of Drupals core
|
||||
File (Field) Paths
|
||||
==================
|
||||
|
||||
[](https://travis-ci.org/Decipher/filefield_paths)
|
||||
|
||||
The File (Field) Paths module extends the default functionality of Drupal's core
|
||||
File module, Image module and many other File upload modules, by adding the
|
||||
ability to use entity based tokens in destination paths and filenames.
|
||||
ability to use entity based tokens in destination paths and file names.
|
||||
|
||||
In simple terms, File (Field) Paths allows you to automatically sort and rename
|
||||
your uploaded files using token based replacement patterns to maintain a nice
|
||||
clean filesystem.
|
||||
|
||||
File (Field) Paths was written and is maintained by Stuart Clark (deciphered).
|
||||
- http://stuar.tc/lark
|
||||
- http://twitter.com/Decipher
|
||||
|
||||
|
||||
Features
|
||||
--------------------------------------------------------------------------------
|
||||
--------
|
||||
|
||||
* Configurable file paths now use entity tokens in addition to user tokens.
|
||||
* Configurable filenames.
|
||||
* Support for:
|
||||
* Drupal core File module.
|
||||
* Drupal core Image module.
|
||||
* Video module.
|
||||
* Configurable file names.
|
||||
* Support for file based fields, including but not limited to:
|
||||
* Drupal core File module.
|
||||
* Drupal core Image module.
|
||||
* Video module.
|
||||
* File path and filename cleanup options:
|
||||
* Filter out words and punctuation by taking advantage of the Pathauto module.
|
||||
* Convert unicode characters into US-ASCII with the Transliteration module.
|
||||
* Remove slashes from tokens.
|
||||
* Filter out words and punctuation by taking advantage of the Pathauto
|
||||
module.
|
||||
* Convert unicode characters into US-ASCII with the Transliteration module.
|
||||
* Automatically updates unprocessed file paths in any Text fields on the entity.
|
||||
* Retroactive updates - rename and/or move previously uploaded files (Use with
|
||||
caution)
|
||||
* Retroactive updates - rename and/or move previously uploaded files.
|
||||
* Active updating - actively rename and/or move previously uploaded files.
|
||||
* Create redirect - automatically create a redirect when moving uploaded files,
|
||||
using the Redirect module.
|
||||
|
||||
|
||||
Required Modules
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
* Token - http://drupal.org/project/token
|
||||
|
||||
|
||||
Recommended Modules
|
||||
--------------------------------------------------------------------------------
|
||||
-------------------
|
||||
|
||||
* [Pathauto](https://www.drupal.org/project/pathauto)
|
||||
* [Redirect](https://www.drupal.org/project/redirect)
|
||||
* [Token](https://www.drupal.org/project/token)
|
||||
* [Transliteration](https://www.drupal.org/project/transliteration)
|
||||
|
||||
* Pathauto - http://drupal.org/project/pathauto
|
||||
* Transliteration - http://drupal.org/project/transliteration
|
||||
|
||||
|
||||
Usage/Configuration
|
||||
--------------------------------------------------------------------------------
|
||||
-------------------
|
||||
|
||||
Once installed, File (Field) Paths needs to be configured for each file field
|
||||
you wish to use.
|
||||
you wish to use. Settings can be found on the settings form of any supported
|
||||
file based field.
|
||||
|
||||
* Drupal core File/Image and other Field based supported modules
|
||||
Settings an be found on the fields configuration page.
|
||||
|
||||
Example:
|
||||
*Example:*
|
||||
|
||||
Administration > Structure > Content types > Article > Manage fields > Image
|
||||
http://[www.yoursite.com/path/to/drupal]/admin/structure/types/manage/article/fields/field_image
|
||||
http://example.com/admin/structure/types/manage/article/fields/field_image
|
||||
|
||||
|
||||
|
||||
Frequently Asked Questions
|
||||
--------------------------------------------------------------------------------
|
||||
--------------------------
|
||||
|
||||
Q. Aren't tokens already supported in the File module?
|
||||
|
||||
@@ -71,9 +74,9 @@ Q. Why aren't my files in the correct folder?
|
||||
|
||||
A. When you are creating or updating an entity the full values for the tokens
|
||||
may not yet be known by Drupal, so the File (Field) Paths module will upload
|
||||
your files to the Fields old file path temporarily and then once you save the
|
||||
entity and Drupal is provided with the tokens values the file will be moved
|
||||
to the appropriate location.
|
||||
your files to a temporary location and then once you save the entity and
|
||||
Drupal is provided with the tokens values the file will be moved to the
|
||||
appropriate location.
|
||||
|
||||
|
||||
Q. Why is there a warning on the 'Retroactive updates' feature?
|
||||
@@ -85,3 +88,13 @@ A. Retroactive updates will go through every single entity of the particular
|
||||
possible that the moving/renaming of these files could break links. It is
|
||||
strongly advised that you only use this functionality on your developmental
|
||||
servers so that you can make sure not to introduce any linking issues.
|
||||
|
||||
|
||||
|
||||
History and Maintainers
|
||||
-----------------------
|
||||
|
||||
File (Field) Paths was written and is maintained by Stuart Clark (deciphered).
|
||||
|
||||
* http://stuar.tc/lark
|
||||
* http://twitter.com/Decipher
|
49
sites/all/modules/filefield_paths/filefield_paths.admin.inc
Normal file
49
sites/all/modules/filefield_paths/filefield_paths.admin.inc
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Administration functions for the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param $form
|
||||
* @param $form_state
|
||||
* @return mixed
|
||||
*/
|
||||
function filefield_paths_settings_form($form, $form_state) {
|
||||
$form['filefield_paths_temp_location'] = array(
|
||||
'#title' => t('Temporary file location'),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => variable_get('filefield_paths_temp_location', 'public://filefield_paths'),
|
||||
'#description' => t('The location that unprocessed files will be uploaded priot to being processed by File (Field) Paths.<br />It is recommended that you use the temporary file system (temporary://) if your server configuration allows for that.'),
|
||||
'#element_validate' => array('filefield_paths_settings_form_temp_location_validate'),
|
||||
);
|
||||
|
||||
return system_settings_form($form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation callback for 'Temporary file location' setting.
|
||||
*
|
||||
* @param $element
|
||||
* @param $form_state
|
||||
* @return bool
|
||||
*/
|
||||
function filefield_paths_settings_form_temp_location_validate($element, $form_state) {
|
||||
$scheme = file_uri_scheme($element['#value']);
|
||||
if (!$scheme) {
|
||||
form_error($element, t('Invalid file location. You must include a file stream wrapper (e.g., public://).'));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!file_stream_wrapper_valid_scheme($scheme)) {
|
||||
form_error($element, t('Invalid file stream wrapper.'));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((!is_dir($element['#value']) || !is_writable($element['#value'])) && !file_prepare_directory($element['#value'], FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
|
||||
form_error($element, t('File location can not be created or is not writable.'));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
71
sites/all/modules/filefield_paths/filefield_paths.api.php
Normal file
71
sites/all/modules/filefield_paths/filefield_paths.api.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Hooks provided by the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Define field(s) to be displayed on the File (Field) Paths settings form and
|
||||
* used during the processing of uploaded files.
|
||||
*
|
||||
* @param $field
|
||||
* The field definition this File (Field) Paths settings field applies to.
|
||||
* @param $instance
|
||||
* The field instance this File (Field) Paths settings field applies to.
|
||||
*
|
||||
* @return array
|
||||
* An array whose keys are field names and whose values are arrays defining
|
||||
* the field, with the following key/value pairs:
|
||||
* - title: The title fo the field.
|
||||
* - form: A keyed array of Form API elements.
|
||||
*
|
||||
* @see hook_filefield_paths_process_file().
|
||||
*/
|
||||
function hook_filefield_paths_field_settings($field, $instance) {
|
||||
return array(
|
||||
'file_path' => array(
|
||||
'title' => 'File path',
|
||||
'form' => array(
|
||||
'value' => array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('File path'),
|
||||
'#maxlength' => 512,
|
||||
'#size' => 128,
|
||||
'#element_validate' => array('_file_generic_settings_file_directory_validate'),
|
||||
'#default_value' => $instance['settings']['file_directory'],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare a compatible field type for use with File (Field) Paths.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function hook_filefield_paths_field_type_info() {
|
||||
return array('file');
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the uploaded files.
|
||||
*
|
||||
* @param $type
|
||||
* The entity type containing the files for processing.
|
||||
* @param $entity
|
||||
* The entity containing the files for processing.
|
||||
* @param $field
|
||||
* The definition of the field containing the files for processing.
|
||||
* @param $instance
|
||||
* The instance of the field containing the files for processing.
|
||||
* @param $langcode
|
||||
* The language code of the field containing the files for processing.
|
||||
* @param $items
|
||||
* A pass-by-reference array of all the files for processing.
|
||||
*
|
||||
* @see filefield_paths_filefield_paths_process_file().
|
||||
*/
|
||||
function hook_filefield_paths_process_file($type, $entity, $field, $instance, $langcode, &$items) {
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Drush integration.
|
||||
@@ -12,20 +13,20 @@ function filefield_paths_drush_command() {
|
||||
|
||||
$items['ffp-update'] = array(
|
||||
'description' => 'Retroactively updates all File (Field) Paths of a chosen field instance.',
|
||||
'arguments' => array(
|
||||
'arguments' => array(
|
||||
'entity_type' => 'Entity type.',
|
||||
'bundle_name' => 'Bundle name.',
|
||||
'field_name' => 'Field name.'
|
||||
'field_name' => 'Field name.'
|
||||
),
|
||||
'options' => array(
|
||||
'options' => array(
|
||||
'all' => 'Retroactively update all File (Field) Paths.',
|
||||
),
|
||||
'examples' => array(
|
||||
'drush ffp-update' => 'Retroactively updates the File (Field) Paths of the instances choosen via an interactive menu.',
|
||||
'examples' => array(
|
||||
'drush ffp-update' => 'Retroactively updates the File (Field) Paths of the instances choosen via an interactive menu.',
|
||||
'drush ffp-update node article field_image' => 'Retroactively updates the File (Field) Paths of all instances of the Article content types Image field.',
|
||||
'drush ffp-update --all' => 'Retroactively update all File (Field) Paths.',
|
||||
'drush ffp-update --all' => 'Retroactively update all File (Field) Paths.',
|
||||
),
|
||||
'aliases' => array('ffpu'),
|
||||
'aliases' => array('ffpu'),
|
||||
);
|
||||
|
||||
return $items;
|
||||
@@ -33,17 +34,23 @@ function filefield_paths_drush_command() {
|
||||
|
||||
/**
|
||||
* Retroactively updates all File (Field) Paths of a chosen field instance.
|
||||
*
|
||||
* @param null $entity_type
|
||||
* @param null $bundle_name
|
||||
* @param null $field_name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function drush_filefield_paths_ffp_update($entity_type = NULL, $bundle_name = NULL, $field_name = NULL) {
|
||||
// Build array of information of all entity types, bundle names and field
|
||||
// names.
|
||||
$field_types = array_keys(_filefield_paths_get_field_types());
|
||||
$info = array();
|
||||
$info = array();
|
||||
foreach (field_info_fields() as $field) {
|
||||
if (in_array($field['type'], $field_types)) {
|
||||
foreach ($field['bundles'] as $entity_type_name => $bundles) {
|
||||
if (!isset($info[$entity_type_name])) {
|
||||
$entity_type_info = entity_get_info($entity_type_name);
|
||||
$entity_type_info = entity_get_info($entity_type_name);
|
||||
$info[$entity_type_name] = array(
|
||||
'#label' => "{$entity_type_info['label']} ({$entity_type_name})",
|
||||
);
|
||||
@@ -56,6 +63,7 @@ function drush_filefield_paths_ffp_update($entity_type = NULL, $bundle_name = NU
|
||||
);
|
||||
}
|
||||
$field = field_info_instance($entity_type_name, $field['field_name'], $bundle);
|
||||
|
||||
$info[$entity_type_name][$bundle][$field['field_name']] = "{$field['label']} ({$field['field_name']})";
|
||||
}
|
||||
}
|
||||
@@ -72,6 +80,7 @@ function drush_filefield_paths_ffp_update($entity_type = NULL, $bundle_name = NU
|
||||
}
|
||||
}
|
||||
_filefield_paths_drush_ffp_update($instances);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -96,6 +105,7 @@ function drush_filefield_paths_ffp_update($entity_type = NULL, $bundle_name = NU
|
||||
}
|
||||
}
|
||||
_filefield_paths_drush_ffp_update($instances);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -118,6 +128,7 @@ function drush_filefield_paths_ffp_update($entity_type = NULL, $bundle_name = NU
|
||||
}
|
||||
}
|
||||
_filefield_paths_drush_ffp_update($instances);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -138,6 +149,7 @@ function drush_filefield_paths_ffp_update($entity_type = NULL, $bundle_name = NU
|
||||
$instances[] = field_info_instance($entity_type, $field_name, $bundle_name);
|
||||
}
|
||||
_filefield_paths_drush_ffp_update($instances);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -148,13 +160,16 @@ function drush_filefield_paths_ffp_update($entity_type = NULL, $bundle_name = NU
|
||||
|
||||
/**
|
||||
* Helper function; Invokes File (Field) Paths Retroactive updates.
|
||||
*
|
||||
* @param $instances
|
||||
*/
|
||||
function _filefield_paths_drush_ffp_update($instances) {
|
||||
foreach ($instances as $instance) {
|
||||
filefield_paths_batch_update($instance);
|
||||
$batch =& batch_get();
|
||||
$batch['progressive'] = FALSE;
|
||||
drush_backend_batch_process();
|
||||
drush_log(dt('!field_name File (Field) Paths updated.', array('!field_name' => "{$instance['label']} ({$instance['entity_type']}-{$instance['bundle']}-{$instance['field_name']})")), 'success');
|
||||
if (filefield_paths_batch_update($instance)) {
|
||||
$batch =& batch_get();
|
||||
$batch['progressive'] = FALSE;
|
||||
drush_backend_batch_process();
|
||||
drush_log(dt('!field_name File (Field) Paths updated.', array('!field_name' => "{$instance['label']} ({$instance['entity_type']}-{$instance['bundle']}-{$instance['field_name']})")), 'success');
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,25 +1,28 @@
|
||||
name = File (Field) Paths
|
||||
description = Adds improved Token based file sorting and renaming functionalities.
|
||||
dependencies[] = token
|
||||
package = Fields
|
||||
test_dependencies[] = pathauto
|
||||
test_dependencies[] = redirect
|
||||
test_dependencies[] = token
|
||||
test_dependencies[] = transliteration
|
||||
configure = admin/config/media/file-system/filefield-paths
|
||||
core = 7.x
|
||||
|
||||
files[] = filefield_paths.install
|
||||
files[] = filefield_paths.module
|
||||
|
||||
files[] = modules/features.inc
|
||||
files[] = modules/file.inc
|
||||
files[] = modules/filefield_paths.drush.inc
|
||||
files[] = modules/filefield_paths.inc
|
||||
files[] = modules/image.inc
|
||||
files[] = modules/token.inc
|
||||
files[] = modules/video.inc
|
||||
|
||||
;files[] = tests/filefield_paths.test
|
||||
; Simpletest files.
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-02-07
|
||||
version = "7.x-1.0-beta3"
|
||||
files[] = tests/filefield_paths.test
|
||||
files[] = tests/filefield_paths.general.test
|
||||
files[] = tests/filefield_paths.text_replace.test
|
||||
files[] = tests/filefield_paths.tokens.test
|
||||
files[] = tests/filefield_paths.update.test
|
||||
files[] = tests/pathauto.test
|
||||
files[] = tests/redirect.test
|
||||
files[] = tests/transliteration.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2018-08-14
|
||||
version = "7.x-1.1"
|
||||
core = "7.x"
|
||||
project = "filefield_paths"
|
||||
datestamp = "1328655041"
|
||||
|
||||
datestamp = "1534256584"
|
||||
|
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the File (Field) Paths module.
|
||||
@@ -13,10 +14,10 @@
|
||||
function filefield_paths_schema_alter(&$schema) {
|
||||
$schema['file_managed']['fields']['origname'] = array(
|
||||
'description' => 'Original name of the file.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -28,14 +29,12 @@ function filefield_paths_install() {
|
||||
// filenames.
|
||||
db_add_field('file_managed', 'origname', array(
|
||||
'description' => 'Original name of the file with no path components. Used by the filefield_paths module.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
));
|
||||
db_update('file_managed')
|
||||
->expression('origname', 'filename')
|
||||
->execute();
|
||||
db_update('file_managed')->expression('origname', 'filename')->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,10 +75,10 @@ function filefield_paths_update_7103() {
|
||||
if (!db_field_exists('file_managed', 'origname')) {
|
||||
db_add_field('file_managed', 'origname', array(
|
||||
'description' => 'Original name of the file with no path components. Used by the filefield_paths module.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
));
|
||||
}
|
||||
db_update('file_managed')
|
||||
@@ -93,10 +92,10 @@ function filefield_paths_update_7103() {
|
||||
*/
|
||||
function filefield_paths_update_7104() {
|
||||
db_add_field('filefield_paths', 'active_updating', array(
|
||||
'type' => 'int',
|
||||
'size' => 'tiny',
|
||||
'type' => 'int',
|
||||
'size' => 'tiny',
|
||||
'not null' => TRUE,
|
||||
'default' => '0'
|
||||
'default' => '0'
|
||||
));
|
||||
|
||||
// migrate variable to filefield_paths table
|
||||
@@ -123,10 +122,10 @@ function filefield_paths_update_7104() {
|
||||
*/
|
||||
function filefield_paths_update_7105() {
|
||||
db_change_field('filefield_paths', 'active_updating', 'active_updating', array(
|
||||
'type' => 'int',
|
||||
'size' => 'tiny',
|
||||
'type' => 'int',
|
||||
'size' => 'tiny',
|
||||
'not null' => TRUE,
|
||||
'default' => 0
|
||||
'default' => 0
|
||||
));
|
||||
}
|
||||
|
||||
@@ -135,16 +134,16 @@ function filefield_paths_update_7105() {
|
||||
*/
|
||||
function filefield_paths_update_7106() {
|
||||
db_change_field('filefield_paths', 'type', 'type', array(
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => ''
|
||||
'default' => ''
|
||||
));
|
||||
db_change_field('filefield_paths', 'field', 'field', array(
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => ''
|
||||
'default' => ''
|
||||
));
|
||||
}
|
||||
|
||||
@@ -152,33 +151,57 @@ function filefield_paths_update_7106() {
|
||||
* Removed filefield_paths table/schema.
|
||||
*/
|
||||
function filefield_paths_update_7107() {
|
||||
$results = db_select('filefield_paths', 'ffp')->fields('ffp')->execute();
|
||||
foreach ($results as $result) {
|
||||
$instance = field_info_instance('node', $result->field, $result->type);
|
||||
if (!is_null($instance) && isset($instance["ffp_{$result->field}}"])) {
|
||||
$filepath = unserialize($result->filepath);
|
||||
$filename = unserialize($result->filename);
|
||||
|
||||
$instance["ffp_{$result->field}"] = array(
|
||||
'file_path' => $filepath['value'],
|
||||
'file_path_cleanup' => array(
|
||||
'file_path_pathauto' => $filepath['pathauto'],
|
||||
'file_path_transliterate' => $filepath['transliterate'],
|
||||
),
|
||||
'file_name' => $filename['value'],
|
||||
'file_name_cleanup' => array(
|
||||
'file_name_pathauto' => $filename['pathauto'],
|
||||
'file_name_transliterate' => $filename['transliterate'],
|
||||
),
|
||||
'active_updating' => $result->active_updating,
|
||||
);
|
||||
field_update_instance($instance);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove filefield_paths table/schema.
|
||||
db_drop_table('filefield_paths');
|
||||
|
||||
// Update field instance settings.
|
||||
drupal_load('module', 'filefield_paths');
|
||||
$field_types = array_keys(_filefield_paths_get_field_types());
|
||||
foreach (field_info_fields() as $field) {
|
||||
if (in_array($field['type'], $field_types)) {
|
||||
foreach ($field['bundles'] as $entity_type => $bundles) {
|
||||
foreach ($bundles as $bundle_name) {
|
||||
$instance = field_info_instance($entity_type, $field['field_name'], $bundle_name);
|
||||
if ($instance["ffp_{$field['field_name']}"] && !isset($instance['settings']['filefield_paths'])) {
|
||||
if (isset($instance["ffp_{$field['field_name']}"]) && !isset($instance['settings']['filefield_paths'])) {
|
||||
$instance['settings']['filefield_paths'] = array(
|
||||
'file_path' => array(
|
||||
'value' => $instance["ffp_{$field['field_name']}"]['file_path'],
|
||||
'file_path' => array(
|
||||
'value' => $instance["ffp_{$field['field_name']}"]['file_path'],
|
||||
'options' => array(
|
||||
'pathauto' => $instance["ffp_{$field['field_name']}"]['file_path_cleanup']['file_path_pathauto'],
|
||||
'pathauto' => $instance["ffp_{$field['field_name']}"]['file_path_cleanup']['file_path_pathauto'],
|
||||
'transliterate' => $instance["ffp_{$field['field_name']}"]['file_path_cleanup']['file_path_transliterate'],
|
||||
),
|
||||
),
|
||||
'file_name' => array(
|
||||
'value' => $instance["ffp_{$field['field_name']}"]['file_name'],
|
||||
'file_name' => array(
|
||||
'value' => $instance["ffp_{$field['field_name']}"]['file_name'],
|
||||
'options' => array(
|
||||
'pathauto' => $instance["ffp_{$field['field_name']}"]['file_name_cleanup']['file_name_pathauto'],
|
||||
'pathauto' => $instance["ffp_{$field['field_name']}"]['file_name_cleanup']['file_name_pathauto'],
|
||||
'transliterate' => $instance["ffp_{$field['field_name']}"]['file_name_cleanup']['file_name_transliterate'],
|
||||
),
|
||||
),
|
||||
'retroactive_update' => $instance["ffp_{$field['field_name']}"]['retroactive_update'],
|
||||
'active_updating' => $instance["ffp_{$field['field_name']}"]['active_updating'],
|
||||
);
|
||||
unset($instance["ffp_{$field['field_name']}"]);
|
||||
|
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains core functions for the File (Field) Paths module.
|
||||
@@ -7,36 +8,78 @@
|
||||
/**
|
||||
* Include additional files.
|
||||
*/
|
||||
$dirname = dirname(__FILE__) . "/modules";
|
||||
$includes = file_scan_directory($dirname, '/.inc$/');
|
||||
foreach (module_list() as $module) {
|
||||
if (file_exists($file = dirname(__FILE__) . "/modules/{$module}.inc")) {
|
||||
if (isset($includes[$file = "{$dirname}/{$module}.inc"])) {
|
||||
require_once $file;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_alter().
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function filefield_paths_form_alter(&$form, $form_state, $form_id) {
|
||||
function filefield_paths_menu() {
|
||||
$items['admin/config/media/file-system/filefield-paths'] = array(
|
||||
'title' => t('File (Field) Paths settings'),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('filefield_paths_settings_form'),
|
||||
'access arguments' => array('administer site configuration'),
|
||||
'type' => MENU_NORMAL_ITEM,
|
||||
'file' => 'filefield_paths.admin.inc',
|
||||
);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_alter().
|
||||
*
|
||||
* @param $form
|
||||
*/
|
||||
function filefield_paths_form_alter(&$form) {
|
||||
// Force all File (Field) Paths uploads to go to the temporary file system
|
||||
// prior to being processed.
|
||||
if (isset($form['#entity']) && isset($form['#entity_type']) && isset($form['#bundle']) && $form['#type'] == 'form') {
|
||||
filefield_paths_temporary_upload_location($form);
|
||||
}
|
||||
|
||||
$field_types = _filefield_paths_get_field_types();
|
||||
if (isset($form['#field']) && in_array($form['#field']['type'], array_keys($field_types))) {
|
||||
$entity_info = entity_get_info($form['#instance']['entity_type']);
|
||||
$settings = isset($form['#instance']['settings']['filefield_paths']) ? $form['#instance']['settings']['filefield_paths'] : array();
|
||||
$settings = isset($form['#instance']['settings']['filefield_paths']) ? $form['#instance']['settings']['filefield_paths'] : array();
|
||||
|
||||
$form['instance']['settings']['filefield_paths_enabled'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Enable File (Field) Paths?'),
|
||||
'#default_value' => isset($form['#instance']['settings']['filefield_paths_enabled']) ? $form['#instance']['settings']['filefield_paths_enabled'] : TRUE,
|
||||
'#weight' => 2,
|
||||
);
|
||||
|
||||
// Hide standard File directory field.
|
||||
$form['instance']['settings']['file_directory']['#access'] = FALSE;
|
||||
$form['instance']['settings']['file_directory']['#states'] = array(
|
||||
'visible' => array(
|
||||
':input[name="instance[settings][filefield_paths_enabled]"]' => array('checked' => FALSE),
|
||||
),
|
||||
);
|
||||
|
||||
// File (Field) Paths fieldset element.
|
||||
$form['instance']['settings']['filefield_paths'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('File (Field) Path settings'),
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('File (Field) Path settings'),
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
'#weight' => 1,
|
||||
'#tree' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
'#weight' => 3,
|
||||
'#tree' => TRUE,
|
||||
'#states' => array(
|
||||
'visible' => array(
|
||||
':input[name="instance[settings][filefield_paths_enabled]"]' => array('checked' => TRUE),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Additional File (Field) Paths widget fields.
|
||||
$fields = module_invoke_all('filefield_paths_field_settings');
|
||||
$fields = module_invoke_all('filefield_paths_field_settings', $form['#field'], $form['#instance']);
|
||||
foreach ($fields as $name => $field) {
|
||||
// Attach widget fields.
|
||||
$form['instance']['settings']['filefield_paths'][$name] = array(
|
||||
@@ -46,13 +89,14 @@ function filefield_paths_form_alter(&$form, $form_state, $form_id) {
|
||||
// Attach widget field form elements.
|
||||
if (isset($field['form']) && is_array($field['form'])) {
|
||||
foreach (array_keys($field['form']) as $delta => $key) {
|
||||
$form['instance']['settings']['filefield_paths'][$name][$key] = array_merge(
|
||||
$field['form'][$key],
|
||||
array(
|
||||
'#element_validate' => array('token_element_validate'),
|
||||
'#token_types' => array('file', $entity_info['token type']),
|
||||
)
|
||||
);
|
||||
$form['instance']['settings']['filefield_paths'][$name][$key] = $field['form'][$key];
|
||||
if (module_exists('token')) {
|
||||
$form['instance']['settings']['filefield_paths'][$name][$key]['#element_validate'][] = 'token_element_validate';
|
||||
$form['instance']['settings']['filefield_paths'][$name][$key]['#token_types'] = array(
|
||||
'file',
|
||||
$entity_info['token type']
|
||||
);
|
||||
}
|
||||
|
||||
// Fetch stored value from instance.
|
||||
if (isset($settings[$name][$key])) {
|
||||
@@ -62,67 +106,82 @@ function filefield_paths_form_alter(&$form, $form_state, $form_id) {
|
||||
|
||||
// Field options.
|
||||
$form['instance']['settings']['filefield_paths'][$name]['options'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('@title options', array('@title' => $field['title'])),
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('@title options', array('@title' => t($field['title']))),
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
'#weight' => 1,
|
||||
'#attributes' => array(
|
||||
'#collapsed' => TRUE,
|
||||
'#weight' => 1,
|
||||
'#attributes' => array(
|
||||
'class' => array("{$name} cleanup")
|
||||
),
|
||||
);
|
||||
// @TODO - Make this more modular.
|
||||
// Cleanup slashes (/).
|
||||
$form['instance']['settings']['filefield_paths'][$name]['options']['slashes'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Remove slashes (/) from tokens'),
|
||||
'#default_value' => isset($settings[$name]['options']['slashes']) ? $settings[$name]['options']['slashes'] : FALSE,
|
||||
'#description' => t('If checked, any slashes (/) in tokens will be removed from %title.', array('%title' => t($field['title']))),
|
||||
);
|
||||
|
||||
// Cleanup field with Pathauto module.
|
||||
$form['instance']['settings']['filefield_paths'][$name]['options']['pathauto'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Cleanup using Pathauto') . '.',
|
||||
'#default_value' => isset($settings[$name]['options']['pathauto']) && module_exists('pathauto')
|
||||
? $settings[$name]['options']['pathauto']
|
||||
: FALSE,
|
||||
'#description' => t('Cleanup @title using', array('@title' => $field['title'])) . ' ' . l(t('Pathauto settings'), 'admin/config/search/path/settings'),
|
||||
'#disabled' => !module_exists('pathauto'),
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Cleanup using Pathauto'),
|
||||
'#default_value' => isset($settings[$name]['options']['pathauto']) && module_exists('pathauto') ? $settings[$name]['options']['pathauto'] : FALSE,
|
||||
'#description' => t('Cleanup %title using <a href="@pathauto">Pathauto settings</a>.', array(
|
||||
'%title' => t($field['title']),
|
||||
'@pathauto' => url('admin/config/search/path/settings')
|
||||
)),
|
||||
'#disabled' => !module_exists('pathauto'),
|
||||
);
|
||||
|
||||
// Transliterate field with Transliteration module.
|
||||
$form['instance']['settings']['filefield_paths'][$name]['options']['transliterate'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Transliterate') . '.',
|
||||
'#default_value' => isset($settings[$name]['options']['transliterate']) && module_exists('transliteration')
|
||||
? $settings[$name]['options']['transliterate']
|
||||
: 0,
|
||||
'#description' => t('Transliterate @title', array('@title' => $field['title'])) . '.',
|
||||
'#disabled' => !module_exists('transliteration'),
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Transliterate'),
|
||||
'#default_value' => isset($settings[$name]['options']['transliterate']) && module_exists('transliteration') ? $settings[$name]['options']['transliterate'] : 0,
|
||||
'#description' => t('Provides one-way string transliteration (romanization) and cleans the %title during upload by replacing unwanted characters.', array('%title' => t($field['title']))),
|
||||
'#disabled' => !module_exists('transliteration'),
|
||||
);
|
||||
|
||||
// Replacement patterns for field.
|
||||
$form['instance']['settings']['filefield_paths']['token_tree'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Replacement patterns'),
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
'#description' => theme('token_tree', array('token_types' => array('file', $entity_info['token type']))),
|
||||
'#weight' => 10,
|
||||
if (module_exists('token')) {
|
||||
$form['instance']['settings']['filefield_paths']['token_tree'] = array(
|
||||
'#theme' => 'token_tree',
|
||||
'#token_types' => array('file', $entity_info['token type']),
|
||||
'#dialog' => TRUE,
|
||||
'#weight' => 10,
|
||||
);
|
||||
}
|
||||
|
||||
// Redirect
|
||||
$form['instance']['settings']['filefield_paths']['redirect'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Create Redirect'),
|
||||
'#description' => t('Create a redirect to the new location when a previously uploaded file is moved.'),
|
||||
'#default_value' => isset($settings['redirect']) ? $settings['redirect'] : FALSE,
|
||||
'#weight' => 11,
|
||||
);
|
||||
if (!module_exists('redirect')) {
|
||||
$form['instance']['settings']['filefield_paths']['redirect']['#disabled'] = TRUE;
|
||||
$form['instance']['settings']['filefield_paths']['redirect']['#description'] .= '<br />' . t('Requires the <a href="https://drupal.org/project/redirect" target="_blank">Redirect</a> module.');
|
||||
}
|
||||
|
||||
// Retroactive updates.
|
||||
$form['instance']['settings']['filefield_paths']['retroactive_update'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Retroactive update'),
|
||||
'#description' => t('Move and rename previously uploaded files') . '.' .
|
||||
'<br /> <strong style="color: #FF0000;">' . t('Warning') . ':</strong> ' .
|
||||
t('This feature should only be used on developmental servers or with extreme caution') . '.',
|
||||
'#weight' => 11,
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Retroactive update'),
|
||||
'#description' => t('Move and rename previously uploaded files.') . '<div>' . t('<strong class="warning">Warning:</strong> This feature should only be used on developmental servers or with extreme caution.') . '</div>',
|
||||
'#weight' => 12,
|
||||
);
|
||||
|
||||
// Active updating.
|
||||
$form['instance']['settings']['filefield_paths']['active_updating'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Active updating'),
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Active updating'),
|
||||
'#default_value' => isset($settings['active_updating']) ? $settings['active_updating'] : FALSE,
|
||||
'#description' => t('Actively move and rename previously uploaded files as required') . '.' .
|
||||
'<br /> <strong style="color: #FF0000;">' . t('Warning') . ':</strong> ' .
|
||||
t('This feature should only be used on developmental servers or with extreme caution') . '.',
|
||||
'#weight' => 12
|
||||
'#description' => t('Actively move and rename previously uploaded files as required.') . '<div>' . t('<strong class="warning">Warning:</strong> This feature should only be used on developmental servers or with extreme caution.') . '</div>',
|
||||
'#weight' => 13
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -131,14 +190,38 @@ function filefield_paths_form_alter(&$form, $form_state, $form_id) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively set temporary upload location of all File (Field) Paths enabled
|
||||
* managed file fields.
|
||||
*
|
||||
* @param $element
|
||||
*/
|
||||
function filefield_paths_temporary_upload_location(&$element) {
|
||||
if (isset($element['#type']) && $element['#type'] == 'managed_file' && isset($element['#entity_type']) && isset($element['#field_name']) && isset($element['#bundle'])) {
|
||||
$instance = field_info_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']);
|
||||
if (isset($instance['settings']['filefield_paths_enabled']) && $instance['settings']['filefield_paths_enabled']) {
|
||||
$element['#upload_location'] = variable_get('filefield_paths_temp_location', 'public://filefield_paths');
|
||||
}
|
||||
return;
|
||||
}
|
||||
foreach (element_children($element) as $child) {
|
||||
filefield_paths_temporary_upload_location($element[$child]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Submit callback for File (Field) Paths settings form.
|
||||
*
|
||||
* @param $form
|
||||
* @param $form_state
|
||||
*/
|
||||
function filefield_paths_form_submit($form, &$form_state) {
|
||||
// Retroactive updates.
|
||||
if ($form_state['values']['instance']['settings']['filefield_paths']['retroactive_update']) {
|
||||
filefield_paths_batch_update($form_state['values']['instance']);
|
||||
batch_process($form_state['redirect']);
|
||||
if ($form_state['values']['instance']['settings']['filefield_paths_enabled'] && $form_state['values']['instance']['settings']['filefield_paths']['retroactive_update']) {
|
||||
if (filefield_paths_batch_update($form_state['values']['instance'])) {
|
||||
batch_process($form_state['redirect']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,40 +229,58 @@ function filefield_paths_form_submit($form, &$form_state) {
|
||||
* Set batch process to update File (Field) Paths.
|
||||
*
|
||||
* @param $instance
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function filefield_paths_batch_update($instance) {
|
||||
$query = new EntityFieldQuery();
|
||||
$query = new EntityFieldQuery();
|
||||
$result = $query->entityCondition('entity_type', $instance['entity_type'])
|
||||
->entityCondition('bundle', array($instance['bundle']))
|
||||
->fieldCondition($instance['field_name'])
|
||||
->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT')
|
||||
->execute();
|
||||
$objects = array_keys($result[$instance['entity_type']]);
|
||||
|
||||
// If there are no results, do not set a batch as there is nothing to process.
|
||||
if (empty($result[$instance['entity_type']])) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$objects = array_keys($result[$instance['entity_type']]);
|
||||
$instance = field_info_instance($instance['entity_type'], $instance['field_name'], $instance['bundle']);
|
||||
|
||||
// Create batch.
|
||||
$batch = array(
|
||||
'title' => t('Updating File (Field) Paths'),
|
||||
'title' => t('Updating File (Field) Paths'),
|
||||
'operations' => array(
|
||||
array('_filefield_paths_batch_update_process', array($objects, $instance))
|
||||
),
|
||||
);
|
||||
batch_set($batch);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch callback for File (Field) Paths retroactive updates.
|
||||
*
|
||||
* @param $objects
|
||||
* @param $instance
|
||||
* @param $context
|
||||
*
|
||||
* @throws FieldException
|
||||
*/
|
||||
function _filefield_paths_batch_update_process($objects, $instance, &$context) {
|
||||
if (!isset($context['sandbox']['progress'])) {
|
||||
$context['sandbox']['progress'] = 0;
|
||||
$context['sandbox']['max'] = count($objects);
|
||||
$context['sandbox']['objects'] = $objects;
|
||||
$context['sandbox']['max'] = count($objects);
|
||||
$context['sandbox']['objects'] = $objects;
|
||||
}
|
||||
|
||||
// Process nodes by groups of 5.
|
||||
$count = min(5, count($context['sandbox']['objects']));
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
// For each oid, load the object, update the files and save it.
|
||||
$oid = array_shift($context['sandbox']['objects']);
|
||||
$oid = array_shift($context['sandbox']['objects']);
|
||||
$entity = current(entity_load($instance['entity_type'], array($oid)));
|
||||
|
||||
// Enable active updating if it isn't already enabled.
|
||||
@@ -189,8 +290,8 @@ function _filefield_paths_batch_update_process($objects, $instance, &$context) {
|
||||
field_update_instance($instance);
|
||||
}
|
||||
|
||||
// Invoke File (Field) Paths implementation of hook_entity_update().
|
||||
filefield_paths_entity_update($entity, $instance['entity_type']);
|
||||
// Invoke field_attach_update().
|
||||
field_attach_update($instance['entity_type'], $entity);
|
||||
|
||||
// Restore active updating to it's previous state if necessary.
|
||||
if (!$active_updating) {
|
||||
@@ -210,93 +311,161 @@ function _filefield_paths_batch_update_process($objects, $instance, &$context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_insert().
|
||||
* Implements hook_field_storage_pre_insert().
|
||||
*
|
||||
* @param $entity_type
|
||||
* @param $entity
|
||||
*/
|
||||
function filefield_paths_entity_insert($entity, $type) {
|
||||
filefield_paths_entity_update($entity, $type);
|
||||
function filefield_paths_field_storage_pre_insert($entity_type, $entity) {
|
||||
filefield_paths_field_storage_pre_update($entity_type, $entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_update().
|
||||
* Implements hook_field_storage_pre_update().
|
||||
*
|
||||
* @param $entity_type
|
||||
* @param $entity
|
||||
*/
|
||||
function filefield_paths_entity_update($entity, $type) {
|
||||
function filefield_paths_field_storage_pre_update($entity_type, $entity) {
|
||||
$field_types = _filefield_paths_get_field_types();
|
||||
$entity_info = entity_get_info($type);
|
||||
$bundle_name = !empty($entity_info['entity keys']['bundle']) ? $entity->{$entity_info['entity keys']['bundle']} : $type;
|
||||
$entity_info = entity_get_info($entity_type);
|
||||
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
|
||||
if ($entity_info['fieldable']) {
|
||||
foreach (field_info_fields($type, $bundle_name) as $field) {
|
||||
foreach (field_info_fields() as $field) {
|
||||
if (in_array($field['type'], array_keys($field_types))) {
|
||||
$files = array();
|
||||
$instance = field_info_instance($type, $field['field_name'], $bundle_name);
|
||||
if (isset($entity->{$field['field_name']})) {
|
||||
$files = array();
|
||||
$instance = field_info_instance($entity_type, $field['field_name'], $bundle);
|
||||
$enabled = (isset($instance['settings']['filefield_paths_enabled']) && $instance['settings']['filefield_paths_enabled']) || !isset($instance['settings']['filefield_paths_enabled']);
|
||||
if ($enabled && isset($entity->{$field['field_name']}) && is_array($entity->{$field['field_name']})) {
|
||||
foreach ($entity->{$field['field_name']} as $langcode => &$deltas) {
|
||||
foreach ($deltas as $delta => &$file) {
|
||||
// Prepare file.
|
||||
if (function_exists($function = "{$field['module']}_field_load")) {
|
||||
$items = array(array(&$file));
|
||||
$function($type, array($entity), $field, array($instance), $langcode, $items, FIELD_LOAD_CURRENT);
|
||||
$function($entity_type, array($entity), $field, array($instance), $langcode, $items, FIELD_LOAD_CURRENT);
|
||||
}
|
||||
$files[] = &$file;
|
||||
}
|
||||
}
|
||||
// Invoke hook_filefield_paths_process_file().
|
||||
foreach (module_implements('filefield_paths_process_file') as $module) {
|
||||
if (function_exists($function = "{$module}_filefield_paths_process_file")) {
|
||||
$function($type, $entity, $field, $instance, $langcode, $files);
|
||||
// Invoke hook_filefield_paths_process_file().
|
||||
foreach (module_implements('filefield_paths_process_file') as $module) {
|
||||
if (function_exists($function = "{$module}_filefield_paths_process_file")) {
|
||||
$function($entity_type, $entity, $field, $instance, $langcode, $files);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($entity->revision)) {
|
||||
// Remember revision flag.
|
||||
$revision = $entity->revision;
|
||||
// Remove revision flag as long as fields already processed it, and no need
|
||||
// to create new revision for moved files.
|
||||
$entity->revision = FALSE;
|
||||
}
|
||||
// Save any changes back to the database.
|
||||
field_attach_update($type, $entity);
|
||||
if (isset($entity->revision)) {
|
||||
// Restore revision flag so that other modules can process it if needed.
|
||||
$entity->revision = $revision;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_presave().
|
||||
*
|
||||
* @param $file
|
||||
*/
|
||||
function filefield_paths_file_presave($file) {
|
||||
// Store original filename in the database.
|
||||
if (empty($file->origname)) {
|
||||
if (empty($file->origname) && isset($file->filename)) {
|
||||
$file->origname = $file->filename;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a redirect for a moved File field.
|
||||
*
|
||||
* @param $source
|
||||
* @param $path
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
function _filefield_paths_create_redirect($source, $path) {
|
||||
global $base_path;
|
||||
watchdog('filefield_paths', 'Creating redirect from @source to @path', array(
|
||||
'@source' => $source,
|
||||
'@path' => $path
|
||||
), WATCHDOG_DEBUG);
|
||||
|
||||
$redirect = new stdClass();
|
||||
redirect_object_prepare($redirect);
|
||||
|
||||
$parsed_source = parse_url(file_create_url($source), PHP_URL_PATH);
|
||||
$parsed_path = parse_url(file_create_url($path), PHP_URL_PATH);
|
||||
|
||||
$redirect->source = drupal_substr(urldecode($parsed_source), drupal_strlen($base_path));
|
||||
$redirect->redirect = drupal_substr(urldecode($parsed_path), drupal_strlen($base_path));
|
||||
|
||||
// Check if the redirect exists before saving.
|
||||
$hash = redirect_hash($redirect);
|
||||
if (!redirect_load_by_hash($hash)) {
|
||||
redirect_save($redirect);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run regular expression over all available text-based fields.
|
||||
*
|
||||
* @param $old
|
||||
* @param $new
|
||||
* @param $entity
|
||||
*/
|
||||
function _filefield_paths_replace_path($old, $new, $entity) {
|
||||
// Build regular expression.
|
||||
$info = parse_url($old);
|
||||
$info['path'] = !empty($info['path']) ? $info['path'] : '';
|
||||
$absolute = str_replace("{$info['host']}{$info['path']}", '', file_create_url($old));
|
||||
$relative = parse_url($absolute, PHP_URL_PATH);
|
||||
$regex = str_replace('/', '\/', "({$absolute}|{$relative}|{$info['scheme']}://)(styles/.*?/{$info['scheme']}/|)({$info['host']}{$info['path']})");
|
||||
if (isset($info['path'])) {
|
||||
$info['host'] .= $info['path'];
|
||||
}
|
||||
|
||||
// Build replacement.
|
||||
$info = parse_url($new);
|
||||
$info['path'] = !empty($info['path']) ? $info['path'] : '';
|
||||
$replacement = "_filefield_paths_replace_path_uri_scheme('\\1', '{$old}', '{$new}') . '\\2{$info['host']}{$info['path']}'";
|
||||
// Generate all path prefix variations.
|
||||
$prefixes = _filefield_paths_replace_path_get_prefixes($info['scheme'], TRUE);
|
||||
$prefixes = implode('|', $prefixes);
|
||||
|
||||
// Generate all image style path variations.
|
||||
$styles['raw'] = "styles/REGEX/{$info['scheme']}/";
|
||||
$styles['urlencode'] = urlencode($styles['raw']);
|
||||
foreach ($styles as &$style) {
|
||||
$style = str_replace(array('/', 'REGEX'), array('\/', '(.*?)'), $style);
|
||||
}
|
||||
$styles = implode('|', $styles);
|
||||
|
||||
// General all path variations.
|
||||
$paths['raw'] = preg_quote($info['host'], '/');
|
||||
$paths['urlencode'] = preg_quote(urlencode($info['host']), '/');
|
||||
$paths['drupal_encode_path'] = preg_quote(drupal_encode_path($info['host']), '/');
|
||||
|
||||
$paths = implode('|', $paths);
|
||||
|
||||
// Newer versions of the Image module add an 8 character token which is
|
||||
// required if the image style hasn't been generated yet.
|
||||
$itok = '';
|
||||
if (defined('IMAGE_DERIVATIVE_TOKEN')) {
|
||||
$itok = '((?:[\?|&](?:\S+?&)*|(?:%3F|%26)(?:\S+?%26)*)' . IMAGE_DERIVATIVE_TOKEN . '(?:=|%3D)(\S{8}))*';
|
||||
}
|
||||
|
||||
// Build regular expression pattern.
|
||||
$pattern = "/({$prefixes})({$styles})*({$paths}){$itok}/";
|
||||
|
||||
// Create an anonymous function for the replacement via preg_replace_callback.
|
||||
$callback = function ($matches) use ($new, $old) {
|
||||
return filefield_paths_replace_path_callback($matches, $new, $old);
|
||||
};
|
||||
if (!$callback) {
|
||||
watchdog('filefield_paths', 'Unable to create an anonymous function to find references of %old and replace with %new.', array(
|
||||
'%old' => $old,
|
||||
'%new' => $new,
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
$fields = field_info_fields();
|
||||
foreach ($fields as $name => $field) {
|
||||
if ($field['module'] == 'text' && isset($entity->{$field['field_name']}) && is_array($entity->{$field['field_name']})) {
|
||||
foreach ($entity->{$field['field_name']} as &$language) {
|
||||
foreach ($language as &$item) {
|
||||
$item['value'] = preg_replace("/$regex/e", $replacement, $item['value']);
|
||||
foreach (array('value', 'summary') as $column) {
|
||||
if (isset($item[$column])) {
|
||||
$item[$column] = preg_replace_callback($pattern, $callback, $item[$column]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -304,49 +473,172 @@ function _filefield_paths_replace_path($old, $new, $entity) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for File (Field) Paths URI updater regular expression.
|
||||
* Helper function; Returns all variations of the file path prefix.
|
||||
*
|
||||
* Determines what format the old URI prefix was and returns the new URI prefix
|
||||
* in the same format.
|
||||
* @param $scheme
|
||||
* @param bool|FALSE $preg_quote
|
||||
* @param bool|FALSE $reset
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function _filefield_paths_replace_path_uri_scheme($prefix, $old, $new) {
|
||||
switch (TRUE) {
|
||||
case $prefix == file_uri_scheme($old) . '://':
|
||||
return file_uri_scheme($new) . '://';
|
||||
function _filefield_paths_replace_path_get_prefixes($scheme, $preg_quote = FALSE, $reset = FALSE) {
|
||||
$prefixes =& drupal_static(__FUNCTION__, array());
|
||||
|
||||
case $prefix == file_create_url(file_uri_scheme($old) . '://'):
|
||||
return file_create_url(file_uri_scheme($new) . '://');
|
||||
// Force clean urls on.
|
||||
$clean_url = $GLOBALS['conf']['clean_url'];
|
||||
$GLOBALS['conf']['clean_url'] = TRUE;
|
||||
|
||||
case $prefix == parse_url(file_create_url(file_uri_scheme($old) . '://'), PHP_URL_PATH):
|
||||
return parse_url(file_create_url(file_uri_scheme($new) . '://'), PHP_URL_PATH);
|
||||
$id = $scheme . '::' . (string) $preg_quote;
|
||||
if (!isset($prefixes[$id]) || $reset) {
|
||||
$prefixes[$id]['uri'] = "{$scheme}://";
|
||||
$prefixes[$id]['absolute'] = file_create_url($prefixes[$id]['uri']);
|
||||
$prefixes[$id]['relative'] = parse_url($prefixes[$id]['absolute'], PHP_URL_PATH);
|
||||
$prefixes[$id]['unclean'] = '?q=' . drupal_substr($prefixes[$id]['relative'], drupal_strlen(base_path()));
|
||||
|
||||
foreach ($prefixes[$id] as $key => $prefix) {
|
||||
$prefixes[$id]["{$key}-urlencode"] = urlencode($prefix);
|
||||
$prefixes[$id]["{$key}-drupal_encode_path"] = drupal_encode_path($prefix);
|
||||
}
|
||||
|
||||
if ($preg_quote) {
|
||||
foreach ($prefixes[$id] as $key => $prefix) {
|
||||
$prefixes[$id][$key] = preg_quote($prefixes[$id][$key], '/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $prefix;
|
||||
// Restore clean url settings.
|
||||
$GLOBALS['conf']['clean_url'] = $clean_url;
|
||||
|
||||
return $prefixes[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for regex string replacement functionality.
|
||||
*
|
||||
* @param $matches
|
||||
* @param $new
|
||||
* @param $old
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function filefield_paths_replace_path_callback($matches, $new, $old) {
|
||||
$prefix = $matches[1];
|
||||
$styles = $matches[2];
|
||||
$query = isset($matches[6]) ? $matches[6] : '';
|
||||
|
||||
// Get file path info for old file.
|
||||
$old_info = parse_url($old);
|
||||
if (isset($old_info['path'])) {
|
||||
$old_info['host'] .= $old_info['path'];
|
||||
}
|
||||
|
||||
// Determine the file path variation type/modifier.
|
||||
$old_prefixes = _filefield_paths_replace_path_get_prefixes($old_info['scheme']);
|
||||
$modifier = NULL;
|
||||
foreach ($old_prefixes as $key => $old_prefix) {
|
||||
if ($prefix == $old_prefix) {
|
||||
$parts = explode('-', $key);
|
||||
$modifier = isset($parts[1]) ? $parts[1] : NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get file path info for new file.
|
||||
$new_info = parse_url($new);
|
||||
if (isset($new_info['path'])) {
|
||||
$new_info['host'] .= $new_info['path'];
|
||||
}
|
||||
|
||||
// Replace prefix.
|
||||
$prefixes = _filefield_paths_replace_path_get_prefixes($new_info['scheme']);
|
||||
if (isset($key) && isset($prefixes[$key])) {
|
||||
$prefix = $prefixes[$key];
|
||||
}
|
||||
|
||||
// Replace styles directory.
|
||||
if (!empty($styles)) {
|
||||
$styles = str_replace($old_info['scheme'], $new_info['scheme'], $styles);
|
||||
|
||||
// Newer versions of the Image module add an 8 character token which is
|
||||
// required if the image style hasn't been generated yet.
|
||||
if (defined('IMAGE_DERIVATIVE_TOKEN') && isset($matches[7])) {
|
||||
$image_style = !empty($matches[3]) ? $matches[3] : $matches[4];
|
||||
// Only replace the token if the old one was valid.
|
||||
if ($matches[7] == image_style_path_token($image_style, $old)) {
|
||||
$query = substr_replace($query, image_style_path_token($image_style, $new), -strlen($matches[7]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace path.
|
||||
$path = $new_info['host'];
|
||||
if (!is_null($modifier) && function_exists($modifier)) {
|
||||
$path = call_user_func($modifier, $path);
|
||||
}
|
||||
|
||||
return $prefix . $styles . $path . $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process and cleanup strings.
|
||||
*
|
||||
* @param $value
|
||||
* @param $data
|
||||
* @param array $settings
|
||||
*
|
||||
* @return mixed|string
|
||||
*/
|
||||
function filefield_paths_process_string($value, $data, $settings = array()) {
|
||||
$transliterate = module_exists('transliteration') && isset($settings['transliterate']) && $settings['transliterate'];
|
||||
$pathauto = module_exists('pathauto') && isset($settings['pathauto']) && $settings['pathauto'] == TRUE;
|
||||
$transliterate = module_exists('transliteration') && isset($settings['transliterate']) && $settings['transliterate'];
|
||||
$pathauto = module_exists('pathauto') && isset($settings['pathauto']) && $settings['pathauto'] == TRUE;
|
||||
$remove_slashes = !empty($settings['slashes']);
|
||||
|
||||
if ($pathauto == TRUE) {
|
||||
module_load_include('inc', 'pathauto');
|
||||
}
|
||||
|
||||
// If '/' is to be removed from tokens, token replacement need to happen after
|
||||
// splitting the paths to subdirs, otherwise tokens containing '/' will be
|
||||
// part of the final path.
|
||||
if (!$remove_slashes) {
|
||||
$value = token_replace($value, $data, array('clear' => TRUE));
|
||||
}
|
||||
$paths = explode('/', $value);
|
||||
foreach ($paths as &$path) {
|
||||
|
||||
// Process string tokens.
|
||||
$path = token_replace($path, $data, array('clear' => TRUE));
|
||||
|
||||
// Cleanup with pathauto.
|
||||
foreach ($paths as $i => &$path) {
|
||||
if ($remove_slashes) {
|
||||
$path = token_replace($path, $data, array('clear' => TRUE));
|
||||
}
|
||||
if ($pathauto == TRUE) {
|
||||
$path_parts = explode('.', $path);
|
||||
foreach ($path_parts as &$path_part) {
|
||||
$path_part = pathauto_cleanstring($path_part);
|
||||
if ('file_name' == $settings['context'] && count($paths) == $i + 1) {
|
||||
$pathinfo = pathinfo($path);
|
||||
$basename = drupal_basename($path);
|
||||
$extension = preg_match('/\.[^.]+$/', $basename, $matches) ? $matches[0] : NULL;
|
||||
$pathinfo['filename'] = !is_null($extension) ? drupal_substr($basename, 0, drupal_strlen($basename) - drupal_strlen($extension)) : $basename;
|
||||
|
||||
if ($remove_slashes) {
|
||||
$path = '';
|
||||
if (!empty($pathinfo['dirname']) && $pathinfo['dirname'] !== '.') {
|
||||
$path .= $pathinfo['dirname'] . '/';
|
||||
}
|
||||
$path .= $pathinfo['filename'];
|
||||
$path = pathauto_cleanstring($path);
|
||||
if (!empty($pathinfo['extension'])) {
|
||||
$path .= '.' . pathauto_cleanstring($pathinfo['extension']);
|
||||
}
|
||||
$path = str_replace('/', '', $path);
|
||||
}
|
||||
else {
|
||||
$path = str_replace($pathinfo['filename'], pathauto_cleanstring($pathinfo['filename']), $path);
|
||||
}
|
||||
}
|
||||
$path = implode('.', $path_parts);
|
||||
else {
|
||||
$path = pathauto_cleanstring($path);
|
||||
}
|
||||
}
|
||||
elseif ($remove_slashes) {
|
||||
$path = str_replace('/', '', $path);
|
||||
}
|
||||
|
||||
// Transliterate string.
|
||||
@@ -363,7 +655,11 @@ function filefield_paths_process_string($value, $data, $settings = array()) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of all available field types for use with File (Field) Paths.
|
||||
*
|
||||
* @param bool|FALSE $reset
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function _filefield_paths_get_field_types($reset = FALSE) {
|
||||
$field_types = &drupal_static(__FUNCTION__);
|
||||
@@ -372,7 +668,7 @@ function _filefield_paths_get_field_types($reset = FALSE) {
|
||||
$field_types = module_invoke_all('filefield_paths_field_type_info');
|
||||
$field_types = array_flip($field_types);
|
||||
foreach (array_keys($field_types) as $type) {
|
||||
$info = field_info_field_types($type);
|
||||
$info = field_info_field_types($type);
|
||||
$field_types[$type] = array(
|
||||
'label' => $info['label']
|
||||
);
|
||||
@@ -381,3 +677,4 @@ function _filefield_paths_get_field_types($reset = FALSE) {
|
||||
|
||||
return $field_types;
|
||||
}
|
||||
|
||||
|
72
sites/all/modules/filefield_paths/filefield_paths.tokens.inc
Normal file
72
sites/all/modules/filefield_paths/filefield_paths.tokens.inc
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tokens for the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_token_info().
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function filefield_paths_token_info() {
|
||||
$info['tokens']['file']['ffp-name-only'] = array(
|
||||
'name' => t("File name"),
|
||||
'description' => t("File name without extension."),
|
||||
);
|
||||
$info['tokens']['file']['ffp-name-only-original'] = array(
|
||||
'name' => t("File name - original"),
|
||||
'description' => t("File name without extension - original."),
|
||||
);
|
||||
$info['tokens']['file']['ffp-extension-original'] = array(
|
||||
'name' => t("File extension - original"),
|
||||
'description' => t("File extension - original."),
|
||||
);
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_tokens().
|
||||
*
|
||||
* @param $type
|
||||
* @param $tokens
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function filefield_paths_tokens($type, $tokens, array $data = array()) {
|
||||
$url_options = array('absolute' => TRUE);
|
||||
if (isset($language)) {
|
||||
$url_options['language'] = $language;
|
||||
}
|
||||
|
||||
$replacements = array();
|
||||
|
||||
if ($type == 'file' && !empty($data['file'])) {
|
||||
$file = $data['file'];
|
||||
|
||||
foreach ($tokens as $name => $original) {
|
||||
switch ($name) {
|
||||
case 'ffp-name-only':
|
||||
$basename = drupal_basename($file->filename);
|
||||
$extension = preg_match('/\.[^.]+$/', $basename, $matches) ? $matches[0] : NULL;
|
||||
$replacements[$original] = !is_null($extension) ? drupal_substr($basename, 0, drupal_strlen($basename) - drupal_strlen($extension)) : $basename;
|
||||
break;
|
||||
|
||||
case 'ffp-name-only-original':
|
||||
$basename = drupal_basename($file->origname);
|
||||
$extension = preg_match('/\.[^.]+$/', $basename, $matches) ? $matches[0] : NULL;
|
||||
$replacements[$original] = !is_null($extension) ? drupal_substr($basename, 0, drupal_strlen($basename) - drupal_strlen($extension)) : $basename;
|
||||
break;
|
||||
|
||||
case 'ffp-extension-original':
|
||||
$replacements[$original] = preg_match('/[^.]+$/', drupal_basename($file->origname), $matches) ? $matches[0] : NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $replacements;
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains Variable functions for the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_variable_info().
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function filefield_paths_variable_info() {
|
||||
$variables['filefield_paths_temp_location'] = array(
|
||||
'title' => t('Temporary file location'),
|
||||
'type' => 'string',
|
||||
'default' => 'public://filefield_paths',
|
||||
'description' => t('The location that unprocessed files will be uploaded priot to being processed by File (Field) Paths.<br />It is recommended that you use the temporary file system (temporary://) if your server configuration allows for that.'),
|
||||
'validate callback' => 'filefield_paths_variable_temp_location_validate',
|
||||
'group' => 'filefield_paths',
|
||||
);
|
||||
|
||||
return $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate callback for 'Temporary file location' variable.
|
||||
*
|
||||
* @param $element
|
||||
*/
|
||||
function filefield_paths_variable_temp_location_validate($element) {
|
||||
// Add FAPI element keys for standard validation callback.
|
||||
$element['#parents'] = array('filefield_paths_temp_location');
|
||||
$element['#value'] = $element['value'];
|
||||
|
||||
// Pass element through standard validation callback.
|
||||
module_load_include('admin.inc', 'filefield_paths');
|
||||
filefield_paths_settings_form_temp_location_validate($element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_variable_group_info().
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function filefield_paths_variable_group_info() {
|
||||
$groups['filefield_paths'] = array(
|
||||
'title' => t('File (Field) Paths'),
|
||||
'description' => t('File (Field) Paths settings.'),
|
||||
'access' => 'administer site configuration',
|
||||
'path' => array(
|
||||
'admin/config/media/file-system/filefield-paths'
|
||||
),
|
||||
);
|
||||
|
||||
return $groups;
|
||||
}
|
@@ -1,16 +1,21 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Features module integration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_features_pipe_field_alter().
|
||||
* Implements hook_features_pipe_field_instance_alter().
|
||||
*
|
||||
* This determines whether exported fields contain File (Field) Paths settings
|
||||
* and if so adds File (Field) Paths as a dependency.
|
||||
*
|
||||
* @param $pipe
|
||||
* @param $data
|
||||
* @param $export
|
||||
*/
|
||||
function filefield_paths_features_pipe_field_alter(&$pipe, $data, &$export) {
|
||||
function filefield_paths_features_pipe_field_instance_alter(&$pipe, $data, &$export) {
|
||||
foreach ($data as $field_identifier) {
|
||||
list($entity_type, $bundle_name, $field_name) = explode('-', $field_identifier);
|
||||
$instance = field_info_instance($entity_type, $field_name, $bundle_name);
|
||||
@@ -19,3 +24,14 @@ function filefield_paths_features_pipe_field_alter(&$pipe, $data, &$export) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_features_pipe_field_alter().
|
||||
*
|
||||
* @param $pipe
|
||||
* @param $data
|
||||
* @param $export
|
||||
*/
|
||||
function filefield_paths_features_pipe_field_alter(&$pipe, $data, &$export) {
|
||||
filefield_paths_features_pipe_field_instance_alter($pipe, $data, $export);
|
||||
}
|
||||
|
@@ -1,11 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* File module integration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_filefield_paths_filed_type_info() on behalf of file.module.
|
||||
* Implements hook_filefield_paths_field_type_info() on behalf of file.module.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function file_filefield_paths_field_type_info() {
|
||||
return array('file');
|
||||
|
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* File (Field) Paths module integration.
|
||||
@@ -6,31 +7,35 @@
|
||||
|
||||
/**
|
||||
* Implements hook_filefield_paths_field_settings().
|
||||
*
|
||||
* @param $field
|
||||
* @param $instance
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function filefield_paths_filefield_paths_field_settings() {
|
||||
function filefield_paths_filefield_paths_field_settings($field, $instance) {
|
||||
return array(
|
||||
'file_path' => array(
|
||||
'title' => 'File path',
|
||||
'sql' => 'filepath',
|
||||
|
||||
'form' => array(
|
||||
'form' => array(
|
||||
'value' => array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('File path'),
|
||||
'#maxlength' => 512,
|
||||
'#size' => 128,
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('File path'),
|
||||
'#maxlength' => 512,
|
||||
'#size' => 128,
|
||||
'#element_validate' => array('_file_generic_settings_file_directory_validate'),
|
||||
'#default_value' => $instance['settings']['file_directory'],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
'file_name' => array(
|
||||
'title' => 'File name',
|
||||
'sql' => 'filename',
|
||||
|
||||
'form' => array(
|
||||
'form' => array(
|
||||
'value' => array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('File name'),
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('File name'),
|
||||
'#maxlength' => 512,
|
||||
'#size' => 128,
|
||||
'#default_value' => '[file:ffp-name-only-original].[file:ffp-extension-original]',
|
||||
),
|
||||
),
|
||||
@@ -40,42 +45,86 @@ function filefield_paths_filefield_paths_field_settings() {
|
||||
|
||||
/**
|
||||
* Implements hook_filefield_paths_process_file().
|
||||
*
|
||||
* @param $type
|
||||
* @param $entity
|
||||
* @param $field
|
||||
* @param $instance
|
||||
* @param $langcode
|
||||
* @param $items
|
||||
*/
|
||||
function filefield_paths_filefield_paths_process_file($type, $entity, $field, $instance, $langcode, &$items) {
|
||||
$settings = $instance['settings']['filefield_paths'];
|
||||
foreach ($items as &$file) {
|
||||
if ($file['timestamp'] == REQUEST_TIME || $settings['active_updating']) {
|
||||
$token_data = array(
|
||||
'file' => (object) $file,
|
||||
$type => $entity
|
||||
);
|
||||
if (isset($instance['settings']['filefield_paths'])) {
|
||||
$settings = $instance['settings']['filefield_paths'];
|
||||
|
||||
// Copy the original file for comparision purposes.
|
||||
$old_file = $file;
|
||||
|
||||
// Process filename.
|
||||
$file['filename'] = !empty($settings['file_name']['value'])
|
||||
? filefield_paths_process_string($settings['file_name']['value'], $token_data, $settings['file_name']['options'])
|
||||
: $file['filename'];
|
||||
|
||||
// Process filepath.
|
||||
$file['uri'] = "{$field['settings']['uri_scheme']}://" . filefield_paths_process_string($settings['file_path']['value'] . "/{$file['filename']}", $token_data, $settings['file_path']['options']);
|
||||
|
||||
// Finalize file if necessary.
|
||||
if ($file !== $old_file) {
|
||||
if (file_prepare_directory(drupal_dirname($file['uri']), FILE_CREATE_DIRECTORY) && file_move((object) $old_file, $file['uri'])) {
|
||||
// Process regular expression.
|
||||
_filefield_paths_replace_path($old_file['uri'], $file['uri'], $entity);
|
||||
|
||||
// Remove any old empty directories.
|
||||
$scheme = file_uri_scheme($old_file['uri']);
|
||||
$paths = explode('/', str_replace("{$scheme}://", '', drupal_dirname($old_file['uri'])));
|
||||
while ($paths) {
|
||||
if (@drupal_rmdir("{$scheme}://" . implode('/', $paths)) == TRUE) {
|
||||
array_pop($paths);
|
||||
continue;
|
||||
// Check that the destination is writeable.
|
||||
$wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_WRITE);
|
||||
foreach ($items as &$file) {
|
||||
$source_scheme = file_uri_scheme($file['uri']);
|
||||
$temporary_scheme = file_uri_scheme(variable_get('filefield_paths_temp_location', 'public://filefield_paths'));
|
||||
$destination_scheme = $field['settings']['uri_scheme'];
|
||||
if (in_array($source_scheme, array($temporary_scheme, $destination_scheme)) && !empty($wrappers[$destination_scheme])) {
|
||||
// Process file if this is a new entity, 'Active updating' is set or
|
||||
// file wasn't previously attached to the entity.
|
||||
if (isset($entity->original) && empty($settings['active_updating']) && !empty($entity->original->{$field['field_name']}[$langcode])) {
|
||||
foreach ($entity->original->{$field['field_name']}[$langcode] as $original_file) {
|
||||
if ($original_file['fid'] == $file['fid']) {
|
||||
continue(2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$token_data = array(
|
||||
'file' => (object) $file,
|
||||
$type => $entity
|
||||
);
|
||||
|
||||
// Copy the original file for comparison purposes.
|
||||
$old_file = $file;
|
||||
|
||||
// Process filename.
|
||||
$settings['file_name']['options']['context'] = 'file_name';
|
||||
$file['filename'] = !empty($settings['file_name']['value']) ? filefield_paths_process_string($settings['file_name']['value'], $token_data, $settings['file_name']['options']) : $file['filename'];
|
||||
|
||||
// Process filepath.
|
||||
$settings['file_path']['options']['context'] = 'file_path';
|
||||
$path = filefield_paths_process_string($settings['file_path']['value'], $token_data, $settings['file_path']['options']);
|
||||
$file['uri'] = file_stream_wrapper_uri_normalize("{$destination_scheme}://{$path}/{$file['filename']}");
|
||||
|
||||
// Ensure file uri is no more than 255 characters.
|
||||
if (drupal_strlen($file['uri']) > 255) {
|
||||
watchdog('filefield_paths', 'File path was truncated.', array(), WATCHDOG_INFO);
|
||||
$pathinfo = pathinfo($file['uri']);
|
||||
$file['uri'] = drupal_substr($file['uri'], 0, 254 - drupal_strlen($pathinfo['extension'])) . ".{$pathinfo['extension']}";
|
||||
}
|
||||
|
||||
// Finalize file if necessary.
|
||||
if ($file !== $old_file) {
|
||||
$dirname = drupal_dirname($file['uri']);
|
||||
if (file_prepare_directory($dirname, FILE_CREATE_DIRECTORY) && $new_file = file_move((object) $old_file, $file['uri'])) {
|
||||
// Process regular expression.
|
||||
_filefield_paths_replace_path($old_file['uri'], $file['uri'], $entity);
|
||||
|
||||
// Create redirect from old location.
|
||||
if (module_exists('redirect') && !empty($settings['redirect']) && $settings['active_updating']) {
|
||||
_filefield_paths_create_redirect($old_file['uri'], $new_file->uri);
|
||||
}
|
||||
|
||||
// Remove any old empty directories.
|
||||
$paths = explode('/', str_replace("{$source_scheme}://", '', drupal_dirname($old_file['uri'])));
|
||||
while ($paths) {
|
||||
if (@drupal_rmdir("{$source_scheme}://" . implode('/', $paths)) == TRUE) {
|
||||
array_pop($paths);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
watchdog('filefield_paths', 'The file %old could not be moved to the destination of %new. Ensure your permissions are set correctly.', array(
|
||||
'%old' => $old_file['uri'],
|
||||
'%new' => $file['uri'],
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Image module integration.
|
||||
@@ -6,7 +7,23 @@
|
||||
|
||||
/**
|
||||
* Implements hook_filefield_paths_field_type_info() on behalf of image.module.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function image_filefield_paths_field_type_info() {
|
||||
return array('image');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu_alter().
|
||||
*
|
||||
* @param $items
|
||||
*/
|
||||
function filefield_paths_menu_alter(&$items) {
|
||||
// Workaround for issue with 'temporary://' image styles not being generated
|
||||
// correctly in Drupal core Image module.
|
||||
// @see https://www.drupal.org/node/2560139
|
||||
if (!isset($items['system/temporary/styles/%image_style']) && isset($items['system/files/styles/%image_style'])) {
|
||||
$items['system/temporary/styles/%image_style'] = $items['system/files/styles/%image_style'];
|
||||
}
|
||||
}
|
||||
|
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Token module integration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_token_info().
|
||||
*/
|
||||
function filefield_paths_token_info() {
|
||||
$info['tokens']['file']['ffp-name-only'] = array(
|
||||
'name' => t("File name"),
|
||||
'description' => t("File name without extension."),
|
||||
);
|
||||
$info['tokens']['file']['ffp-name-only-original'] = array(
|
||||
'name' => t("File name - original"),
|
||||
'description' => t("File name without extension - original."),
|
||||
);
|
||||
$info['tokens']['file']['ffp-extension-original'] = array(
|
||||
'name' => t("File extension - original"),
|
||||
'description' => t("File extension - original."),
|
||||
);
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_tokens().
|
||||
*/
|
||||
function filefield_paths_tokens($type, $tokens, array $data = array(), array $options = array()) {
|
||||
$url_options = array('absolute' => TRUE);
|
||||
if (isset($language)) {
|
||||
$url_options['language'] = $language;
|
||||
}
|
||||
$sanitize = !empty($options['sanitize']);
|
||||
|
||||
$replacements = array();
|
||||
|
||||
if ($type == 'file' && !empty($data['file'])) {
|
||||
$file = $data['file'];
|
||||
|
||||
foreach ($tokens as $name => $original) {
|
||||
switch ($name) {
|
||||
case 'ffp-name-only':
|
||||
$info = pathinfo($file->filename);
|
||||
$replacements[$original] = $info['filename'];
|
||||
break;
|
||||
|
||||
case 'ffp-name-only-original':
|
||||
$info = pathinfo($file->origname);
|
||||
$replacements[$original] = $info['filename'];
|
||||
break;
|
||||
|
||||
case 'ffp-extension-original':
|
||||
$info = pathinfo($file->origname);
|
||||
$replacements[$original] = $info['extension'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $replacements;
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Video module integration.
|
||||
@@ -6,6 +7,8 @@
|
||||
|
||||
/**
|
||||
* Implements hook_filefield_paths_field_type_info() on behalf of video.module.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function video_filefield_paths_field_type_info() {
|
||||
return array('video');
|
||||
|
@@ -0,0 +1,327 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tests for the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class FileFieldPathsGeneralTestCase
|
||||
*/
|
||||
class FileFieldPathsGeneralTestCase extends FileFieldPathsTestCase {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'General functionality',
|
||||
'description' => 'Test general functionality.',
|
||||
'group' => 'File (Field) Paths',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the File (Field) Paths UI works as expected.
|
||||
*/
|
||||
public function testAddField() {
|
||||
// Create a File field.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$instance_settings = array('file_directory' => "fields/{$field_name}");
|
||||
$this->createFileField($field_name, $this->content_type, array(), $instance_settings);
|
||||
|
||||
// Ensure File (Field) Paths settings are present.
|
||||
$this->drupalGet("admin/structure/types/manage/{$this->content_type}/fields/{$field_name}");
|
||||
$this->assertText('Enable File (Field) Paths?', t('File (Field) Path settings are present.'));
|
||||
|
||||
// Ensure that 'Enable File (Field) Paths?' is a direct sibling of
|
||||
// 'File (Field) Path settings'.
|
||||
$element = $this->xpath('//div[contains(@class, :class)]/following-sibling::*[1]/@id', array(':class' => 'form-item-instance-settings-filefield-paths-enabled'));
|
||||
$this->assert(isset($element[0]) && 'edit-instance-settings-filefield-paths' == (string) $element[0], t('Enable checkbox is next to settings fieldset.'));
|
||||
|
||||
// Ensure that the File path used the File directory as it's default value.
|
||||
$this->assertFieldByName('instance[settings][filefield_paths][file_path][value]', "fields/{$field_name}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test File (Field) Paths works as normal when no file uploaded.
|
||||
*/
|
||||
public function testNoFile() {
|
||||
// Create a File field.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$instance_settings['filefield_paths']['file_path']['value'] = 'node/[node:nid]';
|
||||
$instance_settings['filefield_paths']['file_name']['value'] = '[node:nid].[file:ffp-extension-original]';
|
||||
$this->createFileField($field_name, $this->content_type, array(), $instance_settings);
|
||||
|
||||
// Create a node without a file attached.
|
||||
$this->drupalCreateNode(array('type' => $this->content_type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a basic file upload with File (Field) Paths.
|
||||
*/
|
||||
public function testUploadFile() {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
|
||||
// Create a File field with 'node/[node:nid]' as the File path and
|
||||
// '[node:nid].[file:ffp-extension-original]' as the File name.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$instance_settings['filefield_paths']['file_path']['value'] = 'node/[node:nid]';
|
||||
$instance_settings['filefield_paths']['file_name']['value'] = '[node:nid].[file:ffp-extension-original]';
|
||||
$this->createFileField($field_name, $this->content_type, array(), $instance_settings);
|
||||
|
||||
$schemes = array('public', 'private');
|
||||
foreach ($schemes as $scheme) {
|
||||
// Set the field URI scheme.
|
||||
$this->drupalPost("admin/structure/types/manage/{$this->content_type}/fields/{$field_name}", array('field[settings][uri_scheme]' => $scheme), t('Save settings'));
|
||||
|
||||
// Upload a file to a node.
|
||||
$test_file = $this->getTestFile('text');
|
||||
$this->drupalGet("node/add/{$this->content_type}");
|
||||
$edit['title'] = $this->randomName();
|
||||
$edit["files[{$field_name}_{$langcode}_0]"] = $test_file->uri;
|
||||
$this->drupalPost(NULL, $edit, t('Upload'));
|
||||
|
||||
// Ensure that the file was put into the Temporary file location.
|
||||
$temp_location = variable_get('filefield_paths_temp_location', 'public://filefield_paths');
|
||||
$this->assertRaw(file_create_url("{$temp_location}/{$test_file->filename}"), t('File has been uploaded to the temporary file location.'));
|
||||
|
||||
// Save the node.
|
||||
$this->drupalPost(NULL, array(), t('Save'));
|
||||
|
||||
// Get created Node ID.
|
||||
$matches = array();
|
||||
preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches);
|
||||
$nid = $matches[1];
|
||||
|
||||
// Ensure that the File path has been processed correctly.
|
||||
$uri = file_create_url("{$scheme}://node/{$nid}/{$nid}.txt");
|
||||
$this->assertRaw($uri, t('The File path has been processed correctly.'));
|
||||
|
||||
// Delete the node so we can change the URI scheme.
|
||||
node_delete($nid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a multivalue file upload with File (Field) Paths.
|
||||
*/
|
||||
public function testUploadFileMultivalue() {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
|
||||
// Create a multivalue File field with 'node/[node:nid]' as the File path
|
||||
// and '[file:fid].txt' as the File name.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$field_settings['cardinality'] = FIELD_CARDINALITY_UNLIMITED;
|
||||
$instance_settings['filefield_paths']['file_path']['value'] = 'node/[node:nid]';
|
||||
$instance_settings['filefield_paths']['file_name']['value'] = '[file:fid].txt';
|
||||
$this->createFileField($field_name, $this->content_type, $field_settings, $instance_settings);
|
||||
|
||||
// Create a node with three (3) test files.
|
||||
$text_files = $this->drupalGetTestFiles('text');
|
||||
$this->drupalGet("node/add/{$this->content_type}");
|
||||
$this->drupalPost(NULL, array("files[{$field_name}_{$langcode}_0]" => drupal_realpath($text_files[0]->uri)), t('Upload'));
|
||||
$this->drupalPost(NULL, array("files[{$field_name}_{$langcode}_1]" => drupal_realpath($text_files[1]->uri)), t('Upload'));
|
||||
$edit = array(
|
||||
'title' => $this->randomName(),
|
||||
"files[{$field_name}_{$langcode}_2]" => drupal_realpath($text_files[1]->uri),
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
|
||||
// Get created Node ID.
|
||||
$matches = array();
|
||||
preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches);
|
||||
$nid = $matches[1];
|
||||
|
||||
// Ensure that the File path has been processed correctly.
|
||||
$this->assertRaw("{$this->public_files_directory}/node/{$nid}/1.txt", t('The first File path has been processed correctly.'));
|
||||
$this->assertRaw("{$this->public_files_directory}/node/{$nid}/2.txt", t('The second File path has been processed correctly.'));
|
||||
$this->assertRaw("{$this->public_files_directory}/node/{$nid}/3.txt", t('The third File path has been processed correctly.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test File (Field) Paths with a very long path.
|
||||
*/
|
||||
public function testLongPath() {
|
||||
// Create a File field with 'node/[random:hash:sha256]' as the File path.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$instance_settings['filefield_paths']['file_path']['value'] = 'node/[random:hash:sha512]/[random:hash:sha512]';
|
||||
$this->createFileField($field_name, $this->content_type, array(), $instance_settings);
|
||||
|
||||
// Create a node with a test file.
|
||||
$test_file = $this->getTestFile('text');
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $this->content_type);
|
||||
|
||||
// Ensure file path is no more than 255 characters.
|
||||
$node = node_load($nid, NULL, TRUE);
|
||||
$this->assert(drupal_strlen($node->{$field_name}[LANGUAGE_NONE][0]['uri']) <= 255, t('File path is no more than 255 characters'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test File (Field) Paths on a programmatically added file.
|
||||
*/
|
||||
public function testProgrammaticAttach() {
|
||||
// Create a File field with 'node/[node:nid]' as the File path and
|
||||
// '[node:nid].[file:ffp-extension-original]' as the File name.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$instance_settings['filefield_paths']['file_path']['value'] = 'node/[node:nid]';
|
||||
$instance_settings['filefield_paths']['file_name']['value'] = '[node:nid].[file:ffp-extension-original]';
|
||||
$this->createFileField($field_name, $this->content_type, array(), $instance_settings);
|
||||
|
||||
// Create a node without an attached file.
|
||||
$node = $this->drupalCreateNode(array('type' => $this->content_type));
|
||||
|
||||
// Create a file object.
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
$file = new stdClass();
|
||||
$file->fid = NULL;
|
||||
$file->uri = $test_file->uri;
|
||||
$file->filename = basename($file->uri);
|
||||
$file->filemime = file_get_mimetype($file->uri);
|
||||
$file->uid = $GLOBALS['user']->uid;
|
||||
$file->status = FILE_STATUS_PERMANENT;
|
||||
$file->display = TRUE;
|
||||
file_save($file);
|
||||
|
||||
// Adjust timestamp to simulate real-world experience.
|
||||
$file->timestamp = REQUEST_TIME - 60;
|
||||
|
||||
// Attach the file to the node.
|
||||
$node->{$field_name}[LANGUAGE_NONE][0] = (array) $file;
|
||||
node_save($node);
|
||||
|
||||
// Ensure that the File path has been processed correctly.
|
||||
$node = node_load($node->nid, NULL, TRUE);
|
||||
$this->assertEqual("public://node/{$node->nid}/{$node->nid}.txt", $node->{$field_name}[LANGUAGE_NONE][0]['uri'], t('The File path has been processed correctly.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test File (Field) Paths slashes cleanup functionality.
|
||||
*/
|
||||
public function testSlashes() {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
|
||||
// Create a File field with 'node/[node:title]' as the File path and
|
||||
// '[node:title].[file:ffp-extension-original]' as the File name.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$instance_settings['filefield_paths']['file_path']['value'] = 'node/[node:title]';
|
||||
$instance_settings['filefield_paths']['file_name']['value'] = '[node:title].[file:ffp-extension-original]';
|
||||
$this->createFileField($field_name, $this->content_type, array(), $instance_settings);
|
||||
|
||||
// Create a node with a test file.
|
||||
$test_file = $this->getTestFile('text');
|
||||
|
||||
$title = "{$this->randomName()}/{$this->randomName()}";
|
||||
$edit['title'] = $title;
|
||||
$edit["body[{$langcode}][0][value]"] = '';
|
||||
$edit["files[{$field_name}_{$langcode}_0]"] = drupal_realpath($test_file->uri);
|
||||
$this->drupalPost("node/add/{$this->content_type}", $edit, t('Save'));
|
||||
|
||||
// Get created Node ID.
|
||||
$matches = array();
|
||||
preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches);
|
||||
$nid = $matches[1];
|
||||
|
||||
// Ensure slashes are present in file path and name.
|
||||
$node = node_load($nid);
|
||||
$this->assertEqual("public://node/{$title}/{$title}.txt", $node->{$field_name}[$langcode][0]['uri']);
|
||||
|
||||
// Remove slashes.
|
||||
$edit = array(
|
||||
'instance[settings][filefield_paths][file_path][options][slashes]' => TRUE,
|
||||
'instance[settings][filefield_paths][file_name][options][slashes]' => TRUE,
|
||||
'instance[settings][filefield_paths][retroactive_update]' => TRUE,
|
||||
);
|
||||
$this->drupalPost("admin/structure/types/manage/{$this->content_type}/fields/{$field_name}", $edit, t('Save settings'));
|
||||
|
||||
// Ensure slashes are not present in file path and name.
|
||||
$node = node_load($nid, NULL, TRUE);
|
||||
$title = str_replace('/', '', $title);
|
||||
$this->assertEqual("public://node/{$title}/{$title}.txt", $node->{$field_name}[$langcode][0]['uri']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a file usage of a basic file upload with File (Field) Paths.
|
||||
*/
|
||||
public function testFileUsage() {
|
||||
// Create a File field with 'node/[node:nid]' as the File path.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$instance_settings['filefield_paths']['file_path']['value'] = 'node/[node:nid]';
|
||||
$this->createFileField($field_name, $this->content_type, array(), $instance_settings);
|
||||
|
||||
// Create a node with a test file.
|
||||
$test_file = $this->getTestFile('text');
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $this->content_type);
|
||||
|
||||
// Get file usage for uploaded file.
|
||||
$node = node_load($nid, NULL, TRUE);
|
||||
$items = field_get_items('node', $node, $field_name);
|
||||
$file = file_load($items[0]['fid']);
|
||||
$usage = file_usage_list($file);
|
||||
|
||||
// Ensure file usage count for new node is correct.
|
||||
$this->assert(isset($usage['file']['node'][$nid]) && $usage['file']['node'][$nid] == 1, t('File usage count for new node is correct.'));
|
||||
|
||||
// Update node.
|
||||
$this->drupalPost("node/{$nid}/edit", array(), t('Save'));
|
||||
$usage = file_usage_list($file);
|
||||
|
||||
// Ensure file usage count for updated node is correct.
|
||||
$this->assert(isset($usage['file']['node'][$nid]) && $usage['file']['node'][$nid] == 1, t('File usage count for updated node is correct.'));
|
||||
|
||||
// Update node with revision.
|
||||
$this->drupalPost("node/{$nid}/edit", array('revision' => TRUE), t('Save'));
|
||||
$usage = file_usage_list($file);
|
||||
|
||||
// Ensure file usage count for updated node with revision is correct.
|
||||
$this->assert(isset($usage['file']['node'][$nid]) && $usage['file']['node'][$nid] == 2, t('File usage count for updated node with revision is correct.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test File (Field) Paths works with read-only stream wrappers.
|
||||
*/
|
||||
public function testReadOnly() {
|
||||
// Create a File field.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$field_settings = array('uri_scheme' => 'ffp');
|
||||
$instance_settings = array('file_directory' => "fields/{$field_name}");
|
||||
$this->createFileField($field_name, $this->content_type, $field_settings, $instance_settings);
|
||||
|
||||
// Get a test file.
|
||||
$file = $this->getTestFile('image');
|
||||
|
||||
// Prepare the file for the test 'ffp://' read-only stream wrapper.
|
||||
$file->uri = str_replace('public', 'ffp', $file->uri);
|
||||
$uri = file_stream_wrapper_uri_normalize($file->uri);
|
||||
|
||||
// Create a file object.
|
||||
$file = new stdClass();
|
||||
$file->fid = NULL;
|
||||
$file->uri = $uri;
|
||||
$file->filename = basename($file->uri);
|
||||
$file->filemime = file_get_mimetype($file->uri);
|
||||
$file->uid = $GLOBALS['user']->uid;
|
||||
$file->status = FILE_STATUS_PERMANENT;
|
||||
$file->display = TRUE;
|
||||
file_save($file);
|
||||
|
||||
// Attach the file to a node.
|
||||
$node = array();
|
||||
$node['type'] = $this->content_type;
|
||||
$node[$field_name][LANGUAGE_NONE][0] = (array) $file;
|
||||
|
||||
$node = $this->drupalCreateNode($node);
|
||||
|
||||
// Ensure file has been attached to a node.
|
||||
$this->assert(isset($node->{$field_name}[LANGUAGE_NONE][0]) && !empty($node->{$field_name}[LANGUAGE_NONE][0]), t('Read-only file is correctly attached to a node.'));
|
||||
|
||||
$edit = array();
|
||||
$edit['instance[settings][filefield_paths][retroactive_update]'] = TRUE;
|
||||
$edit['instance[settings][filefield_paths][file_path][value]'] = 'node/[node:nid]';
|
||||
$this->drupalPost("admin/structure/types/manage/{$this->content_type}/fields/{$field_name}", $edit, t('Save settings'));
|
||||
|
||||
// Ensure file is still in original location.
|
||||
$this->drupalGet("node/{$node->nid}");
|
||||
$this->assertRaw("{$this->public_files_directory}/{$file->filename}", t('Read-only file not affected by Retroactive updates.'));
|
||||
}
|
||||
}
|
90
sites/all/modules/filefield_paths/tests/filefield_paths.test
Normal file
90
sites/all/modules/filefield_paths/tests/filefield_paths.test
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tests for the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class FileFieldPathsTestCase
|
||||
*/
|
||||
class FileFieldPathsTestCase extends FileFieldTestCase {
|
||||
var $content_type = NULL;
|
||||
var $public_files_directory = NULL;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
function setUp() {
|
||||
// Setup required modules.
|
||||
$modules = func_get_args();
|
||||
if (isset($modules[0]) && is_array($modules[0])) {
|
||||
$modules = $modules[0];
|
||||
}
|
||||
$modules[] = 'filefield_paths_test';
|
||||
$modules[] = 'image';
|
||||
$modules[] = 'token';
|
||||
parent::setUp($modules);
|
||||
|
||||
// Include all optional dependency files.
|
||||
$dirname = dirname(__FILE__) . "/../modules";
|
||||
$includes = file_scan_directory($dirname, '/.inc$/');
|
||||
foreach (array_keys($includes) as $file) {
|
||||
require_once $file;
|
||||
}
|
||||
|
||||
// Create a content type.
|
||||
$content_type = $this->drupalCreateContentType();
|
||||
$this->content_type = $content_type->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
function createFileField($name, $type_name, $field_settings = array(), $instance_settings = array(), $widget_settings = array()) {
|
||||
parent::createFileField($name, $type_name, $field_settings, $instance_settings, $widget_settings);
|
||||
$this->drupalPost("admin/structure/types/manage/{$this->content_type}/fields/{$name}", array(), t('Save settings'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new image field.
|
||||
*
|
||||
* @param $name
|
||||
* The name of the new field (all lowercase), exclude the "field_" prefix.
|
||||
* @param $type_name
|
||||
* The node type that this field will be added to.
|
||||
* @param $field_settings
|
||||
* A list of field settings that will be added to the defaults.
|
||||
* @param $instance_settings
|
||||
* A list of instance settings that will be added to the instance defaults.
|
||||
* @param $widget_settings
|
||||
* A list of widget settings that will be added to the widget defaults.
|
||||
*/
|
||||
function createImageField($name, $type_name, $field_settings = array(), $instance_settings = array(), $widget_settings = array()) {
|
||||
$field = array(
|
||||
'field_name' => $name,
|
||||
'type' => 'image',
|
||||
'settings' => array(),
|
||||
'cardinality' => !empty($field_settings['cardinality']) ? $field_settings['cardinality'] : 1,
|
||||
);
|
||||
$field['settings'] = array_merge($field['settings'], $field_settings);
|
||||
field_create_field($field);
|
||||
|
||||
$instance = array(
|
||||
'field_name' => $name,
|
||||
'label' => $name,
|
||||
'entity_type' => 'node',
|
||||
'bundle' => $type_name,
|
||||
'required' => !empty($instance_settings['required']),
|
||||
'settings' => array(),
|
||||
'widget' => array(
|
||||
'type' => 'image_image',
|
||||
'settings' => array(),
|
||||
),
|
||||
);
|
||||
$instance['settings'] = array_merge($instance['settings'], $instance_settings);
|
||||
$instance['widget']['settings'] = array_merge($instance['widget']['settings'], $widget_settings);
|
||||
field_create_instance($instance);
|
||||
$this->drupalPost("admin/structure/types/manage/{$this->content_type}/fields/{$name}", array(), t('Save settings'));
|
||||
}
|
||||
}
|
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tests for the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class FileFieldPathsTextReplaceTestCase
|
||||
*/
|
||||
class FileFieldPathsTextReplaceTestCase extends FileFieldPathsTestCase {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Text replace functionality',
|
||||
'description' => 'Tests text replace functionality.',
|
||||
'group' => 'File (Field) Paths',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates all variations of the URI for text replacement.
|
||||
*
|
||||
* @param $uri
|
||||
* @param string $type
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getPathVariations($uri, $type = 'image') {
|
||||
// Force clean urls on.
|
||||
$GLOBALS['conf']['clean_url'] = TRUE;
|
||||
|
||||
$variations['uri'] = $uri;
|
||||
$variations['absolute'] = urldecode(file_create_url($uri));
|
||||
$variations['relative'] = parse_url($variations['absolute'], PHP_URL_PATH);
|
||||
|
||||
if ($type == 'image') {
|
||||
$variations['image_style'] = urldecode(image_style_url('thumbnail', $uri));
|
||||
$variations['image_style_relative'] = parse_url($variations['image_style'], PHP_URL_PATH) . '?' . parse_url($variations['image_style'], PHP_URL_QUERY);
|
||||
}
|
||||
|
||||
foreach ($variations as $key => $value) {
|
||||
$variations["{$key}_urlencode"] = urlencode($value);
|
||||
$variations["{$key}_drupal_encode_path"] = drupal_encode_path($value);
|
||||
}
|
||||
|
||||
return $variations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test text replace with multiple file uploads.
|
||||
*/
|
||||
public function testTextReplace() {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
|
||||
// Create a File field with 'node/[node:nid]' as the File path and
|
||||
// '[node:nid].png’ as the File name,
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$instance_settings['filefield_paths']['file_path']['value'] = 'node/[node:nid]';
|
||||
$instance_settings['filefield_paths']['file_name']['value'] = '[node:nid].png';
|
||||
$this->createImageField($field_name, $this->content_type, array(), $instance_settings);
|
||||
|
||||
// Prepare test files.
|
||||
$test_files['basic_image'] = $this->getTestFile('image');
|
||||
$test_files['complex_image'] = $this->getTestFile('image');
|
||||
file_unmanaged_copy($test_files['complex_image']->uri, 'public://test image.png');
|
||||
$files = file_scan_directory('public://', '/test image\.png/');
|
||||
$test_files['complex_image'] = current($files);
|
||||
|
||||
// Iterate over each test file.
|
||||
foreach ($test_files as $type => $test_file) {
|
||||
// Get the available file paths for the test file.
|
||||
$uri = str_replace('public://', variable_get('filefield_paths_temp_location', 'public://filefield_paths') . '/', $test_file->uri);
|
||||
$source_paths = $this->getPathVariations($uri);
|
||||
|
||||
// Upload a file and reference the original path(s) to the file in the body
|
||||
// field.
|
||||
$edit['title'] = $this->randomName();
|
||||
$edit["body[{$langcode}][0][value]"] = '';
|
||||
$edit["files[{$field_name}_{$langcode}_0]"] = drupal_realpath($test_file->uri);
|
||||
foreach ($source_paths as $key => $value) {
|
||||
$edit["body[{$langcode}][0][value]"] .= "{$key}: {$value}\n";
|
||||
}
|
||||
$this->drupalPost("node/add/{$this->content_type}", $edit, t('Save'));
|
||||
|
||||
// Get created Node ID.
|
||||
$matches = array();
|
||||
preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches);
|
||||
$nid = $matches[1];
|
||||
|
||||
// Ensure body field has updated file path.
|
||||
$node = node_load($nid);
|
||||
$destination_paths = $this->getPathVariations($node->{$field_name}[$langcode][0]['uri']);
|
||||
foreach ($destination_paths as $key => $value) {
|
||||
$this->assert($source_paths[$key] !== $destination_paths[$key] && strpos($node->body[$langcode][0]['value'], "{$key}: {$value}") !== FALSE, t('@type %key file path replaced successfully.', array(
|
||||
'@type' => str_replace('_', ' ', drupal_ucfirst($type)),
|
||||
'%key' => $key
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tests for the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class FileFieldPathsTokensTestCase
|
||||
*/
|
||||
class FileFieldPathsTokensTestCase extends FileFieldPathsTestCase {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Token functionality',
|
||||
'description' => 'Tests File (Field) Paths tokens.',
|
||||
'group' => 'File (Field) Paths',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $token
|
||||
* @param $value
|
||||
* @param $data
|
||||
*/
|
||||
public function assertToken($token, $value, $data) {
|
||||
$result = token_replace($token, $data);
|
||||
$this->assertEqual($result, $value, t('Token @token equals @value', array(
|
||||
'@token' => $token,
|
||||
'@value' => $value
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test token values with a text file.
|
||||
*/
|
||||
public function testTokensBasic() {
|
||||
// Prepare a test text file.
|
||||
$text_file = $this->getTestFile('text');
|
||||
file_save($text_file);
|
||||
|
||||
// Ensure tokens are processed correctly.
|
||||
$data = array('file' => $text_file);
|
||||
$this->assertToken('[file:ffp-name-only]', 'text-0', $data);
|
||||
$this->assertToken('[file:ffp-name-only-original]', 'text-0', $data);
|
||||
$this->assertToken('[file:ffp-extension-original]', 'txt', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test token values with a moved text file.
|
||||
*/
|
||||
public function testTokensMoved() {
|
||||
// Prepare a test text file.
|
||||
$text_file = $this->getTestFile('text');
|
||||
file_save($text_file);
|
||||
|
||||
// Move the text file.
|
||||
$moved_file = file_move($text_file, 'public://moved.diff');
|
||||
|
||||
// Ensure tokens are processed correctly.
|
||||
$data = array('file' => $moved_file);
|
||||
$this->assertToken('[file:ffp-name-only]', 'moved', $data);
|
||||
$this->assertToken('[file:ffp-name-only-original]', 'text-0', $data);
|
||||
$this->assertToken('[file:ffp-extension-original]', 'txt', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test token values with a multi-extension text file.
|
||||
*/
|
||||
public function testTokensMultiExtension() {
|
||||
// Prepare a test text file.
|
||||
$text_file = $this->getTestFile('text');
|
||||
file_unmanaged_copy($text_file->uri, 'public://text.multiext.txt');
|
||||
$files = file_scan_directory('public://', '/text\.multiext\.txt/');
|
||||
$multiext_file = current($files);
|
||||
file_save($multiext_file);
|
||||
|
||||
// Ensure tokens are processed correctly.
|
||||
$data = array('file' => $multiext_file);
|
||||
$this->assertToken('[file:ffp-name-only]', 'text.multiext', $data);
|
||||
$this->assertToken('[file:ffp-name-only-original]', 'text.multiext', $data);
|
||||
$this->assertToken('[file:ffp-extension-original]', 'txt', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test token value with a UTF file.
|
||||
* @see https://www.drupal.org/node/1292436
|
||||
*/
|
||||
public function testTokensUTF() {
|
||||
// Prepare a test text file.
|
||||
$text_file = $this->getTestFile('text');
|
||||
file_unmanaged_copy($text_file->uri, 'public://тест.txt');
|
||||
$files = file_scan_directory('public://', '/тест\.txt/');
|
||||
$utf_file = current($files);
|
||||
file_save($utf_file);
|
||||
|
||||
// Ensure tokens are processed correctly.
|
||||
$data = array('file' => $utf_file);
|
||||
$this->assertToken('[file:ffp-name-only]', 'тест', $data);
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tests for the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class FileFieldPathsUpdatesCase
|
||||
*/
|
||||
class FileFieldPathsUpdatesCase extends FileFieldPathsTestCase {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Update functionality',
|
||||
'description' => 'Tests retroactive and active updates functionality.',
|
||||
'group' => 'File (Field) Paths',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test behaviour of Retroactive updates when no updates are needed.
|
||||
*/
|
||||
public function testRetroEmpty() {
|
||||
// Create a File field.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$this->createFileField($field_name, $this->content_type);
|
||||
|
||||
// Trigger retroactive updates.
|
||||
$edit = array(
|
||||
'instance[settings][filefield_paths][retroactive_update]' => TRUE
|
||||
);
|
||||
$this->drupalPost("admin/structure/types/manage/{$this->content_type}/fields/{$field_name}", $edit, t('Save settings'));
|
||||
|
||||
// Ensure no errors are thrown.
|
||||
$this->assertNoText('Error', t('No errors were found.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test basic Retroactive updates functionality.
|
||||
*/
|
||||
public function testRetroBasic() {
|
||||
// Create an Image field.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$this->createImageField($field_name, $this->content_type, array());
|
||||
|
||||
// Modify instance settings.
|
||||
$instance = field_info_instance('node', $field_name, $this->content_type);
|
||||
|
||||
$instance['display']['default']['settings']['image_style'] = 'thumbnail';
|
||||
$instance['display']['default']['settings']['image_link'] = 'content';
|
||||
field_update_instance($instance);
|
||||
$this->drupalGet("admin/structure/types/manage/{$this->content_type}/display");
|
||||
$original_instance = field_info_instance('node', $field_name, $this->content_type);
|
||||
|
||||
// Create a node with a test file.
|
||||
$test_file = $this->getTestFile('image');
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $this->content_type);
|
||||
|
||||
// Ensure that the file is in the default path.
|
||||
$this->drupalGet("node/{$nid}");
|
||||
$this->assertRaw("{$this->public_files_directory}/styles/thumbnail/public/{$test_file->name}", t('The File is in the default path.'));
|
||||
|
||||
// Trigger retroactive updates.
|
||||
$edit['instance[settings][filefield_paths][retroactive_update]'] = TRUE;
|
||||
$edit['instance[settings][filefield_paths][file_path][value]'] = 'node/[node:nid]';
|
||||
$this->drupalPost("admin/structure/types/manage/{$this->content_type}/fields/{$field_name}", $edit, t('Save settings'));
|
||||
|
||||
// Ensure instance display settings haven't changed.
|
||||
// @see https://www.drupal.org/node/2276435
|
||||
drupal_static_reset('_field_info_field_cache');
|
||||
$instance = field_info_instance('node', $field_name, $this->content_type);
|
||||
$this->assert($original_instance['display'] === $instance['display'], t('Instance settings have not changed.'));
|
||||
|
||||
// Ensure that the file path has been retroactively updated.
|
||||
$this->drupalGet("node/{$nid}");
|
||||
$this->assertRaw("{$this->public_files_directory}/styles/thumbnail/public/node/{$nid}/{$test_file->name}", t('The File path has been retroactively updated.'));
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
name = File (Field) Paths tests
|
||||
description = Support module for File (Field) Paths related testing.
|
||||
package = Testing
|
||||
dependencies[] = filefield_paths
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2018-08-14
|
||||
version = "7.x-1.1"
|
||||
core = "7.x"
|
||||
project = "filefield_paths"
|
||||
datestamp = "1534256584"
|
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Core functions for the File (Field) Paths tests module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_stream_wrappers_alter().
|
||||
*
|
||||
* @param $wrappers
|
||||
*/
|
||||
function filefield_paths_test_stream_wrappers_alter(&$wrappers) {
|
||||
$wrappers['ffp'] = $wrappers['public'];
|
||||
$wrappers['ffp']['type'] = STREAM_WRAPPERS_READ_VISIBLE;
|
||||
}
|
84
sites/all/modules/filefield_paths/tests/pathauto.test
Normal file
84
sites/all/modules/filefield_paths/tests/pathauto.test
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Pathauto module tests for the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class FileFieldPathsPathautoCase
|
||||
*/
|
||||
class FileFieldPathsPathautoCase extends FileFieldPathsTestCase {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
function setUp() {
|
||||
// Setup required modules.
|
||||
parent::setUp(array('pathauto'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Pathauto integration',
|
||||
'description' => 'Tests the Pathauto module integration.',
|
||||
'group' => 'File (Field) Paths',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test File (Field) Paths Pathauto UI.
|
||||
*/
|
||||
public function testUI() {
|
||||
// Create a File field.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$this->createFileField($field_name, $this->content_type);
|
||||
|
||||
// Ensure File (Field) Paths Pathauto settings are present and available.
|
||||
$this->drupalGet("admin/structure/types/manage/{$this->content_type}/fields/{$field_name}");
|
||||
foreach (array('path', 'name') as $field) {
|
||||
$this->assertField("instance[settings][filefield_paths][file_{$field}][options][pathauto]", t('Pathauto checkbox is present in File @field settings.', array('@field' => drupal_ucfirst($field))));
|
||||
|
||||
$element = $this->xpath('//input[@name=:name]/@disabled', array(':name' => "instance[settings][filefield_paths][file_{$field}][options][pathauto]"));
|
||||
$this->assert(empty($element), t('Pathauto checkbox is not disabled in File @field settings.', array('@field' => drupal_ucfirst($field))));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Pathauto cleanup in File (Field) Paths.
|
||||
*/
|
||||
public function testPathauto() {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
|
||||
// Create a File field.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
|
||||
$instance_settings['filefield_paths']['file_path']['value'] = 'node/[node:title]';
|
||||
$instance_settings['filefield_paths']['file_path']['options']['pathauto'] = TRUE;
|
||||
$instance_settings['filefield_paths']['file_name']['value'] = '[node:title].[file:ffp-extension-original]';
|
||||
$instance_settings['filefield_paths']['file_name']['options']['pathauto'] = TRUE;
|
||||
|
||||
$this->createFileField($field_name, $this->content_type, array(), $instance_settings);
|
||||
|
||||
// Create a node with a test file.
|
||||
$test_file = $this->getTestFile('text');
|
||||
$edit['title'] = $this->randomString() . ' ' . $this->randomString();
|
||||
|
||||
$edit['files[' . $field_name . '_' . $langcode . '_0]'] = drupal_realpath($test_file->uri);
|
||||
$this->drupalPost("node/add/{$this->content_type}", $edit, t('Save'));
|
||||
|
||||
// Ensure that file path/name have been processed correctly by Pathauto.
|
||||
$node = node_load(1);
|
||||
|
||||
module_load_include('inc', 'pathauto');
|
||||
$parts = explode('/', $node->title);
|
||||
foreach ($parts as &$part) {
|
||||
$part = pathauto_cleanstring($part);
|
||||
}
|
||||
$title = implode('/', $parts);
|
||||
|
||||
$this->assertEqual($node->{$field_name}[$langcode][0]['uri'], "public://node/{$title}/{$title}.txt", t('File path/name has been processed correctly by Pathauto'));
|
||||
}
|
||||
}
|
90
sites/all/modules/filefield_paths/tests/redirect.test
Normal file
90
sites/all/modules/filefield_paths/tests/redirect.test
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Redirect module tests for the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class FileFieldPathsRedirectTestCase
|
||||
*/
|
||||
class FileFieldPathsRedirectTestCase extends FileFieldPathsTestCase {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
function setUp() {
|
||||
// Setup required modules.
|
||||
parent::setUp(array('redirect'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Redirect module integration',
|
||||
'description' => 'Test redirect module integration.',
|
||||
'group' => 'File (Field) Paths',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test File (Field) Paths Redirect UI.
|
||||
*/
|
||||
public function testUI() {
|
||||
// Create a File field.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$this->createFileField($field_name, $this->content_type);
|
||||
|
||||
// Ensure File (Field) Paths Pathauto settings are present and available.
|
||||
$this->drupalGet("admin/structure/types/manage/{$this->content_type}/fields/{$field_name}");
|
||||
|
||||
$this->assertField('instance[settings][filefield_paths][redirect]', t('Redirect checkbox is present in File (Field) Path settings.'));
|
||||
|
||||
$element = $this->xpath('//input[@name=:name]/@disabled', array(':name' => 'instance[settings][filefield_paths][redirect]'));
|
||||
$this->assert(empty($element), t('Redirect checkbox is not disabled.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test File (Field) Paths Redirect functionality.
|
||||
*/
|
||||
public function testRedirect() {
|
||||
global $base_path;
|
||||
$langcode = LANGUAGE_NONE;
|
||||
|
||||
// Create a File field with a random File path.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$instance_settings['filefield_paths']['file_path']['value'] = $this->randomName();
|
||||
$this->createFileField($field_name, $this->content_type, array(), $instance_settings);
|
||||
|
||||
// Create a node with a test file.
|
||||
$test_file = $this->getTestFile('text');
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $this->content_type);
|
||||
|
||||
// Get processed source file uri.
|
||||
$node = node_load($nid, NULL, TRUE);
|
||||
$source = $node->{$field_name}[$langcode][0]['uri'];
|
||||
|
||||
// Update file path and create redirect.
|
||||
$edit = array(
|
||||
'instance[settings][filefield_paths][file_path][value]' => $this->randomName(),
|
||||
'instance[settings][filefield_paths][redirect]' => TRUE,
|
||||
'instance[settings][filefield_paths][retroactive_update]' => TRUE,
|
||||
);
|
||||
$this->drupalPost("admin/structure/types/manage/{$this->content_type}/fields/{$field_name}", $edit, t('Save settings'));
|
||||
|
||||
// Get processed destination file uri.
|
||||
$node = node_load($nid, NULL, TRUE);
|
||||
$destination = $node->{$field_name}[$langcode][0]['uri'];
|
||||
|
||||
// Ensure that the source uri redirects to the destination uri.
|
||||
$parsed_source = parse_url(file_create_url($source), PHP_URL_PATH);
|
||||
$redirect_source = drupal_substr(urldecode($parsed_source), drupal_strlen($base_path));
|
||||
|
||||
$parsed_destination = parse_url(file_create_url($destination), PHP_URL_PATH);
|
||||
$redirect_destination = drupal_substr(urldecode($parsed_destination), drupal_strlen($base_path));
|
||||
|
||||
$redirect = redirect_load_by_source($redirect_source);
|
||||
$this->assert(is_object($redirect) && $redirect->redirect == $redirect_destination, t('Redirect created for relocated file.'));
|
||||
}
|
||||
}
|
82
sites/all/modules/filefield_paths/tests/transliteration.test
Normal file
82
sites/all/modules/filefield_paths/tests/transliteration.test
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Transliteration module tests for the File (Field) Paths module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class FileFieldPathsTransliterationCase
|
||||
*/
|
||||
class FileFieldPathsTransliterationCase extends FileFieldPathsTestCase {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
function setUp() {
|
||||
// Setup required modules.
|
||||
parent::setUp(array('transliteration'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Transliteration integration',
|
||||
'description' => 'Tests the Transliteration module integration.',
|
||||
'group' => 'File (Field) Paths',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test File (Field) Paths Transliteration UI.
|
||||
*/
|
||||
public function testUI() {
|
||||
// Create a File field.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$this->createFileField($field_name, $this->content_type);
|
||||
|
||||
// Ensure File (Field) Paths Transliteration settings are present and available.
|
||||
$this->drupalGet("admin/structure/types/manage/{$this->content_type}/fields/{$field_name}");
|
||||
foreach (array('path', 'name') as $field) {
|
||||
$this->assertField("instance[settings][filefield_paths][file_{$field}][options][transliterate]", t('Transliteration checkbox is present in File @field settings.', array('@field' => drupal_ucfirst($field))));
|
||||
|
||||
$element = $this->xpath('//input[@name=:name]/@disabled', array(':name' => "instance[settings][filefield_paths][file_{$field}][options][transliterate]"));
|
||||
$this->assert(empty($element), t('Transliteration checkbox is not disabled in File @field settings.', array('@field' => drupal_ucfirst($field))));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Transliteration cleanup in File (Field) Paths.
|
||||
*/
|
||||
public function testTransliteration() {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
|
||||
// Create a File field.
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
|
||||
$instance_settings['filefield_paths']['file_path']['value'] = 'node/[node:title]';
|
||||
$instance_settings['filefield_paths']['file_path']['options']['transliterate'] = TRUE;
|
||||
$instance_settings['filefield_paths']['file_name']['value'] = '[node:title].[file:ffp-extension-original]';
|
||||
$instance_settings['filefield_paths']['file_name']['options']['transliterate'] = TRUE;
|
||||
|
||||
$this->createFileField($field_name, $this->content_type, array(), $instance_settings);
|
||||
|
||||
// Create a node with a test file.
|
||||
$test_file = $this->getTestFile('text');
|
||||
$edit['title'] = 'тест';
|
||||
|
||||
$edit['files[' . $field_name . '_' . $langcode . '_0]'] = drupal_realpath($test_file->uri);
|
||||
$this->drupalPost("node/add/{$this->content_type}", $edit, t('Save'));
|
||||
|
||||
// Get created Node ID.
|
||||
$matches = array();
|
||||
preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches);
|
||||
$nid = $matches[1];
|
||||
|
||||
// Ensure that file path/name have been processed correctly by
|
||||
// Transliteration.
|
||||
$node = node_load($nid);
|
||||
$this->assertEqual($node->{$field_name}[$langcode][0]['uri'], "public://node/test/test.txt", t('File path/name has been processed correctly by Transliteration'));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user