Metal Toad: Drupal 8 Migrations, part 3: Migrating Taxonomies from Drupal 7

Planet Drupal - Thu, 2014/12/11 - 1:38am
Drupal 8 Migrations, part 3: Migrating Taxonomies from Drupal 7 December 10th, 2014 Keith Dechant

Drupal 8 provides a flexible, plugin-based architecture for migrating data into a site. In Part 2 of this series, we explored how to migrate users from a Drupal 7 site. We will now expand on this by migrating Taxonomy vocabularies and terms from a Drupal 7 site into Drupal 8.

This article continues our work from Part 2. The code examples pick up where that post left off. If you are trying this code out yourself, it is recommended to start building your custom migration module according to the examples in that post.

Migrating Taxonomy Vocabularies

The Migrate Drupal module (in Drupal 8 core) already contains a migration definition and source plugins to migrate taxonomy data from Drupal 6 to Drupal 8. All we need to do is to adapt the existing code to work with Drupal 7.

The migration definition:

Starting with the "Migrate Custom" module we created in Part 2, we now add the following configuration file.

modules/migrate_custom/config/install/migrate.migration.custom_taxonomy_vocabulary.yml

id: custom_taxonomy_vocabulary label: Drupal 7 taxonomy vocabularies migration_groups: - Drupal 7 source: plugin: custom_taxonomy_vocabulary process: vid: - plugin: machine_name source: machine_name - plugin: dedupe_entity entity_type: taxonomy_vocabulary field: vid length: 32 label: name name: name description: description hierarchy: hierarchy module: module weight: weight destination: plugin: entity:taxonomy_vocabulary

Here we have examples of a few plugins not seen in the previous post:

  • machine_name converts the string into a valid machine name.
  • dedupe_entity prevents machine name conflicts, which would cause imported data to overwrite existing data. For example, a machine name "foo" would be renamed to "foo_2" if name "foo" already existed.

The source plugin

To define the source of our vocabulary data, we create a new file modules/migrate_custom/src/Plugin/migrate/source/Vocabulary.php with the following contents:

<?php   /** * @file * Contains \Drupal\migrate_custom\Plugin\migrate\source\Vocabulary. */   namespace Drupal\migrate_custom\Plugin\migrate\source;   use Drupal\migrate\Row; use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;   /** * Drupal 7 vocabularies source from database. * * @MigrateSource( * id = "custom_taxonomy_vocabulary", * source_provider = "taxonomy" * ) */ class Vocabulary extends DrupalSqlBase {   /** * {@inheritdoc} */ public function query() { $query = $this->select('taxonomy_vocabulary', 'v') ->fields('v', array( 'vid', 'name', 'description', 'hierarchy', 'module', 'weight', 'machine_name' )); return $query; }   /** * {@inheritdoc} */ public function fields() { return array( 'vid' => $this->t('The vocabulary ID.'), 'name' => $this->t('The name of the vocabulary.'), 'description' => $this->t('The description of the vocabulary.'), 'help' => $this->t('Help text to display for the vocabulary.'), 'relations' => $this->t('Whether or not related terms are enabled within the vocabulary. (0 = disabled, 1 = enabled)'), 'hierarchy' => $this->t('The type of hierarchy allowed within the vocabulary. (0 = disabled, 1 = single, 2 = multiple)'), 'weight' => $this->t('The weight of the vocabulary in relation to other vocabularies.'), 'parents' => $this->t("The Drupal term IDs of the term's parents."), 'node_types' => $this->t('The names of the node types the vocabulary may be used with.'), ); }   /** * {@inheritdoc} */ public function getIds() { $ids['vid']['type'] = 'integer'; return $ids; }   }

Note: this file was adapted from the Drupal 6 version in Drupal 8 core. For the original file, see core/modules/migrate_drupal/src/Plugin/migrate/source/d6/Vocabulary.php

The structure of this file is similar to the User source plugin in the previous article. However, because all the data we need is stored in the `taxonomy_vocabulary` table in the source database, we do not need to define the prepareRow() method.

Migrating Taxonomy Terms

We can use a second migration definition to migrate our taxonomy terms. Create the following file:

modules/migrate_custom/config/install/migrate.migration.custom_taxonomy_term.yml

id: custom_taxonomy_term label: Drupal 7 taxonomy terms migration_groups: - Drupal 7 source: plugin: custom_taxonomy_term process: tid: tid vid: plugin: migration migration: custom_taxonomy_vocabulary source: vid name: name description: description weight: weight parent: - plugin: skip_process_on_empty source: parent - plugin: migration migration: custom_taxonomy_term changed: timestamp destination: plugin: entity:taxonomy_term migration_dependencies: required: - custom_taxonomy_vocabulary

In this migration, we make use of the migration process plugin for two of our properties, the vocabulary ID and the parent term ID. This preserves these references in case the referenced entity's ID or machine name changed during the import.

Some machine names and/or IDs will likely change when running your import. This is to be expected, especially because Drupal 8 stores taxonomy vocabularies in the 'config' table, where they are accessed by their machine names instead of by the numeric IDs used in Drupal 7. Fortunately for us, the Migrate module records a map of the old and new IDs in the database. We can then use the migration source plugin to easily look up the old ID or machine name.

The source plugin

To define the source of our term data, we create a new file modules/migrate_custom/src/Plugin/migrate/source/Term.php with the following contents:

<?php   /** * @file * Contains \Drupal\migrate_custom\Plugin\migrate\source\Term. */   namespace Drupal\migrate_custom\Plugin\migrate\source;   use Drupal\migrate\Row; use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;   /** * Drupal 7 taxonomy terms source from database. * * @todo Support term_relation, term_synonym table if possible. * * @MigrateSource( * id = "custom_taxonomy_term", * source_provider = "taxonomy" * ) */ class Term extends DrupalSqlBase {   /** * {@inheritdoc} */ public function query() { $query = $this->select('taxonomy_term_data', 'td') ->fields('td', array('tid', 'vid', 'name', 'description', 'weight', 'format')) ->distinct(); return $query; }   /** * {@inheritdoc} */ public function fields() { return array( 'tid' => $this->t('The term ID.'), 'vid' => $this->t('Existing term VID'), 'name' => $this->t('The name of the term.'), 'description' => $this->t('The term description.'), 'weight' => $this->t('Weight'), 'parent' => $this->t("The Drupal term IDs of the term's parents."), ); }   /** * {@inheritdoc} */ public function prepareRow(Row $row) { // Find parents for this row. $parents = $this->select('taxonomy_term_hierarchy', 'th') ->fields('th', array('parent', 'tid')) ->condition('tid', $row->getSourceProperty('tid')) ->execute() ->fetchCol(); $row->setSourceProperty('parent', $parents); return parent::prepareRow($row); }   /** * {@inheritdoc} */ public function getIds() { $ids['tid']['type'] = 'integer'; return $ids; }   } Reloading the configuration

Remember that migrations are configuration entities. To reload the configuration, we need to uninstall and reinstall our module. Here's a handy Drush command to do this:

drush pm-uninstall migrate_custom -y && drush en migrate_custom

Running the migration

We need to add some new lines to our manifest.yml file:

# A D7 user and taxonomy migration, with dependencies. - custom_user - custom_taxonomy_vocabulary - custom_taxonomy_term

As we did with our user migration, we now run the migration using Drush.

drush migrate-manifest manifest.yml --legacy-db-url=mysql://{dbuser}:{dbpass}@localhost/{dbname}

When including multiple migrations in a single manifest, be aware that drush migrate-manifest doesn't always run them in the order you specified. If, for example, your taxonomy migrations are being run before your user migration, and your taxonomy terms end up missing their UIDs, you might need to create two separate manifest files, to give yourself better control over the order.

Next post: Migrating Nodes from Drupal 7.

Categories:

PreviousNext: Automated style guides with KSS-node

Planet Drupal - Wed, 2014/12/10 - 10:47pm

During PreviousNext’s weekly developers meeting I recently gave a lightning talk about how to use kss-node to auto-generate a website style guide. If you’ve even tangentially followed front-end development, you’ll find that this is yet-another blog post describing “project A implementing technology B with hip, new language/framework C.”

But kss-node is really cool and useful, especially if you understand how it fits into the larger picture of the new web development process. Fortunately, my previous post provides that big picture, so if you’d like to understand how Agile is turning web development inside-out and how style-guide-driven development is the new website development workflow, please go read that first. Then head back here for the screencast to get you started with kss-node.

Categories:

Blue Drop Awards: We're Looking for Guest Bloggers!

Planet Drupal - Wed, 2014/12/10 - 9:20pm

Do you have a unique way of using Drupal? Can you offer helpful tips about Drupal or even have creative solutions to those nagging problems associated with Drupal? Then we would like to offer you a free platform on which to share your voice.

We are looking for people who would like to be featured on the Blue Drop Awards' website discussing the issues and topics surrounding the Drupal platform.

Are you more into doing than telling? Create a video or podcast that offers helpful tips or information relevant to the Drupal community.

Not into creating content but still want to help? We still need volunteers to help manage the blog or newsletters.

If you're interested, please contact erik@bluedropawards.org.

Categories:

Acquia: A Symfony Shop Embraces Drupal 8 & Gets Down to Business

Planet Drupal - Wed, 2014/12/10 - 6:42pm
Language Undefined

Chris Jolly, CTO Ontraq Europe, and his company have a strong technical background, going back to "old school" (pre-internet) IT. Their main focus until now has been eCommerce, Symfony, and solving hard problems like legacy-system integrations. Now, thanks to its use of Symfony framework components, they've started using Drupal 8 as their content management technology of choice! Chris and I talked at DrupalCon Amsterdam about getting there and what they're up to now.

Categories:

Drupal Watchdog: Migrate Overview

Planet Drupal - Wed, 2014/12/10 - 6:16pm
Article


Two years into the development of Drupal 8, Dries Buytaert announced that Drupal 8.0 might ship without an upgrade path.

This unorthodox decision was made to support substantial improvements in Drupal’s major version upgrade process by introducing a robust new sub-system based on the popular contributed modules Migrate and Migrate D2D. The sub-system includes the Migrate module, which provides the basic framework and API, and the Migrate Drupal module, which provides the upgrade paths and framework to enable other Drupal-to-Drupal use cases in contrib.

The substantial wins with this new approach include the ability to move directly from Drupal 6 to Drupal 8 – as well as the possibility of providing more fine-grained control over the process – and the option of continuous content migration.

The migration team is working extraordinarily hard to be ready by the time that D8 is ready for beta. As of March 31, Migrate API has been committed to core. The last blocking issues for Migrate Drupal were resolved during the DevDays sprint, and the team will begin submitting patches for the D6 to D8 migration path to the core queue any day now.

A Drupal 6 to Drupal 8 upgrade without Migrate

Without the new API, an abbreviated move from Drupal 6 to Drupal 8 would have looked something like:

  1. Backup your database
  2. Update core and contrib to the latest version of 6
  3. Disable all contributed modules and switch to the core theme
  4. Delete the D6 code and replace it with D7 core code
  5. Run update.php
  6. Download the D7 contributed modules
  7. Enable the contrib modules
  8. Run update.php
  9. Repeat to upgrade from D7 to D8

For Drush users, the 'drush up' command would vastly simplify this, but two full upgrades — from 6 to 7, then 7 to 8 — would still have been required, inevitably losing data in each step.

Categories:

Annertech: Scalable & Sustainable Media Management for Drupal Websites

Planet Drupal - Wed, 2014/12/10 - 6:08pm
Scalable & Sustainable Media Management for Drupal Websites

*/ /*-->*/

Categories:

SitePoint PHP Drupal: 7 CRM Options Compatible with Drupal

Planet Drupal - Wed, 2014/12/10 - 6:00pm

I love Drupal and end up undertaking most of my programming projects with it. I have been using it for so long that I find it far easier to push out projects with Drupal than with anything else, despite it’s infamous learning curve.

Whether you want to call Drupal a CMS (Content Management System), a CMF (Content Management Framework) or a CMSomething, the ‘C’ always stands for Content. Content is where Drupal shines and is what it’s designed for.

When an organisation is at a stage and mindset that they also want to manage their contacts and interactions effectively they will often need tools designed specifically for that function. These are generally referred to as a CRM, which stands for Client Relationship Manager or Constituent Relationship Manager, depending on the sector (For-Profit or Not-for-Profit respectively). CRMs are big business, with many free and paid options available, all with their own advantages and disadvantages.

Often these interactions that people have with your organisation will include things such as registering for an event, making a donation, becoming a member, expressing interest in a product or receiving a newsletter. This all sounds quite simple, but often representing a business rule in the digital realm is very difficult as everyone thinks ‘their way’ is ‘the only way’ and that surely every off-the-shelf system should represent them out of the box.

Continue reading %7 CRM Options Compatible with Drupal%

Categories:

clemens-tolboom pushed to 8.x at build2be/drupal-rest-test

On github - Wed, 2014/12/10 - 2:43pm
Dec 10, 2014 clemens-tolboom pushed to 8.x at build2be/drupal-rest-test
  • b65216b Fixed undefined index notice.

Code Drop: Drupal Security Tips for Developers

Planet Drupal - Wed, 2014/12/10 - 5:30am

I’ve recently been reviewing a few security related patches and it soon became apparent that many developers make the same mistakes over and over in regards to best practices for security in Drupal. So below, a very short post on the common mistakes and solutions.

Correct usage of t()

Use the right placeholder for t(). You should be using "% and @" which are both escaped to protect against Cross Site Scripting vulnerabilities. Whenever you use "!" as a placeholder, double check the content has already been escaped.

Escaping Output in #markup

If you’re providing a custom field, widget and formatter you need to make sure that any content coming from the admin is correctly escaped. For example, you’re implementing hook_field_formatter_view() and doing something like:

Categories:

Drupal governance announcements: DrupalSouth - Early Bird tix almost sold out!

Planet Drupal - Wed, 2014/12/10 - 2:26am

There are only a few early bird tickets left. So if you want one, grab it now.

https://melbourne2015.drupal.org.au/conference/tickets

Categories:

DrupalSouth - Early Bird tix almost sold out!

Documentation Team - Wed, 2014/12/10 - 2:26am

There are only a few early bird tickets left. So if you want one, grab it now.

https://melbourne2015.drupal.org.au/conference/tickets

Pixelite: How to add subtabs under the User Edit tab in Drupal

Planet Drupal - Wed, 2014/12/10 - 1:00am
tl;dr;

To get your tabs to appear on the user edit page use hook_user_categories() and hook_menu_alter().

The detail

Getting submenu items to appear within the user edit area of Drupal has not always worked as I would expect from reading the documentation around hook_menu(). As it happens the user module provides hooks to make this quite simple.

hook_user_categories() allows you to return a subset of the parameters you’d expect to see in hook_menu().

In this example we would have a new set of tabs added to the User Edit page. The first is Account and is now presented because we have more than one tab here now. The second is Report Settings and it would have a URL like user/12345/edit/report_settings where report_settings is taken from the name parameter.

<?php /** * Implements hook_user_categories(). */ function my_module_user_categories() { return array( array( 'name' => 'report_settings', 'title' => t('Report settings'), 'weight' => 1, 'access callback' => 'user_edit_access', 'access arguments' => array(1), ) ); } ?>

At this point we have a new menu item presented as a tab on the user edit page and clicking it takes us to a blank form with a submit button. I think this is due to the way menu items can inherit behaviour from parent menu items. We’ll be wanting to overload that behaviour though and present our own form. This can be done through hook_menu_alter().

Checking the keys of the array passed to hook_menu_alter() we should find that we have a new one called user/%user_category/edit/report_settings. We can edit this one to point it at our preferred form built using the Form API as usual.

<?php /** * Implements hook_menu_alter(). */ function my_module_menu_alter(&$callbacks) { $callbacks['user/%user_category/edit/report_settings']['page arguments'] = array('my_module_user_report_settings', 1); // We need to set the file path as it defaults to the user module. $callbacks['user/%user_category/edit/report_settings']['file path'] = drupal_get_path('module', 'my_module'); $callbacks['user/%user_category/edit/report_settings']['file'] = 'my_module.user.inc'; } ?> Gotchas
  • You will want to be clearing your menu cache a lot while getting this working. Every edit will require a drush cc menu.
  • Ensure you have set the file path in the hook_menu_alter() if you have your have your page callback or form function for drupal_get_form() in a separate file.
Comments

If you have found that this post has been helpful ping me in the comments, on twitter (@Unifex) or on D.o at Gold.

Categories:

Chapter Three: Principles of Configuration Management - Part One

Planet Drupal - Tue, 2014/12/09 - 8:16pm

This is the first in a series of posts about Drupal 8's configuration management system. This system is one of its most eagerly anticipated features, according to a recent survey. The Configuration Management Initiative (CMI) was the first Drupal 8 initiative to be announced in 2011, and we've learned a lot during thousands of hours of work on the initiative since then. These posts will share what we've learned and provide background on the why and how.



Categories:

Open Source Training: Filter Drupal Content Based on File Type

Planet Drupal - Tue, 2014/12/09 - 7:11pm

One of our members asked an interesting question about Views.

They had a file field on their user profiles. In that field, the user could upload an image, an audio file, or link to a YouTube video. So far, so good. However, in Views, they only wanted to show that field if it contained a video.

Here's the solution to that problem. We're going to show you how to filter Drupal content based on the type of file that's attached to it.

Categories:

Drupal Watchdog: Test Now! - Travis Integration for your Drupal Modules

Planet Drupal - Tue, 2014/12/09 - 6:46pm

Travis-CI is a free-for-OSS continuous integration server, which has become very popular in the PHP world. Drush, Symfony, and dreditor all use it for frequently testing their code base and pull requests for regressions and ensuring new functionality has the needed test coverage.

Compared to the current Drupal testbot, Travis-CI allows testing of not only simpletest on PHP 5.3 (for Drupal 7 projects), but of most everything that you can install on a Debian system, e.g. QUnit for JavaScript, Behat, PHPUnit, but also Ruby based projects, Bash projects, Go projects, etc.

You can also test various scenarios in a matrix like setup, e.g. different PHP versions to ensure your code runs on both PHP 5.3 and 5.4 or with different versions of a dependent library.

This flexibility comes with a price however, because you need to setup the whole environment yourself. The selected PHP version (with xdebug) and composer are pre-installed, but that's it. The Drupal base installation, the running of the tests, the parsing of the test output, and ensuring dependencies are there is all your own responsibility.

And because of that there are many different .travis.yml files floating around the net for various scenarios of setting up this or that, but in the end everyone re-invents the wheel. Until now…

As Easy as it Gets

I am proud to announce the drupal_ti project, which allows any module on drupal.org to easily leverage travis-ci.org for testing:

  • PHPUnit
  • SimpleTest
  • Behat

The process (which I will show in more detail below) is as simple as copying a generic .travis.yml.dist file as .travis.yml to your modules root, push your repository to Github, activate the repository at travis-ci.org and you are done.

Oh, and while you are at it, if you add a .coveralls.yml file, then code coverage is automatically reported to coveralls.io, too (for PHPUnit).

All the hard work of installing drupal, running a web server, setting up Selenium, etc. is done by drupal_ti.

So you don't have to copy some .travis.yml you found on the net and spend hours debugging little edge cases (HHVM and sendmail, how to parse the simpletest output, etc.), but can depend on a proven and self-tested code base.

Features
  • Drupal 8 ready: drupal_ti supports both Drupal 7 and 8 modules. Use DRUPAL_TI_ENVIRONMENT="drupal-8" for your Drupal 8 modules.
  • Tested: drupal_ti tests its own code base for both Drupal 7 and Drupal 8 modules.
  • Modular architecture: drupal_ti has so called 'runners' and you can combine either e.g. "phpunit simpletest" or run them as separate workers by specifying a matrix.
  • Environment aware: drupal_ti has a file for each environment, which makes the code generic for both Drupal 7 and 8.
  • Examples provided: drupal_ti provides easy examples of the needed files in tests/drupal-{7,8}/drupal_ti_test. So you can get started easily!
  • Extensible: By specifying DRUPAL_TI_SCRIPT_DIR_BEFORE or DRUPAL_TI_SCRIPT_DIR_AFTER you can easily create your own runners and environment includes that run before or after the main runners. This could even come from composer.
  • Usable for non-travis CI: Because drupal-ti is just a command and because .travis.yml just has some environment vars, you can just copy the main declarations to some environment.sh file, set the TRAVIS_BUILD_DIR and use it locally, too.
An Example Conversion

My module registry_autoload uses simpletest on drupal.org to test its features. Now I want to test some advanced trait support, which needs PHP 5.4, so travis-ci.org is an option to do so.

Step 1 - Create the GitHub Repository and Push Your Code
  1. Sign in to github.com
  2. Click: + > New repository, enter: registry_autoload
  3. Click: Create repository

Copy the commands displayed by Github to push your code to GitHub. I like to use drupal.org as my upstream and GitHub as my origin remote:

$ git clone --branch 7.x-1.x Fabianx@git.drupal.org:project/registry_autoload.git $ cd registry_autoload $ git remote rename origin upstream $ git remote add origin git@github.com:LionsAd/registry_autoload.git $ git push -u origin 7.x-1.x Step 2 - Activate Travis-ci.org

Now head over to travis-ci.org:

  1. Choose "Sign in with GitHub" and follow instructions
  2. Click on your name at the top right, "Fabian Franz" for me
  3. Click: "Sync now" if you don't see the repository, yet
  4. Simply switch the toggle to "ON" for the project
  5. Click on the repository settings icon (the "tools icon")
  6. Toggle "Build only if .travis.yml is present"
  7. Click on "Build history"
  8. Leave the browser window open
Step 3 - Add drupal_ti .travis.yml

Now checkout a new branch, and add the .travis.yml file:

$ git checkout -b travis-integration $ curl https://raw.githubusercontent.com/LionsAd/drupal_ti/master/.travis.yml.dist -O $ mv .travis.yml.dist .travis.yml

Then, customize the following parts of the file:

# Configuration vars. - DRUPAL_TI_MODULE_NAME="registry_autoload" - DRUPAL_TI_SIMPLETEST_GROUP="Registry"

And:

matrix: # [[[ SELECT ANY OR MORE OPTIONS ]]] - DRUPAL_TI_RUNNERS="simpletest"

The simpletest group is returned from getInfo() in Drupal 7, but an annotation @group x in Drupal 8. Despite the name of the variable, you could also put in a class like RegistryAutoloadTestCase. Basically anything that SimpleTest accepts on the command line as last argument. The clue is that this variable accepts spaces e.g. "DrupalTi Test", which is else very difficult to achieve when passing variables around.

Now add the file and push to GitHub:

$ git add .travis.yml $ git commit -m "Added travis integration" $ git push origin travis-integration Step 4 - Watch the Test Run

Now head back over to your browser window and magically there will be a new build, click on it and you will see a matrix like structure, here shown for build #2:

Click on PHP 5.4 and click the little button on the far right with "follow", to follow the output.

After a while the build is finished and all tests passed:

Congratulations, your project is now tested on travis-ci.org!

Now merge, the branch into your mainline and whenever you want to test a change on travis-ci.org just push a branch or make a pull request:

$ git checkout 7.x-1.x $ git merge travis-integration $ git push origin 7.x-1.x # Also push the changes back to drupal.org $ git push upstream 7.x-1.x

The easiest way to work with this kind of integration is to push all patches to origin first and once satisfied, push to upstream. That way GitHub and drupal.org are always in sync.

To be Continued…

In the next part of this series, I will explore how you can get started with unit testing locally and on travis-ci.org (using drupal_ti) and afterwards we will take a look at some easy behat setup.

If you are curious and want to start now, take a look at the run-* scripts in:

Enjoy and please leave me feedback either in the Drupal issue queue or on the GitHub project page.

About the Author

Fabian Franz is a Senior Performance Engineer and Technical Lead at Tag1
Consulting. He is author of the registry_autoload, service_container and render_cache modules for Drupal 7 and a contributor to Drupal 8 Core in the form of reviews, patches, and co-leader of the Twig initiative.

Tags:  Testing Contributed modules Third-party tools Images: 
Categories:

Aten Design Group: Debugging New to You Drupal Blocks

Planet Drupal - Tue, 2014/12/09 - 5:20pm

Let’s say a friend (or a new client) asks you to make a small change to their Drupal website. You’ve never seen this site before and the original developer(s) are long gone. Of course the text is in some obscure block. Sometimes finding where to make the requested change is easy. Sometimes it’s not. I’m going to go through some debugging tips for such a case.

The first thing you should do is inspect that part of the page with your browser’s dev tools (e.g. Firefox, Chrome). Often IDs and class names will help identify the block.

Here’s an example of the DOM of a view block from the nodequeue module.

<div id="block-views-nodequeue-2-block" class="block block-views contextual-links-region block--marquee">

The ID "block-views-nodequeue-2-block" means this is a views block. "nodequeue-2" is the view machine name, and "block" is the name of the specific display in that view. You can browse the list of views at /admin/structure/views, or in this case, go directly to /admin/structure/views/view/nodequeue_2/edit/block. The path to edit a view in Drupal 7 is always at /admin/structure/views/view/[VIEW NAME]/edit/[DISPLAY NAME]. If contextual links are on, it may be even quicker to access the edit page from the options available. Look for a gear icon in the upper right corner of the section.

Here’s a block defined in code:

<div id="block-cei-custom-blocks-cei-unicef-timeline" class="block block-cei-custom-blocks contextual-links-region">

In this case in cei_custom_blocks_block_info() defines a block delta: $blocks['cei_unicef_timeline'] The code that defines this block’s output will either be in cei_custom_blocks_block_view() or that function will call another.

In one particular case I didn’t have a lot to go on. There was very little in the DOM. This members page consisted of user images, name, and title. The client requested one additional field be included for each user on the members page. It wasn’t a view or anything else easily identifiable. The output was in system block 0 which doesn't give me anything to go on. One particularly unique class name was block-totem-common-embed-type-search-0 (this was the totem install profile) but a search of the code turned up nothing. That’s because the code that built these blocks was highly abstracted. Reviewing that code didn’t reveal where I could add the field either. Finally I searched on another class name. I didn’t find exactly where the class name was inserted, but it happened to match a template file that was in one of the submodule's ‘inc’ directories.

<div<?php print $attributes; ?>> <?php print $user_profile['images']['user_thumb']; ?> <?php print render($title_prefix); ?> <h3><?php print render($user_profile['name']); ?></h3> <?php print render($title_suffix); ?>   <div class="clearfix"></div> </div>

Once I found that, making the needed modification was simple.

To help identify a block, you can also look at what is placing the block on the page. Some ways this can be done include the blocks UI, Context module, Panels, print directly in code, and template files. If a lot of blocks are placed using the blocks UI, this page can get unwieldy. It’s worth searching the codebase for any distinct phrases. A quick search in the database can also be useful.

Blocks saved in the database are in the blocks and blocks_custom tables. One way to find such a block in the database uses a query for some matching text:

SELECT * FROM block_custom WHERE body LIKE "%participate in discussions%"\G

The query matched the following entry:

*************************** 1. row *************************** bid: 3 body: <p><strong>A message from the GEC team</strong></p> <p>During the recent GEC baseline sharing events, one of the key messages that came through loud and clear from you was the value of meeting other projects and exchanging knowledge, sharing challenges, solutions, experiences and advice. We began to see the GEC community take root, and to continue this momentum we are launching the GEC forum &ndash; a place for the GEC Community of Practice to develop and grow. This will be the place for you share your expertise, participate in discussions, and interact with other projects that form the community of the Girls&rsquo; Education Challenge. <a href="http://www.educationinnovations.org/forums/introducing-girls%E2%80%99-education-challenge-forum">Read more...</a></p> <p>&nbsp;</p>   info: GEC welcome message (deliberately not in code) format: full_html

Such a block can be edited at /admin/structure/block/manage/block/3/configure. The path to edit a block is always at /admin/structure/block/manage/[Block ID]/configure.

Hopefully these tips will be useful the next time a completely unknown website is dropped in your lap.

Categories:

Acquia: PHP: Under the Hood, Running the Web

Planet Drupal - Tue, 2014/12/09 - 5:13pm

Most non-technical people out on the Web haven't heard of PHP before. They might not have even heard of many of the products that were built with this technology like Drupal, Magento, or WordPress. And together with other products built with PHP, these run about 83% of all internet web applications. The technology of PHP is very important to an enormous number of businesses, governments, and organisations around the world, so even though people might not be familiar with the language itself, there’s a very good chance they’ve used it online today.

Categories:

Damien McKenna: Need help with (final?) release of Panels for Drupal 6

Planet Drupal - Tue, 2014/12/09 - 4:11am

After more than two and a half years since the last release, we need some help putting together what might be the final release of Panels for Drupal 6:

Tags: 
Categories:

James Oakley: Installing the latest version of Drush

Planet Drupal - Tue, 2014/12/09 - 12:21am

In case you missed it, Drush has evolved recently.

Quick primer for beginners follows. (Although, if you haven't heard of Drush, the chances are this post was not written with you in mind. I blog about many subjects, and there aren't many readers who are interested in all of them!)

Drush stands for Drupal shell - it's a very powerful shell environment for managing Drupal sites using the command-line shell. … Read more about Installing the latest version of Drush

Blog Category: Drupal Planet
Categories:

Visitors Voice: Milestone reached regarding Search API for Drupal 8

Planet Drupal - Mon, 2014/12/08 - 8:55pm
For all of us who care about site search for Drupal, the maintainer Thomas Seidl has written a report about the current status of Search API for Drupal 8. The search crew’s vision is not only to port Search API to Drupal 8, but also to remove all known limitations, making site search for Drupal […]
Categories: