first global commit
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
name = textauthor
|
||||
description = "The description of this module"
|
||||
|
||||
; Core version (required)
|
||||
core = 7.x
|
||||
|
||||
; Package name (see http://drupal.org/node/542202 for a list of names)
|
||||
; package =
|
||||
|
||||
; PHP version requirement (optional)
|
||||
; php = 5.2
|
||||
|
||||
; Loadable code files
|
||||
files[] = textauthor.migratefieldhandler.inc
|
||||
; files[] = textauthor.admin.inc
|
||||
; files[] = textauthor.class.inc
|
||||
|
||||
; Module dependencies
|
||||
dependencies[] = text
|
||||
; dependencies[] = theirmodule (1.2)
|
||||
; dependencies[] = anothermodule (>=2.4)
|
||||
; dependencies[] = views (3.x)
|
||||
|
||||
; Configuration page
|
||||
; configure = admin/config/textauthor
|
||||
|
||||
|
||||
; For further information about configuration options, see
|
||||
; - http://drupal.org/node/542202
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
|
||||
/**
|
||||
* Implements hook_field_schema().
|
||||
*/
|
||||
function textauthor_field_schema($field) {
|
||||
if($field['type'] == 'textauthor'){
|
||||
return array(
|
||||
'columns' => array(
|
||||
'value' => array(
|
||||
'type' => 'text',
|
||||
'size' => 'big',
|
||||
'not null' => FALSE,
|
||||
),
|
||||
'author' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => FALSE,
|
||||
'sortable' => TRUE
|
||||
),
|
||||
'format' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => FALSE,
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'format' => array('format'),
|
||||
),
|
||||
'foreign keys' => array(
|
||||
'format' => array(
|
||||
'table' => 'filter_format',
|
||||
'columns' => array('format' => 'format'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
class MigrateTextAuthorFieldHandler extends MigrateFieldHandler {
|
||||
public function __construct() {
|
||||
$this->registerTypes(array('textauthor'));
|
||||
}
|
||||
|
||||
static function arguments($author = NULL, $format = NULL, $language = NULL) {
|
||||
$arguments = array();
|
||||
if (!is_null($author)) {
|
||||
$arguments['author'] = $author;
|
||||
}
|
||||
if (!is_null($format)) {
|
||||
$arguments['format'] = $format;
|
||||
}
|
||||
if (!is_null($language)) {
|
||||
$arguments['language'] = $language;
|
||||
}
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
public function fields($type) {
|
||||
$fields = array();
|
||||
$fields = array(
|
||||
'author' => t('Subfield: Text author'),
|
||||
'format' => t('Subfield: Text format for the field'),
|
||||
'language' => t('Subfield: Language for the field'),
|
||||
);
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function prepare($entity, array $field_info, array $instance, array $values) {
|
||||
if (isset($values['arguments'])) {
|
||||
$arguments = $values['arguments'];
|
||||
unset($values['arguments']);
|
||||
}
|
||||
else {
|
||||
$arguments = array();
|
||||
}
|
||||
|
||||
$migration = Migration::currentMigration();
|
||||
$destination = $migration->getDestination();
|
||||
$language = $this->getFieldLanguage($entity, $field_info, $arguments);
|
||||
$max_length = isset($field_info['settings']['max_length']) ?
|
||||
$field_info['settings']['max_length'] : 0;
|
||||
|
||||
// Setup the standard Field API array for saving.
|
||||
$delta = 0;
|
||||
foreach ($values as $value) {
|
||||
$item = array();
|
||||
if (isset($arguments['author'])) {
|
||||
if (is_array($arguments['author'])) {
|
||||
$item['author'] = $arguments['author'][$delta];
|
||||
}
|
||||
else {
|
||||
$item['author'] = $arguments['author'];
|
||||
}
|
||||
}
|
||||
if (isset($arguments['format'])) {
|
||||
if (is_array($arguments['format'])) {
|
||||
$format = $arguments['format'][$delta];
|
||||
}
|
||||
else {
|
||||
$format = $arguments['format'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$format = $destination->getTextFormat();
|
||||
}
|
||||
$item['format'] = $item['value_format'] = $format;
|
||||
// Make sure the value will fit
|
||||
if ($max_length) {
|
||||
$item['value'] = drupal_substr($value, 0, $max_length);
|
||||
if (!empty($arguments['track_overflow'])) {
|
||||
$value_length = drupal_strlen($value);
|
||||
if ($value_length > $max_length) {
|
||||
$migration->saveMessage(
|
||||
t('Value for field !field exceeds max length of !max_length, actual length is !length',
|
||||
array('!field' => $instance['field_name'], '!max_length' => $max_length,
|
||||
'!length' => $value_length)),
|
||||
Migration::MESSAGE_INFORMATIONAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$item['value'] = $value;
|
||||
}
|
||||
|
||||
if (is_array($language)) {
|
||||
$current_language = $language[$delta];
|
||||
}
|
||||
else {
|
||||
$current_language = $language;
|
||||
}
|
||||
$return[$current_language][] = $item;
|
||||
$delta++;
|
||||
}
|
||||
|
||||
return isset($return) ? $return : NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_field_info().
|
||||
*/
|
||||
function textauthor_field_info() {
|
||||
return array(
|
||||
'textauthor' => array(
|
||||
'label' => t('Text with author'),
|
||||
'description' => t('This field stores varchar text in the database with author.'),
|
||||
'default_widget' => 'textauthor',
|
||||
'default_formatter' => 'textauthor',
|
||||
'instance_settings' => array('text_processing' => 0),
|
||||
// Support hook_entity_property_info() from contrib "Entity API".
|
||||
// 'property_type' => 'field_item_textauthor',
|
||||
// 'property_callbacks' => array('textauthor_field_property_info_callback'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_instance_settings_form().
|
||||
*/
|
||||
function textauthor_field_instance_settings_form($field, $instance) {
|
||||
$settings = $instance['settings'];
|
||||
|
||||
$form['text_processing'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Text processing'),
|
||||
'#default_value' => $settings['text_processing'],
|
||||
'#options' => array(
|
||||
t('Plain text'),
|
||||
t('Filtered text (user selects text format)'),
|
||||
),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_load().
|
||||
*
|
||||
* Where possible, generate the sanitized version of each field early so that
|
||||
* it is cached in the field cache. This avoids looking up from the filter cache
|
||||
* separately.
|
||||
*
|
||||
* @see text_field_formatter_view()
|
||||
*/
|
||||
function textauthor_field_load($entity_type, $entities, $field, $instances, $langcode, &$items) {
|
||||
foreach ($entities as $id => $entity) {
|
||||
foreach ($items[$id] as $delta => $item) {
|
||||
// Only process items with a cacheable format, the rest will be handled
|
||||
// by formatters if needed.
|
||||
if (empty($instances[$id]['settings']['text_processing']) || filter_format_allowcache($item['format'])) {
|
||||
$items[$id][$delta]['safe_value'] = isset($item['value']) ? _text_sanitize($instances[$id], $langcode, $item, 'value') : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_is_empty().
|
||||
*/
|
||||
function textauthor_field_is_empty($item, $field) {
|
||||
if (!isset($item['value']) || $item['value'] === '') {
|
||||
return !isset($item['author']) || $item['author'] === '';
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_widget_info().
|
||||
*/
|
||||
function textauthor_field_widget_info() {
|
||||
return array(
|
||||
'textauthor' => array(
|
||||
'label' => t('Text with author'),
|
||||
'field types' => array('textauthor'),
|
||||
'settings' => array('size' => 60),
|
||||
'behaviors' => array(
|
||||
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
|
||||
'default value' => FIELD_BEHAVIOR_DEFAULT,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_widget_form().
|
||||
*/
|
||||
function textauthor_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
|
||||
// dsm($element, '$element');
|
||||
|
||||
$main_widget = $element + array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => t('Text'),
|
||||
'#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
|
||||
);
|
||||
|
||||
if($instance['settings']['text_processing']){
|
||||
$element = $main_widget;
|
||||
$element['#type'] = 'text_format';
|
||||
$element['#format'] = isset($items[$delta]['format']) ? $items[$delta]['format'] : NULL;
|
||||
$element['#base_type'] = 'textarea';
|
||||
}else{
|
||||
$element['value'] = $main_widget;
|
||||
}
|
||||
|
||||
$element['author'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('!title Author', array('!title'=>$element['#title'])),
|
||||
'#default_value' => isset($items[$delta]['author']) ? $items[$delta]['author'] : NULL,
|
||||
'#weight' => 1,
|
||||
);
|
||||
//
|
||||
return $element;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
function textauthor_theme($existing, $type, $theme, $path) {
|
||||
return array(
|
||||
'textauthor_formatter' => array(
|
||||
'variables' => array('element' => NULL),
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_formatter_info().
|
||||
*/
|
||||
function textauthor_field_formatter_info() {
|
||||
return array(
|
||||
'textauthor_default' => array(
|
||||
'label' => t('Default'),
|
||||
'field types' => array('textauthor'),
|
||||
),
|
||||
'textauthor_plain' => array(
|
||||
'label' => t('Plain text'),
|
||||
'field types' => array('textauthor'),
|
||||
),
|
||||
|
||||
// The text_trimmed formatter displays the trimmed version of the
|
||||
// full element of the field. It is intended to be used with text
|
||||
// and text_long fields. It also works with text_with_summary
|
||||
// fields though the text_summary_or_trimmed formatter makes more
|
||||
// sense for that field type.
|
||||
'textauthor_trimmed' => array(
|
||||
'label' => t('Trimmed'),
|
||||
'field types' => array('textauthor'),
|
||||
'settings' => array('trim_length' => 600),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_formatter_settings_form().
|
||||
*/
|
||||
function textauthor_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
|
||||
$display = $instance['display'][$view_mode];
|
||||
$settings = $display['settings'];
|
||||
|
||||
$element = array();
|
||||
|
||||
if (strpos($display['type'], '_trimmed') !== FALSE) {
|
||||
$element['trim_length'] = array(
|
||||
'#title' => t('Trim length'),
|
||||
'#type' => 'textfield',
|
||||
'#size' => 10,
|
||||
'#default_value' => $settings['trim_length'],
|
||||
'#element_validate' => array('element_validate_integer_positive'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements hook_field_formatter_view().
|
||||
*/
|
||||
function textauthor_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
|
||||
if ($display['type'] == 'textauthor_default' || $display['type'] == 'textauthor_trimmed') {
|
||||
foreach ($items as $delta => $item) {
|
||||
$output = _textauthor_sanitize($instance, $langcode, $item, 'value');
|
||||
if ($display['type'] == 'textauthor_trimmed') {
|
||||
$output = textauthor_summary($output, $instance['settings']['text_processing'] ? $item['format'] : NULL, $display['settings']['trim_length']);
|
||||
}
|
||||
$items[$delta]['output_value'] = $output;
|
||||
}
|
||||
}
|
||||
|
||||
$elements = array();
|
||||
foreach ($items as $delta => $item) {
|
||||
$elements[$delta] = array(
|
||||
'#markup' => theme('textauthor_formatter', array('element' => $item, 'field' => $instance)),
|
||||
);
|
||||
}
|
||||
return $elements;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes the 'value' or 'summary' data of a text value.
|
||||
*
|
||||
* Depending on whether the field instance uses text processing, data is run
|
||||
* through check_plain() or check_markup().
|
||||
*
|
||||
* @param $instance
|
||||
* The instance definition.
|
||||
* @param $langcode
|
||||
* The language associated to $item.
|
||||
* @param $item
|
||||
* The field value to sanitize.
|
||||
* @param $column
|
||||
* The column to sanitize (either 'value' or 'summary').
|
||||
*
|
||||
* @return
|
||||
* The sanitized string.
|
||||
*/
|
||||
function _textauthor_sanitize($instance, $langcode, $item, $column) {
|
||||
// If the value uses a cacheable text format, text_field_load() precomputes
|
||||
// the sanitized string.
|
||||
if (isset($item["safe_$column"])) {
|
||||
return $item["safe_$column"];
|
||||
}
|
||||
return $instance['settings']['text_processing'] ? check_markup($item[$column], $item['format'], $langcode) : check_plain($item[$column]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a trimmed, formatted version of a text field value.
|
||||
*
|
||||
* If the end of the summary is not indicated using the <!--break--> delimiter
|
||||
* then we generate the summary automatically, trying to end it at a sensible
|
||||
* place such as the end of a paragraph, a line break, or the end of a
|
||||
* sentence (in that order of preference).
|
||||
*
|
||||
* @param $text
|
||||
* The content for which a summary will be generated.
|
||||
* @param $format
|
||||
* The format of the content.
|
||||
* If the PHP filter is present and $text contains PHP code, we do not
|
||||
* split it up to prevent parse errors.
|
||||
* If the line break filter is present then we treat newlines embedded in
|
||||
* $text as line breaks.
|
||||
* If the htmlcorrector filter is present, it will be run on the generated
|
||||
* summary (if different from the incoming $text).
|
||||
* @param $size
|
||||
* The desired character length of the summary. If omitted, the default
|
||||
* value will be used. Ignored if the special delimiter is present
|
||||
* in $text.
|
||||
* @return
|
||||
* The generated summary.
|
||||
*/
|
||||
function textauthor_summary($text, $format = NULL, $size = NULL) {
|
||||
|
||||
if (!isset($size)) {
|
||||
// What used to be called 'teaser' is now called 'summary', but
|
||||
// the variable 'teaser_length' is preserved for backwards compatibility.
|
||||
$size = variable_get('teaser_length', 600);
|
||||
}
|
||||
|
||||
// Find where the delimiter is in the body
|
||||
$delimiter = strpos($text, '<!--break-->');
|
||||
|
||||
// If the size is zero, and there is no delimiter, the entire body is the summary.
|
||||
if ($size == 0 && $delimiter === FALSE) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
// If a valid delimiter has been specified, use it to chop off the summary.
|
||||
if ($delimiter !== FALSE) {
|
||||
return substr($text, 0, $delimiter);
|
||||
}
|
||||
|
||||
// We check for the presence of the PHP evaluator filter in the current
|
||||
// format. If the body contains PHP code, we do not split it up to prevent
|
||||
// parse errors.
|
||||
if (isset($format)) {
|
||||
$filters = filter_list_format($format);
|
||||
if (isset($filters['php_code']) && $filters['php_code']->status && strpos($text, '<?') !== FALSE) {
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a short body, the entire body is the summary.
|
||||
if (drupal_strlen($text) <= $size) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
// If the delimiter has not been specified, try to split at paragraph or
|
||||
// sentence boundaries.
|
||||
|
||||
// The summary may not be longer than maximum length specified. Initial slice.
|
||||
$summary = truncate_utf8($text, $size);
|
||||
|
||||
// Store the actual length of the UTF8 string -- which might not be the same
|
||||
// as $size.
|
||||
$max_rpos = strlen($summary);
|
||||
|
||||
// How much to cut off the end of the summary so that it doesn't end in the
|
||||
// middle of a paragraph, sentence, or word.
|
||||
// Initialize it to maximum in order to find the minimum.
|
||||
$min_rpos = $max_rpos;
|
||||
|
||||
// Store the reverse of the summary. We use strpos on the reversed needle and
|
||||
// haystack for speed and convenience.
|
||||
$reversed = strrev($summary);
|
||||
|
||||
// Build an array of arrays of break points grouped by preference.
|
||||
$break_points = array();
|
||||
|
||||
// A paragraph near the end of sliced summary is most preferable.
|
||||
$break_points[] = array('</p>' => 0);
|
||||
|
||||
// If no complete paragraph then treat line breaks as paragraphs.
|
||||
$line_breaks = array('<br />' => 6, '<br>' => 4);
|
||||
// Newline only indicates a line break if line break converter
|
||||
// filter is present.
|
||||
if (isset($filters['filter_autop'])) {
|
||||
$line_breaks["\n"] = 1;
|
||||
}
|
||||
$break_points[] = $line_breaks;
|
||||
|
||||
// If the first paragraph is too long, split at the end of a sentence.
|
||||
$break_points[] = array('. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1);
|
||||
|
||||
// Iterate over the groups of break points until a break point is found.
|
||||
foreach ($break_points as $points) {
|
||||
// Look for each break point, starting at the end of the summary.
|
||||
foreach ($points as $point => $offset) {
|
||||
// The summary is already reversed, but the break point isn't.
|
||||
$rpos = strpos($reversed, strrev($point));
|
||||
if ($rpos !== FALSE) {
|
||||
$min_rpos = min($rpos + $offset, $min_rpos);
|
||||
}
|
||||
}
|
||||
|
||||
// If a break point was found in this group, slice and stop searching.
|
||||
if ($min_rpos !== $max_rpos) {
|
||||
// Don't slice with length 0. Length must be <0 to slice from RHS.
|
||||
$summary = ($min_rpos === 0) ? $summary : substr($summary, 0, 0 - $min_rpos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the htmlcorrector filter is present, apply it to the generated summary.
|
||||
if (isset($filters['filter_htmlcorrector'])) {
|
||||
$summary = _filter_htmlcorrector($summary);
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
function theme_textauthor_formatter($vars){
|
||||
$output = '';
|
||||
$output .= '<article class="'.$vars['element']['format'].'">'.$vars['element']['output_value'].'</article>';
|
||||
if($vars['element']['author'] != '')
|
||||
$output .= '<address rel="author">'.$vars['element']['author'].'</address>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_prepare_translation().
|
||||
*/
|
||||
function textauthor_field_prepare_translation($entity_type, $entity, $field, $instance, $langcode, &$items, $source_entity, $source_langcode) {
|
||||
// If the translating user is not permitted to use the assigned text format,
|
||||
// we must not expose the source values.
|
||||
$field_name = $field['field_name'];
|
||||
if (!empty($source_entity->{$field_name}[$source_langcode])) {
|
||||
$formats = filter_formats();
|
||||
foreach ($source_entity->{$field_name}[$source_langcode] as $delta => $item) {
|
||||
$format_id = $item['format'];
|
||||
if (!empty($format_id) && !filter_access($formats[$format_id])) {
|
||||
unset($items[$delta]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_filter_format_update().
|
||||
*/
|
||||
function textauthor_filter_format_update($format) {
|
||||
field_cache_clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_filter_format_disable().
|
||||
*/
|
||||
function textauthor_filter_format_disable($format) {
|
||||
field_cache_clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_migrate_api().
|
||||
*/
|
||||
function textauthor_migrate_api() {
|
||||
$api = array(
|
||||
'api' => 2,
|
||||
);
|
||||
return $api;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user