@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Right-to-Left styles for theme in the Aggregator module.
|
||||
*/
|
||||
|
||||
#aggregator .feed-source .feed-icon {
|
||||
float: left;
|
||||
|
@@ -2,11 +2,11 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Admin page callbacks for the aggregator module.
|
||||
* Administration page callbacks for the Aggregator module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Menu callback; displays the aggregator administration page.
|
||||
* Page callback: Displays the Aggregator module administration page.
|
||||
*/
|
||||
function aggregator_admin_overview() {
|
||||
return aggregator_view();
|
||||
@@ -16,7 +16,7 @@ function aggregator_admin_overview() {
|
||||
* Displays the aggregator administration page.
|
||||
*
|
||||
* @return
|
||||
* The page HTML.
|
||||
* A HTML-formatted string with administration page content.
|
||||
*/
|
||||
function aggregator_view() {
|
||||
$result = db_query('SELECT f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.hash, f.etag, f.modified, f.image, f.block, COUNT(i.iid) AS items FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.hash, f.etag, f.modified, f.image, f.block ORDER BY f.title');
|
||||
@@ -56,8 +56,8 @@ function aggregator_view() {
|
||||
* Form constructor for adding and editing feed sources.
|
||||
*
|
||||
* @param $feed
|
||||
* If editing a feed, the feed to edit as a PHP stdClass value; if adding a
|
||||
* new feed, NULL.
|
||||
* (optional) If editing a feed, the feed to edit as a PHP stdClass value; if
|
||||
* adding a new feed, NULL. Defaults to NULL.
|
||||
*
|
||||
* @ingroup forms
|
||||
* @see aggregator_form_feed_validate()
|
||||
@@ -165,6 +165,7 @@ function aggregator_form_feed_validate($form, &$form_state) {
|
||||
* Form submission handler for aggregator_form_feed().
|
||||
*
|
||||
* @see aggregator_form_feed_validate()
|
||||
*
|
||||
* @todo Add delete confirmation dialog.
|
||||
*/
|
||||
function aggregator_form_feed_submit($form, &$form_state) {
|
||||
@@ -398,7 +399,7 @@ function _aggregator_parse_opml($opml) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; refreshes a feed, then redirects to the overview page.
|
||||
* Page callback: Refreshes a feed, then redirects to the overview page.
|
||||
*
|
||||
* @param $feed
|
||||
* An object describing the feed to be refreshed.
|
||||
@@ -590,6 +591,7 @@ function aggregator_form_category_validate($form, &$form_state) {
|
||||
* Form submission handler for aggregator_form_category().
|
||||
*
|
||||
* @see aggregator_form_category_validate()
|
||||
*
|
||||
* @todo Add delete confirmation dialog.
|
||||
*/
|
||||
function aggregator_form_category_submit($form, &$form_state) {
|
||||
|
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Styles for theme in the Aggregator module.
|
||||
*/
|
||||
|
||||
#aggregator .feed-source .feed-title {
|
||||
margin-top: 0;
|
||||
|
@@ -7,8 +7,8 @@ files[] = aggregator.test
|
||||
configure = admin/config/services/aggregator/settings
|
||||
stylesheets[all][] = aggregator.css
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -266,13 +266,13 @@ function aggregator_menu() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Title callback: Returns a title for aggregatory category pages.
|
||||
* Title callback: Returns a title for aggregator category pages.
|
||||
*
|
||||
* @param $category
|
||||
* An aggregator category.
|
||||
*
|
||||
* @return
|
||||
* An aggregator category title.
|
||||
* A string with the aggregator category title.
|
||||
*/
|
||||
function _aggregator_category_title($category) {
|
||||
return $category['title'];
|
||||
@@ -723,7 +723,7 @@ function theme_aggregator_block_item($variables) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely renders HTML content, as allowed.
|
||||
* Renders the HTML content safely, as allowed.
|
||||
*
|
||||
* @param $value
|
||||
* The content to be filtered.
|
||||
@@ -739,7 +739,7 @@ function aggregator_filter_xss($value) {
|
||||
* Checks and sanitizes the aggregator configuration.
|
||||
*
|
||||
* Goes through all fetchers, parsers and processors and checks whether they
|
||||
* are available. If one is missing resets to standard configuration.
|
||||
* are available. If one is missing, resets to standard configuration.
|
||||
*
|
||||
* @return
|
||||
* TRUE if this function resets the configuration; FALSE if not.
|
||||
@@ -775,7 +775,7 @@ function aggregator_sanitize_configuration() {
|
||||
* Items count.
|
||||
*
|
||||
* @return
|
||||
* Plural-formatted "@count items"
|
||||
* A string that is plural-formatted as "@count items".
|
||||
*/
|
||||
function _aggregator_items($count) {
|
||||
return format_plural($count, '1 item', '@count items');
|
||||
|
@@ -2,14 +2,14 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* User page callbacks for the aggregator module.
|
||||
* User page callbacks for the Aggregator module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Menu callback; displays the most recent items gathered from any feed.
|
||||
* Page callback: Displays the most recent items gathered from any feed.
|
||||
*
|
||||
* @return
|
||||
* The items HTML.
|
||||
* The rendered list of items for the feed.
|
||||
*/
|
||||
function aggregator_page_last() {
|
||||
drupal_add_feed('aggregator/rss', variable_get('site_name', 'Drupal') . ' ' . t('aggregator'));
|
||||
@@ -20,13 +20,15 @@ function aggregator_page_last() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; displays all the items captured from a particular feed.
|
||||
* Page callback: Displays all the items captured from the particular feed.
|
||||
*
|
||||
* @param $feed
|
||||
* The feed for which to display all items.
|
||||
*
|
||||
* @return
|
||||
* The rendered list of items for a feed.
|
||||
*
|
||||
* @see aggregator_menu()
|
||||
*/
|
||||
function aggregator_page_source($feed) {
|
||||
drupal_set_title($feed->title);
|
||||
@@ -40,13 +42,13 @@ function aggregator_page_source($feed) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; displays a form with all items captured from a feed.
|
||||
* Page callback: Displays a form with all items captured from a feed.
|
||||
*
|
||||
* @param $feed
|
||||
* The feed for which to list all the aggregated items.
|
||||
* The feed for which to list all of the aggregated items.
|
||||
*
|
||||
* @return
|
||||
* The rendered list of items for a feed.
|
||||
* The rendered list of items for the feed.
|
||||
*
|
||||
* @see aggregator_page_source()
|
||||
*/
|
||||
@@ -55,13 +57,13 @@ function aggregator_page_source_form($form, $form_state, $feed) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; displays all the items aggregated in a particular category.
|
||||
* Page callback: Displays all the items aggregated in a particular category.
|
||||
*
|
||||
* @param $category
|
||||
* The category for which to list all the aggregated items.
|
||||
* The category for which to list all of the aggregated items.
|
||||
*
|
||||
* @return
|
||||
* The rendered list of items for a category.
|
||||
* The rendered list of items for the feed.
|
||||
*/
|
||||
function aggregator_page_category($category) {
|
||||
drupal_add_feed('aggregator/rss/' . $category['cid'], variable_get('site_name', 'Drupal') . ' ' . t('aggregator - @title', array('@title' => $category['title'])));
|
||||
@@ -74,13 +76,13 @@ function aggregator_page_category($category) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; displays a form containing items aggregated in a category.
|
||||
* Page callback: Displays a form containing items aggregated in a category.
|
||||
*
|
||||
* @param $category
|
||||
* The category for which to list all the aggregated items.
|
||||
* The category for which to list all of the aggregated items.
|
||||
*
|
||||
* @return
|
||||
* The rendered list of items for a category.
|
||||
* The rendered list of items for the feed.
|
||||
*
|
||||
* @see aggregator_page_category()
|
||||
*/
|
||||
@@ -166,7 +168,7 @@ function aggregator_feed_items_load($type, $data = NULL) {
|
||||
* The feed source URL.
|
||||
*
|
||||
* @return
|
||||
* The rendered list of items for a feed.
|
||||
* The rendered list of items for the feed.
|
||||
*/
|
||||
function _aggregator_page_list($items, $op, $feed_source = '') {
|
||||
if (user_access('administer news feeds') && ($op == 'categorize')) {
|
||||
@@ -191,10 +193,14 @@ function _aggregator_page_list($items, $op, $feed_source = '') {
|
||||
* @param $items
|
||||
* An array of the feed items.
|
||||
* @param $feed_source
|
||||
* The feed source URL.
|
||||
* (optional) The feed source URL. Defaults to an empty string.
|
||||
*
|
||||
* @return array
|
||||
* An array of FAPI elements.
|
||||
*
|
||||
* @ingroup forms
|
||||
* @see aggregator_categorize_items_submit()
|
||||
* @see theme_aggregator_categorize_items()
|
||||
* @ingroup forms
|
||||
*/
|
||||
function aggregator_categorize_items($items, $feed_source = '') {
|
||||
$form['#submit'][] = 'aggregator_categorize_items_submit';
|
||||
@@ -334,7 +340,12 @@ function template_preprocess_aggregator_item(&$variables) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; displays all the feeds used by the aggregator.
|
||||
* Page callback: Displays all the feeds used by the aggregator.
|
||||
*
|
||||
* @return
|
||||
* An HTML-formatted string.
|
||||
*
|
||||
* @see aggregator_menu()
|
||||
*/
|
||||
function aggregator_page_sources() {
|
||||
$result = db_query('SELECT f.fid, f.title, f.description, f.image, MAX(i.timestamp) AS last FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.description, f.image ORDER BY last DESC, f.title');
|
||||
@@ -358,7 +369,12 @@ function aggregator_page_sources() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; displays all the categories used by the aggregator.
|
||||
* Page callback: Displays all the categories used by the Aggregator module.
|
||||
*
|
||||
* @return string
|
||||
* An HTML formatted string.
|
||||
*
|
||||
* @see aggregator_menu()
|
||||
*/
|
||||
function aggregator_page_categories() {
|
||||
$result = db_query('SELECT c.cid, c.title, c.description FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid LEFT JOIN {aggregator_item} i ON ci.iid = i.iid GROUP BY c.cid, c.title, c.description');
|
||||
@@ -380,7 +396,10 @@ function aggregator_page_categories() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; generate an RSS 0.92 feed of aggregator items or categories.
|
||||
* Page callback: Generates an RSS 0.92 feed of aggregator items or categories.
|
||||
*
|
||||
* @return string
|
||||
* An HTML formatted string.
|
||||
*/
|
||||
function aggregator_page_rss() {
|
||||
$result = NULL;
|
||||
@@ -448,12 +467,14 @@ function theme_aggregator_page_rss($variables) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; generates an OPML representation of all feeds.
|
||||
* Page callback: Generates an OPML representation of all feeds.
|
||||
*
|
||||
* @param $cid
|
||||
* If set, feeds are exported only from a category with this ID. Otherwise, all feeds are exported.
|
||||
* (optional) If set, feeds are exported only from a category with this ID.
|
||||
* Otherwise, all feeds are exported. Defaults to NULL.
|
||||
*
|
||||
* @return
|
||||
* The output XML.
|
||||
* An OPML formatted string.
|
||||
*/
|
||||
function aggregator_page_opml($cid = NULL) {
|
||||
if ($cid) {
|
||||
@@ -468,14 +489,12 @@ function aggregator_page_opml($cid = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the OPML page for a feed.
|
||||
* Prints the OPML page for the feed.
|
||||
*
|
||||
* @param $variables
|
||||
* An associative array containing:
|
||||
* - feeds: An array of the feeds to theme.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_aggregator_page_opml($variables) {
|
||||
|
@@ -131,6 +131,12 @@ function aggregator_form_aggregator_admin_form_alter(&$form, $form_state) {
|
||||
*
|
||||
* Callback for drupal_map_assoc() within
|
||||
* aggregator_form_aggregator_admin_form_alter().
|
||||
*
|
||||
* @param $length
|
||||
* The desired length of teaser text, in bytes.
|
||||
*
|
||||
* @return
|
||||
* A translated string explaining the teaser string length.
|
||||
*/
|
||||
function _aggregator_characters($length) {
|
||||
return ($length == 0) ? t('Unlimited') : format_plural($length, '1 character', '@count characters');
|
||||
|
@@ -5,6 +5,9 @@
|
||||
* Tests for aggregator.module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines a base class for testing the Aggregator module.
|
||||
*/
|
||||
class AggregatorTestCase extends DrupalWebTestCase {
|
||||
function setUp() {
|
||||
parent::setUp('aggregator', 'aggregator_test');
|
||||
@@ -13,10 +16,15 @@ class AggregatorTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aggregator feed (simulate form submission on admin/config/services/aggregator/add/feed).
|
||||
* Creates an aggregator feed.
|
||||
*
|
||||
* This method simulates the form submission on path
|
||||
* admin/config/services/aggregator/add/feed.
|
||||
*
|
||||
* @param $feed_url
|
||||
* If given, feed will be created with this URL, otherwise /rss.xml will be used.
|
||||
* (optional) If given, feed will be created with this URL, otherwise
|
||||
* /rss.xml will be used. Defaults to NULL.
|
||||
*
|
||||
* @return $feed
|
||||
* Full feed object if possible.
|
||||
*
|
||||
@@ -33,7 +41,7 @@ class AggregatorTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an aggregator feed.
|
||||
* Deletes an aggregator feed.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
@@ -44,10 +52,11 @@ class AggregatorTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a randomly generated feed edit array.
|
||||
* Returns a randomly generated feed edit array.
|
||||
*
|
||||
* @param $feed_url
|
||||
* If given, feed will be created with this URL, otherwise /rss.xml will be used.
|
||||
* (optional) If given, feed will be created with this URL, otherwise
|
||||
* /rss.xml will be used. Defaults to NULL.
|
||||
* @return
|
||||
* A feed array.
|
||||
*/
|
||||
@@ -68,7 +77,7 @@ class AggregatorTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of the randomly created feed array.
|
||||
* Returns the count of the randomly created feed array.
|
||||
*
|
||||
* @return
|
||||
* Number of feed items on default feed created by createFeed().
|
||||
@@ -80,10 +89,13 @@ class AggregatorTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update feed items (simulate click to admin/config/services/aggregator/update/$fid).
|
||||
* Updates the feed items.
|
||||
*
|
||||
* This method simulates a click to
|
||||
* admin/config/services/aggregator/update/$fid.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
* Feed object representing the feed, passed by reference.
|
||||
* @param $expected_count
|
||||
* Expected number of feed items.
|
||||
*/
|
||||
@@ -112,7 +124,7 @@ class AggregatorTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm item removal from a feed.
|
||||
* Confirms an item removal from a feed.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
@@ -123,7 +135,7 @@ class AggregatorTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and remove feed items and ensure that the count is zero.
|
||||
* Adds and removes feed items and ensure that the count is zero.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
@@ -140,7 +152,7 @@ class AggregatorTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull feed categories from aggregator_category_feed table.
|
||||
* Pulls feed categories from {aggregator_category_feed} table.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
@@ -154,7 +166,11 @@ class AggregatorTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull categories from aggregator_category table.
|
||||
* Pulls categories from {aggregator_category} table.
|
||||
*
|
||||
* @return
|
||||
* An associative array keyed by category ID and values are set to the
|
||||
* category names.
|
||||
*/
|
||||
function getCategories() {
|
||||
$categories = array();
|
||||
@@ -165,14 +181,14 @@ class AggregatorTestCase extends DrupalWebTestCase {
|
||||
return $categories;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the feed name and URL is unique.
|
||||
* Checks whether the feed name and URL are unique.
|
||||
*
|
||||
* @param $feed_name
|
||||
* String containing the feed name to check.
|
||||
* @param $feed_url
|
||||
* String containing the feed URL to check.
|
||||
*
|
||||
* @return
|
||||
* TRUE if feed is unique.
|
||||
*/
|
||||
@@ -182,10 +198,11 @@ class AggregatorTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a valid OPML file from an array of feeds.
|
||||
* Creates a valid OPML file from an array of feeds.
|
||||
*
|
||||
* @param $feeds
|
||||
* An array of feeds.
|
||||
*
|
||||
* @return
|
||||
* Path to valid OPML file.
|
||||
*/
|
||||
@@ -223,7 +240,7 @@ EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an invalid OPML file.
|
||||
* Creates an invalid OPML file.
|
||||
*
|
||||
* @return
|
||||
* Path to invalid OPML file.
|
||||
@@ -240,7 +257,7 @@ EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a valid but empty OPML file.
|
||||
* Creates a valid but empty OPML file.
|
||||
*
|
||||
* @return
|
||||
* Path to empty OPML file.
|
||||
@@ -275,7 +292,7 @@ EOF;
|
||||
* Creates sample article nodes.
|
||||
*
|
||||
* @param $count
|
||||
* (optional) The number of nodes to generate.
|
||||
* (optional) The number of nodes to generate. Defaults to five.
|
||||
*/
|
||||
function createSampleNodes($count = 5) {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
@@ -290,7 +307,7 @@ EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests aggregator configuration settings.
|
||||
* Tests functionality of the configuration settings in the Aggregator module.
|
||||
*/
|
||||
class AggregatorConfigurationTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
@@ -321,6 +338,9 @@ class AggregatorConfigurationTestCase extends AggregatorTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding aggregator feeds.
|
||||
*/
|
||||
class AddFeedTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -331,7 +351,7 @@ class AddFeedTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed, ensure that it is unique, check the source, and delete the feed.
|
||||
* Creates and ensures that a feed is unique, checks source, and deletes feed.
|
||||
*/
|
||||
function testAddFeed() {
|
||||
$feed = $this->createFeed();
|
||||
@@ -381,6 +401,9 @@ class AddFeedTestCase extends AggregatorTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the categorize feed functionality in the Aggregator module.
|
||||
*/
|
||||
class CategorizeFeedTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -391,7 +414,7 @@ class CategorizeFeedTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed and make sure you can add more than one category to it.
|
||||
* Creates a feed and makes sure you can add more than one category to it.
|
||||
*/
|
||||
function testCategorizeFeed() {
|
||||
|
||||
@@ -424,6 +447,9 @@ class CategorizeFeedTestCase extends AggregatorTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests functionality of updating the feed in the Aggregator module.
|
||||
*/
|
||||
class UpdateFeedTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -434,7 +460,7 @@ class UpdateFeedTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed and attempt to update it.
|
||||
* Creates a feed and attempts to update it.
|
||||
*/
|
||||
function testUpdateFeed() {
|
||||
$remamining_fields = array('title', 'url', '');
|
||||
@@ -466,6 +492,9 @@ class UpdateFeedTestCase extends AggregatorTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests functionality for removing feeds in the Aggregator module.
|
||||
*/
|
||||
class RemoveFeedTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -476,7 +505,7 @@ class RemoveFeedTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a feed and ensure that all it services are removed.
|
||||
* Removes a feed and ensures that all of its services are removed.
|
||||
*/
|
||||
function testRemoveFeed() {
|
||||
$feed = $this->createFeed();
|
||||
@@ -494,6 +523,9 @@ class RemoveFeedTestCase extends AggregatorTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests functionality of updating a feed item in the Aggregator module.
|
||||
*/
|
||||
class UpdateFeedItemTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -504,7 +536,7 @@ class UpdateFeedItemTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test running "update items" from the 'admin/config/services/aggregator' page.
|
||||
* Tests running "update items" from 'admin/config/services/aggregator' page.
|
||||
*/
|
||||
function testUpdateFeedItem() {
|
||||
$this->createSampleNodes();
|
||||
@@ -564,7 +596,7 @@ class RemoveFeedItemTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test running "remove items" from the 'admin/config/services/aggregator' page.
|
||||
* Tests running "remove items" from 'admin/config/services/aggregator' page.
|
||||
*/
|
||||
function testRemoveFeedItem() {
|
||||
// Create a bunch of test feeds.
|
||||
@@ -592,6 +624,9 @@ class RemoveFeedItemTestCase extends AggregatorTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests categorization functionality in the Aggregator module.
|
||||
*/
|
||||
class CategorizeFeedItemTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -602,6 +637,8 @@ class CategorizeFeedItemTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that children of a feed inherit a defined category.
|
||||
*
|
||||
* If a feed has a category, make sure that the children inherit that
|
||||
* categorization.
|
||||
*/
|
||||
@@ -649,6 +686,9 @@ class CategorizeFeedItemTestCase extends AggregatorTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests importing feeds from OPML functionality for the Aggregator module.
|
||||
*/
|
||||
class ImportOPMLTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -659,7 +699,7 @@ class ImportOPMLTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Open OPML import form.
|
||||
* Opens OPML import form.
|
||||
*/
|
||||
function openImportForm() {
|
||||
db_delete('aggregator_category')->execute();
|
||||
@@ -681,7 +721,7 @@ class ImportOPMLTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit form filled with invalid fields.
|
||||
* Submits form filled with invalid fields.
|
||||
*/
|
||||
function validateImportFormFields() {
|
||||
$before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
@@ -707,7 +747,7 @@ class ImportOPMLTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit form with invalid, empty and valid OPML files.
|
||||
* Submits form with invalid, empty, and valid OPML files.
|
||||
*/
|
||||
function submitImportForm() {
|
||||
$before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
@@ -766,6 +806,9 @@ class ImportOPMLTestCase extends AggregatorTestCase {
|
||||
$this->assertTrue($category, 'Categories are correct.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the import of an OPML file.
|
||||
*/
|
||||
function testOPMLImport() {
|
||||
$this->openImportForm();
|
||||
$this->validateImportFormFields();
|
||||
@@ -773,6 +816,9 @@ class ImportOPMLTestCase extends AggregatorTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests functionality of the cron process in the Aggregator module.
|
||||
*/
|
||||
class AggregatorCronTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -783,7 +829,7 @@ class AggregatorCronTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add feeds update them on cron.
|
||||
* Adds feeds and updates them via cron process.
|
||||
*/
|
||||
public function testCron() {
|
||||
// Create feed and test basic updating on cron.
|
||||
@@ -819,6 +865,9 @@ class AggregatorCronTestCase extends AggregatorTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rendering functionality in the Aggregator module.
|
||||
*/
|
||||
class AggregatorRenderingTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -829,9 +878,9 @@ class AggregatorRenderingTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a feed block to the page and checks its links.
|
||||
* Adds a feed block to the page and checks its links.
|
||||
*
|
||||
* TODO: Test the category block as well.
|
||||
* @todo Test the category block as well.
|
||||
*/
|
||||
public function testBlockLinks() {
|
||||
// Create feed.
|
||||
@@ -890,7 +939,7 @@ class AggregatorRenderingTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed and check that feed's page.
|
||||
* Creates a feed and checks that feed's page.
|
||||
*/
|
||||
public function testFeedPage() {
|
||||
// Increase the number of items published in the rss.xml feed so we have
|
||||
@@ -913,7 +962,7 @@ class AggregatorRenderingTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for feed parsing.
|
||||
* Tests feed parsing in the Aggregator module.
|
||||
*/
|
||||
class FeedParserTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
@@ -933,7 +982,7 @@ class FeedParserTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a feed that uses the RSS 0.91 format.
|
||||
* Tests a feed that uses the RSS 0.91 format.
|
||||
*/
|
||||
function testRSS091Sample() {
|
||||
$feed = $this->createFeed($this->getRSS091Sample());
|
||||
@@ -955,7 +1004,7 @@ class FeedParserTestCase extends AggregatorTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a feed that uses the Atom format.
|
||||
* Tests a feed that uses the Atom format.
|
||||
*/
|
||||
function testAtomSample() {
|
||||
$feed = $this->createFeed($this->getAtomSample());
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = block.test
|
||||
configure = admin/structure/block
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -740,7 +740,7 @@ function _block_load_blocks() {
|
||||
/**
|
||||
* Implements hook_block_list_alter().
|
||||
*
|
||||
* Checks the page, user role, and user-specific visibilty settings.
|
||||
* Checks the page, user role, and user-specific visibility settings.
|
||||
* Removes the block if the visibility conditions are not met.
|
||||
*/
|
||||
function block_block_list_alter(&$blocks) {
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -13,8 +13,8 @@ regions[footer] = Footer
|
||||
regions[highlighted] = Highlighted
|
||||
regions[help] = Help
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = blog.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* @file
|
||||
* Right-to-Left styling for the Book module.
|
||||
*/
|
||||
|
||||
.book-navigation .menu {
|
||||
padding: 1em 3em 0 0;
|
||||
|
@@ -2,11 +2,16 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Admin page callbacks for the book module.
|
||||
* Administration page callbacks for the Book module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns an administrative overview of all books.
|
||||
*
|
||||
* @return string
|
||||
* A HTML-formatted string with the administrative page content.
|
||||
*
|
||||
* @see book_menu()
|
||||
*/
|
||||
function book_admin_overview() {
|
||||
$rows = array();
|
||||
@@ -53,6 +58,8 @@ function book_admin_settings() {
|
||||
|
||||
/**
|
||||
* Form validation handler for book_admin_settings().
|
||||
*
|
||||
* @see book_admin_settings_submit()
|
||||
*/
|
||||
function book_admin_settings_validate($form, &$form_state) {
|
||||
$child_type = $form_state['values']['book_child_type'];
|
||||
@@ -149,7 +156,7 @@ function book_admin_edit_submit($form, &$form_state) {
|
||||
* @param $node
|
||||
* The node of the top-level page in the book.
|
||||
* @param $form
|
||||
* The form that is being modified.
|
||||
* The form that is being modified, passed by reference.
|
||||
*
|
||||
* @see book_admin_edit()
|
||||
*/
|
||||
@@ -184,10 +191,10 @@ function _book_admin_table($node, &$form) {
|
||||
* @param $tree
|
||||
* A subtree of the book menu hierarchy.
|
||||
* @param $form
|
||||
* The form that is being modified.
|
||||
* The form that is being modified, passed by reference.
|
||||
*
|
||||
* @return
|
||||
* The form that is being modified.
|
||||
* The modified form array.
|
||||
*
|
||||
* @see book_admin_edit()
|
||||
*/
|
||||
|
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* @file
|
||||
* Styling for the Book module.
|
||||
*/
|
||||
|
||||
.book-navigation .menu {
|
||||
border-top: 1px solid #888;
|
||||
|
@@ -7,8 +7,8 @@ files[] = book.test
|
||||
configure = admin/content/book/settings
|
||||
stylesheets[all][] = book.css
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Javascript behaviors for the Book module.
|
||||
*/
|
||||
|
||||
|
||||
(function ($) {
|
||||
|
||||
Drupal.behaviors.bookFieldsetSummaries = {
|
||||
|
@@ -221,6 +221,9 @@ function _book_outline_remove_access($node) {
|
||||
*
|
||||
* A node can be removed from a book if it is actually in a book and it either
|
||||
* is not a top-level page or is a top-level page with no children.
|
||||
*
|
||||
* @param $node
|
||||
* The node to remove from the outline.
|
||||
*/
|
||||
function _book_node_is_removable($node) {
|
||||
return (!empty($node->book['bid']) && (($node->book['bid'] != $node->nid) || !$node->book['has_children']));
|
||||
@@ -734,7 +737,7 @@ function book_get_flat_menu($book_link) {
|
||||
* @param $tree
|
||||
* A tree of menu links in an array.
|
||||
* @param $flat
|
||||
* A flat array of the menu links from $tree.
|
||||
* A flat array of the menu links from $tree, passed by reference.
|
||||
*
|
||||
* @see book_get_flat_menu().
|
||||
*/
|
||||
@@ -1062,8 +1065,9 @@ function _book_link_defaults($nid) {
|
||||
* to the structured data but can also simply iterate over all elements and
|
||||
* render them (as in the default template).
|
||||
*
|
||||
* The $variables array contains the following elements:
|
||||
* - book_menus
|
||||
* @param $variables
|
||||
* An associative array containing the following key:
|
||||
* - book_menus
|
||||
*
|
||||
* @see book-all-books-block.tpl.php
|
||||
*/
|
||||
@@ -1079,8 +1083,9 @@ function template_preprocess_book_all_books_block(&$variables) {
|
||||
/**
|
||||
* Processes variables for book-navigation.tpl.php.
|
||||
*
|
||||
* The $variables array contains the following elements:
|
||||
* - book_link
|
||||
* @param $variables
|
||||
* An associative array containing the following key:
|
||||
* - book_link
|
||||
*
|
||||
* @see book-navigation.tpl.php
|
||||
*/
|
||||
@@ -1151,8 +1156,9 @@ function template_preprocess_book_navigation(&$variables) {
|
||||
* Reference to the table of contents array. This is modified in place, so the
|
||||
* function does not have a return value.
|
||||
* @param $exclude
|
||||
* Optional array of menu link ID values. Any link whose menu link ID is in
|
||||
* this array will be excluded (along with its children).
|
||||
* (optional) An array of menu link ID values. Any link whose menu link ID is
|
||||
* in this array will be excluded (along with its children). Defaults to an
|
||||
* empty array.
|
||||
* @param $depth_limit
|
||||
* Any link deeper than this value will be excluded (along with its children).
|
||||
*/
|
||||
@@ -1198,10 +1204,11 @@ function book_toc($bid, $depth_limit, $exclude = array()) {
|
||||
/**
|
||||
* Processes variables for book-export-html.tpl.php.
|
||||
*
|
||||
* The $variables array contains the following elements:
|
||||
* - title
|
||||
* - contents
|
||||
* - depth
|
||||
* @param $variables
|
||||
* An associative array containing the following keys:
|
||||
* - title
|
||||
* - contents
|
||||
* - depth
|
||||
*
|
||||
* @see book-export-html.tpl.php
|
||||
*/
|
||||
@@ -1261,7 +1268,8 @@ function book_export_traverse($tree, $visit_func) {
|
||||
* @param $node
|
||||
* The node that will be output.
|
||||
* @param $children
|
||||
* All the rendered child nodes within the current node.
|
||||
* (optional) All the rendered child nodes within the current node. Defaults
|
||||
* to an empty string.
|
||||
*
|
||||
* @return
|
||||
* The HTML generated for the given node.
|
||||
@@ -1280,9 +1288,10 @@ function book_node_export($node, $children = '') {
|
||||
/**
|
||||
* Processes variables for book-node-export-html.tpl.php.
|
||||
*
|
||||
* The $variables array contains the following elements:
|
||||
* - node
|
||||
* - children
|
||||
* @param $variables
|
||||
* An associative array containing the following keys:
|
||||
* - node
|
||||
* - children
|
||||
*
|
||||
* @see book-node-export-html.tpl.php
|
||||
*/
|
||||
@@ -1294,6 +1303,12 @@ function template_preprocess_book_node_export_html(&$variables) {
|
||||
|
||||
/**
|
||||
* Determine if a given node type is in the list of types allowed for books.
|
||||
*
|
||||
* @param $type
|
||||
* A node type.
|
||||
*
|
||||
* @return
|
||||
* A Boolean TRUE if the node type can be included in books; otherwise, FALSE.
|
||||
*/
|
||||
function book_type_is_allowed($type) {
|
||||
return in_array($type, variable_get('book_allowed_types', array('book')));
|
||||
@@ -1336,7 +1351,7 @@ function book_node_type_update($type) {
|
||||
*
|
||||
* @return
|
||||
* A menu link, with the link translated for rendering and data added from the
|
||||
* {book} table.
|
||||
* {book} table. FALSE if there is an error.
|
||||
*/
|
||||
function book_link_load($mlid) {
|
||||
if ($item = db_query("SELECT * FROM {menu_links} ml INNER JOIN {book} b ON b.mlid = ml.mlid LEFT JOIN {menu_router} m ON m.path = ml.router_path WHERE ml.mlid = :mlid", array(
|
||||
|
@@ -7,6 +7,11 @@
|
||||
|
||||
/**
|
||||
* Menu callback: Prints a listing of all books.
|
||||
*
|
||||
* @return string
|
||||
* A HTML-formatted string with the listing of all books content.
|
||||
*
|
||||
* @see book_menu()
|
||||
*/
|
||||
function book_render() {
|
||||
$book_list = array();
|
||||
@@ -36,6 +41,8 @@ function book_render() {
|
||||
* @return
|
||||
* A string representing the node and its children in the book hierarchy in a
|
||||
* format determined by the $type parameter.
|
||||
*
|
||||
* @see book_menu()
|
||||
*/
|
||||
function book_export($type, $nid) {
|
||||
// Check that the node exists and that the current user has access to it.
|
||||
@@ -79,7 +86,6 @@ function book_export($type, $nid) {
|
||||
*/
|
||||
function book_export_html($nid) {
|
||||
if (user_access('access printer-friendly version')) {
|
||||
$export_data = array();
|
||||
$node = node_load($nid);
|
||||
if (isset($node->book)) {
|
||||
$tree = book_menu_subtree_data($node->book);
|
||||
@@ -100,6 +106,11 @@ function book_export_html($nid) {
|
||||
*
|
||||
* @param $node
|
||||
* The book node for which to show the outline.
|
||||
*
|
||||
* @return string
|
||||
* A HTML-formatted string with the outline form for a single node.
|
||||
*
|
||||
* @see book_menu()
|
||||
*/
|
||||
function book_outline($node) {
|
||||
drupal_set_title($node->title);
|
||||
|
@@ -5,14 +5,37 @@
|
||||
* Tests for book.module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests the functionality of the Book module.
|
||||
*/
|
||||
class BookTestCase extends DrupalWebTestCase {
|
||||
|
||||
/**
|
||||
* A book node.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $book;
|
||||
// $book_author is a user with permission to create and edit books.
|
||||
|
||||
/**
|
||||
* A user with permission to create and edit books.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $book_author;
|
||||
// $web_user is a user with permission to view a book
|
||||
// and access the printer-friendly version.
|
||||
|
||||
/**
|
||||
* A user with permission to view a book and access printer-friendly version.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $web_user;
|
||||
// $admin_user is a user with permission to create and edit books and to administer blocks.
|
||||
|
||||
/**
|
||||
* A user with permission to create and edit books and to administer blocks.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $admin_user;
|
||||
|
||||
public static function getInfo() {
|
||||
@@ -36,7 +59,7 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new book with a page hierarchy.
|
||||
* Creates a new book with a page hierarchy.
|
||||
*/
|
||||
function createBook() {
|
||||
// Create new book.
|
||||
@@ -67,7 +90,7 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test book functionality through node interfaces.
|
||||
* Tests book functionality through node interfaces.
|
||||
*/
|
||||
function testBook() {
|
||||
// Create new book.
|
||||
@@ -106,18 +129,20 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the outline of sub-pages; previous, up, and next; and printer friendly version.
|
||||
* Checks the outline of sub-pages; previous, up, and next.
|
||||
*
|
||||
* Also checks the printer friendly version of the outline.
|
||||
*
|
||||
* @param $node
|
||||
* Node to check.
|
||||
* @param $nodes
|
||||
* Nodes that should be in outline.
|
||||
* @param $previous
|
||||
* Previous link node.
|
||||
* (optional) Previous link node. Defaults to FALSE.
|
||||
* @param $up
|
||||
* Up link node.
|
||||
* (optional) Up link node. Defaults to FALSE.
|
||||
* @param $next
|
||||
* Next link node.
|
||||
* (optional) Next link node. Defaults to FALSE.
|
||||
* @param $breadcrumb
|
||||
* The nodes that should be displayed in the breadcrumb.
|
||||
*/
|
||||
@@ -129,23 +154,23 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
|
||||
// Check outline structure.
|
||||
if ($nodes !== NULL) {
|
||||
$this->assertPattern($this->generateOutlinePattern($nodes), t('Node ' . $number . ' outline confirmed.'));
|
||||
$this->assertPattern($this->generateOutlinePattern($nodes), format_string('Node %number outline confirmed.', array('%number' => $number)));
|
||||
}
|
||||
else {
|
||||
$this->pass(t('Node ' . $number . ' doesn\'t have outline.'));
|
||||
$this->pass(format_string('Node %number does not have outline.', array('%number' => $number)));
|
||||
}
|
||||
|
||||
// Check previous, up, and next links.
|
||||
if ($previous) {
|
||||
$this->assertRaw(l('‹ ' . $previous->title, 'node/' . $previous->nid, array('attributes' => array('class' => array('page-previous'), 'title' => t('Go to previous page')))), t('Previous page link found.'));
|
||||
$this->assertRaw(l('‹ ' . $previous->title, 'node/' . $previous->nid, array('attributes' => array('class' => array('page-previous'), 'title' => t('Go to previous page')))), 'Previous page link found.');
|
||||
}
|
||||
|
||||
if ($up) {
|
||||
$this->assertRaw(l('up', 'node/' . $up->nid, array('attributes' => array('class' => array('page-up'), 'title' => t('Go to parent page')))), t('Up page link found.'));
|
||||
$this->assertRaw(l('up', 'node/' . $up->nid, array('attributes' => array('class' => array('page-up'), 'title' => t('Go to parent page')))), 'Up page link found.');
|
||||
}
|
||||
|
||||
if ($next) {
|
||||
$this->assertRaw(l($next->title . ' ›', 'node/' . $next->nid, array('attributes' => array('class' => array('page-next'), 'title' => t('Go to next page')))), t('Next page link found.'));
|
||||
$this->assertRaw(l($next->title . ' ›', 'node/' . $next->nid, array('attributes' => array('class' => array('page-next'), 'title' => t('Go to next page')))), 'Next page link found.');
|
||||
}
|
||||
|
||||
// Compute the expected breadcrumb.
|
||||
@@ -163,20 +188,24 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
// Compare expected and got breadcrumbs.
|
||||
$this->assertIdentical($expected_breadcrumb, $got_breadcrumb, t('The breadcrumb is correctly displayed on the page.'));
|
||||
$this->assertIdentical($expected_breadcrumb, $got_breadcrumb, 'The breadcrumb is correctly displayed on the page.');
|
||||
|
||||
// Check printer friendly version.
|
||||
$this->drupalGet('book/export/html/' . $node->nid);
|
||||
$this->assertText($node->title, t('Printer friendly title found.'));
|
||||
$this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format']), t('Printer friendly body found.'));
|
||||
$this->assertText($node->title, 'Printer friendly title found.');
|
||||
$this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format']), 'Printer friendly body found.');
|
||||
|
||||
$number++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a regular expression to check for the sub-nodes in the outline.
|
||||
* Creates a regular expression to check for the sub-nodes in the outline.
|
||||
*
|
||||
* @param array $nodes Nodes to check in outline.
|
||||
* @param array $nodes
|
||||
* An array of nodes to check in outline.
|
||||
*
|
||||
* @return
|
||||
* A regular expression that locates sub-nodes of the outline.
|
||||
*/
|
||||
function generateOutlinePattern($nodes) {
|
||||
$outline = '';
|
||||
@@ -188,10 +217,12 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create book node.
|
||||
* Creates a book node.
|
||||
*
|
||||
* @param integer $book_nid Book node id or set to 'new' to create new book.
|
||||
* @param integer $parent Parent book reference id.
|
||||
* @param $book_nid
|
||||
* A book node ID or set to 'new' to create a new book.
|
||||
* @param $parent
|
||||
* (optional) Parent book reference ID. Defaults to NULL.
|
||||
*/
|
||||
function createBookNode($book_nid, $parent = NULL) {
|
||||
// $number does not use drupal_static as it should not be reset
|
||||
@@ -216,7 +247,7 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
|
||||
// Check to make sure the book node was created.
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertNotNull(($node === FALSE ? NULL : $node), t('Book node found in database.'));
|
||||
$this->assertNotNull(($node === FALSE ? NULL : $node), 'Book node found in database.');
|
||||
$number++;
|
||||
|
||||
return $node;
|
||||
@@ -236,28 +267,28 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
|
||||
// Make sure each part of the book is there.
|
||||
foreach ($nodes as $node) {
|
||||
$this->assertText($node->title, t('Node title found in printer friendly version.'));
|
||||
$this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format']), t('Node body found in printer friendly version.'));
|
||||
$this->assertText($node->title, 'Node title found in printer friendly version.');
|
||||
$this->assertRaw(check_markup($node->body[LANGUAGE_NONE][0]['value'], $node->body[LANGUAGE_NONE][0]['format']), 'Node body found in printer friendly version.');
|
||||
}
|
||||
|
||||
// Make sure we can't export an unsupported format.
|
||||
$this->drupalGet('book/export/foobar/' . $this->book->nid);
|
||||
$this->assertResponse('404', t('Unsupported export format returned "not found".'));
|
||||
$this->assertResponse('404', 'Unsupported export format returned "not found".');
|
||||
|
||||
// Make sure we get a 404 on a not existing book node.
|
||||
$this->drupalGet('book/export/html/123');
|
||||
$this->assertResponse('404', t('Not existing book node returned "not found".'));
|
||||
$this->assertResponse('404', 'Not existing book node returned "not found".');
|
||||
|
||||
// Make sure an anonymous user cannot view printer-friendly version.
|
||||
$this->drupalLogout();
|
||||
|
||||
// Load the book and verify there is no printer-friendly version link.
|
||||
$this->drupalGet('node/' . $this->book->nid);
|
||||
$this->assertNoLink(t('Printer-friendly version'), t('Anonymous user is not shown link to printer-friendly version.'));
|
||||
$this->assertNoLink(t('Printer-friendly version'), 'Anonymous user is not shown link to printer-friendly version.');
|
||||
|
||||
// Try getting the URL directly, and verify it fails.
|
||||
$this->drupalGet('book/export/html/' . $this->book->nid);
|
||||
$this->assertResponse('403', t('Anonymous user properly forbidden.'));
|
||||
$this->assertResponse('403', 'Anonymous user properly forbidden.');
|
||||
|
||||
// Now grant anonymous users permission to view the printer-friendly
|
||||
// version and verify that node access restrictions still prevent them from
|
||||
@@ -276,30 +307,30 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
// Set block title to confirm that the interface is available.
|
||||
$block_title = $this->randomName(16);
|
||||
$this->drupalPost('admin/structure/block/manage/book/navigation/configure', array('title' => $block_title), t('Save block'));
|
||||
$this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
|
||||
$this->assertText(t('The block configuration has been saved.'), 'Block configuration set.');
|
||||
|
||||
// Set the block to a region to confirm block is available.
|
||||
$edit = array();
|
||||
$edit['blocks[book_navigation][region]'] = 'footer';
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
$this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
|
||||
$this->assertText(t('The block settings have been updated.'), 'Block successfully move to footer region.');
|
||||
|
||||
// Give anonymous users the permission 'node test view'.
|
||||
$edit = array();
|
||||
$edit[DRUPAL_ANONYMOUS_RID . '[node test view]'] = TRUE;
|
||||
$this->drupalPost('admin/people/permissions/' . DRUPAL_ANONYMOUS_RID, $edit, t('Save permissions'));
|
||||
$this->assertText(t('The changes have been saved.'), t("Permission 'node test view' successfully assigned to anonymous users."));
|
||||
$this->assertText(t('The changes have been saved.'), "Permission 'node test view' successfully assigned to anonymous users.");
|
||||
|
||||
// Test correct display of the block.
|
||||
$nodes = $this->createBook();
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertText($block_title, t('Book navigation block is displayed.'));
|
||||
$this->assertText($this->book->title, t('Link to book root (@title) is displayed.', array('@title' => $nodes[0]->title)));
|
||||
$this->assertNoText($nodes[0]->title, t('No links to individual book pages are displayed.'));
|
||||
$this->assertText($block_title, 'Book navigation block is displayed.');
|
||||
$this->assertText($this->book->title, format_string('Link to book root (@title) is displayed.', array('@title' => $nodes[0]->title)));
|
||||
$this->assertNoText($nodes[0]->title, 'No links to individual book pages are displayed.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the book navigation block when an access module is enabled.
|
||||
* Tests the book navigation block when an access module is enabled.
|
||||
*/
|
||||
function testNavigationBlockOnAccessModuleEnabled() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
@@ -312,19 +343,19 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
// Set block display to 'Show block only on book pages'.
|
||||
$edit['book_block_mode'] = 'book pages';
|
||||
$this->drupalPost('admin/structure/block/manage/book/navigation/configure', $edit, t('Save block'));
|
||||
$this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
|
||||
$this->assertText(t('The block configuration has been saved.'), 'Block configuration set.');
|
||||
|
||||
// Set the block to a region to confirm block is available.
|
||||
$edit = array();
|
||||
$edit['blocks[book_navigation][region]'] = 'footer';
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
$this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
|
||||
$this->assertText(t('The block settings have been updated.'), 'Block successfully move to footer region.');
|
||||
|
||||
// Give anonymous users the permission 'node test view'.
|
||||
$edit = array();
|
||||
$edit[DRUPAL_ANONYMOUS_RID . '[node test view]'] = TRUE;
|
||||
$this->drupalPost('admin/people/permissions/' . DRUPAL_ANONYMOUS_RID, $edit, t('Save permissions'));
|
||||
$this->assertText(t('The changes have been saved.'), t('Permission \'node test view\' successfully assigned to anonymous users.'));
|
||||
$this->assertText(t('The changes have been saved.'), "Permission 'node test view' successfully assigned to anonymous users.");
|
||||
|
||||
// Create a book.
|
||||
$this->createBook();
|
||||
@@ -332,12 +363,12 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
// Test correct display of the block to registered users.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('node/' . $this->book->nid);
|
||||
$this->assertText($block_title, t('Book navigation block is displayed to registered users.'));
|
||||
$this->assertText($block_title, 'Book navigation block is displayed to registered users.');
|
||||
$this->drupalLogout();
|
||||
|
||||
// Test correct display of the block to anonymous users.
|
||||
$this->drupalGet('node/' . $this->book->nid);
|
||||
$this->assertText($block_title, t('Book navigation block is displayed to anonymous users.'));
|
||||
$this->assertText($block_title, 'Book navigation block is displayed to anonymous users.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -350,10 +381,10 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
|
||||
// Test access to delete top-level and child book nodes.
|
||||
$this->drupalGet('node/' . $this->book->nid . '/outline/remove');
|
||||
$this->assertResponse('403', t('Deleting top-level book node properly forbidden.'));
|
||||
$this->assertResponse('403', 'Deleting top-level book node properly forbidden.');
|
||||
$this->drupalPost('node/' . $nodes[4]->nid . '/outline/remove', $edit, t('Remove'));
|
||||
$node4 = node_load($nodes[4]->nid, NULL, TRUE);
|
||||
$this->assertTrue(empty($node4->book), t('Deleting child book node properly allowed.'));
|
||||
$this->assertTrue(empty($node4->book), 'Deleting child book node properly allowed.');
|
||||
|
||||
// Delete all child book nodes and retest top-level node deletion.
|
||||
foreach ($nodes as $node) {
|
||||
@@ -362,6 +393,6 @@ class BookTestCase extends DrupalWebTestCase {
|
||||
node_delete_multiple($nids);
|
||||
$this->drupalPost('node/' . $this->book->nid . '/outline/remove', $edit, t('Remove'));
|
||||
$node = node_load($this->book->nid, NULL, TRUE);
|
||||
$this->assertTrue(empty($node->book), t('Deleting childless top-level book node properly allowed.'));
|
||||
$this->assertTrue(empty($node->book), 'Deleting childless top-level book node properly allowed.');
|
||||
}
|
||||
}
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = color.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -98,13 +98,14 @@ function comment_admin_overview($form, &$form_state, $arg) {
|
||||
// Remove the first node title from the node_titles array and attach to
|
||||
// the comment.
|
||||
$comment->node_title = array_shift($node_titles);
|
||||
$comment_body = field_get_items('comment', $comment, 'comment_body');
|
||||
$options[$comment->cid] = array(
|
||||
'subject' => array(
|
||||
'data' => array(
|
||||
'#type' => 'link',
|
||||
'#title' => $comment->subject,
|
||||
'#href' => 'comment/' . $comment->cid,
|
||||
'#options' => array('attributes' => array('title' => truncate_utf8($comment->comment_body[LANGUAGE_NONE][0]['value'], 128)), 'fragment' => 'comment-' . $comment->cid),
|
||||
'#options' => array('attributes' => array('title' => truncate_utf8($comment_body[0]['value'], 128)), 'fragment' => 'comment-' . $comment->cid),
|
||||
),
|
||||
),
|
||||
'author' => theme('username', array('account' => $comment)),
|
||||
|
@@ -9,8 +9,8 @@ files[] = comment.test
|
||||
configure = admin/content/comment
|
||||
stylesheets[all][] = comment.css
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -2041,7 +2041,8 @@ function comment_form($form, &$form_state, $comment) {
|
||||
|
||||
// Attach fields.
|
||||
$comment->node_type = 'comment_node_' . $node->type;
|
||||
field_attach_form('comment', $comment, $form, $form_state);
|
||||
$langcode = entity_language('comment', $comment);
|
||||
field_attach_form('comment', $comment, $form, $form_state, $langcode);
|
||||
|
||||
return $form;
|
||||
}
|
||||
@@ -2066,7 +2067,8 @@ function comment_preview($comment) {
|
||||
$node = node_load($comment->nid);
|
||||
|
||||
if (!form_get_errors()) {
|
||||
$comment->format = $comment->comment_body[LANGUAGE_NONE][0]['format'];
|
||||
$comment_body = field_get_items('comment', $comment, 'comment_body');
|
||||
$comment->format = $comment_body[0]['format'];
|
||||
// Attach the user and time information.
|
||||
if (!empty($comment->name)) {
|
||||
$account = user_load_by_name($comment->name);
|
||||
@@ -2190,7 +2192,9 @@ function comment_submit($comment) {
|
||||
// 1) Filter it into HTML
|
||||
// 2) Strip out all HTML tags
|
||||
// 3) Convert entities back to plain-text.
|
||||
$comment_body = $comment->comment_body[LANGUAGE_NONE][0];
|
||||
$field = field_info_field('comment_body');
|
||||
$langcode = field_is_translatable('comment', $field) ? entity_language('comment', $comment) : LANGUAGE_NONE;
|
||||
$comment_body = $comment->comment_body[$langcode][0];
|
||||
if (isset($comment_body['format'])) {
|
||||
$comment_text = check_markup($comment_body['value'], $comment_body['format']);
|
||||
}
|
||||
@@ -2284,8 +2288,16 @@ function template_preprocess_comment(&$variables) {
|
||||
$variables['comment'] = $comment;
|
||||
$variables['node'] = $node;
|
||||
$variables['author'] = theme('username', array('account' => $comment));
|
||||
|
||||
$variables['created'] = format_date($comment->created);
|
||||
$variables['changed'] = format_date($comment->changed);
|
||||
|
||||
// Avoid calling format_date() twice on the same timestamp.
|
||||
if ($comment->changed == $comment->created) {
|
||||
$variables['changed'] = $variables['created'];
|
||||
}
|
||||
else {
|
||||
$variables['changed'] = format_date($comment->changed);
|
||||
}
|
||||
|
||||
$variables['new'] = !empty($comment->new) ? t('new') : '';
|
||||
$variables['picture'] = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', array('account' => $comment)) : '';
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = contact.test
|
||||
configure = admin/structure/contact
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = contextual.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -7,8 +7,8 @@ files[] = dashboard.test
|
||||
dependencies[] = block
|
||||
configure = admin/dashboard/customize
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* @file
|
||||
* Right-to-Left styling for the Database Logging module.
|
||||
*/
|
||||
|
||||
.form-item-type,
|
||||
.form-item-severity {
|
||||
|
@@ -2,14 +2,19 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Administrative page callbacks for the dblog module.
|
||||
* Administrative page callbacks for the Database Logging module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Menu callback; displays a listing of log messages.
|
||||
* Page callback: Displays a listing of database log messages.
|
||||
*
|
||||
* Messages are truncated at 56 chars. Full-length message could be viewed at
|
||||
* the message details page.
|
||||
* Messages are truncated at 56 chars. Full-length messages can be viewed on the
|
||||
* message details page.
|
||||
*
|
||||
* @see dblog_clear_log_form()
|
||||
* @see dblog_event()
|
||||
* @see dblog_filter_form()
|
||||
* @see dblog_menu()
|
||||
*
|
||||
* @ingroup logging_severity_levels
|
||||
*/
|
||||
@@ -81,12 +86,18 @@ function dblog_overview() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; generic function to display a page of the most frequent events.
|
||||
* Page callback: Shows the most frequent log messages of a given event type.
|
||||
*
|
||||
* Messages are not truncated because events from this page have no detail view.
|
||||
* Messages are not truncated on this page because events detailed herein do not
|
||||
* have links to a detailed view.
|
||||
*
|
||||
* @param $type
|
||||
* type of dblog events to display.
|
||||
* @param string $type
|
||||
* Type of database log events to display (e.g., 'search').
|
||||
*
|
||||
* @return array
|
||||
* A build array in the format expected by drupal_render().
|
||||
*
|
||||
* @see dblog_menu()
|
||||
*/
|
||||
function dblog_top($type) {
|
||||
|
||||
@@ -127,7 +138,16 @@ function dblog_top($type) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; displays details about a log message.
|
||||
* Page callback: Displays details about a specific database log message.
|
||||
*
|
||||
* @param int $id
|
||||
* Unique ID of the database log message.
|
||||
*
|
||||
* @return array|string
|
||||
* If the ID is located in the Database Logging table, a build array in the
|
||||
* format expected by drupal_render(); otherwise, an empty string.
|
||||
*
|
||||
* @see dblog_menu()
|
||||
*/
|
||||
function dblog_event($id) {
|
||||
$severity = watchdog_severity_levels();
|
||||
@@ -184,7 +204,10 @@ function dblog_event($id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build query for dblog administration filters based on session.
|
||||
* Builds a query for database log administration filters based on session.
|
||||
*
|
||||
* @return array
|
||||
* An associative array with keys 'where' and 'args'.
|
||||
*/
|
||||
function dblog_build_filter_query() {
|
||||
if (empty($_SESSION['dblog_overview_filter'])) {
|
||||
@@ -213,9 +236,16 @@ function dblog_build_filter_query() {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List dblog administration filters that can be applied.
|
||||
* Creates a list of database log administration filters that can be applied.
|
||||
*
|
||||
* @return array
|
||||
* Associative array of filters. The top-level keys are used as the form
|
||||
* element names for the filters, and the values are arrays with the following
|
||||
* elements:
|
||||
* - title: Title of the filter.
|
||||
* - where: The filter condition.
|
||||
* - options: Array of options for the select list for the filter.
|
||||
*/
|
||||
function dblog_filters() {
|
||||
$filters = array();
|
||||
@@ -244,7 +274,7 @@ function dblog_filters() {
|
||||
/**
|
||||
* Returns HTML for a log message.
|
||||
*
|
||||
* @param $variables
|
||||
* @param array $variables
|
||||
* An associative array containing:
|
||||
* - event: An object with at least the message and variables properties.
|
||||
* - link: (optional) Format message as link, event->wid is required.
|
||||
@@ -274,11 +304,13 @@ function theme_dblog_message($variables) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return form for dblog administration filters.
|
||||
* Form constructor for the database logging filter form.
|
||||
*
|
||||
* @see dblog_filter_form_validate()
|
||||
* @see dblog_filter_form_submit()
|
||||
* @see dblog_overview()
|
||||
*
|
||||
* @ingroup forms
|
||||
* @see dblog_filter_form_submit()
|
||||
* @see dblog_filter_form_validate()
|
||||
*/
|
||||
function dblog_filter_form($form) {
|
||||
$filters = dblog_filters();
|
||||
@@ -316,12 +348,13 @@ function dblog_filter_form($form) {
|
||||
'#value' => t('Reset')
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate result from dblog administration filter form.
|
||||
* Form validation handler for dblog_filter_form().
|
||||
*
|
||||
* @see dblog_filter_form_submit()
|
||||
*/
|
||||
function dblog_filter_form_validate($form, &$form_state) {
|
||||
if ($form_state['values']['op'] == t('Filter') && empty($form_state['values']['type']) && empty($form_state['values']['severity'])) {
|
||||
@@ -330,7 +363,9 @@ function dblog_filter_form_validate($form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Process result from dblog administration filter form.
|
||||
* Form submission handler for dblog_filter_form().
|
||||
*
|
||||
* @see dblog_filter_form_validate()
|
||||
*/
|
||||
function dblog_filter_form_submit($form, &$form_state) {
|
||||
$op = $form_state['values']['op'];
|
||||
@@ -351,10 +386,10 @@ function dblog_filter_form_submit($form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return form for dblog clear button.
|
||||
* Form constructor for the form that clears out the log.
|
||||
*
|
||||
* @ingroup forms
|
||||
* @see dblog_clear_log_submit()
|
||||
* @ingroup forms
|
||||
*/
|
||||
function dblog_clear_log_form($form) {
|
||||
$form['dblog_clear'] = array(
|
||||
@@ -374,7 +409,7 @@ function dblog_clear_log_form($form) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit callback: clear database with log messages.
|
||||
* Form submission handler for dblog_clear_log_form().
|
||||
*/
|
||||
function dblog_clear_log_submit() {
|
||||
$_SESSION['dblog_overview_filter'] = array();
|
||||
|
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* @file
|
||||
* Admin styles for the Database Logging module.
|
||||
*/
|
||||
|
||||
.form-item-type,
|
||||
.form-item-severity {
|
||||
float: left; /* LTR */
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = dblog.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -85,6 +85,7 @@ function dblog_schema() {
|
||||
'indexes' => array(
|
||||
'type' => array('type'),
|
||||
'uid' => array('uid'),
|
||||
'severity' => array('severity'),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -140,3 +141,19 @@ function dblog_update_7001() {
|
||||
/**
|
||||
* @} End of "addtogroup updates-6.x-to-7.x".
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup updates-7.x-extra
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add an index to the severity column in the watchdog database table.
|
||||
*/
|
||||
function dblog_update_7002() {
|
||||
db_add_index('watchdog', 'severity', array('severity'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-7.x-extra".
|
||||
*/
|
||||
|
@@ -4,9 +4,9 @@
|
||||
* @file
|
||||
* System monitoring and logging for administrators.
|
||||
*
|
||||
* The dblog module monitors your site and keeps a list of
|
||||
* recorded events containing usage and performance data, errors,
|
||||
* warnings, and similar operational information.
|
||||
* The Database Logging module monitors your site and keeps a list of recorded
|
||||
* events containing usage and performance data, errors, warnings, and similar
|
||||
* operational information.
|
||||
*
|
||||
* @see watchdog()
|
||||
*/
|
||||
@@ -96,7 +96,7 @@ function dblog_init() {
|
||||
/**
|
||||
* Implements hook_cron().
|
||||
*
|
||||
* Remove expired log messages.
|
||||
* Controls the size of the log table, paring it to 'dblog_row_limit' messages.
|
||||
*/
|
||||
function dblog_cron() {
|
||||
// Cleanup the watchdog table.
|
||||
@@ -121,6 +121,12 @@ function dblog_cron() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gathers a list of uniquely defined database log message types.
|
||||
*
|
||||
* @return array
|
||||
* List of uniquely defined database log message types.
|
||||
*/
|
||||
function _dblog_get_message_types() {
|
||||
$types = array();
|
||||
|
||||
@@ -135,7 +141,7 @@ function _dblog_get_message_types() {
|
||||
/**
|
||||
* Implements hook_watchdog().
|
||||
*
|
||||
* Note some values may be truncated for database column size restrictions.
|
||||
* Note: Some values may be truncated to meet database column size restrictions.
|
||||
*/
|
||||
function dblog_watchdog(array $log_entry) {
|
||||
Database::getConnection('default', 'default')->insert('watchdog')
|
||||
@@ -155,7 +161,7 @@ function dblog_watchdog(array $log_entry) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter().
|
||||
* Implements hook_form_FORM_ID_alter() for system_logging_settings().
|
||||
*/
|
||||
function dblog_form_system_logging_settings_alter(&$form, $form_state) {
|
||||
$form['dblog_row_limit'] = array(
|
||||
|
@@ -5,8 +5,23 @@
|
||||
* Tests for dblog.module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests logging messages to the database.
|
||||
*/
|
||||
class DBLogTestCase extends DrupalWebTestCase {
|
||||
|
||||
/**
|
||||
* A user with some relevent administrative permissions.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $big_user;
|
||||
|
||||
/**
|
||||
* A user without any permissions.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $any_user;
|
||||
|
||||
public static function getInfo() {
|
||||
@@ -28,7 +43,11 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Login users, create dblog events, and test dblog functionality through the admin and user interfaces.
|
||||
* Tests Database Logging module functionality through interfaces.
|
||||
*
|
||||
* First logs in users, then creates database log events, and finally tests
|
||||
* Database Logging module functionality through both the admin and user
|
||||
* interfaces.
|
||||
*/
|
||||
function testDBLog() {
|
||||
// Login the admin user.
|
||||
@@ -46,12 +65,13 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify setting of the dblog row limit.
|
||||
* Verifies setting of the database log row limit.
|
||||
*
|
||||
* @param integer $count Log row limit.
|
||||
* @param int $row_limit
|
||||
* The row limit.
|
||||
*/
|
||||
private function verifyRowLimit($row_limit) {
|
||||
// Change the dblog row limit.
|
||||
// Change the database log row limit.
|
||||
$edit = array();
|
||||
$edit['dblog_row_limit'] = $row_limit;
|
||||
$this->drupalPost('admin/config/development/logging', $edit, t('Save configuration'));
|
||||
@@ -66,33 +86,35 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify cron applies the dblog row limit.
|
||||
* Verifies that cron correctly applies the database log row limit.
|
||||
*
|
||||
* @param integer $count Log row limit.
|
||||
* @param int $row_limit
|
||||
* The row limit.
|
||||
*/
|
||||
private function verifyCron($row_limit) {
|
||||
// Generate additional log entries.
|
||||
$this->generateLogEntries($row_limit + 10);
|
||||
// Verify dblog row count exceeds row limit.
|
||||
// Verify that the database log row count exceeds the row limit.
|
||||
$count = db_query('SELECT COUNT(wid) FROM {watchdog}')->fetchField();
|
||||
$this->assertTrue($count > $row_limit, t('Dblog row count of @count exceeds row limit of @limit', array('@count' => $count, '@limit' => $row_limit)));
|
||||
|
||||
// Run cron job.
|
||||
// Run a cron job.
|
||||
$this->cronRun();
|
||||
// Verify dblog row count equals row limit plus one because cron adds a record after it runs.
|
||||
// Verify that the database log row count equals the row limit plus one
|
||||
// because cron adds a record after it runs.
|
||||
$count = db_query('SELECT COUNT(wid) FROM {watchdog}')->fetchField();
|
||||
$this->assertTrue($count == $row_limit + 1, t('Dblog row count of @count equals row limit of @limit plus one', array('@count' => $count, '@limit' => $row_limit)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate dblog entries.
|
||||
* Generates a number of random database log events.
|
||||
*
|
||||
* @param integer $count
|
||||
* Number of log entries to generate.
|
||||
* @param $type
|
||||
* The type of watchdog entry.
|
||||
* @param $severity
|
||||
* The severity of the watchdog entry.
|
||||
* @param int $count
|
||||
* Number of watchdog entries to generate.
|
||||
* @param string $type
|
||||
* (optional) The type of watchdog entry. Defaults to 'custom'.
|
||||
* @param int $severity
|
||||
* (optional) The severity of the watchdog entry. Defaults to WATCHDOG_NOTICE.
|
||||
*/
|
||||
private function generateLogEntries($count, $type = 'custom', $severity = WATCHDOG_NOTICE) {
|
||||
global $base_root;
|
||||
@@ -119,42 +141,43 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the logged in user has the desired access to the various dblog nodes.
|
||||
* Confirms that database log reports are displayed at the correct paths.
|
||||
*
|
||||
* @param integer $response HTTP response code.
|
||||
* @param int $response
|
||||
* (optional) HTTP response code. Defaults to 200.
|
||||
*/
|
||||
private function verifyReports($response = 200) {
|
||||
$quote = ''';
|
||||
|
||||
// View dblog help node.
|
||||
// View the database log help page.
|
||||
$this->drupalGet('admin/help/dblog');
|
||||
$this->assertResponse($response);
|
||||
if ($response == 200) {
|
||||
$this->assertText(t('Database logging'), t('DBLog help was displayed'));
|
||||
}
|
||||
|
||||
// View dblog report node.
|
||||
// View the database log report page.
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertResponse($response);
|
||||
if ($response == 200) {
|
||||
$this->assertText(t('Recent log messages'), t('DBLog report was displayed'));
|
||||
}
|
||||
|
||||
// View dblog page-not-found report node.
|
||||
// View the database log page-not-found report page.
|
||||
$this->drupalGet('admin/reports/page-not-found');
|
||||
$this->assertResponse($response);
|
||||
if ($response == 200) {
|
||||
$this->assertText(t('Top ' . $quote . 'page not found' . $quote . ' errors'), t('DBLog page-not-found report was displayed'));
|
||||
}
|
||||
|
||||
// View dblog access-denied report node.
|
||||
// View the database log access-denied report page.
|
||||
$this->drupalGet('admin/reports/access-denied');
|
||||
$this->assertResponse($response);
|
||||
if ($response == 200) {
|
||||
$this->assertText(t('Top ' . $quote . 'access denied' . $quote . ' errors'), t('DBLog access-denied report was displayed'));
|
||||
}
|
||||
|
||||
// View dblog event node.
|
||||
// View the database log event page.
|
||||
$this->drupalGet('admin/reports/event/1');
|
||||
$this->assertResponse($response);
|
||||
if ($response == 200) {
|
||||
@@ -163,7 +186,7 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify events.
|
||||
* Generates and then verifies various types of events.
|
||||
*/
|
||||
private function verifyEvents() {
|
||||
// Invoke events.
|
||||
@@ -179,14 +202,14 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and verify user events.
|
||||
*
|
||||
* Generates and then verifies some user events.
|
||||
*/
|
||||
private function doUser() {
|
||||
// Set user variables.
|
||||
$name = $this->randomName();
|
||||
$pass = user_password();
|
||||
// Add user using form to generate add user event (which is not triggered by drupalCreateUser).
|
||||
// Add a user using the form to generate an add user event (which is not
|
||||
// triggered by drupalCreateUser).
|
||||
$edit = array();
|
||||
$edit['name'] = $name;
|
||||
$edit['mail'] = $name . '@example.com';
|
||||
@@ -195,15 +218,16 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
$edit['status'] = 1;
|
||||
$this->drupalPost('admin/people/create', $edit, t('Create new account'));
|
||||
$this->assertResponse(200);
|
||||
// Retrieve user object.
|
||||
// Retrieve the user object.
|
||||
$user = user_load_by_name($name);
|
||||
$this->assertTrue($user != NULL, t('User @name was loaded', array('@name' => $name)));
|
||||
$user->pass_raw = $pass; // Needed by drupalLogin.
|
||||
// pass_raw property is needed by drupalLogin.
|
||||
$user->pass_raw = $pass;
|
||||
// Login user.
|
||||
$this->drupalLogin($user);
|
||||
// Logout user.
|
||||
$this->drupalLogout();
|
||||
// Fetch row ids in watchdog that relate to the user.
|
||||
// Fetch the row IDs in watchdog that relate to the user.
|
||||
$result = db_query('SELECT wid FROM {watchdog} WHERE uid = :uid', array(':uid' => $user->uid));
|
||||
foreach ($result as $row) {
|
||||
$ids[] = $row->wid;
|
||||
@@ -213,17 +237,18 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
|
||||
// Login the admin user.
|
||||
$this->drupalLogin($this->big_user);
|
||||
// Delete user.
|
||||
// Delete the user created at the start of this test.
|
||||
// We need to POST here to invoke batch_process() in the internal browser.
|
||||
$this->drupalPost('user/' . $user->uid . '/cancel', array('user_cancel_method' => 'user_cancel_reassign'), t('Cancel account'));
|
||||
|
||||
// View the dblog report.
|
||||
// View the database log report.
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Verify events were recorded.
|
||||
// Verify that the expected events were recorded.
|
||||
// Add user.
|
||||
// Default display includes name and email address; if too long then email is replaced by three periods.
|
||||
// Default display includes name and email address; if too long, the email
|
||||
// address is replaced by three periods.
|
||||
$this->assertLogMessage(t('New user: %name (%email).', array('%name' => $name, '%email' => $user->mail)), t('DBLog event was recorded: [add user]'));
|
||||
// Login user.
|
||||
$this->assertLogMessage(t('Session opened for %name.', array('%name' => $name)), t('DBLog event was recorded: [login user]'));
|
||||
@@ -232,7 +257,7 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
// Delete user.
|
||||
$message = t('Deleted user: %name %email.', array('%name' => $name, '%email' => '<' . $user->mail . '>'));
|
||||
$message_text = truncate_utf8(filter_xss($message, array()), 56, TRUE, TRUE);
|
||||
// Verify full message on details page.
|
||||
// Verify that the full message displays on the details page.
|
||||
$link = FALSE;
|
||||
if ($links = $this->xpath('//a[text()="' . html_entity_decode($message_text) . '"]')) {
|
||||
// Found link with the message text.
|
||||
@@ -253,7 +278,7 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
$not_found_url = $this->randomName(60);
|
||||
$this->drupalGet($not_found_url);
|
||||
$this->assertResponse(404);
|
||||
// View dblog page-not-found report page.
|
||||
// View the database log page-not-found report page.
|
||||
$this->drupalGet('admin/reports/page-not-found');
|
||||
$this->assertResponse(200);
|
||||
// Check that full-length URL displayed.
|
||||
@@ -261,9 +286,10 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and verify node events.
|
||||
* Generates and then verifies some node events.
|
||||
*
|
||||
* @param string $type Content type.
|
||||
* @param string $type
|
||||
* A node type (e.g., 'article', 'page' or 'poll').
|
||||
*/
|
||||
private function doNode($type) {
|
||||
// Create user.
|
||||
@@ -272,61 +298,65 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
// Login user.
|
||||
$this->drupalLogin($user);
|
||||
|
||||
// Create node using form to generate add content event (which is not triggered by drupalCreateNode).
|
||||
// Create a node using the form in order to generate an add content event
|
||||
// (which is not triggered by drupalCreateNode).
|
||||
$edit = $this->getContent($type);
|
||||
$langcode = LANGUAGE_NONE;
|
||||
$title = $edit["title"];
|
||||
$this->drupalPost('node/add/' . $type, $edit, t('Save'));
|
||||
$this->assertResponse(200);
|
||||
// Retrieve node object.
|
||||
// Retrieve the node object.
|
||||
$node = $this->drupalGetNodeByTitle($title);
|
||||
$this->assertTrue($node != NULL, t('Node @title was loaded', array('@title' => $title)));
|
||||
// Edit node.
|
||||
// Edit the node.
|
||||
$edit = $this->getContentUpdate($type);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertResponse(200);
|
||||
// Delete node.
|
||||
// Delete the node.
|
||||
$this->drupalPost('node/' . $node->nid . '/delete', array(), t('Delete'));
|
||||
$this->assertResponse(200);
|
||||
// View node (to generate page not found event).
|
||||
// View the node (to generate page not found event).
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertResponse(404);
|
||||
// View the dblog report (to generate access denied event).
|
||||
// View the database log report (to generate access denied event).
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Login the admin user.
|
||||
$this->drupalLogin($this->big_user);
|
||||
// View the dblog report.
|
||||
// View the database log report.
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Verify events were recorded.
|
||||
// Content added.
|
||||
// Verify that node events were recorded.
|
||||
// Was node content added?
|
||||
$this->assertLogMessage(t('@type: added %title.', array('@type' => $type, '%title' => $title)), t('DBLog event was recorded: [content added]'));
|
||||
// Content updated.
|
||||
// Was node content updated?
|
||||
$this->assertLogMessage(t('@type: updated %title.', array('@type' => $type, '%title' => $title)), t('DBLog event was recorded: [content updated]'));
|
||||
// Content deleted.
|
||||
// Was node content deleted?
|
||||
$this->assertLogMessage(t('@type: deleted %title.', array('@type' => $type, '%title' => $title)), t('DBLog event was recorded: [content deleted]'));
|
||||
|
||||
// View dblog access-denied report node.
|
||||
// View the database log access-denied report page.
|
||||
$this->drupalGet('admin/reports/access-denied');
|
||||
$this->assertResponse(200);
|
||||
// Access denied.
|
||||
// Verify that the 'access denied' event was recorded.
|
||||
$this->assertText(t('admin/reports/dblog'), t('DBLog event was recorded: [access denied]'));
|
||||
|
||||
// View dblog page-not-found report node.
|
||||
// View the database log page-not-found report page.
|
||||
$this->drupalGet('admin/reports/page-not-found');
|
||||
$this->assertResponse(200);
|
||||
// Page not found.
|
||||
// Verify that the 'page not found' event was recorded.
|
||||
$this->assertText(t('node/@nid', array('@nid' => $node->nid)), t('DBLog event was recorded: [page not found]'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create content based on content type.
|
||||
* Creates random content based on node content type.
|
||||
*
|
||||
* @param string $type Content type.
|
||||
* @return array Content.
|
||||
* @param string $type
|
||||
* Node content type (e.g., 'article').
|
||||
*
|
||||
* @return array
|
||||
* Random content needed by various node types.
|
||||
*/
|
||||
private function getContent($type) {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
@@ -350,10 +380,13 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create content update based on content type.
|
||||
* Creates random content as an update based on node content type.
|
||||
*
|
||||
* @param string $type Content type.
|
||||
* @return array Content.
|
||||
* @param string $type
|
||||
* Node content type (e.g., 'article').
|
||||
*
|
||||
* @return array
|
||||
* Random content needed by various node types.
|
||||
*/
|
||||
private function getContentUpdate($type) {
|
||||
switch ($type) {
|
||||
@@ -375,11 +408,14 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Login an admin user, create dblog event, and test clearing dblog functionality through the admin interface.
|
||||
* Tests the addition and clearing of log events through the admin interface.
|
||||
*
|
||||
* Logs in the admin user, creates a database log event, and tests the
|
||||
* functionality of clearing the database log through the admin interface.
|
||||
*/
|
||||
protected function testDBLogAddAndClear() {
|
||||
global $base_root;
|
||||
// Get a count of how many watchdog entries there are.
|
||||
// Get a count of how many watchdog entries already exist.
|
||||
$count = db_query('SELECT COUNT(*) FROM {watchdog}')->fetchField();
|
||||
$log = array(
|
||||
'type' => 'custom',
|
||||
@@ -396,27 +432,27 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
);
|
||||
// Add a watchdog entry.
|
||||
dblog_watchdog($log);
|
||||
// Make sure the table count has actually incremented.
|
||||
// Make sure the table count has actually been incremented.
|
||||
$this->assertEqual($count + 1, db_query('SELECT COUNT(*) FROM {watchdog}')->fetchField(), t('dblog_watchdog() added an entry to the dblog :count', array(':count' => $count)));
|
||||
// Login the admin user.
|
||||
$this->drupalLogin($this->big_user);
|
||||
// Now post to clear the db table.
|
||||
// Post in order to clear the database table.
|
||||
$this->drupalPost('admin/reports/dblog', array(), t('Clear log messages'));
|
||||
// Count rows in watchdog that previously related to the deleted user.
|
||||
// Count the rows in watchdog that previously related to the deleted user.
|
||||
$count = db_query('SELECT COUNT(*) FROM {watchdog}')->fetchField();
|
||||
$this->assertEqual($count, 0, t('DBLog contains :count records after a clear.', array(':count' => $count)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the dblog filter on admin/reports/dblog.
|
||||
* Tests the database log filter functionality at admin/reports/dblog.
|
||||
*/
|
||||
protected function testFilter() {
|
||||
$this->drupalLogin($this->big_user);
|
||||
|
||||
// Clear log to ensure that only generated entries are found.
|
||||
// Clear the log to ensure that only generated entries will be found.
|
||||
db_delete('watchdog')->execute();
|
||||
|
||||
// Generate watchdog entries.
|
||||
// Generate 9 random watchdog entries.
|
||||
$type_names = array();
|
||||
$types = array();
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
@@ -432,10 +468,10 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
// View the dblog.
|
||||
// View the database log page.
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
|
||||
// Confirm all the entries are displayed.
|
||||
// Confirm that all the entries are displayed.
|
||||
$count = $this->getTypeCount($types);
|
||||
foreach ($types as $key => $type) {
|
||||
$this->assertEqual($count[$key], $type['count'], 'Count matched');
|
||||
@@ -461,8 +497,8 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
$this->assertEqual(array_sum($count), $type_count, 'Count matched');
|
||||
}
|
||||
|
||||
// Set filter to match each of the three type attributes and confirm the
|
||||
// number of entries displayed.
|
||||
// Set the filter to match each of the two filter-type attributes and
|
||||
// confirm the correct number of entries are displayed.
|
||||
foreach ($types as $key => $type) {
|
||||
$edit = array(
|
||||
'type[]' => array($type['type']),
|
||||
@@ -480,10 +516,14 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the log entry information form the page.
|
||||
* Gets the database log event information from the browser page.
|
||||
*
|
||||
* @return
|
||||
* List of entries and their information.
|
||||
* @return array
|
||||
* List of log events where each event is an array with following keys:
|
||||
* - severity: (int) A database log severity constant.
|
||||
* - type: (string) The type of database log event.
|
||||
* - message: (string) The message for this database log event.
|
||||
* - user: (string) The user associated with this database log event.
|
||||
*/
|
||||
protected function getLogEntries() {
|
||||
$entries = array();
|
||||
@@ -502,11 +542,12 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of entries per type.
|
||||
* Gets the count of database log entries by database log event type.
|
||||
*
|
||||
* @param $types
|
||||
* @param array $types
|
||||
* The type information to compare against.
|
||||
* @return
|
||||
*
|
||||
* @return array
|
||||
* The count of each type keyed by the key of the $types array.
|
||||
*/
|
||||
protected function getTypeCount(array $types) {
|
||||
@@ -524,11 +565,12 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the watchdog severity constant corresponding to the CSS class.
|
||||
* Gets the watchdog severity constant corresponding to the CSS class.
|
||||
*
|
||||
* @param $class
|
||||
* @param string $class
|
||||
* CSS class attribute.
|
||||
* @return
|
||||
*
|
||||
* @return int|null
|
||||
* The watchdog severity constant or NULL if not found.
|
||||
*
|
||||
* @ingroup logging_severity_levels
|
||||
@@ -557,11 +599,12 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the text contained by the element.
|
||||
* Extracts the text contained by the XHTML element.
|
||||
*
|
||||
* @param $element
|
||||
* @param SimpleXMLElement $element
|
||||
* Element to extract text from.
|
||||
* @return
|
||||
*
|
||||
* @return string
|
||||
* Extracted text.
|
||||
*/
|
||||
protected function asText(SimpleXMLElement $element) {
|
||||
@@ -572,21 +615,22 @@ class DBLogTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert messages appear on the log overview screen.
|
||||
* Confirms that a log message appears on the database log overview screen.
|
||||
*
|
||||
* This function should be used only for admin/reports/dblog page, because it
|
||||
* check for the message link text truncated to 56 characters. Other dblog
|
||||
* pages have no detail links so contains a full message text.
|
||||
* This function should only be used for the admin/reports/dblog page, because
|
||||
* it checks for the message link text truncated to 56 characters. Other log
|
||||
* pages have no detail links so they contain the full message text.
|
||||
*
|
||||
* @param $log_message
|
||||
* The message to check.
|
||||
* @param $message
|
||||
* @param string $log_message
|
||||
* The database log message to check.
|
||||
* @param string $message
|
||||
* The message to pass to simpletest.
|
||||
*/
|
||||
protected function assertLogMessage($log_message, $message) {
|
||||
$message_text = truncate_utf8(filter_xss($log_message, array()), 56, TRUE, TRUE);
|
||||
// After filter_xss() HTML entities should be converted to their characters
|
||||
// because assertLink() uses this string in xpath() to query DOM.
|
||||
// After filter_xss(), HTML entities should be converted to their character
|
||||
// equivalents because assertLink() uses this string in xpath() to query the
|
||||
// Document Object Model (DOM).
|
||||
$this->assertLink(html_entity_decode($message_text), 0, $message);
|
||||
}
|
||||
}
|
||||
|
@@ -873,7 +873,7 @@ function hook_field_widget_form(&$form, &$form_state, $field, $instance, $langco
|
||||
'#type' => $instance['widget']['type'],
|
||||
'#default_value' => isset($items[$delta]) ? $items[$delta] : '',
|
||||
);
|
||||
return $element;
|
||||
return array('value' => $element);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1735,11 +1735,14 @@ function hook_field_storage_details_alter(&$details, $field) {
|
||||
* loaded.
|
||||
*/
|
||||
function hook_field_storage_load($entity_type, $entities, $age, $fields, $options) {
|
||||
$field_info = field_info_field_by_ids();
|
||||
$load_current = $age == FIELD_LOAD_CURRENT;
|
||||
|
||||
foreach ($fields as $field_id => $ids) {
|
||||
$field = $field_info[$field_id];
|
||||
// By the time this hook runs, the relevant field definitions have been
|
||||
// populated and cached in FieldInfo, so calling field_info_field_by_id()
|
||||
// on each field individually is more efficient than loading all fields in
|
||||
// memory upfront with field_info_field_by_ids().
|
||||
$field = field_info_field_by_id($field_id);
|
||||
$field_name = $field['field_name'];
|
||||
$table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
|
||||
|
||||
|
@@ -283,7 +283,6 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
|
||||
'language' => NULL,
|
||||
);
|
||||
$options += $default_options;
|
||||
$field_info = field_info_field_by_ids();
|
||||
|
||||
$fields = array();
|
||||
$grouped_instances = array();
|
||||
@@ -307,7 +306,7 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
|
||||
foreach ($instances as $instance) {
|
||||
$field_id = $instance['field_id'];
|
||||
$field_name = $instance['field_name'];
|
||||
$field = $field_info[$field_id];
|
||||
$field = field_info_field_by_id($field_id);
|
||||
$function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
|
||||
if (function_exists($function)) {
|
||||
// Add the field to the list of fields to invoke the hook on.
|
||||
@@ -555,16 +554,23 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
|
||||
* @param $langcode
|
||||
* The language the field values are going to be entered, if no language
|
||||
* is provided the default site language will be used.
|
||||
* @param array $options
|
||||
* An associative array of additional options. See _field_invoke() for
|
||||
* details.
|
||||
*
|
||||
* @see field_form_get_state()
|
||||
* @see field_form_set_state()
|
||||
*/
|
||||
function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode = NULL) {
|
||||
function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode = NULL, $options = array()) {
|
||||
// Validate $options since this is a new parameter added after Drupal 7 was
|
||||
// released.
|
||||
$options = is_array($options) ? $options : array();
|
||||
|
||||
// Set #parents to 'top-level' by default.
|
||||
$form += array('#parents' => array());
|
||||
|
||||
// If no language is provided use the default site language.
|
||||
$options = array('language' => field_valid_language($langcode));
|
||||
$options['language'] = field_valid_language($langcode);
|
||||
$form += (array) _field_invoke_default('form', $entity_type, $entity, $form, $form_state, $options);
|
||||
|
||||
// Add custom weight handling.
|
||||
@@ -614,7 +620,6 @@ function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcod
|
||||
* non-deleted fields are operated on.
|
||||
*/
|
||||
function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $options = array()) {
|
||||
$field_info = field_info_field_by_ids();
|
||||
$load_current = $age == FIELD_LOAD_CURRENT;
|
||||
|
||||
// Merge default options.
|
||||
@@ -692,7 +697,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
|
||||
}
|
||||
// Collect the storage backend if the field has not been loaded yet.
|
||||
if (!isset($skip_fields[$field_id])) {
|
||||
$field = $field_info[$field_id];
|
||||
$field = field_info_field_by_id($field_id);
|
||||
$storages[$field['storage']['type']][$field_id][] = $load_current ? $id : $vid;
|
||||
}
|
||||
}
|
||||
@@ -709,7 +714,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
|
||||
_field_invoke_multiple('load', $entity_type, $queried_entities, $age, $null, $options);
|
||||
|
||||
// Invoke hook_field_attach_load(): let other modules act on loading the
|
||||
// entitiy.
|
||||
// entity.
|
||||
module_invoke_all('field_attach_load', $entity_type, $queried_entities, $age, $options);
|
||||
|
||||
// Build cache data.
|
||||
@@ -769,13 +774,21 @@ function field_attach_load_revision($entity_type, $entities, $options = array())
|
||||
* If validation errors are found, a FieldValidationException is thrown. The
|
||||
* 'errors' property contains the array of errors, keyed by field name,
|
||||
* language and delta.
|
||||
* @param array $options
|
||||
* An associative array of additional options. See _field_invoke() for
|
||||
* details.
|
||||
*/
|
||||
function field_attach_validate($entity_type, $entity) {
|
||||
function field_attach_validate($entity_type, $entity, $options = array()) {
|
||||
// Validate $options since this is a new parameter added after Drupal 7 was
|
||||
// released.
|
||||
$options = is_array($options) ? $options : array();
|
||||
|
||||
$errors = array();
|
||||
// Check generic, field-type-agnostic errors first.
|
||||
_field_invoke_default('validate', $entity_type, $entity, $errors);
|
||||
$null = NULL;
|
||||
_field_invoke_default('validate', $entity_type, $entity, $errors, $null, $options);
|
||||
// Check field-type specific errors.
|
||||
_field_invoke('validate', $entity_type, $entity, $errors);
|
||||
_field_invoke('validate', $entity_type, $entity, $errors, $null, $options);
|
||||
|
||||
// Let other modules validate the entity.
|
||||
// Avoid module_invoke_all() to let $errors be taken by reference.
|
||||
@@ -817,14 +830,21 @@ function field_attach_validate($entity_type, $entity) {
|
||||
* full form structure, or a sub-element of a larger form.
|
||||
* @param $form_state
|
||||
* An associative array containing the current state of the form.
|
||||
* @param array $options
|
||||
* An associative array of additional options. See _field_invoke() for
|
||||
* details.
|
||||
*/
|
||||
function field_attach_form_validate($entity_type, $entity, $form, &$form_state) {
|
||||
function field_attach_form_validate($entity_type, $entity, $form, &$form_state, $options = array()) {
|
||||
// Validate $options since this is a new parameter added after Drupal 7 was
|
||||
// released.
|
||||
$options = is_array($options) ? $options : array();
|
||||
|
||||
// Extract field values from submitted values.
|
||||
_field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state);
|
||||
|
||||
// Perform field_level validation.
|
||||
try {
|
||||
field_attach_validate($entity_type, $entity);
|
||||
field_attach_validate($entity_type, $entity, $options);
|
||||
}
|
||||
catch (FieldValidationException $e) {
|
||||
// Pass field-level validation errors back to widgets for accurate error
|
||||
@@ -836,7 +856,7 @@ function field_attach_form_validate($entity_type, $entity, $form, &$form_state)
|
||||
field_form_set_state($form['#parents'], $field_name, $langcode, $form_state, $field_state);
|
||||
}
|
||||
}
|
||||
_field_invoke_default('form_errors', $entity_type, $entity, $form, $form_state);
|
||||
_field_invoke_default('form_errors', $entity_type, $entity, $form, $form_state, $options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -857,12 +877,19 @@ function field_attach_form_validate($entity_type, $entity, $form, &$form_state)
|
||||
* full form structure, or a sub-element of a larger form.
|
||||
* @param $form_state
|
||||
* An associative array containing the current state of the form.
|
||||
* @param array $options
|
||||
* An associative array of additional options. See _field_invoke() for
|
||||
* details.
|
||||
*/
|
||||
function field_attach_submit($entity_type, $entity, $form, &$form_state) {
|
||||
// Extract field values from submitted values.
|
||||
_field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state);
|
||||
function field_attach_submit($entity_type, $entity, $form, &$form_state, $options = array()) {
|
||||
// Validate $options since this is a new parameter added after Drupal 7 was
|
||||
// released.
|
||||
$options = is_array($options) ? $options : array();
|
||||
|
||||
_field_invoke_default('submit', $entity_type, $entity, $form, $form_state);
|
||||
// Extract field values from submitted values.
|
||||
_field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state, $options);
|
||||
|
||||
_field_invoke_default('submit', $entity_type, $entity, $form, $form_state, $options);
|
||||
|
||||
// Let other modules act on submitting the entity.
|
||||
// Avoid module_invoke_all() to let $form_state be taken by reference.
|
||||
@@ -1093,9 +1120,16 @@ function field_attach_delete_revision($entity_type, $entity) {
|
||||
* @param $langcode
|
||||
* (Optional) The language the field values are to be shown in. If no language
|
||||
* is provided the current language is used.
|
||||
* @param array $options
|
||||
* An associative array of additional options. See _field_invoke() for
|
||||
* details.
|
||||
*/
|
||||
function field_attach_prepare_view($entity_type, $entities, $view_mode, $langcode = NULL) {
|
||||
$options = array('language' => array());
|
||||
function field_attach_prepare_view($entity_type, $entities, $view_mode, $langcode = NULL, $options = array()) {
|
||||
// Validate $options since this is a new parameter added after Drupal 7 was
|
||||
// released.
|
||||
$options = is_array($options) ? $options : array();
|
||||
|
||||
$options['language'] = array();
|
||||
|
||||
// To ensure hooks are only run once per entity, only process items without
|
||||
// the _field_view_prepared flag.
|
||||
@@ -1167,14 +1201,21 @@ function field_attach_prepare_view($entity_type, $entities, $view_mode, $langcod
|
||||
* @param $langcode
|
||||
* The language the field values are to be shown in. If no language is
|
||||
* provided the current language is used.
|
||||
* @param array $options
|
||||
* An associative array of additional options. See _field_invoke() for
|
||||
* details.
|
||||
* @return
|
||||
* A renderable array for the field values.
|
||||
*/
|
||||
function field_attach_view($entity_type, $entity, $view_mode, $langcode = NULL) {
|
||||
function field_attach_view($entity_type, $entity, $view_mode, $langcode = NULL, $options = array()) {
|
||||
// Validate $options since this is a new parameter added after Drupal 7 was
|
||||
// released.
|
||||
$options = is_array($options) ? $options : array();
|
||||
|
||||
// Determine the actual language to display for each field, given the
|
||||
// languages available in the field data.
|
||||
$display_language = field_language($entity_type, $entity, NULL, $langcode);
|
||||
$options = array('language' => $display_language);
|
||||
$options['language'] = $display_language;
|
||||
|
||||
// Invoke field_default_view().
|
||||
$null = NULL;
|
||||
|
@@ -319,7 +319,11 @@ function field_read_field($field_name, $include_additional = array()) {
|
||||
* Reads in fields that match an array of conditions.
|
||||
*
|
||||
* @param array $params
|
||||
* An array of conditions to match against.
|
||||
* An array of conditions to match against. Keys are columns from the
|
||||
* 'field_config' table, values are conditions to match. Additionally,
|
||||
* conditions on the 'entity_type' and 'bundle' columns from the
|
||||
* 'field_config_instance' table are supported (select fields having an
|
||||
* instance on a given bundle).
|
||||
* @param array $include_additional
|
||||
* The default behavior of this function is to not return fields that
|
||||
* are inactive or have been deleted. Setting
|
||||
@@ -337,8 +341,21 @@ function field_read_fields($params = array(), $include_additional = array()) {
|
||||
|
||||
// Turn the conditions into a query.
|
||||
foreach ($params as $key => $value) {
|
||||
// Allow filtering on the 'entity_type' and 'bundle' columns of the
|
||||
// field_config_instance table.
|
||||
if ($key == 'entity_type' || $key == 'bundle') {
|
||||
if (empty($fci_join)) {
|
||||
$fci_join = $query->join('field_config_instance', 'fci', 'fc.id = fci.field_id');
|
||||
}
|
||||
$key = 'fci.' . $key;
|
||||
}
|
||||
else {
|
||||
$key = 'fc.' . $key;
|
||||
}
|
||||
|
||||
$query->condition($key, $value);
|
||||
}
|
||||
|
||||
if (!isset($include_additional['include_inactive']) || !$include_additional['include_inactive']) {
|
||||
$query
|
||||
->condition('fc.active', 1)
|
||||
|
@@ -5,13 +5,14 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = field.module
|
||||
files[] = field.attach.inc
|
||||
files[] = field.info.class.inc
|
||||
files[] = tests/field.test
|
||||
dependencies[] = field_sql_storage
|
||||
required = TRUE
|
||||
stylesheets[all][] = theme/field.css
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
668
modules/field/field.info.class.inc
Normal file
668
modules/field/field.info.class.inc
Normal file
@@ -0,0 +1,668 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @file
|
||||
* Definition of the FieldInfo class.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides field and instance definitions for the current runtime environment.
|
||||
*
|
||||
* A FieldInfo object is created and statically persisted through the request
|
||||
* by the _field_info_field_cache() function. The object properties act as a
|
||||
* "static cache" of fields and instances definitions.
|
||||
*
|
||||
* The preferred way to access definitions is through the getBundleInstances()
|
||||
* method, which keeps cache entries per bundle, storing both fields and
|
||||
* instances for a given bundle. Fields used in multiple bundles are duplicated
|
||||
* in several cache entries, and are merged into a single list in the memory
|
||||
* cache. Cache entries are loaded for bundles as a whole, optimizing memory
|
||||
* and CPU usage for the most common pattern of iterating over all instances of
|
||||
* a bundle rather than accessing a single instance.
|
||||
*
|
||||
* The getFields() and getInstances() methods, which return all existing field
|
||||
* and instance definitions, are kept mainly for backwards compatibility, and
|
||||
* should be avoided when possible, since they load and persist in memory a
|
||||
* potentially large array of information. In many cases, the lightweight
|
||||
* getFieldMap() method should be preferred.
|
||||
*/
|
||||
class FieldInfo {
|
||||
|
||||
/**
|
||||
* Lightweight map of fields across entity types and bundles.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldMap;
|
||||
|
||||
/**
|
||||
* List of $field structures keyed by ID. Includes deleted fields.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldsById = array();
|
||||
|
||||
/**
|
||||
* Mapping of field names to the ID of the corresponding non-deleted field.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldIdsByName = array();
|
||||
|
||||
/**
|
||||
* Whether $fieldsById contains all field definitions or a subset.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $loadedAllFields = FALSE;
|
||||
|
||||
/**
|
||||
* Separately tracks requested field names or IDs that do not exist.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $unknownFields = array();
|
||||
|
||||
/**
|
||||
* Instance definitions by bundle.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $bundleInstances = array();
|
||||
|
||||
/**
|
||||
* Whether $bundleInstances contains all instances definitions or a subset.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $loadedAllInstances = FALSE;
|
||||
|
||||
/**
|
||||
* Separately tracks requested bundles that are empty (or do not exist).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $emptyBundles = array();
|
||||
|
||||
/**
|
||||
* Extra fields by bundle.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $bundleExtraFields = array();
|
||||
|
||||
/**
|
||||
* Clears the "static" and persistent caches.
|
||||
*/
|
||||
public function flush() {
|
||||
$this->fieldMap = NULL;
|
||||
|
||||
$this->fieldsById = array();
|
||||
$this->fieldIdsByName = array();
|
||||
$this->loadedAllFields = FALSE;
|
||||
$this->unknownFields = array();
|
||||
|
||||
$this->bundleInstances = array();
|
||||
$this->loadedAllInstances = FALSE;
|
||||
$this->emptyBundles = array();
|
||||
|
||||
$this->bundleExtraFields = array();
|
||||
|
||||
cache_clear_all('field_info:', 'cache_field', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects a lightweight map of fields across bundles.
|
||||
*
|
||||
* @return
|
||||
* An array keyed by field name. Each value is an array with two entries:
|
||||
* - type: The field type.
|
||||
* - bundles: The bundles in which the field appears, as an array with
|
||||
* entity types as keys and the array of bundle names as values.
|
||||
*/
|
||||
public function getFieldMap() {
|
||||
// Read from the "static" cache.
|
||||
if ($this->fieldMap !== NULL) {
|
||||
return $this->fieldMap;
|
||||
}
|
||||
|
||||
// Read from persistent cache.
|
||||
if ($cached = cache_get('field_info:field_map', 'cache_field')) {
|
||||
$map = $cached->data;
|
||||
|
||||
// Save in "static" cache.
|
||||
$this->fieldMap = $map;
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
$map = array();
|
||||
|
||||
$query = db_query('SELECT fc.type, fci.field_name, fci.entity_type, fci.bundle FROM {field_config_instance} fci INNER JOIN {field_config} fc ON fc.id = fci.field_id WHERE fc.active = 1 AND fc.storage_active = 1 AND fc.deleted = 0 AND fci.deleted = 0');
|
||||
foreach ($query as $row) {
|
||||
$map[$row->field_name]['bundles'][$row->entity_type][] = $row->bundle;
|
||||
$map[$row->field_name]['type'] = $row->type;
|
||||
}
|
||||
|
||||
// Save in "static" and persistent caches.
|
||||
$this->fieldMap = $map;
|
||||
cache_set('field_info:field_map', $map, 'cache_field');
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all active fields, including deleted ones.
|
||||
*
|
||||
* @return
|
||||
* An array of field definitions, keyed by field ID.
|
||||
*/
|
||||
public function getFields() {
|
||||
// Read from the "static" cache.
|
||||
if ($this->loadedAllFields) {
|
||||
return $this->fieldsById;
|
||||
}
|
||||
|
||||
// Read from persistent cache.
|
||||
if ($cached = cache_get('field_info:fields', 'cache_field')) {
|
||||
$this->fieldsById = $cached->data;
|
||||
}
|
||||
else {
|
||||
// Collect and prepare fields.
|
||||
foreach (field_read_fields(array(), array('include_deleted' => TRUE)) as $field) {
|
||||
$this->fieldsById[$field['id']] = $this->prepareField($field);
|
||||
}
|
||||
|
||||
// Store in persistent cache.
|
||||
cache_set('field_info:fields', $this->fieldsById, 'cache_field');
|
||||
}
|
||||
|
||||
// Fill the name/ID map.
|
||||
foreach ($this->fieldsById as $field) {
|
||||
if (!$field['deleted']) {
|
||||
$this->fieldIdsByName[$field['field_name']] = $field['id'];
|
||||
}
|
||||
}
|
||||
|
||||
$this->loadedAllFields = TRUE;
|
||||
|
||||
return $this->fieldsById;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all active, non-deleted instances definitions.
|
||||
*
|
||||
* @param $entity_type
|
||||
* (optional) The entity type.
|
||||
*
|
||||
* @return
|
||||
* If $entity_type is not set, all instances keyed by entity type and bundle
|
||||
* name. If $entity_type is set, all instances for that entity type, keyed
|
||||
* by bundle name.
|
||||
*/
|
||||
public function getInstances($entity_type = NULL) {
|
||||
// If the full list is not present in "static" cache yet.
|
||||
if (!$this->loadedAllInstances) {
|
||||
|
||||
// Read from persistent cache.
|
||||
if ($cached = cache_get('field_info:instances', 'cache_field')) {
|
||||
$this->bundleInstances = $cached->data;
|
||||
}
|
||||
else {
|
||||
// Collect and prepare instances.
|
||||
|
||||
// We also need to populate the static field cache, since it will not
|
||||
// be set by subsequent getBundleInstances() calls.
|
||||
$this->getFields();
|
||||
|
||||
// Initialize empty arrays for all existing entity types and bundles.
|
||||
// This is not strictly needed, but is done to preserve the behavior of
|
||||
// field_info_instances() before http://drupal.org/node/1915646.
|
||||
foreach (field_info_bundles() as $existing_entity_type => $bundles) {
|
||||
foreach ($bundles as $bundle => $bundle_info) {
|
||||
$this->bundleInstances[$existing_entity_type][$bundle] = array();
|
||||
}
|
||||
}
|
||||
|
||||
foreach (field_read_instances() as $instance) {
|
||||
$field = $this->getField($instance['field_name']);
|
||||
$instance = $this->prepareInstance($instance, $field['type']);
|
||||
$this->bundleInstances[$instance['entity_type']][$instance['bundle']][$instance['field_name']] = $instance;
|
||||
}
|
||||
|
||||
// Store in persistent cache.
|
||||
cache_set('field_info:instances', $this->bundleInstances, 'cache_field');
|
||||
}
|
||||
|
||||
$this->loadedAllInstances = TRUE;
|
||||
}
|
||||
|
||||
if (isset($entity_type)) {
|
||||
return isset($this->bundleInstances[$entity_type]) ? $this->bundleInstances[$entity_type] : array();
|
||||
}
|
||||
else {
|
||||
return $this->bundleInstances;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a field definition from a field name.
|
||||
*
|
||||
* This method only retrieves active, non-deleted fields.
|
||||
*
|
||||
* @param $field_name
|
||||
* The field name.
|
||||
*
|
||||
* @return
|
||||
* The field definition, or NULL if no field was found.
|
||||
*/
|
||||
public function getField($field_name) {
|
||||
// Read from the "static" cache.
|
||||
if (isset($this->fieldIdsByName[$field_name])) {
|
||||
$field_id = $this->fieldIdsByName[$field_name];
|
||||
return $this->fieldsById[$field_id];
|
||||
}
|
||||
if (isset($this->unknownFields[$field_name])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not check the (large) persistent cache, but read the definition.
|
||||
|
||||
// Cache miss: read from definition.
|
||||
if ($field = field_read_field($field_name)) {
|
||||
$field = $this->prepareField($field);
|
||||
|
||||
// Save in the "static" cache.
|
||||
$this->fieldsById[$field['id']] = $field;
|
||||
$this->fieldIdsByName[$field['field_name']] = $field['id'];
|
||||
|
||||
return $field;
|
||||
}
|
||||
else {
|
||||
$this->unknownFields[$field_name] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a field definition from a field ID.
|
||||
*
|
||||
* This method only retrieves active fields, deleted or not.
|
||||
*
|
||||
* @param $field_id
|
||||
* The field ID.
|
||||
*
|
||||
* @return
|
||||
* The field definition, or NULL if no field was found.
|
||||
*/
|
||||
public function getFieldById($field_id) {
|
||||
// Read from the "static" cache.
|
||||
if (isset($this->fieldsById[$field_id])) {
|
||||
return $this->fieldsById[$field_id];
|
||||
}
|
||||
if (isset($this->unknownFields[$field_id])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No persistent cache, fields are only persistently cached as part of a
|
||||
// bundle.
|
||||
|
||||
// Cache miss: read from definition.
|
||||
if ($fields = field_read_fields(array('id' => $field_id), array('include_deleted' => TRUE))) {
|
||||
$field = current($fields);
|
||||
$field = $this->prepareField($field);
|
||||
|
||||
// Store in the static cache.
|
||||
$this->fieldsById[$field['id']] = $field;
|
||||
if (!$field['deleted']) {
|
||||
$this->fieldIdsByName[$field['field_name']] = $field['id'];
|
||||
}
|
||||
|
||||
return $field;
|
||||
}
|
||||
else {
|
||||
$this->unknownFields[$field_id] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the instances for a bundle.
|
||||
*
|
||||
* The function also populates the corresponding field definitions in the
|
||||
* "static" cache.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The entity type.
|
||||
* @param $bundle
|
||||
* The bundle name.
|
||||
*
|
||||
* @return
|
||||
* The array of instance definitions, keyed by field name.
|
||||
*/
|
||||
public function getBundleInstances($entity_type, $bundle) {
|
||||
// Read from the "static" cache.
|
||||
if (isset($this->bundleInstances[$entity_type][$bundle])) {
|
||||
return $this->bundleInstances[$entity_type][$bundle];
|
||||
}
|
||||
if (isset($this->emptyBundles[$entity_type][$bundle])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// Read from the persistent cache.
|
||||
if ($cached = cache_get("field_info:bundle:$entity_type:$bundle", 'cache_field')) {
|
||||
$info = $cached->data;
|
||||
|
||||
// Extract the field definitions and save them in the "static" cache.
|
||||
foreach ($info['fields'] as $field) {
|
||||
if (!isset($this->fieldsById[$field['id']])) {
|
||||
$this->fieldsById[$field['id']] = $field;
|
||||
if (!$field['deleted']) {
|
||||
$this->fieldIdsByName[$field['field_name']] = $field['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($info['fields']);
|
||||
|
||||
// Store the instance definitions in the "static" cache'. Empty (or
|
||||
// non-existent) bundles are stored separately, so that they do not
|
||||
// pollute the global list returned by getInstances().
|
||||
if ($info['instances']) {
|
||||
$this->bundleInstances[$entity_type][$bundle] = $info['instances'];
|
||||
}
|
||||
else {
|
||||
$this->emptyBundles[$entity_type][$bundle] = TRUE;
|
||||
}
|
||||
|
||||
return $info['instances'];
|
||||
}
|
||||
|
||||
// Cache miss: collect from the definitions.
|
||||
|
||||
$instances = array();
|
||||
|
||||
// Collect the fields in the bundle.
|
||||
$params = array('entity_type' => $entity_type, 'bundle' => $bundle);
|
||||
$fields = field_read_fields($params);
|
||||
|
||||
// This iterates on non-deleted instances, so deleted fields are kept out of
|
||||
// the persistent caches.
|
||||
foreach (field_read_instances($params) as $instance) {
|
||||
$field = $fields[$instance['field_name']];
|
||||
|
||||
$instance = $this->prepareInstance($instance, $field['type']);
|
||||
$instances[$field['field_name']] = $instance;
|
||||
|
||||
// If the field is not in our global "static" list yet, add it.
|
||||
if (!isset($this->fieldsById[$field['id']])) {
|
||||
$field = $this->prepareField($field);
|
||||
|
||||
$this->fieldsById[$field['id']] = $field;
|
||||
$this->fieldIdsByName[$field['field_name']] = $field['id'];
|
||||
}
|
||||
}
|
||||
|
||||
// Store in the 'static' cache'. Empty (or non-existent) bundles are stored
|
||||
// separately, so that they do not pollute the global list returned by
|
||||
// getInstances().
|
||||
if ($instances) {
|
||||
$this->bundleInstances[$entity_type][$bundle] = $instances;
|
||||
}
|
||||
else {
|
||||
$this->emptyBundles[$entity_type][$bundle] = TRUE;
|
||||
}
|
||||
|
||||
// The persistent cache additionally contains the definitions of the fields
|
||||
// involved in the bundle.
|
||||
$cache = array(
|
||||
'instances' => $instances,
|
||||
'fields' => array()
|
||||
);
|
||||
foreach ($instances as $instance) {
|
||||
$cache['fields'][] = $this->fieldsById[$instance['field_id']];
|
||||
}
|
||||
cache_set("field_info:bundle:$entity_type:$bundle", $cache, 'cache_field');
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the "extra fields" for a bundle.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The entity type.
|
||||
* @param $bundle
|
||||
* The bundle name.
|
||||
*
|
||||
* @return
|
||||
* The array of extra fields.
|
||||
*/
|
||||
public function getBundleExtraFields($entity_type, $bundle) {
|
||||
// Read from the "static" cache.
|
||||
if (isset($this->bundleExtraFields[$entity_type][$bundle])) {
|
||||
return $this->bundleExtraFields[$entity_type][$bundle];
|
||||
}
|
||||
|
||||
// Read from the persistent cache.
|
||||
if ($cached = cache_get("field_info:bundle_extra:$entity_type:$bundle", 'cache_field')) {
|
||||
$this->bundleExtraFields[$entity_type][$bundle] = $cached->data;
|
||||
return $this->bundleExtraFields[$entity_type][$bundle];
|
||||
}
|
||||
|
||||
// Cache miss: read from hook_field_extra_fields(). Note: given the current
|
||||
// shape of the hook, we have no other way than collecting extra fields on
|
||||
// all bundles.
|
||||
$info = array();
|
||||
$extra = module_invoke_all('field_extra_fields');
|
||||
drupal_alter('field_extra_fields', $extra);
|
||||
// Merge in saved settings.
|
||||
if (isset($extra[$entity_type][$bundle])) {
|
||||
$info = $this->prepareExtraFields($extra[$entity_type][$bundle], $entity_type, $bundle);
|
||||
}
|
||||
|
||||
// Store in the 'static' and persistent caches.
|
||||
$this->bundleExtraFields[$entity_type][$bundle] = $info;
|
||||
cache_set("field_info:bundle_extra:$entity_type:$bundle", $info, 'cache_field');
|
||||
|
||||
return $this->bundleExtraFields[$entity_type][$bundle];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a field definition for the current run-time context.
|
||||
*
|
||||
* @param $field
|
||||
* The raw field structure as read from the database.
|
||||
*
|
||||
* @return
|
||||
* The field definition completed for the current runtime context.
|
||||
*/
|
||||
public function prepareField($field) {
|
||||
// Make sure all expected field settings are present.
|
||||
$field['settings'] += field_info_field_settings($field['type']);
|
||||
$field['storage']['settings'] += field_info_storage_settings($field['storage']['type']);
|
||||
|
||||
// Add storage details.
|
||||
$details = (array) module_invoke($field['storage']['module'], 'field_storage_details', $field);
|
||||
drupal_alter('field_storage_details', $details, $field);
|
||||
$field['storage']['details'] = $details;
|
||||
|
||||
// Populate the list of bundles using the field.
|
||||
$field['bundles'] = array();
|
||||
if (!$field['deleted']) {
|
||||
$map = $this->getFieldMap();
|
||||
if (isset($map[$field['field_name']])) {
|
||||
$field['bundles'] = $map[$field['field_name']]['bundles'];
|
||||
}
|
||||
}
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares an instance definition for the current run-time context.
|
||||
*
|
||||
* @param $instance
|
||||
* The raw instance structure as read from the database.
|
||||
* @param $field_type
|
||||
* The field type.
|
||||
*
|
||||
* @return
|
||||
* The field instance array completed for the current runtime context.
|
||||
*/
|
||||
public function prepareInstance($instance, $field_type) {
|
||||
// Make sure all expected instance settings are present.
|
||||
$instance['settings'] += field_info_instance_settings($field_type);
|
||||
|
||||
// Set a default value for the instance.
|
||||
if (field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT && !isset($instance['default_value'])) {
|
||||
$instance['default_value'] = NULL;
|
||||
}
|
||||
|
||||
// Prepare widget settings.
|
||||
$instance['widget'] = $this->prepareInstanceWidget($instance['widget'], $field_type);
|
||||
|
||||
// Prepare display settings.
|
||||
foreach ($instance['display'] as $view_mode => $display) {
|
||||
$instance['display'][$view_mode] = $this->prepareInstanceDisplay($display, $field_type);
|
||||
}
|
||||
|
||||
// Fall back to 'hidden' for view modes configured to use custom display
|
||||
// settings, and for which the instance has no explicit settings.
|
||||
$entity_info = entity_get_info($instance['entity_type']);
|
||||
$view_modes = array_merge(array('default'), array_keys($entity_info['view modes']));
|
||||
$view_mode_settings = field_view_mode_settings($instance['entity_type'], $instance['bundle']);
|
||||
foreach ($view_modes as $view_mode) {
|
||||
if ($view_mode == 'default' || !empty($view_mode_settings[$view_mode]['custom_settings'])) {
|
||||
if (!isset($instance['display'][$view_mode])) {
|
||||
$instance['display'][$view_mode] = array(
|
||||
'type' => 'hidden',
|
||||
'label' => 'above',
|
||||
'settings' => array(),
|
||||
'weight' => 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares widget properties for the current run-time context.
|
||||
*
|
||||
* @param $widget
|
||||
* Widget specifications as found in $instance['widget'].
|
||||
* @param $field_type
|
||||
* The field type.
|
||||
*
|
||||
* @return
|
||||
* The widget properties completed for the current runtime context.
|
||||
*/
|
||||
public function prepareInstanceWidget($widget, $field_type) {
|
||||
$field_type_info = field_info_field_types($field_type);
|
||||
|
||||
// Fill in default values.
|
||||
$widget += array(
|
||||
'type' => $field_type_info['default_widget'],
|
||||
'settings' => array(),
|
||||
'weight' => 0,
|
||||
);
|
||||
|
||||
$widget_type_info = field_info_widget_types($widget['type']);
|
||||
// Fall back to default formatter if formatter type is not available.
|
||||
if (!$widget_type_info) {
|
||||
$widget['type'] = $field_type_info['default_widget'];
|
||||
$widget_type_info = field_info_widget_types($widget['type']);
|
||||
}
|
||||
$widget['module'] = $widget_type_info['module'];
|
||||
// Fill in default settings for the widget.
|
||||
$widget['settings'] += field_info_widget_settings($widget['type']);
|
||||
|
||||
return $widget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts display specifications to the current run-time context.
|
||||
*
|
||||
* @param $display
|
||||
* Display specifications as found in $instance['display']['a_view_mode'].
|
||||
* @param $field_type
|
||||
* The field type.
|
||||
*
|
||||
* @return
|
||||
* The display properties completed for the current runtime context.
|
||||
*/
|
||||
public function prepareInstanceDisplay($display, $field_type) {
|
||||
$field_type_info = field_info_field_types($field_type);
|
||||
|
||||
// Fill in default values.
|
||||
$display += array(
|
||||
'label' => 'above',
|
||||
'type' => $field_type_info['default_formatter'],
|
||||
'settings' => array(),
|
||||
'weight' => 0,
|
||||
);
|
||||
if ($display['type'] != 'hidden') {
|
||||
$formatter_type_info = field_info_formatter_types($display['type']);
|
||||
// Fall back to default formatter if formatter type is not available.
|
||||
if (!$formatter_type_info) {
|
||||
$display['type'] = $field_type_info['default_formatter'];
|
||||
$formatter_type_info = field_info_formatter_types($display['type']);
|
||||
}
|
||||
$display['module'] = $formatter_type_info['module'];
|
||||
// Fill in default settings for the formatter.
|
||||
$display['settings'] += field_info_formatter_settings($display['type']);
|
||||
}
|
||||
|
||||
return $display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares 'extra fields' for the current run-time context.
|
||||
*
|
||||
* @param $extra_fields
|
||||
* The array of extra fields, as collected in hook_field_extra_fields().
|
||||
* @param $entity_type
|
||||
* The entity type.
|
||||
* @param $bundle
|
||||
* The bundle name.
|
||||
*
|
||||
* @return
|
||||
* The list of extra fields completed for the current runtime context.
|
||||
*/
|
||||
public function prepareExtraFields($extra_fields, $entity_type, $bundle) {
|
||||
$entity_type_info = entity_get_info($entity_type);
|
||||
$bundle_settings = field_bundle_settings($entity_type, $bundle);
|
||||
$extra_fields += array('form' => array(), 'display' => array());
|
||||
|
||||
$result = array();
|
||||
// Extra fields in forms.
|
||||
foreach ($extra_fields['form'] as $name => $field_data) {
|
||||
$settings = isset($bundle_settings['extra_fields']['form'][$name]) ? $bundle_settings['extra_fields']['form'][$name] : array();
|
||||
if (isset($settings['weight'])) {
|
||||
$field_data['weight'] = $settings['weight'];
|
||||
}
|
||||
$result['form'][$name] = $field_data;
|
||||
}
|
||||
|
||||
// Extra fields in displayed entities.
|
||||
$data = $extra_fields['display'];
|
||||
foreach ($extra_fields['display'] as $name => $field_data) {
|
||||
$settings = isset($bundle_settings['extra_fields']['display'][$name]) ? $bundle_settings['extra_fields']['display'][$name] : array();
|
||||
$view_modes = array_merge(array('default'), array_keys($entity_type_info['view modes']));
|
||||
foreach ($view_modes as $view_mode) {
|
||||
if (isset($settings[$view_mode])) {
|
||||
$field_data['display'][$view_mode] = $settings[$view_mode];
|
||||
}
|
||||
else {
|
||||
$field_data['display'][$view_mode] = array(
|
||||
'weight' => $field_data['weight'],
|
||||
'visible' => TRUE,
|
||||
);
|
||||
}
|
||||
}
|
||||
unset($field_data['weight']);
|
||||
$result['display'][$name] = $field_data;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@@ -5,6 +5,32 @@
|
||||
* Field Info API, providing information about available fields and field types.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Retrieves the FieldInfo object for the current request.
|
||||
*
|
||||
* @return FieldInfo
|
||||
* An instance of the FieldInfo class.
|
||||
*/
|
||||
function _field_info_field_cache() {
|
||||
// Use the advanced drupal_static() pattern, since this is called very often.
|
||||
static $drupal_static_fast;
|
||||
|
||||
if (!isset($drupal_static_fast)) {
|
||||
$drupal_static_fast['field_info_field_cache'] = &drupal_static(__FUNCTION__);
|
||||
}
|
||||
$field_info = &$drupal_static_fast['field_info_field_cache'];
|
||||
|
||||
if (!isset($field_info)) {
|
||||
// @todo The registry should save the need for an explicit include, but not
|
||||
// a couple upgrade tests (DisabledNodeTypeTestCase,
|
||||
// FilterFormatUpgradePathTestCase...) break in a strange way without it.
|
||||
include_once dirname(__FILE__) . '/field.info.class.inc';
|
||||
$field_info = new FieldInfo();
|
||||
}
|
||||
|
||||
return $field_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* @defgroup field_info Field Info API
|
||||
* @{
|
||||
@@ -34,7 +60,50 @@ function field_info_cache_clear() {
|
||||
entity_info_cache_clear();
|
||||
|
||||
_field_info_collate_types(TRUE);
|
||||
_field_info_collate_fields(TRUE);
|
||||
_field_info_field_cache()->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Collates all information on existing fields and instances.
|
||||
*
|
||||
* Deprecated. This function is kept to ensure backwards compatibility, but has
|
||||
* a serious performance impact, and should be absolutely avoided.
|
||||
* See http://drupal.org/node/1915646.
|
||||
*
|
||||
* Use the regular field_info_*() API functions to access the information, or
|
||||
* field_info_cache_clear() to clear the cached data.
|
||||
*/
|
||||
function _field_info_collate_fields($reset = FALSE) {
|
||||
if ($reset) {
|
||||
_field_info_field_cache()->flush();
|
||||
return;
|
||||
}
|
||||
|
||||
$cache = _field_info_field_cache();
|
||||
|
||||
// Collect fields, and build the array of IDs keyed by field_name.
|
||||
$fields = $cache->getFields();
|
||||
$field_ids = array();
|
||||
foreach ($fields as $id => $field) {
|
||||
if (!$field['deleted']) {
|
||||
$field_ids[$field['field_name']] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
// Collect extra fields for all entity types.
|
||||
$extra_fields = array();
|
||||
foreach (field_info_bundles() as $entity_type => $bundles) {
|
||||
foreach ($bundles as $bundle => $info) {
|
||||
$extra_fields[$entity_type][$bundle] = $cache->getBundleExtraFields($entity_type, $bundle);
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'fields' => $fields,
|
||||
'field_ids' => $field_ids,
|
||||
'instances' => $cache->getInstances(),
|
||||
'extra_fields' => $extra_fields,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,282 +230,69 @@ function _field_info_collate_types($reset = FALSE) {
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collates all information on existing fields and instances.
|
||||
*
|
||||
* @param $reset
|
||||
* If TRUE, clear the cache. The information will be rebuilt from the
|
||||
* database next time it is needed. Defaults to FALSE.
|
||||
*
|
||||
* @return
|
||||
* If $reset is TRUE, nothing.
|
||||
* If $reset is FALSE, an array containing the following elements:
|
||||
* - fields: Array of existing fields, keyed by field ID. This element
|
||||
* lists deleted and non-deleted fields, but not inactive ones.
|
||||
* Each field has an additional element, 'bundles', which is an array
|
||||
* of all non-deleted instances of that field.
|
||||
* - field_ids: Array of field IDs, keyed by field name. This element
|
||||
* only lists non-deleted, active fields.
|
||||
* - instances: Array of existing instances, keyed by entity type, bundle
|
||||
* name and field name. This element only lists non-deleted instances
|
||||
* whose field is active.
|
||||
*/
|
||||
function _field_info_collate_fields($reset = FALSE) {
|
||||
static $info;
|
||||
|
||||
if ($reset) {
|
||||
$info = NULL;
|
||||
cache_clear_all('field_info_fields', 'cache_field');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($info)) {
|
||||
if ($cached = cache_get('field_info_fields', 'cache_field')) {
|
||||
$info = $cached->data;
|
||||
}
|
||||
else {
|
||||
$definitions = array(
|
||||
'field_ids' => field_read_fields(array(), array('include_deleted' => 1)),
|
||||
'instances' => field_read_instances(),
|
||||
);
|
||||
|
||||
// Populate 'fields' with all fields, keyed by ID.
|
||||
$info['fields'] = array();
|
||||
foreach ($definitions['field_ids'] as $key => $field) {
|
||||
$info['fields'][$key] = $definitions['field_ids'][$key] = _field_info_prepare_field($field);
|
||||
}
|
||||
|
||||
// Build an array of field IDs for non-deleted fields, keyed by name.
|
||||
$info['field_ids'] = array();
|
||||
foreach ($info['fields'] as $key => $field) {
|
||||
if (!$field['deleted']) {
|
||||
$info['field_ids'][$field['field_name']] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
// Populate 'instances'. Only non-deleted instances are considered.
|
||||
$info['instances'] = array();
|
||||
foreach (field_info_bundles() as $entity_type => $bundles) {
|
||||
foreach ($bundles as $bundle => $bundle_info) {
|
||||
$info['instances'][$entity_type][$bundle] = array();
|
||||
}
|
||||
}
|
||||
foreach ($definitions['instances'] as $instance) {
|
||||
$field = $info['fields'][$instance['field_id']];
|
||||
$instance = _field_info_prepare_instance($instance, $field);
|
||||
$info['instances'][$instance['entity_type']][$instance['bundle']][$instance['field_name']] = $instance;
|
||||
// Enrich field definitions with the list of bundles where they have
|
||||
// instances. NOTE: Deleted fields in $info['field_ids'] are not
|
||||
// enriched because all of their instances are deleted, too, and
|
||||
// are thus not in $definitions['instances'].
|
||||
$info['fields'][$instance['field_id']]['bundles'][$instance['entity_type']][] = $instance['bundle'];
|
||||
}
|
||||
|
||||
// Populate 'extra_fields'.
|
||||
$extra = module_invoke_all('field_extra_fields');
|
||||
drupal_alter('field_extra_fields', $extra);
|
||||
// Merge in saved settings.
|
||||
foreach ($extra as $entity_type => $bundles) {
|
||||
foreach ($bundles as $bundle => $extra_fields) {
|
||||
$extra_fields = _field_info_prepare_extra_fields($extra_fields, $entity_type, $bundle);
|
||||
$info['extra_fields'][$entity_type][$bundle] = $extra_fields;
|
||||
}
|
||||
}
|
||||
|
||||
cache_set('field_info_fields', $info, 'cache_field');
|
||||
}
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a field definition for the current run-time context.
|
||||
*
|
||||
* Since the field was last saved or updated, new field settings can be
|
||||
* expected.
|
||||
* The functionality has moved to the FieldInfo class. This function is kept as
|
||||
* a backwards-compatibility layer. See http://drupal.org/node/1915646.
|
||||
*
|
||||
* @param $field
|
||||
* The raw field structure as read from the database.
|
||||
* @see FieldInfo::prepareField()
|
||||
*/
|
||||
function _field_info_prepare_field($field) {
|
||||
// Make sure all expected field settings are present.
|
||||
$field['settings'] += field_info_field_settings($field['type']);
|
||||
$field['storage']['settings'] += field_info_storage_settings($field['storage']['type']);
|
||||
|
||||
// Add storage details.
|
||||
$details = (array) module_invoke($field['storage']['module'], 'field_storage_details', $field);
|
||||
drupal_alter('field_storage_details', $details, $field, $instance);
|
||||
$field['storage']['details'] = $details;
|
||||
|
||||
// Initialize the 'bundles' list.
|
||||
$field['bundles'] = array();
|
||||
|
||||
return $field;
|
||||
$cache = _field_info_field_cache();
|
||||
return $cache->prepareField($field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares an instance definition for the current run-time context.
|
||||
*
|
||||
* Since the instance was last saved or updated, a number of things might have
|
||||
* changed: widgets or formatters disabled, new settings expected, new view
|
||||
* modes added...
|
||||
* The functionality has moved to the FieldInfo class. This function is kept as
|
||||
* a backwards-compatibility layer. See http://drupal.org/node/1915646.
|
||||
*
|
||||
* @param $instance
|
||||
* The raw instance structure as read from the database.
|
||||
* @param $field
|
||||
* The field structure for the instance.
|
||||
*
|
||||
* @return
|
||||
* Field instance array.
|
||||
* @see FieldInfo::prepareInstance()
|
||||
*/
|
||||
function _field_info_prepare_instance($instance, $field) {
|
||||
// Make sure all expected instance settings are present.
|
||||
$instance['settings'] += field_info_instance_settings($field['type']);
|
||||
|
||||
// Set a default value for the instance.
|
||||
if (field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT && !isset($instance['default_value'])) {
|
||||
$instance['default_value'] = NULL;
|
||||
}
|
||||
|
||||
$instance['widget'] = _field_info_prepare_instance_widget($field, $instance['widget']);
|
||||
|
||||
foreach ($instance['display'] as $view_mode => $display) {
|
||||
$instance['display'][$view_mode] = _field_info_prepare_instance_display($field, $display);
|
||||
}
|
||||
|
||||
// Fallback to 'hidden' for view modes configured to use custom display
|
||||
// settings, and for which the instance has no explicit settings.
|
||||
$entity_info = entity_get_info($instance['entity_type']);
|
||||
$view_modes = array_merge(array('default'), array_keys($entity_info['view modes']));
|
||||
$view_mode_settings = field_view_mode_settings($instance['entity_type'], $instance['bundle']);
|
||||
foreach ($view_modes as $view_mode) {
|
||||
if ($view_mode == 'default' || !empty($view_mode_settings[$view_mode]['custom_settings'])) {
|
||||
if (!isset($instance['display'][$view_mode])) {
|
||||
$instance['display'][$view_mode] = array(
|
||||
'type' => 'hidden',
|
||||
'label' => 'above',
|
||||
'settings' => array(),
|
||||
'weight' => 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $instance;
|
||||
$cache = _field_info_field_cache();
|
||||
return $cache->prepareInstance($instance, $field['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts display specifications to the current run-time context.
|
||||
*
|
||||
* @param $field
|
||||
* The field structure for the instance.
|
||||
* @param $display
|
||||
* Display specifications as found in
|
||||
* $instance['display']['some_view_mode'].
|
||||
* The functionality has moved to the FieldInfo class. This function is kept as
|
||||
* a backwards-compatibility layer. See http://drupal.org/node/1915646.
|
||||
*
|
||||
* @see FieldInfo::prepareInstanceDisplay()
|
||||
*/
|
||||
function _field_info_prepare_instance_display($field, $display) {
|
||||
$field_type = field_info_field_types($field['type']);
|
||||
|
||||
// Fill in default values.
|
||||
$display += array(
|
||||
'label' => 'above',
|
||||
'type' => $field_type['default_formatter'],
|
||||
'settings' => array(),
|
||||
'weight' => 0,
|
||||
);
|
||||
if ($display['type'] != 'hidden') {
|
||||
$formatter_type = field_info_formatter_types($display['type']);
|
||||
// Fallback to default formatter if formatter type is not available.
|
||||
if (!$formatter_type) {
|
||||
$display['type'] = $field_type['default_formatter'];
|
||||
$formatter_type = field_info_formatter_types($display['type']);
|
||||
}
|
||||
$display['module'] = $formatter_type['module'];
|
||||
// Fill in default settings for the formatter.
|
||||
$display['settings'] += field_info_formatter_settings($display['type']);
|
||||
}
|
||||
|
||||
return $display;
|
||||
$cache = _field_info_field_cache();
|
||||
return $cache->prepareInstanceDisplay($display, $field['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares widget specifications for the current run-time context.
|
||||
*
|
||||
* @param $field
|
||||
* The field structure for the instance.
|
||||
* @param $widget
|
||||
* Widget specifications as found in $instance['widget'].
|
||||
* The functionality has moved to the FieldInfo class. This function is kept as
|
||||
* a backwards-compatibility layer. See http://drupal.org/node/1915646.
|
||||
*
|
||||
* @see FieldInfo::prepareInstanceWidget()
|
||||
*/
|
||||
function _field_info_prepare_instance_widget($field, $widget) {
|
||||
$field_type = field_info_field_types($field['type']);
|
||||
|
||||
// Fill in default values.
|
||||
$widget += array(
|
||||
'type' => $field_type['default_widget'],
|
||||
'settings' => array(),
|
||||
'weight' => 0,
|
||||
);
|
||||
|
||||
$widget_type = field_info_widget_types($widget['type']);
|
||||
// Fallback to default formatter if formatter type is not available.
|
||||
if (!$widget_type) {
|
||||
$widget['type'] = $field_type['default_widget'];
|
||||
$widget_type = field_info_widget_types($widget['type']);
|
||||
}
|
||||
$widget['module'] = $widget_type['module'];
|
||||
// Fill in default settings for the widget.
|
||||
$widget['settings'] += field_info_widget_settings($widget['type']);
|
||||
|
||||
return $widget;
|
||||
$cache = _field_info_field_cache();
|
||||
return $cache->prepareInstanceWidget($widget, $field['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares 'extra fields' for the current run-time context.
|
||||
*
|
||||
* @param $extra_fields
|
||||
* The array of extra fields, as collected in hook_field_extra_fields().
|
||||
* @param $entity_type
|
||||
* The entity type.
|
||||
* @param $bundle
|
||||
* The bundle name.
|
||||
* The functionality has moved to the FieldInfo class. This function is kept as
|
||||
* a backwards-compatibility layer. See http://drupal.org/node/1915646.
|
||||
*
|
||||
* @see FieldInfo::prepareExtraFields()
|
||||
*/
|
||||
function _field_info_prepare_extra_fields($extra_fields, $entity_type, $bundle) {
|
||||
$entity_type_info = entity_get_info($entity_type);
|
||||
$bundle_settings = field_bundle_settings($entity_type, $bundle);
|
||||
$extra_fields += array('form' => array(), 'display' => array());
|
||||
|
||||
$result = array();
|
||||
// Extra fields in forms.
|
||||
foreach ($extra_fields['form'] as $name => $field_data) {
|
||||
$settings = isset($bundle_settings['extra_fields']['form'][$name]) ? $bundle_settings['extra_fields']['form'][$name] : array();
|
||||
if (isset($settings['weight'])) {
|
||||
$field_data['weight'] = $settings['weight'];
|
||||
}
|
||||
$result['form'][$name] = $field_data;
|
||||
}
|
||||
|
||||
// Extra fields in displayed entities.
|
||||
$data = $extra_fields['display'];
|
||||
foreach ($extra_fields['display'] as $name => $field_data) {
|
||||
$settings = isset($bundle_settings['extra_fields']['display'][$name]) ? $bundle_settings['extra_fields']['display'][$name] : array();
|
||||
$view_modes = array_merge(array('default'), array_keys($entity_type_info['view modes']));
|
||||
foreach ($view_modes as $view_mode) {
|
||||
if (isset($settings[$view_mode])) {
|
||||
$field_data['display'][$view_mode] = $settings[$view_mode];
|
||||
}
|
||||
else {
|
||||
$field_data['display'][$view_mode] = array(
|
||||
'weight' => $field_data['weight'],
|
||||
'visible' => TRUE,
|
||||
);
|
||||
}
|
||||
}
|
||||
unset($field_data['weight']);
|
||||
$result['display'][$name] = $field_data;
|
||||
}
|
||||
|
||||
return $result;
|
||||
$cache = _field_info_field_cache();
|
||||
return $cache->prepareExtraFields($extra_fields, $entity_type, $bundle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -583,22 +439,51 @@ function field_info_bundles($entity_type = NULL) {
|
||||
return $bundles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a lightweight map of fields across bundles.
|
||||
*
|
||||
* The function only returns active, non deleted fields.
|
||||
*
|
||||
* @return
|
||||
* An array keyed by field name. Each value is an array with two entries:
|
||||
* - type: The field type.
|
||||
* - bundles: The bundles in which the field appears, as an array with entity
|
||||
* types as keys and the array of bundle names as values.
|
||||
*/
|
||||
function field_info_field_map() {
|
||||
$cache = _field_info_field_cache();
|
||||
return $cache->getFieldMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all field definitions.
|
||||
*
|
||||
* Use of this function should be avoided when possible, since it loads and
|
||||
* statically caches a potentially large array of information. Use
|
||||
* field_info_field_map() instead.
|
||||
*
|
||||
* When iterating over the fields present in a given bundle after a call to
|
||||
* field_info_instances($entity_type, $bundle), it is recommended to use
|
||||
* field_info_field() on each individual field instead.
|
||||
*
|
||||
* @return
|
||||
* An array of field definitions, keyed by field name. Each field has an
|
||||
* additional property, 'bundles', which is an array of all the bundles to
|
||||
* which this field belongs keyed by entity type.
|
||||
*
|
||||
* @see field_info_field_map()
|
||||
*/
|
||||
function field_info_fields() {
|
||||
$cache = _field_info_field_cache();
|
||||
$info = $cache->getFields();
|
||||
|
||||
$fields = array();
|
||||
$info = _field_info_collate_fields();
|
||||
foreach ($info['fields'] as $key => $field) {
|
||||
foreach ($info as $key => $field) {
|
||||
if (!$field['deleted']) {
|
||||
$fields[$field['field_name']] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
@@ -620,10 +505,8 @@ function field_info_fields() {
|
||||
* @see field_info_field_by_id()
|
||||
*/
|
||||
function field_info_field($field_name) {
|
||||
$info = _field_info_collate_fields();
|
||||
if (isset($info['field_ids'][$field_name])) {
|
||||
return $info['fields'][$info['field_ids'][$field_name]];
|
||||
}
|
||||
$cache = _field_info_field_cache();
|
||||
return $cache->getField($field_name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -641,17 +524,19 @@ function field_info_field($field_name) {
|
||||
* @see field_info_field()
|
||||
*/
|
||||
function field_info_field_by_id($field_id) {
|
||||
$info = _field_info_collate_fields();
|
||||
if (isset($info['fields'][$field_id])) {
|
||||
return $info['fields'][$field_id];
|
||||
}
|
||||
$cache = _field_info_field_cache();
|
||||
return $cache->getFieldById($field_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the same data as field_info_field_by_id() for every field.
|
||||
*
|
||||
* This function is typically used when handling all fields of some entities
|
||||
* to avoid thousands of calls to field_info_field_by_id().
|
||||
* Use of this function should be avoided when possible, since it loads and
|
||||
* statically caches a potentially large array of information.
|
||||
*
|
||||
* When iterating over the fields present in a given bundle after a call to
|
||||
* field_info_instances($entity_type, $bundle), it is recommended to use
|
||||
* field_info_field() on each individual field instead.
|
||||
*
|
||||
* @return
|
||||
* An array, each key is a field ID and the values are field arrays as
|
||||
@@ -662,41 +547,57 @@ function field_info_field_by_id($field_id) {
|
||||
* @see field_info_field_by_id()
|
||||
*/
|
||||
function field_info_field_by_ids() {
|
||||
$info = _field_info_collate_fields();
|
||||
return $info['fields'];
|
||||
$cache = _field_info_field_cache();
|
||||
return $cache->getFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information about field instances.
|
||||
*
|
||||
* Use of this function to retrieve instances across separate bundles (i.e.
|
||||
* when the $bundle parameter is NULL) should be avoided when possible, since
|
||||
* it loads and statically caches a potentially large array of information. Use
|
||||
* field_info_field_map() instead.
|
||||
*
|
||||
* When retrieving the instances of a specific bundle (i.e. when both
|
||||
* $entity_type and $bundle_name are provided), the function also populates a
|
||||
* static cache with the corresponding field definitions, allowing fast
|
||||
* retrieval of field_info_field() later in the request.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The entity type for which to return instances.
|
||||
* (optional) The entity type for which to return instances.
|
||||
* @param $bundle_name
|
||||
* The bundle name for which to return instances.
|
||||
* (optional) The bundle name for which to return instances. If $entity_type
|
||||
* is NULL, the $bundle_name parameter is ignored.
|
||||
*
|
||||
* @return
|
||||
* If $entity_type is not set, return all instances keyed by entity type and
|
||||
* bundle name. If $entity_type is set, return all instances for that entity
|
||||
* type, keyed by bundle name. If $entity_type and $bundle_name are set, return
|
||||
* all instances for that bundle.
|
||||
*
|
||||
* @see field_info_field_map()
|
||||
*/
|
||||
function field_info_instances($entity_type = NULL, $bundle_name = NULL) {
|
||||
$info = _field_info_collate_fields();
|
||||
$cache = _field_info_field_cache();
|
||||
|
||||
if (isset($entity_type) && isset($bundle_name)) {
|
||||
return isset($info['instances'][$entity_type][$bundle_name]) ? $info['instances'][$entity_type][$bundle_name] : array();
|
||||
if (!isset($entity_type)) {
|
||||
return $cache->getInstances();
|
||||
}
|
||||
elseif (isset($entity_type)) {
|
||||
return isset($info['instances'][$entity_type]) ? $info['instances'][$entity_type] : array();
|
||||
}
|
||||
else {
|
||||
return $info['instances'];
|
||||
if (!isset($bundle_name)) {
|
||||
return $cache->getInstances($entity_type);
|
||||
}
|
||||
|
||||
return $cache->getBundleInstances($entity_type, $bundle_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of instance data for a specific field and bundle.
|
||||
*
|
||||
* The function populates a static cache with all fields and instances used in
|
||||
* the bundle, allowing fast retrieval of field_info_field() or
|
||||
* field_info_instance() later in the request.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The entity type for the instance.
|
||||
* @param $field_name
|
||||
@@ -709,9 +610,10 @@ function field_info_instances($entity_type = NULL, $bundle_name = NULL) {
|
||||
* NULL if the instance does not exist.
|
||||
*/
|
||||
function field_info_instance($entity_type, $field_name, $bundle_name) {
|
||||
$info = _field_info_collate_fields();
|
||||
if (isset($info['instances'][$entity_type][$bundle_name][$field_name])) {
|
||||
return $info['instances'][$entity_type][$bundle_name][$field_name];
|
||||
$cache = _field_info_field_cache();
|
||||
$info = $cache->getBundleInstances($entity_type, $bundle_name);
|
||||
if (isset($info[$field_name])) {
|
||||
return $info[$field_name];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,11 +671,10 @@ function field_info_instance($entity_type, $field_name, $bundle_name) {
|
||||
* The array of pseudo-field elements in the bundle.
|
||||
*/
|
||||
function field_info_extra_fields($entity_type, $bundle, $context) {
|
||||
$info = _field_info_collate_fields();
|
||||
if (isset($info['extra_fields'][$entity_type][$bundle][$context])) {
|
||||
return $info['extra_fields'][$entity_type][$bundle][$context];
|
||||
}
|
||||
return array();
|
||||
$cache = _field_info_field_cache();
|
||||
$info = $cache->getBundleExtraFields($entity_type, $bundle);
|
||||
|
||||
return isset($info[$context]) ? $info[$context] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -459,6 +459,13 @@ function field_update_7002() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the FieldInfo class to the class registry.
|
||||
*/
|
||||
function field_update_7003() {
|
||||
// Empty update to force a rebuild of the registry.
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-7.x-extra".
|
||||
*/
|
||||
|
@@ -873,7 +873,8 @@ function field_view_field($entity_type, $entity, $field_name, $display = array()
|
||||
if ($field = field_info_field($field_name)) {
|
||||
if (is_array($display)) {
|
||||
// When using custom display settings, fill in default values.
|
||||
$display = _field_info_prepare_instance_display($field, $display);
|
||||
$cache = _field_info_field_cache();
|
||||
$display = $cache->prepareInstanceDisplay($display, $field["type"]);
|
||||
}
|
||||
|
||||
// Hook invocations are done through the _field_invoke() functions in
|
||||
@@ -1197,7 +1198,7 @@ function _element_validate_integer($element, &$form_state) {
|
||||
* Use element_validate_integer_positive() instead.
|
||||
*
|
||||
* @deprecated
|
||||
* @see element_validate_number_positive()
|
||||
* @see element_validate_integer_positive()
|
||||
*/
|
||||
function _element_validate_integer_positive($element, &$form_state) {
|
||||
element_validate_integer_positive($element, $form_state);
|
||||
|
@@ -7,8 +7,8 @@ dependencies[] = field
|
||||
files[] = field_sql_storage.test
|
||||
required = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -324,11 +324,14 @@ function field_sql_storage_field_storage_delete_field($field) {
|
||||
* Implements hook_field_storage_load().
|
||||
*/
|
||||
function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fields, $options) {
|
||||
$field_info = field_info_field_by_ids();
|
||||
$load_current = $age == FIELD_LOAD_CURRENT;
|
||||
|
||||
foreach ($fields as $field_id => $ids) {
|
||||
$field = $field_info[$field_id];
|
||||
// By the time this hook runs, the relevant field definitions have been
|
||||
// populated and cached in FieldInfo, so calling field_info_field_by_id()
|
||||
// on each field individually is more efficient than loading all fields in
|
||||
// memory upfront with field_info_field_by_ids().
|
||||
$field = field_info_field_by_id($field_id);
|
||||
$field_name = $field['field_name'];
|
||||
$table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
|
||||
|
||||
|
@@ -7,8 +7,8 @@ dependencies[] = field
|
||||
dependencies[] = options
|
||||
files[] = tests/list.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -5,8 +5,8 @@ package = Testing
|
||||
version = VERSION
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = number.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = options.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -7,8 +7,8 @@ dependencies[] = field
|
||||
files[] = text.test
|
||||
required = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -85,12 +85,28 @@ class FieldAttachTestCase extends FieldTestCase {
|
||||
}
|
||||
parent::setUp($modules);
|
||||
|
||||
$this->field_name = drupal_strtolower($this->randomName() . '_field_name');
|
||||
$this->field = array('field_name' => $this->field_name, 'type' => 'test_field', 'cardinality' => 4);
|
||||
$this->field = field_create_field($this->field);
|
||||
$this->field_id = $this->field['id'];
|
||||
$this->instance = array(
|
||||
'field_name' => $this->field_name,
|
||||
$this->createFieldWithInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a field and an instance of it.
|
||||
*
|
||||
* @param string $suffix
|
||||
* (optional) A string that should only contain characters that are valid in
|
||||
* PHP variable names as well.
|
||||
*/
|
||||
function createFieldWithInstance($suffix = '') {
|
||||
$field_name = 'field_name' . $suffix;
|
||||
$field = 'field' . $suffix;
|
||||
$field_id = 'field_id' . $suffix;
|
||||
$instance = 'instance' . $suffix;
|
||||
|
||||
$this->$field_name = drupal_strtolower($this->randomName() . '_field_name' . $suffix);
|
||||
$this->$field = array('field_name' => $this->$field_name, 'type' => 'test_field', 'cardinality' => 4);
|
||||
$this->$field = field_create_field($this->$field);
|
||||
$this->$field_id = $this->{$field}['id'];
|
||||
$this->$instance = array(
|
||||
'field_name' => $this->$field_name,
|
||||
'entity_type' => 'test_entity',
|
||||
'bundle' => 'test_bundle',
|
||||
'label' => $this->randomName() . '_label',
|
||||
@@ -107,7 +123,7 @@ class FieldAttachTestCase extends FieldTestCase {
|
||||
)
|
||||
)
|
||||
);
|
||||
field_create_instance($this->instance);
|
||||
field_create_instance($this->$instance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -641,13 +657,18 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
|
||||
* Test field_attach_view() and field_attach_prepare_view().
|
||||
*/
|
||||
function testFieldAttachView() {
|
||||
$this->createFieldWithInstance('_2');
|
||||
|
||||
$entity_type = 'test_entity';
|
||||
$entity_init = field_test_create_stub_entity();
|
||||
$langcode = LANGUAGE_NONE;
|
||||
$options = array('field_name' => $this->field_name_2);
|
||||
|
||||
// Populate values to be displayed.
|
||||
$values = $this->_generateTestFieldValues($this->field['cardinality']);
|
||||
$entity_init->{$this->field_name}[$langcode] = $values;
|
||||
$values_2 = $this->_generateTestFieldValues($this->field_2['cardinality']);
|
||||
$entity_init->{$this->field_name_2}[$langcode] = $values_2;
|
||||
|
||||
// Simple formatter, label displayed.
|
||||
$entity = clone($entity_init);
|
||||
@@ -662,15 +683,47 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
|
||||
),
|
||||
);
|
||||
field_update_instance($this->instance);
|
||||
$formatter_setting_2 = $this->randomName();
|
||||
$this->instance_2['display'] = array(
|
||||
'full' => array(
|
||||
'label' => 'above',
|
||||
'type' => 'field_test_default',
|
||||
'settings' => array(
|
||||
'test_formatter_setting' => $formatter_setting_2,
|
||||
)
|
||||
),
|
||||
);
|
||||
field_update_instance($this->instance_2);
|
||||
// View all fields.
|
||||
field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full');
|
||||
$entity->content = field_attach_view($entity_type, $entity, 'full');
|
||||
$output = drupal_render($entity->content);
|
||||
$this->content = $output;
|
||||
$this->assertRaw($this->instance['label'], "Label is displayed.");
|
||||
$this->assertRaw($this->instance['label'], "First field's label is displayed.");
|
||||
foreach ($values as $delta => $value) {
|
||||
$this->content = $output;
|
||||
$this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
|
||||
}
|
||||
$this->assertRaw($this->instance_2['label'], "Second field's label is displayed.");
|
||||
foreach ($values_2 as $delta => $value) {
|
||||
$this->content = $output;
|
||||
$this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
|
||||
}
|
||||
// View single field (the second field).
|
||||
field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full', $langcode, $options);
|
||||
$entity->content = field_attach_view($entity_type, $entity, 'full', $langcode, $options);
|
||||
$output = drupal_render($entity->content);
|
||||
$this->content = $output;
|
||||
$this->assertNoRaw($this->instance['label'], "First field's label is not displayed.");
|
||||
foreach ($values as $delta => $value) {
|
||||
$this->content = $output;
|
||||
$this->assertNoRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
|
||||
}
|
||||
$this->assertRaw($this->instance_2['label'], "Second field's label is displayed.");
|
||||
foreach ($values_2 as $delta => $value) {
|
||||
$this->content = $output;
|
||||
$this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
|
||||
}
|
||||
|
||||
// Label hidden.
|
||||
$entity = clone($entity_init);
|
||||
@@ -697,7 +750,7 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
|
||||
$this->content = $output;
|
||||
$this->assertNoRaw($this->instance['label'], "Hidden field: label is not displayed.");
|
||||
foreach ($values as $delta => $value) {
|
||||
$this->assertNoRaw($value['value'], "Hidden field: value $delta is not displayed.");
|
||||
$this->assertNoRaw("$formatter_setting|{$value['value']}", "Hidden field: value $delta is not displayed.");
|
||||
}
|
||||
|
||||
// Multiple formatter.
|
||||
@@ -907,11 +960,13 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
|
||||
* hook_field_validate.
|
||||
*/
|
||||
function testFieldAttachValidate() {
|
||||
$this->createFieldWithInstance('_2');
|
||||
|
||||
$entity_type = 'test_entity';
|
||||
$entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
|
||||
$langcode = LANGUAGE_NONE;
|
||||
|
||||
// Set up values to generate errors
|
||||
// Set up all but one values of the first field to generate errors.
|
||||
$values = array();
|
||||
for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
|
||||
$values[$delta]['value'] = -1;
|
||||
@@ -920,6 +975,14 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
|
||||
$values[1]['value'] = 1;
|
||||
$entity->{$this->field_name}[$langcode] = $values;
|
||||
|
||||
// Set up all values of the second field to generate errors.
|
||||
$values_2 = array();
|
||||
for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) {
|
||||
$values_2[$delta]['value'] = -1;
|
||||
}
|
||||
$entity->{$this->field_name_2}[$langcode] = $values_2;
|
||||
|
||||
// Validate all fields.
|
||||
try {
|
||||
field_attach_validate($entity_type, $entity);
|
||||
}
|
||||
@@ -929,26 +992,57 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
|
||||
|
||||
foreach ($values as $delta => $value) {
|
||||
if ($value['value'] != 1) {
|
||||
$this->assertIdentical($errors[$this->field_name][$langcode][$delta][0]['error'], 'field_test_invalid', "Error set on value $delta");
|
||||
$this->assertEqual(count($errors[$this->field_name][$langcode][$delta]), 1, "Only one error set on value $delta");
|
||||
$this->assertIdentical($errors[$this->field_name][$langcode][$delta][0]['error'], 'field_test_invalid', "Error set on first field's value $delta");
|
||||
$this->assertEqual(count($errors[$this->field_name][$langcode][$delta]), 1, "Only one error set on first field's value $delta");
|
||||
unset($errors[$this->field_name][$langcode][$delta]);
|
||||
}
|
||||
else {
|
||||
$this->assertFalse(isset($errors[$this->field_name][$langcode][$delta]), "No error set on value $delta");
|
||||
$this->assertFalse(isset($errors[$this->field_name][$langcode][$delta]), "No error set on first field's value $delta");
|
||||
}
|
||||
}
|
||||
$this->assertEqual(count($errors[$this->field_name][$langcode]), 0, 'No extraneous errors set');
|
||||
foreach ($values_2 as $delta => $value) {
|
||||
$this->assertIdentical($errors[$this->field_name_2][$langcode][$delta][0]['error'], 'field_test_invalid', "Error set on second field's value $delta");
|
||||
$this->assertEqual(count($errors[$this->field_name_2][$langcode][$delta]), 1, "Only one error set on second field's value $delta");
|
||||
unset($errors[$this->field_name_2][$langcode][$delta]);
|
||||
}
|
||||
$this->assertEqual(count($errors[$this->field_name][$langcode]), 0, 'No extraneous errors set for first field');
|
||||
$this->assertEqual(count($errors[$this->field_name_2][$langcode]), 0, 'No extraneous errors set for second field');
|
||||
|
||||
// Validate a single field.
|
||||
$options = array('field_name' => $this->field_name_2);
|
||||
try {
|
||||
field_attach_validate($entity_type, $entity, $options);
|
||||
}
|
||||
catch (FieldValidationException $e) {
|
||||
$errors = $e->errors;
|
||||
}
|
||||
|
||||
foreach ($values_2 as $delta => $value) {
|
||||
$this->assertIdentical($errors[$this->field_name_2][$langcode][$delta][0]['error'], 'field_test_invalid', "Error set on second field's value $delta");
|
||||
$this->assertEqual(count($errors[$this->field_name_2][$langcode][$delta]), 1, "Only one error set on second field's value $delta");
|
||||
unset($errors[$this->field_name_2][$langcode][$delta]);
|
||||
}
|
||||
$this->assertFalse(isset($errors[$this->field_name]), 'No validation errors are set for the first field, despite it having errors');
|
||||
$this->assertEqual(count($errors[$this->field_name_2][$langcode]), 0, 'No extraneous errors set for second field');
|
||||
|
||||
// Check that cardinality is validated.
|
||||
$entity->{$this->field_name}[$langcode] = $this->_generateTestFieldValues($this->field['cardinality'] + 1);
|
||||
$entity->{$this->field_name_2}[$langcode] = $this->_generateTestFieldValues($this->field_2['cardinality'] + 1);
|
||||
// When validating all fields.
|
||||
try {
|
||||
field_attach_validate($entity_type, $entity);
|
||||
}
|
||||
catch (FieldValidationException $e) {
|
||||
$errors = $e->errors;
|
||||
}
|
||||
$this->assertEqual($errors[$this->field_name][$langcode][0][0]['error'], 'field_cardinality', t('Cardinality validation failed.'));
|
||||
|
||||
$this->assertEqual($errors[$this->field_name_2][$langcode][0][0]['error'], 'field_cardinality', 'Cardinality validation failed.');
|
||||
// When validating a single field (the second field).
|
||||
try {
|
||||
field_attach_validate($entity_type, $entity, $options);
|
||||
}
|
||||
catch (FieldValidationException $e) {
|
||||
$errors = $e->errors;
|
||||
}
|
||||
$this->assertEqual($errors[$this->field_name_2][$langcode][0][0]['error'], 'field_cardinality', 'Cardinality validation failed.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -958,34 +1052,59 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
|
||||
* widgets show up.
|
||||
*/
|
||||
function testFieldAttachForm() {
|
||||
$this->createFieldWithInstance('_2');
|
||||
|
||||
$entity_type = 'test_entity';
|
||||
$entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
|
||||
$langcode = LANGUAGE_NONE;
|
||||
|
||||
// When generating form for all fields.
|
||||
$form = array();
|
||||
$form_state = form_state_defaults();
|
||||
field_attach_form($entity_type, $entity, $form, $form_state);
|
||||
|
||||
$langcode = LANGUAGE_NONE;
|
||||
$this->assertEqual($form[$this->field_name][$langcode]['#title'], $this->instance['label'], "Form title is {$this->instance['label']}");
|
||||
$this->assertEqual($form[$this->field_name][$langcode]['#title'], $this->instance['label'], "First field's form title is {$this->instance['label']}");
|
||||
$this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2['label'], "Second field's form title is {$this->instance_2['label']}");
|
||||
for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
|
||||
// field_test_widget uses 'textfield'
|
||||
$this->assertEqual($form[$this->field_name][$langcode][$delta]['value']['#type'], 'textfield', "Form delta $delta widget is textfield");
|
||||
}
|
||||
$this->assertEqual($form[$this->field_name][$langcode][$delta]['value']['#type'], 'textfield', "First field's form delta $delta widget is textfield");
|
||||
}
|
||||
for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) {
|
||||
// field_test_widget uses 'textfield'
|
||||
$this->assertEqual($form[$this->field_name_2][$langcode][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
|
||||
}
|
||||
|
||||
// When generating form for a single field (the second field).
|
||||
$options = array('field_name' => $this->field_name_2);
|
||||
$form = array();
|
||||
$form_state = form_state_defaults();
|
||||
field_attach_form($entity_type, $entity, $form, $form_state, NULL, $options);
|
||||
|
||||
$this->assertFalse(isset($form[$this->field_name]), 'The first field does not exist in the form');
|
||||
$this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2['label'], "Second field's form title is {$this->instance_2['label']}");
|
||||
for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) {
|
||||
// field_test_widget uses 'textfield'
|
||||
$this->assertEqual($form[$this->field_name_2][$langcode][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test field_attach_submit().
|
||||
*/
|
||||
function testFieldAttachSubmit() {
|
||||
$entity_type = 'test_entity';
|
||||
$entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
|
||||
$this->createFieldWithInstance('_2');
|
||||
|
||||
// Build the form.
|
||||
$entity_type = 'test_entity';
|
||||
$entity_init = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
|
||||
$langcode = LANGUAGE_NONE;
|
||||
|
||||
// Build the form for all fields.
|
||||
$form = array();
|
||||
$form_state = form_state_defaults();
|
||||
field_attach_form($entity_type, $entity, $form, $form_state);
|
||||
field_attach_form($entity_type, $entity_init, $form, $form_state);
|
||||
|
||||
// Simulate incoming values.
|
||||
// First field.
|
||||
$values = array();
|
||||
$weights = array();
|
||||
for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
|
||||
@@ -999,22 +1118,59 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
|
||||
}
|
||||
// Leave an empty value. 'field_test' fields are empty if empty().
|
||||
$values[1]['value'] = 0;
|
||||
|
||||
$langcode = LANGUAGE_NONE;
|
||||
// Second field.
|
||||
$values_2 = array();
|
||||
$weights_2 = array();
|
||||
for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) {
|
||||
$values_2[$delta]['value'] = mt_rand(1, 127);
|
||||
// Assign random weight.
|
||||
do {
|
||||
$weight = mt_rand(0, $this->field_2['cardinality']);
|
||||
} while (in_array($weight, $weights_2));
|
||||
$weights_2[$delta] = $weight;
|
||||
$values_2[$delta]['_weight'] = $weight;
|
||||
}
|
||||
// Leave an empty value. 'field_test' fields are empty if empty().
|
||||
$values_2[1]['value'] = 0;
|
||||
// Pretend the form has been built.
|
||||
drupal_prepare_form('field_test_entity_form', $form, $form_state);
|
||||
drupal_process_form('field_test_entity_form', $form, $form_state);
|
||||
$form_state['values'][$this->field_name][$langcode] = $values;
|
||||
$form_state['values'][$this->field_name_2][$langcode] = $values_2;
|
||||
|
||||
// Call field_attach_submit() for all fields.
|
||||
$entity = clone($entity_init);
|
||||
field_attach_submit($entity_type, $entity, $form, $form_state);
|
||||
|
||||
asort($weights);
|
||||
asort($weights_2);
|
||||
$expected_values = array();
|
||||
$expected_values_2 = array();
|
||||
foreach ($weights as $key => $value) {
|
||||
if ($key != 1) {
|
||||
$expected_values[] = array('value' => $values[$key]['value']);
|
||||
}
|
||||
}
|
||||
$this->assertIdentical($entity->{$this->field_name}[$langcode], $expected_values, 'Submit filters empty values');
|
||||
foreach ($weights_2 as $key => $value) {
|
||||
if ($key != 1) {
|
||||
$expected_values_2[] = array('value' => $values_2[$key]['value']);
|
||||
}
|
||||
}
|
||||
$this->assertIdentical($entity->{$this->field_name_2}[$langcode], $expected_values_2, 'Submit filters empty values');
|
||||
|
||||
// Call field_attach_submit() for a single field (the second field).
|
||||
$options = array('field_name' => $this->field_name_2);
|
||||
$entity = clone($entity_init);
|
||||
field_attach_submit($entity_type, $entity, $form, $form_state, $options);
|
||||
$expected_values_2 = array();
|
||||
foreach ($weights_2 as $key => $value) {
|
||||
if ($key != 1) {
|
||||
$expected_values_2[] = array('value' => $values_2[$key]['value']);
|
||||
}
|
||||
}
|
||||
$this->assertFalse(isset($entity->{$this->field_name}), 'The first field does not exist in the entity object');
|
||||
$this->assertIdentical($entity->{$this->field_name_2}[$langcode], $expected_values_2, 'Submit filters empty values');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1144,6 +1300,16 @@ class FieldInfoTestCase extends FieldTestCase {
|
||||
$this->assertIdentical($instances, $expected, "field_info_instances('user') returns " . var_export($expected, TRUE) . '.');
|
||||
$instances = field_info_instances('user', 'user');
|
||||
$this->assertIdentical($instances, array(), "field_info_instances('user', 'user') returns an empty array.");
|
||||
|
||||
// Test that querying for invalid entity types does not add entries in the
|
||||
// list returned by field_info_instances().
|
||||
field_info_cache_clear();
|
||||
field_info_instances('invalid_entity', 'invalid_bundle');
|
||||
// Simulate new request by clearing static caches.
|
||||
drupal_static_reset();
|
||||
field_info_instances('invalid_entity', 'invalid_bundle');
|
||||
$instances = field_info_instances();
|
||||
$this->assertFalse(isset($instances['invalid_entity']), 'field_info_instances() does not contain entries for the invalid entity type that was queried before');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1253,6 +1419,80 @@ class FieldInfoTestCase extends FieldTestCase {
|
||||
$this->assertNull(field_info_instance('comment', 'field', 'comment_node_article'), t('No instances are returned on disabled entity types.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test field_info_field_map().
|
||||
*/
|
||||
function testFieldMap() {
|
||||
// We will overlook fields created by the 'standard' install profile.
|
||||
$exclude = field_info_field_map();
|
||||
|
||||
// Create a new bundle for 'test_entity' entity type.
|
||||
field_test_create_bundle('test_bundle_2');
|
||||
|
||||
// Create a couple fields.
|
||||
$fields = array(
|
||||
array(
|
||||
'field_name' => 'field_1',
|
||||
'type' => 'test_field',
|
||||
),
|
||||
array(
|
||||
'field_name' => 'field_2',
|
||||
'type' => 'hidden_test_field',
|
||||
),
|
||||
);
|
||||
foreach ($fields as $field) {
|
||||
field_create_field($field);
|
||||
}
|
||||
|
||||
// Create a couple instances.
|
||||
$instances = array(
|
||||
array(
|
||||
'field_name' => 'field_1',
|
||||
'entity_type' => 'test_entity',
|
||||
'bundle' => 'test_bundle',
|
||||
),
|
||||
array(
|
||||
'field_name' => 'field_1',
|
||||
'entity_type' => 'test_entity',
|
||||
'bundle' => 'test_bundle_2',
|
||||
),
|
||||
array(
|
||||
'field_name' => 'field_2',
|
||||
'entity_type' => 'test_entity',
|
||||
'bundle' => 'test_bundle',
|
||||
),
|
||||
array(
|
||||
'field_name' => 'field_2',
|
||||
'entity_type' => 'test_cacheable_entity',
|
||||
'bundle' => 'test_bundle',
|
||||
),
|
||||
);
|
||||
foreach ($instances as $instance) {
|
||||
field_create_instance($instance);
|
||||
}
|
||||
|
||||
$expected = array(
|
||||
'field_1' => array(
|
||||
'type' => 'test_field',
|
||||
'bundles' => array(
|
||||
'test_entity' => array('test_bundle', 'test_bundle_2'),
|
||||
),
|
||||
),
|
||||
'field_2' => array(
|
||||
'type' => 'hidden_test_field',
|
||||
'bundles' => array(
|
||||
'test_entity' => array('test_bundle'),
|
||||
'test_cacheable_entity' => array('test_bundle'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Check that the field map is correct.
|
||||
$map = field_info_field_map();
|
||||
$map = array_diff_key($map, $exclude);
|
||||
$this->assertEqual($map, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the field_info settings convenience functions work.
|
||||
*/
|
||||
@@ -1277,6 +1517,31 @@ class FieldInfoTestCase extends FieldTestCase {
|
||||
$this->assertIdentical(field_info_formatter_settings($type), $data['settings'], "field_info_formatter_settings returns {$type}'s formatter settings");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the field info cache can be built correctly.
|
||||
*/
|
||||
function testFieldInfoCache() {
|
||||
// Create a test field and ensure it's in the array returned by
|
||||
// field_info_fields().
|
||||
$field_name = drupal_strtolower($this->randomName());
|
||||
$field = array(
|
||||
'field_name' => $field_name,
|
||||
'type' => 'test_field',
|
||||
);
|
||||
field_create_field($field);
|
||||
$fields = field_info_fields();
|
||||
$this->assertTrue(isset($fields[$field_name]), 'The test field is initially found in the array returned by field_info_fields().');
|
||||
|
||||
// Now rebuild the field info cache, and set a variable which will cause
|
||||
// the cache to be cleared while it's being rebuilt; see
|
||||
// field_test_entity_info(). Ensure the test field is still in the returned
|
||||
// array.
|
||||
field_info_cache_clear();
|
||||
variable_set('field_test_clear_info_cache_in_hook_entity_info', TRUE);
|
||||
$fields = field_info_fields();
|
||||
$this->assertTrue(isset($fields[$field_name]), 'The test field is found in the array returned by field_info_fields() even if its cache is cleared while being rebuilt.');
|
||||
}
|
||||
}
|
||||
|
||||
class FieldFormTestCase extends FieldTestCase {
|
||||
@@ -2178,6 +2443,41 @@ class FieldCrudTestCase extends FieldTestCase {
|
||||
$this->assertTrue($field_definition < $field, t('The field was properly read.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests reading field definitions.
|
||||
*/
|
||||
function testReadFields() {
|
||||
$field_definition = array(
|
||||
'field_name' => 'field_1',
|
||||
'type' => 'test_field',
|
||||
);
|
||||
field_create_field($field_definition);
|
||||
|
||||
// Check that 'single column' criteria works.
|
||||
$fields = field_read_fields(array('field_name' => $field_definition['field_name']));
|
||||
$this->assertTrue(count($fields) == 1 && isset($fields[$field_definition['field_name']]), 'The field was properly read.');
|
||||
|
||||
// Check that 'multi column' criteria works.
|
||||
$fields = field_read_fields(array('field_name' => $field_definition['field_name'], 'type' => $field_definition['type']));
|
||||
$this->assertTrue(count($fields) == 1 && isset($fields[$field_definition['field_name']]), 'The field was properly read.');
|
||||
$fields = field_read_fields(array('field_name' => $field_definition['field_name'], 'type' => 'foo'));
|
||||
$this->assertTrue(empty($fields), 'No field was found.');
|
||||
|
||||
// Create an instance of the field.
|
||||
$instance_definition = array(
|
||||
'field_name' => $field_definition['field_name'],
|
||||
'entity_type' => 'test_entity',
|
||||
'bundle' => 'test_bundle',
|
||||
);
|
||||
field_create_instance($instance_definition);
|
||||
|
||||
// Check that criteria spanning over the field_config_instance table work.
|
||||
$fields = field_read_fields(array('entity_type' => $instance_definition['entity_type'], 'bundle' => $instance_definition['bundle']));
|
||||
$this->assertTrue(count($fields) == 1 && isset($fields[$field_definition['field_name']]), 'The field was properly read.');
|
||||
$fields = field_read_fields(array('entity_type' => $instance_definition['entity_type'], 'field_name' => $instance_definition['field_name']));
|
||||
$this->assertTrue(count($fields) == 1 && isset($fields[$field_definition['field_name']]), 'The field was properly read.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creation of indexes on data column.
|
||||
*/
|
||||
|
@@ -9,6 +9,12 @@
|
||||
* Implements hook_entity_info().
|
||||
*/
|
||||
function field_test_entity_info() {
|
||||
// If requested, clear the field cache while this hook is being called. See
|
||||
// testFieldInfoCache().
|
||||
if (variable_get('field_test_clear_info_cache_in_hook_entity_info', FALSE)) {
|
||||
field_info_cache_clear();
|
||||
}
|
||||
|
||||
$bundles = variable_get('field_test_bundles', array('test_bundle' => array('label' => 'Test Bundle')));
|
||||
$test_entity_modes = array(
|
||||
'full' => array(
|
||||
|
@@ -6,8 +6,8 @@ files[] = field_test.entity.inc
|
||||
version = VERSION
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -1534,7 +1534,7 @@ function field_ui_existing_field_options($entity_type, $bundle) {
|
||||
// - locked fields,
|
||||
// - fields already in the current bundle,
|
||||
// - fields that cannot be added to the entity type,
|
||||
// - fields that that shoud not be added via user interface.
|
||||
// - fields that should not be added via user interface.
|
||||
|
||||
if (empty($field['locked'])
|
||||
&& !field_info_instance($entity_type, $field['field_name'], $bundle)
|
||||
@@ -1544,7 +1544,7 @@ function field_ui_existing_field_options($entity_type, $bundle) {
|
||||
'type' => $field['type'],
|
||||
'type_label' => $field_types[$field['type']]['label'],
|
||||
'field' => $field['field_name'],
|
||||
'label' => t($instance['label']),
|
||||
'label' => $instance['label'],
|
||||
'widget_type' => $instance['widget']['type'],
|
||||
);
|
||||
}
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = field_ui.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -332,23 +332,30 @@ function _field_ui_bundle_admin_path($entity_type, $bundle_name) {
|
||||
* Identifies inactive fields within a bundle.
|
||||
*/
|
||||
function field_ui_inactive_instances($entity_type, $bundle_name = NULL) {
|
||||
if (!empty($bundle_name)) {
|
||||
$inactive = array($bundle_name => array());
|
||||
$params = array('bundle' => $bundle_name);
|
||||
$params = array('entity_type' => $entity_type);
|
||||
|
||||
if (empty($bundle_name)) {
|
||||
$active = field_info_instances($entity_type);
|
||||
$inactive = array();
|
||||
}
|
||||
else {
|
||||
$inactive = array();
|
||||
$params = array();
|
||||
// Restrict to the specified bundle. For consistency with the case where
|
||||
// $bundle_name is NULL, the $active and $inactive arrays are keyed by
|
||||
// bundle name first.
|
||||
$params['bundle'] = $bundle_name;
|
||||
$active = array($bundle_name => field_info_instances($entity_type, $bundle_name));
|
||||
$inactive = array($bundle_name => array());
|
||||
}
|
||||
$params['entity_type'] = $entity_type;
|
||||
|
||||
$active_instances = field_info_instances($entity_type);
|
||||
// Iterate on existing definitions, and spot those that do not appear in the
|
||||
// $active list collected earlier.
|
||||
$all_instances = field_read_instances($params, array('include_inactive' => TRUE));
|
||||
foreach ($all_instances as $instance) {
|
||||
if (!isset($active_instances[$instance['bundle']][$instance['field_name']])) {
|
||||
if (!isset($active[$instance['bundle']][$instance['field_name']])) {
|
||||
$inactive[$instance['bundle']][$instance['field_name']] = $instance;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($bundle_name)) {
|
||||
return $inactive[$bundle_name];
|
||||
}
|
||||
|
@@ -269,7 +269,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
|
||||
*/
|
||||
function assertFieldSettings($bundle, $field_name, $string = 'dummy test string', $entity_type = 'node') {
|
||||
// Reset the fields info.
|
||||
_field_info_collate_fields(TRUE);
|
||||
field_info_cache_clear();
|
||||
// Assert field settings.
|
||||
$field = field_info_field($field_name);
|
||||
$this->assertTrue($field['settings']['test_field_setting'] == $string, t('Field settings were found.'));
|
||||
@@ -360,7 +360,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
|
||||
$this->fieldUIDeleteField($bundle_path1, $this->field_name, $this->field_label, $this->type);
|
||||
|
||||
// Reset the fields info.
|
||||
_field_info_collate_fields(TRUE);
|
||||
field_info_cache_clear();
|
||||
// Check that the field instance was deleted.
|
||||
$this->assertNull(field_info_instance('node', $this->field_name, $this->type), t('Field instance was deleted.'));
|
||||
// Check that the field was not deleted
|
||||
@@ -370,7 +370,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
|
||||
$this->fieldUIDeleteField($bundle_path2, $this->field_name, $this->field_label, $type_name2);
|
||||
|
||||
// Reset the fields info.
|
||||
_field_info_collate_fields(TRUE);
|
||||
field_info_cache_clear();
|
||||
// Check that the field instance was deleted.
|
||||
$this->assertNull(field_info_instance('node', $this->field_name, $type_name2), t('Field instance was deleted.'));
|
||||
// Check that the field was deleted too.
|
||||
|
@@ -261,8 +261,16 @@ function file_field_update($entity_type, $entity, $field, $instance, $langcode,
|
||||
$current_fids[] = $item['fid'];
|
||||
}
|
||||
|
||||
// Compare the original field values with the ones that are being saved.
|
||||
$original = $entity->original;
|
||||
// Compare the original field values with the ones that are being saved. Use
|
||||
// $entity->original to check this when possible, but if it isn't available,
|
||||
// create a bare-bones entity and load its previous values instead.
|
||||
if (isset($entity->original)) {
|
||||
$original = $entity->original;
|
||||
}
|
||||
else {
|
||||
$original = entity_create_stub_entity($entity_type, array($id, $vid, $bundle));
|
||||
field_attach_load($entity_type, array($id => $original), FIELD_LOAD_CURRENT, array('field_id' => $field['id']));
|
||||
}
|
||||
$original_fids = array();
|
||||
if (!empty($original->{$field['field_name']}[$langcode])) {
|
||||
foreach ($original->{$field['field_name']}[$langcode] as $original_item) {
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
dependencies[] = field
|
||||
files[] = tests/file.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -2,13 +2,14 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Admin page callbacks for the filter module.
|
||||
* Administrative page callbacks for the Filter module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Menu callback; Displays a list of all text formats and allows them to be rearranged.
|
||||
* Page callback: Form constructor for a form to list and reorder text formats.
|
||||
*
|
||||
* @ingroup forms
|
||||
* @see filter_menu()
|
||||
* @see filter_admin_overview_submit()
|
||||
*/
|
||||
function filter_admin_overview($form) {
|
||||
@@ -45,6 +46,9 @@ function filter_admin_overview($form) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler for filter_admin_overview().
|
||||
*/
|
||||
function filter_admin_overview_submit($form, &$form_state) {
|
||||
foreach ($form_state['values']['formats'] as $id => $data) {
|
||||
if (is_array($data) && isset($data['weight'])) {
|
||||
@@ -95,7 +99,26 @@ function theme_filter_admin_overview($variables) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; Display a text format form.
|
||||
* Page callback: Displays the text format add/edit form.
|
||||
*
|
||||
* @param object|null $format
|
||||
* (optional) An object representing a format, with the following properties:
|
||||
* - format: A machine-readable name representing the ID of the text format
|
||||
* to save. If this corresponds to an existing text format, that format
|
||||
* will be updated; otherwise, a new format will be created.
|
||||
* - name: The title of the text format.
|
||||
* - cache: (optional) An integer indicating whether the text format is
|
||||
* cacheable (1) or not (0). Defaults to 1.
|
||||
* - status: (optional) An integer indicating whether the text format is
|
||||
* enabled (1) or not (0). Defaults to 1.
|
||||
* - weight: (optional) The weight of the text format, which controls its
|
||||
* placement in text format lists. If omitted, the weight is set to 0.
|
||||
* Defaults to NULL.
|
||||
*
|
||||
* @return
|
||||
* A form array.
|
||||
*
|
||||
* @see filter_menu()
|
||||
*/
|
||||
function filter_admin_format_page($format = NULL) {
|
||||
if (!isset($format->name)) {
|
||||
@@ -109,11 +132,24 @@ function filter_admin_format_page($format = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a text format form.
|
||||
* Form constructor for the text format add/edit form.
|
||||
*
|
||||
* @param $format
|
||||
* A format object having the properties:
|
||||
* - format: A machine-readable name representing the ID of the text format to
|
||||
* save. If this corresponds to an existing text format, that format will be
|
||||
* updated; otherwise, a new format will be created.
|
||||
* - name: The title of the text format.
|
||||
* - cache: An integer indicating whether the text format is cacheable (1) or
|
||||
* not (0). Defaults to 1.
|
||||
* - status: (optional) An integer indicating whether the text format is
|
||||
* enabled (1) or not (0). Defaults to 1.
|
||||
* - weight: (optional) The weight of the text format, which controls its
|
||||
* placement in text format lists. If omitted, the weight is set to 0.
|
||||
*
|
||||
* @ingroup forms
|
||||
* @see filter_admin_format_form_validate()
|
||||
* @see filter_admin_format_form_submit()
|
||||
* @ingroup forms
|
||||
*/
|
||||
function filter_admin_format_form($form, &$form_state, $format) {
|
||||
$is_fallback = ($format->format == filter_fallback_format());
|
||||
@@ -287,7 +323,9 @@ function theme_filter_admin_format_filter_order($variables) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate text format form submissions.
|
||||
* Form validation handler for filter_admin_format_form().
|
||||
*
|
||||
* @see filter_admin_format_form_submit()
|
||||
*/
|
||||
function filter_admin_format_form_validate($form, &$form_state) {
|
||||
$format_format = trim($form_state['values']['format']);
|
||||
@@ -304,7 +342,9 @@ function filter_admin_format_form_validate($form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Process text format form submissions.
|
||||
* Form submission handler for filter_admin_format_form().
|
||||
*
|
||||
* @see filter_admin_format_form_validate()
|
||||
*/
|
||||
function filter_admin_format_form_submit($form, &$form_state) {
|
||||
// Remove unnecessary values.
|
||||
@@ -336,10 +376,14 @@ function filter_admin_format_form_submit($form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; confirm deletion of a format.
|
||||
* Form constructor for the text format deletion confirmation form.
|
||||
*
|
||||
* @ingroup forms
|
||||
* @param $format
|
||||
* An object representing a text format.
|
||||
*
|
||||
* @see filter_menu()
|
||||
* @see filter_admin_disable_submit()
|
||||
* @ingroup forms
|
||||
*/
|
||||
function filter_admin_disable($form, &$form_state, $format) {
|
||||
$form['#format'] = $format;
|
||||
@@ -353,7 +397,7 @@ function filter_admin_disable($form, &$form_state, $format) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Process filter disable form submission.
|
||||
* Form submission handler for filter_admin_disable().
|
||||
*/
|
||||
function filter_admin_disable_submit($form, &$form_state) {
|
||||
$format = $form['#format'];
|
||||
@@ -362,4 +406,3 @@ function filter_admin_disable_submit($form, &$form_state) {
|
||||
|
||||
$form_state['redirect'] = 'admin/config/content/formats';
|
||||
}
|
||||
|
||||
|
@@ -7,8 +7,8 @@ files[] = filter.test
|
||||
required = TRUE
|
||||
configure = admin/config/content/formats
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the filter module.
|
||||
* Install, update, and uninstall functions for the Filter module.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Framework for handling filtering of content.
|
||||
* Framework for handling the filtering of content.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -71,6 +71,7 @@ function filter_theme() {
|
||||
* Implements hook_element_info().
|
||||
*
|
||||
* @see filter_process_format()
|
||||
* @see text_format_wrapper()
|
||||
*/
|
||||
function filter_element_info() {
|
||||
$type['text_format'] = array(
|
||||
@@ -132,13 +133,16 @@ function filter_menu() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Access callback for deleting text formats.
|
||||
* Access callback: Checks access for disabling text formats.
|
||||
*
|
||||
* @param $format
|
||||
* A text format object.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the text format can be disabled by the current user, FALSE
|
||||
* otherwise.
|
||||
*
|
||||
* @see filter_menu()
|
||||
*/
|
||||
function _filter_disable_format_access($format) {
|
||||
// The fallback format can never be disabled.
|
||||
@@ -146,7 +150,7 @@ function _filter_disable_format_access($format) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a text format object from the database.
|
||||
* Loads a text format object from the database.
|
||||
*
|
||||
* @param $format_id
|
||||
* The format ID.
|
||||
@@ -164,29 +168,32 @@ function filter_format_load($format_id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a text format object to the database.
|
||||
* Saves a text format object to the database.
|
||||
*
|
||||
* @param $format
|
||||
* A format object using the properties:
|
||||
* - 'format': A machine-readable name representing the ID of the text format
|
||||
* A format object having the properties:
|
||||
* - format: A machine-readable name representing the ID of the text format
|
||||
* to save. If this corresponds to an existing text format, that format
|
||||
* will be updated; otherwise, a new format will be created.
|
||||
* - 'name': The title of the text format.
|
||||
* - 'status': (optional) An integer indicating whether the text format is
|
||||
* - name: The title of the text format.
|
||||
* - status: (optional) An integer indicating whether the text format is
|
||||
* enabled (1) or not (0). Defaults to 1.
|
||||
* - 'weight': (optional) The weight of the text format, which controls its
|
||||
* - weight: (optional) The weight of the text format, which controls its
|
||||
* placement in text format lists. If omitted, the weight is set to 0.
|
||||
* - 'filters': (optional) An associative, multi-dimensional array of filters
|
||||
* - filters: (optional) An associative, multi-dimensional array of filters
|
||||
* assigned to the text format, keyed by the name of each filter and using
|
||||
* the properties:
|
||||
* - 'weight': (optional) The weight of the filter in the text format. If
|
||||
* - weight: (optional) The weight of the filter in the text format. If
|
||||
* omitted, either the currently stored weight is retained (if there is
|
||||
* one), or the filter is assigned a weight of 10, which will usually
|
||||
* put it at the bottom of the list.
|
||||
* - 'status': (optional) A boolean indicating whether the filter is
|
||||
* - status: (optional) A boolean indicating whether the filter is
|
||||
* enabled in the text format. If omitted, the filter will be disabled.
|
||||
* - 'settings': (optional) An array of configured settings for the filter.
|
||||
* - settings: (optional) An array of configured settings for the filter.
|
||||
* See hook_filter_info() for details.
|
||||
*
|
||||
* @return
|
||||
* SAVED_NEW or SAVED_UPDATED.
|
||||
*/
|
||||
function filter_format_save($format) {
|
||||
$format->name = trim($format->name);
|
||||
@@ -271,7 +278,7 @@ function filter_format_save($format) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable a text format.
|
||||
* Disables a text format.
|
||||
*
|
||||
* There is no core facility to re-enable a disabled format. It is not deleted
|
||||
* to keep information for contrib and to make sure the format ID is never
|
||||
@@ -313,7 +320,15 @@ function filter_format_exists($format_id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a text format form title.
|
||||
* Displays a text format form title.
|
||||
*
|
||||
* @param object $format
|
||||
* A format object.
|
||||
*
|
||||
* @return string
|
||||
* The name of the format.
|
||||
*
|
||||
* @see filter_menu()
|
||||
*/
|
||||
function filter_admin_format_title($format) {
|
||||
return $format->name;
|
||||
@@ -350,6 +365,7 @@ function filter_permission() {
|
||||
*
|
||||
* @param $format
|
||||
* An object representing a text format.
|
||||
*
|
||||
* @return
|
||||
* The machine-readable permission name, or FALSE if the provided text format
|
||||
* is malformed or is the fallback format (which is available to all users).
|
||||
@@ -380,11 +396,13 @@ function filter_modules_disabled($modules) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a list of text formats, ordered by weight.
|
||||
* Retrieves a list of text formats, ordered by weight.
|
||||
*
|
||||
* @param $account
|
||||
* (optional) If provided, only those formats that are allowed for this user
|
||||
* account will be returned. All formats will be returned otherwise.
|
||||
* account will be returned. All formats will be returned otherwise. Defaults
|
||||
* to NULL.
|
||||
*
|
||||
* @return
|
||||
* An array of text format objects, keyed by the format ID and ordered by
|
||||
* weight.
|
||||
@@ -427,7 +445,7 @@ function filter_formats($account = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets text format caches.
|
||||
* Resets the text format caches.
|
||||
*
|
||||
* @see filter_formats()
|
||||
*/
|
||||
@@ -443,6 +461,7 @@ function filter_formats_reset() {
|
||||
*
|
||||
* @param $format
|
||||
* An object representing the text format.
|
||||
*
|
||||
* @return
|
||||
* An array of role names, keyed by role ID.
|
||||
*/
|
||||
@@ -461,6 +480,7 @@ function filter_get_roles_by_format($format) {
|
||||
*
|
||||
* @param $rid
|
||||
* The user role ID to retrieve text formats for.
|
||||
*
|
||||
* @return
|
||||
* An array of text format objects that are allowed for the role, keyed by
|
||||
* the text format ID and ordered by weight.
|
||||
@@ -494,7 +514,8 @@ function filter_get_formats_by_role($rid) {
|
||||
*
|
||||
* @param $account
|
||||
* (optional) The user account to check. Defaults to the currently logged-in
|
||||
* user.
|
||||
* user. Defaults to NULL.
|
||||
*
|
||||
* @return
|
||||
* The ID of the user's default text format.
|
||||
*
|
||||
@@ -525,15 +546,18 @@ function filter_default_format($account = NULL) {
|
||||
* format is initialized to output plain text. Installation profiles and site
|
||||
* administrators have the freedom to configure it further.
|
||||
*
|
||||
* Note that the fallback format is completely distinct from the default
|
||||
* format, which differs per user and is simply the first format which that
|
||||
* user has access to. The default and fallback formats are only guaranteed to
|
||||
* be the same for users who do not have access to any other format; otherwise,
|
||||
* the fallback format's weight determines its placement with respect to the
|
||||
* user's other formats.
|
||||
* Note that the fallback format is completely distinct from the default format,
|
||||
* which differs per user and is simply the first format which that user has
|
||||
* access to. The default and fallback formats are only guaranteed to be the
|
||||
* same for users who do not have access to any other format; otherwise, the
|
||||
* fallback format's weight determines its placement with respect to the user's
|
||||
* other formats.
|
||||
*
|
||||
* Any modules implementing a format deletion functionality must not delete
|
||||
* this format.
|
||||
* Any modules implementing a format deletion functionality must not delete this
|
||||
* format.
|
||||
*
|
||||
* @return
|
||||
* The ID of the fallback text format.
|
||||
*
|
||||
* @see hook_filter_format_disable()
|
||||
* @see filter_default_format()
|
||||
@@ -550,6 +574,9 @@ function filter_fallback_format() {
|
||||
|
||||
/**
|
||||
* Returns the title of the fallback text format.
|
||||
*
|
||||
* @return string
|
||||
* The title of the fallback text format.
|
||||
*/
|
||||
function filter_fallback_format_title() {
|
||||
$fallback_format = filter_format_load(filter_fallback_format());
|
||||
@@ -557,7 +584,10 @@ function filter_fallback_format_title() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all filters provided by modules.
|
||||
* Returns a list of all filters provided by modules.
|
||||
*
|
||||
* @return array
|
||||
* An array of filter formats.
|
||||
*/
|
||||
function filter_get_filters() {
|
||||
$filters = &drupal_static(__FUNCTION__, array());
|
||||
@@ -588,14 +618,16 @@ function filter_get_filters() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for sorting the filter list by filter name.
|
||||
* Sorts an array of filters by filter name.
|
||||
*
|
||||
* Callback for uasort() within filter_get_filters().
|
||||
*/
|
||||
function _filter_list_cmp($a, $b) {
|
||||
return strcmp($a['title'], $b['title']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if text in a certain text format is allowed to be cached.
|
||||
* Checks if the text in a certain text format is allowed to be cached.
|
||||
*
|
||||
* This function can be used to check whether the result of the filtering
|
||||
* process can be cached. A text format may allow caching depending on the
|
||||
@@ -603,6 +635,7 @@ function _filter_list_cmp($a, $b) {
|
||||
*
|
||||
* @param $format_id
|
||||
* The text format ID to check.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the given text format allows caching, FALSE otherwise.
|
||||
*/
|
||||
@@ -619,6 +652,7 @@ function filter_format_allowcache($format_id) {
|
||||
*
|
||||
* @param $format
|
||||
* The text format object to check.
|
||||
*
|
||||
* @return
|
||||
* TRUE if all the filters enabled in the given text format allow caching,
|
||||
* FALSE otherwise.
|
||||
@@ -640,7 +674,7 @@ function _filter_format_is_cacheable($format) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a list of filters for a given text format.
|
||||
* Retrieves a list of filters for a given text format.
|
||||
*
|
||||
* Note that this function returns all associated filters regardless of whether
|
||||
* they are enabled or disabled. All functions working with the filter
|
||||
@@ -694,7 +728,7 @@ function filter_list_format($format_id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Run all the enabled filters on a piece of text.
|
||||
* Runs all the enabled filters on a piece of text.
|
||||
*
|
||||
* Note: Because filters can inject JavaScript or execute PHP code, security is
|
||||
* vital here. When a user supplies a text format, you should validate it using
|
||||
@@ -705,16 +739,20 @@ function filter_list_format($format_id) {
|
||||
* @param $text
|
||||
* The text to be filtered.
|
||||
* @param $format_id
|
||||
* The format id of the text to be filtered. If no format is assigned, the
|
||||
* fallback format will be used.
|
||||
* (optional) The format ID of the text to be filtered. If no format is
|
||||
* assigned, the fallback format will be used. Defaults to NULL.
|
||||
* @param $langcode
|
||||
* Optional: the language code of the text to be filtered, e.g. 'en' for
|
||||
* (optional) The language code of the text to be filtered, e.g. 'en' for
|
||||
* English. This allows filters to be language aware so language specific
|
||||
* text replacement can be implemented.
|
||||
* text replacement can be implemented. Defaults to an empty string.
|
||||
* @param $cache
|
||||
* Boolean whether to cache the filtered output in the {cache_filter} table.
|
||||
* The caller may set this to FALSE when the output is already cached
|
||||
* elsewhere to avoid duplicate cache lookups and storage.
|
||||
* (optional) A Boolean indicating whether to cache the filtered output in the
|
||||
* {cache_filter} table. The caller may set this to FALSE when the output is
|
||||
* already cached elsewhere to avoid duplicate cache lookups and storage.
|
||||
* Defaults to FALSE.
|
||||
*
|
||||
* @return
|
||||
* The filtered text.
|
||||
*
|
||||
* @ingroup sanitization
|
||||
*/
|
||||
@@ -784,8 +822,8 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE)
|
||||
* the text format id specified in #format or the user's default format by
|
||||
* default, if NULL.
|
||||
*
|
||||
* The resulting value for the element will be an array holding the value and the
|
||||
* format. For example, the value for the body element will be:
|
||||
* The resulting value for the element will be an array holding the value and
|
||||
* the format. For example, the value for the body element will be:
|
||||
* @code
|
||||
* $form_state['values']['body']['value'] = 'foo';
|
||||
* $form_state['values']['body']['format'] = 'foo';
|
||||
@@ -795,7 +833,7 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE)
|
||||
* The form element to process. Properties used:
|
||||
* - #base_type: The form element #type to use for the 'value' element.
|
||||
* 'textarea' by default.
|
||||
* - #format: (optional) The text format id to preselect. If NULL or not set,
|
||||
* - #format: (optional) The text format ID to preselect. If NULL or not set,
|
||||
* the default format for the current user will be used.
|
||||
*
|
||||
* @return
|
||||
@@ -933,7 +971,7 @@ function filter_process_format($element) {
|
||||
}
|
||||
|
||||
/**
|
||||
* #pre_render callback for #type 'text_format' to hide field value from prying eyes.
|
||||
* Render API callback: Hides the field value of 'text_format' elements.
|
||||
*
|
||||
* To not break form processing and previews if a user does not have access to a
|
||||
* stored text format, the expanded form elements in filter_process_format() are
|
||||
@@ -976,7 +1014,7 @@ function theme_text_format_wrapper($variables) {
|
||||
* An object representing the text format.
|
||||
* @param $account
|
||||
* (optional) The user account to check access for; if omitted, the currently
|
||||
* logged-in user is used.
|
||||
* logged-in user is used. Defaults to NULL.
|
||||
*
|
||||
* @return
|
||||
* Boolean TRUE if the user is allowed to access the given format.
|
||||
@@ -998,7 +1036,20 @@ function filter_access($format, $account = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for fetching filter tips.
|
||||
* Retrieves the filter tips.
|
||||
*
|
||||
* @param $format_id
|
||||
* The ID of the text format for which to retrieve tips, or -1 to return tips
|
||||
* for all formats accessible to the current user.
|
||||
* @param $long
|
||||
* (optional) Boolean indicating whether the long form of tips should be
|
||||
* returned. Defaults to FALSE.
|
||||
*
|
||||
* @return
|
||||
* An associative array of filtering tips, keyed by filter name. Each
|
||||
* filtering tip is an associative array with elements:
|
||||
* - tip: Tip text.
|
||||
* - id: Filter ID.
|
||||
*/
|
||||
function _filter_tips($format_id, $long = FALSE) {
|
||||
global $user;
|
||||
@@ -1032,14 +1083,14 @@ function _filter_tips($format_id, $long = FALSE) {
|
||||
/**
|
||||
* Parses an HTML snippet and returns it as a DOM object.
|
||||
*
|
||||
* This function loads the body part of a partial (X)HTML document
|
||||
* and returns a full DOMDocument object that represents this document.
|
||||
* You can use filter_dom_serialize() to serialize this DOMDocument
|
||||
* back to a XHTML snippet.
|
||||
* This function loads the body part of a partial (X)HTML document and returns
|
||||
* a full DOMDocument object that represents this document. You can use
|
||||
* filter_dom_serialize() to serialize this DOMDocument back to a XHTML
|
||||
* snippet.
|
||||
*
|
||||
* @param $text
|
||||
* The partial (X)HTML snippet to load. Invalid mark-up
|
||||
* will be corrected on import.
|
||||
* The partial (X)HTML snippet to load. Invalid mark-up will be corrected on
|
||||
* import.
|
||||
* @return
|
||||
* A DOMDocument that represents the loaded (X)HTML snippet.
|
||||
*/
|
||||
@@ -1054,15 +1105,14 @@ function filter_dom_load($text) {
|
||||
/**
|
||||
* Converts a DOM object back to an HTML snippet.
|
||||
*
|
||||
* The function serializes the body part of a DOMDocument
|
||||
* back to an XHTML snippet.
|
||||
*
|
||||
* The resulting XHTML snippet will be properly formatted
|
||||
* to be compatible with HTML user agents.
|
||||
* The function serializes the body part of a DOMDocument back to an XHTML
|
||||
* snippet. The resulting XHTML snippet will be properly formatted to be
|
||||
* compatible with HTML user agents.
|
||||
*
|
||||
* @param $dom_document
|
||||
* A DOMDocument object to serialize, only the tags below
|
||||
* the first <body> node will be converted.
|
||||
*
|
||||
* @return
|
||||
* A valid (X)HTML snippet, as a string.
|
||||
*/
|
||||
@@ -1099,9 +1149,11 @@ function filter_dom_serialize($dom_document) {
|
||||
* @param $dom_element
|
||||
* The element potentially containing a CDATA node.
|
||||
* @param $comment_start
|
||||
* String to use as a comment start marker to escape the CDATA declaration.
|
||||
* (optional) A string to use as a comment start marker to escape the CDATA
|
||||
* declaration. Defaults to '//'.
|
||||
* @param $comment_end
|
||||
* String to use as a comment end marker to escape the CDATA declaration.
|
||||
* (optional) A string to use as a comment end marker to escape the CDATA
|
||||
* declaration. Defaults to an empty string.
|
||||
*/
|
||||
function filter_dom_serialize_escape_cdata_element($dom_document, $dom_element, $comment_start = '//', $comment_end = '') {
|
||||
foreach ($dom_element->childNodes as $node) {
|
||||
@@ -1156,7 +1208,7 @@ function theme_filter_guidelines($variables) {
|
||||
/**
|
||||
* @defgroup standard_filters Standard filters
|
||||
* @{
|
||||
* Filters implemented by the filter.module.
|
||||
* Filters implemented by the Filter module.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -1204,7 +1256,10 @@ function filter_filter_info() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings callback for the HTML filter.
|
||||
* Filter settings callback for the HTML content filter.
|
||||
*
|
||||
* See hook_filter_FILTER_settings() for documentation of parameters and return
|
||||
* value.
|
||||
*/
|
||||
function _filter_html_settings($form, &$form_state, $filter, $format, $defaults) {
|
||||
$filter->settings += $defaults;
|
||||
@@ -1230,7 +1285,7 @@ function _filter_html_settings($form, &$form_state, $filter, $format, $defaults)
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML filter. Provides filtering of input into accepted HTML.
|
||||
* Provides filtering of input into accepted HTML.
|
||||
*/
|
||||
function _filter_html($text, $filter) {
|
||||
$allowed_tags = preg_split('/\s+|<|>/', $filter->settings['allowed_html'], -1, PREG_SPLIT_NO_EMPTY);
|
||||
@@ -1249,7 +1304,9 @@ function _filter_html($text, $filter) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter tips callback for HTML filter.
|
||||
* Filter tips callback: Provides help for the HTML filter.
|
||||
*
|
||||
* @see filter_filter_info()
|
||||
*/
|
||||
function _filter_html_tips($filter, $format, $long = FALSE) {
|
||||
global $base_url;
|
||||
@@ -1347,7 +1404,9 @@ function _filter_html_tips($filter, $format, $long = FALSE) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings callback for URL filter.
|
||||
* Filter URL settings callback: Provides settings for the URL filter.
|
||||
*
|
||||
* @see filter_filter_info()
|
||||
*/
|
||||
function _filter_url_settings($form, &$form_state, $filter, $format, $defaults) {
|
||||
$filter->settings += $defaults;
|
||||
@@ -1366,7 +1425,7 @@ function _filter_url_settings($form, &$form_state, $filter, $format, $defaults)
|
||||
}
|
||||
|
||||
/**
|
||||
* URL filter. Automatically converts text into hyperlinks.
|
||||
* Converts text into hyperlinks automatically.
|
||||
*
|
||||
* This filter identifies and makes clickable three types of "links".
|
||||
* - URLs like http://example.com.
|
||||
@@ -1489,7 +1548,9 @@ function _filter_url($text, $filter) {
|
||||
}
|
||||
|
||||
/**
|
||||
* preg_replace callback to make links out of absolute URLs.
|
||||
* Makes links out of absolute URLs.
|
||||
*
|
||||
* Callback for preg_replace_callback() within _filter_url().
|
||||
*/
|
||||
function _filter_url_parse_full_links($match) {
|
||||
// The $i:th parenthesis in the regexp contains the URL.
|
||||
@@ -1502,7 +1563,9 @@ function _filter_url_parse_full_links($match) {
|
||||
}
|
||||
|
||||
/**
|
||||
* preg_replace callback to make links out of e-mail addresses.
|
||||
* Makes links out of e-mail addresses.
|
||||
*
|
||||
* Callback for preg_replace_callback() within _filter_url().
|
||||
*/
|
||||
function _filter_url_parse_email_links($match) {
|
||||
// The $i:th parenthesis in the regexp contains the URL.
|
||||
@@ -1515,7 +1578,9 @@ function _filter_url_parse_email_links($match) {
|
||||
}
|
||||
|
||||
/**
|
||||
* preg_replace callback to make links out of domain names starting with "www."
|
||||
* Makes links out of domain names starting with "www."
|
||||
*
|
||||
* Callback for preg_replace_callback() within _filter_url().
|
||||
*/
|
||||
function _filter_url_parse_partial_links($match) {
|
||||
// The $i:th parenthesis in the regexp contains the URL.
|
||||
@@ -1528,14 +1593,17 @@ function _filter_url_parse_partial_links($match) {
|
||||
}
|
||||
|
||||
/**
|
||||
* preg_replace callback to escape contents of HTML comments
|
||||
* Escapes the contents of HTML comments.
|
||||
*
|
||||
* Callback for preg_replace_callback() within _filter_url().
|
||||
*
|
||||
* @param $match
|
||||
* An array containing matches to replace from preg_replace_callback(),
|
||||
* whereas $match[1] is expected to contain the content to be filtered.
|
||||
* @param $escape
|
||||
* (optional) Boolean whether to escape (TRUE) or unescape comments (FALSE).
|
||||
* Defaults to neither. If TRUE, statically cached $comments are reset.
|
||||
* (optional) A Boolean indicating whether to escape (TRUE) or unescape
|
||||
* comments (FALSE). Defaults to NULL, indicating neither. If TRUE, statically
|
||||
* cached $comments are reset.
|
||||
*/
|
||||
function _filter_url_escape_comments($match, $escape = NULL) {
|
||||
static $mode, $comments = array();
|
||||
@@ -1582,21 +1650,24 @@ function _filter_url_trim($text, $length = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter tips callback for URL filter.
|
||||
* Filter tips callback: Provides help for the URL filter.
|
||||
*
|
||||
* @see filter_filter_info()
|
||||
*/
|
||||
function _filter_url_tips($filter, $format, $long = FALSE) {
|
||||
return t('Web page addresses and e-mail addresses turn into links automatically.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan input and make sure that all HTML tags are properly closed and nested.
|
||||
* Scans the input and makes sure that HTML tags are properly closed.
|
||||
*/
|
||||
function _filter_htmlcorrector($text) {
|
||||
return filter_dom_serialize(filter_dom_load($text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert line breaks into <p> and <br> in an intelligent fashion.
|
||||
* Converts line breaks into <p> and <br> in an intelligent fashion.
|
||||
*
|
||||
* Based on: http://photomatt.net/scripts/autop
|
||||
*/
|
||||
function _filter_autop($text) {
|
||||
@@ -1662,7 +1733,9 @@ function _filter_autop($text) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter tips callback for auto-paragraph filter.
|
||||
* Filter tips callback: Provides help for the auto-paragraph filter.
|
||||
*
|
||||
* @see filter_filter_info()
|
||||
*/
|
||||
function _filter_autop_tips($filter, $format, $long = FALSE) {
|
||||
if ($long) {
|
||||
@@ -1681,7 +1754,9 @@ function _filter_html_escape($text) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter tips callback for HTML escaping filter.
|
||||
* Filter tips callback: Provides help for the HTML escaping filter.
|
||||
*
|
||||
* @see filter_filter_info()
|
||||
*/
|
||||
function _filter_html_escape_tips($filter, $format, $long = FALSE) {
|
||||
return t('No HTML tags allowed.');
|
||||
|
@@ -2,12 +2,17 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* User page callbacks for the filter module.
|
||||
* User page callbacks for the Filter module.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Menu callback; show a page with long filter tips.
|
||||
* Page callback: Displays a page with long filter tips.
|
||||
*
|
||||
* @return string
|
||||
* An HTML-formatted string.
|
||||
*
|
||||
* @see filter_menu()
|
||||
* @see theme_filter_tips()
|
||||
*/
|
||||
function filter_tips_long() {
|
||||
$format_id = arg(2);
|
||||
@@ -20,13 +25,12 @@ function filter_tips_long() {
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns HTML for a set of filter tips.
|
||||
*
|
||||
* @param $variables
|
||||
* An associative array containing:
|
||||
* - tips: An array containing descriptions and a CSS id in the form of
|
||||
* - tips: An array containing descriptions and a CSS ID in the form of
|
||||
* 'module-name/filter-id' (only used when $long is TRUE) for each
|
||||
* filter in one or more text formats. Example:
|
||||
* @code
|
||||
|
@@ -22,7 +22,7 @@ class FilterCRUDTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CRUD operations for text formats and filters.
|
||||
* Tests CRUD operations for text formats and filters.
|
||||
*/
|
||||
function testTextFormatCRUD() {
|
||||
// Add a text format with minimum data only.
|
||||
@@ -73,7 +73,7 @@ class FilterCRUDTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a text format is properly stored.
|
||||
* Verifies that a text format is properly stored.
|
||||
*/
|
||||
function verifyTextFormat($format) {
|
||||
$t_args = array('%format' => $format->name);
|
||||
@@ -111,7 +111,7 @@ class FilterCRUDTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that filters are properly stored for a text format.
|
||||
* Verifies that filters are properly stored for a text format.
|
||||
*/
|
||||
function verifyFilters($format) {
|
||||
// Verify filter database records.
|
||||
@@ -160,6 +160,9 @@ class FilterCRUDTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the administrative functionality of the Filter module.
|
||||
*/
|
||||
class FilterAdminTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -185,6 +188,9 @@ class FilterAdminTestCase extends DrupalWebTestCase {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the format administration functionality.
|
||||
*/
|
||||
function testFormatAdmin() {
|
||||
// Add text format.
|
||||
$this->drupalGet('admin/config/content/formats');
|
||||
@@ -249,7 +255,7 @@ class FilterAdminTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filter administration functionality.
|
||||
* Tests filter administration functionality.
|
||||
*/
|
||||
function testFilterAdmin() {
|
||||
// URL filter.
|
||||
@@ -413,11 +419,43 @@ class FilterAdminTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the filter format access functionality in the Filter module.
|
||||
*/
|
||||
class FilterFormatAccessTestCase extends DrupalWebTestCase {
|
||||
/**
|
||||
* A user with administrative permissions.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $admin_user;
|
||||
|
||||
/**
|
||||
* A user with 'administer filters' permission.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $filter_admin_user;
|
||||
|
||||
/**
|
||||
* A user with permission to create and edit own content.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $web_user;
|
||||
|
||||
/**
|
||||
* An object representing an allowed text format.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $allowed_format;
|
||||
|
||||
/**
|
||||
* An object representing a disallowed text format.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $disallowed_format;
|
||||
|
||||
public static function getInfo() {
|
||||
@@ -471,6 +509,9 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Filter format access permissions functionality.
|
||||
*/
|
||||
function testFormatPermissions() {
|
||||
// Make sure that a regular user only has access to the text format they
|
||||
// were granted access to, as well to the fallback format.
|
||||
@@ -507,6 +548,9 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
|
||||
$this->assertTrue(isset($options[filter_fallback_format()]), t('The fallback format appears as an option when adding a new node.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if text format is available to a role.
|
||||
*/
|
||||
function testFormatRoles() {
|
||||
// Get the role ID assigned to the regular user; it must be the maximum.
|
||||
$rid = max(array_keys($this->web_user->roles));
|
||||
@@ -528,13 +572,13 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test editing a page using a disallowed text format.
|
||||
* Tests editing a page using a disallowed text format.
|
||||
*
|
||||
* Verifies that regular users and administrators are able to edit a page,
|
||||
* but not allowed to change the fields which use an inaccessible text
|
||||
* format. Also verifies that fields which use a text format that does not
|
||||
* exist can be edited by administrators only, but that the administrator is
|
||||
* forced to choose a new format before saving the page.
|
||||
* Verifies that regular users and administrators are able to edit a page, but
|
||||
* not allowed to change the fields which use an inaccessible text format.
|
||||
* Also verifies that fields which use a text format that does not exist can
|
||||
* be edited by administrators only, but that the administrator is forced to
|
||||
* choose a new format before saving the page.
|
||||
*/
|
||||
function testFormatWidgetPermissions() {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
@@ -650,7 +694,7 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild text format and permission caches in the thread running the tests.
|
||||
* Rebuilds text format and permission caches in the thread running the tests.
|
||||
*/
|
||||
protected function resetFilterCaches() {
|
||||
filter_formats_reset();
|
||||
@@ -658,6 +702,9 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the default filter functionality in the Filter module.
|
||||
*/
|
||||
class FilterDefaultFormatTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -667,6 +714,9 @@ class FilterDefaultFormatTestCase extends DrupalWebTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the default text format is accessible to users.
|
||||
*/
|
||||
function testDefaultTextFormats() {
|
||||
// Create two text formats, and two users. The first user has access to
|
||||
// both formats, but the second user only has access to the second one.
|
||||
@@ -710,7 +760,7 @@ class FilterDefaultFormatTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild text format and permission caches in the thread running the tests.
|
||||
* Rebuilds text format and permission caches in the thread running the tests.
|
||||
*/
|
||||
protected function resetFilterCaches() {
|
||||
filter_formats_reset();
|
||||
@@ -718,6 +768,9 @@ class FilterDefaultFormatTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of check_markup() when it is called without text format.
|
||||
*/
|
||||
class FilterNoFormatTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -727,6 +780,12 @@ class FilterNoFormatTestCase extends DrupalWebTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests text without format.
|
||||
*
|
||||
* Tests if text with no format is filtered the same way as text in the
|
||||
* fallback format.
|
||||
*/
|
||||
function testCheckMarkupNoFormat() {
|
||||
// Create some text. Include some HTML and line breaks, so we get a good
|
||||
// test of the filtering that is applied to it.
|
||||
@@ -757,7 +816,10 @@ class FilterSecurityTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that filtered content is emptied when an actively used filter module is disabled.
|
||||
* Tests removal of filtered content when an active filter is disabled.
|
||||
*
|
||||
* Tests that filtered content is emptied when an actively used filter module
|
||||
* is disabled.
|
||||
*/
|
||||
function testDisableFilterModule() {
|
||||
// Create a new node.
|
||||
@@ -800,7 +862,7 @@ class FilterUnitTestCase extends DrupalUnitTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the line break filter.
|
||||
* Tests the line break filter.
|
||||
*/
|
||||
function testLineBreakFilter() {
|
||||
// Setup dummy filter object.
|
||||
@@ -1060,7 +1122,7 @@ class FilterUnitTestCase extends DrupalUnitTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filter settings, defaults, access restrictions and similar.
|
||||
* Tests filter settings, defaults, access restrictions and similar.
|
||||
*
|
||||
* @todo This is for functions like filter_filter and check_markup, whose
|
||||
* functionality is not completely focused on filtering. Some ideas:
|
||||
@@ -1116,7 +1178,7 @@ class FilterUnitTestCase extends DrupalUnitTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the spam deterrent.
|
||||
* Tests the spam deterrent.
|
||||
*/
|
||||
function testNoFollowFilter() {
|
||||
// Setup dummy filter object.
|
||||
@@ -1147,7 +1209,7 @@ class FilterUnitTestCase extends DrupalUnitTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the loose, admin HTML filter.
|
||||
* Tests the loose, admin HTML filter.
|
||||
*/
|
||||
function testFilterXSSAdmin() {
|
||||
// DRUPAL-SA-2008-044
|
||||
@@ -1541,7 +1603,7 @@ www.example.com with a newline in comments -->
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the HTML corrector filter.
|
||||
* Tests the HTML corrector filter.
|
||||
*
|
||||
* @todo This test could really use some validity checking function.
|
||||
*/
|
||||
@@ -1745,9 +1807,9 @@ body {color:red}
|
||||
* @param $needle
|
||||
* Lowercase, plain text to look for.
|
||||
* @param $message
|
||||
* Message to display if failed.
|
||||
* (optional) Message to display if failed. Defaults to an empty string.
|
||||
* @param $group
|
||||
* The group this message belongs to, defaults to 'Other'.
|
||||
* (optional) The group this message belongs to. Defaults to 'Other'.
|
||||
* @return
|
||||
* TRUE on pass, FALSE on fail.
|
||||
*/
|
||||
@@ -1769,9 +1831,9 @@ body {color:red}
|
||||
* @param $needle
|
||||
* Lowercase, plain text to look for.
|
||||
* @param $message
|
||||
* Message to display if failed.
|
||||
* (optional) Message to display if failed. Defaults to an empty string.
|
||||
* @param $group
|
||||
* The group this message belongs to, defaults to 'Other'.
|
||||
* (optional) The group this message belongs to. Defaults to 'Other'.
|
||||
* @return
|
||||
* TRUE on pass, FALSE on fail.
|
||||
*/
|
||||
@@ -1781,7 +1843,7 @@ body {color:red}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for filter hook invocation.
|
||||
* Tests for Filter's hook invocations.
|
||||
*/
|
||||
class FilterHooksTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
@@ -1799,7 +1861,10 @@ class FilterHooksTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that hooks run correctly on creating, editing, and deleting a text format.
|
||||
* Tests hooks on format management.
|
||||
*
|
||||
* Tests that hooks run correctly on creating, editing, and deleting a text
|
||||
* format.
|
||||
*/
|
||||
function testFilterHooks() {
|
||||
// Add a text format.
|
||||
@@ -1846,6 +1911,11 @@ class FilterHooksTestCase extends DrupalWebTestCase {
|
||||
* Tests filter settings.
|
||||
*/
|
||||
class FilterSettingsTestCase extends DrupalWebTestCase {
|
||||
/**
|
||||
* The installation profile to use with this test class.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $profile = 'testing';
|
||||
|
||||
public static function getInfo() {
|
||||
|
@@ -7,6 +7,10 @@
|
||||
float: right;
|
||||
margin: 0 0 0 9px;
|
||||
}
|
||||
#forum div.indent {
|
||||
margin-left: 0;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.forum-topic-navigation {
|
||||
padding: 1em 3em 0 0;
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@
|
||||
}
|
||||
|
||||
#forum div.indent {
|
||||
margin-left: 20px;
|
||||
margin-left: 20px; /* LTR */
|
||||
}
|
||||
#forum .icon div {
|
||||
background-image: url(../../misc/forum-icons.png);
|
||||
|
@@ -9,8 +9,8 @@ files[] = forum.test
|
||||
configure = admin/structure/forum
|
||||
stylesheets[all][] = forum.css
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -658,7 +658,12 @@ function forum_block_info() {
|
||||
* Implements hook_block_configure().
|
||||
*/
|
||||
function forum_block_configure($delta = '') {
|
||||
$form['forum_block_num_' . $delta] = array('#type' => 'select', '#title' => t('Number of topics'), '#default_value' => variable_get('forum_block_num_' . $delta, '5'), '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)));
|
||||
$form['forum_block_num_' . $delta] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Number of topics'),
|
||||
'#default_value' => variable_get('forum_block_num_' . $delta, '5'),
|
||||
'#options' => drupal_map_assoc(range(2, 20))
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
@@ -677,6 +677,7 @@ class ForumIndexTestCase extends DrupalWebTestCase {
|
||||
'status' => FALSE,
|
||||
);
|
||||
$this->drupalPost("node/{$node->nid}/edit", $edit, t('Save'));
|
||||
$this->drupalGet("node/{$node->nid}");
|
||||
$this->assertText(t('Access denied'), 'Unpublished node is no longer accessible.');
|
||||
|
||||
// Verify that the node no longer appears on the index.
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
files[] = help.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -326,7 +326,7 @@ function image_style_delete_form_submit($form, &$form_state) {
|
||||
/**
|
||||
* Confirmation form to revert a database style to its default.
|
||||
*/
|
||||
function image_style_revert_form($form, $form_state, $style) {
|
||||
function image_style_revert_form($form, &$form_state, $style) {
|
||||
$form_state['image_style'] = $style;
|
||||
|
||||
return confirm_form(
|
||||
|
@@ -7,8 +7,8 @@ dependencies[] = file
|
||||
files[] = image.test
|
||||
configure = admin/config/media/image-styles
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -391,7 +391,8 @@ function image_update_7002(array &$sandbox) {
|
||||
}
|
||||
|
||||
// Process the table at the top of the list.
|
||||
$table = reset(array_keys($sandbox['tables']));
|
||||
$keys = array_keys($sandbox['tables']);
|
||||
$table = reset($keys);
|
||||
$sandbox['processed'] += _image_update_7002_populate_dimensions($table, $sandbox['tables'][$table], $sandbox['last_fid']);
|
||||
|
||||
// Has the table been fully processed?
|
||||
|
@@ -254,7 +254,7 @@ function image_form_system_file_system_settings_alter(&$form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit handler for the file system settings form.
|
||||
* Form submission handler for system_file_system_settings().
|
||||
*
|
||||
* Adds a menu rebuild after the public file path has been changed, so that the
|
||||
* menu router item depending on that file path will be regenerated.
|
||||
@@ -312,9 +312,9 @@ function image_file_download($uri) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Private file access for the original files. Note that we only
|
||||
// check access for non-temporary images, since file.module will
|
||||
// grant access for all temporary files.
|
||||
// Private file access for the original files. Note that we only check access
|
||||
// for non-temporary images, since file.module will grant access for all
|
||||
// temporary files.
|
||||
$files = file_load_multiple(array(), array('uri' => $uri));
|
||||
if (count($files)) {
|
||||
$file = reset($files);
|
||||
@@ -537,7 +537,7 @@ function image_field_update_instance($instance, $prior_instance) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cached versions of a specific file in all styles.
|
||||
* Clears cached versions of a specific file in all styles.
|
||||
*
|
||||
* @param $path
|
||||
* The Drupal file path to the original image.
|
||||
@@ -553,7 +553,7 @@ function image_path_flush($path) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all styles and their settings.
|
||||
* Gets an array of all styles and their settings.
|
||||
*
|
||||
* @return
|
||||
* An array of styles keyed by the image style ID (isid).
|
||||
@@ -614,7 +614,9 @@ function image_styles() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a style by style name or ID. May be used as a loader for menu items.
|
||||
* Loads a style by style name or ID.
|
||||
*
|
||||
* May be used as a loader for menu items.
|
||||
*
|
||||
* @param $name
|
||||
* The name of the style.
|
||||
@@ -623,6 +625,7 @@ function image_styles() {
|
||||
* @param $include
|
||||
* If set, this loader will restrict to a specific type of image style, may be
|
||||
* one of the defined Image style storage constants.
|
||||
*
|
||||
* @return
|
||||
* An image style array containing the following keys:
|
||||
* - "isid": The unique image style ID.
|
||||
@@ -660,12 +663,20 @@ function image_style_load($name = NULL, $isid = NULL, $include = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an image style.
|
||||
* Saves an image style.
|
||||
*
|
||||
* @param style
|
||||
* An image style array.
|
||||
* @return
|
||||
* An image style array. In the case of a new style, 'isid' will be populated.
|
||||
* @param array $style
|
||||
* An image style array containing:
|
||||
* - name: A unique name for the style.
|
||||
* - isid: (optional) An image style ID.
|
||||
*
|
||||
* @return array
|
||||
* An image style array containing:
|
||||
* - name: An unique name for the style.
|
||||
* - old_name: The original name for the style.
|
||||
* - isid: An image style ID.
|
||||
* - is_new: TRUE if this is a new style, and FALSE if it is an existing
|
||||
* style.
|
||||
*/
|
||||
function image_style_save($style) {
|
||||
if (isset($style['isid']) && is_numeric($style['isid'])) {
|
||||
@@ -692,13 +703,14 @@ function image_style_save($style) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an image style.
|
||||
* Deletes an image style.
|
||||
*
|
||||
* @param $style
|
||||
* An image style array.
|
||||
* @param $replacement_style_name
|
||||
* (optional) When deleting a style, specify a replacement style name so
|
||||
* that existing settings (if any) may be converted to a new style.
|
||||
*
|
||||
* @return
|
||||
* TRUE on success.
|
||||
*/
|
||||
@@ -717,14 +729,17 @@ function image_style_delete($style, $replacement_style_name = '') {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all the effects for an image style.
|
||||
* Loads all the effects for an image style.
|
||||
*
|
||||
* @param $style
|
||||
* An image style array.
|
||||
* @return
|
||||
* @param array $style
|
||||
* An image style array containing:
|
||||
* - isid: The unique image style ID that contains this image effect.
|
||||
*
|
||||
* @return array
|
||||
* An array of image effects associated with specified image style in the
|
||||
* format array('isid' => array()), or an empty array if the specified style
|
||||
* has no effects.
|
||||
* @see image_effects()
|
||||
*/
|
||||
function image_style_effects($style) {
|
||||
$effects = image_effects();
|
||||
@@ -739,10 +754,11 @@ function image_style_effects($style) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of image styles suitable for using as select list options.
|
||||
* Gets an array of image styles suitable for using as select list options.
|
||||
*
|
||||
* @param $include_empty
|
||||
* If TRUE a <none> option will be inserted in the options array.
|
||||
*
|
||||
* @return
|
||||
* Array of image styles both key and value are set to style name.
|
||||
*/
|
||||
@@ -763,7 +779,7 @@ function image_style_options($include_empty = TRUE) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; Given a style and image path, generate a derivative.
|
||||
* Page callback: Generates a derivative, given a style and image path.
|
||||
*
|
||||
* After generating an image, transfer it to the requesting agent.
|
||||
*
|
||||
@@ -931,7 +947,7 @@ function image_style_transform_dimensions($style_name, array &$dimensions) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush cached media for a style.
|
||||
* Flushes cached media for a style.
|
||||
*
|
||||
* @param $style
|
||||
* An image style array.
|
||||
@@ -963,12 +979,13 @@ function image_style_flush($style) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URL for an image derivative given a style and image path.
|
||||
* Returns the URL for an image derivative given a style and image path.
|
||||
*
|
||||
* @param $style_name
|
||||
* The name of the style to be used with this image.
|
||||
* @param $path
|
||||
* The path to the image.
|
||||
*
|
||||
* @return
|
||||
* The absolute URL where a style image can be downloaded, suitable for use
|
||||
* in an <img> tag. Requesting the URL will cause the image to be created.
|
||||
@@ -979,7 +996,7 @@ function image_style_url($style_name, $path) {
|
||||
// The token query is added even if the 'image_allow_insecure_derivatives'
|
||||
// variable is TRUE, so that the emitted links remain valid if it is changed
|
||||
// back to the default FALSE.
|
||||
$token_query = array(IMAGE_DERIVATIVE_TOKEN => image_style_path_token($style_name, $path));
|
||||
$token_query = array(IMAGE_DERIVATIVE_TOKEN => image_style_path_token($style_name, file_stream_wrapper_uri_normalize($path)));
|
||||
|
||||
// If not using clean URLs, the image derivative callback is only available
|
||||
// with the query string. If the file does not exist, use url() to ensure
|
||||
@@ -1017,7 +1034,7 @@ function image_style_path_token($style_name, $uri) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URI of an image when using a style.
|
||||
* Returns the URI of an image when using a style.
|
||||
*
|
||||
* The path returned by this function may not exist. The default generation
|
||||
* method only creates images when they are requested by a user's browser.
|
||||
@@ -1026,6 +1043,7 @@ function image_style_path_token($style_name, $uri) {
|
||||
* The name of the style to be used with this image.
|
||||
* @param $uri
|
||||
* The URI or path to the image.
|
||||
*
|
||||
* @return
|
||||
* The URI to an image style image.
|
||||
* @see image_style_url()
|
||||
@@ -1043,10 +1061,11 @@ function image_style_path($style_name, $uri) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a default image style to the database.
|
||||
* Saves a default image style to the database.
|
||||
*
|
||||
* @param style
|
||||
* An image style array provided by a module.
|
||||
*
|
||||
* @return
|
||||
* An image style array. The returned style array will include the new 'isid'
|
||||
* assigned to the style.
|
||||
@@ -1064,7 +1083,7 @@ function image_default_style_save($style) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Revert the changes made by users to a default image style.
|
||||
* Reverts the changes made by users to a default image style.
|
||||
*
|
||||
* @param style
|
||||
* An image style array.
|
||||
@@ -1081,7 +1100,10 @@ function image_default_style_revert($style) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull in image effects exposed by modules implementing hook_image_effect_info().
|
||||
* Returns a set of image effects.
|
||||
*
|
||||
* These image effects are exposed by modules implementing
|
||||
* hook_image_effect_info().
|
||||
*
|
||||
* @return
|
||||
* An array of image effects to be used when transforming images.
|
||||
@@ -1123,7 +1145,7 @@ function image_effect_definitions() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the definition for an image effect.
|
||||
* Loads the definition for an image effect.
|
||||
*
|
||||
* The effect definition is a set of core properties for an image effect, not
|
||||
* containing any user-settings. The definition defines various functions to
|
||||
@@ -1135,6 +1157,7 @@ function image_effect_definitions() {
|
||||
* The name of the effect definition to load.
|
||||
* @param $style
|
||||
* An image style array to which this effect will be added.
|
||||
*
|
||||
* @return
|
||||
* An array containing the image effect definition with the following keys:
|
||||
* - "effect": The unique name for the effect being performed. Usually prefixed
|
||||
@@ -1162,7 +1185,7 @@ function image_effect_definition_load($effect, $style_name = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all image effects from the database.
|
||||
* Loads all image effects from the database.
|
||||
*
|
||||
* @return
|
||||
* An array of all image effects.
|
||||
@@ -1194,7 +1217,7 @@ function image_effects() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a single image effect.
|
||||
* Loads a single image effect.
|
||||
*
|
||||
* @param $ieid
|
||||
* The image effect ID.
|
||||
@@ -1203,6 +1226,7 @@ function image_effects() {
|
||||
* @param $include
|
||||
* If set, this loader will restrict to a specific type of image style, may be
|
||||
* one of the defined Image style storage constants.
|
||||
*
|
||||
* @return
|
||||
* An image effect array, consisting of the following keys:
|
||||
* - "ieid": The unique image effect ID.
|
||||
@@ -1224,10 +1248,11 @@ function image_effect_load($ieid, $style_name, $include = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an image effect.
|
||||
* Saves an image effect.
|
||||
*
|
||||
* @param $effect
|
||||
* An image effect array.
|
||||
*
|
||||
* @return
|
||||
* An image effect array. In the case of a new effect, 'ieid' will be set.
|
||||
*/
|
||||
@@ -1244,7 +1269,7 @@ function image_effect_save($effect) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an image effect.
|
||||
* Deletes an image effect.
|
||||
*
|
||||
* @param $effect
|
||||
* An image effect array.
|
||||
@@ -1256,12 +1281,13 @@ function image_effect_delete($effect) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an image object and effect, perform the effect on the file.
|
||||
* Applies an image effect to the image object.
|
||||
*
|
||||
* @param $image
|
||||
* An image object returned by image_load().
|
||||
* @param $effect
|
||||
* An image effect array.
|
||||
*
|
||||
* @return
|
||||
* TRUE on success. FALSE if unable to perform the image effect on the image.
|
||||
*/
|
||||
@@ -1312,7 +1338,7 @@ function theme_image_style($variables) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept a keyword (center, top, left, etc) and return it as a pixel offset.
|
||||
* Accepts a keyword (center, top, left, etc) and returns it as a pixel offset.
|
||||
*
|
||||
* @param $value
|
||||
* @param $current_pixels
|
||||
|
@@ -167,10 +167,17 @@ class ImageStylesPathAndUrlTestCase extends DrupalWebTestCase {
|
||||
$this->_testImageStyleUrlAndPath('private', FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test image_style_url() with a file URL that has an extra slash in it.
|
||||
*/
|
||||
function testImageStyleUrlExtraSlash() {
|
||||
$this->_testImageStyleUrlAndPath('public', TRUE, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test image_style_url().
|
||||
*/
|
||||
function _testImageStyleUrlAndPath($scheme, $clean_url = TRUE) {
|
||||
function _testImageStyleUrlAndPath($scheme, $clean_url = TRUE, $extra_slash = FALSE) {
|
||||
// Make the default scheme neither "public" nor "private" to verify the
|
||||
// functions work for other than the default scheme.
|
||||
variable_set('file_default_scheme', 'temporary');
|
||||
@@ -196,6 +203,15 @@ class ImageStylesPathAndUrlTestCase extends DrupalWebTestCase {
|
||||
$this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
|
||||
$generate_url = image_style_url($this->style_name, $original_uri);
|
||||
|
||||
// Ensure that the tests still pass when the file is generated by accessing
|
||||
// a poorly constructed (but still valid) file URL that has an extra slash
|
||||
// in it.
|
||||
if ($extra_slash) {
|
||||
$modified_uri = str_replace('://', ':///', $original_uri);
|
||||
$this->assertNotEqual($original_uri, $modified_uri, 'An extra slash was added to the generated file URI.');
|
||||
$generate_url = image_style_url($this->style_name, $modified_uri);
|
||||
}
|
||||
|
||||
if (!$clean_url) {
|
||||
$this->assertTrue(strpos($generate_url, '?q=') !== FALSE, 'When using non-clean URLS, the system path contains the query string.');
|
||||
}
|
||||
@@ -224,6 +240,12 @@ class ImageStylesPathAndUrlTestCase extends DrupalWebTestCase {
|
||||
$this->drupalGet($generate_url);
|
||||
$this->assertResponse(200, t('Image was generated at the URL.'));
|
||||
|
||||
// Make sure that access is denied for existing style files if we do not
|
||||
// have access.
|
||||
variable_del('image_module_test_file_download');
|
||||
$this->drupalGet($generate_url);
|
||||
$this->assertResponse(403, 'Confirmed that access is denied for the private image style.');
|
||||
|
||||
// Repeat this with a different file that we do not have access to and
|
||||
// make sure that access is denied.
|
||||
$file_noaccess = array_shift($files);
|
||||
@@ -805,7 +827,6 @@ class ImageFieldDisplayTestCase extends ImageFieldTestCase {
|
||||
// Only verify HTTP headers when using private scheme and the headers are
|
||||
// sent by Drupal.
|
||||
$this->assertEqual($this->drupalGetHeader('Content-Type'), 'image/png', t('Content-Type header was sent.'));
|
||||
$this->assertEqual($this->drupalGetHeader('Content-Disposition'), 'inline; filename="' . $test_image->filename . '"', t('Content-Disposition header was sent.'));
|
||||
$this->assertEqual($this->drupalGetHeader('Cache-Control'), 'private', t('Cache-Control header was sent.'));
|
||||
|
||||
// Log out and try to access the file.
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = image_module_test.module
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -388,13 +388,13 @@ function locale_languages_edit_form_validate($form, &$form_state) {
|
||||
form_set_error('prefix', t('Domain and path prefix values should not be set at the same time.'));
|
||||
}
|
||||
if (!empty($form_state['values']['domain']) && $duplicate = db_query("SELECT language FROM {languages} WHERE domain = :domain AND language <> :language", array(':domain' => $form_state['values']['domain'], ':language' => $form_state['values']['langcode']))->fetchField()) {
|
||||
form_set_error('domain', t('The domain (%domain) is already tied to a language (%language).', array('%domain' => $form_state['values']['domain'], '%language' => $duplicate->language)));
|
||||
form_set_error('domain', t('The domain (%domain) is already tied to a language (%language).', array('%domain' => $form_state['values']['domain'], '%language' => $duplicate)));
|
||||
}
|
||||
if (empty($form_state['values']['prefix']) && language_default('language') != $form_state['values']['langcode'] && empty($form_state['values']['domain'])) {
|
||||
form_set_error('prefix', t('Only the default language can have both the domain and prefix empty.'));
|
||||
}
|
||||
if (!empty($form_state['values']['prefix']) && $duplicate = db_query("SELECT language FROM {languages} WHERE prefix = :prefix AND language <> :language", array(':prefix' => $form_state['values']['prefix'], ':language' => $form_state['values']['langcode']))->fetchField()) {
|
||||
form_set_error('prefix', t('The prefix (%prefix) is already tied to a language (%language).', array('%prefix' => $form_state['values']['prefix'], '%language' => $duplicate->language)));
|
||||
form_set_error('prefix', t('The prefix (%prefix) is already tied to a language (%language).', array('%prefix' => $form_state['values']['prefix'], '%language' => $duplicate)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = locale.test
|
||||
configure = admin/config/regional/language
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -386,20 +386,53 @@ function locale_form_node_form_alter(&$form, &$form_state) {
|
||||
/**
|
||||
* Form submit handler for node_form().
|
||||
*
|
||||
* Checks if Locale is registered as a translation handler and handle possible
|
||||
* node language changes.
|
||||
*
|
||||
* This submit handler needs to run before entity_form_submit_build_entity()
|
||||
* is invoked by node_form_submit_build_node(), because it alters the values of
|
||||
* attached fields. Therefore, it cannot be a hook_node_submit() implementation.
|
||||
*/
|
||||
function locale_field_node_form_submit($form, &$form_state) {
|
||||
if (field_has_translation_handler('node', 'locale')) {
|
||||
$node = (object) $form_state['values'];
|
||||
$current_language = entity_language('node', $node);
|
||||
list(, , $bundle) = entity_extract_ids('node', $node);
|
||||
locale_field_entity_form_submit('node', $form, $form_state);
|
||||
}
|
||||
|
||||
foreach (field_info_instances('node', $bundle) as $instance) {
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter().
|
||||
*/
|
||||
function locale_form_comment_form_alter(&$form, &$form_state, $form_id) {
|
||||
// If a content type has multilingual support we set the content language as
|
||||
// comment language.
|
||||
if ($form['language']['#value'] == LANGUAGE_NONE && locale_multilingual_node_type($form['#node']->type)) {
|
||||
global $language_content;
|
||||
$form['language']['#value'] = $language_content->language;
|
||||
$submit_callback = 'locale_field_comment_form_submit';
|
||||
array_unshift($form['actions']['preview']['#submit'], $submit_callback);
|
||||
array_unshift($form['#submit'], $submit_callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submit handler for comment_form().
|
||||
*
|
||||
* This submit handler needs to run before entity_form_submit_build_entity()
|
||||
* is invoked by comment_form_submit_build_comment(), because it alters the
|
||||
* values of attached fields.
|
||||
*/
|
||||
function locale_field_comment_form_submit($form, &$form_state) {
|
||||
locale_field_entity_form_submit('comment', $form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles field language on submit for the given entity type.
|
||||
*
|
||||
* Checks if Locale is registered as a translation handler and handle possible
|
||||
* language changes.
|
||||
*/
|
||||
function locale_field_entity_form_submit($entity_type, $form, &$form_state ) {
|
||||
if (field_has_translation_handler($entity_type, 'locale')) {
|
||||
$entity = (object) $form_state['values'];
|
||||
$current_language = entity_language($entity_type, $entity);
|
||||
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
|
||||
|
||||
foreach (field_info_instances($entity_type, $bundle) as $instance) {
|
||||
$field_name = $instance['field_name'];
|
||||
$field = field_info_field($field_name);
|
||||
$previous_language = $form[$field_name]['#language'];
|
||||
@@ -407,7 +440,7 @@ function locale_field_node_form_submit($form, &$form_state) {
|
||||
// Handle a possible language change: new language values are inserted,
|
||||
// previous ones are deleted.
|
||||
if ($field['translatable'] && $previous_language != $current_language) {
|
||||
$form_state['values'][$field_name][$current_language] = $node->{$field_name}[$previous_language];
|
||||
$form_state['values'][$field_name][$current_language] = $entity->{$field_name}[$previous_language];
|
||||
$form_state['values'][$field_name][$previous_language] = array();
|
||||
}
|
||||
}
|
||||
@@ -491,6 +524,9 @@ function locale_field_language_fallback(&$display_language, $entity, $langcode)
|
||||
*/
|
||||
function locale_entity_info_alter(&$entity_info) {
|
||||
$entity_info['node']['translation']['locale'] = TRUE;
|
||||
if (isset($entity_info['comment'])) {
|
||||
$entity_info['comment']['translation']['locale'] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1060,15 +1096,3 @@ function locale_url_outbound_alter(&$path, &$options, $original_path) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter().
|
||||
*/
|
||||
function locale_form_comment_form_alter(&$form, &$form_state, $form_id) {
|
||||
// If a content type has multilingual support we set the content language as
|
||||
// comment language.
|
||||
if ($form['language']['#value'] == LANGUAGE_NONE && locale_multilingual_node_type($form['#node']->type)) {
|
||||
global $language_content;
|
||||
$form['language']['#value'] = $language_content->language;
|
||||
}
|
||||
}
|
||||
|
@@ -2758,7 +2758,7 @@ class LocaleCommentLanguageFunctionalTest extends DrupalWebTestCase {
|
||||
parent::setUp('locale', 'locale_test');
|
||||
|
||||
// Create and login user.
|
||||
$admin_user = $this->drupalCreateUser(array('administer site configuration', 'administer languages', 'access administration pages', 'administer content types', 'create article content'));
|
||||
$admin_user = $this->drupalCreateUser(array('administer site configuration', 'administer languages', 'access administration pages', 'administer content types', 'administer comments', 'create article content'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add language.
|
||||
@@ -2787,6 +2787,12 @@ class LocaleCommentLanguageFunctionalTest extends DrupalWebTestCase {
|
||||
// French no matter what path prefix the URLs have.
|
||||
$edit = array('language' => 'fr');
|
||||
$this->drupalPost("user/{$admin_user->uid}/edit", $edit, t('Save'));
|
||||
|
||||
// Make comment body translatable.
|
||||
$field = field_info_field('comment_body');
|
||||
$field['translatable'] = TRUE;
|
||||
field_update_field($field);
|
||||
$this->assertTrue(field_is_translatable('comment', $field), 'Comment body is translatable.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2817,22 +2823,46 @@ class LocaleCommentLanguageFunctionalTest extends DrupalWebTestCase {
|
||||
foreach (language_list() as $langcode => $language) {
|
||||
// Post a comment with content language $langcode.
|
||||
$prefix = empty($language->prefix) ? '' : $language->prefix . '/';
|
||||
$edit = array("comment_body[$language_none][0][value]" => $this->randomName());
|
||||
$this->drupalPost("{$prefix}node/{$node->nid}", $edit, t('Save'));
|
||||
$comment_values[$node_langcode][$langcode] = $this->randomName();
|
||||
// Initially field form widgets have no language.
|
||||
$edit = array(
|
||||
'subject' => $this->randomName(),
|
||||
"comment_body[$language_none][0][value]" => $comment_values[$node_langcode][$langcode],
|
||||
);
|
||||
$this->drupalPost("{$prefix}node/{$node->nid}", $edit, t('Preview'));
|
||||
// After the first submit the submitted entity language is taken into
|
||||
// account.
|
||||
$edit = array(
|
||||
'subject' => $edit['subject'],
|
||||
"comment_body[$langcode][0][value]" => $comment_values[$node_langcode][$langcode],
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
|
||||
// Check that comment language matches the current content language.
|
||||
$comment = db_select('comment', 'c')
|
||||
->fields('c')
|
||||
$cid = db_select('comment', 'c')
|
||||
->fields('c', array('cid'))
|
||||
->condition('nid', $node->nid)
|
||||
->orderBy('cid', 'DESC')
|
||||
->range(0, 1)
|
||||
->execute()
|
||||
->fetchObject();
|
||||
->fetchField();
|
||||
$comment = comment_load($cid);
|
||||
$comment_langcode = entity_language('comment', $comment);
|
||||
$args = array('%node_language' => $node_langcode, '%comment_language' => $comment_langcode, '%langcode' => $langcode);
|
||||
$this->assertEqual($comment_langcode, $langcode, t('The comment posted with content language %langcode and belonging to the node with language %node_language has language %comment_language', $args));
|
||||
$this->assertEqual($comment->comment_body[$langcode][0]['value'], $comment_values[$node_langcode][$langcode], 'Comment body correctly stored.');
|
||||
}
|
||||
}
|
||||
|
||||
// Check that comment bodies appear in the administration UI.
|
||||
$this->drupalGet('admin/content/comment');
|
||||
foreach ($comment_values as $node_values) {
|
||||
foreach ($node_values as $value) {
|
||||
$this->assertRaw($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -5,8 +5,8 @@ package = Testing
|
||||
version = VERSION
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -395,7 +395,7 @@ function menu_edit_item_validate($form, &$form_state) {
|
||||
else {
|
||||
unset($item['options']['fragment']);
|
||||
}
|
||||
if ($item['link_path'] != $parsed_link['path']) {
|
||||
if (isset($parsed_link['path']) && $item['link_path'] != $parsed_link['path']) {
|
||||
$item['link_path'] = $parsed_link['path'];
|
||||
}
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Informs modules that a custom menu was created.
|
||||
* Respond to a custom menu creation.
|
||||
*
|
||||
* This hook is used to notify modules that a custom menu has been created.
|
||||
* Contributed modules may use the information to perform actions based on the
|
||||
@@ -34,7 +34,7 @@ function hook_menu_insert($menu) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs modules that a custom menu was updated.
|
||||
* Respond to a custom menu update.
|
||||
*
|
||||
* This hook is used to notify modules that a custom menu has been updated.
|
||||
* Contributed modules may use the information to perform actions based on the
|
||||
@@ -59,14 +59,14 @@ function hook_menu_update($menu) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs modules that a custom menu was deleted.
|
||||
* Respond to a custom menu deletion.
|
||||
*
|
||||
* This hook is used to notify modules that a custom menu along with all links
|
||||
* contained in it (if any) has been deleted. Contributed modules may use the
|
||||
* information to perform actions based on the information entered into the menu
|
||||
* system.
|
||||
*
|
||||
* @param $link
|
||||
* @param $menu
|
||||
* An array representing a custom menu:
|
||||
* - menu_name: The unique name of the custom menu.
|
||||
* - title: The human readable menu title.
|
||||
|
@@ -6,8 +6,8 @@ core = 7.x
|
||||
files[] = menu.test
|
||||
configure = admin/structure/menu
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -318,7 +318,7 @@ class MenuTestCase extends DrupalWebTestCase {
|
||||
* @param string $menu_name Menu name.
|
||||
*/
|
||||
function addInvalidMenuLink($menu_name = 'navigation') {
|
||||
foreach (array('-&-', 'admin/people/permissions') as $link_path) {
|
||||
foreach (array('-&-', 'admin/people/permissions', '#') as $link_path) {
|
||||
$edit = array(
|
||||
'link_path' => $link_path,
|
||||
'link_title' => 'title',
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Content type editing UI.
|
||||
* Content type editing user interface.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -388,8 +388,7 @@ function node_node_type_update($info) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all of the relevant fields of a module-defined node type to their
|
||||
* default values.
|
||||
* Resets relevant fields of a module-defined node type to their default values.
|
||||
*
|
||||
* @param $type
|
||||
* The node type to reset. The node type is passed back by reference with its
|
||||
@@ -410,6 +409,8 @@ function node_type_reset($type) {
|
||||
|
||||
/**
|
||||
* Menu callback; delete a single content type.
|
||||
*
|
||||
* @ingroup forms
|
||||
*/
|
||||
function node_type_delete_confirm($form, &$form_state, $type) {
|
||||
$form['type'] = array('#type' => 'value', '#value' => $type->type);
|
||||
@@ -430,6 +431,8 @@ function node_type_delete_confirm($form, &$form_state, $type) {
|
||||
|
||||
/**
|
||||
* Process content type delete confirm submissions.
|
||||
*
|
||||
* @see node_type_delete_confirm()
|
||||
*/
|
||||
function node_type_delete_confirm_submit($form, &$form_state) {
|
||||
node_type_delete($form_state['values']['type']);
|
||||
|
@@ -7,6 +7,10 @@
|
||||
|
||||
/**
|
||||
* Menu callback: confirm rebuilding of permissions.
|
||||
*
|
||||
* @see node_configure_rebuild_confirm_submit()
|
||||
* @see node_menu()
|
||||
* @ingroup forms
|
||||
*/
|
||||
function node_configure_rebuild_confirm() {
|
||||
return confirm_form(array(), t('Are you sure you want to rebuild the permissions on site content?'),
|
||||
@@ -15,6 +19,8 @@ function node_configure_rebuild_confirm() {
|
||||
|
||||
/**
|
||||
* Handler for wipe confirmation
|
||||
*
|
||||
* @see node_configure_rebuild_confirm()
|
||||
*/
|
||||
function node_configure_rebuild_confirm_submit($form, &$form_state) {
|
||||
node_access_rebuild(TRUE);
|
||||
@@ -66,6 +72,9 @@ function node_node_operations() {
|
||||
|
||||
/**
|
||||
* List node administration filters that can be applied.
|
||||
*
|
||||
* @return
|
||||
* An associative array of filters.
|
||||
*/
|
||||
function node_filters() {
|
||||
// Regular filters
|
||||
@@ -110,7 +119,7 @@ function node_filters() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply filters for node administration filters based on session.
|
||||
* Applies filters for node administration filters based on session.
|
||||
*
|
||||
* @param $query
|
||||
* A SelectQuery to which the filters should be applied.
|
||||
@@ -133,7 +142,16 @@ function node_build_filter_query(SelectQueryInterface $query) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return form for node administration filters.
|
||||
* Returns the node administration filters form array to node_admin_content().
|
||||
*
|
||||
* @see node_admin_nodes()
|
||||
* @see node_admin_nodes_submit()
|
||||
* @see node_admin_nodes_validate()
|
||||
* @see node_filter_form_submit()
|
||||
* @see node_multiple_delete_confirm()
|
||||
* @see node_multiple_delete_confirm_submit()
|
||||
*
|
||||
* @ingroup forms
|
||||
*/
|
||||
function node_filter_form() {
|
||||
$session = isset($_SESSION['node_overview_filter']) ? $_SESSION['node_overview_filter'] : array();
|
||||
@@ -208,7 +226,15 @@ function node_filter_form() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Process result from node administration filter form.
|
||||
* Form submission handler for node_filter_form().
|
||||
*
|
||||
* @see node_admin_content()
|
||||
* @see node_admin_nodes()
|
||||
* @see node_admin_nodes_submit()
|
||||
* @see node_admin_nodes_validate()
|
||||
* @see node_filter_form()
|
||||
* @see node_multiple_delete_confirm()
|
||||
* @see node_multiple_delete_confirm_submit()
|
||||
*/
|
||||
function node_filter_form_submit($form, &$form_state) {
|
||||
$filters = node_filters();
|
||||
@@ -240,15 +266,15 @@ function node_filter_form_submit($form, &$form_state) {
|
||||
* Make mass update of nodes, changing all nodes in the $nodes array
|
||||
* to update them with the field values in $updates.
|
||||
*
|
||||
* IMPORTANT NOTE: This function is intended to work when called
|
||||
* from a form submit handler. Calling it outside of the form submission
|
||||
* process may not work correctly.
|
||||
* IMPORTANT NOTE: This function is intended to work when called from a form
|
||||
* submission handler. Calling it outside of the form submission process may not
|
||||
* work correctly.
|
||||
*
|
||||
* @param array $nodes
|
||||
* Array of node nids to update.
|
||||
* @param array $updates
|
||||
* Array of key/value pairs with node field names and the
|
||||
* value to update that field to.
|
||||
* Array of key/value pairs with node field names and the value to update that
|
||||
* field to.
|
||||
*/
|
||||
function node_mass_update($nodes, $updates) {
|
||||
// We use batch processing to prevent timeout when updating a large number
|
||||
@@ -279,7 +305,17 @@ function node_mass_update($nodes, $updates) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Node Mass Update - helper function.
|
||||
* Updates individual nodes when fewer than 10 are queued.
|
||||
*
|
||||
* @param $nid
|
||||
* ID of node to update.
|
||||
* @param $updates
|
||||
* Associative array of updates.
|
||||
*
|
||||
* @return object
|
||||
* An updated node object.
|
||||
*
|
||||
* @see node_mass_update()
|
||||
*/
|
||||
function _node_mass_update_helper($nid, $updates) {
|
||||
$node = node_load($nid, NULL, TRUE);
|
||||
@@ -293,7 +329,14 @@ function _node_mass_update_helper($nid, $updates) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Node Mass Update Batch operation
|
||||
* Executes a batch operation for node_mass_update().
|
||||
*
|
||||
* @param array $nodes
|
||||
* An array of node IDs.
|
||||
* @param array $updates
|
||||
* Associative array of updates.
|
||||
* @param array $context
|
||||
* An array of contextual key/values.
|
||||
*/
|
||||
function _node_mass_update_batch_process($nodes, $updates, &$context) {
|
||||
if (!isset($context['sandbox']['progress'])) {
|
||||
@@ -324,7 +367,15 @@ function _node_mass_update_batch_process($nodes, $updates, &$context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Node Mass Update Batch 'finished' callback.
|
||||
* Menu callback: Reports the status of batch operation for node_mass_update().
|
||||
*
|
||||
* @param bool $success
|
||||
* A boolean indicating whether the batch mass update operation successfully
|
||||
* concluded.
|
||||
* @param int $results
|
||||
* The number of nodes updated via the batch mode process.
|
||||
* @param array $operations
|
||||
* An array of function calls (not used in this function).
|
||||
*/
|
||||
function _node_mass_update_batch_finished($success, $results, $operations) {
|
||||
if ($success) {
|
||||
@@ -339,7 +390,17 @@ function _node_mass_update_batch_finished($success, $results, $operations) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback: content administration.
|
||||
* Page callback: Form constructor for the content administration form.
|
||||
*
|
||||
* @see node_admin_nodes()
|
||||
* @see node_admin_nodes_submit()
|
||||
* @see node_admin_nodes_validate()
|
||||
* @see node_filter_form()
|
||||
* @see node_filter_form_submit()
|
||||
* @see node_menu()
|
||||
* @see node_multiple_delete_confirm()
|
||||
* @see node_multiple_delete_confirm_submit()
|
||||
* @ingroup forms
|
||||
*/
|
||||
function node_admin_content($form, $form_state) {
|
||||
if (isset($form_state['values']['operation']) && $form_state['values']['operation'] == 'delete') {
|
||||
@@ -354,6 +415,15 @@ function node_admin_content($form, $form_state) {
|
||||
|
||||
/**
|
||||
* Form builder: Builds the node administration overview.
|
||||
*
|
||||
* @see node_admin_nodes_submit()
|
||||
* @see node_admin_nodes_validate()
|
||||
* @see node_filter_form()
|
||||
* @see node_filter_form_submit()
|
||||
* @see node_multiple_delete_confirm()
|
||||
* @see node_multiple_delete_confirm_submit()
|
||||
*
|
||||
* @ingroup forms
|
||||
*/
|
||||
function node_admin_nodes() {
|
||||
$admin_access = user_access('administer nodes');
|
||||
@@ -525,8 +595,15 @@ function node_admin_nodes() {
|
||||
/**
|
||||
* Validate node_admin_nodes form submissions.
|
||||
*
|
||||
* Check if any nodes have been selected to perform the chosen
|
||||
* 'Update option' on.
|
||||
* Checks whether any nodes have been selected to perform the chosen 'Update
|
||||
* option' on.
|
||||
*
|
||||
* @see node_admin_nodes()
|
||||
* @see node_admin_nodes_submit()
|
||||
* @see node_filter_form()
|
||||
* @see node_filter_form_submit()
|
||||
* @see node_multiple_delete_confirm()
|
||||
* @see node_multiple_delete_confirm_submit()
|
||||
*/
|
||||
function node_admin_nodes_validate($form, &$form_state) {
|
||||
// Error if there are no items to select.
|
||||
@@ -538,7 +615,14 @@ function node_admin_nodes_validate($form, &$form_state) {
|
||||
/**
|
||||
* Process node_admin_nodes form submissions.
|
||||
*
|
||||
* Execute the chosen 'Update option' on the selected nodes.
|
||||
* Executes the chosen 'Update option' on the selected nodes.
|
||||
*
|
||||
* @see node_admin_nodes()
|
||||
* @see node_admin_nodes_validate()
|
||||
* @see node_filter_form()
|
||||
* @see node_filter_form_submit()
|
||||
* @see node_multiple_delete_confirm()
|
||||
* @see node_multiple_delete_confirm_submit()
|
||||
*/
|
||||
function node_admin_nodes_submit($form, &$form_state) {
|
||||
$operations = module_invoke_all('node_operations');
|
||||
@@ -564,6 +648,17 @@ function node_admin_nodes_submit($form, &$form_state) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple node deletion confirmation form for node_admin_content().
|
||||
*
|
||||
* @see node_admin_nodes()
|
||||
* @see node_admin_nodes_submit()
|
||||
* @see node_admin_nodes_validate()
|
||||
* @see node_filter_form()
|
||||
* @see node_filter_form_submit()
|
||||
* @see node_multiple_delete_confirm_submit()
|
||||
* @ingroup forms
|
||||
*/
|
||||
function node_multiple_delete_confirm($form, &$form_state, $nodes) {
|
||||
$form['nodes'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
|
||||
// array_filter returns only elements with TRUE values
|
||||
@@ -587,6 +682,16 @@ function node_multiple_delete_confirm($form, &$form_state, $nodes) {
|
||||
t('Delete'), t('Cancel'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler for node_multiple_delete_confirm().
|
||||
*
|
||||
* @see node_admin_nodes()
|
||||
* @see node_admin_nodes_submit()
|
||||
* @see node_admin_nodes_validate()
|
||||
* @see node_filter_form()
|
||||
* @see node_filter_form_submit()
|
||||
* @see node_multiple_delete_confirm()
|
||||
*/
|
||||
function node_multiple_delete_confirm_submit($form, &$form_state) {
|
||||
if ($form_state['values']['confirm']) {
|
||||
node_delete_multiple(array_keys($form_state['values']['nodes']));
|
||||
|
@@ -11,8 +11,8 @@
|
||||
* Functions to define and modify content types.
|
||||
*
|
||||
* Each content type is maintained by a primary module, which is either
|
||||
* node.module (for content types created in the user interface) or the
|
||||
* module that implements hook_node_info() to define the content type.
|
||||
* node.module (for content types created in the user interface) or the module
|
||||
* that implements hook_node_info() to define the content type.
|
||||
*
|
||||
* During node operations (create, update, view, delete, etc.), there are
|
||||
* several sets of hooks that get invoked to allow modules to modify the base
|
||||
@@ -22,10 +22,10 @@
|
||||
* function prefix. For example, poll.module defines the base for the Poll
|
||||
* content type as "poll", so during creation of a poll node, hook_insert() is
|
||||
* only invoked by calling poll_insert().
|
||||
* - All-module hooks: This set of hooks is invoked on all implementing
|
||||
* modules, to allow other modules to modify what the primary node module is
|
||||
* doing. For example, hook_node_insert() is invoked on all modules when
|
||||
* creating a poll node.
|
||||
* - All-module hooks: This set of hooks is invoked on all implementing modules,
|
||||
* to allow other modules to modify what the primary node module is doing. For
|
||||
* example, hook_node_insert() is invoked on all modules when creating a poll
|
||||
* node.
|
||||
* - Field hooks: Hooks related to the fields attached to the node. These are
|
||||
* invoked from the field operations functions described below, and can be
|
||||
* either field-type-specific or all-module hooks.
|
||||
@@ -56,16 +56,15 @@
|
||||
* - hook_entity_update() (all)
|
||||
* - hook_node_access_records() (all)
|
||||
* - hook_node_access_records_alter() (all)
|
||||
* - Loading a node (calling node_load(), node_load_multiple(), or
|
||||
* entity_load() with $entity_type of 'node'):
|
||||
* - Loading a node (calling node_load(), node_load_multiple() or entity_load()
|
||||
* with $entity_type of 'node'):
|
||||
* - Node and revision information is read from database.
|
||||
* - hook_load() (node-type-specific)
|
||||
* - field_attach_load_revision() and field_attach_load()
|
||||
* - hook_entity_load() (all)
|
||||
* - hook_node_load() (all)
|
||||
* - Viewing a single node (calling node_view() - note that the input to
|
||||
* node_view() is a loaded node, so the Loading steps above are already
|
||||
* done):
|
||||
* node_view() is a loaded node, so the Loading steps above are already done):
|
||||
* - hook_view() (node-type-specific)
|
||||
* - field_attach_prepare_view()
|
||||
* - hook_entity_prepare_view() (all)
|
||||
@@ -97,9 +96,8 @@
|
||||
* - Revision information is deleted from database
|
||||
* - hook_node_revision_delete() (all)
|
||||
* - field_attach_delete_revision()
|
||||
* - Preparing a node for editing (calling node_form() - note that if it's
|
||||
* an existing node, it will already be loaded; see the Loading section
|
||||
* above):
|
||||
* - Preparing a node for editing (calling node_form() - note that if it is an
|
||||
* existing node, it will already be loaded; see the Loading section above):
|
||||
* - hook_prepare() (node-type-specific)
|
||||
* - hook_node_prepare() (all)
|
||||
* - hook_form() (node-type-specific)
|
||||
@@ -137,16 +135,16 @@
|
||||
* associated with permission to view, edit, and delete individual nodes.
|
||||
*
|
||||
* The realms and grant IDs can be arbitrarily defined by your node access
|
||||
* module; it is common to use role IDs as grant IDs, but that is not
|
||||
* required. Your module could instead maintain its own list of users, where
|
||||
* each list has an ID. In that case, the return value of this hook would be
|
||||
* an array of the list IDs that this user is a member of.
|
||||
* module; it is common to use role IDs as grant IDs, but that is not required.
|
||||
* Your module could instead maintain its own list of users, where each list has
|
||||
* an ID. In that case, the return value of this hook would be an array of the
|
||||
* list IDs that this user is a member of.
|
||||
*
|
||||
* A node access module may implement as many realms as necessary to
|
||||
* properly define the access privileges for the nodes. Note that the system
|
||||
* makes no distinction between published and unpublished nodes. It is the
|
||||
* module's responsibility to provide appropriate realms to limit access to
|
||||
* unpublished content.
|
||||
* A node access module may implement as many realms as necessary to properly
|
||||
* define the access privileges for the nodes. Note that the system makes no
|
||||
* distinction between published and unpublished nodes. It is the module's
|
||||
* responsibility to provide appropriate realms to limit access to unpublished
|
||||
* content.
|
||||
*
|
||||
* Node access records are stored in the {node_access} table and define which
|
||||
* grants are required to access a node. There is a special case for the view
|
||||
@@ -183,7 +181,7 @@
|
||||
* @param $account
|
||||
* The user object whose grants are requested.
|
||||
* @param $op
|
||||
* The node operation to be performed, such as "view", "update", or "delete".
|
||||
* The node operation to be performed, such as 'view', 'update', or 'delete'.
|
||||
*
|
||||
* @return
|
||||
* An array whose keys are "realms" of grants, and whose values are arrays of
|
||||
@@ -264,6 +262,7 @@ function hook_node_grants($account, $op) {
|
||||
* @return
|
||||
* An array of grants as defined above.
|
||||
*
|
||||
* @see hook_node_access_records_alter()
|
||||
* @ingroup node_access
|
||||
*/
|
||||
function hook_node_access_records($node) {
|
||||
@@ -350,12 +349,11 @@ function hook_node_access_records_alter(&$grants, $node) {
|
||||
* Alter user access rules when trying to view, edit or delete a node.
|
||||
*
|
||||
* Node access modules establish rules for user access to content.
|
||||
* hook_node_grants() defines permissions for a user to view, edit or
|
||||
* delete nodes by building a $grants array that indicates the permissions
|
||||
* assigned to the user by each node access module. This hook is called to allow
|
||||
* modules to modify the $grants array by reference, so the interaction of
|
||||
* multiple node access modules can be altered or advanced business logic can be
|
||||
* applied.
|
||||
* hook_node_grants() defines permissions for a user to view, edit or delete
|
||||
* nodes by building a $grants array that indicates the permissions assigned to
|
||||
* the user by each node access module. This hook is called to allow modules to
|
||||
* modify the $grants array by reference, so the interaction of multiple node
|
||||
* access modules can be altered or advanced business logic can be applied.
|
||||
*
|
||||
* @see hook_node_grants()
|
||||
*
|
||||
@@ -374,8 +372,8 @@ function hook_node_access_records_alter(&$grants, $node) {
|
||||
* @param $op
|
||||
* The operation being performed, 'view', 'update' or 'delete'.
|
||||
*
|
||||
* Developers may use this hook to either add additional grants to a user
|
||||
* or to remove existing grants. These rules are typically based on either the
|
||||
* Developers may use this hook to either add additional grants to a user or to
|
||||
* remove existing grants. These rules are typically based on either the
|
||||
* permissions assigned to a user role, or specific attributes of a user
|
||||
* account.
|
||||
*
|
||||
@@ -412,10 +410,10 @@ function hook_node_grants_alter(&$grants, $account, $op) {
|
||||
* @return
|
||||
* An array of operations. Each operation is an associative array that may
|
||||
* contain the following key-value pairs:
|
||||
* - 'label': Required. The label for the operation, displayed in the dropdown
|
||||
* - label: (required) The label for the operation, displayed in the dropdown
|
||||
* menu.
|
||||
* - 'callback': Required. The function to call for the operation.
|
||||
* - 'callback arguments': Optional. An array of additional arguments to pass
|
||||
* - callback: (required) The function to call for the operation.
|
||||
* - callback arguments: (optional) An array of additional arguments to pass
|
||||
* to the callback function.
|
||||
*/
|
||||
function hook_node_operations() {
|
||||
@@ -528,11 +526,10 @@ function hook_node_insert($node) {
|
||||
/**
|
||||
* Act on arbitrary nodes being loaded from the database.
|
||||
*
|
||||
* This hook should be used to add information that is not in the node or
|
||||
* node revisions table, not to replace information that is in these tables
|
||||
* (which could interfere with the entity cache). For performance reasons,
|
||||
* information for all available nodes should be loaded in a single query where
|
||||
* possible.
|
||||
* This hook should be used to add information that is not in the node or node
|
||||
* revisions table, not to replace information that is in these tables (which
|
||||
* could interfere with the entity cache). For performance reasons, information
|
||||
* for all available nodes should be loaded in a single query where possible.
|
||||
*
|
||||
* This hook is invoked during node loading, which is handled by entity_load(),
|
||||
* via classes NodeController and DrupalDefaultEntityController. After the node
|
||||
@@ -572,15 +569,15 @@ function hook_node_load($nodes, $types) {
|
||||
* Modules may implement this hook if they want to have a say in whether or not
|
||||
* a given user has access to perform a given operation on a node.
|
||||
*
|
||||
* The administrative account (user ID #1) always passes any access check,
|
||||
* so this hook is not called in that case. Users with the "bypass node access"
|
||||
* The administrative account (user ID #1) always passes any access check, so
|
||||
* this hook is not called in that case. Users with the "bypass node access"
|
||||
* permission may always view and edit content through the administrative
|
||||
* interface.
|
||||
*
|
||||
* Note that not all modules will want to influence access on all
|
||||
* node types. If your module does not want to actively grant or
|
||||
* block access, return NODE_ACCESS_IGNORE or simply return nothing.
|
||||
* Blindly returning FALSE will break other node access modules.
|
||||
* Note that not all modules will want to influence access on all node types. If
|
||||
* your module does not want to actively grant or block access, return
|
||||
* NODE_ACCESS_IGNORE or simply return nothing. Blindly returning FALSE will
|
||||
* break other node access modules.
|
||||
*
|
||||
* Also note that this function isn't called for node listings (e.g., RSS feeds,
|
||||
* the default home page at path 'node', a recent content block, etc.) See
|
||||
@@ -651,17 +648,17 @@ function hook_node_prepare($node) {
|
||||
/**
|
||||
* Act on a node being displayed as a search result.
|
||||
*
|
||||
* This hook is invoked from node_search_execute(), after node_load()
|
||||
* and node_view() have been called.
|
||||
* This hook is invoked from node_search_execute(), after node_load() and
|
||||
* node_view() have been called.
|
||||
*
|
||||
* @param $node
|
||||
* The node being displayed in a search result.
|
||||
*
|
||||
* @return array
|
||||
* Extra information to be displayed with search result. This information
|
||||
* should be presented as an associative array. It will be concatenated
|
||||
* with the post information (last updated, author) in the default search
|
||||
* result theming.
|
||||
* should be presented as an associative array. It will be concatenated with
|
||||
* the post information (last updated, author) in the default search result
|
||||
* theming.
|
||||
*
|
||||
* @see template_preprocess_search_result()
|
||||
* @see search-result.tpl.php
|
||||
@@ -724,8 +721,8 @@ function hook_node_update($node) {
|
||||
/**
|
||||
* Act on a node being indexed for searching.
|
||||
*
|
||||
* This hook is invoked during search indexing, after node_load(), and after
|
||||
* the result of node_view() is added as $node->rendered to the node object.
|
||||
* This hook is invoked during search indexing, after node_load(), and after the
|
||||
* result of node_view() is added as $node->rendered to the node object.
|
||||
*
|
||||
* @param $node
|
||||
* The node being indexed.
|
||||
@@ -756,8 +753,8 @@ function hook_node_update_index($node) {
|
||||
*
|
||||
* Note: Changes made to the $node object within your hook implementation will
|
||||
* have no effect. The preferred method to change a node's content is to use
|
||||
* hook_node_presave() instead. If it is really necessary to change
|
||||
* the node at the validate stage, you can use form_set_value().
|
||||
* hook_node_presave() instead. If it is really necessary to change the node at
|
||||
* the validate stage, you can use form_set_value().
|
||||
*
|
||||
* @param $node
|
||||
* The node being validated.
|
||||
@@ -874,8 +871,8 @@ function hook_node_view_alter(&$build) {
|
||||
*
|
||||
* This hook allows a module to define one or more of its own node types. For
|
||||
* example, the blog module uses it to define a blog node-type named "Blog
|
||||
* entry." The name and attributes of each desired node type are specified in
|
||||
* an array returned by the hook.
|
||||
* entry." The name and attributes of each desired node type are specified in an
|
||||
* array returned by the hook.
|
||||
*
|
||||
* Only module-provided node types should be defined through this hook. User-
|
||||
* provided (or 'custom') node types should be defined only in the 'node_type'
|
||||
@@ -887,22 +884,22 @@ function hook_node_view_alter(&$build) {
|
||||
* contains a sub-array for each node type, with the machine-readable type
|
||||
* name as the key. Each sub-array has up to 10 attributes. Possible
|
||||
* attributes:
|
||||
* - "name": the human-readable name of the node type. Required.
|
||||
* - "base": the base string used to construct callbacks corresponding to
|
||||
* this node type.
|
||||
* (i.e. if base is defined as example_foo, then example_foo_insert will
|
||||
* be called when inserting a node of that type). This string is usually
|
||||
* the name of the module, but not always. Required.
|
||||
* - "description": a brief description of the node type. Required.
|
||||
* - "help": help information shown to the user when creating a node of
|
||||
* this type.. Optional (defaults to '').
|
||||
* - "has_title": boolean indicating whether or not this node type has a title
|
||||
* field. Optional (defaults to TRUE).
|
||||
* - "title_label": the label for the title field of this content type.
|
||||
* Optional (defaults to 'Title').
|
||||
* - "locked": boolean indicating whether the administrator can change the
|
||||
* machine name of this type. FALSE = changeable (not locked),
|
||||
* TRUE = unchangeable (locked). Optional (defaults to TRUE).
|
||||
* - name: (required) The human-readable name of the node type.
|
||||
* - base: (required) The base string used to construct callbacks
|
||||
* corresponding to this node type (for example, if base is defined as
|
||||
* example_foo, then example_foo_insert will be called when inserting a node
|
||||
* of that type). This string is usually the name of the module, but not
|
||||
* always.
|
||||
* - description: (required) A brief description of the node type.
|
||||
* - help: (optional) Help information shown to the user when creating a node
|
||||
* of this type.
|
||||
* - has_title: (optional) A Boolean indicating whether or not this node type
|
||||
* has a title field.
|
||||
* - title_label: (optional) The label for the title field of this content
|
||||
* type.
|
||||
* - locked: (optional) A Boolean indicating whether the administrator can
|
||||
* change the machine name of this type. FALSE = changeable (not locked),
|
||||
* TRUE = unchangeable (locked).
|
||||
*
|
||||
* The machine name of a node type should contain only letters, numbers, and
|
||||
* underscores. Underscores will be converted into hyphens for the purpose of
|
||||
@@ -950,20 +947,20 @@ function hook_node_info() {
|
||||
* corresponding to the internal name of the ranking mechanism, such as
|
||||
* 'recent', or 'comments'. The values should be arrays themselves, with the
|
||||
* following keys available:
|
||||
* - "title": the human readable name of the ranking mechanism. Required.
|
||||
* - "join": part of a query string to join to any additional necessary
|
||||
* table. This is not necessary if the table required is already joined to
|
||||
* by the base query, such as for the {node} table. Other tables should use
|
||||
* the full table name as an alias to avoid naming collisions. Optional.
|
||||
* - "score": part of a query string to calculate the score for the ranking
|
||||
* mechanism based on values in the database. This does not need to be
|
||||
* wrapped in parentheses, as it will be done automatically; it also does
|
||||
* not need to take the weighted system into account, as it will be done
|
||||
* automatically. It does, however, need to calculate a decimal between
|
||||
* - title: (required) The human readable name of the ranking mechanism.
|
||||
* - join: (optional) The part of a query string to join to any additional
|
||||
* necessary table. This is not necessary if the table required is already
|
||||
* joined to by the base query, such as for the {node} table. Other tables
|
||||
* should use the full table name as an alias to avoid naming collisions.
|
||||
* - score: (required) The part of a query string to calculate the score for
|
||||
* the ranking mechanism based on values in the database. This does not need
|
||||
* to be wrapped in parentheses, as it will be done automatically; it also
|
||||
* does not need to take the weighted system into account, as it will be
|
||||
* done automatically. It does, however, need to calculate a decimal between
|
||||
* 0 and 1; be careful not to cast the entire score to an integer by
|
||||
* inadvertently introducing a variable argument. Required.
|
||||
* - "arguments": if any arguments are required for the score, they can be
|
||||
* specified in an array here.
|
||||
* inadvertently introducing a variable argument.
|
||||
* - arguments: (optional) If any arguments are required for the score, they
|
||||
* can be specified in an array here.
|
||||
*
|
||||
* @ingroup node_api_hooks
|
||||
*/
|
||||
@@ -990,8 +987,8 @@ function hook_ranking() {
|
||||
/**
|
||||
* Respond to node type creation.
|
||||
*
|
||||
* This hook is invoked from node_type_save() after the node type is added
|
||||
* to the database.
|
||||
* This hook is invoked from node_type_save() after the node type is added to
|
||||
* the database.
|
||||
*
|
||||
* @param $info
|
||||
* The node type object that is being created.
|
||||
@@ -1003,8 +1000,8 @@ function hook_node_type_insert($info) {
|
||||
/**
|
||||
* Respond to node type updates.
|
||||
*
|
||||
* This hook is invoked from node_type_save() after the node type is updated
|
||||
* in the database.
|
||||
* This hook is invoked from node_type_save() after the node type is updated in
|
||||
* the database.
|
||||
*
|
||||
* @param $info
|
||||
* The node type object that is being updated.
|
||||
@@ -1258,25 +1255,24 @@ function hook_validate($node, $form, &$form_state) {
|
||||
* This hook is invoked only on the module that defines the node's content type
|
||||
* (use hook_node_view() to act on all node views).
|
||||
*
|
||||
* This hook is invoked during node viewing after the node is fully loaded,
|
||||
* so that the node type module can define a custom method for display, or
|
||||
* add to the default display.
|
||||
* This hook is invoked during node viewing after the node is fully loaded, so
|
||||
* that the node type module can define a custom method for display, or add to
|
||||
* the default display.
|
||||
*
|
||||
* @param $node
|
||||
* The node to be displayed, as returned by node_load().
|
||||
* @param $view_mode
|
||||
* View mode, e.g. 'full', 'teaser', ...
|
||||
* @return
|
||||
* $node. The passed $node parameter should be modified as necessary and
|
||||
* returned so it can be properly presented. Nodes are prepared for display
|
||||
* by assembling a structured array, formatted as in the Form API, in
|
||||
* $node->content. As with Form API arrays, the #weight property can be
|
||||
* used to control the relative positions of added elements. After this
|
||||
* hook is invoked, node_view() calls field_attach_view() to add field
|
||||
* views to $node->content, and then invokes hook_node_view() and
|
||||
* hook_node_view_alter(), so if you want to affect the final
|
||||
* view of the node, you might consider implementing one of these hooks
|
||||
* instead.
|
||||
* The passed $node parameter should be modified as necessary and returned so
|
||||
* it can be properly presented. Nodes are prepared for display by assembling
|
||||
* a structured array, formatted as in the Form API, in $node->content. As
|
||||
* with Form API arrays, the #weight property can be used to control the
|
||||
* relative positions of added elements. After this hook is invoked,
|
||||
* node_view() calls field_attach_view() to add field views to $node->content,
|
||||
* and then invokes hook_node_view() and hook_node_view_alter(), so if you
|
||||
* want to affect the final view of the node, you might consider implementing
|
||||
* one of these hooks instead.
|
||||
*
|
||||
* @ingroup node_api_hooks
|
||||
*/
|
||||
|
@@ -9,8 +9,8 @@ required = TRUE
|
||||
configure = admin/structure/types
|
||||
stylesheets[all][] = node.css
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -914,6 +914,7 @@ function node_update_7012() {
|
||||
* Change {node}.vid default value from 0 to NULL to avoid deadlock issues on MySQL.
|
||||
*/
|
||||
function node_update_7013() {
|
||||
db_drop_unique_key('node', 'vid');
|
||||
db_change_field('node', 'vid', 'vid', array(
|
||||
'description' => 'The current {node_revision}.vid version identifier.',
|
||||
'type' => 'int',
|
||||
@@ -921,6 +922,7 @@ function node_update_7013() {
|
||||
'not null' => FALSE,
|
||||
'default' => NULL,
|
||||
));
|
||||
db_add_unique_key('node', 'vid', array('vid'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -141,6 +141,7 @@ function node_theme() {
|
||||
),
|
||||
'node_admin_overview' => array(
|
||||
'variables' => array('name' => NULL, 'type' => NULL),
|
||||
'file' => 'content_types.inc',
|
||||
),
|
||||
'node_recent_block' => array(
|
||||
'variables' => array('nodes' => NULL),
|
||||
@@ -200,8 +201,8 @@ function node_entity_info() {
|
||||
),
|
||||
);
|
||||
|
||||
// Search integration is provided by node.module, so search-related
|
||||
// view modes for nodes are defined here and not in search.module.
|
||||
// Search integration is provided by node.module, so search-related view modes
|
||||
// for nodes are defined here and not in search.module.
|
||||
if (module_exists('search')) {
|
||||
$return['node']['view modes'] += array(
|
||||
'search_index' => array(
|
||||
@@ -244,6 +245,12 @@ function node_field_display_node_alter(&$display, $context) {
|
||||
|
||||
/**
|
||||
* Entity URI callback.
|
||||
*
|
||||
* @param $node
|
||||
* A node entity.
|
||||
*
|
||||
* @return array
|
||||
* An array with 'path' as the key and the path to the node as its value.
|
||||
*/
|
||||
function node_uri($node) {
|
||||
return array(
|
||||
@@ -296,7 +303,7 @@ function node_title_list($result, $title = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the 'last viewed' timestamp of the specified node for current user.
|
||||
* Updates the 'last viewed' timestamp of the specified node for current user.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
@@ -315,8 +322,14 @@ function node_tag_new($node) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the timestamp at which the current user last viewed the
|
||||
* specified node.
|
||||
* Retrieves the timestamp for the current user's last view of a specified node.
|
||||
*
|
||||
* @param $nid
|
||||
* A node ID.
|
||||
*
|
||||
* @return
|
||||
* If a node has been previously viewed by the user, the timestamp in seconds
|
||||
* of when the last view occurred; otherwise, zero.
|
||||
*/
|
||||
function node_last_viewed($nid) {
|
||||
global $user;
|
||||
@@ -330,12 +343,13 @@ function node_last_viewed($nid) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide on the type of marker to be displayed for a given node.
|
||||
* Determines the type of marker to be displayed for a given node.
|
||||
*
|
||||
* @param $nid
|
||||
* Node ID whose history supplies the "last viewed" timestamp.
|
||||
* @param $timestamp
|
||||
* Time which is compared against node's "last viewed" timestamp.
|
||||
*
|
||||
* @return
|
||||
* One of the MARK constants.
|
||||
*/
|
||||
@@ -359,7 +373,7 @@ function node_mark($nid, $timestamp) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the type name.
|
||||
* Extracts the type name.
|
||||
*
|
||||
* @param $node
|
||||
* Either a string or object, containing the node type information.
|
||||
@@ -461,6 +475,8 @@ function node_type_get_name($node) {
|
||||
* node_type_save(), and obsolete ones are deleted via a call to
|
||||
* node_type_delete(). See _node_types_build() for an explanation of the new
|
||||
* and obsolete types.
|
||||
*
|
||||
* @see _node_types_build()
|
||||
*/
|
||||
function node_types_rebuild() {
|
||||
_node_types_build(TRUE);
|
||||
@@ -483,11 +499,34 @@ function node_type_load($name) {
|
||||
/**
|
||||
* Saves a node type to the database.
|
||||
*
|
||||
* @param $info
|
||||
* The node type to save, as an object.
|
||||
* @param object $info
|
||||
* The node type to save; an object with the following properties:
|
||||
* - type: A string giving the machine name of the node type.
|
||||
* - name: A string giving the human-readable name of the node type.
|
||||
* - base: A string that indicates the base string for hook functions. For
|
||||
* example, 'node_content' is the value used by the UI when creating a new
|
||||
* node type.
|
||||
* - description: A string that describes the node type.
|
||||
* - help: A string giving the help information shown to the user when
|
||||
* creating a node of this type.
|
||||
* - custom: TRUE or FALSE indicating whether this type is defined by a module
|
||||
* (FALSE) or by a user (TRUE) via Add Content Type.
|
||||
* - modified: TRUE or FALSE indicating whether this type has been modified by
|
||||
* an administrator. Currently not used in any way.
|
||||
* - locked: TRUE or FALSE indicating whether the administrator can change the
|
||||
* machine name of this type.
|
||||
* - disabled: TRUE or FALSE indicating whether this type has been disabled.
|
||||
* - has_title: TRUE or FALSE indicating whether this type uses the node title
|
||||
* field.
|
||||
* - title_label: A string containing the label for the title.
|
||||
* - module: A string giving the module defining this type of node.
|
||||
* - orig_type: A string giving the original machine-readable name of this
|
||||
* node type. This may be different from the current type name if the
|
||||
* 'locked' key is FALSE.
|
||||
*
|
||||
* @return
|
||||
* Status flag indicating outcome of the operation.
|
||||
* @return int
|
||||
* A status flag indicating the outcome of the operation, either SAVED_NEW or
|
||||
* SAVED_UPDATED.
|
||||
*/
|
||||
function node_type_save($info) {
|
||||
$existing_type = !empty($info->old_type) ? $info->old_type : $info->type;
|
||||
@@ -540,7 +579,7 @@ function node_type_save($info) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add default body field to a node type.
|
||||
* Adds default body field to a node type.
|
||||
*
|
||||
* @param $type
|
||||
* A node type object.
|
||||
@@ -655,6 +694,7 @@ function node_type_update_nodes($old_type, $type) {
|
||||
*
|
||||
* @param $rebuild
|
||||
* TRUE to rebuild node types. Equivalent to calling node_types_rebuild().
|
||||
*
|
||||
* @return
|
||||
* An object with two properties:
|
||||
* - names: Associative array of the names of node types, keyed by the type.
|
||||
@@ -761,8 +801,9 @@ function node_type_cache_reset() {
|
||||
* which prevents users from changing the machine name of the type.
|
||||
*
|
||||
* @param $info
|
||||
* An object or array containing values to override the defaults. See
|
||||
* hook_node_info() for details on what the array elements mean.
|
||||
* (optional) An object or array containing values to override the defaults.
|
||||
* See hook_node_info() for details on what the array elements mean. Defaults
|
||||
* to an empty array.
|
||||
*
|
||||
* @return
|
||||
* A node type object, with missing values in $info set to their defaults.
|
||||
@@ -845,12 +886,13 @@ function node_rdf_mapping() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a node hook exists.
|
||||
* Determines whether a node hook exists.
|
||||
*
|
||||
* @param $node
|
||||
* A node object or a string containing the node type.
|
||||
* @param $hook
|
||||
* A string containing the name of the hook.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the $hook exists in the node type of $node.
|
||||
*/
|
||||
@@ -860,7 +902,7 @@ function node_hook($node, $hook) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke a node hook.
|
||||
* Invokes a node hook.
|
||||
*
|
||||
* @param $node
|
||||
* A node object or a string containing the node type.
|
||||
@@ -868,6 +910,7 @@ function node_hook($node, $hook) {
|
||||
* A string containing the name of the hook.
|
||||
* @param $a2, $a3, $a4
|
||||
* Arguments to pass on to the hook, after the $node argument.
|
||||
*
|
||||
* @return
|
||||
* The returned value of the invoked hook.
|
||||
*/
|
||||
@@ -880,11 +923,11 @@ function node_invoke($node, $hook, $a2 = NULL, $a3 = NULL, $a4 = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load node entities from the database.
|
||||
* Loads node entities from the database.
|
||||
*
|
||||
* This function should be used whenever you need to load more than one node
|
||||
* from the database. Nodes are loaded into memory and will not require
|
||||
* database access if loaded again during the same page request.
|
||||
* from the database. Nodes are loaded into memory and will not require database
|
||||
* access if loaded again during the same page request.
|
||||
*
|
||||
* @see entity_load()
|
||||
* @see EntityFieldQuery
|
||||
@@ -910,7 +953,7 @@ function node_load_multiple($nids = array(), $conditions = array(), $reset = FAL
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a node object from the database.
|
||||
* Loads a node object from the database.
|
||||
*
|
||||
* @param $nid
|
||||
* The node ID.
|
||||
@@ -934,6 +977,9 @@ function node_load($nid = NULL, $vid = NULL, $reset = FALSE) {
|
||||
*
|
||||
* Fills in a few default values, and then invokes hook_prepare() on the node
|
||||
* type module, and hook_node_prepare() on all modules.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
*/
|
||||
function node_object_prepare($node) {
|
||||
// Set up default values, if required.
|
||||
@@ -963,11 +1009,11 @@ function node_object_prepare($node) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform validation checks on the given node.
|
||||
* Implements hook_validate().
|
||||
*
|
||||
* Performs validation checks on the given node.
|
||||
*/
|
||||
function node_validate($node, $form, &$form_state) {
|
||||
$type = node_type_get_type($node);
|
||||
|
||||
if (isset($node->nid) && (node_last_changed($node->nid) > $node->changed)) {
|
||||
form_set_error('changed', t('The content on this page has either been modified by another user, or you have already submitted modifications using this form. As a result, your changes cannot be saved.'));
|
||||
}
|
||||
@@ -1000,7 +1046,13 @@ function node_validate($node, $form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare node for saving by populating author and creation date.
|
||||
* Prepares node for saving by populating author and creation date.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
*
|
||||
* @return
|
||||
* An updated node object.
|
||||
*/
|
||||
function node_submit($node) {
|
||||
// A user might assign the node author by entering a user name in the node
|
||||
@@ -1021,7 +1073,7 @@ function node_submit($node) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save changes to a node or add a new node.
|
||||
* Saves changes to a node or adds a new node.
|
||||
*
|
||||
* @param $node
|
||||
* The $node object to be saved. If $node->nid is
|
||||
@@ -1159,6 +1211,13 @@ function node_save($node) {
|
||||
* Helper function to save a revision with the uid of the current user.
|
||||
*
|
||||
* The resulting revision ID is available afterward in $node->vid.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @param $uid
|
||||
* The current user's UID.
|
||||
* @param $update
|
||||
* (optional) An array of primary keys' field names to update.
|
||||
*/
|
||||
function _node_save_revision($node, $uid, $update = NULL) {
|
||||
$temp_uid = $node->uid;
|
||||
@@ -1174,7 +1233,7 @@ function _node_save_revision($node, $uid, $update = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a node.
|
||||
* Deletes a node.
|
||||
*
|
||||
* @param $nid
|
||||
* A node ID.
|
||||
@@ -1184,7 +1243,7 @@ function node_delete($nid) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete multiple nodes.
|
||||
* Deletes multiple nodes.
|
||||
*
|
||||
* @param $nids
|
||||
* An array of node IDs.
|
||||
@@ -1237,7 +1296,7 @@ function node_delete_multiple($nids) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a node revision.
|
||||
* Deletes a node revision.
|
||||
*
|
||||
* @param $revision_id
|
||||
* The revision ID to delete.
|
||||
@@ -1262,7 +1321,7 @@ function node_revision_delete($revision_id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an array for rendering the given node.
|
||||
* Generates an array for rendering the given node.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
@@ -1367,8 +1426,8 @@ function node_build_content($node, $view_mode = 'full', $langcode = NULL) {
|
||||
entity_prepare_view('node', array($node->nid => $node), $langcode);
|
||||
$node->content += field_attach_view('node', $node, $view_mode, $langcode);
|
||||
|
||||
// Always display a read more link on teasers because we have no way
|
||||
// to know when a teaser view is different than a full view.
|
||||
// Always display a read more link on teasers because we have no way to know
|
||||
// when a teaser view is different than a full view.
|
||||
$links = array();
|
||||
$node->content['links'] = array(
|
||||
'#theme' => 'links__node',
|
||||
@@ -1400,12 +1459,13 @@ function node_build_content($node, $view_mode = 'full', $langcode = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an array which displays a node detail page.
|
||||
* Generates an array which displays a node detail page.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @param $message
|
||||
* A flag which sets a page title relevant to the revision being viewed.
|
||||
*
|
||||
* @return
|
||||
* A $page element suitable for use by drupal_render().
|
||||
*/
|
||||
@@ -1428,6 +1488,9 @@ function node_show($node, $message = FALSE) {
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
*
|
||||
* @return
|
||||
* The ID of the node if this is a full page view, otherwise FALSE.
|
||||
*/
|
||||
function node_is_page($node) {
|
||||
$page_node = menu_get_object();
|
||||
@@ -1435,7 +1498,7 @@ function node_is_page($node) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Process variables for node.tpl.php
|
||||
* Processes variables for node.tpl.php
|
||||
*
|
||||
* Most themes utilize their own copy of node.tpl.php. The default is located
|
||||
* inside "modules/node/node.tpl.php". Look in there for the full list of
|
||||
@@ -1557,7 +1620,7 @@ function node_permission() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather the rankings from the the hook_ranking implementations.
|
||||
* Gathers the rankings from the the hook_ranking() implementations.
|
||||
*
|
||||
* @param $query
|
||||
* A query object that has been extended with the Search DB Extender.
|
||||
@@ -1804,6 +1867,7 @@ function node_user_delete($account) {
|
||||
* An associative array containing:
|
||||
* - form: A render element representing the form.
|
||||
*
|
||||
* @see node_search_admin()
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_node_search_admin($variables) {
|
||||
@@ -1872,11 +1936,11 @@ function _node_revision_access($node, $op = 'view', $account = NULL) {
|
||||
$node_current_revision = node_load($node->nid);
|
||||
$is_current_revision = $node_current_revision->vid == $node->vid;
|
||||
|
||||
// There should be at least two revisions. If the vid of the given node
|
||||
// and the vid of the current revision differ, then we already have two
|
||||
// There should be at least two revisions. If the vid of the given node and
|
||||
// the vid of the current revision differ, then we already have two
|
||||
// different revisions so there is no need for a separate database check.
|
||||
// Also, if you try to revert to or delete the current revision, that's
|
||||
// not good.
|
||||
// Also, if you try to revert to or delete the current revision, that's not
|
||||
// good.
|
||||
if ($is_current_revision && (db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField() == 1 || $op == 'update' || $op == 'delete')) {
|
||||
$access[$cid] = FALSE;
|
||||
}
|
||||
@@ -1884,8 +1948,8 @@ function _node_revision_access($node, $op = 'view', $account = NULL) {
|
||||
$access[$cid] = TRUE;
|
||||
}
|
||||
else {
|
||||
// First check the access to the current revision and finally, if the
|
||||
// node passed in is not the current revision then access to that, too.
|
||||
// First check the access to the current revision and finally, if the node
|
||||
// passed in is not the current revision then access to that, too.
|
||||
$access[$cid] = node_access($op, $node_current_revision, $account) && ($is_current_revision || node_access($op, $node, $account));
|
||||
}
|
||||
}
|
||||
@@ -1893,6 +1957,14 @@ function _node_revision_access($node, $op = 'view', $account = NULL) {
|
||||
return $access[$cid];
|
||||
}
|
||||
|
||||
/**
|
||||
* Access callback: Checks whether the user has permission to add a node.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the user has add permission, otherwise FALSE.
|
||||
*
|
||||
* @see node_menu()
|
||||
*/
|
||||
function _node_add_access() {
|
||||
$types = node_type_get_types();
|
||||
foreach ($types as $type) {
|
||||
@@ -2110,14 +2182,30 @@ function node_menu_local_tasks_alter(&$data, $router_item, $root_path) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Title callback for a node type.
|
||||
* Title callback: Returns the unsanitized title of the node type edit form.
|
||||
*
|
||||
* @param $type
|
||||
* The node type object.
|
||||
*
|
||||
* @return string
|
||||
* An unsanitized string that is the title of the node type edit form.
|
||||
*
|
||||
* @see node_menu()
|
||||
*/
|
||||
function node_type_page_title($type) {
|
||||
return $type->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Title callback.
|
||||
* Title callback: Returns the title of the node.
|
||||
*
|
||||
* @param $node
|
||||
* The node object.
|
||||
*
|
||||
* @return
|
||||
* An unsanitized string that is the title of the node.
|
||||
*
|
||||
* @see node_menu()
|
||||
*/
|
||||
function node_page_title($node) {
|
||||
return $node->title;
|
||||
@@ -2137,7 +2225,13 @@ function node_last_changed($nid) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all the existing revision numbers.
|
||||
* Returns a list of all the existing revision numbers.
|
||||
*
|
||||
* @param Drupal\node\Node $node
|
||||
* The node entity.
|
||||
*
|
||||
* @return
|
||||
* An associative array keyed by node revision number.
|
||||
*/
|
||||
function node_revision_list($node) {
|
||||
$revisions = array();
|
||||
@@ -2223,16 +2317,16 @@ function node_block_save($delta = '', $edit = array()) {
|
||||
* (optional) The maximum number of nodes to find. Defaults to 10.
|
||||
*
|
||||
* @return
|
||||
* An array of partial node objects or an empty array if there are no recent
|
||||
* nodes visible to the current user.
|
||||
* An array of node entities or an empty array if there are no recent nodes
|
||||
* visible to the current user.
|
||||
*/
|
||||
function node_get_recent($number = 10) {
|
||||
$query = db_select('node', 'n');
|
||||
|
||||
if (!user_access('bypass node access')) {
|
||||
// If the user is able to view their own unpublished nodes, allow them
|
||||
// to see these in addition to published nodes. Check that they actually
|
||||
// have some unpublished nodes to view before adding the condition.
|
||||
// If the user is able to view their own unpublished nodes, allow them to
|
||||
// see these in addition to published nodes. Check that they actually have
|
||||
// some unpublished nodes to view before adding the condition.
|
||||
if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT nid FROM {node} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => NODE_NOT_PUBLISHED))->fetchCol()) {
|
||||
$query->condition(db_or()
|
||||
->condition('n.status', NODE_PUBLISHED)
|
||||
@@ -2362,7 +2456,7 @@ function node_form_block_admin_configure_alter(&$form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submit handler for block configuration form.
|
||||
* Form submission handler for node_form_block_admin_configure_alter().
|
||||
*
|
||||
* @see node_form_block_admin_configure_alter()
|
||||
*/
|
||||
@@ -2394,7 +2488,7 @@ function node_form_block_custom_block_delete_alter(&$form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submit handler for custom block delete form.
|
||||
* Form submission handler for node_form_block_custom_block_delete_alter().
|
||||
*
|
||||
* @see node_form_block_custom_block_delete_alter()
|
||||
*/
|
||||
@@ -2419,8 +2513,8 @@ function node_modules_uninstalled($modules) {
|
||||
/**
|
||||
* Implements hook_block_list_alter().
|
||||
*
|
||||
* Check the content type specific visibilty settings.
|
||||
* Remove the block if the visibility conditions are not met.
|
||||
* Check the content type specific visibilty settings. Remove the block if the
|
||||
* visibility conditions are not met.
|
||||
*/
|
||||
function node_block_list_alter(&$blocks) {
|
||||
global $theme_key;
|
||||
@@ -2485,7 +2579,8 @@ function node_block_list_alter(&$blocks) {
|
||||
* @param $channel
|
||||
* An associative array containing title, link, description and other keys,
|
||||
* to be parsed by format_rss_channel() and format_xml_elements().
|
||||
* A list of channel elements can be found at the @link http://cyber.law.harvard.edu/rss/rss.html RSS 2.0 Specification. @endlink
|
||||
* A list of channel elements can be found at the
|
||||
* @link http://cyber.law.harvard.edu/rss/rss.html RSS 2.0 Specification. @endlink
|
||||
* The link should be an absolute URL.
|
||||
*/
|
||||
function node_feed($nids = FALSE, $channel = array()) {
|
||||
@@ -2505,7 +2600,6 @@ function node_feed($nids = FALSE, $channel = array()) {
|
||||
|
||||
$item_length = variable_get('feed_item_length', 'fulltext');
|
||||
$namespaces = array('xmlns:dc' => 'http://purl.org/dc/elements/1.1/');
|
||||
$teaser = ($item_length == 'teaser');
|
||||
|
||||
// Load all nodes to be rendered.
|
||||
$nodes = node_load_multiple($nids);
|
||||
@@ -2559,7 +2653,7 @@ function node_feed($nids = FALSE, $channel = array()) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a drupal_render() style array from an array of loaded nodes.
|
||||
* Constructs a drupal_render() style array from an array of loaded nodes.
|
||||
*
|
||||
* @param $nodes
|
||||
* An array of nodes as returned by node_load_multiple().
|
||||
@@ -2568,8 +2662,8 @@ function node_feed($nids = FALSE, $channel = array()) {
|
||||
* @param $weight
|
||||
* An integer representing the weight of the first node in the list.
|
||||
* @param $langcode
|
||||
* (optional) A language code to use for rendering. Defaults to the global
|
||||
* content language of the current request.
|
||||
* (optional) A language code to use for rendering. Defaults to NULL which is
|
||||
* the global content language of the current request.
|
||||
*
|
||||
* @return
|
||||
* An array in the format expected by drupal_render().
|
||||
@@ -2588,7 +2682,12 @@ function node_view_multiple($nodes, $view_mode = 'teaser', $weight = 0, $langcod
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; Generate a listing of promoted nodes.
|
||||
* Menu callback: Generates a listing of promoted nodes.
|
||||
*
|
||||
* @return array
|
||||
* An array in the format expected by drupal_render().
|
||||
*
|
||||
* @see node_menu()
|
||||
*/
|
||||
function node_page_default() {
|
||||
$select = db_select('node', 'n')
|
||||
@@ -2638,7 +2737,15 @@ function node_page_default() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; view a single node.
|
||||
* Menu callback: Displays a single node.
|
||||
*
|
||||
* @param $node
|
||||
* The node object.
|
||||
*
|
||||
* @return
|
||||
* A page array suitable for use by drupal_render().
|
||||
*
|
||||
* @see node_menu()
|
||||
*/
|
||||
function node_page_view($node) {
|
||||
// If there is a menu link to this node, the link becomes the last part
|
||||
@@ -2667,7 +2774,7 @@ function node_update_index() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Index a single node.
|
||||
* Indexes a single node.
|
||||
*
|
||||
* @param $node
|
||||
* The node to index.
|
||||
@@ -2771,7 +2878,7 @@ function node_form_search_form_alter(&$form, $form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Form API callback for the search form. Registered in node_form_alter().
|
||||
* Form validation handler for node_form_alter().
|
||||
*/
|
||||
function node_search_validate($form, &$form_state) {
|
||||
// Initialize using any existing basic search keywords.
|
||||
@@ -2819,8 +2926,8 @@ function node_search_validate($form, &$form_state) {
|
||||
* @{
|
||||
* The node access system determines who can do what to which nodes.
|
||||
*
|
||||
* In determining access rights for a node, node_access() first checks
|
||||
* whether the user has the "bypass node access" permission. Such users have
|
||||
* In determining access rights for a node, node_access() first checks whether
|
||||
* the user has the "bypass node access" permission. Such users have
|
||||
* unrestricted access to all nodes. user 1 will always pass this check.
|
||||
*
|
||||
* Next, all implementations of hook_node_access() will be called. Each
|
||||
@@ -2858,8 +2965,7 @@ function node_search_validate($form, &$form_state) {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determine whether the current user may perform the given operation on the
|
||||
* specified node.
|
||||
* Determines whether the current user may perform the operation on the node.
|
||||
*
|
||||
* @param $op
|
||||
* The operation to be performed on the node. Possible values are:
|
||||
@@ -2873,6 +2979,7 @@ function node_search_validate($form, &$form_state) {
|
||||
* @param $account
|
||||
* Optional, a user object representing the user for whom the operation is to
|
||||
* be performed. Determines access for a user other than the current user.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the operation may be performed, FALSE otherwise.
|
||||
*/
|
||||
@@ -3005,6 +3112,7 @@ function node_node_access($node, $op, $account) {
|
||||
*
|
||||
* @param $type
|
||||
* The machine-readable name of the node type.
|
||||
*
|
||||
* @return array
|
||||
* An array of permission names and descriptions.
|
||||
*/
|
||||
@@ -3038,11 +3146,11 @@ function node_list_permissions($type) {
|
||||
*
|
||||
* By default, this will include all node types in the system. To exclude a
|
||||
* specific node from getting permissions defined for it, set the
|
||||
* node_permissions_$type variable to 0. Core does not provide an interface
|
||||
* for doing so, however, contrib modules may exclude their own nodes in
|
||||
* node_permissions_$type variable to 0. Core does not provide an interface for
|
||||
* doing so. However, contrib modules may exclude their own nodes in
|
||||
* hook_install(). Alternatively, contrib modules may configure all node types
|
||||
* at once, or decide to apply some other hook_node_access() implementation
|
||||
* to some or all node types.
|
||||
* at once, or decide to apply some other hook_node_access() implementation to
|
||||
* some or all node types.
|
||||
*
|
||||
* @return
|
||||
* An array of node types managed by this module.
|
||||
@@ -3061,21 +3169,22 @@ function node_permissions_get_configured_types() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an array of permission IDs granted to the given user ID.
|
||||
* Fetches an array of permission IDs granted to the given user ID.
|
||||
*
|
||||
* The implementation here provides only the universal "all" grant. A node
|
||||
* access module should implement hook_node_grants() to provide a grant
|
||||
* list for the user.
|
||||
* access module should implement hook_node_grants() to provide a grant list for
|
||||
* the user.
|
||||
*
|
||||
* After the default grants have been loaded, we allow modules to alter
|
||||
* the grants array by reference. This hook allows for complex business
|
||||
* logic to be applied when integrating multiple node access modules.
|
||||
* After the default grants have been loaded, we allow modules to alter the
|
||||
* grants array by reference. This hook allows for complex business logic to be
|
||||
* applied when integrating multiple node access modules.
|
||||
*
|
||||
* @param $op
|
||||
* The operation that the user is trying to perform.
|
||||
* @param $account
|
||||
* The user object for the user performing the operation. If omitted, the
|
||||
* current user is used.
|
||||
*
|
||||
* @return
|
||||
* An associative array in which the keys are realms, and the values are
|
||||
* arrays of grants for those realms.
|
||||
@@ -3163,11 +3272,10 @@ function node_access_view_all_nodes($account = NULL) {
|
||||
/**
|
||||
* Implements hook_query_TAG_alter().
|
||||
*
|
||||
* This is the hook_query_alter() for queries tagged with 'node_access'.
|
||||
* It adds node access checks for the user account given by the 'account'
|
||||
* meta-data (or global $user if not provided), for an operation given by
|
||||
* the 'op' meta-data (or 'view' if not provided; other possible values are
|
||||
* 'update' and 'delete').
|
||||
* This is the hook_query_alter() for queries tagged with 'node_access'. It adds
|
||||
* node access checks for the user account given by the 'account' meta-data (or
|
||||
* global $user if not provided), for an operation given by the 'op' meta-data
|
||||
* (or 'view' if not provided; other possible values are 'update' and 'delete').
|
||||
*/
|
||||
function node_query_node_access_alter(QueryAlterableInterface $query) {
|
||||
_node_query_node_access_alter($query, 'node');
|
||||
@@ -3206,8 +3314,8 @@ function _node_query_node_access_alter($query, $type) {
|
||||
}
|
||||
|
||||
// If $account can bypass node access, or there are no node access modules,
|
||||
// or the operation is 'view' and the $acount has a global view grant (i.e.,
|
||||
// a view grant for node ID 0), we don't need to alter the query.
|
||||
// or the operation is 'view' and the $account has a global view grant
|
||||
// (such as a view grant for node ID 0), we don't need to alter the query.
|
||||
if (user_access('bypass node access', $account)) {
|
||||
return;
|
||||
}
|
||||
@@ -3394,15 +3502,14 @@ function node_access_acquire_grants($node, $delete = TRUE) {
|
||||
*
|
||||
* If a realm is provided, it will only delete grants from that realm, but it
|
||||
* will always delete a grant from the 'all' realm. Modules that utilize
|
||||
* node_access can use this function when doing mass updates due to widespread
|
||||
* node_access() can use this function when doing mass updates due to widespread
|
||||
* permission changes.
|
||||
*
|
||||
* Note: Don't call this function directly from a contributed module. Call
|
||||
* node_access_acquire_grants() instead.
|
||||
*
|
||||
* @param $node
|
||||
* The $node being written to. All that is necessary is that it contains a
|
||||
* nid.
|
||||
* The node whose grants are being written.
|
||||
* @param $grants
|
||||
* A list of grants to write. Each grant is an array that must contain the
|
||||
* following keys: realm, gid, grant_view, grant_update, grant_delete.
|
||||
@@ -3410,10 +3517,14 @@ function node_access_acquire_grants($node, $delete = TRUE) {
|
||||
* is a module-defined id to define grant privileges. each grant_* field
|
||||
* is a boolean value.
|
||||
* @param $realm
|
||||
* If provided, only read/write grants for that realm.
|
||||
* (optional) If provided, read/write grants for that realm only. Defaults to
|
||||
* NULL.
|
||||
* @param $delete
|
||||
* If false, do not delete records. This is only for optimization purposes,
|
||||
* and assumes the caller has already performed a mass delete of some form.
|
||||
* (optional) If false, does not delete records. This is only for optimization
|
||||
* purposes, and assumes the caller has already performed a mass delete of
|
||||
* some form. Defaults to TRUE.
|
||||
*
|
||||
* @see node_access_acquire_grants()
|
||||
*/
|
||||
function node_access_write_grants($node, $grants, $realm = NULL, $delete = TRUE) {
|
||||
if ($delete) {
|
||||
@@ -3442,21 +3553,23 @@ function node_access_write_grants($node, $grants, $realm = NULL, $delete = TRUE)
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag / unflag the node access grants for rebuilding, or read the current
|
||||
* value of the flag.
|
||||
* Flags or unflags the node access grants for rebuilding.
|
||||
*
|
||||
* If the argument isn't specified, the current value of the flag is returned.
|
||||
* When the flag is set, a message is displayed to users with 'access
|
||||
* administration pages' permission, pointing to the 'rebuild' confirm form.
|
||||
* This can be used as an alternative to direct node_access_rebuild calls,
|
||||
* allowing administrators to decide when they want to perform the actual
|
||||
* (possibly time consuming) rebuild.
|
||||
* When unsure the current user is an administrator, node_access_rebuild
|
||||
* should be used instead.
|
||||
* (possibly time consuming) rebuild. When unsure if the current user is an
|
||||
* administrator, node_access_rebuild() should be used instead.
|
||||
*
|
||||
* @param $rebuild
|
||||
* (Optional) The boolean value to be written.
|
||||
* @return
|
||||
* (If no value was provided for $rebuild) The current value of the flag.
|
||||
*
|
||||
* @return
|
||||
* The current value of the flag if no value was provided for $rebuild.
|
||||
*
|
||||
* @see node_access_rebuild()
|
||||
*/
|
||||
function node_access_needs_rebuild($rebuild = NULL) {
|
||||
if (!isset($rebuild)) {
|
||||
@@ -3471,15 +3584,15 @@ function node_access_needs_rebuild($rebuild = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild the node access database. This is occasionally needed by modules
|
||||
* that make system-wide changes to access levels.
|
||||
* Rebuilds the node access database.
|
||||
*
|
||||
* When the rebuild is required by an admin-triggered action (e.g module
|
||||
* settings form), calling node_access_needs_rebuild(TRUE) instead of
|
||||
* This is occasionally needed by modules that make system-wide changes to
|
||||
* access levels. When the rebuild is required by an admin-triggered action (e.g
|
||||
* module settings form), calling node_access_needs_rebuild(TRUE) instead of
|
||||
* node_access_rebuild() lets the user perform his changes and actually
|
||||
* rebuild only once he is done.
|
||||
*
|
||||
* Note : As of Drupal 6, node access modules are not required to (and actually
|
||||
* Note: As of Drupal 6, node access modules are not required to (and actually
|
||||
* should not) call node_access_rebuild() in hook_enable/disable anymore.
|
||||
*
|
||||
* @see node_access_needs_rebuild()
|
||||
@@ -3543,11 +3656,14 @@ function node_access_rebuild($batch_mode = FALSE) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch operation for node_access_rebuild_batch.
|
||||
* Performs batch operation for node_access_rebuild().
|
||||
*
|
||||
* This is a multistep operation : we go through all nodes by packs of 20.
|
||||
* The batch processing engine interrupts processing and sends progress
|
||||
* feedback after 1 second execution time.
|
||||
* This is a multistep operation: we go through all nodes by packs of 20. The
|
||||
* batch processing engine interrupts processing and sends progress feedback
|
||||
* after 1 second execution time.
|
||||
*
|
||||
* @param array $context
|
||||
* An array of contextual key/value information for rebuild batch process.
|
||||
*/
|
||||
function _node_access_rebuild_batch_operation(&$context) {
|
||||
if (empty($context['sandbox'])) {
|
||||
@@ -3578,7 +3694,14 @@ function _node_access_rebuild_batch_operation(&$context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-processing for node_access_rebuild_batch.
|
||||
* Performs post-processing for node_access_rebuild().
|
||||
*
|
||||
* @param bool $success
|
||||
* A boolean indicating whether the re-build process has completed.
|
||||
* @param array $results
|
||||
* An array of results information.
|
||||
* @param array $operations
|
||||
* An array of function calls (not used in this function).
|
||||
*/
|
||||
function _node_access_rebuild_batch_finished($success, $results, $operations) {
|
||||
if ($success) {
|
||||
@@ -3595,7 +3718,6 @@ function _node_access_rebuild_batch_finished($success, $results, $operations) {
|
||||
* @} End of "defgroup node_access".
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup node_content Hook implementations for user-created content types
|
||||
* @{
|
||||
@@ -3631,6 +3753,7 @@ function node_content_form($node, $form_state) {
|
||||
|
||||
/**
|
||||
* Implements hook_forms().
|
||||
*
|
||||
* All node forms share the same form handler.
|
||||
*/
|
||||
function node_forms() {
|
||||
@@ -3715,6 +3838,12 @@ function node_action_info() {
|
||||
/**
|
||||
* Sets the status of a node to 1 (published).
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @param $context
|
||||
* (optional) Array of additional information about what triggered the action.
|
||||
* Not used for this action.
|
||||
*
|
||||
* @ingroup actions
|
||||
*/
|
||||
function node_publish_action($node, $context = array()) {
|
||||
@@ -3725,6 +3854,12 @@ function node_publish_action($node, $context = array()) {
|
||||
/**
|
||||
* Sets the status of a node to 0 (unpublished).
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @param $context
|
||||
* (optional) Array of additional information about what triggered the action.
|
||||
* Not used for this action.
|
||||
*
|
||||
* @ingroup actions
|
||||
*/
|
||||
function node_unpublish_action($node, $context = array()) {
|
||||
@@ -3735,6 +3870,12 @@ function node_unpublish_action($node, $context = array()) {
|
||||
/**
|
||||
* Sets the sticky-at-top-of-list property of a node to 1.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @param $context
|
||||
* (optional) Array of additional information about what triggered the action.
|
||||
* Not used for this action.
|
||||
*
|
||||
* @ingroup actions
|
||||
*/
|
||||
function node_make_sticky_action($node, $context = array()) {
|
||||
@@ -3745,6 +3886,12 @@ function node_make_sticky_action($node, $context = array()) {
|
||||
/**
|
||||
* Sets the sticky-at-top-of-list property of a node to 0.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @param $context
|
||||
* (optional) Array of additional information about what triggered the action.
|
||||
* Not used for this action.
|
||||
*
|
||||
* @ingroup actions
|
||||
*/
|
||||
function node_make_unsticky_action($node, $context = array()) {
|
||||
@@ -3755,6 +3902,12 @@ function node_make_unsticky_action($node, $context = array()) {
|
||||
/**
|
||||
* Sets the promote property of a node to 1.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @param $context
|
||||
* (optional) Array of additional information about what triggered the action.
|
||||
* Not used for this action.
|
||||
*
|
||||
* @ingroup actions
|
||||
*/
|
||||
function node_promote_action($node, $context = array()) {
|
||||
@@ -3765,6 +3918,12 @@ function node_promote_action($node, $context = array()) {
|
||||
/**
|
||||
* Sets the promote property of a node to 0.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
* @param $context
|
||||
* (optional) Array of additional information about what triggered the action.
|
||||
* Not used for this action.
|
||||
*
|
||||
* @ingroup actions
|
||||
*/
|
||||
function node_unpromote_action($node, $context = array()) {
|
||||
@@ -3775,6 +3934,9 @@ function node_unpromote_action($node, $context = array()) {
|
||||
/**
|
||||
* Saves a node.
|
||||
*
|
||||
* @param $node
|
||||
* The node to be saved.
|
||||
*
|
||||
* @ingroup actions
|
||||
*/
|
||||
function node_save_action($node) {
|
||||
@@ -3791,6 +3953,9 @@ function node_save_action($node) {
|
||||
* Array with the following elements:
|
||||
* - 'owner_uid': User ID to assign to the node.
|
||||
*
|
||||
* @see node_assign_owner_action_form()
|
||||
* @see node_assign_owner_action_validate()
|
||||
* @see node_assign_owner_action_submit()
|
||||
* @ingroup actions
|
||||
*/
|
||||
function node_assign_owner_action($node, $context) {
|
||||
@@ -3801,6 +3966,16 @@ function node_assign_owner_action($node, $context) {
|
||||
|
||||
/**
|
||||
* Generates the settings form for node_assign_owner_action().
|
||||
*
|
||||
* @param $context
|
||||
* Array of additional information about what triggered the action. Includes
|
||||
* the following elements:
|
||||
* - 'owner_uid': User ID to assign to the node.
|
||||
*
|
||||
* @see node_assign_owner_action_submit()
|
||||
* @see node_assign_owner_action_validate()
|
||||
*
|
||||
* @ingroup forms
|
||||
*/
|
||||
function node_assign_owner_action_form($context) {
|
||||
$description = t('The username of the user to which you would like to assign ownership.');
|
||||
@@ -3841,6 +4016,8 @@ function node_assign_owner_action_form($context) {
|
||||
|
||||
/**
|
||||
* Validates settings form for node_assign_owner_action().
|
||||
*
|
||||
* @see node_assign_owner_action_submit()
|
||||
*/
|
||||
function node_assign_owner_action_validate($form, $form_state) {
|
||||
$exists = (bool) db_query_range('SELECT 1 FROM {users} WHERE name = :name', 0, 1, array(':name' => $form_state['values']['owner_name']))->fetchField();
|
||||
@@ -3851,6 +4028,8 @@ function node_assign_owner_action_validate($form, $form_state) {
|
||||
|
||||
/**
|
||||
* Saves settings form for node_assign_owner_action().
|
||||
*
|
||||
* @see node_assign_owner_action_validate()
|
||||
*/
|
||||
function node_assign_owner_action_submit($form, $form_state) {
|
||||
// Username can change, so we need to store the ID, not the username.
|
||||
@@ -3860,6 +4039,14 @@ function node_assign_owner_action_submit($form, $form_state) {
|
||||
|
||||
/**
|
||||
* Generates settings form for node_unpublish_by_keyword_action().
|
||||
*
|
||||
* @param array $context
|
||||
* Array of additional information about what triggered this action.
|
||||
*
|
||||
* @return array
|
||||
* A form array.
|
||||
*
|
||||
* @see node_unpublish_by_keyword_action_submit()
|
||||
*/
|
||||
function node_unpublish_by_keyword_action_form($context) {
|
||||
$form['keywords'] = array(
|
||||
|
@@ -5,7 +5,6 @@
|
||||
* Page callbacks for adding, editing, deleting, and revisions management for content.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Menu callback; presents the node editing form.
|
||||
*/
|
||||
@@ -63,6 +62,12 @@ function theme_node_add_list($variables) {
|
||||
|
||||
/**
|
||||
* Returns a node submission form.
|
||||
*
|
||||
* @param $type
|
||||
* The node type for the submitted node.
|
||||
*
|
||||
* @return
|
||||
* The themed form.
|
||||
*/
|
||||
function node_add($type) {
|
||||
global $user;
|
||||
@@ -75,6 +80,12 @@ function node_add($type) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form validation handler for node_form().
|
||||
*
|
||||
* @see node_form()
|
||||
* @see node_form_submit()
|
||||
*/
|
||||
function node_form_validate($form, &$form_state) {
|
||||
// $form_state['node'] contains the actual entity being edited, but we must
|
||||
// not update it with form values that have not yet been validated, so we
|
||||
@@ -85,7 +96,13 @@ function node_form_validate($form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the node add/edit form array.
|
||||
* Form constructor for the node add/edit form.
|
||||
*
|
||||
* @see node_form_validate()
|
||||
* @see node_form_submit()
|
||||
* @see node_form_build_preview()
|
||||
* @see node_form_delete_submit()
|
||||
* @ingroup forms
|
||||
*/
|
||||
function node_form($form, &$form_state, $node) {
|
||||
global $user;
|
||||
@@ -311,7 +328,12 @@ function node_form($form, &$form_state, $node) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Button submit function: handle the 'Delete' button on the node form.
|
||||
* Form submission handler for node_form().
|
||||
*
|
||||
* Handles the 'Delete' button on the node form.
|
||||
*
|
||||
* @see node_form()
|
||||
* @see node_form_validate()
|
||||
*/
|
||||
function node_form_delete_submit($form, &$form_state) {
|
||||
$destination = array();
|
||||
@@ -323,7 +345,14 @@ function node_form_delete_submit($form, &$form_state) {
|
||||
$form_state['redirect'] = array('node/' . $node->nid . '/delete', array('query' => $destination));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Form submission handler for node_form().
|
||||
*
|
||||
* Handles the 'Preview' button on the node form.
|
||||
*
|
||||
* @see node_form()
|
||||
* @see node_form_validate()
|
||||
*/
|
||||
function node_form_build_preview($form, &$form_state) {
|
||||
$node = node_form_submit_build_node($form, $form_state);
|
||||
$form_state['node_preview'] = node_preview($node);
|
||||
@@ -331,7 +360,15 @@ function node_form_build_preview($form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a node preview.
|
||||
* Generates a node preview.
|
||||
*
|
||||
* @param $node
|
||||
* The node to preview.
|
||||
*
|
||||
* @return
|
||||
* An HTML-formatted string of a node preview.
|
||||
*
|
||||
* @see node_form_build_preview()
|
||||
*/
|
||||
function node_preview($node) {
|
||||
if (node_access('create', $node) || node_access('update', $node)) {
|
||||
@@ -377,6 +414,7 @@ function node_preview($node) {
|
||||
* An associative array containing:
|
||||
* - node: The node object which is being previewed.
|
||||
*
|
||||
* @see node_preview()
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_node_preview($variables) {
|
||||
@@ -407,6 +445,12 @@ function theme_node_preview($variables) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler for node_form().
|
||||
*
|
||||
* @see node_form()
|
||||
* @see node_form_validate()
|
||||
*/
|
||||
function node_form_submit($form, &$form_state) {
|
||||
$node = node_form_submit_build_node($form, $form_state);
|
||||
$insert = empty($node->nid);
|
||||
@@ -426,7 +470,7 @@ function node_form_submit($form, &$form_state) {
|
||||
if ($node->nid) {
|
||||
$form_state['values']['nid'] = $node->nid;
|
||||
$form_state['nid'] = $node->nid;
|
||||
$form_state['redirect'] = 'node/' . $node->nid;
|
||||
$form_state['redirect'] = node_access('view', $node) ? 'node/' . $node->nid : '<front>';
|
||||
}
|
||||
else {
|
||||
// In the unlikely case something went wrong on save, the node will be
|
||||
@@ -472,7 +516,9 @@ function node_form_submit_build_node($form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback -- ask for confirmation of node deletion
|
||||
* Form constructor for the node deletion confirmation form.
|
||||
*
|
||||
* @see node_delete_confirm_submit()
|
||||
*/
|
||||
function node_delete_confirm($form, &$form_state, $node) {
|
||||
$form['#node'] = $node;
|
||||
@@ -488,7 +534,9 @@ function node_delete_confirm($form, &$form_state, $node) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute node deletion
|
||||
* Executes node deletion.
|
||||
*
|
||||
* @see node_delete_confirm()
|
||||
*/
|
||||
function node_delete_confirm_submit($form, &$form_state) {
|
||||
if ($form_state['values']['confirm']) {
|
||||
@@ -502,7 +550,15 @@ function node_delete_confirm_submit($form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an overview table of older revisions of a node.
|
||||
* Generates an overview table of older revisions of a node.
|
||||
*
|
||||
* @param $node
|
||||
* A node object.
|
||||
*
|
||||
* @return array
|
||||
* An array as expected by drupal_render().
|
||||
*
|
||||
* @see node_menu()
|
||||
*/
|
||||
function node_revision_overview($node) {
|
||||
drupal_set_title(t('Revisions for %title', array('%title' => $node->title)), PASS_THROUGH);
|
||||
@@ -553,13 +609,26 @@ function node_revision_overview($node) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask for confirmation of the reversion to prevent against CSRF attacks.
|
||||
* Asks for confirmation of the reversion to prevent against CSRF attacks.
|
||||
*
|
||||
* @param int $node_revision
|
||||
* The node revision ID.
|
||||
*
|
||||
* @return array
|
||||
* An array as expected by drupal_render().
|
||||
*
|
||||
* @see node_menu()
|
||||
* @see node_revision_revert_confirm_submit()
|
||||
* @ingroup forms
|
||||
*/
|
||||
function node_revision_revert_confirm($form, $form_state, $node_revision) {
|
||||
$form['#node_revision'] = $node_revision;
|
||||
return confirm_form($form, t('Are you sure you want to revert to the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', '', t('Revert'), t('Cancel'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler for node_revision_revert_confirm().
|
||||
*/
|
||||
function node_revision_revert_confirm_submit($form, &$form_state) {
|
||||
$node_revision = $form['#node_revision'];
|
||||
$node_revision->revision = 1;
|
||||
@@ -572,11 +641,29 @@ function node_revision_revert_confirm_submit($form, &$form_state) {
|
||||
$form_state['redirect'] = 'node/' . $node_revision->nid . '/revisions';
|
||||
}
|
||||
|
||||
/**
|
||||
* Form constructor for the revision deletion confirmation form.
|
||||
*
|
||||
* This form prevents against CSRF attacks.
|
||||
*
|
||||
* @param $node_revision
|
||||
* The node revision ID.
|
||||
*
|
||||
* @return
|
||||
* An array as expected by drupal_render().
|
||||
*
|
||||
* @see node_menu()
|
||||
* @see node_revision_delete_confirm_submit()
|
||||
* @ingroup forms
|
||||
*/
|
||||
function node_revision_delete_confirm($form, $form_state, $node_revision) {
|
||||
$form['#node_revision'] = $node_revision;
|
||||
return confirm_form($form, t('Are you sure you want to delete the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler for node_revision_delete_confirm().
|
||||
*/
|
||||
function node_revision_delete_confirm_submit($form, &$form_state) {
|
||||
$node_revision = $form['#node_revision'];
|
||||
node_revision_delete($node_revision->vid);
|
||||
|
@@ -149,6 +149,9 @@ class NodeLoadHooksTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the node revision functionality.
|
||||
*/
|
||||
class NodeRevisionsTestCase extends DrupalWebTestCase {
|
||||
protected $nodes;
|
||||
protected $logs;
|
||||
@@ -198,7 +201,7 @@ class NodeRevisionsTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check node revision related operations.
|
||||
* Checks node revision related operations.
|
||||
*/
|
||||
function testRevisions() {
|
||||
$nodes = $this->nodes;
|
||||
@@ -282,6 +285,9 @@ class NodeRevisionsTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the node edit functionality.
|
||||
*/
|
||||
class PageEditTestCase extends DrupalWebTestCase {
|
||||
protected $web_user;
|
||||
protected $admin_user;
|
||||
@@ -302,7 +308,7 @@ class PageEditTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check node edit functionality.
|
||||
* Checks node edit functionality.
|
||||
*/
|
||||
function testPageEdit() {
|
||||
$this->drupalLogin($this->web_user);
|
||||
@@ -369,7 +375,7 @@ class PageEditTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check changing node authored by fields.
|
||||
* Tests changing a node's "authored by" field.
|
||||
*/
|
||||
function testPageAuthoredBy() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
@@ -414,6 +420,9 @@ class PageEditTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the node entity preview functionality.
|
||||
*/
|
||||
class PagePreviewTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -431,7 +440,7 @@ class PagePreviewTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the node preview functionality.
|
||||
* Checks the node preview functionality.
|
||||
*/
|
||||
function testPagePreview() {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
@@ -455,7 +464,7 @@ class PagePreviewTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the node preview functionality, when using revisions.
|
||||
* Checks the node preview functionality, when using revisions.
|
||||
*/
|
||||
function testPagePreviewWithRevisions() {
|
||||
$langcode = LANGUAGE_NONE;
|
||||
@@ -485,6 +494,9 @@ class PagePreviewTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating and saving a node.
|
||||
*/
|
||||
class NodeCreationTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -503,7 +515,7 @@ class NodeCreationTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a "Basic page" node and verify its consistency in the database.
|
||||
* Creates a "Basic page" node and verifies its consistency in the database.
|
||||
*/
|
||||
function testNodeCreation() {
|
||||
// Create a node.
|
||||
@@ -522,7 +534,7 @@ class NodeCreationTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a page node and verify that a transaction rolls back the failed creation
|
||||
* Verifies that a transaction rolls back the failed creation.
|
||||
*/
|
||||
function testFailedPageCreation() {
|
||||
// Create a node.
|
||||
@@ -561,8 +573,30 @@ class NodeCreationTestCase extends DrupalWebTestCase {
|
||||
$records = db_query("SELECT wid FROM {watchdog} WHERE variables LIKE '%Test exception for rollback.%'")->fetchAll();
|
||||
$this->assertTrue(count($records) > 0, t('Rollback explanatory error logged to watchdog.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an unpublished node and confirm correct redirect behavior.
|
||||
*/
|
||||
function testUnpublishedNodeCreation() {
|
||||
// Set "Basic page" content type to be unpublished by default.
|
||||
variable_set('node_options_page', array());
|
||||
// Set the front page to the default "node" page.
|
||||
variable_set('site_frontpage', 'node');
|
||||
|
||||
// Create a node.
|
||||
$edit = array();
|
||||
$edit["title"] = $this->randomName(8);
|
||||
$edit["body[" . LANGUAGE_NONE . "][0][value]"] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the user was redirected to the home page.
|
||||
$this->assertText(t('Welcome to Drupal'), t('The user is redirected to the home page.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the functionality of node entity edit permissions.
|
||||
*/
|
||||
class PageViewTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -573,7 +607,7 @@ class PageViewTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a node and then an anonymous and unpermissioned user attempt to edit the node.
|
||||
* Tests an anonymous and unpermissioned user attempting to edit the node.
|
||||
*/
|
||||
function testPageView() {
|
||||
// Create a node to view.
|
||||
@@ -602,6 +636,9 @@ class PageViewTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the summary length functionality.
|
||||
*/
|
||||
class SummaryLengthTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -612,7 +649,7 @@ class SummaryLengthTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a node and then an anonymous and unpermissioned user attempt to edit the node.
|
||||
* Tests the node summary length functionality.
|
||||
*/
|
||||
function testSummaryLength() {
|
||||
// Create a node to view.
|
||||
@@ -644,6 +681,9 @@ class SummaryLengthTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests XSS functionality with a node entity.
|
||||
*/
|
||||
class NodeTitleXSSTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -653,6 +693,9 @@ class NodeTitleXSSTestCase extends DrupalWebTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests XSS functionality with a node entity.
|
||||
*/
|
||||
function testNodeTitleXSS() {
|
||||
// Prepare a user to do the stuff.
|
||||
$web_user = $this->drupalCreateUser(array('create page content', 'edit any page content'));
|
||||
@@ -678,6 +721,9 @@ class NodeTitleXSSTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the availability of the syndicate block.
|
||||
*/
|
||||
class NodeBlockTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
@@ -709,7 +755,7 @@ class NodeBlockTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the post information displays when enabled for a content type.
|
||||
* Checks that the post information displays when enabled for a content type.
|
||||
*/
|
||||
class NodePostSettingsTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
@@ -728,7 +774,7 @@ class NodePostSettingsTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set "Basic page" content type to display post information and confirm its presence on a new node.
|
||||
* Confirms "Basic page" content type and post information is on a new node.
|
||||
*/
|
||||
function testPagePostInfo() {
|
||||
|
||||
@@ -751,7 +797,7 @@ class NodePostSettingsTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set "Basic page" content type to not display post information and confirm its absence on a new node.
|
||||
* Confirms absence of post information on a new node.
|
||||
*/
|
||||
function testPageNotPostInfo() {
|
||||
|
||||
@@ -774,7 +820,7 @@ class NodePostSettingsTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that data added to nodes by other modules appears in RSS feeds.
|
||||
* Ensures that data added to nodes by other modules appears in RSS feeds.
|
||||
*
|
||||
* Create a node, enable the node_test module to ensure that extra data is
|
||||
* added to the node->content array, then verify that the data appears on the
|
||||
@@ -801,8 +847,7 @@ class NodeRSSContentTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new node and ensure that it includes the custom data when added
|
||||
* to an RSS feed.
|
||||
* Ensures that a new node includes the custom data when added to an RSS feed.
|
||||
*/
|
||||
function testNodeRSSContent() {
|
||||
// Create a node.
|
||||
@@ -841,9 +886,11 @@ class NodeRSSContentTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to verify basic node_access functionality.
|
||||
* Tests basic node_access functionality.
|
||||
*
|
||||
* Note that hook_node_access_records() is covered in another test class.
|
||||
*
|
||||
* @todo Cover hook_node_access in a separate test class.
|
||||
* hook_node_access_records is covered in another test class.
|
||||
*/
|
||||
class NodeAccessTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
@@ -855,7 +902,7 @@ class NodeAccessTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts node_access correctly grants or denies access.
|
||||
* Asserts node_access() correctly grants or denies access.
|
||||
*/
|
||||
function assertNodeAccess($ops, $node, $account) {
|
||||
foreach ($ops as $op => $result) {
|
||||
@@ -910,7 +957,7 @@ class NodeAccessTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to verify hook_node_access_records functionality.
|
||||
* Tests hook_node_access_records() functionality.
|
||||
*/
|
||||
class NodeAccessRecordsTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
@@ -929,7 +976,7 @@ class NodeAccessRecordsTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a node and test the creation of node access rules.
|
||||
* Creates a node and tests the creation of node access rules.
|
||||
*/
|
||||
function testNodeAccessRecords() {
|
||||
// Create an article node.
|
||||
@@ -1005,9 +1052,6 @@ class NodeAccessBaseTableTestCase extends DrupalWebTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable modules and create user with specific permissions.
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp('node_access_test');
|
||||
node_access_rebuild();
|
||||
@@ -1015,7 +1059,7 @@ class NodeAccessBaseTableTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the "private" node access.
|
||||
* Tests the "private" node access functionality.
|
||||
*
|
||||
* - Create 2 users with "access content" and "create article" permissions.
|
||||
* - Each user creates one private and one not private article.
|
||||
@@ -1152,7 +1196,7 @@ class NodeAccessBaseTableTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to check node save related functionality, including import-save
|
||||
* Tests node save related functionality, including import-save.
|
||||
*/
|
||||
class NodeSaveTestCase extends DrupalWebTestCase {
|
||||
|
||||
@@ -1173,7 +1217,8 @@ class NodeSaveTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Import test, to check if custom node ids are saved properly.
|
||||
* Checks whether custom node IDs are saved properly during an import operation.
|
||||
*
|
||||
* Workflow:
|
||||
* - first create a piece of content
|
||||
* - save the content
|
||||
@@ -1207,8 +1252,7 @@ class NodeSaveTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the "created" and "changed" timestamps are set correctly when
|
||||
* saving a new node or updating an existing node.
|
||||
* Verifies accuracy of the "created" and "changed" timestamp functionality.
|
||||
*/
|
||||
function testTimestamps() {
|
||||
// Use the default timestamps.
|
||||
@@ -1307,7 +1351,7 @@ class NodeTypeTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that node type functions (node_type_get_*) work correctly.
|
||||
* Ensures that node type functions (node_type_get_*) work correctly.
|
||||
*
|
||||
* Load available node types and validate the returned data.
|
||||
*/
|
||||
@@ -1326,7 +1370,7 @@ class NodeTypeTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating a content type programmatically and via a form.
|
||||
* Tests creating a content type programmatically and via a form.
|
||||
*/
|
||||
function testNodeTypeCreation() {
|
||||
// Create a content type programmaticaly.
|
||||
@@ -1356,7 +1400,7 @@ class NodeTypeTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test editing a node type using the UI.
|
||||
* Tests editing a node type using the UI.
|
||||
*/
|
||||
function testNodeTypeEditing() {
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types'));
|
||||
@@ -1409,7 +1453,7 @@ class NodeTypeTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that node_types_rebuild() correctly handles the 'disabled' flag.
|
||||
* Tests that node_types_rebuild() correctly handles the 'disabled' flag.
|
||||
*/
|
||||
function testNodeTypeStatus() {
|
||||
// Enable all core node modules, and all types should be active.
|
||||
@@ -1470,7 +1514,7 @@ class NodeTypePersistenceTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test node type customizations persist through disable and uninstall.
|
||||
* Tests that node type customizations persist through disable and uninstall.
|
||||
*/
|
||||
function testNodeTypeCustomizationPersistence() {
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer modules'));
|
||||
@@ -1534,7 +1578,7 @@ class NodeTypePersistenceTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild the node_access table.
|
||||
* Verifies the rebuild functionality for the node_access table.
|
||||
*/
|
||||
class NodeAccessRebuildTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
@@ -1553,6 +1597,9 @@ class NodeAccessRebuildTestCase extends DrupalWebTestCase {
|
||||
$this->web_user = $web_user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rebuilding the node access permissions table.
|
||||
*/
|
||||
function testNodeAccessRebuild() {
|
||||
$this->drupalGet('admin/reports/status');
|
||||
$this->clickLink(t('Rebuild permissions'));
|
||||
@@ -1562,7 +1609,7 @@ class NodeAccessRebuildTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test node administration page functionality.
|
||||
* Tests node administration page functionality.
|
||||
*/
|
||||
class NodeAdminTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
@@ -1630,6 +1677,7 @@ class NodeAdminTestCase extends DrupalWebTestCase {
|
||||
* Tests content overview with different user permissions.
|
||||
*
|
||||
* Taxonomy filters are tested separately.
|
||||
*
|
||||
* @see TaxonomyNodeFilterTestCase
|
||||
*/
|
||||
function testContentAdminPages() {
|
||||
@@ -1727,7 +1775,7 @@ class NodeAdminTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test node title.
|
||||
* Tests node title functionality.
|
||||
*/
|
||||
class NodeTitleTestCase extends DrupalWebTestCase {
|
||||
protected $admin_user;
|
||||
@@ -1747,7 +1795,7 @@ class NodeTitleTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create one node and test if the node title has the correct value.
|
||||
* Creates one node and tests if the node title has the correct value.
|
||||
*/
|
||||
function testNodeTitle() {
|
||||
// Create "Basic page" content with title.
|
||||
@@ -1790,7 +1838,7 @@ class NodeFeedTestCase extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that node_feed accepts and prints extra channel elements.
|
||||
* Ensures that node_feed() accepts and prints extra channel elements.
|
||||
*/
|
||||
function testNodeFeedExtraChannelElements() {
|
||||
ob_start();
|
||||
@@ -1822,7 +1870,7 @@ class NodeBlockFunctionalTest extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the recent comments block.
|
||||
* Tests the recent comments block.
|
||||
*/
|
||||
function testRecentNodeBlock() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
@@ -1935,7 +1983,7 @@ class NodeBlockFunctionalTest extends DrupalWebTestCase {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Test multistep node forms basic options.
|
||||
* Tests basic options of multi-step node forms.
|
||||
*/
|
||||
class MultiStepNodeFormBasicOptionsTest extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
@@ -1953,7 +2001,7 @@ class MultiStepNodeFormBasicOptionsTest extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the default values of basic options to ensure they persist.
|
||||
* Tests changing the default values of basic options to ensure they persist.
|
||||
*/
|
||||
function testMultiStepNodeFormBasicOptions() {
|
||||
$edit = array(
|
||||
@@ -1985,7 +2033,7 @@ class NodeBuildContent extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to ensure that a node's content array is rebuilt on every call to node_build_content().
|
||||
* Ensures that content array is rebuilt on every call to node_build_content().
|
||||
*/
|
||||
function testNodeRebuildContent() {
|
||||
$node = $this->drupalCreateNode();
|
||||
@@ -2065,10 +2113,10 @@ class NodeQueryAlter extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower-level test of 'node_access' query alter, for user with access.
|
||||
* Tests 'node_access' query alter, for user with access.
|
||||
*
|
||||
* Verifies that a non-standard table alias can be used, and that a
|
||||
* user with node access can view the nodes.
|
||||
* Verifies that a non-standard table alias can be used, and that a user with
|
||||
* node access can view the nodes.
|
||||
*/
|
||||
function testNodeQueryAlterLowLevelWithAccess() {
|
||||
// User with access should be able to view 4 nodes.
|
||||
@@ -2088,10 +2136,10 @@ class NodeQueryAlter extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower-level test of 'node_access' query alter, for user without access.
|
||||
* Tests 'node_access' query alter, for user without access.
|
||||
*
|
||||
* Verifies that a non-standard table alias can be used, and that a
|
||||
* user without node access cannot view the nodes.
|
||||
* Verifies that a non-standard table alias can be used, and that a user
|
||||
* without node access cannot view the nodes.
|
||||
*/
|
||||
function testNodeQueryAlterLowLevelNoAccess() {
|
||||
// User without access should be able to view 0 nodes.
|
||||
@@ -2111,10 +2159,10 @@ class NodeQueryAlter extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower-level test of 'node_access' query alter, for edit access.
|
||||
* Tests 'node_access' query alter, for edit access.
|
||||
*
|
||||
* Verifies that a non-standard table alias can be used, and that a
|
||||
* user with view-only node access cannot edit the nodes.
|
||||
* Verifies that a non-standard table alias can be used, and that a user with
|
||||
* view-only node access cannot edit the nodes.
|
||||
*/
|
||||
function testNodeQueryAlterLowLevelEditAccess() {
|
||||
// User with view-only access should not be able to edit nodes.
|
||||
@@ -2136,13 +2184,13 @@ class NodeQueryAlter extends DrupalWebTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower-level test of 'node_access' query alter override.
|
||||
* Tests 'node_access' query alter override.
|
||||
*
|
||||
* Verifies that node_access_view_all_nodes() is called from
|
||||
* node_query_node_access_alter(). We do this by checking that
|
||||
* a user which normally would not have view privileges is able
|
||||
* to view the nodes when we add a record to {node_access} paired
|
||||
* with a corresponding privilege in hook_node_grants().
|
||||
* node_query_node_access_alter(). We do this by checking that a user who
|
||||
* normally would not have view privileges is able to view the nodes when we
|
||||
* add a record to {node_access} paired with a corresponding privilege in
|
||||
* hook_node_grants().
|
||||
*/
|
||||
function testNodeQueryAlterOverride() {
|
||||
$record = array(
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -2,7 +2,9 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Dummy module implementing node access related hooks to test API interaction
|
||||
* A dummy module implementing node access related hooks for testing purposes.
|
||||
*
|
||||
* A dummy module implementing node access related hooks to test API interaction
|
||||
* with the Node module. This module restricts view permission to those with
|
||||
* a special 'node test view' permission.
|
||||
*/
|
||||
@@ -140,6 +142,8 @@ function node_access_test_page() {
|
||||
* database query is shown, and a list of the node IDs, for debugging purposes.
|
||||
* And if there is a query exception, the page says "Exception" and gives the
|
||||
* error.
|
||||
*
|
||||
* @see node_access_test_menu()
|
||||
*/
|
||||
function node_access_entity_test_page() {
|
||||
$output = '';
|
||||
|
@@ -5,8 +5,8 @@ version = VERSION
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-03-07
|
||||
version = "7.21"
|
||||
; Information added by drupal.org packaging script on 2013-04-03
|
||||
version = "7.22"
|
||||
project = "drupal"
|
||||
datestamp = "1362616996"
|
||||
datestamp = "1365027012"
|
||||
|
||||
|
@@ -2,8 +2,10 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Dummy module implementing node related hooks to test API interaction with
|
||||
* the Node module.
|
||||
* A dummy module for testing node related hooks.
|
||||
*
|
||||
* This is a dummy module that implements node related hooks to test API
|
||||
* interaction with the Node module.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user