diff --git a/README.txt b/README.txt index 358d8ca1a02fd9be445c094a14e1f10fed9b5bf2..56d3e5eb50358f648db4b4b1a70efc918f446ea4 100644 --- a/README.txt +++ b/README.txt @@ -1,11 +1,3 @@ - -Examples modules - -This set of modules is intended to show how to use various Drupal features. -It's intended only for developers. - -If you find a problem, bad comment, poor usage, out-of-date API usage, -etc., please post an issue in the issue queue at -http://drupal.org/project/examples. - - +The master branch of Examples is intentionally empty. Please clone a proper +version branch like '7.x-1.x' or '6.x-1.x'. For instructions see the project's +Git tab at http://drupal.org/node/594964/git-instructions. diff --git a/action_example/CHANGELOG.txt b/action_example/CHANGELOG.txt deleted file mode 100644 index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000 --- a/action_example/CHANGELOG.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/action_example/action_example.info b/action_example/action_example.info deleted file mode 100644 index a1fa2378ec0490bcc295727c0ad1902fecf897ba..0000000000000000000000000000000000000000 --- a/action_example/action_example.info +++ /dev/null @@ -1,6 +0,0 @@ -name = Action example -description = Demonstrates providing actions that can be associated to triggers. -package = Example modules -core = 7.x -dependencies[] = trigger -files[] = action_example.test diff --git a/action_example/action_example.module b/action_example/action_example.module deleted file mode 100644 index e802cc7d39ca6444934353f981c1448b5fd44495..0000000000000000000000000000000000000000 --- a/action_example/action_example.module +++ /dev/null @@ -1,360 +0,0 @@ - array( - 'label' => t('Action Example: A basic example action that does nothing'), - 'type' => 'system', - 'configurable' => FALSE, - 'triggers' => array('any'), - ), - 'action_example_unblock_user_action' => array( - 'label' => t('Action Example: Unblock a user'), - 'type' => 'user', - 'configurable' => FALSE, - 'triggers' => array('any'), - ), - 'action_example_node_sticky_action' => array( - 'type' => 'node', - 'label' => t('Action Example: Promote to frontpage and sticky on top any content created by :'), - 'configurable' => TRUE, - 'behavior' => array('changes_property'), - 'triggers' => array('node_presave', 'node_insert', 'node_update'), - ), - ); -} - - - -/** - * Implements hook_menu(). - * - * Simply provide a menu entry which explains what the module does. - */ -function action_example_menu() { - $items['examples/action_example'] = array( - 'title' => 'Action Example', - 'description' => 'Provides a basic information page.', - 'page callback' => '_action_example_page', - 'access callback' => TRUE, - ); - return $items; -} - - -/** - * A simple page to explain to the developer what to do. - */ -function _action_example_page() { - return t("The Action Example provides three example actions which can be configured on the Actions configuration page and assigned to triggers on the Triggers configuration page.", array('@actions_url' => url('admin/config/system/actions'), '@triggers_url' => url('admin/structure/trigger/node'))); -} - -/* - * Most basic action. - * - * This action is not expecting any type of entity object, and can be used with - * any trigger type or any event. - */ - -/** - * Basic example action. - * - * @param $entity - * An optional entity object. - * @param array $context - * Array with parameters for this action: depends on the trigger. - * - * @ingroup actions - */ -function action_example_basic_action(&$entity, $context = array()) { - // - // In this case we are ignoring the entity and the context. This case of - // action is useful when your action does not depend on the context, and - // the function must do something regardless the scope of the trigger. - // Simply announces that the action was executed using a messages. - - drupal_set_message(t('action_example_basic_action fired')); - watchdog('action_example', 'action_example_basic_action fired.'); -} - -// --------------------------------------------------------------------------- -/* - * A complex action for different trigger types. - * - * This action is expecting an entity object user, node or comment. If none of - * the above is provided (because it was not called from an user/node/comment - * trigger event, then the action will be taken on the current logged in user. - * - */ - -/** - * Unblock an user. This action can be fired from different trigger types: - * - User trigger: this user will be unblocked. - * - Node/Comment trigger: the author of the node or comment will be unblocked. - * - Other: (including system or custom defined types), current user will be - * unblocked. (Yes, this seems like an incomprehensible use-case.) - * - * @param $entity - * An optional user object (could be a user, or an author if context is - * node or comment) - * @param array $context - * Array with parameters for this action: depends on the trigger. The context - * is not used in this example. - * - * @ingroup actions - */ -function action_example_unblock_user_action(&$entity, $context = array()) { - - // First we check that entity is a user object. If this is the case, then this - // is a user-type trigger. - if (isset($entity->uid)) { - $uid = $entity->uid; - } - elseif (isset($context['uid'])) { - $uid = $context['uid']; - } - // If neither of those are valid, then block the current user. - else { - $uid = $GLOBALS['user']->uid; - } - $account = user_load($uid); - $account = user_save($account, array('status' => 1)); - watchdog('action_example', 'Unblocked user %name.', array('%name' => $account->name)); - drupal_set_message(t('Unblocked user %name', array('%name' => $account->name))); -} - -// --------------------------------------------------------------------------- -/* - * A complex action using customization. - * - * The next action requires a configuration form to create/configure the action. - * In Drupal these are called 'advanced actions', because they must be - * customized to define their functionality. - * - * The 'action_example_node_sticky_action' allows creating rules to promote and - * set sticky content created by selected users on certain events. A form is - * used to configure which user is affected by this action, and this form - * includes the stanard _validate and _submit hooks. - */ - - -/** - * Generates settings form for action_example_node_sticky_action(). - * - * @param array $context - * An array of options of this action (in case it is being edited) - * @return array $form - * - */ -function action_example_node_sticky_action_form($context) { - /* - * We return a configuration form to set the requirements that will - * match this action before being executed. This is a regular Drupal form and - * may include any type of information you want, but all the fields of the - * form will be saved into the $context variable. - * - * In this case we are promoting all content types submited by this user, but - * it is possible to extend these conditions providing more options in the - * settings form. - */ - $form['author'] = array( - '#title' => t('Author name'), - '#type' => 'textfield', - '#description' => t('Any content created, presaved or updated by this user will be promoted to front page and set as sticky.'), - '#default_value' => isset($context['author']) ? $context['author'] : '', - ); - // Verify user permissions and provide an easier way to fill this field. - if (user_access('access user profiles')) { - $form['author']['#autocomplete_path'] = 'user/autocomplete'; - } - // No more options, return the form. - return $form; -} - -/** - * Validate settings form for action_example_node_sticky_action(). - * Verify that user exists before continuing. - */ -function action_example_node_sticky_action_validate($form, $form_state) { - if (! $account = user_load_by_name($form_state['values']['author']) ) { - form_set_error('author', t('Please, provide a valid username')); - } -} - -/** - * Submit handler for action_example_node_sticky_action. - * - * Returns an associative array of values which will be available in the - * $context when an action is executed. - */ -function action_example_node_sticky_action_submit($form, $form_state) { - return array('author' => $form_state['values']['author']); -} - -/** - * Promote and set sticky flag action. This is the special action that has been - * customized using the configuration form. - * - * @param $node - * A node object provided by the associated trigger. - * @param $context - * Array with the following elements: - * - 'author': username of the author's content this function will promote and - * set as sticky. - * - * @ingroup actions - */ -function action_example_node_sticky_action($node, $context) { - if (function_exists('dsm')) { - dsm($node, 'action_example_node_sticky_action is firing. Here is the $node'); - dsm($context, 'action_example_node_sticky_action is firing. Here is the $context'); - } - // Get the user configured for this special action. - $account = user_load_by_name($context['author']); - // Is the node created by this user? then promote and set as sticky. - if ($account->uid == $node->uid) { - $node->promote = NODE_PROMOTED; - $node->sticky = NODE_STICKY; - watchdog('action', 'Set @type %title to sticky and promoted by special action for user %username.', array('@type' => node_type_get_name($node), '%title' => $node->title, '%username' => $account->name)); - drupal_set_message(t('Set @type %title to sticky and promoted by special action for user %username.', array('@type' => node_type_get_name($node), '%title' => $node->title, '%username' => $account->name))); - } -} diff --git a/action_example/action_example.test b/action_example/action_example.test deleted file mode 100644 index 875f003a588b31f1b1cca92e9536766d8c0586f0..0000000000000000000000000000000000000000 --- a/action_example/action_example.test +++ /dev/null @@ -1,83 +0,0 @@ - 'Action example', - 'description' => 'Perform various tests on action_example module.' , - 'group' => 'Examples', - ); - } - - function setUp() { - parent::setUp('trigger', 'action_example'); - } - - /** - * Test Action Example. - * - * 1. action_example_basic_action: Configure a action_example_basic_action to - * happen when user logs in. - * 2. action_example_unblock_user_action: When a user's profile is being - * viewed, unblock that user. - * 3. action_example_node_sticky_action: Create a user, configure that user - * to always be stickied using advanced configuration. Have the user - * create content; verify that it gets stickied. - */ - function testActionExample() { - // Create an administrative user. - $admin_user = $this->drupalCreateUser(array('administer actions', 'access comments', 'access content', 'post comments', 'skip comment approval', 'create article content', 'access user profiles', 'administer users')); - $this->drupalLogin($admin_user); - - // 1. Assign basic action; then logout and login user and see if it puts - // the message on the screen. - $hash = drupal_hash_base64('action_example_basic_action'); - $edit = array('aid' => $hash); - $this->drupalPost('admin/structure/trigger/user', $edit, t('Assign'), array(), array(), 'trigger-user-login-assign-form'); - - $this->drupalLogout(); - $this->drupalLogin($admin_user); - $this->assertText(t('action_example_basic_action fired')); - - // 2. Unblock: When a user's profile is being viewed, unblock. - $normal_user = $this->drupalCreateUser(); - user_save($normal_user, array('status' => 0)); // Blocked user. - $normal_user = user_load($normal_user->uid, TRUE); - $this->assertFalse($normal_user->status, t('Normal user status has been set to blocked')); - - $hash = drupal_hash_base64('action_example_unblock_user_action'); - $edit = array('aid' => $hash); - $this->drupalPost('admin/structure/trigger/user', $edit, t('Assign'), array(), array(), 'trigger-user-view-assign-form'); - - $this->drupalGet("user/$normal_user->uid"); - $normal_user = user_load($normal_user->uid, TRUE); - $this->assertTrue($normal_user->status, t('Normal user status has been set to unblocked')); - $this->assertRaw(t('Unblocked user %name', array('%name' => $normal_user->name))); - - // 3. Create a user whose posts are always to be stickied. - $sticky_user = $this->drupalCreateUser(array('access comments', 'access content', 'post comments', 'skip comment approval', 'create article content')); - - $action_label = $this->randomName(); - $edit = array( - 'actions_label' => $action_label, - 'author' => $sticky_user -> name, - ); - $aid = $this->configureAdvancedAction('action_example_node_sticky_action', $edit); - $edit = array('aid' => drupal_hash_base64($aid)); - $this->drupalPost('admin/structure/trigger/node', $edit, t('Assign'), array(), array(), 'trigger-node-insert-assign-form'); - // Now create a node and verify that it gets stickied. - $this->drupalLogout(); - $this->drupalLogin($sticky_user); - $node = $this->drupalCreateNode(); - $this->assertTrue($node->sticky, t('Node was set to sticky on creation')); - } -} diff --git a/ajax_example/ajax_example.css b/ajax_example/ajax_example.css deleted file mode 100644 index 5de6e70e68eac719249f232b60f7edec2ad52c23..0000000000000000000000000000000000000000 --- a/ajax_example/ajax_example.css +++ /dev/null @@ -1,20 +0,0 @@ - -/* - * @file ajax_example.css - * CSS for ajax_example. - * - * See @link ajax_example_dependent_dropdown_degrades @endlink for - * details on what this file does. It is not used in any other example. - */ - -/* hide the next button when not degrading to non-javascript browser */ -html.js .next-button { - display: none; -} - -/* Make the next/choose button align to the right of the select control */ -.form-item-dropdown-first, .form-item-question-type-select { - display: inline-block; -} - - diff --git a/ajax_example/ajax_example.info b/ajax_example/ajax_example.info deleted file mode 100644 index 359fe946b8c2556f37add24c9e13996d45db0d6b..0000000000000000000000000000000000000000 --- a/ajax_example/ajax_example.info +++ /dev/null @@ -1,5 +0,0 @@ - -name = AJAX Example -description = An example module showing how to use Drupal AJAX forms -core = 7.x -package = Example modules diff --git a/ajax_example/ajax_example.js b/ajax_example/ajax_example.js deleted file mode 100644 index ce5b88a1b18d2e9a5149335bbbefd8287dfa817e..0000000000000000000000000000000000000000 --- a/ajax_example/ajax_example.js +++ /dev/null @@ -1,31 +0,0 @@ - -/* - * @file ajax_example.js - * JavaScript for ajax_example. - * - * See @link ajax_example_dependent_dropdown_degrades @endlink for - * details on what this file does. It is not used in any other example. - * - */ - -(function($) { - - // Re-enable form elements that are disabled for non-ajax situations. - Drupal.behaviors.enableFormItemsForAjaxForms = { - attach: function() { - // If ajax is enabled. - if (Drupal.ajax) { - $('.enabled-for-ajax').removeAttr('disabled'); - } - - // Below is only for the demo case of showing with js turned off. - // It overrides the behavior of the CSS that would normally turn off - // the 'ok' button when JS is enabled. Here, for demonstration purposes, - // we have AJAX disabled but JS turned on, so use this to simulate. - if (!Drupal.ajax) { - $('html.js .next-button').show(); - } - } - }; - -})(jQuery); diff --git a/ajax_example/ajax_example.module b/ajax_example/ajax_example.module deleted file mode 100644 index 0b29ad093c5ec88acb323143f4e26e1eda7d907a..0000000000000000000000000000000000000000 --- a/ajax_example/ajax_example.module +++ /dev/null @@ -1,549 +0,0 @@ - 'AJAX Example', - 'page callback' => 'ajax_example_intro', - 'access callback' => TRUE, - 'expanded' => TRUE, - ); - - // Change the description of a form element. - $items['examples/ajax_example/simplest'] = array( - 'title' => 'Simplest AJAX Example', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_simplest'), - 'access callback' => TRUE, - 'weight' => 0, - ); - // Generate a changing number of checkboxes. - $items['examples/ajax_example/autocheckboxes'] = array( - 'title' => 'Generate checkboxes', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_autocheckboxes'), - 'access callback' => TRUE, - 'weight' => 1, - ); - // Generate different textfields based on form state. - $items['examples/ajax_example/autotextfields'] = array( - 'title' => 'Generate textfields', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_autotextfields'), - 'access callback' => TRUE, - 'weight' => 2, - ); - - // Submit a form without a page reload. - $items['examples/ajax_example/submit_driven_ajax'] = array( - 'title' => 'Submit-driven AJAX', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_submit_driven_ajax'), - 'access callback' => TRUE, - 'weight' => 3, - ); - - // Repopulate a dropdown based on form state. - $items['examples/ajax_example/dependent_dropdown'] = array( - 'title' => 'Dependent dropdown', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_dependent_dropdown'), - 'access callback' => TRUE, - 'weight' => 4, - ); - // Repopulate a dropdown, but this time with graceful degredation. - // See ajax_example_graceful_degradation.inc. - $items['examples/ajax_example/dependent_dropdown_degrades'] = array( - 'title' => 'Dependent dropdown (with graceful degradation)', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_dependent_dropdown_degrades'), - 'access callback' => TRUE, - 'weight' => 5, - 'file' => 'ajax_example_graceful_degradation.inc', - ); - // The above example as it appears to users with no javascript. - $items['examples/ajax_example/dependent_dropdown_degrades_no_js'] = array( - 'title' => 'Dependent dropdown with javascript off', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_dependent_dropdown_degrades', TRUE), - 'access callback' => TRUE, - 'file' => 'ajax_example_graceful_degradation.inc', - 'weight' => 5, - ); - - // Populate a form section based on input in another element. - $items['examples/ajax_example/dynamic_sections'] = array( - 'title' => 'Dynamic Sections (with graceful degradation)', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_dynamic_sections'), - 'access callback' => TRUE, - 'weight' => 6, - 'file' => 'ajax_example_graceful_degradation.inc', - ); - // The above example as it appears to users with no javascript. - $items['ajax_example/dynamic_sections_no_js'] = array( - 'title' => 'Dynamic Sections w/JS turned off', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_dynamic_sections', TRUE), - 'access callback' => TRUE, - 'weight' => 6, - 'file' => 'ajax_example_graceful_degradation.inc', - ); - - // A classic multi-step wizard, but with no page reloads. - // See ajax_example_graceful_degradation.inc. - $items['examples/ajax_example/wizard'] = array( - 'title' => 'Wizard (with graceful degradation)', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_wizard'), - 'access callback' => TRUE, - 'file' => 'ajax_example_graceful_degradation.inc', - 'weight' => 7, - ); - // The above example as it appears to users with no javascript. - $items['examples/ajax_example/wizard_no_js'] = array( - 'title' => 'Wizard w/JS turned off', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_wizard', TRUE), - 'access callback' => TRUE, - 'file' => 'ajax_example_graceful_degradation.inc', - 'weight' => 7, - ); - - // Add-more button that creates additional form elements. - // See ajax_example_graceful_degradation.inc. - $items['examples/ajax_example/add_more'] = array( - 'title' => 'Add-more button (with graceful degradation)', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_add_more'), - 'access callback' => TRUE, - 'file' => 'ajax_example_graceful_degradation.inc', - 'weight' => 8, - ); - // The above example as it appears to users with no javascript. - $items['examples/ajax_example/add_more_no_js'] = array( - 'title' => 'Add-more button w/JS turned off', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_add_more', TRUE), - 'access callback' => TRUE, - 'file' => 'ajax_example_graceful_degradation.inc', - 'weight' => 8, - ); - - // Use the AJAX framework outside the context of a form using the use-ajax - // class. See ajax_example_misc.inc. - $items['examples/ajax_example/ajax_link'] = array( - 'title' => 'Ajax Link ("use-ajax" class)', - 'page callback' => 'ajax_example_render_link', - 'access callback' => TRUE, - 'file' => 'ajax_example_misc.inc', - 'weight' => 9, - ); - // Use the AJAX framework outside the context of a form using a renderable - // array of type link with the #ajax property. See ajax_example_misc.inc. - $items['examples/ajax_example/ajax_link_renderable'] = array( - 'title' => 'Ajax Link (Renderable Array)', - 'page callback' => 'ajax_example_render_link_ra', - 'access callback' => TRUE, - 'file' => 'ajax_example_misc.inc', - 'weight' => 9, - ); - // A menu callback is required when using ajax outside of the Form API. - $items['ajax_link_callback'] = array( - 'page callback' => 'ajax_link_response', - 'access callback' => 'user_access', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - 'file' => 'ajax_example_misc.inc', - ); - - // Use AJAX framework commands outside of the #ajax form property. - // See ajax_example_advanced.inc. - $items['examples/ajax_example/advanced_commands'] = array( - 'title' => 'AJAX framework commands', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('ajax_example_advanced_commands'), - 'access callback' => TRUE, - 'file' => 'ajax_example_advanced.inc', - 'weight' => 10, - ); - - return $items; -} - -function ajax_example_intro() { - $markup = t('The AJAX example module provides many examples of AJAX including forms, links, and AJAX commands.'); - return $markup; -} - -/** - * @ingroup ajax_examples - * @{ - */ - -/** - * Simple form whose ajax-enabled 'changethis' member causes a text change - * in the description of the 'replace_textfield' member. - * See @link http://drupal.org/node/262422 Form API Tutorial @endlink - */ -function ajax_example_simplest($form, &$form_state) { - $form = array(); - $form['changethis'] = array( - '#title' => t("Choose something and explain why"), - '#type' => 'select', - '#options' => array( - 'one' => 'one', - 'two' => 'two', - 'three' => 'three', - ), - '#ajax' => array( - // #ajax has two required keys: callback and wrapper. - // 'callback' is a function that will be called when this element changes. - 'callback' => 'ajax_example_simplest_callback', - // 'wrapper' is the HTML id of the page element that will be replaced. - 'wrapper' => 'replace_textfield_div', - // There are also several optional keys - see ajax_example_autocheckboxes - // below for details on 'method', 'effect' and 'speed' and - // ajax_example_dependent_dropdown for 'event'. - ), - ); - - // This entire form element will be replaced whenever 'changethis' is updated. - $form['replace_textfield'] = array( - '#type' => 'textfield', - '#title' => t("Why"), - // The prefix/suffix provide the div that we're replacing, named by - // #ajax['wrapper'] above. - '#prefix' => '
first row |
Row $i |
' . t('The color code in this field is @code', array('@code' => $item['rgb'])) . '
'; - } - break; - - // This formatter adds css to the page changing the '.region-content' area's - // background color. If there are many fields, the last one will win. - case 'field_example_color_background': - foreach ($items as $delta => $item) { - drupal_add_css('div.region-content { background-color:' . $item['rgb'] . ';}', array('type' => 'inline') ); - $element[$delta]['#markup'] = '' . t('The content area color has been changed to @code', array('@code' => $item['rgb'])) . '
'; - } - break; - } - - return $element; -} - - -/************************************************************************** - * Field Type API: Widget - * - * The widget is the form element used to receive input from the user - * when the field is being populated. - **************************************************************************/ - -/** - * Implements hook_field_widget_info(). - * - * Three widgets are provided. - * - A simple text-only widget where the user enters the '#ffffff'. - * - A 3-textfield widget that gathers the red, green, and blue values - * separately. - * - A farbtastic colorpicker widget that chooses the value graphically. - */ -function field_example_field_widget_info() { - return array( - 'field_example_text' => array( - 'label' => t('RGB value as #ffffff'), - 'field types' => array('field_example_rgb'), - ), - 'field_example_3text' => array( - 'label' => t('RGB text field'), - 'field types' => array('field_example_rgb'), - ), - 'field_example_colorpicker' => array( - 'label' => t('Color Picker'), - 'field types' => array('field_example_rgb'), - ), - ); -} - -/** - * Implements hook_field_widget_form(). - * - * Three different forms are provided, for the three widget types. - * - * The 'field_example_colorpicker' and 'field_example_text' are essentially - * the same, but field_example_colorpicker adds a javascript colorpicker - * helper. - * - * field_example_3text displays three text fields, one each for red, green, - * and blue. However, the field type defines a single text column, - * rgb, which needs an HTML color spec. Define an element validate - * handler that converts our r, g, and b fields into a simulated single - * 'rgb' form element. - */ -function field_example_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { - $value = isset($items[$delta]['rgb']) ? $items[$delta]['rgb'] : ''; - $element += array( - '#delta' => $delta, - ); - $element['rgb'] = array(); - - switch ($instance['widget']['type']) { - - case 'field_example_colorpicker': - $element['rgb'] += array( - '#suffix' => '', - '#attributes' => array('class' => array('edit-field-example-colorpicker')), - '#attached' => array( - // Add Farbtastic color picker. - 'library' => array( - array('system', 'farbtastic'), - ), - // Add javascript to trigger the colorpicker. - 'js' => array(drupal_get_path('module', 'field_example') . '/field_example.js'), - ), - ); - - // DELIBERATE fall-through: From here on the field_example_text and - // field_example_colorpicker are exactly the same. - case 'field_example_text': - $element['rgb'] += array( - '#type' => 'textfield', - '#default_value' => $value, - // Allow a slightly larger size that the field length to allow for some - // configurations where all characters won't fit in input field. - '#size' => 7, - '#maxlength' => 7, - ); - break; - - case 'field_example_3text': - // Convert rgb value into r, g, and b for #default_value. - if (isset($items[$delta]['rgb'])) { - preg_match_all('@..@', substr($items[$delta]['rgb'], 1), $match); - } - else { - $match = array(array()); - } - - // A fieldset to hold the three text fields. - $element += array( - '#type' => 'fieldset', - '#element_validate' => array('field_example_3text_validate'), - - // The following is set so that the validation function will be able - // to access external value information which otherwise would be - // unavailable. - '#delta' => $delta, - '#attached' => array( - 'css' => array(drupal_get_path('module', 'field_example') . '/field_example.css'), - ), - ); - - // Create a textfield for saturation values for Red, Green, and Blue. - foreach (array('r' => t('Red'), 'g' => t('Green'), 'b' => t('Blue')) as $key => $title) { - $element[$key] = array( - '#type' => 'textfield', - '#title' => $title, - '#size' => 2, - '#default_value' => array_shift($match[0]), - '#attributes' => array('class' => array('rgb-entry')), - // '#description' => t('The 2-digit hexadecimal representation of the @color saturation, like "a1" or "ff"', array('@color' => $title)), - ); - } - break; - - } - return $element; -} - - -/** - * Validate the individual fields and then convert them into a single HTML RGB - * value as text. - */ -function field_example_3text_validate($element, &$form_state) { - $delta = $element['#delta']; // TODO: Isn't there a better way to find out which element? - $field = $form_state['field'][$element['#field_name']][$element['#language']]['field']; - $field_name = $field['field_name']; - if (isset($form_state['values'][$field_name][$element['#language']][$delta])) { - $values = $form_state['values'][$field_name][$element['#language']][$delta]; - foreach (array('r', 'g', 'b') as $colorfield) { - $val = hexdec($values[$colorfield]); - // If they left any empty, we'll set the value empty and quit. - if (strlen($values[$colorfield]) == 0) { - form_set_value($element, array('rgb' => NULL), $form_state); - return; - } - // If they gave us anything that's not hex, reject it. - if ( (strlen($values[$colorfield]) != 2) || $val < 0 || $val > 255) { - form_error($element[$colorfield], t("Saturation value must be a 2-digit hexadecimal value between 00 and ff.")); - } - } - - $value = sprintf('#%02s%02s%02s', $values['r'], $values['g'], $values['b']); - form_set_value($element, array('rgb' => $value), $form_state); - } -} - -/** - * Implements hook_field_widget_error(). - */ -function field_example_field_widget_error($element, $error, $form, &$form_state) { - switch ($error['error']) { - case 'field_example_invalid': - form_error($element, $error['message']); - break; - } -} - - -/** - * Implements hook_menu(). - * - * Provides a simple user interface that tells the developer where to go. - */ -function field_example_menu() { - $items['examples/field_example'] = array( - 'title' => 'Field Example', - 'page callback' => '_field_example_page', - 'access callback' => TRUE, - ); - return $items; -} - -/** - * A simple page to explain to the developer what to do. - */ -function _field_example_page() { - return t("The Field Example provides a field composed of an HTML RGB value, like #ff00ff. To use it, add the field to a content type."); -} diff --git a/field_example/field_example.test b/field_example/field_example.test deleted file mode 100644 index a138fbd43ed39d7126993a6dd061cf803ab47bca..0000000000000000000000000000000000000000 --- a/field_example/field_example.test +++ /dev/null @@ -1,144 +0,0 @@ - 'Field Example', - 'description' => 'Create a content type with example_field_rgb fields, create a node, check for correct values.', - 'group' => 'Examples', - ); - } - function setUp() { - // Enable the email_example module. - parent::setUp(array('field_ui', 'field_example')); - } - - /** - * Test basic functionality of the example field. - * - * - Creates a content type. - * - Adds a single-valued field_example_rgb to it. - * - Adds a multivalued field_example_rgb to it. - * - Creates a node of the new type. - * - Populates the single-valued field. - * - Populates the multivalued field with two items. - * - Tests the result. - */ - function testExampleFieldBasic() { - $content_type_friendly = $this->randomName(20); - $content_type_machine = strtolower($this->randomName(10)); - $title = $this->randomName(20); - - // Create and login user. - $account = $this->drupalCreateUser(array('administer content types')); - $this->drupalLogin($account); - - $this->drupalGet('admin/structure/types'); - - // Create the content type. - $this->clickLink(t('Add content type')); - - $single_field_name_friendly = $this->randomName(20); - $single_field_name_machine = strtolower($this->randomName(10)); - - $edit = array ( - 'name' => $content_type_friendly, - 'type' => $content_type_machine, - ); - $this->drupalPost(NULL, $edit, t('Save and add fields')); - $this->assertText(t('The content type @name has been added.', array('@name' => $content_type_friendly))); - - // Now add a singleton field. - $edit = array ( - 'fields[_add_new_field][label]' => $single_field_name_friendly, - 'fields[_add_new_field][field_name]' => $single_field_name_machine, - 'fields[_add_new_field][type]' => 'field_example_rgb', - 'fields[_add_new_field][widget_type]' => 'field_example_3text', - - ); - $this->drupalPost(NULL, $edit, t('Save')); - - // There are no settings for this, so just press the button. - $this->drupalPost(NULL, array(), t('Save field settings')); - - // Using all the default settings, so press the button. - $this->drupalPost(NULL, array(), t('Save settings')); - $this->assertText(t('Saved @name configuration.', array('@name' => $single_field_name_friendly))); - - // Now we're back on the field-add page. - // Now add a multivalued field. - $multivalue_field_name_friendly = $this->randomName(20); - $multivalue_field_name_machine = strtolower($this->randomName(10)); - $edit = array ( - 'fields[_add_new_field][label]' => $multivalue_field_name_friendly, - 'fields[_add_new_field][field_name]' => $multivalue_field_name_machine, - 'fields[_add_new_field][type]' => 'field_example_rgb', - 'fields[_add_new_field][widget_type]' => 'field_example_3text', - ); - $this->drupalPost(NULL, $edit, t('Save')); - - $this->drupalPost(NULL, array(), t('Save field settings')); - - $edit = array('field[cardinality]' => (string)(-1)); - $this->drupalPost(NULL, $edit, t('Save settings')); - - $this->assertText(t('Saved @name configuration.', array('@name' => $multivalue_field_name_friendly))); - - $this->drupalPost(NULL, array(), t('Save')); - - // Somehow clicking "save" isn't enough, and we have to do a - // node_types_rebuild(). - node_types_rebuild(); - menu_rebuild(); - $type_exists = db_query('SELECT 1 FROM {node_type} WHERE type = :type', array(':type' => $content_type_machine))->fetchField(); - $this->assertTrue($type_exists, 'The new content type has been created in the database.'); - - $permission = 'create ' . $content_type_machine . ' content'; - // Reset the permissions cache. - $this->checkPermissions(array($permission), TRUE); - - // Now that we have a new content type, create a user that has privileges - // on the content type. - $account = $this->drupalCreateUser(array($permission)); - $this->drupalLogin($account); - - $this->drupalGet('node/add/' . $content_type_machine); - - // Add a node. - $edit = array( - 'title' => $title, - 'field_' . $single_field_name_machine . '[und][0][r]' => 'ff', - 'field_' . $single_field_name_machine . '[und][0][g]' => '00', - 'field_' . $single_field_name_machine . '[und][0][b]' => '00', - - 'field_' . $multivalue_field_name_machine . '[und][0][r]' => '00', - 'field_' . $multivalue_field_name_machine . '[und][0][g]' => 'ff', - 'field_' . $multivalue_field_name_machine . '[und][0][b]' => '00', - - ); - // We want to add a 2nd item in the multivalue field, so hit "add another". - $this->drupalPost(NULL, $edit, t('Add another item')); - - $edit = array( - 'field_' . $multivalue_field_name_machine . '[und][1][r]' => '00', - 'field_' . $multivalue_field_name_machine . '[und][1][g]' => '00', - 'field_' . $multivalue_field_name_machine . '[und][1][b]' => 'ff', - ); - // Now we can fill in the second item in the multivalue field and save. - $this->drupalPost(NULL, $edit, t('Save')); - $this->assertText(t('@content_type_friendly @title has been created', array('@content_type_friendly' => $content_type_friendly, '@title' => $title))); - - - $output_strings = $this->xpath("//div[contains(@class,'field-type-field-example-rgb')]/div/div/p/text()"); - - $this->assertEqual((string)$output_strings[0], t("The color code in this field is #ff0000"), t('Found first color code #ff0000')); - $this->assertEqual((string)$output_strings[1], t("The color code in this field is #00ff00"), t('Found second color code #00ff00')); - $this->assertEqual((string)$output_strings[2], t("The color code in this field is #0000ff"), t('Found third color code #0000ff')); - } -} diff --git a/file_example/file_example.info b/file_example/file_example.info deleted file mode 100644 index acdca71e50f20671fdf897e72a0db9851b9b8f7e..0000000000000000000000000000000000000000 --- a/file_example/file_example.info +++ /dev/null @@ -1,6 +0,0 @@ -name = File example -description = Examples of using the Drupal File API and Stream Wrappers. -package = Example modules -core = 7.x -files[] = file_example_session_streams.inc -files[] = file_example.test diff --git a/file_example/file_example.module b/file_example/file_example.module deleted file mode 100644 index c7e0224560653b7fa7cfb5d58467f4331ad9e4ce..0000000000000000000000000000000000000000 --- a/file_example/file_example.module +++ /dev/null @@ -1,522 +0,0 @@ - 'File Example', - 'page callback' => 'file_example_intro', - 'access callback' => TRUE, - 'expanded' => TRUE, - ); - $items['examples/file_example/fileapi'] = array( - 'title' => 'Use File API to read/write a file', - 'page callback' => 'drupal_get_form', - 'access arguments' => array('use file example'), - 'page arguments' => array('file_example_readwrite'), - ); - $items['examples/file_example/access_session'] = array( - 'page callback' => 'file_example_session_contents', - 'access arguments' => array('use file example'), - 'type' => MENU_CALLBACK, - ); - return $items; -} - - -/** - * Implements hook_permission(). - */ -function file_example_permission() { - return array( - 'use file example' => array( - 'title' => t('Use the examples in the File Example module'), - ), - ); -} - - -/** - * Form builder function for the file example readwrite and directory creation - * example. - * - * A simple form that allows creation of a file, managed or unmanaged. It - * also allows reading/deleting a file and creation of a directory. - * @ingroup file_example - */ -function file_example_readwrite($form, &$form_state) { - if (empty($_SESSION['file_example_default_file'])) { - $_SESSION['file_example_default_file'] = 'public://drupal.txt'; - } - $default_file = $_SESSION['file_example_default_file']; - if (empty($_SESSION['file_example_default_directory'])) { - $_SESSION['file_example_default_directory'] = 'public://directory1'; - } - $default_directory = $_SESSION['file_example_default_directory']; - - $form['write_file'] = array( - '#type' => 'fieldset', - '#title' => t('Write to a file'), - ); - $form['write_file']['write_contents'] = array( - '#type' => 'textfield', - '#title' => t('Enter something you would like to write to a file') . ' ' . date('m'), - '#default_value' => t('Put some text here or just use this text'), - ); - - $form['write_file']['destination'] = array( - '#type' => 'textfield', - '#default_value' => $default_file, - '#title' => t('Optional: Enter the streamwrapper saying where it should be written'), - '#description' => t('This may be public://some_dir/test_file.txt or private://another_dir/some_file.txt, for example. If you include a directory, it must already exist. The default is "public://". Since this example supports session://, you can also use something like session://somefile.txt.'), - ); - - $form['write_file']['managed_submit'] = array( - '#type' => 'submit', - '#value' => t('Write managed file'), - '#submit' => array('file_example_managed_write_submit'), - ); - $form['write_file']['unmanaged_submit'] = array( - '#type' => 'submit', - '#value' => t('Write unmanaged file'), - '#submit' => array('file_example_unmanaged_write_submit'), - ); - $form['write_file']['unmanaged_php'] = array( - '#type' => 'submit', - '#value' => t('Unmanaged using PHP'), - '#submit' => array('file_example_unmanaged_php_submit'), - ); - - $form['fileops'] = array( - '#type' => 'fieldset', - '#title' => t('Read from a file'), - ); - $form['fileops']['fileops_file'] = array( - '#type' => 'textfield', - '#default_value' => $default_file, - '#title' => t('Enter the URI of a file'), - '#description' => t('This must be a stream-type description like public://some_file.txt or http://drupal.org or private://another_file.txt or (for this example) session://yet_another_file.txt.'), - ); - $form['fileops']['read_submit'] = array( - '#type' => 'submit', - '#value' => t('Read the file and store it locally'), - '#submit' => array('file_example_read_submit'), - ); - $form['fileops']['delete_submit'] = array( - '#type' => 'submit', - '#value' => t('Delete file'), - '#submit' => array('file_example_delete_submit'), - ); - $form['fileops']['check_submit'] = array( - '#type' => 'submit', - '#value' => t('Check to see if file exists'), - '#submit' => array('file_example_file_check_exists_submit'), - ); - - $form['directory'] = array( - '#type' => 'fieldset', - '#title' => t('Create or prepare a directory'), - ); - - $form['directory']['directory_name'] = array( - '#type' => 'textfield', - '#title' => t('Directory to create/prepare/delete'), - '#default_value' => $default_directory, - '#description' => t('This is a directory as in public://some/directory or private://another/dir.'), - ); - $form['directory']['create_directory'] = array( - '#type' => 'submit', - '#value' => t('Create directory'), - '#submit' => array('file_example_create_directory_submit'), - ); - $form['directory']['delete_directory'] = array( - '#type' => 'submit', - '#value' => t('Delete directory'), - '#submit' => array('file_example_delete_directory_submit'), - ); - $form['directory']['check_directory'] = array( - '#type' => 'submit', - '#value' => t('Check to see if directory exists'), - '#submit' => array('file_example_check_directory_submit'), - ); - - $form['debug'] = array( - '#type' => 'fieldset', - '#title' => t('Debugging'), - ); - $form['debug']['show_session'] = array( - '#type' => 'submit', - '#value' => t('Show $_SESSION contents'), - '#submit' => array('file_example_show_session_contents_submit'), - ); - $form['debug']['show_raw_session'] = array( - '#type' => 'submit', - '#value' => t('Show raw $_SESSION contents'), - '#submit' => array('file_example_show_session_contents_submit'), - ); - - return $form; -} - -/** - * Submit handler to write a managed file. - * - * The key functions used here are: - * - file_save_data(), which takes a buffer and saves it to a named file and - * also creates a tracking record in the database and returns a file object. - * In this function we use FILE_EXISTS_RENAME (the default) as the argument, - * which means that if there's an existing file, create a new non-colliding - * filename and use it. - * - file_create_url(), which converts a URI in the form public://junk.txt or - * private://something/test.txt into a URL like - * http://example.com/sites/default/files/junk.txt. - * @ingroup file_example - */ -function file_example_managed_write_submit($form, &$form_state) { - $data = $form_state['values']['write_contents']; - $uri = !empty($form_state['values']['destination']) ? $form_state['values']['destination'] : NULL; - - // Managed operations work with a file object. - $file_object = file_save_data($data, $uri, FILE_EXISTS_RENAME); - if (!empty($file_object)) { - $url = file_create_url($file_object->uri); - $_SESSION['file_example_default_file'] = $file_object->uri; - drupal_set_message(t('Saved managed file: %file to destination %destination (accessible via !url, actual uri=@uri)', array('%file' => print_r($file_object, TRUE), '%destination' => $uri, '@uri' => $file_object->uri, '!url' => l(t('this URL'), $url)))); - } - else { - drupal_set_message(t('Failed to save the managed file'), 'error'); - } -} - -/** - * Submit handler to write an unmanaged file. - * - * The key functions used here are: - * - file_unmanaged_save_data(), which takes a buffer and saves it to a named - * file, but does not create any kind of tracking record in the database. - * This example uses FILE_EXISTS_REPLACE for the third argument, meaning - * that if there's an existing file at this location, it should be replaced. - * - file_create_url(), which converts a URI in the form public://junk.txt or - * private://something/test.txt into a URL like - * http://example.com/sites/default/files/junk.txt. - * @ingroup file_example - */ - -function file_example_unmanaged_write_submit($form, &$form_state) { - $data = $form_state['values']['write_contents']; - $destination = !empty($form_state['values']['destination']) ? $form_state['values']['destination'] : NULL; - - // With the unmanaged file we just get a filename back. - $filename = file_unmanaged_save_data($data, $destination, FILE_EXISTS_REPLACE); - if ($filename) { - $url = file_create_url($filename); - $_SESSION['file_example_default_file'] = $filename; - drupal_set_message(t('Saved file as %filename (accessible via !url, uri=@uri)', array('%filename' => $filename, '@uri' => $filename, '!url' => l(t('this URL'), $url)))); - } - else { - drupal_set_message(t('Failed to save the file'), 'error'); - } -} - - - -/** - * Submit handler to write an unmanaged file using plain PHP functions. - * - * The key functions used here are: - * - file_unmanaged_save_data(), which takes a buffer and saves it to a named - * file, but does not create any kind of tracking record in the database. - * - file_create_url(), which converts a URI in the form public://junk.txt or - * private://something/test.txt into a URL like - * http://example.com/sites/default/files/junk.txt. - * - drupal_tempnam() generates a temporary filename for use. - * @ingroup file_example - */ - -function file_example_unmanaged_php_submit($form, &$form_state) { - $data = $form_state['values']['write_contents']; - $destination = !empty($form_state['values']['destination']) ? $form_state['values']['destination'] : NULL; - - if (empty($destination)) { - // If no destination has been provided, use a generated name. - $destination = drupal_tempnam('public://', 'file'); - } - - // With all traditional PHP functions we can use the stream wrapper notation - // for a file as well. - $fp = fopen($destination, 'w'); - - // To demonstrate the fact that everything is based on streams, we'll do - // multiple 5-character writes to put this to the file. We could easily - // (and far more conveniently) write it in a single statement with - // fwrite($fp, $data). - $length = strlen($data); - $write_size = 5; - for ($i=0; $i < $length; $i += $write_size) { - $result = fwrite($fp, substr($data, $i, $write_size)); - if ($result === FALSE) { - drupal_set_message(t('Failed writing to the file; '), 'error'); - fclose($fp); - return; - } - } - $url = file_create_url($destination); - $_SESSION['file_example_default_file'] = $destination; - drupal_set_message(t('Saved file as %filename (accessible via !url, uri=@uri)', array('%filename' => $destination, '@uri' => $destination, '!url' => l(t('this URL'), $url)))); -} - -/** - * Submit handler for reading a stream wrapper. - * - * Drupal now has full support for PHP's stream wrappers, which means that - * instead of the traditional use of all the file functions - * ($fp = fopen("/tmp/some_file.txt");) far more sophisticated and generalized - * (and extensible) things can be opened as if they were files. Drupal itself - * provides the public:// and private:// schemes for handling public and - * private files. PHP provides file:// (the default) and http://, so that a - * URL can be read or written (as in a POST) as if it were a file. In addition, - * new schemes can be provided for custom applications, as will be demonstrated - * below. - * - * Here we take the stream wrapper provided in the form. We grab the - * contents with file_get_contents(). Notice that's it's as simple as that: - * file_get_contents("http://example.com") or - * file_get_contents("public://somefile.txt") just works. Although it's - * not necessary, we use file_unmanaged_save_data() to save this file locally - * and then find a local URL for it by using file_create_url(). - * @ingroup file_example - */ -function file_example_read_submit($form, &$form_state) { - $uri = $form_state['values']['fileops_file']; - - if (!is_file($uri)) { - drupal_set_message(t('The file %uri does not exist', array('%uri' => $uri)), 'error'); - return; - } - - // Make a working filename to save this by stripping off the (possible) - // file portion of the streamwrapper. If it's an evil file extension, - // file_munge_filename() will neuter it. - $filename = file_munge_filename(preg_replace('@^.*/@', '', $uri), '', TRUE); - $buffer = file_get_contents($uri); - - if ($buffer) { - $sourcename = file_unmanaged_save_data($buffer, 'public://' . $filename); - if ($sourcename) { - $url = file_create_url($sourcename); - $_SESSION['file_example_default_file'] = $sourcename; - drupal_set_message(t('The file was read and copied to %filename which is accessible at !url', array('%filename' => $sourcename, '!url' => l($url, $url)))); - } - else { - drupal_set_message(t('Failed to save the file')); - } - } - else { // We failed to get the contents of the requested file - drupal_set_message(t('Failed to retrieve the file %file', array('%file' => $uri))); - } -} - -/** - * Submit handler to delete a file. - */ -function file_example_delete_submit($form, &$form_state) { - - $uri = $form_state['values']['fileops_file']; - - // Since we don't know if the file is managed or not, look in the database - // to see. Normally, code would be working with either managed or unmanaged - // files, so this is not a typical situation. - $file_object = file_example_get_managed_file($uri); - - // If a managed file, use file_delete(). - if (!empty($file_object)) { - $result = file_delete($file_object); - if ($result !== TRUE) { - drupal_set_message(t('Failed deleting managed file %uri. Result was %result', array('%uri' => $uri, '%result' => print_r($result, TRUE))), 'error'); - } - else { - drupal_set_message(t('Successfully deleted managed file %uri', array('%uri' => $uri))); - $_SESSION['file_example_default_file'] = $uri; - } - } - // else use file_unmanaged_delete(). - else { - $result = file_unmanaged_delete($uri); - if ($result !== TRUE) { - drupal_set_message(t('Failed deleting unmanaged file %uri', array('%uri' => $uri, 'error'))); - } - else { - drupal_set_message(t('Successfully deleted unmanaged file %uri', array('%uri' => $uri))); - $_SESSION['file_example_default_file'] = $uri; - } - } -} - -/** - * Submit handler to check existence of a file. - */ -function file_example_file_check_exists_submit($form, &$form_state) { - $uri = $form_state['values']['fileops_file']; - if (is_file($uri)) { - drupal_set_message(t('The file %uri exists.', array('%uri' => $uri))); - } - else { - drupal_set_message(t('The file %uri does not exist.', array('%uri' => $uri))); - } - -} -/** - * Submit handler for directory creation. - * Here we create a directory and set proper permissions on it using - * file_prepare_directory(). - * @ingroup file_example - */ -function file_example_create_directory_submit($form, &$form_state) { - $directory = $form_state['values']['directory_name']; - - // The options passed to file_prepare_directory are a bitmask, so we can - // specify either FILE_MODIFY_PERMISSIONS (set permissions on the directory), - // FILE_CREATE_DIRECTORY, or both together: - // FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY. - // FILE_MODIFY_PERMISSIONS will set the permissions of the directory by - // by default to 0755, or to the value of the variable 'file_chmod_directory'. - if (!file_prepare_directory($directory, FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY)) { - drupal_set_message(t('Failed to create %directory.', array('%directory' => $directory)), 'error'); - } - else { - $result = is_dir($directory); - drupal_set_message(t('Directory %directory is ready for use.', array('%directory' => $directory))); - $_SESSION['file_example_default_directory'] = $directory; - } -} - -/** - * Submit handler for directory deletion. - * - * @see file_unmanaged_delete_recursive() - * - * @ingroup file_example - */ -function file_example_delete_directory_submit($form, &$form_state) { - $directory = $form_state['values']['directory_name']; - - $result = file_unmanaged_delete_recursive($directory); - if (!$result) { - drupal_set_message(t('Failed to delete %directory.', array('%directory' => $directory)), 'error'); - } - else { - drupal_set_message(t('Recursively deleted directory %directory.', array('%directory' => $directory))); - $_SESSION['file_example_default_directory'] = $directory; - } -} - -/** - * Submit handler to test directory existence. - * This actually just checks to see if the directory is writable - * @param unknown_type $form - * @param unknown_type $form_state - */ -function file_example_check_directory_submit($form, &$form_state) { - $directory = $form_state['values']['directory_name']; - $result = is_dir($directory); - if (!$result) { - drupal_set_message(t('Directory %directory does not exist.', array('%directory' => $directory))); - } - else { - drupal_set_message(t('Directory %directory exists.', array('%directory' => $directory))); - } -} - -/** - * Utility submit function for debugging: Show $_SESSION. - */ -function file_example_show_session_contents_submit($form, &$form_state) { - if ($form_state['triggering_element']['#value'] == t('Show raw $_SESSION contents')) { - drupal_set_message('' . print_r($_SESSION['file_example'], TRUE) . ''); - } - else { - return file_example_session_contents(NULL); - } -} - -/** - * Utility function to check for and return a managed file. - * In this demonstration code we don't necessarily know if a file is managed - * or not, so often need to check to do the correct behavior. Normal code - * would not have to do this, as it would be working with either managed or - * unmanaged files. - * - * @param $uri - * The URI of the file, like public://test.txt. - */ -function file_example_get_managed_file($uri) { - $fid = db_query('SELECT fid FROM {file_managed} WHERE uri = :uri', array(':uri' => $uri))->fetchField(); - if (!empty($fid)) { - $file_object = file_load($fid); - return $file_object; - } - return FALSE; -} - -/** - * Implements hook_stream_wrappers(). - * hook_stream_wrappers() is Drupal's way of exposing the class that PHP will - * use to provide a new stream wrapper class. In this case, we'll expose the - * 'session' scheme, so a file reference like "session://example/example.txt" - * is readable and writable as a location in the $_SESSION variable. - * - * @see FileExampleSessionStreamWrapper - * - * defgroup streamwrapper_example Stream Wrapper Example - */ -function file_example_stream_wrappers() { - $wrappers = array( - 'session' => array( - 'name' => t('Example: $_SESSION variable storage'), - 'class' => 'FileExampleSessionStreamWrapper', - 'description' => t('Store files in the $_SESSION variable as an example.'), - ), - ); - return $wrappers; -} - -/** - * A utility function to allow us to see what is in a session "file". - * - * @param $session_path - * The path, as in 'example/some/thing.txt'. This actually is a $_SESSION - * key. example/some/thing.txt would be - * $_SESSION['file_example']['some']['thing.txt'] - */ -function file_example_session_contents() { - if (module_exists('devel')) { - dsm($_SESSION['file_example'], t('Entire $_SESSION["file_example"]')); - } - $path_components = func_get_args(); - $session_path = join('/', $path_components); - $content = file_get_contents('session://' . $session_path); - return t('Contents of ') . check_plain($session_path) . ': ' . print_r($content, TRUE); -} - diff --git a/file_example/file_example.test b/file_example/file_example.test deleted file mode 100644 index b9cbcaf764e94841aa90e84aa519969452582a0f..0000000000000000000000000000000000000000 --- a/file_example/file_example.test +++ /dev/null @@ -1,123 +0,0 @@ - 'File Example Functionality', - 'description' => 'Test File Example features and sample streamwrapper.', - 'group' => 'Examples', - ); - } - function setUp() { - parent::setUp(array('file_example')); - $privileged_user = $this->drupalCreateUser(array('use file example')); - $this->drupalLogin($privileged_user); - } - - /** - * Test the basic File Example UI. - * - Create a directory to work with - * - Foreach scheme create and read files using each of the three methods. - */ - function testFileExampleBasic() { - - $expected_text = array( - t('Write managed file') => t('Saved managed file'), - t('Write unmanaged file') => t('Saved file as'), - t('Unmanaged using PHP') => t('Saved file as'), - ); - // For each of the three buttons == three write types - foreach (array(t('Write managed file'), t('Write unmanaged file'), t('Unmanaged using PHP')) as $button) { - // For each scheme supported by Drupal + the session:// wrapper - foreach (array('public', 'private', 'temporary', 'session') as $scheme) { - // Create a directory for use. - $dirname = $scheme . '://' . $this->randomName(10); - - // Directory does not yet exist; assert that. - $edit = array( - 'directory_name' => $dirname, - ); - $this->drupalPost('examples/file_example/fileapi', $edit, t('Check to see if directory exists')); - $this->assertRaw(t('Directory %dirname does not exist', array('%dirname' => $dirname)), t('Verify that directory does not exist.')); - - $this->drupalPost('examples/file_example/fileapi', $edit, t('Create directory')); - $this->assertRaw(t('Directory %dirname is ready for use', array('%dirname' => $dirname))); - - $this->drupalPost('examples/file_example/fileapi', $edit, t('Check to see if directory exists')); - $this->assertRaw(t('Directory %dirname exists', array('%dirname' => $dirname)), t('Verify that directory now does exist.')); - - // Create a file in the directory we created. - $content = $this->randomName(30); - $filename = $dirname . '/' . $this->randomName(30) . '.txt'; - - // Assert that the file we're about to create does not yet exist. - $edit = array( - 'fileops_file' => $filename, - ); - $this->drupalPost('examples/file_example/fileapi', $edit, t('Check to see if file exists')); - $this->assertRaw(t('The file %filename does not exist', array('%filename' => $filename)), t('Verify that file does not yet exist.')); - - debug(t('Processing button=%button, scheme=%scheme, dir=%dirname, file=%filename', array('%button' => $button, '%scheme' => $scheme, '%filename' => $filename, '%dirname' => $dirname))); - $edit = array( - 'write_contents' => $content, - 'destination' => $filename, - ); - $this->drupalPost('examples/file_example/fileapi', $edit, $button); - $this->assertText($expected_text[$button]); - - - // Capture the name of the output file, as it might have changed due - // to file renaming. - $element = $this->xpath('//span[@id="uri"]'); - $output_filename = (string)$element[0]; - debug($output_filename, 'Name of output file'); - - // Click the link provided that is an easy way to get the data for - // checking and make sure that the data we put in is what we get out. - if (!in_array($scheme, array('private', 'temporary'))) { - $this->clickLink(t('this URL')); - $this->assertText($content); - } - - // Verify that the file exists. - $edit = array( - 'fileops_file' => $filename, - ); - $this->drupalPost('examples/file_example/fileapi', $edit, t('Check to see if file exists')); - $this->assertRaw(t('The file %filename exists', array('%filename' => $filename)), t('Verify that file now exists.')); - - // Now read the file that got written above and verify that we can use - // the writing tools. - $edit = array( - 'fileops_file' => $output_filename, - ); - $this->drupalPost('examples/file_example/fileapi', $edit, t('Read the file and store it locally')); - - $this->assertText(t('The file was read and copied')); - - $edit = array( - 'fileops_file' => $filename, - ); - $this->drupalPost('examples/file_example/fileapi', $edit, t('Delete file')); - $this->assertText(t('Successfully deleted')); - $this->drupalPost('examples/file_example/fileapi', $edit, t('Check to see if file exists')); - $this->assertRaw(t('The file %filename does not exist', array('%filename' => $filename)), t('Verify file has been deleted.')); - - $edit = array( - 'directory_name' => $dirname, - ); - $this->drupalPost('examples/file_example/fileapi', $edit, t('Delete directory')); - $this->drupalPost('examples/file_example/fileapi', $edit, t('Check to see if directory exists')); - $this->assertRaw(t('Directory %dirname does not exist', array('%dirname' => $dirname)), t('Verify that directory does not exist after deletion.')); - } - } - } -} diff --git a/file_example/file_example_session_streams.inc b/file_example/file_example_session_streams.inc deleted file mode 100644 index 4c2e1f69d16f44e927d2d74150bb5891aacc3715..0000000000000000000000000000000000000000 --- a/file_example/file_example_session_streams.inc +++ /dev/null @@ -1,678 +0,0 @@ -uri = $uri; - } - - /** - * Implements getUri(). - */ - function getUri() { - return $this->uri; - } - - /** - * Implements getTarget(). - * The "target" is the portion of the URI to the right of the scheme. - * So in session://example/test.txt, the target is 'example/test.txt'. - */ - function getTarget($uri = NULL) { - if (!isset($uri)) { - $uri = $this->uri; - } - - list($scheme, $target) = explode('://', $uri, 2); - - // Remove erroneous leading or trailing, forward-slashes and backslashes. - // In the session:// scheme, there is never a leading slash on the target. - return trim($target, '\/'); - } - - /** - * Implements getMimeType(). - */ - static function getMimeType($uri, $mapping = NULL) { - if (!isset($mapping)) { - // The default file map, defined in file.mimetypes.inc is quite big. - // We only load it when necessary. - include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc'; - $mapping = file_mimetype_mapping(); - } - - $extension = ''; - $file_parts = explode('.', basename($uri)); - - // Remove the first part: a full filename should not match an extension. - array_shift($file_parts); - - // Iterate over the file parts, trying to find a match. - // For my.awesome.image.jpeg, we try: - // - jpeg - // - image.jpeg, and - // - awesome.image.jpeg - while ($additional_part = array_pop($file_parts)) { - $extension = strtolower($additional_part . ($extension ? '.' . $extension : '')); - if (isset($mapping['extensions'][$extension])) { - return $mapping['mimetypes'][$mapping['extensions'][$extension]]; - } - } - - return 'application/octet-stream'; - } - - /** - * Implements getDirectoryPath(). - * In this case there is no directory string, so return an empty string. - */ - public function getDirectoryPath() { - return ''; - } - - /** - * Overrides getExternalUrl(). - * We have set up a helper function and menu entry to provide access to this - * key via HTTP; normally it would be accessible some other way. - */ - function getExternalUrl() { - $path = $this->getLocalPath(); - $url = url('examples/file_example/access_session/' . $path, array('absolute' => TRUE)); - return $url; - } - - /** - * We have no concept of chmod, so just return TRUE. - */ - function chmod($mode) { - return TRUE; - } - - /** - * Implements realpath(). - */ - function realpath() { - return 'session://' . $this->getLocalPath(); - } - - /** - * Returns the local path. - * Here we aren't doing anything but stashing the "file" in a key in the - * $_SESSION variable, so there's not much to do but to create a "path" - * which is really just a key in the $_SESSION variable. So something - * like 'session://one/two/three.txt' becomes - * $_SESSION['file_example']['one']['two']['three.txt'] and the actual path - * is "one/two/three.txt". - * - * @param $uri - * Optional URI, supplied when doing a move or rename. - */ - protected function getLocalPath($uri = NULL) { - if (!isset($uri)) { - $uri = $this->uri; - } - - $path = str_replace('session://', '', $uri); - $path = trim($path, '/'); - return $path; - } - - /** - * Opens a stream, as for fopen(), file_get_contents(), file_put_contents() - * - * @param $uri - * A string containing the URI to the file to open. - * @param $mode - * The file mode ("r", "wb" etc.). - * @param $options - * A bit mask of STREAM_USE_PATH and STREAM_REPORT_ERRORS. - * @param &$opened_path - * A string containing the path actually opened. - * - * @return - * Returns TRUE if file was opened successfully. (Always returns TRUE). - * - * @see http://php.net/manual/en/streamwrapper.stream-open.php - */ - public function stream_open($uri, $mode, $options, &$opened_path) { - $this->uri = $uri; - - // We make $session_content a reference to the appropriate key in the - // $_SESSION variable. So if the local path were - // /example/test.txt it $session_content would now be a - // reference to $_SESSION['file_example']['example']['test.txt']. - $this->session_content = &$this->uri_to_session_key($uri); - - // Reset the stream pointer since this is an open. - $this->stream_pointer = 0; - return TRUE; - } - - /** - * Return a reference to the correct $_SESSION key. - * @param $uri - * The uri: session://something - * @param $create - * If TRUE, create the key - * - * @return - * TRUE if the key exists (which it will if $create was set) - */ - protected function &uri_to_session_key($uri, $create = TRUE) { - $path = $this->getLocalPath($uri); - $path_components = preg_split('/\//', $path); - $fail = FALSE; - $var = &$_SESSION['file_example']; - // Handle case of just session://. - if (strlen($path) == 0) { - return $var; - } - foreach ($path_components as $component) { - if ($create || isset($var[$component])) { - $var = &$var[$component]; - } - else { - return $fail; - } - } - return $var; - } - /** - * Support for flock(). - * The $_SESSION variable has no locking capability, so return TRUE. - * - * @param $operation - * One of the following: - * - LOCK_SH to acquire a shared lock (reader). - * - LOCK_EX to acquire an exclusive lock (writer). - * - LOCK_UN to release a lock (shared or exclusive). - * - LOCK_NB if you don't want flock() to block while locking (not - * supported on Windows). - * - * @return - * Always returns TRUE at the present time. (no support) - * - * @see http://php.net/manual/en/streamwrapper.stream-lock.php - */ - public function stream_lock($operation) { - return TRUE; - } - - /** - * Support for fread(), file_get_contents() etc. - * - * @param $count - * Maximum number of bytes to be read. - * - * @return - * The string that was read, or FALSE in case of an error. - * - * @see http://php.net/manual/en/streamwrapper.stream-read.php - */ - public function stream_read($count) { - if (is_string($this->session_content)) { - $remaining_chars = strlen($this->session_content) - $this->stream_pointer; - $number_to_read = min($count, $remaining_chars); - if ($remaining_chars > 0) { - $buffer = substr($this->session_content, $this->stream_pointer, $number_to_read); - $this->stream_pointer += $number_to_read; - return $buffer; - } - } - return FALSE; - } - - /** - * Support for fwrite(), file_put_contents() etc. - * - * @param $data - * The string to be written. - * - * @return - * The number of bytes written (integer). - * - * @see http://php.net/manual/en/streamwrapper.stream-write.php - */ - public function stream_write($data) { - // Sanitize the data in a simple way since we're putting it into the - // session variable. - $data = check_plain($data); - $this->session_content = substr_replace($this->session_content, $data, $this->stream_pointer); - $this->stream_pointer += strlen($data); - return strlen($data); - } - - /** - * Support for feof(). - * - * @return - * TRUE if end-of-file has been reached. - * - * @see http://php.net/manual/en/streamwrapper.stream-eof.php - */ - public function stream_eof() { - return FALSE; - } - - /** - * Support for fseek(). - * - * @param $offset - * The byte offset to got to. - * @param $whence - * SEEK_SET, SEEK_CUR, or SEEK_END. - * - * @return - * TRUE on success. - * - * @see http://php.net/manual/en/streamwrapper.stream-seek.php - */ - public function stream_seek($offset, $whence) { - if (strlen($this->session_content) >= $offset) { - $this->stream_pointer = $offset; - return TRUE; - } - return FALSE; - } - - /** - * Support for fflush(). - * - * @return - * TRUE if data was successfully stored (or there was no data to store). - * This always returns TRUE, as this example provides and needs no - * flush support. - * - * @see http://php.net/manual/en/streamwrapper.stream-flush.php - */ - public function stream_flush() { - return TRUE; - } - - /** - * Support for ftell(). - * - * @return - * The current offset in bytes from the beginning of file. - * - * @see http://php.net/manual/en/streamwrapper.stream-tell.php - */ - public function stream_tell() { - return $this->stream_pointer; - } - - /** - * Support for fstat(). - * - * @return - * An array with file status, or FALSE in case of an error - see fstat() - * for a description of this array. - * - * @see http://php.net/manual/en/streamwrapper.stream-stat.php - */ - public function stream_stat() { - return array( - 'size' => drupal_strlen($this->session_content), - ); - } - - /** - * Support for fclose(). - * - * @return - * TRUE if stream was successfully closed. - * - * @see http://php.net/manual/en/streamwrapper.stream-close.php - */ - public function stream_close() { - $this->stream_pointer = 0; - unset($this->session_content); // Unassign the reference. - return TRUE; - } - - /** - * Support for unlink(). - * - * @param $uri - * A string containing the uri to the resource to delete. - * - * @return - * TRUE if resource was successfully deleted. - * - * @see http://php.net/manual/en/streamwrapper.unlink.php - */ - public function unlink($uri) { - $path = $this->getLocalPath($uri); - $path_components = preg_split('/\//', $path); - $fail = FALSE; - $unset = '$_SESSION[\'file_example\']'; - foreach ($path_components as $component) { - $unset .= '[\'' . $component . '\']'; - } - // TODO: Is there a better way to delete from an array? - // drupal_array_get_nested_value() doesn't work because it only returns - // a reference; unsetting a reference only unsets the reference. - eval("unset($unset);"); - return TRUE; - } - - /** - * Support for rename(). - * - * @param $from_uri, - * The uri to the file to rename. - * @param $to_uri - * The new uri for file. - * - * @return - * TRUE if file was successfully renamed. - * - * @see http://php.net/manual/en/streamwrapper.rename.php - */ - public function rename($from_uri, $to_uri) { - $from_key = &$this->uri_to_session_key($from_uri); - $to_key = &$this->uri_to_session_key($to_uri); - if (is_dir($to_key) || is_file($to_key)) { - return FALSE; - } - $to_key = $from_key; - unset($from_key); - return TRUE; - } - - /** - * Gets the name of the directory from a given path. - * - * @param $uri - * A URI. - * - * @return - * A string containing the directory name. - * - * @see drupal_dirname() - */ - public function dirname($uri = NULL) { - list($scheme, $target) = explode('://', $uri, 2); - $target = $this->getTarget($uri); - if (strpos($target, '/')) { - $dirname = preg_replace('@/[^/]*$@', '', $target); - } - else - { - $dirname = ''; - } - return $scheme . '://' . $dirname; - } - - /** - * Support for mkdir(). - * - * @param $uri - * A string containing the URI to the directory to create. - * @param $mode - * Permission flags - see mkdir(). - * @param $options - * A bit mask of STREAM_REPORT_ERRORS and STREAM_MKDIR_RECURSIVE. - * - * @return - * TRUE if directory was successfully created. - * - * @see http://php.net/manual/en/streamwrapper.mkdir.php - */ - public function mkdir($uri, $mode, $options) { - // If this already exists, then we can't mkdir. - if (is_dir($uri) || is_file($uri)) { - return FALSE; - } - - // Create the key in $_SESSION; - $this->uri_to_session_key($uri, TRUE); - - // Place a magic file inside it to differentiate this from an empty file. - $marker_uri = $uri . '/.isadir.txt'; - $this->uri_to_session_key($marker_uri, TRUE); - return TRUE; - } - - /** - * Support for rmdir(). - * - * @param $uri - * A string containing the URI to the directory to delete. - * @param $options - * A bit mask of STREAM_REPORT_ERRORS. - * - * @return - * TRUE if directory was successfully removed. - * - * @see http://php.net/manual/en/streamwrapper.rmdir.php - */ - public function rmdir($uri, $options) { - $path = $this->getLocalPath($uri); - $path_components = preg_split('/\//', $path); - $fail = FALSE; - $unset = '$_SESSION[\'file_example\']'; - foreach ($path_components as $component) { - $unset .= '[\'' . $component . '\']'; - } - // TODO: I really don't like this eval. - debug($unset, 'array element to be unset'); - eval("unset($unset);"); - - return TRUE; - } - - /** - * Support for stat(). - * This important function goes back to the Unix way of doing things. - * In this example almost the entire stat array is irrelevant, but the - * mode is very important. It tells PHP whether we have a file or a - * directory and what the permissions are. All that is packed up in a - * bitmask. This is not normal PHP fodder. - * - * @param $uri - * A string containing the URI to get information about. - * @param $flags - * A bit mask of STREAM_URL_STAT_LINK and STREAM_URL_STAT_QUIET. - * - * @return - * An array with file status, or FALSE in case of an error - see fstat() - * for a description of this array. - * - * @see http://php.net/manual/en/streamwrapper.url-stat.php - */ - public function url_stat($uri, $flags) { - - // PHP does not necessarily construct the object before all operations, - // so here we make sure that the startup work is done. - $this->__construct(); - - $key = $this->uri_to_session_key($uri, FALSE); - $return = FALSE; // Default to fail. - $mode = 0; - - // We will call an array a directory and the root is always an array. - if (is_array($key) && array_key_exists('.isadir.txt', $key)) { - $mode = 0040000; // S_IFDIR means it's a directory. - } - else if ($key !== FALSE) { - $mode = 0100000; // S_IFREG, means it's a file. - } - - if ($mode) { - $size = 0; - if ($mode == 0100000) { - $size = drupal_strlen($key); - } - - $mode |= 0777; // There are no protections on this, so all writable. - $return = array( - 'dev' => 0, - 'ino' => 0, - 'mode' => $mode, - 'nlink' => 0, - 'uid' => 0, - 'gid' => 0, - 'rdev' => 0, - 'size' => $size, - 'atime' => 0, - 'mtime' => 0, - 'ctime' => 0, - 'blksize' => 0, - 'blocks' => 0, - ); - } - return $return; - } - - /** - * Support for opendir(). - * - * @param $uri - * A string containing the URI to the directory to open. - * @param $options - * Unknown (parameter is not documented in PHP Manual). - * - * @return - * TRUE on success. - * - * @see http://php.net/manual/en/streamwrapper.dir-opendir.php - */ - public function dir_opendir($uri, $options) { - $var = &$this->uri_to_session_key($uri, FALSE); - if ($var === FALSE || !array_key_exists('.isadir.txt', $var)) { - return FALSE; - } - - // We grab the list of key names, flip it so that .isadir.txt can easily - // be removed, then flip it back so we can easily walk it as a list. - $this->directory_keys = array_flip(array_keys($var)); - unset($this->directory_keys['.isadir.txt']); - $this->directory_keys = array_keys($this->directory_keys); - $this->directory_pointer = 0; - return TRUE; - } - - /** - * Support for readdir(). - * - * @return - * The next filename, or FALSE if there are no more files in the directory. - * - * @see http://php.net/manual/en/streamwrapper.dir-readdir.php - */ - public function dir_readdir() { - if ($this->directory_pointer < count($this->directory_keys)) { - $next = $this->directory_keys[$this->directory_pointer]; - $this->directory_pointer++; - return $next; - } - return FALSE; - } - - /** - * Support for rewinddir(). - * - * @return - * TRUE on success. - * - * @see http://php.net/manual/en/streamwrapper.dir-rewinddir.php - */ - public function dir_rewinddir() { - $this->directory_pointer = 0; - } - - /** - * Support for closedir(). - * - * @return - * TRUE on success. - * - * @see http://php.net/manual/en/streamwrapper.dir-closedir.php - */ - public function dir_closedir() { - $this->directory_pointer = 0; - unset($this->directory_keys); - return TRUE; - } -} diff --git a/filter_example/filter_example.info b/filter_example/filter_example.info deleted file mode 100755 index 888ee7399112430f7bde4cd64bfa689da8ce2840..0000000000000000000000000000000000000000 --- a/filter_example/filter_example.info +++ /dev/null @@ -1,6 +0,0 @@ - -name = Filter example -description = An example module showing how to define a custom filter. -package = Example modules -core = 7.x -files[] = filter_example.test diff --git a/filter_example/filter_example.module b/filter_example/filter_example.module deleted file mode 100755 index bbf0296cfd2990fa7d6294f27124167d2a54b805..0000000000000000000000000000000000000000 --- a/filter_example/filter_example.module +++ /dev/null @@ -1,176 +0,0 @@ -, and - * replace it by the current time. - */ - -/** - * Implements hook_menu(). - */ -function filter_example_menu() { - $items['examples/filter_example'] = array( - 'title' => 'Filter Example', - 'page callback' => '_filter_example_information', - 'access callback' => TRUE, - ); - return $items; -} - -/** - * Implements hook_filter_info(). - * - * Here we define the diferent filters provided by the module. For this example, - * time_filter is a very static and simple replacement, but it requires some - * preparation of the string because of the special html tags < and >. The - * foo_filter is more complex, including its own settings and inline tips. - */ -function filter_example_filter_info() { - $filters['filter_foo'] = array( - 'title' => t('Foo filter'), - 'description' => t('Every instance of "foo" in the input text will be replaced with a preconfigured replacement.'), - 'process callback' => '_filter_example_filter_foo_process', - 'default settings' => array( - 'filter_example_foo' => 'bar', - ), - 'settings callback' => '_filter_example_filter_foo_settings', - 'tips callback' => '_filter_example_filter_foo_tips', - ); - $filters['filter_time'] = array( - 'title' => t('Time tag'), - 'description' => t('Every instance of the special <time /> tag will be replaced with the current date and time in the user\'s specified time zone.'), - 'prepare callback' => '_filter_example_filter_time_prepare', - 'process callback' => '_filter_example_filter_time_process', - 'tips callback' => '_filter_example_filter_time_tips', - ); - return $filters; -} - -/* - * Foo filter - * - * Drupal has several content formats (they are not filters), and in our example - * the foo replacement can be configured for each one of them, allowing an html - * or php replacement, so the module includes a settings callback, with options - * to configure that replacements. Also, a Tips callback will help showing the - * current replacement for the content type being edited. - */ - -/** - * Simply returns a little bit of information about the example. - */ -function _filter_example_information() { - return t( - "There are two filters in this example. The first (foo filter) just replaces - 'foo' with a configurable replacement. The second replaces the string - '' with the current time. To use these filters, go to !link and - configure one of the input formats.", - array('!link' => l("admin/config/content/formats", "admin/config/content/formats")) - ); -} - -/** - * Settings callback for foo filter - * - * Make use of $format to have different replacements for every input format. - * Since we allow the administrator to define the string that gets substituted - * when "foo" is encountered, we need to provide an interface for this kind of - * customization. The object format is also an argument of the callback. - * - * The settings defined in this form are stored in database by the filter module, - * and they will be available in the $filter argument - */ -function _filter_example_filter_foo_settings($form, $form_state, $filter, $format, $defaults) { - $settings['filter_example_foo'] = array( - '#type' => 'textfield', - '#title' => t('Substitution string'), - '#default_value' => isset($filter->settings['filter_example_foo']) ? $filter->settings['filter_example_foo'] : $defaults['filter_example_foo'], - '#description' => t('The string to substitute for "foo" everywhere in the text.') - ); - return $settings; -} - -/** - * Foo filter process callback - * - * The actual filtering is performed here. The supplied text should be returned, - * once any necessary substitutions have taken place. The example just replaces - * foo with our custom defined string in the settings page. - */ -function _filter_example_filter_foo_process($text, $filter, $format) { - $replacement = isset($filter->settings['filter_example_foo']) ? $filter->settings['filter_example_foo'] : 'bar'; - return str_replace('foo', $replacement, $text); -} - - -/** - * Filter tips callback for foo filter. - * - * The tips callback allows filters to provide help text to users during the content - * editing process. Short tips are provided on the content editing screen, while - * long tips are provided on a separate linked page. Short tips are optional, - * but long tips are highly recommended. - */ -function _filter_example_filter_foo_tips($filter, $format, $long = FALSE) { - $replacement = isset($filter->settings['filter_example_foo']) ? $filter->settings['filter_example_foo'] : 'bar'; - if (!$long) { - // This string will be shown in the content add/edit form - return t('foo replaced with %replacement.', array('%replacement' => $replacement)); - } - else { - return t('Every instance of "foo" in the input text will be replaced with a configurable value. You can configure this value and put whatever you want there. The replacement value is "%replacement".', array('%replacement' => $replacement)); - } -} - -/* - * Time filter. - * - * This filter is a little trickier to implement than the previous one. - * Since the input involves special HTML characters (< and >) we have to - * run the filter before HTML is escaped/stripped by other filters. But - * we want to use HTML in our result as well, and so if we run this filter - * first our replacement string could be escaped or stripped. The solution - * is to use the "prepare" operation to escape the special characters, and - * to later replace our escaped version in the "process" step. - */ - -/* - * Time filter prepare callback - * - * We'll use [filter-example-time] as a replacement for the time tag. - * Note that in a more complicated filter a closing tag may also be - * required. For more information, see "Temporary placeholders and - * delimiters" at http://drupal.org/node/209715. - */ -function _filter_example_filter_time_prepare($text, $filter) { - return preg_replace('!!', '[filter-example-time]', $text); -} - -/* - * Time filter process callback - * - * Now, in the "process" step, we'll search for our escaped time tags and - * to the real filtering: replace the xml tag with the date. - */ -function _filter_example_filter_time_process($text, $filter) { - return str_replace('[filter-example-time]', '' . format_date(time()) . '', $text); -} - - -/** - * Filter tips callback for time filter. - * - * The tips callback allows filters to provide help text to users during the content - * editing process. Short tips are provided on the content editing screen, while - * long tips are provided on a separate linked page. Short tips are optional, - * but long tips are highly recommended. - */ -function _filter_example_filter_time_tips($filter, $format, $long = FALSE) { - return t('<time /> is replaced with the current time.'); -} diff --git a/filter_example/filter_example.test b/filter_example/filter_example.test deleted file mode 100644 index 0768601b79e16134a7d58bfee34e3c33150bf9db..0000000000000000000000000000000000000000 --- a/filter_example/filter_example.test +++ /dev/null @@ -1,97 +0,0 @@ - 'Filter example functionality', - 'description' => 'Verify that content is processed by example filter.', - 'group' => 'Examples', - ); - } - - /** - * Enable modules and create user with specific permissions. - */ - function setUp() { - parent::setUp('filter_example'); - - // Load the used input formats. - $this->filtered_html = db_query_range('SELECT * FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'Filtered HTML'))->fetchObject(); - $this->full_html = db_query_range('SELECT * FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'Full HTML'))->fetchObject(); - - // Create user. - $this->web_user = $this->drupalCreateUser(array( - 'administer filters', - filter_permission_name($this->filtered_html), - filter_permission_name($this->full_html), - 'bypass node access', - )); - } - - /** - * Login user, create an example node, and test blog functionality through the admin and user interfaces. - */ - function testFilterExampleBasic() { - // Login the admin user. - $this->drupalLogin($this->web_user); - - // Enable both filters in format id 1 (default format) - $edit = array( - 'filters[filter_time][status]' => 1, - 'filters[filter_foo][status]' => 1, - ); - $this->drupalPost('admin/config/content/formats/' . $this->filtered_html->format, $edit, t('Save configuration')); - - // Create a content type to test the filters (with default format) - $content_type = $this->drupalCreateContentType(); - - // Create a test node - $langcode = LANGUAGE_NONE; - $edit = array( - "title" => $this->randomName(), - "body[$langcode][0][value]" => 'What foo is it? it is ', - ); - $result = $this->drupalPost('node/add/' . $content_type->type, $edit, t('Save')); - $this->assertResponse(200); - $time = format_date(time()); - $this->assertRaw('What bar is it? it is ' . $time . ''); - - // Enable foo filter in other format id 2 - $edit = array( - 'filters[filter_foo][status]' => 1, - ); - $this->drupalPost('admin/config/content/formats/' . $this->full_html->format, $edit, t('Save configuration')); - - // Change foo filter replacement with a random string in format id 2 - $replacement = $this->randomName(); - $options = array( - 'filters[filter_foo][settings][filter_example_foo]' => $replacement, - ); - $this->drupalPost('admin/config/content/formats/' . $this->full_html->format, $options, t('Save configuration')); - - // Create a test node with content format 2 - $langcode = LANGUAGE_NONE; - $edit = array( - "title" => $this->randomName(), - "body[$langcode][0][value]" => 'What foo is it? it is ', - "body[$langcode][0][format]" => $this->full_html->format, - ); - $result = $this->drupalPost('node/add/' . $content_type->type, $edit, t('Save')); - $this->assertResponse(200); - - // Only foo filter is enabled - $this->assertRaw("What " . $replacement . " is it", t('Foo filter successfully verified.')); - } -} diff --git a/form_example/form_example.info b/form_example/form_example.info deleted file mode 100644 index 875fdff1913d2a5e065b3f339bc6e957b7eaa6c2..0000000000000000000000000000000000000000 --- a/form_example/form_example.info +++ /dev/null @@ -1,6 +0,0 @@ - -name = Form example -description = Examples of using the Drupal Form API. -package = Example modules -core = 7.x -files[] = form_example.test diff --git a/form_example/form_example.module b/form_example/form_example.module deleted file mode 100644 index 46eeb504a6b6c4d7205b0771527d8ce3cc7dfa23..0000000000000000000000000000000000000000 --- a/form_example/form_example.module +++ /dev/null @@ -1,153 +0,0 @@ - 'Form Example', - 'page callback' => 'form_example_intro', - 'access callback' => TRUE, - 'expanded' => TRUE, - ); - $items['examples/form_example/tutorial'] = array( - 'title' => 'Form Tutorial', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_tutorial_1'), - 'access callback' => TRUE, - 'description' => 'A set of ten tutorials', - 'file' => 'form_example_tutorial.inc', - 'type' => MENU_NORMAL_ITEM, - ); - $items['examples/form_example/tutorial/1'] = array( - 'title' => '#1', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_tutorial_1'), - 'access callback' => TRUE, - 'description' => 'Tutorial 1: Simplest form', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'file' => 'form_example_tutorial.inc', - ); - $items['examples/form_example/tutorial/2'] = array( - 'title' => '#2', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_tutorial_2'), - 'access callback' => TRUE, - 'description' => 'Tutorial 2: Form with a submit button', - 'type' => MENU_LOCAL_TASK, - 'file' => 'form_example_tutorial.inc', - ); - $items['examples/form_example/tutorial/3'] = array( - 'title' => '#3', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_tutorial_3'), - 'access callback' => TRUE, - 'description' => 'Tutorial 3: Fieldsets', - 'type' => MENU_LOCAL_TASK, - 'file' => 'form_example_tutorial.inc', - ); - $items['examples/form_example/tutorial/4'] = array( - 'title' => '#4', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_tutorial_4'), - 'access callback' => TRUE, - 'description' => 'Tutorial 4: Required fields', - 'type' => MENU_LOCAL_TASK, - 'file' => 'form_example_tutorial.inc', - ); - $items['examples/form_example/tutorial/5'] = array( - 'title' => '#5', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_tutorial_5'), - 'access callback' => TRUE, - 'description' => 'Tutorial 5: More element attributes', - 'type' => MENU_LOCAL_TASK, - 'file' => 'form_example_tutorial.inc', - ); - $items['examples/form_example/tutorial/6'] = array( - 'title' => '#6', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_tutorial_6'), - 'access callback' => TRUE, - 'description' => 'Tutorial 6: Form with a validate handler', - 'type' => MENU_LOCAL_TASK, - 'file' => 'form_example_tutorial.inc', - ); - $items['examples/form_example/tutorial/7'] = array( - 'title' => '#7', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_tutorial_7'), - 'access callback' => TRUE, - 'description' => 'Tutorial 7: Form with a submit handler', - 'type' => MENU_LOCAL_TASK, - 'file' => 'form_example_tutorial.inc', - ); - $items['examples/form_example/tutorial/8'] = array( - 'title' => '#8', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_tutorial_8'), - 'access callback' => TRUE, - 'description' => 'Tutorial 8: Basic multistep form', - 'type' => MENU_LOCAL_TASK, - 'file' => 'form_example_tutorial.inc', - ); - $items['examples/form_example/tutorial/9'] = array( - 'title' => '#9', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_tutorial_9'), - 'access callback' => TRUE, - 'description' => 'Tutorial 9: Form with dynamically added new fields', - 'type' => MENU_LOCAL_TASK, - 'file' => 'form_example_tutorial.inc', - 'weight' => 9, - ); - $items['examples/form_example/tutorial/10'] = array( - 'title' => '#10', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_tutorial_10'), - 'access callback' => TRUE, - 'description' => t('Tutorial 11: Form with file upload'), - 'type' => MENU_LOCAL_TASK, - 'file' => 'form_example_tutorial.inc', - 'weight' => 10, - ); - $items['examples/form_example/states'] = array( - 'title' => '#states example', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_states_form'), - 'access callback' => TRUE, - 'description' => 'How to use the #states attribute in FAPI', - 'file' => 'form_example_states.inc', - ); - $items['examples/form_example/wizard'] = array( - 'title' => 'Extensible wizard example', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_example_wizard'), - 'access callback' => TRUE, - 'description' => 'A general approach to a wizard multistep form.', - 'file' => 'form_example_wizard.inc', - ); - return $items; -} - -function form_example_intro() { - $markup = t('The form example module provides a tutorial, extensible multistep example, and a #states example'); - return array('#markup' => $markup); -} \ No newline at end of file diff --git a/form_example/form_example.test b/form_example/form_example.test deleted file mode 100644 index cf300b2578e9836c13b38720772e80806a1aa316..0000000000000000000000000000000000000000 --- a/form_example/form_example.test +++ /dev/null @@ -1,176 +0,0 @@ - 'Form Example tests', - 'description' => 'Various tests on the form example module.' , - 'group' => 'Examples', - ); - } - - function setUp() { - parent::setUp('form_example'); - } - - /** - * Test each tutorial - */ - function testTutorials() { - // Tutorial #1 - $this->drupalGet('examples/form_example/tutorial'); - $this->assertText(t('#9')); - - // #2 - $this->drupalPost('examples/form_example/tutorial/2', array('name' => t('name')), t('Submit')); - - // #4 - $this->drupalPost('examples/form_example/tutorial/4', - array('first' => t('firstname'), 'last' => t('lastname')), t('Submit')); - $this->drupalPost('examples/form_example/tutorial/4', array(), t('Submit')); - $this->assertText(t('First name field is required')); - $this->assertText(t('Last name field is required')); - - // #5 - $this->drupalPost('examples/form_example/tutorial/5', - array('first' => t('firstname'), 'last' => t('lastname')), t('Submit')); - $this->assertText(t('Please enter your first name')); - $this->drupalPost('examples/form_example/tutorial/4', array(), t('Submit')); - $this->assertText(t('First name field is required')); - $this->assertText(t('Last name field is required')); - - // #6 - $this->drupalPost('examples/form_example/tutorial/6', - array('first' => t('firstname'), 'last' => t('lastname'), 'year_of_birth' => 1955), - t('Submit')); - $this->assertNoText(t('Enter a year between 1900 and 2000')); - $this->drupalPost('examples/form_example/tutorial/6', - array('first' => t('firstname'), 'last' => t('lastname'), 'year_of_birth' => 1855), - t('Submit')); - - $this->assertText(t('Enter a year between 1900 and 2000')); - - // #7 - $this->drupalPost('examples/form_example/tutorial/7', - array('first' => t('firstname'), 'last' => t('lastname'), 'year_of_birth' => 1955), - t('Submit')); - $this->assertText(t('The form has been submitted. name="firstname lastname", year of birth=1955')); - $this->drupalPost('examples/form_example/tutorial/7', - array('first' => t('firstname'), 'last' => t('lastname'), 'year_of_birth' => 1855), - t('Submit')); - - $this->assertText(t('Enter a year between 1900 and 2000')); - - // #8 - $this->drupalPost('examples/form_example/tutorial/8', - array('first' => t('firstname'), 'last' => t('lastname'), 'year_of_birth' => 1955), - t('Next >>')); - - $this->drupalPost(NULL, array('color' => t('green')), t('<< Back')); - $this->drupalPost(NULL, array(), t('Next >>')); - $this->drupalPost(NULL, array('color' => t('red')), t('Submit')); - $this->assertText(t('The form has been submitted. name="firstname lastname", year of birth=1955')); - $this->assertText(t('And the favorite color is red')); - - // #9 - $url = 'examples/form_example/tutorial/9'; - for ($i = 1; $i <= 4; $i++) { - if ($i > 1) { - $url = NULL; // later steps of multistep form take NULL. - } - $this->drupalPost($url, - array("name[$i][first]" => "firstname $i", "name[$i][last]" => "lastname $i", "name[$i][year_of_birth]" => 1950 + $i), - t('Add another name')); - $this->assertText(t('Name #@num', array('@num' => $i + 1))); - } - - // Now remove the last name added (#5). - $this->drupalPost(NULL, array(), t('Remove latest name')); - $this->assertNoText("Name #5"); - - $this->drupalPost(NULL, array(), t('Submit')); - - $this->assertText('Form 9 has been submitted'); - for ($i = 1; $i <= 4; $i++) { - $this->assertText(t('@num: firstname @num lastname @num (@year)', array('@num' => $i, '@year' => 1950 + $i))); - } - - // #10 - $url = 'examples/form_example/tutorial/10'; - - $this->drupalPost($url, array(), t('Submit')); - $this->assertText(t('No file was uploaded.')); - - // Get sample images. - $images = $this->drupalGetTestFiles('image'); - foreach ($images as $image) { - $this->drupalPost($url, array('files[file]' => drupal_realpath($image->uri)), t('Submit')); - $this->assertText(t('The form has been submitted and the image has been saved, filename: @filename.', array('@filename' => $image->filename))); - } - } - - /** - * Test Wizard tutorial - * @TODO improve this using drupal_form_submit - */ - function testWizard() { - // Is the wizard there - $this->drupalGet('examples/form_example/wizard'); - $this->assertText(t('Extensible wizard example')); - - $first_name = $this->randomName(8); - $last_name = $this->randomName(8); - $city = $this->randomName(8); - $aunts_name = $this->randomName(8); - - // Submit the first step of the wizard - $options = array( - 'first_name' => $first_name, - 'last_name' => $last_name, - ); - $this->drupalPost('examples/form_example/wizard', $options, t('Next')); - - // A label city is created, and two buttons appear, Preivous and Next - $this->assertText(t('Hint: Do not enter "San Francisco", and do not leave this out.')); - - // Go back to the beginning and verify that the value is there. - $this->drupalPost(NULL, array(), t('Previous')); - $this->assertFieldByName('first_name', $first_name); - $this->assertFieldByName('last_name', $last_name); - - // Go next. We should keep our values. - $this->drupalPost(NULL, array(), t('Next')); - $this->assertText(t('Hint: Do not enter "San Francisco", and do not leave this out.')); - - // Try "San Francisco". - $this->drupalPost(NULL, array('city' => 'San Francisco'), t('Next')); - $this->assertText(t('You were warned not to enter "San Francisco"')); - - // Try the real city. - $this->drupalPost(NULL, array('city' => $city), t('Next')); - - // Enter the Aunt's name, but then the previous button. - $this->drupalPost(NULL, array('aunts_name'=> $aunts_name), t('Previous')); - $this->assertFieldByName('city', $city); - - // Now go forward and then press finish; check for correct values. - $this->drupalPost(NULL, array(), t('Next')); - $this->drupalPost(NULL, array('aunts_name' => $aunts_name), t('Finish')); - - $this->assertRaw(t('[first_name] => @first_name', array('@first_name' => $first_name))); - $this->assertRaw(t('[last_name] => @last_name', array('@last_name' => $last_name))); - $this->assertRaw(t('[city] => @city', array('@city' => $city))); - $this->assertRaw(t('[aunts_name] => @aunts_name', array('@aunts_name' => $aunts_name))); - } - -} - diff --git a/form_example/form_example_states.inc b/form_example/form_example_states.inc deleted file mode 100644 index 12ee571a0fced614e2df0e66b44000b2d1e0c9af..0000000000000000000000000000000000000000 --- a/form_example/form_example_states.inc +++ /dev/null @@ -1,266 +0,0 @@ - array( - * 'visible' => array( - * ':input[name="student_type"]' => array('value' => t('High School')), - * ), - * ), - * @endcode - * Meaning that the element is to be made visible when the condition is met. - * The condition is a combination of a jQuery selector (which selects the - * element we want to test) and a condition for that element. In this case, - * the condition is whether the value of the 'student_type' element is - * 'High School'. If it is, this element will be visible. - * - * So the syntax is: - * @code - * '#states' => array( - * 'action_to_take_on_this_form_element' => array( - * 'jquery_selector_for_another_element' => array('condition_type' => value), - * ), - * ), - * @endcode - * - * If you need an action to take place only when two different conditions are - * true, then you add both of those conditions to the action. See the - * 'country_writein' element below for an example. - * - * Note that the easiest way to select a textfield, checkbox, or select is - * with the @link http://api.jquery.com/input-selector/ ':input' jquery shortcut @endlink, - * which selects any any of those. - * - * There are examples below of changing or hiding an element when a checkbox - * is checked, when a textarea is filled, when a select has a given value. - * - * See drupal_process_states() for full documentation. - * - * See also @link http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7#states Form API Reference @endlink - */ -function form_example_states_form($form, &$form_state) { - $form['student_type'] = array( - '#type' => 'radios', - '#options' => drupal_map_assoc(array(t('High School'), t('Undergraduate'), t('Graduate'))), - '#title' => t('What type of student are you?') - ); - $form['high_school'] = array( - '#type' => 'fieldset', - '#title' => t('High School Information'), - // This #states rule says that the "high school" fieldset should only - // be shown if the "student_type" form element is set to "High School". - '#states' => array( - 'visible' => array( - ':input[name="student_type"]' => array('value' => t('High School')), - ), - ), - ); - - // High school information. - $form['high_school']['tests_taken'] = array( - '#type' => 'checkboxes', - '#options' => drupal_map_assoc(array(t('SAT'), t('ACT'))), - '#title' => t('What standardized tests did you take?'), - // This #states rule says that this checkboxes array will be visible only - // when $form['student_type'] is set to t('High School'). - // It uses the jQuery selector :input[name=student_type] to choose the - // element which triggers the behavior, and then defines the "High School" - // value as the one that triggers visibility. - '#states' => array( - 'visible' => array( // action to take. - ':input[name="student_type"]' => array('value' => t('High School')), - ), - ), - ); - - $form['high_school']['sat_score'] = array( - '#type' => 'textfield', - '#title' => t('Your SAT score:'), - '#size' => 4, - - // This #states rule limits visibility to when the $form['tests_taken'] - // 'SAT' checkbox is checked." - '#states' => array( - 'visible' => array( // action to take. - ':input[name="tests_taken[SAT]"]' => array('checked' => TRUE), - ), - ), - ); - $form['high_school']['act_score'] = array( - '#type' => 'textfield', - '#title' => t('Your ACT score:'), - '#size' => 4, - - // Set this element visible if the ACT checkbox above is checked. - '#states' => array( - 'visible' => array( // action to take. - ':input[name="tests_taken[ACT]"]' => array('checked' => TRUE), - ), - ), - ); - - // Undergrad information. - $form['undergraduate'] = array( - '#type' => 'fieldset', - '#title' => t('Undergraduate Information'), - // This #states rule says that the "undergraduate" fieldset should only - // be shown if the "student_type" form element is set to "Undergraduate". - '#states' => array( - 'visible' => array( - ':input[name="student_type"]' => array('value' => t('Undergraduate')), - ), - ), - ); - - $form['undergraduate']['how_many_years'] = array( - '#type' => 'select', - '#title' => t('How many years have you completed?'), - // The options here are integers, but since all the action here happens - // using the DOM on the client, we will have to use strings to work with - // them. - '#options' => array( - 1 => t('One'), - 2 => t('Two'), - 3 => t('Three'), - 4 => t('Four'), - 5 => t('Lots'), - ), - ); - - $form['undergraduate']['comment'] = array( - '#type' => 'item', - '#description' => t("Wow, that's a long time."), - '#states' => array( - 'visible' => array( - // Note that '5' must be used here instead of the integer 5. - // The information is coming from the DOM as a string. - ':input[name="how_many_years"]' => array('value' => '5'), - ), - ), - ); - $form['undergraduate']['school_name'] = array( - '#type' => 'textfield', - '#title' => t('Your college or university:'), - ); - $form['undergraduate']['school_country'] = array( - '#type' => 'select', - '#options' => drupal_map_assoc(array(t('UK'), t('Other'))), - '#title' => t('In what country is your college or university located?'), - ); - $form['undergraduate']['country_writein'] = array( - '#type' => 'textfield', - '#size' => 20, - '#title' => t('Please enter the name of the country where your college or university is located.'), - - // Only show this field if school_country is set to 'Other'. - '#states' => array( - 'visible' => array( // Action to take: Make visible. - ':input[name="school_country"]' => array('value' => t('Other')), - ), - ), - ); - - $form['undergraduate']['thanks'] = array( - '#type' => 'item', - '#description' => t('Thanks for providing both your school and your country.'), - '#states' => array( - // Here visibility requires that two separate conditions be true. - 'visible' => array( - 'input[name="school_country"]' => array('value' => t('Other')), - 'input[name="country_writein"]' => array('filled' => TRUE), - ), - ), - ); - $form['undergraduate']['go_away'] = array( - '#type' => 'submit', - '#value' => t('Done with form'), - '#states' => array( - // Here visibility requires that two separate conditions be true. - 'visible' => array( - 'input[name="school_country"]' => array('value' => t('Other')), - 'input[name="country_writein"]' => array('filled' => TRUE), - ), - ), - ); - - // Graduate student information. - $form['graduate'] = array( - '#type' => 'fieldset', - '#title' => t('Graduate School Information'), - // This #states rule says that the "graduate" fieldset should only - // be shown if the "student_type" form element is set to "Graduate". - '#states' => array( - 'visible' => array( - ':input[name="student_type"]' => array('value' => t('Graduate')), - ), - ), - ); - $form['graduate']['more_info'] = array( - '#type' => 'textarea', - '#title' => t('Please describe your graduate studies'), - ); - - $form['graduate']['info_provide'] = array( - '#type' => 'checkbox', - '#title' => t('Check here if you have provided information above'), - '#disabled' => TRUE, - '#states' => array( - // Mark this checkbox checked if the "more_info" textarea has something - // in it, if it's 'filled'. - 'checked' => array( // Action to take: check the checkbox. - ':input[name="more_info"]' => array('filled' => TRUE), - ), - ), - ); - - $form['expand_more_info'] = array( - '#type' => 'checkbox', - '#title' => t('Check here if you want to add more information.'), - ); - $form['more_info'] = array( - '#type' => 'fieldset', - '#title' => t('Additional Information'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - - // Expand the expand_more_info fieldset if the box is checked. - '#states' => array( - 'expanded' => array( - ':input[name="expand_more_info"]' => array('checked' => TRUE), - ), - ), - ); - $form['more_info']['feedback'] = array( - '#type' => 'textarea', - '#title' => t('What do you have to say?'), - ); - - $form['submit'] = array( - '#type' => 'submit', - '#value' => t('Submit your information'), - ); - - return $form; -} - - -function form_example_states_form_submit($form, &$form_state) { - drupal_set_message(t('Submitting values: @values', array('@values' => var_export($form_state['values'], TRUE)))); -} diff --git a/form_example/form_example_tutorial.inc b/form_example/form_example_tutorial.inc deleted file mode 100644 index a34b95f00a1fa41525ebd141042fee9fed719601..0000000000000000000000000000000000000000 --- a/form_example/form_example_tutorial.inc +++ /dev/null @@ -1,756 +0,0 @@ -Drupal handbook.'); -} - -//////////////// Tutorial Example 1 ////////////////////// -/** - * This first form function is from the @link http://drupal.org/node/717722 Form Tutorial handbook page @endlink - * - * It just creates a very basic form with a textfield. - * - * This function is called the "form constructor function". It builds the form. - * It takes a two arguments, $form and $form_state, but if drupal_get_form() - * sends additional arguments, they will be provided after $form_state. - * - * @ingroup form_example - */ -function form_example_tutorial_1($form, &$form_state) { - - $form['description'] = array( - '#type' => 'item', - '#title' => t('A form with nothing but a textfield'), - ); - // This is the first form element. It's a textfield with a label, "Name" - $form['name'] = array( - '#type' => 'textfield', - '#title' => t('Name'), - ); - return $form; -} - - -//////////////// Tutorial Example 2 ////////////////////// - -/** - * This is Example 2, a basic form with a submit button. - * - * @see http://drupal.org/node/717726 - * @ingroup form_example - */ -function form_example_tutorial_2($form, &$form_state) { - $form['description'] = array( - '#type' => 'item', - '#title' => t('A simple form with a submit button'), - ); - - $form['name'] = array( - '#type' => 'textfield', - '#title' => t('Name'), - ); - - // Adds a simple submit button that refreshes the form and clears its contents -- this is the default behavior for forms. - $form['submit'] = array( - '#type' => 'submit', - '#value' => 'Submit', - ); - return $form; -} - -//////////////// Tutorial Example 3 ////////////////////// - -/** - * Example 3: A basic form with fieldsets. - * - * We establish a fieldset element and then place two text fields within - * it, one for a first name and one for a last name. This helps us group - * related content. - * - * Study the code below and you'll notice that we renamed the array of the first - * and last name fields by placing them under the $form['name'] - * array. This tells Form API these fields belong to the $form['name'] fieldset. - * - * @ingroup form_example - */ -function form_example_tutorial_3($form, &$form_state) { - $form['description'] = array( - '#type' => 'item', - '#title' => t('A form with a fieldset'), - ); - - $form['name'] = array( - '#type' => 'fieldset', - '#title' => t('Name'), - ); - $form['name']['first'] = array( - '#type' => 'textfield', - '#title' => t('First name'), - ); - $form['name']['last'] = array( - '#type' => 'textfield', - '#title' => t('Last name'), - ); - - - $form['submit'] = array( - '#type' => 'submit', - '#value' => 'Submit', - ); - return $form; -} - - -//////////////// Tutorial Example 4 ////////////////////// - -/** - * Example 4: Basic form with required fields. - * - * @ingroup form_example - */ -function form_example_tutorial_4($form, &$form_state) { - $form['description'] = array( - '#type' => 'item', - '#title' => t('A form with validation'), - ); - - $form['name'] = array( - '#type' => 'fieldset', - '#title' => t('Name'), - // Make the fieldset collapsible. - '#collapsible' => TRUE, // Added - '#collapsed' => FALSE, // Added - ); - - // Make these fields required. - $form['name']['first'] = array( - '#type' => 'textfield', - '#title' => t('First name'), - '#required' => TRUE, // Added - ); - $form['name']['last'] = array( - '#type' => 'textfield', - '#title' => t('Last name'), - '#required' => TRUE, // Added - ); - - $form['submit'] = array( - '#type' => 'submit', - '#value' => 'Submit', - ); - return $form; -} - - -//////////////// Tutorial Example 5 ////////////////////// - -/** - * Example 5: Basic form with additional element attributes. - * - * This demonstrates additional attributes of text form fields. - * - * For a more extensive example on element types - * @see http://drupal.org/node/751826 - * - * See the @link http://api.drupal.org/api/file/developer/topics/forms_api.html complete form reference @endlink - * - * @ingroup form_example - */ -function form_example_tutorial_5($form, &$form_state) { - $form['description'] = array( - '#type' => 'item', - '#title' => t('A form with additional attributes'), - '#description' => t('This one adds #default_value and #description'), - ); - $form['name'] = array( - '#type' => 'fieldset', - '#title' => t('Name'), - '#collapsible' => TRUE, - '#collapsed' => FALSE, - ); - - $form['name']['first'] = array( - '#type' => 'textfield', - '#title' => t('First name'), - '#required' => TRUE, - '#default_value' => "First name", // added default value. - '#description' => "Please enter your first name.", // added description - '#size' => 20, // added - '#maxlength' => 20, // added - ); - $form['name']['last'] = array( - '#type' => 'textfield', - '#title' => t('Last name'), - '#required' => TRUE, - ); - $form['submit'] = array( - '#type' => 'submit', - '#value' => 'Submit', - ); - return $form; -} - - -//////////////// Tutorial Example 6 ////////////////////// - -/** - * Example 6: A basic form with a validate handler. - * - * From http://drupal.org/node/717736 - * @see form_example_tutorial_6_validate() - * - */ -function form_example_tutorial_6($form, &$form_state) { - $form['description'] = array( - '#type' => 'item', - '#title' => t('A form with a validation handler'), - ); - - $form['name'] = array( - '#type' => 'fieldset', - '#title' => t('Name'), - '#collapsible' => TRUE, - '#collapsed' => FALSE, - ); - $form['name']['first'] = array( - '#type' => 'textfield', - '#title' => t('First name'), - '#required' => TRUE, - '#default_value' => "First name", - '#description' => "Please enter your first name.", - '#size' => 20, - '#maxlength' => 20, - ); - $form['name']['last'] = array( - '#type' => 'textfield', - '#title' => t('Last name'), - '#required' => TRUE, - ); - - // New form field added to permit entry of year of birth. - // The data entered into this field will be validated with - // the default validation function. - $form['year_of_birth'] = array( - '#type' => 'textfield', - '#title' => "Year of birth", - '#description' => 'Format is "YYYY"', - ); - - $form['submit'] = array( - '#type' => 'submit', - '#value' => 'Submit', - ); - return $form; -} - - - -/** - * Now we add a handler/function to validate the data entered into the - * "year of birth" field to make sure it's between the values of 1900 - * and 2000. If not, it displays an error. The value report is - * $form_state['values'] (see http://drupal.org/node/144132#form-state). - * - * Notice the name of the function. It is simply the name of the form - * followed by '_validate'. This is always the name of the default validation - * function. An alternate list of validation functions could have been provided - * in $form['#validate']. - * - * @see form_example_tutorial_6() - * - */ -function form_example_tutorial_6_validate($form, &$form_state) { - $year_of_birth = $form_state['values']['year_of_birth']; - if ($year_of_birth && ($year_of_birth < 1900 || $year_of_birth > 2000)) { - form_set_error('year_of_birth', t('Enter a year between 1900 and 2000.')); - } -} - - - -//////////////// Tutorial Example 7 ////////////////////// - -/** - * Example 7: With a submit handler. - * - * From the handbook page: - * http://drupal.org/node/717740 - * - * @see form_example_tutorial_7_validate() - * @see form_example_tutorial_7_submit() - * @ingroup form_example - * - */ -function form_example_tutorial_7($form, &$form_state) { - $form['description'] = array( - '#type' => 'item', - '#title' => t('A form with a submit handler'), - ); - $form['name'] = array( - '#type' => 'fieldset', - '#title' => t('Name'), - '#collapsible' => TRUE, - '#collapsed' => FALSE, - ); - $form['name']['first'] = array( - '#type' => 'textfield', - '#title' => t('First name'), - '#required' => TRUE, - '#default_value' => "First name", - '#description' => "Please enter your first name.", - '#size' => 20, - '#maxlength' => 20, - ); - $form['name']['last'] = array( - '#type' => 'textfield', - '#title' => t('Last name'), - '#required' => TRUE, - ); - $form['year_of_birth'] = array( - '#type' => 'textfield', - '#title' => "Year of birth", - '#description' => 'Format is "YYYY"', - ); - $form['submit'] = array( - '#type' => 'submit', - '#value' => 'Submit', - ); - return $form; -} - - -/** - * Validation function for form_example_tutorial_7(). - * - */ -function form_example_tutorial_7_validate($form, &$form_state) { - $year_of_birth = $form_state['values']['year_of_birth']; - if ($year_of_birth && ($year_of_birth < 1900 || $year_of_birth > 2000)) { - form_set_error('year_of_birth', t('Enter a year between 1900 and 2000.')); - } -} - -/** - * Submit function for form_example_tutorial_7(). - * - * Adds a submit handler/function to our form to send a successful - * completion message to the screen. - */ -function form_example_tutorial_7_submit($form, &$form_state) { - drupal_set_message(t('The form has been submitted. name="@first @last", year of birth=@year_of_birth', - array('@first' => $form_state['values']['first'], '@last' => $form_state['values']['last'], '@year_of_birth' => $form_state['values']['year_of_birth']))); -} - - -//////////////// Tutorial Example 8 ////////////////////// - -/** - * Example 8: A simple multistep form with a Next and a Back button. - * - * Handbook page: http://drupal.org/node/717750. - * - * For more extensive multistep forms, see - * @link form_example_wizard.inc form_example_wizard.inc @endlink - * - * - * Adds logic to our form builder to give it two pages. - * The @link ajax_example_wizard AJAX Example's Wizard Example @endlink - * gives an AJAX version of this same idea. - * - * @see form_example_tutorial_8_submit() - * @see form_example_tutorial_8_validate() - * @see form_example_tutorial_8_page_two() - * @see form_example_tutorial_8_page_two_submit() - * @see form_example_tutorial_8_next_submit() - * @see form_example_tutorial.inc - * @ingroup form_example - */ -function form_example_tutorial_8($form, &$form_state) { - - // Display page 2 if $form_state['page_num'] == 1 - if (!empty($form_state['page_num']) && $form_state['page_num'] == 2) { - return form_example_tutorial_8_page_two($form, $form_state); - } - - // Otherwise we build page 1. - $form_state['page_num'] = 1; - - $form['description'] = array( - '#type' => 'item', - '#title' => t('A basic multistep form (page 1)'), - ); - - $form['first'] = array( - '#type' => 'textfield', - '#title' => t('First name'), - '#description' => "Please enter your first name.", - '#size' => 20, - '#maxlength' => 20, - '#required' => TRUE, - '#default_value' => !empty($form_state['values']['first']) ? $form_state['values']['first'] : '', - ); - $form['last'] = array( - '#type' => 'textfield', - '#title' => t('Last name'), - '#default_value' => !empty($form_state['values']['last']) ? $form_state['values']['last'] : '', - ); - $form['year_of_birth'] = array( - '#type' => 'textfield', - '#title' => "Year of birth", - '#description' => 'Format is "YYYY"', - '#default_value' => !empty($form_state['values']['year_of_birth']) ? $form_state['values']['year_of_birth'] : '', - ); - $form['next'] = array( - '#type' => 'submit', - '#value' => 'Next >>', - '#submit' => array('form_example_tutorial_8_next_submit'), - '#validate' => array('form_example_tutorial_8_next_validate'), - ); - return $form; -} - -/** - * Returns the form for the second page of form_example_tutorial_8(). - */ -function form_example_tutorial_8_page_two($form, &$form_state) { - $form['description'] = array( - '#type' => 'item', - '#title' => t('A basic multistep form (page 2)'), - ); - - $form['color'] = array( - '#type' => 'textfield', - '#title' => t('Favorite color'), - '#required' => TRUE, - '#default_value' => !empty($form_state['values']['color']) ? $form_state['values']['color'] : '', - ); - $form['submit'] = array( - '#type' => 'submit', - '#value' => t('Submit'), - '#submit' => array('form_example_tutorial_8_page_two_submit'), - ); - $form['back'] = array( - '#type' => 'submit', - '#value' => t('<< Back'), - '#submit' => array('form_example_tutorial_8_page_two_back'), - // We won't bother validating the required 'color' field, since they - // have to come back to this page to submit anyway. - '#limit_validation_errors' => array(), - ); - return $form; -} - - -/** - * Validate handler for the next button on first page. - * - */ -function form_example_tutorial_8_next_validate($form, &$form_state) { - $year_of_birth = $form_state['values']['year_of_birth']; - if ($year_of_birth && ($year_of_birth < 1900 || $year_of_birth > 2000)) { - form_set_error('year_of_birth', t('Enter a year between 1900 and 2000.')); - } -} - -/** - * Submit handler for form_example_tutorial_8() next button. - * - * Capture the values from page one and store them away so they can be used - * at final submit time. - * - */ -function form_example_tutorial_8_next_submit($form, &$form_state) { - - // Values are saved for each page. - // to carry forward to subsequent pages in the form. - // and we tell FAPI to rebuild the form. - $form_state['page_values'][1] = $form_state['values']; - - if (!empty($form_state['page_values'][2])) { - $form_state['values'] = $form_state['page_values'][2]; - } - - // When form rebuilds, it will look at this to figure which page to build. - $form_state['page_num'] = 2; - $form_state['rebuild'] = TRUE; -} - -/** - * Back button handler submit handler. - * - * Since #limit_validation_errors = array() is set, values from page 2 - * will be discarded. We load the page 1 values instead. - */ -function form_example_tutorial_8_page_two_back($form, &$form_state) { - $form_state['values'] = $form_state['page_values'][1]; - $form_state['page_num'] = 1; - $form_state['rebuild'] = TRUE; -} - -/** - * The page 2 submit handler. - * - * This is the final submit handler. Gather all the data together and output - * it in a drupal_set_message(). - */ -function form_example_tutorial_8_page_two_submit($form, &$form_state) { - // Normally, some code would go here to alter the database with the data - // collected from the form. Instead sets a message with drupal_set_message() - // to validate that the code worked. - $page_one_values = $form_state['page_values'][1]; - drupal_set_message(t('The form has been submitted. name="@first @last", year of birth=@year_of_birth', - array('@first' => $page_one_values['first'], '@last' => $page_one_values['last'], '@year_of_birth' => $page_one_values['year_of_birth']))); - - if (!empty($page_one_values['first2'])) { - drupal_set_message(t('Second name: name="@first @last", year of birth=@year_of_birth', - array('@first' => $page_one_values['first2'], '@last' => $page_one_values['last2'], '@year_of_birth' => $page_one_values['year_of_birth2']))); - } - drupal_set_message(t('And the favorite color is @color', array('@color' => $form_state['values']['color']))); - - // If we wanted to redirect on submission, set $form_state['redirect'] - // $form_state['redirect'] = 'node'; // Redirects the user to /node. -} - -//////////////// Tutorial Example 9 ////////////////////// - -/** - * Example 9: A form with a dynamically added new fields. - * - * This example adds default values so that when the form is rebuilt, - * the form will by default have the previously-entered values. - * - * From handbook page http://drupal.org/node/717746. - * - * @see form_example_tutorial_9_add_name() - * @see form_example_tutorial_9_remove_name() - * @see form_example_tutorial_9_submit() - * @see form_example_tutorial_9_validate() - * @ingroup form_example - * - */ -function form_example_tutorial_9($form, &$form_state) { - - // We will have many fields with the same name, so we need to be able to - // access the form hierarchically. - $form['#tree'] = TRUE; - - $form['description'] = array( - '#type' => 'item', - '#title' => t('A form with dynamically added new fields'), - ); - - if (empty($form_state['num_names'])) { - $form_state['num_names'] = 1; - } - - // Build the number of name fieldsets indicated by $form_state['num_names'] - for ($i = 1; $i <= $form_state['num_names']; $i++) { - $form['name'][$i] = array( - '#type' => 'fieldset', - '#title' => t('Name #@num', array('@num' => $i)), - '#collapsible' => TRUE, - '#collapsed' => FALSE, - ); - - $form['name'][$i]['first'] = array( - '#type' => 'textfield', - '#title' => t('First name'), - '#description' => t("Enter first name."), - '#size' => 20, - '#maxlength' => 20, - '#required' => TRUE, - ); - $form['name'][$i]['last'] = array( - '#type' => 'textfield', - '#title' => t('Enter Last name'), - '#required' => TRUE, - ); - $form['name'][$i]['year_of_birth'] = array( - '#type' => 'textfield', - '#title' => t("Year of birth"), - '#description' => t('Format is "YYYY"'), - ); - } - $form['submit'] = array( - '#type' => 'submit', - '#value' => 'Submit', - ); - - // Adds "Add another name" button - $form['add_name'] = array( - '#type' => 'submit', - '#value' => t('Add another name'), - '#submit' => array('form_example_tutorial_9_add_name'), - ); - - // If we have more than one name, this button allows removal of the - // last name. - if ($form_state['num_names'] > 1) { - $form['remove_name'] = array( - '#type' => 'submit', - '#value' => t('Remove latest name'), - '#submit' => array('form_example_tutorial_9_remove_name'), - // Since we are removing a name, don't validate until later. - '#limit_validation_errors' => array(), - ); - } - - return $form; -} - -/** - * Submit handler for "Add another name" button on form_example_tutorial_9(). - * - * $form_state['num_names'] tells the form builder function how many name - * fieldsets to build, so here we increment it. - * - * All elements of $form_state are persisted, so there's no need to use a - * particular key, like the old $form_state['storage']. We can just use - * $form_state['num_names']. - */ -function form_example_tutorial_9_add_name($form, &$form_state) { - // Everything in $form_state is persistent, so we'll just use - // $form_state['add_name'] - $form_state['num_names']++; - - // Setting $form_state['rebuild'] = TRUE causes the form to be rebuilt again. - $form_state['rebuild'] = TRUE; -} - - -function form_example_tutorial_9_remove_name($form, &$form_state) { - if ($form_state['num_names'] > 1) { - $form_state['num_names']--; - } - - // Setting $form_state['rebuild'] = TRUE causes the form to be rebuilt again. - $form_state['rebuild'] = TRUE; -} - -/** - * Validate function for form_example_tutorial_9(). - * - * Adds logic to validate the form to check the validity of the new fields, - * if they exist. - */ -function form_example_tutorial_9_validate($form, &$form_state) { - - for ($i = 1; $i <= $form_state['num_names']; $i++) { - $year_of_birth = $form_state['values']['name'][$i]['year_of_birth']; - - if ($year_of_birth && ($year_of_birth < 1900 || $year_of_birth > 2000)) { - form_set_error("name][$i][year_of_birth", t('Enter a year between 1900 and 2000.')); - } - } -} - -/** - * Submit function for form_example_tutorial_9(). - */ -function form_example_tutorial_9_submit($form, &$form_state) { - $output = t("Form 9 has been submitted. "); - for ($i = 1; $i <= $form_state['num_names']; $i++) { - $output .= t("@num: @first @last (@date)... ", array('@num' => $i, '@first' => $form_state['values']['name'][$i]['first'], - '@last' => $form_state['values']['name'][$i]['last'], '@date' => $form_state['values']['name'][$i]['year_of_birth'])); - } - drupal_set_message($output); -} - -//////////////// Tutorial Example 10 ////////////////////// - -/** - * Example 10: A form with a file upload field. - * - * This example allows the user to upload a file to Drupal which is stored - * physically and with a reference in the database. - * - * @see form_example_tutorial_10_submit() - * @see form_example_tutorial_10_validate() - * @ingroup form_example - * - */ -function form_example_tutorial_10($form_state) { - // enctype="multipart/form-data" required by browsers to handle files. - $form = array( - '#attributes' => array('enctype' => "multipart/form-data"), - ); - - $form['file'] = array( - '#type' => 'file', - '#title' => t('Image'), - '#description' => t('Upload a file, allowed extensions: jpg, jpeg, png, gif'), - ); - - $form['submit'] = array( - '#type' => 'submit', - '#value' => t('Submit'), - ); - - return $form; -} - -/** - * Validate handler for form_example_tutorial_10(). - */ -function form_example_tutorial_10_validate($form, &$form_state) { - $file = file_save_upload('file', array( - 'file_validate_is_image' => array(), // Validates file is really an image. - 'file_validate_extensions' => array('png gif jpg jpeg'), // Validate extensions. - )); - // If the file passed validation: - if ($file) { - // Move the file, into the Drupal file system - if ($file = file_move($file, 'public://')) { - // Save the file for use in the submit handler. - $form_state['storage']['file'] = $file; - } - else { - form_set_error('file', t('Failed to write the uploaded file the site\'s file folder.')); - } - } - else { - form_set_error('file', t('No file was uploaded.')); - } -} - -/** - * Submit handler for form_example_tutorial_10(). - */ -function form_example_tutorial_10_submit($form, &$form_state) { - $file = $form_state['storage']['file']; - // We are done with the file, remove it from storage. - unset($form_state['storage']['file']); - // Make the storage of the file permanent - $file->status = FILE_STATUS_PERMANENT; - // Save file status. - file_save($file); - // Set a response to the user. - drupal_set_message(t('The form has been submitted and the image has been saved, filename: @filename.', array('@filename' => $file->filename))); -} diff --git a/form_example/form_example_wizard.inc b/form_example/form_example_wizard.inc deleted file mode 100644 index 9c59b5b07b8ebf0312f9af0e209a7b1362ef3021..0000000000000000000000000000000000000000 --- a/form_example/form_example_wizard.inc +++ /dev/null @@ -1,283 +0,0 @@ - array( - 'form' => 'form_example_wizard_personal_info', - ), - 2 => array( - 'form' => 'form_example_wizard_location_info', - ), - 3 => array( - 'form' => 'form_example_wizard_other_info', - ), - ); -} - -/** - * The primary formbuilder function for the wizard form. This is the form that - * you should call with drupal_get_form() from your code, and it will include - * the rest of the step forms defined. You are not required to change this - * function, as this will handle all the step actions for you. - * - * This form has two defined submit handlers to process the different steps: - * - Previous: handles the way to get back one step in the wizard. - * - Next: handles each step form submission, - * - * The third handler, the finish button handler, is the default form _submit - * handler used to process the information. - * - * You are not required to change the next or previous handlers, but you must - * change the form_example_wizard_sbumit handler to perform the operations you - * need on the collected information. - */ -function form_example_wizard($form, &$form_state) { - - // Initialize a description of the steps for the wizard. - if (empty($form_state['step'])) { - $form_state['step'] = 1; - - // This array contains the function to be called at each step to get the - // relevant form elements. It will also store state information for each - // step. - $form_state['step_information'] = _form_example_steps(); - } - $step = &$form_state['step']; - drupal_set_title(t('Extensible Wizard: Step @step', array('@step' => $step))); - - // Call the function named in $form_state['step_information'] to get the - // form elements to display for this step. - $form = $form_state['step_information'][$step]['form']($form, $form_state); - - // Show the 'previous' button if appropriate. Note that #submit is set to - // a special submit handler, and that we use #limit_validation_errors to - // skip all complaints about validation when using the back button. The - // values entered will be discarded, but they will not be validated, which - // would be annoying in a "back" button. - if ($step > 1) { - $form['prev'] = array( - '#type' => 'submit', - '#value' => t('Previous'), - '#name' => 'prev', - '#submit' => array('form_example_wizard_previous_submit'), - '#limit_validation_errors' => array(), - ); - } - - // Show the Next button only if there are more steps defined. - if ($step < count($form_state['step_information'])) { - // The Next button should be included on every step - $form['next'] = array( - '#type' => 'submit', - '#value' => t('Next'), - '#name' => 'next', - '#submit' => array('form_example_wizard_next_submit'), - ); - } - else { - // Just in case there are no more steps, we use the default submit handler of - // the form wizard. Call this button Finish, Submit, or whatever you want to - // show. When this button is clicked, the form_example_wizard_submit handler - // will be called. - $form['finish'] = array( - '#type' => 'submit', - '#value' => t('Finish'), - ); - } - - // Include each validation function defined for the different steps. - if (function_exists($form_state['step_information'][$step]['form'] . '_validate')) { - $form['next']['#validate'] = array($form_state['step_information'][$step]['form'] . '_validate'); - } - - return $form; -} - -/** - * Submit handler for the "previous" button. - * - Stores away $form_state['values'] - * - Decrements the step counter - * - Replaces $form_state['values'] with the values from the previous state. - * - Forces form rebuild. - * - * You are not required to change this function. - */ -function form_example_wizard_previous_submit($form, &$form_state) { - $current_step = &$form_state['step']; - $form_state['step_information'][$current_step]['stored_values'] = $form_state['values']; - if ($current_step > 1) { - $current_step--; - $form_state['values'] = $form_state['step_information'][$current_step]['stored_values']; - } - $form_state['rebuild'] = TRUE; -} - -/** - * Submit handler for the 'next' button. - * - Saves away $form_state['values'] - * - Increments the step count. - * - Replace $form_state['values'] from the last time we were at this page - * or with array() if we haven't been here before. - * - Force form rebuild. - * - * You are not required to change this function. - * - * @param unknown_type $form - * @param unknown_type $form_state - */ -function form_example_wizard_next_submit($form, &$form_state) { - $current_step = &$form_state['step']; - $form_state['step_information'][$current_step]['stored_values'] = $form_state['values']; - - if ($current_step < count($form_state['step_information'])) { - $current_step++; - if (!empty($form_state['step_information'][$current_step]['stored_values'])) { - $form_state['values'] = $form_state['step_information'][$current_step]['stored_values']; - } - else { - $form_state['values'] = array(); - } - $form_state['rebuild'] = TRUE; // Force rebuild with next step. - return; - } -} - -// The previous code was a 'skeleton' of a multistep wizard form. You are not -// required to change a line on the previous code (apart from defining your own -// steps in the _form_example_steps() function. -// -// All the code included from here is the content of the wizard, the steps of -// the form. - -// First, let's show the defined steps for the wizard example. - -/** - * Returns form elements for the 'personal info' page of the wizard. This is the - * first step of the wizard, asking for two textfields: first name and last - * name. - */ -function form_example_wizard_personal_info($form, &$form_state) { - $form = array(); - $form['first_name'] = array( - '#type' => 'textfield', - '#title' => t('First Name'), - '#default_value' => !empty($form_state['values']['first_name']) ? $form_state['values']['first_name'] : '', - ); - $form['last_name'] = array( - '#type' => 'textfield', - '#title' => t('Last Name'), - '#default_value' => !empty($form_state['values']['last_name']) ? $form_state['values']['last_name'] : '', - ); - return $form; -} - -/** - * Returns form elements for the 'location info' page of the wizard. This is the - * second step of the wizard. This step asks for a textfield value: a City. This - * step also includes a validation declared later. - */ -function form_example_wizard_location_info($form, &$form_state) { - $form = array(); - $form['city'] = array( - '#type' => 'textfield', - '#title' => t('City'), - '#description' => t('Hint: Do not enter "San Francisco", and do not leave this out.'), - '#required' => TRUE, - '#default_value' => !empty($form_state['values']['city']) ? $form_state['values']['city'] : '', - - ); - return $form; -} - -/** - * Custom validation form for the 'location info' page of the wizard. This is the - * validation function for the second step of the wizard. The city cannot be empty - * or be "San Francisco". - */ -function form_example_wizard_location_info_validate($form, &$form_state) { - if ($form_state['values']['city'] == 'San Francisco') { - form_set_error('city', t('You were warned not to enter "San Francisco"')); - } -} - -/** - * Returns form elements for the 'other info' page of the wizard. This is the - * thid and last step of the example wizard. - */ -function form_example_wizard_other_info($form, &$form_state) { - $form = array(); - $form['aunts_name'] = array( - '#type' => 'textfield', - '#title' => t("Your first cousin's aunt's Social Security number"), - '#default_value' => !empty($form_state['values']['aunts_name']) ? $form_state['values']['aunts_name'] : '', - ); - return $form; -} - -// And now comes the magic of the wizard, the function that should handle all the -// inputs from the user on each different step. -/** - * Wizard form submit handler. - * - Saves away $form_state['values'] - * - Process all the form values. - * - * This demonstration handler just do a drupal_set_message() with the information - * collected on each different step of the wizard. - * - * @param unknown_type $form - * @param unknown_type $form_state - */ -function form_example_wizard_submit($form, &$form_state) { - $current_step = &$form_state['step']; - $form_state['step_information'][$current_step]['stored_values'] = $form_state['values']; - - // In this case we've completed the final page of the wizard, so process the - // submitted information. - drupal_set_message(t('This information was collected by this wizard:')); - foreach($form_state['step_information'] as $index => $value) { - // Remove FAPI fields included in the values (form_token, form_id and form_build_id - // This is not required, you may access the values using $value['stored_values'] - // but I'm removing them to make a more clear representation of the collected - // information as the complete array will be passed through drupal_set_message(). - unset($value['stored_values']['form_id']); - unset($value['stored_values']['form_build_id']); - unset($value['stored_values']['form_token']); - - // Now show all the values. - drupal_set_message(t('Step @num collected the following values:
@result', array('@num' => $index, '@result' => print_r($value['stored_values'], TRUE)))); - } -} diff --git a/image_example/image_example.info b/image_example/image_example.info deleted file mode 100644 index 29f0811230c46d0a028da8cca279109387cd4853..0000000000000000000000000000000000000000 --- a/image_example/image_example.info +++ /dev/null @@ -1,8 +0,0 @@ - -name = Image Example -description = Example implementation of image.module hooks. -package = Example modules -core = 7.x -core = 7.x -dependencies[] = image -files[] = image_example.test diff --git a/image_example/image_example.install b/image_example/image_example.install deleted file mode 100644 index 926d6dae1064ff8e14e7728d3034e8e911675959..0000000000000000000000000000000000000000 --- a/image_example/image_example.install +++ /dev/null @@ -1,46 +0,0 @@ - 'Image Example', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('image_example_style_form'), - 'access arguments' => array('access content'), - 'file' => 'image_example.pages.inc', - ); - return $items; -} - -/** - * Implements hook_help(). - */ -function image_example_help($path) { - switch ($path) { - case 'image_example/styles': - $output = '
' . t('Use this form to upload an image and choose an Image Style to use when displaying the image. This demonstrates basic use of the Drupal 7 Image styles & effects system.') . '
'; - $output .= '' . t('Image styles can be added/edited using the !link.', array('!link' => l(t('Image styles UI'), 'admin/config/media/image-styles'))) . '
'; - return $output; - } -} - -/** - * Implements hook_image_default_styles(). - * - * hook_image_default_styles() declares to Drupal any image styles that are - * provided by the module. An image style is a collection of image effects that - * are performed in a specified order, manipulating the image and generating a - * new derivative image. - * - * This hook can be used to declare image styles that your module depends on or - * allow you to define image styles in code and gain the benefits of using - * a version control system. - */ -function image_example_image_default_styles() { - // This hook returns an array, each component of which describes an image - // style. The array keys are the machine-readable image style names and - // to avoid namespace conflicts should begin with the name of the - // implementing module. e.g.) 'mymodule_stylename'. Styles names should - // use only alpha-numeric characters, underscores (_), and hyphens (-). - $styles = array(); - $styles['image_example_style'] = array(); - - // Each style array consists of an 'effects' array that is made up of - // sub-arrays which define the individual image effects that are combined - // together to create the image style. - $styles['image_example_style']['effects'] = array( - array( - // Name of the image effect. See image_image_effect_info() in - // modules/image/image.effects.inc for a list of image effects available - // in Drupal 7 core. - 'name' => 'image_scale', - // Arguments to pass to the effect callback function. - // The arguments that an effect accepts are documented with each - // individual image_EFFECT_NAME_effect function. See image_scale_effect() - // for an example. - 'data' => array( - 'width' => 100, - 'height' => 100, - 'upscale' => 1, - ), - // The order in which image effects should be applied when using this - // style. - 'weight' => 0, - ), - // Add a second effect to this image style. Effects are executed in order - // and are cummulative. When applying an image style to an image the result - // will be the combination of all effects associated with that style. - array( - 'name' => 'image_example_colorize', - 'data' => array( - 'color' => '#FFFF66', - ), - 'weight' => 1, - ), - ); - - return $styles; -} - -/** - * Implements hook_image_style_save(). - * - * Allows modules to respond to updates to an image style's - * settings. - */ -function image_example_image_style_save($style) { - // The $style parameter is an image style array with one notable exception. - // When a user has choosen to replace a deleted style with another style the - // $style['name'] property contains the name of the replacement style and - // $style['old_name'] contains the name of the style being deleted. - - // Here we update a variable that contains the name of the image style that - // the block provided by this module uses when formating images to use the - // new user choosen style name. - if (isset($style['old_name']) && $style['old_name'] == variable_get('image_example_style_name', '')) { - variable_set('image_example_style_name', $style['name']); - } -} - -/** - * Implements hook_image_style_delete(). - * - * This hook allows modules to respond to image styles being deleted. - * - * @see image_example_style_save() - */ -function image_example_image_style_delete($style) { - // See information about $style paramater in documentation for - // image_example_style_save(). - - // Update the modules variable that contains the name of the image style - // being deleted to the name of the replacement style. - if (isset($style['old_name']) && $style['old_name'] == variable_get('image_example_style_name', '')) { - variable_set('image_example_style_name', $style['name']); - } -} - -/** - * Implements hook_image_style_flush(). - * - * This hook allows modules to respond when a style is being flushed. Styles - * are flushed any time a style is updated, an effect associated with the style - * is updated, a new effect is added to the style, or an existing effect is - * removed. - * - * Flushing removes all images generated using this style from the host. Once a - * style has been flushed derivative images will need to be regenerated. New - * images will be generated automatically as needed but it is worth noting that - * on a busy site with lots of images this could have an impact on performance. - * - * Note: This function does not currently have any effect as the example module - * does not use any caches. It is demonstrated here for completeness sake only. - */ -function image_example_style_flush($style) { - // The $style parameter is an image style array. - - // Empty any caches populated by our module that could contain stale data - // after the style has been flushed. Stale data occurs because the module may - // have cached content with a reference to the derivative image which is - // being deleted. - cache_clear_all('*', 'image_example', TRUE); -} - -/** - * Implements hook_image_styles_alter(). - * - * Allows your module to modify, add, or remove image styles provided - * by other modules. The best use of this hook is to modify default styles that - * have not been overriden by the user. Altering styles that have been - * overriden by the user could have an adverse affect on the user experience. - * If you add an effect to a style through this hook and the user attempts to - * remove the effect it will immediatly be re-applied. - */ -function image_example_image_styles_alter(&$styles) { - // The $styles paramater is an array of image style arrays keyed by style - // name. You can check to see if a style has been overriden by checking the - // $styles['stylename']['storage'] property. - - // Verify that the effect has not been overriden. - if ($styles['thumbnail']['storage'] == IMAGE_STORAGE_DEFAULT) { - // Add an additional colorize effect to the system provided thumbnail - // effect. - $styles['thumbnail']['effects'][] = array( - 'label' => t('Colorize #FFFF66'), - 'name' => 'image_example_colorize', - 'effect callback' => 'image_example_colorize_effect', - 'data' => array( - 'color' => '#FFFF66', - ), - 'weight' => 1, - ); - } -} - -/** - * Implements hook_image_effect_info(). - * - * This hook allows your module to define additional image manipulation effects - * that can be used with image styles. - */ -function image_example_image_effect_info() { - $effects = array(); - - // The array is keyed on the machine-readable effect name. - $effects['image_example_colorize'] = array( - // Human readable name of the effect. - 'label' => t('Colorize'), - // (optional) Brief description of the effect that will be shown when - // adding or configuring this image effect. - 'help' => t('The colorize effect will first remove all color from the source image and then tint the image using the color specified.'), - // Name of function called to perform this effect. - 'effect callback' => 'image_example_colorize_effect', - // (optional) Name of function that provides a $form array with options for - // configuring the effect. Note that you only need to return the fields - // specific to your module. Submit buttons will be added automatically, and - // configuration options will be serailized and added to the 'data' element - // of the effect. The function will recieve the $effect['data'] array as - // its only parameter. - 'form callback' => 'image_example_colorize_form', - // (optional) Name of a theme function that will output a summary of this - // effects configuation. Used when displaying list of effects associated - // with an image style. In this example the function - // theme_image_example_colorize_summary will be called via the theme() - // function. Your module must also implement hook_theme() in order for this - // function to work correctly. See image_example_theme() and - // theme_image_example_colorize_summary(). - 'summary theme' => 'image_example_colorize_summary', - ); - - return $effects; -} - -/** - * Form Builder; Configuration settings for colorize effect. - * - * Create a $form array with the fields necessary for configuring the - * image_example_colorize effect. - * - * Note that this is not a complete form, it only contains the portion of the - * form for configuring the colorize options. Therefore it does not not need to - * include metadata about the effect, nor a submit button. - * - * @param $data - * The current configuration for this colorize effect. - */ -function image_example_colorize_form($data) { - $form = array(); - // You do not need to worry about handling saving/updating/deleting of the - // data collected. The image module will automatically serialize and store - // all data associated with an effect. - $form['color'] = array( - '#type' => 'textfield', - '#title' => t('Color'), - '#description' => t('The color to use when colorizing the image. Use web-style hex colors. e.g.) #FF6633.'), - '#default_value' => isset($data['color']) ? $data['color'] : '', - '#size' => 7, - '#max_length' => 7, - '#required' => TRUE, - ); - return $form; -} - -/** - * Image effect callback; Colorize an image resource. - * - * @param $image - * An image object returned by image_load(). - * @param $data - * An array of attributes to use when performing the colorize effect with the - * following items: - * - "color": The web-style hex color to use when colorizing the image. - * @return - * TRUE on success. FALSE on failure to colorize image. - */ -function image_example_colorize_effect(&$image, $data) { - // Image manipulation should be done to the $image->resource, which will be - // automatically saved as a new image once all effects have been applied. - // If your effect makes changes to the $image->resource that relate to any - // information stored in the $image->info array (width, height, etc.) you - // should update that information as well. See modules/system/image.gd.inc - // for examples of functions that perform image manipulations. - - // Not all GD installations are created equal. It is a good idea to check for - // the existence of image manipulation functions before using them. - // PHP installations using non-bundled GD do not have imagefilter(). More - // information about image manipulation functions is available in the PHP - // manual. http://www.php.net/manual/en/book.image.php - if (!function_exists('imagefilter')) { - watchdog('image', 'The image %image could not be colorized because the imagefilter() function is not available in this PHP installation.', array('%file' => $image->source)); - return FALSE; - } - - // Verify that Drupal is using the PHP GD library for image manipulations - // since this effect depends on functions in the GD library. - if ($image->toolkit != 'gd') { - watchdog('image', 'Image colorize failed on %path. Using non GD toolkit.', array('%path' => $image->source), WATCHDOG_ERROR); - return FALSE; - } - - // Convert short #FFF syntax to full #FFFFFF syntax. - if (strlen($data['color']) == 4) { - $c = $data['color']; - $data['color'] = $c[0] . $c[1] . $c[1] . $c[2] . $c[2] . $c[3] . $c[3]; - } - - // Convert #FFFFFF syntax to hexadecimal colors. - $data['color'] = hexdec(str_replace('#', '0x', $data['color'])); - - // Convert the hexadecimal color value to a color index value. - $rgb = array(); - for ($i = 16; $i >= 0; $i -= 8) { - $rgb[] = (($data['color'] >> $i) & 0xFF); - } - - // First desaturate the image, and then apply the new color. - imagefilter($image->resource, IMG_FILTER_GRAYSCALE); - imagefilter($image->resource, IMG_FILTER_COLORIZE, $rgb[0], $rgb[1], $rgb[2]); - - return TRUE; -} - -/** - * Implements hook_theme(). - */ -function image_example_theme() { - return array( - 'image_example_colorize_summary' => array( - 'variables' => array('data' => NULL), - ), - 'image_example_image' => array( - 'variables' => array('image' => NULL, 'style' => NULL), - 'file' => 'image_example.pages.inc', - ), - ); -} - -/** - * Formats a summary of an image colorize effect. - * - * @param $variables - * An associative array containing: - * - data: The current configuration for this colorize effect. - * - * @ingroup themeable - */ -function theme_image_example_colorize_summary($variables) { - $data = $variables['data']; - return t('as color #@color.', array('@color' => $data['color'])); -} diff --git a/image_example/image_example.pages.inc b/image_example/image_example.pages.inc deleted file mode 100644 index c7206e166d77134bfdebc0c7e24a38205cb2fc30..0000000000000000000000000000000000000000 --- a/image_example/image_example.pages.inc +++ /dev/null @@ -1,147 +0,0 @@ - theme('image_example_image', array('image' => $image, 'style' => $style)), - ); - } - - // Use the #managed_file FAPI element to upload an image file. - $form['image_example_image_fid'] = array( - '#title' => t('Image'), - '#type' => 'managed_file', - '#description' => t('The uploaded image will be displayed on this page using the image style choosen below.'), - '#default_value' => variable_get('image_example_image_fid', ''), - '#upload_location' => 'public://image_example_images/', - ); - - // Provide a select field for choosing an image style to use when displaying - // the image. - $form['image_example_style_name'] = array( - '#title' => t('Image style'), - '#type' => 'select', - '#description' => t('Choose an image style to use when displaying this image.'), - // The image_style_options() function returns an array of all available - // image styles both the key and the value of the array are the image - // style's name. The fucntion takes on paramater, a boolean flag - // signifying wether or not the array should include a' . t('This image is being displayed using the image style %style_name.', array('%style_name' => $style)) . '
'; - return $output; -} \ No newline at end of file diff --git a/image_example/image_example.test b/image_example/image_example.test deleted file mode 100644 index 788f635fa6e12415fac7f2ac177895c89222da5a..0000000000000000000000000000000000000000 --- a/image_example/image_example.test +++ /dev/null @@ -1,103 +0,0 @@ - 'Image example functionality', - 'description' => 'Test functionality of the Image Example module.', - 'group' => 'Examples', - ); - } - - /** - * Enable modules and create user with specific permissions. - */ - function setUp() { - parent::setUp('image_example'); - // Create user with permission to administer image styles. - $this->web_user = $this->drupalCreateUser(array('administer image styles', 'administer blocks')); - } - - /** - * Test implementations of image API hooks. - */ - function testImageExample() { - // Login the admin user. - $this->drupalLogin($this->web_user); - - // Verify that the default style added by - // image_example_image_default_styles() is in the list of image styles. - $image_styles = image_styles(); - $this->assertTrue(isset($image_styles['image_example_style']), t('The default style image_example_style is in the list of image styles.')); - - // Verify that the effect added to the default 'thumbnail' style by - // image_example_image_styles_alter() is present. - $this->assertTrue((isset($image_styles['thumbnail']['effects'][1]['name']) && $image_styles['thumbnail']['effects'][1]['name'] == 'image_example_colorize'), t('Effect added to the thumbnail style via hook_image_styles_alter() is present.')); - - // Create a new image style and add the effect provided by - // image_example_effect_info(). - $new_style = array('name' => strtolower($this->randomName())); - $new_style = image_style_save($new_style); - $this->assertTrue(isset($new_style['isid']), t('Image style @style_name created.', array('@style_name' => $new_style['name']))); - - $edit = array( - 'new' => 'image_example_colorize', - ); - $this->drupalPost('admin/config/media/image-styles/edit/' . $new_style['name'], $edit, t('Add')); - - // Verify the 'color' field provided by image_example_colorize_form() - // appears on the effect configuration page. And that we can fill it out. - $this->assertField('data[color]', t('Color field provided by image_example_effect_colorize_form is present on effect configuration page.')); - $edit = array( - 'data[color]' => '#000000', - ); - $this->drupalPost(NULL, $edit, t('Add effect')); - $this->assertText(t('The image effect was successfully applied.'), t('Colorize effect added to @style_name.', array('@style_name' => $new_style['name']))); - - // Set the variable 'image_example_style_name' to the name of our new style - // then rename the style and ensure the variable name is changed. - - // @todo Enable this block once http://drupal.org/node/713872 is fixed. - if (defined('bug_713872_fixed')) { - $style = image_style_load($new_style['name']); - variable_set('image_example_style_name', $style['name']); - $style['name'] = strtolower($this->randomName()); - $style = image_style_save($style); - $variable = variable_get('image_example_style_name', ''); - $this->assertTrue(($variable == $style['name']), t('Variable image_example_style_name successfully updated when renaming image style.')); - } - } - - /** - * Tests for image block provided by module. - */ - function testImageExamplePage() { - // Login the admin user. - $this->drupalLogin($this->web_user); - $this->drupalCreateNode(array('promote' => 1)); - - // Upload an image to the image page. - $images = $this->drupalGetTestFiles('image'); - $edit = array( - 'files[image_example_image_fid]' => drupal_realpath($images[0]->uri), - 'image_example_style_name' => 'image_example_style', - ); - $this->drupalPost('image_example/styles', $edit, t('Save')); - $this->assertText(t('The image @image_name was uploaded', array('@image_name' => $images[0]->filename)), t('Image uploaded to image block.')); - - // Verify the image is displayed. - $this->drupalGet('image_example/styles'); - $fid = variable_get('image_example_image_fid', FALSE); - $image = isset($fid) ? file_load($fid) : NULL; - $this->assertRaw(file_uri_target($image->uri), t('Image is displayed')); - } -} diff --git a/js_example/accordion.tpl.php b/js_example/accordion.tpl.php deleted file mode 100644 index 6258826e812cf395af04d2bca3875cfdbe988bf7..0000000000000000000000000000000000000000 --- a/js_example/accordion.tpl.php +++ /dev/null @@ -1,54 +0,0 @@ - -- Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer - ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit - amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut - odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate. -
-- Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet - purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor - velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In - suscipit faucibus urna. -
-- Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis. - Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero - ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis - lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui. -
-- Cras dictum. Pellentesque habitant morbi tristique senectus et netus - et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in - faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia - mauris vel est. -
-- Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus. - Class aptent taciti sociosqu ad litora torquent per conubia nostra, per - inceptos himenaeos. -
-" . t( - "The Node Example module provides a custom node type. - You can create new nodes using the node add form. - Nodes that you create will be displayed here.", - array('!nodeadd' => url('node/add/node-example')) - ) . "
"; - } -} - -/** - * A custom theme function. - * - * By using this function to format our node-specific information, themes - * can override this presentation if they wish. This is a simplifed theme - * function purely for illustrative purposes. - */ -function theme_example_node_color($variables) { - $output = '' . $variables['color'] . ''; - return $output; -} diff --git a/node_example/node_example.test b/node_example/node_example.test deleted file mode 100644 index 940ff3e6b9474e0e7e03941ff65eace8d6b7475e..0000000000000000000000000000000000000000 --- a/node_example/node_example.test +++ /dev/null @@ -1,55 +0,0 @@ - 'Node example', - 'description' => 'Verify the custom node type creation.', - 'group' => 'Examples', - ); - } - - function setUp() { - // Enable the module. - parent::setUp('node_example'); - } - - /** - * Verify the functionality of the example module. - */ - function testNodeCreation() { - // Create and login user. - $account = $this->drupalCreateUser(array('access content', 'create node_example content')); - $this->drupalLogin($account); - - // Create a new node. The image makes it more complicated, so skip it. - $edit = array( - 'title' => $this->randomName(), - 'node_example_color[und][0][value]' => 'red', - 'node_example_color[und][1][value]' => 'green', - 'node_example_color[und][2][value]' => 'blue', - 'node_example_quantity[und][0][value]' => 100, - ); - $this->drupalPost('node/add/node-example', $edit, t('Save')); - $this->assertText("Example Node " . $edit['title'] . " has been created", "Found node creation message"); - $this->assertPattern("/The colors available.*red.*green.*blue/", "Correct 'colors available' on node page"); - - // Look on the examples page to make sure it shows up there also. - $this->drupalGet('examples/node_example'); - $this->assertText($edit['title'], "Found random title string"); - $this->assertPattern("/red.*green.*blue/", "Correct 'colors available' on node example page"); - - } -} - diff --git a/nodeapi_example/nodeapi_example.info b/nodeapi_example/nodeapi_example.info deleted file mode 100644 index f50e2a5510cc92f52d4c14ed3b86ba178de279c7..0000000000000000000000000000000000000000 --- a/nodeapi_example/nodeapi_example.info +++ /dev/null @@ -1,6 +0,0 @@ - -name = NodeAPI example -description = Demonstrates using the hook_node_* APIs (formerly hook_nodeapi) to alter a node from a different module. -package = Example modules -core = 7.x -files[] = nodeapi_example.test diff --git a/nodeapi_example/nodeapi_example.install b/nodeapi_example/nodeapi_example.install deleted file mode 100644 index d470be834c32ec6db079e04e47b372d3f2179954..0000000000000000000000000000000000000000 --- a/nodeapi_example/nodeapi_example.install +++ /dev/null @@ -1,60 +0,0 @@ - 'Stores information of extended content.', - 'fields' => array( - 'nid' => array( - 'description' => 'Node ID that the rating is applied to.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0 - ), - 'vid' => array( - 'description' => 'Revision ID, as we are tracking rating with node revisions', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0 - ), - 'rating' => array( - 'description' => 'The rating of the node.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0 - ), - ), - 'primary key' => array('vid'), - 'indexes' => array( - 'nid' => array('nid'), - ), - ); - - return $schema; -} diff --git a/nodeapi_example/nodeapi_example.module b/nodeapi_example/nodeapi_example.module deleted file mode 100755 index 5a221dc06b640e8441984a0dc510721aff669806..0000000000000000000000000000000000000000 --- a/nodeapi_example/nodeapi_example.module +++ /dev/null @@ -1,283 +0,0 @@ - 'fieldset', - '#title' => t('Rating settings'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#group' => 'additional_settings', - '#weight' => -1, - ); - - $form['rating']['nodeapi_example'] = array( - '#type' => 'radios', - '#title' => t('NodeAPI Example Rating'), - '#default_value' => variable_get('nodeapi_example_' . $form['#node_type']->type, FALSE), - '#options' => array(FALSE => t('Disabled'), TRUE => t('Enabled')), - '#description' => t('Should this node have a rating attached to it?'), - ); - } - // If the type and node field are set this may be a node edit form. - elseif (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] . '_node_form' == $form_id) { - // If the rating is enabled for this node type, we insert our control - // into the form. - $node = $form['#node']; - if (variable_get('nodeapi_example_' . $form['type']['#value'], FALSE)) { - $form['nodeapi_example_rating'] = array( - '#type' => 'select', - '#title' => t('Rating'), - '#default_value' => isset($node->nodeapi_example_rating) ? $node->nodeapi_example_rating : '', - '#options' => array(0 => t('Unrated'), 1, 2, 3, 4, 5), - '#required' => TRUE, - '#weight' => 0, - ); - } - } -} - -/** - * hook_nodeapi() has been replaced in Drupal 7 with a set of different hooks - * providing the same or improved functionality. - * - * The replacement functions providing access to events ocurred to content in - * Drupal is listed below, and detailled in the following location: - * http://api.drupal.org/api/group/hooks/7 - * or in the node API declaration file: modules/node/node.api.php - * - * hook_node_access() - Control access to a node. - * hook_node_access_records() - Set permissions for a node to be written to the database. - * hook_node_access_records_alter() - Alter permissions for a node before it is written to the database. - * hook_node_build_alter() - The node content was built, the module may modify the structured content. - * hook_node_delete() - Act on node deletion. - * hook_node_grants() - Inform the node access system what permissions the user has. - * hook_node_grants_alter() - Alter user access rules when trying to view, edit or delete a node. - * hook_node_info() - Defines module-provided node types. - * hook_node_insert() - Respond to node insertion. - * hook_node_load() - Act on node objects when loaded. - * hook_node_operations() - Add mass node operations. - * hook_node_prepare() - The node is about to be shown on the add/edit form. - * hook_node_prepare_translation() - The node is being cloned for translation. - * hook_node_presave() - The node passed validation and is about to be saved. - * hook_node_revision_delete() - A revision of the node is deleted. - * hook_node_search_result() - The node is being displayed as a search result. - * hook_node_type_delete() - Act on node type deletion. - * hook_node_type_insert() - Act on node type creation. - * hook_node_type_update() - Act on node type changes. - * hook_node_update() - The node being updated. - * hook_node_update_index() - The node is being indexed. - * hook_node_validate() - The user has finished editing the node and is previewing or submitting it. - * hook_node_view() - The node content is being assembled before rendering. - * - */ - -/** - * Implements hook_node_validate(). - * - * Check that rating attribute is set in the form submission, the field is - * required - */ -function nodeapi_example_node_validate($node, $form) { - if (variable_get('nodeapi_example_' . $node->type, FALSE)) { - if (isset($node->nodeapi_example_rating) && !$node->nodeapi_example_rating) { - form_set_error('nodeapi_example_rating', t('You must rate this content.')); - } - } -} - -/** - * Implements hook_node_load(). - * - * Load the rating information if available for any of the nodes in the argument - * list. - */ -function nodeapi_example_node_load($nodes, $form) { - foreach ($nodes as $node) { - // We are using the revision id instead of node id - if (variable_get('nodeapi_example_' . $node->type, FALSE)) { - $vids[] = $node->vid; - } - } - // Check if we should load rating for any of the nodes - if (!isset($vids) || !count($vids)) { - return; - } - - // When we read, we don't care about the node->nid, but we look for the right - // revision ID (node->vid) - $result = db_select('nodeapi_example', 'e') - ->fields('e', array( - 'nid', - 'vid', - 'rating', - )) - ->where('e.vid IN (:vids)', array(':vids' => $vids)) - ->execute(); - - foreach ($result as $record) { - $nodes[$record->nid]->nodeapi_example_rating = $record->rating; - } -} - -/** - * Implements hook_node_insert(). - * - * As a new node is being inserted into the database, we need to do our own - * database inserts. - */ -function nodeapi_example_node_insert($node) { - if (variable_get('nodeapi_example_' . $node->type, FALSE)) { - // Notice that we are ignoring any revision information using $node->nid - db_insert('nodeapi_example') - ->fields(array( - 'nid' => $node->nid, - 'vid' => $node->vid, - 'rating' => $node->nodeapi_example_rating, - )) - ->execute(); - } -} - -/** - * Implements hook_node_delete(). - * - * When a node is deleted, we need to remove all related records from our table, - * including all revisions. For the delete operations we use node->nid. - */ -function nodeapi_example_node_delete($node) { - // Notice that we're deleting even if the content type has no rating enabled. - db_delete('nodeapi_example') - ->condition('nid', $node->nid) - ->execute(); -} - -/** - * Implements hook_node_update(). - * - * As an existing node is being updated in the database, we need to do our own - * database updates. - * - * Update is called when an existing node has been changed. Here, we use a - * DELETE then an INSERT rather than an UPDATE. The reason is that a node - * created before this module was installed won't already have a rating - * saved so there would be nothing to update. - */ -function nodeapi_example_node_update($node) { - if (variable_get('nodeapi_example_' . $node->type, FALSE)) { - // If may happen that this node does not have a previous saved rating - // value, so we can't just update it, we need to check first if this - $rating = db_select('nodeapi_example', 'e') - ->fields('e', array( - 'rating', - )) - ->where('e.vid = (:vid)', array(':vid' => $node->vid)) - ->execute()->fetchField(); - - if($rating) { - // node has been rated before. - db_update('nodeapi_example') - ->fields(array('rating' => $node->nodeapi_example_rating)) - ->condition('vid', $node->vid) - ->execute(); - } - else { - // Node was not previously rated, so insert a new rating in database. - nodeapi_example_node_insert($node); - } - } -} - -/** - * Implements hook_view(). - * - * This is a typical implementation that simply runs the node text through - * the output filters. - * - * Finally, we need to take care of displaying our rating when the node is - * viewed. This operation is called after the node has already been prepared - * into HTML and filtered as necessary, so we know we are dealing with an - * HTML teaser and body. We will inject our additional information at the front - * of the node copy. - * - * Using node API 'hook_node_view' is more appropriate than using a filter here, because - * filters transform user-supplied content, whereas we are extending it with - * additional information. - */ -function nodeapi_example_node_view($node, $build_mode = 'full') { - if (variable_get('nodeapi_example_' . $node->type, FALSE)) { - // Make sure to set a rating, also for nodes saved previously and not yet rated. - $rating = isset($node->nodeapi_example_rating) ? $node->nodeapi_example_rating : 0; - $node->content['nodeapi_example'] = array( - '#markup' => theme('nodeapi_example_rating', array('rating' => $rating)), - '#weight' => -1, - ); - } -} - -/** - * Implements hook_theme(). - * - * This lets us tell Drupal about our theme functions and their arguments. - */ -function nodeapi_example_theme() { - return array( - 'nodeapi_example_rating' => array( - 'variables' => array('rating' => NULL), - ), - ); -} - -/** - * A custom theme function. - * - * By using this function to format our rating, themes can override this presentation - * if they wish; for example, they could provide a star graphic for the rating. We - * also wrap the default presentation in a CSS class that is prefixed by the module - * name. This way, style sheets can modify the output without requiring theme code. - */ -function theme_nodeapi_example_rating($variables) { - $options = array( - 0 => t('Unrated'), - 1 => t('Poor'), - 2 => t('Needs improvement'), - 3 => t('Acceptable'), - 4 => t('Good'), - 5 => t('Excellent'), - ); - $output = ' '; - return $output; -} - diff --git a/nodeapi_example/nodeapi_example.test b/nodeapi_example/nodeapi_example.test deleted file mode 100644 index e16ef8e5044a1d50d9dc49ed322441b8d2234a1a..0000000000000000000000000000000000000000 --- a/nodeapi_example/nodeapi_example.test +++ /dev/null @@ -1,211 +0,0 @@ - 'Node API example functionality', - 'description' => 'Demonstrate Node API hooks that allow altering a node. These are the former hook_nodeapi.', - 'group' => 'Examples', - ); - } - - /** - * Enable modules and create user with specific permissions. - */ - function setUp() { - parent::setUp('nodeapi_example'); - - // Create admin user. This module has no access control, so we can use a - // trusted user. Revision access and revert permissions are required too. - $this->web_user = $this->drupalCreateUser(array( - 'administer nodes', // Required to set revision checkbox - 'administer content types', - 'bypass node access', - 'view revisions', - 'revert revisions' - )); - // Login the admin user. - $this->drupalLogin($this->web_user); - } - - /** - * Login user, create an example node, and use the rating system - */ - function testNodeExampleBasic() { - - // Login the user. - $this->drupalLogin($this->web_user); - - // Create custom content type - $content_type = $this->drupalCreateContentType(); - $type = $content_type->type; - - // Go to edit the settings of this content type - $this->drupalGet('admin/structure/types/manage/' . $type); - $this->assertResponse(200); - - // Check if the new Rating options appear in the settings page - $this->assertText(t('NodeAPI Example Rating'), t('Rating options found in content type.')); - $this->assertFieldByName('nodeapi_example', 1, t('Rating is Disabled by default.')); - - // Disable the rating for this content type: 0 for Disabled, 1 for Enabled. - $content_settings = array( - 'nodeapi_example' => 0, - ); - $this->drupalPost('admin/structure/types/manage/' . $type, $content_settings, t('Save content type')); - $this->assertResponse(200); - $this->assertRaw(' has been updated.', t('Settings modified successfully for content type.')); - - // Create an example node - $langcode = LANGUAGE_NONE; - $edit = array( - "title" => $this->randomName(), - ); - $this->drupalPost('node/add/' . $type, $edit, t('Save')); - $this->assertResponse(200); - - // Check that the rating is not shown, as we have not yet enabled it - $this->assertNoRaw('Rating: ', t('Extended rating information is not shown.')); - - // Save current current url (we are viewing the new node) - $node_url = $this->getUrl(); - - // Enable the rating for this content type: 0 for Disabled, 1 for Enabled. - $content_settings = array( - 'nodeapi_example' => TRUE, - ); - $this->drupalPost('admin/structure/types/manage/' . $type, $content_settings, t('Save content type')); - $this->assertResponse(200); - $this->assertRaw(' has been updated.', t('Settings modified successfully for content type.')); - - // Check previously create node. It should be not rated - $this->drupalGet($node_url); - $this->assertResponse(200); - $this->assertRaw(t('Rating: %rating', array('%rating' => t('Unrated'))), t('Content is not rated.')); - - // Rate the content, 4 is for "Good" - $rate = array( - 'nodeapi_example_rating' => 4, - ); - $this->drupalPost($node_url . '/edit', $rate, t('Save')); - $this->assertResponse(200); - - // Check that content has been rated - $this->assertRaw(t('Rating: %rating', array('%rating' => t('Good'))), t('Content is successfully rated.')); - - } - - /** - * Login user, create an example node, and test rating functionality with - * a node using revisions. - */ - function testNodeExampleRevision() { - - // Login the user. - $this->drupalLogin($this->web_user); - - // Create custom content type - $content_type = $this->drupalCreateContentType(); - $type = $content_type->type; - - // Go to edit the settings of this content type - $this->drupalGet('admin/structure/types/manage/' . $type); - $this->assertResponse(200); - - // Check if the new Rating options appear in the settings page - $this->assertText(t('NodeAPI Example Rating'), t('Rating options found in content type.')); - $this->assertFieldByName('nodeapi_example', 1, t('Rating is Disabled by default.')); - - // Disable the rating for this content type: 0 for Disabled, 1 for Enabled. - $content_settings = array( - 'nodeapi_example' => 0, - ); - $this->drupalPost('admin/structure/types/manage/' . $type, $content_settings, t('Save content type')); - $this->assertResponse(200); - $this->assertRaw(' has been updated.', t('Settings modified successfully for content type.')); - - // Create an example node - $langcode = LANGUAGE_NONE; - $edit = array( - "title" => $this->randomName(), - ); - $this->drupalPost('node/add/' . $type, $edit, t('Save')); - $this->assertResponse(200); - - // Check that the rating is not shown, as we have not yet enabled it - $this->assertNoRaw('Rating: ', t('Extended rating information is not shown.')); - - // Save current current url (we are viewing the new node) - $node_url = $this->getUrl(); - - // Enable the rating for this content type: 0 for Disabled, 1 for Enabled. - $content_settings = array( - 'nodeapi_example' => TRUE, - ); - $this->drupalPost('admin/structure/types/manage/' . $type, $content_settings, t('Save content type')); - $this->assertResponse(200); - $this->assertRaw(' has been updated.', t('Settings modified successfully for content type.')); - - // Check previously create node. It should be not rated - $this->drupalGet($node_url); - $this->assertResponse(200); - $this->assertRaw(t('Rating: %rating', array('%rating' => t('Unrated'))), t('Content is not rated.')); - - // Rate the content, 4 is for "Good" - $rate = array( - 'nodeapi_example_rating' => 4, - ); - $this->drupalPost($node_url . '/edit', $rate, t('Save')); - $this->assertResponse(200); - - // Check that content has been rated - $this->assertRaw(t('Rating: %rating', array('%rating' => t('Good'))), t('Content is successfully rated.')); - - // Rate the content to poor using a new revision, 1 is for "Poor" - $rate = array( - 'nodeapi_example_rating' => 1, - 'revision' => 1, - ); - $this->drupalPost($node_url . '/edit', $rate, t('Save')); - $this->assertResponse(200); - - // Check that content has been rated - $this->assertRaw(t('Rating: %rating', array('%rating' => t('Poor'))), t('Content is successfully rated.')); - - //Now switch back to previous revision of the node. - $this->drupalGet($node_url . '/revisions'); - // There is only a revision, so it must work just clicking the first link.. - $this->clickLink('revert'); - $revert_form = $this->getUrl(); - $this->drupalPost($revert_form, array(), t('Revert')); - - // Go back to the node page. - $this->drupalGet($node_url); - $this->assertResponse(200); - - // Check that content has been rated - $this->assertRaw(t('Rating: %rating', array('%rating' => t('Good'))), t('Content rating matches reverted revision.')); - - } - -} diff --git a/page_example/page_example.info b/page_example/page_example.info deleted file mode 100644 index 3160a907f463b82ecf11a72695f97b28cf09ae04..0000000000000000000000000000000000000000 --- a/page_example/page_example.info +++ /dev/null @@ -1,6 +0,0 @@ - -name = Page example -description = An example module showing how to define a page to be displayed to the user at a given URL. -package = Example modules -core = 7.x -files[] = page_example.test diff --git a/page_example/page_example.module b/page_example/page_example.module deleted file mode 100755 index 494ce739ba1762ea8f140aeefd5922fb04df972a..0000000000000000000000000000000000000000 --- a/page_example/page_example.module +++ /dev/null @@ -1,167 +0,0 @@ - array( - 'title' => t('Access simple page'), - 'description' => t('Allow users to access simple page'), - ), - 'access arguments page' => array( - 'title' => t('Access page with arguments'), - 'description' => t('Allow users to access page with arguments'), - ), - ); -} - -/** - * Implements hook_menu(). - * - * hook_menu() must be implemented to emit items to place in the main menu. - * This is a required step for modules wishing to display their own pages, - * because the process of creating the links also tells Drupal what - * callback function to use for a given URL. The menu items returned - * here provide this information to the menu system. - * - * With the below menu definitions, URLs will be interpreted as follows: - * - * If the user accesses http://example.com/?q=examples/page_example/simple, then - * the menu system will first look for a menu item with that path. In this case - * it will find a match, and execute page_example_simple(). - * - * If the user accesses http://example.com/?q=examples/page_example/arguments, - * no match will be found, so the system will look for 'examples/page_example', - * which exists, and that page will be displayed. - * - * If the user accesses http://example.com/?q=examples/page_example/arguments, - * the menu system will find no explicit match so will fall back to execute - * page_example_description(). - * - * If the user accesses - * http://example.com/?q=examples/page_example/arguments/1/2, the menu - * system will first look for examples/page_example/arguments/1/2. Not finding - * a match, it will look for examples/page_example/arguments/1/%. Again not - * finding a match, it will look for examples/page_example/arguments/%/2. - * Yet again not finding a match, it will look for - * examples/page_example/arguments/%/%. This time it finds a match, and so will - * execute page_example_arguments(1, 2). Since the parameters are passed to - * the function after the match, the function can do additional checking or - * make use of them without resulting to the arg() function. - * - * The @link menu_example.module Menu Example @endlink provides extensive - * examples for hook_menu(). - */ -function page_example_menu() { - - // This is the minimum information you can provide for a menu item. This menu - // item will be created in the default menu. - $items['examples/page_example'] = array( - 'title' => 'Page Example', - 'page callback' => 'page_example_description', - 'access callback' => TRUE, - 'expanded' => TRUE, - ); - - $items['examples/page_example/simple'] = array( - 'title' => 'Simple - no arguments', - 'page callback' => 'page_example_simple', - 'access arguments' => array('access simple page'), - ); - - // By using the MENU_CALLBACK type, we can register the callback for this - // path but do not have the item show up in the menu; the admin is not allowed - // to enable the item in the menu, either. - // - // Notice that the 'page arguments' is an array of numbers. These will be - // replaced with the corresponding parts of the menu path. In this case a 0 - // would be replaced by 'example', a 1 by 'arguments', and like wise 2 and 3 will - // be replaced by what ever the user provides. These will be passed as - // arguments to the page_example_arguments() function. - $items['examples/page_example/arguments/%/%'] = array( - 'page callback' => 'page_example_arguments', - 'page arguments' => array(3, 4), - 'access arguments' => array('access arguments page'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - -function page_example_description() { - return array('#markup' => t('The page_example provides two pages, "simple" and "arguments". The simple page just returns a renderable array for display. The arguments page takes two arguments and displays them, as in @arguments_link', array('@simple_link' => url('examples/page_example/simple', array('absolute' => TRUE)), '@arguments_link' => url('examples/page_example/arguments/23/56', array('absolute' => TRUE))))); -} -/** - * A simple page callback. - * - * Page callbacks return a renderable array with the content area of the page. - * The theme system will later render and surround the content in the - * appropriate blocks, navigation, and styling. - * - * If you do not want to use the theme system (for example for outputting an - * image or XML), you should print the content yourself and not return anything. - */ -function page_example_simple() { - return array('#markup' => '' . t('Simple page: The quick brown fox jumps over the lazy dog.') . '
'); -} - -/** - * A more complex page callback that takes arguments. - * - * The arguments are passed in from the page URL. The in our hook_menu - * implementation we instructed the menu system to extract the last two - * parameters of the path and pass them to this function as arguments. - * - * This function also demonstrates a more complex render array in the returned - * values. Instead of just rendering the HTML with a theme('item_list'), the - * list is left unrendered, and a #theme attached to it so that it can be - * rendered as late as possible, giving more parts of the system a chance to - * change it if necessary. - */ -function page_example_arguments($first, $second) { - // Make sure you don't trust the URL to be safe! Always check for exploits. - if (!is_numeric($first) || !is_numeric($second)) { - // We will just show a standard "access denied" page in this case. - drupal_access_denied(); - return; // We actually don't get here. - } - - $list[] = t("First number was @number.", array('@number' => $first)); - $list[] = t("Second number was @number.", array('@number' => $second)); - $list[] = t('The total was @number.', array('@number' => $first + $second)); - - $render_array['page_example_arguments'] = array( - '#theme' => 'item_list', // The theme function to apply to the #items - '#items' => $list, // The list itself. - '#title' => t('Argument Information'), - ); - return $render_array; -} diff --git a/page_example/page_example.test b/page_example/page_example.test deleted file mode 100644 index a806a434e571028626d40d2eafd102b16ab84907..0000000000000000000000000000000000000000 --- a/page_example/page_example.test +++ /dev/null @@ -1,119 +0,0 @@ - 'Page example functionality', - 'description' => 'Creates page and render the content based on the arguments passed in the URL.', - 'group' => 'Examples', - ); - } - - /** - * Enable modules and create user with specific permissions. - */ - function setUp() { - parent::setUp('page_example'); - } - - /** - * Generates a random string of ASCII numeric characters (values 48 to 57). - * - * @param $length - * Length of random string to generate . - * @return - * Randomly generated string. - */ - private static function randomNumber($length = 8) { - $str = ''; - for ($i = 0; $i < $length; $i++) { - $str .= chr(mt_rand(48, 57)); - } - return $str; - } - - /** - * Verify that current user has no access to page. - * - * @param $url - * URL to verify. - */ - function pageExampleVerifyNoAccess($url) { - // Test that page returns 403 Access Denied - $this->drupalGet($url); - $this->assertResponse(403); - } - - /** - * Login user, create an example node, and test blog functionality through the admin and user interfaces. - */ - function testPageExampleBasic() { - - // Verify that anonymous user can't access the pages created by - // page_example module - $this->pageExampleVerifyNoAccess('examples/page_example/simple'); - $this->pageExampleVerifyNoAccess('examples/page_example/arguments/1/2'); - - // Create a regular user and login. - $this->web_user = $this->drupalCreateUser(); - $this->drupalLogin($this->web_user); - - // Verify that regular user can't access the pages created by - // page_example module - $this->pageExampleVerifyNoAccess('examples/page_example/simple'); - $this->pageExampleVerifyNoAccess('examples/page_example/arguments/1/2'); - - // Create a user with permissions to access 'simple' page and login. - $this->web_user = $this->drupalCreateUser(array('access simple page')); - $this->drupalLogin($this->web_user); - - // Verify that user can access simple content - $this->drupalGet('examples/page_example/simple'); - $this->assertResponse(200, t('simple content successfully accessed.')); - $this->assertText(t('The quick brown fox jumps over the lazy dog.'), t('Simple content successfully verified.')); - - // Check if user can't access arguments page - $this->pageExampleVerifyNoAccess('examples/page_example/arguments/1/2'); - - - - // Create a user with permissions to access 'simple' page and login. - $this->web_user = $this->drupalCreateUser(array('access arguments page')); - $this->drupalLogin($this->web_user); - - // Verify that user can access simple content - $first = $this->randomNumber(3); - $second = $this->randomNumber(3); - $this->drupalGet('examples/page_example/arguments/' . $first . '/' . $second); - $this->assertResponse(200, t('arguments content successfully accessed.')); - // Verify argument usage - $this->assertRaw(t("First number was @number.", array('@number' => $first)), t('arguments first argument successfully verified.')); - $this->assertRaw(t("Second number was @number.", array('@number' => $second)), t('arguments second argument successfully verified.')); - $this->assertRaw(t('The total was @number.', array('@number' => $first + $second)), t('arguments content successfully verified.')); - - // Verify incomplete argument call to arguments content - $this->drupalGet('examples/page_example/arguments/' . $first . '/'); - $this->assertText("provides two pages"); - - // Verify invalid argument call to arguments content - $this->drupalGet('examples/page_example/arguments/' . $first . '/' . $this->randomString()); - $this->assertResponse(403, t('Invalid argument for arguments content successfully verified')); - - // Verify invalid argument call to arguments content - $this->drupalGet('examples/page_example/arguments/' . $this->randomString() . '/' . $second); - $this->assertResponse(403, t('Invalid argument for arguments content successfully verified')); - - // Check if user can't access simple page - $this->pageExampleVerifyNoAccess('examples/page_example/simple'); - } -} diff --git a/queue_example/queue_example.css b/queue_example/queue_example.css deleted file mode 100644 index acb456571419a343d46d288ca8cce6b861a78701..0000000000000000000000000000000000000000 --- a/queue_example/queue_example.css +++ /dev/null @@ -1,4 +0,0 @@ - -.form-item-string-to-add, div.form-item-claim-time { - display: inline; -} \ No newline at end of file diff --git a/queue_example/queue_example.info b/queue_example/queue_example.info deleted file mode 100644 index 69b11ef6f2a722360468fb1b99f363703e82597d..0000000000000000000000000000000000000000 --- a/queue_example/queue_example.info +++ /dev/null @@ -1,6 +0,0 @@ - -name = Queue example -description = Examples of using the Drupal Queue API. -package = Example modules -core = 7.x -files[] = queue_example.test diff --git a/queue_example/queue_example.module b/queue_example/queue_example.module deleted file mode 100644 index 1239f40a35e2cafc754ad117b98bbe37a6011b60..0000000000000000000000000000000000000000 --- a/queue_example/queue_example.module +++ /dev/null @@ -1,275 +0,0 @@ - 'Queue Example: Insert and remove', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('queue_example_add_remove_form'), - 'access callback' => TRUE, - ); - - return $items; -} - -/** - * Provides an interface to add items to the queue, to retrieve (claim) - * an item from the head of the queue, and to claim and delete. Also - * allows the user to run cron manually, so that claimed items can be - * released. - */ -function queue_example_add_remove_form($form, &$form_state) { - // Simple counter that makes it possible to put auto-incrementing default - // string into the string to insert. - if (empty($form_state['storage']['insert_counter'])) { - $form_state['storage']['insert_counter'] = 1; - } - - $queue_name = !empty($form_state['values']['queue_name']) ? $form_state['values']['queue_name'] : 'queue_example_first_queue'; - $items = queue_example_retrieve_queue($queue_name); - - // Add CSS to make the form a bit denser. - $form['#attached']['css'] = array(drupal_get_path('module', 'queue_example') . '/queue_example.css'); - - $form['help'] = array( - '#type' => 'markup', - '#markup' => 'Rendered version (light blue):
' . 'Prefixed
'; - $block['#suffix'] = 'Block suffix' . t('Enable the Token module to view the available token browser.', array('@drupal-token' => 'http://drupal.org/project/token')) . '
', - ); - } - - return $form; -} - -/** - * Submit callback; store the submitted values into storage. - */ -function token_example_example_form_submit($form, &$form_state) { - $form_state['storage'] = $form_state['values']; - $form_state['rebuild'] = TRUE; -} - -/** - * Build a list of available content. - */ -function _token_example_get_node() { - if (!user_access('access content') && !user_access('bypass node access')) { - return array(); - } - - $node_query = db_select('node', 'n'); - $node_query->fields('n', array('nid', 'title')); - $node_query->condition('n.status', NODE_PUBLISHED); - $node_query->orderBy('n.created', 'DESC'); - $node_query->range(0, 10); - $node_query->addTag('node_access'); - $nodes = $node_query->execute()->fetchAllKeyed(); - $nodes = array_map('check_plain', $nodes); - return $nodes; -} - -/** - * Build a list of available comments. - */ -function _token_example_get_comment() { - if (!module_exists('comment') || (!user_access('access comments') && !user_access('administer comments'))) { - return array(); - } - - $comment_query = db_select('comment', 'c'); - $comment_query->innerJoin('node', 'n', 'n.nid = c.nid'); - $comment_query->fields('c', array('cid', 'subject')); - $comment_query->condition('n.status', NODE_PUBLISHED); - $comment_query->condition('c.status', COMMENT_PUBLISHED); - $comment_query->orderBy('c.created', 'DESC'); - $comment_query->range(0, 10); - $comment_query->addTag('node_access'); - $comments = $comment_query->execute()->fetchAllKeyed(); - $comments = array_map('check_plain', $comments); - return $comments; -} - -/** - * Build a list of available user accounts. - */ -function _token_example_get_user() { - if (!user_access('access user profiles') && !user_access('administer users')) { - return array(); - } - - $account_query = db_select('users', 'u'); - $account_query->fields('u', array('uid', 'name')); - $account_query->condition('u.uid', 0, '>'); - $account_query->condition('u.status', 1); - $account_query->range(0, 10); - $accounts = $account_query->execute()->fetchAllKeyed(); - $accounts = array_map('check_plain', $accounts); - return $accounts; -} - -/** - * Build a list of available taxonomy terms. - */ -function _token_example_get_taxonomy_term() { - $term_query = db_select('taxonomy_term_data', 'ttd'); - $term_query->fields('ttd', array('tid', 'name')); - $term_query->range(0, 10); - $term_query->addTag('term_access'); - $terms = $term_query->execute()->fetchAllKeyed(); - $terms = array_map('check_plain', $terms); - return $terms; -} - -/** - * Build a list of available files. - */ -function _token_example_get_file() { - $file_query = db_select('file_managed', 'f'); - $file_query->fields('f', array('fid', 'filename')); - $file_query->range(0, 10); - $files = $file_query->execute()->fetchAllKeyed(); - $files = array_map('check_plain', $files); - return $files; -} diff --git a/token_example/token_example.test b/token_example/token_example.test deleted file mode 100644 index 256ec46ff32f218f360a4618ea034a7ff4180b57..0000000000000000000000000000000000000000 --- a/token_example/token_example.test +++ /dev/null @@ -1,63 +0,0 @@ - 'Token example functionality', - 'description' => 'Verify the token example interface.', - 'group' => 'Examples', - 'dependencies' => array('token'), - ); - } - - function setUp() { - parent::setUp('token_example'); - $this->web_user = $this->drupalCreateUser(); - $this->drupalLogin($this->web_user); - } - - function testInterface() { - $filtered_id = db_query("SELECT format FROM {filter_format} WHERE name = 'Filtered HTML'")->fetchField(); - $plain_id = db_query("SELECT format FROM {filter_format} WHERE name = 'Plain text'")->fetchField(); - - $this->drupalGet('examples/token'); - $this->assertNoFieldByName('node'); - $this->assertNoFieldByName('user'); - - $edit = array( - 'text' => 'User [current-user:name] is trying the token example!', - ); - $this->drupalPost(NULL, $edit, t('Submit')); - $this->assertText('User ' . $this->web_user->name . ' is trying the token example!'); - - // Create a node and then make the 'Plain text' text format the default. - $node = $this->drupalCreateNode(array('title' => 'Example node', 'status' => NODE_PUBLISHED)); - db_update('filter_format') - ->fields(array('weight' => -10)) - ->condition('name', 'Plain text') - ->execute(); - - $this->drupalGet('examples/token'); - $this->assertFieldByName('node'); - - $edit = array( - 'text' => 'Would you like to view the [node:type-name] [node:title] with text format [node:body-format] (ID [node:body-format:id])?', - 'node' => $node->nid, - ); - $this->drupalPost(NULL, $edit, t('Submit')); - $this->assertText('Would you like to view the Basic page Example node with text format Filtered HTML (ID ' . $filtered_id . ')?'); - - $edit = array( - 'text' => 'Your default text format is [default-format:name] (ID [default-format:id]).', - ); - $this->drupalPost(NULL, $edit, t('Submit')); - $this->assertText('Your default text format is Plain text (ID ' . $plain_id . ')'); - } -} diff --git a/token_example/token_example.tokens.inc b/token_example/token_example.tokens.inc deleted file mode 100644 index 462e0c952547dec7dfa66bf9868f67cc71a6e91e..0000000000000000000000000000000000000000 --- a/token_example/token_example.tokens.inc +++ /dev/null @@ -1,129 +0,0 @@ - t('Text formats'), - 'description' => t('Tokens related to text formats.'), - 'needs-data' => 'format', - ); - $info['types']['default-format'] = array( - 'name' => t('Default text format'), - 'description' => t("Tokens related to the currently logged in user's default text format."), - 'type' => 'format', - ); - - // Tokens for the text format token type. - $info['tokens']['format']['id'] = array( - 'name' => t('ID'), - 'description' => t("The unique ID of the text format."), - ); - $info['tokens']['format']['name'] = array( - 'name' => t('Name'), - 'description' => t("The name of the text format."), - ); - - // Node tokens. - $info['tokens']['node']['body-format'] = array( - 'name' => t('Body text format'), - 'description' => t("The name of the text format used on the node's body field."), - 'type' => 'format', - ); - - // Comment tokens. - if (module_exists('comment')) { - $info['tokens']['comment']['body-format'] = array( - 'name' => t('Body text format'), - 'description' => t("The name of the text format used on the comment's body field."), - 'type' => 'format', - ); - } - - return $info; -} - -/** - * Implements hook_tokens(). - */ -function token_example_tokens($type, $tokens, array $data = array(), array $options = array()) { - $replacements = array(); - $sanitize = !empty($options['sanitize']); - - // Text format tokens. - if ($type == 'format' && !empty($data['format'])) { - $format = $data['format']; - - foreach ($tokens as $name => $original) { - switch ($name) { - case 'id': - // Since {filter_format}.format is an integer and not user-entered - // text, it does not need to ever be sanitized. - $replacements[$original] = $format->format; - break; - case 'name': - // Since the format name is user-entered text, santize when requested. - $replacements[$original] = $sanitize ? filter_xss($format->name) : $format->name; - break; - } - } - } - - // Default format tokens. - if ($type == 'default-format') { - $default_id = filter_default_format(); - $default_format = filter_format_load($default_id); - $replacements += token_generate('format', $tokens, array('format' => $default_format), $options); - } - - // Node tokens. - if ($type == 'node' && !empty($data['node'])) { - $node = $data['node']; - - foreach ($tokens as $name => $original) { - switch ($name) { - case 'body-format': - $format = filter_format_load($node->body[LANGUAGE_NONE][0]['format']); - $replacements[$original] = $sanitize ? filter_xss($format->name) : $format->name; - break; - } - } - - // Chained token relationships. - if ($format_tokens = token_find_with_prefix($tokens, 'body-format')) { - $body_format = filter_format_load($node->body[LANGUAGE_NONE][0]['format']); - $replacements += token_generate('format', $format_tokens, array('format' => $body_format), $options); - } - } - - // Comment tokens. - if ($type == 'comment' && !empty($data['comment'])) { - $comment = $data['comment']; - - foreach ($tokens as $name => $original) { - switch ($name) { - case 'body-format': - $format = filter_format_load($comment->comment_body[LANGUAGE_NONE][0]['format']); - $replacements[$original] = $sanitize ? filter_xss($format->name) : $format->name; - break; - } - } - - // Chained token relationships. - if ($format_tokens = token_find_with_prefix($tokens, 'body-format')) { - $body_format = filter_format_load($comment->comment_body[LANGUAGE_NONE][0]['format']); - $replacements += token_generate('format', $format_tokens, array('format' => $body_format), $options); - } - } - - return $replacements; -} diff --git a/trigger_example/CHANGELOG.txt b/trigger_example/CHANGELOG.txt deleted file mode 100644 index f01577f15e2deffd843a971d124705560567c1ae..0000000000000000000000000000000000000000 --- a/trigger_example/CHANGELOG.txt +++ /dev/null @@ -1,2 +0,0 @@ - -#618578 by ilo, rfay: D7 trigger example module diff --git a/trigger_example/trigger_example.info b/trigger_example/trigger_example.info deleted file mode 100644 index b7ee8c351a1443ce336891ad552fdba52ec419ac..0000000000000000000000000000000000000000 --- a/trigger_example/trigger_example.info +++ /dev/null @@ -1,7 +0,0 @@ - -name = Trigger example -description = An example showing how a module can provide triggers that can have actions associated with them. -package = Example modules -core = 7.x -dependencies[] = trigger -files[] = trigger_example.test diff --git a/trigger_example/trigger_example.module b/trigger_example/trigger_example.module deleted file mode 100644 index cac508c033bbd3e1c9e2f76ad162963021508eaf..0000000000000000000000000000000000000000 --- a/trigger_example/trigger_example.module +++ /dev/null @@ -1,312 +0,0 @@ - array( - 'user_first_time_login' => array( - 'label' => t('After a user has logged in for the first time'), - ), - ), - 'trigger_example' => array( - 'triggersomething' => array( - 'label' => t('After the triggersomething button is clicked'), - ), - ), - ); -} - -/** - * Triggers are used most of the time to do something when an event happens. - * The most common type of event is a hook invocation, - * but that is not the only possibility. - * - */ - -/** - * triggersomething trigger: Run actions associated with an arbitrary event. - * - * Here pressing a button is a trigger. We have defined a - * custom function as a trigger (trigger_example_triggersomething). - * It will ask for all actions attached to the 'triggersomething' event, - * prepare a basic 'context' for them - * and run all of them. This could have been implemented by a hook - * implementation, but in this demonstration, it will just be called in a - * form's submit. - * - * This function is executed during the submission of the example form defined - * in this module. - * - * @param array $options arguments used to call the triggersomething function, if any. - */ -function trigger_example_triggersomething($options = array()) { - // Ask the trigger module for all actions enqueued for the 'triggersomething' trigger. - $aids = trigger_get_assigned_actions('triggersomething'); - // prepare a basic context, indicating group and "hook", and call all the - // actions with this context as arguments. - $context = array( - 'group' => 'trigger_example', - 'hook' => 'triggersomething' - ); - actions_do(array_keys($aids), (object) $options, $context); -} - - -/** - * The next trigger is more complex, we are providing a trigger for a - * new event: "user first time login". We need to create this event - * first. - */ - -/** - * Implements hook_user_login(). - * - * User first login trigger: Run actions on user first login. - * - * The event "User first time login" does not exist, we should create it before - * it can be used. We use hook_user_login to be informed when a user logs in and - * try to find if the user has previously logged in before. If the user has not - * accessed previously, we make a call to our trigger function. - * - */ -function trigger_example_user_login(&$edit, $account, $category = NULL) { - // Verify user has never accessed the site: last access was creation date. - if ($account->access == 0) { - // Call the aproppriate trigger function - _trigger_example_first_time_login('user_first_time_login', $edit, $account, $category); - } -} - -/** - * Trigger function for "User first time login" - * - * This trigger is a user-type triggers, so is grouped with other user-type - * triggers. It needs to provide all the context that user-type triggers - * provide. For this example, we are going to copy the trigger.module - * implementation for the 'User has logged in' event. - * - * This function will run all the actions assigned to the - * 'user_first_time_login' trigger. - * - * For testing you can use an update query like this to reset a user to - * "never logged in": - * @code - * update users set access=created where name='test1'; - * @endcode - * - * @param string $hook - * the trigger identification. - * @param array $edit - * modifications for the account object (should be empty). - * @param object $account - * user object that has logged in. - * @param string $category - * category of the profile. - * - */ -function _trigger_example_first_time_login($hook, &$edit, $account, $category = NULL) { - // Keep objects for reuse so that changes actions make to objects can persist. - static $objects; - // Get all assigned actions for the 'user_first_time_login' trigger. - $aids = trigger_get_assigned_actions($hook); - $context = array( - 'group' => 'user', - 'hook' => $hook, - 'form_values' => &$edit, - ); - // Instead of making a call to actions_do for all triggers, doing this loop - // we provide the oportunity for actions to alter the account object, and - // the next action should have this altered account object as argument. - foreach ($aids as $aid => $info) { - $type = $info['type']; - if ($type != 'user') { - if (!isset($objects[$type])) { - $objects[$type] = _trigger_normalize_user_context($type, $account); - } - $context['user'] = $account; - actions_do($aid, $objects[$type], $context); - } - else { - actions_do($aid, $account, $context, $category); - } - } -} - -/** - * Helper functions for the module interface to test the triggersomething trigger. - */ - -/** - * Implements hook_help(). - */ -function trigger_example_help($path, $arg) { - switch ($path) { - case 'examples/trigger_example': - $explanation = t( - 'Click the button on this page to call trigger_example_triggersomething() - and fire the triggersomething event. First, you need to create an action - and assign it to the "After the triggersomething button is clicked" trigger, - or nothing will happen. Use the Actions settings page - and assign these actions to the triggersomething event on the - Triggers settings page.$explanation
"; - case 'admin/structure/trigger/system': - return t('you can assign actions to run everytime an email is sent by Drupal'); - case 'admin/structure/trigger/trigger_example': - $explanation = t( - "A trigger is a system event. For the trigger example, it's just a button-press. - To demonstrate the trigger example, choose to associate the 'display a message to the user' - action with the 'after the triggersomething button is pressed' trigger."); - return "$explanation
"; - } -} - -/** - * Implements hook_menu(). - * - * Provide a form that can be used to fire the module's triggers. - */ -function trigger_example_menu() { - $items['examples/trigger_example'] = array( - 'title' => 'Trigger Example', - 'description' => 'Provides a form to demonstrate the trigger example.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('trigger_example_form'), - 'access callback' => TRUE, - ); - return $items; -} - -/** - * Trigger example test form - * - * Provide a button to run the triggersomething event. - */ -function trigger_example_form($form_state) { - $form['triggersomething'] = array( - '#type' => 'submit', - '#value' => t('Run triggersomething event'), - ); - return $form; -} - -/** - * Submit handler for the trigger_example_form. - */ -function trigger_example_form_submit($form, $form_state) { - // If the user clicked the button, then run the triggersomething trigger. - if ($form_state['values']['op'] == t('Run triggersomething event')) { - trigger_example_triggersomething(); - } -} - - -/** - * Optional usage of hook_trigger_info_aler() - * - * This function is not required to write your own triggers, but it may be - * useful when you want to alter existing triggers. - * - */ - -/** - * Implements hook_trigger_info_alter(). - * - * We call hook_trigger_info_alter when we want to change an existing trigger. - * As mentioned earlier, this hook is not required to create your own triggers, - * and should only be used when you need to alter current existing triggers. In - * this example implementation a little change is done to the existing trigger - * provided by core: 'cron' - * - * @param array $triggers - * Array of trigger information returned by hook_trigger_info() - * implementations. - * - * @see hook_trigger_info() - */ -function trigger_example_trigger_info_alter(&$triggers) { - // Make a simple change to an existing core trigger, altering the label - // "When cron runs" to our custom label "On cron execution" - $triggers['system']['cron']['label'] = t('On cron execution'); -} diff --git a/trigger_example/trigger_example.test b/trigger_example/trigger_example.test deleted file mode 100644 index adac43b8c50965c2d129b9ca66515f1ba75290eb..0000000000000000000000000000000000000000 --- a/trigger_example/trigger_example.test +++ /dev/null @@ -1,78 +0,0 @@ - 'Trigger example', - 'description' => 'Perform various tests on trigger_example module.' , - 'group' => 'Examples', - ); - } - - function setUp() { - parent::setUp('trigger', 'trigger_example'); - } - - /** - * Test assigning a configurable action to the triggersomething event. - */ - function testTriggersomethingEvent() { - // Create an administrative user. - $test_user = $this->drupalCreateUser(array('administer actions')); - $this->drupalLogin($test_user); - - // Create a configurable action for display a message to the user - $hash = drupal_hash_base64('system_message_action'); - $action_label = $this->randomName(); - $edit = array( - 'actions_label' => $action_label, - 'message' => $action_label, - ); - $this->drupalPost('admin/config/system/actions/configure/' . $hash, $edit, t('Save')); - $aid = db_query('SELECT aid FROM {actions} WHERE callback = :callback', array(':callback' => 'system_message_action'))->fetchField(); - // $aid is likely 3 but if we add more uses for the sequences table in - // core it might break, so it is easier to get the value from the database. - $edit = array('aid' => drupal_hash_base64($aid)); - - // Note that this only works because there's just one item on the page. - $this->drupalPost('admin/structure/trigger/trigger_example', $edit, t('Assign')); - - // Request triggersomething form and submit. - $this->drupalPost('examples/trigger_example', array(), t('Run triggersomething event')); - // Verify the message is shown to the user. - $this->assertText($action_label, t('The triggersomething event executed the action.')); - } - - function testUserLogin() { - // Create an administrative user. - $admin_user = $this->drupalCreateUser(array('administer actions')); - $this->drupalLogin($admin_user); - - // Create a configurable action for display a message to the user - $hash = drupal_hash_base64('system_message_action'); - $action_label = $this->randomName(); - $edit = array( - 'actions_label' => $action_label, - 'message' => $action_label, - ); - $this->drupalPost('admin/config/system/actions/configure/' . $hash, $edit, t('Save')); - $aid = db_query('SELECT aid FROM {actions} WHERE callback = :callback', array(':callback' => 'system_message_action'))->fetchField(); - $edit = array('aid' => drupal_hash_base64($aid)); - - // Find the correct trigger - $this->drupalPost('admin/structure/trigger/user', $edit, t('Assign'), array(), array(), 'trigger-user-first-time-login-assign-form'); - - $test_user = $this->drupalCreateUser(); - $this->drupalLogin($test_user); - $this->assertText($action_label); - } -} diff --git a/vertical_tabs_example/vertical_tabs_example.info b/vertical_tabs_example/vertical_tabs_example.info deleted file mode 100644 index a61ba4561cd87715505eb1f9d6fdede3220323a6..0000000000000000000000000000000000000000 --- a/vertical_tabs_example/vertical_tabs_example.info +++ /dev/null @@ -1,4 +0,0 @@ -name = Vertical tabs example -description = Show how to use vertical tabs for enhancing user experience. -core = 7.x -package = Example modules diff --git a/vertical_tabs_example/vertical_tabs_example.js b/vertical_tabs_example/vertical_tabs_example.js deleted file mode 100644 index 9aea6e815dee13963f46232c0b21a41aaa2faa59..0000000000000000000000000000000000000000 --- a/vertical_tabs_example/vertical_tabs_example.js +++ /dev/null @@ -1,24 +0,0 @@ - -(function ($) { - -/** - * Custom summary for the module vertical tab. - */ -Drupal.behaviors.vertical_tabs_exampleFieldsetSummaries = { - attach: function (context) { - // Use the fieldset class to identify the vertical tab element - $('fieldset#edit-vertical-tabs-example', context).drupalSetSummary(function (context) { - // Depending on the checkbox status, the settings will be customized, so - // update the summary with the custom setting textfield string or a use a - // default string. - if ($('#edit-vertical-tabs-example-enabled', context).attr('checked')) { - return Drupal.checkPlain($('#edit-vertical-tabs-example-custom-setting', context).val()); - } - else { - return Drupal.t('Using default'); - } - }); - } -}; - -})(jQuery); diff --git a/vertical_tabs_example/vertical_tabs_example.module b/vertical_tabs_example/vertical_tabs_example.module deleted file mode 100644 index fc125363f58062ab9ed8d5bc34a9ad4c80ad001b..0000000000000000000000000000000000000000 --- a/vertical_tabs_example/vertical_tabs_example.module +++ /dev/null @@ -1,89 +0,0 @@ - 'Vertical tabs example', - 'description' => 'Shows how vertical tabs can best be supported by a custom module', - 'page callback' => '_vertical_tabs_example_explanation', - 'access callback' => TRUE, - ); - return $items; -} - -/** - * Implement hook_form_alter(). - * - * Adds custom fieldset to the node form, and attach ajax behaviour for vertical - * panels to update the settings description. - */ -function vertical_tabs_example_form_alter(&$form, $form_state, $form_id) { - // Only include on node add/edit forms. - if (!empty($form['#node_edit_form'])) { - - $form['vertical_tabs_example'] = array( - '#type' => 'fieldset', - '#title' => t('Example vertical tab'), - '#collapsible' => TRUE, - '#collapsed' => FALSE, - // The #group value must match the name of the vertical tabs element. - // In most cases, this is 'additional_settings'. - '#group' => 'additional_settings', - // Attach the javascript for vertical tabs. - '#attached' => array( - 'js' => array( - 'vertical-tabs' => drupal_get_path('module', 'vertical_tabs_example') . '/vertical_tabs_example.js', - ), - ), - '#tree' => TRUE, - '#weight' => -2, - ); - - // This checkbox is used to show or hide the custom settings form using - // javascript (altering states of a container defined later). - $form['vertical_tabs_example']['enabled'] = array( - '#type' => 'checkbox', - '#title' => t('Use custom configuration'), - '#default_value' => FALSE, - ); - - // This container will be used to store the whole form for our custom - // settings. This way, showing/hidding the form using javascript is easier, - // as only one element should be set visible. - $form['vertical_tabs_example']['vertical_tabs_examplecontainer'] = array( - '#type' => 'container', - '#parents' => array('vertical_tabs_example'), - '#states' => array( - 'invisible' => array( - // If the checkbox is not enabled, show the container. - 'input[name="vertical_tabs_example[enabled]"]' => array('checked' => FALSE), - ), - ), - ); - - // The string of this textfield will be shown as summary in the vertical - // tab. - $form['vertical_tabs_example']['vertical_tabs_examplecontainer']['custom_setting'] = array( - '#type' => 'textfield', - '#title' => t('Use this custom setting'), - '#default_value' => '', - '#description' => t('This field is a demonstration about how to use Vertical Tabs in your forms. This setting will not be saved.'), - ); - } -} - -/** - * Simple explanation page. - */ -function _vertical_tabs_example_explanation() { - return t("The Vertical Tabs Example shows how a custom module can best support vertical tabs. To see the effects of this module, look at the node/add form", array('!node_add' => url('node/add'))); -} diff --git a/xmlrpc_example/xmlrpc_example.info b/xmlrpc_example/xmlrpc_example.info deleted file mode 100644 index 8e288127b3e8bd919a866a865a56f989725f2c46..0000000000000000000000000000000000000000 --- a/xmlrpc_example/xmlrpc_example.info +++ /dev/null @@ -1,6 +0,0 @@ - -name = XMLRPC example -description = This is an example of how to implement client and server communications using XML-RPC. -package = Example modules -core = 7.x -files[] = xmlrpc_example.test diff --git a/xmlrpc_example/xmlrpc_example.module b/xmlrpc_example/xmlrpc_example.module deleted file mode 100644 index 225624cd8162a525e2842fa4a6f9f0f8901d3ab3..0000000000000000000000000000000000000000 --- a/xmlrpc_example/xmlrpc_example.module +++ /dev/null @@ -1,647 +0,0 @@ - 'XML-RPC Example', - 'description' => 'Information about the XML-RPC example', - 'page callback' => 'xmlrpc_example_info', - 'access callback' => TRUE, - ); - // This is the server configuration form menu entry. This form can be used to - // configure the settings of the exposed services. An XML-RPC server does not - // require a configuration form, and has been included here as an example. - $items['examples/xmlrpc/server'] = array( - 'title' => 'XML-RPC Server configuration', - 'description' => 'Server configuration form', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('xmlrpc_example_server_form'), - 'access callback' => TRUE, - 'weight' => 0, - ); - // This is the client form menu entry. This form is used to allow user - // interaction with the services, but again, user interface is not required - // to create an XML-RPC client with Drupal. - $items['examples/xmlrpc/client'] = array( - 'title' => 'XML-RPC Client form', - 'description' => 'Demonstrates client side XML-RPC calls with Drupal', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('xmlrpc_example_client_form'), - 'access callback' => TRUE, - 'weight' => 1, - ); - // This part is completely optional. It will allow the modification of services - // defined by this or other modules. This configuration form is used to - // enable the hook_xmlrpc_alter API and alter current existing services - $items['examples/xmlrpc/alter'] = array( - 'title' => 'XML-RPC Alterations', - 'description' => 'Demonstrates how to alter defined XML-RPC services', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('xmlrpc_example_alter_form'), - 'access callback' => TRUE, - 'weight' => 2, - ); - return $items; -} - -/** - * A simple landing-page information function. - */ -function xmlrpc_example_info() { - $server = url($GLOBALS['base_url'] . '/xmlrpc.php', array('external' => TRUE)); - - $options = array( - 'system.listMethods' => array(), - ); - // Make the xmlrpc request and process the results. - $supported_methods = xmlrpc($server, $options); - if ($supported_methods === FALSE) { - drupal_set_message(t('Error return from xmlrpc(): Error: @errno, Message: @message', array('@errno' => xmlrpc_errno(), '@message' => xmlrpc_error_msg()))); - } - - return array( - 'basic' => array('#markup' => t('This XML-RPC example presents code that shows ', array('!server' => url('examples/xmlrpc/server'), '!client' => url('examples/xmlrpc/client'), '!alter' => url('examples/xmlrpc/alter')))), - 'method_array' => array('#markup' => theme('item_list', array('title' => t('These methods are supported by !server', array('!server' => $server)), 'items' => $supported_methods))), - ); -} - -// This is the server part of the module, implementing a simple and little -// server with just two simple services. The server is divided in two -// different parts: the XML-RPC implementation (required) and a webform -// interface (optional) to configure some settings in the server side. -// -// The XMLRPC server will define two different services: -// -// - subtract: perform the subtraction of two numbers. The minimum and maximum -// values returned by the server can be configured in the server configuration -// form. -// - add: perform the addition of two numbers. The minimum and maximum values -// returned by the server can be configured in the server configuration form. -// -// If the result value for the operation is over the maximum limit, a custom -// error number 10001 is returned. This is an arbitrary number and could be any -// number. -// -// If the result value for the operation is below the minimum limit, a custom -// error number 10002 is returned. Again, this value is arbitrary and could be -// any other number. Client applications must know the meaning of the error -// numbers returned by the server. - -// The following code is the XML-RPC implementation of the server part. The first -// step is to define the methods. This methods should be associated to callbacks -// that will be defined later. - -/** - * Implements hook_xmlrpc(). - * - * Provides Drupal with an array to map XML-RPC callbacks to existing functions. - * These functions may be defined in other modules. The example implementation - * defines specific functions for the example services. - * - * Note: Drupal's built-in XML-RPC server already includes several methods by - * default: - * - * Service dicovery methods: - * - system.listMethods: return a list of the methods the server has, by name. - * - system.methodSignature: return a description of the argument format a - * - system.methodHelp: returns a text description of a particular method. - * particular method expects. - * - * Other: - * - system.multicall: perform several method calls in a single xmlrpc request. - * - system.getCapabilities: determine if a given capability is supported. - * - * The methods defined by hook_xmlrpc() will be added to those provided by - * default by Drupal's XML-RPC server. - * - * @see hook_xmlrpc() - */ -function xmlrpc_example_xmlrpc() { - $methods[] = array( - // First argument is the method name. - 'xmlrpc_example.add', - // Callback to execute when this method is requested. - '_xmlrpc_example_server_add', - // An array defines the types of output and input values for this method. - array( - // The first value is the return type, an integer in this case. - 'int', - // First operand is an integer. - 'int', - // Second operatnd is an integer. - 'int', - ), - // Include a little description that is shown when XML-RPC server is - // requested for the implemented methods list. - t('Returns the sum of the two arguments.') // Method description - ); - // The subtract method is similar to the addition, only the method name, - // callback and description are different. - $methods[] = array( - 'xmlrpc_example.subtract', - '_xmlrpc_example_server_subtract', - array('int', 'int', 'int'), - t('Return difference of the two arguments.') - ); - - return $methods; -} - -// The following code for the server is optional if the callbacks already exist. -// A server may implement methods associated to callbacks like node_load(), -// variable_get() or any other existing function (php functions as well). -// -// If the callbacks associated to the methods don't exist they must be -// created. This implementation requires two specific callbacks: -// - _xmlrpc_example_server_add() -// - _xmlrpc_example_server_subtract() -// - -/** - * This is the callback for the xmlrpc_example.add method. - * - * Sum the two arguments and return value or an error if the result is out of the - * configured limits. - * - * @param $num1 - * The first number to be summed. - * @param $num2 - * The second number to be summed. - * @return - * The sum of the arguments, or error if it is not in server defined bounds. - * - * @see xmlrpc_error() - */ -function _xmlrpc_example_server_add($num1, $num2) { - $sum = $num1 + $num2; - // If result is not within maximum and minimum limits, return corresponding error - $max = variable_get('xmlrpc_example_server_max', 10); - $min = variable_get('xmlrpc_example_server_min', 0); - if ($sum > $max) { - return xmlrpc_error(10001, t('Result is over the upper limit (@max) defined by the server.', array('@max' => $max))); - } - if ($sum < $min) { - return xmlrpc_error(10002, t('Result is below the lower limit defined by the server (@min).', array('@min' => $min))); - } - // Otherwise return the result. - return $sum; -} - -/** - * This is the callback for the xmlrpc_example.subtract xmlrpc method. - * - * Return the difference of the two arguments, or an error if the result is out of the - * configured limits.. - * - * - * @param numeric $num1 - * @param numeric $num2 - * @return - * The difference of the two arguments, or error if it is not in server defined bounds. - * - * @see xmlrpc_error() - */ -function _xmlrpc_example_server_subtract($num1, $num2) { - $diference = $num1 - $num2; - $max = variable_get('xmlrpc_example_server_max', 10); - $min = variable_get('xmlrpc_example_server_min', 0); - - // If result is not within maximum and minimum limits, return corresponding error - if ($diference > $max) { - return xmlrpc_error(10001, t('Result is above the upper limit (@max) defined by the server.', array('@max' => $max))); - } - if ($diference < $min) { - return xmlrpc_error(10002, t('Result is below the lower limit (@min) defined by the server.', array('@min' => $min))); - } - // Otherwise return the result. - return $diference; -} - -// User interface for the XML-RPC Server part. -// A server does not require an interface at all. In this implementation we -// use a server configuration form to set the limits available for the addition -// and subtraction operations. - -/** - * Present a form to configure the service options. In this case the maximum - * and minimum values for any of the operations (add or subtraction). - */ -function xmlrpc_example_server_form() { - $form = array(); - $form['explanation'] = array( - '#markup' => '@response', - array('@response' => print_r($result, TRUE))) - ); - } -} - -/** - * Submit: query the XML-RPC endpoint for the method xmlrpc_example.add - * and report the result as a Drupal message. - * - * @param $form - * @param $form_state - * - * @see xmlrpc() - * @see xmlrpc_errno() - * @see xmlrpc_error_msg() - */ -function xmlrpc_example_client_add_submit($form, &$form_state) { - // First define the endpoint of the XML-RPC service, in this case is our - // own server. - $server = url($GLOBALS['base_url'] . '/xmlrpc.php', array('external' => TRUE)); - // Then we should define the method to call. xmlrpc() requires that all the - // information related to the called method is passed as an array in the form - // of 'method_name' => arguments_array - $options = array( - 'xmlrpc_example.add' => array( - (int) $form_state['values']['num1'], - (int) $form_state['values']['num2'], - ), - ); - // Make the xmlrpc request and process the results. - $result = xmlrpc($server, $options); - if ($result === FALSE) { - drupal_set_message( - t('Error return from xmlrpc(): Error: @errno, Message: @message', - array('@errno' => xmlrpc_errno(), '@message' => xmlrpc_error_msg())), - 'error' - ); - } - else { - drupal_set_message( - t('The XML-RPC server returned this response: @response', - array('@response' => print_r($result, TRUE))) - ); - } -} - -/** - * Submit: query the XML-RPC endpoint for the method xmlrpc_example.subtract - * and report the result as a Drupal message. - * - * @param $form - * @param $form_state - * - * @see xmlrpc() - * @see xmlrpc_errno() - * @see xmlrpc_error_msg() - * @see xmlrpc_example_client_add_submit() - */ -function xmlrpc_example_client_subtract_submit($form, &$form_state) { - $server = url($GLOBALS['base_url'] . '/xmlrpc.php', array('external' => TRUE)); - $options = array( - 'xmlrpc_example.subtract' => array( - (int) $form_state['values']['num1'], - (int) $form_state['values']['num2'], - ), - ); - // Make the xmlrpc request and process the results. - $result = xmlrpc($server, $options); - if ($result === FALSE) { - drupal_set_message( - t('Error return from xmlrpc(): Error: @errno, Message: @message', - array('@errno' => xmlrpc_errno(), '@message' => xmlrpc_error_msg())), - 'error' - ); - } - else { - drupal_set_message( - t('The XML-RPC server returned this response: @response', - array('@response' => print_r($result, TRUE))) - ); - } -} - -/** - * Submit a multicall request: query the XML-RPC endpoint for the methods - * xmlrpc_example.add and xmlrpc_example.subtract and report the result as a - * Drupal message. Drupal's XML-RPC client builds the system.multicall request - * automatically when there is more than one method to call. - * - * @param $form - * @param $form_state - * - * @see xmlrpc() - * @see xmlrpc_errno() - * @see xmlrpc_error_msg() - * @see xmlrpc_example_client_multicall_submit() - */ -function xmlrpc_example_client_multicall_submit($form, &$form_state) { - $server = url($GLOBALS['base_url'] . '/xmlrpc.php', array('external' => TRUE)); - - /* - * Drupal's built-in xmlrpc server supports the system.multicall method. - * - * To make a multicall request, the main invoked method should be the - * function 'system.multicall', and the arguments to make this call must be - * defined as an array of single method calls, being the array keys the - * service methods to be called, and the array elements the method arguments. - * - * See the code below this comment as example. - */ - - // Build an array of several calls, Drupal's xmlrpc built-in support will - // construct the correct system.multicall request for the server. - $options = array( - 'xmlrpc_example.add' => array( - (int) $form_state['values']['num1'], - (int) $form_state['values']['num2'], - ), - 'xmlrpc_example.subtract' => array( - (int) $form_state['values']['num1'], - (int) $form_state['values']['num2'], - ), - ); - // Make the xmlrpc request and process the results. - $result = xmlrpc($server, $options); - - if ($result === FALSE) { - drupal_set_message( - t('Error return from xmlrpc(): Error: @errno, Message: @message', - array('@errno' => xmlrpc_errno(), '@message' => xmlrpc_error_msg())) - ); - } - else { - drupal_set_message( - t('The XML-RPC server returned this response:
@response', - array('@response' => print_r($result, TRUE))) - ); - } -} - -// The client part of the module ends here. - -// The alteration part of the module starts here. hook_xmlrpc_alter() is -// useful when you want to extend, limit or alter methods defined by other -// modules. This part is not required to have an XML-RPC server or client -// working, but is useful to understand what can we do using current xmlrpc -// API provided by drupal. -// -// This code can be defined in other module to alter the methods exposed by -// this xmlrpc demonstration server, or can be used to alter methods defined -// by other modules implementing hook_xmlrpc() -// -// As with the rest of the example module, an user interface is not required to -// make use of this hook. A configuration form is included to enable/disable -// this functionality, but this part is optional if you want to implement -// hook_xmlrpc_alter() - - -// This is the XML-RPC code for the alteration part. It will check if an option -// to enable the functionality is enabled and then alter it. We alter the -// 'xmlrpc_example.add' and 'xmlrpc_example.subtract' methods, changing the -// associated callback with custom functions. The modified methods (with -// new callbacks associated) will perform the addition or subtraction of the -// integer inputs, but will never check for limits nor return errors. - -/** - * Implements hook_xmlrpc_alter(). - * - * Check to see if xmlrpc_example.add and xmlrpc_example.subtract methods are - * defined and replace their callbacks with custom code. - * - * @see hook_xmlrpc_alter() - */ -function xmlrpc_example_xmlrpc_alter(&$methods) { - - // Only perform alterations if instructed to do so. - if (!variable_get('xmlrpc_example_alter_enabled', 0)) { - return; - } - // Loop all defined methods (other modules may have include additional methods) - foreach ($methods as $index => $method) { - // First element in the method array is the method name. - if ($method[0] == 'xmlrpc_example.add') { - // Replace current callback with custom callback (second argument of the array) - $methods[$index][1] = '_xmlrpc_example_alter_add'; - } - // Do the same for the substraction method. - if ($method[0] == 'xmlrpc_example.subtract') { - $methods[$index][1] = '_xmlrpc_example_alter_subtract'; - } - } -} - -// Now we define the custom callbacks replacing the original defined by the -// altered methods: xmlrpc_example.add and _xmlrpc_example.subtract . These -// new callbacks will not check if the result of the operation is within the -// limits defined by the server and will always return the value of the operation. - -/** - * Sum the two arguments without limit checking. - * - * This is the replacement callback for the xmlrpc_example.add xmlrpc method. - * - * @param $num1 - * @param $num2 - * @return - * The sum of the arguments - */ -function _xmlrpc_example_alter_add($num1, $num2) { - return $num1 + $num2; -} - -/** - * Return the difference of the two arguments without limit checking. - * - * This is the replacement callback for the xmlrpc_example.subtract xmlrpc method. - * - * @param numeric $num1 - * @param numeric $num2 - * @return - * The difference of the two arguments - */ -function _xmlrpc_example_alter_subtract($num1, $num2) { - return $num1 - $num2; -} - - -// Our implementation of hook_xmlrpc_alter will work only if a system variable -// is set to true, and we need a configuration form to enable/disable this -// 'feature'. This is the user interface to enable or disable the hook_xmlrpc_alter -// operations. - -/** - * Present a form to enable or disable the code implemented in hook_xmlrpc_alter. - */ -function xmlrpc_example_alter_form() { - $form = array(); - $form['explanation'] = array( - '#markup' => '