We partnered with the City of Cambridge to redesign Find It Cambridge, an online opportunity locator serving city residents, in a unique way— designing and developing out in the open, and releasing the software under an open-source license so that other cities can spin up their own Find It platforms.
Cambridge, like many cities, has a wide array of programs and events happening to serve residents. However, it can be difficult for people to find and compare the many offerings out there. The city website has a calendar of events and list of departments. These are limited to government-run programs, though. There are myriad nonprofits and community groups that run programs and events that go unlisted. Social media platforms like Facebook have filled the gap in some areas, but promotion of these opportunities relies in many ways on people's social connections— leaving those most in need of services out of the loop. Find It Cambridge solves this problem by aggregating the many different opportunities happening into one website.
The upgrade and migration from Drupal 7 to Drupal 8 (ready for Drupal 9!) afforded Cambridge and Agaric the opportunity to make the directory of organizations, events, and programs better for families and their children and all involved, grounded in research and testing.
The value of a directory are the listings within it and it's truly a community effort to assemble enough accurate and up-to-date resources in a single place, for it to be useful. For Cambridge, the service providers that work at government agencies and nonprofits are the lifeblood of the directory. Without them, there would be no Find It Cambridge.
The challenge then, is building a system that is easy enough for people (many already pressed for time) to take the time to enter their information into, while structuring the data to be easily searched and filtered on.
Through user research, we mapped the information architecture to the mental models that service providers hold for their events and programs.
Most service providers thought of their events in terms of what the event is about, how to contact the organizers, who it is for, when it is happening, where it is happening, how much it costs, and if there is any sort of registration required. So we organized fields into working tabs to match: About, Contact, For whom, When, Where, Cost, and Signup.
Even with fields grouped by tabs, the form can take some time to complete. That's why we introduced autosave and soft save features. When working on a form, the site automatically saves the current draft every few seconds. Service providers can also save a draft to return to later. Fields that are required for publishing, are optional for a draft.
Service providers have many responsibilities to juggle. It's important that they can start creating an event or program, save it and return to it later before publishing it.
Drupal has powerful workflow states, which we've put to use to help service providers clearly know the status of their content.
A service provider can either save their content as a draft or publish it immediately. If saved as a draft, a banner appears on the page clearly indicating that the event or program is not yet published.
Authors can also create a draft alongside a published version. This allows new versions to be worked on, while maintaining the current page for site visitors.
There are particular ways to write and format content on events and programs to make the most of Find It's features. We provide help text along the way to clue providers in on the best ways to write their content. We also include a character count so providers know if they're staying within the recommended limits for certain text fields.
Certain fields have many options. In some cases the majority of them apply. For example, many educational events are for all ages up to 18. In that scenario, having a "Select All" option speeds up the data entry process. The Selectize JavaScript library adds elegant toggle and check all options to multivalue fields. We created the CheckboxesJS Drupal project so that other Drupal sites can easily incorporate these features on fields of their choosing.
Some fields on Event and Programs only need to show under certain conditions. For example, if an event doesn't require registration, then there's no need to worry service providers with a registration link field. Using conditional logic keeps forms simple and streamlined.
There was a lot of discussion on whether to support repeating rules or instead allow multiple dates. We decided on multiple dates as experience has shown that even repeating events oftentimes have exceptions (and because the events we import from Cambridge Public Libraries are a list of arbitrary dates rather than a recurring rule, and somehow no one in computer science has created a library to produce a best-effort recurring rule from a list of dates).
Find It search is powered by Apache Solr, a popular open-source enterprise search platform. We use its numerous features to make the search results as relevant as possible for site visitors. It's an ongoing process of tweaks; here are some of the things we've done so far.
On content with lots of data like the events and programs of Find It, certain fields carry more importance than others. The title of an event, for example, is one of the most important. The transporation notes, on the other hand, carries less significance in search queries. When someone types the keyword "music lesson", an event with music lesson in the title or summary shows up before a program for English lessons.
When someone searches "childcare" but a program uses "child care", the search engine should know these are equivalent. The same is true for "STEM" and "science education."
Find It supports synonyms. The site manager can define synonyms so that when site visitors search for a certain term, results with matching synonyms show up as well.
We used the results of our user research to show the critical information people need to pin point the right opportunities: title, neighborhood, and a short summary.
Filters help users narrow a search query down to specific criteria. In our testing, we found that age and neighborhood were most important, especially for low-income caregivers. For those of us that rely on public transportation, events and programs need to be nearby. We placed these filters accordingly towards the top of the page.
Naming conventions in Cambridge are unique, which is true for other cities too. Residents might not know the official name of their neighborhood or live at the border between two. We've included a labeled, clickable map to help users choose the right neighborhood. We built this so that other Find It platforms can upload their own SVG map to show their neighborhood.
Find It comes out of the box with four different types of opportunities: Events, Places, Organizations and Programs.
The organization serves as the foundation for opportunities posted on a Find It page. Every event and program posted to Find It, belongs to an organization. This helps an organization's page serve as a mini-website. When an event or program is published, it automatically shows up on its organization page.
Organizations can also have "child" organizations, which is helpful for larger groups that might have distinct sub-committees or departments that have sub-departments.
An event is an opportunity with a clear start and end date. When an event is published it shows up on the Homepage, Events page, Search page and on the organization's page.
Visitors can sort opportunities by start date to find upcoming events.
A program is similar to an event. In fact, most fields are shared between the two. A program though, implies more longevity and commitment than an event. Rather than requiring a specific date or dates, a program can simply be "ongoing." There is the option to include specific dates though.

In the first version of Find It Cambridge, a new opportunity surfaced that didn't quite fit into the event, program, or organization categories. Parks, neighborhood pools, and other destinations were a good fit for Find It's library of opportunities. They have open hours, but many of the event fields were irrelevant. The same went for Programs. In fact, sometimes these places have events or programs happening at them.
These are community-minded destinations people can go to. In other words, places.

Find It is helping Cambridge residents connect with activities and services to improve their lives. We would love to help do the same for other cities, counties, and other communities. The platform is open-source and flexible so that communities can customize it to their needs.
Whether you are city IT staff, a developer that works with cities, or are a resident that could use a Find It in your community, we'd love to talk.
Cities and towns everywhere offer children and adults myriad programs, events, and places for enriching experiences. These activities and services come from various levels and agencies of government—operating schools, libraries, parks, and more—as well as from not-for-profit organizations, civic groups, private educational institutions, and others. However, any given person—say a single parent with three kids—has no time-efficient way of knowing about all of these opportunities.
Cambridge, Massachusetts, took on this problem. No software or website can solve this by itself, but an easily searchable directory with built-in reminders and tools to help keep it up to date makes finding all available opportunities achievable. Developed based on hundreds of hours of research and interviews led by the Cambridge Kids' Council, Find It Cambridge makes it easier for parents and other care-giving adults to find the amazing array of activities, services, and resources that are available for children, youth, and families in Cambridge.
This year, Agaric gave the site a major upgrade and made Find It capabilities freely available for other cities and towns.
If this is of interest to you for your city or region, especially if you work in an afterschool network or are otherwise in the thick of bringing opportunities to children, please get in touch by e-mail, at 1 508 283 3557, or through our contact form!
Sign up below to get (very) occasional updates.
We are proud that Agaric joined the Tech Co-Op Network as an early member. This network of North American tech worker co-ops seeks to encourage collaboration among its members and education of potential new co-op founders and the general public about worker cooperatives: businesses owned and controlled by the people who work in them.
Read all about it!
Martin Owens is a committed programmer that lives for making great code that helps people. He fully supports the Free Software philosophy and likes to publish online as much of his own code as possible. Martin hopes to work for a company where his talents can be used to make great products for users, where he can be stretched and encouraged to learn new things as well as being able to commit to the wider open source landscape where possible.

Saturday, February 2nd, 1:00 - 4 p.m.
Encuentro5 Community Space
9A Hamilton Place, Boston, MA 02108
encuentro5 (e5), DigBoston, UjimaBoston and Agaric Cooperative invite your participation in an important discussion on Technology and Revolution. The event is part of a series of discussions being held nationwide and coordinated by May First/People Link and the Center for Media Justice—leading up to an international convergence in Mexico City later this year.
Notable participants include: Alfredo Lopez, author, Puerto Rican independista, and co-director of May First/People Link; and Rajesh Kasturirangan, mathematician, cognitive scientist, and professor at the National Institute of Advanced Studies in India.
Over the last few decades, technological advances have not only radically changed methods of human communication but have also started to change humanity itself in ways that grassroots organizations on the political left have been slow to address. To the extent we have done so, it has been mostly to advocate for disenfranchised communities’ access to computers and broadband internet service.
But we have largely failed to grapple with issues beyond the rise of the internet and huge corporate social media platforms like Facebook and Twitter. And we’ve barely scratched the surface of those key changes, let alone put much thought into analyzing the effects of newer technologies like robotics, artificial intelligence, big data, and genetic engineering on our communities. This is all the more alarming because rapid technological has aggravated the inequalities about which the left has traditionally cared.
Nonetheless, social-change movements continuously emerge, often in unexpected spaces, but especially in artistic and youth spaces or from insurgent social movements of the oppressed and exploited. They create campaigns to challenge potentially negative technological developments and propose more helpful community-centered technologies in their place.
In the interest of promoting these movements and their just agendas, this gathering will convene organizers for an afternoon of sharing and thinking together. We will be sharing information and analyses about these topics in short, plain-spoken, manageable conversations. Our thinking together will be strategic, asking and answering straightforward questions:
More information at https://techandrev.org
Sign up if you want to know when Mauricio and Agaric give a migration training:
Today we complete the user migration example. In the previous post, we covered how to migrate email, timezone, username, password, and status. This time, we cover creation date, roles, and profile pictures. The source, destination, and dependencies configurations were explained already. Therefore, we are jumping straight to the process transformations in this entry.

You can get the full code example at https://github.com/dinarcon/ud_migrations The module to enable is UD users whose machine name is ud_migrations_users. The two migrations to execute are udm_user_pictures and udm_users. Notice that both migrations belong to the same module. Refer to this article to learn where the module should be placed.
The example assumes Drupal was installed using the standard installation profile. Particularly, we depend on a Picture (user_picture) image field attached to the user entity. The word in parenthesis represents the machine name of the image field.
The explanation below is only for the user migration. It depends on a file migration to get the profile pictures. One motivation to have two migrations is for the images to be deleted if the file migration is rolled back. Note that other techniques exist for migrating images without having to create a separate migration. We have covered two of them in the articles about subfields and constants and pseudofields.
Have a look at the previous post for details on the source values. For reference, the user creation time is provided by the member_since column, and one of the values is April 4, 2014. The following snippet shows how the various user date related properties are set:
created:
plugin: format_date
source: member_since
from_format: 'F j, Y'
to_format: 'U'
changed: '@created'
access: '@created'
login: '@created'The created, entity property stores a UNIX timestamp of when the user was added to Drupal. The value itself is an integer number representing the number of seconds since the epoch. For example, 280299600 represents Sun, 19 Nov 1978 05:00:00 GMT. Kudos to the readers who knew this is Drupal's default expire HTTP header. Bonus points if you knew it was chosen in honor of someone’s birthdate. ;-)
Back to the migration, you need to transform the provided date from Month day, year format to a UNIX timestamp. To do this, you use the format_date plugin. The from_format is set to F j, Y which means your source date consists of:
April.4.2014If the value of from_format does not make sense, you are not alone. It is actually assembled from format characters of the date PHP function. When you need to specify the from and to formats, you basically need to look at the documentation and assemble a string that matches the desired date format. You need to pay close attention because upper and lowercase letters represent different things like Y and y for the year with four-digits versus two-digits respectively. Some date components have subtle variations like d and j for the day with or without leading zeros respectively. Also, take into account white spaces and date component separators. To finish the plugin configuration, you need to set the to_format configuration to something that produces a UNIX timestamp. If you look again at the documentation, you will see that U does the job.
The changed, access, and login entity properties are also dates in UNIX timestamp format. changed indicates when the user account was last updated. access indicates when the user last accessed the site. login indicated when the user last logged in. For brevity, the same value assigned to created is also assigned to these three entity properties. The at sign (@) means copy the value of a previous mapping in the process pipeline. If needed, each property can be set to a different value or left unassigned. None is actually required.
For reference, the roles are provided by the user_roles column, and one of the values is forum moderator, forum admin. It is a comma separated list of roles from the legacy system which need to be mapped to Drupal roles. It is possible that the user_roles column is not provided at all in the source. The following snippet shows how the roles are set:
roles:
- plugin: skip_on_empty
method: process
source: user_roles
- plugin: explode
delimiter: ','
- plugin: callback
callable: trim
- plugin: static_map
map:
'forum admin': administrator
'webmaster': administrator
default_value: nullFirst, the skip_on_empty plugin is used to skip the processing of the roles if the source column is missing. Then, the explode plugin is used to break the list into an array of strings representing the roles. Next, the callback plugin invokes the trim PHP function to remove any leading or trailing whitespace from the role names. Finally, the static_map plugin is used to manually map values from the legacy system to Drupal roles. All of these plugins have been explained previously. Refer to other articles in the series or the plugin documentation for details on how to use and configure them.
There are some things that are worth mentioning about migrating roles using this particular process pipeline. If the comma separated list includes spaces before or after the role name, you need to trim the value because the static map will perform an equality check. Having extraneous space characters will produce a mismatch.
Also, you do not need to map the anonymous or authenticated roles. Drupal users are assumed to be authenticated and cannot be anonymous. Any other role needs to be mapped manually to its machine name. You can find the machine name of any role in its edit page. In the example, only two out of four roles are mapped. Any role that is not found in the static map will be assigned the value null as indicated in the default_value configuration. After processing the null value will be ignored, and no role will be assigned. But you could use this feature to assign a default role in case the static map does not produce a match.
For reference, the profile picture is provided by the user_photo column, and one of the values is P01. This value corresponds to the unique identifier of one record in the udm_user_pictures file migration, which is part of the same demo module. It is important to note that the user_picture field is not a user entity property. The field is created by the standard installation profile and attached to the user entity. You can find its configuration in the “Manage fields” tab of the “Account settings” configuration page at /admin/config/people/accounts. The following snippet shows how profile pictures are set:
user_picture/target_id:
plugin: migration_lookup
migration: udm_user_pictures
source: user_photoImage fields are entity references. Their target_id property needs to be an integer number containing the file id (fid) of the image. This can be obtained using the migration_lookup plugin. Details on how to configure it can be found in this article. You could simply use user_picture as your field mapping because target_id is the default subfield and could be omitted. Also note that the alt subfield is not mapped. If present, its value will be used for the alternative text of the image. But if it is not specified, like in this example, Drupal will automatically generate an alternative text out of the username. An example value would be: Profile picture for user michele.
Technical note: The user entity contains other properties you can write to. For a list of available options, check the baseFieldDefinitions() method of the User class defining the entity. Note that more properties can be available up in the class hierarchy.
And with that, we wrap up the user migration example. We covered how to migrate a user’s mail, timezone, username, password, status, creation date, roles, and profile picture. Along the way, we presented various process plugins that had not been used previously in the series. We showed a couple of examples of process plugin chaining to make sure the migrated data is valid and in the format expected by Drupal.
What did you learn in today’s blog post? Did you know how to process dates for user entity properties? Have you migrated user roles before? Did you know how to import profile pictures? Please share your answers in the comments. Also, I would be grateful if you shared this blog post with others.
Next: Migrating dates into Drupal
This blog post series, cross-posted at UnderstandDrupal.com as well as here on Agaric.coop, is made possible thanks to these generous sponsors. Contact Understand Drupal if your organization would like to support this documentation project, whether it is the migration series or other topics.
At noon on Wednesday July 22nd, 2015, Richard Stallman (RMS) and Noam Chomsky met for the first time. We met in Noam's office, located in the Stata building on the MIT campus in Cambridge, Massachusetts, where Richard also has an office. We sat down to discuss the Free Software Movement, Digital Restrictions Management, then we briefly touched on domain name seizures, workers rights and worker-cooperatives. The atmosphere was jovial yet serious, and the discussion was soon underway.

Noam asked, what is the Free Software Foundation and movement all about? Richard responded that The Free Software Foundation is a nonprofit with a worldwide mission to promote computer user freedom and to defend the rights of all free software users. We raise awareness about computing privacy issues and users rights, by exposing things like Digital Restrictions Management. The movement is our outreach to users seeking adoption of free software and informing the network on issues that support free software and working to change attitudes and support laws that make free software remain free.
RMS then took the time to explain Digital Restrictions Management and a little known practice called domain name seizure. The US government can arbitrarily take a domain away from the domain owner without court approval. There are many reasons a domain may be seized, If your domain ends with .com, no matter what country you are based in, you are subject to VeriSign helping the U.S. Government seize your domain.
On the topic of Digital Restrictions Management, Richard detailed how it prevents people from being good neighbors and sharing files. DRM is often written as "Digital Rights Management", but this is misleading, since it refers to systems that are designed to take away and limit your rights.
Below is a quote by each and a few links to sites with background information:
Richard Stallman
"Isn't it ironic that the proprietary software developers call us communists? We are the ones who have provided for a free market, where they allow only monopoly. … if the user chooses this proprietary software package, he then falls into this monopoly for support … the only way to escape from monopoly is to escape from proprietary software, and that is what the free software movement is all about. We want you to escape and our work is to help you escape. We hope you will escape to the free world."
Richard Stallman websites:
https://en.wikipedia.org/wiki/Richard_Stallman
http://fsf.org
https://gnu.org
https://stallman.org
Noam Chomsky
"How people themselves perceive what they are doing is not a question that interests me. I mean, there are very few people who are going to look into the mirror and say, 'That person I see is a savage monster'; instead, they make up some construction that justifies what they do. If you ask the CEO of some major corporation what he does he will say, in all honesty, that he is slaving 20 hours a day to provide his customers with the best goods or services he can and creating the best possible working conditions for his employees. But then you take a look at what the corporation does, the effect of its legal structure, the vast inequalities in pay and conditions, and you see the reality is something far different."
Noam Chomsky websites:
https://en.wikipedia.org/wiki/Noam_Chomsky
http://web.mit.edu/linguistics/people/faculty/chomsky
http://www.chomsky.info
At the end of our first meeting, Noam suggested that we take a look at congress and see who is voting against the TPP, and then contact those congress members with information about free software initiatives. We all realized that we barely had time to scratch the surface of the talking points we need to cover and agreed to meet again and discuss overlapping issues that are of concern to both the labor movement and the free software movement. We will be targeting issues that have solutions ready to be implemented, and making sure we are all aware of the dangers of proprietary software.
The next meeting will be sometime in the next few months... This is a beginning.
For long-term projects one of the engineering challenges is to cope with technical evolution. The languages, libraries, and third party software like database engines and web servers we are using are under continuous development; new features are only added to the current development branches and security updates are only applied to currently supported releases. Using the example of one of our projects I will point out specific challenges and possible ways to deal with them in a series of posts.
On https://premium.zeit.de the German weekly DIE ZEIT offers subscriptions to digital formats of their newspaper in epub, mobi, pdf and mp3. Since 2011 Drupal 6 with Ubercart was used to take orders and deliver the content. Fulfillment is handled by a third party also providing the service to the company's print publications. User accounts and customer information are stored by a dedicated service running behind the company’s firewall.
In 2013 several challenges slowed down development: The web stack was still running on Ubuntu 8 with PHP 5.2 which had reached end of life. Lack of a comprehensive test suite meant upgrading would be a risky operation or require extensive end-user testing. Also it had turned out Ubercart was not a good fit for the project. Just maintaining a catalog of products and taking orders to be sent to the fulfillment provider does not require a full e-commerce solution.
The first step of reviving the project and upgrading to Drupal 7 was to set up a virtual machine for development, resembling the intended production environment (Debian 7 with Apache, PHP and MySQL). Together with the client and our partners Spry Group, we decided to use Vagrant to create a virtual machine from configuration and provisioning scripts which were committed to the repository. Before writing the provisioning scripts, tests were written to ensure the configuration of the development environment matched expectations.
/**
* Tests if a Drupal web site is served on port 80, and there are no errors.
*/
public function testDrupalWorks() {
$data = file_get_contents('http://127.0.0.1/');
$pos = stripos($data, 'name="Generator" content="Drupal 7"');
$this->assertTrue($pos !== FALSE);
}
/**
* Tests that drush is properly configured.
*/
public function testDrushWorks() {
$output = shell_exec('drush st --pipe');
$this->assertRegExp('#drush_configuration=/etc/drush/drushrc.php#', $output);
}
Above code sample shows two of our infrastructure tests written in PHPUnit. They are executed inside the virtual machine which is supposed to serve a fully working Drupal installation. The second test asserts drush is available and is using the appropriate configuration file. We chose PHPUnit as our testing framework, and we also used it for functional testing of the Drupal web site later. In one of the upcoming posts I am going to explain the approach we developed with Spry Group. These and other infrastructure test suites proved very useful during our transition to provisioning with Chef.
This combination—of a virtual machine to simulate the production environment with corresponding tests validating its functionality—enabled us to adapt to technological evolution in a well-controlled environment. For example, trying out a new stable release of the operating system or even a different OS is a simple matter of creating a new virtual machine and running the test suite against it. The more code we would cover with tests the more likely it would be to detect any issues introduced by a newer version of PHP for example.
Over the coming months I will share further insights that we have learned from this long-term project.
Learn how to get the most out of Drupal from expert practitioners with a passion for teaching.
We have practical experience in developing web sites, migrating content, and running technology projects and we love to learn and to teach. We will impart the knowledge and skills you need to get work done, and done right.